CMake 学习指南三CMake 与 Visual Studio 协作 文档系列说明本文是CMake 学习指南系列的第三篇深入讲解 CMake 与 Visual Studio 的协作机制。系列文档目录 第一篇CMake 基础概念与快速入门 第二篇CMake 项目构建实战第三篇CMake 与 Visual Studio 协作当前文档 第四篇CMake 配置项详解 第五篇CMake 语法深入 第六篇跨平台编译与 CMake 第七篇CMake 高级技巧与最佳实践前置知识阅读本文前请确保已掌握第一篇和第二篇中的基础概念。推荐阅读顺序新手入门第一篇 → 第二篇 → 第三篇深入理解第四篇 → 第五篇 → 第六篇进阶提升第七篇目录1. VS 为什么需要 CMake2. VS 和 CMake 的关系3. Visual Studio 使用 CMake 的两种方式4. 方式一VS 直接打开 CMake 项目5. 方式二CMake 生成 .sln 文件6. 配置阶段 vs 编译阶段7. 什么时候需要重新生成 .sln8. VS 的 CMake 集成机制9. 两种方式对比与选择10. 总结与下一步1. VS 为什么需要 CMake1.1 VS 本身就能编译为什么还要 CMakeVS 确实可以独立完成编译不需要 CMake。你完全可以打开 VS → 新建项目 → 选择 C 项目模板写代码 → 按 F5 → 编译运行全程不需要 CMake。1.2 但 VS 的项目文件是平台绑定的VS 的项目文件.sln/.vcxproj只能在 Windows VS 环境下使用┌─────────────────────────────────────────────────────────┐ │ VS 项目文件的局限性 │ ├─────────────────────────────────────────────────────────┤ │ │ │ MyProject.sln / MyProject.vcxproj │ │ │ │ │ ▼ │ │ 只能在 Windows Visual Studio 下打开和编译 │ │ │ │ ❌ Linux 上无法使用 │ │ ❌ macOS 上无法使用 │ │ ❌ CI/CD 服务器上不方便通常用 Linux │ │ ❌ 其他 IDECLion、Qt Creator无法打开 │ │ │ └─────────────────────────────────────────────────────────┘1.3 CMake 解决跨平台问题┌─────────────────────────────────────────────────────────┐ │ CMake 的跨平台能力 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 一份 CMakeLists.txt │ │ │ │ │ ├──► Windows VS → 生成 .sln → 编译 │ │ ├──► Linux GCC → 生成 Makefile → 编译 │ │ ├──► macOS Clang → 生成 Makefile → 编译 │ │ └──► CI/CD (Linux) → 生成 Makefile → 编译 │ │ │ │ 同一份代码同一份配置所有平台都能编译 │ │ │ └─────────────────────────────────────────────────────────┘1.4 实际场景场景团队协作 ───────────────── 小明用 Windows VS 开发 小李用 Linux VSCode 开发 CI 服务器用 Linux 自动编译 没有 CMake 小明维护 .sln 文件 小李维护 Makefile CI 服务器再维护一套 Makefile 三套配置改一个要同步三个 → 灾难 有了 CMake 所有人共用一份 CMakeLists.txt 改一次所有平台生效 → 省心2. VS 和 CMake 的关系2.1 核心关系CMake 是图纸VS 是施工队┌─────────────────────────────────────────────────────────┐ │ CMake 和 VS 的关系 │ ├─────────────────────────────────────────────────────────┤ │ │ │ CMake 建筑设计师出图纸 │ │ ───────────────────────── │ │ - 画图纸CMakeLists.txt │ │ - 图纸可以给任何施工队用 │ │ │ │ VS 施工队按图纸施工 │ │ ───────────────────── │ │ - 拿到图纸.sln 文件 │ │ - 按图纸施工编译代码 │ │ - 但只能按自己的格式施工只能读 .sln │ │ │ │ CMake 的作用把通用图纸翻译成 VS 能看懂的施工图 │ │ ───────────────────────────────────────── │ │ CMakeLists.txt ──► CMake 翻译 ──► .sln 文件 │ │ │ └─────────────────────────────────────────────────────────┘2.2 分工明确┌─────────────────────────────────────────────────────────┐ │ 分工对比 │ ├──────────────────┬──────────────────────────────────────┤ │ CMake 做的 │ VS 做的 │ ├──────────────────┼──────────────────────────────────────┤ │ 读取 CMakeLists.txt│ 读取 .sln 文件 │ │ 检测编译器 │ 调用 MSVC 编译器 │ │ 查找依赖库 │ 编译 .cpp → .obj │ │ 设置编译选项 │ 链接 .obj → .exe │ │ 生成 .sln 文件 │ 提供调试功能 │ │ ❌ 不编译代码 │ ❌ 不生成 .sln需要 CMake │ └──────────────────┴──────────────────────────────────────┘2.3 两种关系模式┌─────────────────────────────────────────────────────────┐ │ VS 和 CMake 的两种协作模式 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 模式一CMake 在 VS 内部VS 2019 │ │ ───────────────────────────── │ │ VS 内置 CMake 支持 │ │ 用户打开 CMakeLists.txt → VS 自动调用 CMake → 编译 │ │ 用户感知不到 CMake 的存在 │ │ │ │ 模式二CMake 在 VS 外部传统方式 │ │ ───────────────────────────── │ │ 用户手动运行 CMake → 生成 .sln → VS 打开 .sln → 编译 │ │ CMake 和 VS 是独立的两个步骤 │ │ │ └─────────────────────────────────────────────────────────┘2.4 一句话总结CMake 负责生成构建文件VS 负责编译代码。CMake 不依赖 VSVS 也不依赖 CMake。但两者结合可以让你在 Windows 上享受 VS 的强大功能同时保持项目的跨平台能力。3. Visual Studio 使用 CMake 的两种方式在 Windows 上使用 CMake 开发 VS 项目主要有两种方式┌─────────────────────────────────────────────────────────┐ │ VS 使用 CMake 的两种方式 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 方式一VS 直接打开 CMake 项目 │ │ ───────────────────────────── │ │ CMakeLists.txt ──► VS 自动检测并配置 ──► 编译运行 │ │ VS 内部管理 CMake无需手动操作 │ │ │ │ 方式二命令行生成 .sln再用 VS 打开 │ │ ───────────────────────────── │ │ cmake -B build -G Visual Studio 17 2022 │ │ ↓ │ │ 生成 build/MyProject.sln │ │ ↓ │ │ VS 打开 .sln → 编译 │ │ │ └─────────────────────────────────────────────────────────┘4. 方式一VS 直接打开 CMake 项目4.1 工作流程这是VS 2019 及以后版本推荐的方式VS 原生支持 CMake。┌─────────────────────────────────────────────────────────┐ │ VS 直接打开 CMake 项目 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 1. 打开 VS → 文件 → 打开 → 文件夹 │ │ │ │ │ ▼ │ │ 2. 选择包含 CMakeLists.txt 的文件夹 │ │ │ │ │ ▼ │ │ 3. VS 自动检测 CMakeLists.txt │ │ │ │ │ ▼ │ │ 4. VS 自动运行 CMake 配置 │ │ │ │ │ ▼ │ │ 5. 按 F5 直接编译运行 │ │ │ └─────────────────────────────────────────────────────────┘4.2 优点无需手动操作VS 自动处理 CMake 配置配置简单打开文件夹即可VS 集成好IntelliSense、调试、断点全部可用4.3 缺点需要 VS 2019旧版本不支持配置项较少VS 的 CMake 配置界面功能有限4.4 示例# 1. 项目结构MyProject/ ├── CMakeLists.txt ├── src/ │ ├── main.cpp │ └── hello.cpp# 2. 打开 VS# 文件 → 打开 → 文件夹 → 选择 MyProject# 3. VS 自动配置并显示 CMake 输出# 输出窗口会显示# CMake generation started.# CMake generation finished successfully.5. 方式二命令行生成 .sln再用 VS 打开5.1 工作流程这是传统方式通过命令行生成 VS 项目文件再用 VS 打开。┌─────────────────────────────────────────────────────────┐ │ 命令行生成 .sln再用 VS 打开 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 1. 打开命令行CMD 或 PowerShell │ │ │ │ │ ▼ │ │ 2. 运行 cmake 生成 .sln │ │ cmake -B build -G Visual Studio 17 2022 │ │ │ │ │ ▼ │ │ 3. CMake 生成 build/MyProject.sln │ │ │ │ │ ▼ │ │ 4. 用 VS 打开 .sln 文件 │ │ │ │ │ ▼ │ │ 5. 在 VS 中编译、调试、运行 │ │ │ └─────────────────────────────────────────────────────────┘5.2 生成 .sln 的命令# 指定 VS 版本需要 VS 已安装cmake-Bbuild-GVisual Studio 17 2022cmake-Bbuild-GVisual Studio 16 2019cmake-Bbuild-GVisual Studio 15 2017# 不指定 -GCMake 自动选择最佳生成器cmake-Bbuild5.3 生成的目录结构MyProject/ ├── CMakeLists.txt ├── src/ │ ├── main.cpp │ └── hello.cpp └── build/ ├── MyProject.sln ← 解决方案文件 ├── MyProject.vcxproj ← 项目文件 ├── CMakeCache.txt ← CMake 缓存 └── CMakeFiles/ ← CMake 中间文件5.4 优点兼容所有 VS 版本包括旧版本完全控制可以指定生成器、配置选项适合 CI/CD命令行操作可自动化5.5 缺点需要手动运行命令行多一步操作.sln 是自动生成的修改 CMakeLists.txt 后需要重新生成6. 配置阶段 vs 编译阶段6.1 核心概念┌─────────────────────────────────────────────────────────┐ │ CMake 的两个阶段 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 阶段一配置阶段Configuration │ │ ───────────────────────────── │ │ 输入CMakeLists.txt 环境信息 │ │ 做什么 │ │ - 读取 CMakeLists.txt │ │ - 检测编译器、库、依赖 │ │ - 解析所有配置指令 │ │ - 生成 .sln / Makefile 等构建文件 │ │ 输出构建文件.sln / Makefile / .ninja │ │ CMake 参与✅ 这是 CMake 的工作 │ │ │ │ 阶段二编译阶段Build │ │ ───────────────────────────── │ │ 输入构建文件 源代码 │ │ 做什么 │ │ - 读取构建文件中的指令 │ │ - 调用编译器MSVC编译源代码 │ │ - 链接生成可执行文件 │ │ 输出可执行文件.exe │ │ CMake 参与❌ 完全不参与这是 VS/MSBuild 的工作 │ │ │ └─────────────────────────────────────────────────────────┘6.2 关键认知编译阶段与 CMake 无关这是最重要的认知┌─────────────────────────────────────────────────────────┐ │ 编译阶段CMake 完全不参与 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 当你点击生成或运行 cmake --build 时 │ │ │ │ ❌ CMake 不会被调用 │ │ ❌ CMakeLists.txt 不会被读取 │ │ ❌ CMake 不知道你在编译什么 │ │ │ │ ✅ VS 调用 MSBuild │ │ ✅ MSBuild 读取 .sln 文件 │ │ ✅ MSBuild 调用 MSVC 编译器 │ │ ✅ MSVC 编译 .cpp → .obj → 链接 → .exe │ │ │ │ 整个编译过程CMake 完全不在场 │ │ │ └─────────────────────────────────────────────────────────┘6.3 在 VS 中如何体现┌─────────────────────────────────────────────────────────┐ │ VS 中的配置和编译 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 方式一VS 直接打开 CMake │ │ ───────────────────────── │ │ 打开文件夹 → VS 自动配置 → 按 F5 编译 │ │ ↓ ↓ ↓ │ │ 检测到 CMakeLists.txt 运行 CMake 配置 编译源代码 │ │ (CMake 参与) (CMake 不参与) │ │ │ │ 方式二命令行生成 .sln │ │ ───────────────────────── │ │ cmake → 生成 .sln → VS 打开 → 编译 │ │ ↓ ↓ ↓ ↓ │ │ 配置阶段 生成构建文件 加载项目 编译源代码 │ │ (CMake) (VS) (CMake 不参与) │ │ │ └─────────────────────────────────────────────────────────┘6.4 配置阶段做了什么# CMakeLists.txt 中的配置指令 cmake_minimum_required(VERSION 3.10) project(MyProject VERSION 1.0.0) # 这些指令在配置阶段执行 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_executable(MyApp src/main.cpp) # 配置阶段结束时生成 .sln 文件 # .sln 文件描述了编译哪些文件、用什么选项、怎么链接6.5 编译阶段做了什么# 编译阶段执行的实际命令以 MSVC 为例# 这些命令由 MSBuild 自动调用与 CMake 无关cl.exe /c /std:c17 /EHsc /Iinclude src\main.cpp link.exe main.obj /OUT:MyApp.exe7. 什么时候需要重新生成 .sln7.1 需要重新生成的情况┌─────────────────────────────────────────────────────────┐ │ 什么时候需要重新生成 .sln │ ├─────────────────────────────────────────────────────────┤ │ │ │ 1. 修改了 CMakeLists.txt │ │ ───────────────────── │ │ - 添加/删除源文件 │ │ - 添加/删除库 │ │ - 修改编译选项 │ │ - 修改项目配置 │ │ │ │ 2. 新增了源文件使用 file(GLOB) 时 │ │ ───────────────────── │ │ - 新增 .cpp/.h 文件 │ │ - 但使用 CONFIGURE_DEPENDS 时自动处理 │ │ │ │ 3. 更换了编译器或工具链 │ │ ───────────────────── │ │ - 从 MSVC 换成 MinGW │ │ - 更换 VS 版本 │ │ │ │ 4. 修改了 CMake 缓存变量 │ │ ───────────────────── │ │ - 修改 CMAKE_BUILD_TYPE │ │ - 修改 CMAKE_PREFIX_PATH │ │ │ └─────────────────────────────────────────────────────────┘7.2 不需要重新生成的情况┌─────────────────────────────────────────────────────────┐ │ 什么时候不需要重新生成 .sln │ ├─────────────────────────────────────────────────────────┤ │ │ │ 1. 只修改了源代码.cpp/.h │ │ ───────────────────── │ │ - 修改函数实现 │ │ - 修改变量值 │ │ - 修改注释 │ │ - 原因.sln 里记录的是编译哪些文件不是文件内容 │ │ │ │ 2. 只切换 Debug/Release 配置 │ │ ───────────────────── │ │ - VS 中直接切换构建类型 │ │ - 不需要重新运行 CMake │ │ │ │ 3. 只修改了代码逻辑 │ │ ───────────────────── │ │ - 优化算法 │ │ - 修复 bug │ │ │ └─────────────────────────────────────────────────────────┘7.3 实际演示# 初始配置cmake-Bbuild-GVisual Studio 17 2022# 情况1修改 CMakeLists.txt添加新源文件# 修改 CMakeLists.txt → 需要重新配置cmake-Bbuild# 重新生成 .sln# 情况2只修改 main.cpp 中的代码# 不需要重新配置直接编译cmake--buildbuild# 此时 CMake 完全不参与MSBuild 直接编译# 情况3修改 CMakeLists.txt 中的编译选项# 需要重新配置cmake-Bbuild# 重新生成# 情况4切换 Debug/Release# 不需要重新配置cmake--buildbuild--configRelease8. VS 的 CMake 集成机制8.1 VS 如何检测 CMake 项目┌─────────────────────────────────────────────────────────┐ │ VS 检测 CMake 项目的机制 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 1. VS 扫描文件夹寻找 CMakeLists.txt │ │ │ │ │ ▼ │ │ 2. 找到后VS 自动创建 CMakeSettings.json │ │ │ │ │ ▼ │ │ 3. VS 根据配置运行 CMake │ │ │ │ │ ▼ │ │ 4. VS 读取 CMake 输出获取项目信息 │ │ │ │ │ ▼ │ │ 5. VS 显示项目结构提供 IntelliSense │ │ │ └─────────────────────────────────────────────────────────┘8.2 CMakeSettings.jsonVS 专用配置文件{configurations:[{name:x64-Debug,generator:Visual Studio 17 2022,configurationType:Debug,buildRoot:${projectDir}\\out\\build\\${name},installRoot:${projectDir}\\out\\install\\${name},cmakeCommandArgs:,buildCommandArgs:,ctestCommandArgs:,inheritEnvironments:[msvc_x64]},{name:x64-Release,generator:Visual Studio 17 2022,configurationType:Release,buildRoot:${projectDir}\\out\\build\\${name},installRoot:${projectDir}\\out\\install\\${name},cmakeCommandArgs:,buildCommandArgs:,ctestCommandArgs:,inheritEnvironments:[msvc_x64]}]}8.3 VS 的 CMake 输出当 VS 配置 CMake 项目时输出窗口会显示1 CMake generation started for configuration: x64-Debug. 1 Command line: C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe -S D:\MyProject -B D:\MyProject\out\build\x64-Debug -G Visual Studio 17 2022 -A x64 -DCMAKE_CONFIGURATION_TYPESDebug 1 -- The CXX compiler identification is MSVC 19.35.0 1 -- Detecting CXX compiler ABI info 1 -- Detecting CXX compiler ABI info - done 1 -- Check for working CXX compiler: ... - works 1 -- Configuring done 1 -- Generating done 1 -- Build files have been written to: D:/MyProject/out/build/x64-Debug 1 CMake generation finished.8.4 VS 中的 CMake 操作┌─────────────────────────────────────────────────────────┐ │ VS 中的 CMake 操作 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 菜单栏 │ │ ──────── │ │ 项目 → CMake 配置 │ │ 项目 → CMake 缓存 → 删除缓存 │ │ 项目 → CMake 缓存 → 重新生成 │ │ │ │ 工具栏 │ │ ──────── │ │ [x64-Debug ▼] [▶ 启动] [全部生成] │ │ │ │ │ └─ 切换配置、启动调试、编译 │ │ │ │ 右键菜单 │ │ ──────── │ │ 右键 CMakeLists.txt → │ │ - 重新配置 CMake │ │ - 打开 CMake 设置 │ │ - 在终端中打开 │ │ │ └─────────────────────────────────────────────────────────┘9. 两种方式对比与选择9.1 对比表格特性方式一VS 直接打开 CMake方式二命令行生成 .sln VS 打开操作步骤打开文件夹即可命令行 打开 .sln跨平台✅ 一份 CMakeLists.txt✅ 一份 CMakeLists.txt需要 VS 2019✅✅任一 VS 版本均可但推荐新版需要 CMake✅✅适合 CI/CD✅✅命令行更易自动化适合场景新项目、快速开发需要精细控制、CI/CD9.2 选择建议┌─────────────────────────────────────────────────────────┐ │ 如何选择 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 如果你是 │ │ ────────── │ │ • VS 2019/2022 用户想快速开始 │ │ → 方式一VS 直接打开 CMake 项目 │ │ │ │ • 需要精细控制构建过程或使用 CI/CD │ │ → 方式二命令行生成 .sln再用 VS 打开 │ │ │ │ • 团队协作需要统一的构建配置 │ │ → 方式一/二通过 CMakeLists.txt 统一管理 │ │ │ └─────────────────────────────────────────────────────────┘10. 总结与下一步10.1 本篇核心要点✅VS 本身不需要 CMake但 CMake 让项目跨平台✅CMake 是图纸VS 是施工队分工明确✅方式一VS 直接打开 CMake 项目自动配置适合快速开发✅方式二命令行生成 .sln再用 VS 打开适合 CI/CD✅配置阶段CMake 参与生成 .sln✅编译阶段CMake 完全不参与VS/MSBuild 独立工作✅重新生成 .sln修改 CMakeLists.txt 或新增文件时需要✅VS 集成CMakeSettings.json 控制 VS 的 CMake 配置10.2 常见问题Q1修改 CMakeLists.txt 后VS 会自动重新配置吗方式一会自动检测并重新配置方式二需要手动重新运行 cmakeQ2可以在 VS 中修改 CMakeLists.txt 吗可以VS 支持编辑 CMakeLists.txt且有语法高亮Q3生成的 .sln 文件可以手动修改吗可以但下次运行 cmake 时会被覆盖Q4如何切换 Debug/Release方式一VS 工具栏选择方式二VS 解决方案配置管理器Q5编译时 CMake 在做什么什么都不做编译阶段 CMake 完全不参与是 VS/MSBuild 在调用编译器。10.3 下一步学习你已经掌握了 CMake 与 VS 的协作机制接下来可以阅读第四篇[CMake 配置项详解]学习项目基本配置编译选项配置构建类型配置路径配置依赖库配置 提示建议你实际尝试两种方式体验它们的区别。特别是方式一VS 直接打开 CMake 项目这是现代 VS 开发的最佳实践。如果你在阅读过程中遇到问题可以参考系列中的其他文档想复习 CMake 基础→ 第一篇想学习项目构建→ 第二篇想了解所有配置项→ 第四篇想深入学习语法→ 第五篇