Subject: make -j and failure modes
To: None <tech-userlevel@netbsd.org, tech-toolchain@netbsd.org>
From: James Chacon <jmc@netbsd.org>
List: tech-userlevel
Date: 12/09/2003 15:33:58
As folks have noticed (and PR#18573 documents), make -j doesn't stop correctly
on errors. At least in all cases.
The reason for this comes down to rules like the following:
foo:
(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
(and expecting the first command to fail which would be equiv to a multiline
make rule with the 1st one failing)
On NetBSD (and linux for those cross building) that returns:
(exit 1)
(exit 0)
On Solaris, FreeBSD (4.9) it returns:
(exit 1)
I would expect it to exit on error after the first command exits with non-zero.
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.
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.
My take is that's non-obvious behavior and probably /bin/sh should be looked
at and decided if that's correct.
In any case a solution for make -j needs to happen somewhere (and with
hosting on non-NetBSD hosts a reality the most portable method should be
considered of course)
Ideas:
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 .... && ...
(I'm leaning towards #2 but I need opinions/knowledge on whether sh is
doing the right thing or not.)
Thoughts?
James