先给大家讲个真事。
前一阵有同事给我发来一个工程:他照着网上的 CMake 示例写了一整个下午,cmake 终于不报错了,但打开输出目录一看:既没有 .sln,也没有 .exe。他特别委屈地问我:“编译到底生成了什么?我的 VS 项目在哪?”我看了眼他的命令记录就明白了——他只执行了 cmake,没有执行真正的编译命令,也没有在 Visual Studio 里点生成。
很多人对 CMake 的第一印象是“编译工具”,但它本质上是另一回事:CMake 是一个构建系统生成器。它读你写的 CMakeLists.txt,然后帮你翻译成当前平台上能用的构建脚本或工程文件。在 Linux/macOS 上它可能生成 Makefile 或 Ninja 文件,在 Windows 上它可能生成 Visual Studio 工程,之后你还要再用真正的编译器去“构建”一次。把这一步想通,很多“CMake 都成功了但没有 exe”的问题就迎刃而解。
这篇文章不打算讲成面面俱到的官方文档,而是按我平时实际遇到的高频问题来讲:环境准备、第一个 exe、链接不到 main、交叉编译时目标架构报错、MPI 和第三方库引入,以及 CMake 自己运行时崩溃的排查方法。适合刚接触 CMake、想快速把项目跑起来的人,也适合被各种诡异报错折磨到怀疑人生的朋友。
1. CMake不是编译器:它只是帮你生成“下一步命令”的中转站
1.1 从源码到exe中间其实隔了两次“编译”
很多入门资料会说“CMake 能生成可执行文件”,这个说法其实省略了关键步骤。真实的流程是:
- 你写源代码:
main.cpp、utils.cpp、头文件等。 - CMake 读取
CMakeLists.txt,进行配置和生成,产出 Makefile / Ninja / Visual Studio 工程。 - 你调用底层构建工具(make、ninja、MSBuild),它对源文件挨个编译,最后链接出 exe 或 so/a。
CMake 管不到“编译器到底怎么把所有文件变成 exe”这一步,它只负责生成合适的“施工图”。你真正的编译,是在第 3 步完成的。
所以,当有人问我“cmake 编译成功但是没有 exe”的时候,我第一反应永远是:你可能没有执行第二步。CMake 的配置阶段成功,不代表你的代码编译链接过了。命令行下必须再执行一次构建命令,如果是 Visual Studio,则要重新打开生成的 .sln,然后在菜单里点“生成解决方案”。
1.2 生成器决定了你会拿到什么文件
CMake 在配置时要选择一个生成器(generator)。常见的生成器有:
| 生成器 | 典型产物 | 适用场景 |
|---|---|---|
| Unix Makefiles | Makefile | Linux/macOS 下默认 |
| Ninja | build.ninja | 各种平台,追求编译速度 |
| Visual Studio 17 2022 | 若干 .sln 和 .vcxproj | Windows + VS 用户 |
| MinGW Makefiles | Makefile + MinGW 工具 | Windows 下使用 MinGW |
如果完全不加参数,CMake 会根据系统默认选择生成器。但很多 Windows 新手是装了 CMake,又装了 Visual Studio,这时候 CMake 默认生成的极可能是 Visual Studio 项目。于是在你的 build 目录里会出现 项目名.sln,打开它再点生成,exe 才会出现在 Debug/ 或 Release/ 子目录。
另一个常见误区是:在命令行里执行完 cmake -S . -B build 后,以为任务完成了。实际上此时的 build 目录只有“工程文件”,根本没有完成真正的编译。正确的做法是继续执行:
bash复制cmake --build build
如果你用了多个配置,比如 Visual Studio 生成器,最好再指定配置:
bash复制cmake --build build --config Release
Release 下的 exe 通常就在 build/Release/ 里。我之前见过不少朋友把 build/ 目录翻了个底朝天,就是找不到 exe,其实是忽略了多配置生成器会把不同配置放在不同子目录这一点。
1.3 “配置成功”和“编译成功”不是一回事
CMake 的报错分为两类:一类是配置阶段报错,比如 CMakeLists.txt 里写了不支持的语法或找不到依赖;另一类是构建阶段报错,比如你代码里写错了变量名、链接不到某些库。
如果你运行:
bash复制cmake -S . -B build
这一步结束但不报错,它只代表 CMake “理解了你的工程结构”,并成功生成了构建脚本。你的代码有没有语法问题,有没有重复定义 main,CMake 一概不知。想要知道代码是否真的能编译,必须看:
bash复制cmake --build build
的输出。如果你在 Visual Studio 里使用“打开文件夹”方式打开 CMake 工程,也需要等 VS 的“CMake 配置”完成之后,再点编译器工具栏里的“生成”按钮。只看“CMake 配置成功”就以为大功告成,是很多人一开始最容易踩的坑。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 下载和安装阶段容易踩的版本坑:从PATH到“CMake 3.26 is required”
2.1 下载安装:别在系统目录里反复覆盖旧版本
CMake 的安装其实非常简单,但我说句实在话:很多软件问题,都出在安装时的“想当然”上。
最稳妥的方式是到 CMake 官网下载官方二进制包。Windows 用户一般下载 .msi 安装包,安装时记得勾选“Add CMake to the system PATH for all users”;macOS 用户可以直接 brew install cmake;Linux 用户如果发行版仓库里的版本太老,也可以下载官方 .tar.gz 包到 /opt 或 $HOME 下,解压后把 bin 目录加进 PATH。
不要图省事,把新版 CMake 文件直接原样覆盖到旧版目录里。因为你不知道旧版本是否还有共享库或残留组件留在原地,后面我会专门讲一个 CMake 运行时的崩溃案例,原因就是这类混装。宁可多花两分钟下载新包,也不要“覆盖式升级”。
2.2 命令行提示找不到cmake,或者找到的是另一个cmake
安装完 CMake,在终端输入:
bash复制cmake --version
如果提示“command not found”或“不是内部或外部命令”,先检查 PATH。Windows 下安装时如果没有勾选加入 PATH,就需要手动去“
