附录 G - Rust 是如何开发的与 “Nightly Rust”
本附录介绍 Rust 是如何开发的,以及这对作为 Rust 开发者的你有什么影响。
稳定而不停滞
作为一门语言,Rust 非常注重代码的稳定性。我们希望 Rust 成为你可以依赖的坚实基础,如果一切都在不断变化,那就不可能做到这一点。但与此同时,如果我们不能尝试新功能,我们可能要到发布之后才能发现重要的缺陷,而那时已经无法再做更改了。
我们对这个问题的解决方案被称为“稳定而不停滞“(stability without stagnation),我们的指导原则是:你永远不必担心升级到新版本的稳定版 Rust。每次升级都应该是无痛的,同时还能为你带来新功能、更少的 bug 和更快的编译速度。
呜呜!发布通道与列车模型
Rust 的开发基于列车时刻表运作。也就是说,所有开发工作都在 Rust 仓库的 main 分支上进行。发布遵循软件发布列车模型,这一模型曾被 Cisco IOS 和其他软件项目所采用。Rust 有三个发布通道:
- Nightly(每夜版)
- Beta(测试版)
- Stable(稳定版)
大多数 Rust 开发者主要使用稳定版通道,但想要尝试实验性新功能的人可以使用每夜版或测试版。
下面举例说明开发和发布流程是如何运作的:假设 Rust 团队正在准备 Rust 1.5 的发布。该版本于 2015 年 12 月发布,但它能为我们提供真实的版本号。一个新功能被添加到 Rust 中:一个新的提交合入了 main 分支。每天晚上,都会生成一个新的每夜版 Rust。每一天都是发布日,这些发布由我们的发布基础设施自动创建。随着时间推移,我们的发布看起来像这样,每晚一次:
nightly: * - - * - - *
每六周,就到了准备新版本发布的时候了!Rust 仓库的 beta 分支从每夜版使用的 main 分支上分叉出来。现在有两个发布版本:
nightly: * - - * - - *
|
beta: *
大多数 Rust 用户不会主动使用测试版,但会在他们的 CI 系统中针对测试版进行测试,以帮助 Rust 发现可能的回归问题。与此同时,每晚仍然会有一个每夜版发布:
nightly: * - - * - - * - - * - - *
|
beta: *
假设发现了一个回归问题。幸好我们在回归问题潜入稳定版之前有时间测试测试版!修复被应用到 main 分支,这样每夜版就修复了,然后修复被回移(backport)到 beta 分支,并生成一个新的测试版发布:
nightly: * - - * - - * - - * - - * - - *
|
beta: * - - - - - - - - *
在第一个测试版创建六周后,稳定版就该发布了!stable 分支从 beta 分支产生:
nightly: * - - * - - * - - * - - * - - * - * - *
|
beta: * - - - - - - - - *
|
stable: *
好极了!Rust 1.5 完成了!然而,我们忘了一件事:因为六周已经过去了,我们还需要一个下一个版本 Rust 1.6 的新测试版。所以在 stable 从 beta 分叉之后,下一个版本的 beta 又从 nightly 分叉出来:
nightly: * - - * - - * - - * - - * - - * - * - *
| |
beta: * - - - - - - - - * *
|
stable: *
这被称为“列车模型“,因为每六周,一个版本“驶出车站“,但在到达稳定版之前,仍然需要经过测试版通道的旅程。
Rust 每六周发布一次,像时钟一样准时。如果你知道某个 Rust 版本的发布日期,就能知道下一个版本的日期:六周之后。每六周发布一次的一个好处是,下一班列车很快就会到来。如果某个功能恰好错过了某次发布,不必担心:很快就会有下一次!这有助于减轻在发布截止日期前匆忙塞入可能尚未完善的功能的压力。
得益于这个流程,你始终可以查看 Rust 的下一个构建版本,并亲自验证升级是否容易:如果测试版没有按预期工作,你可以向团队报告,并在下一个稳定版发布之前得到修复!测试版中出现问题的情况相对少见,但 rustc 毕竟也是一个软件,bug 总是存在的。
维护时间
Rust 项目只支持最新的稳定版本。当新的稳定版本发布时,旧版本就到达了其生命周期终点(EOL)。这意味着每个版本的支持期为六周。
不稳定功能
这个发布模型还有一个要点:不稳定功能(unstable features)。Rust 使用一种称为“功能标志“(feature flags)的技术来决定在给定版本中启用哪些功能。如果一个新功能正在积极开发中,它会合入 main 分支,因此也会出现在每夜版中,但会被置于一个功能标志之后。如果你作为用户希望尝试这个正在开发中的功能,你可以这样做,但你必须使用每夜版 Rust,并在源代码中添加相应的标志来选择启用。
如果你使用的是测试版或稳定版 Rust,则无法使用任何功能标志。这是让我们在将新功能宣布为永久稳定之前获得实际使用经验的关键。那些希望尝试前沿功能的人可以选择启用,而那些想要稳如磐石的体验的人可以继续使用稳定版,并且知道他们的代码不会出问题。稳定而不停滞。
本书只包含稳定功能的信息,因为正在开发中的功能仍在变化,而且从本书编写时到它们在稳定版中启用时,肯定会有所不同。你可以在网上找到仅限每夜版功能的文档。
Rustup 与 Rust Nightly 的角色
Rustup 使得在不同的 Rust 发布通道之间切换变得很容易,无论是全局切换还是按项目切换。默认情况下,你安装的是稳定版 Rust。例如,要安装每夜版:
$ rustup toolchain install nightly
你也可以用 rustup 查看所有已安装的工具链(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 目录中调用 rustc 或 cargo 时,rustup 都会确保你使用的是每夜版 Rust,而不是默认的稳定版 Rust。当你有很多 Rust 项目时,这非常方便!
RFC 流程与团队
那么你如何了解这些新功能呢?Rust 的开发模型遵循一个征求意见(RFC)流程。如果你希望改进 Rust,可以撰写一份提案,称为 RFC。
任何人都可以编写 RFC 来改进 Rust,这些提案会由 Rust 团队审阅和讨论,团队由许多主题子团队组成。Rust 网站上有完整的团队列表,涵盖项目的各个领域:语言设计、编译器实现、基础设施、文档等。相应的团队会阅读提案和评论,撰写自己的意见,最终就接受或拒绝该功能达成共识。
如果功能被接受,就会在 Rust 仓库中开一个 issue,然后有人来实现它。实现它的人很可能不是最初提出该功能的人!当实现准备就绪后,它会合入 main 分支,并被置于一个功能门控(feature gate)之后,正如我们在“不稳定功能”一节中讨论的那样。
经过一段时间,当使用每夜版的 Rust 开发者们已经能够试用新功能后,团队成员会讨论该功能在每夜版上的表现,并决定它是否应该进入稳定版 Rust。如果决定推进,功能门控就会被移除,该功能就被视为稳定的了!它会搭乘列车进入新的稳定版 Rust。