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.xdnf.cn/news/33924.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

光敏传感器实验

用到 ADC 采集,通过 ADC 采集电压,获取光敏传感器的电阻变化,从而得出环境光线的变化,并在 TFTLCD 上面显示出来。 光敏传感器是最常见的传感器之一,它的种类繁多,主要有:光电管、光电倍增管…

Modbus RTU转Profinet接4台流量器配置案例

Modbus RTU转Profinet是工业自动化领域常见的通讯协议。Modbus RTU因其简单、可靠而被广泛应用于各种设备间的数据传输,而Profinet则以其高速、实时性在现代工业4.0场景中扮演着重要角色。本文将详细解析如何将Modbus RTU转换为Profinet,并通过实际案例来…

【AI系统】推理系统架构

推理系统架构 推理系统架构是 AI 领域中的一个关键组成部分,它负责将训练好的模型应用于实际问题,从而实现智能决策和自动化。在构建一个高效的推理系统时,我们不仅需要考虑其性能和准确性,还需要确保系统的可扩展性、灵活性以及…

家事速配社区新经济与消费新业态创新峰会成功举办,开启多元合作新篇章

2024 年 11 月 28 日,家事速配社区新经济与消费新业态创新峰会在福建福州隆重举行,此次峰会汇聚了各界精英嘉宾,共同见证了一系列具有里程碑意义的合作签约仪式,为社区新经济与消费新业态的融合发展注入强大动力。 上午时分&#…

数字逻辑——二进制

目录 1 信息与编码 1.1 什么是信息? 1.2 什么是编码? 2 数制和码制 2.1 数制 3 一些基本概念 3.1 位(bit) 3.2 字节(byte) 3.3 数据量的大小表示符号 4 二进制 4.1 二进制简介 4.2 二进制的…

PyQt信号槽实现页面的登录与跳转 #页面进一步优化

将登录框中的取消按钮使用信号和槽的机制,关闭界面。 将登录按钮使用信号和槽连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为"admin",密码是否为"123456",如果账号密码匹配成功,当前界面关…

博客园-添加统计图

💖简介 通过WPS在线列表构建博客园每日相关数据统计图。 👉效果 📖实现 前往WPS https://www.kdocs.cn/latest 新建多维表格 创建表格视图 新建仪表盘 新建卡片、折线图 卡片配置示例 折线图配置示例 点击分享获取链接 ⭐链接配置 在co…

浏览器指纹是什么?14种指纹的技术原理

视频版链接: 浏览器指纹是什么?14种指纹背后的技术原理 浏览器指纹简介 这个网站在我没登录的情况下,就能生成一个用户ID。即使我打开了浏览器的无痕模式,生成出来的ID也是一模一样。这背后的技术就是浏览器指纹。即使用户没有登…

Junit5 单元测试入门

基础知识 常用注解含义 Test:标记一个方法为测试方法BeforeEach:标记的方法会在每个测试方法执行前执行AfterEach:标记的方法会在每个测试方法执行后执行BeforeAll:标记的方法会在所有测试方法执行前执行一次AfterAll&#xff1…

JAVA-平台模块系统原理

菜鸟为了巩固所写 目录 菜鸟为了巩固所写 代码之间的依赖性 绘制类型依赖图 扩展到包之间的依赖关系 进一步延伸到jar包之间的依赖性 组件依赖图 JAVA技术领域中的两个著名的“擦除” Java类型的“大泥球” JAVA模块解析 模块解析的过程 模块路径明确模块的搜索与…

DevExtreme JS ASP.NET Core v24.2新功能预览 - 全新的聊天组件

DevExtreme拥有高性能的HTML5 / JavaScript小部件集合,使您可以利用现代Web开发堆栈(包括React,Angular,ASP.NET Core,jQuery,Knockout等)构建交互式的Web应用程序。从Angular和Reac&#xff0c…

总结与反思-50天小总结

作者:麻瓜也要学魔法 时间:2024/12/4 不知不觉中咱博客的码龄居然50天了!内容主要就是运维方面的知识,主打一个学到哪发到哪。 看了看,50天欸!刚好就50篇文章,不得不说(咱还是真稳定…

centos8 mysql 主从复制

原理 一、一主一从 准备工作 1.主库配置 1、修改配置文件 /etc/my.cnf #mysql 服务ID,保证整个集群环境中唯一,取值范围:1-232-1,默认为 server-id1 #是否只读,1 代表只读,0代表读写 read-only0 #忽略的数据,指不需要同步的数据库 #binlog…

iptables防火墙SNAT与DNAT

第二章 iptables防火墙SNAT与DNAT 文章目录 第二章 iptables防火墙SNAT与DNAT1 SNAT1.1 SNAT原理与应用1.2 SNAT工作原理1.3 SNAT转换前提条件2 SNAT示例2.1 网关[服务器配置](https://so.csdn.net/so/search?q服务器配置&spm1001.2101.3001.7020)2.1.1 网关服务器配置网卡…

【推荐100个unity插件之36】Unity6使用DOTS基础篇——Entities(非常适合做一些弹幕射击游戏)

文章目录 前言DOTS 核心组成DOTS 解决传统问题的痛点1、优化内存布局:2、减少垃圾回收和内存管理开销:3、提高并行计算能力:4、高效的系统和组件设计:5、易于扩展和优化: 安装文档在编辑器下构建 ECS World查看Entity的…

AI一键生成原创圣诞印花图案

一、引言 随着科技的飞速发展,AI 已经深入到我们生活和工作的各个角落,为创意设计领域带来了前所未有的变革。在圣诞即将来临之际,想要设计独特的圣诞印花图案却又担心缺乏灵感或专业技能?别担心,千鹿 AI 为我们提供了…

第一部分 —— 密文类型

文章目录 1. Abstract1.1 Some Conceptions 2. TFHE Ciphertexts3. GLWE3.1 Trivial GLWE ciphertexts3.2 LWE 和 RLWE3.3 Public key encryption 4. GLev4.1 Lev and RLev 5. GGSW5.1 GSW and RGSW 1. Abstract TFHE 指的是 全同态加密策略。意思是,允许对密文进行…

进制转换详解

进制转换的基本概念 进制转换是将一个数从一种基数(进制)转换为另一种基数的过程。例如,将十进制数转换为二进制、八进制或十六进制。 转换过程 以十进制数转换为其他进制为例,转换的基本步骤如下: • 除以目标进制…

构建数字影像生态群,致力推动数字经济发展

在当今数字化浪潮汹涌澎湃的时代,数字经济逐渐成为全球经济增长新的核心驱动力。国际数字影像产业园作为数字影像领域的创新高地,正以其独特的优势和不懈的努力,为推动数字经济的蓬勃发展贡献着卓越力量。 国际数字影像产业园凭借其优越的地理…

性能测试工具1:perf

1.介绍 perf是linxu下的一款性能分析工具。Linux的性能计数器是一个新的基于内核的子系统,它为所有性能分析提供了一个框架。它包括硬件级别(CPU/PMU、性能监控单元)功能和软件(软件计数器、跟踪点)功能。 通过perf,应用程序可以利用PMU…