CMake变量可见性学习

CMake的内置变量与message打印的用法 一、预定义变量 PROJECT_SOURCE_DIR 工程的根目录 PROJECT_BINARY_DIR 运行cmake命令的目录,通常是${PROJECT_SOURCE_DIR}/build CMAKE_INCLUDE_PATH 环境变量,非cmake变量 CMAKE_LIBRARY_PATH 环境变量 CMAKE_CURRENT_SOURCE_DIR 当前处理的CMakeLists.txt所在的路径 CMAKE_CURRENT_BINARY_DIR ta... 阅读详情

CMake变量可见性


变量是CMake的基本存储单元,与别的语言的变量在理解上别无二致。CMake变量名大小写敏感,通常与数字、字母、_、-构成。

但是不同的是需要注意CMake变量的作用域。

主要有以下几个作用域

  • 目录作用域
  • 文件作用域
  • 函数作用域
  • Persistent Cache

add_subdirector vs include

假设有以下CMake Project

CMake_Test
|__Child
|	 |_ CMakeLists.txt
|_ CMakeLists.txt

其中CMake_Test目录中的CMakeLists.txt文件内容如下:

# parent CMakeLists.txt

cmake_minimum_required(VERSION 3.2)

project(Test_CMake)

set(A "parent")

add_subdirectory(child)

message("Parent A val ${A}")

child中的CMakeLists.txt

# child CMakeLists.txt

set(A "child")

message("Child A val ${A}")

输出

Child A val child
Parent A val parent

发现子目录的变量只会作用与自身并不会影响Parent目录。是什么原因?

实际上是add_subdirectory命令;在add_subdirectory被执行的时候,会创建一块独立的区域去执行子目录的CMakeLists.txt文件,同时会拷贝一份A的变量去独立区域,大概的示意图如下:

img

如图所以,Child中是Parent的副本。

改变CMakeLists.txt

# parent CMakeLists.txt

cmake_minimum_required(VERSION 3.2)

project(Test_CMake)

add_subdirectory(child)

set(A "parent")

message("Parent A val ${A}")

输出

Child A val 
Parent A val parent

得出结论 add_subdirectory只会对之前可见的变量做拷贝

现在改变Parent CMakeLists.txt的内容

# parent CMakeLists.txt

cmake_minimum_required(VERSION 3.2)

project(Test_CMake)

set(A "parent")

include(child)

message("Parent A val ${A}")

执行结果如下:

Child A val child
Parent A val child

与add_subdirectory相反include使得child与parent的scope一致,所以当我们include中set的时候会直接影响parent的值。

可以简单的理解为add_subdirectory是C++中的传值调用,include是C++中的传引用(指针)调用

img

那么如果是使用add_subdirectory那么如何在child中改变parent的值,实现如下:

# child CMakeLists.txt

set(A "child" PARENT_SCOPE)

message("Child A val ${A}")

输出

Child A val parent
Parent A val child

简单理解:

加入PARENT_SCOPE会直接修改parent目录下Ade值,但是并不会对当前目录下的copy A’进行修改

img

这时候可以看出add_subdirectory的时候是目录作用域,每个目录下的CMakeLists.txt是隔离的。

include时候是文件作用域,都作用在parent CmakeLists

Macro vs Function

# parent CMakeLists.txt

cmake_minimum_required(VERSION 3.2)

project(Test_CMake)

function(fun)
    set(A "fuc A")
endfunction()



set(A "parent")

fun()

# include(child/CMakeLists.txt)
add_subdirectory(child)

message("Parent A val ${A}")

输出

Child A val parent
Parent A val child

说明这时候function中set的变量就好像是函数定义的局部变量不会影响到外部

如果是传值呢????

# parent CMakeLists.txt

cmake_minimum_required(VERSION 3.2)

project(Test_CMake)

function(fun param)
    set(${param} "fuc A")
endfunction()



set(A "parent")

fun(A)

# include(child/CMakeLists.txt)
add_subdirectory(child)

message("Parent A val ${A}")

输出

Child A val parent
Parent A val child

就算是传值也是copy传递的。

img

使用macro代替function

# parent CMakeLists.txt

cmake_minimum_required(VERSION 3.2)

project(Test_CMake)

function(fun param)
    set(${param} "fuc A")
endfunction()

macro(funmacro param)
    set(A "macro fun")
endmacro()



set(A "parent")

# fun(A)
funmacro(A)

# include(child/CMakeLists.txt)
add_subdirectory(child)

