CMake copy_if_different未变更也执行 如何避免解压命令重复运行
问题根源
- 无输出绑定的自定义目标默认始终执行
你用add_custom_target定义的copy_libraries没有关联输出文件,CMake默认会将这类目标标记为每次构建都需要执行,哪怕内部用了copy_if_different只会在文件变更时才真实执行复制操作,目标本身的日志输出、命令触发逻辑都会每次运行,看起来就像copy_if_different没生效。 - 解压目标没有绑定依赖变化逻辑
extract_libraries同样是无输出绑定的全局构建(ALL参数)自定义目标,且依赖了每次都会执行的copy_libraries,所以不管源文件有没有变更,解压命令每次都会触发。
解决方案
调整为用add_custom_command绑定输入输出的依赖关系,让CMake自动根据文件时间戳判断是否需要执行对应操作,修改后的完整代码如下:
set(EXTERNAL_LIB_PATH_SRC "/home/pst/libs/void_lib.tar.gz") set(EXTERNAL_LIB_PATH_DST "/home/pst/my_app/build/external_libs/void_lib.tar.gz") set(UNPACK_PATH "/home/pst/my_app/build/external_libs/unpacked/") # 新增解压标记文件,用于记录上次解压时间 set(EXTRACT_STAMP_FILE "${UNPACK_PATH}/.extract_stamp") # 定义复制操作的自定义命令,关联源文件和目标文件 add_custom_command( OUTPUT ${EXTERNAL_LIB_PATH_DST} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXTERNAL_LIB_PATH_SRC} ${EXTERNAL_LIB_PATH_DST} MAIN_DEPENDENCY ${EXTERNAL_LIB_PATH_SRC} COMMENT "Copying external library if changed" ) # 定义解压操作的自定义命令,依赖复制后的压缩包,仅当压缩包更新时才执行 add_custom_command( OUTPUT ${EXTRACT_STAMP_FILE} COMMAND ${CMAKE_COMMAND} -E make_directory ${UNPACK_PATH} COMMAND ${CCRYPT} -d -k "some_key" ${EXTERNAL_LIB_PATH_DST} -c | ${TAR} -xf - -C ${UNPACK_PATH} -Z COMMAND ${CMAKE_COMMAND} -E touch ${EXTRACT_STAMP_FILE} MAIN_DEPENDENCY ${EXTERNAL_LIB_PATH_DST} COMMENT "Extracting external library if changed" VERBATIM ) # 自定义目标仅依赖解压标记文件,无变更时不会触发 add_custom_target(extract_libraries ALL DEPENDS ${EXTRACT_STAMP_FILE} ) add_dependencies(my_app extract_libraries)
效果说明
- 仅当源压缩包
EXTERNAL_LIB_PATH_SRC发生变更时,才会执行复制操作 - 仅当复制后的目标压缩包
EXTERNAL_LIB_PATH_DST更新时,才会执行解压操作,其余构建场景都会跳过这两步
如果可以明确知道解压后生成的所有文件列表,可将EXTRACT_STAMP_FILE替换为这些解压产物的路径,即可无需额外维护标记文件。
内容的提问来源于stack exchange,提问作者pureofpure
相关产品推荐
相关产品推荐

