• CMake基本语法


    CMake简介

    • CMake 是做什么的?
      CMake是一套类似于automake的跨平台辅助项目编译的工具。 我觉得语法更加简单易用。

    • CMake的工作流程
      CMake处理顶级目录的CMakeLists.txt(CMake的配置文件,配置了子目录,编译目标,编译依赖等等),最后根据配置生成相应的MakeFile。

      使用make命令既可以进行编译。

    CMake 基本语法

    CMake定义了一套领域编程语言或者说脚本,称为CMake语言,支持变量定义、流程控制、函数、预制函数。

    文件组织

    CMake能够处理cmake语言源码。

    在一个项目中,cmake语言源码存在的位置分为以下两种。

    文件夹 (CMakeLists.txt),
    script脚本 (<script>.cmake,后缀不重要)
    
    • Directories

      在项目中,项目根目录的CMakeLists.txt是CMake的入口点,也就是说CMake命令先找CMakeL
      ists.txt,并执行内部的命令,生成构建系统。CMakeLists.txt应该定义了所有的编译控制。
      并用add_subdirectory()指定要处理的子文件夹(子项目),子文件夹内部也要有
      CMakeLists.txt文件,在CMake执行到add_subdirectory()时,CMake会进入到指定的子文
      件夹,然后在子文件夹内部寻找CMakeLists.txt执行,生成子文件夹的构建系统。子文件夹的
      源码的构建工作目录就是在子文件夹内。

    • Scripts
      stripts脚本如果要单独执行,需要cmake -P xxx.cmake。stripts脚本不会生成构建系统,
      因为在stripts脚本中,不允许指定构建目标。

    command

    CMake代码由一系列command的调用组成。包括if else 都属于command。
    类似于下面这个命令

    # 添加可执行目标hello, 参数为world.c
    
    add_executable(hello world.c)
    

    command调用语法为

    identifier(以空格隔开的参数表)
    参数可以用()括起来,表示这个单个参数。
    如if(TRUE OR (TRUE AND FALSE))
    

    注意:command名大小写不敏感

    参数类型有

    方括号形式

    [={len}[
    
    内部随便写点文本,cmake不会内部的变量引用或者换行进行处理。可以保持文本原始样子。${variable}
    
    -escape
    
    ]=]
    

    方括号不允许嵌套

    ={len}的意思:len表示结束符的=个数。当[=2]时, ]==] 才是结束符。

    例子:

    message([=3[
    This is the first line in a bracket argument with bracket length 1.
    No -escape sequences or ${variable} references are evaluated.
    This is always one argument even though it contains a ; character.
    The text does not end on a closing bracket of length 0 like ]].
    It does end in a closing bracket of length 1.
    ]===])
    
    

    引号形式

    引号形式的就是放在""内部的参数,""会被当成一个参数传进函数。""内部的变量引用或者转义会
    被解析。可以用表示字符串还没有结束。

    message("This is a quoted argument containing multiple lines.
    This is always one argument even though it contains a ; character.
    Both \-escape sequences and ${variable} references are evaluated.
    The text does not end on an escaped double-quote like ".
    It does end in an unescaped double quote.
    ")
    

    无引号形式

    CMake支持参数不带任何引号,因为所有值都会转换成String。所有的参数会被封装成List。
    List的分隔符为;,所以参数列表内如果一个字符串用;分割,;两边会被当成两个参数。

    #这里有四个参数
    commandName(arg arg2 arg3;arg4)
    
    foreach(arg
        NoSpace
        Escaped Space
        This;Divides;Into;Five;Arguments
        Escaped;Semicolon
        )
      message("${arg}")
    endforeach()
    

    输出

    NoSpace
    Escaped Space
    This
    Divides
    Into
    Five
    Arguments
    Escaped;Semicolon
    

    注释

    注释分为行注释和块注释

    • 行注释

      # 行注释,只能写一行内容

    • 块注释
      块注释有结尾有开头,可以写多行注释。用[[]]括起来,注意[要紧跟#。

      #[[这是多
      行注释]]

    流程控制

    条件控制

    if(condition)
    elseif(condition)
    else()
    endif()

    if(VAR1 MATCHES "Hello")
        message("this is hello")
        message("this is hello2")
    elseif(VAR1 MATCHES "world")
        message("this is world")
        message("this is world2")
    endif()
    

    循环

    for循环

    语法为

    foreach(loop_var arg1 arg2 ...)
      COMMAND1(ARGS ...)
      COMMAND2(ARGS ...)
      ...
    endforeach(loop_var)
    

    示例

    set(mylist "a" "b" c "d")
    foreach(_var ${mylist})
         message("当前变量是:${_var}")
    endforeach()
    
    

    上面是最简单的用法,还有一个foreach(loop_var RANGE start stop [step]) 的用法。

    
    set(result 0)
    foreach(_var RANGE 0 100)
         math(EXPR result "${result}+${_var}")
    endforeach()
    message("from 0 plus to 100 is:${result}")
    

    在foreach循环中,支持break()和continue()。

    while循环

    while(condition)
      COMMAND1(ARGS ...)
      COMMAND2(ARGS ...)
      ...
    endwhile(condition)
    

    自定义command

    CMake系统内置了一批command,https://cmake.org/cmake/help/v3.7/manual/cmake-commands.7.html
    但是开发者仍然能够自定义command。

    function

    function(<name> [arg1 [arg2 [arg3 ...]]])
      COMMAND1(ARGS ...)
      COMMAND2(ARGS ...)
      ...
    endfunction(<name>)
    

    在function内可以使用一些变量取得传入的参数信息。

    变量名 意义
    ARGC 参数个数
    ARGV 参数列表
    ARGV0 参数0
    ARGV1 参数1
    ARGV2 参数2
    ARGN 超出最后一个预期参数的参数列表

    函数原型声明时,只接受一个参数,那么调用函数时传递给函数的参数列表中,
    从第二个参数(如果有的话)开始就会保存到ARGN。

    例如

    function (argument_tester arg)
        message(STATUS "ARGN: ${ARGN}")
        message(STATUS "ARGC: ${ARGC}")
        message(STATUS "ARGV: ${ARGV}")
        message(STATUS "ARGV0: ${ARGV0}")
        message(STATUS "ARGV0: ${arg}")
    
        list(LENGTH ARGV  argv_len)
        message(STATUS "length of ARGV: ${argv_len}")
        set(i 0)
        while( i LESS ${argv_len})
             list(GET ARGV ${i} argv_value)
             message(STATUS "argv${i}: ${argv_value}")
    
             math(EXPR i "${i} + 1")
        endwhile()
    
    
    endfunction ()
    argument_tester(arg0 arg1 arg2 arg3)
    

    macro

    宏和function的作用是一样的,但是宏只是对字符串的简单替换。和define类似。

    macro( [arg1 [arg2 [arg3 ...]]])
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
    endmacro()

    下面简单的用一个实例区分两者的区别

    set(var "ABC")
    
    macro(Moo arg)
      message("arg = ${arg}")
      set(arg "abc")
      message("# After change the value of arg.")
      message("arg = ${arg}")
    endmacro()
    message("=== Call macro ===")
    Moo(${var})
    
    function(Foo arg)
      message("arg = ${arg}")
      set(arg "abc")
      message("# After change the value of arg.")
      message("arg = ${arg}")
    endfunction()
    message("=== Call function ===")
    Foo(${var})
    
    

    结果为:

    === Call macro ===
    arg = ABC
    # After change the value of arg.
    arg = ABC
    === Call function ===
    arg = ABC
    # After change the value of arg.
    arg = abc
    

    变量定义和引用

    CMake中,变量的值要么是String要么是String组成的List。

    CMake没有用=赋值的操作,只有通过set,option来定义变量。
    option只能定义OFF,ON的变量。

    变量定义

    set

    set分为两种

    • set普通变量
    set(<variable> <value>... [PARENT_SCOPE])
    

    例如

    //VA=a;b, VA是一个字符串list
    set(VA a b)
    //VA=a,VA是一个字符串
    set(VB a)
    
    • set CACHE变量
      CACHE变量会自动保存到CMakeCache.txt中,上次的结果下次继续用。
    set(<variable> <value>... CACHE <type> <docstring> [FORCE])
    

    示例

    set(ICD_LIBRARY "${PROJECT_BINARY_DIR}/lib" CACHE INTERNAL "ICD Library location" )
    

    option

    option(<option_variable> "help string describing option"
           [initial value])
    

    变量引用

    可以使用${variable_name} 。如果变量没有定义,返回空. 变量引用可以嵌套,变量引用的值从内往外计算。

    ${outer_${inner_variable}_variable}.
    

    CMake系统内置了一堆的变量,可以查阅

    https://cmake.org/cmake/help/v3.7/manual/cmake-variables.7.html

    环境变量的访问

    $ENV{VAR}

    变量只有string类型。变量名字大小写敏感,并且可以包含任意字符。
    采用set()/unset()定义和取消定义

    变量作用域存在于set的当前作用域

    变量作用域:

    • Function Scope
      在函数内部set的变量,作用域作用于当前函数及其调用的函数内。return 后就没了。

    • Directory Scope
      再CMakeLists.txt定义的变量(非function内部),作用域在当前Directory及其子Directory中。

    • Persistent Cache
      持久缓存。变量值会缓存到CMakeCache.txt中,下次运行,会使用CMakeCache中的值。

    采用set(variable value CACHE <type> "")方式设置。

    set(ICD_LIBRARY "${PROJECT_BINARY_DIR}/lib" CACHE INTERNAL "ICD Library location" )
    

    CMake将会自动把find_path和option的值放到CMakeCache中。

    Lists

    在CMake中,所有的值都会被当成string来存储,但是在某些情况下, 多个string可以组成list。
    例如在无""参数,多个字符串中间加了一个;。可以使用循环来遍历List

    set(srcs a.c b.c c.c) #sets "srcs" to "a.c;b.c;c.c"
    

    CMake专门提供了一个内置command来处理list

    list(LENGTH <list> <output variable>) //获得list长度
    list(GET <list> <element index> [<element index> ...]
         <output variable>) //获得list的某个位置元素
    list(APPEND <list> [<element> ...])//add
    list(FILTER <list> <INCLUDE|EXCLUDE> REGEX <regular_expression>)//清理
    list(FIND <list> <value> <output variable>) //查找
    list(INSERT <list> <element_index> <element> [<element> ...])
    list(REMOVE_ITEM <list> <value> [<value> ...])
    list(REMOVE_AT <list> <index> [<index> ...])
    list(REMOVE_DUPLICATES <list>)
    list(REVERSE <list>)
    list(SORT <list>)
    
    
  • 相关阅读:
    获取bootstrap table数据并封装 为json
    不自动切换eclipse视图
    over 分析函数之 lag() lead()
    oracle日期的处理
    表空间的创建
    分析函数 over用法 之row_number() runk_number
    oracle 序列
    Laravel 5
    使用hexo+github搭建免费个人博客详细教程
    windows7设置定时任务运行ThinkPHP框架程序
  • 原文地址:https://www.cnblogs.com/stonehat/p/7707578.html
Copyright © 2020-2023  润新知