message("Parent A val ${A}")

输出

Child A val child
Parent A val macro fun
-- Configuring done
-- Generating done

如果改为传参模式

		# parent CMakeLists.txt

cmake_minimum_required(VERSION 3.2)

project(Test_CMake)

function(fun param)
    set(${param} "fuc A")
endfunction()

macro(funmacro param)
    set(${param} "macro fun")
    message("param ${param}")
endmacro()



set(A "parent")

# fun(A)
funmacro(A)

# include(child/CMakeLists.txt)
add_subdirectory(child)

message("Parent A val ${A}")

输出

param A
Child A val child
Parent A val macro fun

通过结果可知,macro与include类似,与Parent工作在同一空间之中。

img

如果想要在add_subdirectory中定义函数改变Parent中的值,就需要在set中加入PARENT_SCOPE。

也就是说function与macro,前者是函数作用域后者是文件作用域。

Persistent Cache

缓存变量,拥有着独立的scope,只能通过特定的请求改变其值,比如set,uset的时候带上Cache选项。Cache变量在整个CMake工程的编译声明周期中都有效。工程中任意的目录都可以访问Cache变量,类似于全局静态变量。需要注意的是,CMake是从上到下进行解析CMakeLists,tx文件的。

set(cache_var1 “persistent-缓存变量1” CACHE STRING “abc”)

编译后,可以在bulid/CMakeCache.txt中看到该变量

参考

cmake-变量作用域

CMake Variable Scope

更多内容

更多内容

cmake常用变量   cmake 提供了很多内置变量,每一个变量都有它自己的含义,cmake官方关于变量的介绍为https://cmake.org/cmake/help/v3.5/manual/cmake-variables.7.html。在这份文档中,对变量进行分类,分为: 提供信息的变量、改变行为的变量、描述系统的变量、控制编译的变量等等。 一、提供信息的变量   提供信息的变量可以提供某种信息,通常只需要读取变量即可,而不需要对变量进行修改。   PROJECT_SOURCE_DIR 工程顶层目录,也就是顶层 CMak 阅读详情

相关推荐

【Cmake】Cmake基础学习

本文主要介绍项目编译工具cmake的基本用法

Jacky_Feng的博客 1392

【cmake】彻底弄懂cmake中的可见性/传递性 INTEFACE 问题

了解旧cmake和modern cmake的区别 是我们理解为什么cmake会进行这样的设计的关键。在cmake的早期版本中(2.xx,新版本叫modern cmake)是使用directory-oriented的方式来管理这些属性的传递性的。当你定义了一个属性,就意味着当前文件夹和子文件夹会使用这些属性。旧版本的cmake在2015年左右经历过一次大更新,全面升级为modern cmake。所有旧的命令都变为了target-oriented。以下是两者的对照表。

beidou111的博客 1888

CMake中常用的预定义变量

CMake中常用的预定义变量 PROJECT_NAME: 通过PROJECT指定的项目名称 project(Demo) PROJECT_SOURCE_DIR: 工程的根目录,上图中的Demo目录 PROJECT_BINARY_DIR: 执行cmake命令的目录,一般是在build目录,在此目录执行cmake .. CMAKE_CURRENT_SOURCE_DIR: 当前CMakeLists.t...

u012086173的博客 2399

【CMake 入门与进阶(14)】 CMake中变量的作用域(附代码)

所以函数内部的代码中,调用 set 之前,引用了变量 ABC,此时它会搜索函数内是否定义了该变量,如果没有,它会向外搜索,结果就找到了外部定义的变量 ABC,所以函数内部的第一条打印信息是"Hello World!从打印信息可知,事实并非我们上面所假设那样,函数内调用 set 去设置变量 ABC,并不是设置了外部变量 ABC 的值,而是在函数新创建了一个变量 ABC,这个与 C 语言是不一样的,跟 Python 很像,如果大家学过 Python 的话应该就知道。所以可知,函数内可以引用函数外部定义的变量。

cj_lsk的博客 839

CMake基础教程(3)cmake变量

主要有隐式定义和显式定义两种。隐式定义的一个例子是PROJECT指令,它会隐式的定义和两个变量;显式定义使用SET就可以通过来引用这个自定义变量了,它等价于HELLO_SRC=main.c。

二进制君 1万+

[CMake教程] 使用变量

