CMake简介

  • CMake 是做什么的?

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

  • CMake的工作流程

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

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

CMake 基本语法

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

文件组织

CMake能够处理cmake语言源码。

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

  1. 文件夹 (CMakeLists.txt),
  2. 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。

类似于下面这个命令

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

command调用语法为

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

注意:command名大小写不敏感

参数类型有

方括号形式

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

方括号不允许嵌套

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

例子:

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

引号形式

引号形式的就是放在""内部的参数,""会被当成一个参数传进函数。""内部的变量引用或者转义会

被解析。可以用\表示字符串还没有结束。

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

无引号形式

CMake支持参数不带任何引号,因为所有值都会转换成String。所有的参数会被封装成List。

List的分隔符为;,所以参数列表内如果一个字符串用;分割,;两边会被当成两个参数。

  1. \#这里有四个参数
  2. commandName(arg arg2 arg3;arg4)
  1. foreach(arg
  2. NoSpace
  3. Escaped\ Space
  4. This;Divides;Into;Five;Arguments
  5. Escaped\;Semicolon
  6. )
  7. message("${arg}")
  8. endforeach()

输出

  1. NoSpace
  2. Escaped Space
  3. This
  4. Divides
  5. Into
  6. Five
  7. Arguments
  8. Escaped;Semicolon

注释

注释分为行注释和块注释

  • 行注释

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

  • 块注释

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

    #[[这是多

    行注释]]

流程控制

条件控制

if(condition)

elseif(condition)

else()

endif()

  1. if(VAR1 MATCHES "Hello")
  2. message("this is hello")
  3. message("this is hello2")
  4. elseif(VAR1 MATCHES "world")
  5. message("this is world")
  6. message("this is world2")
  7. endif()

循环

for循环

语法为

  1. foreach(loop_var arg1 arg2 ...)
  2. COMMAND1(ARGS ...)
  3. COMMAND2(ARGS ...)
  4. ...
  5. endforeach(loop_var)

示例

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

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


  1. set(result 0)
  2. foreach(_var RANGE 0 100)
  3. math(EXPR result "${result}+${_var}")
  4. endforeach()
  5. message("from 0 plus to 100 is:${result}")

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

while循环

  1. while(condition)
  2. COMMAND1(ARGS ...)
  3. COMMAND2(ARGS ...)
  4. ...
  5. endwhile(condition)

自定义command

CMake系统内置了一批command,https://cmake.org/cmake/help/v3.7/manual/cmake-commands.7.html

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

function

  1. function(<name> [arg1 [arg2 [arg3 ...]]])
  2. COMMAND1(ARGS ...)
  3. COMMAND2(ARGS ...)
  4. ...
  5. endfunction(<name>)

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

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

函数原型声明时,只接受一个参数,那么调用函数时传递给函数的参数列表中,

从第二个参数(如果有的话)开始就会保存到ARGN。

例如

  1. function (argument_tester arg)
  2. message(STATUS "ARGN: ${ARGN}")
  3. message(STATUS "ARGC: ${ARGC}")
  4. message(STATUS "ARGV: ${ARGV}")
  5. message(STATUS "ARGV0: ${ARGV0}")
  6. message(STATUS "ARGV0: ${arg}")
  7. list(LENGTH ARGV argv_len)
  8. message(STATUS "length of ARGV: ${argv_len}")
  9. set(i 0)
  10. while( i LESS ${argv_len})
  11. list(GET ARGV ${i} argv_value)
  12. message(STATUS "argv${i}: ${argv_value}")
  13. math(EXPR i "${i} + 1")
  14. endwhile()
  15. endfunction ()
  16. argument_tester(arg0 arg1 arg2 arg3)

macro

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

macro( [arg1 [arg2 [arg3 ...]]])

COMMAND1(ARGS ...)

COMMAND2(ARGS ...)

...

endmacro()

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

  1. set(var "ABC")
  2. macro(Moo arg)
  3. message("arg = ${arg}")
  4. set(arg "abc")
  5. message("# After change the value of arg.")
  6. message("arg = ${arg}")
  7. endmacro()
  8. message("=== Call macro ===")
  9. Moo(${var})
  10. function(Foo arg)
  11. message("arg = ${arg}")
  12. set(arg "abc")
  13. message("# After change the value of arg.")
  14. message("arg = ${arg}")
  15. endfunction()
  16. message("=== Call function ===")
  17. Foo(${var})

结果为:

  1. === Call macro ===
  2. arg = ABC
  3. \# After change the value of arg.
  4. arg = ABC
  5. === Call function ===
  6. arg = ABC
  7. \# After change the value of arg.
  8. arg = abc

变量定义和引用

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

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

option只能定义OFF,ON的变量。

变量定义

set

set分为两种

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

例如

  1. //VA=a;b, VA是一个字符串list
  2. set(VA a b)
  3. //VA=a,VA是一个字符串
  4. set(VB a)
  • set CACHE变量

    CACHE变量会自动保存到CMakeCache.txt中,上次的结果下次继续用。
  1. set(<variable> <value>... CACHE <type> <docstring> [FORCE])

示例

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

option

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

变量引用

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

  1. ${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> "")方式设置。

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

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

Lists

在CMake中,所有的值都会被当成string来存储,但是在某些情况下, 多个string可以组成list。

