大纲 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 项目 1 2 3 first_cmake ├── CMakeLists.txt └── first_cmake.cpp
1 2 3 4 5 6 7 8 #include <iostream> using namespace std;int main (int argc, char *argv []) { cout << "First CMake Test" << endl; return 0 ; }
1 2 3 4 5 6 7 8 # 指定 CMake 版本 cmake_minimum_required (VERSION 3.17) # 指定项目名称 project (first_cmake) # 指定要编译的源文件 add_executable (first_cmake first_cmake.cpp)
1 2 3 4 5 cmake -S . -B build cmake --build build
1 2 3 4 - 参数说明 - `-S`:指定从哪里获取 `CMakeLists.txt` 配置文件,`.` 表示当前目录 - `-B`:指定生成的构建文件应该存放的目录(通常指定为 `build` 目录),默认会存放在当前目录下 - `--build`:指定从哪里获取构建文件进行编译,或者说是指定编译后的输出目录
上述两个 CMake 命令的功能可以分为几部分:调用生成的构建系统:如果之前生成的是 Makefile,它将调用 make
。 如果生成的是 Ninja 构建系统,它将调用 ninja
。 编译项目:它将编译项目中的源代码,并生成可执行文件、库等目标。 自动检测编译工具: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 2 3 4 5 6 7 8 9 10 11 12 13 14 -- Building for: NMake Makefiles CMake Error at CMakeLists.txt:5 (project): Running 'nmake' '-?' failed with: no such file or directory CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage -- Configuring incomplete, errors occurred!
这通常是因为在 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++
编译器。
在 Git Bash 中,要让 CMake 使用 MinGW 提供的 gcc
和 g++
编译器,可以通过指定使用 MinGW Makefiles 配置生成器来完成 1 2 cmake -S . -B build -G "MinGW Makefiles"
一旦配置完成,就可以使用以下命令编译 C/C++ 项目,相当于执行了 mingw32-make -C build
命令 1 2 3 4 - 参数说明 - `-S`:指定从哪里获取 `CMakeLists.txt` 配置文件,`.` 表示当前目录 - `-B`:指定生成的构建文件应该存放的目录(通常指定为 `build` 目录),默认会存放在当前目录下。 - `-G`:指定 CMake 使用哪个配置生成器,比如使用 MinGW Makefiles。
解决方案二 在 Windows 系统上 安装 MinGW ,然后在 Git Bash 中让 CMake 使用 MinGW 自带的 gcc
和 g++
编译器。
在 Git Bash 中,要让 CMake 使用 MinGW 提供的编译器,还可以在 CMakeLists.txt
配置文件中,显式指定 C/C++ 编译器 1 2 3 4 5 set (CMAKE_C_COMPILER "C:/MinGW/bin/gcc.exe" )set (CMAKE_CXX_COMPILER "C:/MinGW/bin/g++.exe" )
然后编译项目代码,必须确保上面设置的编译器路径和 MinGW 的安装路径一致
1 2 3 4 5 cmake -S . -B build cmake --build build
成功编译代码后,最后会显示 gcc
和 g++
编译器都来自 MinGW,而不是 Visual Studio 的 cl.exe
。
特别注意
笔者使用该方案来让 CMake 使用特定的编译器,但最终没有成功,原因暂时未知。
使用 NMake 构建并编译 在 Windows 环境下,若希望让 CMake 使用 NMake 构建并编译项目,可以在 Developer Command Prompt for Visual Studio
开发者命令提示符窗口内执行以下命令:
让 CMake 使用 NMake Makefiles 配置生成器来生成构建文件 1 2 cmake -S . -B build -G "NMake Makefiles"
一旦配置完成,就可以使用以下命令编译 C/C++ 项目,相当于在 build
目录下执行 nmake
命令 1 2 3 4 - 参数说明 - `-S`:指定从哪里获取 `CMakeLists.txt` 配置文件,`.` 表示当前目录。 - `-B`:指定生成的构建文件应该存放的目录(通常指定为 `build` 目录),默认会存放在当前目录下。 - `-G`:指定 CMake 使用哪个配置生成器,比如使用 NMake Makefiles。
提示
若想知道当前版本的 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