CMake 入门教程之一
大纲
前言
本文将介绍 CMake 是什么,并使用 CMake 编译第一个 C/C++ 项目。
CMake 基本概念
什么是 CMake
CMake 是用于构建、测试和软件打包的开源跨平台工具。
为什么要学习 CMake
- 企业项目:不管是构建 Linux 程序还是自动化构建 VS 程序,业内大量公司都在使用 CMake。
- 开源项目:QT、OpenCV、GoogleTest、KDE、OGRE、Android NDK、鸿蒙 ETS NDK 等知名开源项目都使用了 CMake。
- 职业发展:CMake 适用于跨平台自动化构建和部署、持续集成、测试驱动开发、自动化单元测试等场景。
为什么要选用 CMake
为什么需要一个好的构建系统
- 想避免硬编码路径
- 需要在多台计算机上构建一个包
- 想使用 CI(持续集成)
- 需要支持不同的操作系统
- 想支持多个编译器
- 想使用 IDE,但不是所有情况
- 想描述程序的逻辑结构,而不是标志和命令
- 想使用库
- 想使用其他工具来帮助编写代码,比如
ProtoBuf
- 想使用单元测试
为什么需要持续集成
- 每次集成都通过自动化的制造(包括提交、发布、自动化测试)来验证,准确地发现集成错误
- 快速错误,每完成一点更新,就集成到主干,可以快速发现错误,定位错误也比较容易
- 各种不同的更新主干,如果不经常集成,会导致集成的成本变大
- 让产品可以快速地通过,同时保持关键测试合格
- 自动化测试,只要有一个测试用例不通过就不能集成
- 集成并不能删除发现的错误,但可以让它们很容易被发现和改正
为什么是 CMake
- CMake 的特性
- 自动搜索可能需要的程序、库和头文件的能力
- 独立的构建目录,可以安全清理
- 支持创建复杂的自定义命令,例如
qt moc uic
- 配置时选择可选组件的能力
- 从简单的文本文件(CMakeLists.txt)自动生成工作区和项目的能力
- 在静态和共享构建之间轻松切换的能力
- 在大多数平台上自动生成文件依赖项,并支持并行构建
- 每个 IDE 都支持 CMake( CMake 支持几乎所有 IDE)
- 使用 CMake 的软件包比任何其他系统都多
- CMake 的特性
CMake 的工作原理
编译第一个 CMake 项目
- 项目的目录结构
1 | first_cmake |
first_cmake.cpp
源文件
1 |
|
CMakeLists.txt
配置文件
1 | # 指定 CMake 版本 |
- 执行 CMake 编译
1 | # 配置项目,生成构建文件(例如 Makefile 或 Ninja 文件) |
1 | - 参数说明 |
- 上述两个 CMake 命令的功能可以分为几部分:
- 调用生成的构建系统:
- 如果之前生成的是 Makefile,它将调用
make
。 - 如果生成的是 Ninja 构建系统,它将调用
ninja
。
- 如果之前生成的是 Makefile,它将调用
- 编译项目:
- 它将编译项目中的源代码,并生成可执行文件、库等目标。
- 自动检测编译工具:
cmake --build
会根据生成的构建系统(Makefile、Ninja 等)来自动使用正确的工具进行构建,而不需要手动调用make
或ninja
。
- 调用生成的构建系统:
提示
通过 cmake --build build
,可以避免使用特定的生成器工具(例如 make
或 ninja
),并保持跨平台的一致性。
使用指定的 C/C++ 编译器
在使用 CMake 编译 C/C++ 项目时,CMake 会自动根据不同的操作系统类型来调用对应的 C/C++ 编译器,比如:
Linux 操作系统
:使用gcc
、g++
、clang
编译器。Windows 操作系统
:使用 Microsoft Visual C++ 编译器(简称 MSVC),提供了cl.exe
编译和link.exe
链接等命令行工具。
在 Windows 操作系统上,如果不是在 Developer Command Prompt for Visual Studio
开发者命令提示符窗口内执行生成构建文件的 CMake 命令,而是在 Git Bash 内执行命令,那么就会出现以下的错误信息:
1 | # 配置项目,生成构建文件(例如 Makefile 或 Ninja 文件) |
1 | -- Building for: NMake Makefiles |
这通常是因为在 Git Bash 内运行 CMake 时,CMake 找不到 nmake
工具,比如 nmake
工具不可用或没有正确安装。解决该问题的方法是,在 Git Bash 中让 CMake 使用特定的 C/C++ 编译器。
什么是 nmake
nmake
是 Microsoft 的一个构建工具,其作用类似 make
,它通常与 Visual Studio 一起安装,尤其在使用 Microsoft Visual C++ 编译器(简称 MSVC)时,CMake 可能需要它来生成配置文件。
解决方案一
在 Windows 系统上 安装 MinGW,然后在 Git Bash 中让 CMake 使用 MinGW 自带的 gcc
和 g++
编译器。
- 首先删除之前生成的
build
目录
1 | # 删除构建目录 |
- 在 Git Bash 中,要让 CMake 使用 MinGW 提供的
gcc
和g++
编译器,可以通过指定使用 MinGW Makefiles 配置生成器来完成
1 | # 配置项目,生成构建文件(例如 Makefile 或 Ninja 文件) |
- 一旦配置完成,就可以使用以下命令编译 C/C++ 项目,相当于执行了
mingw32-make -C build
命令
1 | # 编译项目,生成可执行文件 |
1 | - 参数说明 |
解决方案二
在 Windows 系统上 安装 MinGW,然后在 Git Bash 中让 CMake 使用 MinGW 自带的 gcc
和 g++
编译器。
- 首先删除之前生成的
build
目录
1 | # 删除构建目录 |
- 在 Git Bash 中,要让 CMake 使用 MinGW 提供的编译器,还可以在
CMakeLists.txt
配置文件中,显式指定 C/C++ 编译器
1 | # 设置 MinGW 提供的 GCC 作为 C 编译器 |
然后编译项目代码,必须确保上面设置的编译器路径和 MinGW 的安装路径一致
1 | # 配置项目,生成构建文件(例如 Makefile 或 Ninja 文件) |
成功编译代码后,最后会显示 gcc
和 g++
编译器都来自 MinGW,而不是 Visual Studio 的 cl.exe
。
特别注意
笔者使用该方案来让 CMake 使用特定的编译器,但最终没有成功,原因暂时未知。
使用 NMake 构建并编译
在 Windows 环境下,若希望让 CMake 使用 NMake 构建并编译项目,可以在 Developer Command Prompt for Visual Studio
开发者命令提示符窗口内执行以下命令:
- 让 CMake 使用 NMake Makefiles 配置生成器来生成构建文件
1 | # 配置项目,生成构建文件(例如 Makefile 或 Ninja 文件) |
- 一旦配置完成,就可以使用以下命令编译 C/C++ 项目,相当于在
build
目录下执行nmake
命令
1 | # 编译项目,生成可执行文件 |
1 | - 参数说明 |
提示
- 若想知道当前版本的 CMake 支持哪些生成器(Generators),可以使用帮助命令
cmake --help
来查看详细的帮助手册。 - CMake 常用的生成器有:NMake Makefiles、MinGW Makefiles、MSYS Makefiles、Ninja 等。
使用常见的编译选项
--target <target>
: 指定要构建的特定目标(例如,生成特定的可执行文件或库)。如果不指定,它会构建所有默认目标。
1 | cmake --build build --target my_target |
--config <configuration>
: 用于多配置生成器(例如 Visual Studio 或 Xcode),可以指定构建的配置类型,如Debug
或Release
。
1 | cmake --build build --config Release |
--clean-first
: 先清理项目再编译,相当于make clean && make
。
1 | cmake --build build --clean-first |