CMake编程实践(四) 控制指令

文章目录

    • 控制指令
      • IF指令
        • 基本语法 if-else-endif:
        • 基本语法:if-elseif-endif
        • 正则比较表达式
        • 数字比较表达式:
        • 按照字母序的排列进行比较:
        • 小括号优先计算
      • WHILE指令
      • FOREACH指令
        • 使用列表 FOREACH(loop_var arg1 arg2 ...)
        • 使用范围 FOREACH(loop_var RANGE total)
        • 使用范围和步进 FOREACH(loop_var RANGE start stop [step])

控制指令

IF指令

基本的逻辑判断语句,和C类似,但有些需要注意的地方

  1. 在IF语句中可以直接使用变量,而不需要加${}
    2. 凡是出现 IF 的地方一定要有对应的ENDIF.出现 ELSEIF 的地方,ENDIF 是可选的。

基本语法 if-else-endif:

IF(expression)
    # THEN section.
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
ELSE(expression)
    # ELSE section.
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
ENDIF(expression)

另外一个指令是 ELSEIF,总体把握一个原则,凡是出现 IF 的地方一定要有对应的
ENDIF.出现 ELSEIF 的地方,ENDIF 是可选的。

基本语法:if-elseif-endif

IF(WIN32)
    #do something related to WIN32
ELSEIF(UNIX)
    #do something related to UNIX
ELSEIF(APPLE)
    #do something related to APPLE
ENDIF(WIN32)

表达式的使用方法如下:
IF(var),如果变量不是:空,0,N, NO, OFF, FALSE, NOTFOUND 或
_NOTFOUND 时,表达式为真。

IF(NOT var ),与上述条件相反。
IF(var1 AND var2),当两个变量都为真是为真。
IF(var1 OR var2),当两个变量其中一个为真时为真。
IF(COMMAND cmd),当给定的 cmd 确实是命令并可以调用是为真。
IF(EXISTS dir)或者 IF(EXISTS file),当目录名或者文件名存在时为真。
IF(file1 IS_NEWER_THAN file2),当 file1 比 file2 新,或者 file1/file2 其
中有一个不存在时为真,文件名请使用完整路径。
IF(IS_DIRECTORY dirname),当 dirname 是目录时,为真。

正则比较表达式

IF(variable MATCHES regex)
IF(string MATCHES regex)
当给定的变量或者字符串能够匹配正则表达式 regex 时为真。比如:
IF(“hello” MATCHES “ell”)
MESSAGE(“true”)
ENDIF(“hello” MATCHES “ell”)

数字比较表达式:

如果给定的字串或变量值是一个有效的数字并且不等号或等号满足的话,表达式返回真。
IF(variable LESS number)
IF(string LESS number)
IF(variable GREATER number)
IF(string GREATER number)
IF(variable EQUAL number)
IF(string EQUAL number)

按照字母序的排列进行比较:

如果给定的字串或变量值依字典序小于(或者大于,或者等于)右边给出的字串或变量值的话,表达式返回真。
IF(variable STRLESS string)
IF(string STRLESS string)
IF(variable STRGREATER string)
IF(string STRGREATER string)
IF(variable STREQUAL string)
IF(string STREQUAL string)

IF(DEFINED variable),如果给定的变量被定义了的话,该表达式为真。如果变量被设置了,它的值是真是假都无所谓。

小括号优先计算

IF((expression) AND (expression OR (expression)))
在小括号内的表达式会首先被计算,然后才按照先前介绍的运算来计算。有内嵌的括号时,最里的括号会作为包含它们的表达式的计算过程的一部分。
IF语句在CMake的历史上出现的相当早,它拥有一些需要特殊介绍的便捷特性。

IF表达式只有在其中有一个单一的保留值的时候,才会精简操作(即不做变量展开——译注);
这些保留值包括:如果是大小写无关的 ON,1, YES,TRUE,Y,它返回真;如果是OFF,0,NO,FALSE,N,NOTFOUND,*-NOTFOUND,IGNORE,它返回假。
这种特性非常合理,它为新作者提供了一种不需要精确匹配true或者false的便利性。这些值会被当做变量处理,即使它们没有使用${}语法的时候,也会被解引用。这意味着,如果你写下了这样的语句:

  IF(boobah)

