【AICon】探索RAG 技术在实际应用中遇到的挑战及应对策略!AICon精华内容已上线73%>>> 了解详情
写点什么

我们是否需要通用的 C++ 软件包管理器?

  • 2017-12-07
  • 本文字数:2916 字

    阅读完需:约 10 分钟

C++ 在软件包管理器上并不存在短板。当前有大量的工具可用,例如 buckaroo cget conan conda cpm cppan hunter 等等,不胜枚举。

可是,如此之多的软件包管理器,反而让开源软件作者难以抉择。或许大家会迫切需要能有一种通用的软件包管理器,但事实上,由于 C++ 尚不具有通用的构建系统,因此看上去也不会存在通用的软件包管理。此外,各种软件包管理器所关注的方面各不相同,例如与 CMake 的直接集成、可重复构建、共享二进制服务器、解决可满足性依赖等。

我建议,不要把注意力都放在如何整合所有的软件包管理器,并形成一种通用的管理器,而是应该尝试如何创建一种标准化方法,理解依赖关系并实现软件包的安装。C++ 软件的开发者只需要符合一种简单的格式,就可以支持多种软件包管理器。这种做法也使开发者可以将注意力集中在不同软件包管理器的独有特性上,而不是将放在如何转换为新格式可使用的软件库上。我们的标准化工作分为两个部分,分别是软件包规范和工具链规范。

任何一个标准化工作想要取得成功,就应构建于当前的实践之上。当前的软件包并没有通用的依赖关系定义方法,因此我们需要在软件包管理器间做一些协同。但是,即便是在不同的构建工具之间,还是存在通用的软件库(或软件包)构建和安装方法,并且很多软件包管理器是构建在同样的工作流上的。C++ 需要的是一种通用格式,将软件包需求提供给不同的软件包管理工具。

本文中,我将探讨具体的标准化工作。

使用需求(Usage Requirement)

当前,软件包管理器的主要工作是安装依赖关系,并决定所安装的版本。提供使用需求并不是软件包管理器的工作。一方面,软件包管理器并不知道使用需求。虽然它可以从所用的依赖关系中做出推测,但推测的内容并不完整。另一方面,构建脚本的确知道使用需求,因此在安装时应使用构建脚本,这样可保持构建脚本和软件包管理器间的不耦合关系。

现在,构建脚本要实现将使用需求告知软件包管理器(这可以通过在构建中的一些查询步骤实现),但这并非构建脚本的当前工作方式。当前,构建脚本生成软件包配置文件,该配置文件进而被下游的构建脚本使用。配置文件有两种格式,即 CMake pkgconfig 。鉴于使用需求超出了软件包管理器的范畴,在此我们将不探讨它的具体内容。但毫无疑问,一种明显的解决方案就是采用依赖于构建的 pkgconfig 文件。

软件包规范

软件包规范是描述软件包内容细节的文件。其中将包括如下域:

  • 软件包名。
  • 描述。
  • 版本。
  • 可能的构建模式,即指定构建软件包所使用的构建系统。相比于依赖软件包管理器去推理构建系统,指定构建模式的方式更好,因为前者时常是模棱两可的。
  • 运行软件包的需求列表,其中包括版本限制。还可以指定需求只是用于构建,或只是用于测试。
  • 将需求中的软件包名映射到一个 URL(或者可能是一个指向软件包的 URL,软件包中包括这些映射)。对于不具有软件包索引的软件包管理器,或是需要可重复构建的软件包管理器,这非常有用。
  • 可能与该软件包具有冲突的软件包列表。
  • 该软件包可替换的软件包列表。

在理想情况下,该规范将存储在软件库本身,可能存储在最顶层。并且为实现快速的访问,软件包管理器还应索引这些文件。

此外,并非所有软件库都可提供这些软件包文件。因此我们需要有一种方式,非侵入式(non-intrusive)地提供软件包文件。在这种情况下,规范中还需指定如下域:

  • 下载软件包的 URL。
  • 可能会使用的构建脚本。在没有提供构建脚本时,或是原始的构建脚本并不充分时,可以使用在此指定的构建脚本。

