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 @@
/* Command processing 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,20 +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/dep.h"
#include "third_party/make/filedef.h"
#include "third_party/make/job.h"
#include "third_party/make/variable.h"
/**/
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/sig.h"
#include "third_party/make/commands.h"
#include "makeint.h"
#include "filedef.h"
#include "os.h"
#include "dep.h"
#include "variable.h"
#include "job.h"
#include "commands.h"
#define FILE_LIST_SEPARATOR ' '
#if VMS
# define FILE_LIST_SEPARATOR (vms_comma_separator ? ',' : ' ')
#else
# define FILE_LIST_SEPARATOR ' '
#endif
static unsigned long
dep_hash_1 (const void *key)
@ -49,10 +51,13 @@ dep_hash_cmp (const void *x, const void *y)
return strcmp (dep_name (dx), dep_name (dy));
}
/* Set FILE's automatic variables up. */
/* Set FILE's automatic variables up.
* Use STEM to set $*.
* If STEM is 0, then set FILE->STEM and $* to the target name with any
* suffix in the .SUFFIXES list stripped off. */
void
set_file_variables (struct file *file)
set_file_variables (struct file *file, const char *stem)
{
struct dep *d;
const char *at, *percent, *star, *less;
@ -86,7 +91,7 @@ set_file_variables (struct file *file)
}
/* $* is the stem from an implicit or static pattern rule. */
if (file->stem == 0)
if (stem == 0)
{
/* In Unix make, $* is set to the target name with
any suffix in the .SUFFIXES list stripped off for
@ -109,25 +114,25 @@ set_file_variables (struct file *file)
for (d = enter_file (strcache_add (".SUFFIXES"))->deps; d ; d = d->next)
{
size_t slen = strlen (dep_name (d));
if (len > slen && strneq (dep_name (d), name + (len - slen), slen))
const char *dn = dep_name (d);
size_t slen = strlen (dn);
if (len > slen && memcmp (dn, name + (len - slen), slen) == 0)
{
file->stem = strcache_add_len (name, len - slen);
file->stem = stem = strcache_add_len (name, len - slen);
break;
}
}
if (d == 0)
file->stem = "";
file->stem = stem = "";
}
star = file->stem;
star = stem;
/* $< is the first not order-only dependency. */
less = "";
for (d = file->deps; d != 0; d = d->next)
if (!d->ignore_mtime && !d->ignore_automatic_vars)
if (!d->ignore_mtime && !d->ignore_automatic_vars && !d->need_2nd_expansion)
{
if (!d->need_2nd_expansion)
less = dep_name (d);
less = dep_name (d);
break;
}
@ -205,8 +210,7 @@ set_file_variables (struct file *file)
#endif
len = strlen (c);
memcpy (cp, c, len);
cp += len;
cp = mempcpy (cp, c, len);
*cp++ = FILE_LIST_SEPARATOR;
if (! (d->changed || always_make_flag))
qmark_len -= len + 1; /* Don't space in $? for this one. */
@ -276,19 +280,16 @@ set_file_variables (struct file *file)
if (d->ignore_mtime)
{
memcpy (bp, c, len);
bp += len;
bp = mempcpy (bp, c, len);
*bp++ = FILE_LIST_SEPARATOR;
}
else
{
memcpy (cp, c, len);
cp += len;
cp = mempcpy (cp, c, len);
*cp++ = FILE_LIST_SEPARATOR;
if (d->changed || always_make_flag)
{
memcpy (qp, c, len);
qp += len;
qp = mempcpy (qp, c, len);
*qp++ = FILE_LIST_SEPARATOR;
}
}
@ -317,14 +318,12 @@ set_file_variables (struct file *file)
void
chop_commands (struct commands *cmds)
{
unsigned int nlines;
unsigned short idx;
unsigned short nlines;
unsigned short i;
char **lines;
/* If we don't have any commands,
or we already parsed them, never mind. */
if (!cmds || cmds->command_lines != 0)
/* If we don't have any commands, or we already parsed them, never mind. */
if (!cmds || cmds->command_lines != NULL)
return;
/* Chop CMDS->commands up into lines in CMDS->command_lines. */
@ -343,25 +342,27 @@ chop_commands (struct commands *cmds)
}
else
{
const char *p;
const char *p = cmds->commands;
size_t max = 5;
nlines = 5;
lines = xmalloc (nlines * sizeof (char *));
idx = 0;
p = cmds->commands;
nlines = 0;
lines = xmalloc (max * sizeof (char *));
while (*p != '\0')
{
const char *end = p;
find_end:;
end = strchr (end, '\n');
if (end == 0)
if (end == NULL)
end = p + strlen (p);
else if (end > p && end[-1] == '\\')
{
int backslash = 1;
const char *b;
for (b = end - 2; b >= p && *b == '\\'; --b)
backslash = !backslash;
if (end > p + 1)
{
const char *b;
for (b = end - 2; b >= p && *b == '\\'; --b)
backslash = !backslash;
}
if (backslash)
{
++end;
@ -369,40 +370,36 @@ chop_commands (struct commands *cmds)
}
}
if (idx == nlines)
if (nlines == USHRT_MAX)
ON (fatal, &cmds->fileinfo,
_("Recipe has too many lines (limit %hu)"), nlines);
if (nlines == max)
{
nlines += 2;
lines = xrealloc (lines, nlines * sizeof (char *));
max += 2;
lines = xrealloc (lines, max * sizeof (char *));
}
lines[idx++] = xstrndup (p, (size_t) (end - p));
lines[nlines++] = xstrndup (p, (size_t) (end - p));
p = end;
if (*p != '\0')
++p;
}
if (idx != nlines)
{
nlines = idx;
lines = xrealloc (lines, nlines * sizeof (char *));
}
}
/* Finally, set the corresponding CMDS->lines_flags elements and the
CMDS->any_recurse flag. */
if (nlines > USHRT_MAX)
ON (fatal, &cmds->fileinfo, _("Recipe has too many lines (%ud)"), nlines);
cmds->ncommand_lines = (unsigned short)nlines;
cmds->ncommand_lines = nlines;
cmds->command_lines = lines;
cmds->any_recurse = 0;
cmds->lines_flags = xmalloc (nlines);
for (idx = 0; idx < nlines; ++idx)
for (i = 0; i < nlines; ++i)
{
unsigned char flags = 0;
const char *p = lines[idx];
const char *p = lines[i];
while (ISBLANK (*p) || *p == '-' || *p == '@' || *p == '+')
switch (*(p++))
@ -419,12 +416,12 @@ chop_commands (struct commands *cmds)
}
/* If no explicit '+' was given, look for MAKE variable references. */
if (!(flags & COMMANDS_RECURSE)
if (! ANY_SET (flags, COMMANDS_RECURSE)
&& (strstr (p, "$(MAKE)") != 0 || strstr (p, "${MAKE}") != 0))
flags |= COMMANDS_RECURSE;
cmds->lines_flags[idx] = flags;
cmds->any_recurse |= flags & COMMANDS_RECURSE ? 1 : 0;
cmds->lines_flags[i] = flags;
cmds->any_recurse |= ANY_SET (flags, COMMANDS_RECURSE) ? 1 : 0;
}
}
@ -456,12 +453,17 @@ execute_file_commands (struct file *file)
initialize_file_variables (file, 0);
set_file_variables (file);
set_file_variables (file, file->stem);
/* If this is a loaded dynamic object, unload it before remaking.
Some systems don't support overwriting a loaded object. */
if (file->loaded)
unload_file (file->name);
/* Some systems don't support overwriting a loaded object so if this one
unload it before remaking. Keep its name in .LOADED: it will be rebuilt
and loaded again. If rebuilding or loading again fail, then we'll exit
anyway and it won't matter. */
if (file->loaded && unload_file (file->name) == 0)
{
file->loaded = 0;
file->unloaded = 1;
}
/* Start the commands running. */
new_job (file);
@ -470,17 +472,36 @@ execute_file_commands (struct file *file)
/* This is set while we are inside fatal_error_signal,
so things can avoid nonreentrant operations. */
int handling_fatal_signal = 0;
volatile sig_atomic_t handling_fatal_signal = 0;
/* Handle fatal signals. */
RETSIGTYPE
void
fatal_error_signal (int sig)
{
#ifdef __MSDOS__
extern int dos_status, dos_command_running;
if (dos_command_running)
{
/* That was the child who got the signal, not us. */
dos_status |= (sig << 8);
return;
}
remove_intermediates (1);
exit (EXIT_FAILURE);
#else /* not __MSDOS__ */
#ifdef _AMIGA
remove_intermediates (1);
if (sig == SIGINT)
fputs (_("*** Break.\n"), stderr);
exit (10);
#else /* not Amiga */
#ifdef WINDOWS32
extern HANDLE main_thread;
/* Windows creates a sperate thread for handling Ctrl+C, so we need
/* Windows creates a separate thread for handling Ctrl+C, so we need
to suspend the main thread, or else we will have race conditions
when both threads call reap_children. */
if (main_thread)
@ -488,12 +509,12 @@ fatal_error_signal (int sig)
DWORD susp_count = SuspendThread (main_thread);
if (susp_count != 0)
fprintf (stderr, "SuspendThread: suspend count = %ld\n", susp_count);
fprintf (stderr, "SuspendThread: suspend count = %lu\n", susp_count);
else if (susp_count == (DWORD)-1)
{
DWORD ierr = GetLastError ();
fprintf (stderr, "SuspendThread: error %ld: %s\n",
fprintf (stderr, "SuspendThread: error %lu: %s\n",
ierr, map_windows32_error_to_string (ierr));
}
}
@ -504,6 +525,10 @@ fatal_error_signal (int sig)
It is blocked now while we run this handler. */
signal (sig, SIG_DFL);
temp_stdin_unlink ();
osync_clear ();
jobserver_clear ();
/* A termination signal won't be sent to the entire
process group, but it means we want to kill the children. */
@ -519,9 +544,12 @@ fatal_error_signal (int sig)
wanted to kill make, remove pending targets. */
if (sig == SIGTERM || sig == SIGINT
#ifdef SIGHUP
|| sig == SIGHUP
#endif
#ifdef SIGQUIT
|| sig == SIGQUIT
|| sig == SIGPIPE
#endif
)
{
struct child *c;
@ -533,10 +561,7 @@ fatal_error_signal (int sig)
(void) remote_kill (c->pid, sig);
for (c = children; c != 0; c = c->next)
{
delete_child_targets (c);
delete_tmpdir (c);
}
delete_child_targets (c);
/* Clean up the children. We don't just use the call below because
we don't want to print the "Waiting for children" message. */
@ -552,10 +577,12 @@ fatal_error_signal (int sig)
remove_intermediates (1);
#ifdef SIGQUIT
if (sig == SIGQUIT)
/* We don't want to send ourselves SIGQUIT, because it will
cause a core dump. Just exit instead. */
exit (MAKE_TROUBLE);
#endif
#ifdef WINDOWS32
if (main_thread)
@ -566,9 +593,11 @@ fatal_error_signal (int sig)
#else
/* Signal the same code; this time it will really be fatal. The signal
will be unblocked when we return and arrive then to kill us. */
if (kill (getpid (), sig) < 0)
if (kill (make_pid (), sig) < 0)
pfatal_with_name ("kill");
#endif /* not WINDOWS32 */
#endif /* not Amiga */
#endif /* not __MSDOS__ */
}
/* Delete FILE unless it's precious or not actually a file (phony),