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

首先,一个CMake要想运行,必须在同目录下有CMake脚本,说说是脚本,其实并没什么可怕,说白了就是一串CMake作者自己写的token语法分析文件--CMakeLists.txt。

这个文件比如你的项目有很多文件夹,必须在每个源代码文件夹下都有一个CMakeLists.txt.它会根据CMake命令中的add_subdirectory自动的递归分析。

讲完脚本的大致概念,让我们现在开始学写我们自己的脚本,在这里我引用CMake官网的相关Sample我们一起学习。注:在CMake中命令是不区分大小写的,而变量跟C一样是区分大小写的,这一点需要注意,我的默认习惯是命令用小写,比较顺手。

[1] cmake_minium_required(VERSION 2.6),版本号VERSION后面的数字根据你所决定的CMake最低版本号来决定,在这里我们用了官网sample的2.6。

[2] project(HELLO), 这代表你整个工程的工程名,同时CMake会根据这个工程名生成两个变量一个是${HELLO_SOURCE_DIR}一个 是${HELLO_BINARY_DIR},前者是当前source源文件所在路径,后者是生成的二进制文件锁在路径,如果你选用的CMake官方推荐的 外部编译模式(建立build,在build生成中间文件和目标文件,和源文件分离)这个时候两者的变量值是不同的,否则相同。

[3] add_subdirectory(Hello) add_subdirectory(Demo),在这里官方例子给出了本目录下有两个sub目录,所以你在顶层写完CMakeLists之后同时也必须在 你add_sub的目录下写相应的CMake脚本,CMake程序并不会再创建额外的进程来进行遍历,它会一层一层的逐步递归下去,其实这也是UNIX设 计的经典哲学--分而治之。

[4] 在Hello目录中: add_library(Hello hello.cxx),表明在这个sub中是生成一个Hello的库,第一个参数是库名,之后的源文件名(可以有多个)。

[5] 在Demo目录中:include_directories(${HELLO_SOURCE_DIR}/Hello)表明当前工程需要去include头 文件的路径为当前源代码所在路径下的Hello目录下,相当于GCC中的-I.另外要注意你如果依次往下写,比如include_directories 之后又来一句include_directories,这个是个追加过程而不是覆盖过程,同学看到可以不用担心自己之前的目录是否被覆盖了。

[6] link_directories(${HELLO_SOURCE_DIR}/Hello)表明当前工程所需要链接的库的路径所在地址,相当于GCC中的-L.

[7] add_executable(helloDemo demo.cxx demo_b.cxx),表明在当前Demo目录下会生成一个可执行文件,可执行文件的后缀名你不需要担心,CMake会自动判断当前环境合理加上。

[8] target_link_libraries(helloDemo Hello)表明可执行文件的生成必须需要库Hello的支持(包括前者include Hello的头文件)。

这个简单的sample讲完,接下来我们来看一下CMake的语法方面的注意点。

首先讲一下添加给GCC预处理宏的几种用法,有的同学一开始肯定想当然的给cmake .. -DMY_FLAG这样来用,其实这样是不对的,这样其实只是给CMake赋予的MY_FLAG的变量,而最终GCC是根本没有感知到该宏有没有定义的, 所以一般用法是两种,一种是在cmake ..的时候加一把CMAKE_CXX_COMPILE_FLAGS=xxx,另外一种是在CMake脚本内部手动加上一句 add_definitions(-DMY_FLAG)这两种方法都可以传给GCC相关的预处理宏,但是还是有区别的,前者针对的有效目录是所有目录,而 后者针对的目录是当前目录乃至当前目录以下的所有子目录,所以在这里需要特别注意。

command (args ...),arg之间可以用空格分离,如果arg中有空格需要用双引号括起来。

其次,CMake中对于字符串支持list格式,即一个变量可以支持字符串数组,比如set(VAR a b c)和set(VAR
a;b;c)两种形式都可以支持${VAR}为a b
c,这种格式时候foreach()进行循环遍历。但是这个时候要注意command(${VAR})表明同时执行了三次command(command
a; command b; command
c;)而command("${VAR}")注意其中的双引号表明只进行了一次遍历(command("a b c"))这个是需要我们注意的。

CMake也提供了流程控制,比如对于C中的if,CMake的写法也是如此if(var) command endif(var)(其中endif中的var可以写成空),判断语句可以有多重形式,可以验证变量是否为true,也可以是否FOUND,(empty, 0, N, NO, OFF, FALSE, NOTFOUND, or -NOTFOUND)等。

CMake同样提供了迭代结构,类似于Qt中的foreach,比如你设置了一个列表字符串var,这个时候你就可以简单的foreach(temp
${var}) command(${temp})
endforeach(${temp})来对var中的变量进行循环迭代处理,这个时候要注意有没有双引号的问题。

CMake也支持自定义编写宏和函数,函数可以像C语言一样内部定义局部变量,宏:macro(var VALUE)
command({var}) endmacro(var)和function(var VALUE) command(${var})
enfunciton(hello)等。

CMake支持include其他.cmake控制,类似于Qt中的pri可以写一些全局的通用脚本。同时CMake的add_definitions也
要重点理解一下,在CMake中,默认的变量命名是name:type=value,所以在cmake命令进行编译的时候可以动态的增加一些你自己的
CMake变量,比如cmake ..
-DMY_VALUE=ON,这个时候你的${MY_VALUE}就被定义了,在CMake脚本里面你可以用if({MY_VALUE})来进行判断当前
时候这个变量被指定,如果被指定了,你可以通过脚本里的add_definitons给gcc添加命令比如
add_definitons(-DMY_VALUE),这个时候的MY_VALUE才真正到了你的编译环境中,前者的MY_VALUE其实是给
CMake脚本用的,这里需要注意。