特别需要指出的是,一些软件包可在所有软件包管理器上使用,非侵入格式可为这些软件包提供一种标准的定义方式。当前,每个软件包管理器都具有自己的格式,它们会重新实现自身的软件包“食谱”。

我们可使用类似于 pkgconfig 的可用格式定义这些信息。这时,其中可以进一步包括 pkgconfig 文件中使用的变量定义和替换。为支持对可选依赖非常有用的条件定义,该格式需要做进一步的扩展。下面给出的例子中展示了这样的软件包文件格式:

复制代码
Name: foo
Description: A foo library
Version: 1.0
Requires:
zlib > 1.5
Dependencies:
zlib = http://zlib.net/zlib-1.2.11.tar.gz

现在的问题是,如何解决软件包文件和构建系统之间的复制问题,因为构建中需要再次请求依赖关系。我希望在将来,构建系统可以读取同一软件包文件,以了解要搜索的依赖关系。如果该问题可以被标准化,那么这种集成是非常有可能的。

工具链规范

在软件包管理器知道了去哪里找到依赖关系后,下一步就是构建和安装软件包。尽管我们可以尽量创建标准的构建脚本,但是有一些构建过于复杂,以至于无法处理每个给出的构建需求。我们知道,CMake 正力图成为一种高层的构建脚本,可生成其它的构建脚本。但即便如此,依然是不够的。软件作者此时会转而使用其它的构建工具。

我们并非力图去做标准化,并给出大而全的构建脚本,而是关注如何实现一种调用构建系统的标准方式,这更为简单。使用 configure、build 和 install 是调用构建的通用方式,这非常易于标准化。这样,软件包管理器的关键部分,是如何告知构建系统所使用的构建“环境”或工具链。当前,每个构建系统都有不同的格式,例如 CMake 使用的是工具链文件,Meson 使用了交叉文件和环境变量,boost 构建使用了一个 user-config.jam 文件,makefile 和 autotools 使用的是一系列环境变量。

因此,我们需要提出一种描述工具链的标准化格式,其中应该包括:

  • 所使用的编译器。
  • 编译器标志。
  • 链接器标志。
  • 系统。
  • 交叉编译。
  • 构建类型(debug 或 release)。
  • 软件库类型(共享库还是静态库)。
  • 头文件目录。
  • 预处理定义。
  • 编译中使用的选项。
  • 链接共享、静态或可执行中使用的选项。
  • 寻找依赖关系的路径列表。
  • 交叉编译中使用的根路径(即 sysroots)。

这里可以使用很简单的格式,例如“变量 = 赋值”的形式。进一步,每个变量应都可在软件包文件中访问,这样可基于工具链确定可选依赖关系。

在整个工具链和构建系统中,标准化的工具链有助于实现一致的构建和安装。也有助于确保构建系统足以处理软件包管理器所需的构建场景。

下面给出一个用于 mingw 工具链的文件:

复制代码
system = windows
cross_compile = true
c_compiler = x86_64-w64-mingw32-gcc
cxx_compiler = x86_64-w64-mingw32-g++
rc_compiler = x86_64-w64-mingw32-windres
root_path = /usr/x86_64-w64-mingw32
emulator = wine
install_prefix = ~/packages
prefix_path = ~/packages

一旦构建系统支持工具链文件,这时编写包装器就是一件相对简化的事情,并由包装器实现标准化格式转换为原生的构建工具。当然,并非每个选项都能被所有的构建工具理解。因此,如果能向用户给出警告,说明某个选项不被某个构建工具所支持,这将十分有帮助的。

进一步考虑

作为 cget 软件包管理器的作者,我也提出了自己的软件包依赖关系描述格式。但是标准化的 C++ 软件包规范,有助于实现在不同的构建和软件包工具间的协同和互操作。此外,如果力图去构建一种通用构建工具和软件包管理器(例如 build2 ),这无疑将是一场艰苦的战斗,并人们也不会很快地采用该工具。因此,我们聚焦于如何尽可能地实现现有实践的标准化,这样用户也不必重写他们的构建文件。

