* New feature: .LIBPATTERNS controls the way -lfoo dependencies are expanded.

* A few tweaks to the system glob test, after trying it on a system where
  it's true.
* Installed patches to archive handling for AIX 4.3 big archives.
* Fix a memory stomp in target-specific variables.
* Fix a memory leak in foreach functions.
This commit is contained in:
Paul Smith 1999-02-22 07:23:30 +00:00
parent 84f38c9c6f
commit a66668aabc
10 changed files with 324 additions and 143 deletions

View file

@ -1,3 +1,34 @@
1999-02-22 Paul D. Smith <psmith@gnu.org>
* NEWS: Mention new .LIBPATTERNS feature.
* make.texinfo (Libraries/Search): Describe the use and
ramifications of the new .LIBPATTERNS variable.
* remake.c (library_search): Instead of searching only for the
hardcoded expansion "libX.a" for a library reference "-lX", we
obtain a list of patterns from the .LIBPATTERNS variable and
search those in order.
* default.c: Added a new default variable .LIBPATTERNS. The
default for UNIX is "lib%.so lib%.a". Amiga and DOS values are
also provided.
* read.c: Remove bogus HAVE_GLOB_H references; always include
vanilla glob.h.
1999-02-21 Paul D. Smith <psmith@gnu.org>
* function.c (expand_function): Set value to 0 to avoid freeing it.
* variable.c (pop_variable_scope): Free the value of the variable.
(try_variable_definition): For simple variables, use
allocated_variable_expand() to avoid stomping on the variable
buffer when we still need it for other things.
* arscan.c: Modified to support AIX 4.3 big archives. The changes
are based on information provided by Phil Adams
<padams@austin.ibm.com>; thanks!
1999-02-19 Paul D. Smith <psmith@gnu.org>
* configure.in: Check to see if the GNU glob library is already

26
NEWS
View file

@ -1,12 +1,21 @@
GNU make NEWS -*-indented-text-*-
History of user-visible changes.
19 May 1998
22 Feb 1999
Copyright (C) 1992,1993,1994,1995,1996,1997,1998 Free Software Foundation, Inc.
Copyright (C) 1992,93,94,95,96,97,98,1999 Free Software Foundation, Inc.
See the end for copying conditions.
All changes mentioned here are more fully described in the GNU make
manual, which is contained in this distribution as the file make.texinfo.
Please send GNU make bug reports to bug-make@gnu.org.
Version 3.78
* Make defines a new variable, .LIBPATTERNS. This variable controls how
the link library dependency expansion (dependencies like ``-lfoo'') is
performed.
Version 3.77
* Implement BSD make's "?=" variable assignment operator. The variable
@ -659,17 +668,14 @@ Version 3.05
----------------------------------------------------------------------
Copyright information:
Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
copyright notice and this permission notice are preserved,
thus giving the recipient permission to redistribute in turn.
copyright notice and this permission notice are preserved, thus
giving the recipient permission to redistribute in turn.
Permission is granted to distribute modified versions
of this document, or of portions of it,
under the above conditions, provided also that they
carry prominent notices stating who last changed them.
Permission is granted to distribute modified versions of this
document, or of portions of it, under the above conditions, provided
also that they carry prominent notices stating who last changed them.
Local variables:
version-control: never

198
arscan.c
View file

