mirror of
https://github.com/mirror/make.git
synced 2025-01-27 04:40:33 +08:00
Implement linker-compatible library search.
This commit is contained in:
parent
5f188b39a4
commit
fe43fa9de3
20
ChangeLog
20
ChangeLog
@ -1,3 +1,23 @@
|
||||
2009-11-12 Boris Kolpackov <boris@codesynthesis.com>
|
||||
|
||||
* vpath.c (vpath_search, selective_vpath_search): Add index arguments
|
||||
which allows the caller to get the index of the matching directory.
|
||||
|
||||
* make.h (vpath_search): Update prototype.
|
||||
|
||||
* remake.c (library_search): Implement linker-compatible library
|
||||
search. Use the new VPATH_SEARCH index functionality to keep track
|
||||
of the directory index for each match. Select the match with the
|
||||
lowest directory index.
|
||||
|
||||
* implicit.c (pattern_search): Pass NULL for the index arguments in
|
||||
the VPATH_SEARCH call.
|
||||
|
||||
* doc/make.texi (Directory Search for Link Libraries): Describe the
|
||||
new search behavior.
|
||||
|
||||
* NEWS: Add a note about the new behavior.
|
||||
|
||||
2009-10-25 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* AUTHORS, et.al.: Update copyright years.
|
||||
|
9
NEWS
9
NEWS
@ -37,6 +37,15 @@ Version 3.81.90
|
||||
patterns are preferred. To detect this feature search for 'shortest-stem'
|
||||
in the .FEATURES special variable.
|
||||
|
||||
* WARNING: Backward-incompatibility!
|
||||
The library search behavior has changed to be compatible with the standard
|
||||
linker behavior. Prior to this version for prerequisites specified using
|
||||
the -lfoo syntax make fist searched for libfoo.so in the current directory,
|
||||
vpath directories, and system directories. If that didn't yield a match,
|
||||
make then searched for libfoo.a in these directories. Starting with this
|
||||
version make searches first for libfoo.so and then for libfoo.a in each
|
||||
of these directories in order.
|
||||
|
||||
* New command line option: --eval=STRING causes STRING to be evaluated as
|
||||
makefile syntax (akin to using the $(eval ...) function). The evaluation is
|
||||
performed after all default rules and variables are defined, but before any
|
||||
|
@ -2425,17 +2425,15 @@ file, and the @emph{file name} of a library generally looks like
|
||||
@file{lib@var{name}.a}, not like @samp{-l@var{name}}.)@refill
|
||||
|
||||
When a prerequisite's name has the form @samp{-l@var{name}}, @code{make}
|
||||
handles it specially by searching for the file @file{lib@var{name}.so} in
|
||||
the current directory, in directories specified by matching @code{vpath}
|
||||
handles it specially by searching for the file @file{lib@var{name}.so},
|
||||
and, if it is not found, for the file @file{lib@var{name}.a} in the current
|
||||
directory, in directories specified by matching @code{vpath}
|
||||
search paths and the @code{VPATH} search path, and then in the
|
||||
directories @file{/lib}, @file{/usr/lib}, and @file{@var{prefix}/lib}
|
||||
(normally @file{/usr/local/lib}, but MS-DOS/MS-Windows versions of
|
||||
@code{make} behave as if @var{prefix} is defined to be the root of the
|
||||
DJGPP installation tree).
|
||||
|
||||
If that file is not found, then the file @file{lib@var{name}.a} is
|
||||
searched for, in the same directories as above.
|
||||
|
||||
For example, if there is a @file{/usr/lib/libcurses.a} library on your
|
||||
system (and no @file{/usr/lib/libcurses.so} file), then
|
||||
|
||||
@ -2457,8 +2455,7 @@ via the @code{.LIBPATTERNS} variable. Each word in the value of this
|
||||
variable is a pattern string. When a prerequisite like
|
||||
@samp{-l@var{name}} is seen, @code{make} will replace the percent in
|
||||
each pattern in the list with @var{name} and perform the above directory
|
||||
searches using that library filename. If no library is found, the next
|
||||
word in the list will be used.
|
||||
searches using each library filename.
|
||||
|
||||
The default value for @code{.LIBPATTERNS} is @samp{lib%.so lib%.a},
|
||||
which provides the default behavior described above.
|
||||
|
@ -721,7 +721,7 @@ pattern_search (struct file *file, int archive,
|
||||
"lib/foo.c", and VPATH=src, searches for
|
||||
"src/lib/foo.c". */
|
||||
{
|
||||
const char *vname = vpath_search (d->name, 0);
|
||||
const char *vname = vpath_search (d->name, 0, NULL, NULL);
|
||||
if (vname)
|
||||
{
|
||||
DBS (DB_IMPLICIT,
|
||||
|
3
make.h
3
make.h
@ -431,7 +431,8 @@ void install_default_implicit_rules (void);
|
||||
|
||||
void build_vpath_lists (void);
|
||||
void construct_vpath_list (char *pattern, char *dirpath);
|
||||
const char *vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr);
|
||||
const char *vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr,
|
||||
unsigned int* vpath_index, unsigned int* path_index);
|
||||
int gpath_search (const char *file, unsigned int len);
|
||||
|
||||
void construct_include_path (const char **arg_dirs);
|
||||
|
101
remake.c
101
remake.c
@ -1280,7 +1280,7 @@ f_mtime (struct file *file, int search)
|
||||
if (mtime == NONEXISTENT_MTIME && search && !file->ignore_vpath)
|
||||
{
|
||||
/* If name_mtime failed, search VPATH. */
|
||||
const char *name = vpath_search (file->name, &mtime);
|
||||
const char *name = vpath_search (file->name, &mtime, NULL, NULL);
|
||||
if (name
|
||||
/* Last resort, is it a library (-lxxx)? */
|
||||
|| (file->name[0] == '-' && file->name[1] == 'l'
|
||||
@ -1533,6 +1533,10 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
|
||||
unsigned int len;
|
||||
unsigned int liblen;
|
||||
|
||||
/* Information about the earliest (in the vpath sequence) match. */
|
||||
unsigned int best_vpath, best_path;
|
||||
unsigned int std_dirs = 0;
|
||||
|
||||
char **dp;
|
||||
|
||||
libpatterns = xstrdup (variable_expand ("$(.LIBPATTERNS)"));
|
||||
@ -1541,7 +1545,9 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
|
||||
lib += 2;
|
||||
liblen = strlen (lib);
|
||||
|
||||
/* Loop through all the patterns in .LIBPATTERNS, and search on each one. */
|
||||
/* Loop through all the patterns in .LIBPATTERNS, and search on each one.
|
||||
To implement the linker-compatible behavior we have to search through
|
||||
all entries in .LIBPATTERNS and choose the "earliest" one. */
|
||||
p2 = libpatterns;
|
||||
while ((p = find_next_token (&p2, &len)) != 0)
|
||||
{
|
||||
@ -1577,51 +1583,80 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)
|
||||
if (mtime_ptr != 0)
|
||||
*mtime_ptr = mtime;
|
||||
file = strcache_add (libbuf);
|
||||
goto fini;
|
||||
/* This by definition will have the best index, so stop now. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now try VPATH search on that. */
|
||||
|
||||
{
|
||||
file = vpath_search (libbuf, mtime_ptr);
|
||||
if (file)
|
||||
goto fini;
|
||||
unsigned int vpath_index, path_index;
|
||||
const char* f = vpath_search (libbuf, mtime_ptr ? &mtime : NULL,
|
||||
&vpath_index, &path_index);
|
||||
if (f)
|
||||
{
|
||||
/* If we have a better match, record it. */
|
||||
if (file == 0 ||
|
||||
vpath_index < best_vpath ||
|
||||
(vpath_index == best_vpath && path_index < best_path))
|
||||
{
|
||||
file = f;
|
||||
best_vpath = vpath_index;
|
||||
best_path = path_index;
|
||||
|
||||
if (mtime_ptr != 0)
|
||||
*mtime_ptr = mtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now try the standard set of directories. */
|
||||
|
||||
if (!buflen)
|
||||
{
|
||||
for (dp = dirs; *dp != 0; ++dp)
|
||||
{
|
||||
int l = strlen (*dp);
|
||||
if (l > libdir_maxlen)
|
||||
libdir_maxlen = l;
|
||||
}
|
||||
buflen = strlen (libbuf);
|
||||
buf = xmalloc(libdir_maxlen + buflen + 2);
|
||||
}
|
||||
{
|
||||
for (dp = dirs; *dp != 0; ++dp)
|
||||
{
|
||||
int l = strlen (*dp);
|
||||
if (l > libdir_maxlen)
|
||||
libdir_maxlen = l;
|
||||
std_dirs++;
|
||||
}
|
||||
buflen = strlen (libbuf);
|
||||
buf = xmalloc(libdir_maxlen + buflen + 2);
|
||||
}
|
||||
else if (buflen < strlen (libbuf))
|
||||
{
|
||||
buflen = strlen (libbuf);
|
||||
buf = xrealloc (buf, libdir_maxlen + buflen + 2);
|
||||
}
|
||||
{
|
||||
buflen = strlen (libbuf);
|
||||
buf = xrealloc (buf, libdir_maxlen + buflen + 2);
|
||||
}
|
||||
|
||||
{
|
||||
/* Use the last std_dirs index for standard directories. This
|
||||
was it will always be greater than the VPATH index. */
|
||||
unsigned int vpath_index = ~((unsigned int)0) - std_dirs;
|
||||
|
||||
for (dp = dirs; *dp != 0; ++dp)
|
||||
{
|
||||
sprintf (buf, "%s/%s", *dp, libbuf);
|
||||
mtime = name_mtime (buf);
|
||||
if (mtime != NONEXISTENT_MTIME)
|
||||
{
|
||||
if (file == 0 || vpath_index < best_vpath)
|
||||
{
|
||||
file = strcache_add (buf);
|
||||
best_vpath = vpath_index;
|
||||
|
||||
if (mtime_ptr != 0)
|
||||
*mtime_ptr = mtime;
|
||||
}
|
||||
}
|
||||
|
||||
vpath_index++;
|
||||
}
|
||||
}
|
||||
|
||||
for (dp = dirs; *dp != 0; ++dp)
|
||||
{
|
||||
sprintf (buf, "%s/%s", *dp, libbuf);
|
||||
mtime = name_mtime (buf);
|
||||
if (mtime != NONEXISTENT_MTIME)
|
||||
{
|
||||
if (mtime_ptr != 0)
|
||||
*mtime_ptr = mtime;
|
||||
file = strcache_add (buf);
|
||||
goto fini;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fini:
|
||||
free (libpatterns);
|
||||
return file;
|
||||
}
|
||||
|
@ -1,3 +1,8 @@
|
||||
2009-11-12 Boris Kolpackov <boris@codesynthesis.com>
|
||||
|
||||
* scripts/features/vpath3: Test for the new library search
|
||||
behavior.
|
||||
|
||||
2009-10-06 Boris Kolpackov <boris@codesynthesis.com>
|
||||
|
||||
* scripts/features/se_explicit: Enable the test for now fixed
|
||||
|
50
tests/scripts/features/vpath3
Normal file
50
tests/scripts/features/vpath3
Normal file
@ -0,0 +1,50 @@
|
||||
# -*-perl-*-
|
||||
|
||||
$description = "Test the interaction of the -lfoo feature and vpath";
|
||||
$details = "";
|
||||
|
||||
open(MAKEFILE,"> $makefile");
|
||||
|
||||
# The Contents of the MAKEFILE ...
|
||||
|
||||
print MAKEFILE "vpath %.a a1\n";
|
||||
print MAKEFILE "vpath %.so b1\n";
|
||||
print MAKEFILE "vpath % a2 b2\n";
|
||||
print MAKEFILE "vpath % b3\n";
|
||||
print MAKEFILE "all: -l1 -l2 -l3; \@echo \$^\n";
|
||||
|
||||
# END of Contents of MAKEFILE
|
||||
|
||||
close(MAKEFILE);
|
||||
|
||||
mkdir("a1", 0777);
|
||||
mkdir("b1", 0777);
|
||||
mkdir("a2", 0777);
|
||||
mkdir("b2", 0777);
|
||||
mkdir("b3", 0777);
|
||||
|
||||
@files_to_touch = ("a1${pathsep}lib1.a",
|
||||
"b1${pathsep}lib1.so",
|
||||
"a2${pathsep}lib2.a",
|
||||
"b2${pathsep}lib2.so",
|
||||
"lib3.a",
|
||||
"b3${pathsep}lib3.so");
|
||||
|
||||
&touch(@files_to_touch);
|
||||
|
||||
&run_make_with_options($makefile,"",&get_logfile);
|
||||
|
||||
# Create the answer to what should be produced by this Makefile
|
||||
$answer = "a1${pathsep}lib1.a a2${pathsep}lib2.a lib3.a\n";
|
||||
|
||||
if (&compare_output($answer,&get_logfile(1)))
|
||||
{
|
||||
unlink @files_to_touch;
|
||||
rmdir("a1");
|
||||
rmdir("b1");
|
||||
rmdir("a2");
|
||||
rmdir("b2");
|
||||
rmdir("b3");
|
||||
}
|
||||
|
||||
1;
|
45
vpath.c
45
vpath.c
@ -320,11 +320,12 @@ gpath_search (const char *file, unsigned int len)
|
||||
/* Search the given VPATH list for a directory where the name pointed to by
|
||||
FILE exists. If it is found, we return a cached name of the existing file
|
||||
and set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no
|
||||
stat call was done). Otherwise we return NULL. */
|
||||
stat call was done). Also set the matching directory index in PATH_INDEX
|
||||
if it is not NULL. Otherwise we return NULL. */
|
||||
|
||||
static const char *
|
||||
selective_vpath_search (struct vpath *path, const char *file,
|
||||
FILE_TIMESTAMP *mtime_ptr)
|
||||
FILE_TIMESTAMP *mtime_ptr, unsigned int* path_index)
|
||||
{
|
||||
int not_target;
|
||||
char *name;
|
||||
@ -504,6 +505,9 @@ selective_vpath_search (struct vpath *path, const char *file,
|
||||
|
||||
/* Store the name we found and return it. */
|
||||
|
||||
if (path_index)
|
||||
*path_index = i;
|
||||
|
||||
return strcache_add_len (name, (p + 1 - name) + flen);
|
||||
}
|
||||
}
|
||||
@ -515,10 +519,12 @@ selective_vpath_search (struct vpath *path, const char *file,
|
||||
/* Search the VPATH list whose pattern matches FILE for a directory where FILE
|
||||
exists. If it is found, return the cached name of an existing file, and
|
||||
set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no
|
||||
stat call was done). Otherwise we return 0. */
|
||||
stat call was done). Also set the matching directory index in VPATH_INDEX
|
||||
and PATH_INDEX if they are not NULL. Otherwise we return 0. */
|
||||
|
||||
const char *
|
||||
vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr)
|
||||
vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr,
|
||||
unsigned int* vpath_index, unsigned int* path_index)
|
||||
{
|
||||
struct vpath *v;
|
||||
|
||||
@ -532,23 +538,40 @@ vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr)
|
||||
|| (vpaths == 0 && general_vpath == 0))
|
||||
return 0;
|
||||
|
||||
if (vpath_index)
|
||||
{
|
||||
*vpath_index = 0;
|
||||
*path_index = 0;
|
||||
}
|
||||
|
||||
for (v = vpaths; v != 0; v = v->next)
|
||||
if (pattern_matches (v->pattern, v->percent, file))
|
||||
{
|
||||
const char *p = selective_vpath_search (v, file, mtime_ptr);
|
||||
if (p)
|
||||
return p;
|
||||
}
|
||||
{
|
||||
if (pattern_matches (v->pattern, v->percent, file))
|
||||
{
|
||||
const char *p = selective_vpath_search (
|
||||
v, file, mtime_ptr, path_index);
|
||||
if (p)
|
||||
return p;
|
||||
}
|
||||
|
||||
if (vpath_index)
|
||||
++*vpath_index;
|
||||
}
|
||||
|
||||
|
||||
if (general_vpath != 0)
|
||||
{
|
||||
const char *p = selective_vpath_search (general_vpath, file, mtime_ptr);
|
||||
const char *p = selective_vpath_search (
|
||||
general_vpath, file, mtime_ptr, path_index);
|
||||
if (p)
|
||||
return p;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Print the data base of VPATH search paths. */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user