CMake中set/unset的使用

      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;e

set(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 e

message("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: beijing

if(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 addr

set(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: hello

unset(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/fengbingchun

set(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[@]}; do
		echo "  $0 ${param}"
	done

	exit -1
}

if [ $# != 1 ]; then
	usage
fi

flag=0
for param in ${params[@]}; do
	if [ $1 == ${param} ]; then
		flag=1
		break
	fi
done

if [ ${flag} == 0 ]; then
	echo "Error: parameter \"$1\" is not supported"
	usage
	exit -1
fi

if [[ ! -d "build" ]]; then
	mkdir build
	cd build
else
	cd build
fi

echo "==== 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:为上面的所有示例代码

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

      GitHubhttps://github.com/fengbingchun/Linux_Code_Test

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值