CMake将会把它当做你写了

  IF(${boobah})

来处理。类似地,如果你写了

  if (fubar AND sol)

CMake将会便捷地把它解释为

  IF("${fubar}" AND "${sol}")

上述两例的后者确实是正确的书写方式,但是前者也是可行的。if语句中只有某些操作有这种特殊的变量处理方式。这些特殊的语句包括:
对于MATCHES运算符,待匹配的左边的参数首先被检查,用来确认它是否是一个已经定义的变量;如果是,该变量的值会被使用,否则就会用它的原始值。
如果MATCHES运算符没有左边的参数,它返回false,但不产生错误。
LESS,GREATER,EQUAL运算符的左边的参数和右边的参数会被独立测试,用来确认它们是否是被定义的变量;如果是,使用它们被定义的值,否则使用它们的原始值。
STRLESS,STRGREATER,STREQUAL运算符的左边的参数和右边的参数会被独立测试,用来确认它们是否是被定义的变量;如果是,使用它们被定义的值,否则使用它们的原始值。
VERSIONLESS,VERSIONGREATER,VERSIONEQUAL运算符的左边的参数和右边的参数会被独立测试,用来确认它们是否是被定义的变量;如果是,使用它们被定义的值,否则使用它们的原始值。
NOT运算符右边的参数会被测试用来确定它是否是布尔常量,如果是,就用这个常量;否则它会被当做一个变量然后被解引用。
AND和OR运算符的左边的参数和右边的参数会被独立测试,用来确认它们是否是布尔常量;如果是,就用这个常量,否则它们会被当做变量然后被解引用。

WHILE指令

WHILE 指令的语法是:

WHILE(condition)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDWHILE(condition)

其真假判断条件可以参考 IF 指令
例:

SET(INDEX_NUM 0)
WHILE(INDEX_NUM LESS 3) 
    MESSAGE("INDEX_NUM:"${INDEX_NUM})
    math(EXPR INDEX_NUM "${INDEX_NUM} + 1")
ENDWHILE()

FOREACH指令

FOREACH 指令的使用方法有三种形式:

使用列表 FOREACH(loop_var arg1 arg2 …)

FOREACH(loop_var arg1 arg2 ...)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDFOREACH(loop_var)

像我们前面使用的 AUX_SOURCE_DIRECTORY 的例子
AUX_SOURCE_DIRECTORY(. SRC_LIST)
FOREACH(F S R C L I S T ) M E S S A G E ( {SRC_LIST}) MESSAGE( SRCLIST)MESSAGE({F})
ENDFOREACH(F)

FOREACH(F "AAA" "BBB" "CCC")
    MESSAGE("FOREACH:"${F})
ENDFOREACH(F)

使用范围 FOREACH(loop_var RANGE total)

FOREACH(loop_var RANGE total)
ENDFOREACH(loop_var)
从 0 到 total 以1为步进,注意,是从0到total都会执行,例如0~3,会执行4次,和C还是有些不一样的。

FOREACH(INDEX RANGE 3)
    MESSAGE("FOREACH INDEX:"${INDEX})
ENDFOREACH()

使用范围和步进 FOREACH(loop_var RANGE start stop [step])

FOREACH(loop_var RANGE start stop [step])
ENDFOREACH(loop_var)
从 start 开始到 stop 结束,以 step 为步进,
举例如下

FOREACH(INDEX RANGE 3 10 2)
    MESSAGE("FOREACH INDEX:"${INDEX})
ENDFOREACH()

最终得到的结果是:
FOREACH INDEX:3
FOREACH INDEX:5
FOREACH INDEX:7
FOREACH INDEX:9
这个指令需要注意的是,直到遇到 ENDFOREACH 指令,整个语句块才会得到真正的执行。

以上基本涵盖了常用的控制语句,特别需要注意的是,在控制语句条件中使用变量,不能用${}引用,而是直接应用变量
名。

你可能感兴趣的:(C/C++,linux,CMake)