本篇摘要
CMake是跨平台构建系统的核心工具。本文详解其安装、基础命令使用,涵盖项目构建、测试执行、安装部署及打包分发全流程。通过实战演示,助你快速掌握现代C++项目工程化管理的关键技能。

欢迎拜访: 点击进入博主主页
本篇主题: CMake从0到完成编写并打包简单介绍
制作日期: 2025.09.12
隶属专栏: 点击进入所属CMake专栏
一.CMake简介
什么是 CMake?
CMake(中大型项目常用) 是一个开源的、跨平台的构建系统生成器 。它本身并不直接编译代码,而是根据一套统一的规则(CMakeLists.txt
文件)来生成不同平台和编译器所需的本地构建文件(如 Unix/Linux 上的 Makefile
或 Windows 上的 Visual Studio
项目文件),从而实现对项目的构建和管理。
为什么需要 CMake?
- 解决跨平台构建难题

- 传统方式: 同一份源代码,在 Linux 平台需要手动编写复杂的 Makefile ,而在 Windows 平台则需要手动配置 Visual Studio 的工程属性。这个过程繁琐、易错且难以维护。
- CMake 方式: 开发者只需编写一次
CMakeLists.txt
配置文件,CMake 就能自动为不同平台生成对应的本地构建文件(如为 Linux 生成Makefile
,为 Windows 生成.sln
解决方案)。真正实现了 "一次编写,到处构建" 。
构建方式 | Linux 平台 | Windows 平台 |
---|---|---|
传统方式 | 手写 Makefile | 手动配置 VS 工程属性 |
CMake方式 | cmake .. ---> Makefile |
cmake .. ---> .sln 解决方案 |
- 强大的工程管理能力
- 语法简单易上手: 相比直接写 Makefile,CMake 的语法更清晰、直观,学习成本更低,表达能力强。
- 功能强大: 支持复杂的大型项目构建,可以轻松管理库的依赖、安装、测试和打包。
- IDE 支持度高: 它已是 C/C++ 事实上的构建标准。CLion、Visual Studio、Qt Creator 等主流 IDE 都对其提供了原生支持,极大提升了开发体验。
- 提升竞争力: 掌握 CMake 是现代 C/C++ 工程师的必备技能,能让你的项目结构更优雅 ,团队协作更高效 ,"也能提升你的个人竞争力"。
CMake优势:
优势 | 传统方式 | CMake方式 | 改进效果 |
---|---|---|---|
解决跨平台构建难题 | 人工编辑Makefile等配置文件 | CMake自动生成构建配置文件 | 一处配置,到处构建 |
语法简单易上手 | Makefile等语法复杂 | 语法简单,表达能力强大 | 大幅减少学习成本,提升研发效率 |
解决包管理难题 | 手动查找包 | 自动查找包 | 包管理规范化 |
IDE对CMake支持度高 | 每个IDE都有自己的构建方式 | 各个IDE都支持使用CMake来构建程序 | 一处配置,多IDE支持 |
官方资源:
总而言之,CMake 通过将构建规则与具体平台解耦,统一并简化了 C/C++ 项目的构建过程 。它就像一位出色的翻译官 和项目经理 ,你告诉它项目的构建需求(用 CMakeLists.txt
书写),它就能将这些需求翻译成各种平台和 IDE 能听懂并执行的指令,最终高效地帮你完成整个项目的编译和管理工作。
二.CMake安装及使用(ubuntu/vscode)
ubuntu:
bash
sudo apt install cmake
bash
root@iv-ye1i2elts0wh2yp1ahah:~# sudo apt install cmake
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
cmake is already the newest version (3.22.1-1ubuntu1.22.04.2).
0 upgraded, 0 newly installed, 0 to remove and 57 not upgraded.
root@iv-ye1i2elts0wh2yp1ahah:~# cmake --version
cmake version 3.22.1

- 默认安装在这个路径的目录里,这样就安装完成了。
对于vscode只需要安装这四个插件即可:

基于CMake 生成第一个cpp程序之hello-world

首先只需要搞个cpp文件外加一个CMakeLists.txt
文件:
cpp
#include <iostream>
int main()
{
std::cout << "hello world!" << std::endl;
return 0;
}
下面进行编写CMakeLists.txt
文件;这里名字不能错
;后面再讲解具体语法:
cpp
cmake_minimum_required(VERSION 3.18)#要求最小版本,后面解释下
project(hello-world)#项目名称-cmake生成的那些文件会记录
add_executable(main main.cpp)# 最终程序及源文件

下面看到此前目录就生成了对应一些文件:
下面简单看下对应的makefile 文件:

- 可以看到有关于编译写的cp程序的makefile语句。

