跟我一起学CMake
如今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的更多相关文章
- c++通过CMake实现debug开关
刚学cmake,很多东西还不是很懂,不过今天刚刚实现了通过CMake控制debug的开关,兴奋之余记录一下. 背景介绍: 最近参与到了一个大的C++项目,很多代码已经非常成熟,我来添加一些辅助功能,但 ...
- 学习用CMake来编写Qt程序
最近开始学习CMake,因为项目需求需要用到Qt,自带的qmake会出现许多问题(比如文件修改之后有时候qmake不会侦测到不会重新编译,需要手动去编译等),于是开始尝试使用CMake来编写Qt程序, ...
- cmake 简学
https://www.cnblogs.com/cv-pr/p/6206921.html
- 使用cmake自动构建工程
公司引擎是用cmake根据目标平台来构建工程的,刚接触的时候深深体会到cmake的方便:如果目标平台是windows,它可以帮你自动构建出vs工程:如果是安卓,自动构建出eclipse工程,如果是IO ...
- CMake入门以及学习笔记
使用cef3替代chromium内核开发产品过程中,第一次接触到系统构建,使用了最常见的CMake.CMake虽然在构建系统中用的比较多,但是使用到的程序员还是很少的.现在在国内能找到的相关资料和博客 ...
- 一起学习CMake – 03
这一节我们就一起来看看如何用CMake来链接自己写的lib库,如何进行这些库文件的管理. 一个团队共同开发软件时,一般都是分模块进行作业的,每个人负责整个软件中的一部分,然后再整合成一个完整的软件系统 ...
- CMake初步(1)
转自:<你所不知的OSG>第一章:CMake初步(1)http://bbs.osgchina.org/forum.php?mod=viewthread&tid=1189&f ...
- 使用 cmake 进行交叉编译
cmake 因为“又”要额外学一门语言而被诟病,但这并不妨碍越来越多私人项目用 cmake 来管理:autoconfig 确实是更好的发行工具,但用 cmake 管理项目显然更加的容易.如果要应用这些 ...
- 从零开始一起学习SLAM | 学习SLAM到底需要学什么?
SLAM涉及的知识面很广,我简单总结了 “SLAM知识树” 如下所示: (公众号菜单栏回复 “树” 可获得清晰版) 可以看到涉及的知识面还是比较广的.这里放出一张SLAM圈子里喜闻乐见的表达悲喜交加心 ...
随机推荐
- ZOJ-2008-Invitation Cards(dijkstra)
题意: 在有向加权图中G(V,E),邮局要从起点S向其他n个节点发送邮件,于是派出n个邮递员,分别到达其他n个地点发送,然后回到起点S,求出所有邮递员所经过的总路程的最小值. 分析: 正向一次dijk ...
- POJ 3177 Redundant Paths(重边标记法,有重边的边双连通分支)
大致题意: 为了保护放牧环境,避免牲畜过度啃咬同一个地方的草皮,牧场主决定利用不断迁移牲畜进行喂养的方法去保护牧草.然而牲畜在迁移过程中也会啃食路上的牧草,所以如果每次迁移都用同一条道路,那么该条道路 ...
- 【动态规划】【缩点】NCPC 2014 G Outing
题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1793 题目大意: 一辆公交车,上面M个座位,N个人(M<=N<=1000) ...
- 【模拟】NEERC15 G Generators(2015-2016 ACM-ICPC)(Codeforces GYM 100851)
题目链接: http://codeforces.com/gym/100851 题目大意: n个序列.每个序列有4个值x,a,b,c,之后按照x=(a*x+b)%c扩展无穷项. 求每个序列各取一个数之后 ...
- HDOJ(HDU) 2212 DFS(阶乘相关、)
Problem Description A DFS(digital factorial sum) number is found by summing the factorial of every d ...
- Java Topology Suite (JTS)与空间数据模型
JTS是Java的处理地理数据的API,它提供以下功能: 实现了OGC关于简单要素SQL查询规范定义的空间数据模型 一个完整的.一致的.基本的二维空间算法的实现,包括二元运算(例如touch和over ...
- cf601A The Two Routes
A. The Two Routes time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...
- UVA 11922 Permutation Transformer(Splay Tree)
题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18902 [思路] 伸展树+打标记. 用伸展树维护这个序列,使得能 ...
- 深度优先搜索DFS
使用递归(隐式地使用栈) 时间代价O(E+V) 输入:图G.起点start(int) 算法过程DFS(G, start) 1. 访问start节点,color[start]=visited 2. p ...
- 使用 virtualenv
关于virtualenv的资料: http://virtualenv-chinese-docs.readthedocs.org/en/latest/ 用的python3,但是搭建 Robot Fram ...