mirror of
https://github.com/mirror/make.git
synced 2025-04-17 06:41:04 +08:00
Add a new variable: MAKE_RESTARTS, to count how many times make has re-exec'd.
When rebuilding makefiles, unset -B if MAKE_RESTARTS is >0.
This commit is contained in:
parent
467115baae
commit
978819e1d6
21
ChangeLog
21
ChangeLog
@ -1,3 +1,24 @@
|
||||
2005-06-25 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
Implement the MAKE_RESTARTS variable, and disable -B if it's >0.
|
||||
Fixes Savannah bug #7566.
|
||||
|
||||
* doc/make.texi (Special Variables): Document MAKE_RESTARTS.
|
||||
* NEWS: Mention MAKE_RESTARTS.
|
||||
* main.c (main): If we see MAKE_RESTARTS in the environment, unset
|
||||
its export flag and obtain its value. When we need to re-exec,
|
||||
increment the value and add it into the environment.
|
||||
(always_make_set): New variable. Change the -B option to set this
|
||||
one instead.
|
||||
(main): When checking makefiles, only set always_make_flag if
|
||||
always_make_set is set AND the restarts flag is 0. When building
|
||||
normal targets, set it IFF always_make_set is set.
|
||||
|
||||
2005-06-17 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* default.c: Change VMS implicit rules to use $$$$ instead of $$
|
||||
in the prerequisites list.
|
||||
|
||||
2005-06-12 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
Fix Savannah bug # 1328.
|
||||
|
5
NEWS
5
NEWS
@ -26,7 +26,7 @@ Version 3.81beta3
|
||||
applies to implicit rules, as well, where the second expansion occurs
|
||||
after the rule is matched. However, this means that you need to
|
||||
double-quote any "$" in your filenames; instead of "foo: boo$$bar" you
|
||||
must write "foo: foo$$$$bar"
|
||||
now must write "foo: foo$$$$bar".
|
||||
|
||||
* New command-line option: -L (--check-symlink-times). On systems that
|
||||
support symbolic links, if this option is given then GNU make will
|
||||
@ -59,6 +59,9 @@ Version 3.81beta3
|
||||
version of GNU make.
|
||||
- .DEFAULT_GOAL: Set the name of the default goal make will
|
||||
use if no goals are provided on the command line.
|
||||
- MAKE_RESTARTS: If set, then this is the number of times this
|
||||
instance of make has been restarted (see "How Makefiles Are Remade"
|
||||
in the manual).
|
||||
- New automatic variable: $| (added in 3.80, actually): contains all
|
||||
the order-only prerequisites defined for the target.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Data base of default implicit rules for GNU Make.
|
||||
Copyright (C) 1988,89,90,91,92,93,94,95,96 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988,1989,1990,1991,1992,1993,1994,1995,
|
||||
1996,2003,2004 Free Software Foundation, Inc.
|
||||
This file is part of GNU Make.
|
||||
|
||||
GNU Make is free software; you can redistribute it and/or modify
|
||||
|
@ -1330,6 +1330,14 @@ foo
|
||||
Note that assigning more than one target name to @code{.DEFAULT_GOAL} is
|
||||
illegal and will result in an error.
|
||||
|
||||
@vindex MAKE_RESTARTS @r{(number of times @code{make} has restarted)}
|
||||
@item MAKE_RESTARTS
|
||||
This variable is set only if this instance of @code{make} has
|
||||
restarted (@pxref{Remaking Makefiles, , How Makefiles Are Remade}): it
|
||||
will contain the number of times this instance has restarted. Note
|
||||
this is not the same as recursion (counted by the @code{MAKELEVEL}
|
||||
variable). You should not set, modify, or export this variable.
|
||||
|
||||
@vindex .VARIABLES @r{(list of variables)}
|
||||
@item .VARIABLES
|
||||
Expands to a list of the @emph{names} of all global variables defined
|
||||
@ -7549,8 +7557,12 @@ These options are ignored for compatibility with other versions of @code{make}.
|
||||
@cindex @code{--always-make}
|
||||
Consider all targets out-of-date. GNU @code{make} proceeds to
|
||||
consider targets and their prerequisites using the normal algorithms;
|
||||
however, all these targets are remade, regardless of the status of
|
||||
their prerequisites.
|
||||
however, all targets so considered are always remade regardless of the
|
||||
status of their prerequisites. To avoid infinite recursion, if
|
||||
@code{MAKE_RESTARTS} (@pxref{Special Variables, , Other Special
|
||||
Variables}) is set to a number greater than 0 this option is disabled
|
||||
when considering whether to remake makefiles (@pxref{Remaking
|
||||
Makefiles, , How Makefiles Are Remade}).
|
||||
|
||||
@item -C @var{dir}
|
||||
@cindex @code{-C}
|
||||
|
124
main.c
124
main.c
@ -271,6 +271,7 @@ int warn_undefined_variables_flag;
|
||||
/* If nonzero, always build all targets, regardless of whether
|
||||
they appear out of date or not. */
|
||||
|
||||
static int always_make_set = 0;
|
||||
int always_make_flag = 0;
|
||||
|
||||
/* If nonzero, we're in the "try to rebuild makefiles" phase. */
|
||||
@ -362,7 +363,7 @@ static const char *const usage[] =
|
||||
static const struct command_switch switches[] =
|
||||
{
|
||||
{ 'b', ignore, 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ 'B', flag, (char *) &always_make_flag, 1, 1, 0, 0, 0, "always-make" },
|
||||
{ 'B', flag, (char *) &always_make_set, 1, 1, 0, 0, 0, "always-make" },
|
||||
{ 'C', string, (char *) &directories, 0, 0, 0, 0, 0, "directory" },
|
||||
{ 'd', flag, (char *) &debug_flag, 1, 1, 0, 0, 0, 0 },
|
||||
{ CHAR_MAX+1, string, (char *) &db_flags, 1, 1, 0, "basic", 0, "debug" },
|
||||
@ -764,7 +765,7 @@ find_and_set_default_shell (char *token)
|
||||
sh_found = 1;
|
||||
} else {
|
||||
char *p;
|
||||
struct variable *v = lookup_variable ("PATH", 4);
|
||||
struct variable *v = lookup_variable (STRING_SIZE_TUPLE ("PATH"));
|
||||
|
||||
/* Search Path for shell */
|
||||
if (v && v->value) {
|
||||
@ -889,6 +890,7 @@ main (int argc, char **argv, char **envp)
|
||||
char **p;
|
||||
struct dep *read_makefiles;
|
||||
PATH_VAR (current_directory);
|
||||
unsigned int restarts = 0;
|
||||
#ifdef WINDOWS32
|
||||
char *unix_path = NULL;
|
||||
char *windows32_path = NULL;
|
||||
@ -1149,9 +1151,8 @@ main (int argc, char **argv, char **envp)
|
||||
v->export = v_export;
|
||||
|
||||
/* Another wrinkle is that POSIX says the value of SHELL set in the
|
||||
makefile should not change the value of SHELL given to
|
||||
subprocesses, which seems silly to me but... */
|
||||
if (strncmp (envp[i], "SHELL=", 6) == 0)
|
||||
makefile won't change the value of SHELL given to subprocesses */
|
||||
if (streq (v->name, "SHELL"))
|
||||
{
|
||||
#ifndef __MSDOS__
|
||||
v->export = v_noexport;
|
||||
@ -1159,6 +1160,13 @@ main (int argc, char **argv, char **envp)
|
||||
shell_var.name = "SHELL";
|
||||
shell_var.value = xstrdup (ep + 1);
|
||||
}
|
||||
|
||||
/* If MAKE_RESTARTS is set, remember it but don't export it. */
|
||||
if (streq (v->name, "MAKE_RESTARTS"))
|
||||
{
|
||||
v->export = v_noexport;
|
||||
restarts = (unsigned int) atoi (ep + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef WINDOWS32
|
||||
@ -1203,12 +1211,12 @@ main (int argc, char **argv, char **envp)
|
||||
|
||||
/* Decode the switches. */
|
||||
|
||||
decode_env_switches ("MAKEFLAGS", 9);
|
||||
decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS"));
|
||||
#if 0
|
||||
/* People write things like:
|
||||
MFLAGS="CC=gcc -pipe" "CFLAGS=-g"
|
||||
and we set the -p, -i and -e switches. Doesn't seem quite right. */
|
||||
decode_env_switches ("MFLAGS", 6);
|
||||
decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS"));
|
||||
#endif
|
||||
decode_switches (argc, argv, 0);
|
||||
#ifdef WINDOWS32
|
||||
@ -1222,14 +1230,18 @@ main (int argc, char **argv, char **envp)
|
||||
|
||||
decode_debug_flags ();
|
||||
|
||||
/* Set always_make_flag if -B was given and we've not restarted already. */
|
||||
always_make_flag = always_make_set && (restarts == 0);
|
||||
|
||||
/* Print version information. */
|
||||
|
||||
if (print_version_flag || print_data_base_flag || db_level)
|
||||
print_version ();
|
||||
{
|
||||
print_version ();
|
||||
|
||||
/* `make --version' is supposed to just print the version and exit. */
|
||||
if (print_version_flag)
|
||||
die (0);
|
||||
/* `make --version' is supposed to just print the version and exit. */
|
||||
if (print_version_flag)
|
||||
die (0);
|
||||
}
|
||||
|
||||
#ifndef VMS
|
||||
/* Set the "MAKE_COMMAND" variable to the name we were invoked with.
|
||||
@ -1376,7 +1388,7 @@ main (int argc, char **argv, char **envp)
|
||||
#endif /* WINDOWS32 */
|
||||
/* Figure out the level of recursion. */
|
||||
{
|
||||
struct variable *v = lookup_variable (MAKELEVEL_NAME, MAKELEVEL_LENGTH);
|
||||
struct variable *v = lookup_variable (STRING_SIZE_TUPLE (MAKELEVEL_NAME));
|
||||
if (v != 0 && v->value[0] != '\0' && v->value[0] != '-')
|
||||
makelevel = (unsigned int) atoi (v->value);
|
||||
else
|
||||
@ -1588,7 +1600,7 @@ main (int argc, char **argv, char **envp)
|
||||
/* We need to know what kind of shell we will be using. */
|
||||
{
|
||||
extern int _is_unixy_shell (const char *_path);
|
||||
struct variable *shv = lookup_variable ("SHELL", 5);
|
||||
struct variable *shv = lookup_variable (STRING_SIZE_TUPLE ("SHELL"));
|
||||
extern int unixy_shell;
|
||||
extern char *default_shell;
|
||||
|
||||
@ -1607,9 +1619,9 @@ main (int argc, char **argv, char **envp)
|
||||
#endif /* __MSDOS__ || __EMX__ */
|
||||
|
||||
/* Decode switches again, in case the variables were set by the makefile. */
|
||||
decode_env_switches ("MAKEFLAGS", 9);
|
||||
decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS"));
|
||||
#if 0
|
||||
decode_env_switches ("MFLAGS", 6);
|
||||
decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS"));
|
||||
#endif
|
||||
|
||||
#if defined (__MSDOS__) || defined (__EMX__)
|
||||
@ -1997,44 +2009,61 @@ main (int argc, char **argv, char **envp)
|
||||
fatal (NILF, _("Couldn't change back to original directory."));
|
||||
}
|
||||
|
||||
#ifndef _AMIGA
|
||||
for (p = environ; *p != 0; ++p)
|
||||
if (strneq (*p, MAKELEVEL_NAME, MAKELEVEL_LENGTH)
|
||||
&& (*p)[MAKELEVEL_LENGTH] == '=')
|
||||
{
|
||||
/* The SGI compiler apparently can't understand
|
||||
the concept of storing the result of a function
|
||||
in something other than a local variable. */
|
||||
char *sgi_loses;
|
||||
sgi_loses = (char *) alloca (40);
|
||||
*p = sgi_loses;
|
||||
sprintf (*p, "%s=%u", MAKELEVEL_NAME, makelevel);
|
||||
break;
|
||||
}
|
||||
#else /* AMIGA */
|
||||
{
|
||||
char buffer[256];
|
||||
int len;
|
||||
|
||||
len = GetVar (MAKELEVEL_NAME, buffer, sizeof (buffer), GVF_GLOBAL_ONLY);
|
||||
|
||||
if (len != -1)
|
||||
{
|
||||
sprintf (buffer, "%u", makelevel);
|
||||
SetVar (MAKELEVEL_NAME, buffer, -1, GVF_GLOBAL_ONLY);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
++restarts;
|
||||
|
||||
if (ISDB (DB_BASIC))
|
||||
{
|
||||
char **p;
|
||||
fputs (_("Re-executing:"), stdout);
|
||||
printf (_("Re-executing[%u]:"), restarts);
|
||||
for (p = nargv; *p != 0; ++p)
|
||||
printf (" %s", *p);
|
||||
putchar ('\n');
|
||||
}
|
||||
|
||||
#ifndef _AMIGA
|
||||
for (p = environ; *p != 0; ++p)
|
||||
{
|
||||
if (strneq (*p, MAKELEVEL_NAME, MAKELEVEL_LENGTH)
|
||||
&& (*p)[MAKELEVEL_LENGTH] == '=')
|
||||
{
|
||||
/* The SGI compiler apparently can't understand
|
||||
the concept of storing the result of a function
|
||||
in something other than a local variable. */
|
||||
char *sgi_loses;
|
||||
sgi_loses = (char *) alloca (40);
|
||||
*p = sgi_loses;
|
||||
sprintf (*p, "%s=%u", MAKELEVEL_NAME, makelevel);
|
||||
}
|
||||
if (strneq (*p, "MAKE_RESTARTS=", 14))
|
||||
{
|
||||
char *sgi_loses;
|
||||
sgi_loses = (char *) alloca (40);
|
||||
*p = sgi_loses;
|
||||
sprintf (*p, "MAKE_RESTARTS=%u", restarts);
|
||||
restarts = 0;
|
||||
}
|
||||
}
|
||||
#else /* AMIGA */
|
||||
{
|
||||
char buffer[256];
|
||||
|
||||
sprintf (buffer, "%u", makelevel);
|
||||
SetVar (MAKELEVEL_NAME, buffer, -1, GVF_GLOBAL_ONLY);
|
||||
|
||||
sprintf (buffer, "%u", restarts);
|
||||
SetVar ("MAKE_RESTARTS", buffer, -1, GVF_GLOBAL_ONLY);
|
||||
restarts = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we didn't set the restarts variable yet, add it. */
|
||||
if (restarts)
|
||||
{
|
||||
char *b = alloca (40);
|
||||
sprintf (b, "MAKE_RESTARTS=%u", restarts);
|
||||
putenv (b);
|
||||
}
|
||||
|
||||
fflush (stdout);
|
||||
fflush (stderr);
|
||||
|
||||
@ -2085,6 +2114,9 @@ main (int argc, char **argv, char **envp)
|
||||
/* Set up `MAKEFLAGS' again for the normal targets. */
|
||||
define_makeflags (1, 0);
|
||||
|
||||
/* Set always_make_flag if -B was given. */
|
||||
always_make_flag = always_make_set;
|
||||
|
||||
/* If there is a temp file from reading a makefile from stdin, get rid of
|
||||
it now. */
|
||||
if (stdin_nm && unlink (stdin_nm) < 0 && errno != ENOENT)
|
||||
@ -2304,7 +2336,7 @@ handle_non_switch_argument (char *arg, int env)
|
||||
struct variable *v;
|
||||
char *value;
|
||||
|
||||
v = lookup_variable ("MAKECMDGOALS", 12);
|
||||
v = lookup_variable (STRING_SIZE_TUPLE ("MAKECMDGOALS"));
|
||||
if (v == 0)
|
||||
value = f->name;
|
||||
else
|
||||
|
@ -1,3 +1,10 @@
|
||||
2005-06-25 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/variables/MAKE_RESTARTS: New file: test the
|
||||
MAKE_RESTARTS variable.
|
||||
* scripts/options/dash-B: Test re-exec doesn't loop infinitely.
|
||||
Tests fix for Savannah bug #7566.
|
||||
|
||||
2005-06-12 Paul D. Smith <psmith@gnu.org>
|
||||
|
||||
* scripts/misc/close_stdout: Add a test for Savannah bug #1328.
|
||||
|
@ -31,9 +31,43 @@ utouch(1000, 'foo');
|
||||
run_make_test(undef, '', "#MAKE#: Nothing to be done for `all'.");
|
||||
run_make_test(undef, '-B', 'cp bar.x foo');
|
||||
|
||||
|
||||
# Clean up
|
||||
|
||||
rmfiles('bar.x', 'foo');
|
||||
|
||||
# Test -B with the re-exec feature: we don't want to re-exec forever
|
||||
# Savannah bug # 7566
|
||||
|
||||
run_make_test('
|
||||
all: ; @:
|
||||
$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
|
||||
include foo.x
|
||||
foo.x: ; @touch $@
|
||||
',
|
||||
'-B', 'MAKE_RESTARTS=
|
||||
#MAKEFILE#:4: foo.x: No such file or directory
|
||||
MAKE_RESTARTS=1');
|
||||
|
||||
rmfiles('foo.x');
|
||||
|
||||
# Test -B with the re-exec feature: we DO want -B in the "normal" part of the
|
||||
# makefile.
|
||||
|
||||
&touch('blah.x');
|
||||
|
||||
run_make_test('
|
||||
all: blah.x ; @echo $@
|
||||
$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
|
||||
include foo.x
|
||||
foo.x: ; @touch $@
|
||||
blah.x: ; @echo $@
|
||||
',
|
||||
'-B', 'MAKE_RESTARTS=
|
||||
#MAKEFILE#:4: foo.x: No such file or directory
|
||||
MAKE_RESTARTS=1
|
||||
blah.x
|
||||
all');
|
||||
|
||||
rmfiles('foo.x', 'blah.x');
|
||||
|
||||
1;
|
||||
|
62
tests/scripts/variables/MAKE_RESTARTS
Normal file
62
tests/scripts/variables/MAKE_RESTARTS
Normal file
@ -0,0 +1,62 @@
|
||||
# -*-perl-*-
|
||||
|
||||
$description = "Test the MAKE_RESTARTS variable.";
|
||||
|
||||
# Test basic capability
|
||||
|
||||
run_make_test('
|
||||
all: ; @:
|
||||
$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
|
||||
include foo.x
|
||||
foo.x: ; @touch $@
|
||||
',
|
||||
'', 'MAKE_RESTARTS=
|
||||
#MAKEFILE#:4: foo.x: No such file or directory
|
||||
MAKE_RESTARTS=1');
|
||||
|
||||
rmfiles('foo.x');
|
||||
|
||||
# Test multiple restarts
|
||||
|
||||
run_make_test('
|
||||
all: ; @:
|
||||
$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
|
||||
include foo.x
|
||||
foo.x: ; @echo "include bar.x" > $@
|
||||
bar.x: ; @touch $@
|
||||
',
|
||||
'', 'MAKE_RESTARTS=
|
||||
#MAKEFILE#:4: foo.x: No such file or directory
|
||||
MAKE_RESTARTS=1
|
||||
foo.x:1: bar.x: No such file or directory
|
||||
MAKE_RESTARTS=2');
|
||||
|
||||
rmfiles('foo.x', 'bar.x');
|
||||
|
||||
# Test multiple restarts and make sure the variable is cleaned up
|
||||
|
||||
run_make_test('
|
||||
recurse:
|
||||
@echo recurse MAKE_RESTARTS=$$MAKE_RESTARTS
|
||||
@$(MAKE) -f #MAKEFILE# all
|
||||
all:
|
||||
@echo all MAKE_RESTARTS=$$MAKE_RESTARTS
|
||||
$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
|
||||
include foo.x
|
||||
foo.x: ; @echo "include bar.x" > $@
|
||||
bar.x: ; @touch $@
|
||||
',
|
||||
'', "MAKE_RESTARTS=
|
||||
#MAKEFILE#:8: foo.x: No such file or directory
|
||||
MAKE_RESTARTS=1
|
||||
foo.x:1: bar.x: No such file or directory
|
||||
MAKE_RESTARTS=2
|
||||
recurse MAKE_RESTARTS=
|
||||
MAKE_RESTARTS=
|
||||
#MAKE#[1]: Entering directory `#PWD#'
|
||||
all MAKE_RESTARTS=
|
||||
#MAKE#[1]: Leaving directory `#PWD#'");
|
||||
|
||||
rmfiles('foo.x', 'bar.x');
|
||||
|
||||
1;
|
Loading…
Reference in New Issue
Block a user