qtcanpool 知 10:包管理雏形

文章目录

  • 前言
  • 痛点
  • 转机
  • 雏形
  • 实践
  • 后语

前言

曾听闻:C++/Qt 没有包管理器,开发起来太不方便。这是一个有过 node.js 开发经验的人对 Qt 的吐槽。
确实,像 python、golang、node.js 这些编程语言都有包管理器,给用户带来了极佳的开发体验。第三方组件触手可得,妈妈再也不用担心我该怎么编译了。

我曾经思考过这个问题,觉得给 Qt 增加包管理器不难,难的是谁来牵头做。比较适合做这个事的应该是 Qt 官方,官方制定标准,Qt 开发者的软件兼容这个标准即可。
PS:我没有思考该怎么做,不过,读者看完本文可能会有点启发。

痛点

作者在维护 qtcanpool 的时候,遇到了库的管理问题,还没有上升到包管理层面(背后的逻辑是相似的)。
举个例子:qtcanpool 的库管理是在 src/libs 目录下添加库目录,然后库目录中直接存放库管理文件和源码文件(源码文件不能进一步放在子 src 目录,不然会影响头文件包含),比如下图的 qcanpool。应用程序在使用库的头文件的时候,头文件需要包含库目录名作为前缀,比如:

#include "qcanpool/extensionbutton.h"

在这里插入图片描述

问题描述:如果作者想引入第三方库,该如何做呢?
问题分析:通常第三方库有自己的目录结构,比如 src、example、tests、doc 等子目录,显然这不符合 qtcanpool 当前的库管理方式,需要做额外的操作。

解决方案一:在 qtcanpool/src/libs 目录下创建第三方库的名称目录,然后将第三方库 src 目录下的内容拷贝过来,再增加相关的库管理文件(pro、pri 文件)。
思考一下:这个方案有哪些问题?

  • 拷贝?
    • 太麻烦了
  • 后续怎么升级呢?
    • 拷贝新的文件覆盖老的文件,修改库管理文件。——还是麻烦

解决方案二:利用 git 的 submodule 功能,在 qtcanpool/src/libs 下创建第三方库的名称目录(如:qads),然后将第三方库以 git 子模块的形式添加到该目录下(如:Qt-Advanced-Docking-System),最后添加相关库管理文件。参考连接:https://gitee.com/icanpool/qtcanpool/tree/2.2.1/src/libs/qads
在这里插入图片描述

思考一下:

  • 拷贝?
    • 拷贝是不可能拷贝的。相比方案一,库文件不需要再拷贝了(开心)
  • 后续怎么升级呢?
    • 更新 git 子模块即可,本质上只需要更新到第三方库的某个提交(开心)
  • 那么问题来了,第三方库的目录结构不符合 qtcanpool 的管理方式,该怎么使用呢?
    • 这就是个问题了,为此需要单独增加一个 qads-inc.pri 管理文件,配置第三方库的头文件路径,接着应用程序的工程中需要 include 这个 pri 文件,然后应用程序中直接包含第三方库的相关头文件(不需要添加库前缀 qads)。—— 这产生了头文件包含风格不统一问题

痛苦是一种常态,作者接受了方案二。

转机

作者先表态:qmake 用习惯了提好用的,cmake 一言难尽。
Qt6 弃用 qmake,全面转向 cmake,并且在 Qt7 中大概率不再支持 qmake。

网友关于 cmake 的感悟:cmake 基本用过的人都不会觉得它有多好,其它 make 系统,比 cmake 使用体验好的没有 cmake 功能多,功能多的没有 cmake 生态完善,总之全面超越 cmake 的还没有出现。

大势所趋,趋之若鹜,毋庸置疑,qtcanpool 也需要支持 cmake。

qtcanpool 的工程管理的思想是来自 qtcreator,那么 cmake 自然也要保持延续。

qtcanpool 的 cmake 框架在 qtcanpool/cmake 目录:

  • 定义一个库,使用方法:add_qtc_library(包含该方法调用的 CMakeLists.txt 文件的上级目录会自动作为头文件搜索路径)
  • 定义一个应用,使用方法:add_qtc_executable

