1
0
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:
Paul Smith 2005-06-25 18:57:28 +00:00
parent 467115baae
commit 978819e1d6
8 changed files with 223 additions and 51 deletions

View File

@ -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
View File

@ -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.

View File

@ -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

View File

@ -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
View File

@ -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

View File

@ -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.

View File

@ -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;

View 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;