CMake列表转字符串时如何转义列表项中的分号?
CMake列表转C编译器定义字符串时保留分号的解决方法
问题场景
给定CMake列表:
set(options "-DVERSION=\\\"42\\\"" "-DADDITIONAL_VERSIONS=\"MODULE_INFO(my_module, \\\"42.0\\\");\"" )
需要将其转换为可直接传递给C编译器的字符串,目标格式如下:
"-DVERSION=\"42\" -DADDITIONAL_VERSIONS="MODULE_INFO(my_module, \"42.0\");""
但转换过程中MODULE_INFO后的分号始终丢失,需支持处理所有合法且正确转义的C预处理器define。
问题根源
CMake中分号是列表的默认分隔符,即使字符串内的分号被转义,若未做特殊保护,在列表处理环节仍会被当作元素拆分标记,导致分号丢失。
解决方案
方案1:遍历拼接法(最直观)
直接遍历列表元素,逐个拼接到结果字符串,避免CMake自动拆分元素:
set(compiled_options "") foreach(opt IN LISTS options) if(compiled_options) string(APPEND compiled_options " ") endif() string(APPEND compiled_options "${opt}") endforeach() # 输出验证 message("转换结果:${compiled_options}")
方案2:占位符替换法
先将元素内的分号替换为CMake不会解析的临时占位符,拼接后再还原:
# 临时替换分号为占位符 set(temp_options "") foreach(opt IN LISTS options) string(REPLACE ";" "__SEMICOLON_MARKER__" temp_opt "${opt}") list(APPEND temp_options "${temp_opt}") endforeach() # 拼接成空格分隔的字符串 string(JOIN " " compiled_options "${temp_options}") # 还原分号 string(REPLACE "__SEMICOLON_MARKER__" ";" compiled_options "${compiled_options}") # 输出验证 message("转换结果:${compiled_options}")
方案3:转义还原法
先对元素内的分号进行转义保护,再将列表转为空格分隔的字符串,最后还原分号:
# 转义元素内的分号,避免被当作列表分隔符 set(escaped_options "") foreach(opt IN LISTS options) string(REPLACE ";" "\\;" escaped_opt "${opt}") list(APPEND escaped_options "${escaped_opt}") endforeach() # 将转义后的列表转为空格分隔的字符串 string(REPLACE ";" " " compiled_options "${escaped_options}") # 还原元素内的分号 string(REPLACE "\\;" ";" compiled_options "${compiled_options}") # 输出验证 message("转换结果:${compiled_options}")
关键注意点
- 使用
foreach(IN LISTS)遍历列表,确保每个原始元素被完整读取,不会因分号被拆分。 - 无论哪种方案,核心都是先保护元素内的分号不被CMake解析为列表分隔符,再进行拼接操作。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

