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.
+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.
* Compiling GNU make now requires a conforming ISO C 1989 compiler and
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
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
* 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.
+
\f
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
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
@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
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__
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. */
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)
{
#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';
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)
{
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
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
}
#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;
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
/* 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;
+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
--- /dev/null
+# -*-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;
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;