CMake, 应该这样学

跟我一起学CMake CMake是一个很强大的工具,在这里以一个学习者的身份来和大家一起学习,可以让大家更快的学习和领会这个强大工具 阅读详情

CMake 是现代构建工具的代表,它在跨平台项目的构建与管理中发挥了不可替代的作用。本篇文章将以循序渐进的方式,结合图表、实战案例和性能对比,从入门到进阶全面剖析 CMake,帮助你快速掌握并灵活运用这一工具。


一、CMake 是什么?

在这里插入图片描述

1.1 定义与背景

CMake,全称 Cross-platform Make,是一个开源的构建工具。它通过描述项目的构建需求,生成具体平台(如 Linux、Windows、macOS)的构建文件(如 Makefile 或 Ninja 文件)。与传统工具相比,CMake 提供了更高的灵活性和可扩展性。

  • 开发背景:CMake 于 2000 年由 Kitware 开发,目的是简化跨平台项目的构建。
  • 主要特点:
    • 支持多种构建系统(如 Ninja、Make、Visual Studio)。
    • 易于集成第三方库。
    • 提供模块化配置和强大的依赖管理。
1.2 CMake 的优劣对比
工具跨平台支持性能灵活性适用场景
CMake优秀高效(结合 Ninja)强中大型项目
Make一般中等中等小型项目
Autotools优秀中等中等GNU/Linux 项目
Meson优秀极高(结合 Ninja)较强高性能构建项目
1.3 CMake 的工作流程

通过一张示意图直观展示 CMake 的构建流程:

CMakeLists.txt → CMake → 构建工具(如 Ninja)→ 可执行文件或库

二、CMake 的基本语法与用法

2.1 最简单的 CMake 示例

创建一个 CMake 项目的基本步骤如下:

  1. 创建 CMakeLists.txt 文件:

    cmake_minimum_required(VERSION 3.15)
    project(MyProject)
    
    # 设置 C++ 标准
    set(CMAKE_CXX_STANDARD 17)
    
    # 添加可执行文件
    add_executable(my_executable main.cpp)
    
  2. 运行以下命令生成构建文件:

    mkdir build && cd build
    cmake ..
    make
    ./my_executable
    
2.2 核心命令详解
指令作用示例
cmake_minimum_required指定 CMake 的最低版本cmake_minimum_required(VERSION 3.15)
project定义项目名称和版本project(MyProject VERSION 1.0)
add_executable添加可执行目标add_executable(my_executable main.cpp)
find_package查找外部库find_package(OpenCV REQUIRED)
target_link_libraries为目标链接外部库target_link_libraries(my_executable OpenCV)

三、CMake 的实际应用

3.1 构建模块化项目

项目结构如下:

MyProject/
├── CMakeLists.txt
├── src/
│   ├── main.cpp
│   ├── CMakeLists.txt
├── include/
│   └── myheader.h

顶层 CMakeLists.txt 内容:

cmake_minimum_required(VERSION 3.15)
project(MyProject)

# 添加子目录
add_subdirectory(src)

# 设置头文件路径
include_directories(include)

src/CMakeLists.txt 内容:

add_executable(my_executable main.cpp)

运行流程:

mkdir build && cd build
cmake ..
make
3.2 集成第三方库

例如,集成 OpenCV:

find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(my_executable ${OpenCV_LIBS})
3.3 性能对比:CMake + Ninja vs. Make

下表对比了使用 Ninja 和 Make 构建的性能:

工具构建时间(秒)文件依赖分析时间(秒)
Ninja5.20.8
Make8.52.3

通过实验,Ninja 在大项目的构建中更具优势。


四、CMake 的最佳实践

4.1 模块化配置

将项目拆分成多个模块,每个模块独立管理自己的 CMakeLists.txt 文件,从而提高项目的可维护性和清晰度。

4.2 自定义构建选项

通过 option 命令创建用户可控的构建选项:

option(ENABLE_TESTS "Enable testing" ON)

if(ENABLE_TESTS)
    add_subdirectory(tests)
endif()
4.3 高效的依赖管理

使用现代 CMake 的 target_* 系列命令,避免全局作用域污染:

target_include_directories(my_executable PRIVATE ${CMAKE_SOURCE_DIR}/include)

