Allow the user to conveniently use Mercury libraries installed in

Estimated hours taken: 70

Allow the user to conveniently use Mercury libraries installed in
non-standard places, by specifying the variables `EXTRA_LIBRARIES' and
`EXTRA_LIB_DIRS' in their Mmakefile.

doc/user_guide.texi:
	Documented the new `EXTRA_LIBRARIES' and `EXTRA_LIB_DIRS' Mmake
	variables.

scripts/Mmake.vars.in:
	Added/changed definitions appropriately to support the new
	variables.
	This included adding a `GRADESTRING' variable which holds the
	canonical name of the grade being used, taking into account all the
	grade flags.

scripts/c2init.in:
	Added a new option to `c2init':
	-I/--init-file-directory <directory> adds the directory to the list
		of directories to search for `.init' files.

util/mkinit.c:
	Added a new option `-I' to add a directory to the list of
	directories to search for `.init' files.
This commit is contained in:
Warwick Harvey
1999-07-26 02:52:46 +00:00
parent 293b4a1d59
commit a7b1401531
4 changed files with 237 additions and 20 deletions

View File

@@ -530,6 +530,18 @@ specified in @code{GRADEFLAGS} and @code{C2INITARGS}, respectively.)
Extra files to be processed by c2init. These variables should not be
used for specifying flags to c2init (that's what @code{C2INITFLAGS} is for)
since they are also used to derive extra dependency information.
@item EXTRA_LIBRARIES
A list of extra Mercury libraries to link into any programs or libraries
that you are building.
Libraries should be specified using their base name; that is, without any
@samp{lib} prefix or extension.
For example the library including the files @file{libfoo.a} and
@file{foo.init} would be referred to as just @samp{foo}.
@item EXTRA_LIB_DIRS
A list of extra Mercury library directory hierarchies to search when
looking for extra libraries.
@end table
Other variables also exist - see
@@ -582,6 +594,7 @@ and, on many platforms, it supports shared object libraries.
* Building libraries::
* Installing libraries::
* Using libraries::
* Supporting multiple grades and architectures::
@end menu
@node Writing libraries
@@ -779,6 +792,45 @@ for each Mercury library being used are all put in a single directory,
which is probably the simplest way of organizing things, but the
Mercury implementation does not require that.
@node Supporting multiple grades and architectures
@section Supporting multiple grades and architectures
In order to better support using and installing libraries in multiple
grades, @samp{mmake} now has some support for alternative library directory
hierarchies.
These have the same structure as the @file{@var{prefix}/lib/mercury} tree,
including the different subdirectories for different grades and different
machine architectures.
Automatically installing a library and all its associated files to such a
tree is not yet supported, but until it is the user can use the same
techniques used for building and installing the core Mercury libraries.
Once a library is installed in such a hierarchy, using it is easy.
Suppose the user wishes to use the library @samp{mypackage} (installed
in the tree rooted at @samp{/some/directory/mypackage}) and the library
@samp{myotherlib} (installed in the tree rooted at
@samp{/some/directory/myotherlib}).
The user need only set the following Mmake variables:
@example
EXTRA_LIB_DIRS = /some/directory/mypackage /some/directory/myotherlib
EXTRA_LIBRARIES = mypackage myotherlib
@end example
Mmake will then ensure that the appropriate directories are searched for
the relevant interface files, module initialisation files, compiled
libraries, etc.
One can specify extra libraries to be used on a program-by-program
basis. For instance, if the program @samp{foo} also uses the library
@samp{mylib4foo}, but the other programs governed by the Mmakefile don't,
then one can declare:
@example
EXTRA_LIBRARIES-foo = mylib4foo
@end example
@node Debugging
@chapter Debugging

View File

@@ -12,9 +12,31 @@
# Ensure that commands use /bin/sh not the user's shell
SHELL = /bin/sh
ALL_EXTRA_LIBRARIES = $(TARGET_EXTRA_LIBRARIES) $(EXTRA_LIBRARIES)
EXTRA_LIB_DIRS =
EXTRA_LIBRARIES =
EXTRA_INT_DIRS = $(patsubst %,%/ints,$(EXTRA_LIB_DIRS))
MERCURY_EXTRA_INT_DIRS = $(EXTRA_INT_DIRS)
EXTRA_C_LIB_DIRS = \
$(patsubst %,%/lib/$(GRADESTRING)/@FULLARCH@,$(EXTRA_LIB_DIRS)) \
$(patsubst %,%/lib/@FULLARCH@,$(EXTRA_LIB_DIRS))
EXTRA_C_INCL_DIRS = $(patsubst %,%/inc,$(EXTRA_LIB_DIRS))
EXTRA_INIT_DIRS = $(patsubst %,%/modules,$(EXTRA_LIB_DIRS))
MERCURY_EXTRA_INIT_DIRS = $(EXTRA_INIT_DIRS)
# Set the directory search path.
# (See the GNU Make manual for documentation about VPATH and GPATH.)
MMAKE_VPATH = $(MERCURY_INT_DIR)
# We need to substitute all spaces with colons for the VPATH to work.
# Getting a space to be recognised as the first argument of the subst
# function is problematic; hence the `$(nullstring)' hack.
# XXX Note that directory names with spaces in them (e.g. under Windows)
# will cause problems for the VPATH settings below, as well as every
# occurrence of $(patsubst ...), since GNU Make does not respect quotes.
nullstring =
MMAKE_VPATH = $(subst $(nullstring) ,:,$(strip \
$(MERCURY_EXTRA_INT_DIRS) $(MERCURY_INT_DIR)\
$(MERCURY_EXTRA_INIT_DIRS)))
VPATH = $(MMAKE_VPATH) # do not remove the `:' from this comment!!!
# the above comment works around a misfeature of
# autoconf which causes it to delete assignments to
@@ -23,15 +45,17 @@ GPATH = $(VPATH)
DEFAULT_GRADE = $(MERCURY_DEFAULT_GRADE)
GRADE = $(DEFAULT_GRADE)
GRADESTRING = $(shell $(MCOGS) $(ALL_GRADEFLAGS))
ALL_GRADEFLAGS = $(GRADEFLAGS) $(EXTRA_GRADEFLAGS) $(TARGET_GRADEFLAGS)
GRADEFLAGS = --grade $(GRADE)
EXTRA_GRADEFLAGS =
MC = mmc
ALL_MCFLAGS = $(MCFLAGS) $(EXTRA_MCFLAGS) $(TARGET_MCFLAGS)
ALL_MCFLAGS = $(MCFLAGS) $(EXTRA_MCFLAGS) $(TARGET_MCFLAGS) $(LIB_MCFLAGS)
MCFLAGS =
EXTRA_MCFLAGS =
LIB_MCFLAGS = $(patsubst %,-I %,$(EXTRA_INT_DIRS))
MCS = $(MC) --split-c-files --compile-only
MCG = $(MC) --compile-to-c
@@ -41,15 +65,24 @@ MCPI = $(MC) --make-private-interface
MCSI = $(MC) --make-short-interface
MCOI = $(MC) --make-optimization-interface
MCTOI = $(MC) --make-transitive-optimization-interface
MCOGS = $(MC) --output-grade-string
ALL_MCIFLAGS = $(MCIFLAGS) $(EXTRA_MCIFLAGS) $(TARGET_MCFLAGS)
ALL_MCPIFLAGS = $(MCPIFLAGS) $(EXTRA_MCPIFLAGS) $(TARGET_MCFLAGS)
ALL_MCSIFLAGS = $(MCSIFLAGS) $(EXTRA_MCSIFLAGS) $(TARGET_MCFLAGS)
ALL_MCOIFLAGS = $(MCOIFLAGS) $(EXTRA_MCOIFLAGS) $(TARGET_MCFLAGS)
ALL_MCTOIFLAGS = $(MCTOIFLAGS) $(EXTRA_MCTOIFLAGS) $(TARGET_MCFLAGS)
ALL_MCDFLAGS = $(MCDFLAGS) $(EXTRA_MCDFLAGS) $(TARGET_MCFLAGS)
ALL_MCGFLAGS = $(MCGFLAGS) $(EXTRA_MCGFLAGS) $(TARGET_MCFLAGS)
ALL_MCSFLAGS = $(MCSFLAGS) $(EXTRA_MCSFLAGS) $(TARGET_MCFLAGS)
ALL_MCIFLAGS = $(MCIFLAGS) $(EXTRA_MCIFLAGS) $(TARGET_MCFLAGS) \
$(LIB_MCFLAGS)
ALL_MCPIFLAGS = $(MCPIFLAGS) $(EXTRA_MCPIFLAGS) $(TARGET_MCFLAGS) \
$(LIB_MCFLAGS)
ALL_MCSIFLAGS = $(MCSIFLAGS) $(EXTRA_MCSIFLAGS) $(TARGET_MCFLAGS) \
$(LIB_MCFLAGS)
ALL_MCOIFLAGS = $(MCOIFLAGS) $(EXTRA_MCOIFLAGS) $(TARGET_MCFLAGS) \
$(LIB_MCFLAGS)
ALL_MCTOIFLAGS = $(MCTOIFLAGS) $(EXTRA_MCTOIFLAGS) $(TARGET_MCFLAGS) \
$(LIB_MCFLAGS)
ALL_MCDFLAGS = $(MCDFLAGS) $(EXTRA_MCDFLAGS) $(TARGET_MCFLAGS) \
$(LIB_MCFLAGS)
ALL_MCGFLAGS = $(MCGFLAGS) $(EXTRA_MCGFLAGS) $(TARGET_MCFLAGS) \
$(LIB_MCFLAGS)
ALL_MCSFLAGS = $(MCSFLAGS) $(EXTRA_MCSFLAGS) $(TARGET_MCFLAGS) \
$(LIB_MCFLAGS)
MCIFLAGS = $(MCFLAGS)
MCPIFLAGS = $(MCFLAGS)
@@ -74,13 +107,17 @@ EXTRA_MCSFLAGS = $(EXTRA_MCFLAGS)
# the options which should be passed to them.
#
C2INIT = c2init
ALL_C2INITFLAGS = $(C2INITFLAGS) $(EXTRA_C2INITFLAGS) $(TARGET_C2INITFLAGS)
ALL_C2INITFLAGS = $(C2INITFLAGS) $(EXTRA_C2INITFLAGS) $(TARGET_C2INITFLAGS) \
$(LIB_C2INITFLAGS)
C2INITFLAGS =
EXTRA_C2INITFLAGS =
LIB_C2INITFLAGS = $(patsubst %,--init-file-directory %,$(EXTRA_INIT_DIRS))
ALL_C2INITARGS = $(C2INITARGS) $(EXTRA_C2INITARGS) $(TARGET_C2INITARGS)
ALL_C2INITARGS = $(C2INITARGS) $(EXTRA_C2INITARGS) $(TARGET_C2INITARGS) \
$(LIB_C2INITARGS)
C2INITARGS =
EXTRA_C2INITARGS =
LIB_C2INITARGS = $(patsubst %,%.init,$(ALL_EXTRA_LIBRARIES))
MGNUC = mgnuc
ALL_MGNUCFLAGS = $(MGNUCFLAGS) $(EXTRA_MGNUCFLAGS) $(TARGET_MGNUCFLAGS) \
@@ -93,13 +130,15 @@ CFLAGS =
EXTRA_CFLAGS =
ML = ml
ALL_MLFLAGS = $(MLFLAGS) $(EXTRA_MLFLAGS) $(TARGET_MLFLAGS)
ALL_MLFLAGS = $(MLFLAGS) $(EXTRA_MLFLAGS) $(TARGET_MLFLAGS) $(LIB_MLFLAGS)
MLFLAGS = $(EXTRA_MLFLAGS)
EXTRA_MLFLAGS =
LIB_MLFLAGS = $(patsubst %,-R%,$(EXTRA_C_LIB_DIRS)) \
$(patsubst %,-L%,$(EXTRA_C_LIB_DIRS))
MLOBJS =
MLPICOBJS = $(MLOBJS:.o=.$(EXT_FOR_PIC_OBJECTS))
ALL_MLLIBS = $(MLLIBS) $(EXTRA_MLLIBS) $(TARGET_MLLIBS)
ALL_MLLIBS = $(MLLIBS) $(EXTRA_MLLIBS) $(TARGET_MLLIBS) $(LIB_MLLIBS)
# XXX ALL_MLLIBS_DEP should contain a list of the file names of the
# libraries specified in ALL_MLLIBS, but I can't see how to know whether
# they should be `.a' or `.so' libraries, so for now we leave it empty.
@@ -107,6 +146,7 @@ ALL_MLLIBS = $(MLLIBS) $(EXTRA_MLLIBS) $(TARGET_MLLIBS)
ALL_MLLIBS_DEP =
MLLIBS =
EXTRA_MLLIBS =
LIB_MLLIBS = $(patsubst %,-l%,$(ALL_EXTRA_LIBRARIES))
MNC = mnc
ALL_MNCFLAGS = $(MNCFLAGS) $(EXTRA_MNCFLAGS) $(TARGET_MNCFLAGS)
@@ -256,6 +296,15 @@ TARGET_RANLIBFLAGS = \
maybe-target-RANLIBFLAGS- = $(RANLIBFLAGS-$@)
maybe-target-RANLIBFLAGS-undefined =
# Note we strip any trailing `_init.c' from `$@' so we get the appropriate
# "base" name, regardless of whether this variable ends up being used as
# an argument of a `c2init' rule or an `ml' rule.
TARGET_EXTRA_LIBRARIES = \
$(maybe-target-EXTRA_LIBRARIES-$(findstring undefined,\
$(origin EXTRA_LIBRARIES-$(patsubst %_init.c,%,$@))))
maybe-target-EXTRA_LIBRARIES- = $(EXTRA_LIBRARIES-$(patsubst %_init.c,%,$@))
maybe-target-EXTRA_LIBRARIES-undefined =
# Support for compiling Mercury programs with Prolog will probably be
# dropped one of these days, so it's probably not worth bothering with these.
TARGET_MNCFLAGS =

