diff options
author | Paul Smith <psmith@gnu.org> | 2004-11-28 23:11:23 +0000 |
---|---|---|
committer | Paul Smith <psmith@gnu.org> | 2004-11-28 23:11:23 +0000 |
commit | 539f513773b2e651d987a7bdbdffd8b5164d58cf (patch) | |
tree | 7a692764273cc0892dbc715b6e095f63f93ea1e8 | |
parent | d27cac1598207e9bfc3ffb47c7e609360b83ca69 (diff) | |
download | gunmake-539f513773b2e651d987a7bdbdffd8b5164d58cf.tar.gz |
Fix for bug #1276: Handle SHELL according to POSIX requirements.
POSIX requires that the value of SHELL in the makefile NOT be exported
to sub-commands. Instead, the value in the environment when make was
invoked should be passed to the environment of sub-commands. Note that
make still uses SHELL to _run_ sub-commands; it just doesn't change the
value of the SHELL variable in the environment of sub-commands.
As an extension to POSIX, if the makefile explicitly exports SHELL then
GNU make _will_ use it in the environment of sub-commands.
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | doc/make.texi | 56 | ||||
-rw-r--r-- | main.c | 43 | ||||
-rw-r--r-- | make.h | 2 | ||||
-rw-r--r-- | tests/ChangeLog | 5 | ||||
-rw-r--r-- | tests/scripts/variables/MAKELEVEL | 3 | ||||
-rw-r--r-- | tests/scripts/variables/SHELL | 49 | ||||
-rw-r--r-- | variable.c | 26 |
8 files changed, 150 insertions, 46 deletions
@@ -1,5 +1,17 @@ 2004-11-28 Paul D. Smith <psmith@gnu.org> + Fix for bug #1276: Handle SHELL according to POSIX requirements. + + * main.c (main): Set SHELL to v_noexport by default. Remember the + original environment setting of SHELL in the env_shell variable. + * main.h: Export new env_shell variable. + * variable.c (target_environment): If we find a v_noexport + variable for SHELL, add a SHELL variable with the env_shell value. + * doc/make.texi (Quick Reference): Document the POSIX behavior. + * doc/make.texi (Variables/Recursion): Ditto. + +2004-11-28 Paul D. Smith <psmith@gnu.org> + * main.c (find_and_set_default_shell) [WINDOWS32]: check for equality of "cmd"/"cmd.exe", not inequality. Fixes bug #11155. Patch by Alessandro Vesely. diff --git a/doc/make.texi b/doc/make.texi index a31c3ad..14d7278 100644 --- a/doc/make.texi +++ b/doc/make.texi @@ -3732,9 +3732,15 @@ line, and if its name consists only of letters, numbers, and underscores. Some shells cannot cope with environment variable names consisting of characters other than letters, numbers, and underscores. -The special variables @code{SHELL} and @code{MAKEFLAGS} are always -exported (unless you unexport them). -@code{MAKEFILES} is exported if you set it to anything. +@cindex SHELL, exported value +The value of the @code{make} variable @code{SHELL} is not exported. +Instead, the value of the @code{SHELL} variable from the invoking +environment is passed to the sub-@code{make}. You can force +@code{make} to export its value for @code{SHELL} by using the +@code{export} directive, described below. + +The special variable @code{MAKEFLAGS} is always exported (unless you +unexport it). @code{MAKEFILES} is exported if you set it to anything. @code{make} automatically passes down variable values that were defined on the command line, by putting them in the @code{MAKEFLAGS} variable. @@ -5137,28 +5143,28 @@ endef @cindex variables, environment @cindex environment Variables in @code{make} can come from the environment in which -@code{make} is run. Every environment variable that @code{make} sees when -it starts up is transformed into a @code{make} variable with the same name -and value. But an explicit assignment in the makefile, or with a command -argument, overrides the environment. (If the @samp{-e} flag is specified, -then values from the environment override assignments in the makefile. -@xref{Options Summary, ,Summary of Options}. -But this is not recommended practice.) +@code{make} is run. Every environment variable that @code{make} sees +when it starts up is transformed into a @code{make} variable with the +same name and value. However, an explicit assignment in the makefile, +or with a command argument, overrides the environment. (If the +@samp{-e} flag is specified, then values from the environment override +assignments in the makefile. @xref{Options Summary, ,Summary of +Options}. But this is not recommended practice.) Thus, by setting the variable @code{CFLAGS} in your environment, you can cause all C compilations in most makefiles to use the compiler switches you prefer. This is safe for variables with standard or conventional meanings -because you know that no makefile will use them for other things. (But +because you know that no makefile will use them for other things. (Note this is not totally reliable; some makefiles set @code{CFLAGS} explicitly and therefore are not affected by the value in the environment.) -When @code{make} is invoked recursively, variables defined in the -outer invocation can be passed to inner invocations through the -environment (@pxref{Recursion, ,Recursive Use of @code{make}}). By -default, only variables that came from the environment or the command -line are passed to recursive invocations. You can use the -@code{export} directive to pass other variables. -@xref{Variables/Recursion, , Communicating Variables to a +When @code{make} runs a command script, variables defined in the +makefile are placed into the environment of that command. This allows +you to pass values to sub-@code{make} invocations. (@pxref{Recursion, +,Recursive Use of @code{make}}). By default, only variables that came +from the environment or the command line are passed to recursive +invocations. You can use the @code{export} directive to pass other +variables. @xref{Variables/Recursion, , Communicating Variables to a Sub-@code{make}}, for full details. Other use of variables from the environment is not recommended. It is not @@ -5167,6 +5173,7 @@ set up outside their control, since this would cause different users to get different results from the same makefile. This is against the whole purpose of most makefiles. +@cindex SHELL, import from environment Such problems would be especially likely with the variable @code{SHELL}, which is normally present in the environment to specify the user's choice of interactive shell. It would be very undesirable for this choice to @@ -5175,6 +5182,15 @@ affect @code{make}. So @code{make} ignores the environment value of usually not set. @xref{Execution, ,Special handling of SHELL on MS-DOS}.)@refill +@cindex SHELL, export to environment +The @code{SHELL} variable is special in another way: just as the value +of the @code{make} variable @code{SHELL} is not taken from the +environment, so also it is not placed into the environment of commands +that @code{make} invokes. Instead, the value of @code{SHELL} from the +invoking environment is provided to the command. You can use +@code{export SHELL} to force the value of the @code{make} variable +@code{SHELL} to be placed in the environment of commands. + @node Target-specific, Pattern-specific, Environment, Using Variables @section Target-specific Variable Values @cindex target-specific variables @@ -9865,7 +9881,9 @@ Directory search path for files not found in the current directory.@* The name of the system default command interpreter, usually @file{/bin/sh}. You can set @code{SHELL} in the makefile to change the shell used to run -commands. @xref{Execution, ,Command Execution}. +commands. @xref{Execution, ,Command Execution}. The @code{SHELL} +variable is handled specially when importing from and exporting to the +environment. @xref{Environment, ,Using Variable from the Environment}. @item MAKESHELL @@ -264,6 +264,10 @@ int always_make_flag = 0; int rebuilding_makefiles = 0; +/* Remember the original value of the SHELL variable, from the environment. */ + +const char *env_shell = 0; + /* The usage output. We write it this way to make life easier for the translators, especially those trying to translate to right-to-left @@ -1045,11 +1049,8 @@ main (int argc, char **argv, char **envp) #ifndef _AMIGA for (i = 0; envp[i] != 0; ++i) { - int do_not_define; - register char *ep = envp[i]; - - /* by default, everything gets defined and exported */ - do_not_define = 0; + int do_not_define = 0; + char *ep = envp[i]; while (*ep != '=') ++ep; @@ -1065,17 +1066,27 @@ main (int argc, char **argv, char **envp) machines where ptrdiff_t is a different size that doesn't widen the same. */ if (!do_not_define) - define_variable (envp[i], (unsigned int) (ep - envp[i]), - ep + 1, o_env, 1) - /* Force exportation of every variable culled from the environment. - We used to rely on target_environment's v_default code to do this. - But that does not work for the case where an environment variable - is redefined in a makefile with `override'; it should then still - be exported, because it was originally in the environment. - 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... */ - ->export = strncmp(envp[i], "SHELL=", 6) ? v_noexport : v_export; + { + struct variable *v; + + v = define_variable (envp[i], (unsigned int) (ep - envp[i]), + ep + 1, o_env, 1); + /* Force exportation of every variable culled from the environment. + We used to rely on target_environment's v_default code to do this. + But that does not work for the case where an environment variable + is redefined in a makefile with `override'; it should then still + be exported, because it was originally in the environment. */ + 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) + { + v->export = v_noexport; + env_shell = xstrdup (ep + 1); + } + } } #ifdef WINDOWS32 /* @@ -496,6 +496,8 @@ extern int print_version_flag, print_directory_flag; extern int warn_undefined_variables_flag, posix_pedantic, not_parallel; extern int clock_skew_detected, rebuilding_makefiles; +extern const char *env_shell; + /* can we run commands via 'sh -c xxx' or must we use batch files? */ extern int batch_mode_shell; diff --git a/tests/ChangeLog b/tests/ChangeLog index 8cc25db..a6423b0 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2004-11-28 Paul D. Smith <psmith@gnu.org> + + * scripts/variables/SHELL: New file: test proper handling of SHELL + according to POSIX rules. Fixes bug #1276. + 2004-10-21 Boris Kolpackov <boris@kolpackov.net> * scripts/functions/word: Test $(firstword ) and $(lastword ). diff --git a/tests/scripts/variables/MAKELEVEL b/tests/scripts/variables/MAKELEVEL index 79a184e..96a4e74 100644 --- a/tests/scripts/variables/MAKELEVEL +++ b/tests/scripts/variables/MAKELEVEL @@ -1,4 +1,4 @@ -# -*-perl-mode-*- +# -*-perl-*- $description = "The following test creates a makefile to test makelevels in Make. It prints \$(MAKELEVEL) and then @@ -9,7 +9,6 @@ open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE <<EOF; -SHELL = /bin/sh all: \t\@echo MAKELEVEL is \$(MAKELEVEL) \techo \$\$MAKELEVEL diff --git a/tests/scripts/variables/SHELL b/tests/scripts/variables/SHELL new file mode 100644 index 0000000..9ff5c4b --- /dev/null +++ b/tests/scripts/variables/SHELL @@ -0,0 +1,49 @@ +# -*-perl-*- + +$description = "Test proper handling of SHELL."; + +# Find the default value when SHELL is not set. On UNIX it will be /bin/sh, +# but on other platforms who knows? +$oshell = $ENV{SHELL}; +delete $ENV{SHELL}; +$mshell = `echo 'all:;\@echo \$(SHELL)' | $make_name -f-`; +chop $mshell; + +# According to POSIX, the value of SHELL in the environment has no impact on +# the value in the makefile. + +$ENV{SHELL} = '/dev/null'; +run_make_test('all:;@echo "$(SHELL)"', '', $mshell); + +# According to POSIX, any value of SHELL set in the makefile should _NOT_ be +# exported to the subshell! I wanted to set SHELL to be $^X (perl) in the +# makefile, but make runs $(SHELL) -c 'commandline' and that doesn't work at +# all when $(SHELL) is perl :-/. So, we just add an extra initial / and hope +# for the best on non-UNIX platforms :-/. + +$ENV{SHELL} = $mshell; + +run_make_test("SHELL := /$mshell\n".' +all:;@echo "$(SHELL) $$SHELL" +', '', "/$mshell $mshell"); + +# As a GNU make extension, if make's SHELL variable is explicitly exported, +# then we really _DO_ export it. + +run_make_test("export SHELL := /$mshell\n".' +all:;@echo "$(SHELL) $$SHELL" +', '', "/$mshell /$mshell"); + + +# Test out setting of SHELL, both exported and not, as a target-specific +# variable. + +run_make_test("all: SHELL := /$mshell\n".' +all:;@echo "$(SHELL) $$SHELL" +', '', "/$mshell $mshell"); + +run_make_test("all: export SHELL := /$mshell\n".' +all:;@echo "$(SHELL) $$SHELL" +', '', "/$mshell $mshell"); + +1; @@ -739,16 +739,14 @@ define_automatic_variables (void) #endif - /* This won't override any definition, but it - will provide one if there isn't one there. */ + /* This won't override any definition, but it will provide one if there + isn't one there. */ v = define_variable ("SHELL", 5, default_shell, o_default, 0); - v->export = v_export; /* Always export SHELL. */ - /* On MSDOS we do use SHELL from environment, since - it isn't a standard environment variable on MSDOS, - so whoever sets it, does that on purpose. - On OS/2 we do not use SHELL from environment but - we have already handled that problem above. */ + /* On MSDOS we do use SHELL from environment, since it isn't a standard + environment variable on MSDOS, so whoever sets it, does that on purpose. + On OS/2 we do not use SHELL from environment but we have already handled + that problem above. */ #if !defined(__MSDOS__) && !defined(__EMX__) /* Don't let SHELL come from the environment. */ if (*v->value == '\0' || v->origin == o_env || v->origin == o_env_override) @@ -809,6 +807,11 @@ target_environment (struct file *file) struct variable makelevel_key; char **result_0; char **result; + struct variable ev; + + /* Set up a fake variable struct for the original SHELL value. */ + ev.name = "SHELL"; + ev.value = env_shell; if (file == 0) set_list = current_variable_set_list; @@ -865,7 +868,12 @@ target_environment (struct file *file) break; case v_noexport: - continue; + if (!streq (v->name, "SHELL")) + continue; + /* If this is the SHELL variable and it's not exported, then + add the value from our original environment. */ + v = &ev; + break; case v_ifset: if (v->origin == o_default) |