【cmake开发(5)】cmake 设置常规变量、环境变量、内置变量;cmake 带参数编译和 -D 选项; c++源码通过-D 选项的宏定义进行条件编译

2023-09-22 11:18:02


在【cmake开发(3)】中,我们设置了 make install 安装目录。这就是变量控制。

一、CMake变量的定义

1、变量是CMake语言的最基本的存储单元。
2、变量的值始终为字符串类型,尽管一些命令将会将其理解为其他类型的值。
3、命令set()和unset()用于显式地设置或重置一个变量,其他命令有可能改变变量的语义。
4、变量名是区分大小写、可以是几乎所有的文本类型
5、变量可以通过set和unset的选项设置不一样的范围:函数范围,目录范围,永久缓存

1.1 定义常规变量

# 设置常规变量
set(<variable> <value> ...)

# 取消常规变量
unset(<variable>)

# 使用 ${<variable>} 语法进行引用。
${<variable>}

取消常规变量,我们可以使用 unset(PATH),也可以使用 set(PATH “”)

使用常规变量

set(PATH "/tmp" "/bin" "/lib")
message("${PATH}")

1.2 打印变量

如何打印一个变量?使用message函数,分为三个消息类型:FATAL_ERROR(致命错误) WARNING(警告) STATUS(正常)

message(WARNING "OpenCV requires Android SDK tools revision 14 or newer.")

1.3 环境变量

1、通过特殊的形式$ENV{varName}设置,要以ENV{varName}开头外。

set(ENV{PATH} "$ENV{PATH}:/opt/myDir")

2、 环境变量在 CMake 执行过程中具有全局范围,并且它们永远不会被缓存。
3、引用环境变量是形式为 $ENV{}。
4、 环境变量的初始化是调用进程时的初始化。我们可以使用 set() 命令设置环境变量,使用 unset() 命令取消环境变量。这些命令只影响正在运行的 CMake 进程,而不影响整个系统环境。更改环境变量的值,不会写入调用进程,也不会被后续的构建或检测进程看到。
5、在 Linux 中通过 export 命令,查看环境变量

1.4 持久缓存

什么是持久缓存的变量?
CMake 存储一组单独的 “缓存变量” 或 “缓存条目”,因为在项目构建树中的多次运行时,我们需要变量的值保持不变。

如何引用缓存的变量?
使用 $CACHE{} 或 ${} 引用缓存条目的值。

如何设置或取消缓存的变量?
一般的情况下,我们不会在源码文件中去设置或取消设置缓存的变量,我们只会引用它。

# 设置缓存条目
set(<variable> <value> ... CACHE <type> <docstring> [FORCE])

# 取消缓存条目
unset(<variable> CACHE)

为:

BOOL: 布尔 ON/OFF 值
FILEPATH: 文件的路径
PATH: 目录的路径
STRING: 目录的路径

1.5 持久缓存原理

CMakeCache.txt 文件用于存储缓存条目,第一次构建时会生成该文件,之后的构建并不会创建该文件。在引用缓存条目时,会去查找该文件,并返回值。

在使用 set() 命令时,默认情况下,如果缓存条目在 CMakeCache.txt 文件不存在,会创建缓存条目,并写入到 CMakeCache.txt 文件中。如果缓存条目在 CMakeCache.txt 文件存在,忽略 set() 命令,不会覆盖现有的缓存条目。但是我们想强制覆盖现有的缓存条目,我们可以 FORCE 选项。

set(BUILD_DEBUG "ON" CACHE STRING "Value Created by Me")
message("BUILD_DEBUG: ${BUILD_DEBUG}")

1.6 内置变量

    CMAKE_SOURCE_DIR
    PROJECT_SOURCE_DIR
    <projectname>_SOURCE_DIR 主cmake所在路径(静态)

CMake编译系统中源CMakeLists.txt目录。需要理解的一个概念是CMake编译系统中,源文件指的是CMakeLists.txt。这个是指整个编译系统最上层的CMakeLists.txt所在的目录,有点像是Workspace目录。

    CMAKE_CURRENT_SOURCE_DIR 当前正在处理的源文件目录