View File

@@ -41,6 +41,9 @@ Options:
(declared in \"init.h\") that can be called from C code.
(A more fine-grained interface is also available;
see \"init.h\" for details.)
-I <directory>, --init-file-directory <directory>
Include <directory> in the list of directories searched to
locate \`.init' files.
-w <label>, --entry-point <label>
Set entry point to <label>.
(Default value is \`mercury__main_2_0'.)
@@ -88,6 +91,7 @@ trace_opt=""
library_opt=""
extra_inits_opt=""
aditi_opt=""
extra_init_dirs=""
# include the file `init_grade_options.sh-subr'
@INIT_GRADE_OPTIONS@
@@ -113,6 +117,9 @@ while true; do
-l-|--no-library)
library_opt="";;
-I|--init-file-directory)
extra_init_dirs="$extra_init_dirs -I $2"; shift;;
-w|--entry-point)
defentry="$2"; shift;;
@@ -176,10 +183,10 @@ esac
case $# in
0) exec $MKINIT $aditi_opt -c"$maxcalls" $init_opt $trace_opt \
$library_opt -w"$defentry" $extra_inits_opt \
$MERCURY_MOD_LIB_MODS
$extra_init_dirs $EXTRA_INIT_FILES $MERCURY_MOD_LIB_MODS
;;
*) exec $MKINIT $aditi_opt -c"$maxcalls" $init_opt $trace_opt \
$library_opt -w"$defentry" $extra_inits_opt "$@" \
$MERCURY_MOD_LIB_MODS
$library_opt -w"$defentry" $extra_inits_opt \
$extra_init_dirs "$@" $EXTRA_INIT_FILES $MERCURY_MOD_LIB_MODS
;;
esac

