- 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.
This commit is contained in:
Paul Smith 2010-07-06 06:37:42 +00:00
parent c78b7265bd
commit c7b469f0f3
9 changed files with 137 additions and 31 deletions

View file

@ -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.

20
NEWS
View file

@ -14,6 +14,15 @@ Version 3.81.90
* 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
@ -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

View file

@ -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

43
job.c
View file

@ -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;

21
main.c
View file

@ -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

5
read.c
View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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;