CMake流程控制
if命令
if命令语法如下:
|
|
if和elseif命令中的表达式可以有多种不同的形式。
基本表达式
最基本的表达式是一个常数:
|
|
CMake判断真假的逻辑比大多数编程语言要复杂一些。对于一个没有引号的常量,规则如下:
- 如果value值为1、ON、YES、TRUE、Y或一个非零的数字,那么它将被视为true,测试不区分大小写。
- 如果value值为0、OFF、NO、FALSE、N、IGNORE、NOTFOUND、空字符串或以-NOTFOUND结尾的字符串,它将被视为false,同样不区分大小写。
- 如果以上两种情况都不适用,它将被视为一个变量名或者字符串,并进一步评估。
|
|
CMake文档中提到的"fall through"案例为以下形式:
|
|
表达式为以下两种情况之一:
- 一个没有引号的(可能是未定义的)变量的名称。
- 一个带引号的字符串。
当使用未加引号的变量名时,该变量的值将与false常数进行比较。如果都不匹配,表达式的结果为true。一个未定义的变量被认为是一个空字符串,因此表达式结果为false。
|
|
当表达式是一个带引号的字符串时,规则如下:
- 在CMake 3.1或更高版本中,带引号的字符串总是为false,无论字符串的值如何(但这可以通过策略设置来重写)。
- 在CMake 3.1之前,如果字符串的值与现有变量的名称相匹配,那么带引号的字符串就会替换为该变量的名称(未带引号),然后继续测试。
逻辑运算符
CMake支持常见的AND、OR和NOT逻辑运算符,以及括号用于控制优先级顺序。
|
|
比较测试
CMake将比较测试分为三个不同的类别:数字、字符串和版本号,但语法形式都遵循相同的模式:
|
|
value1和value2,可以是变量名或(可能带引号)值。如果一个值与定义的变量名称相同,它将被视为一个变量。下表总结了三种类别比较测试支持的运算符:
数字 | 字符串 | 版本号 |
---|---|---|
LESS | STRLESS | VERSION_LESS |
GREATER | STRGREATER | VERSION_GREATER |
EQUAL | STREQUAL | VERSION_EQUAL |
LESS_EQUAL | STRLESS_EQUAL | VERSION_LESS_EQUAL |
GREATER_EQUAL | STRGREATER_EQUAL | VERSION_GREATER_EQUAL |
当进行数字比较时,如果一个操作数不是数字,CMake通常不会报错。根据数字和非数字的混合情况,表达式的结果可能是true或false。
|
|
版本号格式为major[.minor[.patch[.tweak]],其中每个组成部分都是一个非负的整数。当比较两个版本号时,首先比较major部分。只有当major部分相等时,才会比较minor部分,依此类推。缺少的部分被视为零。以下表达式均为true:
|
|
字符串是按字母顺序比较的,对字符串的内容不做任何假设,但要注意变量/字符串替换的潜在情况。
CMake还支持正则表达式测试字符串:
|
|
value遵循前面讲的变量/字符串替换规则,并与regex正则表达式进行比较。如果值匹配,表达式为true。
圆括号可以用来捕获匹配值的部分内容,MATCHES会设置名称为CMAKE_MATCH_<n>
的变量,其中<n>
是要匹配的组,整个匹配的字符串被存储在0组中。
|
|
文件系统测试
CMake还包括一组测试,用来查询文件系统。支持的表达式如下:
|
|
如果其中一个文件缺失或两个文件时间戳相同,IS_NEWER_THAN操作符返回true。使用IS_NEWER_THAN时,应该提供绝对路径,因为相对路径的行为没有定义好。
另一点需要注意的是,与其他大多数if表达式不同,在没有${}的情况下文件系统操作符不会执行任何变量/字符串替换,不管是否有引号。
存在性测试
最后一类if表达式支持测试各种CMake实体是否存在。
|
|
如果在使用if命令的地方存在一个指定名称的实体,那么上述命令都将返回true。
DEFINED
如果一个指定名称的变量存在,则返回true。变量的值并不重要,只测试它是否被定义,也可以用来检查环境变量是否被定义。
COMMAND
测试指定名称的CMake命令、函数或宏是否存在。
POLICY
测试一个特定的策略是否被CMake知道。
TARGET
如果指定名称的CMake目标已由add_executable、add_library或add_custom_target命令之一定义,则返回true。该目标可以在任何目录下定义,只要在执行if测试时它是已知的。
TEST
如果指定名称的CMake测试已由add_test命令定义,则返回true。
最后一个存在性测试在CMake 3.5和更高版本中可用:
|
|
如果变量listVar包含指定的值,则表达式将返回true,其中value遵循通常的变量或字符串替换规则,但listVar必须是一个列表变量的名称。
循环
foreach
CMake提供了foreach命令,能够在一组元素或值上进行迭代。foreach有几种不同的形式,其中最基本的是:
|
|
在上述形式中,对于每个argN值,loopVar被设置为该值并执行循环体。foreach更一般的形式如下:
|
|
使用这种形式时,必须提供ITEMS和LISTS中的一个或两个。当两者都提供时,ITEMS必须出现在LISTS的后面。允许listVarN列表变量为空列表。
|
|
上面的输出是:
|
|
foreach()命令也支持数值范围迭代:
|
|
loopVar被设置为[start, stop]范围内的每个值。如果提供了step选项,那么在每次迭代后,loopVar会加上step,当结果大于stop时,循环停止。
RANGE形式也可以只接受一个参数,像这样:
|
|
这相当于foreach(loopVar RANGE 0 value)
。
while
CMake提供的另一个循环命令是while:
|
|
中断循环
while和foreach循环都支持用break提前退出循环或用continue跳到下一个迭代的开始:
|
|