一文入门CMake
我们前几篇文章已经入门了gcc和Makefile,现在可以来玩玩CMake了。
CMake和Makefile是差不多的,基本上是可以相互替换使用的。CMAke可以生成Makefile,所以本质上我们还是用的Makefile,只不过用了CMake就不用再写Makefile了,会更简单一些。
一般来说小项目我们直接写Makefile,大项目我们就用CMake。
CMake是跨平台的,写起来也比Makefile简单,所以我们还是很有必要学学CMake的。
可以参考官方文档
CMake Reference Documentation — CMake 3.16.9 Documentation
https://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中用的是大括号{ }。
接着我们cmake,make,执行,发现可以正常编译生成可执行文件。

set除了可以定义变量,还可以修改宏定义的值,在CMake中我们可以通过修改一些宏定义的值来做一些配置。后面我们碰到了再说。
在一般情况下,工具文件不会和主文件放在一起,那么我们把工具文件放到单独一个文件夹里。

我们在CMakeLists.txt中也需要做出对应的修改,我们需要指定出头文件的路径。
使用的命令是下面这个。

比如说我放在了my_tools这个文件夹里,那么我就像下面这样子写。
include_directories(${PROJECT_SOURCE_DIR}/my_tools)
其中 PROJECT_SOURCE_DIR 是一个宏定义,它表示的是我们执行cmake命令时提供的CMakeLists.txt所在的路径,我们提取出这个宏定义就可以拼接出我们文件所在的位置了(绝对路径)。
除了上面的命令,还有个命令可以给某个具体的文件指定头文件路径。

参数一指定的是分配头文件目录的文件。
参数二是模式,一共有三种,INTERFACE,PUBLIC,PRIVATE。
简单来说就是如果有别的文件包含了这个文件,那么在设置了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。

接下来我们再链接一下动态库,链接动态库用的是另一个命令(指定库文件路径的命令和上面静态库的一样)。

第一个参数是我们要链接动态库的文件,一般也就是我们的可执行文件。
剩下的参数以两个为一组,每组添加一个动态库。两个参数依次是链接模式和链接的动态库名字。

