CMake中set/unset的使用
Posted fengbingchun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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然后搜索缓存条目。如果找到缓存条目,则使用其值。否则,变量引用的的计算结果为空字符串。$CACHEVAR语法可用于直接查找缓存条目。
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(ENVCMAKE_PREFIX_PATH "github/fengbingchun")
message("CMAKE_PREFIX_PATH: $ENVCMAKE_PREFIX_PATH") # CMAKE_PREFIX_PATH: github/fengbingchun
set(ENVCMAKE_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(ENVCMAKE_PREFIX_PATH "github/fengbingchun")
message("CMAKE_PREFIX_PATH: $ENVCMAKE_PREFIX_PATH") # CMAKE_PREFIX_PATH: github/fengbingchun
unset(ENVCMAKE_PREFIX_PATH)
message("CMAKE_PREFIX_PATH: $ENVCMAKE_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:为上面的所有示例代码
可能的执行结果如下图所示:
GitHub: https://github.com/fengbingchun/Linux_Code_Test
以上是关于CMake中set/unset的使用的主要内容,如果未能解决你的问题,请参考以下文章
mongodb_修改器($inc/$set/$unset/$push/$pop/upsert......)
mongodb_修改器($inc/$set/$unset/$push/$pop/upsert......)