23、生成器:Visual Studio生成器、Xcode生成器、Ninja、Makefile生成器、生成器特定设置
说到CMake,有个概念你绕不开——生成器(Generator)。说白了,CMake本身不编译代码,它是个“项目文件生成器”。你写一堆CMakeLists.txt,它帮你生成Visual Studio的.sln、Xcode的.xcodeproj,或者Ninja/Makefile的构建脚本。然后真正的编译工作,交给这些工具去干。
我个人习惯把生成器分成两类:IDE生成器和命令行生成器。前者生成的是“工程文件”,你打开IDE就能跑;后者生成的是“构建脚本”,你在终端里敲make或ninja就行。今天咱们就把这几个主流生成器挨个捋一遍。
Visual Studio生成器
Windows上做C++开发,Visual Studio是绕不过去的。CMake对VS的支持非常成熟,从VS 2010到VS 2022,每个版本都有对应的生成器名称。
常用的VS生成器有:
Visual Studio 16 2019—— 对应VS 2019Visual Studio 17 2022—— 对应VS 2022Visual Studio 15 2017—— 对应VS 2017
你可能会问:怎么指定用哪个?很简单,在cmake命令行里加 -G 参数:
cmake -G "Visual Studio 17 2022" -A x64 ..
这里 -A x64 指定的是架构。VS生成器支持 Win32、x64、ARM、ARM64 等。我在项目中遇到过一个问题:同事没加 -A,结果默认生成了32位工程,链接第三方64位库时死活过不去。嗯,这个坑踩过一次就记住了。
VS生成器还有个特点:它会生成 .sln 和一堆 .vcxproj 文件。你打开 .sln,所有目标(可执行文件、库、测试)都会出现在解决方案里,每个目标一个项目。调试、编译、部署,跟原生VS项目一模一样。
cmake --help 查看所有可用的生成器列表。CMake会自动检测已安装的VS版本。
Xcode生成器
macOS和iOS开发,Xcode是标配。CMake的Xcode生成器会生成 .xcodeproj 文件,你双击就能在Xcode里打开。
用法也很直接:
cmake -G Xcode ..
Xcode生成器有个特别的地方:它支持多架构构建。比如你想同时编译arm64和x86_64的库,可以在CMake里设置:
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")
然后Xcode生成器会生成一个包含两个架构的工程。你在Xcode里选择“Any Mac”或“Any iOS Simulator”,编译出来的就是通用二进制。我记得第一次用这个功能时,觉得“哇,真方便”——不用手动跑两次编译了。
不过要注意:Xcode生成器生成的工程文件比较大,尤其是项目规模上去之后。我曾经有个项目,CMake配置完生成出来的 .xcodeproj 有200多MB。嗯,这时候你可能要考虑用Ninja了。
Ninja生成器
Ninja是我个人最常用的生成器。它快,真的快。Ninja的设计哲学就是“快”——没有复杂的依赖解析,没有花哨的语法,就是纯纯的构建脚本。
用法:
cmake -G Ninja ..
Ninja生成器会生成一个 build.ninja 文件。你直接敲 ninja 就开始编译了。Ninja支持并行编译,默认会使用所有CPU核心。你想想看,一个大型项目,用Makefile可能要编译5分钟,Ninja可能3分钟就搞定了。
Ninja还有个好处:跨平台。Windows、macOS、Linux都能用。你只需要装好Ninja工具(pip install ninja 或者从官网下载),CMake就能用它生成构建脚本。
build.ninja 文件里的依赖信息。所以如果你手动修改了 build.ninja,CMake重新配置时会覆盖掉。别问我怎么知道的——我曾经手贱改过,然后被覆盖了。
Makefile生成器
Makefile生成器是CMake最传统的生成器。在Linux上,默认就是 Unix Makefiles。用法:
cmake -G "Unix Makefiles" ..
在Windows上,如果你装了MinGW或MSYS,也可以用 MinGW Makefiles 或 MSYS Makefiles。
Makefile生成器会生成一个 Makefile 文件。你敲 make 就开始编译。它支持 make -j4 并行编译,但说实话,在大型项目上,Makefile的依赖解析速度不如Ninja。我做过对比:一个包含500+源文件的项目,Makefile光解析依赖就要花几秒钟,Ninja几乎是瞬间。
不过Makefile生成器有个优点:几乎任何Unix-like系统都自带make工具,不需要额外安装。对于简单的项目,或者你只是想快速验证一下CMake配置,Makefile生成器完全够用。
生成器特定设置
每个生成器都有自己的“脾气”。CMake提供了一些变量,让你针对不同生成器做特殊配置。
| 变量名 | 作用 | 适用生成器 |
|---|---|---|
CMAKE_VS_PLATFORM_NAME |
指定VS平台(Win32/x64/ARM) | Visual Studio |
CMAKE_XCODE_ATTRIBUTE_* |
设置Xcode的build settings | Xcode |
CMAKE_NINJA_OUTPUT_DIR |
指定Ninja输出目录 | Ninja |
CMAKE_MAKE_PROGRAM |
指定make工具路径 | Makefile |
举个例子,在Xcode中你想关闭某个警告,可以这样写:
if(CMAKE_GENERATOR MATCHES "Xcode")
set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_INHIBIT_ALL_WARNINGS "YES")
endif()
在Visual Studio中,你想指定平台工具集:
if(CMAKE_GENERATOR MATCHES "Visual Studio")
set(CMAKE_VS_PLATFORM_TOOLSET "v143") # VS 2022的工具集
endif()
这些生成器特定设置,说白了就是让你“因地制宜”。同一个CMakeLists.txt,在不同平台上生成不同的配置,但逻辑保持一致。我在做跨平台项目时,经常用 CMAKE_GENERATOR 变量做条件判断,确保每个生成器都能输出最优的构建配置。
知识体系图
下面这张图总结了本章的核心内容,帮你快速理清生成器的分类和关系:
核心要点:
- IDE生成器(VS、Xcode)适合需要图形化调试和项目管理的场景
- 命令行生成器(Ninja、Makefile)适合CI/CD、服务器构建、追求编译速度的场景
- Ninja是目前编译速度最快的生成器,强烈推荐用于大型项目
- Makefile生成器兼容性最好,几乎任何Unix系统都能用
- 生成器特定设置让你“一套CMake,多平台适配”
好了,生成器这块就聊到这儿。你只要记住:CMake不编译,它只负责“翻译”——把你的CMakeLists.txt翻译成各种构建工具能理解的格式。选对生成器,能让你的开发效率翻倍。