CMake同样可以使用变量,比如当依赖文件过多或需要生成的项目繁杂,就可以使用变量统一管理,也便于以后的条件编译。 一、定义变量 CMake 定义变量分显式和隐式两种。 显式定义即使用 set 等语句,可以自定义变量名称。 隐式定义是在使用其他语句时自动创建的变量,如 project 是定义项目名称的,但在定义名称的同时,<projectname>_BINARY_DIR 和 <p...

淋曦的进击手记 7591

CMake常用命令(三)set命令

变量variable的作用域为调用set命令的函数或者当前目录,如果使用了PARENT_SCOPE选项,意味着该变量的作用域会传递到上一层(也就是上一层目录或者当前函数的调用者,如果是函数则传递到函数的调用者,如果是目录则传递到上一层目录),并且在当前作用域该变量不受带PARENT_SCOPE选项的set命令的影响(如果变量之前没有定义,那么在当前作用域仍然是无定义的;**结论:**选项PARENT_SCOPE定义的变量作用域在上一层函数,当前函数的变量必须使用不带选项PARENT_SCOPE定义。

qq_26849933的博客 3045

宋浩线性代数笔记

Miao-A-SongHao-Linear-Algebra-Notes bilibili 宋浩老师 “惊叹号” 系列 《线性代数》网课 笔记及时间点目录 Github项目地址:https://github.com/cy69855522/Miao-A-SongHao-Linear-Algebra-Notes ???? 前言 我发现吧,线代没记笔记真不行。 浩浩学习,天天向上。数学网课推荐????宋浩老师的免...

Knife丶小刀博客 4万+

CMake之构建配置

cmake构建目标文件,以及构建目标文件的属性设置等

u010378559的博客 4347

法律AI工具横评:Kimi Work与WorkBuddy,谁更适合法律人?

在人工智能技术日益普及的今天,自然语言处理(NLP)和大语言模型(LLM)正深刻改变着专业领域的工作范式。其核心原理在于通过海量数据训练,使模型能够理解、生成和推理人类语言。这一技术价值在于将从业者从繁琐、重复的信息处理工作中解放出来,极大提升工作效率与知识获取的便捷性。在法律、金融、咨询等对文本处理要求极高的行业,AI助手已展现出在文档分析、信息检索和内容生成方面的巨大潜力。具体到法律应用场景,AI工具能够辅助完成合同审查、法律检索和文书起草等核心任务,成为专业人士的得力助手。本文聚焦于近期备受关注的两款

weixin_30279671的博客 560

fins协议握手信号服务器响应,欧姆龙FinsTCP与FinsUDP协议解析 —— 利用Wireshark对报文逐字节进行解析详细解析附含报文模拟器等...

前言 – Fins欧姆龙这个协议网上极少有相关的模拟器、Tcp的这一块倒是有但是Udp的基本都是不可用1、 Fins协议结构也很简单 协议分为两种 一种tcp一种udp2、 Tcp比Udp的报文会多一层tcp的head头部3、 Udp回应报文在Wireshark中是解析不到(因为他按照UDP的格式去解那指定是解不到)好长时间没有更新过博客了、也比较懒= = 。一、Read(TCP)发包那么这个就很...

weixin_32491317的博客 4440

CMake: 设置编译选项

尽管检查这些变量的方式非常流行,但我们认为更健壮的替代方法是检查所需的标志集是否与给定的编译器一起工作,这样项目中实际上只使用有效的标志。我们学习了构建类型的相关内容,并且可以生成了不同构建类型的库,这一篇我们将介绍编译器选项的相关内容。是指在编译程序时,可以通过设置不同的选项来控制编译器的行为和生成的代码的特性。不同的编译器可能支持不同的选项,具体的选项和使用方法可以参考编译器的文档或者官方网站。此外,一些标志可能会被弃用,或者在编译器的较晚版本中引入。标志确定设置为给定编译器有效的标志,因此将包含在。

jjjstephen的博客 2744

Yolov8-pose关键点检测:通用倒瓶颈(UIB)搜索块结合C2f二次创新 | 轻量化之王MobileNetV4

通用倒瓶颈(UIB)搜索块结合C2f二次创新

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 613

【CMake】环境变量

什么是环境变量?环境变量是操作系统提供给所有运行中程序(进程)的一套全局键值对。CMake 作为一个程序,在启动时会继承它所在 shell(如命令行终端)的所有环境变量。CMake 自己也提供了一套机制来操作这些变量。1. 作用域 (Scope)全局性环境变量在同一个 CMake 进程内部的作用域是全局的。这意味着一旦你设置或修改了一个环境变量,你可以在同一个 CMake 运行过程中的任何地方(无论是在根目录的,还是在深层子目录的,或是在任何.cmake脚本文件中)访问到它。不被缓存。

2301_80224556的博客 1578

YOLOv11改进 | Neck篇 | 双向特征金字塔网络BiFPN助力YOLOv11有效涨点

本文给大家带来的改进机制是BiFPN双向特征金字塔网络,其是一种特征融合层的结构,也就是我们本文改进YOLOv11模型中的Neck部分,它的主要思想是通过多层级的特征金字塔和双向信息传递来提高精度。本文给大家带来的结构可以让大家自行调节网络结构大小,同时能够达到一定的轻量化效果,为什么发BiFPN呢因为它算是YOLO系列改进中的常青树了,大家可以借鉴它的双向特征思想来创新自己的Neck结构本文的BiFPN通过yaml文件配置可以让大家自行调配其结构。

Snu77的博客 9104

UGUI合批杀手:Mask/RectMask2D为何必断合批?

颜色缓冲负责记录像素颜色;模板缓冲负责记录“这个像素的模板值”(一个小整数);渲染时,你可以设定:只有模板值为 X 的地方才允许画;或者往某些区域写特定的模板值。类似于:先拿一支隐形笔在纸上画出一块区域,给它记一个编号“1”,后面的涂色动作只允许涂在“编号为1”的区域上。合批的前提:渲染状态不变,连续元素能一口气画完。材质、贴图、混合模式、Stencil、裁剪区域……都得一致。Mask / RectMask2D 的本质:在渲染状态上加规则——“只在某个区域内允许写像素”。

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 119

Cmake 内置变量

2019 May 31 cmake Cmake 内置变量 信息变量 CMAKE_SYSTEM 系统名称,例如 Linux-2.6.22、FreeBSD-5.4-RELEASE、Windows 5.1 CAMKE_SYSTEM_NAME 系统名称,如 Linux、FreeBSD、Windows CMAKE_SYSTEM_VERSION 系统版本,如 2.6.22 CMAKE_SYS...

测试 5056

4 屏 + 8 摄像头一开,谁在悄悄拖慢你的座舱域控?

如果你觉得座舱卡顿:❌ 别第一反应怪 SoC❌ 别盲目堆算力。

weixin_43199439的博客 148

cmake 变量学习

自定义变量分为隐式定义与显示定义两种由project 和enable_language命令定义的变量称为隐式变量。该命令字段主要是定义工程名,上述命令会隐式定义一些变量,以所定义的project name开头隐式定义变量名例如Nornal变量定义是采用set命令将创建变量,并将 值设置为,在被设置之前, 会被展开。value值可以跟多个,如果是多个value,则variable变量以list形式进行保存。

weixin_47139576的博客 1432

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

CMAKE 变量管理

变量分类 CMake的变量有其作用域,分全局作用域和局部作用域。 局部作用域变化: 1.在切换目录(即CMakeLists.txt变化) 2.调用函数时变化 3.macro不改变作用域。 局部变量 设置变量 set(<variable> <value>... [PARENT_SCOPE]) 如 set(<var "ABC" PARENT_SCOPE) # PAREN...

LaineGates的专栏 6616

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

CMake中的变量: CTest,CPack,CMake内部定义的变量

CMake中的变量: CTest,CPack,CMake内部定义的变量

qq_30150579的博客 2470

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

cmake默认变量,cmake命令

cmake默认变量,cmake命令

ERAtime的博客 801

【CMake】缓存变量

该作用域及其所有由此向下延伸的子作用域(通过`add_subdirectory()`或`function()`调用进入的新作用域)中,任何对`${MY_VAR}`的求值操作都会直接返回这个新设置的普通变量的值。缓存中存储的值依然。

2301_80224556的博客 1442

CMake中的变量: 信息变量

CMake中的变量: 信息变量

qq_30150579的博客 1240

[cmake]cmake中的变量

变量是CMake中的基本的存储单元,一般来说变量的类型是string,也可以根据需求解析成其他类型(例如整形等),通常是用set()来创建/设置一个变量,用unset()释放一个变量。变量名称是大小写敏感,CMake建议只用大小写字母、-和_对变量进行命名。

FL1768317420的博客 1047
上一篇: Leetcode768. 最多能完成排序的块 II
下一篇: 音视频同步原理
黑猫爱小鹿
博客等级 码龄8年 1万+粉丝 205原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值