[6] CMake总结 - 3 IF WHILE FOREACH MACRO FUNCTION

本帖子适用于初学者,StepByStep的入门CMake,CMake也是一门编程语言,只不过是针对编译和链接这种程序构建的过程的语言,学习基本语法就可以初步入门,后面需要什么复杂的功能,进阶掌握需要自己去查找官方文档,后续会给出查阅的一些方式

控制指令

  • IF
    语法:

    IF (expression)
      COMMAND1(ARGS ...)
      COMMAND2(ARGS ...)
      ...
    ELSE (expression)
      COMMAND1(ARGS ...)
      COMMAND2(ARGS ...)
      ...
    ENDIF (expression) # 一定要有ENDIF与IF对应

    另外一个指令是ELSEIF,总体把握一个原则,凡是出现IF的地方一定要有对应的
    ENDIF.出现ELSEIF的地方,ENDIF是可选的。
    IF (expression), expression不为:空,0,N,NO,OFF,FALSE,NOTFOUND或<var>_NOTFOUND,为真
    IF (not exp), 与上面相反
    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 dir) 当dir是目录时,为真
    IF (DEFINED var) 如果变量被定义,为真
    IF (var MATCHES regex) 此处var可以用var名,也可以用${var}
    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 (WIN32)
      MESSAGE(STATUS “This is windows.”)
    ELSE (WIN32)
      MESSAGE(STATUS “This is not windows”)
    ENDIF (WIN32)
    上述代码用来控制在不同的平台进行不同的控制,
    但是,阅读起来却并不是那么舒服,ELSE(WIN32)之类的语句很容易引起歧义。
    可以SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
    这时候就可以写成:
    IF (WIN32)
    ELSE ()
    ENDIF ()
    配合ELSEIF使用,可能的写法是这样:
    IF (WIN32)
      #do something related to WIN32
    ELSEIF (UNIX)
      #do something related to UNIX
    ELSEIF(APPLE)
      #do something related to APPLE
    ENDIF (WIN32)
  • WHILE
    语法:

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

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

  • FOREACH
    FOREACH指令的使用方法有三种形式:
    1. 列表
      语法:

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

      示例:

      AUX_SOURCE_DIRECTORY(. SRC_LIST)
      FOREACH(F ${SRC_LIST})
      MESSAGE(${F})
      ENDFOREACH(F)
    2. 范围
      FOREACH(loop_var RANGE total)
      COMMAND1(ARGS …)
      COMMAND2(ARGS …)

      ENDFOREACH(loop_var)

      从0到total以1为步进
      FOREACH(VAR RANGE 10)
      MESSAGE(${VAR})
      ENDFOREACH(VAR)
      输出:
      0
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
    3. 范围和步进
      语法:
      bash
      FOREACH(loop_var RANGE start stop [step])
      COMMAND1(ARGS ...)
      COMMAND2(ARGS ...)
      ...
      ENDFOREACH(loop_var)

      从start开始到stop结束,以step为步进,
      注意:直到遇到ENDFOREACH指令,整个语句块才会得到真正的执行。

      FOREACH(A RANGE 5 15 3)
      MESSAGE(${A})
      ENDFOREACH(A)
      输出:
      5
      8
      11
      14

函数和宏定义

函数会为变量创建一个局部作用域,而宏则使用全局作用域。范例:

  • 定义一个宏 hello
macro(hello MESSAGE)
   message(${MESSAGE})
endmacro()

# 调用宏 hello
hello("hello world")
  • 定义一个函数 hello
function(hello MESSAGE)
   message(${MESSAGE})
endfunction()

函数和宏可以通过命令 return() 返回,但是函数和宏的返回值必须通过参数传递出去。例如:

cmake_minimum_required(VERSION 2.8)
function(get_func RESULT)
    #RESULT 的值为实参的值,因此需要使用 ${RESULT}
    #这里使用 PARENT_SCOPE 是因为函数会构建一个局部作用域
    set(${RESULT} "Hello Function" PARENT_SCOPE)
endfunction()

macro(get_macro RESULT)
   set(${RESULT} "Hello Macro")
endmacro()

get_func(V1)
#输出 Hello Function
message(${V1}) 
get_macro(V2)
#输出 Hello Macro
message(${V2})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值