附录 G - Rust 的开发方式与 “Nightly Rust”

本附录将介绍 Rust 的开发方式以及这对你作为 Rust 开发者的影响。

稳定而不停滞

作为一门编程语言,Rust 非常重视代码的稳定性。我们希望 Rust 成为你可以依赖的坚实基础,如果事物不断变化,那将是不可能的。同时,如果我们不能尝试新功能,我们可能直到发布后才发现重要的缺陷,那时我们已经无法再做出改变。

我们解决这个问题的方法称为“稳定而不停滞”,我们的指导原则是:你永远不必担心升级到新的稳定版 Rust。每次升级都应该是无痛的,同时还应该带来新功能、更少的错误和更快的编译时间。

火车模型:发布渠道与搭乘火车

Rust 的开发遵循“火车时刻表”模型。也就是说,所有的开发工作都在 Rust 代码库的 master 分支上进行。发布遵循软件发布火车模型,这种模型曾被 Cisco IOS 和其他软件项目使用。Rust 有三个发布渠道:

  • Nightly(每日构建版)
  • Beta(测试版)
  • Stable(稳定版)

大多数 Rust 开发者主要使用稳定版,但那些想要尝试实验性新功能的人可能会使用每日构建版或测试版。

以下是一个开发和发布过程的示例:假设 Rust 团队正在开发 Rust 1.5 的发布。该版本于 2015 年 12 月发布,但我们将使用这个版本来提供现实的版本号。一个新功能被添加到 Rust 中:一个新的提交被合并到 master 分支。每天晚上,都会生成一个新的每日构建版 Rust。每天都是发布日,这些发布由我们的发布基础设施自动创建。因此,随着时间的推移,我们的发布看起来像这样,每晚一次:

nightly: * - - * - - *

每六周,就是准备新发布的时候了!Rust 代码库的 beta 分支从每日构建版使用的 master 分支中分离出来。现在,有两个发布:

nightly: * - - * - - *
                     |
beta:                *

大多数 Rust 用户不会主动使用测试版,但会在他们的 CI 系统中针对测试版进行测试,以帮助 Rust 发现可能的回归问题。与此同时,每晚仍然会有一个每日构建版发布:

nightly: * - - * - - * - - * - - *
                     |
beta:                *

假设发现了一个回归问题。幸好我们在回归问题潜入稳定版之前有时间测试测试版!修复被应用到 master 分支,因此每日构建版被修复,然后修复被反向移植到 beta 分支,并生成一个新的测试版发布:

nightly: * - - * - - * - - * - - * - - *
                     |
beta:                * - - - - - - - - *

在第一个测试版创建六周后,就是稳定版发布的时候了!stable 分支从 beta 分支中分离出来:

nightly: * - - * - - * - - * - - * - - * - * - *
                     |
beta:                * - - - - - - - - *
                                       |
stable:                                *

万岁!Rust 1.5 完成了!然而,我们忘记了一件事:因为六周已经过去,我们还需要一个 下一个 版本 Rust 1.6 的新测试版。因此,在 stablebeta 分离出来后,下一个版本的 beta 再次从 nightly 分离出来:

nightly: * - - * - - * - - * - - * - - * - * - *
                     |                         |
beta:                * - - - - - - - - *       *
                                       |
stable:                                *

这被称为“火车模型”,因为每六周,一个发布“离开车站”,但在成为稳定版之前,它仍然需要经过测试版的旅程。

Rust 每六周发布一次,像时钟一样准确。如果你知道一个 Rust 版本的发布日期,你就可以知道下一个版本的发布日期:六周后。每六周发布一次的一个好处是,下一班火车很快就会到来。如果某个功能恰好错过了某个特定的发布,不用担心:另一个发布很快就会到来!这有助于减少在接近发布截止日期时偷偷加入可能未完善功能的压力。