模式有三种,INTERFACE,PUBLIC,PRIVATE。
我们请文心一言介绍一下吧。
在 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啦,感觉不过瘾的小伙伴可以去官方文档进行更深一步的学习。英语不好的我快看吐了。。。
相关文章:
一文入门CMake
我们前几篇文章已经入门了gcc和Makefile,现在可以来玩玩CMake了。 CMake和Makefile是差不多的,基本上是可以相互替换使用的。CMAke可以生成Makefile,所以本质上我们还是用的Makefile,只不过用了CMake就不用再写Makefile了&#x…...
【LeetCode面试经典150题】117. 填充每个节点的下一个右侧节点指针 II
一、题目 117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode) 给定一个二叉树: struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个…...
RTDETR更换优化器——Lion
RTDETR更换Lion优化器 论文:https://arxiv.org/abs/2302.06675 代码:https://github.com/google/automl/blob/master/lion/lion_pytorch.py 简介: Lion优化器是一种基于梯度的优化算法,旨在提高梯度下降法在深度学习中的优化效果…...
Spring Boot中最佳实践:数据源配置详解
Spring Boot中最佳实践:数据源配置详解 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨在Spring Boot中如何进行最佳实践的数据源…...
第1章 物联网模式简介---独特要求和体系结构原则
物联网用例的独特要求 物联网用例往往在功耗、带宽、分析等方面具有非常独特的要求。此外,物联网实施的固有复杂性(一端的现场设备在计算上受到挑战,另一端的云容量几乎无限)迫使架构师做出艰难的架构决策和实施选择。可用实现技…...
数据挖掘概览
数据挖掘(Data Mining)就是从大量的,不完全的,有噪声的,模糊的,随机的实际应用数据中,提取隐含在其中的,人们事先不知道的,但又是潜在有用的信息和知识的过程. 预测性数据挖掘 分类 定义:分类就是把一些新的数据项映射到给定类别中的某一个类别 分类流程&#x…...
【学习】软件测试中常见的文档类型及其作用
在软件开发的生命周期中,软件测试是确保产品质量的关键步骤。为了系统地进行测试活动,并保证测试结果的有效性和可追溯性,产生了一系列标准化的测试文档。这些文档不仅为测试人员提供了执行指南,而且为项目管理者和利益相关者提供…...
electron的托盘Tray
1.在主进程文件background.js中引入需要的文件 import { Tray, Menu } from "electron"; const path require("path");2.获取托盘图标 const baseSRC process.cwd(); //这里不能使用__dirname,使用dirname会直接获取dist_electron中的文件,…...
Harmony OS UI框架探索笔记
本文探讨了如何将现有的常用架构理论与Arkts和ArkUI结合起来,使代码更有条理,并利用Previewer快速调整布局,同时在不改变代码的情况下运行显示真实数据。 开发环境 Windows 11DevEco Studio 4.0 ReleaseBuild Version: 4.0.0.600, built on…...
transformers evaluate
☆ Evaluate https://huggingface.co/docs/evaluate/main/en/installation ★ 解决方案 常用代码 # 查看支持的评估函数 evaluate.list_evaluation_modules(include_communityTrue)# 加载评估函数 accuracy evaluate.load("accuracy")# load function descripti…...
【ONLYOFFICE深度探索】:ONLYOFFICE桌面编辑器8.1震撼发布,打造高效办公新境界
文章目录 一、功能完善的PDF编辑器:解锁文档处理新维度二、幻灯片版式设计:释放创意,打造专业演示三、改进从右至左显示:尊重多元文化,优化阅读体验四、新增本地化选项:连接全球用户,跨越语言障…...
C++系统相关操作4 - 获取CPU(指令集)架构类型
1. 关键词2. sysutil.h3. sysutil.cpp4. 测试代码5. 运行结果6. 源码地址 1. 关键词 关键词: C 系统调用 CPU架构 指令集 跨平台 实现原理: Unix-like 系统: 可以通过 uname -m 命令获取 CPU 架构类型。Windows 系统: 可以通过环境变量 PROCESSOR_A…...
whisper 实现语音转文字
准备需要转码的音频 https://support.huaweicloud.com/sdkreference-sis/sis_05_0039.html 编码转吗的代码 import whisperif __name__ "__main__":file_path "16k16bit.wav"model whisper.load_model("small")result model.transcribe(f…...
使用VLLM部署llama3量化版
1.首先去魔塔社区下载量化后的llama3模型 git clone https://www.modelscope.cn/huangjintao/Meta-Llama-3-8B-Instruct-AWQ.git 2.跑起来模型 1)python -m vllm.entrypoints.openai.api_server --model /home/cxh/Meta-Llama-3-8B-Instruct-AWQ --dtype auto --…...
计算机缺失OpenCL.dll怎么办,OpenCL.dll丢失的多种解决方法
在使用电脑的过程中,我们经常会遇到一些开机弹窗问题。其中,开机弹窗找不到OpenCL.dll是一种常见的情况。本文将详细介绍开机弹窗找不到OpenCL.dll的原因分析、解决方法以及预防措辞,帮助大家更好地解决这一问题。 一,了解OpenCL.…...
git 本地代码管理
简介 git 能实现本地代码多个更改版本的管理和导出。 首先复制好项目(参考 git clone 别人项目后正确的修改和同步操作 中的前三步) 实操 克隆原始项目 首先,从远程仓库克隆项目到本地: git clone https://github.com/libo-huan…...
Docker(九)-Docker运行redis6.0.8容器实例
1.宿主机新建目录存放redis.conf文件 目的:运行redis容器实例时使用自己的配置文件2.运行redis容器实例 docker run -d -p 6379:6379 --privilegedtrue -v 【宿主机配置文件目录】:/etc/redis/redis.conf -v 【宿主机数据目录】:/data --nameredis6.0.8 redis:6.0…...
似然 与 概率
概率似然概率函数与似然函数的关系似然与机器学习的关系最大似然估计 似然与概率分别是针对不同内容的估计和近似 概率 概率:概率表达给定参数 θ \theta θ下样本随机向量 X x \textbf{X} {x} Xx的可能性。 概率密度函数的定义形式是 f ( x ∣ θ ) f(x|\t…...
Tableau数据可视化与仪表盘搭建
Tableau的主要目的 数据赋能和数据探索。 数据赋能: 1.分析师可以将数据看板发布到线上给其他部门使用 2.自动更新看板 3.自由下载数据 4.线上修改图表 5.邮件发送数据 6.设置数据预警 数据探索: 1.支持亿级数据的连接和处理 2.自由地对字段进行各种…...
web前端——HTML
目录 一、HTML概述 1.HTML是什么? 2.HTML具体化解释 二、HTML基本语法 1.声明 2. Head头标签 3.body身体标签 4.一个html的基本结构 5.标签 6.标签属性 ①属性的格式 ②属性的位置 ③添加多个属性 三、基本常用标签 1.超链接 2.图像标签 ①图像标…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
渗透实战PortSwigger Labs指南:自定义标签XSS和SVG XSS利用
阻止除自定义标签之外的所有标签 先输入一些标签测试,说是全部标签都被禁了 除了自定义的 自定义<my-tag onmouseoveralert(xss)> <my-tag idx onfocusalert(document.cookie) tabindex1> onfocus 当元素获得焦点时(如通过点击或键盘导航&…...
GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...
