CMake中set/unset的使用

article/2025/9/3 15:04:37

      CMake中的set命令用于将普通、缓存或环境变量(normal, cache, or environment variable)设置为给定值,其格式如下:指定<value>...占位符(placeholder)的此命令的签名需要零个或多个参数。多个参数将作为分号分割的list连接,以形成要设置的实际变量值零参数将导致未设置普通变量

set(<variable> <value>... [PARENT_SCOPE])
set(<variable> <value>... CACHE <type> <docstring> [FORCE])
set(ENV{<variable>} [<value>])

      变量是CMake语言中的基本存储单元(basic unit of storage)。它们的值始终是字符串类型尽管某些命令可能会将字符串解释为其它类型的值。set和unset命令显式设置或取消设置变量,但其它命令也具有修改变量的语义(semantics)。变量名称区分大小写,几乎可以包含任何文本,但建议使用仅有字母数字字符加上"_"和"-"组成的名称。
      变量具有动态范围(dynamic scope)。每个变量"set"和"unset"在当前范围内创建一个绑定(creates a binding):
      (1).Function Scope:由function命令创建的命令定义在调用时会在新的变量绑定范围内(new variable binding scope)处理记录的命令。变量"set"或"unset"绑定在此范围内,对当前函数和其中的任何嵌套调用可见,但在function返回后不可见
      (2).Directory Scope:源树(source tree)中的每个目录都有自己的变量绑定。在处理目录的CMakeLists.txt文件之前,CMake会复制当前在父目录(parent directory)中定义的所有变量绑定以初始化新目录范围。CMake脚本,当使用cmake -P时,将变量绑定在一个"directory"范围内。不在function调用内的变量"set"或"unset"绑定到当前目录范围。
      (3).Persistent Cache(持久缓存):CMake存储一组单独的"cache"变量或"cache entries(缓存条目)",其值在project构建树中的多次运行中保持不变。cache entries有一个独立的绑定范围,仅由显式请求(explicit request)修改,例如set和unset命令的CACHE选项。

      Variable References(变量引用)其形式为${<variable>},并在带引号的参数或不带引号的参数内进行评估。变量引用被指定变量或缓存条目的值替换,或者如果两者都未设置,则由空字符串替换。变量引用可以嵌套并从内向外进行评估。
      环境变量引用(environment variable reference)的格式为:$ENV{<variable>}
      缓存变量引用(cache variable reference)的格式为:$CACHE{<variable>}
      if命令有一个特殊的条件语法,它允许以短格式<variable>而不是${<variable>}引用变量。但是环境变量总是需要被引用为$ENV{<variable>}

      在评估变量引用时,CMake首先在function调用堆栈(如果有)中搜索绑定,然后返回到当前目录范围内搜索绑定(如果有)。如果找到"set"绑定,则使用其值。如果找到"unset"绑定,或者没有找到绑定,CMake然后搜索缓存条目。如果找到缓存条目,则使用其值。否则,变量引用的的计算结果为空字符串。$CACHE{VAR}语法可用于直接查找缓存条目。

      Environment Variables:和普通变量一样,有以下区别:
      (1).Scope:环境变量在CMake过程(process)中具有全局范围。它们永远不会被缓存
      (2).References:变量引用的形式为$ENV{<variable>},使用ENV运算符。
      (3).Initialization:CMake环境变量的初始值是调用进程(process)的初始值。可以使用set和unset命令更改值。这些命令只影响正在运行的CMake进程,而不影响整个系统环境(system environment).更改的值不会写回调用进程,后续构建或测试进程也看不到它们。

      Set Normal Variable:在当前function或目录范围内设置给定的<variable>。如果给定了PARENT_SCOPE选项,则变量将设置在当前范围之上的范围内。每个新目录或function命令都会创建一个新范围。也可以使用block命令创建范围。此命令会将变量的值设置到父目录(parent directory)、调用function或包含范围(encompassing scope).变量值的先前状态在当前范围内保持不变(例如,如果它之前未定义,它仍然是未定义的;如果它有一个值,它仍然是那个值)。

