NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

我们是否需要通用的 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:255582
用户头像

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

关注

评论

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

【Python 基础学习】-数据类型

度假的小鱼

11月月更 Python数字类型

【Python 基础学习】-字符串

度假的小鱼

11月月更 Python字符串操作

2022-11-25:连续出现的数字。编写一个 SQL 查询,查找所有至少连续出现三次的数字。 答案是输出1,原因是1是唯一连续出现三次的数字。 DROP TABLE IF EXISTS logs;

福大大架构师每日一题

数据库 福大大

JPQL超详细介绍与JPA命名规则

陈老老老板

Spring JPA 11月月更

超详细图文保姆级教程:App开发新手入门(一)

YonBuilder低代码开发平台

开发者 App 新手入门

支持向量机-探索核函数的优势和缺陷

烧灯续昼2002

Python 机器学习 算法 sklearn 11月月更

@Valid与@Validated的区别

陈老老老板

java; 11月月更

普惠联接,让人类诗意地栖居在大地上

脑极体

明道云Sales Playbook开源版正式发布

明道云

第三章热备份路由选择协议(HSRP)

初学者

网络 11月月更

后台管理不可忽视,华为云会议最新支持管理员分权分域

秃头也爱科技

一文了解 Go 中的指针和结构体

陈明勇

Go golang 指针 结构体 11月月更

跬智信息 (Kyligence) 荣获信创“大比武”重要奖项,坚持做大做实国产软件

Kyligence

数据库 数据分析 云平台技术

第四章TCP/IP网络层设备路由器

初学者

网络 11月月更

第五章TCP/IP 网络在我们身边

初学者

网络 11月月更

有了 Protocol buffer 还是用 JSON

HoneyMoose

云上办公兴起,华为云桌面Workspace更靠谱

IT科技苏辞

Spring Data JPA简介与SpringBoot整合超详细教学

陈老老老板

Spring JPA 11月月更

统一移动办公门户,满足政企高效安全协作需求

WorkPlus

【Python 基础学习】-流程控制

度假的小鱼

11月月更 Python流程控制

高标准企业级安全性,华为云会议为线上沟通保驾护航

爱科技的水月

高效、安全,华为云会议开启云上办公新天地

IT科技苏辞

助力教育信创快速发展,统信软件与山东四所高校建立信创应用重点实验室

统信软件

软件 操作系统 教育 信创产业 教育新创

Linux 文件与目录管理

智趣匠

创建资源文件 11月月更 Linux系统指令

华为云会议AI智能降噪3.0,可抑制200种噪声!

科技之光

一发一存一消费,跟着p8大佬深入学习Java中间件技术及其应用开发

钟奕礼

Java 程序员 java面试 java编程

WorkPlus即时通讯APP,提供智能化、多场景的IM系统解决方案

WorkPlus

阿里云液冷技术荣获CDCC数据中心科技成果一等奖

云布道师

阿里云 基础设施建设

远程触发Jenkins的Pipeline任务

程序员欣宸

jenkins 11月月更 pipiline

几类主流的虚拟化技术

穿过生命散发芬芳

虚拟化技术 11月月更

HDC 2022 开发者主题演讲与技术分论坛干货分享(附课件)

HarmonyOS开发者

HarmonyOS

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