查看英文原文: Does C++ need a universal package manager?

感谢雨多田光对本文的审校。

2017-12-07 17:255547
用户头像

发布了 391 篇内容, 共 126.0 次阅读, 收获喜欢 255 次。

关注

评论

发布
暂无评论
发现更多内容

常规加密算法是什么?原理是怎么样?有哪些?

行云管家

算法 加密算法 国密

降价背后,函数计算规格自主选配功能揭秘

阿里巴巴云原生

阿里云 云原生 函数计算

火山引擎DataLeap的Data Catalog系统公有云实践

字节跳动数据平台

大数据 火山引擎 大数据研发

教你用JavaScript完成进度条

小院里的霍大侠

JavaScript 编程开发 初学者 入门实战

制造业数字化发展,瓴羊Quick BI引起了需求者的关注

夏日星河

java 环境变量配置详细教程(2023 年全网最详细,没有之一)

千锋IT教育

开源共建 | TIS整合数据同步工具ChunJun,携手完善开源生态

袋鼠云数栈

大数据 开源 数据同步工具

老工程师荐读!PCB设计避坑指南

华秋PCB

PCB PCB设计

前端培训程序员不好招吗,应该怎么学习

小谷哥

供应链-数字化招投标/采购/供应商管理系统

金陵老街

数字化 Java‘’ Vue 3 spring-boot

磐久网络|揭秘阿里云HAIL数据中心网络

云布道师

阿里云 数据中心 基础设施建设

LeetCode题解:938. 二叉搜索树的范围和,栈,JavaScript,详细注释

Lee Chen

JavaScript LeetCode

火山引擎 DataTester 智能运营,帮企业实现“千人千面”精准营销

字节跳动数据平台

A/B 测试

透明LED屏幕如何设计显示效果更好?

Dylan

LED LED显示屏

云计算和虚拟化的三个小区别简单说明

行云管家

云计算 虚拟化

TCL 基于 StarRocks 构建统一的数据分析平台

StarRocks

#数据库

New Features | NFTScan 推出 BlueChip、Watch List、Activity Overview

NFT Research

区块链 NFT 数据基础设施

Service Mesh 的下一站是 Sidecarless 吗?

SOFAStack

MOSN

亚信科技亮相南京软博会,数智赋能百行千业

亚信AntDB数据库

AntDB aisware antdb AntDB数据库

Intel Arch SIG:介绍下一代数据中心互联协议CXL及在龙蜥的规划 | 第 54 期

OpenAnolis小助手

开源 直播 intel 龙蜥大讲堂 CXL

元器选型攻略之 电阻

元器件秋姐

元器件知识 元器件科普 电阻 电阻定义 常见电阻

瓴羊Quick BI自助式报表分析工具,令企业的运营服务更高效

夏日星河

华夏银行:详解iDo平台一体化运维的落地过程

嘉为蓝鲸

运维 金融 银行 数字化

java程序员,是不是很想进字节跳动?开发三年的我拿到了入职通知

钟奕礼

Java 程序员 java面试 java编程

跨越速运如何构建实时统一的运单分析

StarRocks

#数据库

基于云边协同架构的五大应用场景革新

阿里云视频云

阿里云 边缘计算 边缘云

阿里P8面试官总结的《2022最新年底java面试题》,搞定90%以上的技术面

钟奕礼

Java 程序员 java面试 java编程

深入了解瓴羊Quick BI,对于商业智能BI发展情况更好分析

巷子

web前端和java培训学编程哪个更好

小谷哥

QuTrunk与MindSpore量子神经网络初探

启科量子开发者官方号

人工智能 ai框架 量子编程

通过支付网关提高第三方支付接入效率

产品海豚湾

产品经理 产品设计 支付系统 产品架构 11月月更

我们是否需要通用的C++软件包管理器?_语言 & 开发_Paul Fultz II_InfoQ精选文章