CMake配置:仅当编译器支持C++20及以上时构建指定库
解决CMake中仅在编译器支持C++20时构建指定库的问题
问题背景
我们的项目通过设置
set(CMAKE_C_STANDARD 17) set(CMAKE_CXX_STANDARD 20)
来启用最高可用的C和C标准,但同时需要兼容不支持C20的旧编译器。现有部分库依赖C20特性,希望通过CMake配置让这些库仅在编译器支持C20时才构建,且不想在代码中使用#ifdef __cplusplus >= ...这类预处理指令。
解决方案
1. 检测编译器对C++20的实际支持
CMake提供的check_cxx_compiler_flag可以初步检测编译flag支持,但结合try_compile能更准确判断编译器是否真的能编译C++20代码:
include(CheckCXXCompilerFlag) check_cxx_compiler_flag("-std=c++20" COMPILER_SUPPORTS_CXX20) if(COMPILER_SUPPORTS_CXX20) # 用实际C++20特性代码验证编译能力 try_compile(CXX20_WORKS ${CMAKE_BINARY_DIR}/cxx20_check SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/cxx20_test.cpp" CMAKE_FLAGS "-DCMAKE_CXX_STANDARD=20" "-DCMAKE_CXX_STANDARD_REQUIRED=ON" OUTPUT_VARIABLE CXX20_COMPILE_OUTPUT ) endif()
配套的cxx20_test.cpp可以用一个简单的C++20特性示例:
#include <concepts> template<typename T> requires std::integral<T> T add(T a, T b) { return a + b; } int main() { return add(1, 2); }
2. 条件构建依赖C++20的库
在库的CMake配置中,根据检测结果控制是否构建:
if(CXX20_WORKS) add_library(cxx20_dependent_lib STATIC src/lib_file1.cpp src/lib_file2.cpp ) # 为该库明确指定C++20特性要求 target_compile_features(cxx20_dependent_lib PRIVATE cxx_std_20) # 配置头文件路径、链接依赖等 target_include_directories(cxx20_dependent_lib PUBLIC include) else() message(STATUS "编译器不支持C++20,跳过cxx20_dependent_lib构建") endif()
3. 主项目条件链接目标库
在主项目的可执行文件或其他库中,同样根据检测结果决定是否链接依赖库:
add_executable(main_app main.cpp) # 主项目使用最高可用标准,CMake会自动适配编译器支持的版本 target_compile_features(main_app PRIVATE cxx_std_20) if(CXX20_WORKS) target_link_libraries(main_app PRIVATE cxx20_dependent_lib) endif()
关键说明
- 用
target_compile_features替代全局CMAKE_CXX_STANDARD,能为单个目标精准指定特性需求,CMake会自动处理编译器兼容性。 try_compile比单纯检测编译flag更可靠,可避免部分编译器声称支持C++20但实际特性缺失的情况。- 全程在CMake层面处理逻辑,无需在代码中加入预处理指令,保持代码整洁。
内容的提问来源于stack exchange,提问作者user8694474
相关产品推荐
相关产品推荐

