You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免CMake为两个相似库重复构建?附设计合理性咨询

解决共享库测试重复编译与内部符号访问问题

避免重复编译的方法

最直接的方案是用CMake的对象库(OBJECT Library),先把源码编译成可复用的对象文件,再基于这些对象构建正式库和测试库,这样源码只会编译一次。

修改后的CMake代码如下:

# 先编译对象库,源码仅编译一次
add_library(mylib_objects OBJECT ${SOURCES})

# 构建正式共享库,链接对象库并启用符号限制
add_library(mylib SHARED $<TARGET_OBJECTS:mylib_objects>)
export_signatures(mylib)
install(TARGETS mylib DESTINATION "${CMAKE_INSTALL_PREFIX}/lib")

# 若启用测试构建,基于同一份对象库构建无符号限制的测试库
if(ENABLE_TEST_BUILD)
    add_library(mylib-test SHARED $<TARGET_OBJECTS:mylib_objects>)
endif()

这样就能避免util.cpp等源码被重复编译,大幅减少构建时间。

当前设计的合理性分析

你的思路是对的:通过构建无符号限制的测试库绕开内部符号无法访问的问题,能保证正式库的符号安全性。但原实现的问题在于直接重复创建共享库目标,导致CMake重复编译源码,属于实现方式不够高效,而非设计思路错误。

额外优化建议

  1. 无需安装测试库:测试库仅用于本地测试,不需要安装到系统路径,可去掉测试库的install指令,避免污染正式安装目录。
  2. 直接编译测试代码:如果测试代码不多,也可以不单独建测试库,而是把测试源码和mylib_objects直接链接成测试可执行文件,减少目标数量:
    if(ENABLE_TEST_BUILD)
        add_executable(mylib-tests test.cpp $<TARGET_OBJECTS:mylib_objects>)
        target_link_libraries(mylib-tests ...) # 链接测试框架等依赖
    endif()
    
  3. 条件控制符号限制:如果不想维护两个库目标,也可以给正式库添加条件编译开关,仅在非测试模式下启用符号限制:
    add_library(mylib SHARED ${SOURCES})
    if(NOT ENABLE_TEST_BUILD)
        export_signatures(mylib)
    endif()
    install(TARGETS mylib DESTINATION "${CMAKE_INSTALL_PREFIX}/lib")
    
    但这种方式要注意:发布构建时必须确保ENABLE_TEST_BUILD处于关闭状态,避免正式库意外暴露内部符号。

内容的提问来源于stack exchange,提问作者rahman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 08:31:17