Import GNU Make 4.4.1

Landlock Make hasn't been working well on AARCH64 systems. Let's do this
over the right way, using our new build tools.
This commit is contained in:
Justine Tunney 2023-11-30 20:50:10 -08:00
parent 9315ebbfd9
commit 14bf57180f
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
88 changed files with 13931 additions and 16191 deletions

View file

@ -1,5 +1,5 @@
/* Implicit rule searching for GNU Make.
Copyright (C) 1988-2020 Free Software Foundation, Inc.
Copyright (C) 1988-2023 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
@ -12,19 +12,22 @@ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>. */
this program. If not, see <https://www.gnu.org/licenses/>. */
#include "third_party/make/makeint.inc"
#include "third_party/make/filedef.h"
#include "third_party/make/rule.h"
#include "third_party/make/dep.h"
#include "third_party/make/debug.h"
#include "third_party/make/variable.h"
#include "third_party/make/job.h" /* struct child, used inside commands.h */
#include "third_party/make/commands.h" /* set_file_variables */
#include "makeint.h"
#include "filedef.h"
#include "rule.h"
#include "dep.h"
#include "debug.h"
#include "variable.h"
#include "job.h" /* struct child, used inside commands.h */
#include "commands.h" /* set_file_variables */
#include "shuffle.h"
#include <assert.h>
static int pattern_search (struct file *file, int archive,
unsigned int depth, unsigned int recursions);
unsigned int depth, unsigned int recursions,
int allow_compat_rules);
/* For a FILE which has no commands specified, try to figure out some
from the implicit pattern rules.
@ -42,7 +45,7 @@ try_implicit_rule (struct file *file, unsigned int depth)
(the archive search omits the archive name), it is more specific and
should come first. */
if (pattern_search (file, 0, depth, 0))
if (pattern_search (file, 0, depth, 0, 0))
return 1;
#ifndef NO_ARCHIVES
@ -52,8 +55,11 @@ try_implicit_rule (struct file *file, unsigned int depth)
{
DBF (DB_IMPLICIT,
_("Looking for archive-member implicit rule for '%s'.\n"));
if (pattern_search (file, 1, depth, 0))
if (pattern_search (file, 1, depth, 0, 0))
return 1;
DBS (DB_IMPLICIT,
(_("No archive-member implicit rule found for '%s'.\n"),
file->name));
}
#endif
@ -153,6 +159,8 @@ struct patdeps
struct file *file;
unsigned int ignore_mtime : 1;
unsigned int ignore_automatic_vars : 1;
unsigned int is_explicit : 1;
unsigned int wait_here : 1;
};
/* This structure stores information about pattern rules that we need
@ -200,7 +208,8 @@ stemlen_compare (const void *v1, const void *v2)
static int
pattern_search (struct file *file, int archive,
unsigned int depth, unsigned int recursions)
unsigned int depth, unsigned int recursions,
int allow_compat_rules)
{
/* Filename we are searching for a rule for. */
const char *filename = archive ? strchr (file->name, '(') : file->name;
@ -223,7 +232,11 @@ pattern_search (struct file *file, int archive,
/* Names of possible dependencies are constructed in this buffer.
We may replace % by $(*F) for second expansion, increasing the length. */
char *depname = alloca (namelen + max_pattern_dep_length + 4);
size_t deplen = namelen + max_pattern_dep_length + 4;
char *depname = alloca (deplen);
#ifndef NDEBUG
char *dend = depname + deplen;
#endif
/* The start and length of the stem of FILENAME for the current rule. */
const char *stem = 0;
@ -251,6 +264,7 @@ pattern_search (struct file *file, int archive,
int specific_rule_matched = 0;
unsigned int ri; /* uninit checks OK */
int found_compat_rule = 0;
struct rule *rule;
char *pathdir = NULL;
@ -258,6 +272,8 @@ pattern_search (struct file *file, int archive,
PATH_VAR (stem_str); /* @@ Need to get rid of stem, stemlen, etc. */
++depth;
#ifndef NO_ARCHIVES
if (archive || ar_name (filename))
lastslash = 0;
@ -268,6 +284,14 @@ pattern_search (struct file *file, int archive,
but not counting any slash at the end. (foo/bar/ counts as
bar/ in directory foo/, not empty in directory foo/bar/.) */
lastslash = memrchr (filename, '/', namelen - 1);
#ifdef VMS
if (lastslash == NULL)
lastslash = strrchr (filename, ']');
if (lastslash == NULL)
lastslash = strrchr (filename, '>');
if (lastslash == NULL)
lastslash = strrchr (filename, ':');
#endif
#ifdef HAVE_DOS_PATHS
/* Handle backslashes (possibly mixed with forward slashes)
and the case of "d:file". */
@ -300,7 +324,9 @@ pattern_search (struct file *file, int archive,
don't use it here. */
if (rule->in_use)
{
DBS (DB_IMPLICIT, (_("Avoiding implicit rule recursion.\n")));
DBS (DB_IMPLICIT,
(_("Avoiding implicit rule recursion for rule '%s'.\n"),
get_rule_defn (rule)));
continue;
}
@ -331,7 +357,11 @@ pattern_search (struct file *file, int archive,
check_lastslash = 0;
if (lastslash)
{
#ifdef VMS
check_lastslash = strpbrk (target, "/]>:") == NULL;
#else
check_lastslash = strchr (target, '/') == 0;
#endif
#ifdef HAVE_DOS_PATHS
/* Didn't find it yet: check for DOS-type directories. */
if (check_lastslash)
@ -419,6 +449,8 @@ pattern_search (struct file *file, int archive,
for (intermed_ok = 0; intermed_ok < 2; ++intermed_ok)
{
pat = deplist;
if (intermed_ok)
DBS (DB_IMPLICIT, (_("Trying harder.\n")));
/* Try each pattern rule till we find one that applies. If it does,
expand its dependencies (as substituted) and chain them in DEPS. */
@ -467,6 +499,10 @@ pattern_search (struct file *file, int archive,
}
}
DBS (DB_IMPLICIT,
(_("Trying pattern rule '%s' with stem '%.*s'.\n"),
get_rule_defn (rule), (int) stemlen, stem));
if (stemlen + (check_lastslash ? pathlen : 0) > GET_PATH_MAX)
{
DBS (DB_IMPLICIT, (_("Stem too long: '%s%.*s'.\n"),
@ -475,9 +511,6 @@ pattern_search (struct file *file, int archive,
continue;
}
DBS (DB_IMPLICIT, (_("Trying pattern rule with stem '%.*s'.\n"),
(int) stemlen, stem));
if (!check_lastslash)
{
memcpy (stem_str, stem, stemlen);
@ -496,10 +529,6 @@ pattern_search (struct file *file, int archive,
if (rule->deps == 0)
break;
/* Temporary assign STEM to file->stem (needed to set file
variables below). */
file->stem = stem_str;
/* Mark this rule as in use so a recursive pattern_search won't try
to use it. */
rule->in_use = 1;
@ -514,7 +543,6 @@ pattern_search (struct file *file, int archive,
while (1)
{
struct dep *dl, *d;
char *p;
/* If we're out of name to parse, start the next prereq. */
if (! nptr)
@ -528,32 +556,33 @@ pattern_search (struct file *file, int archive,
/* If we don't need a second expansion, just replace the %. */
if (! dep->need_2nd_expansion)
{
p = strchr (nptr, '%');
if (p == 0)
char *p;
int is_explicit = 1;
const char *cp = strchr (nptr, '%');
if (cp == 0)
strcpy (depname, nptr);
else
{
char *o = depname;
if (check_lastslash)
{
memcpy (o, filename, pathlen);
o += pathlen;
}
memcpy (o, nptr, p - nptr);
o += p - nptr;
memcpy (o, stem, stemlen);
o += stemlen;
strcpy (o, p + 1);
o = mempcpy (o, filename, pathlen);
o = mempcpy (o, nptr, cp - nptr);
o = mempcpy (o, stem, stemlen);
strcpy (o, cp + 1);
is_explicit = 0;
}
/* Parse the expanded string. It might have wildcards. */
p = depname;
dl = PARSE_FILE_SEQ (&p, struct dep, MAP_NUL, NULL, PARSEFS_ONEWORD);
dl = PARSE_FILE_SEQ (&p, struct dep, MAP_NUL, NULL,
PARSEFS_ONEWORD|PARSEFS_WAIT);
for (d = dl; d != NULL; d = d->next)
{
++deps_found;
d->ignore_mtime = dep->ignore_mtime;
d->ignore_automatic_vars = dep->ignore_automatic_vars;
d->wait_here |= dep->wait_here;
d->is_explicit = is_explicit;
}
/* We've used up this dep, so next time get a new one. */
@ -573,17 +602,22 @@ pattern_search (struct file *file, int archive,
{
int add_dir = 0;
size_t len;
const char *end;
struct dep **dptr;
int is_explicit;
const char *cp;
char *p;
nptr = get_next_word (nptr, &len);
if (nptr == 0)
continue;
end = nptr + len;
/* See this is a transition to order-only prereqs. */
/* See if this is a transition to order-only prereqs. */
if (! order_only && len == 1 && nptr[0] == '|')
{
order_only = 1;
nptr += len;
nptr = end;
continue;
}
@ -598,49 +632,76 @@ pattern_search (struct file *file, int archive,
(since $* and $(*F) are simple variables) there won't be
additional re-expansion of the stem. */
p = lindex (nptr, nptr + len, '%');
if (p == 0)
cp = lindex (nptr, end, '%');
if (cp == 0)
{
memcpy (depname, nptr, len);
depname[len] = '\0';
is_explicit = 1;
}
else
{
size_t i = p - nptr;
/* Go through all % between NPTR and END.
Copy contents of [NPTR, END) to depname, with the
first % after NPTR and then each first % after white
space replaced with $* or $(*F). depname has enough
room to substitute each % with $(*F). */
char *o = depname;
memcpy (o, nptr, i);
o += i;
if (check_lastslash)
is_explicit = 0;
for (;;)
{
add_dir = 1;
memcpy (o, "$(*F)", 5);
o += 5;
size_t i = cp - nptr;
assert (o + i < dend);
o = mempcpy (o, nptr, i);
if (check_lastslash)
{
add_dir = 1;
assert (o + 5 < dend);
o = mempcpy (o, "$(*F)", 5);
}
else
{
assert (o + 2 < dend);
o = mempcpy (o, "$*", 2);
}
assert (o < dend);
++cp;
assert (cp <= end);
nptr = cp;
if (nptr == end)
break;
/* Skip the rest of this word then find the next %.
No need to worry about order-only, or nested
functions: NPTR went though get_next_word. */
while (cp < end && ! END_OF_TOKEN (*cp))
++cp;
cp = lindex (cp, end, '%');
if (cp == 0)
break;
}
else
{
memcpy (o, "$*", 2);
o += 2;
}
memcpy (o, p + 1, len - i - 1);
o[len - i - 1] = '\0';
len = end - nptr;
memcpy (o, nptr, len);
o[len] = '\0';
}
/* Set up for the next word. */
nptr += len;
nptr = end;
/* Initialize and set file variables if we haven't already
done so. */
if (!file_vars_initialized)
{
initialize_file_variables (file, 0);
set_file_variables (file);
set_file_variables (file, stem_str);
file_vars_initialized = 1;
}
/* Update the stem value in $* for this rule. */
else if (!file_variables_set)
{
define_variable_for_file (
"*", 1, file->stem, o_automatic, 0, file);
"*", 1, stem_str, o_automatic, 0, file);
file_variables_set = 1;
}
@ -654,7 +715,8 @@ pattern_search (struct file *file, int archive,
/* Parse the expanded string. */
struct dep *dp = PARSE_FILE_SEQ (&p, struct dep,
order_only ? MAP_NUL : MAP_PIPE,
add_dir ? pathdir : NULL, PARSEFS_NONE);
add_dir ? pathdir : NULL,
PARSEFS_WAIT);
*dptr = dp;
for (d = dp; d != NULL; d = d->next)
@ -662,6 +724,7 @@ pattern_search (struct file *file, int archive,
++deps_found;
if (order_only)
d->ignore_mtime = 1;
d->is_explicit = is_explicit;
dptr = &d->next;
}
@ -692,8 +755,10 @@ pattern_search (struct file *file, int archive,
/* Go through the nameseq and handle each as a prereq name. */
for (d = dl; d != 0; d = d->next)
{
struct dep *expl_d;
struct file *df;
int is_rule = d->name == dep_name (dep);
int explicit = 0;
struct dep *dp = 0;
if (file_impossible_p (d->name))
{
@ -702,9 +767,11 @@ pattern_search (struct file *file, int archive,
second pass either since we know that will fail. */
DBS (DB_IMPLICIT,
(is_rule
? _("Rejecting impossible rule prerequisite '%s'.\n")
: _("Rejecting impossible implicit prerequisite '%s'.\n"),
d->name));
? _("Rejecting rule '%s' due to impossible rule"
" prerequisite '%s'.\n")
: _("Rejecting rule '%s' due to impossible implicit"
" prerequisite '%s'.\n"),
get_rule_defn (rule), d->name));
tryrules[ri].rule = 0;
failed = 1;
@ -714,41 +781,86 @@ pattern_search (struct file *file, int archive,
memset (pat, '\0', sizeof (struct patdeps));
pat->ignore_mtime = d->ignore_mtime;
pat->ignore_automatic_vars = d->ignore_automatic_vars;
pat->wait_here = d->wait_here;
pat->is_explicit = d->is_explicit;
DBS (DB_IMPLICIT,
(is_rule
? _("Trying rule prerequisite '%s'.\n")
: _("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. */
df = lookup_file (d->name);
for (expl_d = file->deps; expl_d != 0; expl_d = expl_d->next)
if (streq (dep_name (expl_d), d->name))
break;
if (expl_d != 0)
if (df && df->is_explicit)
pat->is_explicit = 1;
/* If we found a file for the dep, set its intermediate flag.
df->is_explicit is set when the dep file is mentioned
explicitly on some other rule. d->is_explicit is set when
the dep file is mentioned explicitly on this rule. E.g.:
%.x : %.y ; ...
then:
one.x:
one.y: # df->is_explicit
vs.
one.x: one.y # d->is_explicit
*/
if (df && !df->is_explicit && !d->is_explicit)
df->intermediate = 1;
/* If the pattern prereq is also explicitly mentioned for
FILE, skip all tests below since it must be built no
matter which implicit rule we choose. */
if (df && df->is_target)
/* This prerequisite is mentioned explicitly as a target of
some rule. */
explicit = 1;
else
for (dp = file->deps; dp != 0; dp = dp->next)
if (streq (d->name, dep_name (dp)))
break;
/* If dp is set, this prerequisite is mentioned explicitly as
a prerequisite of the current target. */
if (explicit || dp)
{
(pat++)->name = d->name;
DBS (DB_IMPLICIT, (_("'%s' ought to exist.\n"), d->name));
continue;
}
/* The DEP->changed flag says that this dependency resides
in a nonexistent directory. So we normally can skip
looking for the file. However, if CHECK_LASTSLASH is
set, then the dependency file we are actually looking for
is in a different directory (the one gotten by prepending
FILENAME's directory), so it might actually exist. */
/* @@ dep->changed check is disabled. */
if (lookup_file (d->name) != 0
/*|| ((!dep->changed || check_lastslash) && */
|| file_exists_p (d->name))
if (file_exists_p (d->name))
{
(pat++)->name = d->name;
DBS (DB_IMPLICIT, (_("Found '%s'.\n"), d->name));
continue;
}
if (df && allow_compat_rules)
{
(pat++)->name = d->name;
DBS (DB_IMPLICIT,
(_("Using compatibility rule '%s' due to '%s'.\n"),
get_rule_defn (rule), d->name));
continue;
}
if (df)
{
/* This prerequisite is mentioned explicitly as a
prerequisite on some rule, but it is not a
prerequisite of the current target. Therefore, this
prerequisite does not qualify as ought-to-exist. Keep
note of this rule and continue the search. If a more
suitable rule is not found, then use this rule. */
DBS (DB_IMPLICIT,
(_("Prerequisite '%s' of rule '%s' does not qualify"
" as ought to exist.\n"),
d->name, get_rule_defn (rule)));
found_compat_rule = 1;
}
/* This code, given FILENAME = "lib/foo.o", dependency name
"lib/foo.c", and VPATH=src, searches for
"src/lib/foo.c". */
@ -757,7 +869,7 @@ pattern_search (struct file *file, int archive,
if (vname)
{
DBS (DB_IMPLICIT,
(_("Found prerequisite '%s' as VPATH '%s'\n"),
(_("Found prerequisite '%s' as VPATH '%s'.\n"),
d->name, vname));
(pat++)->name = d->name;
continue;
@ -765,13 +877,15 @@ pattern_search (struct file *file, int archive,
}
/* We could not find the file in any place we should look.
Try to make this dependency as an intermediate file, but
Look for an implicit rule to make this dependency, but
only on the second pass. */
if (intermed_ok)
{
DBS (DB_IMPLICIT,
(_("Looking for a rule with intermediate file '%s'.\n"),
(d->is_explicit || (df && df->is_explicit)
? _("Looking for a rule with explicit file '%s'.\n")
: _("Looking for a rule with intermediate file '%s'.\n"),
d->name));
if (int_file == 0)
@ -781,8 +895,9 @@ pattern_search (struct file *file, int archive,
if (pattern_search (int_file,
0,
depth + 1,
recursions + 1))
depth,
recursions + 1,
allow_compat_rules))
{
pat->pattern = int_file->name;
int_file->name = d->name;
@ -799,11 +914,24 @@ pattern_search (struct file *file, int archive,
free_variable_set (int_file->variables);
if (int_file->pat_variables)
free_variable_set (int_file->pat_variables);
file_impossible (d->name);
/* Keep prerequisites explicitly mentioned on unrelated
rules as "possible" to let compatibility search find
such prerequisites. */
if (df == 0)
file_impossible (d->name);
}
/* A dependency of this rule does not exist. Therefore, this
rule fails. */
if (intermed_ok)
DBS (DB_IMPLICIT,
(_("Rejecting rule '%s' "
"due to impossible prerequisite '%s'.\n"),
get_rule_defn (rule), d->name));
else
DBS (DB_IMPLICIT, (_("Not found '%s'.\n"), d->name));
failed = 1;
break;
}
@ -815,10 +943,6 @@ pattern_search (struct file *file, int archive,
break;
}
/* Reset the stem in FILE. */
file->stem = 0;
/* This rule is no longer 'in use' for recursive searches. */
rule->in_use = 0;
@ -870,24 +994,24 @@ pattern_search (struct file *file, int archive,
struct file *imf = pat->file;
struct file *f = lookup_file (imf->name);
/* We don't want to delete an intermediate file that happened
to be a prerequisite of some (other) target. Mark it as
secondary. We don't want it to be precious as that disables
DELETE_ON_ERROR etc. */
if (f != 0)
f->secondary = 1;
else
if (!f)
f = enter_file (imf->name);
f->deps = imf->deps;
f->cmds = imf->cmds;
f->stem = imf->stem;
f->variables = imf->variables;
/* Setting target specific variables for a file causes the file to be
entered to the database as a prerequisite. Implicit search then
treats this file as explicitly mentioned. Preserve target specific
variables of this file. */
merge_variable_set_lists(&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;
f->is_explicit |= imf->is_explicit || pat->is_explicit;
f->notintermediate |= imf->notintermediate || no_intermediates;
f->intermediate |= !f->is_explicit && !f->notintermediate;
f->tried_implicit = 1;
imf = lookup_file (pat->pattern);
@ -904,7 +1028,9 @@ pattern_search (struct file *file, int archive,
dep = alloc_dep ();
dep->ignore_mtime = pat->ignore_mtime;
dep->is_explicit = pat->is_explicit;
dep->ignore_automatic_vars = pat->ignore_automatic_vars;
dep->wait_here = pat->wait_here;
s = strcache_add (pat->name);
if (recursions)
dep->name = s;
@ -930,8 +1056,14 @@ pattern_search (struct file *file, int archive,
dep->next = file->deps;
file->deps = dep;
/* The file changed its dependencies; schedule the shuffle. */
file->was_shuffled = 0;
}
if (!file->was_shuffled)
shuffle_deps_recursive (file->deps);
if (!tryrules[foundrule].checked_lastslash)
{
/* Always allocate new storage, since STEM might be on the stack for an
@ -953,11 +1085,16 @@ pattern_search (struct file *file, int archive,
file->cmds = rule->cmds;
file->is_target = 1;
/* Set precious flag. */
/* Set precious and notintermediate flags. */
{
struct file *f = lookup_file (rule->targets[tryrules[foundrule].matches]);
if (f && f->precious)
file->precious = 1;
if (f)
{
if (f->precious)
file->precious = 1;
if (f->notintermediate || no_intermediates)
file->notintermediate = 1;
}
}
/* If this rule builds other targets, too, put the others into FILE's
@ -973,11 +1110,9 @@ pattern_search (struct file *file, int archive,
struct dep *new = alloc_dep ();
/* GKM FIMXE: handle '|' here too */
memcpy (p, rule->targets[ri],
rule->suffixes[ri] - rule->targets[ri] - 1);
p += rule->suffixes[ri] - rule->targets[ri] - 1;
memcpy (p, file->stem, fullstemlen);
p += fullstemlen;
p = mempcpy (p, rule->targets[ri],
rule->suffixes[ri] - rule->targets[ri] - 1);
p = mempcpy (p, file->stem, fullstemlen);
memcpy (p, rule->suffixes[ri],
rule->lens[ri] - (rule->suffixes[ri] - rule->targets[ri])+1);
new->name = strcache_add (nm);
@ -986,8 +1121,13 @@ pattern_search (struct file *file, int archive,
/* Set precious flag. */
f = lookup_file (rule->targets[ri]);
if (f && f->precious)
new->file->precious = 1;
if (f)
{
if (f->precious)
new->file->precious = 1;
if (f->notintermediate || no_intermediates)
new->file->notintermediate = 1;
}
/* Set the is_target flag so that this file is not treated as
intermediate by the pattern rule search algorithm and
@ -1001,5 +1141,23 @@ pattern_search (struct file *file, int archive,
free (tryrules);
free (deplist);
return rule != 0;
--depth;
if (rule)
{
DBS (DB_IMPLICIT, (_("Found implicit rule '%s' for '%s'.\n"),
get_rule_defn (rule), filename));
return 1;
}
if (found_compat_rule)
{
DBS (DB_IMPLICIT, (_("Searching for a compatibility rule for '%s'.\n"),
filename));
assert (allow_compat_rules == 0);
return pattern_search (file, archive, depth, recursions, 1);
}
DBS (DB_IMPLICIT, (_("No implicit rule found for '%s'.\n"), filename));
return 0;
}