add_custom_command 失败时不会重新 运行
add_custom_command does not re-run on failure
在 CMake 中,我想将 add_custom_command(... POST_BUILD ...)
与可能会失败的 COMMAND
一起使用。
观察
- 运行
make
第一次会失败,因为add_custom_command( ... COMMAND exit 1)
的退出码不是0
。 --> 这是我所期望的。
- 运行
make
第二次就可以通过,因为指定的命令
在 add_custom_command
中不会再 运行 了。 --> 这不是我想要的。我希望 make
在自定义命令起作用之前失败。
最小失败示例
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."
)
问题
- 我该如何解决这个问题?
- 这是 CMake 的预期行为吗?
一个解决方案
我知道我可以创建一个自定义命令,它不是 POST_BUILD
,而是在成功时输出一个文件 TARGET.passed
。但是,我想避免这种情况。因为 POST_BUILD 在这里似乎是最合适的用法。 (我正在更改结果文件的功能。)
这曾经是 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
)
- 将自定义命令从
TARGET
上的 POST_BUILD
切换为独立命令。因此使它 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.done
。 make
和 make all
将按预期工作。
在 CMake 中,我想将 add_custom_command(... POST_BUILD ...)
与可能会失败的 COMMAND
一起使用。
观察
- 运行
make
第一次会失败,因为add_custom_command( ... COMMAND exit 1)
的退出码不是0
。 --> 这是我所期望的。 - 运行
make
第二次就可以通过,因为指定的命令 在add_custom_command
中不会再 运行 了。 --> 这不是我想要的。我希望make
在自定义命令起作用之前失败。
最小失败示例
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."
)
问题
- 我该如何解决这个问题?
- 这是 CMake 的预期行为吗?
一个解决方案
我知道我可以创建一个自定义命令,它不是 POST_BUILD
,而是在成功时输出一个文件 TARGET.passed
。但是,我想避免这种情况。因为 POST_BUILD 在这里似乎是最合适的用法。 (我正在更改结果文件的功能。)
这曾经是 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
) - 将自定义命令从
TARGET
上的POST_BUILD
切换为独立命令。因此使它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.done
。 make
和 make all
将按预期工作。