Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f72bfe6

Browse files
committedMay 3, 2016
rustbuild: Document many more parts of the build
This commit expands the bootstrap build system's `README.md` as well as ensuring that all API documentation is present and up-to-date. Additionally a new `config.toml.example` file is checked in with commented out versions of all possible configuration values.
1 parent d80497e commit f72bfe6

File tree

19 files changed

+726
-47
lines changed

19 files changed

+726
-47
lines changed
 

‎src/bootstrap/README.md

Lines changed: 136 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Bootstrapping Rust
1+
# rustbuild - Bootstrapping Rust
22

33
This is an in-progress README which is targeted at helping to explain how Rust
44
is bootstrapped and in general some of the technical details of the build
@@ -8,20 +8,64 @@ system.
88
> intended to be the primarily used one just yet. The makefiles are currently
99
> the ones that are still "guaranteed to work" as much as possible at least.
1010
11-
## Using the new build system
11+
## Using rustbuild
1212

1313
When configuring Rust via `./configure`, pass the following to enable building
1414
via this build system:
1515

1616
```
1717
./configure --enable-rustbuild
18+
make
1819
```
1920

20-
## ...
21+
Afterwards the `Makefile` which is generated will have a few commands like
22+
`make check`, `make tidy`, etc. For finer-grained control, the
23+
`bootstrap.py` entry point can be used:
24+
25+
```
26+
python src/bootstrap/bootstrap.py
27+
```
28+
29+
This accepts a number of options like `--stage` and `--step` which can configure
30+
what's actually being done.
31+
32+
## Configuring rustbuild
33+
34+
There are currently two primary methods for configuring the rustbuild build
35+
system. First, the `./configure` options serialized in `config.mk` will be
36+
parsed and read. That is, if any `./configure` options are passed, they'll be
37+
handled naturally.
38+
39+
Next, rustbuild offers a TOML-based configuration system with a `config.toml`
40+
file in the same location as `config.mk`. An example of this configuration can
41+
be found at `src/bootstrap/config.toml.example`, and the configuration file
42+
can also be passed as `--config path/to/config.toml` if the build system is
43+
being invoked manually (via the python script).
44+
45+
## Build stages
46+
47+
The rustbuild build system goes through a few phases to actually build the
48+
compiler. What actually happens when you invoke rustbuild is:
49+
50+
1. The entry point script, `src/bootstrap/bootstrap.py` is run. This script is
51+
responsible for downloading the stage0 compiler/Cargo binaries, and it then
52+
compiles the build system itself (this folder). Finally, it then invokes the
53+
actual `boostrap` binary build system.
54+
2. In Rust, `bootstrap` will slurp up all configuration, perform a number of
55+
sanity checks (compilers exist for example), and then start building the
56+
stage0 artifacts.
57+
3. The stage0 `cargo` downloaded earlier is used to build the standard library
58+
and the compiler, and then these binaries are then copied to the `stage1`
59+
directory. That compiler is then used to generate the stage1 artifacts which
60+
are then copied to the stage2 directory, and then finally the stage2
61+
artifacts are generated using that compiler.
62+
63+
The goal of each stage is to (a) leverage Cargo as much as possible and failing
64+
that (b) leverage Rust as much as possible!
2165

2266
## Directory Layout
2367

24-
This build system houses all output under the `target` directory, which looks
68+
This build system houses all output under the `build` directory, which looks
2569
like this:
2670

2771
```
@@ -42,6 +86,12 @@ build/
4286
debug/
4387
release/
4488
89+
# Output of the dist-related steps like dist-std, dist-rustc, and dist-docs
90+
dist/
91+
92+
# Temporary directory used for various input/output as part of various stages
93+
tmp/
94+
4595
# Each remaining directory is scoped by the "host" triple of compilation at
4696
# hand.
4797
x86_64-unknown-linux-gnu/
@@ -50,7 +100,8 @@ build/
50100
# folder is under. The exact layout here will likely depend on the platform,
51101
# and this is also built with CMake so the build system is also likely
52102
# different.
53-
compiler-rt/build/
103+
compiler-rt/
104+
build/
54105
55106
# Output folder for LLVM if it is compiled for this target
56107
llvm/
@@ -67,6 +118,17 @@ build/
67118
share/
68119
...
69120
121+
# Output folder for all documentation of this target. This is what's filled
122+
# in whenever the `doc` step is run.
123+
doc/
124+
125+
# Output for all compiletest-based test suites
126+
test/
127+
run-pass/
128+
compile-fail/
129+
debuginfo/
130+
...
131+
70132
# Location where the stage0 Cargo and Rust compiler are unpacked. This
71133
# directory is purely an extracted and overlaid tarball of these two (done
72134
# by the bootstrapy python script). In theory the build system does not
@@ -82,7 +144,9 @@ build/
82144
# invocation. The build system instruments calling Cargo in the right order
83145
# with the right variables to ensure these are filled in correctly.
84146
stageN-std/
147+
stageN-test/
85148
stageN-rustc/
149+
stageN-tools/
86150
87151
# This is a special case of the above directories, **not** filled in via
88152
# Cargo but rather the build system itself. The stage0 compiler already has
@@ -96,7 +160,7 @@ build/
96160
# Basically this directory is just a temporary artifact use to configure the
97161
# stage0 compiler to ensure that the libstd we just built is used to
98162
# compile the stage1 compiler.
99-
stage0-rustc/lib/
163+
stage0-sysroot/lib/
100164
101165
# These output directories are intended to be standalone working
102166
# implementations of the compiler (corresponding to each stage). The build
@@ -108,3 +172,69 @@ build/
108172
stage2/
109173
stage3/
110174
```
175+
176+
## Cargo projects
177+
178+
The current build is unfortunately not quite as simple as `cargo build` in a
179+
directory, but rather the compiler is split into three different Cargo projects:
180+
181+
* `src/rustc/std_shim` - a project which builds and compiles libstd
182+
* `src/rustc/test_shim` - a project which builds and compiles libtest
183+
* `src/rustc` - the actual compiler itself
184+
185+
Each "project" has a corresponding Cargo.lock file with all dependencies, and
186+
this means that building the compiler involves running Cargo three times. The
187+
structure here serves two goals:
188+
189+
1. Facilitating dependencies coming from crates.io. These dependencies don't
190+
depend on `std`, so libstd is a separate project compiled ahead of time
191+
before the actual compiler builds.
192+
2. Splitting "host artifacts" from "target artifacts". That is, when building
193+
code for an arbitrary target you don't need the entire compiler, but you'll
194+
end up needing libraries like libtest that depend on std but also want to use
195+
crates.io dependencies. Hence, libtest is split out as its own project that
196+
is sequenced after `std` but before `rustc`. This project is built for all
197+
targets.
198+
199+
There is some loss in build parallelism here because libtest can be compiled in
200+
parallel with a number of rustc artifacts, but in theory the loss isn't too bad!
201+
202+
## Build tools
203+
204+
We've actually got quite a few tools that we use in the compiler's build system
205+
and for testing. To organize these, each tool is a project in `src/tools` with a
206+
corresponding `Cargo.toml`. All tools are compiled with Cargo (currently having
207+
independent `Cargo.lock` files) and do not currently explicitly depend on the
208+
compiler or standard library. Compiling each tool is sequenced after the
209+
appropriate libstd/libtest/librustc compile above.
210+
211+
## Extending rustbuild
212+
213+
So you'd like to add a feature to the rustbuild build system or just fix a bug.
214+
Great! One of the major motivational factors for moving away from `make` is that
215+
Rust is in theory much easier to read, modify, and write. If you find anything
216+
excessively confusing, please open an issue on this and we'll try to get it
217+
documented or simplified pronto.
218+
219+
First up, you'll probably want to read over the documentation above as that'll
220+
give you a high level overview of what rustbuild is doing. You also probably
221+
want to play around a bit yourself by just getting it up and running before you
222+
dive too much into the actual build system itself.
223+
224+
After that, each module in rustbuild should have enough documentation to keep
225+
you up and running. Some general areas that you may be interested in modifying
226+
are:
227+
228+
* Adding a new build tool? Take a look at `build/step.rs` for examples of other
229+
tools, as well as `build/mod.rs`.
230+
* Adding a new compiler crate? Look no further! Adding crates can be done by
231+
adding a new directory with `Cargo.toml` followed by configuring all
232+
`Cargo.toml` files accordingly.
233+
* Adding a new dependency from crates.io? We're still working on that, so hold
234+
off on that for now.
235+
* Adding a new configuration option? Take a look at `build/config.rs` or perhaps
236+
`build/flags.rs` and then modify the build elsewhere to read that option.
237+
* Adding a sanity check? Take a look at `build/sanity.rs`.
238+
239+
If you have any questions feel free to reach out on `#rust-internals` on IRC or
240+
open an issue in the bug tracker!

