From 978819e1d6e9354b5b20d15c875bef98579873ae Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Sat, 25 Jun 2005 18:57:28 +0000 Subject: [PATCH] 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. --- ChangeLog | 21 ++++++ NEWS | 5 +- default.c | 3 +- doc/make.texi | 16 ++++- main.c | 120 +++++++++++++++++++++------------- tests/ChangeLog | 7 ++ tests/scripts/options/dash-B | 36 +++++++++- tests/scripts/variables/MAKE_RESTARTS | 62 ++++++++++++++++++ 8 files changed, 221 insertions(+), 49 deletions(-) create mode 100644 tests/scripts/variables/MAKE_RESTARTS diff --git a/ChangeLog b/ChangeLog index 227c0b4..648e502 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2005-06-25 Paul D. Smith + + 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 + + * default.c: Change VMS implicit rules to use $$$$ instead of $$ + in the prerequisites list. + 2005-06-12 Paul D. Smith 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 + + * 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 * 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; -- 2.7.4