- 也是成功完成运行。
回答之前的两个问题:
-
为什么要设最低版本?
为了防止你用旧版本的CMake软件去编译一个用了新功能的新项目,导致各种报错。
cmake_minimum_required
命令就是用来提前检查版本,不够就直接告诉你,避免后续出现一堆看不懂的错误。 -
CMake里的"目标"是啥?
就是你想让CMake帮你生成的东西,比如一个可执行程序(exe)或者一个库文件(lib/dll)。它是CMake里最核心的概念,所有操作基本都是围绕"目标"来进行的。
cmake生成构建系统
输入cmake;看下对应用法:

简单说就是CMake的三种用法:
cmake <源码路径>
- 在当前目录 生成编译文件,源码在别处(常用
cmake ..
)。 - 一般默认搞一个build目录;然后CMakeLists.txt等目录在上级目录;把对应的工程目录生成在build里。
演示下:

- 这里它说已经生成完了;其实是之前在上级目录搞过一次cmake;对应的cmakecache文件有记录;它的目标路径就是build的上级目录;因此需要删除cache在生成。

- 此时就说已经搞到build目录里了。
cmake <已有构建目录>
- 重新生成 一个已有目录的编译文件(常用
cmake .
)。
演示下:

cmake -S <源码> -B <构建目录>
(推荐!)
- 一条命令 直接指定源码和输出目录,自动创建,最方便(如
cmake -S . -B build
)。
演示下:

- 这里就是手动指明对应CMakeLists.txt文件所在位置以及目标路径而已。
推荐使用第三种 -S -B的方式,这是目前最清晰、最方便且能保持项目目录干净的方法。
使用cmake --build 完成编译链接原理
⽣成构建⽂件以后,就可以使⽤cmake(cmake --build
)来编译链接,也可以使⽤第三⽅构建系统进⾏。因为⽣成的makefile就在构建树的根⽬录下,所以可以直接在此⽬录运⾏make。
比如用cmake进行:

因为有makefile故makefile也是可以的:

下面解释下为啥cmake --build可以做到:
可以看到对应的CMakeCache.txt
文件存在:
- 可以发现这个
--build
最后也是调用的make(搞了个软链接)。
ctest 命令
-
测试工具
ctest 是 CMake 自带的测试工具,用于运行和管理项目中定义的测试用例。
-
依赖配置
需在
CMakeLists.txt
中通过enable_testing()
(或者include(CTest)
)和add_test()
显式定义测试,否则会报No tests found
。 -
基本命令
ctest
:运行所有测试。ctest -N
:列出所有测试(不执行)。ctest -R <正则表达式>
:运行匹配名称的测试。ctest -V
:输出详细日志(包括测试的打印内容)。
-
测试结果
输出统计通过/失败的测试数量,并返回非零值(若存在失败测试)。
-
常用选项
--output-on-failure
:失败时打印测试输出。-j <N>
:并行运行 N 个测试。--rerun-failed
:仅重新运行失败的测试。
-
与 Make 的关系
make test
底层调用ctest
,但直接使用ctest
功能更灵活(如过滤测试、并行执行等)。 -
适用场景
适用于 C/C++ 项目(或其他 CMake 支持的语言),需结合 CMake 构建系统使用。
一句话:ctest 是 CMake 项目的测试入口,通过配置驱动,支持灵活运行和筛选测试用例。
下面测试下:
修改对应的CMakeLists.txt来添加测试:
cpp
cmake_minimum_required(VERSION 3.18)#要求最小版本,后面解释下
project(hello-world)#项目名称-cmake生成的那些文件会记录
add_executable(main main.cpp)# 最终程序及源文件
# # 4 生成测试二进制可执行程序
add_executable(testAdd test.cpp)
# 4 开启测试功能 & 集成测试逻辑
include(CTest)
add_test(
NAME Case_Add
COMMAND testAdd
)
搞一个错误的测试:
cpp
#include <iostream>
#include<cassert>
int main()
{
assert(1+2==0);
}
然后进行cmake后;进行makefile test或者ctest:

也可以直接运行;最简单粗暴:

然后有个报错日志点击进去;可以看到对应信息:

下面看下为什么ctest和make test 等效:

- cmake后生成的一个ctest的文件;默认就启动了对应测试程序。
至于make test;其实是间接调用了ctest的功能(从makefile中可看出):

