49

在执行 linux 工具时,我有一个 makefile 规则。我需要检查 tool 命令的退出状态,如果该命令失败,则必须中止 make。

我试着用 $?, $$? \$?等在makefile中。但是当makefile运行时它们给了我语法错误。

这样做的正确方法是什么?

这是Makefile中的相关规则

    mycommand \
    if [ $$? -ne 0 ]; \
    then \
        echo "mycommand failed"; \
        false; \
    fi
4

4 回答 4

72

在makefile中-:

mycommand || (echo "mycommand failed $$?"; exit 1)

makefile 操作中的每一行都会调用一个新的 shell - 必须在命令失败的操作行中检查错误。

如果 mycommand 失败,则逻辑分支到 echo 语句然后退出。

于 2013-05-01T08:49:03.660 回答
27

以下是其他几种方法:


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 中执行。

于 2017-06-02T09:05:10.433 回答
3

如果您想要的只是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 > $@
于 2017-06-02T11:06:17.080 回答
0

对于那些仍然无法修复它的人,问题中的原始片段在mycommand. 因此,工作示例是:

    mycommand; \  # <<== here's the missing semicolon
    if [ $$? -ne 0 ]; \
    then \
        echo "mycommand failed"; \
        false; \
    fi
于 2021-11-25T04:29:39.183 回答