CMake的file(GENERATE)命令能否解析变量?存在哪些变量解析限制?
CMake file(GENERATE) 变量解析规则与问题修复方案
一、file(GENERATE) 可解析变量的限制
file(GENERATE)在CMake的生成阶段执行,此时配置阶段(CMakeLists.txt解析执行阶段)已经结束,变量解析有明确限制:
- 不支持配置阶段定义的普通局部/全局非缓存变量:这类变量仅在配置阶段有效,生成阶段会被销毁,无法被识别
- 支持的变量类型仅包括:
- 缓存变量:通过
set(VAR VAL CACHE ...)定义的变量,会持久化到CMakeCache.txt,生成阶段可正常读取 - CMake内置的全局生成阶段有效变量:比如
CMAKE_CURRENT_LIST_DIR、PROJECT_NAME等内置固定变量
- 缓存变量:通过
- 额外注意:如果使用
INPUT参数读取外部模板文件,模板内的${VAR}不会在配置阶段自动展开,只会在生成阶段尝试匹配变量,匹配失败就会原样输出${VAR}内容。
二、问题原因
你定义的COURAGE_COMPOSITES是配置阶段的普通变量,仅在配置阶段有效,执行message时是配置阶段所以能正常打印值,但进入生成阶段执行file(GENERATE)时该变量已经销毁,模板中无法识别,就直接原样输出了变量名。
三、两种修复方案
方案1:将变量改为缓存变量
修改COURAGE_COMPOSITES的定义逻辑,增加CACHE参数让它持久化为缓存变量,生成阶段即可正常读取:
# 定义时添加CACHE参数,INTERNAL类型不会在cmake-gui中显示,FORCE强制覆盖已有值 set(COURAGE_COMPOSITES ${COURAGE_COMPOSITES} CACHE INTERNAL "Composites list" FORCE) message("Registered composites: ${COURAGE_COMPOSITES}") file(GENERATE OUTPUT ${OUTPUT_PATH}/output.xml INPUT ${INPUT_PATH}/output.xml.in)
方案2:先调用configure_file预展开普通变量
如果不想修改原变量的作用域,可以先用configure_file在配置阶段把模板里的普通变量展开,生成带生成器表达式的中间模板,再传入file(GENERATE)处理:
# 第一步:配置阶段展开普通变量,生成中间模板 configure_file(${INPUT_PATH}/output.xml.in ${CMAKE_CURRENT_BINARY_DIR}/output.xml.tmp) # 第二步:生成阶段处理生成器表达式,输出最终文件 file(GENERATE OUTPUT ${OUTPUT_PATH}/output.xml INPUT ${CMAKE_CURRENT_BINARY_DIR}/output.xml.tmp)
这个方案更通用,不需要调整原有变量的定义逻辑,适配绝大多数场景。
内容的提问来源于stack exchange,提问作者kutschkem
相关产品推荐
相关产品推荐

