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