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

如何在CMake独立子目录中高效编译GoogleTest测试且避免重复编译?

CMake主程序与测试共享源码避免重复编译的解决方案

推荐方案:拆分主程序为静态库+轻量执行文件

这是软件工程中处理此类问题的标准做法,完全满足你“仅构建单个ProjectMain可执行文件”的需求,同时彻底消除重复编译:

根目录CMakeLists.txt配置:

cmake_minimum_required(VERSION 3.10)
project(Project)

# 配置全局包含目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 创建静态库,封装所有业务逻辑代码(排除main.cpp)
add_library(ProjectLib STATIC
    src/foo_class.cpp
)

# 构建主程序可执行文件,仅依赖静态库和main函数文件
add_executable(ProjectMain
    src/main.cpp
)
target_link_libraries(ProjectMain PRIVATE ProjectLib)

# 引入测试子项目
add_subdirectory(test)

测试目录test/CMakeLists.txt配置:

# 查找并导入Google Test
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
include_directories(${PROJECT_SOURCE_DIR}/include)

# 构建测试可执行文件
add_executable(ProjectTest
    src/foo_class_test.cpp
)
# 链接静态库和gtest_main,复用已编译的业务代码
target_link_libraries(ProjectTest PRIVATE
    ProjectLib
    GTest::gtest_main
)

# 自动发现并注册测试用例
include(GoogleTest)
gtest_discover_tests(ProjectTest)

此方案中,foo_class.cpp仅编译一次(生成静态库),ProjectMain是独立的单个可执行文件,测试程序通过链接静态库直接获取业务代码的实现,没有重复编译开销,且代码结构更清晰、易维护。

替代方案:使用CMake对象库(Object Library)

如果确实不想生成独立的库文件,可以用CMake的对象库——一种仅编译源码为目标文件、不生成完整库的中间目标,同样实现源码单次编译:

根目录CMakeLists.txt调整:

cmake_minimum_required(VERSION 3.10)
project(Project)

include_directories(${PROJECT_SOURCE_DIR}/include)

# 创建对象库,编译业务源码为目标文件
add_library(ProjectObjects OBJECT
    src/foo_class.cpp
)

# 构建主程序,直接复用对象库的目标文件
add_executable(ProjectMain
    src/main.cpp
    $<TARGET_OBJECTS:ProjectObjects>
)

add_subdirectory(test)

测试目录test/CMakeLists.txt调整:

find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
include_directories(${PROJECT_SOURCE_DIR}/include)

# 构建测试程序,复用对象库的目标文件
add_executable(ProjectTest
    src/foo_class_test.cpp
    $<TARGET_OBJECTS:ProjectObjects>
)
target_link_libraries(ProjectTest PRIVATE GTest::gtest_main)

include(GoogleTest)
gtest_discover_tests(ProjectTest)

对象库不会生成额外的库文件,直接复用编译好的目标文件,既保证主程序是单个可执行,又避免了重复编译。

为什么不推荐“直接将主程序源码添加到测试目标”

这种方式会触发重复编译,因为CMake会为每个可执行目标独立编译源码,导致相同的foo_class.cpp被编译两次,浪费构建资源,不建议采用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 23:45:41