如何用CMake同时构建32位和64位GoogleTest测试程序
同一CMake项目中同时构建32/64位GoogleTest测试程序的架构冲突解决办法
问题背景
为支持32/64位核心的平台开发软件,需用GoogleTest分别为两类软件编写单元测试:32位软件的测试程序必须以32位构建,64位软件的测试程序以64位构建,这意味着要分别编译对应架构的GoogleTest。
单独构建子目录可正常工作,但根目录通过add_subdirectory同时添加两个子目录后构建失败——GoogleTest仅被构建一次,导致架构不兼容,触发链接错误。
需求:
- VSCode环境下无需手动修改
cmake.sourceDirectory,一次性编译两种架构的所有测试程序 - 不将预编译库及GoogleTest头文件加入Git仓库,优先使用CMake FetchContent特性按需获取编译
- 分别编译构建各目标,规避架构冲突
项目结构:
├─ CMakeLists.txt ├─ test32/ ├─ CMakeLists.txt ├─ src/ ├─ calc32.c ├─ calc32.h ├─ tests/ ├─ tests32.cpp ├─ unit_tests_main.cpp └─ test64/ ├─ CMakeLists.txt ├─ src/ ├─ calc64.c ├─ calc64.h ├─ tests/ ├─ tests64.cpp ├─ unit_tests_main.cpp
原根目录CMakeLists.txt:
cmake_minimum_required(VERSION 3.14) project(tests) add_subdirectory("test32") add_subdirectory("test64")
原test32与test64目录的CMakeLists.txt基本一致,仅32位版本多了设置-m32属性的代码。
解决方案
核心问题是FetchContent默认全局共享依赖构建结果,导致32/64位GoogleTest冲突。解决思路是让每个子项目独立构建专属的GoogleTest实例,互不干扰。
1. 根目录CMakeLists.txt无需修改
保持原结构即可,确保CMake版本≥3.14。
2. 修改test32/CMakeLists.txt
替换FetchContent_MakeAvailable为手动流程,指定独立的依赖目录,并在构建GoogleTest时直接设置32位编译选项:
project(test32) cmake_minimum_required(VERSION 3.14) set(EXEC_NAME "calc32") set(TEST_EXEC_NAME "calc32_tests") set(TEST_DIR "./tests") set(SRC_DIR "./src") include(GoogleTest) include(FetchContent) enable_testing() FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG v1.13.0 ) # 为32位测试单独设置依赖目录,避免与64位共享 set(FETCHCONTENT_BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}/_deps) FetchContent_Populate(googletest) # 全局设置32位编译链接选项,确保GoogleTest本身以32位构建 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") # 构建32位GoogleTest,EXCLUDE_FROM_ALL避免被根项目默认触发 add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) # 恢复全局编译选项,避免影响其他子项目 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_RELEASE}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_RELEASE}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") add_executable(${TEST_EXEC_NAME} ${TEST_DIR}/unit_tests_main.cpp ${TEST_DIR}/tests32.cpp ${SRC_DIR}/calc32.c ) # 强制测试程序以32位构建 set_target_properties(${TEST_EXEC_NAME} PROPERTIES COMPILE_OPTIONS "-m32" LINK_FLAGS "-m32") target_include_directories(${TEST_EXEC_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${SRC_DIR} ) target_link_libraries( ${TEST_EXEC_NAME} gtest ) gtest_discover_tests(${TEST_EXEC_NAME})
3. 修改test64/CMakeLists.txt
同样使用独立依赖目录,默认构建64位GoogleTest:
project(test64) cmake_minimum_required(VERSION 3.14) set(EXEC_NAME "calc64") set(TEST_EXEC_NAME "calc64_tests") set(TEST_DIR "./tests") set(SRC_DIR "./src") include(GoogleTest) include(FetchContent) enable_testing() FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG v1.13.0 ) # 为64位测试单独设置依赖目录 set(FETCHCONTENT_BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}/_deps) FetchContent_Populate(googletest) # 构建64位GoogleTest add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) add_executable(${TEST_EXEC_NAME} ${TEST_DIR}/unit_tests_main.cpp ${TEST_DIR}/tests64.cpp ${SRC_DIR}/calc64.c ) target_include_directories(${TEST_EXEC_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${SRC_DIR} ) target_link_libraries( ${TEST_EXEC_NAME} gtest ) gtest_discover_tests(${TEST_EXEC_NAME})
关键说明
FETCHCONTENT_BASE_DIR指定为当前子项目二进制目录下的_deps,确保两个子项目的GoogleTest下载、构建目录完全独立,无交叉污染。- 用
FetchContent_Populate+add_subdirectory替代FetchContent_MakeAvailable,完全控制GoogleTest的构建流程,从根源保证架构匹配。 EXCLUDE_FROM_ALL参数确保GoogleTest仅在测试程序依赖时才会构建,不会被根项目的all目标默认触发。
修改完成后,根项目构建时会分别编译32位/64位的GoogleTest及对应测试程序,无架构冲突,无需手动修改VSCode配置即可一次性完成所有编译。
内容的提问来源于stack exchange,提问作者Nr7
相关产品推荐
相关产品推荐

