CMake编译时在静态库生成前替换目标文件的方法
解决CMake中替换静态库目标文件的问题
我来给你捋捋这个问题,你要的是把Proj_A里带伪功能的A_OBJECT.o替换掉Proj_B静态库中同名的原版文件对吧?之前用file()、configure_file()这些没成,大概率是时机没抓对——CMake的配置阶段和构建阶段要区分开,下面给你两个实用的方案:
方案一:直接修改Proj_B的源文件列表
这个方案最直接,就是从Proj_B的编译源里移除生成原版A_OBJECT.o的源文件,替换成Proj_A已经编译好的目标文件:
# 先确保Proj_A在Proj_B之前构建 add_dependencies(Proj_B Proj_A) # 获取Proj_A生成的A_OBJECT.o的完整路径(用CMake生成表达式跨平台获取) set(PROJ_A_OBJ_FILE "$<TARGET_FILE_DIR:Proj_A>/A_OBJECT.o") # 假设Proj_B的源文件列表存在变量Proj_B_SOURCES中,移除生成原版的源文件(比如A_OBJECT.c) list(REMOVE_ITEM Proj_B_SOURCES "A_OBJECT.c") # 把Proj_A的目标文件加入Proj_B的编译列表 list(APPEND Proj_B_SOURCES "${PROJ_A_OBJ_FILE}") # 重新定义Proj_B的静态库目标 add_library(Proj_B STATIC ${Proj_B_SOURCES})
解释:通过add_dependencies确保Proj_A先完成编译,这样它的A_OBJECT.o才会存在;用$<TARGET_FILE_DIR:Proj_A>可以自动获取Proj_A目标文件所在的目录,避免硬编码路径出错。
方案二:构建后用ar工具替换静态库中的目标文件
如果不想修改Proj_B的源列表,可以在Proj_B静态库生成后,用ar工具删除其中的原版A_OBJECT.o,再把Proj_A的版本加进去:
# 确保Proj_A优先构建 add_dependencies(Proj_B Proj_A) # 定义构建后的替换命令 add_custom_command(TARGET Proj_B POST_BUILD # 从Proj_B静态库中删除原版A_OBJECT.o COMMAND ${CMAKE_AR} d $<TARGET_FILE:Proj_B> A_OBJECT.o # 把Proj_A的A_OBJECT.o添加到静态库中 COMMAND ${CMAKE_AR} r $<TARGET_FILE:Proj_B> "$<TARGET_FILE_DIR:Proj_A>/A_OBJECT.o" COMMENT "Replacing A_OBJECT.o in Proj_B with Proj_A's test version" )
解释:CMAKE_AR是CMake提供的跨平台变量,会自动适配不同系统的归档工具;POST_BUILD确保这个命令在Proj_B静态库生成后执行,$<TARGET_FILE:Proj_B>直接获取静态库的完整路径,不用手动拼接。
为什么之前的方法没成功?
你之前试的file()、configure_file()都是在CMake配置阶段执行的,而目标文件是在构建阶段才生成的,配置阶段根本拿不到这些文件,自然无法替换。上面两个方案都是在构建阶段触发操作,正好匹配文件生成的时机。
内容的提问来源于stack exchange,提问作者mruva
相关产品推荐
相关产品推荐