另外CMake中的set_target_properties也很强大,可以用他来做很多事情,我目前用到的就是给Qt自动
moc,set_target_properties(${target} PROPERTIES AUTOMOC
ON)这个时候你的target就会被自动moc不需要自己手动去添加了。

到这里,我们差不多简单的学习了一下CMake的相关语法,不得不说CMake是一个管理项目很棒的高级工具,要学会利用好这个工具,我们还需要投入更多
的精力来学习,所以一起努力来迎接CMake的美好吧,enjoy! 同时也希望志同道合的朋友可以互相交流,给我留言或者私信,谢谢!

跟我一起学CMake的更多相关文章

  1. c++通过CMake实现debug开关

    刚学cmake,很多东西还不是很懂,不过今天刚刚实现了通过CMake控制debug的开关,兴奋之余记录一下. 背景介绍: 最近参与到了一个大的C++项目,很多代码已经非常成熟,我来添加一些辅助功能,但 ...

  2. 学习用CMake来编写Qt程序

    最近开始学习CMake,因为项目需求需要用到Qt,自带的qmake会出现许多问题(比如文件修改之后有时候qmake不会侦测到不会重新编译,需要手动去编译等),于是开始尝试使用CMake来编写Qt程序, ...

  3. cmake 简学

    https://www.cnblogs.com/cv-pr/p/6206921.html

  4. 使用cmake自动构建工程

    公司引擎是用cmake根据目标平台来构建工程的,刚接触的时候深深体会到cmake的方便:如果目标平台是windows,它可以帮你自动构建出vs工程:如果是安卓,自动构建出eclipse工程,如果是IO ...

  5. CMake入门以及学习笔记

    使用cef3替代chromium内核开发产品过程中,第一次接触到系统构建,使用了最常见的CMake.CMake虽然在构建系统中用的比较多,但是使用到的程序员还是很少的.现在在国内能找到的相关资料和博客 ...

  6. 一起学习CMake – 03

    这一节我们就一起来看看如何用CMake来链接自己写的lib库,如何进行这些库文件的管理. 一个团队共同开发软件时,一般都是分模块进行作业的,每个人负责整个软件中的一部分,然后再整合成一个完整的软件系统 ...

  7. CMake初步(1)

    转自:<你所不知的OSG>第一章:CMake初步(1)http://bbs.osgchina.org/forum.php?mod=viewthread&tid=1189&f ...

  8. 使用 cmake 进行交叉编译

    cmake 因为“又”要额外学一门语言而被诟病,但这并不妨碍越来越多私人项目用 cmake 来管理:autoconfig 确实是更好的发行工具,但用 cmake 管理项目显然更加的容易.如果要应用这些 ...

  9. 从零开始一起学习SLAM | 学习SLAM到底需要学什么?

    SLAM涉及的知识面很广,我简单总结了 “SLAM知识树” 如下所示: (公众号菜单栏回复 “树” 可获得清晰版) 可以看到涉及的知识面还是比较广的.这里放出一张SLAM圈子里喜闻乐见的表达悲喜交加心 ...

随机推荐

  1. 并查集(逆序处理):HDU 5652 India and China Origins

    India and China Origins Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/ ...

  2. Sort Colors —— LeetCode

    Given an array with n objects colored red, white or blue, sort them so that objects of the same colo ...

  3. HDOJ(HDU) 2113 Secret Number(遍历数字位数的每个数字)

    Problem Description 有一天, KIKI 收到一张奇怪的信, 信上要KIKI 计算出给定数各个位上数字为偶数的和. eg. 5548 结果为12 , 等于 4 + 8 KIKI 很苦 ...

  4. 完美逆向百度手机助手5.0底部菜单栏 - Android Tabhost 点击动画

    先看看百度手机助手5.0的样子: 发现他是用一个CustomTabHost.java来实现底部TabHost点击效果的,很漂亮,点击Tab的时候文字会上跑,图片会从底部跑出来的一个小动画. 下面我用自 ...

  5. Django之牛刀初试

    一.Django安装 1.使用pip安装django pip3 inistall django 2.将django-admin加入到环境变量中 # 如果是windows的系统需要操作这一步,linux ...

  6. HDOJ 5184 Brackets 卡特兰数扩展

    既求从点(0,0)仅仅能向上或者向右而且不穿越y=x到达点(a,b)有多少总走法... 有公式: C(a+b,min(a,b))-C(a+b,min(a,b)-1)  /// 折纸法证明卡特兰数: h ...

  7. 技术型创业者easy遇到的三大问题

    关于创业这事儿.由于经历的事情实在是太多了,所以真是想到哪儿写到哪儿. 这一篇算是<杂记>的番外篇.我今天想说的东西太多了,实在是非常想和很多其它人讨论讨论关于创业的事情. 这样的感觉就像 ...

  8. C#中MessageBox使用方法大全(附效果图)

    我们在程序中常常会用到MessageBox. MessageBox.Show()共同拥有21中重载方法.现将其常见使用方法总结例如以下: 1.MessageBox.Show("Hello~~ ...

  9. Windows Minifilter驱动 - 调式 (4)

    写不论什么程序动态调试是很重要的.驱动开发也不例外. 通常如今写驱动的时候,都是在VM上跑的,调试手段基本也是本地windbg + 虚拟机. 虚拟机配置 我用的是win7, 第一步,看以下.成功运行后 ...

  10. Java基础知识强化之IO流笔记12:递归之递归解决问题的思想(图解)

    1. 使用递归计算5!的结果,递归思想的本质如下: 2. 下面就要使用代码实现这个递归: 递归实现分析: (1)做递归要写一个方法 (2)出口条件 (3)规律 代码实现如下: package com. ...