Saturday, August 9, 2008

Making Makefiles Behave: Loops

The last command in a shell for loop determines whether the loop succeeds or fails.

This succeeds:
$ for i in false true; do echo $i; $i; done
false
true
$ echo $?
0
This fails
$ for i in true false; do echo $i; $i; done
true
false
$ echo $?
1
When does this matter? In Makefiles. Suppose you have a make rule that looks like this:
foo:
for dir in $(SUBDIRS); do $(MAKE) -C $$dir; done
A failure of one of the subdirectory makes will not cause the make to fail!

How do you solve this? There are several sophisticated ways, but the dead-easy way is to start the Makefile like this:
SHELL := /bin/bash -e
This will cause all shell commands to be executed with the -e flag, which causes any simple command to terminate the shell.
$ ( set -e; for i in false true; do echo $i; $i; done )
false
$ echo $?
1
(I have to put the command and the set -e in parens here -- though not in the Makefile -- because any failure causes the command to fail and the shell to exit, so the following "echo $?" would never be reached.

No comments: