15. CMake与IDE:生成Visual Studio/Xcode/CodeBlocks工程,CMAKE_GENERATOR的选择
说实话,很多刚接触CMake的朋友都会问一个问题:「CMake不是个构建工具吗?怎么还能生成IDE工程?」
嗯,这确实是CMake最强大的特性之一。它不直接编译代码,而是作为「构建系统的生成器」。你写一份CMakeLists.txt,它就能帮你生成Visual Studio的.sln文件、Xcode的.xcodeproj、或者CodeBlocks的.cbp文件。说白了,CMake是个「万能适配器」。
15.1 为什么需要生成IDE工程?
我在项目中遇到过好几次这样的情况:团队里有人用VS,有人用CLion,还有人用Xcode。如果每个人都手写一份工程文件,那维护成本简直不敢想。
CMake的解决方案很简单——你只维护一份CMakeLists.txt,剩下的交给CMAKE_GENERATOR。
核心思想:CMake是「元构建系统」,它不直接编译,而是生成其他构建系统能识别的工程文件。
15.2 CMAKE_GENERATOR 是什么?
CMAKE_GENERATOR 是一个CMake变量,它决定了CMake会生成哪种格式的工程文件。你可以把它理解成「输出格式选择器」。
常见的生成器有这些:
| 生成器名称 | 目标IDE/工具 | 适用平台 | 生成的文件 |
|---|---|---|---|
| Visual Studio 17 2022 | Visual Studio 2022 | Windows | .sln + .vcxproj |
| Visual Studio 16 2019 | Visual Studio 2019 | Windows | .sln + .vcxproj |
| Xcode | Xcode | macOS | .xcodeproj |
| CodeBlocks - Ninja | CodeBlocks | 跨平台 | .cbp |
| CodeBlocks - Unix Makefiles | CodeBlocks | Linux/macOS | .cbp |
| Ninja | Ninja(命令行) | 跨平台 | build.ninja |
| Unix Makefiles | GNU Make | Linux/macOS | Makefile |
小提示:在Windows上,如果你不指定生成器,CMake会自动检测已安装的Visual Studio版本。我个人习惯在命令行里显式指定,避免踩坑。
15.3 如何指定生成器?
有两种方式:
方式一:命令行指定
# 生成Visual Studio 2022工程
cmake -B build -G "Visual Studio 17 2022"
# 生成Xcode工程
cmake -B build -G "Xcode"
# 生成CodeBlocks工程(使用Ninja作为底层构建工具)
cmake -B build -G "CodeBlocks - Ninja"
方式二:在CMakeLists.txt中设置(不推荐)
# 不推荐这样做,会降低跨平台性
set(CMAKE_GENERATOR "Visual Studio 17 2022" CACHE INTERNAL "")
注意:在CMakeLists.txt里硬编码生成器是个坏习惯。你想想看,如果别人在Linux上运行你的CMakeLists.txt,却强制要求生成VS工程,那不就报错了吗?
15.4 生成器与平台架构
这里有个容易忽略的点——生成器还决定了目标架构。比如Visual Studio生成器可以指定是x86还是x64:
# 生成64位工程
cmake -B build -G "Visual Studio 17 2022" -A x64
# 生成32位工程
cmake -B build -G "Visual Studio 17 2022" -A Win32
对于Xcode生成器,你可以指定架构:
# 生成iOS模拟器工程
cmake -B build -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="x86_64"
# 生成真机工程
cmake -B build -G "Xcode" -DCMAKE_OSX_ARCHITECTURES="arm64"
15.5 生成器与构建工具的关系
你可能注意到了,像CodeBlocks - Ninja这样的生成器名字里有两个部分。前半部分是IDE,后半部分是底层构建工具。
为什么会这样?
因为IDE工程文件只是「壳」,真正干活的是底层的构建工具。CodeBlocks本身不编译代码,它调用Ninja或Make来干活。Visual Studio也一样,它调用MSBuild。
我画了张图帮你理解这个关系:
从这张图你能看明白:CMake是「翻译官」,它把你的构建需求翻译成不同IDE能理解的语言。但真正干活的,还是底层的构建工具。
15.6 如何查看可用的生成器?
如果你不确定当前系统支持哪些生成器,可以用这个命令:
cmake --help
输出里会列出所有可用的生成器。比如在Windows上,你可能会看到:
Generators
Visual Studio 17 2022 = Generates Visual Studio 2022 project files.
Visual Studio 16 2019 = Generates Visual Studio 2019 project files.
Visual Studio 15 2017 = Generates Visual Studio 2017 project files.
Ninja = Generates build.ninja files.
Unix Makefiles = Generates standard UNIX makefiles.
CodeBlocks - Ninja = Generates CodeBlocks project files (Ninja).
CodeBlocks - Unix Makefiles = Generates CodeBlocks project files (Unix Makefiles).
小技巧:在Windows上,如果你装了多个VS版本,可以用-G参数自由切换。我经常在VS2019和VS2022之间来回切,测试兼容性。
15.7 生成器与预设(Presets)
CMake 3.19之后引入了预设(Presets)功能,可以让你把常用的生成器配置存起来。我个人非常喜欢这个特性。
在项目根目录创建CMakePresets.json:
{
"version": 3,
"configurePresets": [
{
"name": "vs2022-debug",
"displayName": "VS2022 Debug",
"generator": "Visual Studio 17 2022",
"architecture": "x64",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "xcode-release",
"displayName": "Xcode Release",
"generator": "Xcode",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
]
}
然后一行命令就能切换:
# 使用VS2022 Debug预设
cmake --preset vs2022-debug
# 使用Xcode Release预设
cmake --preset xcode-release
15.8 避坑指南
我曾经在跨平台项目上踩过一个坑:在Windows上生成VS工程后,直接双击.sln文件打开,然后编译——一切正常。但当我用命令行cmake --build时,却报错了。
原因是什么?
因为VS工程默认使用MSBuild,而MSBuild需要指定平台工具集。如果你在CMake里没设置CMAKE_GENERATOR_TOOLSET,它可能默认用了一个不存在的工具集版本。
解决方案:
# 显式指定工具集
cmake -B build -G "Visual Studio 17 2022" -T v143
另一个常见问题是生成器缓存。如果你第一次用-G "Visual Studio 16 2019"生成了工程,第二次想换成-G "Ninja",但忘了删掉build目录——CMake会报错说生成器不匹配。
重要:切换生成器时,一定要清空build目录!否则CMake会拒绝执行。我建议养成习惯:切换生成器前先rm -rf build或rd /s build。
15.9 生成器选择策略
说了这么多,到底该怎么选?我总结了几条经验:
- Windows + Visual Studio用户:选
Visual Studio 17 2022,调试体验最好 - macOS + Xcode用户:选
Xcode,原生支持Apple Silicon和iOS - Linux开发者:选
Ninja,编译速度比Make快很多 - 跨平台IDE用户:选
CodeBlocks - Ninja,兼顾IDE体验和编译速度 - CI/CD环境:选
Ninja或Unix Makefiles,轻量无依赖
你想想看,如果团队里有人用VS、有人用CLion、还有人用VSCode,那最好的策略就是每个人各自指定自己想要的生成器。CMakeLists.txt里只写平台无关的逻辑,生成器的选择交给开发者自己。
嗯,这就是CMake的哲学——一次编写,到处生成。
本章要点回顾:
- CMAKE_GENERATOR 决定了CMake输出哪种IDE工程文件
- 常见生成器:Visual Studio、Xcode、CodeBlocks、Ninja、Unix Makefiles
- 生成器可以通过
-G命令行参数指定,不要在CMakeLists.txt里硬编码 - 生成器还影响目标架构(x86/x64/arm64)和平台工具集
- 切换生成器时必须清空build目录
- CMake Presets可以简化生成器的管理
公众号:蓝海资料掘金营,微信deep3321