CMake编译树中可能包含多个CMakeLists.txt,前面我们知道顶层CMakeLists.txt由变量CMAKE_SOURCE_DIR表示,CMake编译系统会分别进入不同的CMakeLists.txt所在的目录执行cmake命令,此时进入的子目录就是CMAKE_CURRENT_SOURCE_DIR

更多解释可以查看:https://blog.csdn.net/weixin_39258979/article/details/110225829

二、 带参数编译

cmake编译参数

进入源码目录后

cmake . -LH  --查看之前编译参数

ccmake .  使用cmake gui界面进行查看和编辑编译用到的参数

源码目录下 INSTALL-SOURCE 文件后面有详细说明

举例:

一般常用参数如下:

-DCMAKE_INSTALL_PREFIX=/usr/local/mysql       \    #安装路径
-DMYSQL_DATADIR=/usr/local/mysql/data            \    #数据文件存放位置

-DCMAKE_BUILD_TYPE=:

debug, 充满了调试信息的版本,没优化,coding的时候测试用
release,一点调试信息都没有的版本,最终发布用。
relwithdebinfo(默认),优化过带有调试信息的版本,我在内测的时候用,甚至对最终发布也会用。它会有调试信息,所以只要有debugger,出了问题好查。

2.1 我们可以看到了 -D 选项,一般配合 option 命令

通过使用 cmake 工具,添加 -D 选项,通过设置变量,来改变选项。
-D 选项,语法如下:

-D <var>[:<type>]=<value>

可以忽略<type>类型,-D 选项中,-D 与<var>变量之间,可以有空格,但是 <var> 变量之后必须有 = 等号。

以选项变量 TEST_DEBUG 为例:

# 下面形式是相同的
cmake -DTEST_DEBUG=ON ..
cmake -D TEST_DEBUG=ON ..
# 如果我们要使用选项,一般赋值为 ON。其实选项的值只要是除 OFF 之外任意的值,都算使用了该选项,一般我们不使用这种形式
cmake -DTEST_DEBUG=ON ..
cmake -DTEST_DEBUG=123 ..
# 如果我们忽略使用选项,一般赋值为 OFF。其实赋值为空 或者 不出添加 -D 选项,都不会使用
cmake -DTEST_DEBUG=OFF ..
cmake -DTEST_DEBUG= ..
cmake ..

我们在Cmakelists 中一般使用option(<variable> "<help_text>" [value]) 配合 -D。给定说明的文本 和 默认值。在阅读 CMakeLists.txt 脚本时,我们可以很好的知道有哪些可选功能。

cmake_minimum_required(VERSION 3.0.0)

project(file_system)

option(TEST_DEBUG "option for debug" ON)

message("TEST_DEBUG Value: ${TEST_DEBUG}")

