跟我一起学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圈子里喜闻乐见的表达悲喜交加心 ...
随机推荐
- POJ3126 Prime Path(BFS)
题目链接. AC代码如下: #include <iostream> #include <cstdio> #include <cstring> #include &l ...
- supesite 标签语法
http://blog.sina.com.cn/s/blog_a3c7706701018c8o.html
- HDOJ 2016 数据的交换输出
Problem Description 输入n(n<100)个数,找出其中最小的数,将它与最前面的数交换后输出这些数. Input 输入数据有多组,每组占一行,每行的开始是一个整数n,表示这个测 ...
- CodeForces 595A
题目链接: http://codeforces.com/problemset/problem/595/A 题意: 一栋楼,有n层,每层有m户,每户有2个窗户,问这栋楼还有多少户没有睡觉(只要一个窗户灯 ...
- 高效算法——J 中途相遇法,求和
---恢复内容开始--- J - 中途相遇法 Time Limit:9000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Su ...
- 浅谈层次化的AI架构
原文地址:http://www.aisharing.com/archives/86/comment-page-1 记得在以前的一篇文章中谈到了一种类似于双缓冲的AI结构,最近在整理一些东西的时候,发现 ...
- Power Calculus 快速幂计算 (IDA*/打表)
原题:1374 - Power Calculus 题意: 求最少用几次乘法或除法,可以从x得到x^n.(每次只能从已经得到的数字里选择两个进行操作) 举例: x^31可以通过最少6次操作得到(5次乘, ...
- 最常用的Eclipse快捷键【转载】
本文是一些最实用.最齐全.最省时间的 Eclipse 快捷键总结,这些快捷键可以让帮助你完成工作中的任何一个操作.欢迎参考. 1. ctrl+shift+r:打开资源 这可能是所有快捷键组合中最省时间 ...
- js中正则表达式的使用
1,作用:匹配一个字符串中的一些内容2,声明和使用: 1),构造函数 var reg=new RegExp(/表达式/) 2),字面量 var reg=/表达式/ 推荐使用 eg: var reg=/ ...
- 学习restful 架构
越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency).高 ...