CMake生成器表达式中列表展开报错的解决咨询
CMake生成器表达式错误修复:多源文件条件添加问题
问题重现
用户编写的CMakeLists.txt代码如下:
set(MAIN_SOURCES src/main.cpp src/main.hpp ) set(FEATURE_SOURCES src/feature.cpp src/feature.hpp ) option(ENABLE_FEATURE "Enable feature in app" ON) add_executable(app) target_sources(app PRIVATE ${MAIN_SOURCES} $<$<BOOL:${ENABLE_FEATURE}>:${FEATURE_SOURCES}> )
配置时触发错误:
CMake Error in CMakeLists.txt: Cannot find source file: src/feature.hpp>
用户尝试给生成器表达式添加引号后,错误依然存在。
问题原因
当FEATURE_SOURCES作为多元素列表展开时,生成器表达式会被拆分成多个部分:原本的$<$<BOOL:ON>:${FEATURE_SOURCES}>会展开为$<$<BOOL:ON>:src/feature.cpp src/feature.hpp>,CMake会将空格视为元素分隔符,把src/feature.hpp>当成独立的源文件(末尾多余的>是生成器表达式的闭合符号被拆分导致的),自然找不到这个文件。
生成器表达式中,冒号:后面只能接收单个参数,直接展开多元素列表会触发解析错误。
正确写法
方法1:用$<JOIN>拼接列表
通过$<JOIN>将多源文件列表用分号(CMake的列表分隔符)拼接成单个参数,避免拆分:
target_sources(app PRIVATE ${MAIN_SOURCES} $<$<BOOL:${ENABLE_FEATURE}>:$<JOIN:${FEATURE_SOURCES},;>> )
方法2:使用传统if条件判断(更直观)
如果不需要生成器表达式的跨配置特性,直接用CMake的if语句实现条件添加,代码可读性更高:
add_executable(app) target_sources(app PRIVATE ${MAIN_SOURCES}) if(ENABLE_FEATURE) target_sources(app PRIVATE ${FEATURE_SOURCES}) endif()
为什么加引号没用?
CMake在解析生成器表达式时,不会将引号视为列表的包裹符号,引号会被当作普通字符处理,展开后依然会按空格拆分元素,因此无法解决问题。
内容的提问来源于stack exchange,提问作者Arthur Pinheiro
相关产品推荐
相关产品推荐