五、常见问题与解决方案

5.1 常见错误
  1. 找不到库
    错误提示:

    Could not find package configuration file ...
    

    解决方案:

    • 检查库是否安装。
    • 设置 CMAKE_PREFIX_PATH 环境变量,指定库的路径。
  2. 构建工具选择错误
    错误提示:

    ninja: error: build.ninja: No such file or directory
    

    解决方案:

    • 使用 cmake -G Ninja 指定生成器。

六、进阶技巧

6.1 使用 CTest 进行单元测试

CMake 原生支持测试框架:

enable_testing()
add_test(NAME MyTest COMMAND my_executable)
6.2 自定义命令与任务

通过 add_custom_command 实现构建流程的个性化:

add_custom_command(
    OUTPUT generated_file.cpp
    COMMAND python generate_code.py
    DEPENDS input_data.json
)
6.3 生成多配置构建

通过 CMakePresets.json 提供灵活的构建配置:

{
  "configurePresets": [
    {
      "name": "Debug",
      "generator": "Ninja",
      "binaryDir": "build/Debug",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug"
      }
    }
  ]
}

七、学习路径

  1. 入门: 学习基本命令和小项目实践。
  2. 提升: 集成常见第三方库(如 OpenCV、Boost)。
  3. 进阶: 学习模块化配置、依赖管理和跨平台构建。
  4. 实践: 分析开源项目的 CMakeLists.txt 文件。

八、总结与展望

通过本文,你不仅可以快速上手 CMake,还能掌握现代化的项目构建思路。未来,建议持续关注 CMake 的新特性(如增强的 Presets 支持)以及工具链的整合趋势(如与 Conan 的结合)。CMake,不仅是工具,更是高效开发的必备技能。

[Ubuntu] 无论如何都能学明白的Cmake入门 目录1 CMakeLists.txt 怎么写1.1 语句含义1.2 一些实例1.2.1 创建一个可执行文件1.2.2 引用.h文件 1 CMakeLists.txt 怎么写 1.1 语句含义 cmake 是一个跨平台、开源的构建系统。它是一个集软件构建、测试、打包于一身的软件。它使用与平台和编译器独立的配置文件来对软件编译过程进行控制。 CMakeLists.txt直接指定了程序的编译规则。 因为仅仅只是作为一个入门学习。我们的目标是 完成软件编译 完成静态库/共享库的建立 使用静态库/共享库 首先我们 阅读详情

相关推荐

CMake用法详解 使用方法说明

CMake 用法详解,简单描述了CMake 的使用方法,通过简单的例子

【CMake基础入门】

在实际工作中推荐使用CMake构建G +项目,CMake是用于构建、测试和软件打包的开源跨平台工具;特性:1·自动搜索可能需要的程序、库和头文件的能力;2.独立的构建目录(如build) ,可以安全清理3·支持复杂的自定义命令(下载、生成各种文件)4·自定义配置可选组件5·从简单的文本文件( csakeLists.txt)自动生成工作区和项目的能力6·在主流平台上自动生成文件依赖项并支持并行构建7· 几乎支持所有的IDE。

qq_51607131的博客 2266

Nginx国密HTTPS实战:SM2双证书部署与TongSuo编译指南

HTTPS作为保障网络通信安全的基石,其核心在于SSL/TLS协议与公钥基础设施(PKI)。它通过非对称加密实现身份认证与密钥交换,再结合对称加密确保数据传输的机密性与完整性。在金融、政务等对自主可控有严格要求的领域,采用符合国家密码管理局标准的国密算法(SM2/SM3/SM4)替代国际通用算法(如RSA/SHA-256/AES),已成为满足安全合规要求的关键技术路径。国密SSL不仅是一套算法替换,更涉及从底层密码库到上层应用服务的完整技术栈改造。其核心价值在于实现密码技术的自主可控,提升特定场景下的安全防

weixin_29323365的博客 497

cmake超详细入门教程,学不会你捶我~

我们在平时编译代码的时,面对简单的代码,直接GCC编译就好,稍微多一点,可以编写Makefile来编译,以上编译起来都很轻松,可是平时工作的时候基本都是大工程呀,代码文件少则几十个文件了,这种情况下就头疼了,咋办呢?今天我来教你使用cmake轻松解决问题~提示:以下是本篇文章正文内容,下面案例可供参考关于cmake的使用方法还有很多,这里只是做了一个最基本的介绍,后期有机会在进行详细补充~

