CMake扁平化层级构建可执行文件及依赖的配置咨询
需求可行性与实现方案
你的需求完全可以实现,现代CMake提供了多种符合要求的方案,既能保证各子项目独立维护,又能按需编译依赖,同时遵循现代CMake的最佳实践(避免全局设置,采用目标级配置)。
最佳方案:使用FetchContent管理本地/独立子项目
这个方案完美契合你的需求:各子项目(app、square)可以独立维护(甚至作为单独的Git仓库),根项目按需拉取并编译依赖,完全避免add_subdirectory()和全局的include_directories()。
1. 配置子项目的CMakeLists.txt
square子项目的CMakeLists.txt
cmake_minimum_required(VERSION 3.14) project(square LANGUAGES CXX) # 创建静态库目标 add_library(square STATIC src/lolerji_square.cpp ) # 设置目标的包含目录(仅针对该目标,非全局) target_include_directories(square PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ) # 设置C++标准 target_compile_features(square PUBLIC cxx_std_17)
app子项目的CMakeLists.txt
cmake_minimum_required(VERSION 3.14) project(app LANGUAGES CXX) # 创建可执行文件目标 add_executable(app src/main.cpp ) # 设置C++标准 target_compile_features(app PRIVATE cxx_std_17) # 声明依赖的square库(后续由根项目通过FetchContent提供) find_package(square REQUIRED) # 链接依赖库 target_link_libraries(app PRIVATE square::square)
2. 配置根目录的CMakeLists.txt
根项目负责管理所有子项目的依赖,按需拉取并编译:
cmake_minimum_required(VERSION 3.14) project(MyRootProject LANGUAGES CXX) # 启用FetchContent模块 include(FetchContent) # 引入square子项目(本地路径配置) FetchContent_Declare( square SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/square # 若为独立Git仓库,替换为: # GIT_REPOSITORY https://your-git-repo/square.git # GIT_TAG main ) # 引入app子项目 FetchContent_Declare( app SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/app # 若为独立Git仓库,替换为: # GIT_REPOSITORY https://your-git-repo/app.git # GIT_TAG main ) # 按需构建依赖:先构建square,再构建app FetchContent_MakeAvailable(square app)
3. 构建流程
在根目录创建build文件夹并执行构建:
mkdir build && cd build cmake .. cmake --build .
该方案优势:
- 每个子项目完全独立,可单独编译、测试、维护
- 根项目按需拉取依赖,仅当app被构建时,square才会自动编译
- 所有配置均为目标级,避免全局污染,符合现代CMake规范
备选方案:同一仓库下的目标级配置(允许使用add_subdirectory)
如果子项目都在同一仓库下,且可接受add_subdirectory(),这是更简洁的方案,同样遵循现代CMake实践:
根目录CMakeLists.txt
cmake_minimum_required(VERSION 3.14) project(MyRootProject LANGUAGES CXX) # 添加子项目(仅添加,不做全局设置) add_subdirectory(square) add_subdirectory(app)
square子项目的CMakeLists.txt(同最佳方案)
cmake_minimum_required(VERSION 3.14) project(square LANGUAGES CXX) add_library(square STATIC src/lolerji_square.cpp) target_include_directories(square PUBLIC include) target_compile_features(square PUBLIC cxx_std_17)
app子项目的CMakeLists.txt
cmake_minimum_required(VERSION 3.14) project(app LANGUAGES CXX) add_executable(app src/main.cpp) target_compile_features(app PRIVATE cxx_std_17) # 直接链接square目标,无需find_package target_link_libraries(app PRIVATE square)
该方案优势:配置更简洁,适合同一仓库内的子项目管理,同样避免了include_directories()的全局设置,使用目标级的链接和包含目录。
关键注意事项
- 始终用
target_include_directories()替代include_directories():前者仅作用于指定目标,避免全局路径污染 - 使用
target_compile_features()或target_compile_options()设置编译标准和选项,而非全局的CMAKE_CXX_STANDARD - 依赖声明优先用
find_package()或直接链接目标,而非硬编码路径 - 每个子项目都应能独立构建,确保可维护性
内容的提问来源于stack exchange,提问作者LoLeRji
相关产品推荐
相关产品推荐