install命令
CMake install
命令就是告诉系统:
"当我执行 make install
时,请把我的文件放到这些位置。"
最常用的三条命令:
-
安装可执行程序
cmakeinstall(TARGETS 程序名 DESTINATION bin)
程序会被安装到
/usr/local/bin/
-
安装库文件
cmakeinstall(TARGETS 库名 DESTINATION lib)
库文件会被安装到
/usr/local/lib/
-
安装头文件
cmakeinstall(FILES 头文件.h DESTINATION include)
头文件会被安装到
/usr/local/include/
怎么用?
- 在
CMakeLists.txt
里写上这些命令 - 编译项目:
cmake . && make
- 执行安装:
sudo make install/ cmake --install .
一句话:
install
就是定义"软件安装时要拷贝哪些文件到系统目录"的规则。
演示下:
以之前写的helloworld程序为例:

- 在之前camke的txt文件添加上这些。

- 这两个命令都是可以的。

- 可以运行。
cmake --install .
原理:
找到对应cmake后生成的文件:

- 这里.就是表示exe的路径;然后
CMAKE_INSTALL_PREFIX
;是对应的编写的txt中GNUInstallDirs通用规定的一个路径(如linux下的
/usr/local`);最后就被转成了对应目录里。
为啥对应的make install也可以:
- 这是一个脚本文件(
cmake_install.cmake
);里面写的正是对应的上面install原理执行的操作的指令;所以说也是调用了cmake --install .
。
cpake命令
CPack 简单介绍
cpack
是 CMake 自带的打包工具,用来把编译好的程序打包成安装包 (如 .deb
、.rpm
、.zip
、.msi
等)。
最简用法(3步)
-
在
CMakeLists.txt
末尾加一行:cmakeinclude(CPack)
-
编译项目:
bashcmake -B build && cmake --build build
-
打包:
bashcd build && cpack
生成默认格式的安装包(如
.zip
或.tar.gz
)。
常用打包格式
命令 | 输出格式 | 适用系统 |
---|---|---|
cpack -G ZIP |
.zip |
所有平台 |
cpack -G TGZ |
.tar.gz |
Linux/macOS |
cpack -G DEB |
.deb |
Debian/Ubuntu |
cpack -G RPM |
.rpm |
RedHat/CentOS |
cpack -G NSIS |
.exe |
Windows |
示例:打包一个 Debian 包
bash
cpack -G DEB -D CPACK_DEBIAN_PACKAGE_NAME="myapp" \
-D CPACK_DEBIAN_PACKAGE_VERSION="1.0"
生成 myapp-1.0.deb
,可直接用 dpkg -i
安装。
总结
cpack
依赖 CMake 的install
规则 (先定义install
,再打包)。- 默认打包
install
安装的所有文件。 - 一条命令生成多种系统安装包,无需手动压缩。
CPack 打包过程:
首先搞一个安装那些包的临时目录;然后执行cmake_install.cmake
这个文件(对应install也执行它但是目的目录是usr/local/bin;但是cpack的目的目录是创建的包临时目录(_CPack_Packages
));读取之前install把安装的程序路径写到的install_manifest.txt
这个文件里的内容;然后进行打包按照指定格式进行压缩到对应临时目的目录。
下面执行一下:
只需要在之前的编写的cmake的txt加上:

执行一下:

- 成功cpack。

- 执行cpack的时候如果出错;可能是这里权限问题;需要加上sudo。
- 还可以看到生成了不同格式压缩包;以及对应脚本一键配置(执行后就自动把对应头文件,源文件,库文件等自动放在对应位置;安装对应配置等)。

- 发现可以成功运行;因此一些项目就可靠它;进行打包好;把对应的文件包发给客户;客户直接可以自动解压运行或者通过脚本一键配置。
下面看下为啥正常的包的名字是这样:
- 可以看到对应的cpack的配置文件有这些信息;都是默认的;但是也可以手动修改。
因此总结下:
包的全称就是包的名称+包后缀(啥类型压缩包)
包的名称就是项目名称+包的版本+系统名称
其他常见用法
-
脚本模式 (
cmake -P
)用于执行纯 CMake 脚本,不进行任何构建(如配置、生成Makefile等)。适合完成文件操作、环境检查等与编译构建无关的自动化任务。
比如(makefile就调用了):

-
命令模式 (
cmake -E
)用于调用 CMake 内置的跨平台等效命令(如复制、删除、创建目录等),其底层会转换为对应操作系统(如 Linux 的
rm
)的命令,以保证脚本在不同系统上的兼容性。
比如(makefile就调用了):

-
查看帮助 (
cmake --help
)用于快速查询 CMake 命令行工具的使用方法、支持的生成器(Generator)列表以及各类命令行参数的功能说明。


- 这里可以查询不熟悉指令;或者去对应官网。
三.工程源码
四.本篇小结
本篇将从CMake基础概念到实战应用,完整走通构建、测试、安装、打包全流程。掌握cmake、ctest、cpack核心命令用法,理解跨平台构建原理。学会编写CMakeLists.txt,实现项目高效管理和一键分发,提升C++工程化能力。