在执行 linux 工具时,我有一个 makefile 规则。我需要检查 tool 命令的退出状态,如果该命令失败,则必须中止 make。
我试着用 $?, $$? \$?等在makefile中。但是当makefile运行时它们给了我语法错误。
这样做的正确方法是什么?
这是Makefile中的相关规则
mycommand \ if [ $$? -ne 0 ]; \ then \ echo "mycommand failed"; \ false; \ fi
在makefile中-:
mycommand || (echo "mycommand failed $$?"; exit 1)
makefile 操作中的每一行都会调用一个新的 shell - 必须在命令失败的操作行中检查错误。
如果 mycommand 失败,则逻辑分支到 echo 语句然后退出。
以下是其他几种方法:
shell
&.SHELLSTATUS
some_recipe:
@echo $(shell echo 'doing stuff'; exit 123)
@echo 'command exited with $(.SHELLSTATUS)'
@exit $(.SHELLSTATUS)
输出:
$ make some_recipe
doing stuff
command exited with 123
make: *** [Makefile:4: some_recipe] Error 123
它确实有一个警告,即shell
命令输出不是流式传输的,所以当它完成时,你最终会转储到标准输出。
$?
some_recipe:
@echo 'doing stuff'; sh -c 'exit 123';\
EXIT_CODE=$$?;\
echo "command exited with $$EXIT_CODE";\
exit $$EXIT_CODE
或者,更容易阅读:
.ONESHELL:
some_recipe:
@echo 'doing stuff'; sh -c 'exit 123'
@EXIT_CODE=$$?
@echo "command exited with $$EXIT_CODE"
@exit $$EXIT_CODE
输出:
$ make some_recipe
doing stuff
command exited with 123
make: *** [Makefile:2: some_recipe] Error 123
它本质上是一串命令,在同一个 shell 中执行。
如果您想要的只是make
当工具以非零状态退出时中止make
,默认情况下已经这样做了。
示例Makefile
:
a: b
@echo making $@
b:
@echo making $@
@false
@echo already failed
. 这就是我的make
:
$ make
making b
make: *** [Makefile:6: b] Error 1
确保删除部分或全部创建的目标,以防失败。例如,这个
a: b
@gena $+ > $@
b:
@genb > $@
不正确:如果第一次尝试genb
失败,它可能会留下一个不正确b
的,在第二次尝试时,它make
会假设是正确的。所以你需要做类似的事情
a: b
@gena $+ > $@ || { rm $@; exit 1; }
b:
@genb > $@
对于那些仍然无法修复它的人,问题中的原始片段在mycommand
. 因此,工作示例是:
mycommand; \ # <<== here's the missing semicolon
if [ $$? -ne 0 ]; \
then \
echo "mycommand failed"; \
false; \
fi