编译器自举

本小节与自举过程有关。

运行x.py时,您将看到如下输出:

Building stage0 std artifacts
Copying stage0 std from stage0
Building stage0 compiler artifacts
Copying stage0 rustc from stage0
Building LLVM for x86_64-apple-darwin
Building stage0 codegen artifacts
Assembling stage1 compiler
Building stage1 std artifacts
Copying stage1 std from stage1
Building stage1 compiler artifacts
Copying stage1 rustc from stage1
Building stage1 codegen artifacts
Assembling stage2 compiler
Uplifting stage1 std
Copying stage2 std from stage1
Generating unstable book md files
Building stage0 tool unstable-book-gen
Building stage0 tool rustbook
Documenting standalone
Building rustdoc for stage2
Documenting book redirect pages
Documenting stage2 std
Building rustdoc for stage1
Documenting stage2 whitelisted compiler
Documenting stage2 compiler
Documenting stage2 rustdoc
Documenting error index
Uplifting stage1 rustc
Copying stage2 rustc from stage1
Building stage2 tool error_index_generator

在这里可以更深入地了解x.py的各个阶段:

A diagram of the rustc compilation phases

请记住,此图只是一个简化,即rustdoc可以在不同阶段构建,当传递诸如--keep-stage之类的标志或存在和宿主机类型不同的目标时,该过程会有所不同。

下表列出了各种阶段操作的输出:

Stage 0 动作Output
提取betabuild/HOST/stage0
stage0 构建 bootstrapbuild/bootstrap
stage0 构建 libstdbuild/HOST/stage0-std/TARGET
复制 stage0-std (HOST only)build/HOST/stage0-sysroot/lib/rustlib/HOST
stage0 使用stage0-sysroot构建 rustcbuild/HOST/stage0-rustc/HOST
复制 stage0-rustc (可执行文件除外)build/HOST/stage0-sysroot/lib/rustlib/HOST
构建 llvmbuild/HOST/llvm
stage0 使用stage0-sysroot构建 codegenbuild/HOST/stage0-codegen/HOST
stage0 使用stage0-sysroot构建 rustdocbuild/HOST/stage0-tools/HOST

--stage=0 到此为止。

Stage 1 动作Output
复制 (提升) stage0-rustc 可执行文件到 stage1build/HOST/stage1/bin
复制 (提升) stage0-codegenstage1build/HOST/stage1/lib
复制 (提升) stage0-sysrootstage1build/HOST/stage1/lib
stage1 构建 libstdbuild/HOST/stage1-std/TARGET
复制 stage1-std (HOST only)build/HOST/stage1/lib/rustlib/HOST
stage1 构建 rustcbuild/HOST/stage1-rustc/HOST
复制 stage1-rustc (可执行文件除外)build/HOST/stage1/lib/rustlib/HOST
stage1 构建 codegenbuild/HOST/stage1-codegen/HOST

--stage=1 到此为止。

Stage 2 动作Output
复制 (提升) stage1-rustc 可执行文件build/HOST/stage2/bin
复制 (提升) stage1-sysrootbuild/HOST/stage2/lib and build/HOST/stage2/lib/rustlib/HOST
stage2 构建 libstd (除 HOST?)build/HOST/stage2-std/TARGET
复制 stage2-std (非 HOST 目标)build/HOST/stage2/lib/rustlib/TARGET
stage2 构建 rustdocbuild/HOST/stage2-tools/HOST
复制 rustdocbuild/HOST/stage2/bin

--stage=2 到此为止。

注意,x.py使用的约定是:

  • “stage N 产品”是由stage N编译器产生的制品。
  • “stage (N+1)编译器”由“stage N 产品”组成。
  • “--stage N”标志表示使用stage N构建。

简而言之,stage 0使用stage0编译器创建stage0产品,随后将其提升为stage1

每次编译任何主要产品(stdrustc)时,都会执行两个步骤。 当std由N级编译器编译时,该std将链接到由N级编译器构建的程序(包括稍后构建的rustc)。 stage (N+1)编译器还将使用它与自身链接。 如果有人认为stage (N+1)编译器“只是”我们正在使用阶段N编译器构建的另一个程序,那么这有点直观。 在某些方面,可以将rustc(二进制文件,而不是rustbuild步骤)视为少数no_core二进制文件之一。

因此,“stage0 std制品”实际上是下载的stage0编译器的输出,并且将用于stage0编译器构建的任何内容: 例如 rustc制品。 当它宣布正在“构建stage1 std制品”时,它已进入下一个自举阶段。 在以后的阶段中,这种模式仍在继续。

还要注意,根据stage的不同,构建主机std和目标std的情况有所不同(例如,在表格中看到stage2仅构建非主机std目标。 这是因为在stage2期间,主机std是从stage 1std提升过来的—— 特别地,当宣布“ Building stage 1 artifacts”时,它也随后被复制到stage2中(编译器的libdir sysroot))。

对于编译器的任何有用的工作,这个std都是非常必要的。 具体来说,它用作新编译的编译器所编译程序的std (因此,当您编译fn main() {}时,它将链接到使用x.py build --stage 1 src/libstd编译的最后一个std)。

由stage0编译器生成的rustc链接到新构建的libstd,这意味着在大多数情况下仅需要对std进行cfg门控,以便rustc可以立即使用添加到std的功能。 添加后,无需进入下载的Beta。由stage1/bin/rustc编译器构建的libstd,也称“stage1 std”构件,不一定与该编译器具有ABI兼容性。 也就是说,rustc二进制文件很可能无法使用此std本身。 然而,它与stage1/bin/rustc二进制文件所构建的任何程序(包括其自身)都具有ABI兼容性,因此从某种意义上讲,它们是配对的。

这也是--keep-stage 1 src/libstd起作用的地方。 由于对编译器的大多数更改实际上并未更改ABI,因此,一旦在阶段1中生成了libstd,您就可以将其与其他编译器一起使用。 如果ABI没变,那就很好了,不需要花费时间重新编译std--keep-stage假设先前的编译没有问题,然后将这些制品复制到适当的位置,从而跳过cargo调用。

我们首先构建std,然后构建rustc的原因基本上是因为我们要最小化rustc代码中的cfg(stage0)。 当前rustc总是与“新的”std链接,因此它不必关心std的差异。它可以假定std尽可能新。

我们需要两次构建它的原因是因为ABI兼容性。 Beta编译器具有自己的ABI,而stage1/bin/rustc编译器将使用新的ABI生成程序/库。 我们曾经要编译3次,但是由于我们假设ABI在代码库中是恒定的, 我们假定“stage2”编译器生成的库(由stage1/bin/rustc编译器产生)与stage1/bin/rustc编译器产生的库ABI兼容。 这意味着我们可以跳过最后一次编译 —— 只需使用stage2/bin/rustc编译器自身所使用的库。

这个stage2/bin/rustc编译器和stage 1 {std, rustc}一起被交付给最终用户。

环境变量

在自举过程中,使用了很多编译器内部的环境变量。 如果您尝试运行rustc的中间版本,有时可能需要手动设置其中一些环境变量。 否则,您将得到如下错误:

thread 'main' panicked at 'RUSTC_STAGE was not set: NotPresent', src/libcore/result.rs:1165:5

如果./stageN/bin/rustc给出了有关环境变量的错误,那通常意味着有些不对劲 ——或者您正在尝试编译例如librustclibstd或依赖于环境变量的东西。 在极少数情况下,您才会需要在这种情况下调用rustc, 您可以通过在x.py命令中添加以下标志来找到环境变量值:--on-fail=print-env