‎src/bootstrap/build/cc.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,29 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! C-compiler probing and detection.
12+
//!
13+
//! This module will fill out the `cc` and `cxx` maps of `Build` by looking for
14+
//! C and C++ compilers for each target configured. A compiler is found through
15+
//! a number of vectors (in order of precedence)
16+
//!
17+
//! 1. Configuration via `target.$target.cc` in `config.toml`.
18+
//! 2. Configuration via `target.$target.android-ndk` in `config.toml`, if
19+
//! applicable
20+
//! 3. Special logic to probe on OpenBSD
21+
//! 4. The `CC_$target` environment variable.
22+
//! 5. The `CC` environment variable.
23+
//! 6. "cc"
24+
//!
25+
//! Some of this logic is implemented here, but much of it is farmed out to the
26+
//! `gcc` crate itself, so we end up having the same fallbacks as there.
27+
//! Similar logic is then used to find a C++ compiler, just some s/cc/c++/ is
28+
//! used.
29+
//!
30+
//! It is intended that after this module has run no C/C++ compiler will
31+
//! ever be probed for. Instead the compilers found here will be used for
32+
//! everything.
33+
1134
use std::process::Command;
1235

1336
use build_helper::{cc2ar, output};

‎src/bootstrap/build/channel.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::env;
11+
//! Build configuration for Rust's release channels.
12+
//!
13+
//! Implements the stable/beta/nightly channel distinctions by setting various
14+
//! flags like the `unstable_features`, calculating variables like `release` and
15+
//! `package_vers`, and otherwise indicating to the compiler what it should
16+
//! print out as part of its version information.
17+
1218
use std::fs::{self, File};
1319
use std::io::prelude::*;
1420
use std::process::Command;
@@ -19,6 +25,9 @@ use md5;
1925
use build::Build;
2026

2127
pub fn collect(build: &mut Build) {
28+
// Currently the canonical source for the release number (e.g. 1.10.0) and
29+
// the prerelease version (e.g. `.1`) is in `mk/main.mk`. We "parse" that
30+
// here to learn about those numbers.
2231
let mut main_mk = String::new();
2332
t!(t!(File::open(build.src.join("mk/main.mk"))).read_to_string(&mut main_mk));
2433
let mut release_num = "";
@@ -32,7 +41,8 @@ pub fn collect(build: &mut Build) {
3241
}
3342
}
3443