function(func)set(func_var1 "hello")set(func_var2 "beijing" PARENT_SCOPE)
endfunction()set(var a b c d e) # create a list
message("var: ${var}") # var: a;b;c;d;eset(var "a b c d e") # creates a string or a list with one item in it
message("var: ${var}") # var: a b c d emessage("func_var1: ${func_var1}") # func_var1:
message("func_var2: ${func_var2}") # func_var2:
func()
message("func_var1: ${func_var1}") # func_var1:
message("func_var2: ${func_var2}") # func_var2: beijingif(DEFINED func_var1)message("defined func_var1") # won't print
endif()
if(DEFINED func_var2)message("defined func_var2") # print
endif()set(var )
if(DEFINED var)message("defined var") # won't print
endif()

      Set Cache Entry:设置给定的cache <variable> (cache entry)。由于缓存条目(cache entry)旨在提供用户可设置的值,因此默认情况下不会覆盖现有的缓存条目。使用FORCE选项覆盖现有条目

      <type>必须指定为以下之一:
      (1).BOOL:布尔值:ON/OFF
      (2).FILEPATH:磁盘上文件的路径
      (3).PATH:磁盘上目录的路径
      (4).STRING:一行文字
      (5).INTERNAL:一行文字,用于内部。它们可用于在运行之间持久存储变量。使用这种类型意味着FORCE
      <docstring>必须指定为一行文本。
      如果在调用之前缓存条目不存在或给出了FORCE选项,则缓存条目将设置为给定值
      如果已经存在同名的普通变量,则缓存变量的内容将无法直接访问
      cache变量信息会存入CMakeCache.txt.

set(var "csdn addr" CACHE STRING "https://blog.csdn.net/fengbingchun")
message("var: ${var}") # var: csdn addr
set(var "github addr" CACHE STRING "https://github.com/fengbingchun") # 默认情况下不会覆盖现有的缓存条目
message("var: ${var}") # var: csdn addrset(var "github addr" CACHE STRING "https://github.com/fengbingchun" FORCE) # 使用FORCE选项覆盖现有条目
message("var: ${var}") # var: github addr# 如果已经存在同名的普通变量,则缓存变量的内容将无法直接访问
set(var2 "hello")
set(var2 "beijing" CACHE STRING "addr")
message("var2: ${var2}") # var2: hello
set(var2 "beijing" CACHE STRING "addr" FORCE)
message("var2: ${var2}") # var2: hellounset(var2)
set(var2 "beijing" CACHE STRING "addr" FORCE)
message("var2: ${var2}") # var2: beijing

      Set Environment Variable: 将Environment Variable设置为给定值。随后的$ENV{<variable>}调用将返回这个新值。此命令仅影响当前的CMake进程(process),而不影响调用CMake的进程,也不影响整个系统环境,也不影响后续构建或测试进程的环境
      如果在ENV{<variable>}之后没有给出参数或者如果<value>是一个空字符串,那么这个命令将清除环境变量的任何现有值。
      <value>之后的参数被忽略。如果发现额外的参会,将触发warning。

set(ENV{CMAKE_PREFIX_PATH} "github/fengbingchun")
message("CMAKE_PREFIX_PATH: $ENV{CMAKE_PREFIX_PATH}") # CMAKE_PREFIX_PATH: github/fengbingchunset(ENV{CMAKE_PREFIX_PATH} github/fengbingchun Linux_Code_Test) # CMake Warning (dev) at test_set.cmake:59 (set):#   Only the first value argument is used when setting an environment variable.#   Argument 'Linux_Code_Test' and later are unused.

      CMake中的unset命令用于取消设置变量、缓存变量或环境变量(variable, cache variable, or environment variable),其格式如下:

unset(<variable> [CACHE | PARENT_SCOPE])
unset(ENV{<variable>})

      Unset Normal Variable or Cache Entry:从当前范围中删除一个普通变量,使其变为未定义。如果存在CACHE,则删除缓存变量而不是普通变量。注意:在评估(evaluating)${VAR}形式的变量引用时,CMake首先搜索具有该名称的普通变量。如果不存在这样的普通变量,则CMake将搜索具有该名称的缓存条目(cache entry)。因此,unsetting普通变量可以暴露以前隐藏的缓存变量。要强制${VAR}形式的变量引用返回空字符串,使用set(<variable> ""),它会清除普通变量但保留它的定义
      如果PARENT_SCOPE存在,则该变量将从当前范围之上的范围中删除。

set(var "hello")
unset(var)
if(NOT DEFINED var)message("no defined var")  # print
else()message("defined var")
endif()func()
message("func_var2: ${func_var2}") # func_var2: beijing
unset(func_var2)
if(DEFINED func_var2)message("defined func_var2") # won't print
endif()

      Unset Environment Variable:从当前可用的环境变量中删除<variable>。随后的$ENV{<variable>}调用将返回空字符串。此命令仅影响当前的CMake进程(process),而不影响调用CMake的进程,也不影响整个系统环境,也不影响后续构建或测试进程的环境。

