CMake 全流程开发实战:从零开始掌握C++项目构建、测试到一键分发的完整解决方案

发布于:2025-09-13 ⋅ 阅读:(19) ⋅ 点赞:(0)

本篇摘要

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

在这里插入图片描述

欢迎拜访: 点击进入博主主页

本篇主题: CMake从0到完成编写并打包简单介绍

制作日期: 2025.09.12

隶属专栏: 点击进入所属CMake专栏

一.CMake简介

什么是 CMake?

CMake(中大型项目常用) 是一个开源的、跨平台的构建系统生成器。它本身并不直接编译代码,而是根据一套统一的规则(CMakeLists.txt 文件)来生成不同平台和编译器所需的本地构建文件(如 Unix/Linux 上的 Makefile 或 Windows 上的 Visual Studio 项目文件),从而实现对项目的构建和管理。

为什么需要 CMake?

  1. 解决跨平台构建难题

在这里插入图片描述

  • 传统方式: 同一份源代码,在 Linux 平台需要手动编写复杂的 Makefile,而在 Windows 平台则需要手动配置 Visual Studio 的工程属性。这个过程繁琐、易错且难以维护。
  • CMake 方式: 开发者只需编写一次 CMakeLists.txt 配置文件,CMake 就能自动为不同平台生成对应的本地构建文件(如为 Linux 生成 Makefile,为 Windows 生成 .sln 解决方案)。真正实现了 “一次编写,到处构建”
构建方式 Linux 平台 Windows 平台
传统方式 手写 Makefile 手动配置 VS 工程属性
CMake方式 cmake .. —> Makefile cmake .. —> .sln 解决方案
  1. 强大的工程管理能力
  • 语法简单易上手: 相比直接写 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:

sudo apt install cmake
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文件:

#include <iostream>
int main()
{
    std::cout << "hello world!" << std::endl;
    return 0;
}

下面进行编写CMakeLists.txt文件;这里名字不能错;后面再讲解具体语法:

cmake_minimum_required(VERSION 3.18)#要求最小版本,后面解释下

project(hello-world)#项目名称-cmake生成的那些文件会记录

add_executable(main main.cpp)# 最终程序及源文件

在这里插入图片描述

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

在这里插入图片描述
在这里插入图片描述

下面简单看下对应的makefile 文件:

在这里插入图片描述

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

在这里插入图片描述

  • 也是成功完成运行。

回答之前的两个问题:

  1. 为什么要设最低版本?

    为了防止你用旧版本的CMake软件去编译一个用了新功能的新项目,导致各种报错。cmake_minimum_required 命令就是用来提前检查版本,不够就直接告诉你,避免后续出现一堆看不懂的错误。

  2. CMake里的“目标”是啥?

    就是你想让CMake帮你生成的东西,比如一个可执行程序(exe)或者一个库文件(lib/dll)。它是CMake里最核心的概念,所有操作基本都是围绕“目标”来进行的。

cmake生成构建系统

输入cmake;看下对应用法:

在这里插入图片描述

简单说就是CMake的三种用法:

  1. cmake <源码路径>
  • 当前目录生成编译文件,源码在别处(常用 cmake ..)。
  • 一般默认搞一个build目录;然后CMakeLists.txt等目录在上级目录;把对应的工程目录生成在build里。

演示下:

在这里插入图片描述

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

在这里插入图片描述

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

演示下:

在这里插入图片描述

  1. 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 命令

  1. 测试工具

    ctest 是 CMake 自带的测试工具,用于运行和管理项目中定义的测试用例。

  2. 依赖配置

    需在 CMakeLists.txt 中通过 enable_testing() (或者include(CTest))和 add_test() 显式定义测试,否则会报 No tests found

  3. 基本命令

    • ctest:运行所有测试。
    • ctest -N:列出所有测试(不执行)。
    • ctest -R <正则表达式>:运行匹配名称的测试。
    • ctest -V:输出详细日志(包括测试的打印内容)。
  4. 测试结果

    输出统计通过/失败的测试数量,并返回非零值(若存在失败测试)。

  5. 常用选项

    • --output-on-failure:失败时打印测试输出。
    • -j <N>:并行运行 N 个测试。
    • --rerun-failed:仅重新运行失败的测试。
  6. 与 Make 的关系

    make test 底层调用 ctest,但直接使用 ctest 功能更灵活(如过滤测试、并行执行等)。

  7. 适用场景

    适用于 C/C++ 项目(或其他 CMake 支持的语言),需结合 CMake 构建系统使用。

一句话:ctest 是 CMake 项目的测试入口,通过配置驱动,支持灵活运行和筛选测试用例。

下面测试下:

修改对应的CMakeLists.txt来添加测试:

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
)

搞一个错误的测试:

#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 时,请把我的文件放到这些位置。”

最常用的三条命令:

  1. 安装可执行程序

    install(TARGETS 程序名 DESTINATION bin)
    

    程序会被安装到 /usr/local/bin/

  2. 安装库文件

    install(TARGETS 库名 DESTINATION lib)
    

    库文件会被安装到 /usr/local/lib/

  3. 安装头文件

    install(FILES 头文件.h DESTINATION include)
    

    头文件会被安装到 /usr/local/include/

怎么用?

  1. CMakeLists.txt 里写上这些命令
  2. 编译项目:cmake . && make
  3. 执行安装: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步)

  1. CMakeLists.txt 末尾加一行:
    include(CPack)
    
  2. 编译项目:
    cmake -B build && cmake --build build
    
  3. 打包:
    cd 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 包

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的配置文件有这些信息;都是默认的;但是也可以手动修改。

因此总结下:

包的全称就是包的名称+包后缀(啥类型压缩包)
包的名称就是项目名称+包的版本+系统名称

其他常见用法

  1. 脚本模式 (cmake -P)

    用于执行纯 CMake 脚本,不进行任何构建(如配置、生成Makefile等)。适合完成文件操作、环境检查等与编译构建无关的自动化任务。

比如(makefile就调用了):

在这里插入图片描述

  1. 命令模式 (cmake -E)

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

比如(makefile就调用了):

在这里插入图片描述

  1. 查看帮助 (cmake --help)

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

在这里插入图片描述

在这里插入图片描述

  • 这里可以查询不熟悉指令;或者去对应官网。

三.工程源码

点击获取工程源码

四.本篇小结

本篇将从CMake基础概念到实战应用,完整走通构建、测试、安装、打包全流程。掌握cmake、ctest、cpack核心命令用法,理解跨平台构建原理。学会编写CMakeLists.txt,实现项目高效管理和一键分发,提升C++工程化能力。