mirror of
https://git.savannah.gnu.org/git/make.git
synced 2024-12-26 14:00:55 +00:00
Allow dynamically loaded objects to be rebuilt by make.
This commit is contained in:
parent
8e0a5645b8
commit
b70aa3709e
8 changed files with 1167 additions and 1061 deletions
19
ChangeLog
19
ChangeLog
|
@ -1,5 +1,24 @@
|
|||
2013-01-19 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* doc/make.texi (load Directive): Update to discuss location of
|
||||
loaded object file.
|
||||
(Remaking Loaded Objects): Document remaking of loaded objects.
|
||||
|
||||
* main.c (main): Rename READ_MAKEFILES to READ_FILES.
|
||||
* read.c: Change READ_MAKEFILES to READ_FILES since it now
|
||||
contains loaded object files as well.
|
||||
(read_all_makefiles): Ditto.
|
||||
(eval_makefile): Ditto.
|
||||
(eval): Add any loaded file to the READ_FILES list, so that it
|
||||
will be considered for re-build.
|
||||
|
||||
* load.c (load_file): Return the simple filename (no symbol) in
|
||||
the LDNAME argument (now a const char **).
|
||||
This filename should no longer have "./" prepended: modify the
|
||||
function to always check the current directory if the name has no
|
||||
"/", before using the normal methods.
|
||||
* make.h: Change the load_file() prototype.
|
||||
|
||||
* README.git: Add a bit more documentation on Git workflow & rules.
|
||||
|
||||
2013-01-13 Paul Smith <psmith@gnu.org>
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
@include version.texi
|
||||
@set EDITION 0.72
|
||||
@set RCSID $Id$
|
||||
|
||||
@settitle GNU @code{make}
|
||||
@setchapternewpage odd
|
||||
|
@ -27,7 +26,7 @@ of @cite{The GNU Make Manual}, for GNU @code{make} version @value{VERSION}.
|
|||
|
||||
Copyright @copyright{} 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
|
||||
1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
|
||||
2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
|
@ -348,6 +347,7 @@ GNU Guile Integration
|
|||
Loading Dynamic Objects
|
||||
|
||||
* load Directive:: Loading dynamic objects as extensions.
|
||||
* Remaking Loaded Objects:: How loaded objects get remade.
|
||||
|
||||
@end detailmenu
|
||||
@end menu
|
||||
|
@ -1287,7 +1287,6 @@ in the makefiles. @xref{Include, , Including Other Makefiles}.
|
|||
|
||||
@node Remaking Makefiles, Overriding Makefiles, MAKEFILES Variable, Makefiles
|
||||
@section How Makefiles Are Remade
|
||||
|
||||
@cindex updating makefiles
|
||||
@cindex remaking makefiles
|
||||
@cindex makefile, remaking of
|
||||
|
@ -6295,7 +6294,6 @@ Has GNU Guile available as an embedded extension language.
|
|||
@item load
|
||||
Supports dynamically loadable objects for creating custom extensions.
|
||||
@xref{Loading Objects, ,Loading Dynamic Objects}.
|
||||
|
||||
@end table
|
||||
|
||||
@vindex .INCLUDE_DIRS @r{(list of include directories)}
|
||||
|
@ -10539,11 +10537,11 @@ program, although this can be inefficient.
|
|||
In cases where the built-in capabilities of GNU @code{make} are
|
||||
insufficient to your requirements there are two options for extending
|
||||
@code{make}. On systems where it's provided, you can utilize GNU
|
||||
Guile as an embedded scripting language (@pxref{Guile Integration,
|
||||
,GNU Guile Integration}). On systems which support dynamically
|
||||
loadable objects, you can write your own extension in any language
|
||||
(which can be compiled into such an object) and load it to provide
|
||||
extended capabilities (@pxref{load Directive, ,The @code{load} Directive}).
|
||||
Guile as an embedded scripting language (@pxref{Guile Integration,,GNU
|
||||
Guile Integration}). On systems which support dynamically loadable
|
||||
objects, you can write your own extension in any language (which can
|
||||
be compiled into such an object) and load it to provide extended
|
||||
capabilities (@pxref{load Directive, ,The @code{load} Directive}).
|
||||
|
||||
@menu
|
||||
* Guile Integration:: Using Guile as an embedded scripting language.
|
||||
|
@ -10786,15 +10784,16 @@ providing new capabilities which may then be invoked by your makefile.
|
|||
The @code{load} directive is used to load a dynamic object. Once the
|
||||
object is loaded, a ``setup'' function will be invoked to allow the
|
||||
object to initialize itself and register new facilities with GNU
|
||||
@code{make}. Typically a dynamic object would create new functions,
|
||||
@code{make}. A dynamic object might include new @code{make} functions,
|
||||
for example, and the ``setup'' function would register them with GNU
|
||||
@code{make}'s function handling system.
|
||||
|
||||
@menu
|
||||
* load Directive:: Loading dynamic objects as extensions.
|
||||
* Remaking Loaded Objects:: How loaded objects get remade.
|
||||
@end menu
|
||||
|
||||
@node load Directive, , Loading Objects, Loading Objects
|
||||
@node load Directive, Remaking Loaded Objects, Loading Objects, Loading Objects
|
||||
@subsection The @code{load} Directive
|
||||
@cindex load directive
|
||||
@cindex extensions, load directive
|
||||
|
@ -10814,21 +10813,33 @@ or:
|
|||
load @var{object-file}(@var{symbol-name}) @dots{}
|
||||
@end example
|
||||
|
||||
In the first form, the file @var{object-file} is dynamically loaded by
|
||||
GNU @code{make}. On failure, @code{make} will print a message and
|
||||
exit. If the load succeeds @code{make} will invoke an initializing
|
||||
function whose name is created by taking the base file name of
|
||||
@var{object-file}, up to the first character which is not a valid
|
||||
symbol name character (alphanumerics and underscores are valid symbol
|
||||
name characters). To this prefix will be appended the suffix
|
||||
@code{_gmake_setup}, then this symbol will be invoked.
|
||||
The file @var{object-file} is dynamically loaded by GNU @code{make}.
|
||||
If @var{object-file} does not include a directory path then it is
|
||||
first looked for in the current directory. If it is not found there,
|
||||
or a directory path is included, then system-specific paths will be
|
||||
searched. If the load fails for any reason, @code{make} will print a
|
||||
message and exit.
|
||||
|
||||
In the second form, the function @var{symbol-name} will be invoked.
|
||||
If the load succeeds @code{make} will invoke an initializing function.
|
||||
|
||||
If @var{symbol-name} is provided, it will be used as the name of the
|
||||
initializing function.
|
||||
|
||||
If no @var{symbol-name} is provided, the initializing function name is
|
||||
created by taking the base file name of @var{object-file}, up to the
|
||||
first character which is not a valid symbol name character
|
||||
(alphanumerics and underscores are valid symbol name characters). To
|
||||
this prefix will be appended the suffix @code{_gmake_setup}.
|
||||
|
||||
More than one object file may be loaded with a single @code{load}
|
||||
directive, and both forms of @code{load} arguments may be used in the
|
||||
same directive.
|
||||
|
||||
The initializing function will be provided the file name and line
|
||||
number of the invocation of the @code{load} operation. It should
|
||||
return a value of type @code{int}, which must be @code{0} on failure
|
||||
and non-@code{0} on success.
|
||||
|
||||
For example:
|
||||
|
||||
@example
|
||||
|
@ -10864,6 +10875,22 @@ generated if an object fails to load. The failed object is not added
|
|||
to the @code{.LOADED} variable, which can then be consulted to
|
||||
determine if the load was successful.
|
||||
|
||||
@node Remaking Loaded Objects, , load Directive, Loading Objects
|
||||
@subsection How Loaded Objects Are Remade
|
||||
@cindex updating load objects
|
||||
@cindex remaking load objects
|
||||
@cindex load objects, remaking of
|
||||
|
||||
Loaded objects undergo the same re-make procedure as makefiles
|
||||
(@pxref{Remaking Makefiles, ,How Makefiles Are Remade}). If any
|
||||
loaded object is recreated, then @code{make} will start from scratch
|
||||
and re-read all the makefiles, and reload the object files again. It
|
||||
is not necessary for the loaded object to do anything special to
|
||||
support this.@refill
|
||||
|
||||
It's up to the makefile author to provide the rules needed for
|
||||
rebuilding the loaded object.
|
||||
|
||||
@node Features, Missing, Extending make, Top
|
||||
@chapter Features of GNU @code{make}
|
||||
@cindex features of GNU @code{make}
|
||||
|
@ -11007,6 +11034,12 @@ nonexistent file comes from SunOS 4 @code{make}. (But note that SunOS 4
|
|||
The @code{!=} shell assignment operator exists in many BSD of
|
||||
@code{make} and is purposefully implemented here to behave identically
|
||||
to those implementations.
|
||||
|
||||
@item
|
||||
Various build management tools are implemented using scripting
|
||||
languages such as Perl or Python and thus provide a natural embedded
|
||||
scripting language, similar to GNU @code{make}'s integration of GNU
|
||||
Guile.
|
||||
@end itemize
|
||||
|
||||
The remaining features are inventions new in GNU @code{make}:
|
||||
|
@ -11116,6 +11149,10 @@ Various new built-in implicit rules.
|
|||
The built-in variable @samp{MAKE_VERSION} gives the version number of
|
||||
@code{make}.
|
||||
@vindex MAKE_VERSION
|
||||
|
||||
@item
|
||||
Load dynamic objects which can modify the behavior of @code{make}.
|
||||
@xref{Loading Objects, ,Loading Dynamic Objects}.
|
||||
@end itemize
|
||||
|
||||
@node Missing, Makefile Conventions, Features, Top
|
||||
|
|
43
load.c
43
load.c
|
@ -58,12 +58,12 @@ init_symbol (const struct floc *flocp, const char *ldname, load_func_t symp)
|
|||
}
|
||||
|
||||
int
|
||||
load_file (const struct floc *flocp, const char *ldname, int noerror)
|
||||
load_file (const struct floc *flocp, const char **ldname, int noerror)
|
||||
{
|
||||
load_func_t symp;
|
||||
const char *fp;
|
||||
char *symname = NULL;
|
||||
char *new = alloca (strlen (ldname) + CSTRLEN (SYMBOL_EXTENSION) + 1);
|
||||
char *new = alloca (strlen (*ldname) + CSTRLEN (SYMBOL_EXTENSION) + 1);
|
||||
|
||||
if (! global_dl)
|
||||
{
|
||||
|
@ -73,27 +73,27 @@ load_file (const struct floc *flocp, const char *ldname, int noerror)
|
|||
}
|
||||
|
||||
/* If a symbol name was provided, use it. */
|
||||
fp = strchr (ldname, '(');
|
||||
fp = strchr (*ldname, '(');
|
||||
if (fp)
|
||||
{
|
||||
const char *ep;
|
||||
|
||||
/* If there's an open paren, see if there's a close paren: if so use
|
||||
/* There's an open paren, so see if there's a close paren: if so use
|
||||
that as the symbol name. We can't have whitespace: it would have
|
||||
been chopped up before this function is called. */
|
||||
ep = strchr (fp+1, ')');
|
||||
if (ep && ep[1] == '\0')
|
||||
{
|
||||
int l = fp - ldname;;
|
||||
int l = fp - *ldname;;
|
||||
|
||||
++fp;
|
||||
if (fp == ep)
|
||||
fatal (flocp, _("Empty symbol name for load: %s"), ldname);
|
||||
fatal (flocp, _("Empty symbol name for load: %s"), *ldname);
|
||||
|
||||
/* Make a copy of the ldname part. */
|
||||
memcpy (new, ldname, l);
|
||||
memcpy (new, *ldname, l);
|
||||
new[l] = '\0';
|
||||
ldname = new;
|
||||
*ldname = new;
|
||||
|
||||
/* Make a copy of the symbol name part. */
|
||||
symname = new + l + 1;
|
||||
|
@ -102,14 +102,17 @@ load_file (const struct floc *flocp, const char *ldname, int noerror)
|
|||
}
|
||||
}
|
||||
|
||||
/* Add this name to the string cache so it can be reused later. */
|
||||
*ldname = strcache_add (*ldname);
|
||||
|
||||
/* If we didn't find a symbol name yet, construct it from the ldname. */
|
||||
if (! symname)
|
||||
{
|
||||
char *p = new;
|
||||
|
||||
fp = strrchr (ldname, '/');
|
||||
fp = strrchr (*ldname, '/');
|
||||
if (!fp)
|
||||
fp = ldname;
|
||||
fp = *ldname;
|
||||
else
|
||||
++fp;
|
||||
while (isalnum (*fp) || *fp == '_')
|
||||
|
@ -118,12 +121,22 @@ load_file (const struct floc *flocp, const char *ldname, int noerror)
|
|||
symname = new;
|
||||
}
|
||||
|
||||
DB (DB_VERBOSE, (_("Loading symbol %s from %s\n"), symname, ldname));
|
||||
DB (DB_VERBOSE, (_("Loading symbol %s from %s\n"), symname, *ldname));
|
||||
|
||||
/* See if it's already defined. */
|
||||
symp = (load_func_t) dlsym (global_dl, symname);
|
||||
if (! symp) {
|
||||
void *dlp = dlopen (ldname, RTLD_LAZY|RTLD_GLOBAL);
|
||||
void *dlp = NULL;
|
||||
|
||||
/* If the path has no "/", try the current directory first. */
|
||||
if (! strchr (*ldname, '/'))
|
||||
dlp = dlopen (concat (2, "./", *ldname), RTLD_LAZY|RTLD_GLOBAL);
|
||||
|
||||
/* If we haven't opened it yet, try the default search path. */
|
||||
if (! dlp)
|
||||
dlp = dlopen (*ldname, RTLD_LAZY|RTLD_GLOBAL);
|
||||
|
||||
/* Still no? Then fail. */
|
||||
if (! dlp)
|
||||
{
|
||||
if (noerror)
|
||||
|
@ -136,17 +149,17 @@ load_file (const struct floc *flocp, const char *ldname, int noerror)
|
|||
symp = dlsym (dlp, symname);
|
||||
if (! symp)
|
||||
fatal (flocp, _("Failed to load symbol %s from %s: %s"),
|
||||
symname, ldname, dlerror());
|
||||
symname, *ldname, dlerror());
|
||||
}
|
||||
|
||||
/* Invoke the symbol to initialize the loaded object. */
|
||||
return init_symbol(flocp, ldname, symp);
|
||||
return init_symbol(flocp, *ldname, symp);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int
|
||||
load_file (const struct floc *flocp, const char *ldname, int noerror)
|
||||
load_file (const struct floc *flocp, const char **ldname, int noerror)
|
||||
{
|
||||
if (! noerror)
|
||||
fatal (flocp, _("The 'load' operation is not supported on this platform."));
|
||||
|
|
4
make.h
4
make.h
|
@ -476,9 +476,9 @@ int strcache_setbufsize (unsigned int size);
|
|||
int guile_gmake_setup (const struct floc *flocp);
|
||||
#endif
|
||||
|
||||
/* Loadable object support */
|
||||
/* Loadable object support. Sets to the strcached name of the loaded file. */
|
||||
typedef int (*load_func_t)(const struct floc *flocp);
|
||||
int load_file (const struct floc *flocp, const char *filename, int noerror);
|
||||
int load_file (const struct floc *flocp, const char **filename, int noerror);
|
||||
|
||||
#ifdef HAVE_VFORK_H
|
||||
# include <vfork.h>
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2013-01-19 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/features/load: Test loaded files with and without "./"
|
||||
prefix. Add tests for automatically rebuilding loaded files if
|
||||
they are out of date or non-existent.
|
||||
|
||||
2013-01-13 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/features/archives: Add a check targets that have parens,
|
||||
|
|
|
@ -49,7 +49,7 @@ run_make_test('testload.so: testload.c ; @$(CC) -g -shared -fPIC -o $@ $<',
|
|||
# TEST 1
|
||||
run_make_test(q!
|
||||
all: ; @echo $(func-a foo) $(func-b bar)
|
||||
load ./testload.so
|
||||
load testload.so
|
||||
!,
|
||||
'', "func-a\n");
|
||||
|
||||
|
@ -64,19 +64,42 @@ load ./testload.so(explicit_setup)
|
|||
# TEST 3
|
||||
# Verify the .LOADED variable
|
||||
run_make_test(q!
|
||||
all: ; @echo $(filter ./testload.so,$(.LOADED)) $(func-a foo) $(func-b bar)
|
||||
load ./testload.so(explicit_setup)
|
||||
all: ; @echo $(filter testload.so,$(.LOADED)) $(func-a foo) $(func-b bar)
|
||||
load testload.so(explicit_setup)
|
||||
!,
|
||||
'', "./testload.so func-b\n");
|
||||
'', "testload.so func-b\n");
|
||||
|
||||
# TEST 4
|
||||
# Check multiple loads
|
||||
run_make_test(q!
|
||||
all: ; @echo $(filter ./testload.so,$(.LOADED)) $(func-a foo) $(func-b bar)
|
||||
all: ; @echo $(filter testload.so,$(.LOADED)) $(func-a foo) $(func-b bar)
|
||||
load ./testload.so
|
||||
load ./testload.so(explicit_setup)
|
||||
load testload.so(explicit_setup)
|
||||
!,
|
||||
'', "./testload.so func-a\n");
|
||||
'', "testload.so func-a\n");
|
||||
|
||||
# TEST 5
|
||||
# Check auto-rebuild of loaded file that's out of date
|
||||
utouch(-10, 'testload.so');
|
||||
touch('testload.c');
|
||||
|
||||
run_make_test(q!
|
||||
all: ; @echo $(func-a foo) $(func-b bar)
|
||||
load ./testload.so
|
||||
testload.so: testload.c ; @echo "rebuilding $@"; $(CC) -g -shared -fPIC -o $@ $<
|
||||
!,
|
||||
'', "rebuilding testload.so\nfunc-a\n");
|
||||
|
||||
# TEST 5
|
||||
# Check auto-rebuild of loaded file when it doesn't exist
|
||||
unlink('testload.so');
|
||||
|
||||
run_make_test(q!
|
||||
all: ; @echo $(func-a foo) $(func-b bar)
|
||||
-load ./testload.so(explicit_setup)
|
||||
%.so: %.c ; @echo "rebuilding $@"; $(CC) -g -shared -fPIC -o $@ $<
|
||||
!,
|
||||
'', "rebuilding testload.so\nfunc-b\n");
|
||||
|
||||
unlink(qw(testload.c testload.so)) unless $keep;
|
||||
|
||||
|
|
Loading…
Reference in a new issue