6sigma2@polari.UUCP (Brian Matthews) (06/07/91)
I'm trying to write some make rules that use test to conditionally execute different shell commands. For instance, if a certain make variable has one value, I want to do one thing, otherwise something else. The obvious solution is to do something like this: if $(VAR) = val1; then command1; else command2; fi If VAR happens to contain val1, or I'm using a System V-like make, everything works fine. However, if VAR doesn't contain val1, BSD-like makes seem to bail out as soon as the test fails - the else command2 isn't executed, and the make fails. For a concrete example, put: SHELL=/bin/sh a: b c @echo a made b: @if test x = x; then echo b made;fi c: @if test x = y; then echo c not made;else echo c made;fi In a file called Makefile and do a make. I would expect to see: b made c made a made but when using BSD-like makes (on BSD 4.3 or Ultrix for example) make fails with exit code 1 after outputting b made. I've tried all sort of different things, including prefixing the if with set +e (thinking the shell was bailing out when test exited with a 1), running in a subshell and doing an exit 0, etc. I can put a - before the @if, but I'd rather not, because I would like the make to stop if the command executed as a consequence of the test result fails. Any ideas? -- Brian L. Matthews blm@6sceng.UUCP
torek@elf.ee.lbl.gov (Chris Torek) (06/07/91)
In article <4378@polari.UUCP> 6sigma2@polari.UUCP (Brian Matthews) writes: >I'm trying to write some make rules that use test to conditionally >execute different shell commands. ... BSD-like makes seem to bail out >as soon as the test fails ... >c: > @if test x = y; then echo c not made;else echo c made;fi >... make fails with exit code 1 after outputting b made. > >I've tried all sort of different things, including prefixing the if >with set +e (thinking the shell was bailing out when test exited with >a 1), running in a subshell and doing an exit 0, etc. You were on the right track. The problem is a bug in the BSD Bourne shell; under -e, it improperly exits for *all* nonzero subprocess exits, rather than only those which are tested. The bug is partially fixed in 4.3BSD-tahoe: I fixed the if foo; then bar; else baz; fi case but forgot to hit up the foo && bar || baz cases (I got thoroughly sick of working on sh in just the few minutes it took to fix if, while, and until: Bourne's pseudo-Algol is a nightmare). The reason `set +e' did not help is that the BSD Bourne shell was so old that it did not have `set +' for turning off options. Once -e is set in such a shell, you cannot get rid of it. >I can put a - before the @if, but I'd rather not, because I would >like the make to stop if the command executed as a consequence of >the test result fails. Unfortunately, unless you have source, you are stuck with that. I had a version of the BSD Bourne shell which I had deBourned and then fixed this and a number of other bugs, but it has fallen by the wayside; BSD now uses a Bourne-shell clone based on Kenneth Almquist's `ash' as /bin/sh. -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov
clewis@ferret.ocunix.on.ca (Chris Lewis) (06/08/91)
In article <4378@polari.UUCP> 6sigma2@polari.UUCP (Brian Matthews) writes: Hi Brian, long time no see. >I'm trying to write some make rules that use test to conditionally >execute different shell commands. >The obvious solution is to do something like this: > if $(VAR) = val1; then command1; else command2; fi >If VAR happens to contain val1, or I'm using a System V-like make, >everything works fine. However, if VAR doesn't contain val1, BSD-like >makes seem to bail out as soon as the test fails - the else command2 >isn't executed, and the make fails. This is a bug in the BSD shell. To-wit, make starts the shell script with "-e" set, and the test's failure causes the shell script to terminate immediately rather than processing thru the else clause. You can test this yourself with the following shell script: set -e if test x = y then echo wha? else echo "worked properly" fi On non-SYSV shells this won't print anything. I think this botch was even in V7. What I usually do is this: # comment out on System V. IGNORESH = set +e ; all: $(IGNORESH) if .... \ then ... Unfortunately, you have to check the returns of each subcommand individually (as you would do in a normal script), and on error execute "exit 1". Psroff has this in its makefiles, and even a way of testing whether you need it commented out or not. BTW: go multi line on your shell scripts, it makes them a lot easier to read even if you have to put backslashes on the ends of all of the lines... If it wasn't for this stupid botch in BSD, set -e and trap 0's would make error recovery in shell scripts easy and portable... Grrr! -- Chris Lewis, Phone: (613) 832-0541, Domain: clewis@ferret.ocunix.on.ca UUCP: ...!cunews!latour!ecicrl!clewis; Ferret Mailing List: ferret-request@eci386; Psroff (not Adobe Transcript) enquiries: psroff-request@eci386 or Canada 416-832-0541. Psroff 3.0 in c.s.u soon!