I'm trying to write a makefile to package up some PHP scripts. I would also like it to check for syntax errors (using the built in php lint tool) before building the final zip file, to prevent any accidental errors slipping in.
So far I have
all: dist clean: rm -f output.zip dist: clean for i in `find . -name "*.php"`; do php -l $$i; done zip -r output.zip src -x "*/.*" "*/tests*"
This works, but if there is a PHP error I would like it to break and not continue building the zip file (for obvious reasons). Currently they may just get lost in the pages of output from successful lint runs and the zip file.
Am I going about this the right way? Should I be using a make loop rather than a shell loop? How to you get make to abort on shell command errors?
You can do something like this:
for i in `find . -name "*.php"`; do \ php -l $$i; \ if [ $$? -ne 0 ] ; then exit 42 ; fi \ done
for loop in your
dist recipe is hiding the exit status of
php -l from make, so it doesn't know to exit. Mat's answer shows how to fix that by having the shell command exit on error.
The shell loop could be avoided entirely like this:
all: dist clean: rm -f output.zip LINT_TARGETS := $(addprefix lint-,$(shell find . -name "*.php")) .PHONY: $(LINT_TARGETS) $(LINT_TARGETS):lint-%:% php -l $< dist: clean $(LINT_TARGETS) zip -r output.zip src -x "*/.*" "*/tests*"
Now there's a phony target with a static pattern rule to run each of the
php -l commands. If any of them fails, the
dist recipe will not run. This is arguably harder to read than a shell loop, but it means that a) the error message from make itself will finger the problematic file for you and b) with
make -j you can have multithreaded lint checks :-)