【问题标题】:How to make makefile exit with error when using a loop?使用循环时如何使makefile退出并出错?
【发布时间】:2013-10-17 20:29:04
【问题描述】:

如果我有以下 bash 命令:

for i in ./ x ; do ls $i ; done && echo OK

执行“ls ./”,然后执行“ls x”,失败(x缺失),不打印OK。

如果

for i in x ./ ; do ls $i ; done && echo OK

即使 "ls x" 失败,因为 for 循环中的最后一条语句成功,也会打印 OK。这是在 makefile 中使用 shell for 循环时的问题:

x:
    for i in $(LIST) ; do \
        cmd $$i  ;\
    done 

如果 cmd 的任何单个执行失败,我如何使 make 失败?

【问题讨论】:

    标签: bash makefile


    【解决方案1】:

    使用break 命令在命令失败时终止循环

    x:
        for i in $(LIST) ; do \
            cmd $$i || break ;\
        done 
    

    不过,这不会使 makefile 中止。您可以改为使用 exit 和非零代码:

    x:
        for i in $(LIST) ; do \
            cmd $$i || exit 1 ;\
        done 
    

    【讨论】:

    • 似乎不起作用。将 cmd 替换为 ls 和 LIST=non_existing_file,然后在 "ls non_existing_file" 失败后 make 继续其愉快的方式。
    • 另一个选项是在运行循环之前set -e
    • 调用exit 不会终止makefile。它生成一个 shell,告诉它除了 exit 什么都不做。 exit 1 导致 makefile 规则失败,因为它导致 shell 退出并显示错误代码,表示失败。
    • @DavidC。已经为for 命令生成了shell。 exit 不会产生新的 shell,它会导致该 shell 退出(这也会停止循环)。然后给它一个非零代码会导致make 终止。
    • 糟糕。我忘记了for 循环。 exit 调用本身会产生一个新的 shell。
    【解决方案2】:

    执行命令后,使用$?检查该命令的返回值,因为它的make文件需要使用双$。如果它不为零,则退出失败。

    x:
        set -e
        for i in $(LIST); do \
            cmd $$i; \
            [[ $$? != 0 ]] && exit -1; \
            echo 'done'; \
        done
    

    【讨论】:

    • 除非你在 GNU make 中使用 .ONESHELL,否则 make 会在自己的 shell 中执行每一行,因此 set -e 不会影响 for 循环。但是,您可以通过转义换行符并添加分号来将 set -e 与循环一起加入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    • 2022-07-12
    相关资源
    最近更新 更多