变量的传播规则:父会传给子

父模块里定义的变量,会传递给子模块。
image.png

变量的传播规则:子不传给父

变量的传播规则:子不传给父

image.png
如果父模块里本来就定义了同名变量,则离开子模块后仍保持父模块原来设置的值。
image.png

如果子模块需要向父模块里传变量怎么办?

可以用 setPARENT_SCOPE 选项,把一个变量传递到上一层作用域(也就是父模块)。
image.png

如果父模块里没有定义 MYVAR 的话,也可以用缓存变量向外部传变量(不推荐)。但是这样就不光父模块可见了,父模块的父模块,到处都可见。
image.png

除了父子模块之外还有哪些是带独立作用域的

环境变量的访问方式:$ENV{xx}

  • ${xx} 访问的是局部变量,局部变量服从刚刚所说的父子模块传播规则。
  • 而还有一种特殊的方式可以访问到系统的环境变量(environment variable):$ENV{xx}
  • 比如 $ENV{PATH} 就是获取 PATH 这个环境变量的值。

image.png
image.png

缓存变量的访问方式:$CACHE{xx}

此外,还可以用 $CACHE{xx} 来访问缓存里的 xx 变量。缓存变量和环境变量是不论父子模块都共用的,没有作用域一说。
image.png

${xx} 找不到局部变量时,会自动去找缓存变量

${xx} 当找不到名为 xx 的局部变量时,就会去在缓存里查找名为 xx的缓存变量。因此这里 CMAKE_BUILD_TYPE 虽然在代码里没被 set,但是他被-D参数固定在缓存里了。所以 ${CMAKE_BUILD_TYPE} 自动变成 $CACHE{CMAKE_BUILD_TYPE} 从而找到变量。

image.png

if (DEFINED xx) 判断某变量是否存在

if (DEFINED MYVAR)可以判断是否存在 MYVAR 这个局部变量或缓存变量。
image.png
值得注意的是:空字符串不代表变量不存在。因此即使是空字符串 DEFINED 也认为存在。
image.png

if (xx) 就可以判断某变量是否存在且不为空字符串

可以直接用 if (xx) 来判断是否为空字符串,因为空字符串等价于 FALSE
image.png

if (DEFINED ENV{xx}) 判断某环境变量是否存在

因为 $ENV{xx} 代表环境变量,因此在 setif 中也可以用 ENV{xx}来表示环境变量。

因为 set 的第一参数和 if 的参数都是不加 $ 的,所以要设置 ${x} 就变成了 set(x ...)。而设置 $ENV{x} 自然就是 set(ENV{x} ...) 咯。同理还可以用 if (DEFINED CACHE{x}) 判断是否存在这个缓存变量,但是 set(CACHE{x} ...) 就不行。
image.png

从 bash 设置环境变量试试看

image.png
image.png