35-
// FIXME: this is duplicating makefile logic
44+
// Depending on the channel, passed in `./configure --release-channel`,
45+
// determine various properties of the build.
3646
match &build.config.channel[..] {
3747
"stable" => {
3848
build.release = release_num.to_string();
@@ -58,6 +68,8 @@ pub fn collect(build: &mut Build) {
5868
}
5969
build.version = build.release.clone();
6070

71+
// If we have a git directory, add in some various SHA information of what
72+
// commit this compiler was compiled from.
6173
if fs::metadata(build.src.join(".git")).is_ok() {
6274
let ver_date = output(Command::new("git").current_dir(&build.src)
6375
.arg("log").arg("-1")
@@ -80,11 +92,14 @@ pub fn collect(build: &mut Build) {
8092
build.short_ver_hash = Some(short_ver_hash);
8193
}
8294

95+
// Calculate this compiler's bootstrap key, which is currently defined as
96+
// the first 8 characters of the md5 of the release string.
8397
let key = md5::compute(build.release.as_bytes());
8498
build.bootstrap_key = format!("{:02x}{:02x}{:02x}{:02x}",
8599
key[0], key[1], key[2], key[3]);
86-
env::set_var("RUSTC_BOOTSTRAP_KEY", &build.bootstrap_key);
87100

101+
// Slurp up the stage0 bootstrap key as we're bootstrapping from an
102+
// otherwise stable compiler.
88103
let mut s = String::new();
89104
t!(t!(File::open(build.src.join("src/stage0.txt"))).read_to_string(&mut s));
90105
if let Some(line) = s.lines().find(|l| l.starts_with("rustc_key")) {

‎src/bootstrap/build/check.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! Implementation of the various `check-*` targets of the build system.
12+
//!
13+
//! This file implements the various regression test suites that we execute on
14+
//! our CI.
15+
1116
use std::fs;
1217
use std::path::{PathBuf, Path};
1318
use std::process::Command;
@@ -16,15 +21,22 @@ use build_helper::output;
1621

1722
use build::{Build, Compiler};
1823

24+
/// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
25+
///
26+
/// This tool in `src/tools` will verify the validity of all our links in the
27+
/// documentation to ensure we don't have a bunch of dead ones.
1928
pub fn linkcheck(build: &Build, stage: u32, host: &str) {
2029
println!("Linkcheck stage{} ({})", stage, host);
2130
let compiler = Compiler::new(stage, host);
2231
build.run(build.tool_cmd(&compiler, "linkchecker")
2332
.arg(build.out.join(host).join("doc")));
2433
}
2534

35+
/// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler.
36+
///
37+
/// This tool in `src/tools` will check out a few Rust projects and run `cargo
38+
/// test` to ensure that we don't regress the test suites there.
2639
pub fn cargotest(build: &Build, stage: u32, host: &str) {
27-
2840
let ref compiler = Compiler::new(stage, host);
2941

3042
// Configure PATH to find the right rustc. NB. we have to use PATH
@@ -47,6 +59,11 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) {
4759
.arg(&out_dir));
4860
}
4961

62+
/// Runs the `tidy` tool as compiled in `stage` by the `host` compiler.
63+
///
64+
/// This tool in `src/tools` checks up on various bits and pieces of style and
65+
/// otherwise just implements a few lint-like checks that are specific to the
66+
/// compiler itself.
5067
pub fn tidy(build: &Build, stage: u32, host: &str) {
5168
println!("tidy check stage{} ({})", stage, host);
5269
let compiler = Compiler::new(stage, host);
@@ -58,13 +75,21 @@ fn testdir(build: &Build, host: &str) -> PathBuf {
5875
build.out.join(host).join("test")
5976
}
6077

78+
/// Executes the `compiletest` tool to run a suite of tests.
79+
///
80+
/// Compiles all tests with `compiler` for `target` with the specified
81+
/// compiletest `mode` and `suite` arguments. For example `mode` can be
82+
/// "run-pass" or `suite` can be something like `debuginfo`.
6183
pub fn compiletest(build: &Build,
6284
compiler: &Compiler,
6385
target: &str,
6486
mode: &str,
6587
suite: &str) {
6688
let mut cmd = build.tool_cmd(compiler, "compiletest");
6789

90+
// compiletest currently has... a lot of arguments, so let's just pass all
91+
// of them!
92+
6893
cmd.arg("--compile-lib-path").arg(build.rustc_libdir(compiler));
6994
cmd.arg("--run-lib-path").arg(build.sysroot_libdir(compiler, target));
7095
cmd.arg("--rustc-path").arg(build.compiler_path(compiler));
@@ -114,6 +139,8 @@ pub fn compiletest(build: &Build,
114139
cmd.arg("--verbose");
115140
}
116141

142+
// Only pass correct values for these flags for the `run-make` suite as it
143+
// requires that a C++ compiler was configured which isn't always the case.
117144
if suite == "run-make" {
118145
let llvm_config = build.llvm_config(target);
119146
let llvm_components = output(Command::new(&llvm_config).arg("--components"));
@@ -140,11 +167,19 @@ pub fn compiletest(build: &Build,
140167
}
141168
}
142169
}
170+
build.add_bootstrap_key(compiler, &mut cmd);
143171

144172
build.run(&mut cmd);
145173
}
146174

175+
/// Run `rustdoc --test` for all documentation in `src/doc`.
176+
///
177+
/// This will run all tests in our markdown documentation (e.g. the book)
178+
/// located in `src/doc`. The `rustdoc` that's run is the one that sits next to
179+
/// `compiler`.
147180
pub fn docs(build: &Build, compiler: &Compiler) {
181+
// Do a breadth-first traversal of the `src/doc` directory and just run
182+
// tests for all files that end in `*.md`
148183
let mut stack = vec![build.src.join("src/doc")];
149184

150185
while let Some(p) = stack.pop() {
@@ -162,6 +197,12 @@ pub fn docs(build: &Build, compiler: &Compiler) {
162197
}
163198
}
164199

200+
/// Run the error index generator tool to execute the tests located in the error
201+
/// index.
202+
///
203+
/// The `error_index_generator` tool lives in `src/tools` and is used to
204+
/// generate a markdown file from the error indexes of the code base which is
205+
/// then passed to `rustdoc --test`.
165206
pub fn error_index(build: &Build, compiler: &Compiler) {
166207
println!("Testing error-index stage{}", compiler.stage);
167208

‎src/bootstrap/build/clean.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! Implementation of `make clean` in rustbuild.
12+
//!
13+
//! Responsible for cleaning out a build directory of all old and stale
14+
//! artifacts to prepare for a fresh build. Currently doesn't remove the
15+
//! `build/cache` directory (download cache) or the `build/$target/llvm`
16+
//! directory as we want that cached between builds.
17+
1118
use std::fs;
1219
use std::path::Path;
1320

‎src/bootstrap/build/compile.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! Implementation of compiling various phases of the compiler and standard
12+
//! library.
13+
//!
14+
//! This module contains some of the real meat in the rustbuild build system
15+
//! which is where Cargo is used to compiler the standard library, libtest, and
16+
//! compiler. This module is also responsible for assembling the sysroot as it
17+
//! goes along from the output of the previous stage.
18+
1119
use std::collections::HashMap;
1220
use std::fs;
1321
use std::path::{Path, PathBuf};
@@ -35,6 +43,8 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
3543
copy(&build.compiler_rt_built.borrow()[target],
3644
&libdir.join(staticlib("compiler-rt", target)));
3745

46+
// Some platforms have startup objects that may be required to produce the
47+
// libstd dynamic library, for example.
3848
build_startup_objects(build, target, &libdir);
3949

4050
let out_dir = build.cargo_out(compiler, Mode::Libstd, target);
@@ -154,7 +164,6 @@ pub fn test_link(build: &Build,
154164
add_to_sysroot(&out_dir, &libdir);
155165
}
156166

157-
158167
/// Build the compiler.
159168
///
160169
/// This will build the compiler for a particular stage of the build using

‎src/bootstrap/build/config.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! Serialized configuration of a build.
12+
//!
13+
//! This module implements parsing `config.mk` and `config.toml` configuration
14+
//! files to tweak how the build runs.
15+
1116
use std::collections::HashMap;
1217
use std::env;
1318
use std::fs::File;
@@ -27,7 +32,9 @@ use toml::{Parser, Decoder, Value};
2732
/// is generated from `./configure`.
2833
///
2934
/// Note that this structure is not decoded directly into, but rather it is
30-
/// filled out from the decoded forms of the structs below.
35+
/// filled out from the decoded forms of the structs below. For documentation
36+
/// each field, see the corresponding fields in
37+
/// `src/bootstrap/config.toml.example`.
3138
#[derive(Default)]
3239
pub struct Config {
3340
pub ccache: bool,
@@ -250,6 +257,11 @@ impl Config {
250257
return config
251258
}
252259

260+
/// "Temporary" routine to parse `config.mk` into this configuration.
261+
///
262+
/// While we still have `./configure` this implements the ability to decode
263+
/// that configuration into this. This isn't exactly a full-blown makefile
264+
/// parser, but hey it gets the job done!
253265
pub fn update_with_config_mk(&mut self) {
254266
let mut config = String::new();
255267
File::open("config.mk").unwrap().read_to_string(&mut config).unwrap();

‎src/bootstrap/build/dist.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! Implementation of the various distribution aspects of the compiler.
12+
//!
13+
//! This module is responsible for creating tarballs of the standard library,
14+
//! compiler, and documentation. This ends up being what we distribute to
15+
//! everyone as well.
16+
//!
17+
//! No tarball is actually created literally in this file, but rather we shell
18+
//! out to `rust-installer` still. This may one day be replaced with bits and
19+
//! pieces of `rustup.rs`!
20+
1121
use std::fs::{self, File};
1222
use std::io::Write;
1323
use std::path::{PathBuf, Path};
@@ -33,6 +43,9 @@ fn tmpdir(build: &Build) -> PathBuf {
3343
build.out.join("tmp/dist")
3444
}
3545

46+
/// Builds the `rust-docs` installer component.
47+
///
48+
/// Slurps up documentation from the `stage`'s `host`.
3649
pub fn docs(build: &Build, stage: u32, host: &str) {
3750
println!("Dist docs stage{} ({})", stage, host);
3851
let name = format!("rust-docs-{}", package_vers(build));
@@ -68,6 +81,12 @@ pub fn docs(build: &Build, stage: u32, host: &str) {
6881
}
6982
}
7083

84+
/// Build the `rust-mingw` installer component.
85+
///
86+
/// This contains all the bits and pieces to run the MinGW Windows targets
87+
/// without any extra installed software (e.g. we bundle gcc, libraries, etc).
88+
/// Currently just shells out to a python script, but that should be rewritten
89+
/// in Rust.
7190
pub fn mingw(build: &Build, host: &str) {
7291
println!("Dist mingw ({})", host);
7392
let name = format!("rust-mingw-{}", package_vers(build));
@@ -102,6 +121,7 @@ pub fn mingw(build: &Build, host: &str) {
102121
t!(fs::remove_dir_all(&image));
103122
}
104123

124+
/// Creates the `rustc` installer component.
105125
pub fn rustc(build: &Build, stage: u32, host: &str) {
106126
println!("Dist rustc stage{} ({})", stage, host);
107127
let name = format!("rustc-{}", package_vers(build));
@@ -209,6 +229,7 @@ pub fn rustc(build: &Build, stage: u32, host: &str) {
209229
}
210230
}
211231

232+
/// Copies debugger scripts for `host` into the `sysroot` specified.
212233
pub fn debugger_scripts(build: &Build,
213234
sysroot: &Path,
214235
host: &str) {
@@ -237,7 +258,8 @@ pub fn debugger_scripts(build: &Build,
237258
}
238259
}
239260

240-
261+
/// Creates the `rust-std` installer component as compiled by `compiler` for the
262+
/// target `target`.
241263
pub fn std(build: &Build, compiler: &Compiler, target: &str) {
242264
println!("Dist std stage{} ({} -> {})", compiler.stage, compiler.host,
243265
target);

‎src/bootstrap/build/doc.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! Documentation generation for rustbuild.
12+
//!
13+
//! This module implements generation for all bits and pieces of documentation
14+
//! for the Rust project. This notably includes suites like the rust book, the
15+
//! nomicon, standalone documentation, etc.
16+
//!
17+
//! Everything here is basically just a shim around calling either `rustbook` or
18+
//! `rustdoc`.
19+
1120
use std::fs::{self, File};
1221
use std::io::prelude::*;
1322
use std::path::Path;
@@ -16,6 +25,11 @@ use std::process::Command;
1625
use build::{Build, Compiler, Mode};
1726
use build::util::{up_to_date, cp_r};
1827

28+
/// Invoke `rustbook` as compiled in `stage` for `target` for the doc book
29+
/// `name` into the `out` path.
30+
///
31+
/// This will not actually generate any documentation if the documentation has
32+
/// already been generated.
1933
pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str, out: &Path) {
2034
t!(fs::create_dir_all(out));
2135

@@ -35,6 +49,14 @@ pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str, out: &Path)
3549
.arg(out));
3650
}
3751

52+
/// Generates all standalone documentation as compiled by the rustdoc in `stage`
53+
/// for the `target` into `out`.
54+
///
55+
/// This will list all of `src/doc` looking for markdown files and appropriately
56+
/// perform transformations like substituting `VERSION`, `SHORT_HASH`, and
57+
/// `STAMP` alongw ith providing the various header/footer HTML we've cutomized.
58+
///
59+
/// In the end, this is just a glorified wrapper around rustdoc!
3860
pub fn standalone(build: &Build, stage: u32, target: &str, out: &Path) {
3961
println!("Documenting stage{} standalone ({})", stage, target);
4062
t!(fs::create_dir_all(out));
@@ -105,6 +127,10 @@ pub fn standalone(build: &Build, stage: u32, target: &str, out: &Path) {
105127
}
106128
}
107129

130+
/// Compile all standard library documentation.
131+
///
132+
/// This will generate all documentation for the standard library and its
133+
/// dependencies. This is largely just a wrapper around `cargo doc`.
108134
pub fn std(build: &Build, stage: u32, target: &str, out: &Path) {
109135
println!("Documenting stage{} std ({})", stage, target);
110136
t!(fs::create_dir_all(out));
@@ -123,6 +149,10 @@ pub fn std(build: &Build, stage: u32, target: &str, out: &Path) {
123149
cp_r(&out_dir, out)
124150
}
125151

152+
/// Compile all libtest documentation.
153+
///
154+
/// This will generate all documentation for libtest and its dependencies. This
155+
/// is largely just a wrapper around `cargo doc`.
126156
pub fn test(build: &Build, stage: u32, target: &str, out: &Path) {
127157
println!("Documenting stage{} test ({})", stage, target);
128158
let compiler = Compiler::new(stage, &build.config.build);
@@ -139,6 +169,10 @@ pub fn test(build: &Build, stage: u32, target: &str, out: &Path) {
139169
cp_r(&out_dir, out)
140170
}
141171

172+
/// Generate all compiler documentation.
173+
///
174+
/// This will generate all documentation for the compiler libraries and their
175+
/// dependencies. This is largely just a wrapper around `cargo doc`.
142176
pub fn rustc(build: &Build, stage: u32, target: &str, out: &Path) {
143177
println!("Documenting stage{} compiler ({})", stage, target);
144178
let compiler = Compiler::new(stage, &build.config.build);
@@ -156,6 +190,8 @@ pub fn rustc(build: &Build, stage: u32, target: &str, out: &Path) {
156190
cp_r(&out_dir, out)
157191
}
158192

193+
/// Generates the HTML rendered error-index by running the
194+
/// `error_index_generator` tool.
159195
pub fn error_index(build: &Build, stage: u32, target: &str, out: &Path) {
160196
println!("Documenting stage{} error index ({})", stage, target);
161197
t!(fs::create_dir_all(out));

‎src/bootstrap/build/flags.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,19 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! Command-line interface of the rustbuild build system.
12+
//!
13+
//! This module implements the command-line parsing of the build system which
14+
//! has various flags to configure how it's run.
15+
1116
use std::fs;
1217
use std::path::PathBuf;
1318
use std::process;
1419
use std::slice;
1520

1621
use getopts::Options;
1722

23+
/// Deserialized version of all flags for this compile.
1824
pub struct Flags {
1925
pub verbose: bool,
2026
pub stage: Option<u32>,

‎src/bootstrap/build/mod.rs

Lines changed: 143 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! Implementation of rustbuild, the Rust build system.
12+
//!
13+
//! This module, and its descendants, are the implementation of the Rust build
14+
//! system. Most of this build system is backed by Cargo but the outer layer
15+
//! here serves as the ability to orchestrate calling Cargo, sequencing Cargo
16+
//! builds, building artifacts like LLVM, etc.
17+
//!
18+
//! More documentation can be found in each respective module below.
19+
1120
use std::cell::RefCell;
1221
use std::collections::HashMap;
1322
use std::env;
@@ -21,6 +30,14 @@ use num_cpus;
2130

2231
use build::util::{exe, mtime, libdir, add_lib_path};
2332

33+
/// A helper macro to `unwrap` a result except also print out details like:
34+
///
35+
/// * The file/line of the panic
36+
/// * The expression that failed
37+
/// * The error itself
38+
///
39+
/// This is currently used judiciously throughout the build system rather than
40+
/// using a `Result` with `try!`, but this may change on day...
2441
macro_rules! t {
2542
($e:expr) => (match $e {
2643
Ok(e) => e,
@@ -53,12 +70,27 @@ mod job {
5370
pub use build::config::Config;
5471
pub use build::flags::Flags;
5572

73+
/// A structure representing a Rust compiler.
74+
///
75+
/// Each compiler has a `stage` that it is associated with and a `host` that
76+
/// corresponds to the platform the compiler runs on. This structure is used as
77+
/// a parameter to many methods below.
5678
#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)]
5779
pub struct Compiler<'a> {
5880
stage: u32,
5981
host: &'a str,
6082
}
6183

84+
/// Global configuration for the build system.
85+
///
86+
/// This structure transitively contains all configuration for the build system.
87+
/// All filesystem-encoded configuration is in `config`, all flags are in
88+
/// `flags`, and then parsed or probed information is listed in the keys below.
89+
///
90+
/// This structure is a parameter of almost all methods in the build system,
91+
/// although most functions are implemented as free functions rather than
92+
/// methods specifically on this structure itself (to make it easier to
93+
/// organize).
6294
pub struct Build {
6395
// User-specified configuration via config.toml
6496
config: Config,
@@ -92,14 +124,33 @@ pub struct Build {
92124
compiler_rt_built: RefCell<HashMap<String, PathBuf>>,
93125
}
94126

127+
/// The various "modes" of invoking Cargo.
128+
///
129+
/// These entries currently correspond to the various output directories of the
130+
/// build system, with each mod generating output in a different directory.
95131
pub enum Mode {
132+
/// This cargo is going to build the standard library, placing output in the
133+
/// "stageN-std" directory.
96134
Libstd,
135+
136+
/// This cargo is going to build libtest, placing output in the
137+
/// "stageN-test" directory.
97138
Libtest,
139+
140+
/// This cargo is going to build librustc and compiler libraries, placing
141+
/// output in the "stageN-rustc" directory.
98142
Librustc,
143+
144+
/// This cargo is going to some build tool, placing output in the
145+
/// "stageN-tools" directory.
99146
Tool,
100147
}
101148

102149
impl Build {
150+
/// Creates a new set of build configuration from the `flags` on the command
151+
/// line and the filesystem `config`.
152+
///
153+
/// By default all build output will be placed in the current directory.
103154
pub fn new(flags: Flags, config: Config) -> Build {
104155
let cwd = t!(env::current_dir());
105156
let src = flags.src.clone().unwrap_or(cwd.clone());
@@ -141,6 +192,7 @@ impl Build {
141192
}
142193
}
143194

195+
/// Executes the entire build, as configured by the flags and configuration.
144196
pub fn build(&mut self) {
145197
use build::step::Source::*;
146198

@@ -161,6 +213,16 @@ impl Build {
161213
self.verbose("updating submodules");
162214
self.update_submodules();
163215

216+
// The main loop of the build system.
217+
//
218+
// The `step::all` function returns a topographically sorted list of all
219+
// steps that need to be executed as part of this build. Each step has a
220+
// corresponding entry in `step.rs` and indicates some unit of work that
221+
// needs to be done as part of the build.
222+
//
223+
// Almost all of these are simple one-liners that shell out to the
224+
// corresponding functionality in the extra modules, where more
225+
// documentation can be found.
164226
for target in step::all(self) {
165227
let doc_out = self.out.join(&target.target).join("doc");
166228
match target.src {
@@ -338,6 +400,10 @@ impl Build {
338400
}
339401
}
340402

403+
/// Updates all git submodules that we have.
404+
///
405+
/// This will detect if any submodules are out of date an run the necessary
406+
/// commands to sync them all with upstream.
341407
fn update_submodules(&self) {
342408
if !self.config.submodules {
343409
return
@@ -350,6 +416,11 @@ impl Build {
350416
cmd.current_dir(&self.src).arg("submodule");
351417
return cmd
352418
};
419+
420+
// FIXME: this takes a seriously long time to execute on Windows and a
421+
// nontrivial amount of time on Unix, we should have a better way
422+
// of detecting whether we need to run all the submodule commands
423+
// below.
353424
let out = output(git_submodule().arg("status"));
354425
if !out.lines().any(|l| l.starts_with("+") || l.starts_with("-")) {
355426
return
@@ -366,8 +437,9 @@ impl Build {
366437
.arg("git").arg("checkout").arg("."));
367438
}
368439

369-
/// Clear out `dir` if our build has been flagged as dirty, and also set
370-
/// ourselves as dirty if `file` changes when `f` is executed.
440+
/// Clear out `dir` if `input` is newer.
441+
///
442+
/// After this executes, it will also ensure that `dir` exists.
371443
fn clear_if_dirty(&self, dir: &Path, input: &Path) {
372444
let stamp = dir.join(".stamp");
373445
if mtime(&stamp) < mtime(input) {
@@ -381,8 +453,10 @@ impl Build {
381453
/// Prepares an invocation of `cargo` to be run.
382454
///
383455
/// This will create a `Command` that represents a pending execution of
384-
/// Cargo for the specified stage, whether or not the standard library is
385-
/// being built, and using the specified compiler targeting `target`.
456+
/// Cargo. This cargo will be configured to use `compiler` as the actual
457+
/// rustc compiler, its output will be scoped by `mode`'s output directory,
458+
/// it will pass the `--target` flag for the specified `target`, and will be
459+
/// executing the Cargo command `cmd`.
386460
fn cargo(&self,
387461
compiler: &Compiler,
388462
mode: Mode,
@@ -398,6 +472,9 @@ impl Build {
398472
// Customize the compiler we're running. Specify the compiler to cargo
399473
// as our shim and then pass it some various options used to configure
400474
// how the actual compiler itself is called.
475+
//
476+
// These variables are primarily all read by
477+
// src/bootstrap/{rustc,rustdoc.rs}
401478
cargo.env("RUSTC", self.out.join("bootstrap/debug/rustc"))
402479
.env("RUSTC_REAL", self.compiler_path(compiler))
403480
.env("RUSTC_STAGE", compiler.stage.to_string())
@@ -414,16 +491,7 @@ impl Build {
414491
.env("RUSTDOC_REAL", self.rustdoc(compiler))
415492
.env("RUSTC_FLAGS", self.rustc_flags(target).join(" "));
416493

417-
// Set the bootstrap key depending on which stage compiler we're using.
418-
// In stage0 we're using a previously released stable compiler, so we
419-
// use the stage0 bootstrap key. Otherwise we use our own build's
420-
// bootstrap key.
421-
let bootstrap_key = if compiler.is_snapshot(self) {
422-
&self.bootstrap_key_stage0
423-
} else {
424-
&self.bootstrap_key
425-
};
426-
cargo.env("RUSTC_BOOTSTRAP_KEY", bootstrap_key);
494+
self.add_bootstrap_key(compiler, &mut cargo);
427495

428496
// Specify some various options for build scripts used throughout
429497
// the build.
@@ -443,7 +511,7 @@ impl Build {
443511

444512
// Environment variables *required* needed throughout the build
445513
//
446-
// FIXME: should update code to not require this env vars
514+
// FIXME: should update code to not require this env var
447515
cargo.env("CFG_COMPILER_HOST_TRIPLE", target);
448516

449517
if self.config.verbose || self.flags.verbose {
@@ -522,6 +590,12 @@ impl Build {
522590
if self.config.rust_optimize {"release"} else {"debug"}
523591
}
524592

593+
/// Returns the sysroot for the `compiler` specified that *this build system
594+
/// generates*.
595+
///
596+
/// That is, the sysroot for the stage0 compiler is not what the compiler
597+
/// thinks it is by default, but it's the same as the default for stages
598+
/// 1-3.
525599
fn sysroot(&self, compiler: &Compiler) -> PathBuf {
526600
if compiler.stage == 0 {
527601
self.out.join(compiler.host).join("stage0-sysroot")
@@ -530,6 +604,8 @@ impl Build {
530604
}
531605
}
532606

607+
/// Returns the libdir where the standard library and other artifacts are
608+
/// found for a compiler's sysroot.
533609
fn sysroot_libdir(&self, compiler: &Compiler, target: &str) -> PathBuf {
534610
self.sysroot(compiler).join("lib").join("rustlib")
535611
.join(target).join("lib")
@@ -561,11 +637,17 @@ impl Build {
561637
}
562638

563639
/// Root output directory for LLVM compiled for `target`
640+
///
641+
/// Note that if LLVM is configured externally then the directory returned
642+
/// will likely be empty.
564643
fn llvm_out(&self, target: &str) -> PathBuf {
565644
self.out.join(target).join("llvm")
566645
}
567646

568-
/// Returns the path to `llvm-config` for the specified target
647+
/// Returns the path to `llvm-config` for the specified target.
648+
///
649+
/// If a custom `llvm-config` was specified for target then that's returned
650+
/// instead.
569651
fn llvm_config(&self, target: &str) -> PathBuf {
570652
let target_config = self.config.target_config.get(target);
571653
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
@@ -576,7 +658,7 @@ impl Build {
576658
}
577659
}
578660

579-
/// Returns the path to `llvm-config` for the specified target
661+
/// Returns the path to `FileCheck` binary for the specified target
580662
fn llvm_filecheck(&self, target: &str) -> PathBuf {
581663
let target_config = self.config.target_config.get(target);
582664
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
@@ -603,15 +685,37 @@ impl Build {
603685
self.out.join(target).join("rust-test-helpers")
604686
}
605687

688+
/// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic
689+
/// library lookup path.
606690
fn add_rustc_lib_path(&self, compiler: &Compiler, cmd: &mut Command) {
607691
// Windows doesn't need dylib path munging because the dlls for the
608692
// compiler live next to the compiler and the system will find them
609693
// automatically.
610-
if cfg!(windows) { return }
694+
if cfg!(windows) {
695+
return
696+
}
611697

612698
add_lib_path(vec![self.rustc_libdir(compiler)], cmd);
613699
}
614700

701+
/// Adds the compiler's bootstrap key to the environment of `cmd`.
702+
fn add_bootstrap_key(&self, compiler: &Compiler, cmd: &mut Command) {
703+
// In stage0 we're using a previously released stable compiler, so we
704+
// use the stage0 bootstrap key. Otherwise we use our own build's
705+
// bootstrap key.
706+
let bootstrap_key = if compiler.is_snapshot(self) {
707+
&self.bootstrap_key_stage0
708+
} else {
709+
&self.bootstrap_key
710+
};
711+
cmd.env("RUSTC_BOOTSTRAP_KEY", bootstrap_key);
712+
}
713+
714+
/// Returns the compiler's libdir where it stores the dynamic libraries that
715+
/// it itself links against.
716+
///
717+
/// For example this returns `<sysroot>/lib` on Unix and `<sysroot>/bin` on
718+
/// Windows.
615719
fn rustc_libdir(&self, compiler: &Compiler) -> PathBuf {
616720
if compiler.is_snapshot(self) {
617721
self.rustc_snapshot_libdir()
@@ -620,30 +724,38 @@ impl Build {
620724
}
621725
}
622726

727+
/// Returns the libdir of the snapshot compiler.
623728
fn rustc_snapshot_libdir(&self) -> PathBuf {
624729
self.rustc.parent().unwrap().parent().unwrap()
625730
.join(libdir(&self.config.build))
626731
}
627732

733+
/// Runs a command, printing out nice contextual information if it fails.
628734
fn run(&self, cmd: &mut Command) {
629735
self.verbose(&format!("running: {:?}", cmd));
630736
run_silent(cmd)
631737
}
632738

739+
/// Prints a message if this build is configured in verbose mode.
633740
fn verbose(&self, msg: &str) {
634741
if self.flags.verbose || self.config.verbose {
635742
println!("{}", msg);
636743
}
637744
}
638745

746+
/// Returns the number of parallel jobs that have been configured for this
747+
/// build.
639748
fn jobs(&self) -> u32 {
640749
self.flags.jobs.unwrap_or(num_cpus::get() as u32)
641750
}
642751

752+
/// Returns the path to the C compiler for the target specified.
643753
fn cc(&self, target: &str) -> &Path {
644754
self.cc[target].0.path()
645755
}
646756

757+
/// Returns a list of flags to pass to the C compiler for the target
758+
/// specified.
647759
fn cflags(&self, target: &str) -> Vec<String> {
648760
// Filter out -O and /O (the optimization flags) that we picked up from
649761
// gcc-rs because the build scripts will determine that for themselves.
@@ -663,15 +775,26 @@ impl Build {
663775
return base
664776
}
665777

778+
/// Returns the path to the `ar` archive utility for the target specified.
666779
fn ar(&self, target: &str) -> &Path {
667780
&self.cc[target].1
668781
}
669782

783+
/// Returns the path to the C++ compiler for the target specified, may panic
784+
/// if no C++ compiler was configured for the target.
670785
fn cxx(&self, target: &str) -> &Path {
671786
self.cxx[target].path()
672787
}
673788

789+
/// Returns flags to pass to the compiler to generate code for `target`.
674790
fn rustc_flags(&self, target: &str) -> Vec<String> {
791+
// New flags should be added here with great caution!
792+
//
793+
// It's quite unfortunate to **require** flags to generate code for a
794+
// target, so it should only be passed here if absolutely necessary!
795+
// Most default configuration should be done through target specs rather
796+
// than an entry here.
797+
675798
let mut base = Vec::new();
676799
if target != self.config.build && !target.contains("msvc") {
677800
base.push(format!("-Clinker={}", self.cc(target).display()));
@@ -681,10 +804,12 @@ impl Build {
681804
}
682805

683806
impl<'a> Compiler<'a> {
807+
/// Creates a new complier for the specified stage/host
684808
fn new(stage: u32, host: &'a str) -> Compiler<'a> {
685809
Compiler { stage: stage, host: host }
686810
}
687811

812+
/// Returns whether this is a snapshot compiler for `build`'s configuration
688813
fn is_snapshot(&self, build: &Build) -> bool {
689814
self.stage == 0 && self.host == build.config.build
690815
}

‎src/bootstrap/build/native.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! Compilation of native dependencies like LLVM.
12+
//!
13+
//! Native projects like LLVM unfortunately aren't suited just yet for
14+
//! compilation in build scripts that Cargo has. This is because thie
15+
//! compilation takes a *very* long time but also because we don't want to
16+
//! compile LLVM 3 times as part of a normal bootstrap (we want it cached).
17+
//!
18+
//! LLVM and compiler-rt are essentially just wired up to everything else to
19+
//! ensure that they're always in place if needed.
20+
1121
use std::path::Path;
1222
use std::process::Command;
1323
use std::fs;
@@ -19,6 +29,7 @@ use gcc;
1929
use build::Build;
2030
use build::util::{exe, staticlib, up_to_date};
2131

32+
/// Compile LLVM for `target`.
2233
pub fn llvm(build: &Build, target: &str) {
2334
// If we're using a custom LLVM bail out here, but we can only use a
2435
// custom LLVM for the build triple.
@@ -116,6 +127,10 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) {
116127
panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version)
117128
}
118129

130+
/// Compiles the `compiler-rt` library, or at least the builtins part of it.
131+
///
132+
/// This uses the CMake build system and an existing LLVM build directory to
133+
/// compile the project.
119134
pub fn compiler_rt(build: &Build, target: &str) {
120135
let dst = build.compiler_rt_out(target);
121136
let arch = target.split('-').next().unwrap();
@@ -171,6 +186,8 @@ pub fn compiler_rt(build: &Build, target: &str) {
171186
cfg.build();
172187
}
173188

189+
/// Compiles the `rust_test_helpers.c` library which we used in various
190+
/// `run-pass` test suites for ABI testing.
174191
pub fn test_helpers(build: &Build, target: &str) {
175192
let dst = build.test_helpers_out(target);
176193
let src = build.src.join("src/rt/rust_test_helpers.c");

‎src/bootstrap/build/sanity.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! Sanity checking performed by rustbuild before actually executing anything.
12+
//!
13+
//! This module contains the implementation of ensuring that the build
14+
//! environment looks reasonable before progressing. This will verify that
15+
//! various programs like git and python exist, along with ensuring that all C
16+
//! compilers for cross-compiling are found.
17+
//!
18+
//! In theory if we get past this phase it's a bug if a build fails, but in
19+
//! practice that's likely not true!
20+
1121
use std::collections::HashSet;
1222
use std::env;
1323
use std::ffi::{OsStr, OsString};

‎src/bootstrap/build/step.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! Major workhorse of rustbuild, definition and dependencies between stages of
12+
//! the copmile.
13+
//!
14+
//! The primary purpose of this module is to define the various `Step`s of
15+
//! execution of the build. Each `Step` has a corresponding `Source` indicating
16+
//! what it's actually doing along with a number of dependencies which must be
17+
//! executed first.
18+
//!
19+
//! This module will take the CLI as input and calculate the steps required for
20+
//! the build requested, ensuring that all intermediate pieces are in place.
21+
//! Essentially this module is a `make`-replacement, but not as good.
22+
1123
use std::collections::HashSet;
1224

1325
use build::{Build, Compiler};
@@ -18,6 +30,15 @@ pub struct Step<'a> {
1830
pub target: &'a str,
1931
}
2032

33+
/// Macro used to iterate over all targets that are recognized by the build
34+
/// system.
35+
///
36+
/// Whenever a new step is added it will involve adding an entry here, updating
37+
/// the dependencies section below, and then adding an implementation of the
38+
/// step in `build/mod.rs`.
39+
///
40+
/// This macro takes another macro as an argument and then calls that macro with
41+
/// all steps that the build system knows about.
2142
macro_rules! targets {
2243
($m:ident) => {
2344
$m! {
@@ -110,6 +131,9 @@ macro_rules! targets {
110131
}
111132
}
112133

134+
// Define the `Source` enum by iterating over all the steps and peeling out just
135+
// the types that we want to define.
136+
113137
macro_rules! item { ($a:item) => ($a) }
114138

115139
macro_rules! define_source {
@@ -125,6 +149,12 @@ macro_rules! define_source {
125149

126150
targets!(define_source);
127151

152+
/// Calculate a list of all steps described by `build`.
153+
///
154+
/// This will inspect the flags passed in on the command line and use that to
155+
/// build up a list of steps to execute. These steps will then be transformed
156+
/// into a topologically sorted list which when executed left-to-right will
157+
/// correctly sequence the entire build.
128158
pub fn all(build: &Build) -> Vec<Step> {
129159
let mut ret = Vec::new();
130160
let mut all = HashSet::new();
@@ -146,6 +176,8 @@ pub fn all(build: &Build) -> Vec<Step> {
146176
}
147177
}
148178

179+
/// Determines what top-level targets are requested as part of this build,
180+
/// returning them as a list.
149181
fn top_level(build: &Build) -> Vec<Step> {
150182
let mut targets = Vec::new();
151183
let stage = build.flags.stage.unwrap_or(2);
@@ -161,8 +193,10 @@ fn top_level(build: &Build) -> Vec<Step> {
161193
.unwrap_or(host.target)
162194
};
163195

196+
// First, try to find steps on the command line.
164197
add_steps(build, stage, &host, &target, &mut targets);
165198

199+
// If none are specified, then build everything.
166200
if targets.len() == 0 {
167201
let t = Step {
168202
src: Source::Llvm { _dummy: () },
@@ -260,8 +294,14 @@ impl<'a> Step<'a> {
260294
Step { target: target, src: self.src.clone() }
261295
}
262296

297+
// Define ergonomic constructors for each step defined above so they can be
298+
// easily constructed.
263299
targets!(constructors);
264300

301+
/// Mapping of all dependencies for rustbuild.
302+
///
303+
/// This function receives a step, the build that we're building for, and
304+
/// then returns a list of all the dependencies of that step.
265305
pub fn deps(&self, build: &'a Build) -> Vec<Step<'a>> {
266306
match self.src {
267307
Source::Rustc { stage: 0 } => {

‎src/bootstrap/build/util.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! Various utility functions used throughout rustbuild.
12+
//!
13+
//! Simple things like testing the various filesystem operations here and there,
14+
//! not a lot of interesting happenings here unfortunately.
15+
1116
use std::env;
1217
use std::path::{Path, PathBuf};
1318
use std::fs;
@@ -16,6 +21,7 @@ use std::process::Command;
1621
use bootstrap::{dylib_path, dylib_path_var};
1722
use filetime::FileTime;
1823

24+
/// Returns the `name` as the filename of a static library for `target`.
1925
pub fn staticlib(name: &str, target: &str) -> String {
2026
if target.contains("windows-msvc") {
2127
format!("{}.lib", name)
@@ -24,12 +30,15 @@ pub fn staticlib(name: &str, target: &str) -> String {
2430
}
2531
}
2632

33+
/// Returns the last-modified time for `path`, or zero if it doesn't exist.
2734
pub fn mtime(path: &Path) -> FileTime {
2835
fs::metadata(path).map(|f| {
2936
FileTime::from_last_modification_time(&f)
3037
}).unwrap_or(FileTime::zero())
3138
}
3239

40+
/// Copies a file from `src` to `dst`, attempting to use hard links and then
41+
/// falling back to an actually filesystem copy if necessary.
3342
pub fn copy(src: &Path, dst: &Path) {
3443
let res = fs::hard_link(src, dst);
3544
let res = res.or_else(|_| fs::copy(src, dst).map(|_| ()));
@@ -39,6 +48,8 @@ pub fn copy(src: &Path, dst: &Path) {
3948
}
4049
}
4150

51+
/// Copies the `src` directory recursively to `dst`. Both are assumed to exist
52+
/// when this function is called.
4253
pub fn cp_r(src: &Path, dst: &Path) {
4354
for f in t!(fs::read_dir(src)) {
4455
let f = t!(f);
@@ -66,14 +77,18 @@ pub fn exe(name: &str, target: &str) -> String {
6677
}
6778
}
6879

80+
/// Returns whether the file name given looks like a dynamic library.
6981
pub fn is_dylib(name: &str) -> bool {
7082
name.ends_with(".dylib") || name.ends_with(".so") || name.ends_with(".dll")
7183
}
7284

85+
/// Returns the corresponding relative library directory that the compiler's
86+
/// dylibs will be found in.
7387
pub fn libdir(target: &str) -> &'static str {
7488
if target.contains("windows") {"bin"} else {"lib"}
7589
}
7690

91+
/// Adds a list of lookup paths to `cmd`'s dynamic library lookup path.
7792
pub fn add_lib_path(path: Vec<PathBuf>, cmd: &mut Command) {
7893
let mut list = dylib_path();
7994
for path in path {
@@ -82,7 +97,10 @@ pub fn add_lib_path(path: Vec<PathBuf>, cmd: &mut Command) {
8297
cmd.env(dylib_path_var(), t!(env::join_paths(list)));
8398
}
8499

85-
#[allow(dead_code)] // this will be used soon
100+
/// Returns whether `dst` is up to date given that the file or files in `src`
101+
/// are used to generate it.
102+
///
103+
/// Uses last-modified time checks to verify this.
86104
pub fn up_to_date(src: &Path, dst: &Path) -> bool {
87105
let threshold = mtime(dst);
88106
let meta = t!(fs::metadata(src));

‎src/bootstrap/config.toml.example

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# Sample TOML configuration file for building Rust.
2+
#
3+
# All options are commented out by default in this file, and they're commented
4+
# out with their default values. The build system by default looks for
5+
# `config.toml` in the current directory of a build for build configuration, but
6+
# a custom configuration file can also be specified with `--config` to the build
7+
# system.
8+
9+
# =============================================================================
10+
# Tweaking how LLVM is compiled
11+
# =============================================================================
12+
[llvm]
13+
14+
# Indicates whether the LLVM build is a Release or Debug build
15+
#optimize = true
16+
17+
# Indicates whether the LLVM assertions are enabled or not
18+
#assertions = false
19+
20+
# Indicates whether ccache is used when building LLVM
21+
#ccache = false
22+
23+
# If an external LLVM root is specified, we automatically check the version by
24+
# default to make sure it's within the range that we're expecting, but setting
25+
# this flag will indicate that this version check should not be done.
26+
#version-check = false
27+
28+
# Link libstdc++ statically into the librustc_llvm instead of relying on a
29+
# dynamic version to be available.
30+
#static-libstdcpp = false
31+
32+
# Tell the LLVM build system to use Ninja instead of the platform default for
33+
# the generated build system. This can sometimes be faster than make, for
34+
# example.
35+
#ninja = false
36+
37+
# =============================================================================
38+
# General build configuration options
39+
# =============================================================================
40+
[build]
41+
42+
# Build triple for the original snapshot compiler. This must be a compiler that
43+
# nightlies are already produced for. The current platform must be able to run
44+
# binaries of this build triple and the nightly will be used to bootstrap the
45+
# first compiler.
46+
#build = "x86_64-unknown-linux-gnu" # defaults to your host platform
47+
48+
# In addition to the build triple, other triples to produce full compiler
49+
# toolchains for. Each of these triples will be bootstrapped from the build
50+
# triple and then will continue to bootstrap themselves. This platform must
51+
# currently be able to run all of the triples provided here.
52+
#host = ["x86_64-unknown-linux-gnu"] # defaults to just the build triple
53+
54+
# In addition to all host triples, other triples to produce the standard library
55+
# for. Each host triple will be used to produce a copy of the standard library
56+
# for each target triple.
57+
#target = ["x86_64-unknown-linux-gnu"] # defaults to just the build triple
58+
59+
# Instead of downloading the src/nightlies.txt version of Cargo specified, use
60+
# this Cargo binary instead to build all Rust code
61+
#cargo = "/path/to/bin/cargo"
62+
63+
# Instead of downloading the src/nightlies.txt version of the compiler
64+
# specified, use this rustc binary instead as the stage0 snapshot compiler.
65+
#rustc = "/path/to/bin/rustc"
66+
67+
# Flag to specify whether any documentation is built. If false, rustdoc and
68+
# friends will still be compiled but they will not be used to generate any
69+
# documentation.
70+
#docs = true
71+
72+
# Indicate whether the compiler should be documented in addition to the standard
73+
# library and facade crates.
74+
#compiler-docs = false
75+
76+
# =============================================================================
77+
# Options for compiling Rust code itself
78+
# =============================================================================
79+
[rust]
80+
81+
# Whether or not to optimize the compiler and standard library
82+
#optimize = true
83+
84+
# Number of codegen units to use for each compiler invocation. A value of 0
85+
# means "the number of cores on this machine", and 1+ is passed through to the
86+
# compiler.
87+
#codegen-units = 1
88+
89+
# Whether or not debug assertions are enabled for the compiler and standard
90+
# library
91+
#debug-assertions = false
92+
93+
# Whether or not debuginfo is emitted
94+
#debuginfo = false
95+
96+
# Whether or not jemalloc is built and enabled
97+
#use-jemalloc = true
98+
99+
# Whether or not jemalloc is built with its debug option set
100+
#debug-jemalloc = false
101+
102+
# The default linker that will be used by the generated compiler. Note that this
103+
# is not the linker used to link said compiler.
104+
#default-linker = "cc"
105+
106+
# The default ar utility that will be used by the generated compiler if LLVM
107+
# cannot be used. Note that this is not used to assemble said compiler.
108+
#default-ar = "ar"
109+
110+
# The "channel" for the Rust build to produce. The stable/beta channels only
111+
# allow using stable features, whereas the nightly and dev channels allow using
112+
# nightly features
113+
#channel = "dev"
114+
115+
# The root location of the MUSL installation directory. The library directory
116+
# will also need to contain libunwind.a for an unwinding implementation.
117+
#musl-root = "..."
118+
119+
# By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix
120+
# platforms to ensure that the compiler is usable by default from the build
121+
# directory (as it links to a number of dynamic libraries). This may not be
122+
# desired in distributions, for example.
123+
#rpath = true
124+
125+
# =============================================================================
126+
# Options for specific targets
127+
#
128+
# Each of the following options is scoped to the specific target triple in
129+
# question and is used for determining how to compile each target.
130+
# =============================================================================
131+
[target.x86_64-unknown-linux-gnu]
132+
133+
# C compiler to be used to compiler C code and link Rust code. Note that the
134+
# default value is platform specific, and if not specified it may also depend on
135+
# what platform is crossing to what platform.
136+
#cc = "cc"
137+
138+
# C++ compiler to be used to compiler C++ code (e.g. LLVM and our LLVM shims).
139+
# This is only used for host targets.
140+
#cxx = "c++"
141+
142+
# Path to the `llvm-config` binary of the installation of a custom LLVM to link
143+
# against. Note that if this is specifed we don't compile LLVM at all for this
144+
# target.
145+
#llvm-config = "../path/to/llvm/root/bin/llvm-config"
146+
147+
# Path to the custom jemalloc static library to link into the standard library
148+
# by default. This is only used if jemalloc is still enabled above
149+
#jemalloc = "/path/to/jemalloc/libjemalloc_pic.a"
150+
151+
# If this target is for Android, this option will be required to specify where
152+
# the NDK for the target lives. This is used to find the C compiler to link and
153+
# build native code.
154+
#android-ndk = "/path/to/ndk"

‎src/bootstrap/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,17 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! A small helper library shared between the build system's executables
12+
//!
13+
//! Currently this just has some simple utilities for modifying the dynamic
14+
//! library lookup path.
15+
1116
use std::env;
1217
use std::ffi::OsString;
1318
use std::path::PathBuf;
1419

20+
/// Returns the environment variable which the dynamic library lookup path
21+
/// resides in for this platform.
1522
pub fn dylib_path_var() -> &'static str {
1623
if cfg!(target_os = "windows") {
1724
"PATH"
@@ -22,6 +29,8 @@ pub fn dylib_path_var() -> &'static str {
2229
}
2330
}
2431

32+
/// Parses the `dylib_path_var()` environment variable, returning a list of
33+
/// paths that are members of this lookup path.
2534
pub fn dylib_path() -> Vec<PathBuf> {
2635
env::split_paths(&env::var_os(dylib_path_var()).unwrap_or(OsString::new()))
2736
.collect()

‎src/bootstrap/main.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! rustbuild, the Rust build system
12+
//!
13+
//! This is the entry point for the build system used to compile the `rustc`
14+
//! compiler. Lots of documentation can be found in the `README.md` file next to
15+
//! this file, and otherwise documentation can be found throughout the `build`
16+
//! directory in each respective module.
17+
1118
#![deny(warnings)]
1219

1320
extern crate bootstrap;
@@ -32,8 +39,11 @@ fn main() {
3239
let args = env::args().skip(1).collect::<Vec<_>>();
3340
let flags = Flags::parse(&args);
3441
let mut config = Config::parse(&flags.build, flags.config.clone());
42+
43+
// compat with `./configure` while we're still using that
3544
if std::fs::metadata("config.mk").is_ok() {
3645
config.update_with_config_mk();
3746
}
47+
3848
Build::new(flags, config).build();
3949
}

‎src/bootstrap/rustc.rs

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ extern crate bootstrap;
2929

3030
use std::env;
3131
use std::ffi::OsString;
32-
use std::path::PathBuf;
3332
use std::process::Command;
3433

3534
fn main() {
@@ -54,37 +53,33 @@ fn main() {
5453
cmd.args(&args)
5554
.arg("--cfg").arg(format!("stage{}", env::var("RUSTC_STAGE").unwrap()));
5655

57-
if target.is_none() {
58-
// Build scripts are always built with the snapshot compiler, so we need
59-
// to be sure to set up the right path information for the OS dynamic
60-
// linker to find the libraries in question.
61-
if let Some(p) = env::var_os("RUSTC_SNAPSHOT_LIBDIR") {
62-
let mut path = bootstrap::dylib_path();
63-
path.insert(0, PathBuf::from(p));
64-
cmd.env(bootstrap::dylib_path_var(), env::join_paths(path).unwrap());
65-
}
66-
} else {
56+
if let Some(target) = target {
57+
// The stage0 compiler has a special sysroot distinct from what we
58+
// actually downloaded, so we just always pass the `--sysroot` option.
6759
cmd.arg("--sysroot").arg(env::var_os("RUSTC_SYSROOT").unwrap());
6860

6961
// When we build Rust dylibs they're all intended for intermediate
7062
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
7163
// linking all deps statically into the dylib.
7264
cmd.arg("-Cprefer-dynamic");
7365

66+
// Help the libc crate compile by assisting it in finding the MUSL
67+
// native libraries.
7468
if let Some(s) = env::var_os("MUSL_ROOT") {
7569
let mut root = OsString::from("native=");
7670
root.push(&s);
7771
root.push("/lib");
7872
cmd.arg("-L").arg(&root);
7973
}
74+
75+
// Pass down extra flags, commonly used to configure `-Clinker` when
76+
// cross compiling.
8077
if let Ok(s) = env::var("RUSTC_FLAGS") {
8178
cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::<Vec<_>>());
8279
}
83-
}
8480

85-
// Set various options from config.toml to configure how we're building
86-
// code.
87-
if let Some(target) = target {
81+
// Set various options from config.toml to configure how we're building
82+
// code.
8883
if env::var("RUSTC_DEBUGINFO") == Ok("true".to_string()) {
8984
cmd.arg("-g");
9085
}

0 commit comments

Comments
 (0)
Please sign in to comment.