make add_custom_command失败,目标被删除

cmake add_custom_command failure, target gets deleted

本文关键字:目标 删除 command add custom make 失败      更新时间:2023-10-16

我正在使用CMake构建一个测试可执行文件。在构建过程中,我希望运行可执行文件,它将返回测试是否通过。如果没有,我希望构建失败。然而,当我使用add_custom_command(... POST_BUILD ... ),并使用Makefile生成器时,测试可执行文件将被删除(请在这个问题中解释:为什么GNU要删除文件)。

是否有办法让CMake将可执行文件视为.PRECIOUS,或者更改CMakeLists.txt,以便在测试失败时不会删除可执行文件?

作为参考,我的CMakeList.txt看起来像这样(从实际简化):

add_executable(UnitTest unittest.cpp)
add_custom_command(TARGET UnitTest POST_BUILD COMMAND $<TARGET_FILE:UnitTest>)

我所指的解决方案是使用add_custom_target而不是add_custom_command。虽然它不会删除可执行文件,如果测试失败,构建过程作为一个整体失败,如果runUnitTest失败,这个目标不会作为构建UnitTest目标的结果而被构建。

add_executable(UnitTest unittest.cpp)
add_custom_target(runUnitTest UnitTest COMMAND $<TARGET_FILE:UnitTest> DEPENDS UnitTest)

我遇到了同样的问题:我有一个单元测试,我只想在以下条件下运行:

  1. 测试已修改。
  2. 被测代码已修改
  3. 测试执行失败。

如果测试运行失败,我希望测试二进制文件保留用于调试。

我最终使用的解决方案使用一个标志文件来指示测试已经运行并且不再需要再次执行。注意,该标志必须位于二进制目录中,这样其他构建才不会受到影响。然而,设置WORKING_DIRECTORY是为了让测试可以访问相对于源位置的只读数据文件。这是它的样子——我把它放在一个宏中,这样我所有的单元测试都可以调用它,宏的唯一输入是测试可执行文件:

set (TEST_FLAG_FILE ${CMAKE_CURRENT_BINARY_DIR}/${TEST_EXECUTABLE}.PASSED)
# This isn't normally needed since a rebuild will have a newer time stamp.
# But it adds robustness to handle changes to the system clock.
add_custom_command(TARGET ${TEST_EXECUTABLE} 
    COMMENT "Unit test ${TEST_EXECUTABLE} rebuilt; clearing flag ${TEST_FLAG_FILE}." 
    COMMAND ${CMAKE_COMMAND} -E remove -f ${TEST_FLAG_FILE}
    POST_BUILD 
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# This command only runs if the flag isn't present or is older than the executable.
add_custom_command(OUTPUT ${TEST_FLAG_FILE}
    COMMENT "Unit Test Execution: ${TEST_EXECUTABLE}" 
    COMMAND ${TEST_EXECUTABLE}
    COMMAND ${CMAKE_COMMAND} -E touch ${TEST_FLAG_FILE}
    MAIN_DEPENDENCY ${TEST_EXECUTABLE} 
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# Any "make all" will evaluate the preceding custom command.
add_custom_target(run_${TEST_EXECUTABLE} ALL DEPENDS ${TEST_FLAG_FILE})