CMake:如何仅当测试目标或其依赖变更时执行测试命令
解决方案:仅当测试目标变更时自动运行测试
针对你的需求,我有两种贴合CMake机制的方案,都不需要使用add_custom_command(OUTPUT ...)创建虚拟文件:
方案1:分测试独立触发(推荐)
如果你的测试可以独立运行(即每个测试只需要在自身更新时执行),可以为每个测试可执行文件单独添加POST_BUILD命令。这样当某个测试目标被重新构建时,只会自动运行该测试,完全符合CMake的依赖追踪逻辑:
# 为testExec1添加构建后执行逻辑 add_custom_command(TARGET testExec1 POST_BUILD COMMAND testExec1 COMMENT "-- Running testExec1 after build..." ) # 为testExec2添加构建后执行逻辑 add_custom_command(TARGET testExec2 POST_BUILD COMMAND testExec2 COMMENT "-- Running testExec2 after build..." )
这种方式的优势:
- 完全利用CMake的目标依赖,只有当对应测试可执行文件变更时才会触发测试
- 不需要额外的虚拟文件或复杂逻辑
- 测试执行更高效,不会重复运行未变更的测试
方案2:任意测试变更时统一运行所有测试
如果你需要只要有一个测试目标变更,就运行全部测试,可以借助脚本检查文件修改时间,避免每次构建都重复执行:
add_custom_target(runTests ALL # 用shell脚本判断是否需要运行测试: # 1. 如果没有标记文件,直接运行 # 2. 如果任一测试可执行文件比标记文件新,运行测试并更新标记 COMMAND bash -c "if [ ! -f .last_test_run ] || [ $<TARGET_FILE:testExec1> -nt .last_test_run ] || [ $<TARGET_FILE:testExec2> -nt .last_test_run ]; then \ echo '-- Running all tests...'; \ $<TARGET_FILE:testExec1> && $<TARGET_FILE:testExec2> && touch .last_test_run; \ fi" DEPENDS testExec1 testExec2 COMMENT "-- Checking if tests need to run..." )
这里的$<TARGET_FILE:testExec1>是CMake的生成器表达式,能正确获取测试可执行文件的绝对路径,避免路径问题。脚本中的.last_test_run是一个简单的标记文件,但它不是通过add_custom_command(OUTPUT...)创建的,而是由脚本自动生成/更新,符合你避免特定虚拟文件创建方式的要求。
为什么之前的方法有问题?
- 带
ALL的add_custom_target:CMake会认为自定义目标没有输出,因此每次构建都会标记为“过时”,强制运行 - 绑定单个目标的
POST_BUILD命令:只会在该目标构建时触发,无法感知其他测试目标的变更
内容的提问来源于stack exchange,提问作者RL-S
相关产品推荐
相关产品推荐

