Repository: rust
Issue: bootstrapping rustc for a custom target no longers works since 1.48, assembles stages for `build` not `host`
Labels: T-bootstrap,C-bug

I'm working with Yocto's meta-rust layer, trying to build rustc 1.49. I'm building on a regular x86_64 Linux host, but we use a custom JSON target specification due to rust-lang/cargo#3349. So we have `x86_64-unknown-linux-gnu` (real Rust triple) cross-bootstrapping for `x86_64-linux` (custom target which is essentially the same as `x86_64-unknown-linux-gnu` but with a different name):

```
target = ["x86_64-linux"]
host = ["x86_64-linux"]
build = "x86_64-unknown-linux-gnu"
```

With rust 1.47, `x.py build --stage 2 src/rustc` gives us the desired bootstrapping behaviour:

```
Building stage0 std artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage0 std from stage0 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
Building stage0 compiler artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage0 rustc from stage0 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
Assembling stage1 compiler (x86_64-unknown-linux-gnu)
Building stage1 std artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage1 std from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
Building stage1 compiler artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage1 rustc from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
Assembling stage2 compiler (x86_64-unknown-linux-gnu)
Uplifting stage1 std (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage2 std from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
Uplifting stage1 rustc (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage2 rustc from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
Building stage1 std artifacts (x86_64-unknown-linux-gnu -> x86_64-linux)
Copying stage1 std from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-linux)
Uplifting stage1 std (x86_64-unknown-linux-gnu -> x86_64-linux)
Copying stage2 std from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-linux)
Building stage1 compiler artifacts (x86_64-unknown-linux-gnu -> x86_64-linux)
Copying stage1 rustc from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-linux)
Uplifting stage1 rustc (x86_64-unknown-linux-gnu -> x86_64-linux)
Copying stage2 rustc from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-linux)
Assembling stage2 compiler (x86_64-linux)
Uplifting stage1 std (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage2 std from stage1 (x86_64-unknown-linux-gnu -> x86_64-linux / x86_64-unknown-linux-gnu)
Uplifting stage1 rustc (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage2 rustc from stage1 (x86_64-unknown-linux-gnu -> x86_64-linux / x86_64-unknown-linux-gnu)
Uplifting stage1 std (x86_64-unknown-linux-gnu -> x86_64-linux)
Copying stage2 std from stage1 (x86_64-unknown-linux-gnu -> x86_64-linux / x86_64-linux)
Uplifting stage1 rustc (x86_64-unknown-linux-gnu -> x86_64-linux)
Copying stage2 rustc from stage1 (x86_64-unknown-linux-gnu -> x86_64-linux / x86_64-linux)
```

(Note that it also insisted on building a compiler for the build triple `x86_64-unknown-linux-gnu` as well as the host `x86_64-linux`, which is unnecessary but not harmful. It seems this has been addressed in bootstrap since 1.47.)

The end result with 1.47 above is that the `build/x86_64-linux/stage2` directory contains an assembled rustc for the host `x86_64-linux` with libstd for `x86_64-linux` (and `x86_64-unknown-linux-gnu`).

However, with 1.48 and 1.49 the bootstrap behaviour has changed in a way that I still don't grok. When I run `x.py build --stage 2` it seems both stage0 and stage1 are built for `x86_64-unknown-linux-gnu`. There is no stage1 built for the host `x86_64-linux` which is what I would expect.

```
Building stage0 std artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage0 std from stage0 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
Building stage0 compiler artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage0 rustc from stage0 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
Assembling stage1 compiler (x86_64-unknown-linux-gnu)
Building stage1 std artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage1 std from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
Building stage1 compiler artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage1 rustc from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
Assembling stage2 compiler (x86_64-unknown-linux-gnu)
Building stage1 std artifacts (x86_64-unknown-linux-gnu -> x86_64-linux)
Copying stage1 std from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-linux)
Uplifting stage1 std (x86_64-unknown-linux-gnu -> x86_64-linux)
Copying stage2 std from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-linux)
Building stage1 compiler artifacts (x86_64-unknown-linux-gnu -> x86_64-linux)
Copying stage1 rustc from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-linux)
Assembling stage2 compiler (x86_64-linux)
Building rustdoc for stage2 (x86_64-linux)
```

As a result, this step: `Uplifting stage1 std (x86_64-unknown-linux-gnu -> x86_64-linux)` doesn't actually do what it says. The `build/x86_64-linux/stage2` directory ends up containing a compiler, but its rustlib directory is empty:

```
$ find build/x86_64-linux/stage2
build/x86_64-linux/stage2/
build/x86_64-linux/stage2/lib
build/x86_64-linux/stage2/lib/rustlib
build/x86_64-linux/stage2/lib/rustlib/src
build/x86_64-linux/stage2/lib/rustlib/src/rust
build/x86_64-linux/stage2/lib/rustlib/x86_64-linux
build/x86_64-linux/stage2/lib/rustlib/x86_64-linux/lib
build/x86_64-linux/stage2/lib/rustlib/x86_64-linux/codegen-backends
build/x86_64-linux/stage2/lib/libstd-0689b0d4825be2a9.so
build/x86_64-linux/stage2/lib/libtest-c874a8d9a6c5eeb1.so
build/x86_64-linux/stage2/lib/libchalk_derive-882f59f2b68bc54d.so
build/x86_64-linux/stage2/lib/librustc_driver-3d1b959398c548de.so
build/x86_64-linux/stage2/lib/librustc_macros-47465b30dcf2dd0e.so
build/x86_64-linux/stage2/lib/libtracing_attributes-72e8112b29a353da.so
build/x86_64-linux/stage2/bin
build/x86_64-linux/stage2/bin/rustc
build/x86_64-linux/stage2/bin/rustdoc
```

That step seems to be copying into `build/x86_64-unknown-linux-gnu/stage2` instead.

Complete build config and target spec for reference:
[config.toml](https://github.com/rust-lang/rust/files/5916877/config.toml.txt)
[x86_64-linux.json](https://github.com/rust-lang/rust/files/5916884/x86_64-linux.json.txt)