例如在无""参数,多个字符串中间加了一个;。可以使用循环来遍历List

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

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

  1. list(LENGTH <list> <output variable>) //获得list长度
  2. list(GET <list> <element index> [<element index> ...]
  3. <output variable>) //获得list的某个位置元素
  4. list(APPEND <list> [<element> ...])//add
  5. list(FILTER <list> <INCLUDE|EXCLUDE> REGEX <regular_expression>)//清理
  6. list(FIND <list> <value> <output variable>) //查找
  7. list(INSERT <list> <element_index> <element> [<element> ...])
  8. list(REMOVE_ITEM <list> <value> [<value> ...])
  9. list(REMOVE_AT <list> <index> [<index> ...])
  10. list(REMOVE_DUPLICATES <list>)
  11. list(REVERSE <list>)
  12. list(SORT <list>)

CMake基本语法的更多相关文章

  1. CMake set 语法

    参考CMake官方文档:https://cmake.org/cmake/help/v3.14/command/set.html 1. 普通变量 set(<variable> <val ...

  2. CMake语法—缓存变量(Cache Variable)

    目录 CMake语法-缓存变量(Cache Variable) 1 CMake缓存变量 2 定义缓存变量 2.1 定义格式 2.2 定义示例代码 2.3 运行结果 2.4 小结 3 CMakeCach ...

  3. 《CMake实践》笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE

    <CMake实践>笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE <CMake实践>笔记二:INSTALL/CMAKE_INSTALL_PREFIX &l ...

  4. CMake实践(1)

    简介: 目录结构t1/main.cpp; t1/CMakeLists.txt 说明: main.cpp: #include <stdio.h> int main(){    printf( ...

  5. 跟我一起学CMake

    如今CMake使用的人数越来越多,包括我项目组里,很多大牛们在写Qt程序的时候都不用自带的qmake,貌似会出现很多问题,他们往往都用自己写的CMake来编译系统,今天我也和大家一起来学学这个高大上的 ...

  6. CMake 条件判断

    CMake简介 CMake 是做什么的? CMake是一套类似于automake的跨平台辅助项目编译的工具. 我觉得语法更加简单易用. CMake的工作流程 CMake处理顶级目录的CMakeList ...

  7. cmake简明使用指南

    cmake简明使用指南 Last update 2018/8/8 先执行cmake生成makefile,然后看看里面的内容,(至少在ubuntu16.04上的cmake3.5.1上),有如下内容提供: ...

  8. [转] CMake

    转载地址:https://www.cnblogs.com/lidabo/p/7359422.html cmake 简介 CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装( ...

  9. cmake使用方法详解

    cmake 简介 CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程).他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性 ...

随机推荐

  1. 大数相加(类似杭电acm1002)

    /*输入两个非常大的整数(完全超出了int.long的表示范围),这个整数的长度可能超过100位,计算并输出这两个数相加的结果.*/ //自己用题目所给的案例测试,输出是正确的,也能输出正确的结果,不 ...

  2. 《android开发艺术探索》读书笔记(六)--Drawable

    接上篇<android开发艺术探索>读书笔记(五)--RemoteViews [BitmapDrawable] 简单的图片 <!xml version="1.0" ...

  3. UVA - 11636 Hello World! (贪心)

    思路:复制次数最少并且可以部分复制,那么贪心地让当前尽量多的复制,如果最后一次复制会超过n,那就部分复制.即满足并且x尽量小. AC代码 #include <stdio.h> const ...

  4. HDU5992 - Finding Hotels

    原题链接 Description 给出个二维平面上的点,每个点有权值.次询问,求所有权值小于等于的点中,距离坐标的欧几里得距离最小的点.如果有多个满足条件的点,输出最靠前的一个. Solution 拿 ...

  5. chmod 与大写 X

    chmod(1) 手册页中对权限位的描述中提及到 rwxXst 六个权限标记, rwx 是几乎所有 Linux 初学者都会学到的,更进者会了解到 st 两个标记,但 X 却少有提起.所以笔者大致了解了 ...

  6. 关于adb is down 的两个解决方案

    在Android开发过程中经常遇到这样的一个问题,The connection to adb is down, and a severe error has occured. 解决方案一: 1.为了以 ...

  7. Python模拟登录成功与失败处理方式(不涉及前端)

    任务说明: (1) 用户输入用户名,如不存在此用户不能登录: (2) 用户在输入密码时,如果连续输入三次错误,则该用户被锁定一段时间; (3) 用户被锁定一段时间后,可再次进行尝试登录: 程序使用库: ...

  8. 用dd实现linux硬盘备份

    一个去年的老本,500G硬盘,空间各种捉急,准备迁移到公司的台式机上,却发现Linux上迁移环境没有Windows下那么方便,只能复制整块硬盘了. 从公司拿了一块1T的硬盘,插入移动硬盘盒(淘宝上搞的 ...

  9. 笔记︱决策树族——梯度提升树(GBDT)

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 本笔记来源于CDA DSC,L2-R语言课程所 ...

  10. HashMap和Hashtable的异同点

    HashMap和Hashtable的异同点 不同点: 1.HashMap的父类是AbstractMap,而Hashtable的父类是Dictiionary: 2.HashMap的key和value可以 ...