博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CMake基本语法
阅读量:6831 次
发布时间:2019-06-26

本文共 6202 字,大约阅读时间需要 20 分钟。

CMake简介

  • CMake 是做什么的?

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

  • CMake的工作流程

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

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

CMake 基本语法

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

文件组织

CMake能够处理cmake语言源码。

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

文件夹 (CMakeLists.txt),script脚本 (
  • 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.cadd_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()

输出

NoSpaceEscaped SpaceThisDividesIntoFiveArgumentsEscaped;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,

但是开发者仍然能够自定义command。

function

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

在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(
... [PARENT_SCOPE])

例如

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

示例

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

option

option(
"help string describing option" [initial value])

变量引用

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

${outer_${inner_variable}_variable}.

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

环境变量的访问

$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长度list(GET
[
...]
) //获得list的某个位置元素list(APPEND
[
...])//addlist(FILTER
REGEX
)//清理list(FIND
) //查找list(INSERT
[
...])list(REMOVE_ITEM
[
...])list(REMOVE_AT
[
...])list(REMOVE_DUPLICATES
)list(REVERSE
)list(SORT
)

转载于:https://www.cnblogs.com/stonehat/p/7707578.html

你可能感兴趣的文章
利用构建缓存机制缩短Docker镜像构建时间
查看>>
LeetCode31.下一个排列 JavaScript
查看>>
极简教程: 使用 matplotlib 绘制 GIF 动图
查看>>
数据库分片(Database Sharding)详解
查看>>
技术风险防控平台:打造金融交易系统的故障免疫能力
查看>>
怎样把酷狗音乐wav转化成高品质的MP3格式?
查看>>
浅谈算法学习
查看>>
区块链智能合约solidity入门
查看>>
js ES6 求数组的交集,并集,还有差集
查看>>
java-LearningRxjava-ch01-Thinking Reactively
查看>>
前端知识点——图片
查看>>
thinkphp源码分析(三)—自动加载篇(Loader的分析)
查看>>
Blink 真香
查看>>
一块听听:Mixin 主网上线语音直播文字稿
查看>>
brew安装错误brew Error: /usr/local must be writable!
查看>>
可应用于实际的14个NLP突破性研究成果(三)
查看>>
Git命令
查看>>
CentOS 6.9 安装最新版本 git
查看>>
[LeetCode] 41. First Missing Positive
查看>>
深入理解react
查看>>