如何用CMake生成含全量项目及单可执行文件的VS解决方案
嘿,我明白你想要的是一个灵活的CMake项目结构——既能有一个包含所有组件的总解决方案,又能为每个单独的可执行文件生成只包含自身和必要依赖的独立方案,对吧?我来给你一步步解决这个问题!
你的核心需求
你需要两种构建方式:
- 一个总解决方案:包含所有库和可执行文件,方便整体构建和管理;
- 多个独立解决方案:每个可执行文件对应一个方案,只包含自身和它依赖的静态库,完全不涉及其他无关项目。
现有项目结构与问题
先梳理下你当前的项目结构:
/path/to/base/ ├── CMakeLists.txt ├── app1/ │ ├── <app1源码文件> │ └── CMakeLists.txt ├── app2/ │ ├── <app2源码文件> │ └── CMakeLists.txt └── lib/ ├── <lib源码文件> └── CMakeLists.txt
你当前的CMake脚本存在两个关键问题:
- 根目录构建的冗余问题:运行根目录的CMake时,生成的VS解决方案会把所有项目捆绑在一起——哪怕你只打开app1的项目,VS也会默认显示并可能触发app2的构建,不符合你“模块化”的需求;
- 单独构建app的依赖缺失问题:直接运行app1目录的CMake时,生成的解决方案会缺失lib目标,因为lib的定义不在app1的脚本里,导致无法正确链接编译。
解决方案:让每个组件可独立引用
我们只需要对现有CMake脚本做几处小修改,就能实现你想要的灵活构建效果:
1. 优化lib的CMake脚本
首先让lib的脚本可以被其他项目正确引入,修改lib/CMakeLists.txt:
cmake_minimum_required(VERSION 3.1) project(lib) # 定义静态库目标 add_library(lib <lib源码文件>) # 可选:导出目标,方便其他项目更规范地引用 export(TARGETS lib FILE libTargets.cmake)
2. 修改app的CMake脚本,自动引入依赖
以app1/CMakeLists.txt为例,添加逻辑:如果当前是单独构建app1,就主动引入lib的目录;如果是根目录统一构建,就直接用已存在的lib目标。app2的脚本做完全相同的修改:
cmake_minimum_required(VERSION 3.1) project(app1) # 检查lib目标是否已存在,不存在则主动引入lib目录 if(NOT TARGET lib) # 用相对路径指向lib目录,同时指定单独的构建目录避免污染源码 add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../lib ${CMAKE_CURRENT_BINARY_DIR}/lib) endif() # 定义可执行文件并链接lib add_executable(app1 <app1源码文件>) target_link_libraries(app1 lib)
3. 保留根目录的总解决方案
根目录的CMakeLists.txt可以保持不变,它依然负责生成包含所有项目的总解决方案:
cmake_minimum_required(VERSION 3.1) add_subdirectory(lib) add_subdirectory(app1) add_subdirectory(app2)
额外进阶:用CMake预设简化构建
如果你使用CMake 3.19及以上版本,可以在根目录添加CMakePresets.json,一键生成不同类型的解决方案,大幅简化操作:
{ "version": 3, "configurePresets": [ { "name": "all-projects", "displayName": "所有项目(总解决方案)", "description": "生成包含lib、app1、app2的完整解决方案", "binaryDir": "${sourceDir}/build/all", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" } }, { "name": "app1-only", "displayName": "仅构建App1", "description": "生成只包含app1和lib的独立解决方案", "sourceDir": "${sourceDir}/app1", "binaryDir": "${sourceDir}/build/app1", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" } }, { "name": "app2-only", "displayName": "仅构建App2", "description": "生成只包含app2和lib的独立解决方案", "sourceDir": "${sourceDir}/app2", "binaryDir": "${sourceDir}/build/app2", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" } } ] }
使用时只需要在命令行执行:
# 生成总解决方案 cmake --preset all-projects # 生成app1的独立解决方案 cmake --preset app1-only
效果验证
- 总解决方案:运行根目录CMake或
all-projects预设,得到包含所有组件的VS解决方案,每个app仅依赖lib,不会触发其他无关项目的构建; - 独立解决方案:运行app1目录的CMake或
app1-only预设,得到仅包含app1和lib的解决方案,完全独立于app2,完美符合你的需求。
内容的提问来源于stack exchange,提问作者Philipp
相关产品推荐
相关产品推荐

