]> git.proxmox.com Git - rustc.git/blame - src/doc/rustc-dev-guide/src/building/bootstrapping.md
New upstream version 1.68.2+dfsg1
[rustc.git] / src / doc / rustc-dev-guide / src / building / bootstrapping.md
CommitLineData
60c5eb7d
XL
1# Bootstrapping the Compiler
2
6a06907d
XL
3<!-- toc -->
4
60c5eb7d 5
3c0e092e 6[*Bootstrapping*][boot] is the process of using a compiler to compile itself.
6a06907d
XL
7More accurately, it means using an older compiler to compile a newer version
8of the same compiler.
9
10This raises a chicken-and-egg paradox: where did the first compiler come from?
11It must have been written in a different language. In Rust's case it was
12[written in OCaml][ocaml-compiler]. However it was abandoned long ago and the
13only way to build a modern version of rustc is a slightly less modern
14version.
15
16This is exactly how `x.py` works: it downloads the current beta release of
17rustc, then uses it to compile the new compiler.
18
19## Stages of bootstrapping
20
f2b60f7d
FG
21Compiling `rustc` is done in stages. Here's a diagram, adapted from Joshua Nelson's
22[talk on bootstrapping][rustconf22-talk] at RustConf 2022, with detailed explanations below.
23
24The `A`, `B`, `C`, and `D` show the ordering of the stages of bootstrapping.
25<span style="background-color: lightblue; color: black">Blue</span> nodes are downloaded,
26<span style="background-color: yellow; color: black">yellow</span> nodes are built with the
27stage0 compiler, and
28<span style="background-color: lightgreen; color: black">green</span> nodes are built with the
29stage1 compiler.
30
9c376795 31[rustconf22-talk]: https://www.youtube.com/watch?v=oUIjG-y4zaA
f2b60f7d
FG
32
33```mermaid
34graph TD
35 s0c["stage0 compiler (1.63)"]:::downloaded -->|A| s0l("stage0 std (1.64)"):::with-s0c;
36 s0c & s0l --- stepb[ ]:::empty;
37 stepb -->|B| s0ca["stage0 compiler artifacts (1.64)"]:::with-s0c;
38 s0ca -->|copy| s1c["stage1 compiler (1.64)"]:::with-s0c;
39 s1c -->|C| s1l("stage1 std (1.64)"):::with-s1c;
40 s1c & s1l --- stepd[ ]:::empty;
41 stepd -->|D| s1ca["stage1 compiler artifacts (1.64)"]:::with-s1c;
42 s1ca -->|copy| s2c["stage2 compiler"]:::with-s1c;
43
44 classDef empty width:0px,height:0px;
45 classDef downloaded fill: lightblue;
46 classDef with-s0c fill: yellow;
47 classDef with-s1c fill: lightgreen;
48```
3c0e092e
XL
49
50### Stage 0
51
52The stage0 compiler is usually the current _beta_ `rustc` compiler
53and its associated dynamic libraries,
54which `x.py` will download for you.
55(You can also configure `x.py` to use something else.)
56
2b03887a 57The stage0 compiler is then used only to compile `src/bootstrap`, `std`, and `rustc`.
3c0e092e
XL
58When compiling `rustc`, the stage0 compiler uses the freshly compiled `std`.
59There are two concepts at play here:
60a compiler (with its set of dependencies)
61and its 'target' or 'object' libraries (`std` and `rustc`).
62Both are staged, but in a staggered manner.
63
64### Stage 1
65
66The rustc source code is then compiled with the stage0 compiler to produce the stage1 compiler.
67
68### Stage 2
69
70We then rebuild our stage1 compiler with itself to produce the stage2 compiler.
71
72In theory, the stage1 compiler is functionally identical to the stage2 compiler,
73but in practice there are subtle differences.
74In particular, the stage1 compiler itself was built by stage0
75and hence not by the source in your working directory.
2b03887a
FG
76This means that the ABI generated by the stage0 compiler may not match the ABI that would have been
77made by the stage1 compiler, which can cause problems for dynamic libraries, tests, and tools using
78`rustc_private`.
79
80Note that the `proc_macro` crate avoids this issue with a C FFI layer called `proc_macro::bridge`,
81allowing it to be used with stage 1.
3c0e092e
XL
82
83The `stage2` compiler is the one distributed with `rustup` and all other install methods.
84However, it takes a very long time to build
85because one must first build the new compiler with an older compiler
86and then use that to build the new compiler with itself.
87For development, you usually only want the `stage1` compiler,
064997fb 88which you can build with `./x.py build library`.
a2a8927a 89See [Building the Compiler](./how-to-build-and-run.html#building-the-compiler).
3c0e092e
XL
90
91### Stage 3
92
93Stage 3 is optional. To sanity check our new compiler, we
94can build the libraries with the stage2 compiler. The result ought
95to be identical to before, unless something has broken.
96
97### Building the stages
6a06907d
XL
98
99`x.py` tries to be helpful and pick the stage you most likely meant for each subcommand.
100These defaults are as follows:
101
102- `check`: `--stage 0`
103- `doc`: `--stage 0`
104- `build`: `--stage 1`
105- `test`: `--stage 1`
106- `dist`: `--stage 2`
107- `install`: `--stage 2`
108- `bench`: `--stage 2`
109
110You can always override the stage by passing `--stage N` explicitly.
111
112For more information about stages, [see below](#understanding-stages-of-bootstrap).
113
114## Complications of bootstrapping
115
116Since the build system uses the current beta compiler to build the stage-1
117bootstrapping compiler, the compiler source code can't use some features
118until they reach beta (because otherwise the beta compiler doesn't support
119them). On the other hand, for [compiler intrinsics][intrinsics] and internal
120features, the features _have_ to be used. Additionally, the compiler makes
121heavy use of nightly features (`#![feature(...)]`). How can we resolve this
122problem?
123
124There are two methods used:
1251. The build system sets `--cfg bootstrap` when building with `stage0`, so we
126can use `cfg(not(bootstrap))` to only use features when built with `stage1`.
127This is useful for e.g. features that were just stabilized, which require
128`#![feature(...)]` when built with `stage0`, but not for `stage1`.
1292. The build system sets `RUSTC_BOOTSTRAP=1`. This special variable means to
130_break the stability guarantees_ of rust: Allow using `#![feature(...)]` with
131a compiler that's not nightly. This should never be used except when
132bootstrapping the compiler.
133
3c0e092e 134[boot]: https://en.wikipedia.org/wiki/Bootstrapping_(compilers)
6a06907d
XL
135[intrinsics]: ../appendix/glossary.md#intrinsic
136[ocaml-compiler]: https://github.com/rust-lang/rust/tree/ef75860a0a72f79f97216f8aaa5b388d98da6480/src/boot
137
138## Contributing to bootstrap
139
140When you use the bootstrap system, you'll call it through `x.py`.
141However, most of the code lives in `src/bootstrap`.
142`bootstrap` has a difficult problem: it is written in Rust, but yet it is run
5099ac24 143before the Rust compiler is built! To work around this, there are two
6a06907d
XL
144components of bootstrap: the main one written in rust, and `bootstrap.py`.
145`bootstrap.py` is what gets run by `x.py`. It takes care of downloading the
146`stage0` compiler, which will then build the bootstrap binary written in
147Rust.
148
149Because there are two separate codebases behind `x.py`, they need to
150be kept in sync. In particular, both `bootstrap.py` and the bootstrap binary
151parse `config.toml` and read the same command line arguments. `bootstrap.py`
152keeps these in sync by setting various environment variables, and the
153programs sometimes have to add arguments that are explicitly ignored, to be
154read by the other.
155
156### Adding a setting to config.toml
157
158This section is a work in progress. In the meantime, you can see an example
159contribution [here][bootstrap-build].
160
161[bootstrap-build]: https://github.com/rust-lang/rust/pull/71994
162
163## Understanding stages of bootstrap
164
165### Overview
166
167This is a detailed look into the separate bootstrap stages.
168
169The convention `x.py` uses is that:
3c0e092e 170
6a06907d
XL
171- A `--stage N` flag means to run the stage N compiler (`stageN/rustc`).
172- A "stage N artifact" is a build artifact that is _produced_ by the stage N compiler.
3c0e092e 173- The stage N+1 compiler is assembled from stage N *artifacts*. This
6a06907d
XL
174 process is called _uplifting_.
175
176#### Build artifacts
177
178Anything you can build with `x.py` is a _build artifact_.
179Build artifacts include, but are not limited to:
180
181- binaries, like `stage0-rustc/rustc-main`
182- shared objects, like `stage0-sysroot/rustlib/libstd-6fae108520cf72fe.so`
183- [rlib] files, like `stage0-sysroot/rustlib/libstd-6fae108520cf72fe.rlib`
184- HTML files generated by rustdoc, like `doc/std`
185
186[rlib]: ../serialization.md
187
6a06907d
XL
188#### Examples
189
3c0e092e
XL
190- `./x.py build --stage 0` means to build with the beta `rustc`.
191- `./x.py doc --stage 0` means to document using the beta `rustdoc`.
192- `./x.py test --stage 0 library/std` means to run tests on the standard library
6a06907d
XL
193 without building `rustc` from source ('build with stage 0, then test the
194 artifacts'). If you're working on the standard library, this is normally the
195 test command you want.
9c376795 196- `./x.py test tests/ui` means to build the stage 1 compiler and run
6a06907d
XL
197 `compiletest` on it. If you're working on the compiler, this is normally the
198 test command you want.
199
200#### Examples of what *not* to do
201
9c376795
FG
202- `./x.py test --stage 0 tests/ui` is not useful: it runs tests on the
203 _beta_ compiler and doesn't build `rustc` from source. Use `test tests/ui`
6a06907d 204 instead, which builds stage 1 from source.
3c0e092e 205- `./x.py test --stage 0 compiler/rustc` builds the compiler but runs no tests:
6a06907d
XL
206 it's running `cargo test -p rustc`, but cargo doesn't understand Rust's
207 tests. You shouldn't need to use this, use `test` instead (without arguments).
3c0e092e
XL
208- `./x.py build --stage 0 compiler/rustc` builds the compiler, but does not build
209 libstd or even libcore. Most of the time, you'll want `./x.py build
064997fb 210 library` instead, which allows compiling programs without needing to define
3c0e092e 211 lang items.
6a06907d 212
3c0e092e 213### Building vs. running
6a06907d
XL
214
215Note that `build --stage N compiler/rustc` **does not** build the stage N compiler:
3c0e092e 216instead it builds the stage N+1 compiler _using_ the stage N compiler.
6a06907d
XL
217
218In short, _stage 0 uses the stage0 compiler to create stage0 artifacts which
219will later be uplifted to be the stage1 compiler_.
220
221In each stage, two major steps are performed:
222
2231. `std` is compiled by the stage N compiler.
3c0e092e
XL
2242. That `std` is linked to programs built by the stage N compiler,
225 including the stage N artifacts (stage N+1 compiler).
6a06907d
XL
226
227This is somewhat intuitive if one thinks of the stage N artifacts as "just"
228another program we are building with the stage N compiler:
229`build --stage N compiler/rustc` is linking the stage N artifacts to the `std`
230built by the stage N compiler.
60c5eb7d 231
6a06907d
XL
232### Stages and `std`
233
234Note that there are two `std` libraries in play here:
2351. The library _linked_ to `stageN/rustc`, which was built by stage N-1 (stage N-1 `std`)
2362. The library _used to compile programs_ with `stageN/rustc`, which was
237 built by stage N (stage N `std`).
238
239Stage N `std` is pretty much necessary for any useful work with the stage N compiler.
240Without it, you can only compile programs with `#![no_core]` -- not terribly useful!
241
242The reason these need to be different is because they aren't necessarily ABI-compatible:
5e7ed085 243there could be new layout optimizations, changes to MIR, or other changes
6a06907d
XL
244to Rust metadata on nightly that aren't present in beta.
245
246This is also where `--keep-stage 1 library/std` comes into play. Since most
247changes to the compiler don't actually change the ABI, once you've produced a
248`std` in stage 1, you can probably just reuse it with a different compiler.
249If the ABI hasn't changed, you're good to go, no need to spend time
250recompiling that `std`.
251`--keep-stage` simply assumes the previous compile is fine and copies those
252artifacts into the appropriate place, skipping the cargo invocation.
253
3c0e092e
XL
254### Cross-compiling rustc
255
064997fb 256*Cross-compiling* is the process of compiling code that will run on another architecture.
3c0e092e
XL
257For instance, you might want to build an ARM version of rustc using an x86 machine.
258Building stage2 `std` is different when you are cross-compiling.
6a06907d 259
6a06907d
XL
260This is because `x.py` uses a trick: if `HOST` and `TARGET` are the same,
261it will reuse stage1 `std` for stage2! This is sound because stage1 `std`
262was compiled with the stage1 compiler, i.e. a compiler using the source code
263you currently have checked out. So it should be identical (and therefore ABI-compatible)
264to the `std` that `stage2/rustc` would compile.
265
266However, when cross-compiling, stage1 `std` will only run on the host.
267So the stage2 compiler has to recompile `std` for the target.
268
3c0e092e
XL
269(See in the table how stage2 only builds non-host `std` targets).
270
6a06907d
XL
271### Why does only libstd use `cfg(bootstrap)`?
272
273The `rustc` generated by the stage0 compiler is linked to the freshly-built
274`std`, which means that for the most part only `std` needs to be cfg-gated,
275so that `rustc` can use features added to std immediately after their addition,
276without need for them to get into the downloaded beta.
277
278Note this is different from any other Rust program: stage1 `rustc`
279is built by the _beta_ compiler, but using the _master_ version of libstd!
280
281The only time `rustc` uses `cfg(bootstrap)` is when it adds internal lints
282that use diagnostic items. This happens very rarely.
283
284### What is a 'sysroot'?
285
286When you build a project with cargo, the build artifacts for dependencies
287are normally stored in `target/debug/deps`. This only contains dependencies cargo
288knows about; in particular, it doesn't have the standard library. Where do
289`std` or `proc_macro` come from? It comes from the **sysroot**, the root
290of a number of directories where the compiler loads build artifacts at runtime.
291The sysroot doesn't just store the standard library, though - it includes
292anything that needs to be loaded at runtime. That includes (but is not limited
293to):
294
295- `libstd`/`libtest`/`libproc_macro`
296- The compiler crates themselves, when using `rustc_private`. In-tree these
297 are always present; out of tree, you need to install `rustc-dev` with rustup.
298- `libLLVM.so`, the shared object file for the LLVM project. In-tree this is
299 either built from source or downloaded from CI; out-of-tree, you need to
300 install `llvm-tools-preview` with rustup.
301
302All the artifacts listed so far are *compiler* runtime dependencies. You can
303see them with `rustc --print sysroot`:
304
305```
306$ ls $(rustc --print sysroot)/lib
307libchalk_derive-0685d79833dc9b2b.so libstd-25c6acf8063a3802.so
308libLLVM-11-rust-1.50.0-nightly.so libtest-57470d2aa8f7aa83.so
309librustc_driver-4f0cc9f50e53f0ba.so libtracing_attributes-e4be92c35ab2a33b.so
310librustc_macros-5f0ec4a119c6ac86.so rustlib
311```
312
313There are also runtime dependencies for the standard library! These are in
314`lib/rustlib`, not `lib/` directly.
315
316```
317$ ls $(rustc --print sysroot)/lib/rustlib/x86_64-unknown-linux-gnu/lib | head -n 5
318libaddr2line-6c8e02b8fedc1e5f.rlib
319libadler-9ef2480568df55af.rlib
320liballoc-9c4002b5f79ba0e1.rlib
321libcfg_if-512eb53291f6de7e.rlib
322libcompiler_builtins-ef2408da76957905.rlib
323```
324
325`rustlib` includes libraries like `hashbrown` and `cfg_if`, which are not part
326of the public API of the standard library, but are used to implement it.
327`rustlib` is part of the search path for linkers, but `lib` will never be part
328of the search path.
329
330#### -Z force-unstable-if-unmarked
331
332Since `rustlib` is part of the search path, it means we have to be careful
333about which crates are included in it. In particular, all crates except for
334the standard library are built with the flag `-Z force-unstable-if-unmarked`,
335which means that you have to use `#![feature(rustc_private)]` in order to
336load it (as opposed to the standard library, which is always available).
337
338The `-Z force-unstable-if-unmarked` flag has a variety of purposes to help
339enforce that the correct crates are marked as unstable. It was introduced
340primarily to allow rustc and the standard library to link to arbitrary crates
341on crates.io which do not themselves use `staged_api`. `rustc` also relies on
342this flag to mark all of its crates as unstable with the `rustc_private`
343feature so that each crate does not need to be carefully marked with
344`unstable`.
345
346This flag is automatically applied to all of `rustc` and the standard library
347by the bootstrap scripts. This is needed because the compiler and all of its
348dependencies are shipped in the sysroot to all users.
349
350This flag has the following effects:
351
352- Marks the crate as "unstable" with the `rustc_private` feature if it is not
353 itself marked as stable or unstable.
354- Allows these crates to access other forced-unstable crates without any need
355 for attributes. Normally a crate would need a `#![feature(rustc_private)]`
356 attribute to use other unstable crates. However, that would make it
357 impossible for a crate from crates.io to access its own dependencies since
358 that crate won't have a `feature(rustc_private)` attribute, but *everything*
359 is compiled with `-Z force-unstable-if-unmarked`.
360
361Code which does not use `-Z force-unstable-if-unmarked` should include the
362`#![feature(rustc_private)]` crate attribute to access these force-unstable
2b03887a 363crates. This is needed for things that link `rustc`, such as `miri` or
6a06907d
XL
364`clippy`.
365
366You can find more discussion about sysroots in:
367- The [rustdoc PR] explaining why it uses `extern crate` for dependencies loaded from sysroot
368- [Discussions about sysroot on Zulip](https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/deps.20in.20sysroot/)
369- [Discussions about building rustdoc out of tree](https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/How.20to.20create.20an.20executable.20accessing.20.60rustc_private.60.3F)
370
371[rustdoc PR]: https://github.com/rust-lang/rust/pull/76728
372
2b03887a
FG
373## Passing flags to commands invoked by `bootstrap`
374
375`x.py` allows you to pass stage-specific flags to `rustc` and `cargo` when bootstrapping.
376The `RUSTFLAGS_BOOTSTRAP` environment variable is passed as `RUSTFLAGS` to the bootstrap stage
377(stage0), and `RUSTFLAGS_NOT_BOOTSTRAP` is passed when building artifacts for later stages.
378`RUSTFLAGS` will work, but also affects the build of `bootstrap` itself, so it will be rare to want
379to use it.
380Finally, `MAGIC_EXTRA_RUSTFLAGS` bypasses the `cargo` cache to pass flags to rustc without
381recompiling all dependencies.
382
383`RUSTDOCFLAGS`, `RUSTDOCFLAGS_BOOTSTRAP`, and `RUSTDOCFLAGS_NOT_BOOTSTRAP` are anologous to
384`RUSTFLAGS`, but for rustdoc.
385
386`CARGOFLAGS` will pass arguments to cargo itself (e.g. `--timings`). `CARGOFLAGS_BOOTSTRAP` and
387`CARGOFLAGS_NOT_BOOTSTRAP` work analogously to `RUSTFLAGS_BOOTSTRAP`.
388
9c376795 389`--test-args` will pass arguments through to the test runner. For `tests/ui`, this is
2b03887a
FG
390compiletest; for unit tests and doctests this is the `libtest` runner. Most test runner accept
391`--help`, which you can use to find out the options accepted by the runner.
6a06907d 392
2b03887a
FG
393## Environment Variables
394
395During bootstrapping, there are a bunch of compiler-internal environment
396variables that are used. If you are trying to run an intermediate version of
397`rustc`, sometimes you may need to set some of these environment variables
398manually. Otherwise, you get an error like the following:
399
400```text
401thread 'main' panicked at 'RUSTC_STAGE was not set: NotPresent', library/core/src/result.rs:1165:5
402```
403
404If `./stageN/bin/rustc` gives an error about environment variables, that
405usually means something is quite wrong -- or you're trying to compile e.g.
406`rustc` or `std` or something that depends on environment variables. In
407the unlikely case that you actually need to invoke rustc in such a situation,
408you can tell the bootstrap shim to print all env variables by adding `-vvv` to your `x.py` command.
409
410### Directories and artifacts generated by `bootstrap`
411
412This is an incomplete reference for the outputs generated by bootstrap:
60c5eb7d
XL
413
414| Stage 0 Action | Output |
415|-----------------------------------------------------------|----------------------------------------------|
416| `beta` extracted | `build/HOST/stage0` |
417| `stage0` builds `bootstrap` | `build/bootstrap` |
6a06907d 418| `stage0` builds `test`/`std` | `build/HOST/stage0-std/TARGET` |
60c5eb7d
XL
419| copy `stage0-std` (HOST only) | `build/HOST/stage0-sysroot/lib/rustlib/HOST` |
420| `stage0` builds `rustc` with `stage0-sysroot` | `build/HOST/stage0-rustc/HOST` |
04454e1e 421| copy `stage0-rustc` (except executable) | `build/HOST/stage0-sysroot/lib/rustlib/HOST` |
60c5eb7d
XL
422| build `llvm` | `build/HOST/llvm` |
423| `stage0` builds `codegen` with `stage0-sysroot` | `build/HOST/stage0-codegen/HOST` |
6a06907d 424| `stage0` builds `rustdoc`, `clippy`, `miri`, with `stage0-sysroot` | `build/HOST/stage0-tools/HOST` |
60c5eb7d
XL
425
426`--stage=0` stops here.
427
428| Stage 1 Action | Output |
429|-----------------------------------------------------|---------------------------------------|
430| copy (uplift) `stage0-rustc` executable to `stage1` | `build/HOST/stage1/bin` |
431| copy (uplift) `stage0-codegen` to `stage1` | `build/HOST/stage1/lib` |
432| copy (uplift) `stage0-sysroot` to `stage1` | `build/HOST/stage1/lib` |
6a06907d 433| `stage1` builds `test`/`std` | `build/HOST/stage1-std/TARGET` |
60c5eb7d
XL
434| copy `stage1-std` (HOST only) | `build/HOST/stage1/lib/rustlib/HOST` |
435| `stage1` builds `rustc` | `build/HOST/stage1-rustc/HOST` |
436| copy `stage1-rustc` (except executable) | `build/HOST/stage1/lib/rustlib/HOST` |
437| `stage1` builds `codegen` | `build/HOST/stage1-codegen/HOST` |
438
439`--stage=1` stops here.
440
6a06907d
XL
441| Stage 2 Action | Output |
442|--------------------------------------------------------|-----------------------------------------------------------------|
443| copy (uplift) `stage1-rustc` executable | `build/HOST/stage2/bin` |
444| copy (uplift) `stage1-sysroot` | `build/HOST/stage2/lib and build/HOST/stage2/lib/rustlib/HOST` |
445| `stage2` builds `test`/`std` (not HOST targets) | `build/HOST/stage2-std/TARGET` |
446| copy `stage2-std` (not HOST targets) | `build/HOST/stage2/lib/rustlib/TARGET` |
447| `stage2` builds `rustdoc`, `clippy`, `miri` | `build/HOST/stage2-tools/HOST` |
448| copy `rustdoc` | `build/HOST/stage2/bin` |
60c5eb7d
XL
449
450`--stage=2` stops here.