CMake基础及操作笔记
CMake 基础与操作:从入门到精通
前言
CMake 是一个功能强大、跨平台的构建工具,广泛用于 C++ 项目管理。它通过简洁的配置文件(CMakeLists.txt)描述编译过程,生成适用于不同平台的构建脚本(如 Makefile 或 Visual Studio 项目文件)。以下是 CMake 的核心优势:
- 跨平台支持:CMake 支持 Linux、Windows、macOS 等多种操作系统,统一管理不同平台的编译流程。
- 简洁高效:相比手写冗长的 Makefile,CMake 用几行代码即可完成复杂构建任务。
- 生态丰富:CMake 是许多 C++ 项目(如 Qt、Boost)的标配,社区支持广泛。
- 灵活性:支持模块化管理、动态/静态库生成、自定义编译选项等。
本文将从基础语法到高级用法,结合实例和最佳实践,帮助你快速上手 CMake,适合初学者学习、开发者复习以及博客分享。
为什么要使用 CMake?
CMake 的出现解决了传统构建工具的痛点:
- 跨平台编译:不同平台(如 Linux 用
gcc
、Windows 用MSVC
)有不同的编译工具和命令,CMake 提供统一的配置方式,生成适合目标平台的构建文件。 - 简化项目管理:只需在 CMakeLists.txt 中添加新文件(如
bar.cpp
),即可自动纳入构建流程,无需手动修改 Makefile。 - 模块化与可扩展性:CMake 支持复杂项目结构(如多目录、库依赖),通过简单的指令完成配置。
CMake 项目流程
以下是典型 CMake 项目的工作流程:
- 编写
CMakeLists.txt
,定义项目结构、源文件、库依赖等。 - 运行
cmake
命令生成构建系统(如 Makefile)。 - 运行
make
或其他构建工具,生成可执行文件或库。
例如,当添加新文件 bar.cpp
时,只需更新 CMakeLists.txt
,CMake 会自动处理依赖和编译。
CMake 语法特性
1. 基础语法
CMake 使用简单的指令(command)格式,语法如下:
# 指令(参数1 参数2 ...)
command(arg1 arg2 ...)
- 参数:用括号括起来,参数间以空格或分号分隔。
- 大小写:
- 指令名称(如
set
、add_executable
)对大小写不敏感。 - 变量名和参数值对大小写敏感。
- 指令名称(如
- 语句结束:CMake 语句不以分号结尾(与 C/C++ 不同)。
示例:
# 定义变量 HELLO,值为 hello.cpp
set(HELLO hello.cpp)# 生成可执行文件 hello,使用 main.cpp 和 hello.cpp
add_executable(hello main.cpp hello.cpp)# 也可以用变量引用
add_executable(hello main.cpp ${HELLO})
2. 变量引用
CMake 使用 ${变量名}
语法引用变量值,但在某些控制语句(如 if
)中直接使用变量名。
示例:
set(MY_VAR "value") # 定义变量
message("MY_VAR is ${MY_VAR}") # 引用变量,输出:MY_VAR is valueif(MY_VAR) # 直接使用变量名message("MY_VAR is defined")
endif()
注意:变量名大小写敏感,MY_VAR
和 my_var
是不同的变量。
3. 注释
CMake 使用 #
表示单行注释,支持行内和行首注释。
# 这是一个单行注释
set(FOO bar) # 定义变量 FOO
常用 CMake 指令
以下是 CMake 中最常用的指令,涵盖项目配置、文件管理、编译选项等。
1. cmake_minimum_required
指定 CMake 的最低版本要求,通常作为 CMakeLists.txt
的第一条指令。
cmake_minimum_required(VERSION 3.10) # 要求最低 CMake 版本 3.10
推荐:使用较新的版本(如 3.10 或以上),以支持更多功能和修复。
2. project
定义项目名称和支持的语言(如 C、C++)。
project(MyProject CXX) # 项目名为 MyProject,使用 C++
- 可选参数:
VERSION
(项目版本)、LANGUAGES
(支持的语言,如C CXX
)。 - 作用:设置项目元数据,生成变量如
PROJECT_NAME
。
3. set
显式定义变量,用于存储文件列表、路径等。
set(SRC_FILES sayhello.cpp hello.cpp) # 定义源文件列表
set(CMAKE_CXX_STANDARD 11) # 设置 C++ 标准
4. add_executable
生成可执行文件,指定源文件或变量。
add_executable(myapp main.cpp ${SRC_FILES}) # 生成可执行文件 myapp
5. include_directories
添加头文件搜索路径,类似 g++
的 -I
选项。
include_directories(/usr/include/mylib ./include) # 添加头文件路径
提示:现代 CMake 推荐使用 target_include_directories
代替,作用域更明确。
6. link_directories
添加库文件搜索路径,类似 g++
的 -L
选项。
link_directories(/usr/lib/mylib ./lib) # 添加库文件路径
注意:同样推荐使用 target_link_directories
替代。
7. add_library
生成静态库(.a
)或动态库(.so
/ .dll
)。
add_library(my_static_lib STATIC ${SRC_FILES}) # 生成静态库
add_library(my_shared_lib SHARED ${SRC_FILES}) # 生成动态库
8. add_compile_options
添加编译选项,作用于所有目标。
add_compile_options(-Wall -std=c++11) # 添加编译选项
注意:正确指令是 add_compile_options
(文档中 add_compile_option
是笔误)。
9. target_link_libraries
为目标(可执行文件或库)指定链接的库,类似 g++
的 -l
选项。
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE my_static_lib) # 链接静态库
参数:
PUBLIC
:链接库对目标及其依赖公开。PRIVATE
:仅对目标有效。INTERFACE
:仅对依赖目标有效。
CMake 常用变量
CMake 提供内置变量,用于控制编译行为和环境。
1. CMAKE_C_FLAGS
/ CMAKE_CXX_FLAGS
设置 C 或 C++ 编译器的选项。
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall") # 追加 C++11 标准和警告
建议:使用 add_compile_options
或 target_compile_options
替代,直接修改这些变量可能导致不可预测的行为。
2. CMAKE_BUILD_TYPE
指定编译类型,常见值:
Debug
:调试模式,包含调试信息。Release
:发布模式,优化性能。
set(CMAKE_BUILD_TYPE Debug) # 调试模式
# set(CMAKE_BUILD_TYPE Release) # 发布模式
3. CMAKE_SOURCE_DIR
/ CMAKE_BINARY_DIR
CMAKE_SOURCE_DIR
:项目源代码根目录。CMAKE_BINARY_DIR
:构建目录(运行cmake
的目录)。
示例:
message("Source dir: ${CMAKE_SOURCE_DIR}")
message("Binary dir: ${CMAKE_BINARY_DIR}")
实用示例:一个完整的 CMake 项目
以下是一个简单的 C++ 项目结构,展示如何使用 CMake 管理多文件项目。
项目结构
myproject/
├── CMakeLists.txt
├── include/
│ └── hello.h
├── src/
│ ├── main.cpp
│ └── hello.cpp
├── lib/
└── build/
hello.h
#pragma once
void say_hello();
hello.cpp
#include <iostream>
#include "hello.h"void say_hello() {std::cout << "Hello, CMake!" << std::endl;
}
main.cpp
#include "hello.h"int main() {say_hello();return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyProject CXX)# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)# 添加源文件
set(SRC_FILES src/hello.cpp)# 添加头文件路径
include_directories(${CMAKE_SOURCE_DIR}/include)# 生成可执行文件
add_executable(myapp src/main.cpp ${SRC_FILES})
构建步骤
-
创建
build
目录并进入:mkdir build && cd build
-
运行 CMake 生成构建文件:
cmake ..
-
编译项目:
make
-
运行程序:
./myapp
输出:
Hello, CMake!
最佳实践与常见问题
最佳实践
- 使用现代 CMake:优先使用
target_*
指令(如target_include_directories
、target_link_libraries
),避免全局指令(如include_directories
)。 - 模块化设计:将子目录放入独立的
CMakeLists.txt
,通过add_subdirectory
组织。 - 明确版本控制:始终设置
cmake_minimum_required
和 C++ 标准(如CMAKE_CXX_STANDARD
)。 - 分离构建目录:在
build
目录中运行cmake
,保持源代码目录干净。
常见问题
- 头文件未找到:检查
include_directories
或target_include_directories
是否正确设置路径。 - 链接错误:确保
target_link_libraries
指定了正确的库名称和路径。 - 变量未定义:检查变量名大小写是否一致,CMake 变量名区分大小写。
扩展资源
- 官方文档:CMake 官方文档(https://cmake.org/documentation/)是学习高级特性的最佳资源。
- 教程推荐:
- 《Professional CMake》:深入解析 CMake 的书籍。
- Online tutorials on platforms like YouTube or blogs like Modern CMake.
- 工具支持:CMake 集成在 CLion、VS Code 等 IDE 中,配置后可自动补全和调试。
总结
CMake 是现代 C++ 开发的必备工具,通过简单的配置文件实现跨平台、模块化的项目管理。本文从基础语法到实用示例,覆盖了 CMake 的核心功能和最佳实践。希望这份笔记能帮助你快速上手 CMake,并在学习、开发和分享中发挥价值!
相关文章:
CMake基础及操作笔记
CMake 基础与操作:从入门到精通 前言 CMake 是一个功能强大、跨平台的构建工具,广泛用于 C 项目管理。它通过简洁的配置文件(CMakeLists.txt)描述编译过程,生成适用于不同平台的构建脚本(如 Makefile 或 …...

在Oracle到GreatSQL迁移中排序规则改变引发的乱码问题分析及解决
在Oracle到GreatSQL迁移中排序规则改变引发的乱码问题分析及解决 一、引言 某老系统数据库从 Oracle 迁移至 GreatSQL 过程中,首批迁移(存储过程、表结构、基础数据)顺利完成。然而,第二批数据迁移时出现主键冲突问题࿱…...

开源物联网平台(OpenRemote)
在物联网技术蓬勃发展的当下,OpenRemote作为一款强大的开源物联网平台,正逐渐在多个领域崭露头角。尤其是在智能能源管理领域,它为微电网和分布式能源网络提供了全面且灵活的数据集成与管理方案,展现出独特的优势。 OpenRemote提供…...

JavaScript入门【3】面向对象
1.对象: 1.概述: 在js中除了5中基本类型之外,剩下得都是对象Object类型(引用类型),他们的顶级父类是Object;2.形式: 在js中,对象类型的格式为key-value形式,key表示属性,value表示属性的值3.创建对象的方式: 方式1:通过new关键字创建(不常用) let person new Object();// 添…...

软件安全检测报告:如何全面评估企业级办公软件安全性?
软件安全检测报告对软件的整体安全性进行了全面而细致的评估与呈现,既揭露了软件防范非法入侵的能力,同时也为软件的开发与优化提供了关键性的参考依据。 引言情况 撰写报告旨在明确呈现软件的安全性状态,并为后续的改进工作提供依据。在阐…...
区间dp(竞赛)
一、介绍 区间 dp 其实就是左右端点固定之后,用已经得出的小区间来更新大区间答案的 dp 方式。 非常重要的要素:小区间得到大区间,衍生出来的问题就是对于大区间如何划分成若干小区间,这直接决定了方程的书写。之后的例题中慢慢…...

PySide6 GUI 学习笔记——常用类及控件使用方法(常用类颜色常量QColorConstants)
文章目录 一、概述二、颜色常量表标准 Qt 颜色SVG 颜色(部分) 三、Python 代码示例四、代码说明五、版本兼容性六、延伸阅读 一、概述 QColorConstants 是 Qt for Python 提供的一个预定义颜色常量集合,包含标准Qt颜色和SVG规范颜色。这些常…...

大模型技术演进与应用场景深度解析
摘要 本文系统梳理了当前主流大模型的技术架构演进路径,通过对比分析GPT、BERT等典型模型的创新突破,揭示大模型在参数规模、训练范式、应用适配等方面的核心差异。结合医疗、金融、教育等八大行业的实践案例,深入探讨大模型落地的技术挑战与解决方案,为从业者提供体系化的…...

鸿蒙5.0项目开发——鸿蒙天气项目的实现(主页1)
【高心星出品】 文章目录 页面效果:页面功能:页面执行流程:1. 页面初始化阶段2. 定位获取阶段3. 天气数据加载阶段 这个页面是整个天气应用的核心,集成了天气查询、定位、搜索等主要功能,提供了完整的天气信息服务。 …...
python项目参考文献
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...

【ESP32】ESP-IDF开发 | 低功耗蓝牙开发 | GATT规范和ATT属性协议 + 电池电量服务例程
1. 简介 低功耗蓝牙中最为核心的部分当属 GATT(Generic Attribute Profile),全称通用属性配置文件。而 GATT 又是建立在 ATT 协议(属性协议)的基础之上,为 ATT 协议传输和存储的数据建立了通用操作和框架。…...

2025 年九江市第二十三届中职学校技能大赛 (网络安全)赛项竞赛样题
2025 年九江市第二十三届中职学校技能大赛 (网络安全)赛项竞赛样题 (二)A 模块基础设施设置/安全加固(200 分)A-1 任务一登录安全加固(Windows,Linux)A-2 任务二 Nginx 安全策略&…...

【记录】Windows|竖屏怎么调整分辨率使横竖双屏互动鼠标丝滑
本文版本:Windows11,记录一下,我最后调整的比较舒适的分辨率是800*1280。 文章目录 第一步 回到桌面第二步 右键桌面第三步 设置横屏为主显示器第四步 调整分辨率使之符合你的需求第五步 勾选轻松在显示器之间移动光标第六步 拖动屏幕符合物理…...

开源项目实战学习之YOLO11:12.2 ultralytics-models-sam-decoders.py源码分析
👉 点击关注不迷路 👉 点击关注不迷路 👉 另外,前些天发现了一个巨牛的AI人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。感兴趣的可以点击相关跳转链接。 点击跳转到网站。 ultralytics-models-sam 1.sam-modules-decoders.pyblocks.py: 定义模型中的各…...

数据结构*优先级队列(堆)
什么是优先级队列(堆) 优先级队列一般通过堆(Heap)这种数据结构来实现,堆是一种特殊的完全二叉树,其每个节点都满足堆的性质。如下图所示就是一个堆: 堆的存储方式 由于堆是一棵完全二叉树,所以也满足二…...

汽车Wafer连接器:工业设备神经网络的隐形革命者
汽车Wafer连接器正在突破传统车载场景的边界,以毫米级精密结构重构工业设备的连接范式。这款厚度不足3毫米的超薄连接器,在新能源电池模组中承载200A持续电流的同时,仍能保持85℃温升的稳定表现,其每平方厘米高达120针的触点密度&…...

微信小程序:封装表格组件并引用
一、效果 封装表格组件,在父页面中展示表格组件并显示数据 二、表格组件 1、创建页面 创建一个components文件夹,专门用于存储组件的文件夹 创建Table表格组件 2、视图层 (1)表头数据 这里会从父组件中传递表头数据,这里为columns,后续会讲解数据由来 循环表头数组,…...
湖北理元理律师事务所:债务优化中的双维支持实践解析
在债务压力与生活质量失衡的社会议题下,法律服务机构的功能边界正在从单一的法律咨询向复合型支持延伸。湖北理元理律师事务所通过“法律心理”双维服务模式,探索债务优化与生活保障的平衡路径,其方法论或为行业提供实践参考。 法律框架&…...
uniapp在APP上如何使用websocket--详解
UniApp 在 APP 端如何使用 WebSocket以及常见问题 一、WebSocket 基础概念 WebSocket 是一种在单个TCP连接上进行全双工通信的协议,适用于实时数据传输场景(如聊天室、实时游戏、股票行情等)。 与传统HTTP对比 特性WebSocketHTTP连接方式…...
计网| 网际控制报文协议(ICMP)
目录 网际控制报文协议(ICMP) 一、ICMP 基础特性 二、ICMP 报文分类及作用 差错报告报文 询问报文 网际控制报文协议(ICMP) ICMP(Internet Control Message Protocol,网际控制报文协议)是 …...

Conda 完全指南:从环境管理到工具集成
Conda 完全指南:从环境管理到工具集成 在数据科学、机器学习和 Python 开发领域,环境管理一直是令人头疼的问题。不同项目依赖的库版本冲突、Python 解释器版本不兼容等问题频繁出现,而 Conda 的出现彻底解决了这些痛点。作为目前最流行的跨…...

安卓中0dp和match_parent区别
安卓中的 0dp 和 match_parent 的区别? 第一章 前言 有段时间,看到同事在编写代码的时候,写到的是 0dp 有时候自己写代码的时候,编写的是 match_parent 发现有时候效果很类似。 后来通过一个需求案例,才发现两者有着…...
蓝桥杯-不完整的算式
问题描述 小蓝在黑板上写了一个形如 AopBCAopBC 的算式,其中 AA、BB、CC 都是非负整数,opop 是 、-、*、/、-、*、/(整除)四种运算之一。不过 AA、opop、BB、CC 这四部分有一部分被不小心的同学擦掉了。 给出这个不完整的算式&a…...

信贷风控笔记4——贷前策略之额度、定价(面试准备12)
1.贷前模型的策略应用 分类:审批准入(对头尾部区分度要求高):单一规则(找lift>3的分数做规则);二维交叉;拒绝回捞 额度定价(对排序性要求高)&am…...

A级、B级弱电机房数据中心建设运营汇报方案
该方案围绕A 级、B 级弱电机房数据中心建设与运营展开,依据《数据中心设计规范》等标准,施工范围涵盖 10 类机房及配套设施,采用专业化施工团队与物资调配体系,强调标签规范、线缆隐藏等细节管理。运营阶段建立三方协同运维模式,针对三级故障制定30 分钟至 1 小时响应机制…...

Linux中的域名解析服务器
一、DNS(域名系统)详解 1. 核心功能与特点 特性说明核心作用将域名(如 www.example.com)转换为 IP 地址(如 192.168.1.1),实现人类可读地址与机器可读地址的映射。端口与协议- 默认端口&#…...
如何优化Java中十进制字符串转十六进制的性能
在 Java 中优化十进制字符串转十六进制的性能,可以从减少对象创建、避免正则表达式、使用高效数据结构等方面入手。以下是具体的优化方案: 1. 避免字符串分割,直接遍历字符数组 原始方法(频繁创建子字符串)࿱…...

CycleISP: Real Image Restoration via Improved Data Synthesis通过改进数据合成实现真实图像恢复
摘要 大规模数据集的可用性极大释放了深度卷积神经网络(CNN)的潜力。然而,针对单图像去噪问题,获取真实数据集成本高昂且流程繁琐。因此,图像去噪算法主要基于合成数据开发与评估,这些数据通常通过广泛假设的加性高斯白噪声(AWGN)生成。尽管CNN在合成数据集上表现优异…...

Day28 Python打卡训练营
知识点回顾: 1. 类的定义 2. pass占位语句 3. 类的初始化方法 4. 类的普通方法 5. 类的继承:属性的继承、方法的继承 作业 题目1:定义圆(Circle)类 要求: 1. 包含属性:半径 radius。 2. …...
【OpenCV】基本数据类型及常见图像模式
是什么?能做什么?解决什么问题?为什么用它? OpenCV:是一个基于开源发行的跨平台计算机视觉库,实现 一、应用场景: 目标识别:人脸、车辆、车牌...自动驾驶医学影像分析视频内容理解与分析&…...