C++ CMake构建时如何为单个外部库单独指定不同编译选项
概述
问题背景
- 使用Clion作为开发工具,在C++项目中引入Google Benchmark库。
遇到的问题
- 项目默认采用
Debug构建类型时,同步引入的Benchmark库也会以Debug模式编译,但Google Benchmark必须使用Release模式构建才能正常运行。
现有方案的缺陷
- 曾尝试在Clion的CMake配置中添加
-DCMAKE_BUILD_TYPE=Release参数,但该操作会让整个项目切换为Release构建模式,无法保留主程序的Debug编译配置。
核心诉求
如何为单个依赖库指定独立的编译配置?
当前使用的CMake代码
# 目标可执行程序(需要以Debug模式运行) add_executable(benchmark_test thread/benchmark_test.cpp thread/benchmark_test.h) # 禁止Benchmark库编译自身的测试用例 set(BENCHMARK_ENABLE_TESTING NO) # 引入Benchmark库(源码存放于项目根目录下) # 需要该库以Release模式编译 add_subdirectory(benchmark) # 将目标程序与Benchmark库进行链接 target_link_libraries(benchmark_test benchmark)
已尝试但未生效的方案
# 原以为该指令会将所有构建目标设为Release模式,但未生效(可能受Clion环境影响) add_compile_options(-DCMAKE_BUILD_TYPE=Release) #=================================================================== # 目前尝试过的最接近可行的方案 set(GCC_COMPILE_OPTIONS "-DCMAKE_BUILD_TYPE=Release") target_compile_options(benchmark_main PUBLIC "$<$<CONFIG:Debug>:${GCC_COMPILE_DEBUG_OPTIONS}>") target_compile_options(benchmark PUBLIC "$<$<CONFIG:Debug>:${GCC_COMPILE_DEBUG_OPTIONS}>")
接触CMake时间不长,如果问题描述存在信息遗漏欢迎补充说明。
解决方案
之前尝试的方案不生效,核心原因有两点:
CMAKE_BUILD_TYPE是CMake的目录级全局变量,仅在变量设置完成后调用add_subdirectory、add_executable、add_library等目标创建指令时才会生效,在目标创建后修改不会改变已有目标的编译配置。-DCMAKE_BUILD_TYPE=XXX是CMake配置阶段的传入参数,不是编译器可识别的编译选项,通过add_compile_options或target_compile_options传给编译器完全无效。
正确实现方式是在引入benchmark子目录前临时覆写构建类型变量,子目录配置完成后立刻恢复原有变量值,不会影响主项目的编译配置,修改后的代码如下:
# 目标可执行程序(需要以Debug模式运行) add_executable(benchmark_test thread/benchmark_test.cpp thread/benchmark_test.h) # 禁止Benchmark库编译自身的测试用例 set(BENCHMARK_ENABLE_TESTING NO) # 单独给Benchmark设置Release编译配置 set(_TEMP_CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}) # 暂存当前项目的构建类型 set(CMAKE_BUILD_TYPE Release) # 临时切换为Release add_subdirectory(benchmark) set(CMAKE_BUILD_TYPE ${_TEMP_CMAKE_BUILD_TYPE}) # 恢复原项目的构建类型 # 将目标程序与Benchmark库进行链接 target_link_libraries(benchmark_test benchmark)
补充说明
- 该方案适配Clion默认使用的Ninja、Unix Makefiles等单配置生成器,日常GCC/Clang开发环境可直接使用。如果使用Visual Studio这类多配置生成器,需要单独通过生成器表达式为benchmark目标指定各配置下的编译参数,但不影响Clion场景下的使用。
- 不要通过手动给benchmark目标加
-O2等优化参数模拟Release效果,Google Benchmark内部通过编译宏判断构建类型,Debug模式下即使开启最高优化等级,也会注入额外的性能检查逻辑,直接导致基准测试结果失真。
内容的提问来源于stack exchange,提问作者Hykosit
相关产品推荐
相关产品推荐

