CMake自定义目标配置:输出数量变化时避免无意义重建
解决方案
问题根源在于CMake会将add_custom_command的COMMAND内容作为构建触发条件的一部分,只要命令行参数变化,即使输出文件未过时,也会重新执行目标。要实现仅当输出文件过时才运行,需要让COMMAND固定不变,同时让脚本根据CMake配置阶段生成的标志来决定是否生成额外输出。
修改步骤
1. 调整CMakeLists.txt
- 在配置阶段生成标志文件,告知脚本是否需要生成
bar.txt - 固定
add_custom_command的命令行,避免随MORE_OUTPUT参数变化 - 让自定义目标依赖所有输出文件,确保开启额外输出时能正确检查
bar.txt
修改后的CMakeLists.txt:
cmake_minimum_required(VERSION 3.14) project(example VERSION 1.0.0 LANGUAGES ) # 生成标志文件,存放于构建目录,避免污染源码目录 set(GENERATE_BAR_FLAG ${CMAKE_CURRENT_BINARY_DIR}/generate_bar.flag) if(NOT MORE_OUTPUT STREQUAL "") file(WRITE ${GENERATE_BAR_FLAG} "1") else() if(EXISTS ${GENERATE_BAR_FLAG}) file(REMOVE ${GENERATE_BAR_FLAG}) endif() endif() # 定义输出文件列表 list(APPEND outputs ${CMAKE_CURRENT_SOURCE_DIR}/foo.txt) if(NOT MORE_OUTPUT STREQUAL "") list(APPEND outputs ${CMAKE_CURRENT_SOURCE_DIR}/bar.txt) endif() add_custom_command( DEPENDS something.txt OUTPUT ${outputs} # 命令行固定,仅传递标志文件路径(路径不随MORE_OUTPUT变化) COMMAND ./file_generator.sh ${GENERATE_BAR_FLAG} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ ) # 目标依赖所有输出文件,确保开启MORE_OUTPUT时bar.txt被正确处理 add_custom_target(EXAMPLE ALL DEPENDS ${outputs})
2. 修改file_generator.sh
- 不再依赖命令行参数,改为检查标志文件是否存在来决定是否生成
bar.txt
修改后的file_generator.sh:
#!/bin/bash GENERATE_BAR_FLAG="$1" # 确保foo.txt始终更新 touch foo.txt # 仅当标志文件存在时生成bar.txt if [ -f "${GENERATE_BAR_FLAG}" ]; then touch bar.txt fi
效果验证
- 当
something.txt未修改,且输出文件(foo.txt及开启MORE_OUTPUT时的bar.txt)已存在且最新时,无论MORE_OUTPUT参数如何变化,目标都不会重新执行 - 当
something.txt修改,或输出文件不存在时,目标会执行脚本,根据标志文件决定是否生成bar.txt - 切换
MORE_OUTPUT参数后,若新增的输出文件(如bar.txt)不存在,CMake会触发脚本生成该文件,符合预期
内容的提问来源于stack exchange,提问作者Jeff G
相关产品推荐
相关产品推荐

