【问题标题】:How to delete the target file in case of error in Makefile?Makefile出错时如何删除目标文件?
【发布时间】:2017-05-31 08:55:00
【问题描述】:

在以下示例中,我希望在出现错误时删除foo。不幸的是,它不起作用。

foo:
    perl -e 'die()' > $@ || [rm $@ -a true]

怎么了?

【问题讨论】:

  • 你试过perl -e 'die()' > $@ || rm $@吗?
  • 是的,但它不会传播第一个进程的$?
  • 然后perl -e 'die()' > $@ || { rm $@; exit 1; }(除非您需要准确传播第一个进程的退出状态)
  • 应引用特殊变量$@(例如perl -e 'die()' > "$@" || rm "$@"
  • @Leon perl -e 'die()' > $@ || { rm $@; false;} 应该也可以工作并且避免退出太快

标签: bash makefile


【解决方案1】:

GNU make 可以为你做到这一点。

Special Built-in Target Names:

.DELETE_ON_ERROR

如果 .DELETE_ON_ERROR 在 makefile 中的任何位置被提及为目标,则如果规则的目标已更改并且其配方以非零退出状态退出,则 make 将删除规则的目标,就像它在收到信号时所做的那样。


创建文件是一个非原子操作是一个普遍的问题。并非总是可以在终止时删除不完整或损坏的文件,例如,当程序被 SIGKILL 或 OOM-killer 杀死时。换句话说,所有涉及删除文件的解决方案都容易失败。

稳健的通用解决方案是:

  1. 使用临时文件名创建文件。
  2. 文件完成并具有正确的权限后,将其重命名为最终名称。 Renaming a file is an atomic operations in UNIX,只要文件在同一个文件系统中。

例如:

foo:
    perl -e 'die()' > $@~
    mv --force $@~ $@

【讨论】:

    【解决方案2】:

    这对我有用……

    foo: 
        @perl -e 'die()' > $@ || { echo "removing $@ because exit code was $${?}"; rm $@; }
    

    输出

    Died at -e line 1.
    removing foo because exit code was 255
    

    【讨论】:

      猜你喜欢
      • 2013-02-17
      • 1970-01-01
      • 1970-01-01
      • 2019-12-31
      • 1970-01-01
      • 1970-01-01
      • 2020-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多