if(TEST_DEBUG)
	message("Select Option TEST_DEBUG")
	add_definitions(-DTEST_DEBUG")
endif()

你可以 option 命令,设置选项值 [value] 为 ON 或 OFF,如果默认是使用选项变量,设置为 ON 值。

如果我们想使用 TEST_DEBUG 功能,因为默认该功能是使用,则执行 cmake …。如果不想使用该功能,则执行 cmake -DTEST_DEBUG=OFF …。

2.2 c++源码通过-D 选项的宏定义进行条件编译

test.c 源码使用 TEST_DEBUG 宏,结合 预处理器定义C/C++ 条件编译

#ifdef TEST_DEBUG
...
#endif

参考

https://blog.csdn.net/weixin_39258979/article/details/110225829
https://blog.csdn.net/m0_57845572/article/details/118412228
https://blog.csdn.net/m0_57845572/article/details/118400027

更多推荐

Node.js环境安装与服务设置,结合内网穿透随时随地公网访问!

文章目录前言1.安装Node.js环境2.创建node.js服务3.访问node.js服务4.内网穿透4.1安装配置cpolar内网穿透4.2创建隧道映射本地端口5.固定公网地址前言Node.js是能够在服务器端运行JavaScript的开放源代码、跨平台运行环境。Node.js由OpenJSFoundation(原为

flutter产物以aar形式嵌入android原生工程

以前做的项目中,flutter都是作为module嵌入原生工程中,新公司项目却是以aar形式嵌入android工程,这种优点是原生工程不必配置flutter环境也能跑了,这里记录一下简单步骤。创建一个fluttermodule通过androidstudio创建一个fluttermodule,注意不要创建成flutter

KMP算法

卡尔老师视频链接KMP算法:KMP算法,全称为Knuth-Morris-Pratt算法,是一种用于字符串匹配的高效算法。它的主要思想是利用已经匹配过的字符信息,避免不必要的回溯,从而提高匹配的效率。KMP算法的核心是构建一个辅助数组next,用来记录模式串中每个字符对应的最长公共前缀和后缀的长度。通过这个数组,可以在匹

(二十七)mmdetection实用工具: Visualization

目录一、基础绘制接口二、基础存储接口三、任意点位进行可视化一、基础绘制接口可视化器(Visualizer):可视化器负责对模型的特征图、预测结果和训练过程中产生的结构化日志进行可视化,支持Tensorboard和WanDB等多种可视化后端。importtorchimportmmcvfrommmengine.visual

口袋参谋:新品上架如何做市场调查?这个方法超实用

很多商家在新品上架之前,都会对宝贝的市场行情进行调查分析,只有了解指定关键词下的行业市场数据,了解消费者需求,才能针对性的进行卖货。可是我们要是人工一点点去搜集,一点点去翻找,很多数据是没法进行人工去统计的,如果你要这样做的话,新品上架那是遥遥无期了。​那还有更好的办法吗?有些商家会专门去购买生意参谋里的市场洞察,对于

Linux cp命令使用指南:详细教程及实际应用场景解析

文章目录Linux中的cp命令使用指南1.简介1.1Linux操作系统简介1.2文件系统和目录结构1.3cp命令概述2.cp命令基本用法2.1复制文件2.2复制目录2.3复制多个文件或目录2.4递归复制2.5强制覆盖已存在文件2.6保留文件权限和属性3.高级用法3.1保留符号链接3.2仅复制更新的文件3.3拷贝到远程主

【Redis】深入理解 Redis 持久化机制 —— RDB 和 AOF

文章目录一、Redis的持久化二、RDB持久化机制2.1对RBD的认识RDB的概念RDB持久化机制的优缺点RDB的相关配置2.2RDB的触发时机2.2RDB的触发时机自动触发手动触发:SAVE和BGSAVE2.3RDB文件的处理保存RDB文件压缩RDB文件校验RDB文件三、AOF持久化机制3.1对AOF的认识AOF的概

【SLAM】视觉SLAM简介

【SLAM】视觉SLAM简介task04主要了解了SLAM的主流框架,清楚VSALM中间接法与直接法的主要区别在什么地方,其各自的优势是什么,了解前端与后端的关系是什么1.什么是SLAM2.VSALM中间接法与直接法的主要区别在什么地方,其各自的优势是什么?在SLAM(SimultaneousLocalizationa

Rsync学习笔记1

企业架构Web服务器的文件及时同步:1)能够理解为何要服务器的文件同步;2)能够简单描述实现文件同步的几种方式;3)能够实现服务器文件实时同步的案例;服务器同步文件的必要性:当业务代码发生改变,上传到web服务器的时候,因为架构已经不是单台服务器提供服务,而是由多台Web服务器提供服务,业务代码需要同时上传到多台Web

2023数学建模研赛华为杯E题思路-出血性脑卒中临床智能诊疗建模

E题出血性脑卒中临床智能诊疗建模三、请建模回答如下问题1血肿扩张风险相关因素探索建模。a)请根据“表1”(字段:入院首次影像检查流水号,发病到首次影像检查时间间隔),“表2”(字段:各时间点流水号及对应的HM_volume),判断患者sub001至sub100发病后48小时内是否发生血肿扩张事件。结果填写规范:1是0否

【Spring】BeanName 的自动生成原理

🎈博客主页:🌈我的主页🌈🎈欢迎点赞👍收藏🌟留言📝欢迎讨论!👏🎈本文由【泠青沼~】原创,首发于CSDN🚩🚩🚩🎈由于博主是在学小白一枚,难免会有错误,有任何问题欢迎评论区留言指出,感激不尽!🌠个人主页目录🌟一、默认name生成原理🌟二、id和name属性处理原理🌟一、默认name生成原理在

热文推荐