View File

@@ -23,6 +23,8 @@
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include "getopt.h"
#include "mercury_conf.h"
#include "mercury_std.h"
@@ -32,7 +34,7 @@
#define MAXLINE 256 /* maximum number of characters per line */
/* (characters after this limit are ignored) */
/* --- used to collect Aditi data constant names --- */
/* --- used to collect a list of strings, e.g. Aditi data constant names --- */
typedef struct String_List_struct {
char *data;
@@ -57,6 +59,12 @@ static bool need_tracing = FALSE;
static int num_modules = 0;
static int num_errors = 0;
/* List of directories to search for init files */
static String_List *init_file_dirs = NULL;
/* Pointer to tail of the init_file_dirs list */
static String_List **init_file_dirs_tail = &init_file_dirs;
/* List of names of Aditi-RL code constants. */
static String_List *rl_data = NULL;
@@ -229,6 +237,9 @@ static const char if_need_to_init[] =
/* --- function prototypes --- */
static void parse_options(int argc, char *argv[]);
static void usage(void);
static void do_path_search(void);
static char *find_init_file(const char *basename);
static bool file_exists(const char *filename);
static void output_headers(void);
static void output_sub_init_functions(void);
static void output_main_init_function(void);
@@ -279,6 +290,8 @@ main(int argc, char **argv)
parse_options(argc, argv);
do_path_search();
output_headers();
output_sub_init_functions();
output_main_init_function();
@@ -304,8 +317,9 @@ main(int argc, char **argv)
static void
parse_options(int argc, char *argv[])
{
int c;
while ((c = getopt(argc, argv, "ac:iltw:x")) != EOF) {
int c;
String_List *tmp_slist;
while ((c = getopt(argc, argv, "ac:iI:ltw:x")) != EOF) {
switch (c) {
case 'a':
aditi = TRUE;
@@ -320,6 +334,21 @@ parse_options(int argc, char *argv[])
need_initialization_code = TRUE;
break;
case 'I':
/*
** Add the directory name to the end of the
** search path for `.init' files.
*/
tmp_slist = (String_List *)
checked_malloc(sizeof(String_List));
tmp_slist->next = NULL;
tmp_slist->data = (char *)
checked_malloc(strlen(optarg) + 1);
strcpy(tmp_slist->data, optarg);
*init_file_dirs_tail = tmp_slist;
init_file_dirs_tail = &tmp_slist->next;
break;
case 'l':
output_main_func = FALSE;
break;
@@ -355,6 +384,86 @@ usage(void)
exit(1);
}
/*---------------------------------------------------------------------------*/
/*
** Scan the list of files for ones not found in the current
** directory, and replace them with their full path equivalent
** if they are found in the list of search directories.
*/
static void
do_path_search(void)
{
int filenum;
char *init_file;
for (filenum = 0; filenum < num_files; filenum++) {
init_file = find_init_file(files[filenum]);
if (init_file != NULL)
files[filenum] = init_file;
}
}
/*
** Search the init file directory list to locate the file.
** If the file is in the current directory or is not in any of the
** search directories, then return NULL. Otherwise return the full
** path name to the file.
** It is the caller's responsibility to free the returned buffer
** holding the full path name when it is no longer needed.
*/
static char *
find_init_file(const char *basename)
{
char *filename;
char *dirname;
String_List *dir_ptr;
int dirlen;
int baselen;
int len;
if (file_exists(basename)) {
/* File is in current directory, so no search required */
return NULL;
}
baselen = strlen(basename);
for (dir_ptr = init_file_dirs; dir_ptr != NULL;
dir_ptr = dir_ptr->next)
{
dirname = dir_ptr->data;
dirlen = strlen(dirname);
len = dirlen + 1 + baselen;
filename = (char *) checked_malloc(len + 1);
strcpy(filename, dirname);
filename[dirlen] = '/';
strcpy(filename + dirlen + 1, basename);
if (file_exists(filename))
return filename;
free(filename);
}
/* Did not find file */
return NULL;
}
/*
** Check whether a file exists.
** At some point in the future it may be worth making this
** implementation more portable.
*/
static bool
file_exists(const char *filename)
{
struct stat buf;
return (stat(filename, &buf) == 0);
}
/*---------------------------------------------------------------------------*/
static void