@ -213,11 +213,28 @@ ar_scan (archive, function, arg)
#endif
#endif
/* On AIX, define these symbols to be sure to get both archive formats.
AIX 4.3 introduced the "big" archive format to support 64-bit object
files, so on AIX 4.3 systems we need to support both the "normal" and
"big" archive formats. An archive's format is indicated in the
"fl_magic" field of the "FL_HDR" structure. For a normal archive,
this field will be the string defined by the AIAMAG symbol. For a
"big" archive, it will be the string defined by the AIAMAGBIG symbol
(at least on AIX it works this way).
Note: we'll define these symbols regardless of which AIX version
we're compiling on, but this is okay since we'll use the new symbols
only if they're present. */
#ifdef _AIX
# define __AR_SMALL__
# define __AR_BIG__
#endif
#include <ar.h>
/* Cray's <ar.h> apparently defines this. */
#ifndef AR_HDR_SIZE
#define AR_HDR_SIZE (sizeof (struct ar_hdr))
# define AR_HDR_SIZE (sizeof (struct ar_hdr))
#endif
/* Takes three arguments ARCHIVE, FUNCTION and ARG.
@ -255,6 +272,10 @@ ar_scan (archive, function, arg)
{
#ifdef AIAMAG
FL_HDR fl_header;
#ifdef AIAMAGBIG
int big_archive = 0;
FL_HDR_BIG fl_header_big;
#endif
#else
int long_name = 0;
#endif
@ -276,11 +297,42 @@ ar_scan (archive, function, arg)
#ifdef AIAMAG
{
register int nread = read (desc, (char *) &fl_header, FL_HSZ);
if (nread != FL_HSZ || bcmp (fl_header.fl_magic, AIAMAG, SAIAMAG))
if (nread != FL_HSZ)
{
(void) close (desc);
return -2;
}
#ifdef AIAMAGBIG
/* If this is a "big" archive, then set the flag and
re-read the header into the "big" structure. */
if (!bcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG))
{
big_archive = 1;
/* seek back to beginning of archive */
if (lseek (desc, 0, 0) < 0)
{
(void) close (desc);
return -2;
}
/* re-read the header into the "big" structure */
nread = read (desc, (char *) &fl_header_big, FL_HSZ_BIG);
if (nread != FL_HSZ_BIG)
{
(void) close (desc);
return -2;
}
}
else
#endif
/* Check to make sure this is a "normal" archive. */
if (bcmp (fl_header.fl_magic, AIAMAG, SAIAMAG))
{
(void) close (desc);
return -2;
}
}
#else
{
@ -308,8 +360,18 @@ ar_scan (archive, function, arg)
long int member_offset;
long int last_member_offset;
sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset);
sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset);
#ifdef AIAMAGBIG
if ( big_archive )
{
sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset);
sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset);
}
else
#endif
{
sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset);
sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset);
}
if (member_offset == 0)
{
@ -330,6 +392,9 @@ ar_scan (archive, function, arg)
{
register int nread;
struct ar_hdr member_header;
#ifdef AIAMAGBIG
struct ar_hdr_big member_header_big;
#endif
#ifdef AIAMAG
char name[256];
int name_len;
@ -352,34 +417,73 @@ ar_scan (archive, function, arg)
}
#ifdef AIAMAG
#define AR_MEMHDR (AR_HDR_SIZE - sizeof (member_header._ar_name))
nread = read (desc, (char *) &member_header, AR_MEMHDR);
#define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
if (nread != AR_MEMHDR)
#ifdef AIAMAGBIG
if (big_archive)
{
(void) close (desc);
return -2;
nread = read (desc, (char *) &member_header_big,
AR_MEMHDR_SZ(member_header_big) );
if (nread != AR_MEMHDR_SZ(member_header_big))
{
(void) close (desc);
return -2;
}
sscanf (member_header_big.ar_namlen, "%4d", &name_len);
nread = read (desc, name, name_len);
if (nread != name_len)
{
(void) close (desc);
return -2;
}
name[name_len] = 0;
sscanf (member_header_big.ar_date, "%12ld", &dateval);
sscanf (member_header_big.ar_uid, "%12d", &uidval);
sscanf (member_header_big.ar_gid, "%12d", &gidval);
sscanf (member_header_big.ar_mode, "%12o", &eltmode);
sscanf (member_header_big.ar_size, "%20ld", &eltsize);
data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big)
+ name_len + 2);
}
sscanf (member_header.ar_namlen, "%4d", &name_len);
nread = read (desc, name, name_len);
if (nread != name_len)
else
#endif
{
(void) close (desc);
return -2;
nread = read (desc, (char *) &member_header,
AR_MEMHDR_SZ(member_header) );
if (nread != AR_MEMHDR_SZ(member_header))
{
(void) close (desc);
return -2;
}
sscanf (member_header.ar_namlen, "%4d", &name_len);
nread = read (desc, name, name_len);
if (nread != name_len)
{
(void) close (desc);
return -2;
}
name[name_len] = 0;
sscanf (member_header.ar_date, "%12ld", &dateval);
sscanf (member_header.ar_uid, "%12d", &uidval);
sscanf (member_header.ar_gid, "%12d", &gidval);
sscanf (member_header.ar_mode, "%12o", &eltmode);
sscanf (member_header.ar_size, "%12ld", &eltsize);
data_offset = (member_offset + AR_MEMHDR_SZ(member_header)
+ name_len + 2);
}
name[name_len] = 0;
sscanf (member_header.ar_date, "%12ld", &dateval);
sscanf (member_header.ar_uid, "%12d", &uidval);
sscanf (member_header.ar_gid, "%12d", &gidval);
sscanf (member_header.ar_mode, "%12o", &eltmode);
sscanf (member_header.ar_size, "%12ld", &eltsize);
if ((data_offset = member_offset + AR_MEMHDR + name_len + 2) % 2)
++data_offset;
data_offset += data_offset % 2;
fnval =
(*function) (desc, name, 0,
@ -493,7 +597,12 @@ ar_scan (archive, function, arg)
/* End of the chain. */
break;
sscanf (member_header.ar_nxtmem, "%12ld", &member_offset);
#ifdef AIAMAGBIG
if (big_archive)
sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset);
else
#endif
sscanf (member_header.ar_nxtmem, "%12ld", &member_offset);
if (lseek (desc, member_offset, 0) != member_offset)
{
@ -562,37 +671,6 @@ ar_name_equal (name, mem, truncated)
if (p != 0)
name = p + 1;
/* We no longer use this kludge, since we
now support long archive member names. */
#if 0 && !defined (AIAMAG) && !defined (APOLLO)
{
/* `reallylongname.o' matches `reallylongnam.o'.
If member names have a trailing slash, that's `reallylongna.o'. */
struct ar_hdr h;
unsigned int max = sizeof (h.ar_name);
unsigned int namelen, memlen;
if (strncmp (name, mem, max - 3))
return 0;
namelen = strlen (name);
memlen = strlen (mem);
if (namelen > memlen && memlen >= max - 1
&& name[namelen - 2] == '.' && name[namelen - 1] == 'o'
&& mem[memlen - 2] == '.' && mem[memlen - 1] == 'o')
return 1;
if (namelen != memlen)
return 0;
return (namelen < max - 3 || !strcmp (name + max - 3, mem + max - 3));
}
#else /* AIX or APOLLO. */
#ifndef VMS
if (truncated)
{
@ -611,8 +689,6 @@ ar_name_equal (name, mem, truncated)
#endif /* !VMS */
return !strcmp (name, mem);
#endif
}
#ifndef VMS

View file

@ -154,17 +154,20 @@ rm -f s.conftest conftoast
AC_MSG_CHECKING(if system libc has GNU glob)
AC_CACHE_VAL(make_cv_sys_gnu_glob, [
AC_TRY_CPP([
#include <features.h>
#include <glob.h>
#include <fnmatch.h>
#define GLOB_INTERFACE_VERSION 1
#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
#if defined _LIBC || !defined __GNU_LIBRARY__ || __GNU_LIBRARY__ <= 1
# error no gnu glob
#else
# include <gnu-versions.h>
# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
# error have gnu glob
# if _GNU_GLOB_INTERFACE_VERSION != GLOB_INTERFACE_VERSION
# error no gnu glob
# endif
#endif
], make_cv_sys_gnu_glob=no, make_cv_sys_gnu_glob=yes)])
], make_cv_sys_gnu_glob=yes, make_cv_sys_gnu_glob=no)])
case "$make_cv_sys_gnu_glob" in
yes) AC_MSG_RESULT(yes) ;;
no) AC_MSG_RESULT([no; using local copy])