set(ENV{CMAKE_PREFIX_PATH} "github/fengbingchun")
message("CMAKE_PREFIX_PATH: $ENV{CMAKE_PREFIX_PATH}") # CMAKE_PREFIX_PATH: github/fengbingchun
unset(ENV{CMAKE_PREFIX_PATH})
message("CMAKE_PREFIX_PATH: $ENV{CMAKE_PREFIX_PATH}") # CMAKE_PREFIX_PATH:

      执行上述测试代码需要3个文件:build.sh, CMakeLists.txt, test_set.cmake

      build.sh内容如下:

#! /bin/bash# supported input parameters(cmake commands)
params=(function macro cmake_parse_arguments \find_library find_path find_file find_program find_package \cmake_policy cmake_minimum_required project include \string list set foreach message option if)usage()
{echo "Error: $0 needs to have an input parameter"echo "supported input parameters:"for param in ${params[@]}; doecho "  $0 ${param}"doneexit -1
}if [ $# != 1 ]; thenusage
fiflag=0
for param in ${params[@]}; doif [ $1 == ${param} ]; thenflag=1breakfi
doneif [ ${flag} == 0 ]; thenecho "Error: parameter \"$1\" is not supported"usageexit -1
fiif [[ ! -d "build" ]]; thenmkdir buildcd build
elsecd build
fiecho "==== test $1 ===="# test_set.cmake: cmake -DTEST_CMAKE_FEATURE=$1 --log-level=verbose ..
# test_option.cmake: cmake -DTEST_CMAKE_FEATURE=$1 -DBUILD_PYTORCH=ON ..
cmake -DTEST_CMAKE_FEATURE=$1 ..
# It can be executed directly on the terminal, no need to execute build.sh, for example: cmake -P test_set.cmake

      CMakeLists.txt内容如下:

cmake_minimum_required(VERSION 3.22)
project(cmake_feature_usage)message("#### current cmake version: ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}")
include(test_${TEST_CMAKE_FEATURE}.cmake)
message("==== test finish ====")

      test_set.cmake:为上面的所有示例代码

      可能的执行结果如下图所示:

      GitHub: https://github.com/fengbingchun/Linux_Code_Test


http://chatgpt.dhexx.cn/article/XY6Y2ivU.shtml

相关文章

Nginx缓存静态文件

nginx的一大功能就是完成静态资源的分离部署&#xff0c;减轻后端服务器的压力&#xff0c;如果给这些静态资源再加一级nginx的缓存&#xff0c;可以进一步提升访问效率。 第一步&#xff1a;添加nginx.conf的http级别的缓存配置 ##cache##proxy_connect_timeout 500;#跟后端服…

第一个c语言简单小程序

还有很多不会的地方&#xff0c;以后还要好好学习才行

C语言小程序实现电脑关机

一、需求分析 1.电脑在2分钟后关机&#xff1b; 2.输入 我最棒 则取消电脑关机 3.输入错误时&#xff0c;可以在2分钟内重复输入 二、代码 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() {char arr[10] {0};system("shutd…

【C/C++ 经典小程序(一)】

【1】九九乘法表 输出9*9口诀。共9行9列&#xff0c;i控制行&#xff0c;j控制列。 #include <stdio.h> void main() {int i,j,result;for (i1;i<10;i){ for(j1;j<i;j){resulti*j;printf("%d*%d%-3d",i,j,result);/*-3d表示左对齐&#xff0c;占3位*/}pr…

c语言编写简单实用的小程序,C语言编写一个小程序

用C/C编写一个小程序 #include using namespace std; int main() { int b[6]{1,2,2,3,4,5},i,j,k,l,m,n,p,c,d,*a[6]; for(j0;j<6;j) a[j]&b[j]; for(j0;j<6;j) { a[0]&b[j]; for(k0;k<6;k) { if(kj) continue; a[1]&b[k]; for(l0;l<6;l) { if(lj||lk)…

编写C语言的最简单小程序Hello world和函数使用

编写C语言的最简单小程序Hello world 一、示例一 1、编写demo.c程序 #include<stdio.h> int main() {printf("Hello world!");return 0; } 程序的第一行 #include <stdio.h> 是预处理器指令&#xff0c;告诉 C 编译器在实际编译之前要包含 stdio.h 文…

C语言小程序:通讯录(文件版)

在静态版本的通讯录里面实现了通讯录的基本逻辑&#xff0c;但是空间大小是固定的&#xff0c;这样子就会显得很不灵活&#xff0c;会有浪费空间和空间不足的问题&#xff0c;所以在动态版本的通讯里面我们通过动态内存开辟使用malloc函数给通讯录动态的开辟一块空间&#xff0…

C语言有趣的小程序

最近闲着没事写了一个C语言小程序,就当作是玩玩。 本小程序的各个功能都是通过dos命令来实现的。 运行结果如下图: 该小程序有以下几个功能: 1、启动计算器 2、新建记事本 3、打开画图板 4、定时关机(15s、30s、60s) 5、显示系统时间或修改 6、重启计算机 小程序源代码…

C语言小程序:通讯录(静态版)

哈喽各位老铁们&#xff0c;今天给大家带来一期通讯录的静态版本的实现&#xff0c;何为静态版本后面会做解释&#xff0c;话不多说&#xff0c;直接开始&#xff01; 关于通讯录&#xff0c;其实也就是类似于我们手机上的通讯录一样&#xff0c;有着各种各样的功能&#xff0c…

C语言小程序分享

本文为大一时所写的文章&#xff08;2017/4/23&#xff09;&#xff0c;文笔还很生疏&#xff0c;在很多问题上认识不深&#xff0c;算是在学校的微信公众号上的一个编程探究模块上的投稿&#xff0c;本人当时也参与了本模块的维护和管理。补档。 上个周末的一个下午&#xff0…

C语言小程序-学生成绩统计系统

C语言小程序-学生成绩统计系统 参考了 另一位博主的代码(https://blog.csdn.net/qq_36503589/article/details/53106983) 我后来写的成绩排序版本链接&#xff1a;https://blog.csdn.net/qq_43617268/article/details/103491760 功能介绍&#xff1a;本程序可以输入50人以内的…

C语言10个经典小程序——小白必备!

网上有很多的人说编程有多么多么无聊。。。。So Boring ! 。。。其实小编想说:不要管别人怎么说,别人说什么,做你自己喜欢做的事就好。坚持下来,你会发现编程的乐趣的。。。。当然,如果你觉得学习编程语言很痛苦,坚持了一段时间后无果,南无果断放弃未必不是一个好的选择…

C语言小程序:如何用代码“画”出一个爱心

利用ASCII编码第三个字符&#xff0c;作为基础&#xff0c;然后利用三个多重循环画出一个爱心出来。要使用控制台改变运行框大小和文字的颜色&#xff0c;黑白的爱心不免有些诡异。 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <math.h> #inclu…

我的第一个c语言小程序

标题&#xff1a;判断题答题小程序 Author: plc6666 软工专业 工科男 格言&#xff1a;总有人间一两风&#xff0c;填我十万八千梦。 文章目录 标题&#xff1a;判断题答题小程序 一.程序的由来二.程序的状况1.程序实现了颜色转换的功能2.程序能随机抽20题&#xff0c;不重复3.…

C语言10个经典小程序

【程序1】 题目&#xff1a;有1、2、3、4个数字&#xff0c;能组成多少个互不相同且无重复数字的三位数&#xff1f;都是多少&#xff1f; 1.程序分析&#xff1a;可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去       掉不满足条件的排列。 2.程序源…

用 C语言的写出几个小程序

系列文章目录 前言 1、第一章&#xff1a;求出一个整型数组中的最大值 2、第二章&#xff1a;打印出100~999之间所有的水仙花数 3、第三章&#xff1a;输入一个数&#xff0c;打印出n行杨辉三角 4、第四章&#xff1a;小只因跳楼梯问题 5、第五章&#xff1a;创建一个含是…

C语言小程序

1、猜数字游戏 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h>//猜数字游戏 int main() {int guess 0;//生成随机数//0~99 --> 1~100int ret rand() % 100 1;//生成随机数的函数printf("请猜数字 …

服务器登录原理,单点登陆(单点登录原理)

单点登录简介 SSO&CAS是什么 单点登录适合什么场景 单点登录的三种实现方式 CAS的几个重要知识点 CAS的实现过程 单点登录简介 单点登录(SingleSignOn&#xff0c;SSO)&#xff0c;就是通过用户的一次性鉴别登录。当用户在身份认证服务器上登录一次以后&#xff0c;即可获得…

单点登陆 SSO

参考文章 同域下的单点登录 &#xff08;sso.a.com、app1.a.com、app2.a.com&#xff09; 统一通过sso.a.com 登录&#xff0c;但有以下两个问题&#xff1a; 1、Cookie是不能跨域的&#xff0c;我们Cookie的domain属性是sso.a.com&#xff0c;在给app1.a.com和app2.a.com发送…

五、微服务版单点登陆系统(SSO)

微服务版单点登陆系统(SSO)实践 文章目录 微服务版单点登陆系统(SSO)实践一、单点登陆系统简介1. 背景分析2. 单点登陆系统概述3. 单点登陆系统解决方案设计 二、单点登陆系统初步设计1. 服务设计2. 工程结构设计 三、系统基础服务工程设计及实现1. 业务描述2. 表结构设计3. 工…