diff --git a/NEWS b/NEWS index 41b6518e..e98cb45c 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ GNU make NEWS -*-indented-text-*- History of user-visible changes. - 05 Oct 2014 + 12 Jul 2015 See the end of this file for copyrights and conditions. @@ -9,12 +9,17 @@ manual, which is contained in this distribution as the file doc/make.texi. See the README file and the GNU make manual for instructions for reporting bugs. -Version 4.1.90 (05 Oct 2014) +Version 4.1.90 (12 Jul 2015) A complete list of bugs fixed in this version is available here: http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=106&set=custom +* New variable: $(.SHELLSTATUS) is set to the exit status of the last != or + $(shell ...) function invoked in this instance of make. This will be "0" if + successful or not "0" if not successful. The variable value is unset if no + != or $(shell ...) function has been invoked. + * VMS-specific changes: * Perl test harness now works. diff --git a/doc/make.texi b/doc/make.texi index b0f5af73..86a1aebc 100644 --- a/doc/make.texi +++ b/doc/make.texi @@ -5669,7 +5669,7 @@ endif @end example The shell assignment operator @samp{!=} can be used to execute a -program and set a variable to its output. This operator first +shell script and set a variable to its output. This operator first evaluates the right-hand side, then passes that result to the shell for execution. If the result of the execution ends in a newline, that one newline is removed; all other newlines are replaced by spaces. @@ -5694,6 +5694,9 @@ hash := $(shell printf '\043') var := $(shell find . -name "*.c") @end example +As with the @code{shell} function, the exit status of the just-invoked +shell script is stored in the @code{.SHELLSTATUS} variable. + @node Appending, Override Directive, Setting, Using Variables @section Appending More Text to Variables @@ -8024,6 +8027,10 @@ implications of using the @code{shell} function within recursively expanded variables vs.@: simply expanded variables (@pxref{Flavors, ,The Two Flavors of Variables}). +@vindex .SHELLSTATUS +After the @code{shell} function or @samp{!=} assignment operator is +used, its exit status is placed in the @code{.SHELLSTATUS} variable. + Here are some examples of the use of the @code{shell} function: @example diff --git a/function.c b/function.c index 8bd2b5ce..02a25eb5 100644 --- a/function.c +++ b/function.c @@ -1450,7 +1450,22 @@ fold_newlines (char *buffer, unsigned int *length, int trim_newlines) } pid_t shell_function_pid = 0; -int shell_function_completed; +static int shell_function_completed; + +void +shell_completed (int exit_code, int exit_sig) +{ + char buf[256]; + + shell_function_pid = 0; + if (exit_sig == 0 && exit_code == 127) + shell_function_completed = -1; + else + shell_function_completed = 1; + + sprintf (buf, "%d", exit_code); + define_variable_cname (".SHELLSTATUS", buf, o_override, 0); +} #ifdef WINDOWS32 /*untested*/ @@ -1630,14 +1645,15 @@ msdos_openpipe (int* pipedes, int *pidp, char *text) errno = EINTR; else if (errno == 0) errno = ENOMEM; - shell_function_completed = -1; + if (fpipe) + pclose (fpipe); + shell_completed (127, 0); } else { pipedes[0] = fileno (fpipe); *pidp = 42; /* Yes, the Meaning of Life, the Universe, and Everything! */ errno = e; - shell_function_completed = 1; } return fpipe; } @@ -1696,7 +1712,7 @@ func_shell_base (char *o, char **argv, int trim_newlines) #endif return o; } -#endif +#endif /* !__MSDOS__ */ /* Using a target environment for 'shell' loses in cases like: export var = $(shell echo foobie) @@ -1743,7 +1759,7 @@ func_shell_base (char *o, char **argv, int trim_newlines) if (pipedes[0] < 0) { /* Open of the pipe failed, mark as failed execution. */ - shell_function_completed = -1; + shell_completed (127, 0); perror_with_name (error_prefix, "pipe"); return o; } @@ -1824,7 +1840,10 @@ func_shell_base (char *o, char **argv, int trim_newlines) /* Close the read side of the pipe. */ #ifdef __MSDOS__ if (fpipe) - (void) pclose (fpipe); + { + int st = pclose (fpipe); + shell_completed (st, 0); + } #else (void) close (pipedes[0]); #endif @@ -1843,9 +1862,9 @@ func_shell_base (char *o, char **argv, int trim_newlines) } shell_function_pid = 0; - /* The child_handler function will set shell_function_completed - to 1 when the child dies normally, or to -1 if it - dies with status 127, which is most likely an exec fail. */ + /* shell_completed() will set shell_function_completed to 1 when the + child dies normally, or to -1 if it dies with status 127, which is + most likely an exec fail. */ if (shell_function_completed == -1) { diff --git a/job.c b/job.c index 2ba0977e..244def03 100644 --- a/job.c +++ b/job.c @@ -558,7 +558,6 @@ child_handler (int sig UNUSED) } extern pid_t shell_function_pid; -extern int shell_function_completed; /* Reap all dead children, storing the returned status and the new command state ('cs_finished') in the 'file' member of the 'struct child' for the @@ -816,11 +815,7 @@ reap_children (int block, int err) /* Check if this is the child of the 'shell' function. */ if (!remote && pid == shell_function_pid) { - /* It is. Leave an indicator for the 'shell' function. */ - if (exit_sig == 0 && exit_code == 127) - shell_function_completed = -1; - else - shell_function_completed = 1; + shell_completed (exit_code, exit_sig); break; } diff --git a/tests/scripts/functions/shell b/tests/scripts/functions/shell index 723cd0ed..4702b096 100644 --- a/tests/scripts/functions/shell +++ b/tests/scripts/functions/shell @@ -4,11 +4,26 @@ $description = 'Test the $(shell ...) function.'; $details = ''; +# Test standard shell +run_make_test('.PHONY: all +OUT := $(shell echo hi) +all: ; @echo $(OUT) + ','','hi'); # Test shells inside rules. run_make_test('.PHONY: all all: ; @echo $(shell echo hi) -','','hi'); + ','','hi'); + +# Verify .SHELLSTATUS +run_make_test('.PHONY: all +PRE := $(.SHELLSTATUS) +$(shell exit 0) +OK := $(.SHELLSTATUS) +$(shell exit 1) +BAD := $(.SHELLSTATUS) +all: ; @echo PRE=$(PRE) OK=$(OK) BAD=$(BAD) + ','','PRE= OK=0 BAD=1'); # Test unescaped comment characters in shells. Savannah bug #20513 @@ -27,6 +42,6 @@ run_make_test(' export HI = $(shell echo hi) .PHONY: all all: ; @echo $$HI -','','hi'); + ','','hi'); 1; diff --git a/variable.h b/variable.h index fa2dbbd1..d8fb0d1f 100644 --- a/variable.h +++ b/variable.h @@ -134,7 +134,7 @@ char *patsubst_expand_pat (char *o, const char *text, const char *pattern, const char *replace_percent); char *patsubst_expand (char *o, const char *text, char *pattern, char *replace); char *func_shell_base (char *o, char **argv, int trim_newlines); - +void shell_completed (int exit_code, int exit_sig); /* expand.c */ char *recursively_expand_for_file (struct variable *v, struct file *file);