View file

@ -425,6 +425,16 @@ static char *default_variables[] =
"SCCS_OUTPUT_OPTION", "-G$@",
#endif
#ifdef _AMIGA
".LIBPATTERNS", "%.lib",
#else
#ifdef __MSDOS__
".LIBPATTERNS", "lib%.a $(DJDIR)/lib/lib%.a",
#else
".LIBPATTERNS", "lib%.so lib%.a",
#endif
#endif
#endif /* !VMS */
0, 0
};

View file

@ -876,6 +876,7 @@ expand_function (o, function, text, end)
/* Kill the last space. */
--o;
v->value = 0;
pop_variable_scope ();
free (var);

View file

@ -1971,16 +1971,19 @@ directory search with no extra effort.
@cindex @code{VPATH}, and link libraries
@cindex search path for dependencies (@code{VPATH}), and link libraries
@cindex @code{-l} (library search)
@cindex link libraries, patterns matching
@cindex @code{.LIBPATTERNS}, and link libraries
@vindex .LIBPATTERNS
Directory search applies in a special way to libraries used with the
linker. This special feature comes into play when you write a dependency
whose name is of the form @samp{-l@var{name}}. (You can tell something
strange is going on here because the dependency is normally the name of a
file, and the @emph{file name} of the library looks like
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 dependency's name has the form @samp{-l@var{name}}, @code{make}
handles it specially by searching for the file @file{lib@var{name}.a} in
handles it specially by searching for the file @file{lib@var{name}.so} 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}
@ -1988,7 +1991,11 @@ directories @file{/lib}, @file{/usr/lib}, and @file{@var{prefix}/lib}
@code{make} behave as if @var{prefix} is defined to be the root of the
DJGPP installation tree).
For example,
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
@example
@group
@ -2002,6 +2009,21 @@ would cause the command @samp{cc foo.c /usr/lib/libcurses.a -o foo} to
be executed when @file{foo} is older than @file{foo.c} or than
@file{/usr/lib/libcurses.a}.@refill
Although the default set of files to be searched for is
@file{lib@var{name}.so} and @file{lib@var{name}.a}, this is customizable
via the @code{.LIBPATTERNS} variable. Each word in the value of this
variable is a pattern string. When a dependency 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.
The default value for @code{.LIBPATTERNS} is ``@samp{lib%.so lib%.a}'',
which provides the default behavior described above.
You can turn off link library expansion completely by setting this
variable to an empty value.
@node Phony Targets, Force Targets, Directory Search, Rules
@section Phony Targets
@cindex phony targets

