C ++依赖管理的方法,或者为什么我们构建Buckaroo

Pro Image PhotographyUnsplash拍摄的照片

C ++是一种不常见的语言,因为它还没有主要的程序包管理器( 我们正在努力 !)。 结果,C ++开发人员转向了几种不同的方法来跨项目重用代码。

缺乏标准化对生态系统产生了负面影响。 有一个“仅标头” C ++库的手工业 ,它是只有几个文件的微型库,可以直接复制到项目中。 Boost等单片库变得越来越大,因为添加“一个以上的功能”比集成其他库要容易得多。 我们真的可以说这两种极端情况是组织代码的最佳方式,还是仅仅是生态系统差距的结果?

我们真的可以说这两种极端情况是组织代码的最佳方式,还是仅仅是生态系统差距的结果?

作为C ++开发人员,可以使用哪些依赖关系管理方法? 它们有何不同?最佳方法是什么?

我们要去哪里? 🤔

好的,因此在决定最佳方法并解释我们构建Buckaroo的原因之前,务必要说明我们要实现的目标。 什么是依赖项管理解决方案,什么使之有益?

什么是依赖管理?

依赖性管理是维护与项目所用外部库的链接的过程。 通过添加依赖关系,您可以在项目中重用代码,这有两个优点:

  1. 您不必自己编写该代码。
  2. 您可以从在生产环境中测试代码的其他用户社区中受益。

依赖管理器通过提供自动化工具使维护这些外部库变得更加容易。

什么使一个好的依赖关系管理器?

对于大多数用例,我们提出了一个好的包装解决方案必须满足的要求列表。

1.向项目添加新的依赖关系应该很容易。

似乎很明显,但是在追求其他要求时很容易错过这一点。 如果很难添加依赖项,那么开发人员将更有可能重新实现功能。 他们的一次性实施不会像社区实施那样经过良好的测试,并且开发人员将把时间从其他功能上转移开。

由于依赖关系图可能很复杂,因此在安装过程中,应该自动获取并解决传递性依赖关系。

2.了解项目使用的依赖关系应该很简单。

轻松添加依赖项可以鼓励代码的重用,但不利的一面是过度狂热的导入可能会带来意外的复杂性。 开发人员可以轻松检查所使用的依赖项,并在需求变化时对其进行修剪,这一点至关重要。 为了帮助调试,依赖项的源代码应易于使用。

3.它应可在所有主要平台上使用。 交叉编译应该很容易,而不仅仅是经过深思熟虑。

对C ++的普遍误解是,与Java等VM语言不同,该代码无法跨平台移植。 事实是C ++是可移植的,但是方式不同。 Java可以编译为字节码格式,这是平台无关的并且可以部署在任何地方,而C ++只能在编译之前移植。 这意味着要保持可移植性,C ++程序包管理器必须提供每个程序包的源代码,并且二进制文件仅作为优化。

4.依赖项安装应具有可重复性。 每个开发人员都应构建相同的代码。

正如可重复性在构建系统中至关重要,在任何构建在顶部的程序包管理器中都至关重要。 可再现性意味着开发人员可以放心,正在测试和部署的代码就是他们期望的。 这样可以防止细微的错误仅出现在某些机器上,从而导致生产停工和无休止的开发人员沮丧!

5.依赖关系应以项目为中心。 换句话说,安装依赖项不应修改您的系统。

以项目为中心的解决方案在编写软件时非常重要,因为它们可以减少尝试不同依赖项时的摩擦。 如果添加依赖项需要更改计算机的配置,那么开发人员将不愿意尝试; 某些事情可能会中断,没人希望记住之后如何重新配置​​。 更糟糕的是,依赖关系可能与某些系统组件的要求不兼容。 包装解决方案应完全在项目内部工作。

6.发布新软件包应该很容易。

当开发人员将他们的工作贡献给开源社区,或者仅仅贡献给组织内的同事时,他们的工作效果就会成倍增加。 我们应该鼓励这一点! 最好的方法是使发布程序包变得异常容易。 该过程应为自助服务; 不需要其他基础架构,也不需要等待批准。

7.需要最少数量的其他基础架构,例如服务器。

不管部署有多么容易,额外的基础架构都会带来额外的成本并增加另一个故障点。 一个好的解决方案将尽可能使用现有的基础架构。

不同的方法

好的,让我们开始快速汇总各种方法。

复制和粘贴

这是最简单的依赖管理方法,甚至在某些大型项目中使用它!

这种方法的问题是它提供的实际管理很少。 必须手动解决代码的传递性依赖关系,依赖关系升级是手动的,最关键的是,开发人员必须跟踪复制的确切版本。 如果二进制文件已被复制粘贴,那么交叉编译将很困难。

值得称赞的是,复制和粘贴方法不需要任何外部工具,可重复性是免费提供的,并且设置非常简单。

apt-get(和类似的)

一些开发人员认为C ++已经有一个软件包管理器,并且它已经内置在Linux中。 使用apt-get ,可以将许多C ++库安装到目标计算机上。

那么,为什么不使用apt-get呢? 尽管apt-get是将应用程序安装到计算机上的绝佳方法,但是在使用系统软件包管理器处理项目级软件包时会出现问题:

  • 它与操作系统绑定。 apt-get只能在Linux上正常运行,并且通常只能在Debian环境中使用。
  • 在系统上安装二进制文件对交叉编译没有帮助。
  • 它会修改您的系统。 当您在两个需要不同版本的依赖项的项目中工作时,会发生什么?
  • apt-get不能保证可重复性,尽管其他程序包管理器也可以。 👍
  • 您几乎无法控制所选的ABI,构建配置或使用的标准库。
