如何通过CMake脚本读取.cfg文件批量设置环境变量?
当然可以!在CMake里完全能实现批量从.cfg文件提取并设置变量的需求,我给你一套实用的方案,附带详细解释:
核心思路
通过CMake的文件查找、内容读取和正则匹配能力,完成三个关键步骤:
- 定位所有目标
.cfg文件 - 逐个读取文件内容,匹配出所有
VAR_NAME="<VAR_VALUE>"格式的变量条目 - 拆分变量名和值,将其设置为CMake变量
完整实现代码
# 1. 查找当前目录下所有的*.cfg文件(如果需要递归查找子目录,改用GLOB_RECURSE) file(GLOB CFG_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.cfg") # 2. 遍历每个找到的cfg文件 foreach(CFG_FILE ${CFG_FILES}) # 读取整个cfg文件的内容到临时变量 file(READ "${CFG_FILE}" CFG_CONTENT) # 3. 使用正则表达式匹配所有符合格式的变量条目 # 正则说明:捕获两个分组——第一个是变量名(字母/数字/下划线),第二个是双引号包裹的值 string(REGEX MATCHALL "([A-Za-z0-9_]+)=\"([^\"]*)\"" CFG_VARS "${CFG_CONTENT}") # 4. 遍历每个匹配到的变量条目,拆分并设置CMake变量 foreach(CFG_VAR ${CFG_VARS}) # 提取变量名(第一个捕获组) string(REGEX REPLACE "([A-Za-z0-9_]+)=\"([^\"]*)\"" "\\1" VAR_NAME "${CFG_VAR}") # 提取变量值(第二个捕获组) string(REGEX REPLACE "([A-Za-z0-9_]+)=\"([^\"]*)\"" "\\2" VAR_VALUE "${CFG_VAR}") # 设置CMake变量:这里用CACHE INTERNAL是让变量在整个项目可见,你也可以根据需求调整作用域 # 如果需要让父目录的CMakeLists.txt也能访问,加上PARENT_SCOPE参数 set(${VAR_NAME} "${VAR_VALUE}" CACHE INTERNAL "Parsed from ${CFG_FILE}") # 可选:打印日志,确认变量是否正确解析 message(STATUS "Parsed variable from ${CFG_FILE}: ${VAR_NAME} = ${VAR_VALUE}") endforeach() endforeach()
关键细节与优化建议
- 文件查找范围:如果需要递归查找子目录下的
.cfg文件,把file(GLOB)改成file(GLOB_RECURSE)即可,但要注意GLOB类命令不会自动跟踪文件新增/删除,若需要动态感知,建议改用file(GLOB_RECURSE CONFIGURE_DEPENDS)(CMake 3.12+支持)。 - 忽略注释行:如果你的
.cfg文件里有#开头的注释,可以拆分每行后逐个处理,过滤掉注释行再匹配变量:string(REPLACE "\n" ";" CFG_LINES "${CFG_CONTENT}") foreach(LINE ${CFG_LINES}) string(STRIP "${LINE}" LINE_STIPPED) if(NOT LINE_STIPPED MATCHES "^#") string(REGEX MATCH "([A-Za-z0-9_]+)=\"([^\"]*)\"" _MATCH "${LINE_STIPPED}") if(_MATCH) # 后续拆分变量名和值的逻辑和之前一致 endif() endif() endforeach() - 变量冲突处理:如果多个
.cfg文件有同名变量,后处理的文件会覆盖先处理的变量值。如果需要避免覆盖,可以在变量名前加上文件名前缀,比如:get_filename_component(CFG_BASENAME "${CFG_FILE}" NAME_WE) set("${CFG_BASENAME}_${VAR_NAME}" "${VAR_VALUE}" CACHE INTERNAL "Parsed from ${CFG_FILE}") - 特殊字符兼容:如果变量值里包含双引号,需要在
.cfg文件里用转义符(比如\"),同时调整正则表达式来匹配转义后的引号,比如把([^\"]*)改成((?:\\\\\"|[^\"])*)。
内容的提问来源于stack exchange,提问作者amigo421
相关产品推荐
相关产品推荐

