You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 13:42:47