summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2010-07-06 06:37:42 +0000
committerPaul Smith <psmith@gnu.org>2010-07-06 06:37:42 +0000
commitc7b469f0f337247acb83067d8f4aa4dc76b8a9a9 (patch)
treeb3b657564a46ef50c7478480f2659064b7e0d12d
parentc78b7265bd1ee374a5e515d79448d0e3452b5ede (diff)
downloadgunmake-c7b469f0f337247acb83067d8f4aa4dc76b8a9a9.tar.gz
- Enhance .POSIX to set -e when invoking shells, as demanded by a
backward-incompatible change in the 2008 POSIX specification. - Add the .SHELLFLAGS variable so people can choose their own shell flags. - Add tests for this. - Add documentation for this.
-rw-r--r--ChangeLog10
-rw-r--r--NEWS20
-rw-r--r--doc/make.texi22
-rw-r--r--job.c43
-rw-r--r--main.c21
-rw-r--r--read.c5
-rw-r--r--tests/ChangeLog7
-rw-r--r--tests/scripts/targets/POSIX26
-rw-r--r--tests/scripts/variables/SHELL14
9 files changed, 137 insertions, 31 deletions
diff --git a/ChangeLog b/ChangeLog
index 7b9711b..f77391c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2010-07-06 Paul Smith <psmith@gnu.org>
+
+ * main.c (main): Set a default value of "-c" for .SHELLFLAGS.
+ * NEWS: Mention the new behavior of .POSIX and the new .SHELLFLAGS
+ variable.
+ * job.c (construct_command_argv): Retrieve the .SHELLFLAGS value
+ and pass it to construct_command_argv_internal().
+ (construct_command_argv_internal): If .SHELLFLAGS is non-standard
+ use the slow path. Use that value instead of hard-coded "-c".
+
2010-07-05 Paul Smith <psmith@gnu.org>
* implicit.c (pattern_search): lastslash can be const.
diff --git a/NEWS b/NEWS
index f452686..b9577c9 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,15 @@ Version 3.81.90
standard runtime library.
* WARNING: Backward-incompatibility!
+ The POSIX standard for make was changed in the 2008 version in a
+ fundamentally incompatible way: make is required to invoke the shell as if
+ the '-e' flag were provided. Because this would break many makefiles that
+ have been written to conform to the original text of the standard, the
+ default behavior of GNU make remains to invoke the shell with simply '-c'.
+ However, any makefile specifying the .POSIX special target will follow the
+ new POSIX standard and pass '-e' to the shell. See also .SHELLFLAGS below.
+
+* WARNING: Backward-incompatibility!
The '$?' variable now contains all prerequisites that caused the target to
be considered out of date, even if they do not exist (previously only
existing targets were provided in $?).
@@ -58,6 +67,10 @@ Version 3.81.90
set and reset at will; recipes will use the value active when they were
first parsed. To detect this feature check the value of $(.RECIPEPREFIX).
+* New special variable: .SHELLFLAGS allows you to change the options passed to
+ the shell when it invokes recipes. By default the value will be "-c" (or
+ "-ec" if .POSIX is set).
+
* New variable modifier 'private': prefixing a variable assignment with the
modifier 'private' suppresses inheritance of that variable by
prerequisites. This is most useful for target- and pattern-specific
@@ -66,13 +79,17 @@ Version 3.81.90
* New make directive: 'undefine' allows you to undefine a variable so
that it appears as if it was never set. Both $(flavor) and $(origin)
functions will return 'undefined' for such a variable. To detect this
- feature search for 'undefine in the .FEATURES special variable.
+ feature search for 'undefine' in the .FEATURES special variable.
* The parser for variable assignments has been enhanced to allow multiple
modifiers ('export', 'override', 'private') on the same line as variables,
including define/endef variables, and in any order. Also, it is possible
to create variables and targets named as these modifiers.
+* The 'define' make directive now allows a variable assignment operator after
+ the variable name, to allow for simple, conditional, or appending multi-line
+ variable assignment.
+
Version 3.81
@@ -109,7 +126,6 @@ Version 3.81
of this SysV feature you will need to update them.
* WARNING: Backward-incompatibility!
-
In order to comply with POSIX, the way in which GNU make processes
backslash-newline sequences in recipes has changed. If your makefiles
use backslash-newline sequences inside of single-quoted strings in
diff --git a/doc/make.texi b/doc/make.texi
index 7187e19..35a40dd 100644
--- a/doc/make.texi
+++ b/doc/make.texi
@@ -2873,6 +2873,21 @@ of @code{make} will be run serially, even if the @samp{-j} option is
given. Any recursively invoked @code{make} command will still run
recipes in parallel (unless its makefile also contains this target).
Any prerequisites on this target are ignored.
+
+@findex .POSIX
+@item .POSIX
+@cindex POSIX-conforming mode, setting
+
+If @code{.POSIX} is mentioned as a target, then the makefile will be
+parsed and run in POSIX-conforming mode. This does @emph{not} mean
+that only POSIX-conforming makefiles will be accepted: all advanced
+GNU @code{make} features are still available. Rather, this target
+causes @code{make} to behave as required by POSIX in those areas
+where @code{make}'s default behavior differs.
+
+In particular, if this target is mentioned then recipes will be
+invoked as if the shell had been passed the @code{-e} flag: the first
+failing command in a recipe will cause the recipe to fail immediately.
@end table
Any defined implicit rule suffix also counts as a special target if it
@@ -3713,11 +3728,16 @@ truncated, at least).
@subsection Choosing the Shell
@cindex shell, choosing the
@cindex @code{SHELL}, value of
+@cindex @code{.SHELLFLAGS}, value of
@vindex SHELL
+@vindex .SHELLFLAGS
The program used as the shell is taken from the variable @code{SHELL}.
If this variable is not set in your makefile, the program
-@file{/bin/sh} is used as the shell.
+@file{/bin/sh} is used as the shell. The argument(s) passed to the
+shell are taken from the variable @code{.SHELLFLAGS}. The default
+value of @code{.SHELLFLAGS} is @code{-c} normally, or @code{-ec} in
+POSIX-conforming mode.
@cindex environment, @code{SHELL} in
Unlike most variables, the variable @code{SHELL} is never set from the
diff --git a/job.c b/job.c
index 03d8a83..8e83a47 100644
--- a/job.c
+++ b/job.c
@@ -2228,7 +2228,7 @@ void clean_tmp (void)
static char **
construct_command_argv_internal (char *line, char **restp, char *shell,
- char *ifs, int flags,
+ char *shellflags, char *ifs, int flags,
char **batch_filename_ptr)
{
#ifdef __MSDOS__
@@ -2436,6 +2436,12 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
if (*ap != ' ' && *ap != '\t' && *ap != '\n')
goto slow;
+ if (shellflags != 0)
+ if (shellflags[0] != '-'
+ || ((shellflags[1] != 'c' || shellflags[2] != '\0')
+ && (shellflags[1] != 'e' || shellflags[2] != 'c' || shellflags[3] != '\0')))
+ goto slow;
+
i = strlen (line) + 1;
/* More than 1 arg per character is impossible. */
@@ -2717,34 +2723,33 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
if (*line == '\0')
return 0;
#endif /* WINDOWS32 */
+
{
/* SHELL may be a multi-word command. Construct a command line
- "SHELL -c LINE", with all special chars in LINE escaped.
+ "$(SHELL) $(.SHELLFLAGS) LINE", with all special chars in LINE escaped.
Then recurse, expanding this command line to get the final
argument list. */
unsigned int shell_len = strlen (shell);
-#ifndef VMS
- static char minus_c[] = " -c ";
-#else
- static char minus_c[] = "";
-#endif
unsigned int line_len = strlen (line);
+ unsigned int sflags_len = strlen (shellflags);
- char *new_line = alloca (shell_len + (sizeof (minus_c)-1)
+ char *new_line = alloca (shell_len + 1 + sflags_len + 1
+ (line_len*2) + 1);
char *command_ptr = NULL; /* used for batch_mode_shell mode */
# ifdef __EMX__ /* is this necessary? */
if (!unixy_shell)
- minus_c[1] = '/'; /* " /c " */
+ shellflags[0] = '/'; /* "/c" */
# endif
ap = new_line;
memcpy (ap, shell, shell_len);
ap += shell_len;
- memcpy (ap, minus_c, sizeof (minus_c) - 1);
- ap += sizeof (minus_c) - 1;
+ *(ap++) = ' ';
+ memcpy (ap, shellflags, sflags_len);
+ ap += sflags_len;
+ *(ap++) = ' ';
command_ptr = ap;
for (p = line; *p != '\0'; ++p)
{
@@ -2794,7 +2799,7 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
#endif
*ap++ = *p;
}
- if (ap == new_line + shell_len + sizeof (minus_c) - 1)
+ if (ap == new_line + shell_len + sflags_len + 2)
/* Line was empty. */
return 0;
*ap = '\0';
@@ -2846,8 +2851,10 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
new_argv[2] = NULL;
} else
#endif /* WINDOWS32 */
+
if (unixy_shell)
- new_argv = construct_command_argv_internal (new_line, 0, 0, 0, flags, 0);
+ new_argv = construct_command_argv_internal (new_line, 0, 0, 0, 0, flags, 0);
+
#ifdef __EMX__
else if (!unixy_shell)
{
@@ -2923,10 +2930,10 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
instead of recursively calling ourselves, because we
cannot backslash-escape the special characters (see above). */
new_argv = xmalloc (sizeof (char *));
- line_len = strlen (new_line) - shell_len - sizeof (minus_c) + 1;
+ line_len = strlen (new_line) - shell_len - sflags_len - 2;
new_argv[0] = xmalloc (line_len + 1);
strncpy (new_argv[0],
- new_line + shell_len + sizeof (minus_c) - 1, line_len);
+ new_line + shell_len + sflags_len + 2, line_len);
new_argv[0][line_len] = '\0';
}
#else
@@ -2958,7 +2965,7 @@ char **
construct_command_argv (char *line, char **restp, struct file *file,
int cmd_flags, char **batch_filename_ptr)
{
- char *shell, *ifs;
+ char *shell, *ifs, *shellflags;
char **argv;
#ifdef VMS
@@ -3063,15 +3070,17 @@ construct_command_argv (char *line, char **restp, struct file *file,
}
#endif /* __EMX__ */
+ shellflags = allocated_variable_expand_for_file ("$(.SHELLFLAGS)", file);
ifs = allocated_variable_expand_for_file ("$(IFS)", file);
warn_undefined_variables_flag = save;
}
- argv = construct_command_argv_internal (line, restp, shell, ifs,
+ argv = construct_command_argv_internal (line, restp, shell, shellflags, ifs,
cmd_flags, batch_filename_ptr);
free (shell);
+ free (shellflags);
free (ifs);
#endif /* !VMS */
return argv;
diff --git a/main.c b/main.c
index 20b445a..c972e65 100644
--- a/main.c
+++ b/main.c
@@ -1123,26 +1123,27 @@ main (int argc, char **argv, char **envp)
define_variable_cname (".VARIABLES", "", o_default, 0)->special = 1;
/* define_variable_cname (".TARGETS", "", o_default, 0)->special = 1; */
define_variable_cname (".RECIPEPREFIX", "", o_default, 0)->special = 1;
+ define_variable_cname (".SHELLFLAGS", "-c", o_default, 0);
/* Set up .FEATURES
We must do this in multiple calls because define_variable_cname() is
a macro and some compilers (MSVC) don't like conditionals in macros. */
- define_variable_cname (".FEATURES",
- "target-specific order-only second-expansion else-if"
- " shortest-stem undefine",
- o_default, 0);
+ {
+ const char *features = "target-specific order-only second-expansion"
+ " else-if shortest-stem undefine"
#ifndef NO_ARCHIVES
- do_variable_definition (NILF, ".FEATURES", "archives",
- o_default, f_append, 0);
+ " archives"
#endif
#ifdef MAKE_JOBSERVER
- do_variable_definition (NILF, ".FEATURES", "jobserver",
- o_default, f_append, 0);
+ " jobserver"
#endif
#ifdef MAKE_SYMLINKS
- do_variable_definition (NILF, ".FEATURES", "check-symlink",
- o_default, f_append, 0);
+ " check-symlink"
#endif
+ ;
+
+ define_variable_cname (".FEATURES", features, o_default, 0);
+ }
/* Read in variables from the environment. It is important that this be
done before $(MAKE) is figured out so its definitions will not be
diff --git a/read.c b/read.c
index 591f1f3..1e8d2f3 100644
--- a/read.c
+++ b/read.c
@@ -1958,7 +1958,10 @@ record_files (struct nameseq *filenames, const char *pattern,
/* Check for special targets. Do it here instead of, say, snap_deps()
so that we can immediately use the value. */
if (streq (name, ".POSIX"))
- posix_pedantic = 1;
+ {
+ posix_pedantic = 1;
+ define_variable_cname (".SHELLFLAGS", "-ec", o_default, 0);
+ }
else if (streq (name, ".SECONDEXPANSION"))
second_expansion = 1;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index c8f3aab..a611422 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,10 @@
+2010-07-06 Paul Smith <psmith@gnu.org>
+
+ * scripts/variables/SHELL: Test the new .SHELLFLAGS variable.
+
+ * scripts/targets/POSIX: New file. Test the .POSIX special target.
+ Verify that enabling .POSIX changes the shell flags to set -e.
+
2010-07-01 Paul Smith <psmith@gnu.org>
* scripts/features/recursion: Add a space to separate command-line
diff --git a/tests/scripts/targets/POSIX b/tests/scripts/targets/POSIX
new file mode 100644
index 0000000..662c16d
--- /dev/null
+++ b/tests/scripts/targets/POSIX
@@ -0,0 +1,26 @@
+# -*-perl-*-
+
+$description = "Test the behaviour of the .PHONY target.";
+
+$details = "";
+
+
+# Ensure turning on .POSIX enables the -e flag for the shell
+
+run_make_test(q!
+.POSIX:
+all: ; @false; true
+!,
+ '', "#MAKE#: *** [all] Error 1\n", 512);
+
+# User settings must override .POSIX
+
+run_make_test(q!
+.SHELLFLAGS = -xc
+.POSIX:
+all: ; @false; true
+!,
+ '', "+ false\n+ true\n");
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/variables/SHELL b/tests/scripts/variables/SHELL
index a303540..69871d2 100644
--- a/tests/scripts/variables/SHELL
+++ b/tests/scripts/variables/SHELL
@@ -56,4 +56,18 @@ two: export SHELL := /./$mshell\n".'
one two:;@echo "$@: $(SHELL) $$SHELL"
', '', "two: /./$mshell /./$mshell\none: /././$mshell $mshell\n");
+# Test .SHELLFLAGS
+
+run_make_test(q!
+.SHELLFLAGS = -xc
+all: ; @true
+!,
+ '', "+ true\n");
+
+run_make_test(q!
+.SHELLFLAGS = -xec
+all: ; @true; false; true
+!,
+ '', "+ true\n+ false\n#MAKE#: *** [all] Error 1\n", 512);
+
1;