summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@kolpackov.net>2009-11-12 16:42:36 +0000
committerBoris Kolpackov <boris@kolpackov.net>2009-11-12 16:42:36 +0000
commitfe43fa9de38d9e1f18bdc1924a2cee72f244bdd5 (patch)
tree7d0ef232e5e4c9b694784fe3b76f5006ced0e5e7
parent5f188b39a49a7eb0d06979b451863dd7ff26a074 (diff)
downloadgunmake-fe43fa9de38d9e1f18bdc1924a2cee72f244bdd5.tar.gz
Implement linker-compatible library search.
-rw-r--r--ChangeLog20
-rw-r--r--NEWS9
-rw-r--r--doc/make.texi11
-rw-r--r--implicit.c2
-rw-r--r--make.h3
-rw-r--r--remake.c101
-rw-r--r--tests/ChangeLog5
-rw-r--r--tests/scripts/features/vpath350
-rw-r--r--vpath.c45
9 files changed, 193 insertions, 53 deletions
diff --git a/ChangeLog b/ChangeLog
index 8ee33c4..e8c89d1 100644
--- a/ChangeLog
+++ b/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.
diff --git a/NEWS b/NEWS
index 661f87b..f452686 100644
--- a/NEWS
+++ b/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
diff --git a/doc/make.texi b/doc/make.texi
index 7a3be3b..7187e19 100644
--- a/doc/make.texi
+++ b/doc/make.texi
@@ -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.
diff --git a/implicit.c b/implicit.c
index 492599f..6e67b71 100644
--- a/implicit.c
+++ b/implicit.c
@@ -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,
diff --git a/make.h b/make.h
index c4b0c32..2841c7f 100644
--- a/make.h
+++ b/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);
diff --git a/remake.c b/remake.c
index 0855ace..8bfd23b 100644
--- a/remake.c
+++ b/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;
}
diff --git a/tests/ChangeLog b/tests/ChangeLog
index f446dcb..eaacaec 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -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
diff --git a/tests/scripts/features/vpath3 b/tests/scripts/features/vpath3
new file mode 100644
index 0000000..978c5ee
--- /dev/null
+++ b/tests/scripts/features/vpath3
@@ -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;
diff --git a/vpath.c b/vpath.c
index 9685468..e9cd691 100644
--- a/vpath.c
+++ b/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. */