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.
|
|
|
|
|
|
|
|
> **Note**: This build system is currently under active development and is not
|
|
|
|
> intended to be the primarily used one just yet. The makefiles are currently
|
|
|
|
> the ones that are still "guaranteed to work" as much as possible at least.
|
|
|
|
|
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
|
|
|
|
```
|
|
|
|
|
|
|
|
* `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
|
|
|
|
|
|
|
|
There are currently two primary methods for configuring the rustbuild build
|
|
|
|
system. First, 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.
|
|
|
|
|
|
|
|
Next, rustbuild offers a TOML-based configuration system with a `config.toml`
|
|
|
|
file in the same location as `config.mk`. An example of this configuration can
|
|
|
|
be found at `src/bootstrap/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).
|
|
|
|
|
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
|
|
|
|
|
|
|
## 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:
|
|
|
|
|
|
|
|
* `src/rustc/std_shim` - a project which builds and compiles libstd
|
|
|
|
* `src/rustc/test_shim` - a project which builds and compiles libtest
|
|
|
|
* `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:
|
|
|
|
|
2016-11-16 14:31:19 -06:00
|
|
|
* Adding a new build tool? Take a look at `bootstrap/step.rs` for examples of
|
|
|
|
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.
|
|
|
|
* Adding a new dependency from crates.io? We're still working on that, so hold
|
|
|
|
off on that for now.
|
2016-11-16 14:31:19 -06:00
|
|
|
* Adding a new configuration option? Take a look at `bootstrap/config.rs` or
|
|
|
|
perhaps `bootstrap/flags.rs` and then modify the build elsewhere to read that
|
|
|
|
option.
|
|
|
|
* Adding a sanity check? Take a look at `bootstrap/sanity.rs`.
|
2016-05-02 17:16:15 -05:00
|
|
|
|
|
|
|
If you have any questions feel free to reach out on `#rust-internals` on IRC or
|
|
|
|
open an issue in the bug tracker!
|