Docker和apt-get🐳

解决apt-get问题的一种方法是在Docker容器内进行所有开发。 为您正在处理的每个项目创建一个容器,然后将每个项目依赖项作为系统依赖项安装在该容器中。

当然可以,但是有一些限制:

  • 开发本机Windows软件或多或少是一个初学者。 是的,您可以在Windows上使用Docker,但是它仍然是Linux环境。 您将需要交叉编译,然后在Docker外部运行以进行测试。
  • 您仍然仅限于apt-get提供的软件包,并且这些随时间而变化。
  • Docker以root身份运行,从安全角度来看这值得怀疑。 (更正: Docker现在是无根的
  • 由于Docker保留了系统库的副本,因此它需要大量的磁盘空间。
  • 您可能需要在Docker容器中第二次安装工具。
  • 现在,工具已与项目绑定在一起,因此团队中的每个人都必须具有完全相同的工具,否则您将需要管理多个图像。
Git子模块

子模块是Git的一项功能,它允许您将另一个Git存储库包含为文件夹。 如果您已经在使用Git,那么它是一项强大的功能,不需要额外的工具。

子模块的限制是它不提供依赖关系解析。 为什么这么重要? 假设您有一个像这样的依赖图:

显然,我们可以解决此问题:

但是,子模块不允许您表达此类要求,因此您必须手动进行解析。 对于小型项目而言,这不是问题,但是随着依赖性列表的增加,它变成了一个。

最重要的是,子模块无法简化依赖图。 假设您具有以下项目系统:

因此BC都需要库D 这样,我们应该只构建一次D ,然后将结果重新用于构建BC 子模块在这里没有帮助我们。 我们必须通过脚本编写构建系统来手动确保发生这种情况。

CMake外部项目

CMake具有用于下载外部项目的功能,称为ExternalProject_Add 。 它具有大量设置 ,因此很有可能可以对其进行配置以执行您需要的操作。

然而:

  • 这是不可复制的。 ExternalProject_Add可以从不稳定的URL和Git分支下载模块。
  • 几乎没有标准化。 CMake依赖于易碎的变量名约定。
  • CMake语法to令人讨厌,并且与其他语法选择相比没有任何优势。
  • 依赖关系解析仍必须手动完成。
以项目为中心的包管理器

以项目为中心的软件包管理器是将依赖项安装到项目文件夹中而不是系统上的软件包管理器。 这样想吧:以项目为中心的打包经理是用于构建项目的; 系统软件包管理器用于安装软件

已经尝试了多种语言来构建以项目为中心的包管理器。 对于JavaScript生态系统而言,其中最成功的无疑是NPM。

资料来源: blog.npmjs.org

(顺便说一句,如果您正在使用JavaScript,请帮自己一个忙,并考虑切换到Yarn )。

巴卡鲁

我们将Buckaroo构建为一个以项目为中心的C ++软件包管理器。 这里 替代 ,我们将尽在另一篇文章全面的比较,但没有一个现有的解决方案非常符合我们的要求。 这是Buckaroo如何堆叠的概述。

1.向项目添加新的依赖关系应该很容易。

Buckaroo依赖项安装在一个命令中,例如:

2.了解项目使用的依赖关系应该很简单。

每个项目都包含一个buckaroo.json文件,该文件指定了项目的依赖项。 此外,还有一个buckaroo.lock.json文件,该文件确切指定版本的解析方式。

3.它应可在所有主要平台上使用。 交叉编译应该很容易,而不仅仅是经过深思熟虑。

Buckaroo支持macOS,Windows(预览版)和Linux。 所有Buckaroo软件包都是使用Buck作为构建系统从源代码构建的,从而可以使用“构建风格”进行交叉编译。

4.安装依赖项应具有可复制性。 每个开发人员都应构建相同的代码。

与Yarn一样,Buckaroo将依赖关系解析的准确结果保存到一个锁定文件中,这确保了每个部署都使用完全相同的依赖关系。

此外,由于所有Buckaroo软件包均使用Buck生成,因此它可以提供可复制的版本。 CMake无法保证这一点。

5.依赖关系应以项目为中心。 换句话说,安装依赖项不应修改您的系统。

Buckaroo完全是本地项目。 只有下载缓存和一些用户设置位于项目文件夹之外。 这样可以确保您的CI服务器生成与您完全相同的代码。

6.发布新软件包应该很容易。

发布一个Buckaroo包很简单:

1.将Buck构建文件写入项目
2.添加一个buckaroo.json文件
3.创建GitHub版本

而已! 有关更多信息,请参见本指南

7.需要最少数量的其他基础架构,例如服务器。

Buckaroo利用现有的基础架构(例如GitHub),因此您不需要托管自己的服务器。

结论

希望本文能够解释Buckaroo背后的一些动机。 总结一下:

  • 在项目中使用以项目为中心的包管理器(例如Buckaroo)有很多优点。
  • 使用系统软件包管理器来安装工具并进行部署。
  • 如果您需要最少的工具,那么Git子模块是一个合理的选择。
  • 复制和粘贴对于微小的依赖项(例如Catch)是可行的,但是使用包管理器仍然更加方便。
准备开始了吗? 🤠

如果您想尝试Buckaroo ,最好的起点是文档 。 您可以浏览Buckaroo.pm上的现有软件包,或在愿望清单上请求更多。

From: https://hackernoon.com/approaches-to-c-dependency-management-or-why-we-built-buckaroo-26049d4646e7

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值