如何在编译前通过CMake替换源文件中的任意字符串?
实现CMake构建阶段的字符串替换编译方案
完全可行,无需外部工具,通过CMake的自定义命令配合内置文件操作命令就能实现。具体步骤如下:
定义文件路径
在CMakeLists.txt中先声明源文件和构建目录中生成的修改后文件路径:set(SOURCE_MAIN "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp") set(GENERATED_MAIN "${CMAKE_BINARY_DIR}/main_modified.cpp")添加构建阶段的替换命令
使用add_custom_command创建一个自定义构建步骤,在构建时读取源文件、替换指定字符串并写入新文件。这里提供两种实现方式:方式一:使用单独的CMake脚本文件
在项目根目录创建
replace_script.cmake,内容如下:# 读取源文件内容 file(READ "${SRC}" FILE_CONTENT) # 执行字符串替换 string(REPLACE "${OLD_STRING}" "${NEW_STRING}" MODIFIED_CONTENT "${FILE_CONTENT}") # 将修改后的内容写入目标文件 file(WRITE "${DST}" "${MODIFIED_CONTENT}")然后在CMakeLists.txt中调用这个脚本:
add_custom_command( OUTPUT ${GENERATED_MAIN} COMMAND ${CMAKE_COMMAND} -D SRC=${SOURCE_MAIN} -D DST=${GENERATED_MAIN} -D OLD_STRING="a = statement;" -D NEW_STRING="// something else" -P "${CMAKE_CURRENT_SOURCE_DIR}/replace_script.cmake" DEPENDS ${SOURCE_MAIN} COMMENT "Performing string replacement on main.cpp..." )方式二:内嵌脚本(无需额外文件)
如果不想新增脚本文件,可以直接将替换逻辑嵌入到命令中:
add_custom_command( OUTPUT ${GENERATED_MAIN} COMMAND ${CMAKE_COMMAND} -E echo " file(READ \"${SOURCE_MAIN}\" CONTENT) string(REPLACE \"a = statement;\" \"// something else\" MODIFIED CONTENT) file(WRITE \"${GENERATED_MAIN}\" MODIFIED) " | ${CMAKE_COMMAND} -P - DEPENDS ${SOURCE_MAIN} COMMENT "Modifying main.cpp in build stage..." )编译生成可执行文件
将生成的修改后文件作为源文件,创建可执行目标:add_executable(myapp ${GENERATED_MAIN})
关键说明
- 该方案在构建阶段执行替换,而非配置阶段,每次源文件
main.cpp修改后,构建时都会自动重新生成修改后的文件并编译。 - 完全依赖CMake内置命令,无需调用sed、awk等外部工具,跨平台兼容性好。
- 解决了
configure_file只能替换预定义变量标记(如@VAR@)的限制,支持任意字符串的精准替换。
内容的提问来源于stack exchange,提问作者Benjamin Buch
相关产品推荐
相关产品推荐