12
read.c
View file

@ -18,6 +18,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <assert.h>
#include <glob.h>
#include "make.h"
#include "dep.h"
#include "filedef.h"
@ -26,12 +28,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "variable.h"
#include "rule.h"
/* This is POSIX.2, but most systems using -DPOSIX probably don't have it. */
#ifdef HAVE_GLOB_H
#include <glob.h>
#else
#include "glob/glob.h"
#endif
#ifndef WINDOWS32
#ifndef _AMIGA
@ -1564,9 +1560,7 @@ record_files (filenames, pattern, pattern_percent, deps, cmds_started,
if (!pattern_matches (pattern, pattern_percent, name))
{
/* Give a warning if the rule is meaningless. */
error (flocp,
"target `%s' doesn't match the target pattern",
name);
error (flocp,"target `%s' doesn't match the target pattern", name);
this = 0;
}
else

137
remake.c
View file

@ -21,6 +21,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "job.h"
#include "commands.h"
#include "dep.h"
#include "variable.h"
#include <assert.h>
#ifdef HAVE_FCNTL_H
@ -1188,82 +1190,111 @@ library_search (lib, mtime_ptr)
0
};
static char *libpatterns = NULL;
char *libname = &(*lib)[2]; /* Name without the `-l'. */
FILE_TIMESTAMP mtime;
/* Buffer to construct possible names in. */
char *buf = xmalloc (sizeof (LIBDIR) + 8 + strlen (libname) + 4 + 2 + 1);
/* Loop variables for the libpatterns value. */
char *p, *p2;
int len;
char *file, **dp;
/* Look first for `libNAME.a' in the current directory. */
#ifndef _AMIGA
sprintf (buf, "lib%s.a", libname);
#else
sprintf (buf, "%s.lib", libname);
#endif
mtime = name_mtime (buf);
if (mtime != (FILE_TIMESTAMP) -1)
/* If we don't have libpatterns, get it. */
if (!libpatterns)
{
*lib = buf;
if (mtime_ptr != 0)
*mtime_ptr = mtime;
return 1;
int save = warn_undefined_variables_flag;
warn_undefined_variables_flag = 0;
libpatterns = strdup (variable_expand ("$(strip $(.LIBPATTERNS))"));
warn_undefined_variables_flag = save;
}
/* Now try VPATH search on that. */
file = buf;
if (vpath_search (&file, mtime_ptr))
/* Loop through all the patterns in .LIBPATTERNS, and search on each one. */
p2 = libpatterns;
while ((p = find_next_token (&p2, &len)) != 0)
{
free (buf);
*lib = file;
return 1;
}
static char *buf = NULL;
static int buflen = 0;
static int libdir_maxlen = -1;
char *libbuf = variable_expand ("");
/* Now try the standard set of directories. */
#ifdef __MSDOS__
{
/* The default library directory is at ${DJDIR}/lib. */
struct variable *djdir = lookup_variable ("DJDIR", 5);
if (djdir)
/* Expand the pattern using LIBNAME as a replacement. */
{
size_t djdir_len = strlen (djdir->value);
char c = p[len];
char *p3, *p4;
if (djdir_len > sizeof(LIBDIR) + 8 + strlen(libname) + 4 + 2)
buf = (char *) xrealloc (djdir_len + 1);
sprintf (buf, "%s/lib/lib%s.a", djdir->value, libname);
mtime = name_mtime (buf);
if (mtime != (FILE_TIMESTAMP) -1)
p[len] = '\0';
p3 = find_percent (p);
if (!p3)
{
*lib = buf;
if (mtime_ptr != 0)
*mtime_ptr = mtime;
return 1;
/* Give a warning if there is no pattern, then remove the
pattern so it's ignored next time. */
error (NILF, ".LIBPATTERNS element `%s' is not a pattern", p);
for (; len; --len, ++p)
*p = ' ';
*p = c;
continue;
}
p4 = variable_buffer_output (libbuf, p, p3-p);
p4 = variable_buffer_output (p4, libname, strlen (libname));
p4 = variable_buffer_output (p4, p3+1, len - (p3-p));
p[len] = c;
}
}
#endif
for (dp = dirs; *dp != 0; ++dp)
{
#ifndef _AMIGA
sprintf (buf, "%s/lib%s.a", *dp, libname);
#else
sprintf (buf, "%s/%s.lib", *dp, libname);
#endif
mtime = name_mtime (buf);
/* Look first for `libNAME.a' in the current directory. */
mtime = name_mtime (libbuf);
if (mtime != (FILE_TIMESTAMP) -1)
{
*lib = buf;
*lib = strdup (libbuf);
if (mtime_ptr != 0)
*mtime_ptr = mtime;
return 1;
}
/* Now try VPATH search on that. */
file = libbuf;
if (vpath_search (&file, mtime_ptr))
{
*lib = file;
return 1;
}
/* 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);
}
else if (buflen < strlen (libbuf))
{
buflen = strlen (libbuf);
buf = xrealloc (buf, libdir_maxlen + buflen + 2);
}
for (dp = dirs; *dp != 0; ++dp)
{
sprintf (buf, "%s/%s", *dp, libbuf);
mtime = name_mtime (buf);
if (mtime != (FILE_TIMESTAMP) -1)
{
*lib = strdup (buf);
if (mtime_ptr != 0)
*mtime_ptr = mtime;
return 1;
}
}
}
free (buf);
return 0;
}

View file

@ -265,6 +265,8 @@ pop_variable_scope ()
next = v->next;
free (v->name);
if (v->value)
free (v->value);
free ((char *) v);
}
}
@ -687,7 +689,7 @@ try_variable_definition (flocp, line, origin)
register char *end;
enum { f_bogus,
f_simple, f_recursive, f_append, f_conditional } flavor = f_bogus;
char *name, *expanded_name, *value;
char *name, *expanded_name, *value, *alloc_value=NULL;
struct variable *v;
while (1)
@ -775,8 +777,11 @@ try_variable_definition (flocp, line, origin)
/* Should not be possible. */
abort ();
case f_simple:
/* A simple variable definition "var := value". Expand the value. */
value = variable_expand (p);
/* A simple variable definition "var := value". Expand the value.
We have to allocate memory since otherwise it'll clobber the
variable buffer, and we still need that. */
alloc_value = allocated_variable_expand (p);
value = alloc_value;
break;
case f_conditional:
/* A conditional variable definition "var ?= value".
@ -931,6 +936,8 @@ try_variable_definition (flocp, line, origin)
v = define_variable (expanded_name, strlen (expanded_name),
value, origin, flavor == f_recursive);
if (alloc_value)
free (alloc_value);
free (expanded_name);
return v;