mirror of
https://github.com/mirror/make.git
synced 2025-01-27 12:51:07 +08:00
- Fix broken handling of order-only prereqs in secondary expansion
of implicit rules. - Fix leaked memory when dealing with implicit rule chains that have file variables or pattern variables.
This commit is contained in:
parent
0afbbf8595
commit
d65b267e4a
12
ChangeLog
12
ChangeLog
@ -1,4 +1,14 @@
|
||||
2009-09-23 Paul <psmith@gnu.org>
|
||||
2009-09-24 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* implicit.c (pattern_search): Add back support for order-only
|
||||
prerequisites for secondary expansion implicit rules, that were
|
||||
accidentally dropped. If we find a "|", enable order-only mode
|
||||
and set IGNORE_MTIME on all deps that are seen afterward.
|
||||
(pattern_search): Fix memory leaks: for intermediate files where
|
||||
we've already set the file variable and pattern variable sets, be
|
||||
sure to either save or free them as appropriate.
|
||||
|
||||
2009-09-23 Paul Smith <psmith@gnu.org>
|
||||
|
||||
Rework the way secondary expansion is stored, for efficiency.
|
||||
This changes secondary expansion so that ONLY WHEN we know we have
|
||||
|
111
implicit.c
111
implicit.c
@ -1,7 +1,7 @@
|
||||
/* Implicit rule searching for GNU Make.
|
||||
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
|
||||
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
|
||||
Foundation, Inc.
|
||||
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 Free
|
||||
Software Foundation, Inc.
|
||||
This file is part of GNU Make.
|
||||
|
||||
GNU Make is free software; you can redistribute it and/or modify it under the
|
||||
@ -145,7 +145,7 @@ get_next_word (const char *buffer, unsigned int *length)
|
||||
}
|
||||
|
||||
/* This structure stores information about the expanded prerequisites for a
|
||||
pattern rule. NAME is always set, to the strcache'd name of the prereq.
|
||||
pattern rule. NAME is always set to the strcache'd name of the prereq.
|
||||
FILE and PATTERN will be set for intermediate files only. IGNORE_MTIME is
|
||||
copied from the prerequisite we expanded.
|
||||
*/
|
||||
@ -230,7 +230,7 @@ pattern_search (struct file *file, int archive,
|
||||
that is not just `%'. */
|
||||
int specific_rule_matched = 0;
|
||||
|
||||
struct nameseq ns_simple;
|
||||
struct dep dep_simple;
|
||||
|
||||
unsigned int ri; /* uninit checks OK */
|
||||
struct rule *rule;
|
||||
@ -273,8 +273,6 @@ pattern_search (struct file *file, int archive,
|
||||
|
||||
pathlen = lastslash - filename + 1;
|
||||
|
||||
ns_simple.next = 0;
|
||||
|
||||
/* First see which pattern rules match this target and may be considered.
|
||||
Put them in TRYRULES. */
|
||||
|
||||
@ -415,12 +413,14 @@ pattern_search (struct file *file, int archive,
|
||||
for (ri = 0; ri < nrules; ri++)
|
||||
{
|
||||
struct dep *dep;
|
||||
unsigned int failed = 0;
|
||||
int check_lastslash;
|
||||
unsigned int failed = 0;
|
||||
int file_variables_set = 0;
|
||||
unsigned int deps_found = 0;
|
||||
/* NPTR points to the part of the prereq we haven't processed. */
|
||||
const char *nptr = 0;
|
||||
const char *dir = NULL;
|
||||
int order_only = 0;
|
||||
|
||||
rule = tryrules[ri];
|
||||
|
||||
@ -444,6 +444,15 @@ pattern_search (struct file *file, int archive,
|
||||
{
|
||||
stem += pathlen;
|
||||
stemlen -= pathlen;
|
||||
|
||||
/* We need to add the directory prefix, so set it up. */
|
||||
if (! pathdir)
|
||||
{
|
||||
pathdir = alloca (pathlen + 1);
|
||||
memcpy (pathdir, filename, pathlen);
|
||||
pathdir[pathlen] = '\0';
|
||||
}
|
||||
dir = pathdir;
|
||||
}
|
||||
|
||||
DBS (DB_IMPLICIT, (_("Trying pattern rule with stem `%.*s'.\n"),
|
||||
@ -473,22 +482,9 @@ pattern_search (struct file *file, int archive,
|
||||
nptr = dep_name (dep);
|
||||
while (1)
|
||||
{
|
||||
const char *dir = NULL;
|
||||
struct nameseq *ns, *n;
|
||||
struct dep *dl, *d;
|
||||
char *p;
|
||||
|
||||
/* If we need to add the directory prefix set it up. */
|
||||
if (check_lastslash)
|
||||
{
|
||||
if (! pathdir)
|
||||
{
|
||||
pathdir = alloca (pathlen + 1);
|
||||
memcpy (pathdir, filename, pathlen);
|
||||
pathdir[pathlen] = '\0';
|
||||
}
|
||||
dir = pathdir;
|
||||
}
|
||||
|
||||
/* If we're out of name to parse, start the next prereq. */
|
||||
if (! nptr)
|
||||
{
|
||||
@ -501,9 +497,11 @@ pattern_search (struct file *file, int archive,
|
||||
/* If we don't need a second expansion, just replace the %. */
|
||||
if (! dep->need_2nd_expansion)
|
||||
{
|
||||
dep_simple = *dep;
|
||||
dep_simple.next = 0;
|
||||
p = strchr (nptr, '%');
|
||||
if (p == 0)
|
||||
ns_simple.name = nptr;
|
||||
dep_simple.name = nptr;
|
||||
else
|
||||
{
|
||||
char *o = depname;
|
||||
@ -517,9 +515,9 @@ pattern_search (struct file *file, int archive,
|
||||
memcpy (o, stem_str, stemlen);
|
||||
o += stemlen;
|
||||
strcpy (o, p + 1);
|
||||
ns_simple.name = strcache_add (depname);
|
||||
dep_simple.name = strcache_add (depname);
|
||||
}
|
||||
ns = &ns_simple;
|
||||
dl = &dep_simple;
|
||||
|
||||
/* We've used up this dep, so next time get a new one. */
|
||||
nptr = 0;
|
||||
@ -537,7 +535,6 @@ pattern_search (struct file *file, int archive,
|
||||
resulting prerequisite. */
|
||||
else
|
||||
{
|
||||
int order_only = 0;
|
||||
int add_dir = 0;
|
||||
unsigned int len;
|
||||
|
||||
@ -545,6 +542,14 @@ pattern_search (struct file *file, int archive,
|
||||
if (nptr == 0)
|
||||
continue;
|
||||
|
||||
/* See this is a transition to order-only prereqs. */
|
||||
if (! order_only && len == 1 && nptr[0] == '|')
|
||||
{
|
||||
order_only = 1;
|
||||
nptr += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the dependency name has %, substitute the stem. If we
|
||||
just replace % with the stem value then later, when we do
|
||||
the 2nd expansion, we will re-expand this stem value
|
||||
@ -587,12 +592,15 @@ pattern_search (struct file *file, int archive,
|
||||
p = variable_expand_for_file (depname, file);
|
||||
|
||||
/* Parse the expanded string. */
|
||||
ns = parse_file_seq (&p, sizeof (struct dep),
|
||||
order_only ? '\0' : '|',
|
||||
dl = PARSE_FILE_SEQ (&p, struct dep, order_only ? '\0' : '|',
|
||||
add_dir ? dir : NULL, 0);
|
||||
|
||||
for (n = ns; n != NULL; n = n->next)
|
||||
for (d = dl; d != NULL; d = d->next)
|
||||
{
|
||||
++deps_found;
|
||||
if (order_only)
|
||||
d->ignore_mtime = 1;
|
||||
}
|
||||
|
||||
/* Set up for the next word. */
|
||||
nptr += len;
|
||||
@ -611,12 +619,12 @@ pattern_search (struct file *file, int archive,
|
||||
}
|
||||
|
||||
/* Go through the nameseq and handle each as a prereq name. */
|
||||
for (n = ns; n != 0; n = n->next)
|
||||
for (d = dl; d != 0; d = d->next)
|
||||
{
|
||||
struct dep *expl_d;
|
||||
int is_rule = n->name == dep_name (dep);
|
||||
int is_rule = d->name == dep_name (dep);
|
||||
|
||||
if (file_impossible_p (n->name))
|
||||
if (file_impossible_p (d->name))
|
||||
{
|
||||
/* If this prereq has already been ruled "impossible",
|
||||
then the rule fails. Don't bother trying it on the
|
||||
@ -625,7 +633,7 @@ pattern_search (struct file *file, int archive,
|
||||
(is_rule
|
||||
? _("Rejecting impossible rule prerequisite `%s'.\n")
|
||||
: _("Rejecting impossible implicit prerequisite `%s'.\n"),
|
||||
n->name));
|
||||
d->name));
|
||||
tryrules[ri] = 0;
|
||||
|
||||
failed = 1;
|
||||
@ -633,23 +641,23 @@ pattern_search (struct file *file, int archive,
|
||||
}
|
||||
|
||||
memset (pat, '\0', sizeof (struct patdeps));
|
||||
pat->ignore_mtime = dep->ignore_mtime;
|
||||
pat->ignore_mtime = d->ignore_mtime;
|
||||
|
||||
DBS (DB_IMPLICIT,
|
||||
(is_rule
|
||||
? _("Trying rule prerequisite `%s'.\n")
|
||||
: _("Trying implicit prerequisite `%s'.\n"), n->name));
|
||||
: _("Trying implicit prerequisite `%s'.\n"), d->name));
|
||||
|
||||
/* If this prereq is also explicitly mentioned for FILE,
|
||||
skip all tests below since it must be built no matter
|
||||
which implicit rule we choose. */
|
||||
|
||||
for (expl_d = file->deps; expl_d != 0; expl_d = expl_d->next)
|
||||
if (streq (dep_name (expl_d), n->name))
|
||||
if (streq (dep_name (expl_d), d->name))
|
||||
break;
|
||||
if (expl_d != 0)
|
||||
{
|
||||
(pat++)->name = n->name;
|
||||
(pat++)->name = d->name;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -661,11 +669,11 @@ pattern_search (struct file *file, int archive,
|
||||
FILENAME's directory), so it might actually exist. */
|
||||
|
||||
/* @@ dep->changed check is disabled. */
|
||||
if (lookup_file (n->name) != 0
|
||||
if (lookup_file (d->name) != 0
|
||||
/*|| ((!dep->changed || check_lastslash) && */
|
||||
|| file_exists_p (n->name))
|
||||
|| file_exists_p (d->name))
|
||||
{
|
||||
(pat++)->name = n->name;
|
||||
(pat++)->name = d->name;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -673,13 +681,13 @@ pattern_search (struct file *file, int archive,
|
||||
"lib/foo.c", and VPATH=src, searches for
|
||||
"src/lib/foo.c". */
|
||||
{
|
||||
const char *vname = vpath_search (n->name, 0);
|
||||
const char *vname = vpath_search (d->name, 0);
|
||||
if (vname)
|
||||
{
|
||||
DBS (DB_IMPLICIT,
|
||||
(_("Found prerequisite `%s' as VPATH `%s'\n"),
|
||||
n->name, vname));
|
||||
(pat++)->name = n->name;
|
||||
d->name, vname));
|
||||
(pat++)->name = d->name;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -692,12 +700,12 @@ pattern_search (struct file *file, int archive,
|
||||
{
|
||||
DBS (DB_IMPLICIT,
|
||||
(_("Looking for a rule with intermediate file `%s'.\n"),
|
||||
n->name));
|
||||
d->name));
|
||||
|
||||
if (int_file == 0)
|
||||
int_file = alloca (sizeof (struct file));
|
||||
memset (int_file, '\0', sizeof (struct file));
|
||||
int_file->name = n->name;
|
||||
int_file->name = d->name;
|
||||
|
||||
if (pattern_search (int_file,
|
||||
0,
|
||||
@ -705,9 +713,9 @@ pattern_search (struct file *file, int archive,
|
||||
recursions + 1))
|
||||
{
|
||||
pat->pattern = int_file->name;
|
||||
int_file->name = n->name;
|
||||
int_file->name = d->name;
|
||||
pat->file = int_file;
|
||||
(pat++)->name = n->name;
|
||||
(pat++)->name = d->name;
|
||||
int_file = 0;
|
||||
continue;
|
||||
}
|
||||
@ -717,7 +725,9 @@ pattern_search (struct file *file, int archive,
|
||||
go through the search again later. */
|
||||
if (int_file->variables)
|
||||
free_variable_set (int_file->variables);
|
||||
file_impossible (n->name);
|
||||
if (int_file->pat_variables)
|
||||
free_variable_set (int_file->pat_variables);
|
||||
file_impossible (d->name);
|
||||
}
|
||||
|
||||
/* A dependency of this rule does not exist. Therefore, this
|
||||
@ -727,8 +737,8 @@ pattern_search (struct file *file, int archive,
|
||||
}
|
||||
|
||||
/* Free the ns chain. */
|
||||
if (ns != &ns_simple)
|
||||
free_ns_chain (ns);
|
||||
if (dl != &dep_simple)
|
||||
free_dep_chain (dl);
|
||||
|
||||
if (failed)
|
||||
break;
|
||||
@ -803,6 +813,9 @@ pattern_search (struct file *file, int archive,
|
||||
f->deps = imf->deps;
|
||||
f->cmds = imf->cmds;
|
||||
f->stem = imf->stem;
|
||||
f->variables = imf->variables;
|
||||
f->pat_variables = imf->pat_variables;
|
||||
f->pat_searched = imf->pat_searched;
|
||||
f->also_make = imf->also_make;
|
||||
f->is_target = 1;
|
||||
f->intermediate = 1;
|
||||
|
@ -1,4 +1,9 @@
|
||||
2009-09-23 Paul <psmith@gnu.org>
|
||||
2009-09-24 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/features/se_implicit: Add a test for order-only
|
||||
secondary expansion prerequisites.
|
||||
|
||||
2009-09-23 Paul Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/features/patternrules: Test that we can remove pattern
|
||||
rules, both single and multiple prerequisites. Savannah bug #18622.
|
||||
|
@ -210,6 +210,17 @@ oo$ba.1
|
||||
oo$ba
|
||||
');
|
||||
|
||||
# Test #9: Check the value of $^
|
||||
run_make_test(q!
|
||||
.SECONDEXPANSION:
|
||||
|
||||
%.so: | $$(extra) ; @echo $^
|
||||
|
||||
foo.so: extra := foo.o
|
||||
foo.so:
|
||||
foo.o:
|
||||
!,
|
||||
'', "\n");
|
||||
|
||||
# This tells the test driver that the perl test script executed properly.
|
||||
1;
|
||||
|
Loading…
Reference in New Issue
Block a user