Cargo: Rust 的社区 crate 托管服务

2014 年 11 月 20 日 · Alex Crichton

今天我很高兴地宣布,crates.io 已上线并准备就绪。该网站是发现/下载 Rust crate 的中心位置,并且 Cargo 今天就可以开始向其发布了。在接下来的几个月里,我们希望勇敢的早期采用者们能帮助我们测试这个注册表,使其久经考验。

在 Rust 本身明年年初稳定之前,注册表依赖项需要经常更新。生产环境用户可能希望在此之前继续使用 Git 依赖项。

什么是 Cargo?

Cargo 是一个面向 Rust 的用 Rust 编写的包管理器。管理依赖项是一个根本性的难题,但幸运的是,在过去十年中,包管理器的设计取得了很大进展。Cargo 由 Carl Lerche 和 Yehuda Katz 设计,沿袭了 BundlerNPM 等成功项目的传统。

  1. Cargo 利用 crates.io 培养一个繁荣的 crate 社区,其中的 crate 可以轻松地相互协作,并能持续多年。

  2. Cargo 使开发者摆脱了管理依赖项的烦恼,并确保所有协作者构建的是相同的代码。

  3. Cargo 让你的依赖项能够指定如何构建它们,并为你管理整个构建过程。

Cargo 上的社区

为了感受 Cargo 如何实现其目标,让我们看看它的一些核心机制。

声明依赖项

Cargo 让依赖第三方代码就像依赖标准库一样简单。使用 Cargo 时,每个 crate 都有一个相关的清单(manifest)来描述自身及其依赖项。添加新的依赖项现在就像在清单中添加一行一样简单,这种便捷性使得 Cargo 在短短几个月内就促成了一个庞大且不断增长的 Rust 项目和库网络,这在以前是根本不可能的。

然而,仅靠 Cargo 并非完整的解决方案。发现依赖项仍然困难,并且无法保证这些依赖项在未来多年内都可用。

crates.io

为了与 Cargo 配合使用,中心化的 crates.io 网站作为发布和发现库的单一位置。这个仓库作为 crate 随时间推移发布的永久存储,以确保项目在多年后也能始终使用完全相同的版本进行构建。到目前为止,Cargo 用户主要只是直接从 GitHub 仓库下载依赖项,但现在主要来源将转移到 crates.io。

其他编程语言社区在采用这种中心化仓库形式方面取得了巨大成功。例如,rubygems.org 是你获取 Bundler 依赖项的一站式商店,而 npmjs.org 仅本月下载量就超过了 6 亿次!我们希望 crates.io 能在 Rust 生态系统中扮演类似的角色,作为 Rust 1.0 版本长期稳定的重要基础设施。

版本控制与可复现构建

在过去几年里,语义化版本(Semantic Versioning)的概念越来越受欢迎,作为库开发者在进行破坏性更改时,与用户轻松清晰沟通的一种方式。语义化版本的核心思想很简单:每个新版本被归类为次版本或主版本,只有主版本才能引入破坏性变更。Cargo 允许你为依赖项指定版本范围,默认含义是“兼容于”。

在指定版本范围时,应用程序通常会请求同一 crate 的多个版本,Cargo 通过选择每个请求的主版本的最高版本(“稳定代码”)来解决这个问题。这极大地鼓励使用稳定发布版本,同时仍然允许不稳定代码(例如 1.0 之前版本和 Git 版本)的重复存在。

一旦依赖项及其版本集被计算出来,Cargo 会生成一个Cargo.lock 文件来编码这些信息。然后这个“锁文件”会分发给应用程序的协作者,以确保跨时间、跨机器、跨环境的构建中,所构建的 crate 保持一致。

构建代码

到目前为止,我们已经了解了 Cargo 如何在管理使用哪个版本的同时,促进社区项目的发现和重用。现在 Cargo 只需解决实际编译所有这些代码的问题了!

由于对它正在构建的 Rust 代码有深入的了解,Cargo 能够提供一些不错的标准功能以及一些 Rust 特有的功能。

  • 默认情况下,Cargo 会尽可能并行地构建多个 crate。这不仅适用于并行构建上游依赖项,也适用于本地 crate 的各种项,如测试套件、二进制文件和单元测试。

  • Cargo 提供开箱即用的单元测试支持,既支持 crate 本身的单元测试,也支持集成测试形式。这甚至包括示例程序,以确保它们不会失效。

  • Cargo 为依赖图中的所有 crate 生成文档,并且它甚至可以运行Rust 的文档测试,以确保文档中的示例保持最新。

  • Cargo 可以在编译任何 crate 之前运行构建脚本(build script),以执行诸如代码生成、编译原生依赖项或检测本地系统上的原生依赖项等任务。

  • Cargo 提供开箱即用的交叉编译支持。交叉编译只需简单地指定 --target 选项即可完成,Cargo 将管理诸如为正确平台编译插件及其他构建依赖项等任务。

还有哪些计划?

crates.io 的发布是推动 Cargo 生态系统向前发展的关键一步,但故事并未就此结束。crates.io 的使用架构是基于稳定的编译器(stable compiler)的,这应该很快就会到来!此外,还有一些 crates.io 的扩展,例如托管文档服务或 CI 构建基础设施钩子,这些都可以使用 crates.io API 构建出来。

这仅仅是 crates.io 的开始,我很高兴能开始从一个地方找到所有的 Rust crate。我迫不及待地想看到注册表在 1.0 版本时的样子,我只能想象 1.0 版本之后会是什么样子!