如何用CMake构建可独立编译子项目并共享公共CMake变量?
实现CMake多示例项目的全局配置共享(支持全量/独立编译)
核心思路
把公共编译、链接配置抽成独立的CMake模块,顶层项目加载后批量引入所有子示例;每个子示例单独编译时,自动向上查找并加载顶层的公共配置,彻底避免重复复制配置代码。
步骤1:重构项目结构
新增cmake/CommonConfig.cmake统一存放公共配置,调整后结构如下:
- top level CMakeLists.txt cmake/ CommonConfig.cmake -- example_A # 建议把带空格的目录名改成下划线格式,避免CMake路径解析问题 A.cpp CMakeLists.txt -- example_B B.cpp CMakeLists.txt -- example_C C.cpp CMakeLists.txt
步骤2:编写公共配置文件 cmake/CommonConfig.cmake
把所有公共选项集中放在这里:
# C++编译公共选项 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -fexperimental-library") # 链接公共选项 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc++abi -fuse-ld=lld") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -lc++abi -fuse-ld=lld") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lc++abi -fuse-ld=lld") # C++标准配置 set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF)
步骤3:编写顶层 CMakeLists.txt
加载公共配置后,批量引入所有子示例:
cmake_minimum_required(VERSION 3.16) project(AllExamples) # 加载全局公共配置 include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/CommonConfig.cmake) # 引入所有子示例项目 add_subdirectory(example_A) add_subdirectory(example_B) add_subdirectory(example_C)
步骤4:编写子示例的 CMakeLists.txt
每个子项目只需少量代码,自动适配全量/独立编译场景:
cmake_minimum_required(VERSION 3.16) project(ExampleA) # 每个子项目改对应的名称 # 检查是否已加载全局配置,未加载则自动定位顶层配置文件 if(NOT DEFINED CMAKE_CXX_STANDARD) get_filename_component(ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../ ABSOLUTE) include(${ROOT_DIR}/cmake/CommonConfig.cmake) endif() # 生成可执行文件,每个子项目改对应的源文件名 add_executable(exampleA A.cpp)
验证方式
全量构建所有示例:在顶层目录执行
mkdir build && cd build cmake .. make -j$(nproc)所有示例会同时编译,自动应用公共配置。
独立编译单个示例:比如进入
example_A目录执行mkdir build && cd build cmake .. make子项目会自动加载顶层的公共配置,无需手动复制任何编译选项。
关键细节
- 必须避免目录名带空格,否则CMake路径解析容易出问题。
get_filename_component确保子项目能正确定位顶层目录,不管用户从哪个路径执行CMake命令。- 用
NOT DEFINED CMAKE_CXX_STANDARD判断配置是否已加载,避免重复设置引发冲突。
内容的提问来源于stack exchange,提问作者Learning Lin
相关产品推荐
相关产品推荐