得益于这个过程,你总是可以查看下一个 Rust 版本,并亲自验证升级是否容易:如果测试版发布没有按预期工作,你可以向团队报告,并在下一个稳定版发布之前修复它!测试版发布中的问题相对较少,但 rustc 仍然是一个软件,错误确实存在。

维护时间

Rust 项目支持最新的稳定版本。当一个新的稳定版本发布时,旧版本将达到其生命周期结束(EOL)。这意味着每个版本支持六周。

不稳定功能

这种发布模型还有一个问题:不稳定功能。Rust 使用一种称为“功能标志”的技术来确定在给定版本中启用了哪些功能。如果一个新功能正在积极开发中,它会被合并到 master 分支,因此也会出现在每日构建版中,但位于一个 功能标志 后面。如果你作为用户希望尝试这个正在开发中的功能,你可以这样做,但你必须使用 Rust 的每日构建版,并在源代码中使用适当的标志来选择加入。

如果你使用的是 Rust 的测试版或稳定版,你不能使用任何功能标志。这是我们在宣布功能稳定之前获得实际使用经验的关键。那些希望尝试最新功能的人可以这样做,而那些希望获得稳定体验的人可以坚持使用稳定版,并知道他们的代码不会崩溃。稳定而不停滞。

本书只包含关于稳定功能的信息,因为正在开发中的功能仍在变化,而且它们在这本书编写时和它们在稳定版中启用时肯定会有所不同。你可以在网上找到仅适用于每日构建版功能的文档。

Rustup 和 Rust Nightly 的作用

Rustup 使得在不同 Rust 发布渠道之间切换变得容易,无论是在全局还是每个项目的基础上。默认情况下,你将安装稳定版 Rust。例如,要安装每日构建版:

$ rustup toolchain install nightly

你还可以查看你安装的所有 工具链(Rust 的发布版本及其相关组件)。以下是你的一位作者在 Windows 电脑上的示例:

> rustup toolchain list
stable-x86_64-pc-windows-msvc (default)
beta-x86_64-pc-windows-msvc
nightly-x86_64-pc-windows-msvc

如你所见,稳定工具链是默认的。大多数 Rust 用户大多数时间都使用稳定版。你可能希望大多数时间使用稳定版,但在特定项目上使用每日构建版,因为你关心某个前沿功能。为此,你可以在该项目的目录中使用 rustup override 来设置每日构建版工具链,以便 rustup 在该目录中使用:

$ cd ~/projects/needs-nightly
$ rustup override set nightly

现在,每次你在 ~/projects/needs-nightly 目录中调用 rustccargo 时,rustup 将确保你使用的是每日构建版 Rust,而不是默认的稳定版 Rust。当你有很多 Rust 项目时,这非常方便!

RFC 流程与团队

那么你如何了解这些新功能呢?Rust 的开发模型遵循 请求评论(RFC)流程。如果你想改进 Rust,你可以写一份提案,称为 RFC。

任何人都可以写 RFC 来改进 Rust,提案由 Rust 团队审查和讨论,该团队由许多主题子团队组成。你可以在 Rust 的网站 上找到团队的完整列表,其中包括项目的每个领域的团队:语言设计、编译器实现、基础设施、文档等。适当的团队会阅读提案和评论,写下他们自己的评论,最终达成共识,决定是否接受或拒绝该功能。

如果功能被接受,Rust 代码库上会打开一个问题,然后有人可以实现它。实现它的人很可能不是最初提出该功能的人!当实现准备好时,它会合并到 master 分支,并位于一个功能标志后面,正如我们在 “不稳定功能” 部分讨论的那样。

经过一段时间,一旦使用每日构建版的 Rust 开发者能够尝试新功能,团队成员将讨论该功能,它在每日构建版中的表现如何,并决定是否应该将其纳入稳定版 Rust。如果决定继续推进,功能标志将被移除,该功能现在被认为是稳定的!它将搭乘火车进入新的稳定版 Rust 发布。