mirror of
https://github.com/mirror/make.git
synced 2025-03-27 20:40:35 +08: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
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>
|
2010-07-05 Paul Smith <psmith@gnu.org>
|
||||||
|
|
||||||
* implicit.c (pattern_search): lastslash can be const.
|
* 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
|
* Compiling GNU make now requires a conforming ISO C 1989 compiler and
|
||||||
standard runtime library.
|
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!
|
* WARNING: Backward-incompatibility!
|
||||||
The '$?' variable now contains all prerequisites that caused the target to
|
The '$?' variable now contains all prerequisites that caused the target to
|
||||||
be considered out of date, even if they do not exist (previously only
|
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
|
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).
|
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
|
* New variable modifier 'private': prefixing a variable assignment with the
|
||||||
modifier 'private' suppresses inheritance of that variable by
|
modifier 'private' suppresses inheritance of that variable by
|
||||||
prerequisites. This is most useful for target- and pattern-specific
|
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
|
* New make directive: 'undefine' allows you to undefine a variable so
|
||||||
that it appears as if it was never set. Both $(flavor) and $(origin)
|
that it appears as if it was never set. Both $(flavor) and $(origin)
|
||||||
functions will return 'undefined' for such a variable. To detect this
|
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
|
* The parser for variable assignments has been enhanced to allow multiple
|
||||||
modifiers ('export', 'override', 'private') on the same line as variables,
|
modifiers ('export', 'override', 'private') on the same line as variables,
|
||||||
including define/endef variables, and in any order. Also, it is possible
|
including define/endef variables, and in any order. Also, it is possible
|
||||||
to create variables and targets named as these modifiers.
|
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
|
Version 3.81
|
||||||
|
|
||||||
@ -109,7 +126,6 @@ Version 3.81
|
|||||||
of this SysV feature you will need to update them.
|
of this SysV feature you will need to update them.
|
||||||
|
|
||||||
* WARNING: Backward-incompatibility!
|
* WARNING: Backward-incompatibility!
|
||||||
|
|
||||||
In order to comply with POSIX, the way in which GNU make processes
|
In order to comply with POSIX, the way in which GNU make processes
|
||||||
backslash-newline sequences in recipes has changed. If your makefiles
|
backslash-newline sequences in recipes has changed. If your makefiles
|
||||||
use backslash-newline sequences inside of single-quoted strings in
|
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
|
given. Any recursively invoked @code{make} command will still run
|
||||||
recipes in parallel (unless its makefile also contains this target).
|
recipes in parallel (unless its makefile also contains this target).
|
||||||
Any prerequisites on this target are ignored.
|
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
|
@end table
|
||||||
|
|
||||||
Any defined implicit rule suffix also counts as a special target if it
|
Any defined implicit rule suffix also counts as a special target if it
|
||||||
@ -3713,11 +3728,16 @@ truncated, at least).
|
|||||||
@subsection Choosing the Shell
|
@subsection Choosing the Shell
|
||||||
@cindex shell, choosing the
|
@cindex shell, choosing the
|
||||||
@cindex @code{SHELL}, value of
|
@cindex @code{SHELL}, value of
|
||||||
|
@cindex @code{.SHELLFLAGS}, value of
|
||||||
|
|
||||||
@vindex SHELL
|
@vindex SHELL
|
||||||
|
@vindex .SHELLFLAGS
|
||||||
The program used as the shell is taken from the variable @code{SHELL}.
|
The program used as the shell is taken from the variable @code{SHELL}.
|
||||||
If this variable is not set in your makefile, the program
|
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
|
@cindex environment, @code{SHELL} in
|
||||||
Unlike most variables, the variable @code{SHELL} is never set from the
|
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 **
|
static char **
|
||||||
construct_command_argv_internal (char *line, char **restp, char *shell,
|
construct_command_argv_internal (char *line, char **restp, char *shell,
|
||||||
char *ifs, int flags,
|
char *shellflags, char *ifs, int flags,
|
||||||
char **batch_filename_ptr)
|
char **batch_filename_ptr)
|
||||||
{
|
{
|
||||||
#ifdef __MSDOS__
|
#ifdef __MSDOS__
|
||||||
@ -2436,6 +2436,12 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
|
|||||||
if (*ap != ' ' && *ap != '\t' && *ap != '\n')
|
if (*ap != ' ' && *ap != '\t' && *ap != '\n')
|
||||||
goto slow;
|
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;
|
i = strlen (line) + 1;
|
||||||
|
|
||||||
/* More than 1 arg per character is impossible. */
|
/* 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')
|
if (*line == '\0')
|
||||||
return 0;
|
return 0;
|
||||||
#endif /* WINDOWS32 */
|
#endif /* WINDOWS32 */
|
||||||
|
|
||||||
{
|
{
|
||||||
/* SHELL may be a multi-word command. Construct a command line
|
/* 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
|
Then recurse, expanding this command line to get the final
|
||||||
argument list. */
|
argument list. */
|
||||||
|
|
||||||
unsigned int shell_len = strlen (shell);
|
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 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);
|
+ (line_len*2) + 1);
|
||||||
char *command_ptr = NULL; /* used for batch_mode_shell mode */
|
char *command_ptr = NULL; /* used for batch_mode_shell mode */
|
||||||
|
|
||||||
# ifdef __EMX__ /* is this necessary? */
|
# ifdef __EMX__ /* is this necessary? */
|
||||||
if (!unixy_shell)
|
if (!unixy_shell)
|
||||||
minus_c[1] = '/'; /* " /c " */
|
shellflags[0] = '/'; /* "/c" */
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
ap = new_line;
|
ap = new_line;
|
||||||
memcpy (ap, shell, shell_len);
|
memcpy (ap, shell, shell_len);
|
||||||
ap += shell_len;
|
ap += shell_len;
|
||||||
memcpy (ap, minus_c, sizeof (minus_c) - 1);
|
*(ap++) = ' ';
|
||||||
ap += sizeof (minus_c) - 1;
|
memcpy (ap, shellflags, sflags_len);
|
||||||
|
ap += sflags_len;
|
||||||
|
*(ap++) = ' ';
|
||||||
command_ptr = ap;
|
command_ptr = ap;
|
||||||
for (p = line; *p != '\0'; ++p)
|
for (p = line; *p != '\0'; ++p)
|
||||||
{
|
{
|
||||||
@ -2794,7 +2799,7 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
|
|||||||
#endif
|
#endif
|
||||||
*ap++ = *p;
|
*ap++ = *p;
|
||||||
}
|
}
|
||||||
if (ap == new_line + shell_len + sizeof (minus_c) - 1)
|
if (ap == new_line + shell_len + sflags_len + 2)
|
||||||
/* Line was empty. */
|
/* Line was empty. */
|
||||||
return 0;
|
return 0;
|
||||||
*ap = '\0';
|
*ap = '\0';
|
||||||
@ -2846,8 +2851,10 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
|
|||||||
new_argv[2] = NULL;
|
new_argv[2] = NULL;
|
||||||
} else
|
} else
|
||||||
#endif /* WINDOWS32 */
|
#endif /* WINDOWS32 */
|
||||||
|
|
||||||
if (unixy_shell)
|
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__
|
#ifdef __EMX__
|
||||||
else if (!unixy_shell)
|
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
|
instead of recursively calling ourselves, because we
|
||||||
cannot backslash-escape the special characters (see above). */
|
cannot backslash-escape the special characters (see above). */
|
||||||
new_argv = xmalloc (sizeof (char *));
|
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);
|
new_argv[0] = xmalloc (line_len + 1);
|
||||||
strncpy (new_argv[0],
|
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';
|
new_argv[0][line_len] = '\0';
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -2958,7 +2965,7 @@ char **
|
|||||||
construct_command_argv (char *line, char **restp, struct file *file,
|
construct_command_argv (char *line, char **restp, struct file *file,
|
||||||
int cmd_flags, char **batch_filename_ptr)
|
int cmd_flags, char **batch_filename_ptr)
|
||||||
{
|
{
|
||||||
char *shell, *ifs;
|
char *shell, *ifs, *shellflags;
|
||||||
char **argv;
|
char **argv;
|
||||||
|
|
||||||
#ifdef VMS
|
#ifdef VMS
|
||||||
@ -3063,15 +3070,17 @@ construct_command_argv (char *line, char **restp, struct file *file,
|
|||||||
}
|
}
|
||||||
#endif /* __EMX__ */
|
#endif /* __EMX__ */
|
||||||
|
|
||||||
|
shellflags = allocated_variable_expand_for_file ("$(.SHELLFLAGS)", file);
|
||||||
ifs = allocated_variable_expand_for_file ("$(IFS)", file);
|
ifs = allocated_variable_expand_for_file ("$(IFS)", file);
|
||||||
|
|
||||||
warn_undefined_variables_flag = save;
|
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);
|
cmd_flags, batch_filename_ptr);
|
||||||
|
|
||||||
free (shell);
|
free (shell);
|
||||||
|
free (shellflags);
|
||||||
free (ifs);
|
free (ifs);
|
||||||
#endif /* !VMS */
|
#endif /* !VMS */
|
||||||
return argv;
|
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 (".VARIABLES", "", o_default, 0)->special = 1;
|
||||||
/* define_variable_cname (".TARGETS", "", 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 (".RECIPEPREFIX", "", o_default, 0)->special = 1;
|
||||||
|
define_variable_cname (".SHELLFLAGS", "-c", o_default, 0);
|
||||||
|
|
||||||
/* Set up .FEATURES
|
/* Set up .FEATURES
|
||||||
We must do this in multiple calls because define_variable_cname() is
|
We must do this in multiple calls because define_variable_cname() is
|
||||||
a macro and some compilers (MSVC) don't like conditionals in macros. */
|
a macro and some compilers (MSVC) don't like conditionals in macros. */
|
||||||
define_variable_cname (".FEATURES",
|
{
|
||||||
"target-specific order-only second-expansion else-if"
|
const char *features = "target-specific order-only second-expansion"
|
||||||
" shortest-stem undefine",
|
" else-if shortest-stem undefine"
|
||||||
o_default, 0);
|
|
||||||
#ifndef NO_ARCHIVES
|
#ifndef NO_ARCHIVES
|
||||||
do_variable_definition (NILF, ".FEATURES", "archives",
|
" archives"
|
||||||
o_default, f_append, 0);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAKE_JOBSERVER
|
#ifdef MAKE_JOBSERVER
|
||||||
do_variable_definition (NILF, ".FEATURES", "jobserver",
|
" jobserver"
|
||||||
o_default, f_append, 0);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAKE_SYMLINKS
|
#ifdef MAKE_SYMLINKS
|
||||||
do_variable_definition (NILF, ".FEATURES", "check-symlink",
|
" check-symlink"
|
||||||
o_default, f_append, 0);
|
|
||||||
#endif
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
define_variable_cname (".FEATURES", features, o_default, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Read in variables from the environment. It is important that this be
|
/* Read in variables from the environment. It is important that this be
|
||||||
done before $(MAKE) is figured out so its definitions will not 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()
|
/* Check for special targets. Do it here instead of, say, snap_deps()
|
||||||
so that we can immediately use the value. */
|
so that we can immediately use the value. */
|
||||||
if (streq (name, ".POSIX"))
|
if (streq (name, ".POSIX"))
|
||||||
posix_pedantic = 1;
|
{
|
||||||
|
posix_pedantic = 1;
|
||||||
|
define_variable_cname (".SHELLFLAGS", "-ec", o_default, 0);
|
||||||
|
}
|
||||||
else if (streq (name, ".SECONDEXPANSION"))
|
else if (streq (name, ".SECONDEXPANSION"))
|
||||||
second_expansion = 1;
|
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>
|
2010-07-01 Paul Smith <psmith@gnu.org>
|
||||||
|
|
||||||
* scripts/features/recursion: Add a space to separate command-line
|
* 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"
|
one two:;@echo "$@: $(SHELL) $$SHELL"
|
||||||
', '', "two: /./$mshell /./$mshell\none: /././$mshell $mshell\n");
|
', '', "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;
|
1;
|
||||||
|
Loading…
Reference in New Issue
Block a user