【Spiffo】环境配置:最简cmake工程构建(含使用例)
简介:
本期介绍一下如何配置一个最简单可用cmake工程以及如何在自己的工程里添加第三方库/在已有工程下添加自己的库。目前只涉及最基本的框架搭建,因为想要一篇精通cmake基本上不太可能,而且很可能看晕,所以这里推荐先搞懂最基本的框架,需要什么高级功能再现场管AI要也能保证搭出来的框架能用。
附框架demo:
链接: https://pan.baidu.com/s/1kxLcraBES84QA2p3vKiwvg 提取码: x52c
一、cmake工程最基本的构造
(1)最简工程
首先看一下cmake工程一般都长什么样子:
cmake的主要作用是辅助构建Makefile的规则,所以和Makefile工程一样,cmake工程一般也存在include和src分别存储头文件和源文件,同时外加了CMakeLists.txt来替代Makefile(因为这个的编写比Makefile更符合直觉,更简单,也更易于移植)和build文件夹来存放编译的中间文件。
CMakeLists.txt中指定编译规则的方法如下:
可以看到,规则文件可以大概划为三段,分别是工程的一些基本设置,这些设置可以理解为不需要修改的内容(等到真需要修改的时候自己就能悟到需要修改了,很神奇);指定src;指定include,每行具体什么意思后面说。有main,有头文件和源,一个最简单的c工程内所有的要素就指定清楚了。
使用方面,进入build目录,输入下面指令后即可生成对应的编译规则
cmake ..
然后make即可编译
(2)含第三方库的工程
但是通常情况下,如果要制作一个完整项目,我们不可能亲自处理所有的琐碎的小问题(比如格式转换,模型制作,数据处理等),难免要使用第三方库来帮我们处理这些事情,以便我们能够集中精力在主要的程序逻辑上。
而如果使用第三方库的话,其中又包含它自己的CMakeList和include以及src,可以用一张图来概括cmake工程的结构为:
这也就是说,如果CMakeLists.txt规定好了层级之间的关系的话,就能打通不同层之间的调用关系了,接下来给一个例子进行演示。
二、不同层级之间CMakeLists.txt的关系以及如何引用
(1)根CMakLists.txt是什么样的
上面说了配置文件可以分为三段,其中后两段是需要按需修改的,分别为指定src和指定include:
1)指定src
指定的过程主要就是两行内容,
一个是使用 add_executabel()创建可执行文件的对象,
然后target_sources()将源文件编译后放入其中,
至于上面的打包,只是为了方便管理,懒得做的话直接列举出来换掉MAIN_SOURCE这个变量即可
(比如说变成 target_sources(${PROJECT_NAME PRIVATE main.c source1.c source2.c})这样)。当然不必一个一个指定文件,不过我推荐这么做,因为自动搜索文件容易出现稀奇古怪的问题(比如说FILE(GLOB )的方法)。
2)指定include
指定头文件直接一行target_include_directory()即可搞定
(2)不同层级的连接
现在假定ThirdParty_lib是一个第三方库(同样是一个cmake工程,不是的话得自己组装一下,后面说怎么办),如果要在我们的工程中引用它的API的话,就需要告诉我们项目的CMakeList.txt存在一个这样的工程要作为子工程使用。
在根CMakeLists.txt中为:
add_subdirectory()指明了需要在这个文件夹下搜索子工程或库
Target_link_libraries()指明了链接库的名称,要链接叫做ThirdParty的库
关于这个名称,则是由子项目来定义的(看最下面绿色和红色)
也可以看到两个CMakeList.txt在各自指定include和src上的操作是非常相似的
规定完以后便可以在主函数main.c中调用ThirdParty_lib库中的API了
编译运行可以看到API可用
三、使用例
(1)库类型
在举例之前我们要知道库大概分为几类:
1)单文件库
比如各种规定格式的库,这种库只有一个.h,他的函数定义以及逻辑全部写在了同一个文件里,比如:
STB Libraries,https://github.com/nothings/stb
TinyXML2, https://github.com/leethomason/tinyxml2
这种类型的库只需要把.h文件放入我们工程的include文件夹即可,也不需要另外再分支出来一个子工程
2)系统库
系统库一般来说就是apt install下来或者下载完make install的库,这种库也不需要进行过多操作,工程中直接引用即可,比如:
libpng / libjpeg,libpng.org: top level
FFmpeg,FFmpeg
注意,顺便一提,:
引用工程头文件使用,#include “”
引用系统头文件则使用, #include <>
3)多文件库
这种一般比较大,和工程也强相关,一般来说是各种框架性的东西,比如图形框架,实时操作系统框架等,这种就需要用到上述的配置方法,所以这里举一个例子。
(2)配置举例
比如我想在我的工程内内嵌一个lvgl图形框架,那么我应该在我的工程根目录添加一个我自己的CMakeLists.txt
至于链接库的名称是什么,得自己去工程相关文件里找找看(仔细阅读CMakeLists.txt里的引用说明,包能找到的)
编写完以后,就可以常规地进入build生成Makefile并编译了
编译出来的可执行程序就在规则里规定的地方
四、如何配置交叉编译
当然了,有时候这个工程不见得就是给编译它的设备用的,所以再补一个交叉编译如何配置
在工程目录新建一个叫做toolchain.cmake的文件,其中指明你的交叉编译器的路径(如果已经配置了系统环境变量的话直接在CMakeList.txt里指定编译器也可以)
然后生成Make file时指令改成这样即可:
cmake -DCMAKE_TOOLCHAIN_FILE=”../toolchain.cmake” ..
总结
到这里基本上配置出来的cmake工程框架就是可用的了(虽然其功能远不止于此),编写的原则总结起来就是指定src的那两行、指定include的那两行以及链接库如何引用,记住这几个东西类推子工程的配置文件即可。