十年饮冰,难凉热血,保持热爱,奔赴星海! 6万+

HyperLynx VX2.5 实战:5分钟搞定LPDDR4X内存的批量仿真与报告分析

本文详细介绍了如何使用HyperLynx VX2.5进行LPDDR4X内存的批量仿真与报告分析,通过智能网络分组和并行计算技术,5分钟内即可完成全流程验证。文章涵盖工程准备、批量仿真配置、报告解析及典型问题解决方案,帮助工程师高效提升PCB仿真效率,确保移动设备内存接口的稳定性与性能。

weixin_42683394的博客 400

不用加速器!Google Earth Pro登录失败自救手册:从服务器连接到地图加载的完整排错流程

本文详细解析了Google Earth Pro登录失败的常见问题及解决方案,包括服务器连接失败、地图加载异常等。通过基础排查、内置修复工具使用和高级配置调整,帮助用户无需加速器即可解决启动问题、黑屏和转圈圈等困扰,提升软件使用体验。

weixin_29227425的博客 482

CMake 入门教程 详解(看这篇就够)

当前处理的二进制目录的绝对路径(即构建目录)。当前处理的源代码目录的绝对路径(即源代码的顶层目录)。当前正在处理的 CMakeLists.txt 文件所在的目录的绝对路径。当前正在处理的 CMakeLists.txt 文件对应的二进制目录的绝对路径。这可能与源代码目录不同,尤其是在使用 out-of-source 构建时。安装路径的前缀,用于时的安装目标路径。分别用于指定 C++ 和 C 编译器的完整路径。

啊渊的专栏 4644

【经验&技巧】IBIS AMI模型眼图仿真问题探讨

在ADS的仿真环境中,不论发送和接收的AMI模型是否为true或者false,都可以将通道仿真设置为统计模式,但是,如果有一方的Init函数为false,在统计模式下,处于false状态的模型将不能执行其自带的后处理功能,如下图所示,左边的统计模式和右边的逐比特模式眼图存在明显的差异,原因在于,接收端的init函数为false导致在统计模式中不能对眼图进行DFE处理,换言之,此时统计模式下的眼图就是未经任何处理的“生图”。

一只豌豆象的博客 1766

CMake语法结构说明

CMake语法结构说明

qq_30150579的博客 773

ethernet eth0: Could not attach to PHY

整个流程看下来就是MAC connect PHY的过程失败了,失败的具体原因根据config_init,上图(bcm54xx_config_init) ,从此方向入手去定位原因;我这里的问题是has_gmac4没有置1,根据 has_gmac4: uses GMAC4 core.按照上面的调用逻辑,添加了部分打印,定位到__phy_read接口返回失败。stmmac_mdio_read 大部分都是linux的标准接口。最终取决于平台用的是哪家的phy,调用config_init。

无线互联&网络介绍 2701

python基础:工作会用到的90%的python代码都在这了(万字详解!)

Python 备忘单是 Python 3 编程语言的单页参考表 著名的“Hello World”程序在 Python 中的实现 Python 不能在没有赋值的情况下声明变量 变量可以存放不同类型的值 内置数据类型 序列指一批有序的元素,集合指一批无序且不重复的元素查看: 数据类型 查看: 字符串 查看: 列表 查看: 判断 查看: 循环 查看: 函数 查看: 文件处理 表示 x 和 y 的商, 表示 x 和 y 的底商,另见 StackOverflow f-字符串 (Python 3.6+) 查看

数据知道的博客 1万+

CMake详细教程

CMake入门详细教程

m0_43424329的博客 6452

052、联发科Imagiq HyperEngine架构适配:天玑9000/9200的ISP多核并行调度与Tuning Toolkit调优案例

摘要: 项目组在适配联发科天玑9200的Imagiq 890 ISP架构时,遇到多摄预览功耗过高、帧率不稳等问题。通过分析多核调度机制,调整辅核QoS通道、优化AI-ISP协同模式(采用FREERUN+运动补偿),并利用Tuning Toolkit的Pipeline Viewer动态分配负载,最终降低功耗30mA、提升画质。关键经验包括:避免多核带宽冲突、合理配置动态时钟策略,以及统一校准参数版本管理。天玑9000/9200的HyperEngine架构需优先理解多核协同逻辑,再针对性调优,否则易引发场景兼容

