Allow dynamically loaded objects to be rebuilt by make.

This commit is contained in:
Paul Smith 2013-01-20 00:55:57 -05:00
parent 8e0a5645b8
commit b70aa3709e
8 changed files with 1167 additions and 1061 deletions

View file

@ -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>

View file

@ -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
View file

@ -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."));

1146
main.c

File diff suppressed because it is too large Load diff

4
make.h
View file

@ -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>

896
read.c

File diff suppressed because it is too large Load diff

View file

@ -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,

View file

@ -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;