用户可以参考 qcanpool 库和 fancydemo 应用,此处不再赘述。
再赘述一下:qtc 是 qtcreator 的缩写,也是 qtcanpool 的缩写,挺完美的!

雏形

啊,cmake 真香!
cmake 管理确实很方便,就是学习曲线有点陡峭!

qtcanpool 集成了 cmake 之后,定义一个库非常方便(通过 add_qtc_library)。而且 cmake 通过 add_subdirectory 也非常方便引入库。

qtcanpool 中应用程序使用库头文件是遵循包含库目录名称的,如:#include "qcanpool/fancywindow.h“

思考:这个目录名称有点像模块名,可类比于 python 的包名(比如:import qcanpool,from qcanpool import FancyWindow)。python 开发的第三方库通常源码会放在模块名目录下,如:src/qcanpool/*.py,qcanpool/*.py

基于上述思考,如果 Qt 开发的第三方库源码不放在 src 目录下,而是放在库名称的目录下,是不是就可以保证包含头文件的时候带有库名前缀呢?

实践

样例库:qxmaterial
仓库地址:https://gitee.com/icanpool/qtcanpool-qxmaterial
在这里插入图片描述
目录结构:

  • examples:存放使用库的示例应用
  • qxmaterial: 是库名称目录,存放源码文件
  • CMakeLists.txt:库的 cmake 配置文件
    cmake_minimum_required(VERSION 3.10)if (NOT QTCANPOOL_DIR)  include(config.cmake)
    endif()add_subdirectory(qxmaterial)
    
  • confg.cmake:该仓库作为独立仓库(非 qtcanpool 子仓库)时的工程配置文件,该文件需要依赖 qtcanpool/cmake 框架。

如何使用呢?

  • qtcanpool-qxmaterial 作为一个独立仓库时。可以独立将库向前演进,通过 examples 中的应用示例可以独立验证该库。有点小瑕疵,就是该仓库需要依赖 qtcanpool 中的 cmake 框架(依赖的目的是为了保证框架的唯一性),默认二者需要保证目录层级是同级关系(可以根据实际情况修改 config.cmake 中的 QTCANPOOL_DIR 路径),如:
    qtcanpool
    qtcanpool-qxmaterial
    
  • qtcanpool-qxmaterial 作为 qtcanpool 的子库时。利用 git 的 submodule 功能,在 qtcanpool/src/libs 下创建第三方库的名称目录(如:qxmaterial),然后将第三方库以 git 子模块的形式添加到该目录下(如:qtcanpool-qxmaterial,子模块路径可以更改,不一定要保持和仓库名称一致),并添加一个库管理文件 CMakeLists.txt。
    qtcanpoolsrclibsqxmaterialqtcanpool-qxmaterialCMakeListst.txt
    

CMakeLists.txt 内容如下:

add_subdirectory(qtcanpool-qxmaterial)

背后的逻辑是:

  • add_subdirectory(qtcanpool-qxmaterial) 会包含 qtcanpool-qxmaterial 目录内的 CMakeLists.txt 文件,内容如下:
    在这里插入图片描述

  • 如果作为 qtcanpool 的子库(即子目录),qtcanpool 会在顶层 CMakeLists.txt 中定义 QTCANPOOL_DIR,那么就不会包含 config.cmake,add_subdirectory(qtcanpool-qxmaterial) 相当于进一步调用 add_subdirectory(qxmaterial)

  • add_subdirectory(qxmaterial) 会包含 qtcanpool-qxmaterial/qxmaterial 目录内的 CMakeListst.txt 文件,内容如下:
    在这里插入图片描述

  • qxmaterial 目录内的 CMakeLists.txt 文件中调用 add_qtc_library 添加库,根据规则,那么该 CMakeLists.txt 文件的上一级目录会作为头文件的搜索目录,即 qtcanpool/src/libs/qxmaterial/qtcanpool-qxmaterial 会作为头文件搜索路径,如下所示:

    qtcanpoolsrclibsqxmaterialqtcanpool-qxmaterial    -----> 作为头文件搜索路径qxmaterial          -----> 应用程序如果包含 "qxmaterial/xxx.h" 头文件,将自动会匹配该目录内的对应头文件CMakeLists.txtCMakeLists.txtCMakeListst.txt
    

后语

本文所述的包管理只适合 qtcanpool,读者们若有启发欢迎交流!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/63359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全知识:网络安全网格架构

在数字化转型的主导下,大多数组织利用多云或混合环境,包括本地基础设施、云服务和应用程序以及第三方实体,以及在网络中运行的用户和设备身份。在这种情况下,保护组织资产免受威胁涉及实现一个统一的框架,该框架根据组…

CEEMDAN-CPO-VMD二次分解(CEEMDAN+冠豪猪优化算法CPO优化VMD)

CEEMDAN-CPO-VMD二次分解(CEEMDAN冠豪猪优化算法CPO优化VMD) 目录 CEEMDAN-CPO-VMD二次分解(CEEMDAN冠豪猪优化算法CPO优化VMD)效果一览基本介绍程序设计参考资料 效果一览 基本介绍 首先运用CEEMDAN对数据进行一次分解&#xff…

Ubuntu 22.04安装Nessus(离线激活模式)

Ubuntu 22.04安装Nessus 一、 Nessus 简介二、Nessus下载安装三、激活Nessus四、创建一个基础扫描五、 破解Nessus只能扫描16个地址的限制六、更新插件 一、 Nessus 简介 Nessus 官网: https://www.tenable.com/ Nessus号称世界上最流行的扫描程序,Nessu…

Ubuntu22.04深度学习环境安装【显卡驱动安装】

前言 使用Windows配置环境失败,其中有一个包只有Linux版本,Windows版本的只有python3.10的,所以直接选用Linux来配置环境,显卡安装比较麻烦,单独出一期。 显卡驱动安装 方法一:在线安装(操作…

简单的动态带特殊符号敏感词校验

简单的动态带特殊符号敏感词校验 敏感词之前进行了简单了解,使用结巴分词自带词库可以实现,具体参考我的如下博文 敏感词校验 此次在此基础进行了部分优化,优化过程本人简单记录一下,具体优化改造步骤如下所示 1.需求 我们公司…

TCP客户端服务器端通信(线程池版)

1、什么是监听套接字,和UDP相比,TCP为什么文件描述符变多了? 在网络编程中,TCP和UDP是两种常见的传输协议,它们之间最大的不同之一在于连接的管理方式。为了更好地理解这个区别,我们可以用一个生动的比喻来…

微搭低代码AI组件单词消消乐从0到1实践

目录 1 为什么要开发单词消消乐2 需要具备什么功能3 采用什么技术方案实现4 逻辑设计4.1 数据结构设计4.2 游戏的核心逻辑4.3 数据设计 5 代码详解5.1 导入依赖5.2 定义函数组件5.3 数据初始化5.4 状态定义5.5 打乱解释的逻辑5.6 定义选择单词的函数5.7 定义选择解释的函数5.8 …

泷羽sec学习打卡-shell命令6

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都 与本人无关,切莫逾越法律红线,否则后果自负 关于shell的那些事儿-shell6 if条件判断for循环-1for循环-2实践是检验真理的唯一标准 if条件判断 创建…

QT 中 sqlite 数据库使用

一、前提 --pro文件添加sql模块QT core gui sql二、使用 说明 --用于与数据库建立连接QSqlDatabase--执行各种sql语句QSqlQuery--提供数据库特定的错误信息QSqlError查看qt支持的驱动 QStringList list QSqlDatabase::drivers();qDebug()<<list;连接 sqlite3 数据库 …

万字长文解读深度学习——dVAE(DALL·E的核心部件)

&#x1f33a;历史文章列表&#x1f33a; 深度学习——优化算法、激活函数、归一化、正则化 深度学习——权重初始化、评估指标、梯度消失和梯度爆炸 深度学习——前向传播与反向传播、神经网络&#xff08;前馈神经网络与反馈神经网络&#xff09;、常见算法概要汇总 万字长…

【Python】练习【24-12-8】

题目出处 《Python程序设计基础&#xff08;第2版&#xff09;》&#xff0c;李东方等 主编&#xff0c;电子工业出版社&#xff0c;北京&#xff0c;2020.1 第 3 章&#xff1a;《Python程序的基本流程控制》 题目描述 3、编写程序&#xff0c;产生两个10以内的随机整数&a…

五、docker的网络模式

五、docker的网络模式 5.1 Docker的四种网络模式 当你安装docker时&#xff0c;它会自动创建三个网络&#xff0c;可使用如下命令查看&#xff1a; [rootlocalhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 7390284b02d6 bridge bridge lo…

二叉树优选算法(一)

一、根据二叉树创建字符串 题目介绍&#xff1a; 给你二叉树的根节点 root &#xff0c;请你采用前序遍历的方式&#xff0c;将二叉树转化为一个由括号和整数组成的字符串&#xff0c;返回构造出的字符串。 空节点使用一对空括号对 "()" 表示&#xff0c;转化后需…

C++_关于异常处理throw-try-catch

文章目录 作用1. 无异常捕获2. 有异常捕获 作用 简单说&#xff0c;异常处理机制主要作用是让程序能够继续执行&#xff0c;或者以一种可控的方式终止&#xff0c;而非让程序因为错误直接崩溃 一个简单的动态数组类&#xff0c;来看看有异常捕获和无异常捕获的区别 1. 无异常…

Java的封装、继承、多态

书接上文&#xff0c;我们聊完了Java的类和对象&#xff0c;有没有唤起你脑海的一些记忆呢&#xff0c;我们有了类和对象的基础之后&#xff0c;我们就可以衍生出来封装继承和多态。 封装 我理解一个东西&#xff0c;我一般会先想这个是什么&#xff0c;再是怎么用&#xff0…

【C#】新建窗体文件,Form、UserControl

从用途、功能性和架构方面进行描述。 1. 继承自 Form 的窗体&#xff08;通常是窗口&#xff09;&#xff1a; 在 C# 中&#xff0c;Form 是用于创建应用程序的主窗口或对话框窗口的类。当您继承自 Form 时&#xff0c;您创建的是一个完整的窗口&#xff0c;可以显示内容、与…

OSCP:我理解的Web环境知识

你需要特别关注以下模块所涵盖的知识点&#xff0c;因为它们在考试中出现的概率很高。 1、SQL 注入&#xff08;SQL Injection&#xff09; ●允许攻击者注入自定义的、潜在恶意的 SQL 代码&#xff0c;由底层数据库执行。 ●可能导致数据泄露或目标服务器上的远程代码执行&…

Fiddler 5.21.0 使用指南:过滤浏览器HTTP(S)流量下(四)

概述 在上一篇文章中&#xff0c;我们介绍了一部分简单的过滤功能&#xff0c;已经可以帮助我们较为准确的定位到感兴趣的请求&#xff1b;提升我们的工作效率&#xff0c;我们可以通过设置更为复杂的过滤规则&#xff0c;精准到定位的我们想要的请求和响应信息。专注于分析对…

LabVIEW氢同位素单质气体定量分装系统

氢同位素单质气体在多个行业中有重要应用&#xff0c;如能源和化工。传统的分装方法面临精度和自动化程度不足的问题。为此&#xff0c;开发了一套基于LabVIEW和质量流量控制器的定量分装系统&#xff0c;提高分装精度和效率&#xff0c;同时减少资源浪费和环境污染。 项目背景…

最新AI问答创作运营系统(SparkAi系统),GPT-4.0/GPT-4o多模态模型+联网搜索提问+问答分析+AI绘画+管理后台系统

目录 一、人工智能 系统介绍文档 二、功能模块介绍 系统快速体验 三、系统功能模块 3.1 AI全模型支持/插件系统 AI大模型 多模态模型文档分析 多模态识图理解能力 联网搜索回复总结 3.2 AI智能体应用 3.2.1 AI智能体/GPTs商店 3.2.2 AI智能体/GPTs工作台 3.2.3 自…