add_custom_command在失败时不会重新运行

时间:2017-01-11 17:58:15

标签: cmake add-custom-command

在CMake中,我想将add_custom_command(... POST_BUILD ...)与可能失败的COMMAND一起使用。

观察

  1. 首次运行make将失败,因为add_custom_command( ... COMMAND exit 1)的退出代码不是0。 - >这就是我所期望的。
  2. 第二次运行make将通过,因为指定的命令 在add_custom_command中将不会再次运行。 - >这不是我想要的。我希望make失败,直到自定义命令工作。
  3. 最小化失败示例

    project(Foo)
    cmake_minimum_required(VERSION 3.2)
    
    
    # Create main.cc
    ##include <iostream>
    #
    #int main() {
    #  std::cout << "Hello, World!" << std::endl;
    #}
    add_executable(main main.cc)
    
    add_custom_command(TARGET main POST_BUILD
              COMMAND exit 1  # In the real example, I am changing capabilities of the resulting binary with /sbin/setcap, which might fail.
              COMMENT "Doing stuff."
              )
    

    问题

    1. 如何解决此问题?
    2. 这是CMake的预期行为吗?
    3. 一种解决方案

      我知道我可以创建一个不是POST_BUILD的自定义命令,而是在成功时输出文件TARGET.passed。但是,我想避免这种情况。因为POST_BUILD似乎是最合适的用法。 (我正在更改生成的文件的功能。)

1 个答案:

答案 0 :(得分:2)

这曾经是CMake中的一个错误。

在以下提交中已修复:

commit 4adf1dad2a6e462364bae81030c928599d11c24f
Author: Brad King <brad.king@kitware.com>
Date:   Mon Mar 30 16:32:26 2015 -0400

    Makefile: Tell GNU make to delete rule outputs on error (#15474)

    Add .DELETE_ON_ERROR to the "build.make" files that contain the actual
    build rules that generate files.  This tells GNU make to delete the
    output of a rule if the recipe modifies the output but returns failure.
    This is particularly useful for custom commands that use shell
    redirection to produce a file.

    Do not add .DELETE_ON_ERROR for Borland or Watcom make tools because
    they may not tolerate it and would not honor it anyway.  Other make
    tools that do not understand .DELETE_ON_ERROR will not be hurt.

    Suggested-by: Andrey Vihrov <andrey.vihrov@gmail.com>

该修复程序的最早版本是CMake 3.3.0

解决方法

  • 创建一个额外的输出目标,该目标取决于已成功运行的自定义命令。 (下面称为main.done
  • 将自定义命令从POST_BUILD上的TARGET切换为独立命令。因此,将OUTPUT设为文件(main.intermediate_step以下)。
  • 使用该选项运行第二个COMMAND以使用touch创建所述文件。

代码:

project(Foo)
cmake_minimum_required(VERSION 3.2)


# Create main.cc
##include <iostream>
#
#int main() {
#  std::cout << "Hello, World!" << std::endl;
#}
add_executable(main main.cc)

add_custom_command(TARGET main POST_BUILD
          COMMAND exit 1  # In the real example, I am changing capabilities of the resulting binary with /sbin/setcap, which might fail.
          COMMENT "Doing stuff."
          )

add_custom_command(OUTPUT main.intermediate_step
                  COMMAND  exit 1  # In the real example, I am changing capabilities of the resulting binary with /sbin/setcap, which might fail.
                  COMMAND touch main_setcap.passed
                  DEPENDS main
                  COMMENT "Doing stuff."
)
add_custom_target(main.done ALL DEPENDS main.intermediate_step)

注意:make main不会运行自定义命令。请使用make main.donemakemake all将按预期工作。