zzfmlxs的博客 36

一步一步学CMake 之 CMake详细介绍

CMake是可跨平台的构建和编译大型项目的工具,CMake不是一套编译工具,它里面并不包含编译器,它能做的只是减轻我们输入繁琐命令的负担。另外,如果软件想跨平台,必须要保证能够在不同平台编译。而如果使用Make 工具,就得为每一种标准写一次 Makefile,那这就太痛苦了。。。 CMake并不直接构建出最终的软件,而是产生标准的构建文档(比如Unix下的makefile,Mac下的xcode...

wanzew的博客 2284

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Cmake确实应该用到的时候再学

最近在做项目用到Cmake相关的知识,之前做的是BSP驱动开发,基本用不到Cmake,唯一和Cmake有交集的应该是我们移植网关项目,不过也只是修修改改,直到最近用到Cmake开发项目,才...

嵌入式Linux 588

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

笨蛋学C++ 之 CMake的使用

主要是自己对CMake进行学习的一个总结过程,有一些自己的体会,也参考了网络上其他资源,有一些未完善的东西,后期再好好完善!

YSL_Monet的博客 1179

学C++从CMake学起

编译器,是一个根据源代码生成机器码的程序。该命令会调用编译器程序 g++,让他读取 main.cpp 中的源码,并根据 C++标准生成相应的机器指令码,输出到 a.out 这个文件中,称为可执行文件。./a.out之后执行该命令,操作系统会读取刚刚生成的可执行文件,从而执行其中编译器成机器码,调用系统提供的printf函数,并在终端显示出Hello, world.

lwx666sl的博客 951

也学CMAKE 【转】

# Modern CMake全攻略 [TOC]## 前言 接触`Cmake`是一个偶然事件,平时我都是手撸`Make`或者人工添加指定`cpp文件`到`VS`的工程目录。然而在后续工作效率提升的思考中,我不断发现,想要快速发布版本构建,使用命令行无疑是最快捷的,并不需要频繁挪动鼠标去做一系列重复而低效的`劳动。 在一顿常规资料搜索后,才了解到`Modern Cmake`运动(让CMAKE更加规范,控制各级构建的变量泄露),实际上相关的资料乏善可陈,众多模板又参差不齐;最终我想总结下相关的经验来做一个最合适的

loveboon1的专栏 289

cmake字符串转数组_跟我一起学CMake

如今CMake使用的人数越来越多,包括我项目组里,很多大牛们在写Qt程序的时候都不用自带的qmake,貌似会出现很多问题,他们往往都用自己写的CMake来编译系统,今天我也和大家一起来学学这个高大上的工具--CMake。首先,一个CMake要想运行,必须在同目录下有CMake脚本,说说是脚本,其实并没什么可怕,说白了就是一串CMake作者自己写的token语法分析文件--CMakeLists.tx...

weixin_39636253的博客 603

学C++从Cmake学起

include //方式1 #include "hellolib/hello.h" //方式2// #include "hello.h" or #include //CMake中增加 # target_include_directories(a.out PUBLIC hellolib) int main() {hello();return 0;}如果另一个 b.out 也需要用 hellolib 这个库,难道也得再指定一遍搜索路径吗?不需要,

喜欢打篮球的普通人 2865

不知道怎么学 CMake ?这份精炼的学习路线拯救你!

CMake 作为现代构建工具,核心价值在于跨平台、灵活配置和高效管理。它统一了不同平台的构建流程,简化了复杂的依赖关系,并提供了强大的测试、打包和部署能力。学习 CMake 能够提升开发效率、确保软件质量并简化发布流程。从基础概念入手,逐步掌握高级技巧,并结合实践不断探索,你就能充分利用 CMake 的优势。

Lion_Long的博客 1492

【Linux杂学】CMake:编写 CMakeLists

无

哥特的博客 1072
上一篇: 熟悉的 Docker,陌生的 Podman
下一篇: 从容器到Podman:一个全方位的剖析
嵌入式孙老师
博客等级 码龄7年 5687粉丝 900原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值