变量是CMake中的基本的存储单元,一般来说变量的类型是string,也可以根据需求解析成其他类型(例如整形等),通常是用set()来创建/设置一个变量,用unset()释放一个变量。变量名称是大小写敏感,CMake建议只用大小写字母、-和_对变量进行命名。
变量的范围
-
Block范围(Block Scope)
使用block()和endblock()命令对,来创建一个变量范围,具体可以参考对Block范围的描述。简单的来说,就是可以使用block()创建出的空间,也可以通过block()指定外部的变量,以便block()创建的空间内进行操作。
-
函数范围(Function Scope)
使用function定义一个函数,同时也会创建一个变量范围,与block创建的范围相比,主要有两点差异:
1、function默认可以使用上层范围内的变量,而block需要指定具体的变量才能访问,不指定无法访问;
2、function内创建的变量,如果不使用PARENT_SCOPE选项,无法传递到调用fcuntion的范围,而block内部创建的变量默认可以传递到外层。
更多请参考function的命令使用说明。
-
目录范围(Directory Scope)
-
持久化缓存(Persistent Cache)
CMake单独存储了名为"缓存条目"或"缓存"变量,这类变量的值是持久存储的,可以全局共享。在使用set()创建的时候需要使用CACHE选项指定。
变量的分类
-
普通变量
使用set()命令或者使用cmake -D创建的变量,如果在set()命令创建时候使用了CACHE选项,那么该变量会持久存储(在CMakeCache.txt文件中)。
-
CMake保留变量
CMake保留了一些变量命名方式,这些变量的使用与普通变量类似,但是建议工程在创建新的变量时避免使用CMake保留变量的命名方式,防止变量冲突,
CMake保留了如下几类变量命名方式:
1、以CMAKE_开头命名的变量(大小写不敏感)
2、以_CMAKE_ 开头命名的变量(大小写不敏感)
3、以下划线_开头,随后跟的是
-
CMake环境变量
CMake会继承调用方的环境变量,例如在shell中输入命令cmake .,此时该shell的环境变量会传递给CMake,可以通过cmake -E env name=value修改传入的变量,也可以通过set()修改,但是这些修改并不会影响到调用方(例如shell)的环境变量,也不会被CMake缓存起来,修改只会在当次运行的CMake构建中生效。可以使用cmake -E environment查看当前的环境变量。
变量的访问
CMake中变量的查找顺序
-
普通变量
访问普通变量的方式${VAR},其中VAR是变量名。
特别的,对于缓存变量,也可以使用$CACHE{VAR}进行访问,CACHE表示类型是缓存变量。
-
环境变量
访问变量的方式$ENV{VAR},其中VAR是变量名,ENV表示类型是环境变量。
下面以一个例子进行说明,创建2个普通变量:VAR1、VAR2;2个缓存变量:VAR1、VAR;3个环境变量:VAR2、VAR、VAR_EX,可以看到它们之间存在变量名冲突的情况,可以通过如下例子说明它们之间的访问顺序。
CMakeLists.txt文件内容:
cmake_minimum_required(VERSION 3.22)
project(variable_test)
set(VAR1 "normal-var1")
set(VAR2 "normal-var2")
set(VAR1 "cache-var1" CACHE STRING "prompt:cache var1")
set(VAR "cache-var" CACHE STRING "prompt:cache var")
set(ENV{VAR2} "env-var2")
set(ENV{VAR} "env-var")
set(ENV{VAR_EX} "env-var-ex")
message("VAR1: ${VAR1}")
message("VAR2: ${VAR2}")
message("CACHE VAR1: $CACHE{VAR1}, ${VAR1}")
message("CACHE VAR: $CACHE{VAR}, ${VAR}")
message("CACHE VAR2: $CACHE{VAR2}")
message("ENV VAR2: $ENV{VAR2}, ${VAR2}")
message("ENV VAR: $ENV{VAR}, ${VAR}")
message("ENV VAR-EX by nomal ref: ${VAR_EX}")
执行cmake .后的输出:
VAR1: normal-var1
VAR2: normal-var2
CACHE VAR1: cache-var1, normal-var1
CACHE VAR: cache-var, cache-var
CACHE VAR2:
ENV VAR2: env-var2, normal-var2
ENV VAR: env-var, cache-var
ENV VAR-EX by nomal ref:
上面的输出说明:
1、如果不使用$ENV,是不会从环境变量中去查找的。${ENV_VAR}的输出(空)证明了这一点;
2、在第一点的基础上,环境变量和普通变量存在于两个空间,互不干涉,$ENV{VAR}, ${VAR}的输出证明了这一点;
3、普通变量如果和缓存变量命名冲突,除非指定$CACHE来访问,否则会先找到普通变量,$CACHE{VAR1}, ${VAR1}的输出证明了这一点;
4、直接指定$CACHE来访问缓存变量,会跳过对普通变量的查找,$CACHE{VAR1}的输出证明了这一点。
附录:参考文档