Change:
To reproduce, make sure you have an entirely clean checkout -- I did . Then run This will go on for a while and ultimately fail with Notably, it doesn't seem to build LLVM at all -- which may be why it can't find a codegen-backend...
Turns out that works fine. However, stage 0 tests with doctests still seem pretty much broken. Can these even reasonably work without having a "bootstrap rustdoc"?
Cc
Note that it fails in stage 1 as well -- both of these fail:

Discussion:
let compiler = self.compiler(self.top_stage, host); cmd.env("RUSTC_STAGE", compiler.stage.to_string()) .env("RUSTC_SYSROOT", self.sysroot(compiler)) <del> .env( "RUSTDOC_LIBDIR", self.sysroot_libdir(compiler, self.config.build), ) </del> <ins> // Note that this is *not* the sysroot_libdir because rustdoc must be linked // equivalently to rustc. .env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler)) </ins> .env("CFG_RELEASE_CHANNEL", &self.config.channel) .env("RUSTDOC_REAL", self.rustdoc(host)) .env("RUSTDOC_CRATE_VERSION", self.rust_version())

} else { &maybe_sysroot }; <del> let libdir = sysroot.join(libdir(&compiler.host)); </del> <ins> let libdir = self.rustc_libdir(compiler); </ins> // Customize the compiler we're running. Specify the compiler to cargo // as our shim and then pass it some various options used to configure

cargo.env("RUSTC_ERROR_FORMAT", error_format); } if cmd != "build" && cmd != "check" && cmd != "rustc" && want_rustdoc { <del> cargo.env("RUSTDOC_LIBDIR", self.sysroot_libdir(compiler, self.config.build)); </del> <ins> cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler)); </ins> } if mode.is_tool() {

fn run(self, builder: &Builder) -> PathBuf { let target_compiler = builder.compiler(builder.top_stage, self.host); <ins> if target_compiler.stage == 0 { if !target_compiler.is_snapshot(builder) { panic!("rustdoc in stage 0 must be snapshot rustdoc"); } return builder.initial_rustc.with_file_name(exe("rustdoc", &target_compiler.host)); } </ins> let target = target_compiler.host; <del> let build_compiler = if target_compiler.stage == 0 { builder.compiler(0, builder.config.build) } else if target_compiler.stage >= 2 { // Past stage 2, we consider the compiler to be ABI-compatible and hence capable of // building rustdoc itself. builder.compiler(target_compiler.stage, builder.config.build) } else { // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise // we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage // compilers, which isn't what we want. builder.compiler(target_compiler.stage - 1, builder.config.build) }; builder.ensure(compile::Rustc { compiler: build_compiler, target }); builder.ensure(compile::Rustc { compiler: build_compiler, target: builder.config.build, }); </del> <ins> // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise // we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage // compilers, which isn't what we want. Rustdoc should be linked in the same way as the // rustc compiler it's paired with, so it must be built with the previous stage compiler. let build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build); // The presence of `target_compiler` ensures that the necessary libraries (codegen backends, // compiler libraries, ...) are built. Rustdoc does not require the presence of any // libraries within sysroot_libdir (i.e., rustlib), though doctests may want it (since // they'll be linked to those libraries). As such, don't explicitly `ensure` any additional // libraries here. The intuition here is that If we've built a compiler, we should be able // to build rustdoc. </ins> let mut cargo = prepare_tool_cargo( builder,