如何在makefiles中终止shell命令错误


How do you abort on shell command errors in makefiles?

我想写一个makefile来打包一些PHP脚本。我还希望它在构建最终的zip文件之前检查语法错误(使用内置的php lint工具),以防止任何意外错误。

目前我有

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*"

这工作,但如果有一个PHP错误,我希望它打破,而不是继续构建zip文件(出于明显的原因)。目前,它们可能只是丢失在成功的lint运行和zip文件的输出页面中。

我这样做对吗?我应该使用make循环而不是shell循环吗?如何在shell命令错误时中止?

你可以这样做:

for i in `find . -name "*.php"`; do '
  php -l $$i; '
  if [ $$? -ne 0 ] ; then exit 42 ; fi '
done

您的dist配方中的shell for循环隐藏了php -l从make的退出状态,因此它不知道退出。Mat的答案展示了如何通过在出错时使用shell命令退出来解决这个问题。

可以这样完全避免shell循环:

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*"

现在有一个带有静态模式规则的假目标来运行每个php -l命令。如果其中任何一个失败,dist配方将不会运行。这可能比shell循环更难阅读,但这意味着a) make本身的错误消息将为您指出有问题的文件,b)使用make -j,您可以进行多线程lint检查:-)