Subject: Re: make -j and failure modes
To: None <jmc@netbsd.org>
From: Ben Harris <bjh21@netbsd.org>
List: tech-userlevel
Date: 12/10/2003 00:40:45
In article <m2n.s.1ATpUq-000hYr@chiark.greenend.org.uk> you write:
> (cd ${.CURDIR} && make bar)
> (cd ${.CURDIR} && make bar2)
>
>With non-compat mode (i.e. what -j turns make into) that gets turned into
>a shell script and fed via stdin to sh -ev.
>
>i.e. 1 script for all the commands. (which is a nice performance boost from
>running a separate shell instance for each one).
>
>Here's the catch. This is basically equiv to:
>
>printf "(exit 1)\n(exit 0)\n" | sh -ev
Not quite correct. It's closer to:
printf "(false)\n(true)\n" | sh -ev
>According to SUSE3:
>
>-e When this option is on, if a simple command fails for any of the reasons
> listed in Consequences of Shell Errors or returns an exit status value >0,
> and is not part of the compound list following a while, until, or if
> keyword, and is not a part of an AND or OR list, and is not a pipeline
> preceded by the ! reserved word, then the shell shall immediately exit.
Note "simple command". A group like "(false)" is not a simple command. The
command "false" is a simple command, but it's executed in a subshell
environment.
>I'm purely guessing here but bash (/bin/sh on my linux box) and our shell
>seem to be taking the group command definition to mean -e has no effect.
Not quite correct. As an example (bash and NetBSD sh agree here too):
wraith:~$ bash -posix -e -c '(false; echo foo);(echo bar)'
bar
The "-e" option meant that the first "false" caused the subshell it was
executing in to exit, but the outer shell carried on, because the command
that it saw fail was a compound command.
>1. Have make scan the command for parens and if it finds them, exec via
> the compat methods.
>2. Fix sh to deal with group'd commands and -e. Then provide nbsh as a host
> tool and tell make to use it.
>3. Go through all the Makefile's and change (... && ...) into .... && ...
That will mean that the directory change is still in effect for the next
command, which is precisely what the parens are there to avoid. I'd
suggest:
4. Change all (foo && bar) to (foo && bar) || exit $?
>(I'm leaning towards #2 but I need opinions/knowledge on whether sh is
>doing the right thing or not.)
I think both behaviours are arguably correct, and since it's not terribly
hard (if slightly ugly) to write scripts that cope with both, we should just
do that.
--
Ben Harris <bjh21@NetBSD.org>
Portmaster, NetBSD/acorn26 <URL:http://www.NetBSD.org/Ports/acorn26/>