如何在CMake自定义目标调用的子进程中使用缓存变量
问题根因
cmake -P运行脚本属于脚本模式,该模式下不会自动加载父项目构建目录下的CMakeCache.txt,也不会默认将CACHE变量写入到父项目的缓存文件中。你在脚本中定义的CACHE变量仅存在于当前CMake子进程的生命周期内,进程结束后就会销毁,所以下次运行脚本时读取不到旧值。
解决方案
根据你的使用场景可以选择以下三种方案:
方案1:仅需读取父项目已有缓存变量
如果只需要在脚本中读取父项目配置阶段已经定义的缓存变量,直接在调用脚本时通过-D参数显式传入即可,无需修改脚本逻辑:
add_custom_target(TargetName COMMAND ${CMAKE_COMMAND} -D MY_CACHE_VARIABLE=${MY_CACHE_VARIABLE} -P ${CMAKE_SOURCE_DIR}/cmake/script.cmake BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/generated/output WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} VERBATIM )
该方案适合不需要将脚本中修改的变量回写到父缓存的场景。
方案2:需要将脚本变量同步到父项目缓存
如果需要让脚本中修改的变量在父项目重新配置、或者后续脚本运行时都能读取到,可以手动调用CMake命令将变量写入父项目缓存:
- 先修改自定义目标定义,将父项目构建目录、源码目录传入脚本:
add_custom_target(TargetName COMMAND ${CMAKE_COMMAND} -D PARENT_BINARY_DIR=${CMAKE_BINARY_DIR} -D PARENT_SOURCE_DIR=${CMAKE_SOURCE_DIR} -P ${CMAKE_SOURCE_DIR}/cmake/script.cmake BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/generated/output WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} VERBATIM )
- 脚本中先加载父缓存,修改后再写回:
# 加载父项目已有缓存 load_cache(${PARENT_BINARY_DIR}) message("MY_CACHE_VARIABLE = ${MY_CACHE_VARIABLE}") # 写回新值到父缓存 execute_process( COMMAND ${CMAKE_COMMAND} -S ${PARENT_SOURCE_DIR} -B ${PARENT_BINARY_DIR} -D MY_CACHE_VARIABLE:INTERNAL="VALUE" COMMAND_ERROR_IS_FATAL ANY )
如果使用CMake 3.21及以上版本,可以用cmake -E set_cache命令简化写入逻辑。
方案3:脚本私有持久化缓存
如果不需要和父项目共享缓存,仅需要脚本自己持久化存储变量,可以将变量存在独立的私有缓存文件中:
# 读取私有缓存 set(SCRIPT_CACHE_PATH ${CMAKE_CURRENT_BINARY_DIR}/script_cache.cmake) if(EXISTS ${SCRIPT_CACHE_PATH}) include(${SCRIPT_CACHE_PATH}) endif() message("MY_CACHE_VARIABLE = ${MY_CACHE_VARIABLE}") # 写入私有缓存 set(MY_CACHE_VARIABLE "VALUE") file(WRITE ${SCRIPT_CACHE_PATH} "set(MY_CACHE_VARIABLE \"${MY_CACHE_VARIABLE}\" CACHE INTERNAL \"\")")
该方案和父项目缓存完全隔离,不会互相影响。
内容的提问来源于stack exchange,提问作者Peter Shurgalin
相关产品推荐
相关产品推荐

