2016-05-02 17:16:15 -05:00
|
|
|
# rustbuild - Bootstrapping Rust
|
2015-11-19 17:20:12 -06:00
|
|
|
|
|
|
|
This is an in-progress README which is targeted at helping to explain how Rust
|
|
|
|
is bootstrapped and in general some of the technical details of the build
|
|
|
|
system.
|
|
|
|
|
2016-05-02 17:16:15 -05:00
|
|
|
## Using rustbuild
|
2015-11-19 17:20:12 -06:00
|
|
|
|
2016-10-21 15:18:09 -05:00
|
|
|
The rustbuild build system has a primary entry point, a top level `x.py` script:
|
2015-11-19 17:20:12 -06:00
|
|
|
|
|
|
|
```
|
2016-10-21 15:18:09 -05:00
|
|
|
python ./x.py build
|
2015-11-19 17:20:12 -06:00
|
|
|
```
|
|
|
|
|
2016-10-21 15:18:09 -05:00
|
|
|
Note that if you're on Unix you should be able to execute the script directly:
|
2016-05-02 17:16:15 -05:00
|
|
|
|
|
|
|
```
|
2016-10-21 15:18:09 -05:00
|
|
|
./x.py build
|
2016-05-02 17:16:15 -05:00
|
|
|
```
|
|
|
|
|
2016-12-13 10:31:48 -06:00
|
|
|
The script accepts commands, flags, and arguments to determine what to do:
|
2016-10-21 15:18:09 -05:00
|
|
|
|
|
|
|
* `build` - a general purpose command for compiling code. Alone `build` will
|
|
|
|
bootstrap the entire compiler, and otherwise arguments passed indicate what to
|
|
|
|
build. For example:
|
|
|
|
|
|
|
|
```
|
|
|
|
# build the whole compiler
|
|
|
|
./x.py build
|
|
|
|
|
2016-11-29 13:14:37 -06:00
|
|
|
# build the stage1 compiler
|
2016-10-21 15:18:09 -05:00
|
|
|
./x.py build --stage 1
|
|
|
|
|
|
|
|
# build stage0 libstd
|
|
|
|
./x.py build --stage 0 src/libstd
|
|
|
|
|
|
|
|
# build a particular crate in stage0
|
|
|
|
./x.py build --stage 0 src/libtest
|
|
|
|
```
|
|
|
|
|
2016-12-14 18:10:44 -06:00
|
|
|
If files are dirty that would normally be rebuilt from stage 0, that can be
|
2017-10-08 18:15:17 -05:00
|
|
|
overridden using `--keep-stage 0`. Using `--keep-stage n` will skip all steps
|
2016-12-14 18:10:44 -06:00
|
|
|
that belong to stage n or earlier:
|
|
|
|
|
|
|
|
```
|
|
|
|
# keep old build products for stage 0 and build stage 1
|
|
|
|
./x.py build --keep-stage 0 --stage 1
|
|
|
|
```
|
|
|
|
|
2016-10-21 15:18:09 -05:00
|
|
|
* `test` - a command for executing unit tests. Like the `build` command this
|
|
|
|
will execute the entire test suite by default, and otherwise it can be used to
|
|
|
|
select which test suite is run:
|
|
|
|
|
|
|
|
```
|
|
|
|
# run all unit tests
|
|
|
|
./x.py test
|
|
|
|
|
|
|
|
# execute the run-pass test suite
|
|
|
|
./x.py test src/test/run-pass
|
|
|
|
|
|
|
|
# execute only some tests in the run-pass test suite
|
2016-12-13 10:31:48 -06:00
|
|
|
./x.py test src/test/run-pass --test-args substring-of-test-name
|
2016-10-21 15:18:09 -05:00
|
|
|
|
|
|
|
# execute tests in the standard library in stage0
|
|
|
|
./x.py test --stage 0 src/libstd
|
|
|
|
|
|
|
|
# execute all doc tests
|
|
|
|
./x.py test src/doc
|
|
|
|
```
|
|
|
|
|
|
|
|
* `doc` - a command for building documentation. Like above can take arguments
|
|
|
|
for what to document.
|
|
|
|
|
2016-05-02 17:16:15 -05:00
|
|
|
## Configuring rustbuild
|
|
|
|
|
2017-08-21 07:22:01 -05:00
|
|
|
There are currently two methods for configuring the rustbuild build system.
|
2016-05-02 17:16:15 -05:00
|
|
|
|
2017-08-21 07:22:01 -05:00
|
|
|
First, rustbuild offers a TOML-based configuration system with a `config.toml`
|
2017-08-26 17:01:48 -05:00
|
|
|
file. An example of this configuration can be found at `config.toml.example`,
|
|
|
|
and the configuration file can also be passed as `--config path/to/config.toml`
|
|
|
|
if the build system is being invoked manually (via the python script).
|
2017-08-21 07:22:01 -05:00
|
|
|
|
|
|
|
Next, the `./configure` options serialized in `config.mk` will be
|
|
|
|
parsed and read. That is, if any `./configure` options are passed, they'll be
|
|
|
|
handled naturally. `./configure` should almost never be used for local
|
|
|
|
installations, and is primarily useful for CI. Prefer to customize behavior
|
|
|
|
using `config.toml`.
|
2016-05-02 17:16:15 -05:00
|
|
|
|
2016-11-16 14:31:19 -06:00
|
|
|
Finally, rustbuild makes use of the [gcc-rs crate] which has [its own
|
|
|
|
method][env-vars] of configuring C compilers and C flags via environment
|
|
|
|
variables.
|
|
|
|
|
|
|
|
[gcc-rs crate]: https://github.com/alexcrichton/gcc-rs
|
|
|
|
[env-vars]: https://github.com/alexcrichton/gcc-rs#external-configuration-via-environment-variables
|
|
|
|
|
2016-05-02 17:16:15 -05:00
|
|
|
## Build stages
|
|
|
|
|
|
|
|
The rustbuild build system goes through a few phases to actually build the
|
|
|
|
compiler. What actually happens when you invoke rustbuild is:
|
|
|
|
|
2016-10-21 15:18:09 -05:00
|
|
|
1. The entry point script, `x.py` is run. This script is
|
2016-05-02 17:16:15 -05:00
|
|
|
responsible for downloading the stage0 compiler/Cargo binaries, and it then
|
|
|
|
compiles the build system itself (this folder). Finally, it then invokes the
|
2016-06-22 08:09:11 -05:00
|
|
|
actual `bootstrap` binary build system.
|
2016-05-02 17:16:15 -05:00
|
|
|
2. In Rust, `bootstrap` will slurp up all configuration, perform a number of
|
|
|
|
sanity checks (compilers exist for example), and then start building the
|
|
|
|
stage0 artifacts.
|
|
|
|
3. The stage0 `cargo` downloaded earlier is used to build the standard library
|
|
|
|
and the compiler, and then these binaries are then copied to the `stage1`
|
|
|
|
directory. That compiler is then used to generate the stage1 artifacts which
|
|
|
|
are then copied to the stage2 directory, and then finally the stage2
|
|
|
|
artifacts are generated using that compiler.
|
|
|
|
|
|
|
|
The goal of each stage is to (a) leverage Cargo as much as possible and failing
|
|
|
|
that (b) leverage Rust as much as possible!
|
2015-11-19 17:20:12 -06:00
|
|
|
|
2016-11-16 17:02:56 -06:00
|
|
|
## Incremental builds
|
|
|
|
|
|
|
|
You can configure rustbuild to use incremental compilation. Because
|
|
|
|
incremental is new and evolving rapidly, if you want to use it, it is
|
|
|
|
recommended that you replace the snapshot with a locally installed
|
|
|
|
nightly build of rustc. You will want to keep this up to date.
|
|
|
|
|
|
|
|
To follow this course of action, first thing you will want to do is to
|
|
|
|
install a nightly, presumably using `rustup`. You will then want to
|
|
|
|
configure your directory to use this build, like so:
|
|
|
|
|
|
|
|
```
|
2017-10-13 12:51:38 -05:00
|
|
|
# configure to use local rust instead of downloading a beta.
|
2016-11-16 17:02:56 -06:00
|
|
|
# `--local-rust-root` is optional here. If elided, we will
|
|
|
|
# use whatever rustc we find on your PATH.
|
2017-10-18 16:00:15 -05:00
|
|
|
> configure --local-rust-root=~/.cargo/ --enable-local-rebuild
|
2016-11-16 17:02:56 -06:00
|
|
|
```
|
|
|
|
|
|
|
|
After that, you can use the `--incremental` flag to actually do
|
|
|
|
incremental builds:
|
|
|
|
|
|
|
|
```
|
|
|
|
> ../x.py build --incremental
|
|
|
|
```
|
|
|
|
|
|
|
|
The `--incremental` flag will store incremental compilation artifacts
|
2016-12-22 09:58:08 -06:00
|
|
|
in `build/<host>/stage0-incremental`. Note that we only use incremental
|
2016-11-16 17:02:56 -06:00
|
|
|
compilation for the stage0 -> stage1 compilation -- this is because
|
|
|
|
the stage1 compiler is changing, and we don't try to cache and reuse
|
|
|
|
incremental artifacts across different versions of the compiler. For
|
|
|
|
this reason, `--incremental` defaults to `--stage 1` (though you can
|
|
|
|
manually select a higher stage, if you prefer).
|
|
|
|
|
|
|
|
You can always drop the `--incremental` to build as normal (but you
|
|
|
|
will still be using the local nightly as your bootstrap).
|
|
|
|
|
2015-11-19 17:20:12 -06:00
|
|
|
## Directory Layout
|
|
|
|
|
2016-05-02 17:16:15 -05:00
|
|
|
This build system houses all output under the `build` directory, which looks
|
2015-11-19 17:20:12 -06:00
|
|
|
like this:
|
|
|
|
|
|
|
|
```
|
|
|
|
# Root folder of all output. Everything is scoped underneath here
|
|
|
|
build/
|
|
|
|
|
|
|
|
# Location where the stage0 compiler downloads are all cached. This directory
|
|
|
|
# only contains the tarballs themselves as they're extracted elsewhere.
|
|
|
|
cache/
|
|
|
|
2015-12-19/
|
|
|
|
2016-01-15/
|
|
|
|
2016-01-21/
|
|
|
|
...
|
|
|
|
|
|
|
|
# Output directory for building this build system itself. The stage0
|
|
|
|
# cargo/rustc are used to build the build system into this location.
|
|
|
|
bootstrap/
|
|
|
|
debug/
|
|
|
|
release/
|
|
|
|
|
2016-05-02 17:16:15 -05:00
|
|
|
# Output of the dist-related steps like dist-std, dist-rustc, and dist-docs
|
|
|
|
dist/
|
|
|
|
|
|
|
|
# Temporary directory used for various input/output as part of various stages
|
|
|
|
tmp/
|
|
|
|
|
2015-11-19 17:20:12 -06:00
|
|
|
# Each remaining directory is scoped by the "host" triple of compilation at
|
|
|
|
# hand.
|
|
|
|
x86_64-unknown-linux-gnu/
|
|
|
|
|
|
|
|
# The build artifacts for the `compiler-rt` library for the target this
|
|
|
|
# folder is under. The exact layout here will likely depend on the platform,
|
|
|
|
# and this is also built with CMake so the build system is also likely
|
|
|
|
# different.
|
2016-05-02 17:16:15 -05:00
|
|
|
compiler-rt/
|
|
|
|
build/
|
2015-11-19 17:20:12 -06:00
|
|
|
|
|
|
|
# Output folder for LLVM if it is compiled for this target
|
|
|
|
llvm/
|
|
|
|
|
|
|
|
# build folder (e.g. the platform-specific build system). Like with
|
|
|
|
# compiler-rt this is compiled with CMake
|
|
|
|
build/
|
|
|
|
|
|
|
|
# Installation of LLVM. Note that we run the equivalent of 'make install'
|
|
|
|
# for LLVM to setup these folders.
|
|
|
|
bin/
|
|
|
|
lib/
|
|
|
|
include/
|
|
|
|
share/
|
|
|
|
...
|
|
|
|
|
2016-05-02 17:16:15 -05:00
|
|
|
# Output folder for all documentation of this target. This is what's filled
|
|
|
|
# in whenever the `doc` step is run.
|
|
|
|
doc/
|
|
|
|
|
|
|
|
# Output for all compiletest-based test suites
|
|
|
|
test/
|
|
|
|
run-pass/
|
|
|
|
compile-fail/
|
|
|
|
debuginfo/
|
|
|
|
...
|
|
|
|
|
2015-11-19 17:20:12 -06:00
|
|
|
# Location where the stage0 Cargo and Rust compiler are unpacked. This
|
|
|
|
# directory is purely an extracted and overlaid tarball of these two (done
|
|
|
|
# by the bootstrapy python script). In theory the build system does not
|
|
|
|
# modify anything under this directory afterwards.
|
|
|
|
stage0/
|
|
|
|
|
|
|
|
# These to build directories are the cargo output directories for builds of
|
|
|
|
# the standard library and compiler, respectively. Internally these may also
|
|
|
|
# have other target directories, which represent artifacts being compiled
|
|
|
|
# from the host to the specified target.
|
|
|
|
#
|
|
|
|
# Essentially, each of these directories is filled in by one `cargo`
|
|
|
|
# invocation. The build system instruments calling Cargo in the right order
|
|
|
|
# with the right variables to ensure these are filled in correctly.
|
|
|
|
stageN-std/
|
2016-05-02 17:16:15 -05:00
|
|
|
stageN-test/
|
2015-11-19 17:20:12 -06:00
|
|
|
stageN-rustc/
|
2016-05-02 17:16:15 -05:00
|
|
|
stageN-tools/
|
2015-11-19 17:20:12 -06:00
|
|
|
|
|
|
|
# This is a special case of the above directories, **not** filled in via
|
|
|
|
# Cargo but rather the build system itself. The stage0 compiler already has
|
|
|
|
# a set of target libraries for its own host triple (in its own sysroot)
|
|
|
|
# inside of stage0/. When we run the stage0 compiler to bootstrap more
|
|
|
|
# things, however, we don't want to use any of these libraries (as those are
|
|
|
|
# the ones that we're building). So essentially, when the stage1 compiler is
|
|
|
|
# being compiled (e.g. after libstd has been built), *this* is used as the
|
|
|
|
# sysroot for the stage0 compiler being run.
|
|
|
|
#
|
|
|
|
# Basically this directory is just a temporary artifact use to configure the
|
|
|
|
# stage0 compiler to ensure that the libstd we just built is used to
|
|
|
|
# compile the stage1 compiler.
|
2016-05-02 17:16:15 -05:00
|
|
|
stage0-sysroot/lib/
|
2015-11-19 17:20:12 -06:00
|
|
|
|
|
|
|
# These output directories are intended to be standalone working
|
|
|
|
# implementations of the compiler (corresponding to each stage). The build
|
|
|
|
# system will link (using hard links) output from stageN-{std,rustc} into
|
|
|
|
# each of these directories.
|
|
|
|
#
|
|
|
|
# In theory there is no extra build output in these directories.
|
|
|
|
stage1/
|
|
|
|
stage2/
|
|
|
|
stage3/
|
|
|
|
```
|
2016-05-02 17:16:15 -05:00
|
|
|
|
|
|
|
## Cargo projects
|
|
|
|
|
|
|
|
The current build is unfortunately not quite as simple as `cargo build` in a
|
|
|
|
directory, but rather the compiler is split into three different Cargo projects:
|
|
|
|
|
2017-02-15 10:53:18 -06:00
|
|
|
* `src/libstd` - the standard library
|
|
|
|
* `src/libtest` - testing support, depends on libstd
|
2016-05-02 17:16:15 -05:00
|
|
|
* `src/rustc` - the actual compiler itself
|
|
|
|
|
|
|
|
Each "project" has a corresponding Cargo.lock file with all dependencies, and
|
|
|
|
this means that building the compiler involves running Cargo three times. The
|
|
|
|
structure here serves two goals:
|
|
|
|
|
|
|
|
1. Facilitating dependencies coming from crates.io. These dependencies don't
|
|
|
|
depend on `std`, so libstd is a separate project compiled ahead of time
|
|
|
|
before the actual compiler builds.
|
|
|
|
2. Splitting "host artifacts" from "target artifacts". That is, when building
|
|
|
|
code for an arbitrary target you don't need the entire compiler, but you'll
|
|
|
|
end up needing libraries like libtest that depend on std but also want to use
|
|
|
|
crates.io dependencies. Hence, libtest is split out as its own project that
|
|
|
|
is sequenced after `std` but before `rustc`. This project is built for all
|
|
|
|
targets.
|
|
|
|
|
|
|
|
There is some loss in build parallelism here because libtest can be compiled in
|
|
|
|
parallel with a number of rustc artifacts, but in theory the loss isn't too bad!
|
|
|
|
|
|
|
|
## Build tools
|
|
|
|
|
|
|
|
We've actually got quite a few tools that we use in the compiler's build system
|
|
|
|
and for testing. To organize these, each tool is a project in `src/tools` with a
|
|
|
|
corresponding `Cargo.toml`. All tools are compiled with Cargo (currently having
|
|
|
|
independent `Cargo.lock` files) and do not currently explicitly depend on the
|
|
|
|
compiler or standard library. Compiling each tool is sequenced after the
|
|
|
|
appropriate libstd/libtest/librustc compile above.
|
|
|
|
|
|
|
|
## Extending rustbuild
|
|
|
|
|
|
|
|
So you'd like to add a feature to the rustbuild build system or just fix a bug.
|
|
|
|
Great! One of the major motivational factors for moving away from `make` is that
|
|
|
|
Rust is in theory much easier to read, modify, and write. If you find anything
|
|
|
|
excessively confusing, please open an issue on this and we'll try to get it
|
|
|
|
documented or simplified pronto.
|
|
|
|
|
|
|
|
First up, you'll probably want to read over the documentation above as that'll
|
|
|
|
give you a high level overview of what rustbuild is doing. You also probably
|
|
|
|
want to play around a bit yourself by just getting it up and running before you
|
|
|
|
dive too much into the actual build system itself.
|
|
|
|
|
|
|
|
After that, each module in rustbuild should have enough documentation to keep
|
|
|
|
you up and running. Some general areas that you may be interested in modifying
|
|
|
|
are:
|
|
|
|
|
2017-08-21 07:22:01 -05:00
|
|
|
* Adding a new build tool? Take a look at `bootstrap/tool.rs` for examples of
|
2016-11-16 14:31:19 -06:00
|
|
|
other tools.
|
2016-05-02 17:16:15 -05:00
|
|
|
* Adding a new compiler crate? Look no further! Adding crates can be done by
|
|
|
|
adding a new directory with `Cargo.toml` followed by configuring all
|
|
|
|
`Cargo.toml` files accordingly.
|
2017-08-21 07:22:01 -05:00
|
|
|
* Adding a new dependency from crates.io? This should just work inside the
|
|
|
|
compiler artifacts stage (everything other than libtest and libstd).
|
|
|
|
* Adding a new configuration option? You'll want to modify `bootstrap/flags.rs`
|
|
|
|
for command line flags and then `bootstrap/config.rs` to copy the flags to the
|
|
|
|
`Config` struct.
|
2016-11-16 14:31:19 -06:00
|
|
|
* Adding a sanity check? Take a look at `bootstrap/sanity.rs`.
|
2016-05-02 17:16:15 -05:00
|
|
|
|
2017-08-21 07:22:01 -05:00
|
|
|
If you have any questions feel free to reach out on `#rust-infra` on IRC or ask on
|
|
|
|
internals.rust-lang.org. When you encounter bugs, please file issues on the
|
|
|
|
rust-lang/rust issue tracker.
|