现代 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 多节点 前言 服务注册与发现是微服…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...