summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog21
-rw-r--r--NEWS5
-rw-r--r--default.c3
-rw-r--r--doc/make.texi16
-rw-r--r--main.c120
-rw-r--r--tests/ChangeLog7
-rw-r--r--tests/scripts/options/dash-B36
-rw-r--r--tests/scripts/variables/MAKE_RESTARTS62
8 files changed, 221 insertions, 49 deletions
diff --git a/ChangeLog b/ChangeLog
index 227c0b4..648e502 100644
--- a/ChangeLog
+++ b/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.
diff --git a/NEWS b/NEWS
index b3a5634..b39114d 100644
--- a/NEWS
+++ b/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.
diff --git a/default.c b/default.c
index 58855c6..ba96c61 100644
--- a/default.c
+++ b/default.c
@@ -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
diff --git a/doc/make.texi b/doc/make.texi
index f17a5d4..f51fe32 100644
--- a/doc/make.texi
+++ b/doc/make.texi
@@ -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}
diff --git a/main.c b/main.c
index 60d11ab..0be958d 100644
--- a/main.c
+++ b/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 ();
- /* Print version information. */
+ /* 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,43 +2009,60 @@ main (int argc, char **argv, char **envp)
fatal (NILF, _("Couldn't change back to original directory."));
}
+ ++restarts;
+
+ if (ISDB (DB_BASIC))
+ {
+ char **p;
+ 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);
- break;
- }
+ {
+ 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];
- int len;
- len = GetVar (MAKELEVEL_NAME, buffer, sizeof (buffer), GVF_GLOBAL_ONLY);
+ sprintf (buffer, "%u", makelevel);
+ SetVar (MAKELEVEL_NAME, buffer, -1, GVF_GLOBAL_ONLY);
- if (len != -1)
- {
- 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 (ISDB (DB_BASIC))
- {
- char **p;
- fputs (_("Re-executing:"), stdout);
- for (p = nargv; *p != 0; ++p)
- printf (" %s", *p);
- putchar ('\n');
- }
+ /* 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
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 2e22195..90fbf7d 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -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.
diff --git a/tests/scripts/options/dash-B b/tests/scripts/options/dash-B
index 4ac377f..864a01f 100644
--- a/tests/scripts/options/dash-B
+++ b/tests/scripts/options/dash-B
@@ -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;
diff --git a/tests/scripts/variables/MAKE_RESTARTS b/tests/scripts/variables/MAKE_RESTARTS
new file mode 100644
index 0000000..53ab738
--- /dev/null
+++ b/tests/scripts/variables/MAKE_RESTARTS
@@ -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;