做网站前端视频,自动的东莞网站制作公司,航空摄影设计,西安机械加工网站建设我们前几篇文章已经入门了gcc和Makefile#xff0c;现在可以来玩玩CMake了。
CMake和Makefile是差不多的#xff0c;基本上是可以相互替换使用的。CMAke可以生成Makefile#xff0c;所以本质上我们还是用的Makefile#xff0c;只不过用了CMake就不用再写Makefile了#x…我们前几篇文章已经入门了gcc和Makefile现在可以来玩玩CMake了。
CMake和Makefile是差不多的基本上是可以相互替换使用的。CMAke可以生成Makefile所以本质上我们还是用的Makefile只不过用了CMake就不用再写Makefile了会更简单一些。
一般来说小项目我们直接写Makefile大项目我们就用CMake。
CMake是跨平台的写起来也比Makefile简单所以我们还是很有必要学学CMake的。
可以参考官方文档
CMake Reference Documentation — CMake 3.16.9 Documentationhttps://cmake.org/cmake/help/v3.16/
首先我们先来安装一下CMake。
sudo apt-get install cmake
再输入下面命令看看版本能看到就是正常安装成功了。
cmake --version
接下来我们就可以开始写CMake了写Makefile的时候我们直接建一个名字叫“Makefile”或者“makefile”然后开始写就行了CMake也差不多只不过我们的脚本文件需要叫“CMakeLists.txt”
首先我们先在CMakeLists.txt里开头写上一句。
cmake_minimum_required(VERSION 3.0)
这一句是什么意思呢从名字我们也可以看个大概意思就是说我们通过这一句可以指定我们CMake的最低版本VERSION是固定的上面3.0是指定的最低版本号。
官方文档英文看不懂机翻的稀里糊涂但是我还是把截图放这边吧以官方文档说的为准。 因为CMake是跨平台的所以我们是可以把CMakeLists.txt连通项目文件一起发给别人然后别人再调用CMake去执行生成对应系统的Makefile再通过Makefile去编译生成可执行文件问题就在这每个人环境不一样CMake的版本也不一样如果我们在CMakeLists.txt里用到了高版本才有的语句那么别人低版本的CMake是会报错的因此我们可以指定CMake的最低版本来防止这种情况发生。
当然不加这句也可以但是我们最好是加上。
除了上面的我们再加一个。
project(test)
这个意思是给我们的项目起名为test。 除了起名之外还以添加别的设置但是一般情况下我们设置个项目名就行了。
有了上面两行基础的设置之后可有可无接下来最关键的还是设置我们要生成的可执行文件以及对应的依赖。 add_executable(test test.c)
使用上面的命令指定生成的可执行目标再在后面加上对应的依赖最简单的CMakeLists.txt就算是写好了。就像下面这样。 接着我们使用cmake后面跟上执行的CMakeLists.txt文件的路径。 然后我们就可以看到CMake替我们生成了不少文件但是最重要的是Makefile文件所以我们还需要执行一下make。
可以看成make之后给我们正常编译生成出了可执行文件也能正常执行。 test.c里就是普普通通的打印一句“Hello World”。 最简单的用法就如上面这样。
接下来我们深入一点点。
在Makefile中我们可以使用变量在CMake中我们也是可以使用变量的不过使用方式略有不同。
我们在CMake中定义变量需要使用一个命令set。 我们现在来改一改test.c这个文件。 包含了一个头文件并且调用了其中一个函数。那么我们要编译获取可执行文件的话就需要多一个依赖文件了。
接下来我们再使用变量来改改CMakeLists.txt 使用set来定义一个变量变量名在set命令中第一个参数的位置后续用黄框框出的是设置的变量的值可以有多个用分号或者空格隔开。使用的时候和Makefile不一样CMake中用的是大括号{ }。
接着我们cmakemake执行发现可以正常编译生成可执行文件。 set除了可以定义变量还可以修改宏定义的值在CMake中我们可以通过修改一些宏定义的值来做一些配置。后面我们碰到了再说。
在一般情况下工具文件不会和主文件放在一起那么我们把工具文件放到单独一个文件夹里。 我们在CMakeLists.txt中也需要做出对应的修改我们需要指定出头文件的路径。
使用的命令是下面这个。 比如说我放在了my_tools这个文件夹里那么我就像下面这样子写。
include_directories(${PROJECT_SOURCE_DIR}/my_tools)其中 PROJECT_SOURCE_DIR 是一个宏定义它表示的是我们执行cmake命令时提供的CMakeLists.txt所在的路径我们提取出这个宏定义就可以拼接出我们文件所在的位置了绝对路径。
除了上面的命令还有个命令可以给某个具体的文件指定头文件路径。 参数一指定的是分配头文件目录的文件。
参数二是模式一共有三种INTERFACEPUBLICPRIVATE。
简单来说就是如果有别的文件包含了这个文件那么在设置了PUBLC模式的情况下包含了这个文件的别的文件也可以搜索这个命令指定的头文件目录设置PRIVATE模式的话就不行。剩下INTERFACE这个模式这个我不太理解个人感觉和PRIVATE差不多比PRIVATE更“私人一点”没啥特殊需求咱用PUBLIC就行了。
这样我们就指定完头文件路径CMake也可以正常识别到头文件了。但是这样还是有个问题因为我把库文件的 .c 和 .h都挪到my_tools这个文件夹里了而我的CMakeLists.txt是下面这样的。 头文件是能找到但是头文件对应的源文件还是找不到原因就是我们像上面这么写的话CMake会在当前目录下找而不是跑到头文件路径下找。
解决方案有三。
第一头文件放一个文件夹里源文件放一个文件夹里这样路径也能对得上。
第二修改变量中mytool1.c的路径。
第三我们使用CMake中的命令来代替我们写死的源文件路径。 使用上面的file用法很多但是我们只看红框框出来的。file可以帮助我们到指定路径去搜索文件并且存到变量里。
我们一共需要给这个命令传入三个参数第一个是GLOB或者GLOB_RECURSE用来指定搜索的方式GLOB只会在指定的路径下搜索足够了GLOB_RECURSE会在指定路径下递归寻找费时间。
第二个是存放结果的变量。
第三个是指定的路径以及寻找的文件类型。
光说比较空泛我们直接修改一下我们的CMakeLists.txt。 参数一 GLOB表示让CMake只在我们指定的路径下寻找。
参数二 给一个参数来存放结果看得出来和我们普通编程不太一样这个变量可以不声明不初始化直接给就行。
参数三 路径可以通过通配符来指定我们要搜索的文件后缀。
这样改过之后CMake就能正常运行了生成的Makefile也能够生成可执行文件。
除了我们上面这样分开编写源文件和头文件然后一起塞给主文件编译生成可执行文件我们还可以先打包成库文件再塞给主文件生成可执行文件。
我们先看看静态库怎么做。 使用上面这个命令我们需要给三个参数。
第一个是指定我们制作的静态库的名字。
第二个我们直接给STATIC表示制作的是静态库。
第三就是把源文件塞进去。
现在我们一样是先改改CMakeLists.txt把用不到的先注释了。 我们指定的静态库名称是tool但是生成的是libtool.a 也就是说CMake会自动帮我们生成静态库名字的前缀和后缀。
如果我们制作的是动态库则只需要把第二个参数从STATIC改成SHARED即可其他不用动。 动态库的后缀在Linux中是 .so而静态库是 .a 。
我们注意到库文件默认生成的位置是和CMakeLists.txt在同一级目录下的本来CMake就会生成一堆中间文件现在又整这一出会显得我们的文件夹很乱因此我们可以通过指定库文件输出路径来使得我们的目录变得清爽一点。
我们可以使用set来修改一个宏定义进而对库文件的输出路径进行设置。这个宏定义就是LIBRARY_OUTPUT_PATH
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)可以看到已经给我们输出到指定目录下了甚至之前我都没这个文件夹CMake还帮我建了个。 那我们已经制作出了静态库和动态库了那么下一步就是要使用它们了。
先说怎么使用静态库。
说是使用也可以说是链接因为库文件的本质就是将多个工具文件编译成 .o之后再合到一起。因此我们要使用的话第一就是包含对应的头文件这样才知道有哪些函数可以使用第二就是在链接阶段和主文件放一起生成可执行文件。
我们分三步走第一步是指定头文件路径第二步是指定库文件路径第三步是指定链接的库文件。
指定头文件路径我们上面说过了我们直接跳到第二步用的是下面这个命令。 我们就像指定头文件路径那样把库文件路径塞进去就行。
下一步指定链接的库文件。 指定链接的库文件的时候我们指定的库文件名字可以是全称libxxx.a也可以掐头去尾就像我们制作库文件名字那样。
最终修改一下CMakeLists.txt。 接下来我们再链接一下动态库链接动态库用的是另一个命令指定库文件路径的命令和上面静态库的一样。 第一个参数是我们要链接动态库的文件一般也就是我们的可执行文件。
剩下的参数以两个为一组每组添加一个动态库。两个参数依次是链接模式和链接的动态库名字。 模式有三种INTERFACEPUBLICPRIVATE。
我们请文心一言介绍一下吧。 在 CMake 中target_link_libraries() 函数用于指定一个目标如库或可执行文件所依赖的其他库。当你链接库到另一个目标时你经常需要指定这些依赖是如何被传播的。这就是 INTERFACE、PUBLIC 和 PRIVATE 关键字的作用。它们用于指定库链接时的可见性和传播规则。 以下是这些关键字的详细解释 PRIVATE 当一个库 A 使用 PRIVATE 关键字链接到另一个库 B 时这意味着库 A 会直接链接到库 B但库 A 的消费者即链接到库 A 的其他目标不会看到或链接到库 B。简单来说PRIVATE 链接是库 A 内部的事情不会影响它的消费者。 PUBLIC 当一个库 A 使用 PUBLIC 关键字链接到另一个库 B 时这意味着库 A 会直接链接到库 B并且任何链接到库 A 的目标如可执行文件或其他库也会自动链接到库 B。换句话说库 A 的消费者会“继承”库 A 的 PUBLIC 依赖。 INTERFACE 当一个库 A 使用 INTERFACE 关键字链接到另一个库 B 时这意味着库 A 的消费者即链接到库 A 的其他目标会链接到库 B但库 A 本身不会直接链接到库 B。这通常用于创建一个“接口”或“契约”指定库 A 的消费者需要哪些额外的库但库 A 本身在编译时并不需要这些库。 示例 假设你有三个库LibA、LibB 和 LibC。 LibA 使用 PUBLIC 链接到 LibB。一个可执行文件 Exe 使用 LibA 和 LibC。 在这种情况下 LibA 会直接链接到 LibB。Exe 会自动链接到 LibA 和 LibB因为 LibA 是 PUBLIC 链接到 LibB 的但它不会自动链接到 LibC除非你也指定了 Exe 需要链接到 LibC。 使用这些关键字可以帮助你更精细地控制你的构建系统和依赖关系特别是在创建库和框架时。 没什么特殊需求的话我们直接给个PUBLIC就行甚至默认就是PUBLIC我们不写都可以。
那么到此为止我们就算入门CMake啦感觉不过瘾的小伙伴可以去官方文档进行更深一步的学习。英语不好的我快看吐了。。。