现代 cmake (cmake 3.x) 操作大全
cmake 是一个跨平台编译工具,它面向各种平台提供适配的编译系统配置文件,进而调用这些编译系统完成编译工作。cmake 进入3.x 版本,指令大量更新,一些老的指令开始被新的指令集替代,并加入了一些更加高效的指令/参数。本文归纳了cmake 3.x 版本的常用指令,方便使用时备查。
关于cmake工具的简单介绍和VS Code cmake Tools 环境配置,可以参考我的另一篇博客。本文参考资料:【公开课】现代CMake高级教程 - Bilibili 小彭老师,CMake Reference Documentation
ps: 本文是大全类文档,适合备查,完整学习
cmake
强烈建议跟随官方tutorial,会有非常好的效果
cmake 项目构建流程
典型的cmake 项目构建流程如下:
-
配置阶段 Configure:根据编写的
CmakeLists.txt
文件,以及选择的编译系统,生成该系统的构建规则文件。(例如,对make
生成Makefile
,对MSVC
生成sln
(可以在VS中打开))cmake -B build
- 以上指令可以在当前目录下创建
build
目录,而不需要事先创建并进入 - 通过
-D
设置缓存变量,格式-D<OPTION>=<VALUE>
,如:- 编译器路径:
CMAKE_C_COMPILTER
,CMAKE_CXX_COMPILER
等 - 安装路径(在Configure阶段配置):
CMAKE_INSTALL_PREFIX
- 构建模式:
CMAKE_BUILD_TYPE
- 自定义缓存变量:
-Dvar:type=value
,可以将option
设定为OFF
,即表示不启用(会覆盖CMakeLists中的默认选项)
- 编译器路径:
-G
指定生成器(Generator,即构建系统),可以通过--help
查看支持的列表-A
指定架构(For MSVC build system)-T
指定工具链,例如使用ClangCL
:-T ClangCL,host=x64
(For MSVC build system)- 推荐使用
Ninja
作为生成器,效率较高
- 以上指令可以在当前目录下创建
-
编译阶段 Build:根据生成的构建规则,调用构建系统进行构建,这一步真正输出项目目标(可执行文件、共享库等)
cmake --build build
-
构建完成后,可以在
build
目录下找到输出结果(MSVC并不是直接放在build
下,而是在构建模式对应目录下(Debug
,Release
),这与其他不同)
项目配置变量
项目配置变量是控制项目构建,以及包含项目信息的关键变量。这些变量可以在命令行配置(缓存变量),也可以在CMakeLists内部修改。
项目构建模式
一般有四种项目构建模式:
- Debug 调试模式:不优化,生成调试信息
-O0 -g
- Release 发布模式:最优化,性能最佳
-O3 -DNDEBUG
MinSizeRel
最小体积发布 :生成项目文件小,性能优化不完全-Os -DNDEBUG
RelWithDebInfo
带调试信息发布-O2 -g -DNDEBUG
- 默认为Debug模式
可以通过在CMakeLists中增加默认选项脚本的方法修改默认选项为Release
if (NOT CMAKE_BUILD_TYPE)set(CMAKE_BUILD_TYPE Release)
endif()
项目信息
使用命令project
初始化项目信息
project(<PROJECT-NAME> [<language-name>...])
project(<PROJECT-NAME>[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]][DESCRIPTION <project-description-string>][HOMEPAGE_URL <url-string>][LANGUAGES <language-name>...])
- language: 指定项目使用语言,默认
C CXX
- 支持
C CXX ASM FORTRAN CUDA OBJC OBJCXX ISPC
- 支持
VERSION
字段:设置项目版本号,会自动配置相关变量
该命令将初始化名为project_name
的项目,并给相关变量赋值:
PROJECT_NAME
: 项目名称CMAKE_PROJECT_NAME
:根项目名称PROJECT_SOURCE_DIR
:项目源码路径,即初始化project的CMakeLists.txt
所在路径PROJECT_BINARY_DIR
:项目输出路径,通常是./build
路径CMAKE_CURRENT_SOURCE_DIR
:当前源码路径CMAKE_CURRENT_BINARY_DIR
:当前输出路径,即当前CMakeLists.txt
所在路径,子模块中指子模块路径- 更多属性,请参考project — CMake 3.25.1 Documentation
项目语言标准
一般通过如下指令设置标准(推荐放在project
指令前,会在project语言启用时检测)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
- 设置C标准为C11, C++设置CXX对应属性
CMAKE_C_STANDARD_REQUIRED
在启用语言时检查编译器是否支持该标准CMAKE_C_EXTENSIONS
是否启用GNU拓展语言特性(对跨平台有影响)
添加构建目标
构建目标主要有两种类型:
可执行文件 executable
使用add_executable
命令添加可执行文件目标:
add_executable(<name> [WIN32] [MACOSX_BUNDLE][EXCLUDE_FROM_ALL][source1] [source2 ...])
- 添加一个
name
的可执行文件目标,源文件来自source
- 可以是列表或者空格分开的多个文件名
- 也可以是变量
${var_name}
,目录的所有文件可以使用aux_source_directory
添加
- 其中,
source
可以省略(>3.11)
,并在后面以target_sources
的形式给出
库 library
add_library(<name> [STATIC | SHARED | MODULE][EXCLUDE_FROM_ALL][<source>...])
STATIC/SHARED
指定生成静态库/动态库,默认静态
另外还有对象库object library
add_library(<name> OBJECT [<source>...])
-
对象库不输出实际的库文件,而是可以直接被加入到其他构建目标中,如:
add_library(... $<TARGET_OBJECTS:objlib> ...) add_executable(... $<TARGET_OBJECTS:objlib> ...)
或者使用
target_link_libraries()
链接到对象库(CMAKE >3.12) -
注意:动态库不能直接引用静态库,因为动态库开启PIC,而静态库没有
- 解决方案:使用对象库替代静态库,或者为静态库配置PIC
set_property(TARGET target_name PROPERTY POSITION_INDEPENDENT_CODE ON)
- 解决方案:使用对象库替代静态库,或者为静态库配置PIC
-
另外,Windows平台如果要使用动态库,则需要添加宏
-
声明前添加
#ifdef _MSC_VER__declspce(dllimport) #endif
-
定义前加
#ifdef _MSC_VER__declspce(dllexport) #endif
-
配置构建目标
设置对象属性
set_target_properties(target_name PROPERTIESproperty_name value...)
使用set_target_properties
设置编译目标属性
这些属性包括(详细信息参考cmake-properties(7) — CMake 3.25.1 Documentation):
- 语言标准版本
- 编译器设置
- 目标输出位置
*_OUTPUT_DIRECTORY
链接三方库
使用target_link_libraries()
链接第三方库
target_link_libraries(<target> ... <item>... ...)
其中,item可以是:
- 库对象名(使用
add_library( IMPORTED)
引入) - 指向库文件的完整路径
- 库文件名,这会调用链接器自动搜索(在Linux下可以依据lib搜索)
优化方案(对使用cmake的三方库,限Linux):
find_package(LIBRARY_NAME REQUIRED)
target_link_libraries(<target> [PUBLIC] LIBRARY_NAME::library_target_name)
- 使用
find_package
会在/usr/lib/cmake
下增加.cmake
配置文件,cmake会自动搜索并链接相应的库。 - 另外,在链接库的时候,还会按照配置文件进行引用传播,引用其的对象自动引用其头文件目录。
编译时定义
使用target_compile_definitions
来配置编译时宏定义,这些定义可以在C/C++的宏中被使用
target_compile_definitions(target PUBLIC def)
- 将def设置到target的编译过程中
安装 install
install(TARGETS <target>... [destination])
以上命令用于安装对象到destination
子命令还可以是:
FILES
安装文件,如头文件等DIRECTORY
目录- 详见install — CMake 3.25.1 Documentation
部署 ctest
使用enable_testing
以启用ctest,ctest会自动执行命令,并匹配输出,自动化完成测试
以下示例增加一个ctest,并设置匹配的输出结果
add_test(NAME Usage COMMAND Tutorial)
set_tests_properties(UsagePROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number")
如果程序输出:Usage:[any]number
,就算正确通过
还可以将测试集写为函数,增强代码复用性
function (do_test target arg result)add_test(NAME Comp${arg} COMMAND ${target} ${arg})set_tests_properties(Comp${arg}PROPERTIES PASS_REGULAR_EXPRESSION "${arg} is ${result}")
endfunction()function (do_math_test target)do_test(${target} 4 2)do_test(${target} -25 "(-nan|nan|0)")
endfunction()
do_math_test(Tutorial)
Scripting Commands
- cmake命令不区分大小写,不过小写命令更推荐使用
- cmake 变量,参数等区分大小写
基础设置变量
使用set
命令来设置变量:
set(<variable> <value>... [PARENT_SCOPE])
- 如果value为空格分隔的字符串(不加引号),则被认为是列表
- 列表也可以用
"a;b"
(以分号分隔,加引号)等效
CMakeLists 文件结构
通常情况下,CMakeLists文件结构如下所示:
cmake_minimum_required(VERSION 3.0)project(project_name)...
cmake_minimum_required
指定了该项目生成需要的最小版本project()
指定项目名称,该命令以下部分都是该项目的配置
批量添加文件
aux_source_directory(<variable> <source_dir>)
此命令将添加source_dir
下的所有匹配文件到variable
中。(匹配文件根据项目语言决定)
文件操作指令
-
file
是cmake中的文件操作指令,可以完成复制、创建等一系列工作,也可以用于查找文件:file(GLOB <variable> CONFIGURE_DEPENDS <globbing-expressions>)
CONFIGURE_DEPENDS
可以在文件更新时自动更新cmake- 后面是查找文件的表达式,可以是通配符,如
*.cpp *.h
等
-
configure_file
可以完成文件配置,按照模板文件生成目标文件configure_file(Config.h.in ${PROJECT_SOURCE_DIR}/Config.h)
该命令会将模板文件
Config.h.in
中内容替换为实际配置内容,并将头文件写入source
目录下的Config.h
中,这样,可以完成对文件内容的修改,如启用选项,编辑#define
常量,或其他宏补全效果。常用模板格式如下:
#define FOO_STR "@FOO_STR@" #cmakedefine FOO_ENABLE
该命令会将
@
号包含的部分转换为cmake 执行环境中变量,使用cmakedefine
,如果cmake环境中存在变量,则会将其修改为#define FOO_ENABLE
即,如果在CMakeLists中设置
set(FOO_STR "Hello world") option(FOO_ENABLE True)
则模板文件中的定义将被输出为:
#define FOO_STR "Hello world" #define FOO_ENABLE
输出字符串
使用message
命令输出字符串
message([<mode>] "message text" ...)
其中模式可以为下列等:
STATUS
状态信息,前面带--
WARNING
警告信息,黄色警告FATAL_ERROR
致命错误INFO
默认,前面不带任何,白色,输出到stderr
列表 list
使用list
命令来构建,操作列表
Readinglist(LENGTH <list> <out-var>)list(GET <list> <element index> [<index> ...] <out-var>)list(JOIN <list> <glue> <out-var>)list(SUBLIST <list> <begin> <length> <out-var>)Searchlist(FIND <list> <value> <out-var>)Modificationlist(APPEND <list> [<element>...])list(FILTER <list> {INCLUDE | EXCLUDE} REGEX <regex>)list(INSERT <list> <index> [<element>...])list(POP_BACK <list> [<out-var>...])list(POP_FRONT <list> [<out-var>...])list(PREPEND <list> [<element>...])list(REMOVE_ITEM <list> <value>...)list(REMOVE_AT <list> <index>...)list(REMOVE_DUPLICATES <list>)list(TRANSFORM <list> <ACTION> [...])Orderinglist(REVERSE <list>)list(SORT <list> [...])
详见list — CMake 3.25.1 Documentation,[下一小节](#选项 option)会有应用选项的列表操作
选项 option
使用option
来生成选项,这些选项**会在ccmake
**或cmake-gui
中被显示
option(VAR_NAME [Description] [default_value])
option
中的默认选项会被命令行中的-D
选项覆盖
例如,
option(USE_MYMATH "Enable MyMath Library" True)
在cmake-gui
中,会显示如下,并可以被配置

一般项目情形下,需要使用option
来控制某个子功能是否启动,可以使用以下命令(接上例USE_MYMATH
):
if (USE_MYMATH)add_subdirectory(MathFunctions)list(APPEND EXTRA_LIBS MathFunctions)list(APPEND EXTRA_INCLUDES MathFunctions)
endif()
如果选项中启用USE_MYMATH
,才会进行库引用
生成器表达式
使用生成器表达式可以简化指令
$<$<var_name:value>:statement>
只有在变量=值时,才会表现为statement
,否则,生成器表达式的值为空
变量与作用域
默认变量传播规则:parent->child
如果要child->parent,则增加选项PARENT_SCOPE
Usage Requirements
在外部引用项目时,需要满足一些特定条件,这些条件称为usage requirements
只要项目开发者编写Usage Requirements,使用者就可以直接通过link完成寻找包和链接功能,而不需要另外的配置(添加include等),是现代cmake的主要构成。
同时,这些引用也是会传递的,不需要进行额外配置(但要保证配置正确)
在配置项目时,一般有三种配置选项PRIVATE|PUBLIC|INTERFACE
,其中,PRIVATE
仅限于项目自身编译时使用,INTERFACE
是Usage Requirements,它要求所有使用该库的项目添加该动作。PUBLIC
则是两者兼有。
例如,
add_library(MathFunctions mysqrt.cxx)
target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
以上指令会使所有引用该库(MathFunctions
)的项目自动引用该项目的头文件
相关文章:

现代 cmake (cmake 3.x) 操作大全
cmake 是一个跨平台编译工具,它面向各种平台提供适配的编译系统配置文件,进而调用这些编译系统完成编译工作。cmake 进入3.x 版本,指令大量更新,一些老的指令开始被新的指令集替代,并加入了一些更加高效的指令/参数。本…...

how https works?https工作原理
简单一句话: https http TLShttps 工作原理:HTTPS (Hypertext Transfer Protocol Secure)是一种带有安全性的通信协议,用于在互联网上传输信息。它通过使用加密来保护数据的隐私和完整性。下面是 HTTPS 的工作原理:初始化安全会…...

Docker的资源控制管理
目录 一、CPU控制 1、设置CPU使用率上限 2、设置CPU资源占用比(设置多个容器时才有效) 3、设置容器绑定指定的CPU 二、对内存使用进行限制 1、创建指定物理内存的容器 2、创建指定物理内存和swap的容器 3、 对磁盘IO配额控制(blkio&a…...
MMSeg无法使用单类自定义数据集训练
文章首发及后续更新:https://mwhls.top/4423.html,无图/无目录/格式错误/更多相关请至首发页查看。 新的更新内容请到mwhls.top查看。 欢迎提出任何疑问及批评,非常感谢! 摘要:将三通道图像转为一通道图像,…...

Redis使用方式
一、Redis基础部分: 1、redis介绍与安装比mysql快10倍以上 *****************redis适用场合**************** 1.取最新N个数据的操作 2.排行榜应用,取TOP N 操作 3.需要精确设定过期时间的应用 4.计数器应用 5.Uniq操作,获取某段时间所有数据排重值 6.实时系统,反垃圾系统7.P…...
无主之地3重型武器节奏评分榜(9.25) 枪械名 红字效果 元素属性 清图评分 Boss战评分 泛用性评分 特殊性评分 最终评级 掉落点 掉率 图片 瘟疫传播
无主之地3重型武器节奏评分榜(9.25) 枪械名 红字效果 元素属性 清图评分 Boss战评分 泛用性评分 特殊性评分 最终评级 掉落点 掉率 图片 瘟疫传播者 发射巨大能量球,能量球会额外生成追踪附近敌人的伴生弹 全属性 SSS SSS SSS - T0 伊甸6号-…...
什么是编程什么是算法
1.绪论 编程应在一个开发环境中完成源程序的编译和运行。首先,发现高级语言开发环境,TC,Windows系统的C++,R语言更适合数学专业的学生。然后学习掌握编程的方法,在学校学习,有时间的人可以在网上学习,或者购买教材自学。最后,编写源程序,并且在开发环境中实践。 例如…...
【c++】函数
文章目录函数的定义函数的调用值传递常见样式函数的声明函数的分文件编写函数的作用: 将一段经常使用的代码封装起来,减少重复代码。 一个较大的程序,一般分为若干个程序块,每个模板实现特定的功能。 函数的定义 返回值类型 函数…...
[golang gin框架] 1.Gin环境搭建,程序的热加载,路由GET,POST,PUT,DELETE
一.Gin 介绍Gin 是一个 Go (Golang) 编写的轻量级 http web 框架,运行速度非常快,如果你是性能和高效的追求者,推荐你使用 Gin 框架.Gin 最擅长的就是 Api 接口的高并发,如果项目的规模不大,业务相对简单,这…...

【开源】祁启云网络验证系统V1.11
简介 祁启云免费验证系统 一个使用golang语言、Web框架beego、前端Naive-Ui-Admin开发的免费网络验证系统 版本 当前版本1.11 更新方法 请直接将本目录中的verification.exe/verification直接覆盖到你服务器部署的目录,更新前,请先关闭正在运行的验…...

震源机制(Focal Mechanisms)之沙滩球(Bench Ball)
沙滩球包含如下信息: a - 判断断层类型,可根据球的颜色快速判断 b - 判断断层的走向(strike),倾角(dip) c - 确定滑移角/滑动角(rake) 走向 ,倾角,滑移角 如不了解断层的定义,可以先阅读:震…...
C++入门:多态
多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。C 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。1、纯虚函数声明如下: virtual void funtion1()0; 纯…...
华为OD真题_工位序列统计友好度最大值(100分)(C++实现)
题目描述 工位由序列F1,F2…Fn组成,Fi值为0、1或2。其中0代表空置,1代表有人,2代表障碍物。 1、某一空位的友好度为左右连续老员工数之和 2、为方便新员工学习求助,优先安排友好度高的空位 给出工位序列,求所有空位中友好度的最大值。 输入描述 第一行为工位序列:F1,F…...
[ruby on rails]MD5、SHA1、SHA256、Base64、aes-128-cbc、aes-256-ecb
md5 puts Digest::MD5.hexdigest(admin) sha1 require digest/sha1 puts Digest::SHA1.hexdigest(admin)base64 require base64 code Base64.encode64(admin) source Base64.decode64(code)aes-128-cbc # base64 解密数据 session_key Base64.decode64(session_ke…...
《NFL星计划》:拉斯维加斯突袭者·橄榄1号位
拉斯维加斯袭击者(英语: Las Vegas Raiders)又译拉斯维加斯侵略者或拉斯维加斯突击者,是一支主场位于美国内华达州拉斯维加斯的职业美式橄榄球球队,属全国橄榄球联盟 (NFL) 的美国橄榄球联合会 (AFC) 西区。实际上&…...

韩顺平Linux基础学习(1)
内容概括...

Rust学习入门--【6】Rust 基础语法
Rust 基础语法 变量,数据类型,注释,函数和控制流,这些是大部分编程语言都具有的编程概念。 本节将学习理解这些概念。 变量 Rust 是强类型语言,但具有自动判断变量类型的能力。这很容易让人与弱类型语言产生混淆。…...

LINUX提权入门手册
前言 发点存货 LINUX权限简介 在学习提权之前我们先了解一下linux里面的权限我们使用命令: ls -al即可查看列出文件所属的权限: 文件头前面都有一段类似的字符,下面我们仔细分析一下里面符号分别代表什么。 -rw-r--r-- 1 root root 第一个符号-的…...

MSI_MSI-X中断之源码分析
MSI_MSI-X中断之源码分析 文章目录MSI_MSI-X中断之源码分析一、 怎么发出MSI/MSI-X中断1.1 在RK3399上体验1.1.1 安装工具1.1.2 查看设备MSI-X信息1.1.3 验证MSI-X信息二、 怎么使用MSI/MSI-X三、 MSI/MSI-X中断源码分析3.1 IRQ Domain创建流程3.1.1 GIC3.1.2 ITS3.1.3 PCI MSI…...

Docker--consul
目录 前言 一、Consul 简介 1.1、 consul 概述 1.2 、consul 的两种模式 1.3、consul 提供的一些关键特性 二、Consul 容器服务更新与发现 三、consul 部署 3.2、查看集群信息 四、registrator服务器 consul-template 五、consul 多节点 前言 服务注册与发现是微服…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...

代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...

【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...

jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...

Spring AOP代理对象生成原理
代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】,这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...