美文网首页
cmake进阶内建变量及指令(六)

cmake进阶内建变量及指令(六)

作者: 仙人掌__ | 来源:发表于2019-10-03 20:34 被阅读0次

    前言

    cmake构建系统有一套自己的语法树

    定义变量

    • 定义和取消变量的语法:
      set(variable_name variable_value) #定义变量
      set(variable_name variable_value) #改变变量的值
      unset(variable_name) #取消变量的定义
      变量名区分大小写,且值始终是string类型的。cmake中 ON、YES、TRUE、非0数字、非空字符串代表真;OFF、NO、FALSE、0、空字符串("")代表假

    • 变量引用的形式为${variable_name},在IF语句和foreach(IN LISTS)中却是IF(variable_name)和foreach(var IN LISTS variable_name)

    • 环境变量引用的形式为$ENV{variable_name}

    • 变量嵌套引用,规则为从右往左依次进行替换,例如${outer_${inner_variable}veriable}

    创建sample9,创建如下setvar.cmake内容:

    # CMake 最低版本号要求
    cmake_minimum_required(VERSION 2.8)
    
    # 定义变量
    # 可以为一个值,也可以为多个值
    set(VAR1 on)
    set(VAR2 2;GREATER;1) #和set(VAR2 2 GREATER 1)等价
    set(VAR3 1 GREATER 2)
    set(VAR4 1)
    
    # 引用变量
    message(STATUS "this is a varibale 1 " ${VAR1})
    message(STATUS "this is a varibale 2 " ${VAR2})
    message(STATUS "this is a varibale 3 ${VAR2}")
    message(STATUS "this is a varibale 4 ${VAR${VAR4}}")    #实际上是输出${VAR1}
    IF(VAR)
    message(STATUS "VAR IS tru 1 " ${VAR})
    ENDIF(VAR)
    IF(${VAR2}) #IF语句会先将${VAR1} 替换成 2 GREATER 1(和2;GREATER;1等价),而这是一个为true的表达式
    message(STATUS "VAR IS tru 2 ${VAR2}")
    ENDIF()
    IF(${VAR3}) #IF语句会先将${VAR3} 替换成 1 GREATER 2 而这是一个为false的表达式
    message(STATUS "VAR IS tru 3 ${VAR3}")
    ENDIF()
    IF(VAR3)    #VAR3 本身为1 GREATER 2 为true
    message(STATUS "VAR IS tru 4 ${VAR3}")
    ENDIF()
    foreach(arg VAR3)   #arg在值VAR3中循环
        message(STATUS "VAR IS tru 5 ${arg}")
    endforeach()
    foreach(arg ${VAR3})    #foreach语句先将${VAR3}替换为1 GREATER 2,所以实际上可循环的值为1、GREATER、2
        message(STATUS "VAR IS tru 6 ${arg}")
    endforeach()
    foreach(arg IN LISTS VAR3)  #跟if语句一样,会把VAR3当变量处理,所以实际上可循环的值为1、GREATER、2
        message(STATUS "VAR IS tru 7 ${arg}")
    endforeach()
    foreach(arg IN LISTS ${VAR3}) #跟if语句一样,先将${VAR3}先进行替换,替换后的变量并没有定义,所以不进入此循环
        message(STATUS "VAR IS tru 8 ${arg}")
    endforeach()
    # 引用环境变量
    message(STATUS "ENV IS tru " $ENV{CMAKE_INCLUDE_PATH})
    

    依次执行如下命令

    export CMAKE_INCLUDE_PATH=/usr/local
    cmake -P setvar.cmake 
    

    输出如下:

    -- this is a varibale 1 on
    -- this is a varibale 2 on
    -- this is a varibale 3 2;GREATER;1
    -- this is a varibale 4 on
    -- VAR IS tru 2 2;GREATER;1
    -- VAR IS tru 4 1;GREATER;2
    -- VAR IS tru 5 VAR3
    -- VAR IS tru 6 1
    -- VAR IS tru 6 GREATER
    -- VAR IS tru 6 2
    -- VAR IS tru 7 1
    -- VAR IS tru 7 GREATER
    -- VAR IS tru 7 2
    -- ENV IS tru /usr/local
    

    cmake -P xxx.cmake 不会构建工程,只是执行cmake语法

    option指令

    option(var_name description defval)
    定义一个变量var_name,它的默认值为defval。如果cmake参数通过-var_name=otherval方式指定了var_name的值则其值为otherval,否则为defval

    # CMake 最低版本号要求
    cmake_minimum_required(VERSION 2.8)
    
    # 定义变量
    option(Build_DEBUG "debug or release?" OFF)
    option(Build_TEST "debug or release?" 1)
    if (Build_DEBUG) 
        message(STATUS "VAR2 IS tru 1 " ${Build_DEBUG})
    endif()
    message(STATUS "VAR2 IS tru 2 " ${Build_TEST})
    

    指定参数的cmake 命令 cmake -DBuild_DEBUG=OFF -P if_option.cmake;输出

    -- VAR2 IS tru 2 ON
    

    流程和循环语句

    cmake语法树里面也有自己的流程控制语句。

    • IF语句,它的格式为:

    if(expression)
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    elseif([expression2])
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    else([expression])
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    endif([expression])

    expression表达式有如下种类:

    • 变量
      1、YES,非0数字, ON,TRUE,Y,非空字符串为真
      2、NO,0,OFF,NO,FALSE,N, 空字符串(""),变量未定义为假
    • 单目逻辑表达式
      1、EXISTS
      2、COMMAND,
      3、DEFINED
      4、NOT
    • 双目逻辑表达式
      1、EQUAL, LESS, LESS_EQUAL, GREATER, GREATER_EQUAL
      2、STREQUAL, STRLESS, STRLESS_EQUAL, STRGREATER, STRGREATER_EQUAL
      3、VERSION_EQUAL, VERSION_LESS, VERSION_LESS_EQUAL, VERSION_GREATER, VERSION_GREATER_EQUAL
      4、AND
      5、OR
    • 函数表达式
      MATCHES
    • 多组合表达式
      用括号括起来
      (expr1) AND (expr2 OR (expr3))

    tips:
    在cmake中 ON代表真,OFF代表假
    在sample9中,新建if_option.cmake内容如下:

    # CMake 最低版本号要求
    cmake_minimum_required(VERSION 2.8)
    
    # 定义变量
    set(VAR1 ON)
    set(VAR2 OFF)
    set(VAR3 1 2 4)
    
    # IF引用变量,直接使用变量名代表对变量的引用。如果换成${变量名},则会先
    # 将${变量名}替换成它的值,然后取它的值所对应的的变量的值
    IF(VAR1)    #直接引用
    message(STATUS "VAR IS tru  1 " ${VAR1})
    ELSEIF(${VAR2}) #  ${VAR2}的值为OFF,而变量OFF未定义,所以为FALSE
    message(STATUS "VAR2 IS tru 2" ${VAR2})
    ELSE()
    message(STATUS "VAR3 IS tru 3 " ${VAR3})
    ENDIF()
    
    if(DEFINED VAR1) #变量是否定义过了
    message(STATUS "DEFINED 4 ")
    endif()
    if(NOT VAR2) #取变量的相反值
    message(STATUS "NOT 5 ")
    endif()
    if(VAR3 MATCHES ";") #变量是否含有";",一般在用set()设置变量传递多个参数时,该变量都含有";"
    message(STATUS "MATCHES ;")
    endif()
    

    执行命令 cmake -P if_option.cmake
    输出为:

    -- VAR IS tru  1 ON
    -- DEFINED 4
    -- NOT 5
    -- MATCHES ;
    

    foreach循环

    1. 第一种形式
      foreach(loop_var arg1 arg2 ...)
      ...
      endforeach(loop_var)
    # 第一种形式 foreach 循环 i依次取后面列表中的每个值,后面列表中的值可以是纯数字或者数字与字符串的混合
    foreach(I ddd ggg 2 4)
    message(STATUS "CUR I is " ${I})
    endforeach(I)
    

    输出

    -- CUR I is ddd
    -- CUR I is ggg
    -- CUR I is 2
    -- CUR I is 4
    
    1. 第二种形式
      foreach(loop_var RANGE total)
      endforeach(loop_var)

    从0开始直到total结束(包含total),这里就是对纯数字的遍历了

    2、第二种形式
    foreach(I RANGE 5)
    message(STATUS "CUR I is " ${I})
    endforeach(I)
    

    输出:

    -- CUR I is 0
    -- CUR I is 1
    -- CUR I is 2
    -- CUR I is 3
    -- CUR I is 4
    -- CUR I is 5
    

    3、第三种形式
    foreach(loop_var RANGE start stop [step])
    endforeach(loop_var)
    从start开始直到stop结束之间的值,可以设置步进值step。也是纯数字的遍历

    # 第三种形式,从1开始 5结束 步长2遍历,也是纯数字的遍历
    foreach(I RANGE 1 5 2)
    message(STATUS "CUR I is " ${I})
    endforeach(I)
    

    输出

    -- CUR I is 1
    -- CUR I is 3
    -- CUR I is 5
    

    4、第四种形式
    foreach(loop_var IN [LISTS [list1 [...]]] [ITEMS [item1 [...]]])
    endforeach(loop_var)

    set(A 0;1)
    set(B 2 3)
    set(C "4 5")
    set(D 6;7 8)
    set(E "")
    # 注意 LISTS 后面的必须是变量
    foreach(X IN LISTS A B C D E)
        message(STATUS "X=${X}")
    endforeach()
    # 这两种方式是等价的
    foreach(X IN ITEMS ${A} ${B} ${C} ${D} ${E})
        message(STATUS "X=${X}")
    endforeach()
    

    输出

    -- X=0
    -- X=1
    -- X=2
    -- X=3
    -- X=4 5
    -- X=6
    -- X=7
    -- X=8
    

    while循环

    while(condition)
    ....
    ...
    endwhile(condition)

    在sample9中创建while.cmake 内容为:

    set(condition 1)
    
    #while 循环
    while(condition LESS 5)
    message(STATUS "condition" ${condition})
    set(condition 10)
    endwhile(condition LESS 5)
    

    输出

    -- condition1
    

    内建变量

    • FILE指令

    文件操作相关指令,总共有如下几种情况:

    1.FILE(WRITE filename "message to write"... )

    在当前路径下的文件名filename名字中写入内容message to write,如果文件不存在则创建,会覆盖已存在内容

    2.FILE(APPEND filename "message to write"... )

    在当前路径下的文件名filename名字中写入内容message to write,如果文件不存在则创建,为追加写入

    3.FILE(READ filename variable)

    从当前路径的文件名filename中读取内容,并赋值给变量variable

    4.FILE(GLOB variable [RELATIVE path] [globbing expressions]...)

    在指定的路径[RELATIVE path]中根据指定的正则表达式[globbing expressions]搜索所有文件,将结果赋值给变量variable;...代表可以指定多个正则表达式

    5.FILE(GLOB_RECURSE variable [RELATIVE path] [globbing expressions]...)

    在指定的路径[RELATIVE path]中过滤掉指定的正则表达式[globbing expressions]之外的所有文件,将结果赋值给变量variable;...代表可以指定多个正则表达式

    list指令

    list指令和if语句一样,引用变量时也是直接使用变量名而非${变量名}

    • LENGTH返回列表的长度
      list(LENGTH <list_var><output_variable>)

    • GET返回列表中指定下标的元素;如果超出范围报错
      list(GET <list_var> <index> [<index> ...] <var1>[<var2>....])

    • APPEND添加新元素到列表中
      list(APPEND <list_var><element> [<element> ...])

    • FIND查找指定值的索引;不存在返回-1
      list(FIND <list_var><value><var>)

    • INSERT将值插入指定索引处
      list(INSERT <list_var><element_index> <element> [...])

    • REMOVE_ITEM交换两个值的位置
      list(REMOVE_ITEM <list_var> <value>[<value> ...])

    • REVERSE反转列表
      list(REVERSE <list_var>)

    • SORT排序列表
      list(SORT <list_var>)

    # CMake 最低版本号要求
    cmake_minimum_required(VERSION 2.8)
    
    # 定义变量
    set(VAR1 "OFF")
    set(VAR2 "DD")
    set(VAR3 2 GREATER 1)
    # 将长度存入len2变量 为1;len3变量 为3
    list(LENGTH VAR2 len2)
    list(LENGTH VAR3 len3)
    message(STATUS "len3 ${len3} len2 ${len2}")
    # 获取指定索引(0开始)的元素;分别将索引0 1的值写入变量list_var0和list_var1处;超出范围则报错
    list(GET VAR3 0 1 list_var0 list_var1)
    message(STATUS "list_var0 ${list_var0} list_var1 ${list_var1}")
    #将元素添加到列表中
    list(APPEND VAR3 0 1)
    message(STATUS "VAR3 ${VAR3}")
    #查找指定值的索引,如果不存在 返回-1
    list(FIND VAR3 5 var_index)
    message(STATUS "var_index ${var_index}")
    #插入值到指定索引处
    list(INSERT VAR3 2 insert)
    message(STATUS "VAR3 1 ${VAR3}")
    # 交换两个值的位置
    list(REMOVE_ITEM VAR3 2 insert)
    message(STATUS "VAR3 2 ${VAR3}")
    # 反转列表
    list(REVERSE VAR3)
    message(STATUS "VAR3 3 ${VAR3}")
    # 排序列表
    list(SORT VAR3)
    message(STATUS "VAR3 4 ${VAR3}")
    

    输出如下:

    -- len3 3 len2 1
    -- list_var0  list_var1 2;GREATER;2
    -- VAR3 2;GREATER;1;0;1
    -- var_index -1
    -- VAR3 1 2;GREATER;insert;1;0;1
    -- VAR3 2 GREATER;1;0;1
    -- VAR3 3 1;0;1;GREATER
    -- VAR3 4 0;1;1;GREATER
    

    相关文章

      网友评论

          本文标题:cmake进阶内建变量及指令(六)

          本文链接:https://www.haomeiwen.com/subject/ezwnyctx.html