mirror of
https://git.savannah.gnu.org/git/make.git
synced 2025-01-27 01:27:58 +00:00
- 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:
parent
c78b7265bd
commit
c7b469f0f3
9 changed files with 137 additions and 31 deletions
10
ChangeLog
10
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.
|
||||
|
|
20
NEWS
20
NEWS
|
@ -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
|
||||
|
|
|
@ -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
43
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;
|
||||
|
|
21
main.c
21
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
|
||||
|
|
5
read.c
5
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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
26
tests/scripts/targets/POSIX
Normal file
26
tests/scripts/targets/POSIX
Normal 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;
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue