前言从上一篇的文章中,相信大家也了解了cmake这个东西,但是呢它不是只是看一下就能会的,这种东西还是要实践才能学会,那么如果你已经实践过了,就会体会到上一篇文章在实际中使用到底是多么的难搞,比如:
生成很多垃圾文件,这是我的第一个体会….需要手动去指定编译的文件无法指定编译器,编译选项等等很多东西….如果有子目录也不能完全适用….以及一些其他的问题….总的来说就是在真正项目中压根就没法适用的工程,那为什么我要写呢,因为那是我学习的过程,总不能一口吞下一个大胖子是不是,接下来的一系列文章我就会让cmake变得能在实际中使用,越来越自动化,更方便构建。。。
外部构建第一个问题,在运行cmake .后会产生很多垃圾文件,那么我们可以让它在一个build目录下去编译,生成的垃圾文件放在这个目录下就好了,不需要的时候直接清除即可。
可能有人会问,它不能像makefile一样直接make clean 或者make distclean清除编译的垃圾文件吗,我当时学的时候也谷歌过,但是,很遗憾没有,使用我才让它产生的垃圾文件放在build目录下,其实不能说是垃圾文件,只不过是一些中间文件,记录某些东西的,我用不上它,所以认为是垃圾…仅此而已。
对此官方的解释是:
cmakelists.txt 可以执行脚本并通过脚本生成一些临时文件,但是却没有办法来跟踪这些临时文件到底是哪些,因此,没有办法提供一个可靠的 clean 方案。
那怎么办呢?很简单,从cmake的语法我们就知道,它在构建的时候指定了path,也就是顶层cmakelists.txt 入口的路径。
cmake path那么很显然,它可以是相对路径而不是绝对路径,毕竟点‘.’ 表示当前路径, 点点‘..’ 表示上一级路径,那么我们可以新建一个build目录,然后在build目录下去运行:
cmake ..这在cmake中称之为外部构建(out-of-source build),而 cmake 强烈推荐的就是外部构建!
我自己也写了个build的脚本,内容非常简单,主要做两件事:
创建一个build目录(存在就不会重新创建的)进入build目录然后外部构建cmake生成makefile文件后运行make命令编译#!/bin/bashmkdir -p buildcd buildcmake ..make因此在编译的时候直接运行这个脚本即可,生成的内容全部都在build目录下。
这是原始目录.├── build.sh├── cmakelists.txt└── main.c0 directories, 3 files编译后在build目录下生成很多文件,包括 makefile、section2(可执行程序)等
cmakecache.txt cmakefiles cmake_install.cmake makefile section2补充一点,如果你想看到cmake生成的垃圾文件比你源码还多的时候,你就会爱死外部构建这种骚操作了~
自动查找源码不得不说,cmake是个很好的自动化构建工具,既然是自动化,那么很的东西都是自动的,比如查找源码,cmake就提供查找源码的命令:
aux_source_directory( )它的主要作用就是: 查找在某个路径下的所有源文件 ,注意,是所有源码文件,当你的目录下有很多个源码文件的时候,他就主动去查找了,哦,当然,它也只会查找源码文件,比如*.c 、 *.cpp 、*.cc啦,反正只要是源码就可以了,但是什么txt 、 *.h文件这些它是不会记录下来的。
dir :指定的目录(可以是绝对路径也可以是相对路径)variable:将输出结果列表储存在指定的变量中。反正这个命令就很方便,我在某个目录下有啥源码文件,我都会被记录到变量,然后在cmake直接使用即可。当然后续也有其他的命令去找源码文件,一口吃不了一个大胖子,先了解这个先,后续慢慢学习~
变量在cmake中,变量是十分常见的,我正在就简单讲解下基本的语法吧:
定义变量常用的函数是:
set(variable_name variable)取消定义变量是
unset(variable_name )variable_name :变量名字variable:变量的值变量的的值始终是string(字符串)类型,变量名字是区分大小写的,一般变量命名还是正常点比较好,别搞太多乱七八糟的特殊符号,只要数字、字母,下划线_ 、横线-就差不多了,变量的作用域也是有全局与局部之分,与c语言、java都差不多,我也不多说了。我的例程中全局变量是全部大写,局部变量是全小写的,也是比较好区分。
变量引用的形式为${variable_name},变量引用被变量的值替换,或者如果变量没有被设置,则由空字符串替换。变量引用可以嵌套,例如${outer_${inner_variable}veriable};环境变量引用的形式为$env{variable},并在相同的上下文中作为正常变量引用。
打印日志在cmake构建的时候,你可能不知道某些变量是啥内容,那么就在终端打印出来看看就好了,这根我们写代码中的printf函数差不多,给直接打一串字符串出来瞧瞧….
message([ message to display ...)首先呢,是指定消息的类型:
(无) = 重要消息;status = 非重要消息;warning = cmake 警告, 会继续执行;author_warning = cmake 警告 (dev), 会继续执行;send_error = cmake 错误, 继续执行,但是会跳过生成的步骤;fatal_error = cmake 错误, 终止所有处理过程;正常情况下我都是输出一些状态信息——status,打印个变量啦,打印下代码的执行顺序啦等等….
后面就是有些字符串信息了,变量在这里直接引用就好,毕竟变量本身就是字符串….
section3给出个实例代码:
当前目录存在2个c文件,分别是main.c、power.c就是简单计算x的y次方,纯粹是个demo,我自己也懒得写,并不是因为代码有多高深,所以这代码我是从网上找的,来自@潘伟洲大神的cmake测试代码:https://github.com/wzpan/cmake-demo。
main.c#include #include #include power.hint main(int argc, char *argv[]){ if (argc < 3){ printf(usage: %s base exponent \\n, argv[0]); return 1; } double base = atof(argv[1]); int exponent = atoi(argv[2]); double result = power(base, exponent); printf(%g ^ %d is %g\\n, base, exponent, result); return 0;}power.cdouble power(double base, int exponent){ int result = base; int i; if (exponent == 0) { return 1; } for(i = 1; i < exponent; ++i){ result = result * base; } return result;}然后就是cmakelists.txt文件:
# cmake 最低版本号要求cmake_minimum_required (version 2.8)# 项目信息project (section3)# 查找当前目录下的所有源文件# 并将名称保存到 dir_srcs 变量aux_source_directory(. dir_srcs)# 指定生成目标add_executable(section3 ${dir_srcs})相比于上一篇文章,我这个cmakelists.txt文件只是添加了aux_source_directory命令去自动扫描当前目录下的源码文件,并且保存到dir_srcs 变量中,仅此而已!!
然后在add_executable命令中,用${dir_srcs}变量代替指定的源码文件source1 source2 ... sourcen,当然你也可以打印一下${dir_srcs}变量到底保存了什么,如果不出意外的话,它保存的就是./main.c; ./power.c,表示的是当前目录下的main.c、power.c这两个文件,而分号代表它是一个list,后续会讲解怎么去提取list的内容….
message(status ${dir_srcs})然后用外部构建的方式去编译代码:
jie@pc:~/github/cmake/section3$ ./build.sh -- the c compiler identification is gnu 7.4.0-- the cxx compiler identification is gnu 7.4.0-- check for working c compiler: /usr/bin/cc-- check for working c compiler: /usr/bin/cc -- works-- detecting c compiler abi info-- detecting c compiler abi info - done-- detecting c compile features-- detecting c compile features - done-- check for working cxx compiler: /usr/bin/c++-- check for working cxx compiler: /usr/bin/c++ -- works-- detecting cxx compiler abi info-- detecting cxx compiler abi info - done-- detecting cxx compile features-- detecting cxx compile features - done-- configuring done-- generating done-- build files have been written to: /home/jie/github/cmake/section3/buildscanning dependencies of target section3[ 33%] building c object cmakefiles/section3.dir/main.c.o[ 66%] building c object cmakefiles/section3.dir/power.c.o[100%] linking c executable section3[100%] built target section3很明显生成了正确可执行文件~
代码下载https://github.com/jiejietop/cmake
广和通荣获“2021中国共享换电通信物联技术领导品牌”
iPhone 8再添黑科技,玩机永不发烫 !
雷克萨斯RX 200t上手体验评测
人工智能在保险行业中的应用介绍
北京高压科学中心: 硅材料在纳米尺度的塑性机制
CMake实战教程-2
如何更好的建设智能电网
将HM10 BLE模块设置为iBeacon的教程
基于FPGA平台构建汽车辅助驾驶系统算法
LORA无线测温系统在防爆电机中的应用
三星VS华为,谁是你心中的最强王者?
智能家居好物带你近距离体验未来智能生活
5G的到来对于我们的文化生活来说意味着什么
单片机开发中UART、I2C、RS485接口总线解析
艾比森与南大光电公布2020年第一季度业绩预告 预计净利润均同向上升
ADI研讨会:高性能FPGA的供电设计
比亚迪的两个“老对手”联手:吉利汽车牵手宁德时代成立合资公司
容积真空泵标准释疑,体积流率Yes抽气速率No
电压参考电路设计关键问题
达摩院:2020的科技趋势