Add a new variable: MAKE_RESTARTS, to count how many times make has re-exec'd.
authorPaul Smith <psmith@gnu.org>
Sat, 25 Jun 2005 18:57:28 +0000 (18:57 +0000)
committerPaul Smith <psmith@gnu.org>
Sat, 25 Jun 2005 18:57:28 +0000 (18:57 +0000)
When rebuilding makefiles, unset -B if MAKE_RESTARTS is >0.

ChangeLog
NEWS
default.c
doc/make.texi
main.c
tests/ChangeLog
tests/scripts/options/dash-B
tests/scripts/variables/MAKE_RESTARTS [new file with mode: 0644]

index 227c0b4..648e502 100644 (file)
--- 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 (file)
--- 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.
 
index 58855c6..ba96c61 100644 (file)
--- 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
index f17a5d4..f51fe32 100644 (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}
diff --git a/main.c b/main.c
index 60d11ab..0be958d 100644 (file)
--- 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
index 2e22195..90fbf7d 100644 (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.
index 4ac377f..864a01f 100644 (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;
diff --git a/tests/scripts/variables/MAKE_RESTARTS b/tests/scripts/variables/MAKE_RESTARTS
new file mode 100644 (file)
index 0000000..53ab738
--- /dev/null
@@ -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;