update dev guidelines

Signed-off-by: onur-ozkan <work@onurozkan.dev>
This commit is contained in:
onur-ozkan 2025-03-14 08:59:23 +03:00
parent 19a333ad0f
commit 09eb3b3f78
3 changed files with 41 additions and 61 deletions

View File

@ -45,13 +45,13 @@ compiler.
```mermaid ```mermaid
graph TD graph TD
s0c["stage0 compiler (1.63)"]:::downloaded -->|A| s0l("stage0 std (1.64)"):::with-s0c; s0c["stage0 compiler (1.86.0-beta.1)"]:::downloaded -->|A| s0l("stage0 std (1.86.0-beta.1)"):::downloaded;
s0c & s0l --- stepb[ ]:::empty; s0c & s0l --- stepb[ ]:::empty;
stepb -->|B| s0ca["stage0 compiler artifacts (1.64)"]:::with-s0c; stepb -->|B| s0ca["stage0 compiler artifacts (1.87.0-dev)"]:::with-s0c;
s0ca -->|copy| s1c["stage1 compiler (1.64)"]:::with-s0c; s0ca -->|copy| s1c["stage1 compiler (1.87.0-dev)"]:::with-s0c;
s1c -->|C| s1l("stage1 std (1.64)"):::with-s1c; s1c -->|C| s1l("stage1 std (1.87.0-dev)"):::with-s1c;
s1c & s1l --- stepd[ ]:::empty; s1c & s1l --- stepd[ ]:::empty;
stepd -->|D| s1ca["stage1 compiler artifacts (1.64)"]:::with-s1c; stepd -->|D| s1ca["stage1 compiler artifacts (1.87.0-dev)"]:::with-s1c;
s1ca -->|copy| s2c["stage2 compiler"]:::with-s1c; s1ca -->|copy| s2c["stage2 compiler"]:::with-s1c;
classDef empty width:0px,height:0px; classDef empty width:0px,height:0px;
@ -62,19 +62,22 @@ graph TD
### Stage 0: the pre-compiled compiler ### Stage 0: the pre-compiled compiler
The stage0 compiler is usually the current _beta_ `rustc` compiler and its The stage0 compiler is by default the very recent _beta_ `rustc` compiler and its
associated dynamic libraries, which `./x.py` will download for you. (You can associated dynamic libraries, which `./x.py` will download for you. (You can
also configure `./x.py` to use something else.) also configure `./x.py` to change stage0 to something else.)
The stage0 compiler is then used only to compile [`src/bootstrap`], The stage0 compiler is then used only to compile [`src/bootstrap`] and [`compiler/rustc`].
[`library/std`], and [`compiler/rustc`]. When assembling the libraries and When assembling the libraries and binaries that will become the stage1 `rustc` compiler,
binaries that will become the stage1 `rustc` compiler, the freshly compiled the freshly compiled `rustc` and beta `std` are used.
`std` and `rustc` are used. There are two concepts at play here: a compiler
(with its set of dependencies) and its 'target' or 'object' libraries (`std` and Note that to build the stage1 compiler we use the precompiled beta compiler and beta std from stage0.
`rustc`). Both are staged, but in a staggered manner. Therefore, to use a compiler with a std that is freshly built from the tree, you need to build the
stage2 compiler.
There are two concepts at play here: a compiler (with its set of dependencies) and its
'target' or 'object' libraries (`std` and `rustc`). Both are staged, but in a staggered manner.
[`compiler/rustc`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc [`compiler/rustc`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc
[`library/std`]: https://github.com/rust-lang/rust/tree/master/library/std
[`src/bootstrap`]: https://github.com/rust-lang/rust/tree/master/src/bootstrap [`src/bootstrap`]: https://github.com/rust-lang/rust/tree/master/src/bootstrap
### Stage 1: from current code, by an earlier compiler ### Stage 1: from current code, by an earlier compiler
@ -84,16 +87,14 @@ The rustc source code is then compiled with the `stage0` compiler to produce the
### Stage 2: the truly current compiler ### Stage 2: the truly current compiler
We then rebuild our `stage1` compiler with itself to produce the `stage2` We then rebuild our `stage1` compiler with in-tree std to produce the `stage2`
compiler. compiler.
In theory, the `stage1` compiler is functionally identical to the `stage2` The `stage1` compiler itself was built by precompiled `stage0` compiler and std
compiler, but in practice there are subtle differences. In particular, the and hence not by the source in your working directory. This means that the ABI
`stage1` compiler itself was built by `stage0` and hence not by the source in generated by the `stage0` compiler may not match the ABI that would have been made
your working directory. This means that the ABI generated by the `stage0` by the `stage1` compiler, which can cause problems for dynamic libraries, tests
compiler may not match the ABI that would have been made by the `stage1` and tools using `rustc_private`.
compiler, which can cause problems for dynamic libraries, tests, and tools using
`rustc_private`.
Note that the `proc_macro` crate avoids this issue with a `C` FFI layer called Note that the `proc_macro` crate avoids this issue with a `C` FFI layer called
`proc_macro::bridge`, allowing it to be used with `stage1`. `proc_macro::bridge`, allowing it to be used with `stage1`.
@ -101,9 +102,10 @@ Note that the `proc_macro` crate avoids this issue with a `C` FFI layer called
The `stage2` compiler is the one distributed with `rustup` and all other install The `stage2` compiler is the one distributed with `rustup` and all other install
methods. However, it takes a very long time to build because one must first methods. However, it takes a very long time to build because one must first
build the new compiler with an older compiler and then use that to build the new build the new compiler with an older compiler and then use that to build the new
compiler with itself. For development, you usually only want the `stage1` compiler with itself.
compiler, which you can build with `./x build library`. See [Building the
compiler](../how-to-build-and-run.html#building-the-compiler). For development, you usually only want to use `--stage 1` flag to build things.
See [Building the compiler](../how-to-build-and-run.html#building-the-compiler).
### Stage 3: the same-result test ### Stage 3: the same-result test
@ -114,10 +116,11 @@ something has broken.
### Building the stages ### Building the stages
The script [`./x`] tries to be helpful and pick the stage you most likely meant The script [`./x`] tries to be helpful and pick the stage you most likely meant
for each subcommand. These defaults are as follows: for each subcommand. Here are some `x` commands with their default stages:
- `check`: `--stage 0` - `check`: `--stage 1`
- `doc`: `--stage 0` - `clippy`: `--stage 1`
- `doc`: `--stage 1`
- `build`: `--stage 1` - `build`: `--stage 1`
- `test`: `--stage 1` - `test`: `--stage 1`
- `dist`: `--stage 2` - `dist`: `--stage 2`
@ -208,9 +211,6 @@ include, but are not limited to:
### Building vs. running ### Building vs. running
Note that `build --stage N compiler/rustc` **does not** build the stage N
compiler: instead it builds the stage N+1 compiler _using_ the stage N compiler.
In short, _stage 0 uses the `stage0` compiler to create `stage0` artifacts which In short, _stage 0 uses the `stage0` compiler to create `stage0` artifacts which
will later be uplifted to be the stage1 compiler_. will later be uplifted to be the stage1 compiler_.
@ -268,23 +268,6 @@ However, when cross-compiling, `stage1` `std` will only run on the host. So the
(See in the table how `stage2` only builds non-host `std` targets). (See in the table how `stage2` only builds non-host `std` targets).
### Why does only libstd use `cfg(bootstrap)`?
For docs on `cfg(bootstrap)` itself, see [Complications of
Bootstrapping](#complications-of-bootstrapping).
The `rustc` generated by the `stage0` compiler is linked to the freshly-built
`std`, which means that for the most part only `std` needs to be `cfg`-gated, so
that `rustc` can use features added to `std` immediately after their addition,
without need for them to get into the downloaded `beta` compiler.
Note this is different from any other Rust program: `stage1` `rustc` is built by
the _beta_ compiler, but using the _master_ version of `libstd`!
The only time `rustc` uses `cfg(bootstrap)` is when it adds internal lints that
use diagnostic items, or when it uses unstable library features that were
recently changed.
### What is a 'sysroot'? ### What is a 'sysroot'?
When you build a project with `cargo`, the build artifacts for dependencies are When you build a project with `cargo`, the build artifacts for dependencies are
@ -459,7 +442,6 @@ compiler itself uses to run. These aren't actually used by artifacts the new
compiler generates. This step also copies the `rustc` and `rustdoc` binaries we compiler generates. This step also copies the `rustc` and `rustdoc` binaries we
generated into `build/$HOST/stage/bin`. generated into `build/$HOST/stage/bin`.
The `stage1/bin/rustc` is a fully functional compiler, but it doesn't yet have The `stage1/bin/rustc` is a fully functional compiler built with the beta compiler and std.
any libraries to link built binaries or libraries to. The next 3 steps will To use a compiler built entirely from source with the in-tree compiler and std, you need to build
provide those libraries for it; they are mostly equivalent to constructing the the stage2 compiler, which is compiled using the stage1 compiler and std.
`stage1/bin` compiler so we don't go through them individually here.

View File

@ -217,7 +217,6 @@ probably the best "go to" command for building a local compiler:
This may *look* like it only builds the standard library, but that is not the case. This may *look* like it only builds the standard library, but that is not the case.
What this command does is the following: What this command does is the following:
- Build `std` using the stage0 compiler
- Build `rustc` using the stage0 compiler - Build `rustc` using the stage0 compiler
- This produces the stage1 compiler - This produces the stage1 compiler
- Build `std` using the stage1 compiler - Build `std` using the stage1 compiler
@ -241,8 +240,7 @@ build. The **full** `rustc` build (what you get with `./x build
--stage 2 compiler/rustc`) has quite a few more steps: --stage 2 compiler/rustc`) has quite a few more steps:
- Build `rustc` with the stage1 compiler. - Build `rustc` with the stage1 compiler.
- The resulting compiler here is called the "stage2" compiler. - The resulting compiler here is called the "stage2" compiler, which uses stage1 std from the previous command.
- Build `std` with stage2 compiler.
- Build `librustdoc` and a bunch of other things with the stage2 compiler. - Build `librustdoc` and a bunch of other things with the stage2 compiler.
You almost never need to do this. You almost never need to do this.
@ -250,14 +248,14 @@ You almost never need to do this.
### Build specific components ### Build specific components
If you are working on the standard library, you probably don't need to build If you are working on the standard library, you probably don't need to build
the compiler unless you are planning to use a recently added nightly feature. every other default component. Instead, you can build a specific component by
Instead, you can just build using the bootstrap compiler. providing its name, like this:
```bash ```bash
./x build --stage 0 library ./x build --stage 1 library
``` ```
If you choose the `library` profile when running `x setup`, you can omit `--stage 0` (it's the If you choose the `library` profile when running `x setup`, you can omit `--stage 1` (it's the
default). default).
## Creating a rustup toolchain ## Creating a rustup toolchain
@ -271,7 +269,7 @@ you will likely need to build at some point; for example, if you want
to run the entire test suite). to run the entire test suite).
```bash ```bash
rustup toolchain link stage0 build/host/stage0-sysroot # beta compiler + stage0 std rustup toolchain link stage0 build/host/stage0-sysroot # beta compiler + beta std
rustup toolchain link stage1 build/host/stage1 rustup toolchain link stage1 build/host/stage1
rustup toolchain link stage2 build/host/stage2 rustup toolchain link stage2 build/host/stage2
``` ```

View File

@ -68,7 +68,7 @@ kinds of builds (sets of jobs).
After each push to a pull request, a set of `pr` jobs are executed. Currently, After each push to a pull request, a set of `pr` jobs are executed. Currently,
these execute the `x86_64-gnu-llvm-X`, `x86_64-gnu-tools`, `mingw-check-1`, `mingw-check-2` these execute the `x86_64-gnu-llvm-X`, `x86_64-gnu-tools`, `mingw-check-1`, `mingw-check-2`
and `mingw-check-tidy` jobs, all running on Linux. These execute a relatively short and `mingw-check-tidy` jobs, all running on Linux. These execute a relatively short
(~30 minutes) and lightweight test suite that should catch common issues. More (~40 minutes) and lightweight test suite that should catch common issues. More
specifically, they run a set of lints, they try to perform a cross-compile check specifically, they run a set of lints, they try to perform a cross-compile check
build to Windows mingw (without producing any artifacts) and they test the build to Windows mingw (without producing any artifacts) and they test the
compiler using a *system* version of LLVM. Unfortunately, it would take too many compiler using a *system* version of LLVM. Unfortunately, it would take too many