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.
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.
@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
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
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
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
int rebuilding_makefiles = 0;
+/* Remember the original value of the SHELL variable, from the environment. */
+
+const char *env_shell = 0;
+
\f
/* The usage output. We write it this way to make life easier for the
translators, especially those trying to translate to right-to-left
#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;
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
/*
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;
+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 ).
-# -*-perl-mode-*-
+# -*-perl-*-
$description = "The following test creates a makefile to test
makelevels in Make. It prints \$(MAKELEVEL) and then
# The Contents of the MAKEFILE ...
print MAKEFILE <<EOF;
-SHELL = /bin/sh
all:
\t\@echo MAKELEVEL is \$(MAKELEVEL)
\techo \$\$MAKELEVEL
--- /dev/null
+# -*-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;
#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)
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;
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)