From 0a1b5e8bc01061f54716005fd8ea37cc4997bfd9 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 4 Jul 2017 17:53:53 -0600 Subject: [PATCH 01/51] Move rule configs out of step --- src/bootstrap/check.rs | 231 +++++++++++++++++++++++++++++++++++ src/bootstrap/compile.rs | 252 +++++++++++++++++++++++++++++++++++++++ src/bootstrap/dist.rs | 102 ++++++++++++++++ src/bootstrap/doc.rs | 95 +++++++++++++++ src/bootstrap/install.rs | 42 +++++++ src/bootstrap/lib.rs | 1 - src/bootstrap/native.rs | 15 +++ 7 files changed, 737 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index e4b0e2fb9ca0c..5e553cf8d6fb8 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -81,6 +81,12 @@ fn try_run_quiet(build: &Build, cmd: &mut Command) { } } +// rules.test("check-linkchecker", "src/tools/linkchecker") +// .dep(|s| s.name("tool-linkchecker").stage(0)) +// .dep(|s| s.name("default:doc")) +// .default(build.config.docs) +// .host(true) +// .run(move |s| check::linkcheck(build, s.target)); /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler. /// /// This tool in `src/tools` will verify the validity of all our links in the @@ -94,6 +100,11 @@ pub fn linkcheck(build: &Build, host: &str) { .arg(build.out.join(host).join("doc"))); } +// rules.test("check-cargotest", "src/tools/cargotest") +// .dep(|s| s.name("tool-cargotest").stage(0)) +// .dep(|s| s.name("librustc")) +// .host(true) +// .run(move |s| check::cargotest(build, s.stage, s.target)); /// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler. /// /// This tool in `src/tools` will check out a few Rust projects and run `cargo @@ -116,6 +127,10 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) { .env("RUSTDOC", build.rustdoc(&compiler))); } +//rules.test("check-cargo", "cargo") +// .dep(|s| s.name("tool-cargo")) +// .host(true) +// .run(move |s| check::cargo(build, s.stage, s.target)); /// Runs `cargo test` for `cargo` packaged with Rust. pub fn cargo(build: &Build, stage: u32, host: &str) { let compiler = &Compiler::new(stage, host); @@ -160,6 +175,12 @@ fn path_for_cargo(build: &Build, compiler: &Compiler) -> OsString { env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("") } +//rules.test("check-tidy", "src/tools/tidy") +// .dep(|s| s.name("tool-tidy").stage(0)) +// .default(true) +// .host(true) +// .only_build(true) +// .run(move |s| check::tidy(build, s.target)); /// Runs the `tidy` tool as compiled in `stage` by the `host` compiler. /// /// This tool in `src/tools` checks up on various bits and pieces of style and @@ -184,6 +205,104 @@ fn testdir(build: &Build, host: &str) -> PathBuf { build.out.join(host).join("test") } +// // ======================================================================== +// // Test targets +// // +// // Various unit tests and tests suites we can run +// { +// let mut suite = |name, path, mode, dir| { +// rules.test(name, path) +// .dep(|s| s.name("libtest")) +// .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) +// .dep(|s| s.name("test-helpers")) +// .dep(|s| s.name("remote-copy-libs")) +// .default(mode != "pretty") // pretty tests don't run everywhere +// .run(move |s| { +// check::compiletest(build, &s.compiler(), s.target, mode, dir) +// }); +// }; +// +// suite("check-ui", "src/test/ui", "ui", "ui"); +// suite("check-rpass", "src/test/run-pass", "run-pass", "run-pass"); +// suite("check-cfail", "src/test/compile-fail", "compile-fail", "compile-fail"); +// suite("check-pfail", "src/test/parse-fail", "parse-fail", "parse-fail"); +// suite("check-rfail", "src/test/run-fail", "run-fail", "run-fail"); +// suite("check-rpass-valgrind", "src/test/run-pass-valgrind", +// "run-pass-valgrind", "run-pass-valgrind"); +// suite("check-mir-opt", "src/test/mir-opt", "mir-opt", "mir-opt"); +// if build.config.codegen_tests { +// suite("check-codegen", "src/test/codegen", "codegen", "codegen"); +// } +// suite("check-codegen-units", "src/test/codegen-units", "codegen-units", +// "codegen-units"); +// suite("check-incremental", "src/test/incremental", "incremental", +// "incremental"); +// } +// +// if build.build.contains("msvc") { +// // nothing to do for debuginfo tests +// } else { +// rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb") +// .dep(|s| s.name("libtest")) +// .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) +// .dep(|s| s.name("test-helpers")) +// .dep(|s| s.name("debugger-scripts")) +// .run(move |s| check::compiletest(build, &s.compiler(), s.target, +// "debuginfo-lldb", "debuginfo")); +// rules.test("check-debuginfo-gdb", "src/test/debuginfo-gdb") +// .dep(|s| s.name("libtest")) +// .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) +// .dep(|s| s.name("test-helpers")) +// .dep(|s| s.name("debugger-scripts")) +// .dep(|s| s.name("remote-copy-libs")) +// .run(move |s| check::compiletest(build, &s.compiler(), s.target, +// "debuginfo-gdb", "debuginfo")); +// let mut rule = rules.test("check-debuginfo", "src/test/debuginfo"); +// rule.default(true); +// if build.build.contains("apple") { +// rule.dep(|s| s.name("check-debuginfo-lldb")); +// } else { +// rule.dep(|s| s.name("check-debuginfo-gdb")); +// } +// } +// +// +// +// { +// let mut suite = |name, path, mode, dir| { +// rules.test(name, path) +// .dep(|s| s.name("librustc")) +// .dep(|s| s.name("test-helpers")) +// .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) +// .default(mode != "pretty") +// .host(true) +// .run(move |s| { +// check::compiletest(build, &s.compiler(), s.target, mode, dir) +// }); +// }; +// +// suite("check-ui-full", "src/test/ui-fulldeps", "ui", "ui-fulldeps"); +// suite("check-rpass-full", "src/test/run-pass-fulldeps", +// "run-pass", "run-pass-fulldeps"); +// suite("check-rfail-full", "src/test/run-fail-fulldeps", +// "run-fail", "run-fail-fulldeps"); +// suite("check-cfail-full", "src/test/compile-fail-fulldeps", +// "compile-fail", "compile-fail-fulldeps"); +// suite("check-rmake", "src/test/run-make", "run-make", "run-make"); +// suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc"); +// suite("check-pretty", "src/test/pretty", "pretty", "pretty"); +// suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty", +// "run-pass"); +// suite("check-pretty-rfail", "src/test/run-fail/pretty", "pretty", +// "run-fail"); +// suite("check-pretty-valgrind", "src/test/run-pass-valgrind/pretty", "pretty", +// "run-pass-valgrind"); +// suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps/pretty", +// "pretty", "run-pass-fulldeps"); +// suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps/pretty", +// "pretty", "run-fail-fulldeps"); +// } + /// Executes the `compiletest` tool to run a suite of tests. /// /// Compiles all tests with `compiler` for `target` with the specified @@ -338,6 +457,11 @@ pub fn compiletest(build: &Build, try_run(build, &mut cmd); } +// rules.test("check-docs", "src/doc") +// .dep(|s| s.name("libtest")) +// .default(true) +// .host(true) +// .run(move |s| check::docs(build, &s.compiler())); /// Run `rustdoc --test` for all documentation in `src/doc`. /// /// This will run all tests in our markdown documentation (e.g. the book) @@ -370,6 +494,12 @@ pub fn docs(build: &Build, compiler: &Compiler) { } } +//rules.test("check-error-index", "src/tools/error_index_generator") +// .dep(|s| s.name("libstd")) +// .dep(|s| s.name("tool-error-index").host(s.host).stage(0)) +// .default(true) +// .host(true) +// .run(move |s| check::error_index(build, &s.compiler())); /// Run the error index generator tool to execute the tests located in the error /// index. /// @@ -420,6 +550,68 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { } } +// for (krate, path, _default) in krates("std") { +// rules.test(&krate.test_step, path) +// .dep(|s| s.name("libtest")) +// .dep(|s| s.name("remote-copy-libs")) +// .run(move |s| check::krate(build, &s.compiler(), s.target, +// Mode::Libstd, TestKind::Test, +// Some(&krate.name))); +// } +// rules.test("check-std-all", "path/to/nowhere") +// .dep(|s| s.name("libtest")) +// .dep(|s| s.name("remote-copy-libs")) +// .default(true) +// .run(move |s| check::krate(build, &s.compiler(), s.target, +// Mode::Libstd, TestKind::Test, None)); +// +// // std benchmarks +// for (krate, path, _default) in krates("std") { +// rules.bench(&krate.bench_step, path) +// .dep(|s| s.name("libtest")) +// .dep(|s| s.name("remote-copy-libs")) +// .run(move |s| check::krate(build, &s.compiler(), s.target, +// Mode::Libstd, TestKind::Bench, +// Some(&krate.name))); +// } +// rules.bench("bench-std-all", "path/to/nowhere") +// .dep(|s| s.name("libtest")) +// .dep(|s| s.name("remote-copy-libs")) +// .default(true) +// .run(move |s| check::krate(build, &s.compiler(), s.target, +// Mode::Libstd, TestKind::Bench, None)); +// +// for (krate, path, _default) in krates("test") { +// rules.test(&krate.test_step, path) +// .dep(|s| s.name("libtest")) +// .dep(|s| s.name("remote-copy-libs")) +// .run(move |s| check::krate(build, &s.compiler(), s.target, +// Mode::Libtest, TestKind::Test, +// Some(&krate.name))); +// } +// rules.test("check-test-all", "path/to/nowhere") +// .dep(|s| s.name("libtest")) +// .dep(|s| s.name("remote-copy-libs")) +// .default(true) +// .run(move |s| check::krate(build, &s.compiler(), s.target, +// Mode::Libtest, TestKind::Test, None)); +// for (krate, path, _default) in krates("rustc-main") { +// rules.test(&krate.test_step, path) +// .dep(|s| s.name("librustc")) +// .dep(|s| s.name("remote-copy-libs")) +// .host(true) +// .run(move |s| check::krate(build, &s.compiler(), s.target, +// Mode::Librustc, TestKind::Test, +// Some(&krate.name))); +// } +// rules.test("check-rustc-all", "path/to/nowhere") +// .dep(|s| s.name("librustc")) +// .dep(|s| s.name("remote-copy-libs")) +// .default(true) +// .host(true) +// .run(move |s| check::krate(build, &s.compiler(), s.target, +// Mode::Librustc, TestKind::Test, None)); + /// Run all unit tests plus documentation tests for an entire crate DAG defined /// by a `Cargo.toml` /// @@ -596,6 +788,34 @@ fn find_tests(dir: &Path, target: &str) -> Vec { dst } +// // Some test suites are run inside emulators or on remote devices, and most +// // of our test binaries are linked dynamically which means we need to ship +// // the standard library and such to the emulator ahead of time. This step +// // represents this and is a dependency of all test suites. +// // +// // Most of the time this step is a noop (the `check::emulator_copy_libs` +// // only does work if necessary). For some steps such as shipping data to +// // QEMU we have to build our own tools so we've got conditional dependencies +// // on those programs as well. Note that the remote test client is built for +// // the build target (us) and the server is built for the target. +// rules.test("remote-copy-libs", "path/to/nowhere") +// .dep(|s| s.name("libtest")) +// .dep(move |s| { +// if build.remote_tested(s.target) { +// s.name("tool-remote-test-client").target(s.host).stage(0) +// } else { +// Step::noop() +// } +// }) +// .dep(move |s| { +// if build.remote_tested(s.target) { +// s.name("tool-remote-test-server") +// } else { +// Step::noop() +// } +// }) +// .run(move |s| check::remote_copy_libs(build, &s.compiler(), s.target)); +// pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) { if !build.remote_tested(target) { return @@ -632,6 +852,11 @@ pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) { } } +//rules.test("check-distcheck", "distcheck") +// .dep(|s| s.name("dist-plain-source-tarball")) +// .dep(|s| s.name("dist-src")) +// .run(move |_| check::distcheck(build)); + /// Run "distcheck", a 'make check' from a tarball pub fn distcheck(build: &Build) { if build.build != "x86_64-unknown-linux-gnu" { @@ -684,6 +909,12 @@ pub fn distcheck(build: &Build) { .current_dir(&dir)); } +//rules.test("check-bootstrap", "src/bootstrap") +// .default(true) +// .host(true) +// .only_build(true) +// .run(move |_| check::bootstrap(build)); +// /// Test the build system itself pub fn bootstrap(build: &Build) { let mut cmd = Command::new(&build.initial_cargo); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 5a3106c7d5e64..4a972ebf8df9d 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -32,6 +32,121 @@ use channel::GitInfo; use util::{exe, libdir, is_dylib, copy}; use {Build, Compiler, Mode}; +// for (krate, path, _default) in krates("std") { +// rules.build(&krate.build_step, path) +// .dep(|s| s.name("startup-objects")) +// .dep(move |s| s.name("rustc").host(&build.build).target(s.host)) +// .run(move |s| compile::std(build, s.target, &s.compiler())); +// } +// for (krate, path, _default) in krates("test") { +// rules.build(&krate.build_step, path) +// .dep(|s| s.name("libstd-link")) +// .run(move |s| compile::test(build, s.target, &s.compiler())); +// } +// for (krate, path, _default) in krates("rustc-main") { +// rules.build(&krate.build_step, path) +// .dep(|s| s.name("libtest-link")) +// .dep(move |s| s.name("llvm").host(&build.build).stage(0)) +// .dep(|s| s.name("may-run-build-script")) +// .run(move |s| compile::rustc(build, s.target, &s.compiler())); +// } +// +// // Crates which have build scripts need to rely on this rule to ensure that +// // the necessary prerequisites for a build script are linked and located in +// // place. +// rules.build("may-run-build-script", "path/to/nowhere") +// .dep(move |s| { +// s.name("libstd-link") +// .host(&build.build) +// .target(&build.build) +// }); + +// // ======================================================================== +// // Crate compilations +// // +// // Tools used during the build system but not shipped +// // These rules are "pseudo rules" that don't actually do any work +// // themselves, but represent a complete sysroot with the relevant compiler +// // linked into place. +// // +// // That is, depending on "libstd" means that when the rule is completed then +// // the `stage` sysroot for the compiler `host` will be available with a +// // standard library built for `target` linked in place. Not all rules need +// // the compiler itself to be available, just the standard library, so +// // there's a distinction between the two. +// rules.build("libstd", "src/libstd") +// .dep(|s| s.name("rustc").target(s.host)) +// .dep(|s| s.name("libstd-link")); +// rules.build("libtest", "src/libtest") +// .dep(|s| s.name("libstd")) +// .dep(|s| s.name("libtest-link")) +// .default(true); +// rules.build("librustc", "src/librustc") +// .dep(|s| s.name("libtest")) +// .dep(|s| s.name("librustc-link")) +// .host(true) +// .default(true); + +// Helper method to define the rules to link a crate into its place in the +// sysroot. +// +// The logic here is a little subtle as there's a few cases to consider. +// Not all combinations of (stage, host, target) actually require something +// to be compiled, but rather libraries could get propagated from a +// different location. For example: +// +// * Any crate with a `host` that's not the build triple will not actually +// compile something. A different `host` means that the build triple will +// actually compile the libraries, and then we'll copy them over from the +// build triple to the `host` directory. +// +// * Some crates aren't even compiled by the build triple, but may be copied +// from previous stages. For example if we're not doing a full bootstrap +// then we may just depend on the stage1 versions of libraries to be +// available to get linked forward. +// +// * Finally, there are some cases, however, which do indeed comiple crates +// and link them into place afterwards. +// +// The rule definition below mirrors these three cases. The `dep` method +// calculates the correct dependency which either comes from stage1, a +// different compiler, or from actually building the crate itself (the `dep` +// rule). The `run` rule then mirrors these three cases and links the cases +// forward into the compiler sysroot specified from the correct location. +fn crate_rule<'a, 'b>(build: &'a Build, + rules: &'b mut Rules<'a>, + krate: &'a str, + dep: &'a str, + link: fn(&Build, &Compiler, &Compiler, &str)) + -> RuleBuilder<'a, 'b> { + let mut rule = rules.build(&krate, "path/to/nowhere"); + rule.dep(move |s| { + if build.force_use_stage1(&s.compiler(), s.target) { + s.host(&build.build).stage(1) + } else if s.host == build.build { + s.name(dep) + } else { + s.host(&build.build) + } + }) + .run(move |s| { + if build.force_use_stage1(&s.compiler(), s.target) { + link(build, + &s.stage(1).host(&build.build).compiler(), + &s.compiler(), + s.target) + } else if s.host == build.build { + link(build, &s.compiler(), &s.compiler(), s.target) + } else { + link(build, + &s.host(&build.build).compiler(), + &s.compiler(), + s.target) + } + }); + rule +} + /// Build the standard library. /// /// This will build the standard library for a particular stage of the build @@ -93,6 +208,14 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) { &libstd_stamp(build, &compiler, target)); } + +// crate_rule(build, +// &mut rules, +// "libstd-link", +// "build-crate-std", +// compile::std_link) +// .dep(|s| s.name("startup-objects")) +// .dep(|s| s.name("create-sysroot").target(s.host)); /// Link all libstd rlibs/dylibs into the sysroot location. /// /// Links those artifacts generated by `compiler` to a the `stage` compiler's @@ -147,6 +270,10 @@ fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) { } } +// rules.build("startup-objects", "src/rtstartup") +// .dep(|s| s.name("create-sysroot").target(s.host)) +// .run(move |s| compile::build_startup_objects(build, &s.compiler(), s.target)); + /// Build and prepare startup objects like rsbegin.o and rsend.o /// /// These are primarily used on Windows right now for linking executables/dlls. @@ -209,6 +336,14 @@ pub fn test(build: &Build, target: &str, compiler: &Compiler) { &libtest_stamp(build, compiler, target)); } + +// crate_rule(build, +// &mut rules, +// "libtest-link", +// "build-crate-test", +// compile::test_link) +// .dep(|s| s.name("libstd-link")); + /// Same as `std_link`, only for libtest pub fn test_link(build: &Build, compiler: &Compiler, @@ -303,6 +438,12 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) { &librustc_stamp(build, compiler, target)); } +// crate_rule(build, +// &mut rules, +// "librustc-link", +// "build-crate-rustc-main", +// compile::rustc_link) +// .dep(|s| s.name("libtest-link")); /// Same as `std_link`, only for librustc pub fn rustc_link(build: &Build, compiler: &Compiler, @@ -342,12 +483,27 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf { PathBuf::from(out.trim()) } +// rules.build("create-sysroot", "path/to/nowhere") +// .run(move |s| compile::create_sysroot(build, &s.compiler())); pub fn create_sysroot(build: &Build, compiler: &Compiler) { let sysroot = build.sysroot(compiler); let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot)); } +// the compiler with no target libraries ready to go +// rules.build("rustc", "src/rustc") +// .dep(|s| s.name("create-sysroot").target(s.host)) +// .dep(move |s| { +// if s.stage == 0 { +// Step::noop() +// } else { +// s.name("librustc") +// .host(&build.build) +// .stage(s.stage - 1) +// } +// }) +// .run(move |s| compile::assemble_rustc(build, s.stage, s.target)); /// Prepare a new compiler from the artifacts in `stage` /// /// This will assemble a compiler in `build/$host/stage$stage`. The compiler @@ -418,6 +574,29 @@ fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) { } } +//// ======================================================================== +//// Build tools +//// +//// Tools used during the build system but not shipped +//// "pseudo rule" which represents completely cleaning out the tools dir in +//// one stage. This needs to happen whenever a dependency changes (e.g. +//// libstd, libtest, librustc) and all of the tool compilations above will +//// be sequenced after this rule. +//rules.build("maybe-clean-tools", "path/to/nowhere") +// .after("librustc-tool") +// .after("libtest-tool") +// .after("libstd-tool"); +// +//rules.build("librustc-tool", "path/to/nowhere") +// .dep(|s| s.name("librustc")) +// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Librustc)); +//rules.build("libtest-tool", "path/to/nowhere") +// .dep(|s| s.name("libtest")) +// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libtest)); +//rules.build("libstd-tool", "path/to/nowhere") +// .dep(|s| s.name("libstd")) +// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libstd)); +// /// Build a tool in `src/tools` /// /// This will build the specified tool with the specified `host` compiler in @@ -435,6 +614,79 @@ pub fn maybe_clean_tools(build: &Build, stage: u32, target: &str, mode: Mode) { build.clear_if_dirty(&out_dir, &stamp); } + +// rules.build("tool-rustbook", "src/tools/rustbook") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("librustc-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "rustbook")); +// rules.build("tool-error-index", "src/tools/error_index_generator") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("librustc-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator")); +// rules.build("tool-unstable-book-gen", "src/tools/unstable-book-gen") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "unstable-book-gen")); +// rules.build("tool-tidy", "src/tools/tidy") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "tidy")); +// rules.build("tool-linkchecker", "src/tools/linkchecker") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "linkchecker")); +// rules.build("tool-cargotest", "src/tools/cargotest") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "cargotest")); +// rules.build("tool-compiletest", "src/tools/compiletest") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libtest-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "compiletest")); +// rules.build("tool-build-manifest", "src/tools/build-manifest") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "build-manifest")); +// rules.build("tool-remote-test-server", "src/tools/remote-test-server") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-server")); +// rules.build("tool-remote-test-client", "src/tools/remote-test-client") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-client")); +// rules.build("tool-rust-installer", "src/tools/rust-installer") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "rust-installer")); +// rules.build("tool-cargo", "src/tools/cargo") +// .host(true) +// .default(build.config.extended) +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .dep(|s| s.stage(0).host(s.target).name("openssl")) +// .dep(move |s| { +// // Cargo depends on procedural macros, which requires a full host +// // compiler to be available, so we need to depend on that. +// s.name("librustc-link") +// .target(&build.build) +// .host(&build.build) +// }) +// .run(move |s| compile::tool(build, s.stage, s.target, "cargo")); +// rules.build("tool-rls", "src/tools/rls") +// .host(true) +// .default(build.config.extended) +// .dep(|s| s.name("librustc-tool")) +// .dep(|s| s.stage(0).host(s.target).name("openssl")) +// .dep(move |s| { +// // rls, like cargo, uses procedural macros +// s.name("librustc-link") +// .target(&build.build) +// .host(&build.build) +// }) +// .run(move |s| compile::tool(build, s.stage, s.target, "rls")); +// + /// Build a tool in `src/tools` /// /// This will build the specified tool with the specified `host` compiler in diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 8fae1dd99d8b9..2cf3ca73952ac 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -18,6 +18,14 @@ //! out to `rust-installer` still. This may one day be replaced with bits and //! pieces of `rustup.rs`! +// /// Helper to depend on a stage0 build-only rust-installer tool. +// fn tool_rust_installer<'a>(build: &'a Build, step: &Step<'a>) -> Step<'a> { +// step.name("tool-rust-installer") +// .host(&build.build) +// .target(&build.build) +// .stage(0) +// } + use std::env; use std::fs::{self, File}; use std::io::{Read, Write}; @@ -53,6 +61,12 @@ fn rust_installer(build: &Build) -> Command { build.tool_cmd(&Compiler::new(0, &build.build), "rust-installer") } +// rules.dist("dist-docs", "src/doc") +// .default(true) +// .only_host_build(true) +// .dep(|s| s.name("default:doc")) +// .dep(move |s| tool_rust_installer(build, s)) +// .run(move |s| dist::docs(build, s.stage, s.target)); /// Builds the `rust-docs` installer component. /// /// Slurps up documentation from the `stage`'s `host`. @@ -222,6 +236,16 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: } } +// rules.dist("dist-mingw", "path/to/nowhere") +// .default(true) +// .only_host_build(true) +// .dep(move |s| tool_rust_installer(build, s)) +// .run(move |s| { +// if s.target.contains("pc-windows-gnu") { +// dist::mingw(build, s.target) +// } +// }); +// /// Build the `rust-mingw` installer component. /// /// This contains all the bits and pieces to run the MinGW Windows targets @@ -254,6 +278,13 @@ pub fn mingw(build: &Build, host: &str) { t!(fs::remove_dir_all(&image)); } +// rules.dist("dist-rustc", "src/librustc") +// .dep(move |s| s.name("rustc").host(&build.build)) +// .host(true) +// .only_host_build(true) +// .default(true) +// .dep(move |s| tool_rust_installer(build, s)) +// .run(move |s| dist::rustc(build, s.stage, s.target)); /// Creates the `rustc` installer component. pub fn rustc(build: &Build, stage: u32, host: &str) { println!("Dist rustc stage{} ({})", stage, host); @@ -352,6 +383,9 @@ pub fn rustc(build: &Build, stage: u32, host: &str) { } } +//rules.test("debugger-scripts", "src/etc/lldb_batchmode.py") +// .run(move |s| dist::debugger_scripts(build, &build.sysroot(&s.compiler()), +// s.target)); /// Copies debugger scripts for `host` into the `sysroot` specified. pub fn debugger_scripts(build: &Build, sysroot: &Path, @@ -386,6 +420,21 @@ pub fn debugger_scripts(build: &Build, } } +// rules.dist("dist-std", "src/libstd") +// .dep(move |s| { +// // We want to package up as many target libraries as possible +// // for the `rust-std` package, so if this is a host target we +// // depend on librustc and otherwise we just depend on libtest. +// if build.config.host.iter().any(|t| t == s.target) { +// s.name("librustc-link") +// } else { +// s.name("libtest-link") +// } +// }) +// .default(true) +// .only_host_build(true) +// .dep(move |s| tool_rust_installer(build, s)) +// .run(move |s| dist::std(build, &s.compiler(), s.target)); /// Creates the `rust-std` installer component as compiled by `compiler` for the /// target `target`. pub fn std(build: &Build, compiler: &Compiler, target: &str) { @@ -436,6 +485,12 @@ pub fn rust_src_installer(build: &Build) -> PathBuf { distdir(build).join(&format!("{}.tar.gz", name)) } +// rules.dist("dist-analysis", "analysis") +// .default(build.config.extended) +// .dep(|s| s.name("dist-std")) +// .only_host_build(true) +// .dep(move |s| tool_rust_installer(build, s)) +// .run(move |s| dist::analysis(build, &s.compiler(), s.target)); /// Creates a tarball of save-analysis metadata, if available. pub fn analysis(build: &Build, compiler: &Compiler, target: &str) { assert!(build.config.extended); @@ -520,6 +575,13 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di } } +// rules.dist("dist-src", "src") +// .default(true) +// .host(true) +// .only_build(true) +// .only_host_build(true) +// .dep(move |s| tool_rust_installer(build, s)) +// .run(move |_| dist::rust_src(build)); /// Creates the `rust-src` installer component pub fn rust_src(build: &Build) { println!("Dist src"); @@ -587,6 +649,13 @@ pub fn rust_src(build: &Build) { const CARGO_VENDOR_VERSION: &str = "0.1.4"; +// rules.dist("dist-plain-source-tarball", "src") +// .default(build.config.rust_dist_src) +// .host(true) +// .only_build(true) +// .only_host_build(true) +// .dep(move |s| tool_rust_installer(build, s)) +// .run(move |_| dist::plain_source_tarball(build)); /// Creates the plain source tarball pub fn plain_source_tarball(build: &Build) { println!("Create plain source tarball"); @@ -704,6 +773,12 @@ fn write_file(path: &Path, data: &[u8]) { t!(vf.write_all(data)); } +// rules.dist("dist-cargo", "cargo") +// .host(true) +// .only_host_build(true) +// .dep(|s| s.name("tool-cargo")) +// .dep(move |s| tool_rust_installer(build, s)) +// .run(move |s| dist::cargo(build, s.stage, s.target)); pub fn cargo(build: &Build, stage: u32, target: &str) { println!("Dist cargo stage{} ({})", stage, target); let compiler = Compiler::new(stage, &build.build); @@ -764,6 +839,12 @@ pub fn cargo(build: &Build, stage: u32, target: &str) { build.run(&mut cmd); } +// rules.dist("dist-rls", "rls") +// .host(true) +// .only_host_build(true) +// .dep(|s| s.name("tool-rls")) +// .dep(move |s| tool_rust_installer(build, s)) +// .run(move |s| dist::rls(build, s.stage, s.target)); pub fn rls(build: &Build, stage: u32, target: &str) { assert!(build.config.extended); println!("Dist RLS stage{} ({})", stage, target); @@ -813,6 +894,20 @@ pub fn rls(build: &Build, stage: u32, target: &str) { build.run(&mut cmd); } +// rules.dist("dist-extended", "extended") +// .default(build.config.extended) +// .host(true) +// .only_host_build(true) +// .dep(|d| d.name("dist-std")) +// .dep(|d| d.name("dist-rustc")) +// .dep(|d| d.name("dist-mingw")) +// .dep(|d| d.name("dist-docs")) +// .dep(|d| d.name("dist-cargo")) +// .dep(|d| d.name("dist-rls")) +// .dep(|d| d.name("dist-analysis")) +// .dep(move |s| tool_rust_installer(build, s)) +// .run(move |s| dist::extended(build, s.stage, s.target)); + /// Creates a combined installer for the specified target in the provided stage. pub fn extended(build: &Build, stage: u32, target: &str) { println!("Dist extended stage{} ({})", stage, target); @@ -1198,6 +1293,13 @@ fn add_env(build: &Build, cmd: &mut Command, target: &str) { } } +// rules.dist("dist-sign", "hash-and-sign") +// .host(true) +// .only_build(true) +// .only_host_build(true) +// .dep(move |s| s.name("tool-build-manifest").target(&build.build).stage(0)) +// .run(move |_| dist::hash_and_sign(build)); +// pub fn hash_and_sign(build: &Build) { let compiler = Compiler::new(0, &build.build); let mut cmd = build.tool_cmd(&compiler, "build-manifest"); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 7dbc3e5553957..432fdb6a3cb8c 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -27,6 +27,24 @@ use {Build, Compiler, Mode}; use util::{cp_r, symlink_dir}; use build_helper::up_to_date; +// rules.doc("doc-nomicon", "src/doc/nomicon") +// .dep(move |s| { +// s.name("tool-rustbook") +// .host(&build.build) +// .target(&build.build) +// .stage(0) +// }) +// .default(build.config.docs) +// .run(move |s| doc::rustbook(build, s.target, "nomicon")); +// rules.doc("doc-reference", "src/doc/reference") +// .dep(move |s| { +// s.name("tool-rustbook") +// .host(&build.build) +// .target(&build.build) +// .stage(0) +// }) +// .default(build.config.docs) +// .run(move |s| doc::rustbook(build, s.target, "reference")); /// Invoke `rustbook` for `target` for the doc book `name`. /// /// This will not actually generate any documentation if the documentation has @@ -36,6 +54,21 @@ pub fn rustbook(build: &Build, target: &str, name: &str) { rustbook_src(build, target, name, &src); } +//rules.doc("doc-unstable-book", "src/doc/unstable-book") +// .dep(move |s| { +// s.name("tool-rustbook") +// .host(&build.build) +// .target(&build.build) +// .stage(0) +// }) +// .dep(move |s| s.name("doc-unstable-book-gen")) +// .default(build.config.docs) +// .run(move |s| doc::rustbook_src(build, +// s.target, +// "unstable-book", +// &build.md_doc_out(s.target))); + + /// Invoke `rustbook` for `target` for the doc book `name` from the `src` path. /// /// This will not actually generate any documentation if the documentation has @@ -61,6 +94,15 @@ pub fn rustbook_src(build: &Build, target: &str, name: &str, src: &Path) { .arg(out)); } +// rules.doc("doc-book", "src/doc/book") +// .dep(move |s| { +// s.name("tool-rustbook") +// .host(&build.build) +// .target(&build.build) +// .stage(0) +// }) +// .default(build.config.docs) +// .run(move |s| doc::book(build, s.target, "book")); /// Build the book and associated stuff. /// /// We need to build: @@ -137,6 +179,15 @@ fn invoke_rustdoc(build: &Build, target: &str, markdown: &str) { build.run(&mut cmd); } +// rules.doc("doc-standalone", "src/doc") +// .dep(move |s| { +// s.name("rustc") +// .host(&build.build) +// .target(&build.build) +// .stage(0) +// }) +// .default(build.config.docs) +// .run(move |s| doc::standalone(build, s.target)); /// Generates all standalone documentation as compiled by the rustdoc in `stage` /// for the `target` into `out`. /// @@ -209,6 +260,12 @@ pub fn standalone(build: &Build, target: &str) { } } +// for (krate, path, default) in krates("std") { +// rules.doc(&krate.doc_step, path) +// .dep(|s| s.name("libstd-link")) +// .default(default && build.config.docs) +// .run(move |s| doc::std(build, s.stage, s.target)); +// } /// Compile all standard library documentation. /// /// This will generate all documentation for the standard library and its @@ -268,6 +325,14 @@ pub fn std(build: &Build, stage: u32, target: &str) { cp_r(&my_out, &out); } +// for (krate, path, default) in krates("test") { +// rules.doc(&krate.doc_step, path) +// .dep(|s| s.name("libtest-link")) +// // Needed so rustdoc generates relative links to std. +// .dep(|s| s.name("doc-crate-std")) +// .default(default && build.config.compiler_docs) +// .run(move |s| doc::test(build, s.stage, s.target)); +// } /// Compile all libtest documentation. /// /// This will generate all documentation for libtest and its dependencies. This @@ -298,6 +363,17 @@ pub fn test(build: &Build, stage: u32, target: &str) { cp_r(&my_out, &out); } + +// for (krate, path, default) in krates("rustc-main") { +// rules.doc(&krate.doc_step, path) +// .dep(|s| s.name("librustc-link")) +// // Needed so rustdoc generates relative links to std. +// .dep(|s| s.name("doc-crate-std")) +// .host(true) +// .default(default && build.config.docs) +// .run(move |s| doc::rustc(build, s.stage, s.target)); +// } +// /// Generate all compiler documentation. /// /// This will generate all documentation for the compiler libraries and their @@ -345,6 +421,13 @@ pub fn rustc(build: &Build, stage: u32, target: &str) { cp_r(&my_out, &out); } +// rules.doc("doc-error-index", "src/tools/error_index_generator") +// .dep(move |s| s.name("tool-error-index").target(&build.build).stage(0)) +// .dep(move |s| s.name("librustc-link")) +// .default(build.config.docs) +// .host(true) +// .run(move |s| doc::error_index(build, s.target)); + /// Generates the HTML rendered error-index by running the /// `error_index_generator` tool. pub fn error_index(build: &Build, target: &str) { @@ -362,6 +445,18 @@ pub fn error_index(build: &Build, target: &str) { build.run(&mut index); } +// rules.doc("doc-unstable-book-gen", "src/tools/unstable-book-gen") +// .dep(move |s| { +// s.name("tool-unstable-book-gen") +// .host(&build.build) +// .target(&build.build) +// .stage(0) +// }) +// .dep(move |s| s.name("libstd-link")) +// .default(build.config.docs) +// .host(true) +// .run(move |s| doc::unstable_book_gen(build, s.target)); + pub fn unstable_book_gen(build: &Build, target: &str) { println!("Generating unstable book md files ({})", target); let out = build.md_doc_out(target).join("unstable-book"); diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 8e2ef527b1658..638b0613bf2cc 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -148,3 +148,45 @@ fn add_destdir(path: &Path, destdir: &Option) -> PathBuf { } ret } +/* +rules.install("install-docs", "src/doc") + .default(build.config.docs) + .only_host_build(true) + .dep(|s| s.name("dist-docs")) + .run(move |s| install::Installer::new(build).install_docs(s.stage, s.target)); +rules.install("install-std", "src/libstd") + .default(true) + .only_host_build(true) + .dep(|s| s.name("dist-std")) + .run(move |s| install::Installer::new(build).install_std(s.stage)); +rules.install("install-cargo", "cargo") + .default(build.config.extended) + .host(true) + .only_host_build(true) + .dep(|s| s.name("dist-cargo")) + .run(move |s| install::Installer::new(build).install_cargo(s.stage, s.target)); +rules.install("install-rls", "rls") + .default(build.config.extended) + .host(true) + .only_host_build(true) + .dep(|s| s.name("dist-rls")) + .run(move |s| install::Installer::new(build).install_rls(s.stage, s.target)); +rules.install("install-analysis", "analysis") + .default(build.config.extended) + .only_host_build(true) + .dep(|s| s.name("dist-analysis")) + .run(move |s| install::Installer::new(build).install_analysis(s.stage, s.target)); +rules.install("install-src", "src") + .default(build.config.extended) + .host(true) + .only_build(true) + .only_host_build(true) + .dep(|s| s.name("dist-src")) + .run(move |s| install::Installer::new(build).install_src(s.stage)); +rules.install("install-rustc", "src/librustc") + .default(true) + .host(true) + .only_host_build(true) + .dep(|s| s.name("dist-rustc")) + .run(move |s| install::Installer::new(build).install_rustc(s.stage, s.target)); +*/ diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index e06de5bac4b15..e51bb5b65a9d7 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -106,7 +106,6 @@ mod flags; mod install; mod native; mod sanity; -mod step; pub mod util; #[cfg(windows)] diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 20eec97d8e5aa..d28060559aca5 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -33,6 +33,16 @@ use Build; use util; use build_helper::up_to_date; +/ rules.build("llvm", "src/llvm") +// .host(true) +// .dep(move |s| { +// if s.target == build.build { +// Step::noop() +// } else { +// s.target(&build.build) +// } +// }) +// .run(move |s| native::llvm(build, s.target)); /// Compile LLVM for `target`. pub fn llvm(build: &Build, target: &str) { // If we're using a custom LLVM bail out here, but we can only use a @@ -216,6 +226,8 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) { panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version) } +//rules.build("test-helpers", "src/rt/rust_test_helpers.c") +// .run(move |s| native::test_helpers(build, s.target)); /// Compiles the `rust_test_helpers.c` library which we used in various /// `run-pass` test suites for ABI testing. pub fn test_helpers(build: &Build, target: &str) { @@ -253,6 +265,9 @@ const OPENSSL_VERS: &'static str = "1.0.2k"; const OPENSSL_SHA256: &'static str = "6b3977c61f2aedf0f96367dcfb5c6e578cf37e7b8d913b4ecb6643c3cb88d8c0"; +//rules.build("openssl", "path/to/nowhere") +// .run(move |s| native::openssl(build, s.target)); + pub fn openssl(build: &Build, target: &str) { let out = match build.openssl_dir(target) { Some(dir) => dir, From 001e9f349087124165ed6deea6a87e0b158bba21 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 4 Jul 2017 19:41:43 -0600 Subject: [PATCH 02/51] Move code into Step trait implementations. No changes are introduced to code body. This commit will not build; it is done to permit a better diff in later commits. --- src/bootstrap/check.rs | 1005 +++++++++++++--------- src/bootstrap/compile.rs | 870 +++++++++---------- src/bootstrap/dist.rs | 1765 ++++++++++++++++++++------------------ src/bootstrap/doc.rs | 651 ++++++++------ src/bootstrap/native.rs | 612 ++++++------- src/bootstrap/tool.rs | 205 +++++ 6 files changed, 2861 insertions(+), 2247 deletions(-) create mode 100644 src/bootstrap/tool.rs diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 5e553cf8d6fb8..0278b8d5dbf2b 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -25,9 +25,14 @@ use std::io::Read; use build_helper::{self, output}; -use {Build, Compiler, Mode}; +use {Build, Mode}; use dist; -use util::{self, dylib_path, dylib_path_var, exe}; +use util::{self, dylib_path, dylib_path_var}; + +use compile; +use native; +use builder::{Kind, Builder, Compiler, Step}; +use tool::Tool; const ADB_TEST_DIR: &str = "/data/tmp/work"; @@ -87,17 +92,30 @@ fn try_run_quiet(build: &Build, cmd: &mut Command) { // .default(build.config.docs) // .host(true) // .run(move |s| check::linkcheck(build, s.target)); -/// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler. -/// -/// This tool in `src/tools` will verify the validity of all our links in the -/// documentation to ensure we don't have a bunch of dead ones. -pub fn linkcheck(build: &Build, host: &str) { - println!("Linkcheck ({})", host); - let compiler = Compiler::new(0, host); - let _time = util::timeit(); - try_run(build, build.tool_cmd(&compiler, "linkchecker") - .arg(build.out.join(host).join("doc"))); +#[derive(Serialize)] +pub struct Linkcheck<'a> { + host: &'a str, +} + +impl<'a> Step<'a> for Linkcheck<'a> { + type Output = (); + + /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler. + /// + /// This tool in `src/tools` will verify the validity of all our links in the + /// documentation to ensure we don't have a bunch of dead ones. + fn run(self, builder: &Builder) { + let build = builder.build; + let host = self.host; + + println!("Linkcheck ({})", host); + let compiler = Compiler::new(0, host); + + let _time = util::timeit(); + try_run(build, build.tool_cmd(&compiler, "linkchecker") + .arg(build.out.join(host).join("doc"))); + } } // rules.test("check-cargotest", "src/tools/cargotest") @@ -105,65 +123,120 @@ pub fn linkcheck(build: &Build, host: &str) { // .dep(|s| s.name("librustc")) // .host(true) // .run(move |s| check::cargotest(build, s.stage, s.target)); -/// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler. -/// -/// This tool in `src/tools` will check out a few Rust projects and run `cargo -/// test` to ensure that we don't regress the test suites there. -pub fn cargotest(build: &Build, stage: u32, host: &str) { - let compiler = Compiler::new(stage, host); - // Note that this is a short, cryptic, and not scoped directory name. This - // is currently to minimize the length of path on Windows where we otherwise - // quickly run into path name limit constraints. - let out_dir = build.out.join("ct"); - t!(fs::create_dir_all(&out_dir)); +#[derive(Serialize)] +pub struct Cargotest<'a> { + stage: u32, + host: &'a str, +} - let _time = util::timeit(); - let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest")); - build.prepare_tool_cmd(&compiler, &mut cmd); - try_run(build, cmd.arg(&build.initial_cargo) - .arg(&out_dir) - .env("RUSTC", build.compiler_path(&compiler)) - .env("RUSTDOC", build.rustdoc(&compiler))); +impl<'a> Step<'a> for Cargotest<'a> { + type Output = (); + + /// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler. + /// + /// This tool in `src/tools` will check out a few Rust projects and run `cargo + /// test` to ensure that we don't regress the test suites there. + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let host = self.host; + let compiler = Compiler::new(stage, host); + + // Note that this is a short, cryptic, and not scoped directory name. This + // is currently to minimize the length of path on Windows where we otherwise + // quickly run into path name limit constraints. + let out_dir = build.out.join("ct"); + t!(fs::create_dir_all(&out_dir)); + + let _time = util::timeit(); + let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest")); + build.prepare_tool_cmd(&compiler, &mut cmd); + try_run(build, cmd.arg(&build.initial_cargo) + .arg(&out_dir) + .env("RUSTC", build.compiler_path(&compiler)) + .env("RUSTDOC", build.rustdoc(&compiler))); + } } //rules.test("check-cargo", "cargo") // .dep(|s| s.name("tool-cargo")) // .host(true) // .run(move |s| check::cargo(build, s.stage, s.target)); -/// Runs `cargo test` for `cargo` packaged with Rust. -pub fn cargo(build: &Build, stage: u32, host: &str) { - let compiler = &Compiler::new(stage, host); - let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); - cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml")); - if !build.fail_fast { - cargo.arg("--no-fail-fast"); - } +#[derive(Serialize)] +pub struct Cargo<'a> { + stage: u32, + host: &'a str, +} + +impl<'a> Step<'a> for Cargo<'a> { + type Output = (); + + /// Runs `cargo test` for `cargo` packaged with Rust. + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let ref compiler = Compiler::new(stage, host); + + // Configure PATH to find the right rustc. NB. we have to use PATH + // and not RUSTC because the Cargo test suite has tests that will + // fail if rustc is not spelled `rustc`. + let path = build.sysroot(compiler).join("bin"); + let old_path = env::var_os("PATH").unwrap_or_default(); + let newpath = env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect(""); + + let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); + cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml")); + if !build.fail_fast { + cargo.arg("--no-fail-fast"); + } - // Don't build tests dynamically, just a pain to work with - cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); + let compiler = &Compiler::new(stage, host); - // Don't run cross-compile tests, we may not have cross-compiled libstd libs - // available. - cargo.env("CFG_DISABLE_CROSS_TESTS", "1"); + let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); + cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml")); + if !build.fail_fast { + cargo.arg("--no-fail-fast"); + } + + // Don't build tests dynamically, just a pain to work with + cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); + + // Don't run cross-compile tests, we may not have cross-compiled libstd libs + // available. + cargo.env("CFG_DISABLE_CROSS_TESTS", "1"); - try_run(build, cargo.env("PATH", &path_for_cargo(build, compiler))); + try_run(build, cargo.env("PATH", &path_for_cargo(build, compiler))); + } } -/// Runs `cargo test` for the rls. -pub fn rls(build: &Build, stage: u32, host: &str) { - let compiler = &Compiler::new(stage, host); +#[derive(Serialize)] +pub struct Rls<'a> { + stage: u32, + host: &'a str, +} - let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); - cargo.arg("--manifest-path").arg(build.src.join("src/tools/rls/Cargo.toml")); +impl<'a> Step<'a> for Rls<'a> { + type Output = (); - // Don't build tests dynamically, just a pain to work with - cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); + /// Runs `cargo test` for the rls. + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let host = self.host; + let compiler = &Compiler::new(stage, host); - build.add_rustc_lib_path(compiler, &mut cargo); + let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); + cargo.arg("--manifest-path").arg(build.src.join("src/tools/rls/Cargo.toml")); - try_run(build, &mut cargo); + // Don't build tests dynamically, just a pain to work with + cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); + + build.add_rustc_lib_path(compiler, &mut cargo); + + try_run(build, &mut cargo); + } } fn path_for_cargo(build: &Build, compiler: &Compiler) -> OsString { @@ -173,6 +246,13 @@ fn path_for_cargo(build: &Build, compiler: &Compiler) -> OsString { let path = build.sysroot(compiler).join("bin"); let old_path = env::var_os("PATH").unwrap_or_default(); env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("") +||||||| parent of adabe3889e... Move code into Step trait implementations. + try_run(build, cargo.env("PATH", newpath)); +======= + try_run(build, cargo.env("PATH", newpath)); + let host = self.host; + } +>>>>>>> adabe3889e... Move code into Step trait implementations. } //rules.test("check-tidy", "src/tools/tidy") @@ -181,24 +261,37 @@ fn path_for_cargo(build: &Build, compiler: &Compiler) -> OsString { // .host(true) // .only_build(true) // .run(move |s| check::tidy(build, s.target)); -/// Runs the `tidy` tool as compiled in `stage` by the `host` compiler. -/// -/// This tool in `src/tools` checks up on various bits and pieces of style and -/// otherwise just implements a few lint-like checks that are specific to the -/// compiler itself. -pub fn tidy(build: &Build, host: &str) { - let _folder = build.fold_output(|| "tidy"); - println!("tidy check ({})", host); - let compiler = Compiler::new(0, host); - let mut cmd = build.tool_cmd(&compiler, "tidy"); - cmd.arg(build.src.join("src")); - if !build.config.vendor { - cmd.arg("--no-vendor"); - } - if build.config.quiet_tests { - cmd.arg("--quiet"); + +#[derive(Serialize)] +pub struct Tidy<'a> { + host: &'a str, +} + +impl<'a> Step<'a> for Tidy<'a> { + type Output = (); + + /// Runs the `tidy` tool as compiled in `stage` by the `host` compiler. + /// + /// This tool in `src/tools` checks up on various bits and pieces of style and + /// otherwise just implements a few lint-like checks that are specific to the + /// compiler itself. + fn run(self, builder: &Builder) { + let build = builder.build; + let host = self.host; + + let _folder = build.fold_output(|| "tidy"); + println!("tidy check ({})", host); + let compiler = Compiler::new(0, host); + let mut cmd = build.tool_cmd(&compiler, "tidy"); + cmd.arg(build.src.join("src")); + if !build.config.vendor { + cmd.arg("--no-vendor"); + } + if build.config.quiet_tests { + cmd.arg("--quiet"); + } + try_run(build, &mut cmd); } - try_run(build, &mut cmd); } fn testdir(build: &Build, host: &str) -> PathBuf { @@ -303,158 +396,171 @@ fn testdir(build: &Build, host: &str) -> PathBuf { // "pretty", "run-fail-fulldeps"); // } -/// Executes the `compiletest` tool to run a suite of tests. -/// -/// Compiles all tests with `compiler` for `target` with the specified -/// compiletest `mode` and `suite` arguments. For example `mode` can be -/// "run-pass" or `suite` can be something like `debuginfo`. -pub fn compiletest(build: &Build, - compiler: &Compiler, - target: &str, - mode: &str, - suite: &str) { - let _folder = build.fold_output(|| format!("test_{}", suite)); - println!("Check compiletest suite={} mode={} ({} -> {})", - suite, mode, compiler.host, target); - let mut cmd = Command::new(build.tool(&Compiler::new(0, compiler.host), - "compiletest")); - build.prepare_tool_cmd(compiler, &mut cmd); - - // compiletest currently has... a lot of arguments, so let's just pass all - // of them! - - cmd.arg("--compile-lib-path").arg(build.rustc_libdir(compiler)); - cmd.arg("--run-lib-path").arg(build.sysroot_libdir(compiler, target)); - cmd.arg("--rustc-path").arg(build.compiler_path(compiler)); - cmd.arg("--rustdoc-path").arg(build.rustdoc(compiler)); - cmd.arg("--src-base").arg(build.src.join("src/test").join(suite)); - cmd.arg("--build-base").arg(testdir(build, compiler.host).join(suite)); - cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target)); - cmd.arg("--mode").arg(mode); - cmd.arg("--target").arg(target); - cmd.arg("--host").arg(compiler.host); - cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.build)); - - if let Some(ref nodejs) = build.config.nodejs { - cmd.arg("--nodejs").arg(nodejs); - } - - let mut flags = vec!["-Crpath".to_string()]; - if build.config.rust_optimize_tests { - flags.push("-O".to_string()); - } - if build.config.rust_debuginfo_tests { - flags.push("-g".to_string()); - } - - let mut hostflags = build.rustc_flags(&compiler.host); - hostflags.extend(flags.clone()); - cmd.arg("--host-rustcflags").arg(hostflags.join(" ")); +#[derive(Serialize)] +pub struct Compiletest<'a> { + compiler: Compiler<'a>, + target: &'a str, + mode: &'a str, + suite: &'a str, +} - let mut targetflags = build.rustc_flags(&target); - targetflags.extend(flags); - targetflags.push(format!("-Lnative={}", - build.test_helpers_out(target).display())); - cmd.arg("--target-rustcflags").arg(targetflags.join(" ")); +impl<'a> Step<'a> for Compiletest<'a> { + type Output = (); + + /// Executes the `compiletest` tool to run a suite of tests. + /// + /// Compiles all tests with `compiler` for `target` with the specified + /// compiletest `mode` and `suite` arguments. For example `mode` can be + /// "run-pass" or `suite` can be something like `debuginfo`. + fn run(self, builder: &Builder) { + let build = builder.build; + let compiler = self.compiler; + let target = self.target; + let mode = self.mode; + let suite = self.suite; + let _folder = build.fold_output(|| format!("test_{}", suite)); + println!("Check compiletest suite={} mode={} ({} -> {})", + suite, mode, compiler.host, target); + let mut cmd = Command::new(build.tool(&Compiler::new(0, compiler.host), + "compiletest")); + build.prepare_tool_cmd(compiler, &mut cmd); + + // compiletest currently has... a lot of arguments, so let's just pass all + // of them! + + cmd.arg("--compile-lib-path").arg(build.rustc_libdir(compiler)); + cmd.arg("--run-lib-path").arg(build.sysroot_libdir(compiler, target)); + cmd.arg("--rustc-path").arg(build.compiler_path(compiler)); + cmd.arg("--rustdoc-path").arg(build.rustdoc(compiler)); + cmd.arg("--src-base").arg(build.src.join("src/test").join(suite)); + cmd.arg("--build-base").arg(testdir(build, compiler.host).join(suite)); + cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target)); + cmd.arg("--mode").arg(mode); + cmd.arg("--target").arg(target); + cmd.arg("--host").arg(compiler.host); + cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.build)); + + if let Some(ref nodejs) = build.config.nodejs { + cmd.arg("--nodejs").arg(nodejs); + } - cmd.arg("--docck-python").arg(build.python()); + let mut flags = vec!["-Crpath".to_string()]; + if build.config.rust_optimize_tests { + flags.push("-O".to_string()); + } + if build.config.rust_debuginfo_tests { + flags.push("-g".to_string()); + } - if build.build.ends_with("apple-darwin") { - // Force /usr/bin/python on macOS for LLDB tests because we're loading the - // LLDB plugin's compiled module which only works with the system python - // (namely not Homebrew-installed python) - cmd.arg("--lldb-python").arg("/usr/bin/python"); - } else { - cmd.arg("--lldb-python").arg(build.python()); - } + let mut hostflags = build.rustc_flags(&compiler.host); + hostflags.extend(flags.clone()); + cmd.arg("--host-rustcflags").arg(hostflags.join(" ")); + + let mut targetflags = build.rustc_flags(&target); + targetflags.extend(flags); + targetflags.push(format!("-Lnative={}", + build.test_helpers_out(target).display())); + cmd.arg("--target-rustcflags").arg(targetflags.join(" ")); + + cmd.arg("--docck-python").arg(build.python()); + + if build.build.ends_with("apple-darwin") { + // Force /usr/bin/python on macOS for LLDB tests because we're loading the + // LLDB plugin's compiled module which only works with the system python + // (namely not Homebrew-installed python) + cmd.arg("--lldb-python").arg("/usr/bin/python"); + } else { + cmd.arg("--lldb-python").arg(build.python()); + } - if let Some(ref gdb) = build.config.gdb { - cmd.arg("--gdb").arg(gdb); - } - if let Some(ref vers) = build.lldb_version { - cmd.arg("--lldb-version").arg(vers); - } - if let Some(ref dir) = build.lldb_python_dir { - cmd.arg("--lldb-python-dir").arg(dir); - } - let llvm_config = build.llvm_config(target); - let llvm_version = output(Command::new(&llvm_config).arg("--version")); - cmd.arg("--llvm-version").arg(llvm_version); - if !build.is_rust_llvm(target) { - cmd.arg("--system-llvm"); - } + if let Some(ref gdb) = build.config.gdb { + cmd.arg("--gdb").arg(gdb); + } + if let Some(ref vers) = build.lldb_version { + cmd.arg("--lldb-version").arg(vers); + } + if let Some(ref dir) = build.lldb_python_dir { + cmd.arg("--lldb-python-dir").arg(dir); + } + let llvm_config = build.llvm_config(target); + let llvm_version = output(Command::new(&llvm_config).arg("--version")); + cmd.arg("--llvm-version").arg(llvm_version); + if !build.is_rust_llvm(target) { + cmd.arg("--system-llvm"); + } - cmd.args(&build.flags.cmd.test_args()); + cmd.args(&build.flags.cmd.test_args()); - if build.is_verbose() { - cmd.arg("--verbose"); - } + if build.is_verbose() { + cmd.arg("--verbose"); + } - if build.config.quiet_tests { - cmd.arg("--quiet"); - } + if build.config.quiet_tests { + cmd.arg("--quiet"); + } - // Only pass correct values for these flags for the `run-make` suite as it - // requires that a C++ compiler was configured which isn't always the case. - if suite == "run-make" { - let llvm_components = output(Command::new(&llvm_config).arg("--components")); - let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags")); - cmd.arg("--cc").arg(build.cc(target)) - .arg("--cxx").arg(build.cxx(target).unwrap()) - .arg("--cflags").arg(build.cflags(target).join(" ")) - .arg("--llvm-components").arg(llvm_components.trim()) - .arg("--llvm-cxxflags").arg(llvm_cxxflags.trim()); - } else { - cmd.arg("--cc").arg("") - .arg("--cxx").arg("") - .arg("--cflags").arg("") - .arg("--llvm-components").arg("") - .arg("--llvm-cxxflags").arg(""); - } + // Only pass correct values for these flags for the `run-make` suite as it + // requires that a C++ compiler was configured which isn't always the case. + if suite == "run-make" { + let llvm_components = output(Command::new(&llvm_config).arg("--components")); + let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags")); + cmd.arg("--cc").arg(build.cc(target)) + .arg("--cxx").arg(build.cxx(target).unwrap()) + .arg("--cflags").arg(build.cflags(target).join(" ")) + .arg("--llvm-components").arg(llvm_components.trim()) + .arg("--llvm-cxxflags").arg(llvm_cxxflags.trim()); + } else { + cmd.arg("--cc").arg("") + .arg("--cxx").arg("") + .arg("--cflags").arg("") + .arg("--llvm-components").arg("") + .arg("--llvm-cxxflags").arg(""); + } - if build.remote_tested(target) { - cmd.arg("--remote-test-client") - .arg(build.tool(&Compiler::new(0, &build.build), - "remote-test-client")); - } + if build.remote_tested(target) { + cmd.arg("--remote-test-client") + .arg(build.tool(&Compiler::new(0, &build.build), + "remote-test-client")); + } - // Running a C compiler on MSVC requires a few env vars to be set, to be - // sure to set them here. - // - // Note that if we encounter `PATH` we make sure to append to our own `PATH` - // rather than stomp over it. - if target.contains("msvc") { - for &(ref k, ref v) in build.cc[target].0.env() { - if k != "PATH" { - cmd.env(k, v); + // Running a C compiler on MSVC requires a few env vars to be set, to be + // sure to set them here. + // + // Note that if we encounter `PATH` we make sure to append to our own `PATH` + // rather than stomp over it. + if target.contains("msvc") { + for &(ref k, ref v) in build.cc[target].0.env() { + if k != "PATH" { + cmd.env(k, v); + } } } - } - cmd.env("RUSTC_BOOTSTRAP", "1"); - build.add_rust_test_threads(&mut cmd); + cmd.env("RUSTC_BOOTSTRAP", "1"); + build.add_rust_test_threads(&mut cmd); - if build.config.sanitizers { - cmd.env("SANITIZER_SUPPORT", "1"); - } + if build.config.sanitizers { + cmd.env("SANITIZER_SUPPORT", "1"); + } - if build.config.profiler { - cmd.env("PROFILER_SUPPORT", "1"); - } + if build.config.profiler { + cmd.env("PROFILER_SUPPORT", "1"); + } - cmd.arg("--adb-path").arg("adb"); - cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR); - if target.contains("android") { - // Assume that cc for this target comes from the android sysroot - cmd.arg("--android-cross-path") - .arg(build.cc(target).parent().unwrap().parent().unwrap()); - } else { - cmd.arg("--android-cross-path").arg(""); - } + cmd.arg("--adb-path").arg("adb"); + cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR); + if target.contains("android") { + // Assume that cc for this target comes from the android sysroot + cmd.arg("--android-cross-path") + .arg(build.cc(target).parent().unwrap().parent().unwrap()); + } else { + cmd.arg("--android-cross-path").arg(""); + } - build.ci_env.force_coloring_in_ci(&mut cmd); + build.ci_env.force_coloring_in_ci(&mut cmd); - let _time = util::timeit(); - try_run(build, &mut cmd); + let _time = util::timeit(); + try_run(build, &mut cmd); + } } // rules.test("check-docs", "src/doc") @@ -500,28 +606,41 @@ pub fn docs(build: &Build, compiler: &Compiler) { // .default(true) // .host(true) // .run(move |s| check::error_index(build, &s.compiler())); -/// Run the error index generator tool to execute the tests located in the error -/// index. -/// -/// The `error_index_generator` tool lives in `src/tools` and is used to -/// generate a markdown file from the error indexes of the code base which is -/// then passed to `rustdoc --test`. -pub fn error_index(build: &Build, compiler: &Compiler) { - let _folder = build.fold_output(|| "test_error_index"); - println!("Testing error-index stage{}", compiler.stage); - let dir = testdir(build, compiler.host); - t!(fs::create_dir_all(&dir)); - let output = dir.join("error-index.md"); - - let _time = util::timeit(); - build.run(build.tool_cmd(&Compiler::new(0, compiler.host), - "error_index_generator") - .arg("markdown") - .arg(&output) - .env("CFG_BUILD", &build.build)); +#[derive(Serialize)] +pub struct ErrorIndex<'a> { + compiler: Compiler<'a>, +} - markdown_test(build, compiler, &output); +impl<'a> Step<'a> for ErrorIndex<'a> { + type Output = (); + + /// Run the error index generator tool to execute the tests located in the error + /// index. + /// + /// The `error_index_generator` tool lives in `src/tools` and is used to + /// generate a markdown file from the error indexes of the code base which is + /// then passed to `rustdoc --test`. + fn run(self, builder: &Builder) { + let build = builder.build; + let compiler = self.compiler; + + let _folder = build.fold_output(|| "test_error_index"); + println!("Testing error-index stage{}", compiler.stage); + + let dir = testdir(build, compiler.host); + t!(fs::create_dir_all(&dir)); + let output = dir.join("error-index.md"); + + let _time = util::timeit(); + build.run(build.tool_cmd(&Compiler::new(0, compiler.host), + "error_index_generator") + .arg("markdown") + .arg(&output) + .env("CFG_BUILD", &build.build)); + + markdown_test(build, compiler, &output); + } } fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { @@ -612,120 +731,135 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { // .run(move |s| check::krate(build, &s.compiler(), s.target, // Mode::Librustc, TestKind::Test, None)); -/// Run all unit tests plus documentation tests for an entire crate DAG defined -/// by a `Cargo.toml` -/// -/// This is what runs tests for crates like the standard library, compiler, etc. -/// It essentially is the driver for running `cargo test`. -/// -/// Currently this runs all tests for a DAG by passing a bunch of `-p foo` -/// arguments, and those arguments are discovered from `cargo metadata`. -pub fn krate(build: &Build, - compiler: &Compiler, - target: &str, - mode: Mode, - test_kind: TestKind, - krate: Option<&str>) { - let (name, path, features, root) = match mode { - Mode::Libstd => { - ("libstd", "src/libstd", build.std_features(), "std") - } - Mode::Libtest => { - ("libtest", "src/libtest", String::new(), "test") - } - Mode::Librustc => { - ("librustc", "src/rustc", build.rustc_features(), "rustc-main") - } - _ => panic!("can only test libraries"), - }; - let _folder = build.fold_output(|| { - format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, name) - }); - println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage, - compiler.host, target); - - // If we're not doing a full bootstrap but we're testing a stage2 version of - // libstd, then what we're actually testing is the libstd produced in - // stage1. Reflect that here by updating the compiler that we're working - // with automatically. - let compiler = if build.force_use_stage1(compiler, target) { - Compiler::new(1, compiler.host) - } else { - compiler.clone() - }; - - // Build up the base `cargo test` command. - // - // Pass in some standard flags then iterate over the graph we've discovered - // in `cargo metadata` with the maps above and figure out what `-p` - // arguments need to get passed. - let mut cargo = build.cargo(&compiler, mode, target, test_kind.subcommand()); - cargo.arg("--manifest-path") - .arg(build.src.join(path).join("Cargo.toml")) - .arg("--features").arg(features); - if test_kind.subcommand() == "test" && !build.fail_fast { - cargo.arg("--no-fail-fast"); - } +#[derive(Serialize)] +pub struct Krate<'a> { + compiler: Compiler<'a>, + target: &'a str, + mode: Mode, + test_kind: TestKind, + krate: Option<&'a str>, +} - match krate { - Some(krate) => { - cargo.arg("-p").arg(krate); - } - None => { - let mut visited = HashSet::new(); - let mut next = vec![root]; - while let Some(name) = next.pop() { - // Right now jemalloc is our only target-specific crate in the - // sense that it's not present on all platforms. Custom skip it - // here for now, but if we add more this probably wants to get - // more generalized. - // - // Also skip `build_helper` as it's not compiled normally for - // target during the bootstrap and it's just meant to be a - // helper crate, not tested. If it leaks through then it ends up - // messing with various mtime calculations and such. - if !name.contains("jemalloc") && name != "build_helper" { - cargo.arg("-p").arg(&format!("{}:0.0.0", name)); - } - for dep in build.crates[name].deps.iter() { - if visited.insert(dep) { - next.push(dep); +impl<'a> Step<'a> for Krate<'a> { + type Output = (); + + /// Run all unit tests plus documentation tests for an entire crate DAG defined + /// by a `Cargo.toml` + /// + /// This is what runs tests for crates like the standard library, compiler, etc. + /// It essentially is the driver for running `cargo test`. + /// + /// Currently this runs all tests for a DAG by passing a bunch of `-p foo` + /// arguments, and those arguments are discovered from `cargo metadata`. + fn run(self, builder: &Builder) { + let build = builder.build; + let compiler = self.compiler; + let target = self.target; + let mode = self.mode; + let test_kind = self.test_kind; + let krate = self.krate; + + let (name, path, features, root) = match mode { + Mode::Libstd => { + ("libstd", "src/libstd", build.std_features(), "std") + } + Mode::Libtest => { + ("libtest", "src/libtest", String::new(), "test") + } + Mode::Librustc => { + ("librustc", "src/rustc", build.rustc_features(), "rustc-main") + } + _ => panic!("can only test libraries"), + }; + let _folder = build.fold_output(|| { + format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, name) + }); + println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage, + compiler.host, target); + + // If we're not doing a full bootstrap but we're testing a stage2 version of + // libstd, then what we're actually testing is the libstd produced in + // stage1. Reflect that here by updating the compiler that we're working + // with automatically. + let compiler = if build.force_use_stage1(compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler.clone() + }; + + // Build up the base `cargo test` command. + // + // Pass in some standard flags then iterate over the graph we've discovered + // in `cargo metadata` with the maps above and figure out what `-p` + // arguments need to get passed. + let mut cargo = build.cargo(&compiler, mode, target, test_kind.subcommand()); + cargo.arg("--manifest-path") + .arg(build.src.join(path).join("Cargo.toml")) + .arg("--features").arg(features); + if test_kind.subcommand() == "test" && !build.fail_fast { + cargo.arg("--no-fail-fast"); + } + + match krate { + Some(krate) => { + cargo.arg("-p").arg(krate); + } + None => { + let mut visited = HashSet::new(); + let mut next = vec![root]; + while let Some(name) = next.pop() { + // Right now jemalloc is our only target-specific crate in the + // sense that it's not present on all platforms. Custom skip it + // here for now, but if we add more this probably wants to get + // more generalized. + // + // Also skip `build_helper` as it's not compiled normally for + // target during the bootstrap and it's just meant to be a + // helper crate, not tested. If it leaks through then it ends up + // messing with various mtime calculations and such. + if !name.contains("jemalloc") && name != "build_helper" { + cargo.arg("-p").arg(&format!("{}:0.0.0", name)); + } + for dep in build.crates[name].deps.iter() { + if visited.insert(dep) { + next.push(dep); + } } } } } - } - - // The tests are going to run with the *target* libraries, so we need to - // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent. - // - // Note that to run the compiler we need to run with the *host* libraries, - // but our wrapper scripts arrange for that to be the case anyway. - let mut dylib_path = dylib_path(); - dylib_path.insert(0, build.sysroot_libdir(&compiler, target)); - cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); - - if target.contains("emscripten") || build.remote_tested(target) { - cargo.arg("--no-run"); - } - cargo.arg("--"); + // The tests are going to run with the *target* libraries, so we need to + // ensure that those libraries show up in the LD_LIBRARY_PATH equivalent. + // + // Note that to run the compiler we need to run with the *host* libraries, + // but our wrapper scripts arrange for that to be the case anyway. + let mut dylib_path = dylib_path(); + dylib_path.insert(0, build.sysroot_libdir(&compiler, target)); + cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); + + if target.contains("emscripten") || build.remote_tested(target) { + cargo.arg("--no-run"); + } - if build.config.quiet_tests { - cargo.arg("--quiet"); - } + cargo.arg("--"); - let _time = util::timeit(); + if build.config.quiet_tests { + cargo.arg("--quiet"); + } - if target.contains("emscripten") { - build.run(&mut cargo); - krate_emscripten(build, &compiler, target, mode); - } else if build.remote_tested(target) { - build.run(&mut cargo); - krate_remote(build, &compiler, target, mode); - } else { - cargo.args(&build.flags.cmd.test_args()); - try_run(build, &mut cargo); + let _time = util::timeit(); + + if target.contains("emscripten") { + build.run(&mut cargo); + krate_emscripten(build, &compiler, target, mode); + } else if build.remote_tested(target) { + build.run(&mut cargo); + krate_remote(build, &compiler, target, mode); + } else { + cargo.args(&build.flags.cmd.test_args()); + try_run(build, &mut cargo); + } } } @@ -816,38 +950,52 @@ fn find_tests(dir: &Path, target: &str) -> Vec { // }) // .run(move |s| check::remote_copy_libs(build, &s.compiler(), s.target)); // -pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) { - if !build.remote_tested(target) { - return - } - println!("REMOTE copy libs to emulator ({})", target); - t!(fs::create_dir_all(build.out.join("tmp"))); +#[derive(Serialize)] +pub struct RemoteCopyLibs<'a> { + compiler: Compiler<'a>, + target: &'a str, +} - let server = build.cargo_out(compiler, Mode::Tool, target) - .join(exe("remote-test-server", target)); +impl<'a> Step<'a> for RemoteCopyLibs<'a> { + type Output = (); - // Spawn the emulator and wait for it to come online - let tool = build.tool(&Compiler::new(0, &build.build), - "remote-test-client"); - let mut cmd = Command::new(&tool); - cmd.arg("spawn-emulator") - .arg(target) - .arg(&server) - .arg(build.out.join("tmp")); - if let Some(rootfs) = build.qemu_rootfs(target) { - cmd.arg(rootfs); - } - build.run(&mut cmd); + fn run(self, builder: &Builder) { + let build = builder.build; + let compiler = self.compiler; + let target = self.target; + if !build.remote_tested(target) { + return + } + + println!("REMOTE copy libs to emulator ({})", target); + t!(fs::create_dir_all(build.out.join("tmp"))); - // Push all our dylibs to the emulator - for f in t!(build.sysroot_libdir(compiler, target).read_dir()) { - let f = t!(f); - let name = f.file_name().into_string().unwrap(); - if util::is_dylib(&name) { - build.run(Command::new(&tool) - .arg("push") - .arg(f.path())); + let server = build.cargo_out(compiler, Mode::Tool, target) + .join(exe("remote-test-server", target)); + + // Spawn the emulator and wait for it to come online + let tool = build.tool(&Compiler::new(0, &build.build), + "remote-test-client"); + let mut cmd = Command::new(&tool); + cmd.arg("spawn-emulator") + .arg(target) + .arg(&server) + .arg(build.out.join("tmp")); + if let Some(rootfs) = build.qemu_rootfs(target) { + cmd.arg(rootfs); + } + build.run(&mut cmd); + + // Push all our dylibs to the emulator + for f in t!(build.sysroot_libdir(compiler, target).read_dir()) { + let f = t!(f); + let name = f.file_name().into_string().unwrap(); + if util::is_dylib(&name) { + build.run(Command::new(&tool) + .arg("push") + .arg(f.path())); + } } } } @@ -857,56 +1005,65 @@ pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) { // .dep(|s| s.name("dist-src")) // .run(move |_| check::distcheck(build)); -/// Run "distcheck", a 'make check' from a tarball -pub fn distcheck(build: &Build) { - if build.build != "x86_64-unknown-linux-gnu" { - return - } - if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") { - return - } - if !build.config.target.iter().any(|s| s == "x86_64-unknown-linux-gnu") { - return - } +#[derive(Serialize)] +pub struct Distcheck; - println!("Distcheck"); - let dir = build.out.join("tmp").join("distcheck"); - let _ = fs::remove_dir_all(&dir); - t!(fs::create_dir_all(&dir)); - - let mut cmd = Command::new("tar"); - cmd.arg("-xzf") - .arg(dist::rust_src_location(build)) - .arg("--strip-components=1") - .current_dir(&dir); - build.run(&mut cmd); - build.run(Command::new("./configure") - .args(&build.config.configure_args) - .arg("--enable-vendor") - .current_dir(&dir)); - build.run(Command::new(build_helper::make(&build.build)) - .arg("check") - .current_dir(&dir)); - - // Now make sure that rust-src has all of libstd's dependencies - println!("Distcheck rust-src"); - let dir = build.out.join("tmp").join("distcheck-src"); - let _ = fs::remove_dir_all(&dir); - t!(fs::create_dir_all(&dir)); - - let mut cmd = Command::new("tar"); - cmd.arg("-xzf") - .arg(dist::rust_src_installer(build)) - .arg("--strip-components=1") - .current_dir(&dir); - build.run(&mut cmd); - - let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml"); - build.run(Command::new(&build.initial_cargo) - .arg("generate-lockfile") - .arg("--manifest-path") - .arg(&toml) - .current_dir(&dir)); +impl<'a> Step<'a> for Distcheck { + type Output = (); + + /// Run "distcheck", a 'make check' from a tarball + fn run(self, builder: &Builder) { + let build = builder.build; + + if build.build != "x86_64-unknown-linux-gnu" { + return + } + if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") { + return + } + if !build.config.target.iter().any(|s| s == "x86_64-unknown-linux-gnu") { + return + } + + println!("Distcheck"); + let dir = build.out.join("tmp").join("distcheck"); + let _ = fs::remove_dir_all(&dir); + t!(fs::create_dir_all(&dir)); + + let mut cmd = Command::new("tar"); + cmd.arg("-xzf") + .arg(dist::rust_src_location(build)) + .arg("--strip-components=1") + .current_dir(&dir); + build.run(&mut cmd); + build.run(Command::new("./configure") + .args(&build.config.configure_args) + .arg("--enable-vendor") + .current_dir(&dir)); + build.run(Command::new(build_helper::make(&build.build)) + .arg("check") + .current_dir(&dir)); + + // Now make sure that rust-src has all of libstd's dependencies + println!("Distcheck rust-src"); + let dir = build.out.join("tmp").join("distcheck-src"); + let _ = fs::remove_dir_all(&dir); + t!(fs::create_dir_all(&dir)); + + let mut cmd = Command::new("tar"); + cmd.arg("-xzf") + .arg(dist::rust_src_installer(build)) + .arg("--strip-components=1") + .current_dir(&dir); + build.run(&mut cmd); + + let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml"); + build.run(Command::new(&build.initial_cargo) + .arg("generate-lockfile") + .arg("--manifest-path") + .arg(&toml) + .current_dir(&dir)); + } } //rules.test("check-bootstrap", "src/bootstrap") @@ -914,18 +1071,26 @@ pub fn distcheck(build: &Build) { // .host(true) // .only_build(true) // .run(move |_| check::bootstrap(build)); -// -/// Test the build system itself -pub fn bootstrap(build: &Build) { - let mut cmd = Command::new(&build.initial_cargo); - cmd.arg("test") - .current_dir(build.src.join("src/bootstrap")) - .env("CARGO_TARGET_DIR", build.out.join("bootstrap")) - .env("RUSTC_BOOTSTRAP", "1") - .env("RUSTC", &build.initial_rustc); - if !build.fail_fast { - cmd.arg("--no-fail-fast"); + +#[derive(Serialize)] +pub struct Bootstrap; + +impl<'a> for Step<'a> Bootstrap { + type Output = (); + + /// Test the build system itself + fn run(self, builder: &Builder) { + let build = builder.build; + let mut cmd = Command::new(&build.initial_cargo); + cmd.arg("test") + .current_dir(build.src.join("src/bootstrap")) + .env("CARGO_TARGET_DIR", build.out.join("bootstrap")) + .env("RUSTC_BOOTSTRAP", "1") + .env("RUSTC", &build.initial_rustc); + if !build.fail_fast { + cmd.arg("--no-fail-fast"); + } + cmd.arg("--").args(&build.flags.cmd.test_args()); + try_run(build, &mut cmd); } - cmd.arg("--").args(&build.flags.cmd.test_args()); - try_run(build, &mut cmd); } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 4a972ebf8df9d..cf1e11f7ac820 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -32,24 +32,6 @@ use channel::GitInfo; use util::{exe, libdir, is_dylib, copy}; use {Build, Compiler, Mode}; -// for (krate, path, _default) in krates("std") { -// rules.build(&krate.build_step, path) -// .dep(|s| s.name("startup-objects")) -// .dep(move |s| s.name("rustc").host(&build.build).target(s.host)) -// .run(move |s| compile::std(build, s.target, &s.compiler())); -// } -// for (krate, path, _default) in krates("test") { -// rules.build(&krate.build_step, path) -// .dep(|s| s.name("libstd-link")) -// .run(move |s| compile::test(build, s.target, &s.compiler())); -// } -// for (krate, path, _default) in krates("rustc-main") { -// rules.build(&krate.build_step, path) -// .dep(|s| s.name("libtest-link")) -// .dep(move |s| s.name("llvm").host(&build.build).stage(0)) -// .dep(|s| s.name("may-run-build-script")) -// .run(move |s| compile::rustc(build, s.target, &s.compiler())); -// } // // // Crates which have build scripts need to rely on this rule to ensure that // // the necessary prerequisites for a build script are linked and located in @@ -147,65 +129,84 @@ fn crate_rule<'a, 'b>(build: &'a Build, rule } -/// Build the standard library. -/// -/// This will build the standard library for a particular stage of the build -/// using the `compiler` targeting the `target` architecture. The artifacts -/// created will also be linked into the sysroot directory. -pub fn std(build: &Build, target: &str, compiler: &Compiler) { - let libdir = build.sysroot_libdir(compiler, target); - t!(fs::create_dir_all(&libdir)); - - let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); - println!("Building stage{} std artifacts ({} -> {})", compiler.stage, - compiler.host, target); - - let out_dir = build.cargo_out(compiler, Mode::Libstd, target); - build.clear_if_dirty(&out_dir, &build.compiler_path(compiler)); - let mut cargo = build.cargo(compiler, Mode::Libstd, target, "build"); - let mut features = build.std_features(); - - if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { - cargo.env("MACOSX_DEPLOYMENT_TARGET", target); - } +// for (krate, path, _default) in krates("std") { +// rules.build(&krate.build_step, path) +// .dep(|s| s.name("startup-objects")) +// .dep(move |s| s.name("rustc").host(&build.build).target(s.host)) +// .run(move |s| compile::std(build, s.target, &s.compiler())); +// } +#[derive(Serialize)] +pub struct Std<'a> { + pub target: &'a str, + pub compiler: &'a Compiler<'a>, +} - // When doing a local rebuild we tell cargo that we're stage1 rather than - // stage0. This works fine if the local rust and being-built rust have the - // same view of what the default allocator is, but fails otherwise. Since - // we don't have a way to express an allocator preference yet, work - // around the issue in the case of a local rebuild with jemalloc disabled. - if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc { - features.push_str(" force_alloc_system"); - } +impl<'a> Step<'a> for Std<'a> { + type Output = (); + + /// Build the standard library. + /// + /// This will build the standard library for a particular stage of the build + /// using the `compiler` targeting the `target` architecture. The artifacts + /// created will also be linked into the sysroot directory. + fn run(self, builder: &Builder) { + let build = builder.build; + let target = self.target; + let compiler = self.compiler; + let libdir = build.sysroot_libdir(compiler, target); + t!(fs::create_dir_all(&libdir)); + + let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); + println!("Building stage{} std artifacts ({} -> {})", compiler.stage, + compiler.host, target); + + let out_dir = build.cargo_out(compiler, Mode::Libstd, target); + build.clear_if_dirty(&out_dir, &build.compiler_path(compiler)); + let mut cargo = build.cargo(compiler, Mode::Libstd, target, "build"); + let mut features = build.std_features(); + + if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { + cargo.env("MACOSX_DEPLOYMENT_TARGET", target); + } - if compiler.stage != 0 && build.config.sanitizers { - // This variable is used by the sanitizer runtime crates, e.g. - // rustc_lsan, to build the sanitizer runtime from C code - // When this variable is missing, those crates won't compile the C code, - // so we don't set this variable during stage0 where llvm-config is - // missing - // We also only build the runtimes when --enable-sanitizers (or its - // config.toml equivalent) is used - cargo.env("LLVM_CONFIG", build.llvm_config(target)); - } - cargo.arg("--features").arg(features) - .arg("--manifest-path") - .arg(build.src.join("src/libstd/Cargo.toml")); + // When doing a local rebuild we tell cargo that we're stage1 rather than + // stage0. This works fine if the local rust and being-built rust have the + // same view of what the default allocator is, but fails otherwise. Since + // we don't have a way to express an allocator preference yet, work + // around the issue in the case of a local rebuild with jemalloc disabled. + if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc { + features.push_str(" force_alloc_system"); + } - if let Some(target) = build.config.target_config.get(target) { - if let Some(ref jemalloc) = target.jemalloc { - cargo.env("JEMALLOC_OVERRIDE", jemalloc); + if compiler.stage != 0 && build.config.sanitizers { + // This variable is used by the sanitizer runtime crates, e.g. + // rustc_lsan, to build the sanitizer runtime from C code + // When this variable is missing, those crates won't compile the C code, + // so we don't set this variable during stage0 where llvm-config is + // missing + // We also only build the runtimes when --enable-sanitizers (or its + // config.toml equivalent) is used + cargo.env("LLVM_CONFIG", build.llvm_config(target)); } - } - if target.contains("musl") { - if let Some(p) = build.musl_root(target) { - cargo.env("MUSL_ROOT", p); + cargo.arg("--features").arg(features) + .arg("--manifest-path") + .arg(build.src.join("src/libstd/Cargo.toml")); + + if let Some(target) = build.config.target_config.get(target) { + if let Some(ref jemalloc) = target.jemalloc { + cargo.env("JEMALLOC_OVERRIDE", jemalloc); + } + } + if target.contains("musl") { + if let Some(p) = build.musl_root(target) { + cargo.env("MUSL_ROOT", p); + } } - } - run_cargo(build, - &mut cargo, - &libstd_stamp(build, &compiler, target)); + run_cargo(build, + &mut cargo, + &libstd_stamp(build, &compiler, target)); + } } @@ -216,36 +217,49 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) { // compile::std_link) // .dep(|s| s.name("startup-objects")) // .dep(|s| s.name("create-sysroot").target(s.host)); -/// Link all libstd rlibs/dylibs into the sysroot location. -/// -/// Links those artifacts generated by `compiler` to a the `stage` compiler's -/// sysroot for the specified `host` and `target`. -/// -/// Note that this assumes that `compiler` has already generated the libstd -/// libraries for `target`, and this method will find them in the relevant -/// output directory. -pub fn std_link(build: &Build, - compiler: &Compiler, - target_compiler: &Compiler, - target: &str) { - println!("Copying stage{} std from stage{} ({} -> {} / {})", - target_compiler.stage, - compiler.stage, - compiler.host, - target_compiler.host, - target); - let libdir = build.sysroot_libdir(target_compiler, target); - add_to_sysroot(&libdir, &libstd_stamp(build, compiler, target)); - - if target.contains("musl") && !target.contains("mips") { - copy_musl_third_party_objects(build, target, &libdir); - } - if build.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" { - // The sanitizers are only built in stage1 or above, so the dylibs will - // be missing in stage0 and causes panic. See the `std()` function above - // for reason why the sanitizers are not built in stage0. - copy_apple_sanitizer_dylibs(&build.native_dir(target), "osx", &libdir); +#[derive(Serialize)] +pub struct StdLink<'a> { + pub compiler: Compiler<'a>, + pub target_compiler: Compiler<'a>, + pub target: &'a str, +} + +impl<'a> Step<'a> for StdLink<'a> { + type Output = (); + + /// Link all libstd rlibs/dylibs into the sysroot location. + /// + /// Links those artifacts generated by `compiler` to a the `stage` compiler's + /// sysroot for the specified `host` and `target`. + /// + /// Note that this assumes that `compiler` has already generated the libstd + /// libraries for `target`, and this method will find them in the relevant + /// output directory. + fn run(self, builder: &Builder) { + let build = builder.build; + let compiler = self.compiler; + let target_compiler = self.target_compiler; + let target = self.target; + println!("Copying stage{} std from stage{} ({} -> {} / {})", + target_compiler.stage, + compiler.stage, + compiler.host, + target_compiler.host, + target); + let libdir = build.sysroot_libdir(target_compiler, target); + add_to_sysroot(&libdir, &libstd_stamp(build, compiler, target)); + + if target.contains("musl") && !target.contains("mips") { + copy_musl_third_party_objects(build, target, &libdir); + } + + if build.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" { + // The sanitizers are only built in stage1 or above, so the dylibs will + // be missing in stage0 and causes panic. See the `std()` function above + // for reason why the sanitizers are not built in stage0. + copy_apple_sanitizer_dylibs(&build.native_dir(target), "osx", &libdir); + } } } @@ -274,66 +288,97 @@ fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) { // .dep(|s| s.name("create-sysroot").target(s.host)) // .run(move |s| compile::build_startup_objects(build, &s.compiler(), s.target)); -/// Build and prepare startup objects like rsbegin.o and rsend.o -/// -/// These are primarily used on Windows right now for linking executables/dlls. -/// They don't require any library support as they're just plain old object -/// files, so we just use the nightly snapshot compiler to always build them (as -/// no other compilers are guaranteed to be available). -pub fn build_startup_objects(build: &Build, for_compiler: &Compiler, target: &str) { - if !target.contains("pc-windows-gnu") { - return - } +#[derive(Serialize)] +pub struct StartupObjects<'a> { + pub for_compiler: Compiler<'a>, + pub target: &'a str, +} - let compiler = Compiler::new(0, &build.build); - let compiler_path = build.compiler_path(&compiler); - let src_dir = &build.src.join("src/rtstartup"); - let dst_dir = &build.native_dir(target).join("rtstartup"); - let sysroot_dir = &build.sysroot_libdir(for_compiler, target); - t!(fs::create_dir_all(dst_dir)); - t!(fs::create_dir_all(sysroot_dir)); - - for file in &["rsbegin", "rsend"] { - let src_file = &src_dir.join(file.to_string() + ".rs"); - let dst_file = &dst_dir.join(file.to_string() + ".o"); - if !up_to_date(src_file, dst_file) { - let mut cmd = Command::new(&compiler_path); - build.run(cmd.env("RUSTC_BOOTSTRAP", "1") - .arg("--cfg").arg(format!("stage{}", compiler.stage)) - .arg("--target").arg(target) - .arg("--emit=obj") - .arg("--out-dir").arg(dst_dir) - .arg(src_file)); +impl<'a> Step<'a> for StartupObjects<'a> { + type Output = (); + + /// Build and prepare startup objects like rsbegin.o and rsend.o + /// + /// These are primarily used on Windows right now for linking executables/dlls. + /// They don't require any library support as they're just plain old object + /// files, so we just use the nightly snapshot compiler to always build them (as + /// no other compilers are guaranteed to be available). + fn run(self, builder: &Builder) { + let build = builder.build; + let for_compiler = self.for_compiler; + let target = self.target; + if !target.contains("pc-windows-gnu") { + return } - copy(dst_file, &sysroot_dir.join(file.to_string() + ".o")); - } + let compiler = Compiler::new(0, &build.build); + let compiler_path = build.compiler_path(&compiler); + let src_dir = &build.src.join("src/rtstartup"); + let dst_dir = &build.native_dir(target).join("rtstartup"); + let sysroot_dir = &build.sysroot_libdir(for_compiler, target); + t!(fs::create_dir_all(dst_dir)); + t!(fs::create_dir_all(sysroot_dir)); + + for file in &["rsbegin", "rsend"] { + let src_file = &src_dir.join(file.to_string() + ".rs"); + let dst_file = &dst_dir.join(file.to_string() + ".o"); + if !up_to_date(src_file, dst_file) { + let mut cmd = Command::new(&compiler_path); + build.run(cmd.env("RUSTC_BOOTSTRAP", "1") + .arg("--cfg").arg(format!("stage{}", compiler.stage)) + .arg("--target").arg(target) + .arg("--emit=obj") + .arg("--out-dir").arg(dst_dir) + .arg(src_file)); + } - for obj in ["crt2.o", "dllcrt2.o"].iter() { - copy(&compiler_file(build.cc(target), obj), &sysroot_dir.join(obj)); + copy(dst_file, &sysroot_dir.join(file.to_string() + ".o")); + } + + for obj in ["crt2.o", "dllcrt2.o"].iter() { + copy(&compiler_file(build.cc(target), obj), &sysroot_dir.join(obj)); + } } } -/// Build libtest. -/// -/// This will build libtest and supporting libraries for a particular stage of -/// the build using the `compiler` targeting the `target` architecture. The -/// artifacts created will also be linked into the sysroot directory. -pub fn test(build: &Build, target: &str, compiler: &Compiler) { - let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); - println!("Building stage{} test artifacts ({} -> {})", compiler.stage, - compiler.host, target); - let out_dir = build.cargo_out(compiler, Mode::Libtest, target); - build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); - let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build"); - if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { - cargo.env("MACOSX_DEPLOYMENT_TARGET", target); +// for (krate, path, _default) in krates("test") { +// rules.build(&krate.build_step, path) +// .dep(|s| s.name("libstd-link")) +// .run(move |s| compile::test(build, s.target, &s.compiler())); +// } +#[derive(Serialize)] +pub struct Test<'a> { + pub compiler: Compiler<'a>, + pub target: &'a str, +} + +impl<'a> Step<'a> for Test<'a> { + type Output = (); + + /// Build libtest. + /// + /// This will build libtest and supporting libraries for a particular stage of + /// the build using the `compiler` targeting the `target` architecture. The + /// artifacts created will also be linked into the sysroot directory. + fn run(self, builder: &Builder) { + let build = builder.build; + let target = self.target; + let compiler = self.compiler; + let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); + println!("Building stage{} test artifacts ({} -> {})", compiler.stage, + compiler.host, target); + let out_dir = build.cargo_out(compiler, Mode::Libtest, target); + build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); + let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build"); + if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { + cargo.env("MACOSX_DEPLOYMENT_TARGET", target); + } + cargo.arg("--manifest-path") + .arg(build.src.join("src/libtest/Cargo.toml")); + run_cargo(build, + &mut cargo, + &libtest_stamp(build, compiler, target)); } - cargo.arg("--manifest-path") - .arg(build.src.join("src/libtest/Cargo.toml")); - run_cargo(build, - &mut cargo, - &libtest_stamp(build, compiler, target)); } @@ -344,98 +389,131 @@ pub fn test(build: &Build, target: &str, compiler: &Compiler) { // compile::test_link) // .dep(|s| s.name("libstd-link")); -/// Same as `std_link`, only for libtest -pub fn test_link(build: &Build, - compiler: &Compiler, - target_compiler: &Compiler, - target: &str) { - println!("Copying stage{} test from stage{} ({} -> {} / {})", - target_compiler.stage, - compiler.stage, - compiler.host, - target_compiler.host, - target); - add_to_sysroot(&build.sysroot_libdir(target_compiler, target), - &libtest_stamp(build, compiler, target)); +#[derive(Serialize)] +pub struct TestLink<'a> { + pub compiler: Compiler<'a>, + pub target_compiler: Compiler<'a>, + pub target: &'a str, } -/// Build the compiler. -/// -/// This will build the compiler for a particular stage of the build using -/// the `compiler` targeting the `target` architecture. The artifacts -/// created will also be linked into the sysroot directory. -pub fn rustc(build: &Build, target: &str, compiler: &Compiler) { - let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); - println!("Building stage{} compiler artifacts ({} -> {})", - compiler.stage, compiler.host, target); - - let out_dir = build.cargo_out(compiler, Mode::Librustc, target); - build.clear_if_dirty(&out_dir, &libtest_stamp(build, compiler, target)); - - let mut cargo = build.cargo(compiler, Mode::Librustc, target, "build"); - cargo.arg("--features").arg(build.rustc_features()) - .arg("--manifest-path") - .arg(build.src.join("src/rustc/Cargo.toml")); - - // Set some configuration variables picked up by build scripts and - // the compiler alike - cargo.env("CFG_RELEASE", build.rust_release()) - .env("CFG_RELEASE_CHANNEL", &build.config.channel) - .env("CFG_VERSION", build.rust_version()) - .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default()); - - if compiler.stage == 0 { - cargo.env("CFG_LIBDIR_RELATIVE", "lib"); - } else { - let libdir_relative = build.config.libdir_relative.clone().unwrap_or(PathBuf::from("lib")); - cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative); +impl<'a> Step<'a> for Step<'a> { + type Output = (); + + /// Same as `std_link`, only for libtest + fn run(self, builder: &Builder) { + let build = builder.build; + let compiler = self.compiler; + let target_compiler = self.target_compiler; + let target = self.target; + println!("Copying stage{} test from stage{} ({} -> {} / {})", + target_compiler.stage, + compiler.stage, + compiler.host, + target_compiler.host, + target); + add_to_sysroot(&build.sysroot_libdir(target_compiler, target), + &libtest_stamp(build, compiler, target)); } +} - // If we're not building a compiler with debugging information then remove - // these two env vars which would be set otherwise. - if build.config.rust_debuginfo_only_std { - cargo.env_remove("RUSTC_DEBUGINFO"); - cargo.env_remove("RUSTC_DEBUGINFO_LINES"); - } +// for (krate, path, _default) in krates("rustc-main") { +// rules.build(&krate.build_step, path) +// .dep(|s| s.name("libtest-link")) +// .dep(move |s| s.name("llvm").host(&build.build).stage(0)) +// .dep(|s| s.name("may-run-build-script")) +// .run(move |s| compile::rustc(build, s.target, &s.compiler())); +// } - if let Some(ref ver_date) = build.rust_info.commit_date() { - cargo.env("CFG_VER_DATE", ver_date); - } - if let Some(ref ver_hash) = build.rust_info.sha() { - cargo.env("CFG_VER_HASH", ver_hash); - } - if !build.unstable_features() { - cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1"); - } - // Flag that rust llvm is in use - if build.is_rust_llvm(target) { - cargo.env("LLVM_RUSTLLVM", "1"); - } - cargo.env("LLVM_CONFIG", build.llvm_config(target)); - let target_config = build.config.target_config.get(target); - if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { - cargo.env("CFG_LLVM_ROOT", s); - } - // Building with a static libstdc++ is only supported on linux right now, - // not for MSVC or macOS - if build.config.llvm_static_stdcpp && - !target.contains("windows") && - !target.contains("apple") { - cargo.env("LLVM_STATIC_STDCPP", - compiler_file(build.cxx(target).unwrap(), "libstdc++.a")); - } - if build.config.llvm_link_shared { - cargo.env("LLVM_LINK_SHARED", "1"); - } - if let Some(ref s) = build.config.rustc_default_linker { - cargo.env("CFG_DEFAULT_LINKER", s); - } - if let Some(ref s) = build.config.rustc_default_ar { - cargo.env("CFG_DEFAULT_AR", s); +#[derive(Serialize)] +pub struct Rustc<'a> { + pub compiler: Compiler<'a>, + pub target: &'a str, +} + +impl<'a> Step<'a> for Rustc<'a> { + type Output = (); + + /// Build the compiler. + /// + /// This will build the compiler for a particular stage of the build using + /// the `compiler` targeting the `target` architecture. The artifacts + /// created will also be linked into the sysroot directory. + fn run(self, builder: &Builder) { + let build = builder.build; + let compiler = self.compiler; + let target = self.target; + let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); + println!("Building stage{} compiler artifacts ({} -> {})", + compiler.stage, compiler.host, target); + + let out_dir = build.cargo_out(compiler, Mode::Librustc, target); + build.clear_if_dirty(&out_dir, &libtest_stamp(build, compiler, target)); + + let mut cargo = build.cargo(compiler, Mode::Librustc, target, "build"); + cargo.arg("--features").arg(build.rustc_features()) + .arg("--manifest-path") + .arg(build.src.join("src/rustc/Cargo.toml")); + + // Set some configuration variables picked up by build scripts and + // the compiler alike + cargo.env("CFG_RELEASE", build.rust_release()) + .env("CFG_RELEASE_CHANNEL", &build.config.channel) + .env("CFG_VERSION", build.rust_version()) + .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default()); + + if compiler.stage == 0 { + cargo.env("CFG_LIBDIR_RELATIVE", "lib"); + } else { + let libdir_relative = build.config.libdir_relative.clone().unwrap_or(PathBuf::from("lib")); + cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative); + } + + // If we're not building a compiler with debugging information then remove + // these two env vars which would be set otherwise. + if build.config.rust_debuginfo_only_std { + cargo.env_remove("RUSTC_DEBUGINFO"); + cargo.env_remove("RUSTC_DEBUGINFO_LINES"); + } + + if let Some(ref ver_date) = build.rust_info.commit_date() { + cargo.env("CFG_VER_DATE", ver_date); + } + if let Some(ref ver_hash) = build.rust_info.sha() { + cargo.env("CFG_VER_HASH", ver_hash); + } + if !build.unstable_features() { + cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1"); + } + // Flag that rust llvm is in use + if build.is_rust_llvm(target) { + cargo.env("LLVM_RUSTLLVM", "1"); + } + cargo.env("LLVM_CONFIG", build.llvm_config(target)); + let target_config = build.config.target_config.get(target); + if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { + cargo.env("CFG_LLVM_ROOT", s); + } + // Building with a static libstdc++ is only supported on linux right now, + // not for MSVC or macOS + if build.config.llvm_static_stdcpp && + !target.contains("windows") && + !target.contains("apple") { + cargo.env("LLVM_STATIC_STDCPP", + compiler_file(build.cxx(target).unwrap(), "libstdc++.a")); + } + if build.config.llvm_link_shared { + cargo.env("LLVM_LINK_SHARED", "1"); + } + if let Some(ref s) = build.config.rustc_default_linker { + cargo.env("CFG_DEFAULT_LINKER", s); + } + if let Some(ref s) = build.config.rustc_default_ar { + cargo.env("CFG_DEFAULT_AR", s); + } + run_cargo(build, + &mut cargo, + &librustc_stamp(build, compiler, target)); } - run_cargo(build, - &mut cargo, - &librustc_stamp(build, compiler, target)); } // crate_rule(build, @@ -444,19 +522,31 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) { // "build-crate-rustc-main", // compile::rustc_link) // .dep(|s| s.name("libtest-link")); -/// Same as `std_link`, only for librustc -pub fn rustc_link(build: &Build, - compiler: &Compiler, - target_compiler: &Compiler, - target: &str) { - println!("Copying stage{} rustc from stage{} ({} -> {} / {})", - target_compiler.stage, - compiler.stage, - compiler.host, - target_compiler.host, - target); - add_to_sysroot(&build.sysroot_libdir(target_compiler, target), - &librustc_stamp(build, compiler, target)); +#[derive(Serialize)] +pub struct RustcLink<'a> { + pub compiler: Compiler<'a>, + pub target_compiler: Compiler<'a>, + pub target: &'a str, +} + +impl<'a> Step<'a> for RustcLink<'a> { + type Output = (); + + /// Same as `std_link`, only for librustc + fn run(self, builder: &Builder) { + let build = builder.build; + let compiler = self.compiler; + let target_compiler = self.target_compiler; + let target = self.target; + println!("Copying stage{} rustc from stage{} ({} -> {} / {})", + target_compiler.stage, + compiler.stage, + compiler.host, + target_compiler.host, + target); + add_to_sysroot(&build.sysroot_libdir(target_compiler, target), + &librustc_stamp(build, compiler, target)); + } } /// Cargo's output path for the standard library in a given stage, compiled @@ -485,10 +575,28 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf { // rules.build("create-sysroot", "path/to/nowhere") // .run(move |s| compile::create_sysroot(build, &s.compiler())); -pub fn create_sysroot(build: &Build, compiler: &Compiler) { - let sysroot = build.sysroot(compiler); - let _ = fs::remove_dir_all(&sysroot); - t!(fs::create_dir_all(&sysroot)); + +#[derive(Serialize)] +pub struct Sysroot<'a> { + pub compiler: Compiler<'a>, +} + +impl<'a> Step<'a> for Sysroot<'a> { + type Output = (); + + /// Returns the sysroot for the `compiler` specified that *this build system + /// generates*. + /// + /// That is, the sysroot for the stage0 compiler is not what the compiler + /// thinks it is by default, but it's the same as the default for stages + /// 1-3. + fn run(self, builder: &Builder) { + let build = builder.build; + let compiler = self.compiler; + let sysroot = build.sysroot(compiler); + let _ = fs::remove_dir_all(&sysroot); + t!(fs::create_dir_all(&sysroot)); + } } // the compiler with no target libraries ready to go @@ -504,54 +612,68 @@ pub fn create_sysroot(build: &Build, compiler: &Compiler) { // } // }) // .run(move |s| compile::assemble_rustc(build, s.stage, s.target)); -/// Prepare a new compiler from the artifacts in `stage` -/// -/// This will assemble a compiler in `build/$host/stage$stage`. The compiler -/// must have been previously produced by the `stage - 1` build.build -/// compiler. -pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { - // nothing to do in stage0 - if stage == 0 { - return - } - println!("Copying stage{} compiler ({})", stage, host); +#[derive(Serialize)] +pub struct Assemble<'a> { + pub stage: u32, + pub host: &'a str, +} - // The compiler that we're assembling - let target_compiler = Compiler::new(stage, host); +impl<'a> Step<'a> for Assemble<'a> { + type Output = (); + + /// Prepare a new compiler from the artifacts in `stage` + /// + /// This will assemble a compiler in `build/$host/stage$stage`. The compiler + /// must have been previously produced by the `stage - 1` build.build + /// compiler. + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let host = self.host; + // nothing to do in stage0 + if stage == 0 { + return + } + + println!("Copying stage{} compiler ({})", stage, host); - // The compiler that compiled the compiler we're assembling - let build_compiler = Compiler::new(stage - 1, &build.build); + // The compiler that we're assembling + let target_compiler = Compiler::new(stage, host); - // Link in all dylibs to the libdir - let sysroot = build.sysroot(&target_compiler); - let sysroot_libdir = sysroot.join(libdir(host)); - t!(fs::create_dir_all(&sysroot_libdir)); - let src_libdir = build.sysroot_libdir(&build_compiler, host); - for f in t!(fs::read_dir(&src_libdir)).map(|f| t!(f)) { - let filename = f.file_name().into_string().unwrap(); - if is_dylib(&filename) { - copy(&f.path(), &sysroot_libdir.join(&filename)); + // The compiler that compiled the compiler we're assembling + let build_compiler = Compiler::new(stage - 1, &build.build); + + // Link in all dylibs to the libdir + let sysroot = build.sysroot(&target_compiler); + let sysroot_libdir = sysroot.join(libdir(host)); + t!(fs::create_dir_all(&sysroot_libdir)); + let src_libdir = build.sysroot_libdir(&build_compiler, host); + for f in t!(fs::read_dir(&src_libdir)).map(|f| t!(f)) { + let filename = f.file_name().into_string().unwrap(); + if is_dylib(&filename) { + copy(&f.path(), &sysroot_libdir.join(&filename)); + } } - } - let out_dir = build.cargo_out(&build_compiler, Mode::Librustc, host); - - // Link the compiler binary itself into place - let rustc = out_dir.join(exe("rustc", host)); - let bindir = sysroot.join("bin"); - t!(fs::create_dir_all(&bindir)); - let compiler = build.compiler_path(&target_compiler); - let _ = fs::remove_file(&compiler); - copy(&rustc, &compiler); - - // See if rustdoc exists to link it into place - let rustdoc = exe("rustdoc", host); - let rustdoc_src = out_dir.join(&rustdoc); - let rustdoc_dst = bindir.join(&rustdoc); - if fs::metadata(&rustdoc_src).is_ok() { - let _ = fs::remove_file(&rustdoc_dst); - copy(&rustdoc_src, &rustdoc_dst); + let out_dir = build.cargo_out(&build_compiler, Mode::Librustc, host); + + // Link the compiler binary itself into place + let rustc = out_dir.join(exe("rustc", host)); + let bindir = sysroot.join("bin"); + t!(fs::create_dir_all(&bindir)); + let compiler = build.compiler_path(&target_compiler); + let _ = fs::remove_file(&compiler); + copy(&rustc, &compiler); + + // See if rustdoc exists to link it into place + let rustdoc = exe("rustdoc", host); + let rustdoc_src = out_dir.join(&rustdoc); + let rustdoc_dst = bindir.join(&rustdoc); + if fs::metadata(&rustdoc_src).is_ok() { + let _ = fs::remove_file(&rustdoc_dst); + copy(&rustdoc_src, &rustdoc_dst); + } } } @@ -574,160 +696,6 @@ fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) { } } -//// ======================================================================== -//// Build tools -//// -//// Tools used during the build system but not shipped -//// "pseudo rule" which represents completely cleaning out the tools dir in -//// one stage. This needs to happen whenever a dependency changes (e.g. -//// libstd, libtest, librustc) and all of the tool compilations above will -//// be sequenced after this rule. -//rules.build("maybe-clean-tools", "path/to/nowhere") -// .after("librustc-tool") -// .after("libtest-tool") -// .after("libstd-tool"); -// -//rules.build("librustc-tool", "path/to/nowhere") -// .dep(|s| s.name("librustc")) -// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Librustc)); -//rules.build("libtest-tool", "path/to/nowhere") -// .dep(|s| s.name("libtest")) -// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libtest)); -//rules.build("libstd-tool", "path/to/nowhere") -// .dep(|s| s.name("libstd")) -// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libstd)); -// -/// Build a tool in `src/tools` -/// -/// This will build the specified tool with the specified `host` compiler in -/// `stage` into the normal cargo output directory. -pub fn maybe_clean_tools(build: &Build, stage: u32, target: &str, mode: Mode) { - let compiler = Compiler::new(stage, &build.build); - - let stamp = match mode { - Mode::Libstd => libstd_stamp(build, &compiler, target), - Mode::Libtest => libtest_stamp(build, &compiler, target), - Mode::Librustc => librustc_stamp(build, &compiler, target), - _ => panic!(), - }; - let out_dir = build.cargo_out(&compiler, Mode::Tool, target); - build.clear_if_dirty(&out_dir, &stamp); -} - - -// rules.build("tool-rustbook", "src/tools/rustbook") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("librustc-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "rustbook")); -// rules.build("tool-error-index", "src/tools/error_index_generator") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("librustc-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator")); -// rules.build("tool-unstable-book-gen", "src/tools/unstable-book-gen") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "unstable-book-gen")); -// rules.build("tool-tidy", "src/tools/tidy") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "tidy")); -// rules.build("tool-linkchecker", "src/tools/linkchecker") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "linkchecker")); -// rules.build("tool-cargotest", "src/tools/cargotest") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "cargotest")); -// rules.build("tool-compiletest", "src/tools/compiletest") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libtest-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "compiletest")); -// rules.build("tool-build-manifest", "src/tools/build-manifest") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "build-manifest")); -// rules.build("tool-remote-test-server", "src/tools/remote-test-server") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-server")); -// rules.build("tool-remote-test-client", "src/tools/remote-test-client") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-client")); -// rules.build("tool-rust-installer", "src/tools/rust-installer") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "rust-installer")); -// rules.build("tool-cargo", "src/tools/cargo") -// .host(true) -// .default(build.config.extended) -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .dep(|s| s.stage(0).host(s.target).name("openssl")) -// .dep(move |s| { -// // Cargo depends on procedural macros, which requires a full host -// // compiler to be available, so we need to depend on that. -// s.name("librustc-link") -// .target(&build.build) -// .host(&build.build) -// }) -// .run(move |s| compile::tool(build, s.stage, s.target, "cargo")); -// rules.build("tool-rls", "src/tools/rls") -// .host(true) -// .default(build.config.extended) -// .dep(|s| s.name("librustc-tool")) -// .dep(|s| s.stage(0).host(s.target).name("openssl")) -// .dep(move |s| { -// // rls, like cargo, uses procedural macros -// s.name("librustc-link") -// .target(&build.build) -// .host(&build.build) -// }) -// .run(move |s| compile::tool(build, s.stage, s.target, "rls")); -// - -/// Build a tool in `src/tools` -/// -/// This will build the specified tool with the specified `host` compiler in -/// `stage` into the normal cargo output directory. -pub fn tool(build: &Build, stage: u32, target: &str, tool: &str) { - let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool)); - println!("Building stage{} tool {} ({})", stage, tool, target); - - let compiler = Compiler::new(stage, &build.build); - - let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build"); - let dir = build.src.join("src/tools").join(tool); - cargo.arg("--manifest-path").arg(dir.join("Cargo.toml")); - - // We don't want to build tools dynamically as they'll be running across - // stages and such and it's just easier if they're not dynamically linked. - cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); - - if let Some(dir) = build.openssl_install_dir(target) { - cargo.env("OPENSSL_STATIC", "1"); - cargo.env("OPENSSL_DIR", dir); - cargo.env("LIBZ_SYS_STATIC", "1"); - } - - cargo.env("CFG_RELEASE_CHANNEL", &build.config.channel); - - let info = GitInfo::new(&dir); - if let Some(sha) = info.sha() { - cargo.env("CFG_COMMIT_HASH", sha); - } - if let Some(sha_short) = info.sha_short() { - cargo.env("CFG_SHORT_COMMIT_HASH", sha_short); - } - if let Some(date) = info.commit_date() { - cargo.env("CFG_COMMIT_DATE", date); - } - - build.run(&mut cargo); -} - - // Avoiding a dependency on winapi to keep compile times down #[cfg(unix)] fn stderr_isatty() -> bool { diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 2cf3ca73952ac..8aa9ad7021e6f 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -67,46 +67,61 @@ fn rust_installer(build: &Build) -> Command { // .dep(|s| s.name("default:doc")) // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::docs(build, s.stage, s.target)); -/// Builds the `rust-docs` installer component. -/// -/// Slurps up documentation from the `stage`'s `host`. -pub fn docs(build: &Build, stage: u32, host: &str) { - println!("Dist docs stage{} ({})", stage, host); - if !build.config.docs { - println!("\tskipping - docs disabled"); - return - } - let name = pkgname(build, "rust-docs"); - let image = tmpdir(build).join(format!("{}-{}-image", name, host)); - let _ = fs::remove_dir_all(&image); +#[derive(Serialize)] +pub struct Docs<'a> { + stage: u32, + host: &'a str, +} - let dst = image.join("share/doc/rust/html"); - t!(fs::create_dir_all(&dst)); - let src = build.out.join(host).join("doc"); - cp_r(&src, &dst); +impl<'a> Step<'a> for Docs<'a> { + type Output = (); + + /// Builds the `rust-docs` installer component. + /// + /// Slurps up documentation from the `stage`'s `host`. + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let host = self.host; + + println!("Dist docs stage{} ({})", stage, host); + if !build.config.docs { + println!("\tskipping - docs disabled"); + return + } - let mut cmd = rust_installer(build); - cmd.arg("generate") - .arg("--product-name=Rust-Documentation") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rust-documentation-is-installed.") - .arg("--image-dir").arg(&image) - .arg("--work-dir").arg(&tmpdir(build)) - .arg("--output-dir").arg(&distdir(build)) - .arg(format!("--package-name={}-{}", name, host)) - .arg("--component-name=rust-docs") - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--bulk-dirs=share/doc/rust/html"); - build.run(&mut cmd); - t!(fs::remove_dir_all(&image)); + let name = pkgname(build, "rust-docs"); + let image = tmpdir(build).join(format!("{}-{}-image", name, host)); + let _ = fs::remove_dir_all(&image); - // As part of this step, *also* copy the docs directory to a directory which - // buildbot typically uploads. - if host == build.build { - let dst = distdir(build).join("doc").join(build.rust_package_vers()); + let dst = image.join("share/doc/rust/html"); t!(fs::create_dir_all(&dst)); + let src = build.out.join(host).join("doc"); cp_r(&src, &dst); + + let mut cmd = rust_installer(build); + cmd.arg("generate") + .arg("--product-name=Rust-Documentation") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Rust-documentation-is-installed.") + .arg("--image-dir").arg(&image) + .arg("--work-dir").arg(&tmpdir(build)) + .arg("--output-dir").arg(&distdir(build)) + .arg(format!("--package-name={}-{}", name, host)) + .arg("--component-name=rust-docs") + .arg("--legacy-manifest-dirs=rustlib,cargo") + .arg("--bulk-dirs=share/doc/rust/html"); + build.run(&mut cmd); + t!(fs::remove_dir_all(&image)); + + // As part of this step, *also* copy the docs directory to a directory which + // buildbot typically uploads. + if host == build.build { + let dst = distdir(build).join("doc").join(build.rust_package_vers()); + t!(fs::create_dir_all(&dst)); + cp_r(&src, &dst); + } } } @@ -245,37 +260,48 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: // dist::mingw(build, s.target) // } // }); -// -/// Build the `rust-mingw` installer component. -/// -/// This contains all the bits and pieces to run the MinGW Windows targets -/// without any extra installed software (e.g. we bundle gcc, libraries, etc). -pub fn mingw(build: &Build, host: &str) { - println!("Dist mingw ({})", host); - let name = pkgname(build, "rust-mingw"); - let image = tmpdir(build).join(format!("{}-{}-image", name, host)); - let _ = fs::remove_dir_all(&image); - t!(fs::create_dir_all(&image)); - // The first argument is a "temporary directory" which is just - // thrown away (this contains the runtime DLLs included in the rustc package - // above) and the second argument is where to place all the MinGW components - // (which is what we want). - make_win_dist(&tmpdir(build), &image, host, &build); +#[derive(Serialize)] +pub struct Mingw<'a> { + host: &'a str, +} - let mut cmd = rust_installer(build); - cmd.arg("generate") - .arg("--product-name=Rust-MinGW") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rust-MinGW-is-installed.") - .arg("--image-dir").arg(&image) - .arg("--work-dir").arg(&tmpdir(build)) - .arg("--output-dir").arg(&distdir(build)) - .arg(format!("--package-name={}-{}", name, host)) - .arg("--component-name=rust-mingw") - .arg("--legacy-manifest-dirs=rustlib,cargo"); - build.run(&mut cmd); - t!(fs::remove_dir_all(&image)); +impl<'a> Step<'a> for Mingw<'a> { + type Output = (); + + /// Build the `rust-mingw` installer component. + /// + /// This contains all the bits and pieces to run the MinGW Windows targets + /// without any extra installed software (e.g. we bundle gcc, libraries, etc). + fn run(self, builder: &Builder) { + let build = builder.build; + let host = self.host; + println!("Dist mingw ({})", host); + let name = pkgname(build, "rust-mingw"); + let image = tmpdir(build).join(format!("{}-{}-image", name, host)); + let _ = fs::remove_dir_all(&image); + t!(fs::create_dir_all(&image)); + + // The first argument is a "temporary directory" which is just + // thrown away (this contains the runtime DLLs included in the rustc package + // above) and the second argument is where to place all the MinGW components + // (which is what we want). + make_win_dist(&tmpdir(build), &image, host, &build); + + let mut cmd = rust_installer(build); + cmd.arg("generate") + .arg("--product-name=Rust-MinGW") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Rust-MinGW-is-installed.") + .arg("--image-dir").arg(&image) + .arg("--work-dir").arg(&tmpdir(build)) + .arg("--output-dir").arg(&distdir(build)) + .arg(format!("--package-name={}-{}", name, host)) + .arg("--component-name=rust-mingw") + .arg("--legacy-manifest-dirs=rustlib,cargo"); + build.run(&mut cmd); + t!(fs::remove_dir_all(&image)); + } } // rules.dist("dist-rustc", "src/librustc") @@ -285,138 +311,166 @@ pub fn mingw(build: &Build, host: &str) { // .default(true) // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::rustc(build, s.stage, s.target)); -/// Creates the `rustc` installer component. -pub fn rustc(build: &Build, stage: u32, host: &str) { - println!("Dist rustc stage{} ({})", stage, host); - let name = pkgname(build, "rustc"); - let image = tmpdir(build).join(format!("{}-{}-image", name, host)); - let _ = fs::remove_dir_all(&image); - let overlay = tmpdir(build).join(format!("{}-{}-overlay", name, host)); - let _ = fs::remove_dir_all(&overlay); - - // Prepare the rustc "image", what will actually end up getting installed - prepare_image(build, stage, host, &image); - - // Prepare the overlay which is part of the tarball but won't actually be - // installed - let cp = |file: &str| { - install(&build.src.join(file), &overlay, 0o644); - }; - cp("COPYRIGHT"); - cp("LICENSE-APACHE"); - cp("LICENSE-MIT"); - cp("README.md"); - // tiny morsel of metadata is used by rust-packaging - let version = build.rust_version(); - t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); - - // On MinGW we've got a few runtime DLL dependencies that we need to - // include. The first argument to this script is where to put these DLLs - // (the image we're creating), and the second argument is a junk directory - // to ignore all other MinGW stuff the script creates. - // - // On 32-bit MinGW we're always including a DLL which needs some extra - // licenses to distribute. On 64-bit MinGW we don't actually distribute - // anything requiring us to distribute a license, but it's likely the - // install will *also* include the rust-mingw package, which also needs - // licenses, so to be safe we just include it here in all MinGW packages. - if host.contains("pc-windows-gnu") { - make_win_dist(&image, &tmpdir(build), host, build); - - let dst = image.join("share/doc"); - t!(fs::create_dir_all(&dst)); - cp_r(&build.src.join("src/etc/third-party"), &dst); - } - // Finally, wrap everything up in a nice tarball! - let mut cmd = rust_installer(build); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rust-is-ready-to-roll.") - .arg("--image-dir").arg(&image) - .arg("--work-dir").arg(&tmpdir(build)) - .arg("--output-dir").arg(&distdir(build)) - .arg("--non-installed-overlay").arg(&overlay) - .arg(format!("--package-name={}-{}", name, host)) - .arg("--component-name=rustc") - .arg("--legacy-manifest-dirs=rustlib,cargo"); - build.run(&mut cmd); - t!(fs::remove_dir_all(&image)); - t!(fs::remove_dir_all(&overlay)); - - fn prepare_image(build: &Build, stage: u32, host: &str, image: &Path) { - let src = build.sysroot(&Compiler::new(stage, host)); - let libdir = libdir(host); - - // Copy rustc/rustdoc binaries - t!(fs::create_dir_all(image.join("bin"))); - cp_r(&src.join("bin"), &image.join("bin")); - - // Copy runtime DLLs needed by the compiler - if libdir != "bin" { - for entry in t!(src.join(libdir).read_dir()).map(|e| t!(e)) { - let name = entry.file_name(); - if let Some(s) = name.to_str() { - if is_dylib(s) { - install(&entry.path(), &image.join(libdir), 0o644); - } - } - } - } - - // Man pages - t!(fs::create_dir_all(image.join("share/man/man1"))); - cp_r(&build.src.join("man"), &image.join("share/man/man1")); - - // Debugger scripts - debugger_scripts(build, &image, host); +#[derive(Serialize)] +pub struct Rustc<'a> { + stage: u32, + host: &'a str, +} - // Misc license info +impl<'a> Step<'a> for Rustc<'a> { + type Output = (); + + /// Creates the `rustc` installer component. + fn run(self, builder: &builder) { + let build = builder.build; + let stage = self.stage; + let host = self.host; + println!("Dist rustc stage{} ({})", stage, host); + let name = pkgname(build, "rustc"); + let image = tmpdir(build).join(format!("{}-{}-image", name, host)); + let _ = fs::remove_dir_all(&image); + let overlay = tmpdir(build).join(format!("{}-{}-overlay", name, host)); + let _ = fs::remove_dir_all(&overlay); + + // Prepare the rustc "image", what will actually end up getting installed + prepare_image(build, stage, host, &image); + + // Prepare the overlay which is part of the tarball but won't actually be + // installed let cp = |file: &str| { - install(&build.src.join(file), &image.join("share/doc/rust"), 0o644); + install(&build.src.join(file), &overlay, 0o644); }; cp("COPYRIGHT"); cp("LICENSE-APACHE"); cp("LICENSE-MIT"); cp("README.md"); + // tiny morsel of metadata is used by rust-packaging + let version = build.rust_version(); + t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + + // On MinGW we've got a few runtime DLL dependencies that we need to + // include. The first argument to this script is where to put these DLLs + // (the image we're creating), and the second argument is a junk directory + // to ignore all other MinGW stuff the script creates. + // + // On 32-bit MinGW we're always including a DLL which needs some extra + // licenses to distribute. On 64-bit MinGW we don't actually distribute + // anything requiring us to distribute a license, but it's likely the + // install will *also* include the rust-mingw package, which also needs + // licenses, so to be safe we just include it here in all MinGW packages. + if host.contains("pc-windows-gnu") { + make_win_dist(&image, &tmpdir(build), host, build); + + let dst = image.join("share/doc"); + t!(fs::create_dir_all(&dst)); + cp_r(&build.src.join("src/etc/third-party"), &dst); + } + + // Finally, wrap everything up in a nice tarball! + let mut cmd = rust_installer(build); + cmd.arg("generate") + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Rust-is-ready-to-roll.") + .arg("--image-dir").arg(&image) + .arg("--work-dir").arg(&tmpdir(build)) + .arg("--output-dir").arg(&distdir(build)) + .arg("--non-installed-overlay").arg(&overlay) + .arg(format!("--package-name={}-{}", name, host)) + .arg("--component-name=rustc") + .arg("--legacy-manifest-dirs=rustlib,cargo"); + build.run(&mut cmd); + t!(fs::remove_dir_all(&image)); + t!(fs::remove_dir_all(&overlay)); + + fn prepare_image(build: &Build, stage: u32, host: &str, image: &Path) { + let src = build.sysroot(&Compiler::new(stage, host)); + let libdir = libdir(host); + + // Copy rustc/rustdoc binaries + t!(fs::create_dir_all(image.join("bin"))); + cp_r(&src.join("bin"), &image.join("bin")); + + // Copy runtime DLLs needed by the compiler + if libdir != "bin" { + for entry in t!(src.join(libdir).read_dir()).map(|e| t!(e)) { + let name = entry.file_name(); + if let Some(s) = name.to_str() { + if is_dylib(s) { + install(&entry.path(), &image.join(libdir), 0o644); + } + } + } + } + + // Man pages + t!(fs::create_dir_all(image.join("share/man/man1"))); + cp_r(&build.src.join("man"), &image.join("share/man/man1")); + + // Debugger scripts + debugger_scripts(build, &image, host); + + // Misc license info + let cp = |file: &str| { + install(&build.src.join(file), &image.join("share/doc/rust"), 0o644); + }; + cp("COPYRIGHT"); + cp("LICENSE-APACHE"); + cp("LICENSE-MIT"); + cp("README.md"); + } } } + + //rules.test("debugger-scripts", "src/etc/lldb_batchmode.py") // .run(move |s| dist::debugger_scripts(build, &build.sysroot(&s.compiler()), // s.target)); -/// Copies debugger scripts for `host` into the `sysroot` specified. -pub fn debugger_scripts(build: &Build, - sysroot: &Path, - host: &str) { - let dst = sysroot.join("lib/rustlib/etc"); - t!(fs::create_dir_all(&dst)); - let cp_debugger_script = |file: &str| { - install(&build.src.join("src/etc/").join(file), &dst, 0o644); - }; - if host.contains("windows-msvc") { - // windbg debugger scripts - install(&build.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"), - 0o755); - - cp_debugger_script("natvis/liballoc.natvis"); - cp_debugger_script("natvis/libcore.natvis"); - } else { - cp_debugger_script("debugger_pretty_printers_common.py"); - // gdb debugger scripts - install(&build.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), - 0o755); +#[derive(Serialize)] +pub struct DebuggerScripts<'a> { + sysroot: &'a Path, + host: &'a str, +} - cp_debugger_script("gdb_load_rust_pretty_printers.py"); - cp_debugger_script("gdb_rust_pretty_printing.py"); +impl<'a> Step<'a> for DebuggerScripts<'a> { + type Output = (); - // lldb debugger scripts - install(&build.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), + /// Copies debugger scripts for `host` into the `sysroot` specified. + fn run(self, builder: &Builder) { + let build = builder.build; + let host = self.host; + let sysroot = self.sysroot; + let dst = sysroot.join("lib/rustlib/etc"); + t!(fs::create_dir_all(&dst)); + let cp_debugger_script = |file: &str| { + install(&build.src.join("src/etc/").join(file), &dst, 0o644); + }; + if host.contains("windows-msvc") { + // windbg debugger scripts + install(&build.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"), 0o755); - cp_debugger_script("lldb_rust_formatters.py"); + cp_debugger_script("natvis/liballoc.natvis"); + cp_debugger_script("natvis/libcore.natvis"); + } else { + cp_debugger_script("debugger_pretty_printers_common.py"); + + // gdb debugger scripts + install(&build.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), + 0o755); + + cp_debugger_script("gdb_load_rust_pretty_printers.py"); + cp_debugger_script("gdb_rust_pretty_printing.py"); + + // lldb debugger scripts + install(&build.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), + 0o755); + + cp_debugger_script("lldb_rust_formatters.py"); + } } } @@ -435,18 +489,6 @@ pub fn debugger_scripts(build: &Build, // .only_host_build(true) // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::std(build, &s.compiler(), s.target)); -/// Creates the `rust-std` installer component as compiled by `compiler` for the -/// target `target`. -pub fn std(build: &Build, compiler: &Compiler, target: &str) { - println!("Dist std stage{} ({} -> {})", compiler.stage, compiler.host, - target); - - // The only true set of target libraries came from the build triple, so - // let's reduce redundant work by only producing archives from that host. - if compiler.host != build.build { - println!("\tskipping, not a build host"); - return - } let name = pkgname(build, "rust-std"); let image = tmpdir(build).join(format!("{}-{}-image", name, target)); @@ -491,48 +533,62 @@ pub fn rust_src_installer(build: &Build) -> PathBuf { // .only_host_build(true) // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::analysis(build, &s.compiler(), s.target)); -/// Creates a tarball of save-analysis metadata, if available. -pub fn analysis(build: &Build, compiler: &Compiler, target: &str) { - assert!(build.config.extended); - println!("Dist analysis"); - - if compiler.host != build.build { - println!("\tskipping, not a build host"); - return; - } - // Package save-analysis from stage1 if not doing a full bootstrap, as the - // stage2 artifacts is simply copied from stage1 in that case. - let compiler = if build.force_use_stage1(compiler, target) { - Compiler::new(1, compiler.host) - } else { - compiler.clone() - }; +#[derive(Serialize)] +pub struct Analysis<'a> { + compiler: Compiler<'a>, + target: &'a str, +} - let name = pkgname(build, "rust-analysis"); - let image = tmpdir(build).join(format!("{}-{}-image", name, target)); +impl<'a> Step<'a> for Analysis<'a> { + type Output = (); - let src = build.stage_out(&compiler, Mode::Libstd).join(target).join("release").join("deps"); + /// Creates a tarball of save-analysis metadata, if available. + fn run(self, builder: &Builder) { + let build = builder.build; + let compiler = self.compiler; + let target = self.target; + assert!(build.config.extended); + println!("Dist analysis"); - let image_src = src.join("save-analysis"); - let dst = image.join("lib/rustlib").join(target).join("analysis"); - t!(fs::create_dir_all(&dst)); - println!("image_src: {:?}, dst: {:?}", image_src, dst); - cp_r(&image_src, &dst); + if compiler.host != build.build { + println!("\tskipping, not a build host"); + return; + } - let mut cmd = rust_installer(build); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=save-analysis-saved.") - .arg("--image-dir").arg(&image) - .arg("--work-dir").arg(&tmpdir(build)) - .arg("--output-dir").arg(&distdir(build)) - .arg(format!("--package-name={}-{}", name, target)) - .arg(format!("--component-name=rust-analysis-{}", target)) - .arg("--legacy-manifest-dirs=rustlib,cargo"); - build.run(&mut cmd); - t!(fs::remove_dir_all(&image)); + // Package save-analysis from stage1 if not doing a full bootstrap, as the + // stage2 artifacts is simply copied from stage1 in that case. + let compiler = if build.force_use_stage1(compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler.clone() + }; + + let name = pkgname(build, "rust-analysis"); + let image = tmpdir(build).join(format!("{}-{}-image", name, target)); + + let src = build.stage_out(&compiler, Mode::Libstd).join(target).join("release").join("deps"); + + let image_src = src.join("save-analysis"); + let dst = image.join("lib/rustlib").join(target).join("analysis"); + t!(fs::create_dir_all(&dst)); + println!("image_src: {:?}, dst: {:?}", image_src, dst); + cp_r(&image_src, &dst); + + let mut cmd = rust_installer(build); + cmd.arg("generate") + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=save-analysis-saved.") + .arg("--image-dir").arg(&image) + .arg("--work-dir").arg(&tmpdir(build)) + .arg("--output-dir").arg(&distdir(build)) + .arg(format!("--package-name={}-{}", name, target)) + .arg(format!("--component-name=rust-analysis-{}", target)) + .arg("--legacy-manifest-dirs=rustlib,cargo"); + build.run(&mut cmd); + t!(fs::remove_dir_all(&image)); + } } fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_dir: &Path) { @@ -582,69 +638,78 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di // .only_host_build(true) // .dep(move |s| tool_rust_installer(build, s)) // .run(move |_| dist::rust_src(build)); -/// Creates the `rust-src` installer component -pub fn rust_src(build: &Build) { - println!("Dist src"); - - let name = pkgname(build, "rust-src"); - let image = tmpdir(build).join(format!("{}-image", name)); - let _ = fs::remove_dir_all(&image); - let dst = image.join("lib/rustlib/src"); - let dst_src = dst.join("rust"); - t!(fs::create_dir_all(&dst_src)); - - // This is the reduced set of paths which will become the rust-src component - // (essentially libstd and all of its path dependencies) - let std_src_dirs = [ - "src/build_helper", - "src/liballoc", - "src/liballoc_jemalloc", - "src/liballoc_system", - "src/libbacktrace", - "src/libcollections", - "src/libcompiler_builtins", - "src/libcore", - "src/liblibc", - "src/libpanic_abort", - "src/libpanic_unwind", - "src/librand", - "src/librustc_asan", - "src/librustc_lsan", - "src/librustc_msan", - "src/librustc_tsan", - "src/libstd", - "src/libstd_unicode", - "src/libunwind", - "src/rustc/compiler_builtins_shim", - "src/rustc/libc_shim", - "src/libtest", - "src/libterm", - "src/jemalloc", - "src/libprofiler_builtins", - ]; - let std_src_dirs_exclude = [ - "src/compiler-rt/test", - "src/jemalloc/test/unit", - ]; - - copy_src_dirs(build, &std_src_dirs[..], &std_src_dirs_exclude[..], &dst_src); +#[derive(Serialize)] +pub struct Src; + +impl<'a> Step<'a> for Src { + type Output = (); + + /// Creates the `rust-src` installer component + fn run(self, builder: &Builder) { + let build = builder.build; + println!("Dist src"); + + let name = pkgname(build, "rust-src"); + let image = tmpdir(build).join(format!("{}-image", name)); + let _ = fs::remove_dir_all(&image); + + let dst = image.join("lib/rustlib/src"); + let dst_src = dst.join("rust"); + t!(fs::create_dir_all(&dst_src)); + + // This is the reduced set of paths which will become the rust-src component + // (essentially libstd and all of its path dependencies) + let std_src_dirs = [ + "src/build_helper", + "src/liballoc", + "src/liballoc_jemalloc", + "src/liballoc_system", + "src/libbacktrace", + "src/libcollections", + "src/libcompiler_builtins", + "src/libcore", + "src/liblibc", + "src/libpanic_abort", + "src/libpanic_unwind", + "src/librand", + "src/librustc_asan", + "src/librustc_lsan", + "src/librustc_msan", + "src/librustc_tsan", + "src/libstd", + "src/libstd_unicode", + "src/libunwind", + "src/rustc/compiler_builtins_shim", + "src/rustc/libc_shim", + "src/libtest", + "src/libterm", + "src/jemalloc", + "src/libprofiler_builtins", + ]; + let std_src_dirs_exclude = [ + "src/compiler-rt/test", + "src/jemalloc/test/unit", + ]; - // Create source tarball in rust-installer format - let mut cmd = rust_installer(build); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Awesome-Source.") - .arg("--image-dir").arg(&image) - .arg("--work-dir").arg(&tmpdir(build)) - .arg("--output-dir").arg(&distdir(build)) - .arg(format!("--package-name={}", name)) - .arg("--component-name=rust-src") - .arg("--legacy-manifest-dirs=rustlib,cargo"); - build.run(&mut cmd); + copy_src_dirs(build, &std_src_dirs[..], &std_src_dirs_exclude[..], &dst_src); + + // Create source tarball in rust-installer format + let mut cmd = rust_installer(build); + cmd.arg("generate") + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Awesome-Source.") + .arg("--image-dir").arg(&image) + .arg("--work-dir").arg(&tmpdir(build)) + .arg("--output-dir").arg(&distdir(build)) + .arg(format!("--package-name={}", name)) + .arg("--component-name=rust-src") + .arg("--legacy-manifest-dirs=rustlib,cargo"); + build.run(&mut cmd); - t!(fs::remove_dir_all(&image)); + t!(fs::remove_dir_all(&image)); + } } const CARGO_VENDOR_VERSION: &str = "0.1.4"; @@ -656,82 +721,91 @@ const CARGO_VENDOR_VERSION: &str = "0.1.4"; // .only_host_build(true) // .dep(move |s| tool_rust_installer(build, s)) // .run(move |_| dist::plain_source_tarball(build)); -/// Creates the plain source tarball -pub fn plain_source_tarball(build: &Build) { - println!("Create plain source tarball"); - - // Make sure that the root folder of tarball has the correct name - let plain_name = format!("{}-src", pkgname(build, "rustc")); - let plain_dst_src = tmpdir(build).join(&plain_name); - let _ = fs::remove_dir_all(&plain_dst_src); - t!(fs::create_dir_all(&plain_dst_src)); - - // This is the set of root paths which will become part of the source package - let src_files = [ - "COPYRIGHT", - "LICENSE-APACHE", - "LICENSE-MIT", - "CONTRIBUTING.md", - "README.md", - "RELEASES.md", - "configure", - "x.py", - ]; - let src_dirs = [ - "man", - "src", - ]; - - copy_src_dirs(build, &src_dirs[..], &[], &plain_dst_src); - // Copy the files normally - for item in &src_files { - copy(&build.src.join(item), &plain_dst_src.join(item)); - } +#[derive(Serialize)] +pub struct PlainSourceTarball; + +impl<'a> Step<'a> for PlainSourceTarball { + type Output = (); + + /// Creates the plain source tarball + fn run(self, builder: &Builder) { + let build = builder.build; + println!("Create plain source tarball"); + + // Make sure that the root folder of tarball has the correct name + let plain_name = format!("{}-src", pkgname(build, "rustc")); + let plain_dst_src = tmpdir(build).join(&plain_name); + let _ = fs::remove_dir_all(&plain_dst_src); + t!(fs::create_dir_all(&plain_dst_src)); + + // This is the set of root paths which will become part of the source package + let src_files = [ + "COPYRIGHT", + "LICENSE-APACHE", + "LICENSE-MIT", + "CONTRIBUTING.md", + "README.md", + "RELEASES.md", + "configure", + "x.py", + ]; + let src_dirs = [ + "man", + "src", + ]; - // Create the version file - write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes()); + copy_src_dirs(build, &src_dirs[..], &[], &plain_dst_src); - // If we're building from git sources, we need to vendor a complete distribution. - if build.rust_info.is_git() { - // Get cargo-vendor installed, if it isn't already. - let mut has_cargo_vendor = false; - let mut cmd = Command::new(&build.initial_cargo); - for line in output(cmd.arg("install").arg("--list")).lines() { - has_cargo_vendor |= line.starts_with("cargo-vendor "); + // Copy the files normally + for item in &src_files { + copy(&build.src.join(item), &plain_dst_src.join(item)); } - if !has_cargo_vendor { + + // Create the version file + write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes()); + + // If we're building from git sources, we need to vendor a complete distribution. + if build.rust_info.is_git() { + // Get cargo-vendor installed, if it isn't already. + let mut has_cargo_vendor = false; + let mut cmd = Command::new(&build.initial_cargo); + for line in output(cmd.arg("install").arg("--list")).lines() { + has_cargo_vendor |= line.starts_with("cargo-vendor "); + } + if !has_cargo_vendor { + let mut cmd = Command::new(&build.initial_cargo); + cmd.arg("install") + .arg("--force") + .arg("--debug") + .arg("--vers").arg(CARGO_VENDOR_VERSION) + .arg("cargo-vendor") + .env("RUSTC", &build.initial_rustc); + build.run(&mut cmd); + } + + // Vendor all Cargo dependencies let mut cmd = Command::new(&build.initial_cargo); - cmd.arg("install") - .arg("--force") - .arg("--debug") - .arg("--vers").arg(CARGO_VENDOR_VERSION) - .arg("cargo-vendor") - .env("RUSTC", &build.initial_rustc); + cmd.arg("vendor") + .current_dir(&plain_dst_src.join("src")); build.run(&mut cmd); } - // Vendor all Cargo dependencies - let mut cmd = Command::new(&build.initial_cargo); - cmd.arg("vendor") - .current_dir(&plain_dst_src.join("src")); + // Create plain source tarball + let mut tarball = rust_src_location(build); + tarball.set_extension(""); // strip .gz + tarball.set_extension(""); // strip .tar + if let Some(dir) = tarball.parent() { + t!(fs::create_dir_all(dir)); + } + let mut cmd = rust_installer(build); + cmd.arg("tarball") + .arg("--input").arg(&plain_name) + .arg("--output").arg(&tarball) + .arg("--work-dir=.") + .current_dir(tmpdir(build)); build.run(&mut cmd); } - - // Create plain source tarball - let mut tarball = rust_src_location(build); - tarball.set_extension(""); // strip .gz - tarball.set_extension(""); // strip .tar - if let Some(dir) = tarball.parent() { - t!(fs::create_dir_all(dir)); - } - let mut cmd = rust_installer(build); - cmd.arg("tarball") - .arg("--input").arg(&plain_name) - .arg("--output").arg(&tarball) - .arg("--work-dir=.") - .current_dir(tmpdir(build)); - build.run(&mut cmd); } fn install(src: &Path, dstdir: &Path, perms: u32) { @@ -779,64 +853,78 @@ fn write_file(path: &Path, data: &[u8]) { // .dep(|s| s.name("tool-cargo")) // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::cargo(build, s.stage, s.target)); -pub fn cargo(build: &Build, stage: u32, target: &str) { - println!("Dist cargo stage{} ({})", stage, target); - let compiler = Compiler::new(stage, &build.build); - - let src = build.src.join("src/tools/cargo"); - let etc = src.join("src/etc"); - let release_num = build.release_num("cargo"); - let name = pkgname(build, "cargo"); - let version = build.cargo_info.version(build, &release_num); - - let tmp = tmpdir(build); - let image = tmp.join("cargo-image"); - drop(fs::remove_dir_all(&image)); - t!(fs::create_dir_all(&image)); - - // Prepare the image directory - t!(fs::create_dir_all(image.join("share/zsh/site-functions"))); - t!(fs::create_dir_all(image.join("etc/bash_completion.d"))); - let cargo = build.cargo_out(&compiler, Mode::Tool, target) - .join(exe("cargo", target)); - install(&cargo, &image.join("bin"), 0o755); - for man in t!(etc.join("man").read_dir()) { - let man = t!(man); - install(&man.path(), &image.join("share/man/man1"), 0o644); + +#[derive(Serialize)] +pub struct Cargo<'a> { + stage: u32, + target: &'a str, +} + +impl<'a> Step<'a> for Cargo<'a> { + type Output = (); + + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let target = self.target; + println!("Dist cargo stage{} ({})", stage, target); + let compiler = Compiler::new(stage, &build.build); + + let src = build.src.join("src/tools/cargo"); + let etc = src.join("src/etc"); + let release_num = build.release_num("cargo"); + let name = pkgname(build, "cargo"); + let version = build.cargo_info.version(build, &release_num); + + let tmp = tmpdir(build); + let image = tmp.join("cargo-image"); + drop(fs::remove_dir_all(&image)); + t!(fs::create_dir_all(&image)); + + // Prepare the image directory + t!(fs::create_dir_all(image.join("share/zsh/site-functions"))); + t!(fs::create_dir_all(image.join("etc/bash_completion.d"))); + let cargo = build.cargo_out(&compiler, Mode::Tool, target) + .join(exe("cargo", target)); + install(&cargo, &image.join("bin"), 0o755); + for man in t!(etc.join("man").read_dir()) { + let man = t!(man); + install(&man.path(), &image.join("share/man/man1"), 0o644); + } + install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644); + copy(&etc.join("cargo.bashcomp.sh"), + &image.join("etc/bash_completion.d/cargo")); + let doc = image.join("share/doc/cargo"); + install(&src.join("README.md"), &doc, 0o644); + install(&src.join("LICENSE-MIT"), &doc, 0o644); + install(&src.join("LICENSE-APACHE"), &doc, 0o644); + install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644); + + // Prepare the overlay + let overlay = tmp.join("cargo-overlay"); + drop(fs::remove_dir_all(&overlay)); + t!(fs::create_dir_all(&overlay)); + install(&src.join("README.md"), &overlay, 0o644); + install(&src.join("LICENSE-MIT"), &overlay, 0o644); + install(&src.join("LICENSE-APACHE"), &overlay, 0o644); + install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644); + t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + + // Generate the installer tarball + let mut cmd = rust_installer(build); + cmd.arg("generate") + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Rust-is-ready-to-roll.") + .arg("--image-dir").arg(&image) + .arg("--work-dir").arg(&tmpdir(build)) + .arg("--output-dir").arg(&distdir(build)) + .arg("--non-installed-overlay").arg(&overlay) + .arg(format!("--package-name={}-{}", name, target)) + .arg("--component-name=cargo") + .arg("--legacy-manifest-dirs=rustlib,cargo"); + build.run(&mut cmd); } - install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644); - copy(&etc.join("cargo.bashcomp.sh"), - &image.join("etc/bash_completion.d/cargo")); - let doc = image.join("share/doc/cargo"); - install(&src.join("README.md"), &doc, 0o644); - install(&src.join("LICENSE-MIT"), &doc, 0o644); - install(&src.join("LICENSE-APACHE"), &doc, 0o644); - install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644); - - // Prepare the overlay - let overlay = tmp.join("cargo-overlay"); - drop(fs::remove_dir_all(&overlay)); - t!(fs::create_dir_all(&overlay)); - install(&src.join("README.md"), &overlay, 0o644); - install(&src.join("LICENSE-MIT"), &overlay, 0o644); - install(&src.join("LICENSE-APACHE"), &overlay, 0o644); - install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644); - t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); - - // Generate the installer tarball - let mut cmd = rust_installer(build); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rust-is-ready-to-roll.") - .arg("--image-dir").arg(&image) - .arg("--work-dir").arg(&tmpdir(build)) - .arg("--output-dir").arg(&distdir(build)) - .arg("--non-installed-overlay").arg(&overlay) - .arg(format!("--package-name={}-{}", name, target)) - .arg("--component-name=cargo") - .arg("--legacy-manifest-dirs=rustlib,cargo"); - build.run(&mut cmd); } // rules.dist("dist-rls", "rls") @@ -845,53 +933,66 @@ pub fn cargo(build: &Build, stage: u32, target: &str) { // .dep(|s| s.name("tool-rls")) // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::rls(build, s.stage, s.target)); -pub fn rls(build: &Build, stage: u32, target: &str) { - assert!(build.config.extended); - println!("Dist RLS stage{} ({})", stage, target); - let compiler = Compiler::new(stage, &build.build); - - let src = build.src.join("src/tools/rls"); - let release_num = build.release_num("rls"); - let name = pkgname(build, "rls"); - let version = build.rls_info.version(build, &release_num); - - let tmp = tmpdir(build); - let image = tmp.join("rls-image"); - drop(fs::remove_dir_all(&image)); - t!(fs::create_dir_all(&image)); - - // Prepare the image directory - let rls = build.cargo_out(&compiler, Mode::Tool, target) - .join(exe("rls", target)); - install(&rls, &image.join("bin"), 0o755); - let doc = image.join("share/doc/rls"); - install(&src.join("README.md"), &doc, 0o644); - install(&src.join("LICENSE-MIT"), &doc, 0o644); - install(&src.join("LICENSE-APACHE"), &doc, 0o644); - - // Prepare the overlay - let overlay = tmp.join("rls-overlay"); - drop(fs::remove_dir_all(&overlay)); - t!(fs::create_dir_all(&overlay)); - install(&src.join("README.md"), &overlay, 0o644); - install(&src.join("LICENSE-MIT"), &overlay, 0o644); - install(&src.join("LICENSE-APACHE"), &overlay, 0o644); - t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); - - // Generate the installer tarball - let mut cmd = rust_installer(build); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=RLS-ready-to-serve.") - .arg("--image-dir").arg(&image) - .arg("--work-dir").arg(&tmpdir(build)) - .arg("--output-dir").arg(&distdir(build)) - .arg("--non-installed-overlay").arg(&overlay) - .arg(format!("--package-name={}-{}", name, target)) - .arg("--component-name=rls") - .arg("--legacy-manifest-dirs=rustlib,cargo"); - build.run(&mut cmd); +#[derive(Serialize)] +pub struct Rls<'a> { + stage: u32, + target: &'a str, +} + +impl<'a> Step<'a> for Rls<'a> { + type Output = (); + + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let target = self.target; + assert!(build.config.extended); + println!("Dist RLS stage{} ({})", stage, target); + let compiler = Compiler::new(stage, &build.build); + + let src = build.src.join("src/tools/rls"); + let release_num = build.release_num("rls"); + let name = pkgname(build, "rls"); + let version = build.rls_info.version(build, &release_num); + + let tmp = tmpdir(build); + let image = tmp.join("rls-image"); + drop(fs::remove_dir_all(&image)); + t!(fs::create_dir_all(&image)); + + // Prepare the image directory + let rls = build.cargo_out(&compiler, Mode::Tool, target) + .join(exe("rls", target)); + install(&rls, &image.join("bin"), 0o755); + let doc = image.join("share/doc/rls"); + install(&src.join("README.md"), &doc, 0o644); + install(&src.join("LICENSE-MIT"), &doc, 0o644); + install(&src.join("LICENSE-APACHE"), &doc, 0o644); + + // Prepare the overlay + let overlay = tmp.join("rls-overlay"); + drop(fs::remove_dir_all(&overlay)); + t!(fs::create_dir_all(&overlay)); + install(&src.join("README.md"), &overlay, 0o644); + install(&src.join("LICENSE-MIT"), &overlay, 0o644); + install(&src.join("LICENSE-APACHE"), &overlay, 0o644); + t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + + // Generate the installer tarball + let mut cmd = rust_installer(build); + cmd.arg("generate") + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=RLS-ready-to-serve.") + .arg("--image-dir").arg(&image) + .arg("--work-dir").arg(&tmpdir(build)) + .arg("--output-dir").arg(&distdir(build)) + .arg("--non-installed-overlay").arg(&overlay) + .arg(format!("--package-name={}-{}", name, target)) + .arg("--component-name=rls") + .arg("--legacy-manifest-dirs=rustlib,cargo"); + build.run(&mut cmd); + } } // rules.dist("dist-extended", "extended") @@ -908,358 +1009,372 @@ pub fn rls(build: &Build, stage: u32, target: &str) { // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::extended(build, s.stage, s.target)); -/// Creates a combined installer for the specified target in the provided stage. -pub fn extended(build: &Build, stage: u32, target: &str) { - println!("Dist extended stage{} ({})", stage, target); - - let dist = distdir(build); - let rustc_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "rustc"), - target)); - let cargo_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "cargo"), - target)); - let rls_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "rls"), - target)); - let analysis_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "rust-analysis"), - target)); - let docs_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "rust-docs"), - target)); - let mingw_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "rust-mingw"), - target)); - let std_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "rust-std"), - target)); - - let tmp = tmpdir(build); - let overlay = tmp.join("extended-overlay"); - let etc = build.src.join("src/etc/installer"); - let work = tmp.join("work"); - - let _ = fs::remove_dir_all(&overlay); - install(&build.src.join("COPYRIGHT"), &overlay, 0o644); - install(&build.src.join("LICENSE-APACHE"), &overlay, 0o644); - install(&build.src.join("LICENSE-MIT"), &overlay, 0o644); - let version = build.rust_version(); - t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); - install(&etc.join("README.md"), &overlay, 0o644); - - // When rust-std package split from rustc, we needed to ensure that during - // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering - // the std files during uninstall. To do this ensure that rustc comes - // before rust-std in the list below. - let mut tarballs = vec![rustc_installer, cargo_installer, rls_installer, - analysis_installer, docs_installer, std_installer]; - if target.contains("pc-windows-gnu") { - tarballs.push(mingw_installer); - } - let mut input_tarballs = tarballs[0].as_os_str().to_owned(); - for tarball in &tarballs[1..] { - input_tarballs.push(","); - input_tarballs.push(tarball); - } +#[derive(Serialize)] +pub struct Extended<'a> { + stage: u32, + target: &'a str, +} - let mut cmd = rust_installer(build); - cmd.arg("combine") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rust-is-ready-to-roll.") - .arg("--work-dir").arg(&work) - .arg("--output-dir").arg(&distdir(build)) - .arg(format!("--package-name={}-{}", pkgname(build, "rust"), target)) - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--input-tarballs").arg(input_tarballs) - .arg("--non-installed-overlay").arg(&overlay); - build.run(&mut cmd); +impl<'a> Step<'a> for Extended<'a> { + type Output = (); + + /// Creates a combined installer for the specified target in the provided stage. + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let target = self.target; + + println!("Dist extended stage{} ({})", stage, target); + + let dist = distdir(build); + let rustc_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rustc"), + target)); + let cargo_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "cargo"), + target)); + let rls_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rls"), + target)); + let analysis_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rust-analysis"), + target)); + let docs_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rust-docs"), + target)); + let mingw_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rust-mingw"), + target)); + let std_installer = dist.join(format!("{}-{}.tar.gz", + pkgname(build, "rust-std"), + target)); + + let tmp = tmpdir(build); + let overlay = tmp.join("extended-overlay"); + let etc = build.src.join("src/etc/installer"); + let work = tmp.join("work"); + + let _ = fs::remove_dir_all(&overlay); + install(&build.src.join("COPYRIGHT"), &overlay, 0o644); + install(&build.src.join("LICENSE-APACHE"), &overlay, 0o644); + install(&build.src.join("LICENSE-MIT"), &overlay, 0o644); + let version = build.rust_version(); + t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + install(&etc.join("README.md"), &overlay, 0o644); + + // When rust-std package split from rustc, we needed to ensure that during + // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering + // the std files during uninstall. To do this ensure that rustc comes + // before rust-std in the list below. + let mut tarballs = vec![rustc_installer, cargo_installer, rls_installer, + analysis_installer, docs_installer, std_installer]; + if target.contains("pc-windows-gnu") { + tarballs.push(mingw_installer); + } + let mut input_tarballs = tarballs[0].as_os_str().to_owned(); + for tarball in &tarballs[1..] { + input_tarballs.push(","); + input_tarballs.push(tarball); + } - let mut license = String::new(); - t!(t!(File::open(build.src.join("COPYRIGHT"))).read_to_string(&mut license)); - license.push_str("\n"); - t!(t!(File::open(build.src.join("LICENSE-APACHE"))).read_to_string(&mut license)); - license.push_str("\n"); - t!(t!(File::open(build.src.join("LICENSE-MIT"))).read_to_string(&mut license)); - - let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18"; - let mut rtf = rtf.to_string(); - rtf.push_str("\n"); - for line in license.lines() { - rtf.push_str(line); - rtf.push_str("\\line "); - } - rtf.push_str("}"); - - if target.contains("apple-darwin") { - let pkg = tmp.join("pkg"); - let _ = fs::remove_dir_all(&pkg); - t!(fs::create_dir_all(pkg.join("rustc"))); - t!(fs::create_dir_all(pkg.join("cargo"))); - t!(fs::create_dir_all(pkg.join("rust-docs"))); - t!(fs::create_dir_all(pkg.join("rust-std"))); - t!(fs::create_dir_all(pkg.join("rls"))); - t!(fs::create_dir_all(pkg.join("rust-analysis"))); - - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target)), - &pkg.join("rustc")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "cargo"), target)), - &pkg.join("cargo")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target)), - &pkg.join("rust-docs")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)), - &pkg.join("rust-std")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target)), - &pkg.join("rls")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target)), - &pkg.join("rust-analysis")); - - install(&etc.join("pkg/postinstall"), &pkg.join("rustc"), 0o755); - install(&etc.join("pkg/postinstall"), &pkg.join("cargo"), 0o755); - install(&etc.join("pkg/postinstall"), &pkg.join("rust-docs"), 0o755); - install(&etc.join("pkg/postinstall"), &pkg.join("rust-std"), 0o755); - install(&etc.join("pkg/postinstall"), &pkg.join("rls"), 0o755); - install(&etc.join("pkg/postinstall"), &pkg.join("rust-analysis"), 0o755); - - let pkgbuild = |component: &str| { - let mut cmd = Command::new("pkgbuild"); - cmd.arg("--identifier").arg(format!("org.rust-lang.{}", component)) - .arg("--scripts").arg(pkg.join(component)) - .arg("--nopayload") - .arg(pkg.join(component).with_extension("pkg")); - build.run(&mut cmd); - }; - pkgbuild("rustc"); - pkgbuild("cargo"); - pkgbuild("rust-docs"); - pkgbuild("rust-std"); - pkgbuild("rls"); - pkgbuild("rust-analysis"); - - // create an 'uninstall' package - install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755); - pkgbuild("uninstall"); - - t!(fs::create_dir_all(pkg.join("res"))); - t!(t!(File::create(pkg.join("res/LICENSE.txt"))).write_all(license.as_bytes())); - install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644); - let mut cmd = Command::new("productbuild"); - cmd.arg("--distribution").arg(etc.join("pkg/Distribution.xml")) - .arg("--resources").arg(pkg.join("res")) - .arg(distdir(build).join(format!("{}-{}.pkg", - pkgname(build, "rust"), - target))) - .arg("--package-path").arg(&pkg); + let mut cmd = rust_installer(build); + cmd.arg("combine") + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Rust-is-ready-to-roll.") + .arg("--work-dir").arg(&work) + .arg("--output-dir").arg(&distdir(build)) + .arg(format!("--package-name={}-{}", pkgname(build, "rust"), target)) + .arg("--legacy-manifest-dirs=rustlib,cargo") + .arg("--input-tarballs").arg(input_tarballs) + .arg("--non-installed-overlay").arg(&overlay); build.run(&mut cmd); - } - if target.contains("windows") { - let exe = tmp.join("exe"); - let _ = fs::remove_dir_all(&exe); - t!(fs::create_dir_all(exe.join("rustc"))); - t!(fs::create_dir_all(exe.join("cargo"))); - t!(fs::create_dir_all(exe.join("rls"))); - t!(fs::create_dir_all(exe.join("rust-analysis"))); - t!(fs::create_dir_all(exe.join("rust-docs"))); - t!(fs::create_dir_all(exe.join("rust-std"))); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target)) - .join("rustc"), - &exe.join("rustc")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "cargo"), target)) - .join("cargo"), - &exe.join("cargo")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target)) - .join("rust-docs"), - &exe.join("rust-docs")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)) - .join(format!("rust-std-{}", target)), - &exe.join("rust-std")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target)) - .join("rls"), - &exe.join("rls")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target)) - .join(format!("rust-analysis-{}", target)), - &exe.join("rust-analysis")); - - t!(fs::remove_file(exe.join("rustc/manifest.in"))); - t!(fs::remove_file(exe.join("cargo/manifest.in"))); - t!(fs::remove_file(exe.join("rust-docs/manifest.in"))); - t!(fs::remove_file(exe.join("rust-std/manifest.in"))); - t!(fs::remove_file(exe.join("rls/manifest.in"))); - t!(fs::remove_file(exe.join("rust-analysis/manifest.in"))); - - if target.contains("windows-gnu") { - t!(fs::create_dir_all(exe.join("rust-mingw"))); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-mingw"), target)) - .join("rust-mingw"), - &exe.join("rust-mingw")); - t!(fs::remove_file(exe.join("rust-mingw/manifest.in"))); + let mut license = String::new(); + t!(t!(File::open(build.src.join("COPYRIGHT"))).read_to_string(&mut license)); + license.push_str("\n"); + t!(t!(File::open(build.src.join("LICENSE-APACHE"))).read_to_string(&mut license)); + license.push_str("\n"); + t!(t!(File::open(build.src.join("LICENSE-MIT"))).read_to_string(&mut license)); + + let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18"; + let mut rtf = rtf.to_string(); + rtf.push_str("\n"); + for line in license.lines() { + rtf.push_str(line); + rtf.push_str("\\line "); } - - install(&etc.join("exe/rust.iss"), &exe, 0o644); - install(&etc.join("exe/modpath.iss"), &exe, 0o644); - install(&etc.join("exe/upgrade.iss"), &exe, 0o644); - install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644); - t!(t!(File::create(exe.join("LICENSE.txt"))).write_all(license.as_bytes())); - - // Generate exe installer - let mut cmd = Command::new("iscc"); - cmd.arg("rust.iss") - .current_dir(&exe); - if target.contains("windows-gnu") { - cmd.arg("/dMINGW"); + rtf.push_str("}"); + + if target.contains("apple-darwin") { + let pkg = tmp.join("pkg"); + let _ = fs::remove_dir_all(&pkg); + t!(fs::create_dir_all(pkg.join("rustc"))); + t!(fs::create_dir_all(pkg.join("cargo"))); + t!(fs::create_dir_all(pkg.join("rust-docs"))); + t!(fs::create_dir_all(pkg.join("rust-std"))); + t!(fs::create_dir_all(pkg.join("rls"))); + t!(fs::create_dir_all(pkg.join("rust-analysis"))); + + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target)), + &pkg.join("rustc")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "cargo"), target)), + &pkg.join("cargo")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target)), + &pkg.join("rust-docs")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)), + &pkg.join("rust-std")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target)), + &pkg.join("rls")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target)), + &pkg.join("rust-analysis")); + + install(&etc.join("pkg/postinstall"), &pkg.join("rustc"), 0o755); + install(&etc.join("pkg/postinstall"), &pkg.join("cargo"), 0o755); + install(&etc.join("pkg/postinstall"), &pkg.join("rust-docs"), 0o755); + install(&etc.join("pkg/postinstall"), &pkg.join("rust-std"), 0o755); + install(&etc.join("pkg/postinstall"), &pkg.join("rls"), 0o755); + install(&etc.join("pkg/postinstall"), &pkg.join("rust-analysis"), 0o755); + + let pkgbuild = |component: &str| { + let mut cmd = Command::new("pkgbuild"); + cmd.arg("--identifier").arg(format!("org.rust-lang.{}", component)) + .arg("--scripts").arg(pkg.join(component)) + .arg("--nopayload") + .arg(pkg.join(component).with_extension("pkg")); + build.run(&mut cmd); + }; + pkgbuild("rustc"); + pkgbuild("cargo"); + pkgbuild("rust-docs"); + pkgbuild("rust-std"); + pkgbuild("rls"); + pkgbuild("rust-analysis"); + + // create an 'uninstall' package + install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755); + pkgbuild("uninstall"); + + t!(fs::create_dir_all(pkg.join("res"))); + t!(t!(File::create(pkg.join("res/LICENSE.txt"))).write_all(license.as_bytes())); + install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644); + let mut cmd = Command::new("productbuild"); + cmd.arg("--distribution").arg(etc.join("pkg/Distribution.xml")) + .arg("--resources").arg(pkg.join("res")) + .arg(distdir(build).join(format!("{}-{}.pkg", + pkgname(build, "rust"), + target))) + .arg("--package-path").arg(&pkg); + build.run(&mut cmd); } - add_env(build, &mut cmd, target); - build.run(&mut cmd); - install(&exe.join(format!("{}-{}.exe", pkgname(build, "rust"), target)), - &distdir(build), - 0o755); - // Generate msi installer - let wix = PathBuf::from(env::var_os("WIX").unwrap()); - let heat = wix.join("bin/heat.exe"); - let candle = wix.join("bin/candle.exe"); - let light = wix.join("bin/light.exe"); - - let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"]; - build.run(Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("rustc") - .args(&heat_flags) - .arg("-cg").arg("RustcGroup") - .arg("-dr").arg("Rustc") - .arg("-var").arg("var.RustcDir") - .arg("-out").arg(exe.join("RustcGroup.wxs"))); - build.run(Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("rust-docs") - .args(&heat_flags) - .arg("-cg").arg("DocsGroup") - .arg("-dr").arg("Docs") - .arg("-var").arg("var.DocsDir") - .arg("-out").arg(exe.join("DocsGroup.wxs")) - .arg("-t").arg(etc.join("msi/squash-components.xsl"))); - build.run(Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("cargo") - .args(&heat_flags) - .arg("-cg").arg("CargoGroup") - .arg("-dr").arg("Cargo") - .arg("-var").arg("var.CargoDir") - .arg("-out").arg(exe.join("CargoGroup.wxs")) - .arg("-t").arg(etc.join("msi/remove-duplicates.xsl"))); - build.run(Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("rust-std") - .args(&heat_flags) - .arg("-cg").arg("StdGroup") - .arg("-dr").arg("Std") - .arg("-var").arg("var.StdDir") - .arg("-out").arg(exe.join("StdGroup.wxs"))); - build.run(Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("rls") - .args(&heat_flags) - .arg("-cg").arg("RlsGroup") - .arg("-dr").arg("Rls") - .arg("-var").arg("var.RlsDir") - .arg("-out").arg(exe.join("RlsGroup.wxs")) - .arg("-t").arg(etc.join("msi/remove-duplicates.xsl"))); - build.run(Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("rust-analysis") - .args(&heat_flags) - .arg("-cg").arg("AnalysisGroup") - .arg("-dr").arg("Analysis") - .arg("-var").arg("var.AnalysisDir") - .arg("-out").arg(exe.join("AnalysisGroup.wxs")) - .arg("-t").arg(etc.join("msi/remove-duplicates.xsl"))); - if target.contains("windows-gnu") { + if target.contains("windows") { + let exe = tmp.join("exe"); + let _ = fs::remove_dir_all(&exe); + t!(fs::create_dir_all(exe.join("rustc"))); + t!(fs::create_dir_all(exe.join("cargo"))); + t!(fs::create_dir_all(exe.join("rls"))); + t!(fs::create_dir_all(exe.join("rust-analysis"))); + t!(fs::create_dir_all(exe.join("rust-docs"))); + t!(fs::create_dir_all(exe.join("rust-std"))); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target)) + .join("rustc"), + &exe.join("rustc")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "cargo"), target)) + .join("cargo"), + &exe.join("cargo")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target)) + .join("rust-docs"), + &exe.join("rust-docs")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)) + .join(format!("rust-std-{}", target)), + &exe.join("rust-std")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target)) + .join("rls"), + &exe.join("rls")); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target)) + .join(format!("rust-analysis-{}", target)), + &exe.join("rust-analysis")); + + t!(fs::remove_file(exe.join("rustc/manifest.in"))); + t!(fs::remove_file(exe.join("cargo/manifest.in"))); + t!(fs::remove_file(exe.join("rust-docs/manifest.in"))); + t!(fs::remove_file(exe.join("rust-std/manifest.in"))); + t!(fs::remove_file(exe.join("rls/manifest.in"))); + t!(fs::remove_file(exe.join("rust-analysis/manifest.in"))); + + if target.contains("windows-gnu") { + t!(fs::create_dir_all(exe.join("rust-mingw"))); + cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-mingw"), target)) + .join("rust-mingw"), + &exe.join("rust-mingw")); + t!(fs::remove_file(exe.join("rust-mingw/manifest.in"))); + } + + install(&etc.join("exe/rust.iss"), &exe, 0o644); + install(&etc.join("exe/modpath.iss"), &exe, 0o644); + install(&etc.join("exe/upgrade.iss"), &exe, 0o644); + install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644); + t!(t!(File::create(exe.join("LICENSE.txt"))).write_all(license.as_bytes())); + + // Generate exe installer + let mut cmd = Command::new("iscc"); + cmd.arg("rust.iss") + .current_dir(&exe); + if target.contains("windows-gnu") { + cmd.arg("/dMINGW"); + } + add_env(build, &mut cmd, target); + build.run(&mut cmd); + install(&exe.join(format!("{}-{}.exe", pkgname(build, "rust"), target)), + &distdir(build), + 0o755); + + // Generate msi installer + let wix = PathBuf::from(env::var_os("WIX").unwrap()); + let heat = wix.join("bin/heat.exe"); + let candle = wix.join("bin/candle.exe"); + let light = wix.join("bin/light.exe"); + + let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"]; build.run(Command::new(&heat) .current_dir(&exe) .arg("dir") - .arg("rust-mingw") + .arg("rustc") .args(&heat_flags) - .arg("-cg").arg("GccGroup") - .arg("-dr").arg("Gcc") - .arg("-var").arg("var.GccDir") - .arg("-out").arg(exe.join("GccGroup.wxs"))); - } + .arg("-cg").arg("RustcGroup") + .arg("-dr").arg("Rustc") + .arg("-var").arg("var.RustcDir") + .arg("-out").arg(exe.join("RustcGroup.wxs"))); + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-docs") + .args(&heat_flags) + .arg("-cg").arg("DocsGroup") + .arg("-dr").arg("Docs") + .arg("-var").arg("var.DocsDir") + .arg("-out").arg(exe.join("DocsGroup.wxs")) + .arg("-t").arg(etc.join("msi/squash-components.xsl"))); + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("cargo") + .args(&heat_flags) + .arg("-cg").arg("CargoGroup") + .arg("-dr").arg("Cargo") + .arg("-var").arg("var.CargoDir") + .arg("-out").arg(exe.join("CargoGroup.wxs")) + .arg("-t").arg(etc.join("msi/remove-duplicates.xsl"))); + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-std") + .args(&heat_flags) + .arg("-cg").arg("StdGroup") + .arg("-dr").arg("Std") + .arg("-var").arg("var.StdDir") + .arg("-out").arg(exe.join("StdGroup.wxs"))); + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rls") + .args(&heat_flags) + .arg("-cg").arg("RlsGroup") + .arg("-dr").arg("Rls") + .arg("-var").arg("var.RlsDir") + .arg("-out").arg(exe.join("RlsGroup.wxs")) + .arg("-t").arg(etc.join("msi/remove-duplicates.xsl"))); + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-analysis") + .args(&heat_flags) + .arg("-cg").arg("AnalysisGroup") + .arg("-dr").arg("Analysis") + .arg("-var").arg("var.AnalysisDir") + .arg("-out").arg(exe.join("AnalysisGroup.wxs")) + .arg("-t").arg(etc.join("msi/remove-duplicates.xsl"))); + if target.contains("windows-gnu") { + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-mingw") + .args(&heat_flags) + .arg("-cg").arg("GccGroup") + .arg("-dr").arg("Gcc") + .arg("-var").arg("var.GccDir") + .arg("-out").arg(exe.join("GccGroup.wxs"))); + } - let candle = |input: &Path| { - let output = exe.join(input.file_stem().unwrap()) - .with_extension("wixobj"); - let arch = if target.contains("x86_64") {"x64"} else {"x86"}; - let mut cmd = Command::new(&candle); - cmd.current_dir(&exe) - .arg("-nologo") - .arg("-dRustcDir=rustc") - .arg("-dDocsDir=rust-docs") - .arg("-dCargoDir=cargo") - .arg("-dStdDir=rust-std") - .arg("-dRlsDir=rls") - .arg("-dAnalysisDir=rust-analysis") - .arg("-arch").arg(&arch) - .arg("-out").arg(&output) - .arg(&input); - add_env(build, &mut cmd, target); + let candle = |input: &Path| { + let output = exe.join(input.file_stem().unwrap()) + .with_extension("wixobj"); + let arch = if target.contains("x86_64") {"x64"} else {"x86"}; + let mut cmd = Command::new(&candle); + cmd.current_dir(&exe) + .arg("-nologo") + .arg("-dRustcDir=rustc") + .arg("-dDocsDir=rust-docs") + .arg("-dCargoDir=cargo") + .arg("-dStdDir=rust-std") + .arg("-dRlsDir=rls") + .arg("-dAnalysisDir=rust-analysis") + .arg("-arch").arg(&arch) + .arg("-out").arg(&output) + .arg(&input); + add_env(build, &mut cmd, target); + + if target.contains("windows-gnu") { + cmd.arg("-dGccDir=rust-mingw"); + } + build.run(&mut cmd); + }; + candle(&etc.join("msi/rust.wxs")); + candle(&etc.join("msi/ui.wxs")); + candle(&etc.join("msi/rustwelcomedlg.wxs")); + candle("RustcGroup.wxs".as_ref()); + candle("DocsGroup.wxs".as_ref()); + candle("CargoGroup.wxs".as_ref()); + candle("StdGroup.wxs".as_ref()); + candle("RlsGroup.wxs".as_ref()); + candle("AnalysisGroup.wxs".as_ref()); if target.contains("windows-gnu") { - cmd.arg("-dGccDir=rust-mingw"); + candle("GccGroup.wxs".as_ref()); } - build.run(&mut cmd); - }; - candle(&etc.join("msi/rust.wxs")); - candle(&etc.join("msi/ui.wxs")); - candle(&etc.join("msi/rustwelcomedlg.wxs")); - candle("RustcGroup.wxs".as_ref()); - candle("DocsGroup.wxs".as_ref()); - candle("CargoGroup.wxs".as_ref()); - candle("StdGroup.wxs".as_ref()); - candle("RlsGroup.wxs".as_ref()); - candle("AnalysisGroup.wxs".as_ref()); - - if target.contains("windows-gnu") { - candle("GccGroup.wxs".as_ref()); - } - t!(t!(File::create(exe.join("LICENSE.rtf"))).write_all(rtf.as_bytes())); - install(&etc.join("gfx/banner.bmp"), &exe, 0o644); - install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644); - - let filename = format!("{}-{}.msi", pkgname(build, "rust"), target); - let mut cmd = Command::new(&light); - cmd.arg("-nologo") - .arg("-ext").arg("WixUIExtension") - .arg("-ext").arg("WixUtilExtension") - .arg("-out").arg(exe.join(&filename)) - .arg("rust.wixobj") - .arg("ui.wixobj") - .arg("rustwelcomedlg.wixobj") - .arg("RustcGroup.wixobj") - .arg("DocsGroup.wixobj") - .arg("CargoGroup.wixobj") - .arg("StdGroup.wixobj") - .arg("RlsGroup.wixobj") - .arg("AnalysisGroup.wixobj") - .current_dir(&exe); - - if target.contains("windows-gnu") { - cmd.arg("GccGroup.wixobj"); - } - // ICE57 wrongly complains about the shortcuts - cmd.arg("-sice:ICE57"); + t!(t!(File::create(exe.join("LICENSE.rtf"))).write_all(rtf.as_bytes())); + install(&etc.join("gfx/banner.bmp"), &exe, 0o644); + install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644); + + let filename = format!("{}-{}.msi", pkgname(build, "rust"), target); + let mut cmd = Command::new(&light); + cmd.arg("-nologo") + .arg("-ext").arg("WixUIExtension") + .arg("-ext").arg("WixUtilExtension") + .arg("-out").arg(exe.join(&filename)) + .arg("rust.wixobj") + .arg("ui.wixobj") + .arg("rustwelcomedlg.wixobj") + .arg("RustcGroup.wixobj") + .arg("DocsGroup.wixobj") + .arg("CargoGroup.wixobj") + .arg("StdGroup.wixobj") + .arg("RlsGroup.wixobj") + .arg("AnalysisGroup.wixobj") + .current_dir(&exe); - build.run(&mut cmd); + if target.contains("windows-gnu") { + cmd.arg("GccGroup.wixobj"); + } + // ICE57 wrongly complains about the shortcuts + cmd.arg("-sice:ICE57"); + + build.run(&mut cmd); - t!(fs::rename(exe.join(&filename), distdir(build).join(&filename))); + t!(fs::rename(exe.join(&filename), distdir(build).join(&filename))); + } } } @@ -1299,36 +1414,44 @@ fn add_env(build: &Build, cmd: &mut Command, target: &str) { // .only_host_build(true) // .dep(move |s| s.name("tool-build-manifest").target(&build.build).stage(0)) // .run(move |_| dist::hash_and_sign(build)); -// -pub fn hash_and_sign(build: &Build) { - let compiler = Compiler::new(0, &build.build); - let mut cmd = build.tool_cmd(&compiler, "build-manifest"); - let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| { - panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n") - }); - let addr = build.config.dist_upload_addr.as_ref().unwrap_or_else(|| { - panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n") - }); - let file = build.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| { - panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n") - }); - let mut pass = String::new(); - t!(t!(File::open(&file)).read_to_string(&mut pass)); - - let today = output(Command::new("date").arg("+%Y-%m-%d")); - - cmd.arg(sign); - cmd.arg(distdir(build)); - cmd.arg(today.trim()); - cmd.arg(build.rust_package_vers()); - cmd.arg(build.package_vers(&build.release_num("cargo"))); - cmd.arg(build.package_vers(&build.release_num("rls"))); - cmd.arg(addr); - - t!(fs::create_dir_all(distdir(build))); - - let mut child = t!(cmd.stdin(Stdio::piped()).spawn()); - t!(child.stdin.take().unwrap().write_all(pass.as_bytes())); - let status = t!(child.wait()); - assert!(status.success()); + +#[derive(Serialize)] +pub struct HashSign; + +impl<'a> Step<'a> for HashSign { + type Output = (); + + fn run(self, builder: &Builder) { + let build = builder.build; + let compiler = Compiler::new(0, &build.build); + let mut cmd = build.tool_cmd(&compiler, "build-manifest"); + let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| { + panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n") + }); + let addr = build.config.dist_upload_addr.as_ref().unwrap_or_else(|| { + panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n") + }); + let file = build.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| { + panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n") + }); + let mut pass = String::new(); + t!(t!(File::open(&file)).read_to_string(&mut pass)); + + let today = output(Command::new("date").arg("+%Y-%m-%d")); + + cmd.arg(sign); + cmd.arg(distdir(build)); + cmd.arg(today.trim()); + cmd.arg(build.rust_package_vers()); + cmd.arg(build.package_vers(&build.release_num("cargo"))); + cmd.arg(build.package_vers(&build.release_num("rls"))); + cmd.arg(addr); + + t!(fs::create_dir_all(distdir(build))); + + let mut child = t!(cmd.stdin(Stdio::piped()).spawn()); + t!(child.stdin.take().unwrap().write_all(pass.as_bytes())); + let status = t!(child.wait()); + assert!(status.success()); + } } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 432fdb6a3cb8c..466d63a15acbd 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -45,13 +45,27 @@ use build_helper::up_to_date; // }) // .default(build.config.docs) // .run(move |s| doc::rustbook(build, s.target, "reference")); -/// Invoke `rustbook` for `target` for the doc book `name`. -/// -/// This will not actually generate any documentation if the documentation has -/// already been generated. -pub fn rustbook(build: &Build, target: &str, name: &str) { - let src = build.src.join("src/doc"); - rustbook_src(build, target, name, &src); + +#[derive(Serialize)] +pub struct Rustbook<'a> { + target: &'a str, + name: &'a str, +} + +impl<'a> Step<'a> for Rustbook<'a> { + type Output = (); + + /// Invoke `rustbook` for `target` for the doc book `name`. + /// + /// This will not actually generate any documentation if the documentation has + /// already been generated. + fn run(self, builder: &Builder) { + let build = builder.build; + let target = self.target; + let name = self.name; + let src = build.src.join("src/doc"); + rustbook_src(build, target, name, &src); + } } //rules.doc("doc-unstable-book", "src/doc/unstable-book") @@ -68,30 +82,44 @@ pub fn rustbook(build: &Build, target: &str, name: &str) { // "unstable-book", // &build.md_doc_out(s.target))); +#[derive(Serialize)] +pub struct RustbookSrc<'a> { + target: &'a str, + name: &'a str, + src: &'a Path, +} -/// Invoke `rustbook` for `target` for the doc book `name` from the `src` path. -/// -/// This will not actually generate any documentation if the documentation has -/// already been generated. -pub fn rustbook_src(build: &Build, target: &str, name: &str, src: &Path) { - let out = build.doc_out(target); - t!(fs::create_dir_all(&out)); - - let out = out.join(name); - let compiler = Compiler::new(0, &build.build); - let src = src.join(name); - let index = out.join("index.html"); - let rustbook = build.tool(&compiler, "rustbook"); - if up_to_date(&src, &index) && up_to_date(&rustbook, &index) { - return +impl<'a> Step<'a> for RustbookSrc<'a> { + type Output = (); + + /// Invoke `rustbook` for `target` for the doc book `name` from the `src` path. + /// + /// This will not actually generate any documentation if the documentation has + /// already been generated. + fn run(self, builder: &Builder) { + let build = builder.build; + let target = self.target; + let name = self.name; + let src = self.src; + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); + + let out = out.join(name); + let compiler = Compiler::new(0, &build.build); + let src = src.join(name); + let index = out.join("index.html"); + let rustbook = build.tool(&compiler, "rustbook"); + if up_to_date(&src, &index) && up_to_date(&rustbook, &index) { + return + } + println!("Rustbook ({}) - {}", target, name); + let _ = fs::remove_dir_all(&out); + build.run(build.tool_cmd(&compiler, "rustbook") + .arg("build") + .arg(&src) + .arg("-d") + .arg(out)); } - println!("Rustbook ({}) - {}", target, name); - let _ = fs::remove_dir_all(&out); - build.run(build.tool_cmd(&compiler, "rustbook") - .arg("build") - .arg(&src) - .arg("-d") - .arg(out)); } // rules.doc("doc-book", "src/doc/book") @@ -103,34 +131,48 @@ pub fn rustbook_src(build: &Build, target: &str, name: &str, src: &Path) { // }) // .default(build.config.docs) // .run(move |s| doc::book(build, s.target, "book")); -/// Build the book and associated stuff. -/// -/// We need to build: -/// -/// * Book (first edition) -/// * Book (second edition) -/// * Index page -/// * Redirect pages -pub fn book(build: &Build, target: &str, name: &str) { - // build book first edition - rustbook(build, target, &format!("{}/first-edition", name)); - - // build book second edition - rustbook(build, target, &format!("{}/second-edition", name)); - - // build the index page - let index = format!("{}/index.md", name); - println!("Documenting book index ({})", target); - invoke_rustdoc(build, target, &index); - - // build the redirect pages - println!("Documenting book redirect pages ({})", target); - for file in t!(fs::read_dir(build.src.join("src/doc/book/redirects"))) { - let file = t!(file); - let path = file.path(); - let path = path.to_str().unwrap(); - - invoke_rustdoc(build, target, path); + +#[derive(Serialize)] +pub struct TheBook<'a> { + target: &'a str, + name: &'a str, +} + +impl<'a> Step<'a> for TheBook<'a> { + type Output = (); + + /// Build the book and associated stuff. + /// + /// We need to build: + /// + /// * Book (first edition) + /// * Book (second edition) + /// * Index page + /// * Redirect pages + fn run(self, builder: &Builder) { + let build = builder.build; + let target = self.target; + let name = self.name; + // build book first edition + rustbook(build, target, &format!("{}/first-edition", name)); + + // build book second edition + rustbook(build, target, &format!("{}/second-edition", name)); + + // build the index page + let index = format!("{}/index.md", name); + println!("Documenting book index ({})", target); + invoke_rustdoc(build, target, &index); + + // build the redirect pages + println!("Documenting book redirect pages ({})", target); + for file in t!(fs::read_dir(build.src.join("src/doc/book/redirects"))) { + let file = t!(file); + let path = file.path(); + let path = path.to_str().unwrap(); + + invoke_rustdoc(build, target, path); + } } } @@ -188,75 +230,87 @@ fn invoke_rustdoc(build: &Build, target: &str, markdown: &str) { // }) // .default(build.config.docs) // .run(move |s| doc::standalone(build, s.target)); -/// Generates all standalone documentation as compiled by the rustdoc in `stage` -/// for the `target` into `out`. -/// -/// This will list all of `src/doc` looking for markdown files and appropriately -/// perform transformations like substituting `VERSION`, `SHORT_HASH`, and -/// `STAMP` alongw ith providing the various header/footer HTML we've cutomized. -/// -/// In the end, this is just a glorified wrapper around rustdoc! -pub fn standalone(build: &Build, target: &str) { - println!("Documenting standalone ({})", target); - let out = build.doc_out(target); - t!(fs::create_dir_all(&out)); - - let compiler = Compiler::new(0, &build.build); - - let favicon = build.src.join("src/doc/favicon.inc"); - let footer = build.src.join("src/doc/footer.inc"); - let full_toc = build.src.join("src/doc/full-toc.inc"); - t!(fs::copy(build.src.join("src/doc/rust.css"), out.join("rust.css"))); - let version_input = build.src.join("src/doc/version_info.html.template"); - let version_info = out.join("version_info.html"); - - if !up_to_date(&version_input, &version_info) { - let mut info = String::new(); - t!(t!(File::open(&version_input)).read_to_string(&mut info)); - let info = info.replace("VERSION", &build.rust_release()) - .replace("SHORT_HASH", build.rust_info.sha_short().unwrap_or("")) - .replace("STAMP", build.rust_info.sha().unwrap_or("")); - t!(t!(File::create(&version_info)).write_all(info.as_bytes())); - } +#[derive(Serialize)] +pub struct Standalone<'a> { + target: &'a str, +} - for file in t!(fs::read_dir(build.src.join("src/doc"))) { - let file = t!(file); - let path = file.path(); - let filename = path.file_name().unwrap().to_str().unwrap(); - if !filename.ends_with(".md") || filename == "README.md" { - continue +impl<'a> Step<'a> for Standalone<'a> { + type Output = (); + + /// Generates all standalone documentation as compiled by the rustdoc in `stage` + /// for the `target` into `out`. + /// + /// This will list all of `src/doc` looking for markdown files and appropriately + /// perform transformations like substituting `VERSION`, `SHORT_HASH`, and + /// `STAMP` alongw ith providing the various header/footer HTML we've cutomized. + /// + /// In the end, this is just a glorified wrapper around rustdoc! + fn run(self, builder: &Builder) { + let build = builder.build; + let target = self.target; + println!("Documenting standalone ({})", target); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); + + let compiler = Compiler::new(0, &build.build); + + let favicon = build.src.join("src/doc/favicon.inc"); + let footer = build.src.join("src/doc/footer.inc"); + let full_toc = build.src.join("src/doc/full-toc.inc"); + t!(fs::copy(build.src.join("src/doc/rust.css"), out.join("rust.css"))); + + let version_input = build.src.join("src/doc/version_info.html.template"); + let version_info = out.join("version_info.html"); + + if !up_to_date(&version_input, &version_info) { + let mut info = String::new(); + t!(t!(File::open(&version_input)).read_to_string(&mut info)); + let info = info.replace("VERSION", &build.rust_release()) + .replace("SHORT_HASH", build.rust_info.sha_short().unwrap_or("")) + .replace("STAMP", build.rust_info.sha().unwrap_or("")); + t!(t!(File::create(&version_info)).write_all(info.as_bytes())); } - let html = out.join(filename).with_extension("html"); - let rustdoc = build.rustdoc(&compiler); - if up_to_date(&path, &html) && - up_to_date(&footer, &html) && - up_to_date(&favicon, &html) && - up_to_date(&full_toc, &html) && - up_to_date(&version_info, &html) && - up_to_date(&rustdoc, &html) { - continue + for file in t!(fs::read_dir(build.src.join("src/doc"))) { + let file = t!(file); + let path = file.path(); + let filename = path.file_name().unwrap().to_str().unwrap(); + if !filename.ends_with(".md") || filename == "README.md" { + continue + } + + let html = out.join(filename).with_extension("html"); + let rustdoc = build.rustdoc(&compiler); + if up_to_date(&path, &html) && + up_to_date(&footer, &html) && + up_to_date(&favicon, &html) && + up_to_date(&full_toc, &html) && + up_to_date(&version_info, &html) && + up_to_date(&rustdoc, &html) { + continue + } + + let mut cmd = Command::new(&rustdoc); + build.add_rustc_lib_path(&compiler, &mut cmd); + cmd.arg("--html-after-content").arg(&footer) + .arg("--html-before-content").arg(&version_info) + .arg("--html-in-header").arg(&favicon) + .arg("--markdown-playground-url") + .arg("https://play.rust-lang.org/") + .arg("-o").arg(&out) + .arg(&path); + + if filename == "not_found.md" { + cmd.arg("--markdown-no-toc") + .arg("--markdown-css") + .arg("https://doc.rust-lang.org/rust.css"); + } else { + cmd.arg("--markdown-css").arg("rust.css"); + } + build.run(&mut cmd); } - - let mut cmd = Command::new(&rustdoc); - build.add_rustc_lib_path(&compiler, &mut cmd); - cmd.arg("--html-after-content").arg(&footer) - .arg("--html-before-content").arg(&version_info) - .arg("--html-in-header").arg(&favicon) - .arg("--markdown-playground-url") - .arg("https://play.rust-lang.org/") - .arg("-o").arg(&out) - .arg(&path); - - if filename == "not_found.md" { - cmd.arg("--markdown-no-toc") - .arg("--markdown-css") - .arg("https://doc.rust-lang.org/rust.css"); - } else { - cmd.arg("--markdown-css").arg("rust.css"); - } - build.run(&mut cmd); } } @@ -266,63 +320,77 @@ pub fn standalone(build: &Build, target: &str) { // .default(default && build.config.docs) // .run(move |s| doc::std(build, s.stage, s.target)); // } -/// Compile all standard library documentation. -/// -/// This will generate all documentation for the standard library and its -/// dependencies. This is largely just a wrapper around `cargo doc`. -pub fn std(build: &Build, stage: u32, target: &str) { - println!("Documenting stage{} std ({})", stage, target); - let out = build.doc_out(target); - t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.build); - let compiler = if build.force_use_stage1(&compiler, target) { - Compiler::new(1, compiler.host) - } else { - compiler - }; - let out_dir = build.stage_out(&compiler, Mode::Libstd) - .join(target).join("doc"); - let rustdoc = build.rustdoc(&compiler); - // Here what we're doing is creating a *symlink* (directory junction on - // Windows) to the final output location. This is not done as an - // optimization but rather for correctness. We've got three trees of - // documentation, one for std, one for test, and one for rustc. It's then - // our job to merge them all together. - // - // Unfortunately rustbuild doesn't know nearly as well how to merge doc - // trees as rustdoc does itself, so instead of actually having three - // separate trees we just have rustdoc output to the same location across - // all of them. - // - // This way rustdoc generates output directly into the output, and rustdoc - // will also directly handle merging. - let my_out = build.crate_doc_out(target); - build.clear_if_dirty(&my_out, &rustdoc); - t!(symlink_dir_force(&my_out, &out_dir)); - - let mut cargo = build.cargo(&compiler, Mode::Libstd, target, "doc"); - cargo.arg("--manifest-path") - .arg(build.src.join("src/libstd/Cargo.toml")) - .arg("--features").arg(build.std_features()); - - // We don't want to build docs for internal std dependencies unless - // in compiler-docs mode. When not in that mode, we whitelist the crates - // for which docs must be built. - if !build.config.compiler_docs { - cargo.arg("--no-deps"); - for krate in &["alloc", "collections", "core", "std", "std_unicode"] { - cargo.arg("-p").arg(krate); - // Create all crate output directories first to make sure rustdoc uses - // relative links. - // FIXME: Cargo should probably do this itself. - t!(fs::create_dir_all(out_dir.join(krate))); +#[derive(Serialize)] +pub struct Std<'a> { + stage: u32, + target: &'a str, +} + +impl<'a> Step<'a> for Std<'a> { + type Output = (); + + /// Compile all standard library documentation. + /// + /// This will generate all documentation for the standard library and its + /// dependencies. This is largely just a wrapper around `cargo doc`. + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let target = self.target; + println!("Documenting stage{} std ({})", stage, target); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); + let compiler = Compiler::new(stage, &build.build); + let compiler = if build.force_use_stage1(&compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler + }; + let out_dir = build.stage_out(&compiler, Mode::Libstd) + .join(target).join("doc"); + let rustdoc = build.rustdoc(&compiler); + + // Here what we're doing is creating a *symlink* (directory junction on + // Windows) to the final output location. This is not done as an + // optimization but rather for correctness. We've got three trees of + // documentation, one for std, one for test, and one for rustc. It's then + // our job to merge them all together. + // + // Unfortunately rustbuild doesn't know nearly as well how to merge doc + // trees as rustdoc does itself, so instead of actually having three + // separate trees we just have rustdoc output to the same location across + // all of them. + // + // This way rustdoc generates output directly into the output, and rustdoc + // will also directly handle merging. + let my_out = build.crate_doc_out(target); + build.clear_if_dirty(&my_out, &rustdoc); + t!(symlink_dir_force(&my_out, &out_dir)); + + let mut cargo = build.cargo(&compiler, Mode::Libstd, target, "doc"); + cargo.arg("--manifest-path") + .arg(build.src.join("src/libstd/Cargo.toml")) + .arg("--features").arg(build.std_features()); + + // We don't want to build docs for internal std dependencies unless + // in compiler-docs mode. When not in that mode, we whitelist the crates + // for which docs must be built. + if !build.config.compiler_docs { + cargo.arg("--no-deps"); + for krate in &["alloc", "collections", "core", "std", "std_unicode"] { + cargo.arg("-p").arg(krate); + // Create all crate output directories first to make sure rustdoc uses + // relative links. + // FIXME: Cargo should probably do this itself. + t!(fs::create_dir_all(out_dir.join(krate))); + } } - } - build.run(&mut cargo); - cp_r(&my_out, &out); + build.run(&mut cargo); + cp_r(&my_out, &out); + } } // for (krate, path, default) in krates("test") { @@ -333,36 +401,49 @@ pub fn std(build: &Build, stage: u32, target: &str) { // .default(default && build.config.compiler_docs) // .run(move |s| doc::test(build, s.stage, s.target)); // } -/// Compile all libtest documentation. -/// -/// This will generate all documentation for libtest and its dependencies. This -/// is largely just a wrapper around `cargo doc`. -pub fn test(build: &Build, stage: u32, target: &str) { - println!("Documenting stage{} test ({})", stage, target); - let out = build.doc_out(target); - t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.build); - let compiler = if build.force_use_stage1(&compiler, target) { - Compiler::new(1, compiler.host) - } else { - compiler - }; - let out_dir = build.stage_out(&compiler, Mode::Libtest) - .join(target).join("doc"); - let rustdoc = build.rustdoc(&compiler); - // See docs in std above for why we symlink - let my_out = build.crate_doc_out(target); - build.clear_if_dirty(&my_out, &rustdoc); - t!(symlink_dir_force(&my_out, &out_dir)); - - let mut cargo = build.cargo(&compiler, Mode::Libtest, target, "doc"); - cargo.arg("--manifest-path") - .arg(build.src.join("src/libtest/Cargo.toml")); - build.run(&mut cargo); - cp_r(&my_out, &out); +#[derive(Serialize)] +pub struct Test<'a> { + stage: u32, + test: &'a str, } +impl<'a> Step<'a> for Test<'a> { + type Output = (); + + /// Compile all libtest documentation. + /// + /// This will generate all documentation for libtest and its dependencies. This + /// is largely just a wrapper around `cargo doc`. + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let target = self.target; + println!("Documenting stage{} test ({})", stage, target); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); + let compiler = Compiler::new(stage, &build.build); + let compiler = if build.force_use_stage1(&compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler + }; + let out_dir = build.stage_out(&compiler, Mode::Libtest) + .join(target).join("doc"); + let rustdoc = build.rustdoc(&compiler); + + // See docs in std above for why we symlink + let my_out = build.crate_doc_out(target); + build.clear_if_dirty(&my_out, &rustdoc); + t!(symlink_dir_force(&my_out, &out_dir)); + + let mut cargo = build.cargo(&compiler, Mode::Libtest, target, "doc"); + cargo.arg("--manifest-path") + .arg(build.src.join("src/libtest/Cargo.toml")); + build.run(&mut cargo); + cp_r(&my_out, &out); + } +} // for (krate, path, default) in krates("rustc-main") { // rules.doc(&krate.doc_step, path) @@ -374,51 +455,65 @@ pub fn test(build: &Build, stage: u32, target: &str) { // .run(move |s| doc::rustc(build, s.stage, s.target)); // } // -/// Generate all compiler documentation. -/// -/// This will generate all documentation for the compiler libraries and their -/// dependencies. This is largely just a wrapper around `cargo doc`. -pub fn rustc(build: &Build, stage: u32, target: &str) { - println!("Documenting stage{} compiler ({})", stage, target); - let out = build.doc_out(target); - t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.build); - let compiler = if build.force_use_stage1(&compiler, target) { - Compiler::new(1, compiler.host) - } else { - compiler - }; - let out_dir = build.stage_out(&compiler, Mode::Librustc) - .join(target).join("doc"); - let rustdoc = build.rustdoc(&compiler); - // See docs in std above for why we symlink - let my_out = build.crate_doc_out(target); - build.clear_if_dirty(&my_out, &rustdoc); - t!(symlink_dir_force(&my_out, &out_dir)); - - let mut cargo = build.cargo(&compiler, Mode::Librustc, target, "doc"); - cargo.arg("--manifest-path") - .arg(build.src.join("src/rustc/Cargo.toml")) - .arg("--features").arg(build.rustc_features()); - - if build.config.compiler_docs { - // src/rustc/Cargo.toml contains bin crates called rustc and rustdoc - // which would otherwise overwrite the docs for the real rustc and - // rustdoc lib crates. - cargo.arg("-p").arg("rustc_driver") - .arg("-p").arg("rustdoc"); - } else { - // Like with libstd above if compiler docs aren't enabled then we're not - // documenting internal dependencies, so we have a whitelist. - cargo.arg("--no-deps"); - for krate in &["proc_macro"] { - cargo.arg("-p").arg(krate); +#[derive(Serialize)] +pub struct Rustc<'a> { + stage: u32, + target: &'a str, +} + +impl<'a> Step<'a> for Rustc<'a> { + type Output = (); + + /// Generate all compiler documentation. + /// + /// This will generate all documentation for the compiler libraries and their + /// dependencies. This is largely just a wrapper around `cargo doc`. + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let target = self.target; + println!("Documenting stage{} compiler ({})", stage, target); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); + let compiler = Compiler::new(stage, &build.build); + let compiler = if build.force_use_stage1(&compiler, target) { + Compiler::new(1, compiler.host) + } else { + compiler + }; + let out_dir = build.stage_out(&compiler, Mode::Librustc) + .join(target).join("doc"); + let rustdoc = build.rustdoc(&compiler); + + // See docs in std above for why we symlink + let my_out = build.crate_doc_out(target); + build.clear_if_dirty(&my_out, &rustdoc); + t!(symlink_dir_force(&my_out, &out_dir)); + + let mut cargo = build.cargo(&compiler, Mode::Librustc, target, "doc"); + cargo.arg("--manifest-path") + .arg(build.src.join("src/rustc/Cargo.toml")) + .arg("--features").arg(build.rustc_features()); + + if build.config.compiler_docs { + // src/rustc/Cargo.toml contains bin crates called rustc and rustdoc + // which would otherwise overwrite the docs for the real rustc and + // rustdoc lib crates. + cargo.arg("-p").arg("rustc_driver") + .arg("-p").arg("rustdoc"); + } else { + // Like with libstd above if compiler docs aren't enabled then we're not + // documenting internal dependencies, so we have a whitelist. + cargo.arg("--no-deps"); + for krate in &["proc_macro"] { + cargo.arg("-p").arg(krate); + } } - } - build.run(&mut cargo); - cp_r(&my_out, &out); + build.run(&mut cargo); + cp_r(&my_out, &out); + } } // rules.doc("doc-error-index", "src/tools/error_index_generator") @@ -428,21 +523,32 @@ pub fn rustc(build: &Build, stage: u32, target: &str) { // .host(true) // .run(move |s| doc::error_index(build, s.target)); -/// Generates the HTML rendered error-index by running the -/// `error_index_generator` tool. -pub fn error_index(build: &Build, target: &str) { - println!("Documenting error index ({})", target); - let out = build.doc_out(target); - t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(0, &build.build); - let mut index = build.tool_cmd(&compiler, "error_index_generator"); - index.arg("html"); - index.arg(out.join("error-index.html")); - - // FIXME: shouldn't have to pass this env var - index.env("CFG_BUILD", &build.build); +#[derive(Serialize)] +pub struct ErrorIndex<'a> { + target: &'a str, +} - build.run(&mut index); +impl<'a> Step<'a> for ErrorIndex<'a> { + type Output = (); + + /// Generates the HTML rendered error-index by running the + /// `error_index_generator` tool. + fn run(self, builder: &Builder) { + let builder = builder.build; + let target = self.target; + println!("Documenting error index ({})", target); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); + let compiler = Compiler::new(0, &build.build); + let mut index = build.tool_cmd(&compiler, "error_index_generator"); + index.arg("html"); + index.arg(out.join("error-index.html")); + + // FIXME: shouldn't have to pass this env var + index.env("CFG_BUILD", &build.build); + + build.run(&mut index); + } } // rules.doc("doc-unstable-book-gen", "src/tools/unstable-book-gen") @@ -457,17 +563,28 @@ pub fn error_index(build: &Build, target: &str) { // .host(true) // .run(move |s| doc::unstable_book_gen(build, s.target)); -pub fn unstable_book_gen(build: &Build, target: &str) { - println!("Generating unstable book md files ({})", target); - let out = build.md_doc_out(target).join("unstable-book"); - t!(fs::create_dir_all(&out)); - t!(fs::remove_dir_all(&out)); - let compiler = Compiler::new(0, &build.build); - let mut cmd = build.tool_cmd(&compiler, "unstable-book-gen"); - cmd.arg(build.src.join("src")); - cmd.arg(out); +#[derive(Serialize)] +pub struct UnstableBookGen<'a> { + target: &'a str, +} - build.run(&mut cmd); +impl<'a> Step<'a> for UnstableBookGen<'a> { + type Output = (); + + fn run(self, builder: &Builder) { + let build = builder.build; + let target = self.target; + println!("Generating unstable book md files ({})", target); + let out = build.md_doc_out(target).join("unstable-book"); + t!(fs::create_dir_all(&out)); + t!(fs::remove_dir_all(&out)); + let compiler = Compiler::new(0, &build.build); + let mut cmd = build.tool_cmd(&compiler, "unstable-book-gen"); + cmd.arg(build.src.join("src")); + cmd.arg(out); + + build.run(&mut cmd); + } } fn symlink_dir_force(src: &Path, dst: &Path) -> io::Result<()> { diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index d28060559aca5..6ae5c03bfeb4c 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -33,7 +33,7 @@ use Build; use util; use build_helper::up_to_date; -/ rules.build("llvm", "src/llvm") +/j/ rules.build("llvm", "src/llvm") // .host(true) // .dep(move |s| { // if s.target == build.build { @@ -43,173 +43,185 @@ use build_helper::up_to_date; // } // }) // .run(move |s| native::llvm(build, s.target)); -/// Compile LLVM for `target`. -pub fn llvm(build: &Build, target: &str) { - // If we're using a custom LLVM bail out here, but we can only use a - // custom LLVM for the build triple. - if let Some(config) = build.config.target_config.get(target) { - if let Some(ref s) = config.llvm_config { - return check_llvm_version(build, s); + +#[derive(Serialize)] +pub struct Llvm<'a> { + pub target: &'a str, +} + +impl<'a> Step<'a> for Llvm<'a> { + type Output = (); + + /// Compile LLVM for `target`. + fn run(self, builder: &Builder) { + let build = builder.build; + let target = self.target; + // If we're using a custom LLVM bail out here, but we can only use a + // custom LLVM for the build triple. + if let Some(config) = build.config.target_config.get(target) { + if let Some(ref s) = config.llvm_config { + return check_llvm_version(build, s); + } } - } - let rebuild_trigger = build.src.join("src/rustllvm/llvm-rebuild-trigger"); - let mut rebuild_trigger_contents = String::new(); - t!(t!(File::open(&rebuild_trigger)).read_to_string(&mut rebuild_trigger_contents)); + let rebuild_trigger = build.src.join("src/rustllvm/llvm-rebuild-trigger"); + let mut rebuild_trigger_contents = String::new(); + t!(t!(File::open(&rebuild_trigger)).read_to_string(&mut rebuild_trigger_contents)); - let out_dir = build.llvm_out(target); - let done_stamp = out_dir.join("llvm-finished-building"); - if done_stamp.exists() { - let mut done_contents = String::new(); - t!(t!(File::open(&done_stamp)).read_to_string(&mut done_contents)); + let out_dir = build.llvm_out(target); + let done_stamp = out_dir.join("llvm-finished-building"); + if done_stamp.exists() { + let mut done_contents = String::new(); + t!(t!(File::open(&done_stamp)).read_to_string(&mut done_contents)); - // If LLVM was already built previously and contents of the rebuild-trigger file - // didn't change from the previous build, then no action is required. - if done_contents == rebuild_trigger_contents { - return + // If LLVM was already built previously and contents of the rebuild-trigger file + // didn't change from the previous build, then no action is required. + if done_contents == rebuild_trigger_contents { + return + } + } + if build.config.llvm_clean_rebuild { + drop(fs::remove_dir_all(&out_dir)); } - } - if build.config.llvm_clean_rebuild { - drop(fs::remove_dir_all(&out_dir)); - } - let _folder = build.fold_output(|| "llvm"); - println!("Building LLVM for {}", target); - let _time = util::timeit(); - t!(fs::create_dir_all(&out_dir)); + let _folder = build.fold_output(|| "llvm"); + println!("Building LLVM for {}", target); + let _time = util::timeit(); + t!(fs::create_dir_all(&out_dir)); - // http://llvm.org/docs/CMake.html - let mut cfg = cmake::Config::new(build.src.join("src/llvm")); - if build.config.ninja { - cfg.generator("Ninja"); - } + // http://llvm.org/docs/CMake.html + let mut cfg = cmake::Config::new(build.src.join("src/llvm")); + if build.config.ninja { + cfg.generator("Ninja"); + } - let profile = match (build.config.llvm_optimize, build.config.llvm_release_debuginfo) { - (false, _) => "Debug", - (true, false) => "Release", - (true, true) => "RelWithDebInfo", - }; - - // NOTE: remember to also update `config.toml.example` when changing the defaults! - let llvm_targets = match build.config.llvm_targets { - Some(ref s) => s, - None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon", - }; - - let llvm_exp_targets = match build.config.llvm_experimental_targets { - Some(ref s) => s, - None => "", - }; - - let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"}; - - cfg.target(target) - .host(&build.build) - .out_dir(&out_dir) - .profile(profile) - .define("LLVM_ENABLE_ASSERTIONS", assertions) - .define("LLVM_TARGETS_TO_BUILD", llvm_targets) - .define("LLVM_EXPERIMENTAL_TARGETS_TO_BUILD", llvm_exp_targets) - .define("LLVM_INCLUDE_EXAMPLES", "OFF") - .define("LLVM_INCLUDE_TESTS", "OFF") - .define("LLVM_INCLUDE_DOCS", "OFF") - .define("LLVM_ENABLE_ZLIB", "OFF") - .define("WITH_POLLY", "OFF") - .define("LLVM_ENABLE_TERMINFO", "OFF") - .define("LLVM_ENABLE_LIBEDIT", "OFF") - .define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string()) - .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) - .define("LLVM_DEFAULT_TARGET_TRIPLE", target); - - if target.contains("msvc") { - cfg.define("LLVM_USE_CRT_DEBUG", "MT"); - cfg.define("LLVM_USE_CRT_RELEASE", "MT"); - cfg.define("LLVM_USE_CRT_RELWITHDEBINFO", "MT"); - cfg.static_crt(true); - } + let profile = match (build.config.llvm_optimize, build.config.llvm_release_debuginfo) { + (false, _) => "Debug", + (true, false) => "Release", + (true, true) => "RelWithDebInfo", + }; - if target.starts_with("i686") { - cfg.define("LLVM_BUILD_32_BITS", "ON"); - } + // NOTE: remember to also update `config.toml.example` when changing the defaults! + let llvm_targets = match build.config.llvm_targets { + Some(ref s) => s, + None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon", + }; - if let Some(num_linkers) = build.config.llvm_link_jobs { - if num_linkers > 0 { - cfg.define("LLVM_PARALLEL_LINK_JOBS", num_linkers.to_string()); - } - } + let llvm_exp_targets = match build.config.llvm_experimental_targets { + Some(ref s) => s, + None => "", + }; - // http://llvm.org/docs/HowToCrossCompileLLVM.html - if target != build.build { - // FIXME: if the llvm root for the build triple is overridden then we - // should use llvm-tblgen from there, also should verify that it - // actually exists most of the time in normal installs of LLVM. - let host = build.llvm_out(&build.build).join("bin/llvm-tblgen"); - cfg.define("CMAKE_CROSSCOMPILING", "True") - .define("LLVM_TABLEGEN", &host); - } + let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"}; + + cfg.target(target) + .host(&build.build) + .out_dir(&out_dir) + .profile(profile) + .define("LLVM_ENABLE_ASSERTIONS", assertions) + .define("LLVM_TARGETS_TO_BUILD", llvm_targets) + .define("LLVM_EXPERIMENTAL_TARGETS_TO_BUILD", llvm_exp_targets) + .define("LLVM_INCLUDE_EXAMPLES", "OFF") + .define("LLVM_INCLUDE_TESTS", "OFF") + .define("LLVM_INCLUDE_DOCS", "OFF") + .define("LLVM_ENABLE_ZLIB", "OFF") + .define("WITH_POLLY", "OFF") + .define("LLVM_ENABLE_TERMINFO", "OFF") + .define("LLVM_ENABLE_LIBEDIT", "OFF") + .define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string()) + .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) + .define("LLVM_DEFAULT_TARGET_TRIPLE", target); - let sanitize_cc = |cc: &Path| { if target.contains("msvc") { - OsString::from(cc.to_str().unwrap().replace("\\", "/")) - } else { - cc.as_os_str().to_owned() + cfg.define("LLVM_USE_CRT_DEBUG", "MT"); + cfg.define("LLVM_USE_CRT_RELEASE", "MT"); + cfg.define("LLVM_USE_CRT_RELWITHDEBINFO", "MT"); + cfg.static_crt(true); } - }; - let configure_compilers = |cfg: &mut cmake::Config| { - // MSVC with CMake uses msbuild by default which doesn't respect these - // vars that we'd otherwise configure. In that case we just skip this - // entirely. - if target.contains("msvc") && !build.config.ninja { - return + if target.starts_with("i686") { + cfg.define("LLVM_BUILD_32_BITS", "ON"); } - let cc = build.cc(target); - let cxx = build.cxx(target).unwrap(); - - // Handle msvc + ninja + ccache specially (this is what the bots use) - if target.contains("msvc") && - build.config.ninja && - build.config.ccache.is_some() { - let mut cc = env::current_exe().expect("failed to get cwd"); - cc.set_file_name("sccache-plus-cl.exe"); - - cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc)) - .define("CMAKE_CXX_COMPILER", sanitize_cc(&cc)); - cfg.env("SCCACHE_PATH", - build.config.ccache.as_ref().unwrap()) - .env("SCCACHE_TARGET", target); - - // If ccache is configured we inform the build a little differently hwo - // to invoke ccache while also invoking our compilers. - } else if let Some(ref ccache) = build.config.ccache { - cfg.define("CMAKE_C_COMPILER", ccache) - .define("CMAKE_C_COMPILER_ARG1", sanitize_cc(cc)) - .define("CMAKE_CXX_COMPILER", ccache) - .define("CMAKE_CXX_COMPILER_ARG1", sanitize_cc(cxx)); - } else { - cfg.define("CMAKE_C_COMPILER", sanitize_cc(cc)) - .define("CMAKE_CXX_COMPILER", sanitize_cc(cxx)); + if let Some(num_linkers) = build.config.llvm_link_jobs { + if num_linkers > 0 { + cfg.define("LLVM_PARALLEL_LINK_JOBS", num_linkers.to_string()); + } } - cfg.build_arg("-j").build_arg(build.jobs().to_string()); - cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" ")); - cfg.define("CMAKE_CXX_FLAGS", build.cflags(target).join(" ")); - }; + // http://llvm.org/docs/HowToCrossCompileLLVM.html + if target != build.build { + // FIXME: if the llvm root for the build triple is overridden then we + // should use llvm-tblgen from there, also should verify that it + // actually exists most of the time in normal installs of LLVM. + let host = build.llvm_out(&build.build).join("bin/llvm-tblgen"); + cfg.define("CMAKE_CROSSCOMPILING", "True") + .define("LLVM_TABLEGEN", &host); + } - configure_compilers(&mut cfg); + let sanitize_cc = |cc: &Path| { + if target.contains("msvc") { + OsString::from(cc.to_str().unwrap().replace("\\", "/")) + } else { + cc.as_os_str().to_owned() + } + }; - if env::var_os("SCCACHE_ERROR_LOG").is_some() { - cfg.env("RUST_LOG", "sccache=warn"); - } + let configure_compilers = |cfg: &mut cmake::Config| { + // MSVC with CMake uses msbuild by default which doesn't respect these + // vars that we'd otherwise configure. In that case we just skip this + // entirely. + if target.contains("msvc") && !build.config.ninja { + return + } + + let cc = build.cc(target); + let cxx = build.cxx(target).unwrap(); + + // Handle msvc + ninja + ccache specially (this is what the bots use) + if target.contains("msvc") && + build.config.ninja && + build.config.ccache.is_some() { + let mut cc = env::current_exe().expect("failed to get cwd"); + cc.set_file_name("sccache-plus-cl.exe"); + + cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc)) + .define("CMAKE_CXX_COMPILER", sanitize_cc(&cc)); + cfg.env("SCCACHE_PATH", + build.config.ccache.as_ref().unwrap()) + .env("SCCACHE_TARGET", target); + + // If ccache is configured we inform the build a little differently hwo + // to invoke ccache while also invoking our compilers. + } else if let Some(ref ccache) = build.config.ccache { + cfg.define("CMAKE_C_COMPILER", ccache) + .define("CMAKE_C_COMPILER_ARG1", sanitize_cc(cc)) + .define("CMAKE_CXX_COMPILER", ccache) + .define("CMAKE_CXX_COMPILER_ARG1", sanitize_cc(cxx)); + } else { + cfg.define("CMAKE_C_COMPILER", sanitize_cc(cc)) + .define("CMAKE_CXX_COMPILER", sanitize_cc(cxx)); + } + + cfg.build_arg("-j").build_arg(build.jobs().to_string()); + cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" ")); + cfg.define("CMAKE_CXX_FLAGS", build.cflags(target).join(" ")); + }; - // FIXME: we don't actually need to build all LLVM tools and all LLVM - // libraries here, e.g. we just want a few components and a few - // tools. Figure out how to filter them down and only build the right - // tools and libs on all platforms. - cfg.build(); + configure_compilers(&mut cfg); - t!(t!(File::create(&done_stamp)).write_all(rebuild_trigger_contents.as_bytes())); + if env::var_os("SCCACHE_ERROR_LOG").is_some() { + cfg.env("RUST_LOG", "sccache=warn"); + } + + // FIXME: we don't actually need to build all LLVM tools and all LLVM + // libraries here, e.g. we just want a few components and a few + // tools. Figure out how to filter them down and only build the right + // tools and libs on all platforms. + cfg.build(); + + t!(t!(File::create(&done_stamp)).write_all(rebuild_trigger_contents.as_bytes())); + } } fn check_llvm_version(build: &Build, llvm_config: &Path) { @@ -228,39 +240,52 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) { //rules.build("test-helpers", "src/rt/rust_test_helpers.c") // .run(move |s| native::test_helpers(build, s.target)); -/// Compiles the `rust_test_helpers.c` library which we used in various -/// `run-pass` test suites for ABI testing. -pub fn test_helpers(build: &Build, target: &str) { - let dst = build.test_helpers_out(target); - let src = build.src.join("src/rt/rust_test_helpers.c"); - if up_to_date(&src, &dst.join("librust_test_helpers.a")) { - return - } - let _folder = build.fold_output(|| "build_test_helpers"); - println!("Building test helpers"); - t!(fs::create_dir_all(&dst)); - let mut cfg = gcc::Config::new(); - - // We may have found various cross-compilers a little differently due to our - // extra configuration, so inform gcc of these compilers. Note, though, that - // on MSVC we still need gcc's detection of env vars (ugh). - if !target.contains("msvc") { - if let Some(ar) = build.ar(target) { - cfg.archiver(ar); +#[derive(Serialize)] +pub struct TestHelpers<'a> { + target: &'a str, +} + +impl<'a> Step<'a> for TestHelpers<'a> { + type Output = (); + + /// Compiles the `rust_test_helpers.c` library which we used in various + /// `run-pass` test suites for ABI testing. + fn run(self, builder: &Builder) { + let build = builder.build; + let target = self.target; + let dst = build.test_helpers_out(target); + let src = build.src.join("src/rt/rust_test_helpers.c"); + if up_to_date(&src, &dst.join("librust_test_helpers.a")) { + return + } + + let _folder = build.fold_output(|| "build_test_helpers"); + println!("Building test helpers"); + t!(fs::create_dir_all(&dst)); + let mut cfg = gcc::Config::new(); + + // We may have found various cross-compilers a little differently due to our + // extra configuration, so inform gcc of these compilers. Note, though, that + // on MSVC we still need gcc's detection of env vars (ugh). + if !target.contains("msvc") { + if let Some(ar) = build.ar(target) { + cfg.archiver(ar); + } + cfg.compiler(build.cc(target)); } - cfg.compiler(build.cc(target)); - } - cfg.cargo_metadata(false) - .out_dir(&dst) - .target(target) - .host(&build.build) - .opt_level(0) - .debug(false) - .file(build.src.join("src/rt/rust_test_helpers.c")) - .compile("librust_test_helpers.a"); + cfg.cargo_metadata(false) + .out_dir(&dst) + .target(target) + .host(&build.build) + .opt_level(0) + .debug(false) + .file(build.src.join("src/rt/rust_test_helpers.c")) + .compile("librust_test_helpers.a"); + } } + const OPENSSL_VERS: &'static str = "1.0.2k"; const OPENSSL_SHA256: &'static str = "6b3977c61f2aedf0f96367dcfb5c6e578cf37e7b8d913b4ecb6643c3cb88d8c0"; @@ -268,124 +293,135 @@ const OPENSSL_SHA256: &'static str = //rules.build("openssl", "path/to/nowhere") // .run(move |s| native::openssl(build, s.target)); -pub fn openssl(build: &Build, target: &str) { - let out = match build.openssl_dir(target) { - Some(dir) => dir, - None => return, - }; +#[derive(Serialize)] +pub struct Openssl<'a> { + target: &'a str, +} - let stamp = out.join(".stamp"); - let mut contents = String::new(); - drop(File::open(&stamp).and_then(|mut f| f.read_to_string(&mut contents))); - if contents == OPENSSL_VERS { - return - } - t!(fs::create_dir_all(&out)); - - let name = format!("openssl-{}.tar.gz", OPENSSL_VERS); - let tarball = out.join(&name); - if !tarball.exists() { - let tmp = tarball.with_extension("tmp"); - // originally from https://www.openssl.org/source/... - let url = format!("https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/{}", - name); - let mut ok = false; - for _ in 0..3 { - let status = Command::new("curl") - .arg("-o").arg(&tmp) - .arg(&url) - .status() - .expect("failed to spawn curl"); - if status.success() { - ok = true; - break - } +impl<'a> Step<'a> for Openssl<'a> { + type Output = (); + + fn run(self, builder: &Builder) { + let build = bulder.build; + let target = self.target; + let out = match build.openssl_dir(target) { + Some(dir) => dir, + None => return, + }; + + let stamp = out.join(".stamp"); + let mut contents = String::new(); + drop(File::open(&stamp).and_then(|mut f| f.read_to_string(&mut contents))); + if contents == OPENSSL_VERS { + return } - if !ok { - panic!("failed to download openssl source") + t!(fs::create_dir_all(&out)); + + let name = format!("openssl-{}.tar.gz", OPENSSL_VERS); + let tarball = out.join(&name); + if !tarball.exists() { + let tmp = tarball.with_extension("tmp"); + // originally from https://www.openssl.org/source/... + let url = format!("https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/{}", + name); + let mut ok = false; + for _ in 0..3 { + let status = Command::new("curl") + .arg("-o").arg(&tmp) + .arg(&url) + .status() + .expect("failed to spawn curl"); + if status.success() { + ok = true; + break + } + } + if !ok { + panic!("failed to download openssl source") + } + let mut shasum = if target.contains("apple") { + let mut cmd = Command::new("shasum"); + cmd.arg("-a").arg("256"); + cmd + } else { + Command::new("sha256sum") + }; + let output = output(&mut shasum.arg(&tmp)); + let found = output.split_whitespace().next().unwrap(); + if found != OPENSSL_SHA256 { + panic!("downloaded openssl sha256 different\n\ + expected: {}\n\ + found: {}\n", OPENSSL_SHA256, found); + } + t!(fs::rename(&tmp, &tarball)); } - let mut shasum = if target.contains("apple") { - let mut cmd = Command::new("shasum"); - cmd.arg("-a").arg("256"); - cmd - } else { - Command::new("sha256sum") + let obj = out.join(format!("openssl-{}", OPENSSL_VERS)); + let dst = build.openssl_install_dir(target).unwrap(); + drop(fs::remove_dir_all(&obj)); + drop(fs::remove_dir_all(&dst)); + build.run(Command::new("tar").arg("xf").arg(&tarball).current_dir(&out)); + + let mut configure = Command::new(obj.join("Configure")); + configure.arg(format!("--prefix={}", dst.display())); + configure.arg("no-dso"); + configure.arg("no-ssl2"); + configure.arg("no-ssl3"); + + let os = match target { + "aarch64-linux-android" => "linux-aarch64", + "aarch64-unknown-linux-gnu" => "linux-aarch64", + "arm-linux-androideabi" => "android", + "arm-unknown-linux-gnueabi" => "linux-armv4", + "arm-unknown-linux-gnueabihf" => "linux-armv4", + "armv7-linux-androideabi" => "android-armv7", + "armv7-unknown-linux-gnueabihf" => "linux-armv4", + "i686-apple-darwin" => "darwin-i386-cc", + "i686-linux-android" => "android-x86", + "i686-unknown-freebsd" => "BSD-x86-elf", + "i686-unknown-linux-gnu" => "linux-elf", + "i686-unknown-linux-musl" => "linux-elf", + "mips-unknown-linux-gnu" => "linux-mips32", + "mips64-unknown-linux-gnuabi64" => "linux64-mips64", + "mips64el-unknown-linux-gnuabi64" => "linux64-mips64", + "mipsel-unknown-linux-gnu" => "linux-mips32", + "powerpc-unknown-linux-gnu" => "linux-ppc", + "powerpc64-unknown-linux-gnu" => "linux-ppc64", + "powerpc64le-unknown-linux-gnu" => "linux-ppc64le", + "s390x-unknown-linux-gnu" => "linux64-s390x", + "x86_64-apple-darwin" => "darwin64-x86_64-cc", + "x86_64-linux-android" => "linux-x86_64", + "x86_64-unknown-freebsd" => "BSD-x86_64", + "x86_64-unknown-linux-gnu" => "linux-x86_64", + "x86_64-unknown-linux-musl" => "linux-x86_64", + "x86_64-unknown-netbsd" => "BSD-x86_64", + _ => panic!("don't know how to configure OpenSSL for {}", target), }; - let output = output(&mut shasum.arg(&tmp)); - let found = output.split_whitespace().next().unwrap(); - if found != OPENSSL_SHA256 { - panic!("downloaded openssl sha256 different\n\ - expected: {}\n\ - found: {}\n", OPENSSL_SHA256, found); + configure.arg(os); + configure.env("CC", build.cc(target)); + for flag in build.cflags(target) { + configure.arg(flag); } - t!(fs::rename(&tmp, &tarball)); - } - let obj = out.join(format!("openssl-{}", OPENSSL_VERS)); - let dst = build.openssl_install_dir(target).unwrap(); - drop(fs::remove_dir_all(&obj)); - drop(fs::remove_dir_all(&dst)); - build.run(Command::new("tar").arg("xf").arg(&tarball).current_dir(&out)); - - let mut configure = Command::new(obj.join("Configure")); - configure.arg(format!("--prefix={}", dst.display())); - configure.arg("no-dso"); - configure.arg("no-ssl2"); - configure.arg("no-ssl3"); - - let os = match target { - "aarch64-linux-android" => "linux-aarch64", - "aarch64-unknown-linux-gnu" => "linux-aarch64", - "arm-linux-androideabi" => "android", - "arm-unknown-linux-gnueabi" => "linux-armv4", - "arm-unknown-linux-gnueabihf" => "linux-armv4", - "armv7-linux-androideabi" => "android-armv7", - "armv7-unknown-linux-gnueabihf" => "linux-armv4", - "i686-apple-darwin" => "darwin-i386-cc", - "i686-linux-android" => "android-x86", - "i686-unknown-freebsd" => "BSD-x86-elf", - "i686-unknown-linux-gnu" => "linux-elf", - "i686-unknown-linux-musl" => "linux-elf", - "mips-unknown-linux-gnu" => "linux-mips32", - "mips64-unknown-linux-gnuabi64" => "linux64-mips64", - "mips64el-unknown-linux-gnuabi64" => "linux64-mips64", - "mipsel-unknown-linux-gnu" => "linux-mips32", - "powerpc-unknown-linux-gnu" => "linux-ppc", - "powerpc64-unknown-linux-gnu" => "linux-ppc64", - "powerpc64le-unknown-linux-gnu" => "linux-ppc64le", - "s390x-unknown-linux-gnu" => "linux64-s390x", - "x86_64-apple-darwin" => "darwin64-x86_64-cc", - "x86_64-linux-android" => "linux-x86_64", - "x86_64-unknown-freebsd" => "BSD-x86_64", - "x86_64-unknown-linux-gnu" => "linux-x86_64", - "x86_64-unknown-linux-musl" => "linux-x86_64", - "x86_64-unknown-netbsd" => "BSD-x86_64", - _ => panic!("don't know how to configure OpenSSL for {}", target), - }; - configure.arg(os); - configure.env("CC", build.cc(target)); - for flag in build.cflags(target) { - configure.arg(flag); - } - // There is no specific os target for android aarch64 or x86_64, - // so we need to pass some extra cflags - if target == "aarch64-linux-android" || target == "x86_64-linux-android" { - configure.arg("-mandroid"); - configure.arg("-fomit-frame-pointer"); - } - // Make PIE binaries - // Non-PIE linker support was removed in Lollipop - // https://source.android.com/security/enhancements/enhancements50 - if target == "i686-linux-android" { - configure.arg("no-asm"); + // There is no specific os target for android aarch64 or x86_64, + // so we need to pass some extra cflags + if target == "aarch64-linux-android" || target == "x86_64-linux-android" { + configure.arg("-mandroid"); + configure.arg("-fomit-frame-pointer"); + } + // Make PIE binaries + // Non-PIE linker support was removed in Lollipop + // https://source.android.com/security/enhancements/enhancements50 + if target == "i686-linux-android" { + configure.arg("no-asm"); + } + configure.current_dir(&obj); + println!("Configuring openssl for {}", target); + build.run_quiet(&mut configure); + println!("Building openssl for {}", target); + build.run_quiet(Command::new("make").arg("-j1").current_dir(&obj)); + println!("Installing openssl for {}", target); + build.run_quiet(Command::new("make").arg("install").current_dir(&obj)); + + let mut f = t!(File::create(&stamp)); + t!(f.write_all(OPENSSL_VERS.as_bytes())); } - configure.current_dir(&obj); - println!("Configuring openssl for {}", target); - build.run_quiet(&mut configure); - println!("Building openssl for {}", target); - build.run_quiet(Command::new("make").arg("-j1").current_dir(&obj)); - println!("Installing openssl for {}", target); - build.run_quiet(Command::new("make").arg("install").current_dir(&obj)); - - let mut f = t!(File::create(&stamp)); - t!(f.write_all(OPENSSL_VERS.as_bytes())); } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs new file mode 100644 index 0000000000000..52ec273c3e8cd --- /dev/null +++ b/src/bootstrap/tool.rs @@ -0,0 +1,205 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::env; +use std::path::{Path, PathBuf}; +use std::process::Command; + +use Mode; +use builder::{Step, Builder}; +use util::{exe, add_lib_path}; +use compile::{self, stamp, Rustc}; +use native; +use channel::GitInfo; + +//// ======================================================================== +//// Build tools +//// +//// Tools used during the build system but not shipped +//// "pseudo rule" which represents completely cleaning out the tools dir in +//// one stage. This needs to happen whenever a dependency changes (e.g. +//// libstd, libtest, librustc) and all of the tool compilations above will +//// be sequenced after this rule. +//rules.build("maybe-clean-tools", "path/to/nowhere") +// .after("librustc-tool") +// .after("libtest-tool") +// .after("libstd-tool"); +// +//rules.build("librustc-tool", "path/to/nowhere") +// .dep(|s| s.name("librustc")) +// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Librustc)); +//rules.build("libtest-tool", "path/to/nowhere") +// .dep(|s| s.name("libtest")) +// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libtest)); +//rules.build("libstd-tool", "path/to/nowhere") +// .dep(|s| s.name("libstd")) +// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libstd)); +// + +#[derive(Serialize)] +pub struct CleanTools<'a> { + pub stage: u32, + pub target: &'a str, + pub mode: Mode, +} + +impl<'a> Step<'a> for CleanTools<'a> { + type Output = (); + + /// Build a tool in `src/tools` + /// + /// This will build the specified tool with the specified `host` compiler in + /// `stage` into the normal cargo output directory. + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let target = self.target; + let mode = self.mode; + + let compiler = Compiler::new(stage, &build.build); + + let stamp = match mode { + Mode::Libstd => libstd_stamp(build, &compiler, target), + Mode::Libtest => libtest_stamp(build, &compiler, target), + Mode::Librustc => librustc_stamp(build, &compiler, target), + _ => panic!(), + }; + let out_dir = build.cargo_out(&compiler, Mode::Tool, target); + build.clear_if_dirty(&out_dir, &stamp); + } +} + +// rules.build("tool-rustbook", "src/tools/rustbook") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("librustc-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "rustbook")); +// rules.build("tool-error-index", "src/tools/error_index_generator") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("librustc-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator")); +// rules.build("tool-unstable-book-gen", "src/tools/unstable-book-gen") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "unstable-book-gen")); +// rules.build("tool-tidy", "src/tools/tidy") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "tidy")); +// rules.build("tool-linkchecker", "src/tools/linkchecker") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "linkchecker")); +// rules.build("tool-cargotest", "src/tools/cargotest") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "cargotest")); +// rules.build("tool-compiletest", "src/tools/compiletest") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libtest-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "compiletest")); +// rules.build("tool-build-manifest", "src/tools/build-manifest") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "build-manifest")); +// rules.build("tool-remote-test-server", "src/tools/remote-test-server") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-server")); +// rules.build("tool-remote-test-client", "src/tools/remote-test-client") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-client")); +// rules.build("tool-rust-installer", "src/tools/rust-installer") +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .run(move |s| compile::tool(build, s.stage, s.target, "rust-installer")); +// rules.build("tool-cargo", "src/tools/cargo") +// .host(true) +// .default(build.config.extended) +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .dep(|s| s.stage(0).host(s.target).name("openssl")) +// .dep(move |s| { +// // Cargo depends on procedural macros, which requires a full host +// // compiler to be available, so we need to depend on that. +// s.name("librustc-link") +// .target(&build.build) +// .host(&build.build) +// }) +// .run(move |s| compile::tool(build, s.stage, s.target, "cargo")); +// rules.build("tool-rls", "src/tools/rls") +// .host(true) +// .default(build.config.extended) +// .dep(|s| s.name("librustc-tool")) +// .dep(|s| s.stage(0).host(s.target).name("openssl")) +// .dep(move |s| { +// // rls, like cargo, uses procedural macros +// s.name("librustc-link") +// .target(&build.build) +// .host(&build.build) +// }) +// .run(move |s| compile::tool(build, s.stage, s.target, "rls")); +// + +#[derive(Serialize)] +pub struct Tool<'a> { + pub stage: u32, + pub target: &'a str, + pub tool: &'a str, +} + +impl<'a> Step<'a> for Tool<'a> { + type Output = (); + + /// Build a tool in `src/tools` + /// + /// This will build the specified tool with the specified `host` compiler in + /// `stage` into the normal cargo output directory. + fn run(self, builder: &Builder) { + let build = builder.build; + let stage = self.stage; + let target = self.target; + let tool = self.tool; + + let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool)); + println!("Building stage{} tool {} ({})", stage, tool, target); + + let compiler = Compiler::new(stage, &build.build); + + let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build"); + let dir = build.src.join("src/tools").join(tool); + cargo.arg("--manifest-path").arg(dir.join("Cargo.toml")); + + // We don't want to build tools dynamically as they'll be running across + // stages and such and it's just easier if they're not dynamically linked. + cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); + + if let Some(dir) = build.openssl_install_dir(target) { + cargo.env("OPENSSL_STATIC", "1"); + cargo.env("OPENSSL_DIR", dir); + cargo.env("LIBZ_SYS_STATIC", "1"); + } + + cargo.env("CFG_RELEASE_CHANNEL", &build.config.channel); + + let info = GitInfo::new(&dir); + if let Some(sha) = info.sha() { + cargo.env("CFG_COMMIT_HASH", sha); + } + if let Some(sha_short) = info.sha_short() { + cargo.env("CFG_SHORT_COMMIT_HASH", sha_short); + } + if let Some(date) = info.commit_date() { + cargo.env("CFG_COMMIT_DATE", date); + } + + build.run(&mut cargo); + } +} From 6b3413d825fa61a16fcfaa37a114eaf3efe88eb3 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 5 Jul 2017 06:41:27 -0600 Subject: [PATCH 03/51] Change code to work with the new system --- src/bootstrap/check.rs | 389 ++++++++++++++++++++++++++++++++++----- src/bootstrap/compile.rs | 220 +++++++++++++++++++--- src/bootstrap/dist.rs | 197 ++++++++++++++++++-- src/bootstrap/doc.rs | 324 ++++++++++++++++++++++++++++---- src/bootstrap/install.rs | 163 +++++++++++----- src/bootstrap/native.rs | 18 +- src/bootstrap/tool.rs | 329 +++++++++++++++++++++++++-------- 7 files changed, 1394 insertions(+), 246 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 0278b8d5dbf2b..2fd02d3d7c48f 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -100,6 +100,8 @@ pub struct Linkcheck<'a> { impl<'a> Step<'a> for Linkcheck<'a> { type Output = (); + const ONLY_HOSTS: bool = true; + const DEFAULT: bool = true; /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler. /// @@ -110,12 +112,27 @@ impl<'a> Step<'a> for Linkcheck<'a> { let host = self.host; println!("Linkcheck ({})", host); - let compiler = Compiler::new(0, host); + + builder.default_doc(None); let _time = util::timeit(); - try_run(build, build.tool_cmd(&compiler, "linkchecker") + try_run(build, builder.tool_cmd(Tool::Linkchecker) .arg(build.out.join(host).join("doc"))); } + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/tools/linkchecker") + } + + fn make_run(builder: &Builder, path: Option<&Path>, host: &str, _target: &str) { + if path.is_some() { + builder.ensure(Linkcheck { host }); + } else { + if builder.build.config.docs { + builder.ensure(Linkcheck { host }); + } + } + } } // rules.test("check-cargotest", "src/tools/cargotest") @@ -132,6 +149,7 @@ pub struct Cargotest<'a> { impl<'a> Step<'a> for Cargotest<'a> { type Output = (); + const ONLY_HOSTS: bool = true; /// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler. /// @@ -139,9 +157,8 @@ impl<'a> Step<'a> for Cargotest<'a> { /// test` to ensure that we don't regress the test suites there. fn run(self, builder: &Builder) { let build = builder.build; - let stage = self.stage; - let host = self.host; - let compiler = Compiler::new(stage, host); + let compiler = builder.compiler(self.stage, host); + builder.ensure(compile::Rustc { compiler, target: compiler.host }); // Note that this is a short, cryptic, and not scoped directory name. This // is currently to minimize the length of path on Windows where we otherwise @@ -150,8 +167,7 @@ impl<'a> Step<'a> for Cargotest<'a> { t!(fs::create_dir_all(&out_dir)); let _time = util::timeit(); - let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest")); - build.prepare_tool_cmd(&compiler, &mut cmd); + let mut cmd = builder.tool_cmd(Tool::CargoTest); try_run(build, cmd.arg(&build.initial_cargo) .arg(&out_dir) .env("RUSTC", build.compiler_path(&compiler)) @@ -172,21 +188,34 @@ pub struct Cargo<'a> { impl<'a> Step<'a> for Cargo<'a> { type Output = (); + const ONLY_HOSTS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("cargo") // FIXME: Why is this not src/tools/cargo? + } + + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + builder.ensure(TestCargo { + compiler: builder.compiler(builder.top_stage, host), + target, + }); + } /// Runs `cargo test` for `cargo` packaged with Rust. fn run(self, builder: &Builder) { let build = builder.build; - let stage = self.stage; - let ref compiler = Compiler::new(stage, host); + let compiler = builder.compiler(self.stage, self.host); // Configure PATH to find the right rustc. NB. we have to use PATH // and not RUSTC because the Cargo test suite has tests that will // fail if rustc is not spelled `rustc`. let path = build.sysroot(compiler).join("bin"); let old_path = env::var_os("PATH").unwrap_or_default(); - let newpath = env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect(""); + let newpath = env::join_paths( + iter::once(path).chain(env::split_paths(&old_path)) + ).expect(""); - let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); + let mut cargo = build.cargo(compiler, Mode::Tool, self.host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml")); if !build.fail_fast { cargo.arg("--no-fail-fast"); @@ -250,7 +279,6 @@ fn path_for_cargo(build: &Build, compiler: &Compiler) -> OsString { try_run(build, cargo.env("PATH", newpath)); ======= try_run(build, cargo.env("PATH", newpath)); - let host = self.host; } >>>>>>> adabe3889e... Move code into Step trait implementations. } @@ -269,6 +297,9 @@ pub struct Tidy<'a> { impl<'a> Step<'a> for Tidy<'a> { type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + const ONLY_BUILD: bool = true; /// Runs the `tidy` tool as compiled in `stage` by the `host` compiler. /// @@ -281,8 +312,7 @@ impl<'a> Step<'a> for Tidy<'a> { let _folder = build.fold_output(|| "tidy"); println!("tidy check ({})", host); - let compiler = Compiler::new(0, host); - let mut cmd = build.tool_cmd(&compiler, "tidy"); + let mut cmd = build.tool_cmd(Tool::Tidy); cmd.arg(build.src.join("src")); if !build.config.vendor { cmd.arg("--no-vendor"); @@ -292,6 +322,16 @@ impl<'a> Step<'a> for Tidy<'a> { } try_run(build, &mut cmd); } + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/tools/tidy") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, _target: &str) { + builder.ensure(Tidy { + host: &builder.build.build, + }); + } } fn testdir(build: &Build, host: &str) -> PathBuf { @@ -404,8 +444,78 @@ pub struct Compiletest<'a> { suite: &'a str, } +static COMPILETESTS: &[(bool, &str, &str, &str)] = &[ + // default, path, mode, suite + (true, "src/test/codegen", "codegen", "codegen"), + (true, "src/test/codegen-units", "codegen-units", "codegen-units"), + (true, "src/test/compile-fail", "compile-fail", "compile-fail"), + (true, "src/test/incremental", "incremental", "incremental"), + (true, "src/test/mir-opt", "mir-opt", "mir-opt"), + (true, "src/test/parse-fail", "parse-fail", "parse-fail"), + (true, "src/test/run-fail", "run-fail", "run-fail"), + (true, "src/test/run-pass", "run-pass", "run-pass"), + (true, "src/test/run-pass-valgrind", "run-pass-valgrind", "run-pass-valgrind"), + (true, "src/test/ui", "ui", "ui"), + (false, "src/test/debuginfo-lldb", "debuginfo-lldb", "debuginfo"), + (false, "src/test/debuginfo-gdb", "debuginfo-gdb", "debuginfo"), + + // FIXME: What this runs varies depending on the native platform being apple + (true, "src/test/debuginfo", "debuginfo-XXX", "debuginfo"), + + (true, "src/test/ui-fulldeps", "ui", "ui-fulldeps"), + (true, "src/test/run-pass-fulldeps", "run-pass", "run-pass-fulldeps"), + (true, "src/test/run-fail-fulldeps", "run-fail", "run-fail-fulldeps"), + (true, "src/test/compile-fail-fulldeps", "compile-fail", "compile-fail-fulldeps"), + (true, "src/test/run-make", "run-make", "run-make"), + (true, "src/test/rustdoc", "rustdoc", "rustdoc"), + + (false, "src/test/pretty", "pretty", "pretty"), + (false, "src/test/run-pass/pretty", "pretty", "run-pass"), + (false, "src/test/run-fail/pretty", "pretty", "run-fail"), + (false, "src/test/run-pass-valgrind/pretty", "pretty", "run-pass-valgrind"), + (false, "src/test/run-pass-fulldeps/pretty", "pretty", "run-pass-fulldeps"), + (false, "src/test/run-fail-fulldeps/pretty", "pretty", "run-fail-fulldeps"), +]; + + impl<'a> Step<'a> for Compiletest<'a> { type Output = (); + const DEFAULT: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + // Note that this is general, while a few more cases are skipped inside + // run() itself. This is to avoid duplication across should_run and + // make_run. + COMPILETESTS.iter().any(|&(_, test_path, _, _)| { + path.ends_with(test_path) + }) + } + + fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { + let compiler = builder.compiler(builder.top_stage, host); + + let test = path.map(|path| { + COMPILETESTS.iter().find(|&&(_, test_path, _, _)| { + path.ends_with(test_path) + }).unwrap_or_else(|| { + panic!("make_run in compile test to receive test path, received {:?}", path); + }) + }); + + if let Some(test) = test { // specific test + builder.ensure(Compiletest { + compiler, target, mode: test.2, suite: test.3 + }); + } else { // default tests + for &(default, _, mode, suite) in COMPILETESTS { + if default { + builder.ensure(Compiletest { + compiler, target, mode, suite + }); + } + } + } + } /// Executes the `compiletest` tool to run a suite of tests. /// @@ -418,12 +528,58 @@ impl<'a> Step<'a> for Compiletest<'a> { let target = self.target; let mode = self.mode; let suite = self.suite; + + // Skip codegen tests if they aren't enabled in configuration. + if !build.config.codegen_tests && suite == "codegen" { + return; + } + + if suite == "debuginfo" { + if mode == "debuginfo-XXX" { + return if build.build.contains("apple") { + builder.ensure(Compiletest { + mode: "debuginfo-lldb", + ..self + }) + } else { + builder.ensure(Compiletest { + mode: "debuginfo-gdb", + ..self + }) + }; + } + + // Skip debuginfo tests on MSVC + if build.build.contains("msvc") { + return; + } + + builder.ensure(dist::DebuggerScripts { + sysroot: &builder.sysroot(compiler), + host: compiler.host + }); + } + + if suite.ends_with("fulldeps") || + // FIXME: Does pretty need librustc compiled? Note that there are + // fulldeps test suites with mode = pretty as well. + mode == "pretty" || + mode == "rustdoc" || + mode == "run-make" { + builder.ensure(compile::Rustc { compiler, target }); + } + + builder.ensure(compile::Test { compiler, target }); + builder.ensure(native::TestHelpers { target }); + + if mode == "debuginfo-gdb" { + builder.ensure(RemoteCopyLibs { compiler, target }); + } + let _folder = build.fold_output(|| format!("test_{}", suite)); println!("Check compiletest suite={} mode={} ({} -> {})", suite, mode, compiler.host, target); - let mut cmd = Command::new(build.tool(&Compiler::new(0, compiler.host), - "compiletest")); - build.prepare_tool_cmd(compiler, &mut cmd); + let mut cmd = builder.tool_cmd(Tool::Compiletest); // compiletest currently has... a lot of arguments, so let's just pass all // of them! @@ -518,9 +674,7 @@ impl<'a> Step<'a> for Compiletest<'a> { } if build.remote_tested(target) { - cmd.arg("--remote-test-client") - .arg(build.tool(&Compiler::new(0, &build.build), - "remote-test-client")); + cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient)); } // Running a C compiler on MSVC requires a few env vars to be set, to be @@ -614,6 +768,18 @@ pub struct ErrorIndex<'a> { impl<'a> Step<'a> for ErrorIndex<'a> { type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/tools/error_index_generator") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { + builder.ensure(ErrorIndex { + compiler: builder.compiler(builder.top_stage, host), + }); + } /// Run the error index generator tool to execute the tests located in the error /// index. @@ -625,6 +791,8 @@ impl<'a> Step<'a> for ErrorIndex<'a> { let build = builder.build; let compiler = self.compiler; + builder.ensure(compile::Std { compiler, target: compiler.host }); + let _folder = build.fold_output(|| "test_error_index"); println!("Testing error-index stage{}", compiler.stage); @@ -633,8 +801,7 @@ impl<'a> Step<'a> for ErrorIndex<'a> { let output = dir.join("error-index.md"); let _time = util::timeit(); - build.run(build.tool_cmd(&Compiler::new(0, compiler.host), - "error_index_generator") + build.run(build.tool_cmd(Tool::ErrorIndex) .arg("markdown") .arg(&output) .env("CFG_BUILD", &build.build)); @@ -669,6 +836,86 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { } } +// for (krate, path, _default) in krates("rustc-main") { +// rules.test(&krate.test_step, path) +// .dep(|s| s.name("librustc")) +// .dep(|s| s.name("remote-copy-libs")) +// .host(true) +// .run(move |s| check::krate(build, &s.compiler(), s.target, +// Mode::Librustc, TestKind::Test, +// Some(&krate.name))); +// } +// rules.test("check-rustc-all", "path/to/nowhere") +// .dep(|s| s.name("librustc")) +// .dep(|s| s.name("remote-copy-libs")) +// .default(true) +// .host(true) +// .run(move |s| check::krate(build, &s.compiler(), s.target, +// Mode::Librustc, TestKind::Test, None)); +#[derive(Serialize)] +pub struct KrateLibrustc<'a> { + compiler: Compiler<'a>, + target: &'a str, + test_kind: TestKind, + krate: Option<&'a str>, +} + +impl<'a> Step<'a> for KrateLibrustc<'a> { + type Output = (); + const NAME: &'static str = "check librustc"; + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(builder: &Builder, path: &Path) -> bool { + builder.crates("rustc-main").into_iter().any(|(_, krate_path)| { + path.ends_with(krate_path) + }) + } + + fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { + let compiler = builder.compiler(builder.top_stage, host); + + let run = |name: Option<&str>| { + let test_kind = if builder.kind == Kind::Test { + TestKind::Test + } else if builder.kind == Kind::Bench { + TestKind::Bench + } else { + panic!("unexpected builder.kind in Krate: {:?}", builder.kind); + }; + + builder.ensure(KrateLibrustc { + compiler, + target, + test_kind: test_kind, + krate: name, + }); + }; + + if let Some(path) = path { + for (name, krate_path) in builder.crates("rustc-main") { + if path.ends_with(krate_path) { + run(Some(name)); + } + } + } else { + run(None); + } + } + + + fn run(self, builder: &Builder) { + builder.ensure(Krate { + compiler: self.compiler, + target: self.target, + mode: Mode::Librustc, + test_kind: self.test_kind, + krate: self.krate, + }); + } +} + + // for (krate, path, _default) in krates("std") { // rules.test(&krate.test_step, path) // .dep(|s| s.name("libtest")) @@ -714,22 +961,6 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { // .default(true) // .run(move |s| check::krate(build, &s.compiler(), s.target, // Mode::Libtest, TestKind::Test, None)); -// for (krate, path, _default) in krates("rustc-main") { -// rules.test(&krate.test_step, path) -// .dep(|s| s.name("librustc")) -// .dep(|s| s.name("remote-copy-libs")) -// .host(true) -// .run(move |s| check::krate(build, &s.compiler(), s.target, -// Mode::Librustc, TestKind::Test, -// Some(&krate.name))); -// } -// rules.test("check-rustc-all", "path/to/nowhere") -// .dep(|s| s.name("librustc")) -// .dep(|s| s.name("remote-copy-libs")) -// .default(true) -// .host(true) -// .run(move |s| check::krate(build, &s.compiler(), s.target, -// Mode::Librustc, TestKind::Test, None)); #[derive(Serialize)] pub struct Krate<'a> { @@ -742,6 +973,53 @@ pub struct Krate<'a> { impl<'a> Step<'a> for Krate<'a> { type Output = (); + const DEFAULT: bool = true; + + fn should_run(builder: &Builder, path: &Path) -> bool { + builder.crates("std").into_iter().any(|(_, krate_path)| { + path.ends_with(krate_path) + }) || + builder.crates("test").into_iter().any(|(_, krate_path)| { + path.ends_with(krate_path) + }) + } + + fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { + let compiler = builder.compiler(builder.top_stage, host); + + let run = |mode: Mode, name: Option<&str>| { + let test_kind = if builder.kind == Kind::Test { + TestKind::Test + } else if builder.kind == Kind::Bench { + TestKind::Bench + } else { + panic!("unexpected builder.kind in Krate: {:?}", builder.kind); + }; + + builder.ensure(Krate { + compiler, target, + mode: mode, + test_kind: test_kind, + krate: name, + }); + }; + + if let Some(path) = path { + for (name, krate_path) in builder.crates("std") { + if path.ends_with(krate_path) { + run(Mode::Libstd, Some(name)); + } + } + for (name, krate_path) in builder.crates("test") { + if path.ends_with(krate_path) { + run(Mode::Libtest, Some(name)); + } + } + } else { + run(Mode::Libstd, None); + run(Mode::Libtest, None); + } + } /// Run all unit tests plus documentation tests for an entire crate DAG defined /// by a `Cargo.toml` @@ -759,6 +1037,8 @@ impl<'a> Step<'a> for Krate<'a> { let test_kind = self.test_kind; let krate = self.krate; + builder.ensure(compile::Test { compiler, target }); + builder.ensure(RemoteCopyLibs { compiler, target }); let (name, path, features, root) = match mode { Mode::Libstd => { ("libstd", "src/libstd", build.std_features(), "std") @@ -782,7 +1062,7 @@ impl<'a> Step<'a> for Krate<'a> { // stage1. Reflect that here by updating the compiler that we're working // with automatically. let compiler = if build.force_use_stage1(compiler, target) { - Compiler::new(1, compiler.host) + builder.compiler(1, compiler.host) } else { compiler.clone() }; @@ -855,7 +1135,7 @@ impl<'a> Step<'a> for Krate<'a> { krate_emscripten(build, &compiler, target, mode); } else if build.remote_tested(target) { build.run(&mut cargo); - krate_remote(build, &compiler, target, mode); + krate_remote(builder, &compiler, target, mode); } else { cargo.args(&build.flags.cmd.test_args()); try_run(build, &mut cargo); @@ -882,15 +1162,14 @@ fn krate_emscripten(build: &Build, } } -fn krate_remote(build: &Build, +fn krate_remote(build: &Builder, compiler: &Compiler, target: &str, mode: Mode) { let out_dir = build.cargo_out(compiler, mode, target); let tests = find_tests(&out_dir.join("deps"), target); - let tool = build.tool(&Compiler::new(0, &build.build), - "remote-test-client"); + let tool = builder.tool_exe(Tool::RemoteTestClient); for test in tests { let mut cmd = Command::new(&tool); cmd.arg("run") @@ -968,15 +1247,17 @@ impl<'a> Step<'a> for RemoteCopyLibs<'a> { return } + builder.ensure(compile::Test { compiler, target }); + println!("REMOTE copy libs to emulator ({})", target); t!(fs::create_dir_all(build.out.join("tmp"))); - let server = build.cargo_out(compiler, Mode::Tool, target) - .join(exe("remote-test-server", target)); + // FIXME: This builds the tool for the native build triple + // (build.build); that is probably wrong. Should build for target. + let server = builder.tool_exe(Tool::RemoteTestServer); // Spawn the emulator and wait for it to come online - let tool = build.tool(&Compiler::new(0, &build.build), - "remote-test-client"); + let tool = builder.tool_exe(Tool::RemoteTestClient); let mut cmd = Command::new(&tool); cmd.arg("spawn-emulator") .arg(target) @@ -1025,6 +1306,9 @@ impl<'a> Step<'a> for Distcheck { return } + builder.ensure(dist::PlainSourceTarball); + builder.ensure(dist::Src); + println!("Distcheck"); let dir = build.out.join("tmp").join("distcheck"); let _ = fs::remove_dir_all(&dir); @@ -1077,6 +1361,9 @@ pub struct Bootstrap; impl<'a> for Step<'a> Bootstrap { type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + const ONLY_BUILD: bool = true; /// Test the build system itself fn run(self, builder: &Builder) { @@ -1093,4 +1380,12 @@ impl<'a> for Step<'a> Bootstrap { cmd.arg("--").args(&build.flags.cmd.test_args()); try_run(build, &mut cmd); } + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/bootstrap") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, _target: &str) { + builder.ensure(Bootstrap); + } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index cf1e11f7ac820..07a0f63e6cb92 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -129,6 +129,9 @@ fn crate_rule<'a, 'b>(build: &'a Build, rule } +// rules.build("libstd", "src/libstd") +// .dep(|s| s.name("rustc").target(s.host)) +// .dep(|s| s.name("libstd-link")); // for (krate, path, _default) in krates("std") { // rules.build(&krate.build_step, path) // .dep(|s| s.name("startup-objects")) @@ -143,6 +146,21 @@ pub struct Std<'a> { impl<'a> Step<'a> for Std<'a> { type Output = (); + const DEFAULT: bool = true; + + fn should_run(builder: &Builder, path: &Path) -> bool { + path.ends_with("src/libstd") || + builder.crates("std").into_iter().any(|(_, krate_path)| { + path.ends_with(krate_path) + }) + } + + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + builder.ensure(Std { + compiler: builder.compiler(builder.top_stage, host), + target, + }) + } /// Build the standard library. /// @@ -153,8 +171,23 @@ impl<'a> Step<'a> for Std<'a> { let build = builder.build; let target = self.target; let compiler = self.compiler; - let libdir = build.sysroot_libdir(compiler, target); - t!(fs::create_dir_all(&libdir)); + + builder.ensure(StartupObjects { compiler, target }); + + if build.force_use_stage1(compiler, target) { + let from = builder.compiler(1, &build.build); + builder.ensure(Std { + compiler: from, + target: target, + }); + println!("Uplifting stage1 std ({} -> {})", from.host, target); + builder.ensure(StdLink { + compiler: from, + target_compiler: compiler, + target: target, + }); + return; + } let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); println!("Building stage{} std artifacts ({} -> {})", compiler.stage, @@ -162,7 +195,7 @@ impl<'a> Step<'a> for Std<'a> { let out_dir = build.cargo_out(compiler, Mode::Libstd, target); build.clear_if_dirty(&out_dir, &build.compiler_path(compiler)); - let mut cargo = build.cargo(compiler, Mode::Libstd, target, "build"); + let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "build"); let mut features = build.std_features(); if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { @@ -188,6 +221,7 @@ impl<'a> Step<'a> for Std<'a> { // config.toml equivalent) is used cargo.env("LLVM_CONFIG", build.llvm_config(target)); } + cargo.arg("--features").arg(features) .arg("--manifest-path") .arg(build.src.join("src/libstd/Cargo.toml")); @@ -206,6 +240,12 @@ impl<'a> Step<'a> for Std<'a> { run_cargo(build, &mut cargo, &libstd_stamp(build, &compiler, target)); + + builder.ensure(StdLink { + compiler: builder.compiler(compiler.stage, &build.build), + target_compiler: compiler, + target: target, + }); } } @@ -219,7 +259,7 @@ impl<'a> Step<'a> for Std<'a> { // .dep(|s| s.name("create-sysroot").target(s.host)); #[derive(Serialize)] -pub struct StdLink<'a> { +struct StdLink<'a> { pub compiler: Compiler<'a>, pub target_compiler: Compiler<'a>, pub target: &'a str, @@ -297,6 +337,17 @@ pub struct StartupObjects<'a> { impl<'a> Step<'a> for StartupObjects<'a> { type Output = (); + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/rtstartup") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + builder.ensure(StartupObjects { + compiler: builder.compiler(builder.top_stage, host), + target, + }) + } + /// Build and prepare startup objects like rsbegin.o and rsend.o /// /// These are primarily used on Windows right now for linking executables/dlls. @@ -354,6 +405,21 @@ pub struct Test<'a> { impl<'a> Step<'a> for Test<'a> { type Output = (); + const DEFAULT: bool = true; + + fn should_run(builder: &Builder, path: &Path) -> bool { + path.ends_with("src/libtest") || + builder.crates("test").into_iter().any(|(_, krate_path)| { + path.ends_with(krate_path) + }) + } + + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + builder.ensure(Test { + compiler: builder.compiler(builder.top_stage, host), + target, + }) + } /// Build libtest. /// @@ -364,6 +430,23 @@ impl<'a> Step<'a> for Test<'a> { let build = builder.build; let target = self.target; let compiler = self.compiler; + + builder.ensure(Std { compiler, target }); + + if build.force_use_stage1(compiler, target) { + builder.ensure(Test { + compiler: builder.compiler(1, &build.build), + target: target, + }); + println!("Uplifting stage1 test ({} -> {})", &build.build, target); + builder.ensure(TestLink { + compiler: builder.compiler(1, &build.build), + target_compiler: compiler, + target: target, + }); + return; + } + let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); println!("Building stage{} test artifacts ({} -> {})", compiler.stage, compiler.host, target); @@ -378,6 +461,12 @@ impl<'a> Step<'a> for Test<'a> { run_cargo(build, &mut cargo, &libtest_stamp(build, compiler, target)); + + builder.ensure(TestLink { + compiler: builder.compiler(1, &build.build), + target_compiler: compiler, + target: target, + }); } } @@ -432,6 +521,22 @@ pub struct Rustc<'a> { impl<'a> Step<'a> for Rustc<'a> { type Output = (); + const ONLY_HOSTS: bool = true; + const DEFAULT: bool = true; + + fn should_run(builder: &Builder, path: &Path) -> bool { + path.ends_with("src/librustc") || + builder.crates("rustc-main").into_iter().any(|(_, krate_path)| { + path.ends_with(krate_path) + }) + } + + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + builder.ensure(Rustc { + compiler: builder.compiler(builder.top_stage, host), + target, + }) + } /// Build the compiler. /// @@ -442,6 +547,33 @@ impl<'a> Step<'a> for Rustc<'a> { let build = builder.build; let compiler = self.compiler; let target = self.target; + + builder.ensure(Test { compiler, target }); + + // Build LLVM for our target. This will implicitly build the host LLVM + // if necessary. + builder.ensure(native::Llvm { target }); + + if build.force_use_stage1(compiler, target) { + builder.ensure(Rustc { + compiler: builder.compiler(1, &build.build), + target: target, + }); + println!("Uplifting stage1 rustc ({} -> {})", &build.build, target); + builder.ensure(RustcLink { + compiler: builder.compiler(1, &build.build), + target_compiler: compiler, + target, + }); + return; + } + + // Ensure that build scripts have a std to link against. + builder.ensure(Std { + compiler: builder.compiler(self.compiler.stage, &build.build), + target: &build.build, + }); + let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); println!("Building stage{} compiler artifacts ({} -> {})", compiler.stage, compiler.host, target); @@ -513,6 +645,12 @@ impl<'a> Step<'a> for Rustc<'a> { run_cargo(build, &mut cargo, &librustc_stamp(build, compiler, target)); + + builder.ensure(RustcLink { + compiler: builder.compiler(compiler.stage, &build.build), + target_compiler: compiler, + target, + }); } } @@ -523,7 +661,7 @@ impl<'a> Step<'a> for Rustc<'a> { // compile::rustc_link) // .dep(|s| s.name("libtest-link")); #[derive(Serialize)] -pub struct RustcLink<'a> { +struct RustcLink<'a> { pub compiler: Compiler<'a>, pub target_compiler: Compiler<'a>, pub target: &'a str, @@ -551,19 +689,19 @@ impl<'a> Step<'a> for RustcLink<'a> { /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. -fn libstd_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf { +pub fn libstd_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf { build.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp") } /// Cargo's output path for libtest in a given stage, compiled by a particular /// compiler for the specified target. -fn libtest_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf { +pub fn libtest_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf { build.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp") } /// Cargo's output path for librustc in a given stage, compiled by a particular /// compiler for the specified target. -fn librustc_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf { +pub fn librustc_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf { build.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp") } @@ -582,7 +720,7 @@ pub struct Sysroot<'a> { } impl<'a> Step<'a> for Sysroot<'a> { - type Output = (); + type Output = PathBuf; /// Returns the sysroot for the `compiler` specified that *this build system /// generates*. @@ -590,12 +728,17 @@ impl<'a> Step<'a> for Sysroot<'a> { /// That is, the sysroot for the stage0 compiler is not what the compiler /// thinks it is by default, but it's the same as the default for stages /// 1-3. - fn run(self, builder: &Builder) { + fn run(self, builder: &Builder) -> PathBuf { let build = builder.build; let compiler = self.compiler; - let sysroot = build.sysroot(compiler); + let sysroot = if compiler.stage == 0 { + build.out.join(compiler.host).join("stage0-sysroot") + } else { + build.out.join(compiler.host).join(format!("stage{}", compiler.stage)) + }; let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot)); + sysroot } } @@ -615,8 +758,11 @@ impl<'a> Step<'a> for Sysroot<'a> { #[derive(Serialize)] pub struct Assemble<'a> { - pub stage: u32, - pub host: &'a str, + /// The compiler which we will produce in this step. Assemble itself will + /// take care of ensuring that the necessary prerequisites to do so exist, + /// that is, this target can be a stage2 compiler and Assemble will build + /// previous stages for you. + pub target_compiler: Compiler<'a>, } impl<'a> Step<'a> for Assemble<'a> { @@ -629,20 +775,48 @@ impl<'a> Step<'a> for Assemble<'a> { /// compiler. fn run(self, builder: &Builder) { let build = builder.build; - let stage = self.stage; - let host = self.host; - // nothing to do in stage0 - if stage == 0 { - return + let target_compiler = self.target_compiler; + + if target_compiler.stage == 0 { + assert_eq!(build.build, target_compiler.host, + "Cannot obtain compiler for non-native build triple at stage 0"); + // The stage 0 compiler for the build triple is always pre-built. + return target_compiler; } - println!("Copying stage{} compiler ({})", stage, host); + // Get the compiler that we'll use to bootstrap ourselves. + let build_compiler = if target_compiler.host != build.build { + // Build a compiler for the host platform. We cannot use the stage0 + // compiler for the host platform for this because it doesn't have + // the libraries we need. FIXME: Perhaps we should download those + // libraries? It would make builds faster... + builder.ensure(Assemble { + target_compiler: Compiler { + // FIXME: It may be faster if we build just a stage 1 + // compiler and then use that to bootstrap this compiler + // forward. + stage: target_compiler.stage - 1, + host: &build.build + }, + }) + } else { + // Build the compiler we'll use to build the stage requested. This + // may build more than one compiler (going down to stage 0). + builder.ensure(Assemble { + target_compiler: target_compiler.with_stage(target_compiler.stage - 1), + }) + }; - // The compiler that we're assembling - let target_compiler = Compiler::new(stage, host); + // Build the libraries for this compiler to link to (i.e., the libraries + // it uses at runtime). NOTE: Crates the target compiler compiles don't + // link to these. (FIXME: Is that correct? It seems to be correct most + // of the time but I think we do link to these for stage2/bin compilers + // when not performing a full bootstrap). + builder.ensure(Rustc { compiler: build_compiler, target: target_compiler.host }); - // The compiler that compiled the compiler we're assembling - let build_compiler = Compiler::new(stage - 1, &build.build); + let stage = target_compiler.stage; + let host = target_compiler.host; + println!("Assembling stage{} compiler ({})", stage, host); // Link in all dylibs to the libdir let sysroot = build.sysroot(&target_compiler); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 8aa9ad7021e6f..da513b1f2f669 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -76,6 +76,19 @@ pub struct Docs<'a> { impl<'a> Step<'a> for Docs<'a> { type Output = (); + const DEFAULT: bool = true; + const ONLY_BUILD_TARGETS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/doc") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + builder.ensure(Docs { + stage: builder.top_stage, + host: target, + }); + } /// Builds the `rust-docs` installer component. /// @@ -85,6 +98,8 @@ impl<'a> Step<'a> for Docs<'a> { let stage = self.stage; let host = self.host; + builder.default_doc(None); + println!("Dist docs stage{} ({})", stage, host); if !build.config.docs { println!("\tskipping - docs disabled"); @@ -268,6 +283,18 @@ pub struct Mingw<'a> { impl<'a> Step<'a> for Mingw<'a> { type Output = (); + const DEFAULT: bool = true; + const ONLY_BUILD_TARGETS: bool = true; + + fn should_run(_builder: &Builder, _path: &Path) -> bool { + false + } + + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { + builder.ensure(Mingw { + host: host, + }); + } /// Build the `rust-mingw` installer component. /// @@ -276,6 +303,11 @@ impl<'a> Step<'a> for Mingw<'a> { fn run(self, builder: &Builder) { let build = builder.build; let host = self.host; + + if !host.contains("pc-windows-gnu") { + return; + } + println!("Dist mingw ({})", host); let name = pkgname(build, "rust-mingw"); let image = tmpdir(build).join(format!("{}-{}-image", name, host)); @@ -320,6 +352,20 @@ pub struct Rustc<'a> { impl<'a> Step<'a> for Rustc<'a> { type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + const ONLY_BUILD_TARGETS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/librustc") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { + builder.ensure(Rustc { + stage: builder.top_stage, + host: host, + }); + } /// Creates the `rustc` installer component. fn run(self, builder: &builder) { @@ -334,7 +380,7 @@ impl<'a> Step<'a> for Rustc<'a> { let _ = fs::remove_dir_all(&overlay); // Prepare the rustc "image", what will actually end up getting installed - prepare_image(build, stage, host, &image); + prepare_image(builder, stage, host, &image); // Prepare the overlay which is part of the tarball but won't actually be // installed @@ -384,8 +430,9 @@ impl<'a> Step<'a> for Rustc<'a> { t!(fs::remove_dir_all(&image)); t!(fs::remove_dir_all(&overlay)); - fn prepare_image(build: &Build, stage: u32, host: &str, image: &Path) { - let src = build.sysroot(&Compiler::new(stage, host)); + fn prepare_image(builder: &Builder, stage: u32, host: &str, image: &Path) { + let build = builder.build; + let src = build.sysroot(builder.compiler(stage, host)); let libdir = libdir(host); // Copy rustc/rustdoc binaries @@ -409,7 +456,10 @@ impl<'a> Step<'a> for Rustc<'a> { cp_r(&build.src.join("man"), &image.join("share/man/man1")); // Debugger scripts - debugger_scripts(build, &image, host); + builder.ensure(DebuggerScripts { + sysroot: &image, + host: host, + }); // Misc license info let cp = |file: &str| { @@ -423,8 +473,6 @@ impl<'a> Step<'a> for Rustc<'a> { } } - - //rules.test("debugger-scripts", "src/etc/lldb_batchmode.py") // .run(move |s| dist::debugger_scripts(build, &build.sysroot(&s.compiler()), // s.target)); @@ -438,6 +486,18 @@ pub struct DebuggerScripts<'a> { impl<'a> Step<'a> for DebuggerScripts<'a> { type Output = (); + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/etc/lldb_batchmode.py") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { + builder.ensure(DebuggerScripts { + // FIXME: builder.top_stage is likely wrong in some cases. + sysroot: &builder.sysroot(builder.compiler(builder.top_stage, host)), + host: host, + }); + } + /// Copies debugger scripts for `host` into the `sysroot` specified. fn run(self, builder: &Builder) { let build = builder.build; @@ -542,6 +602,22 @@ pub struct Analysis<'a> { impl<'a> Step<'a> for Analysis<'a> { type Output = (); + const DEFAULT: bool = true; + const ONLY_BUILD_TARGETS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("analysis") + } + + fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { + if path.is_none() && !builder.build.config.extended { + return; + } + builder.ensure(Analysis { + compiler: builder.compiler(builder.top_stage, host), + target: target, + }); + } /// Creates a tarball of save-analysis metadata, if available. fn run(self, builder: &Builder) { @@ -559,7 +635,7 @@ impl<'a> Step<'a> for Analysis<'a> { // Package save-analysis from stage1 if not doing a full bootstrap, as the // stage2 artifacts is simply copied from stage1 in that case. let compiler = if build.force_use_stage1(compiler, target) { - Compiler::new(1, compiler.host) + builder.compiler(1, compiler.host) } else { compiler.clone() }; @@ -567,7 +643,8 @@ impl<'a> Step<'a> for Analysis<'a> { let name = pkgname(build, "rust-analysis"); let image = tmpdir(build).join(format!("{}-{}-image", name, target)); - let src = build.stage_out(&compiler, Mode::Libstd).join(target).join("release").join("deps"); + let src = build.stage_out(compiler, Mode::Libstd) + .join(target).join("release").join("deps"); let image_src = src.join("save-analysis"); let dst = image.join("lib/rustlib").join(target).join("analysis"); @@ -644,6 +721,18 @@ pub struct Src; impl<'a> Step<'a> for Src { type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + const ONLY_BUILD_TARGETS: bool = true; + const ONLY_BUILD: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, _target: &str) { + builder.ensure(Src); + } /// Creates the `rust-src` installer component fn run(self, builder: &Builder) { @@ -727,6 +816,22 @@ pub struct PlainSourceTarball; impl<'a> Step<'a> for PlainSourceTarball { type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + const ONLY_BUILD_TARGETS: bool = true; + const ONLY_BUILD: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src") + } + + fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, _target: &str) { + if path.is_none() && !builder.build.config.rust_dist_src { + return; + } + + builder.ensure(PlainSourceTarball); + } /// Creates the plain source tarball fn run(self, builder: &Builder) { @@ -862,13 +967,29 @@ pub struct Cargo<'a> { impl<'a> Step<'a> for Cargo<'a> { type Output = (); + const ONLY_BUILD_TARGETS: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("cargo") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + builder.ensure(Cargo { + stage: builder.top_stage, + target: target, + }); + } fn run(self, builder: &Builder) { let build = builder.build; let stage = self.stage; let target = self.target; + + builder.ensure(tool::Cargo { stage, target }); + println!("Dist cargo stage{} ({})", stage, target); - let compiler = Compiler::new(stage, &build.build); + let compiler = builder.compiler(stage, &build.build); let src = build.src.join("src/tools/cargo"); let etc = src.join("src/etc"); @@ -941,14 +1062,30 @@ pub struct Rls<'a> { impl<'a> Step<'a> for Rls<'a> { type Output = (); + const ONLY_BUILD_TARGETS: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("rls") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + builder.ensure(Rls { + stage: builder.top_stage, + target: target, + }); + } fn run(self, builder: &Builder) { let build = builder.build; let stage = self.stage; let target = self.target; assert!(build.config.extended); + + builder.ensure(tool::Rls { stage, target }); + println!("Dist RLS stage{} ({})", stage, target); - let compiler = Compiler::new(stage, &build.build); + let compiler = builder.compiler(stage, &build.build); let src = build.src.join("src/tools/rls"); let release_num = build.release_num("rls"); @@ -1017,12 +1154,38 @@ pub struct Extended<'a> { impl<'a> Step<'a> for Extended<'a> { type Output = (); + const DEFAULT: bool = true; + const ONLY_BUILD_TARGETS: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("cargo") + } + + fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { + if path.is_none() && !builder.build.config.extended { + return; + } + builder.ensure(Extended { + compiler: builder.compiler(builder.top_stage, host), + target: target, + }); + } /// Creates a combined installer for the specified target in the provided stage. fn run(self, builder: &Builder) { let build = builder.build; let stage = self.stage; let target = self.target; + let compiler = builder.compiler(stage, &build.build); + + builder.ensure(Std { compiler, target }); + builder.ensure(Rustc { stage, host }); + builder.ensure(Mingw { host }); + builder.ensure(Docs { stage, host }); + builder.ensure(Cargo { stage, target }); + builder.ensure(Rls { stage, target }); + builder.ensure(Analysis { compiler, target }); println!("Dist extended stage{} ({})", stage, target); @@ -1420,11 +1583,21 @@ pub struct HashSign; impl<'a> Step<'a> for HashSign { type Output = (); + const ONLY_BUILD_TARGETS: bool = true; + const ONLY_HOSTS: bool = true; + const ONLY_BUILD: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("hash-and-sign") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, _target: &str) { + builder.ensure(HashSign); + } fn run(self, builder: &Builder) { let build = builder.build; - let compiler = Compiler::new(0, &build.build); - let mut cmd = build.tool_cmd(&compiler, "build-manifest"); + let mut cmd = builder.tool_cmd(Tool::BuildManifest); let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| { panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n") }); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 466d63a15acbd..11edee6234459 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -27,27 +27,70 @@ use {Build, Compiler, Mode}; use util::{cp_r, symlink_dir}; use build_helper::up_to_date; -// rules.doc("doc-nomicon", "src/doc/nomicon") -// .dep(move |s| { -// s.name("tool-rustbook") -// .host(&build.build) -// .target(&build.build) -// .stage(0) -// }) -// .default(build.config.docs) -// .run(move |s| doc::rustbook(build, s.target, "nomicon")); -// rules.doc("doc-reference", "src/doc/reference") -// .dep(move |s| { -// s.name("tool-rustbook") -// .host(&build.build) -// .target(&build.build) -// .stage(0) -// }) -// .default(build.config.docs) -// .run(move |s| doc::rustbook(build, s.target, "reference")); +macro_rules! book { + ($($name:ident, $path:expr, $book_name:expr;)+) => { + $( + #[derive(Serialize)] + pub struct $name<'a> { + target: &'a str, + } + + impl<'a> Step<'a> for $name<'a> { + type Output = (); + const NAME: &'static str = concat!(stringify!($book_name), " - book"); + const DEFAULT: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with($path) + } + + fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + if path.is_none() && !builder.build.config.docs { + // Not a default rule if docs are disabled. + return; + } + + builder.ensure($name { + target, + }); + } + + fn run(self, builder: &Builder) { + builder.ensure(Rustbook { + target: self.target, + name: $book_name, + }) + } + } + )+ + } +} + +book!( + // rules.doc("doc-nomicon", "src/doc/nomicon") + // .dep(move |s| { + // s.name("tool-rustbook") + // .host(&build.build) + // .target(&build.build) + // .stage(0) + // }) + // .default(build.config.docs) + // .run(move |s| doc::rustbook(build, s.target, "nomicon")); + Nomicon, "src/doc/book", "nomicon"; + // rules.doc("doc-reference", "src/doc/reference") + // .dep(move |s| { + // s.name("tool-rustbook") + // .host(&build.build) + // .target(&build.build) + // .stage(0) + // }) + // .default(build.config.docs) + // .run(move |s| doc::rustbook(build, s.target, "reference")); + Reference, "src/doc/reference", "reference"; +); #[derive(Serialize)] -pub struct Rustbook<'a> { +struct Rustbook<'a> { target: &'a str, name: &'a str, } @@ -60,11 +103,12 @@ impl<'a> Step<'a> for Rustbook<'a> { /// This will not actually generate any documentation if the documentation has /// already been generated. fn run(self, builder: &Builder) { - let build = builder.build; - let target = self.target; - let name = self.name; - let src = build.src.join("src/doc"); - rustbook_src(build, target, name, &src); + let src = builder.build.src.join("src/doc"); + builder.ensure(RustbookSrc { + target: self.target, + name: self.name, + src: &src, + }); } } @@ -81,6 +125,42 @@ impl<'a> Step<'a> for Rustbook<'a> { // s.target, // "unstable-book", // &build.md_doc_out(s.target))); +#[derive(Serialize)] +pub struct UnstableBook<'a> { + target: &'a str, +} + +impl<'a> Step<'a> for UnstableBook<'a> { + type Output = (); + const NAME: &'static str = "unstable book documentation"; + const DEFAULT: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/doc/unstable-book") + } + + fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + if path.is_none() && !builder.build.config.docs { + // Not a default rule if docs are disabled. + return; + } + + builder.ensure(UnstableBook { + target, + }); + } + + fn run(self, builder: &Builder) { + builder.ensure(UnstableBookGen { + target: self.target, + }); + builder.ensure(RustbookSrc { + target: self.target, + name: "unstable-book", + src: &builder.build.md_doc_out(self.target), + }) + } +} #[derive(Serialize)] pub struct RustbookSrc<'a> { @@ -105,16 +185,15 @@ impl<'a> Step<'a> for RustbookSrc<'a> { t!(fs::create_dir_all(&out)); let out = out.join(name); - let compiler = Compiler::new(0, &build.build); let src = src.join(name); let index = out.join("index.html"); - let rustbook = build.tool(&compiler, "rustbook"); + let rustbook = builder.tool_exe(Tool::Rustbook); if up_to_date(&src, &index) && up_to_date(&rustbook, &index) { return } println!("Rustbook ({}) - {}", target, name); let _ = fs::remove_dir_all(&out); - build.run(build.tool_cmd(&compiler, "rustbook") + build.run(builder.tool_cmd(Tool::Rustbook) .arg("build") .arg(&src) .arg("-d") @@ -154,10 +233,16 @@ impl<'a> Step<'a> for TheBook<'a> { let target = self.target; let name = self.name; // build book first edition - rustbook(build, target, &format!("{}/first-edition", name)); + builder.ensure(Rustbook { + target: target, + name: &format!("{}/first-edition", name), + }); // build book second edition - rustbook(build, target, &format!("{}/second-edition", name)); + builder.ensure(Rustbook { + target: target, + name: &format!("{}/second-edition", name), + }); // build the index page let index = format!("{}/index.md", name); @@ -238,6 +323,22 @@ pub struct Standalone<'a> { impl<'a> Step<'a> for Standalone<'a> { type Output = (); + const DEFAULT: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/doc") + } + + fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + if path.is_none() && !builder.build.config.docs { + // Not a default rule if docs are disabled. + return; + } + + builder.ensure(Standalone { + target, + }); + } /// Generates all standalone documentation as compiled by the rustdoc in `stage` /// for the `target` into `out`. @@ -254,7 +355,7 @@ impl<'a> Step<'a> for Standalone<'a> { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(0, &build.build); + let compiler = builder.compiler(0, &build.build); let favicon = build.src.join("src/doc/favicon.inc"); let footer = build.src.join("src/doc/footer.inc"); @@ -329,6 +430,34 @@ pub struct Std<'a> { impl<'a> Step<'a> for Std<'a> { type Output = (); + const DEFAULT: bool = true; + + fn should_run(builder: &Builder, path: &Path) -> bool { + builder.crates("std").into_iter().any(|(_, krate_path)| { + path.ends_with(krate_path) + }) + } + + fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + let run = || { + builder.ensure(Std { + stage: builder.top_stage, + target + }); + }; + + if let Some(path) = path { + for (_, krate_path) in builder.crates("std") { + if path.ends_with(krate_path) { + run(); + } + } + } else { + if builder.build.config.docs { + run(); + } + } + } /// Compile all standard library documentation. /// @@ -341,12 +470,14 @@ impl<'a> Step<'a> for Std<'a> { println!("Documenting stage{} std ({})", stage, target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.build); - let compiler = if build.force_use_stage1(&compiler, target) { - Compiler::new(1, compiler.host) + let compiler = builder.compiler(stage, &build.build); + let compiler = if build.force_use_stage1(compiler, target) { + builder.compiler(1, compiler.host) } else { compiler }; + + builder.ensure(compile::Std { compiler, target }); let out_dir = build.stage_out(&compiler, Mode::Libstd) .join(target).join("doc"); let rustdoc = build.rustdoc(&compiler); @@ -410,6 +541,34 @@ pub struct Test<'a> { impl<'a> Step<'a> for Test<'a> { type Output = (); + const DEFAULT: bool = true; + + fn should_run(builder: &Builder, path: &Path) -> bool { + builder.crates("test").into_iter().any(|(_, krate_path)| { + path.ends_with(krate_path) + }) + } + + fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + let run = || { + builder.ensure(Test { + stage: builder.top_stage, + target + }); + }; + + if let Some(path) = path { + for (_, krate_path) in builder.crates("test") { + if path.ends_with(krate_path) { + run(); + } + } + } else { + if builder.build.config.docs { + run(); + } + } + } /// Compile all libtest documentation. /// @@ -422,12 +581,17 @@ impl<'a> Step<'a> for Test<'a> { println!("Documenting stage{} test ({})", stage, target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.build); - let compiler = if build.force_use_stage1(&compiler, target) { - Compiler::new(1, compiler.host) + let compiler = builder.compiler(stage, &build.build); + let compiler = if build.force_use_stage1(compiler, target) { + builder.compiler(1, compiler.host) } else { compiler }; + + // Build libstd docs so that we generate relative links + builder.ensure(Std { stage, target }); + + builder.ensure(compile::Test { compiler, target }); let out_dir = build.stage_out(&compiler, Mode::Libtest) .join(target).join("doc"); let rustdoc = build.rustdoc(&compiler); @@ -464,6 +628,35 @@ pub struct Rustc<'a> { impl<'a> Step<'a> for Rustc<'a> { type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(builder: &Builder, path: &Path) -> bool { + builder.crates("rustc-main").into_iter().any(|(_, krate_path)| { + path.ends_with(krate_path) + }) + } + + fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + let run = || { + builder.ensure(Rustc { + stage: builder.top_stage, + target + }); + }; + + if let Some(path) = path { + for (_, krate_path) in builder.crates("rustc-main") { + if path.ends_with(krate_path) { + run(); + } + } + } else { + if builder.build.config.compiler_docs { + run(); + } + } + } /// Generate all compiler documentation. /// @@ -476,12 +669,17 @@ impl<'a> Step<'a> for Rustc<'a> { println!("Documenting stage{} compiler ({})", stage, target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(stage, &build.build); - let compiler = if build.force_use_stage1(&compiler, target) { - Compiler::new(1, compiler.host) + let compiler = builder.compiler(stage, &build.build); + let compiler = if build.force_use_stage1(compiler, target) { + builder.compiler(1, compiler.host) } else { compiler }; + + // Build libstd docs so that we generate relative links + builder.ensure(Std { stage, target }); + + builder.ensure(compile::Rustc { compiler, target }); let out_dir = build.stage_out(&compiler, Mode::Librustc) .join(target).join("doc"); let rustdoc = build.rustdoc(&compiler); @@ -530,17 +728,40 @@ pub struct ErrorIndex<'a> { impl<'a> Step<'a> for ErrorIndex<'a> { type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/tools/error_index_generator") + } + + fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + if path.is_none() && !builder.build.config.docs { + // Not a default rule if docs are disabled. + return; + } + + builder.ensure(ErrorIndex { + target, + }); + } /// Generates the HTML rendered error-index by running the /// `error_index_generator` tool. fn run(self, builder: &Builder) { let builder = builder.build; let target = self.target; + + builder.ensure(compile::Rustc { + compiler: builder.compiler(0, &build.build), + target, + }); + println!("Documenting error index ({})", target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let compiler = Compiler::new(0, &build.build); - let mut index = build.tool_cmd(&compiler, "error_index_generator"); + let mut index = builder.tool_cmd(Tool::ErrorIndex); index.arg("html"); index.arg(out.join("error-index.html")); @@ -570,10 +791,33 @@ pub struct UnstableBookGen<'a> { impl<'a> Step<'a> for UnstableBookGen<'a> { type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/doc/unstable-book") + } + + fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + if path.is_none() && !builder.build.config.docs { + // Not a default rule if docs are disabled. + return; + } + + builder.ensure(UnstableBookGen { + target, + }); + } fn run(self, builder: &Builder) { let build = builder.build; let target = self.target; + + builder.ensure(compile::Std { + compiler: builder.compiler(builder.top_stage, &build.build), + target, + }); + println!("Generating unstable book md files ({})", target); let out = build.md_doc_out(target).join("unstable-book"); t!(fs::create_dir_all(&out)); diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 638b0613bf2cc..3e895bbe90017 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -148,45 +148,124 @@ fn add_destdir(path: &Path, destdir: &Option) -> PathBuf { } ret } -/* -rules.install("install-docs", "src/doc") - .default(build.config.docs) - .only_host_build(true) - .dep(|s| s.name("dist-docs")) - .run(move |s| install::Installer::new(build).install_docs(s.stage, s.target)); -rules.install("install-std", "src/libstd") - .default(true) - .only_host_build(true) - .dep(|s| s.name("dist-std")) - .run(move |s| install::Installer::new(build).install_std(s.stage)); -rules.install("install-cargo", "cargo") - .default(build.config.extended) - .host(true) - .only_host_build(true) - .dep(|s| s.name("dist-cargo")) - .run(move |s| install::Installer::new(build).install_cargo(s.stage, s.target)); -rules.install("install-rls", "rls") - .default(build.config.extended) - .host(true) - .only_host_build(true) - .dep(|s| s.name("dist-rls")) - .run(move |s| install::Installer::new(build).install_rls(s.stage, s.target)); -rules.install("install-analysis", "analysis") - .default(build.config.extended) - .only_host_build(true) - .dep(|s| s.name("dist-analysis")) - .run(move |s| install::Installer::new(build).install_analysis(s.stage, s.target)); -rules.install("install-src", "src") - .default(build.config.extended) - .host(true) - .only_build(true) - .only_host_build(true) - .dep(|s| s.name("dist-src")) - .run(move |s| install::Installer::new(build).install_src(s.stage)); -rules.install("install-rustc", "src/librustc") - .default(true) - .host(true) - .only_host_build(true) - .dep(|s| s.name("dist-rustc")) - .run(move |s| install::Installer::new(build).install_rustc(s.stage, s.target)); -*/ + +macro_rules! install { + ($($name:ident, + $path:expr, + $default_cond:expr, + only_hosts: $only_hosts:expr, + ($sel:ident, $builder:ident), + $run_item:block $(, $c:ident)*;)+) => { + $(#[derive(Serialize)] + pub struct $name<'a> { + pub stage: u32, + pub target: &'a str, + pub host: &'a str, + } + + impl<'a> Step<'a> for $name<'a> { + type Output = (); + const NAME: &'static str = concat!("install ", stringify!($name)); + const DEFAULT: bool = true; + const ONLY_BUILD_TARGETS: bool = true; + const ONLY_HOSTS: bool = $only_hosts; + $(const $c: bool = true;)* + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with($path) + } + + fn make_run($builder: &Builder, path: Option<&Path>, host: &str, target: &str) { + if path.is_none() && !($default_cond) { + return; + } + $builder.ensure($name { + stage: $builder.top_stage, + target, + host, + }); + } + + fn run($sel, $builder: &Builder) { + $run_item + } + })+ + } +} + +install!( + // rules.install("install-docs", "src/doc") + // .default(build.config.docs) + // .only_host_build(true) + // .dep(|s| s.name("dist-docs")) + // .run(move |s| install::Installer::new(build).install_docs(s.stage, s.target)); + Docs, "src/doc", builder.build.config.docs, only_hosts: false, (self, builder), { + builder.ensure(dist::Docs { stage: self.stage, host: self.host }); + Installer::new(builder.build).install_docs(self.stage, self.target); + }; + // rules.install("install-std", "src/libstd") + // .default(true) + // .only_host_build(true) + // .dep(|s| s.name("dist-std")) + // .run(move |s| install::Installer::new(build).install_std(s.stage)); + Std, "src/libstd", true, only_hosts: true, (self, builder), { + builder.ensure(dist::Std { + compiler: builder.compiler(self.stage, self.host), + target: self.target + }); + Installer::new(builder.build).install_std(self.stage); + }; + // rules.install("install-cargo", "cargo") + // .default(build.config.extended) + // .host(true) + // .only_host_build(true) + // .dep(|s| s.name("dist-cargo")) + // .run(move |s| install::Installer::new(build).install_cargo(s.stage, s.target)); + Cargo, "cargo", builder.build.config.extended, only_hosts: true, (self, builder), { + builder.ensure(dist::Cargo { stage: self.stage, target: self.target }); + Installer::new(builder.build).install_cargo(self.stage, self.target); + }; + // rules.install("install-rls", "rls") + // .default(build.config.extended) + // .host(true) + // .only_host_build(true) + // .dep(|s| s.name("dist-rls")) + // .run(move |s| install::Installer::new(build).install_rls(s.stage, s.target)); + Rls, "rls", builder.build.config.extended, only_hosts: true, (self, builder), { + builder.ensure(dist::Rls { stage: self.stage, target: self.target }); + Installer::new(builder.build).install_rls(self.stage, self.target); + }; + // rules.install("install-analysis", "analysis") + // .default(build.config.extended) + // .only_host_build(true) + // .dep(|s| s.name("dist-analysis")) + // .run(move |s| install::Installer::new(build).install_analysis(s.stage, s.target)); + Analysis, "analysis", builder.build.config.extended, only_hosts: false, (self, builder), { + builder.ensure(dist::Analysis { + compiler: builder.compiler(self.stage, self.host), + target: self.target + }); + Installer::new(builder.build).install_analysis(self.stage, self.target); + }; + // rules.install("install-src", "src") + // .default(build.config.extended) + // .host(true) + // .only_build(true) + // .only_host_build(true) + // .dep(|s| s.name("dist-src")) + // .run(move |s| install::Installer::new(build).install_src(s.stage)); + Src, "src", builder.build.config.extended, only_hosts: true, (self, builder), { + builder.ensure(dist::Src); + Installer::new(builder.build).install_src(self.stage); + }, ONLY_BUILD; + // rules.install("install-rustc", "src/librustc") + // .default(true) + // .host(true) + // .only_host_build(true) + // .dep(|s| s.name("dist-rustc")) + // .run(move |s| install::Installer::new(build).install_rustc(s.stage, s.target)); + Rustc, "src/librustc", builder.build.config.extended, only_hosts: true, (self, builder), { + builder.ensure(dist::Rustc { stage: self.stage, host: self.host }); + Installer::new(builder.build).install_rustc(self.stage, self.target); + }; +); diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 6ae5c03bfeb4c..2b44f33db8e18 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -33,7 +33,7 @@ use Build; use util; use build_helper::up_to_date; -/j/ rules.build("llvm", "src/llvm") +// rules.build("llvm", "src/llvm") // .host(true) // .dep(move |s| { // if s.target == build.build { @@ -51,6 +51,7 @@ pub struct Llvm<'a> { impl<'a> Step<'a> for Llvm<'a> { type Output = (); + const ONLY_HOSTS: bool = true; /// Compile LLVM for `target`. fn run(self, builder: &Builder) { @@ -151,6 +152,7 @@ impl<'a> Step<'a> for Llvm<'a> { // http://llvm.org/docs/HowToCrossCompileLLVM.html if target != build.build { + builder.ensure(Llvm { target: &build.build }); // FIXME: if the llvm root for the build triple is overridden then we // should use llvm-tblgen from there, also should verify that it // actually exists most of the time in normal installs of LLVM. @@ -249,6 +251,14 @@ pub struct TestHelpers<'a> { impl<'a> Step<'a> for TestHelpers<'a> { type Output = (); + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/rt/rust_test_helpers.c") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + builder.ensure(TestHelpers { target }) + } + /// Compiles the `rust_test_helpers.c` library which we used in various /// `run-pass` test suites for ABI testing. fn run(self, builder: &Builder) { @@ -295,12 +305,16 @@ const OPENSSL_SHA256: &'static str = #[derive(Serialize)] pub struct Openssl<'a> { - target: &'a str, + pub target: &'a str, } impl<'a> Step<'a> for Openssl<'a> { type Output = (); + fn should_run(_builder: &Builder, _path: &Path) -> bool { + false + } + fn run(self, builder: &Builder) { let build = bulder.build; let target = self.target; diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 52ec273c3e8cd..442ca7aadbc05 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -15,7 +15,7 @@ use std::process::Command; use Mode; use builder::{Step, Builder}; use util::{exe, add_lib_path}; -use compile::{self, stamp, Rustc}; +use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp, Rustc}; use native; use channel::GitInfo; @@ -63,7 +63,7 @@ impl<'a> Step<'a> for CleanTools<'a> { let target = self.target; let mode = self.mode; - let compiler = Compiler::new(stage, &build.build); + let compiler = builder.compiler(stage, &build.build); let stamp = match mode { Mode::Libstd => libstd_stamp(build, &compiler, target), @@ -76,103 +76,39 @@ impl<'a> Step<'a> for CleanTools<'a> { } } -// rules.build("tool-rustbook", "src/tools/rustbook") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("librustc-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "rustbook")); -// rules.build("tool-error-index", "src/tools/error_index_generator") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("librustc-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator")); -// rules.build("tool-unstable-book-gen", "src/tools/unstable-book-gen") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "unstable-book-gen")); -// rules.build("tool-tidy", "src/tools/tidy") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "tidy")); -// rules.build("tool-linkchecker", "src/tools/linkchecker") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "linkchecker")); -// rules.build("tool-cargotest", "src/tools/cargotest") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "cargotest")); -// rules.build("tool-compiletest", "src/tools/compiletest") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libtest-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "compiletest")); -// rules.build("tool-build-manifest", "src/tools/build-manifest") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "build-manifest")); -// rules.build("tool-remote-test-server", "src/tools/remote-test-server") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-server")); -// rules.build("tool-remote-test-client", "src/tools/remote-test-client") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-client")); -// rules.build("tool-rust-installer", "src/tools/rust-installer") -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .run(move |s| compile::tool(build, s.stage, s.target, "rust-installer")); -// rules.build("tool-cargo", "src/tools/cargo") -// .host(true) -// .default(build.config.extended) -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .dep(|s| s.stage(0).host(s.target).name("openssl")) -// .dep(move |s| { -// // Cargo depends on procedural macros, which requires a full host -// // compiler to be available, so we need to depend on that. -// s.name("librustc-link") -// .target(&build.build) -// .host(&build.build) -// }) -// .run(move |s| compile::tool(build, s.stage, s.target, "cargo")); -// rules.build("tool-rls", "src/tools/rls") -// .host(true) -// .default(build.config.extended) -// .dep(|s| s.name("librustc-tool")) -// .dep(|s| s.stage(0).host(s.target).name("openssl")) -// .dep(move |s| { -// // rls, like cargo, uses procedural macros -// s.name("librustc-link") -// .target(&build.build) -// .host(&build.build) -// }) -// .run(move |s| compile::tool(build, s.stage, s.target, "rls")); -// - #[derive(Serialize)] -pub struct Tool<'a> { +pub struct ToolBuild<'a> { pub stage: u32, pub target: &'a str, pub tool: &'a str, + pub mode: Mode, } -impl<'a> Step<'a> for Tool<'a> { - type Output = (); +impl<'a> Step<'a> for ToolBuild<'a> { + type Output = PathBuf; /// Build a tool in `src/tools` /// /// This will build the specified tool with the specified `host` compiler in /// `stage` into the normal cargo output directory. - fn run(self, builder: &Builder) { + fn run(self, builder: &Builder) -> PathBuf { let build = builder.build; let stage = self.stage; let target = self.target; let tool = self.tool; + let compiler = builder.compiler(stage, &build.build); + builder.ensure(CleanTools { stage, target, mode: self.mode }); + match self.mode { + Mode::Libstd => builder.ensure(compile::Std { compiler, target }), + Mode::Libtest => builder.ensure(compile::Test { compiler, target }), + Mode::Librustc => builder.ensure(compile::Rustc { compiler, target }), + Mode::Tool => panic!("unexpected Mode::Tool for tool build") + } + let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool)); println!("Building stage{} tool {} ({})", stage, tool, target); - let compiler = Compiler::new(stage, &build.build); - let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build"); let dir = build.src.join("src/tools").join(tool); cargo.arg("--manifest-path").arg(dir.join("Cargo.toml")); @@ -201,5 +137,238 @@ impl<'a> Step<'a> for Tool<'a> { } build.run(&mut cargo); + build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, compiler.host)) + } +} + +macro_rules! tool { + ($($name:ident, $path:expr, $tool_name:expr, $mode:expr;)+) => { + #[derive(Copy, Clone)] + pub enum Tool { + $( + $name, + )+ + } + + impl<'a> Builder<'a> { + pub fn tool_exe(&self, tool: Tool) -> PathBuf { + match tool { + $(Tool::$name => + self.ensure($name { + stage: 0, + target: &self.build.build, + }), + )+ + } + } + } + + $( + #[derive(Serialize)] + pub struct $name<'a> { + pub stage: u32, + pub target: &'a str, + } + + impl<'a> Step<'a> for $name<'a> { + type Output = PathBuf; + const NAME: &'static str = concat!(stringify!($name), " tool"); + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with($path) + } + + fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + builder.ensure($name { + stage: builder.top_stage, + target, + }); + } + + fn run(self, builder: &Builder) -> PathBuf { + builder.ensure(ToolBuild { + stage: self.stage, + target: self.target, + tool: $tool_name, + mode: $mode, + }) + } + } + )+ + } +} + +tool!( + // rules.build("tool-rustbook", "src/tools/rustbook") + // .dep(|s| s.name("maybe-clean-tools")) + // .dep(|s| s.name("librustc-tool")) + // .run(move |s| compile::tool(build, s.stage, s.target, "rustbook")); + Rustbook, "src/tools/rustbook", "rustbook", Mode::Librustc; + // rules.build("tool-error-index", "src/tools/error_index_generator") + // .dep(|s| s.name("maybe-clean-tools")) + // .dep(|s| s.name("librustc-tool")) + // .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator")); + ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::Librustc; + // rules.build("tool-unstable-book-gen", "src/tools/unstable-book-gen") + // .dep(|s| s.name("maybe-clean-tools")) + // .dep(|s| s.name("libstd-tool")) + // .run(move |s| compile::tool(build, s.stage, s.target, "unstable-book-gen")); + UnstableBook, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::Libstd; + // rules.build("tool-tidy", "src/tools/tidy") + // .dep(|s| s.name("maybe-clean-tools")) + // .dep(|s| s.name("libstd-tool")) + // .run(move |s| compile::tool(build, s.stage, s.target, "tidy")); + Tidy, "src/tools/tidy", "tidy", Mode::Libstd; + // rules.build("tool-linkchecker", "src/tools/linkchecker") + // .dep(|s| s.name("maybe-clean-tools")) + // .dep(|s| s.name("libstd-tool")) + // .run(move |s| compile::tool(build, s.stage, s.target, "linkchecker")); + Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::Libstd; + // rules.build("tool-cargotest", "src/tools/cargotest") + // .dep(|s| s.name("maybe-clean-tools")) + // .dep(|s| s.name("libstd-tool")) + // .run(move |s| compile::tool(build, s.stage, s.target, "cargotest")); + CargoTest, "src/tools/cargotest", "cargotest", Mode::Libstd; + // rules.build("tool-compiletest", "src/tools/compiletest") + // .dep(|s| s.name("maybe-clean-tools")) + // .dep(|s| s.name("libtest-tool")) + // .run(move |s| compile::tool(build, s.stage, s.target, "compiletest")); + Compiletest, "src/tools/compiletest", "compiletest", Mode::Libtest; + // rules.build("tool-build-manifest", "src/tools/build-manifest") + // .dep(|s| s.name("maybe-clean-tools")) + // .dep(|s| s.name("libstd-tool")) + // .run(move |s| compile::tool(build, s.stage, s.target, "build-manifest")); + BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Libstd; + // rules.build("tool-remote-test-server", "src/tools/remote-test-server") + // .dep(|s| s.name("maybe-clean-tools")) + // .dep(|s| s.name("libstd-tool")) + // .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-server")); + RemoteTestServer, "src/tools/remote-test-server", "remote-test-server", Mode::Libstd; + // rules.build("tool-remote-test-client", "src/tools/remote-test-client") + // .dep(|s| s.name("maybe-clean-tools")) + // .dep(|s| s.name("libstd-tool")) + // .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-client")); + RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd; + // rules.build("tool-rust-installer", "src/tools/rust-installer") + // .dep(|s| s.name("maybe-clean-tools")) + // .dep(|s| s.name("libstd-tool")) + // .run(move |s| compile::tool(build, s.stage, s.target, "rust-installer")); + RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd; +); + +// rules.build("tool-cargo", "src/tools/cargo") +// .host(true) +// .default(build.config.extended) +// .dep(|s| s.name("maybe-clean-tools")) +// .dep(|s| s.name("libstd-tool")) +// .dep(|s| s.stage(0).host(s.target).name("openssl")) +// .dep(move |s| { +// // Cargo depends on procedural macros, which requires a full host +// // compiler to be available, so we need to depend on that. +// s.name("librustc-link") +// .target(&build.build) +// .host(&build.build) +// }) +// .run(move |s| compile::tool(build, s.stage, s.target, "cargo")); +#[derive(Serialize)] +pub struct Cargo<'a> { + pub stage: u32, + pub target: &'a str, +} + +impl<'a> Step<'a> for Cargo<'a> { + type Output = PathBuf; + const NAME: &'static str = "cargo tool"; + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/tools/cargo") + } + + fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + if path.is_none() && !builder.build.config.extended { + return; + } + builder.ensure(Cargo { + stage: builder.top_stage, + target, + }); + } + + fn run(self, builder: &Builder) -> PathBuf { + builder.ensure(native::Openssl { + target: self.target, + }); + // Cargo depends on procedural macros, which requires a full host + // compiler to be available, so we need to depend on that. + builder.ensure(Rustc { + compiler: builder.compiler(builder.top_stage, &builder.build.build), + target: &builder.build.build, + }); + builder.ensure(ToolBuild { + stage: self.stage, + target: self.target, + tool: "cargo", + mode: Mode::Libstd, + }) + } +} + +// rules.build("tool-rls", "src/tools/rls") +// .host(true) +// .default(build.config.extended) +// .dep(|s| s.name("librustc-tool")) +// .dep(|s| s.stage(0).host(s.target).name("openssl")) +// .dep(move |s| { +// // rls, like cargo, uses procedural macros +// s.name("librustc-link") +// .target(&build.build) +// .host(&build.build) +// }) +// .run(move |s| compile::tool(build, s.stage, s.target, "rls")); +// +#[derive(Serialize)] +pub struct Rls<'a> { + pub stage: u32, + pub target: &'a str, +} + +impl<'a> Step<'a> for Rls<'a> { + type Output = PathBuf; + const NAME: &'static str = "RLS tool"; + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/tools/rls") + } + + fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + if path.is_none() && !builder.build.config.extended { + return; + } + builder.ensure(Cargo { + stage: builder.top_stage, + target, + }); + } + + fn run(self, builder: &Builder) -> PathBuf { + builder.ensure(native::Openssl { + target: self.target, + }); + // RLS depends on procedural macros, which requires a full host + // compiler to be available, so we need to depend on that. + builder.ensure(Rustc { + compiler: builder.compiler(builder.top_stage, &builder.build.build), + target: &builder.build.build, + }); + builder.ensure(ToolBuild { + stage: self.stage, + target: self.target, + tool: "rls", + mode: Mode::Librustc, + }) } } From cd3dd803a7b10e89253068202890a200d4b88eb5 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 5 Jul 2017 10:20:20 -0600 Subject: [PATCH 04/51] Add Builder and Step definitions. --- src/bootstrap/builder.rs | 468 +++++++++++++++++++++++++++++++++++++++ src/bootstrap/cache.rs | 102 +++++++++ src/bootstrap/lib.rs | 34 ++- 3 files changed, 599 insertions(+), 5 deletions(-) create mode 100644 src/bootstrap/builder.rs create mode 100644 src/bootstrap/cache.rs diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs new file mode 100644 index 0000000000000..37f6954c842d8 --- /dev/null +++ b/src/bootstrap/builder.rs @@ -0,0 +1,468 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use serde::{Serialize, Deserialize}; + +use std::cell::RefCell; +use std::collections::HashSet; +use std::path::{Path, PathBuf}; +use std::process::Command; +use std::fs; + +use compile; +use install; +use dist; +use util::{exe, libdir, add_lib_path}; +use {Build, Mode}; +use cache::{Cache, Key}; +use check; +use flags::Subcommand; +use doc; + +pub struct Builder<'a> { + pub build: &'a Build, + pub top_stage: u32, + pub kind: Kind, + cache: Cache, + stack: RefCell>, +} + +impl<'a> Deref for Builder<'a> { + type Target = Build; + + fn deref(&self) -> &Self::Target { + self.build + } +} + +pub trait Step<'a>: Sized { + type Output: Serialize + Deserialize<'a>; + const NAME: &'static str; + + const DEFAULT: bool = false; + + /// Run this rule for all hosts, and just the same hosts as the targets. + const ONLY_HOSTS: bool = false; + + /// Run this rule for all targets, but only with the native host. + const ONLY_BUILD_TARGETS: bool = false; + + /// Only run this step with the build triple as host and target. + const ONLY_BUILD: bool = false; + + fn run(self, builder: &'a Builder) -> Self::Output; + + fn should_run(_builder: &'a Builder, _path: &Path) -> bool { false } + + fn make_run( + _builder: &'a Builder, + _path: Option<&Path>, + _host: &'a str, + _target: &'a str, + ) { unimplemented!() } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Kind { + Build, + Test, + Bench, + Dist, + Doc, + Install, +} + +macro_rules! check { + (@inner $self:ident, $rule:ty, $path:expr) => { + let build = $self.build; + let hosts = if <$rule>::ONLY_BUILD_TARGETS || <$rule>::ONLY_BUILD { + &build.config.host[..1] + } else { + &build.hosts + }; + + // Determine the actual targets participating in this rule. + // NOTE: We should keep the full projection from build triple to + // the hosts for the dist steps, now that the hosts array above is + // truncated to avoid duplication of work in that case. Therefore + // the original non-shadowed hosts array is used below. + let targets = if <$rule>::ONLY_HOSTS { + // If --target was specified but --host wasn't specified, + // don't run any host-only tests. Also, respect any `--host` + // overrides as done for `hosts`. + if build.flags.host.len() > 0 { + &build.flags.host[..] + } else if build.flags.target.len() > 0 { + &[] + } else if <$rule>::ONLY_BUILD { + &build.config.host[..1] + } else { + &build.config.host[..] + } + } else { + &build.targets + }; + + build.verbose(&format!("executing {} with hosts={:?}, targets={:?}", + stringify!($rule), hosts, targets)); + for host in hosts { + for target in targets { + <$rule>::make_run($self, $path, host, target); + } + } + }; + ($self:ident, $paths:ident, $($rule:ty),+ $(,)*) => {{ + let paths = $paths; + if paths.is_empty() { + $({ + if <$rule>::DEFAULT { + check!(@inner $self, $rule, None); + } + })+ + } else { + for path in paths { + $({ + if <$rule>::should_run($self, path) { + check!(@inner $self, $rule, Some(path)); + } + })+ + } + } + }}; +} + +impl<'a> Builder<'a> { + pub fn run(build: &Build) { + let (kind, paths) = match build.flags.cmd { + Subcommand::Build { ref paths } => (Kind::Build, &paths[..]), + Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]), + Subcommand::Test { ref paths, .. } => (Kind::Test, &paths[..]), + Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]), + Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]), + Subcommand::Install { ref paths } => (Kind::Install, &paths[..]), + Subcommand::Clean => panic!(), + }; + + let builder = Builder { + build: build, + top_stage: build.flags.stage.unwrap_or(2), + kind: kind, + cache: Cache::new(), + stack: RefCell::new(Vec::new()), + }; + + let builder = &builder; + match builder.kind { + Kind::Build => check!(builder, paths, compile::Std, compile::Test, compile::Rustc, + compile::StartupObjects), + Kind::Test => check!(builder, paths, check::Tidy, check::Bootstrap, check::Compiletest, + check::Krate, check::KrateLibrustc, check::Linkcheck, check::Cargotest, + check::TestCargo, check::Docs, check::ErrorIndex, check::Distcheck), + Kind::Bench => check!(builder, paths, check::Krate, check::KrateLibrustc), + Kind::Doc => builder.default_doc(Some(paths)), + Kind::Dist => check!(builder, paths, dist::Docs, dist::Mingw, dist::Rustc, + dist::DebuggerScripts, dist::Std, dist::Analysis, dist::Src, + dist::PlainSourceTarball, dist::Cargo, dist::Rls, dist::Extended, dist::HashSign), + Kind::Install => check!(builder, paths, install::Docs, install::Std, install::Cargo, + install::Rls, install::Analysis, install::Src, install::Rustc), + } + } + + pub fn default_doc(&self, paths: Option<&[PathBuf]>) { + let paths = paths.unwrap_or(&[]); + check!(self, paths, doc::UnstableBook, doc::UnstableBookGen, doc::Rustbook, doc::Book, + doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, + doc::Nomicon, doc::Reference); + } + + pub fn compiler(&'a self, stage: u32, host: &'a str) -> Compiler<'a> { + self.ensure(compile::Assemble { target_compiler: Compiler { stage, host } }) + } + + pub fn rustc(&self, compiler: Compiler) -> PathBuf { + if compiler.is_snapshot(self) { + self.build.initial_rustc.clone() + } else { + self.compiler(compiler.stage, compiler.host); + self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host)) + } + } + + pub fn rustdoc(&self, compiler: Compiler) -> PathBuf { + let mut rustdoc = self.rustc(compiler); + rustdoc.pop(); + rustdoc.push(exe("rustdoc", compiler.host)); + rustdoc + } + + pub fn sysroot(&self, compiler: Compiler<'a>) -> PathBuf { + self.ensure(compile::Sysroot { compiler }) + } + + /// Returns the libdir where the standard library and other artifacts are + /// found for a compiler's sysroot. + pub fn sysroot_libdir(&self, compiler: Compiler<'a>, target: &'a str) -> PathBuf { + #[derive(Serialize)] + struct Libdir<'a> { + compiler: Compiler<'a>, + target: &'a str, + } + impl<'a> Step<'a> for Libdir<'a> { + type Output = PathBuf; + const NAME: &'static str = "sysroot libdir"; + fn run(self, builder: &Builder) -> PathBuf { + let sysroot = builder.sysroot(self.compiler) + .join("lib").join("rustlib").join(self.target).join("lib"); + let _ = fs::remove_dir_all(&sysroot); + t!(fs::create_dir_all(&sysroot)); + sysroot + } + } + self.ensure(Libdir { compiler, target }) + } + + /// Returns the compiler's libdir where it stores the dynamic libraries that + /// it itself links against. + /// + /// For example this returns `/lib` on Unix and `/bin` on + /// Windows. + pub fn rustc_libdir(&self, compiler: Compiler) -> PathBuf { + if compiler.is_snapshot(self) { + self.build.rustc_snapshot_libdir() + } else { + self.sysroot(compiler).join(libdir(compiler.host)) + } + } + + /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic + /// library lookup path. + pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Command) { + // Windows doesn't need dylib path munging because the dlls for the + // compiler live next to the compiler and the system will find them + // automatically. + if cfg!(windows) { + return + } + + add_lib_path(vec![self.rustc_libdir(compiler)], cmd); + } + + /// Prepares an invocation of `cargo` to be run. + /// + /// This will create a `Command` that represents a pending execution of + /// Cargo. This cargo will be configured to use `compiler` as the actual + /// rustc compiler, its output will be scoped by `mode`'s output directory, + /// it will pass the `--target` flag for the specified `target`, and will be + /// executing the Cargo command `cmd`. + pub fn cargo(&self, compiler: Compiler, mode: Mode, target: &str, cmd: &str) -> Command { + let build = self.build; + + // Clear out the output we're about to generate if our compiler changed + { + let out_dir = build.cargo_out(compiler, mode, target); + build.clear_if_dirty(&out_dir, &self.rustc(compiler)); + } + + let mut cargo = Command::new(&build.initial_cargo); + let out_dir = build.stage_out(compiler, mode); + + cargo.env("CARGO_TARGET_DIR", out_dir) + .arg(cmd) + .arg("-j").arg(build.jobs().to_string()) + .arg("--target").arg(target); + + // FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005 + // Force cargo to output binaries with disambiguating hashes in the name + cargo.env("__CARGO_DEFAULT_LIB_METADATA", &self.build.config.channel); + + let stage; + if compiler.stage == 0 && build.local_rebuild { + // Assume the local-rebuild rustc already has stage1 features. + stage = 1; + } else { + stage = compiler.stage; + } + + self.build.verbose(&format!("cargo using: {:?}", self.rustc(compiler))); + + // Customize the compiler we're running. Specify the compiler to cargo + // as our shim and then pass it some various options used to configure + // how the actual compiler itbuild is called. + // + // These variables are primarily all read by + // src/bootstrap/bin/{rustc.rs,rustdoc.rs} + cargo.env("RUSTBUILD_NATIVE_DIR", build.native_dir(target)) + .env("RUSTC", build.out.join("bootstrap/debug/rustc")) + .env("RUSTC_REAL", self.rustc(compiler)) + .env("RUSTC_STAGE", stage.to_string()) + .env("RUSTC_CODEGEN_UNITS", + build.config.rust_codegen_units.to_string()) + .env("RUSTC_DEBUG_ASSERTIONS", + build.config.rust_debug_assertions.to_string()) + .env("RUSTC_SYSROOT", self.sysroot(compiler)) + .env("RUSTC_LIBDIR", self.rustc_libdir(compiler)) + .env("RUSTC_RPATH", build.config.rust_rpath.to_string()) + .env("RUSTDOC", build.out.join("bootstrap/debug/rustdoc")) + .env("RUSTDOC_REAL", self.rustdoc(compiler)) + .env("RUSTC_FLAGS", build.rustc_flags(target).join(" ")); + + if mode != Mode::Tool { + // Tools don't get debuginfo right now, e.g. cargo and rls don't + // get compiled with debuginfo. + cargo.env("RUSTC_DEBUGINFO", build.config.rust_debuginfo.to_string()) + .env("RUSTC_DEBUGINFO_LINES", build.config.rust_debuginfo_lines.to_string()) + .env("RUSTC_FORCE_UNSTABLE", "1"); + + // Currently the compiler depends on crates from crates.io, and + // then other crates can depend on the compiler (e.g. proc-macro + // crates). Let's say, for example that rustc itbuild depends on the + // bitflags crate. If an external crate then depends on the + // bitflags crate as well, we need to make sure they don't + // conflict, even if they pick the same verison of bitflags. We'll + // want to make sure that e.g. a plugin and rustc each get their + // own copy of bitflags. + + // Cargo ensures that this works in general through the -C metadata + // flag. This flag will frob the symbols in the binary to make sure + // they're different, even though the source code is the exact + // same. To solve this problem for the compiler we extend Cargo's + // already-passed -C metadata flag with our own. Our rustc.rs + // wrapper around the actual rustc will detect -C metadata being + // passed and frob it with this extra string we're passing in. + cargo.env("RUSTC_METADATA_SUFFIX", "rustc"); + } + + // Enable usage of unstable features + cargo.env("RUSTC_BOOTSTRAP", "1"); + build.add_rust_test_threads(&mut cargo); + + // Almost all of the crates that we compile as part of the bootstrap may + // have a build script, including the standard library. To compile a + // build script, however, it itbuild needs a standard library! This + // introduces a bit of a pickle when we're compiling the standard + // library itbuild. + // + // To work around this we actually end up using the snapshot compiler + // (stage0) for compiling build scripts of the standard library itbuild. + // The stage0 compiler is guaranteed to have a libstd available for use. + // + // For other crates, however, we know that we've already got a standard + // library up and running, so we can use the normal compiler to compile + // build scripts in that situation. + if mode == Mode::Libstd { + cargo.env("RUSTC_SNAPSHOT", &build.initial_rustc) + .env("RUSTC_SNAPSHOT_LIBDIR", build.rustc_snapshot_libdir()); + } else { + cargo.env("RUSTC_SNAPSHOT", self.rustc(compiler)) + .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_libdir(compiler)); + } + + // Ignore incremental modes except for stage0, since we're + // not guaranteeing correctness across builds if the compiler + // is changing under your feet.` + if build.flags.incremental && compiler.stage == 0 { + let incr_dir = build.incremental_dir(compiler); + cargo.env("RUSTC_INCREMENTAL", incr_dir); + } + + if let Some(ref on_fail) = build.flags.on_fail { + cargo.env("RUSTC_ON_FAIL", on_fail); + } + + cargo.env("RUSTC_VERBOSE", format!("{}", build.verbosity)); + + // Specify some various options for build scripts used throughout + // the build. + // + // FIXME: the guard against msvc shouldn't need to be here + if !target.contains("msvc") { + cargo.env(format!("CC_{}", target), build.cc(target)) + .env(format!("AR_{}", target), build.ar(target).unwrap()) // only msvc is None + .env(format!("CFLAGS_{}", target), build.cflags(target).join(" ")); + + if let Ok(cxx) = build.cxx(target) { + cargo.env(format!("CXX_{}", target), cxx); + } + } + + if build.config.extended && compiler.is_final_stage(self) { + cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string()); + } + + // When being built Cargo will at some point call `nmake.exe` on Windows + // MSVC. Unfortunately `nmake` will read these two environment variables + // below and try to intepret them. We're likely being run, however, from + // MSYS `make` which uses the same variables. + // + // As a result, to prevent confusion and errors, we remove these + // variables from our environment to prevent passing MSYS make flags to + // nmake, causing it to blow up. + if cfg!(target_env = "msvc") { + cargo.env_remove("MAKE"); + cargo.env_remove("MAKEFLAGS"); + } + + // Environment variables *required* throughout the build + // + // FIXME: should update code to not require this env var + cargo.env("CFG_COMPILER_HOST_TRIPLE", target); + + if build.is_verbose() { + cargo.arg("-v"); + } + // FIXME: cargo bench does not accept `--release` + if build.config.rust_optimize && cmd != "bench" { + cargo.arg("--release"); + } + if build.config.locked_deps { + cargo.arg("--locked"); + } + if build.config.vendor || build.is_sudo { + cargo.arg("--frozen"); + } + + build.ci_env.force_coloring_in_ci(&mut cargo); + + cargo + } + + pub fn ensure + Serialize>(&'a self, step: S) -> S::Output + where + S::Output: 'a + { + let key = Cache::to_key(&step); + { + let mut stack = self.stack.borrow_mut(); + if stack.contains(&key) { + let mut out = String::new(); + out += &format!("\n\nCycle in build detected when adding {:?}\n", key); + for el in stack.iter().rev() { + out += &format!("\t{:?}\n", el); + } + panic!(out); + } + if let Some(out) = self.cache.get::(&key) { + self.build.verbose(&format!("{}c {:?}", " ".repeat(stack.len()), key)); + + return out; + } + self.build.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), key)); + stack.push(key.clone()); + } + let out = step.run(self); + { + let mut stack = self.stack.borrow_mut(); + assert_eq!(stack.pop().as_ref(), Some(&key)); + } + self.build.verbose(&format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), key)); + self.cache.put(key.clone(), &out); + self.cache.get::(&key).unwrap() + } +} diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs new file mode 100644 index 0000000000000..bc69c6fcffdd8 --- /dev/null +++ b/src/bootstrap/cache.rs @@ -0,0 +1,102 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use serde_json; +use serde::{Serialize, Deserialize}; + +use std::fmt; +use std::mem; +use std::intrinsics; +use std::collections::HashMap; +use std::cell::RefCell; + +/// This is essentially a HashMap which allows storing any type in its input and +/// any type in its output. It is a write-once cache; values are never evicted, +/// which means that references to the value can safely be returned from the +/// get() method. +// +// FIXME: This type does not permit retrieving &Path from a PathBuf, primarily +// due to a lack of any obvious way to ensure that this is safe, but also not +// penalize other cases (e.g., deserializing u32 -> &u32, which is non-optimal). +#[derive(Debug)] +pub struct Cache(RefCell>>); + +fn to_json(element: &T) -> String { + let type_id = unsafe { + intrinsics::type_name::() + }; + + t!(serde_json::to_string(&(type_id, element))) +} + +fn from_json<'a, O: Deserialize<'a>>(data: &'a str) -> O { + let type_id = unsafe { + intrinsics::type_name::() + }; + + let (de_type_id, element): (&'a str, O) = t!(serde_json::from_str(data)); + + assert_eq!(type_id, de_type_id); + + element +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct Key(String); + +impl fmt::Debug for Key { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str(&self.0) + } +} + +impl Cache { + pub fn new() -> Cache { + Cache(RefCell::new(HashMap::new())) + } + + pub fn to_key(key: &K) -> Key { + Key(to_json(key)) + } + + /// Puts a value into the cache. Will panic if called more than once with + /// the same key. + /// + /// Returns the internal key utilized, as an opaque structure, useful only + /// for debugging. + pub fn put(&self, key: Key, value: &V) + where + V: Serialize, + { + let mut cache = self.0.borrow_mut(); + let value = to_json(value); + assert!(!cache.contains_key(&key), "processing {:?} a second time", key); + // Store a boxed str so that it's location in memory never changes and + // it's safe for us to return references to it (so long as they live as + // long as us). + cache.insert(key, value.into_boxed_str()); + } + + pub fn get<'a, V>(&'a self, key: &Key) -> Option + where + V: Deserialize<'a> + 'a, + { + let cache = self.0.borrow(); + cache.get(key).map(|v| { + // Change the lifetime. This borrow is valid for as long as self lives; + // the data we're accessing will live as long as us and will be in a + // stable location, since we use Box. + let v = unsafe { + mem::transmute::<&str, &'a str>(v) + }; + from_json(v) + }) + } +} diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index e51bb5b65a9d7..97994f7bf2a9d 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -93,6 +93,8 @@ use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppresse use util::{exe, libdir, add_lib_path, OutputFolder, CiEnv}; +use builder::Builder; + mod cc; mod channel; mod check; @@ -107,6 +109,7 @@ mod install; mod native; mod sanity; pub mod util; +mod builder; #[cfg(windows)] mod job; @@ -1077,16 +1080,37 @@ impl Build { None } } + + /// Get a list of crates from a root crate. + /// + /// Returns Vec<(crate, path to crate, is_root_crate)> + fn crates(&self, root: &str) -> Vec<(&str, &Path)> { + let mut ret = Vec::new(); + let mut list = vec![root]; + let mut visited = HashSet::new(); + while let Some(krate) = list.pop() { + let krate = &self.crates[krate]; + // If we can't strip prefix, then out-of-tree path + let path = krate.path.strip_prefix(&self.src).unwrap_or(&krate.path); + ret.push((&*krate.name, path)); + for dep in &krate.deps { + if visited.insert(dep) && dep != "build_helper" { + list.push(dep); + } + } + } + ret + } } impl<'a> Compiler<'a> { - /// Creates a new complier for the specified stage/host - fn new(stage: u32, host: &'a str) -> Compiler<'a> { - Compiler { stage: stage, host: host } + pub fn with_stage(mut self, stage: u32) -> Compiler<'a> { + self.stage = stage; + self } /// Returns whether this is a snapshot compiler for `build`'s configuration - fn is_snapshot(&self, build: &Build) -> bool { + pub fn is_snapshot(&self, builder: &Build) -> bool { self.stage == 0 && self.host == build.build } @@ -1094,7 +1118,7 @@ impl<'a> Compiler<'a> { /// current build session. /// This takes into account whether we're performing a full bootstrap or /// not; don't directly compare the stage with `2`! - fn is_final_stage(&self, build: &Build) -> bool { + pub fn is_final_stage(&self, build: &Build) -> bool { let final_stage = if build.config.full_bootstrap { 2 } else { 1 }; self.stage >= final_stage } From 60388303c770a6e9409f3afa75d31d9125f871e3 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 5 Jul 2017 10:46:41 -0600 Subject: [PATCH 05/51] Fixes warnings and errors introduced while moving code around --- src/Cargo.lock | 3 ++ src/bootstrap/Cargo.toml | 3 ++ src/bootstrap/builder.rs | 10 ++-- src/bootstrap/check.rs | 48 ++++++++--------- src/bootstrap/compile.rs | 112 ++++++++++++++++++++------------------- src/bootstrap/dist.rs | 69 ++++++++++++------------ src/bootstrap/doc.rs | 53 +++++++++--------- src/bootstrap/flags.rs | 11 ++-- src/bootstrap/install.rs | 5 +- src/bootstrap/lib.rs | 78 +++++++++------------------ src/bootstrap/native.rs | 5 +- src/bootstrap/tool.rs | 15 +++--- 12 files changed, 199 insertions(+), 213 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 3c8d1164863de..c210f80431bd7 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -137,6 +137,9 @@ dependencies = [ "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 8842dce0257dd..f557dcc476381 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -38,3 +38,6 @@ getopts = "0.2" rustc-serialize = "0.3" gcc = "0.3.50" libc = "0.2" +serde = "1.0" +serde_json = "1.0" +serde_derive = "1.0" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 37f6954c842d8..b5ae6aa1d2700 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -11,10 +11,10 @@ use serde::{Serialize, Deserialize}; use std::cell::RefCell; -use std::collections::HashSet; use std::path::{Path, PathBuf}; use std::process::Command; use std::fs; +use std::ops::Deref; use compile; use install; @@ -26,6 +26,8 @@ use check; use flags::Subcommand; use doc; +pub use Compiler; + pub struct Builder<'a> { pub build: &'a Build, pub top_stage: u32, @@ -44,7 +46,6 @@ impl<'a> Deref for Builder<'a> { pub trait Step<'a>: Sized { type Output: Serialize + Deserialize<'a>; - const NAME: &'static str; const DEFAULT: bool = false; @@ -164,7 +165,7 @@ impl<'a> Builder<'a> { compile::StartupObjects), Kind::Test => check!(builder, paths, check::Tidy, check::Bootstrap, check::Compiletest, check::Krate, check::KrateLibrustc, check::Linkcheck, check::Cargotest, - check::TestCargo, check::Docs, check::ErrorIndex, check::Distcheck), + check::Cargo, check::Docs, check::ErrorIndex, check::Distcheck), Kind::Bench => check!(builder, paths, check::Krate, check::KrateLibrustc), Kind::Doc => builder.default_doc(Some(paths)), Kind::Dist => check!(builder, paths, dist::Docs, dist::Mingw, dist::Rustc, @@ -177,7 +178,7 @@ impl<'a> Builder<'a> { pub fn default_doc(&self, paths: Option<&[PathBuf]>) { let paths = paths.unwrap_or(&[]); - check!(self, paths, doc::UnstableBook, doc::UnstableBookGen, doc::Rustbook, doc::Book, + check!(self, paths, doc::UnstableBook, doc::UnstableBookGen, doc::Rustbook, doc::TheBook, doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon, doc::Reference); } @@ -216,7 +217,6 @@ impl<'a> Builder<'a> { } impl<'a> Step<'a> for Libdir<'a> { type Output = PathBuf; - const NAME: &'static str = "sysroot libdir"; fn run(self, builder: &Builder) -> PathBuf { let sysroot = builder.sysroot(self.compiler) .join("lib").join("rustlib").join(self.target).join("lib"); diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 2fd02d3d7c48f..0d838a507ce95 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -37,7 +37,7 @@ use tool::Tool; const ADB_TEST_DIR: &str = "/data/tmp/work"; /// The two modes of the test runner; tests or benchmarks. -#[derive(Copy, Clone)] +#[derive(Serialize, Copy, Clone)] pub enum TestKind { /// Run `cargo test` Test, @@ -157,7 +157,7 @@ impl<'a> Step<'a> for Cargotest<'a> { /// test` to ensure that we don't regress the test suites there. fn run(self, builder: &Builder) { let build = builder.build; - let compiler = builder.compiler(self.stage, host); + let compiler = builder.compiler(self.stage, self.host); builder.ensure(compile::Rustc { compiler, target: compiler.host }); // Note that this is a short, cryptic, and not scoped directory name. This @@ -170,8 +170,8 @@ impl<'a> Step<'a> for Cargotest<'a> { let mut cmd = builder.tool_cmd(Tool::CargoTest); try_run(build, cmd.arg(&build.initial_cargo) .arg(&out_dir) - .env("RUSTC", build.compiler_path(&compiler)) - .env("RUSTDOC", build.rustdoc(&compiler))); + .env("RUSTC", build.compiler_path(compiler)) + .env("RUSTDOC", build.rustdoc(compiler))); } } @@ -194,10 +194,10 @@ impl<'a> Step<'a> for Cargo<'a> { path.ends_with("cargo") // FIXME: Why is this not src/tools/cargo? } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { - builder.ensure(TestCargo { - compiler: builder.compiler(builder.top_stage, host), - target, + fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + builder.ensure(Cargotest { + stage: builder.top_stage, + host: target, }); } @@ -209,7 +209,7 @@ impl<'a> Step<'a> for Cargo<'a> { // Configure PATH to find the right rustc. NB. we have to use PATH // and not RUSTC because the Cargo test suite has tests that will // fail if rustc is not spelled `rustc`. - let path = build.sysroot(compiler).join("bin"); + let path = builder.sysroot(compiler).join("bin"); let old_path = env::var_os("PATH").unwrap_or_default(); let newpath = env::join_paths( iter::once(path).chain(env::split_paths(&old_path)) @@ -312,7 +312,7 @@ impl<'a> Step<'a> for Tidy<'a> { let _folder = build.fold_output(|| "tidy"); println!("tidy check ({})", host); - let mut cmd = build.tool_cmd(Tool::Tidy); + let mut cmd = builder.tool_cmd(Tool::Tidy); cmd.arg(build.src.join("src")); if !build.config.vendor { cmd.arg("--no-vendor"); @@ -585,7 +585,7 @@ impl<'a> Step<'a> for Compiletest<'a> { // of them! cmd.arg("--compile-lib-path").arg(build.rustc_libdir(compiler)); - cmd.arg("--run-lib-path").arg(build.sysroot_libdir(compiler, target)); + cmd.arg("--run-lib-path").arg(builder.sysroot_libdir(compiler, target)); cmd.arg("--rustc-path").arg(build.compiler_path(compiler)); cmd.arg("--rustdoc-path").arg(build.rustdoc(compiler)); cmd.arg("--src-base").arg(build.src.join("src/test").join(suite)); @@ -608,7 +608,7 @@ impl<'a> Step<'a> for Compiletest<'a> { flags.push("-g".to_string()); } - let mut hostflags = build.rustc_flags(&compiler.host); + let mut hostflags = build.rustc_flags(compiler.host); hostflags.extend(flags.clone()); cmd.arg("--host-rustcflags").arg(hostflags.join(" ")); @@ -801,7 +801,7 @@ impl<'a> Step<'a> for ErrorIndex<'a> { let output = dir.join("error-index.md"); let _time = util::timeit(); - build.run(build.tool_cmd(Tool::ErrorIndex) + build.run(builder.tool_cmd(Tool::ErrorIndex) .arg("markdown") .arg(&output) .env("CFG_BUILD", &build.build)); @@ -810,7 +810,7 @@ impl<'a> Step<'a> for ErrorIndex<'a> { } } -fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { +fn markdown_test(build: &Build, compiler: Compiler, markdown: &Path) { let mut file = t!(File::open(markdown)); let mut contents = String::new(); t!(file.read_to_string(&mut contents)); @@ -862,7 +862,6 @@ pub struct KrateLibrustc<'a> { impl<'a> Step<'a> for KrateLibrustc<'a> { type Output = (); - const NAME: &'static str = "check librustc"; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -1072,7 +1071,7 @@ impl<'a> Step<'a> for Krate<'a> { // Pass in some standard flags then iterate over the graph we've discovered // in `cargo metadata` with the maps above and figure out what `-p` // arguments need to get passed. - let mut cargo = build.cargo(&compiler, mode, target, test_kind.subcommand()); + let mut cargo = build.cargo(compiler, mode, target, test_kind.subcommand()); cargo.arg("--manifest-path") .arg(build.src.join(path).join("Cargo.toml")) .arg("--features").arg(features); @@ -1115,7 +1114,7 @@ impl<'a> Step<'a> for Krate<'a> { // Note that to run the compiler we need to run with the *host* libraries, // but our wrapper scripts arrange for that to be the case anyway. let mut dylib_path = dylib_path(); - dylib_path.insert(0, build.sysroot_libdir(&compiler, target)); + dylib_path.insert(0, builder.sysroot_libdir(compiler, target)); cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); if target.contains("emscripten") || build.remote_tested(target) { @@ -1132,10 +1131,10 @@ impl<'a> Step<'a> for Krate<'a> { if target.contains("emscripten") { build.run(&mut cargo); - krate_emscripten(build, &compiler, target, mode); + krate_emscripten(build, compiler, target, mode); } else if build.remote_tested(target) { build.run(&mut cargo); - krate_remote(builder, &compiler, target, mode); + krate_remote(builder, compiler, target, mode); } else { cargo.args(&build.flags.cmd.test_args()); try_run(build, &mut cargo); @@ -1144,7 +1143,7 @@ impl<'a> Step<'a> for Krate<'a> { } fn krate_emscripten(build: &Build, - compiler: &Compiler, + compiler: Compiler, target: &str, mode: Mode) { let out_dir = build.cargo_out(compiler, mode, target); @@ -1162,10 +1161,11 @@ fn krate_emscripten(build: &Build, } } -fn krate_remote(build: &Builder, - compiler: &Compiler, +fn krate_remote(builder: &Builder, + compiler: Compiler, target: &str, mode: Mode) { + let build = builder.build; let out_dir = build.cargo_out(compiler, mode, target); let tests = find_tests(&out_dir.join("deps"), target); @@ -1269,7 +1269,7 @@ impl<'a> Step<'a> for RemoteCopyLibs<'a> { build.run(&mut cmd); // Push all our dylibs to the emulator - for f in t!(build.sysroot_libdir(compiler, target).read_dir()) { + for f in t!(builder.sysroot_libdir(compiler, target).read_dir()) { let f = t!(f); let name = f.file_name().into_string().unwrap(); if util::is_dylib(&name) { @@ -1359,7 +1359,7 @@ impl<'a> Step<'a> for Distcheck { #[derive(Serialize)] pub struct Bootstrap; -impl<'a> for Step<'a> Bootstrap { +impl<'a> Step<'a> for Bootstrap { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 07a0f63e6cb92..f64aa636da10d 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -28,9 +28,11 @@ use build_helper::{output, mtime, up_to_date}; use filetime::FileTime; use rustc_serialize::json; -use channel::GitInfo; use util::{exe, libdir, is_dylib, copy}; use {Build, Compiler, Mode}; +use native; + +use builder::{Step, Builder}; // // // Crates which have build scripts need to rely on this rule to ensure that @@ -95,39 +97,39 @@ use {Build, Compiler, Mode}; // different compiler, or from actually building the crate itself (the `dep` // rule). The `run` rule then mirrors these three cases and links the cases // forward into the compiler sysroot specified from the correct location. -fn crate_rule<'a, 'b>(build: &'a Build, - rules: &'b mut Rules<'a>, - krate: &'a str, - dep: &'a str, - link: fn(&Build, &Compiler, &Compiler, &str)) - -> RuleBuilder<'a, 'b> { - let mut rule = rules.build(&krate, "path/to/nowhere"); - rule.dep(move |s| { - if build.force_use_stage1(&s.compiler(), s.target) { - s.host(&build.build).stage(1) - } else if s.host == build.build { - s.name(dep) - } else { - s.host(&build.build) - } - }) - .run(move |s| { - if build.force_use_stage1(&s.compiler(), s.target) { - link(build, - &s.stage(1).host(&build.build).compiler(), - &s.compiler(), - s.target) - } else if s.host == build.build { - link(build, &s.compiler(), &s.compiler(), s.target) - } else { - link(build, - &s.host(&build.build).compiler(), - &s.compiler(), - s.target) - } - }); - rule -} +// fn crate_rule<'a, 'b>(build: &'a Build, +// rules: &'b mut Rules<'a>, +// krate: &'a str, +// dep: &'a str, +// link: fn(&Build, compiler, compiler, &str)) +// -> RuleBuilder<'a, 'b> { +// let mut rule = rules.build(&krate, "path/to/nowhere"); +// rule.dep(move |s| { +// if build.force_use_stage1(&s.compiler(), s.target) { +// s.host(&build.build).stage(1) +// } else if s.host == build.build { +// s.name(dep) +// } else { +// s.host(&build.build) +// } +// }) +// .run(move |s| { +// if build.force_use_stage1(&s.compiler(), s.target) { +// link(build, +// &s.stage(1).host(&build.build).compiler(), +// &s.compiler(), +// s.target) +// } else if s.host == build.build { +// link(build, &s.compiler(), &s.compiler(), s.target) +// } else { +// link(build, +// &s.host(&build.build).compiler(), +// &s.compiler(), +// s.target) +// } +// }); +// rule +// } // rules.build("libstd", "src/libstd") // .dep(|s| s.name("rustc").target(s.host)) @@ -141,7 +143,7 @@ fn crate_rule<'a, 'b>(build: &'a Build, #[derive(Serialize)] pub struct Std<'a> { pub target: &'a str, - pub compiler: &'a Compiler<'a>, + pub compiler: Compiler<'a>, } impl<'a> Step<'a> for Std<'a> { @@ -239,7 +241,7 @@ impl<'a> Step<'a> for Std<'a> { run_cargo(build, &mut cargo, - &libstd_stamp(build, &compiler, target)); + &libstd_stamp(build, compiler, target)); builder.ensure(StdLink { compiler: builder.compiler(compiler.stage, &build.build), @@ -287,7 +289,7 @@ impl<'a> Step<'a> for StdLink<'a> { compiler.host, target_compiler.host, target); - let libdir = build.sysroot_libdir(target_compiler, target); + let libdir = builder.sysroot_libdir(target_compiler, target); add_to_sysroot(&libdir, &libstd_stamp(build, compiler, target)); if target.contains("musl") && !target.contains("mips") { @@ -330,7 +332,7 @@ fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) { #[derive(Serialize)] pub struct StartupObjects<'a> { - pub for_compiler: Compiler<'a>, + pub compiler: Compiler<'a>, pub target: &'a str, } @@ -356,17 +358,17 @@ impl<'a> Step<'a> for StartupObjects<'a> { /// no other compilers are guaranteed to be available). fn run(self, builder: &Builder) { let build = builder.build; - let for_compiler = self.for_compiler; + let for_compiler = self.compiler; let target = self.target; if !target.contains("pc-windows-gnu") { return } - let compiler = Compiler::new(0, &build.build); - let compiler_path = build.compiler_path(&compiler); + let compiler = builder.compiler(0, &build.build); + let compiler_path = build.compiler_path(compiler); let src_dir = &build.src.join("src/rtstartup"); let dst_dir = &build.native_dir(target).join("rtstartup"); - let sysroot_dir = &build.sysroot_libdir(for_compiler, target); + let sysroot_dir = &builder.sysroot_libdir(for_compiler, target); t!(fs::create_dir_all(dst_dir)); t!(fs::create_dir_all(sysroot_dir)); @@ -485,7 +487,7 @@ pub struct TestLink<'a> { pub target: &'a str, } -impl<'a> Step<'a> for Step<'a> { +impl<'a> Step<'a> for TestLink<'a> { type Output = (); /// Same as `std_link`, only for libtest @@ -500,7 +502,7 @@ impl<'a> Step<'a> for Step<'a> { compiler.host, target_compiler.host, target); - add_to_sysroot(&build.sysroot_libdir(target_compiler, target), + add_to_sysroot(&builder.sysroot_libdir(target_compiler, target), &libtest_stamp(build, compiler, target)); } } @@ -682,26 +684,26 @@ impl<'a> Step<'a> for RustcLink<'a> { compiler.host, target_compiler.host, target); - add_to_sysroot(&build.sysroot_libdir(target_compiler, target), + add_to_sysroot(&builder.sysroot_libdir(target_compiler, target), &librustc_stamp(build, compiler, target)); } } /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. -pub fn libstd_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf { +pub fn libstd_stamp(build: &Build, compiler: Compiler, target: &str) -> PathBuf { build.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp") } /// Cargo's output path for libtest in a given stage, compiled by a particular /// compiler for the specified target. -pub fn libtest_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf { +pub fn libtest_stamp(build: &Build, compiler: Compiler, target: &str) -> PathBuf { build.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp") } /// Cargo's output path for librustc in a given stage, compiled by a particular /// compiler for the specified target. -pub fn librustc_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf { +pub fn librustc_stamp(build: &Build, compiler: Compiler, target: &str) -> PathBuf { build.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp") } @@ -766,14 +768,14 @@ pub struct Assemble<'a> { } impl<'a> Step<'a> for Assemble<'a> { - type Output = (); + type Output = Compiler<'a>; /// Prepare a new compiler from the artifacts in `stage` /// /// This will assemble a compiler in `build/$host/stage$stage`. The compiler /// must have been previously produced by the `stage - 1` build.build /// compiler. - fn run(self, builder: &Builder) { + fn run(self, builder: &Builder) -> Compiler<'a> { let build = builder.build; let target_compiler = self.target_compiler; @@ -819,10 +821,10 @@ impl<'a> Step<'a> for Assemble<'a> { println!("Assembling stage{} compiler ({})", stage, host); // Link in all dylibs to the libdir - let sysroot = build.sysroot(&target_compiler); + let sysroot = builder.sysroot(target_compiler); let sysroot_libdir = sysroot.join(libdir(host)); t!(fs::create_dir_all(&sysroot_libdir)); - let src_libdir = build.sysroot_libdir(&build_compiler, host); + let src_libdir = builder.sysroot_libdir(build_compiler, host); for f in t!(fs::read_dir(&src_libdir)).map(|f| t!(f)) { let filename = f.file_name().into_string().unwrap(); if is_dylib(&filename) { @@ -830,13 +832,13 @@ impl<'a> Step<'a> for Assemble<'a> { } } - let out_dir = build.cargo_out(&build_compiler, Mode::Librustc, host); + let out_dir = build.cargo_out(build_compiler, Mode::Librustc, host); // Link the compiler binary itself into place let rustc = out_dir.join(exe("rustc", host)); let bindir = sysroot.join("bin"); t!(fs::create_dir_all(&bindir)); - let compiler = build.compiler_path(&target_compiler); + let compiler = build.compiler_path(target_compiler); let _ = fs::remove_file(&compiler); copy(&rustc, &compiler); @@ -848,6 +850,8 @@ impl<'a> Step<'a> for Assemble<'a> { let _ = fs::remove_file(&rustdoc_dst); copy(&rustdoc_src, &rustdoc_dst); } + + target_compiler } } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index da513b1f2f669..4a93e50425d4a 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -37,6 +37,9 @@ use build_helper::output; use {Build, Compiler, Mode}; use channel; use util::{cp_r, libdir, is_dylib, cp_filtered, copy, exe}; +use builder::{Builder, Step}; +use compile; +use tool::{self, Tool}; pub fn pkgname(build: &Build, component: &str) -> String { if component == "cargo" { @@ -57,8 +60,8 @@ pub fn tmpdir(build: &Build) -> PathBuf { build.out.join("tmp/dist") } -fn rust_installer(build: &Build) -> Command { - build.tool_cmd(&Compiler::new(0, &build.build), "rust-installer") +fn rust_installer(builder: &Builder) -> Command { + builder.tool_cmd(Tool::RustInstaller) } // rules.dist("dist-docs", "src/doc") @@ -70,8 +73,8 @@ fn rust_installer(build: &Build) -> Command { #[derive(Serialize)] pub struct Docs<'a> { - stage: u32, - host: &'a str, + pub stage: u32, + pub host: &'a str, } impl<'a> Step<'a> for Docs<'a> { @@ -115,7 +118,7 @@ impl<'a> Step<'a> for Docs<'a> { let src = build.out.join(host).join("doc"); cp_r(&src, &dst); - let mut cmd = rust_installer(build); + let mut cmd = rust_installer(builder); cmd.arg("generate") .arg("--product-name=Rust-Documentation") .arg("--rel-manifest-dir=rustlib") @@ -320,7 +323,7 @@ impl<'a> Step<'a> for Mingw<'a> { // (which is what we want). make_win_dist(&tmpdir(build), &image, host, &build); - let mut cmd = rust_installer(build); + let mut cmd = rust_installer(builder); cmd.arg("generate") .arg("--product-name=Rust-MinGW") .arg("--rel-manifest-dir=rustlib") @@ -346,8 +349,8 @@ impl<'a> Step<'a> for Mingw<'a> { #[derive(Serialize)] pub struct Rustc<'a> { - stage: u32, - host: &'a str, + pub stage: u32, + pub host: &'a str, } impl<'a> Step<'a> for Rustc<'a> { @@ -368,7 +371,7 @@ impl<'a> Step<'a> for Rustc<'a> { } /// Creates the `rustc` installer component. - fn run(self, builder: &builder) { + fn run(self, builder: &Builder) { let build = builder.build; let stage = self.stage; let host = self.host; @@ -414,7 +417,7 @@ impl<'a> Step<'a> for Rustc<'a> { } // Finally, wrap everything up in a nice tarball! - let mut cmd = rust_installer(build); + let mut cmd = rust_installer(builder); cmd.arg("generate") .arg("--product-name=Rust") .arg("--rel-manifest-dir=rustlib") @@ -432,7 +435,7 @@ impl<'a> Step<'a> for Rustc<'a> { fn prepare_image(builder: &Builder, stage: u32, host: &str, image: &Path) { let build = builder.build; - let src = build.sysroot(builder.compiler(stage, host)); + let src = builder.sysroot(builder.compiler(stage, host)); let libdir = libdir(host); // Copy rustc/rustdoc binaries @@ -474,13 +477,13 @@ impl<'a> Step<'a> for Rustc<'a> { } //rules.test("debugger-scripts", "src/etc/lldb_batchmode.py") -// .run(move |s| dist::debugger_scripts(build, &build.sysroot(&s.compiler()), +// .run(move |s| dist::debugger_scripts(build, &builder.sysroot(&s.compiler()), // s.target)); #[derive(Serialize)] pub struct DebuggerScripts<'a> { - sysroot: &'a Path, - host: &'a str, + pub sysroot: &'a Path, + pub host: &'a str, } impl<'a> Step<'a> for DebuggerScripts<'a> { @@ -596,8 +599,8 @@ pub fn rust_src_installer(build: &Build) -> PathBuf { #[derive(Serialize)] pub struct Analysis<'a> { - compiler: Compiler<'a>, - target: &'a str, + pub compiler: Compiler<'a>, + pub target: &'a str, } impl<'a> Step<'a> for Analysis<'a> { @@ -652,7 +655,7 @@ impl<'a> Step<'a> for Analysis<'a> { println!("image_src: {:?}, dst: {:?}", image_src, dst); cp_r(&image_src, &dst); - let mut cmd = rust_installer(build); + let mut cmd = rust_installer(builder); cmd.arg("generate") .arg("--product-name=Rust") .arg("--rel-manifest-dir=rustlib") @@ -784,7 +787,7 @@ impl<'a> Step<'a> for Src { copy_src_dirs(build, &std_src_dirs[..], &std_src_dirs_exclude[..], &dst_src); // Create source tarball in rust-installer format - let mut cmd = rust_installer(build); + let mut cmd = rust_installer(builder); cmd.arg("generate") .arg("--product-name=Rust") .arg("--rel-manifest-dir=rustlib") @@ -903,7 +906,7 @@ impl<'a> Step<'a> for PlainSourceTarball { if let Some(dir) = tarball.parent() { t!(fs::create_dir_all(dir)); } - let mut cmd = rust_installer(build); + let mut cmd = rust_installer(builder); cmd.arg("tarball") .arg("--input").arg(&plain_name) .arg("--output").arg(&tarball) @@ -961,8 +964,8 @@ fn write_file(path: &Path, data: &[u8]) { #[derive(Serialize)] pub struct Cargo<'a> { - stage: u32, - target: &'a str, + pub stage: u32, + pub target: &'a str, } impl<'a> Step<'a> for Cargo<'a> { @@ -1005,7 +1008,7 @@ impl<'a> Step<'a> for Cargo<'a> { // Prepare the image directory t!(fs::create_dir_all(image.join("share/zsh/site-functions"))); t!(fs::create_dir_all(image.join("etc/bash_completion.d"))); - let cargo = build.cargo_out(&compiler, Mode::Tool, target) + let cargo = build.cargo_out(compiler, Mode::Tool, target) .join(exe("cargo", target)); install(&cargo, &image.join("bin"), 0o755); for man in t!(etc.join("man").read_dir()) { @@ -1032,7 +1035,7 @@ impl<'a> Step<'a> for Cargo<'a> { t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); // Generate the installer tarball - let mut cmd = rust_installer(build); + let mut cmd = rust_installer(builder); cmd.arg("generate") .arg("--product-name=Rust") .arg("--rel-manifest-dir=rustlib") @@ -1056,8 +1059,8 @@ impl<'a> Step<'a> for Cargo<'a> { // .run(move |s| dist::rls(build, s.stage, s.target)); #[derive(Serialize)] pub struct Rls<'a> { - stage: u32, - target: &'a str, + pub stage: u32, + pub target: &'a str, } impl<'a> Step<'a> for Rls<'a> { @@ -1098,7 +1101,7 @@ impl<'a> Step<'a> for Rls<'a> { t!(fs::create_dir_all(&image)); // Prepare the image directory - let rls = build.cargo_out(&compiler, Mode::Tool, target) + let rls = build.cargo_out(compiler, Mode::Tool, target) .join(exe("rls", target)); install(&rls, &image.join("bin"), 0o755); let doc = image.join("share/doc/rls"); @@ -1116,7 +1119,7 @@ impl<'a> Step<'a> for Rls<'a> { t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); // Generate the installer tarball - let mut cmd = rust_installer(build); + let mut cmd = rust_installer(builder); cmd.arg("generate") .arg("--product-name=Rust") .arg("--rel-manifest-dir=rustlib") @@ -1162,12 +1165,12 @@ impl<'a> Step<'a> for Extended<'a> { path.ends_with("cargo") } - fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { + fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { if path.is_none() && !builder.build.config.extended { return; } builder.ensure(Extended { - compiler: builder.compiler(builder.top_stage, host), + stage: builder.top_stage, target: target, }); } @@ -1180,9 +1183,9 @@ impl<'a> Step<'a> for Extended<'a> { let compiler = builder.compiler(stage, &build.build); builder.ensure(Std { compiler, target }); - builder.ensure(Rustc { stage, host }); - builder.ensure(Mingw { host }); - builder.ensure(Docs { stage, host }); + builder.ensure(Rustc { stage, host: target }); + builder.ensure(Mingw { host: target }); + builder.ensure(Docs { stage, host: target }); builder.ensure(Cargo { stage, target }); builder.ensure(Rls { stage, target }); builder.ensure(Analysis { compiler, target }); @@ -1240,7 +1243,7 @@ impl<'a> Step<'a> for Extended<'a> { input_tarballs.push(tarball); } - let mut cmd = rust_installer(build); + let mut cmd = rust_installer(builder); cmd.arg("combine") .arg("--product-name=Rust") .arg("--rel-manifest-dir=rustlib") diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 11edee6234459..000ab101d85d5 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -23,10 +23,14 @@ use std::io; use std::path::Path; use std::process::Command; -use {Build, Compiler, Mode}; +use Mode; use util::{cp_r, symlink_dir}; use build_helper::up_to_date; +use builder::{Builder, Step}; +use tool::Tool; +use compile; + macro_rules! book { ($($name:ident, $path:expr, $book_name:expr;)+) => { $( @@ -37,7 +41,6 @@ macro_rules! book { impl<'a> Step<'a> for $name<'a> { type Output = (); - const NAME: &'static str = concat!(stringify!($book_name), " - book"); const DEFAULT: bool = true; fn should_run(_builder: &Builder, path: &Path) -> bool { @@ -90,7 +93,7 @@ book!( ); #[derive(Serialize)] -struct Rustbook<'a> { +pub struct Rustbook<'a> { target: &'a str, name: &'a str, } @@ -132,7 +135,6 @@ pub struct UnstableBook<'a> { impl<'a> Step<'a> for UnstableBook<'a> { type Output = (); - const NAME: &'static str = "unstable book documentation"; const DEFAULT: bool = true; fn should_run(_builder: &Builder, path: &Path) -> bool { @@ -247,7 +249,7 @@ impl<'a> Step<'a> for TheBook<'a> { // build the index page let index = format!("{}/index.md", name); println!("Documenting book index ({})", target); - invoke_rustdoc(build, target, &index); + invoke_rustdoc(builder, target, &index); // build the redirect pages println!("Documenting book redirect pages ({})", target); @@ -256,19 +258,20 @@ impl<'a> Step<'a> for TheBook<'a> { let path = file.path(); let path = path.to_str().unwrap(); - invoke_rustdoc(build, target, path); + invoke_rustdoc(builder, target, path); } } } -fn invoke_rustdoc(build: &Build, target: &str, markdown: &str) { +fn invoke_rustdoc(builder: &Builder, target: &str, markdown: &str) { + let build = builder.build; let out = build.doc_out(target); - let compiler = Compiler::new(0, &build.build); + let compiler = builder.compiler(0, &build.build); let path = build.src.join("src/doc").join(markdown); - let rustdoc = build.rustdoc(&compiler); + let rustdoc = build.rustdoc(compiler); let favicon = build.src.join("src/doc/favicon.inc"); let footer = build.src.join("src/doc/footer.inc"); @@ -287,7 +290,7 @@ fn invoke_rustdoc(build: &Build, target: &str, markdown: &str) { let mut cmd = Command::new(&rustdoc); - build.add_rustc_lib_path(&compiler, &mut cmd); + build.add_rustc_lib_path(compiler, &mut cmd); let out = out.join("book"); @@ -383,7 +386,7 @@ impl<'a> Step<'a> for Standalone<'a> { } let html = out.join(filename).with_extension("html"); - let rustdoc = build.rustdoc(&compiler); + let rustdoc = build.rustdoc(compiler); if up_to_date(&path, &html) && up_to_date(&footer, &html) && up_to_date(&favicon, &html) && @@ -394,7 +397,7 @@ impl<'a> Step<'a> for Standalone<'a> { } let mut cmd = Command::new(&rustdoc); - build.add_rustc_lib_path(&compiler, &mut cmd); + build.add_rustc_lib_path(compiler, &mut cmd); cmd.arg("--html-after-content").arg(&footer) .arg("--html-before-content").arg(&version_info) .arg("--html-in-header").arg(&favicon) @@ -478,9 +481,9 @@ impl<'a> Step<'a> for Std<'a> { }; builder.ensure(compile::Std { compiler, target }); - let out_dir = build.stage_out(&compiler, Mode::Libstd) + let out_dir = build.stage_out(compiler, Mode::Libstd) .join(target).join("doc"); - let rustdoc = build.rustdoc(&compiler); + let rustdoc = build.rustdoc(compiler); // Here what we're doing is creating a *symlink* (directory junction on // Windows) to the final output location. This is not done as an @@ -499,7 +502,7 @@ impl<'a> Step<'a> for Std<'a> { build.clear_if_dirty(&my_out, &rustdoc); t!(symlink_dir_force(&my_out, &out_dir)); - let mut cargo = build.cargo(&compiler, Mode::Libstd, target, "doc"); + let mut cargo = build.cargo(compiler, Mode::Libstd, target, "doc"); cargo.arg("--manifest-path") .arg(build.src.join("src/libstd/Cargo.toml")) .arg("--features").arg(build.std_features()); @@ -536,7 +539,7 @@ impl<'a> Step<'a> for Std<'a> { #[derive(Serialize)] pub struct Test<'a> { stage: u32, - test: &'a str, + target: &'a str, } impl<'a> Step<'a> for Test<'a> { @@ -592,16 +595,16 @@ impl<'a> Step<'a> for Test<'a> { builder.ensure(Std { stage, target }); builder.ensure(compile::Test { compiler, target }); - let out_dir = build.stage_out(&compiler, Mode::Libtest) + let out_dir = build.stage_out(compiler, Mode::Libtest) .join(target).join("doc"); - let rustdoc = build.rustdoc(&compiler); + let rustdoc = build.rustdoc(compiler); // See docs in std above for why we symlink let my_out = build.crate_doc_out(target); build.clear_if_dirty(&my_out, &rustdoc); t!(symlink_dir_force(&my_out, &out_dir)); - let mut cargo = build.cargo(&compiler, Mode::Libtest, target, "doc"); + let mut cargo = build.cargo(compiler, Mode::Libtest, target, "doc"); cargo.arg("--manifest-path") .arg(build.src.join("src/libtest/Cargo.toml")); build.run(&mut cargo); @@ -680,16 +683,16 @@ impl<'a> Step<'a> for Rustc<'a> { builder.ensure(Std { stage, target }); builder.ensure(compile::Rustc { compiler, target }); - let out_dir = build.stage_out(&compiler, Mode::Librustc) + let out_dir = build.stage_out(compiler, Mode::Librustc) .join(target).join("doc"); - let rustdoc = build.rustdoc(&compiler); + let rustdoc = build.rustdoc(compiler); // See docs in std above for why we symlink let my_out = build.crate_doc_out(target); build.clear_if_dirty(&my_out, &rustdoc); t!(symlink_dir_force(&my_out, &out_dir)); - let mut cargo = build.cargo(&compiler, Mode::Librustc, target, "doc"); + let mut cargo = build.cargo(compiler, Mode::Librustc, target, "doc"); cargo.arg("--manifest-path") .arg(build.src.join("src/rustc/Cargo.toml")) .arg("--features").arg(build.rustc_features()); @@ -749,7 +752,7 @@ impl<'a> Step<'a> for ErrorIndex<'a> { /// Generates the HTML rendered error-index by running the /// `error_index_generator` tool. fn run(self, builder: &Builder) { - let builder = builder.build; + let build = builder.build; let target = self.target; builder.ensure(compile::Rustc { @@ -760,7 +763,6 @@ impl<'a> Step<'a> for ErrorIndex<'a> { println!("Documenting error index ({})", target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = Compiler::new(0, &build.build); let mut index = builder.tool_cmd(Tool::ErrorIndex); index.arg("html"); index.arg(out.join("error-index.html")); @@ -822,8 +824,7 @@ impl<'a> Step<'a> for UnstableBookGen<'a> { let out = build.md_doc_out(target).join("unstable-book"); t!(fs::create_dir_all(&out)); t!(fs::remove_dir_all(&out)); - let compiler = Compiler::new(0, &build.build); - let mut cmd = build.tool_cmd(&compiler, "unstable-book-gen"); + let mut cmd = builder.tool_cmd(Tool::UnstableBookGen); cmd.arg(build.src.join("src")); cmd.arg(out); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 5804df34e8b38..30bc8cdef4ad2 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -23,7 +23,6 @@ use getopts::Options; use Build; use config::Config; use metadata; -use step; /// Deserialized version of all flags for this compile. pub struct Flags { @@ -246,10 +245,12 @@ Arguments: config.build = flags.build.clone(); let mut build = Build::new(flags, config); metadata::build(&mut build); - let maybe_rules_help = step::build_rules(&build).get_help(subcommand); - if maybe_rules_help.is_some() { - extra_help.push_str(maybe_rules_help.unwrap().as_str()); - } + + // FIXME: How should this happen now? Not super clear... + // let maybe_rules_help = step::build_rules(&build).get_help(subcommand); + // if maybe_rules_help.is_some() { + // extra_help.push_str(maybe_rules_help.unwrap().as_str()); + // } } else { extra_help.push_str(format!("Run `./x.py {} -h -v` to see a list of available paths.", subcommand).as_str()); diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 3e895bbe90017..4361a4d369a46 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -18,8 +18,10 @@ use std::fs; use std::path::{Path, PathBuf, Component}; use std::process::Command; +use dist::{self, pkgname, sanitize_sh, tmpdir}; + use Build; -use dist::{pkgname, sanitize_sh, tmpdir}; +use builder::{Builder, Step}; pub struct Installer<'a> { build: &'a Build, @@ -165,7 +167,6 @@ macro_rules! install { impl<'a> Step<'a> for $name<'a> { type Output = (); - const NAME: &'static str = concat!("install ", stringify!($name)); const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = $only_hosts; diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 97994f7bf2a9d..b58b46eb8f251 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -65,9 +65,15 @@ //! also check out the `src/bootstrap/README.md` file for more information. #![deny(warnings)] +#![feature(associated_consts)] +#![feature(core_intrinsics)] #[macro_use] extern crate build_helper; +#[macro_use] +extern crate serde_derive; +extern crate serde; +extern crate serde_json; extern crate cmake; extern crate filetime; extern crate gcc; @@ -81,9 +87,8 @@ extern crate libc; use std::cell::Cell; use std::cmp; -use std::collections::HashMap; +use std::collections::{HashSet, HashMap}; use std::env; -use std::ffi::OsString; use std::fs::{self, File}; use std::io::Read; use std::path::{PathBuf, Path}; @@ -93,8 +98,6 @@ use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppresse use util::{exe, libdir, add_lib_path, OutputFolder, CiEnv}; -use builder::Builder; - mod cc; mod channel; mod check; @@ -110,6 +113,8 @@ mod native; mod sanity; pub mod util; mod builder; +mod cache; +mod tool; #[cfg(windows)] mod job; @@ -139,7 +144,7 @@ pub use flags::{Flags, Subcommand}; /// Each compiler has a `stage` that it is associated with and a `host` that /// corresponds to the platform the compiler runs on. This structure is used as /// a parameter to many methods below. -#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] +#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Copy, Hash, Debug)] pub struct Compiler<'a> { stage: u32, host: &'a str, @@ -212,7 +217,7 @@ struct Crate { /// /// These entries currently correspond to the various output directories of the /// build system, with each mod generating output in a different directory. -#[derive(Clone, Copy, PartialEq, Eq)] +#[derive(Serialize, Clone, Copy, PartialEq, Eq)] pub enum Mode { /// Build the standard library, placing output in the "stageN-std" directory. Libstd, @@ -301,12 +306,6 @@ impl Build { } } - fn build_slice(&self) -> &[String] { - unsafe { - std::slice::from_raw_parts(&self.build, 1) - } - } - /// Executes the entire build, as configured by the flags and configuration. pub fn build(&mut self) { unsafe { @@ -335,7 +334,7 @@ impl Build { self.verbose("learning about cargo"); metadata::build(self); - step::run(self); + builder::Builder::run(&self); } /// Clear out `dir` if `input` is newer. @@ -361,7 +360,7 @@ impl Build { /// it will pass the `--target` flag for the specified `target`, and will be /// executing the Cargo command `cmd`. fn cargo(&self, - compiler: &Compiler, + compiler: Compiler, mode: Mode, target: &str, cmd: &str) -> Command { @@ -528,7 +527,7 @@ impl Build { } /// Get a path to the compiler specified. - fn compiler_path(&self, compiler: &Compiler) -> PathBuf { + fn compiler_path(&self, compiler: Compiler) -> PathBuf { if compiler.is_snapshot(self) { self.initial_rustc.clone() } else { @@ -537,13 +536,13 @@ impl Build { } /// Get the specified tool built by the specified compiler - fn tool(&self, compiler: &Compiler, tool: &str) -> PathBuf { + fn tool(&self, compiler: Compiler, tool: &str) -> PathBuf { self.cargo_out(compiler, Mode::Tool, compiler.host) .join(exe(tool, compiler.host)) } /// Get the `rustdoc` executable next to the specified compiler - fn rustdoc(&self, compiler: &Compiler) -> PathBuf { + fn rustdoc(&self, compiler: Compiler) -> PathBuf { let mut rustdoc = self.compiler_path(compiler); rustdoc.pop(); rustdoc.push(exe("rustdoc", compiler.host)); @@ -552,8 +551,8 @@ impl Build { /// Get a `Command` which is ready to run `tool` in `stage` built for /// `host`. - fn tool_cmd(&self, compiler: &Compiler, tool: &str) -> Command { - let mut cmd = Command::new(self.tool(&compiler, tool)); + fn tool_cmd(&self, compiler: Compiler, tool: &str) -> Command { + let mut cmd = Command::new(self.tool(compiler, tool)); self.prepare_tool_cmd(compiler, &mut cmd); cmd } @@ -562,7 +561,7 @@ impl Build { /// /// Notably this munges the dynamic library lookup path to point to the /// right location to run `compiler`. - fn prepare_tool_cmd(&self, compiler: &Compiler, cmd: &mut Command) { + fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) { let host = compiler.host; let mut paths = vec![ self.sysroot_libdir(compiler, compiler.host), @@ -624,23 +623,9 @@ impl Build { if self.config.rust_optimize {"release"} else {"debug"} } - /// Returns the sysroot for the `compiler` specified that *this build system - /// generates*. - /// - /// That is, the sysroot for the stage0 compiler is not what the compiler - /// thinks it is by default, but it's the same as the default for stages - /// 1-3. - fn sysroot(&self, compiler: &Compiler) -> PathBuf { - if compiler.stage == 0 { - self.out.join(compiler.host).join("stage0-sysroot") - } else { - self.out.join(compiler.host).join(format!("stage{}", compiler.stage)) - } - } - /// Get the directory for incremental by-products when using the /// given compiler. - fn incremental_dir(&self, compiler: &Compiler) -> PathBuf { + fn incremental_dir(&self, compiler: Compiler) -> PathBuf { self.out.join(compiler.host).join(format!("stage{}-incremental", compiler.stage)) } @@ -661,7 +646,7 @@ impl Build { /// stage when running with a particular host compiler. /// /// The mode indicates what the root directory is for. - fn stage_out(&self, compiler: &Compiler, mode: Mode) -> PathBuf { + fn stage_out(&self, compiler: Compiler, mode: Mode) -> PathBuf { let suffix = match mode { Mode::Libstd => "-std", Mode::Libtest => "-test", @@ -676,7 +661,7 @@ impl Build { /// running a particular compiler, wehther or not we're building the /// standard library, and targeting the specified architecture. fn cargo_out(&self, - compiler: &Compiler, + compiler: Compiler, mode: Mode, target: &str) -> PathBuf { self.stage_out(compiler, mode).join(target).join(self.cargo_dir()) @@ -759,19 +744,6 @@ impl Build { self.native_dir(target).join("rust-test-helpers") } - /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic - /// library lookup path. - fn add_rustc_lib_path(&self, compiler: &Compiler, cmd: &mut Command) { - // Windows doesn't need dylib path munging because the dlls for the - // compiler live next to the compiler and the system will find them - // automatically. - if cfg!(windows) { - return - } - - add_lib_path(vec![self.rustc_libdir(compiler)], cmd); - } - /// Adds the `RUST_TEST_THREADS` env var if necessary fn add_rust_test_threads(&self, cmd: &mut Command) { if env::var_os("RUST_TEST_THREADS").is_none() { @@ -784,7 +756,7 @@ impl Build { /// /// For example this returns `/lib` on Unix and `/bin` on /// Windows. - fn rustc_libdir(&self, compiler: &Compiler) -> PathBuf { + fn rustc_libdir(&self, compiler: Compiler) -> PathBuf { if compiler.is_snapshot(self) { self.rustc_snapshot_libdir() } else { @@ -960,7 +932,7 @@ impl Build { /// /// When all of these conditions are met the build will lift artifacts from /// the previous stage forward. - fn force_use_stage1(&self, compiler: &Compiler, target: &str) -> bool { + fn force_use_stage1(&self, compiler: Compiler, target: &str) -> bool { !self.config.full_bootstrap && compiler.stage >= 2 && self.config.host.iter().any(|h| h == target) @@ -1110,7 +1082,7 @@ impl<'a> Compiler<'a> { } /// Returns whether this is a snapshot compiler for `build`'s configuration - pub fn is_snapshot(&self, builder: &Build) -> bool { + pub fn is_snapshot(&self, build: &Build) -> bool { self.stage == 0 && self.host == build.build } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 2b44f33db8e18..06af4ceac12e2 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -32,6 +32,7 @@ use gcc; use Build; use util; use build_helper::up_to_date; +use builder::{Builder, Step}; // rules.build("llvm", "src/llvm") // .host(true) @@ -245,7 +246,7 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) { #[derive(Serialize)] pub struct TestHelpers<'a> { - target: &'a str, + pub target: &'a str, } impl<'a> Step<'a> for TestHelpers<'a> { @@ -316,7 +317,7 @@ impl<'a> Step<'a> for Openssl<'a> { } fn run(self, builder: &Builder) { - let build = bulder.build; + let build = builder.build; let target = self.target; let out = match build.openssl_dir(target) { Some(dir) => dir, diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 442ca7aadbc05..234a903ee6cf1 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -66,12 +66,12 @@ impl<'a> Step<'a> for CleanTools<'a> { let compiler = builder.compiler(stage, &build.build); let stamp = match mode { - Mode::Libstd => libstd_stamp(build, &compiler, target), - Mode::Libtest => libtest_stamp(build, &compiler, target), - Mode::Librustc => librustc_stamp(build, &compiler, target), + Mode::Libstd => libstd_stamp(build, compiler, target), + Mode::Libtest => libtest_stamp(build, compiler, target), + Mode::Librustc => librustc_stamp(build, compiler, target), _ => panic!(), }; - let out_dir = build.cargo_out(&compiler, Mode::Tool, target); + let out_dir = build.cargo_out(compiler, Mode::Tool, target); build.clear_if_dirty(&out_dir, &stamp); } } @@ -109,7 +109,7 @@ impl<'a> Step<'a> for ToolBuild<'a> { let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool)); println!("Building stage{} tool {} ({})", stage, tool, target); - let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build"); + let mut cargo = build.cargo(compiler, Mode::Tool, target, "build"); let dir = build.src.join("src/tools").join(tool); cargo.arg("--manifest-path").arg(dir.join("Cargo.toml")); @@ -172,7 +172,6 @@ macro_rules! tool { impl<'a> Step<'a> for $name<'a> { type Output = PathBuf; - const NAME: &'static str = concat!(stringify!($name), " tool"); fn should_run(_builder: &Builder, path: &Path) -> bool { path.ends_with($path) @@ -213,7 +212,7 @@ tool!( // .dep(|s| s.name("maybe-clean-tools")) // .dep(|s| s.name("libstd-tool")) // .run(move |s| compile::tool(build, s.stage, s.target, "unstable-book-gen")); - UnstableBook, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::Libstd; + UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::Libstd; // rules.build("tool-tidy", "src/tools/tidy") // .dep(|s| s.name("maybe-clean-tools")) // .dep(|s| s.name("libstd-tool")) @@ -278,7 +277,6 @@ pub struct Cargo<'a> { impl<'a> Step<'a> for Cargo<'a> { type Output = PathBuf; - const NAME: &'static str = "cargo tool"; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -336,7 +334,6 @@ pub struct Rls<'a> { impl<'a> Step<'a> for Rls<'a> { type Output = PathBuf; - const NAME: &'static str = "RLS tool"; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; From 1a844ebb8f8f3ec2fed09a23597207d35ae1a28e Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 5 Jul 2017 10:48:02 -0600 Subject: [PATCH 06/51] Move tool_cmd to tool.rs --- src/bootstrap/lib.rs | 39 --------------------------------------- src/bootstrap/tool.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index b58b46eb8f251..c1e42c67128c5 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -549,45 +549,6 @@ impl Build { rustdoc } - /// Get a `Command` which is ready to run `tool` in `stage` built for - /// `host`. - fn tool_cmd(&self, compiler: Compiler, tool: &str) -> Command { - let mut cmd = Command::new(self.tool(compiler, tool)); - self.prepare_tool_cmd(compiler, &mut cmd); - cmd - } - - /// Prepares the `cmd` provided to be able to run the `compiler` provided. - /// - /// Notably this munges the dynamic library lookup path to point to the - /// right location to run `compiler`. - fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) { - let host = compiler.host; - let mut paths = vec![ - self.sysroot_libdir(compiler, compiler.host), - self.cargo_out(compiler, Mode::Tool, host).join("deps"), - ]; - - // On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make - // mode) and that C compiler may need some extra PATH modification. Do - // so here. - if compiler.host.contains("msvc") { - let curpaths = env::var_os("PATH").unwrap_or(OsString::new()); - let curpaths = env::split_paths(&curpaths).collect::>(); - for &(ref k, ref v) in self.cc[compiler.host].0.env() { - if k != "PATH" { - continue - } - for path in env::split_paths(v) { - if !curpaths.contains(&path) { - paths.push(path); - } - } - } - } - add_lib_path(paths, cmd); - } - /// Get the space-separated set of activated features for the standard /// library. fn std_features(&self) -> String { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 234a903ee6cf1..f13f9e7d07cee 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -369,3 +369,44 @@ impl<'a> Step<'a> for Rls<'a> { }) } } + +impl<'a> Builder<'a> { + /// Get a `Command` which is ready to run `tool` in `stage` built for + /// `host`. + fn tool_cmd(&self, compiler: Compiler, tool: &str) -> Command { + let mut cmd = Command::new(self.tool(compiler, tool)); + self.prepare_tool_cmd(compiler, &mut cmd); + cmd + } + + /// Prepares the `cmd` provided to be able to run the `compiler` provided. + /// + /// Notably this munges the dynamic library lookup path to point to the + /// right location to run `compiler`. + fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) { + let host = compiler.host; + let mut paths = vec![ + self.sysroot_libdir(compiler, compiler.host), + self.cargo_out(compiler, Mode::Tool, host).join("deps"), + ]; + + // On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make + // mode) and that C compiler may need some extra PATH modification. Do + // so here. + if compiler.host.contains("msvc") { + let curpaths = env::var_os("PATH").unwrap_or(OsString::new()); + let curpaths = env::split_paths(&curpaths).collect::>(); + for &(ref k, ref v) in self.cc[compiler.host].0.env() { + if k != "PATH" { + continue + } + for path in env::split_paths(v) { + if !curpaths.contains(&path) { + paths.push(path); + } + } + } + } + add_lib_path(paths, cmd); + } +} From 276090e870a6a1685701bc91425ffb44439385fd Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 5 Jul 2017 10:54:19 -0600 Subject: [PATCH 07/51] Fix tool_cmd --- src/bootstrap/lib.rs | 6 ------ src/bootstrap/tool.rs | 8 +++++--- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index c1e42c67128c5..13bb08e1b0c2e 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -535,12 +535,6 @@ impl Build { } } - /// Get the specified tool built by the specified compiler - fn tool(&self, compiler: Compiler, tool: &str) -> PathBuf { - self.cargo_out(compiler, Mode::Tool, compiler.host) - .join(exe(tool, compiler.host)) - } - /// Get the `rustdoc` executable next to the specified compiler fn rustdoc(&self, compiler: Compiler) -> PathBuf { let mut rustdoc = self.compiler_path(compiler); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index f13f9e7d07cee..933080ca5fe18 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -13,6 +13,7 @@ use std::path::{Path, PathBuf}; use std::process::Command; use Mode; +use Compiler; use builder::{Step, Builder}; use util::{exe, add_lib_path}; use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp, Rustc}; @@ -373,8 +374,9 @@ impl<'a> Step<'a> for Rls<'a> { impl<'a> Builder<'a> { /// Get a `Command` which is ready to run `tool` in `stage` built for /// `host`. - fn tool_cmd(&self, compiler: Compiler, tool: &str) -> Command { - let mut cmd = Command::new(self.tool(compiler, tool)); + pub fn tool_cmd(&self, tool: Tool) -> Command { + let mut cmd = Command::new(self.tool_exe(tool)); + let compiler = self.compiler(0, &self.build.build); self.prepare_tool_cmd(compiler, &mut cmd); cmd } @@ -394,7 +396,7 @@ impl<'a> Builder<'a> { // mode) and that C compiler may need some extra PATH modification. Do // so here. if compiler.host.contains("msvc") { - let curpaths = env::var_os("PATH").unwrap_or(OsString::new()); + let curpaths = env::var_os("PATH").unwrap_or_default(); let curpaths = env::split_paths(&curpaths).collect::>(); for &(ref k, ref v) in self.cc[compiler.host].0.env() { if k != "PATH" { From 7db49fb4670ed09616d2c05b2e6c1444cee78071 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 5 Jul 2017 11:14:54 -0600 Subject: [PATCH 08/51] Move cargo() to Builder --- src/bootstrap/builder.rs | 93 ++++++++++----------- src/bootstrap/lib.rs | 174 --------------------------------------- 2 files changed, 43 insertions(+), 224 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index b5ae6aa1d2700..ae614e75632b5 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -261,68 +261,61 @@ impl<'a> Builder<'a> { /// rustc compiler, its output will be scoped by `mode`'s output directory, /// it will pass the `--target` flag for the specified `target`, and will be /// executing the Cargo command `cmd`. - pub fn cargo(&self, compiler: Compiler, mode: Mode, target: &str, cmd: &str) -> Command { - let build = self.build; - - // Clear out the output we're about to generate if our compiler changed - { - let out_dir = build.cargo_out(compiler, mode, target); - build.clear_if_dirty(&out_dir, &self.rustc(compiler)); - } - - let mut cargo = Command::new(&build.initial_cargo); - let out_dir = build.stage_out(compiler, mode); - + fn cargo(&self, + compiler: Compiler, + mode: Mode, + target: &str, + cmd: &str) -> Command { + let mut cargo = Command::new(&self.initial_cargo); + let out_dir = self.stage_out(compiler, mode); cargo.env("CARGO_TARGET_DIR", out_dir) .arg(cmd) - .arg("-j").arg(build.jobs().to_string()) + .arg("-j").arg(self.jobs().to_string()) .arg("--target").arg(target); // FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005 // Force cargo to output binaries with disambiguating hashes in the name - cargo.env("__CARGO_DEFAULT_LIB_METADATA", &self.build.config.channel); + cargo.env("__CARGO_DEFAULT_LIB_METADATA", &self.config.channel); let stage; - if compiler.stage == 0 && build.local_rebuild { + if compiler.stage == 0 && self.local_rebuild { // Assume the local-rebuild rustc already has stage1 features. stage = 1; } else { stage = compiler.stage; } - self.build.verbose(&format!("cargo using: {:?}", self.rustc(compiler))); - // Customize the compiler we're running. Specify the compiler to cargo // as our shim and then pass it some various options used to configure - // how the actual compiler itbuild is called. + // how the actual compiler itself is called. // // These variables are primarily all read by // src/bootstrap/bin/{rustc.rs,rustdoc.rs} - cargo.env("RUSTBUILD_NATIVE_DIR", build.native_dir(target)) - .env("RUSTC", build.out.join("bootstrap/debug/rustc")) - .env("RUSTC_REAL", self.rustc(compiler)) + cargo.env("RUSTBUILD_NATIVE_DIR", self.native_dir(target)) + .env("RUSTC", self.out.join("bootstrap/debug/rustc")) + .env("RUSTC_REAL", self.compiler_path(compiler)) .env("RUSTC_STAGE", stage.to_string()) .env("RUSTC_CODEGEN_UNITS", - build.config.rust_codegen_units.to_string()) + self.config.rust_codegen_units.to_string()) .env("RUSTC_DEBUG_ASSERTIONS", - build.config.rust_debug_assertions.to_string()) + self.config.rust_debug_assertions.to_string()) .env("RUSTC_SYSROOT", self.sysroot(compiler)) .env("RUSTC_LIBDIR", self.rustc_libdir(compiler)) - .env("RUSTC_RPATH", build.config.rust_rpath.to_string()) - .env("RUSTDOC", build.out.join("bootstrap/debug/rustdoc")) + .env("RUSTC_RPATH", self.config.rust_rpath.to_string()) + .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc")) .env("RUSTDOC_REAL", self.rustdoc(compiler)) - .env("RUSTC_FLAGS", build.rustc_flags(target).join(" ")); + .env("RUSTC_FLAGS", self.rustc_flags(target).join(" ")); if mode != Mode::Tool { // Tools don't get debuginfo right now, e.g. cargo and rls don't // get compiled with debuginfo. - cargo.env("RUSTC_DEBUGINFO", build.config.rust_debuginfo.to_string()) - .env("RUSTC_DEBUGINFO_LINES", build.config.rust_debuginfo_lines.to_string()) + cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string()) + .env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string()) .env("RUSTC_FORCE_UNSTABLE", "1"); // Currently the compiler depends on crates from crates.io, and // then other crates can depend on the compiler (e.g. proc-macro - // crates). Let's say, for example that rustc itbuild depends on the + // crates). Let's say, for example that rustc itself depends on the // bitflags crate. If an external crate then depends on the // bitflags crate as well, we need to make sure they don't // conflict, even if they pick the same verison of bitflags. We'll @@ -341,58 +334,58 @@ impl<'a> Builder<'a> { // Enable usage of unstable features cargo.env("RUSTC_BOOTSTRAP", "1"); - build.add_rust_test_threads(&mut cargo); + self.add_rust_test_threads(&mut cargo); // Almost all of the crates that we compile as part of the bootstrap may // have a build script, including the standard library. To compile a - // build script, however, it itbuild needs a standard library! This + // build script, however, it itself needs a standard library! This // introduces a bit of a pickle when we're compiling the standard - // library itbuild. + // library itself. // // To work around this we actually end up using the snapshot compiler - // (stage0) for compiling build scripts of the standard library itbuild. + // (stage0) for compiling build scripts of the standard library itself. // The stage0 compiler is guaranteed to have a libstd available for use. // // For other crates, however, we know that we've already got a standard // library up and running, so we can use the normal compiler to compile // build scripts in that situation. if mode == Mode::Libstd { - cargo.env("RUSTC_SNAPSHOT", &build.initial_rustc) - .env("RUSTC_SNAPSHOT_LIBDIR", build.rustc_snapshot_libdir()); + cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc) + .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir()); } else { - cargo.env("RUSTC_SNAPSHOT", self.rustc(compiler)) + cargo.env("RUSTC_SNAPSHOT", self.compiler_path(compiler)) .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_libdir(compiler)); } // Ignore incremental modes except for stage0, since we're // not guaranteeing correctness across builds if the compiler // is changing under your feet.` - if build.flags.incremental && compiler.stage == 0 { - let incr_dir = build.incremental_dir(compiler); + if self.flags.incremental && compiler.stage == 0 { + let incr_dir = self.incremental_dir(compiler); cargo.env("RUSTC_INCREMENTAL", incr_dir); } - if let Some(ref on_fail) = build.flags.on_fail { + if let Some(ref on_fail) = self.flags.on_fail { cargo.env("RUSTC_ON_FAIL", on_fail); } - cargo.env("RUSTC_VERBOSE", format!("{}", build.verbosity)); + cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity)); // Specify some various options for build scripts used throughout // the build. // // FIXME: the guard against msvc shouldn't need to be here if !target.contains("msvc") { - cargo.env(format!("CC_{}", target), build.cc(target)) - .env(format!("AR_{}", target), build.ar(target).unwrap()) // only msvc is None - .env(format!("CFLAGS_{}", target), build.cflags(target).join(" ")); + cargo.env(format!("CC_{}", target), self.cc(target)) + .env(format!("AR_{}", target), self.ar(target).unwrap()) // only msvc is None + .env(format!("CFLAGS_{}", target), self.cflags(target).join(" ")); - if let Ok(cxx) = build.cxx(target) { + if let Ok(cxx) = self.cxx(target) { cargo.env(format!("CXX_{}", target), cxx); } } - if build.config.extended && compiler.is_final_stage(self) { + if mode == Mode::Libstd && self.config.extended && compiler.is_final_stage(self) { cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string()); } @@ -414,21 +407,21 @@ impl<'a> Builder<'a> { // FIXME: should update code to not require this env var cargo.env("CFG_COMPILER_HOST_TRIPLE", target); - if build.is_verbose() { + if self.is_verbose() { cargo.arg("-v"); } // FIXME: cargo bench does not accept `--release` - if build.config.rust_optimize && cmd != "bench" { + if self.config.rust_optimize && cmd != "bench" { cargo.arg("--release"); } - if build.config.locked_deps { + if self.config.locked_deps { cargo.arg("--locked"); } - if build.config.vendor || build.is_sudo { + if self.config.vendor || self.is_sudo { cargo.arg("--frozen"); } - build.ci_env.force_coloring_in_ci(&mut cargo); + self.ci_env.force_coloring_in_ci(&mut cargo); cargo } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 13bb08e1b0c2e..58a5316ea0a66 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -352,180 +352,6 @@ impl Build { t!(File::create(stamp)); } - /// Prepares an invocation of `cargo` to be run. - /// - /// This will create a `Command` that represents a pending execution of - /// Cargo. This cargo will be configured to use `compiler` as the actual - /// rustc compiler, its output will be scoped by `mode`'s output directory, - /// it will pass the `--target` flag for the specified `target`, and will be - /// executing the Cargo command `cmd`. - fn cargo(&self, - compiler: Compiler, - mode: Mode, - target: &str, - cmd: &str) -> Command { - let mut cargo = Command::new(&self.initial_cargo); - let out_dir = self.stage_out(compiler, mode); - cargo.env("CARGO_TARGET_DIR", out_dir) - .arg(cmd) - .arg("-j").arg(self.jobs().to_string()) - .arg("--target").arg(target); - - // FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005 - // Force cargo to output binaries with disambiguating hashes in the name - cargo.env("__CARGO_DEFAULT_LIB_METADATA", &self.config.channel); - - let stage; - if compiler.stage == 0 && self.local_rebuild { - // Assume the local-rebuild rustc already has stage1 features. - stage = 1; - } else { - stage = compiler.stage; - } - - // Customize the compiler we're running. Specify the compiler to cargo - // as our shim and then pass it some various options used to configure - // how the actual compiler itself is called. - // - // These variables are primarily all read by - // src/bootstrap/bin/{rustc.rs,rustdoc.rs} - cargo.env("RUSTBUILD_NATIVE_DIR", self.native_dir(target)) - .env("RUSTC", self.out.join("bootstrap/debug/rustc")) - .env("RUSTC_REAL", self.compiler_path(compiler)) - .env("RUSTC_STAGE", stage.to_string()) - .env("RUSTC_CODEGEN_UNITS", - self.config.rust_codegen_units.to_string()) - .env("RUSTC_DEBUG_ASSERTIONS", - self.config.rust_debug_assertions.to_string()) - .env("RUSTC_SYSROOT", self.sysroot(compiler)) - .env("RUSTC_LIBDIR", self.rustc_libdir(compiler)) - .env("RUSTC_RPATH", self.config.rust_rpath.to_string()) - .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc")) - .env("RUSTDOC_REAL", self.rustdoc(compiler)) - .env("RUSTC_FLAGS", self.rustc_flags(target).join(" ")); - - if mode != Mode::Tool { - // Tools don't get debuginfo right now, e.g. cargo and rls don't - // get compiled with debuginfo. - cargo.env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string()) - .env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string()) - .env("RUSTC_FORCE_UNSTABLE", "1"); - - // Currently the compiler depends on crates from crates.io, and - // then other crates can depend on the compiler (e.g. proc-macro - // crates). Let's say, for example that rustc itself depends on the - // bitflags crate. If an external crate then depends on the - // bitflags crate as well, we need to make sure they don't - // conflict, even if they pick the same verison of bitflags. We'll - // want to make sure that e.g. a plugin and rustc each get their - // own copy of bitflags. - - // Cargo ensures that this works in general through the -C metadata - // flag. This flag will frob the symbols in the binary to make sure - // they're different, even though the source code is the exact - // same. To solve this problem for the compiler we extend Cargo's - // already-passed -C metadata flag with our own. Our rustc.rs - // wrapper around the actual rustc will detect -C metadata being - // passed and frob it with this extra string we're passing in. - cargo.env("RUSTC_METADATA_SUFFIX", "rustc"); - } - - // Enable usage of unstable features - cargo.env("RUSTC_BOOTSTRAP", "1"); - self.add_rust_test_threads(&mut cargo); - - // Almost all of the crates that we compile as part of the bootstrap may - // have a build script, including the standard library. To compile a - // build script, however, it itself needs a standard library! This - // introduces a bit of a pickle when we're compiling the standard - // library itself. - // - // To work around this we actually end up using the snapshot compiler - // (stage0) for compiling build scripts of the standard library itself. - // The stage0 compiler is guaranteed to have a libstd available for use. - // - // For other crates, however, we know that we've already got a standard - // library up and running, so we can use the normal compiler to compile - // build scripts in that situation. - if mode == Mode::Libstd { - cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc) - .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir()); - } else { - cargo.env("RUSTC_SNAPSHOT", self.compiler_path(compiler)) - .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_libdir(compiler)); - } - - // Ignore incremental modes except for stage0, since we're - // not guaranteeing correctness across builds if the compiler - // is changing under your feet.` - if self.flags.incremental && compiler.stage == 0 { - let incr_dir = self.incremental_dir(compiler); - cargo.env("RUSTC_INCREMENTAL", incr_dir); - } - - if let Some(ref on_fail) = self.flags.on_fail { - cargo.env("RUSTC_ON_FAIL", on_fail); - } - - cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity)); - - // Specify some various options for build scripts used throughout - // the build. - // - // FIXME: the guard against msvc shouldn't need to be here - if !target.contains("msvc") { - cargo.env(format!("CC_{}", target), self.cc(target)) - .env(format!("AR_{}", target), self.ar(target).unwrap()) // only msvc is None - .env(format!("CFLAGS_{}", target), self.cflags(target).join(" ")); - - if let Ok(cxx) = self.cxx(target) { - cargo.env(format!("CXX_{}", target), cxx); - } - } - - if mode == Mode::Libstd && - self.config.extended && - compiler.is_final_stage(self) { - cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string()); - } - - // When being built Cargo will at some point call `nmake.exe` on Windows - // MSVC. Unfortunately `nmake` will read these two environment variables - // below and try to intepret them. We're likely being run, however, from - // MSYS `make` which uses the same variables. - // - // As a result, to prevent confusion and errors, we remove these - // variables from our environment to prevent passing MSYS make flags to - // nmake, causing it to blow up. - if cfg!(target_env = "msvc") { - cargo.env_remove("MAKE"); - cargo.env_remove("MAKEFLAGS"); - } - - // Environment variables *required* throughout the build - // - // FIXME: should update code to not require this env var - cargo.env("CFG_COMPILER_HOST_TRIPLE", target); - - if self.is_verbose() { - cargo.arg("-v"); - } - // FIXME: cargo bench does not accept `--release` - if self.config.rust_optimize && cmd != "bench" { - cargo.arg("--release"); - } - if self.config.locked_deps { - cargo.arg("--locked"); - } - if self.config.vendor || self.is_sudo { - cargo.arg("--frozen"); - } - - self.ci_env.force_coloring_in_ci(&mut cargo); - - cargo - } - /// Get a path to the compiler specified. fn compiler_path(&self, compiler: Compiler) -> PathBuf { if compiler.is_snapshot(self) { From c114fe576f12be5b17e34c37dc34283f25d2eae1 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 5 Jul 2017 11:21:33 -0600 Subject: [PATCH 09/51] Finish fixing warnings and errors. Bootstrap builds. --- src/bootstrap/builder.rs | 39 ++++++++++++++++++++------------------- src/bootstrap/check.rs | 23 ++++++++++++----------- src/bootstrap/compile.rs | 12 ++++++------ src/bootstrap/dist.rs | 2 +- src/bootstrap/doc.rs | 20 ++++++++++---------- src/bootstrap/lib.rs | 32 +------------------------------- src/bootstrap/tool.rs | 2 +- 7 files changed, 51 insertions(+), 79 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index ae614e75632b5..589401ea24e2c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -187,22 +187,6 @@ impl<'a> Builder<'a> { self.ensure(compile::Assemble { target_compiler: Compiler { stage, host } }) } - pub fn rustc(&self, compiler: Compiler) -> PathBuf { - if compiler.is_snapshot(self) { - self.build.initial_rustc.clone() - } else { - self.compiler(compiler.stage, compiler.host); - self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host)) - } - } - - pub fn rustdoc(&self, compiler: Compiler) -> PathBuf { - let mut rustdoc = self.rustc(compiler); - rustdoc.pop(); - rustdoc.push(exe("rustdoc", compiler.host)); - rustdoc - } - pub fn sysroot(&self, compiler: Compiler<'a>) -> PathBuf { self.ensure(compile::Sysroot { compiler }) } @@ -254,6 +238,23 @@ impl<'a> Builder<'a> { add_lib_path(vec![self.rustc_libdir(compiler)], cmd); } + /// Get a path to the compiler specified. + pub fn rustc(&self, compiler: Compiler) -> PathBuf { + if compiler.is_snapshot(self) { + self.initial_rustc.clone() + } else { + self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host)) + } + } + + /// Get the `rustdoc` executable next to the specified compiler + pub fn rustdoc(&self, compiler: Compiler) -> PathBuf { + let mut rustdoc = self.rustc(compiler); + rustdoc.pop(); + rustdoc.push(exe("rustdoc", compiler.host)); + rustdoc + } + /// Prepares an invocation of `cargo` to be run. /// /// This will create a `Command` that represents a pending execution of @@ -261,7 +262,7 @@ impl<'a> Builder<'a> { /// rustc compiler, its output will be scoped by `mode`'s output directory, /// it will pass the `--target` flag for the specified `target`, and will be /// executing the Cargo command `cmd`. - fn cargo(&self, + pub fn cargo(&self, compiler: Compiler, mode: Mode, target: &str, @@ -293,7 +294,7 @@ impl<'a> Builder<'a> { // src/bootstrap/bin/{rustc.rs,rustdoc.rs} cargo.env("RUSTBUILD_NATIVE_DIR", self.native_dir(target)) .env("RUSTC", self.out.join("bootstrap/debug/rustc")) - .env("RUSTC_REAL", self.compiler_path(compiler)) + .env("RUSTC_REAL", self.rustc(compiler)) .env("RUSTC_STAGE", stage.to_string()) .env("RUSTC_CODEGEN_UNITS", self.config.rust_codegen_units.to_string()) @@ -353,7 +354,7 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc) .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir()); } else { - cargo.env("RUSTC_SNAPSHOT", self.compiler_path(compiler)) + cargo.env("RUSTC_SNAPSHOT", self.rustc(compiler)) .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_libdir(compiler)); } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 0d838a507ce95..f253ce8016073 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -170,8 +170,8 @@ impl<'a> Step<'a> for Cargotest<'a> { let mut cmd = builder.tool_cmd(Tool::CargoTest); try_run(build, cmd.arg(&build.initial_cargo) .arg(&out_dir) - .env("RUSTC", build.compiler_path(compiler)) - .env("RUSTDOC", build.rustdoc(compiler))); + .env("RUSTC", builder.rustc(compiler)) + .env("RUSTDOC", builder.rustdoc(compiler))); } } @@ -215,7 +215,7 @@ impl<'a> Step<'a> for Cargo<'a> { iter::once(path).chain(env::split_paths(&old_path)) ).expect(""); - let mut cargo = build.cargo(compiler, Mode::Tool, self.host, "test"); + let mut cargo = builder.cargo(compiler, Mode::Tool, self.host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml")); if !build.fail_fast { cargo.arg("--no-fail-fast"); @@ -584,10 +584,10 @@ impl<'a> Step<'a> for Compiletest<'a> { // compiletest currently has... a lot of arguments, so let's just pass all // of them! - cmd.arg("--compile-lib-path").arg(build.rustc_libdir(compiler)); + cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(compiler)); cmd.arg("--run-lib-path").arg(builder.sysroot_libdir(compiler, target)); - cmd.arg("--rustc-path").arg(build.compiler_path(compiler)); - cmd.arg("--rustdoc-path").arg(build.rustdoc(compiler)); + cmd.arg("--rustc-path").arg(builder.rustc(compiler)); + cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler)); cmd.arg("--src-base").arg(build.src.join("src/test").join(suite)); cmd.arg("--build-base").arg(testdir(build, compiler.host).join(suite)); cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target)); @@ -806,11 +806,12 @@ impl<'a> Step<'a> for ErrorIndex<'a> { .arg(&output) .env("CFG_BUILD", &build.build)); - markdown_test(build, compiler, &output); + markdown_test(builder, compiler, &output); } } -fn markdown_test(build: &Build, compiler: Compiler, markdown: &Path) { +fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) { + let build = builder.build; let mut file = t!(File::open(markdown)); let mut contents = String::new(); t!(file.read_to_string(&mut contents)); @@ -819,8 +820,8 @@ fn markdown_test(build: &Build, compiler: Compiler, markdown: &Path) { } println!("doc tests for: {}", markdown.display()); - let mut cmd = Command::new(build.rustdoc(compiler)); - build.add_rustc_lib_path(compiler, &mut cmd); + let mut cmd = Command::new(builder.rustdoc(compiler)); + builder.add_rustc_lib_path(compiler, &mut cmd); build.add_rust_test_threads(&mut cmd); cmd.arg("--test"); cmd.arg(markdown); @@ -1071,7 +1072,7 @@ impl<'a> Step<'a> for Krate<'a> { // Pass in some standard flags then iterate over the graph we've discovered // in `cargo metadata` with the maps above and figure out what `-p` // arguments need to get passed. - let mut cargo = build.cargo(compiler, mode, target, test_kind.subcommand()); + let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand()); cargo.arg("--manifest-path") .arg(build.src.join(path).join("Cargo.toml")) .arg("--features").arg(features); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index f64aa636da10d..2c544bf1f949e 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -196,7 +196,7 @@ impl<'a> Step<'a> for Std<'a> { compiler.host, target); let out_dir = build.cargo_out(compiler, Mode::Libstd, target); - build.clear_if_dirty(&out_dir, &build.compiler_path(compiler)); + build.clear_if_dirty(&out_dir, &builder.rustc(compiler)); let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "build"); let mut features = build.std_features(); @@ -365,7 +365,7 @@ impl<'a> Step<'a> for StartupObjects<'a> { } let compiler = builder.compiler(0, &build.build); - let compiler_path = build.compiler_path(compiler); + let compiler_path = builder.rustc(compiler); let src_dir = &build.src.join("src/rtstartup"); let dst_dir = &build.native_dir(target).join("rtstartup"); let sysroot_dir = &builder.sysroot_libdir(for_compiler, target); @@ -454,7 +454,7 @@ impl<'a> Step<'a> for Test<'a> { compiler.host, target); let out_dir = build.cargo_out(compiler, Mode::Libtest, target); build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); - let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build"); + let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "build"); if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } @@ -465,7 +465,7 @@ impl<'a> Step<'a> for Test<'a> { &libtest_stamp(build, compiler, target)); builder.ensure(TestLink { - compiler: builder.compiler(1, &build.build), + compiler: builder.compiler(compiler.stage, &build.build), target_compiler: compiler, target: target, }); @@ -583,7 +583,7 @@ impl<'a> Step<'a> for Rustc<'a> { let out_dir = build.cargo_out(compiler, Mode::Librustc, target); build.clear_if_dirty(&out_dir, &libtest_stamp(build, compiler, target)); - let mut cargo = build.cargo(compiler, Mode::Librustc, target, "build"); + let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build"); cargo.arg("--features").arg(build.rustc_features()) .arg("--manifest-path") .arg(build.src.join("src/rustc/Cargo.toml")); @@ -838,7 +838,7 @@ impl<'a> Step<'a> for Assemble<'a> { let rustc = out_dir.join(exe("rustc", host)); let bindir = sysroot.join("bin"); t!(fs::create_dir_all(&bindir)); - let compiler = build.compiler_path(target_compiler); + let compiler = builder.rustc(target_compiler); let _ = fs::remove_file(&compiler); copy(&rustc, &compiler); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 4a93e50425d4a..a2f779514a997 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -998,7 +998,7 @@ impl<'a> Step<'a> for Cargo<'a> { let etc = src.join("src/etc"); let release_num = build.release_num("cargo"); let name = pkgname(build, "cargo"); - let version = build.cargo_info.version(build, &release_num); + let version = builder.cargo_info.version(build, &release_num); let tmp = tmpdir(build); let image = tmp.join("cargo-image"); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 000ab101d85d5..3493f4e66bca0 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -271,7 +271,7 @@ fn invoke_rustdoc(builder: &Builder, target: &str, markdown: &str) { let path = build.src.join("src/doc").join(markdown); - let rustdoc = build.rustdoc(compiler); + let rustdoc = builder.rustdoc(compiler); let favicon = build.src.join("src/doc/favicon.inc"); let footer = build.src.join("src/doc/footer.inc"); @@ -290,7 +290,7 @@ fn invoke_rustdoc(builder: &Builder, target: &str, markdown: &str) { let mut cmd = Command::new(&rustdoc); - build.add_rustc_lib_path(compiler, &mut cmd); + builder.add_rustc_lib_path(compiler, &mut cmd); let out = out.join("book"); @@ -386,7 +386,7 @@ impl<'a> Step<'a> for Standalone<'a> { } let html = out.join(filename).with_extension("html"); - let rustdoc = build.rustdoc(compiler); + let rustdoc = builder.rustdoc(compiler); if up_to_date(&path, &html) && up_to_date(&footer, &html) && up_to_date(&favicon, &html) && @@ -397,7 +397,7 @@ impl<'a> Step<'a> for Standalone<'a> { } let mut cmd = Command::new(&rustdoc); - build.add_rustc_lib_path(compiler, &mut cmd); + builder.add_rustc_lib_path(compiler, &mut cmd); cmd.arg("--html-after-content").arg(&footer) .arg("--html-before-content").arg(&version_info) .arg("--html-in-header").arg(&favicon) @@ -483,7 +483,7 @@ impl<'a> Step<'a> for Std<'a> { builder.ensure(compile::Std { compiler, target }); let out_dir = build.stage_out(compiler, Mode::Libstd) .join(target).join("doc"); - let rustdoc = build.rustdoc(compiler); + let rustdoc = builder.rustdoc(compiler); // Here what we're doing is creating a *symlink* (directory junction on // Windows) to the final output location. This is not done as an @@ -502,7 +502,7 @@ impl<'a> Step<'a> for Std<'a> { build.clear_if_dirty(&my_out, &rustdoc); t!(symlink_dir_force(&my_out, &out_dir)); - let mut cargo = build.cargo(compiler, Mode::Libstd, target, "doc"); + let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "doc"); cargo.arg("--manifest-path") .arg(build.src.join("src/libstd/Cargo.toml")) .arg("--features").arg(build.std_features()); @@ -597,14 +597,14 @@ impl<'a> Step<'a> for Test<'a> { builder.ensure(compile::Test { compiler, target }); let out_dir = build.stage_out(compiler, Mode::Libtest) .join(target).join("doc"); - let rustdoc = build.rustdoc(compiler); + let rustdoc = builder.rustdoc(compiler); // See docs in std above for why we symlink let my_out = build.crate_doc_out(target); build.clear_if_dirty(&my_out, &rustdoc); t!(symlink_dir_force(&my_out, &out_dir)); - let mut cargo = build.cargo(compiler, Mode::Libtest, target, "doc"); + let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "doc"); cargo.arg("--manifest-path") .arg(build.src.join("src/libtest/Cargo.toml")); build.run(&mut cargo); @@ -685,14 +685,14 @@ impl<'a> Step<'a> for Rustc<'a> { builder.ensure(compile::Rustc { compiler, target }); let out_dir = build.stage_out(compiler, Mode::Librustc) .join(target).join("doc"); - let rustdoc = build.rustdoc(compiler); + let rustdoc = builder.rustdoc(compiler); // See docs in std above for why we symlink let my_out = build.crate_doc_out(target); build.clear_if_dirty(&my_out, &rustdoc); t!(symlink_dir_force(&my_out, &out_dir)); - let mut cargo = build.cargo(compiler, Mode::Librustc, target, "doc"); + let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc"); cargo.arg("--manifest-path") .arg(build.src.join("src/rustc/Cargo.toml")) .arg("--features").arg(build.rustc_features()); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 58a5316ea0a66..2a7cc58bddd8e 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -96,7 +96,7 @@ use std::process::Command; use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime}; -use util::{exe, libdir, add_lib_path, OutputFolder, CiEnv}; +use util::{exe, libdir, OutputFolder, CiEnv}; mod cc; mod channel; @@ -352,23 +352,6 @@ impl Build { t!(File::create(stamp)); } - /// Get a path to the compiler specified. - fn compiler_path(&self, compiler: Compiler) -> PathBuf { - if compiler.is_snapshot(self) { - self.initial_rustc.clone() - } else { - self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host)) - } - } - - /// Get the `rustdoc` executable next to the specified compiler - fn rustdoc(&self, compiler: Compiler) -> PathBuf { - let mut rustdoc = self.compiler_path(compiler); - rustdoc.pop(); - rustdoc.push(exe("rustdoc", compiler.host)); - rustdoc - } - /// Get the space-separated set of activated features for the standard /// library. fn std_features(&self) -> String { @@ -532,19 +515,6 @@ impl Build { } } - /// Returns the compiler's libdir where it stores the dynamic libraries that - /// it itself links against. - /// - /// For example this returns `/lib` on Unix and `/bin` on - /// Windows. - fn rustc_libdir(&self, compiler: Compiler) -> PathBuf { - if compiler.is_snapshot(self) { - self.rustc_snapshot_libdir() - } else { - self.sysroot(compiler).join(libdir(compiler.host)) - } - } - /// Returns the libdir of the snapshot compiler. fn rustc_snapshot_libdir(&self) -> PathBuf { self.initial_rustc.parent().unwrap().parent().unwrap() diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 933080ca5fe18..50e76c324c3ea 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -110,7 +110,7 @@ impl<'a> Step<'a> for ToolBuild<'a> { let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool)); println!("Building stage{} tool {} ({})", stage, tool, target); - let mut cargo = build.cargo(compiler, Mode::Tool, target, "build"); + let mut cargo = builder.cargo(compiler, Mode::Tool, target, "build"); let dir = build.src.join("src/tools").join(tool); cargo.arg("--manifest-path").arg(dir.join("Cargo.toml")); From ef1d1bdc18e62a4b89c64bf87c7dfbd57aba8933 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 6 Jul 2017 09:15:08 -0600 Subject: [PATCH 10/51] Move code out of macro and into generic method. --- src/bootstrap/builder.rs | 79 ++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 589401ea24e2c..eceb68d1f4dd8 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -81,57 +81,19 @@ pub enum Kind { } macro_rules! check { - (@inner $self:ident, $rule:ty, $path:expr) => { - let build = $self.build; - let hosts = if <$rule>::ONLY_BUILD_TARGETS || <$rule>::ONLY_BUILD { - &build.config.host[..1] - } else { - &build.hosts - }; - - // Determine the actual targets participating in this rule. - // NOTE: We should keep the full projection from build triple to - // the hosts for the dist steps, now that the hosts array above is - // truncated to avoid duplication of work in that case. Therefore - // the original non-shadowed hosts array is used below. - let targets = if <$rule>::ONLY_HOSTS { - // If --target was specified but --host wasn't specified, - // don't run any host-only tests. Also, respect any `--host` - // overrides as done for `hosts`. - if build.flags.host.len() > 0 { - &build.flags.host[..] - } else if build.flags.target.len() > 0 { - &[] - } else if <$rule>::ONLY_BUILD { - &build.config.host[..1] - } else { - &build.config.host[..] - } - } else { - &build.targets - }; - - build.verbose(&format!("executing {} with hosts={:?}, targets={:?}", - stringify!($rule), hosts, targets)); - for host in hosts { - for target in targets { - <$rule>::make_run($self, $path, host, target); - } - } - }; ($self:ident, $paths:ident, $($rule:ty),+ $(,)*) => {{ let paths = $paths; if paths.is_empty() { $({ if <$rule>::DEFAULT { - check!(@inner $self, $rule, None); + $self.maybe_run::<$rule>(None); } })+ } else { for path in paths { $({ if <$rule>::should_run($self, path) { - check!(@inner $self, $rule, Some(path)); + $self.maybe_run::<$rule>(Some(path)); } })+ } @@ -427,6 +389,43 @@ impl<'a> Builder<'a> { cargo } + fn maybe_run>(&'a self, path: Option<&Path>) { + let build = self.build; + let hosts = if S::ONLY_BUILD_TARGETS || S::ONLY_BUILD { + &build.config.host[..1] + } else { + &build.hosts + }; + + // Determine the actual targets participating in this rule. + // NOTE: We should keep the full projection from build triple to + // the hosts for the dist steps, now that the hosts array above is + // truncated to avoid duplication of work in that case. Therefore + // the original non-shadowed hosts array is used below. + let targets = if S::ONLY_HOSTS { + // If --target was specified but --host wasn't specified, + // don't run any host-only tests. Also, respect any `--host` + // overrides as done for `hosts`. + if build.flags.host.len() > 0 { + &build.flags.host[..] + } else if build.flags.target.len() > 0 { + &[] + } else if S::ONLY_BUILD { + &build.config.host[..1] + } else { + &build.config.host[..] + } + } else { + &build.targets + }; + + for host in hosts { + for target in targets { + S::make_run(self, path, host, target); + } + } + } + pub fn ensure + Serialize>(&'a self, step: S) -> S::Output where S::Output: 'a From e62fdf3a595d030d50ce5ec51add8b1ff5ee1cce Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 6 Jul 2017 09:42:50 -0600 Subject: [PATCH 11/51] Pacify tidy --- src/bootstrap/compile.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 2c544bf1f949e..ab4eec0199f0b 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -598,7 +598,8 @@ impl<'a> Step<'a> for Rustc<'a> { if compiler.stage == 0 { cargo.env("CFG_LIBDIR_RELATIVE", "lib"); } else { - let libdir_relative = build.config.libdir_relative.clone().unwrap_or(PathBuf::from("lib")); + let libdir_relative = + build.config.libdir_relative.clone().unwrap_or(PathBuf::from("lib")); cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative); } From 8264e42cb2d70ceea06109b36ce5ef46da647859 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Fri, 7 Jul 2017 11:17:37 -0600 Subject: [PATCH 12/51] Add documentation to Step and related methods on Builder. --- src/bootstrap/builder.rs | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index eceb68d1f4dd8..e6432e8938c1c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -44,12 +44,20 @@ impl<'a> Deref for Builder<'a> { } } -pub trait Step<'a>: Sized { - type Output: Serialize + Deserialize<'a>; +pub trait Step<'a>: Serialize + Sized { + /// The output type of this step. This is used in a few places to return a + /// `PathBuf` when directories are created or to return a `Compiler` once + /// it's been assembled. + /// + /// When possible, this should be used instead of implicitly creating files + /// in a prearranged directory that will later be used by the build system. + /// It's not always practical, however, since it makes avoiding rebuilds + /// somewhat harder. + type Output: Serialize + Deserialize<'a> + 'a; const DEFAULT: bool = false; - /// Run this rule for all hosts, and just the same hosts as the targets. + /// Run this rule for all hosts without cross compiling. const ONLY_HOSTS: bool = false; /// Run this rule for all targets, but only with the native host. @@ -58,10 +66,22 @@ pub trait Step<'a>: Sized { /// Only run this step with the build triple as host and target. const ONLY_BUILD: bool = false; + /// Primary function to execute this rule. Can call `builder.ensure(...)` + /// with other steps to run those. fn run(self, builder: &'a Builder) -> Self::Output; + /// When bootstrap is passed a set of paths, this controls whether this rule + /// will execute. However, it does not get called in a "default" context + /// when we are not passed any paths; in that case, make_run is called + /// directly. fn should_run(_builder: &'a Builder, _path: &Path) -> bool { false } + /// Build up a "root" rule, either as a default rule or from a path passed + /// to us. + /// + /// When path is `None`, we are executing in a context where no paths were + /// passed. When `./x.py build` is run, for example, this rule could get + /// called if it is in the correct list below with a path of `None`. fn make_run( _builder: &'a Builder, _path: Option<&Path>, @@ -145,6 +165,10 @@ impl<'a> Builder<'a> { doc::Nomicon, doc::Reference); } + /// Obtain a compiler at a given stage and for a given host. Explictly does + /// not take `Compiler` since all `Compiler` instances are meant to be + /// obtained through this function, since it ensures that they are valid + /// (i.e., built and assembled). pub fn compiler(&'a self, stage: u32, host: &'a str) -> Compiler<'a> { self.ensure(compile::Assemble { target_compiler: Compiler { stage, host } }) } @@ -426,10 +450,10 @@ impl<'a> Builder<'a> { } } - pub fn ensure + Serialize>(&'a self, step: S) -> S::Output - where - S::Output: 'a - { + /// Ensure that a given step is built, returning it's output. This will + /// cache the step, so it is safe (and good!) to call this as often as + /// needed to ensure that all dependencies are built. + pub fn ensure>(&'a self, step: S) -> S::Output { let key = Cache::to_key(&step); { let mut stack = self.stack.borrow_mut(); From b881aaed90f56af95fe7da6bedcb9144f82ba93d Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Mon, 3 Jul 2017 18:20:46 -0600 Subject: [PATCH 13/51] Document the process more thoroughly --- src/bootstrap/lib.rs | 83 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2a7cc58bddd8e..d6b474ab3aff1 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -23,38 +23,87 @@ //! //! ## Architecture //! -//! Although this build system defers most of the complicated logic to Cargo -//! itself, it still needs to maintain a list of targets and dependencies which -//! it can itself perform. Rustbuild is made up of a list of rules with -//! dependencies amongst them (created in the `step` module) and then knows how -//! to execute each in sequence. Each time rustbuild is invoked, it will simply -//! iterate through this list of steps and execute each serially in turn. For -//! each step rustbuild relies on the step internally being incremental and +//! The build system defers most of the complicated logic managing invocations +//! of rustc and rustdoc to Cargo itself. However, moving through various stages +//! and copying artifacts is still necessary for it to do. Each time rustbuild +//! is invoked, it will iterate through the list of predefined steps and execute +//! each serially in turn if it matches the paths passed or is a default rule. +//! For each step rustbuild relies on the step internally being incremental and //! parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded //! to appropriate test harnesses and such. //! //! Most of the "meaty" steps that matter are backed by Cargo, which does indeed //! have its own parallelism and incremental management. Later steps, like //! tests, aren't incremental and simply run the entire suite currently. +//! However, compiletest itself tries to avoid running tests when the artifacts +//! that are involved (mainly the compiler) haven't changed. //! //! When you execute `x.py build`, the steps which are executed are: //! //! * First, the python script is run. This will automatically download the -//! stage0 rustc and cargo according to `src/stage0.txt`, or using the cached +//! stage0 rustc and cargo according to `src/stage0.txt`, or use the cached //! versions if they're available. These are then used to compile rustbuild //! itself (using Cargo). Finally, control is then transferred to rustbuild. //! //! * Rustbuild takes over, performs sanity checks, probes the environment, -//! reads configuration, builds up a list of steps, and then starts executing -//! them. +//! reads configuration, and starts executing steps as it reads the command +//! line arguments (paths) or going through the default rules. //! -//! * The stage0 libstd is compiled -//! * The stage0 libtest is compiled -//! * The stage0 librustc is compiled -//! * The stage1 compiler is assembled -//! * The stage1 libstd, libtest, librustc are compiled -//! * The stage2 compiler is assembled -//! * The stage2 libstd, libtest, librustc are compiled +//! The build output will be something like the following: +//! +//! Building stage0 std artifacts +//! Copying stage0 std +//! Building stage0 test artifacts +//! Copying stage0 test +//! Building stage0 compiler artifacts +//! Copying stage0 rustc +//! Assembling stage1 compiler +//! Building stage1 std artifacts +//! Copying stage1 std +//! Building stage1 test artifacts +//! Copying stage1 test +//! Building stage1 compiler artifacts +//! Copying stage1 rustc +//! Assembling stage2 compiler +//! Uplifting stage1 std +//! Uplifting stage1 test +//! Uplifting stage1 rustc +//! +//! Let's disect that a little: +//! +//! ## Building stage0 {std,test,compiler} artifacts +//! +//! These steps use the provided (downloaded, usually) compiler to compile the +//! local Rust source into libraries we can use. +//! +//! ## Copying stage0 {std,test,rustc} +//! +//! This copies the build output from Cargo into +//! `build/$HOST/stage0-sysroot/lib/rustlib/$ARCH/lib`. FIXME: This step's +//! documentation should be expanded -- the information already here may be +//! incorrect. +//! +//! ## Assembling stage1 compiler +//! +//! This copies the libraries we built in "building stage0 ... artifacts" into +//! the stage1 compiler's lib directory. These are the host libraries that the +//! compiler itself uses to run. These aren't actually used by artifacts the new +//! compiler generates. This step also copies the rustc and rustdoc binaries we +//! generated into build/$HOST/stage/bin. +//! +//! The stage1/bin/rustc is a fully functional compiler, but it doesn't yet have +//! any libraries to link built binaries or libraries to. The next 3 steps will +//! provide those libraries for it; they are mostly equivalent to constructing +//! the stage1/bin compiler so we don't go through them individually. +//! +//! ## Uplifiting stage1 {std,test,rustc} +//! +//! This step copies the libraries from the stage1 compiler sysroot into the +//! stage2 compiler. This is done to avoid rebuilding the compiler; libraries +//! we'd build in this step should be identical (in function, if not necessarily +//! identical on disk) so there's no need to recompile the compiler again. Note +//! that if you want to, you can enable the full-bootstrap option to change this +//! behavior. //! //! Each step is driven by a separate Cargo project and rustbuild orchestrates //! copying files between steps and otherwise preparing for Cargo to run. From 1ab893060388e1dc0bca95a29b47b49cc9b23288 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Fri, 7 Jul 2017 11:51:57 -0600 Subject: [PATCH 14/51] Move compiletest config into a struct --- src/bootstrap/check.rs | 139 ++++++++++++++++++++++++++++++----------- 1 file changed, 102 insertions(+), 37 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index f253ce8016073..a847a2f47f661 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -444,37 +444,99 @@ pub struct Compiletest<'a> { suite: &'a str, } -static COMPILETESTS: &[(bool, &str, &str, &str)] = &[ - // default, path, mode, suite - (true, "src/test/codegen", "codegen", "codegen"), - (true, "src/test/codegen-units", "codegen-units", "codegen-units"), - (true, "src/test/compile-fail", "compile-fail", "compile-fail"), - (true, "src/test/incremental", "incremental", "incremental"), - (true, "src/test/mir-opt", "mir-opt", "mir-opt"), - (true, "src/test/parse-fail", "parse-fail", "parse-fail"), - (true, "src/test/run-fail", "run-fail", "run-fail"), - (true, "src/test/run-pass", "run-pass", "run-pass"), - (true, "src/test/run-pass-valgrind", "run-pass-valgrind", "run-pass-valgrind"), - (true, "src/test/ui", "ui", "ui"), - (false, "src/test/debuginfo-lldb", "debuginfo-lldb", "debuginfo"), - (false, "src/test/debuginfo-gdb", "debuginfo-gdb", "debuginfo"), +#[derive(Copy, Clone, Debug)] +struct Test { + default: bool, + path: &'static str, + mode: &'static str, + suite: &'static str, +} + +static COMPILETESTS: &[Test] = &[ + Test { default: true, path: "src/test/codegen", mode: "codegen", suite: "codegen" }, + Test { + default: true, + path: "src/test/codegen-units", + mode: "codegen-units", + suite: "codegen-units", + }, + Test { + default: true, + path: "src/test/compile-fail", + mode: "compile-fail", + suite: "compile-fail", + }, + Test { default: true, path: "src/test/incremental", mode: "incremental", suite: "incremental" }, + Test { default: true, path: "src/test/mir-opt", mode: "mir-opt", suite: "mir-opt" }, + Test { default: true, path: "src/test/parse-fail", mode: "parse-fail", suite: "parse-fail" }, + Test { default: true, path: "src/test/run-fail", mode: "run-fail", suite: "run-fail" }, + Test { default: true, path: "src/test/run-pass", mode: "run-pass", suite: "run-pass" }, + Test { + default: true, + path: "src/test/run-pass-valgrind", + mode: "run-pass-valgrind", + suite: "run-pass-valgrind" + }, + Test { default: true, path: "src/test/ui", mode: "ui", suite: "ui" }, + Test { + default: false, + path: "src/test/debuginfo-lldb", + mode: "debuginfo-lldb", + suite: "debuginfo" + }, + Test { + default: false, + path: "src/test/debuginfo-gdb", + mode: "debuginfo-gdb", + suite: "debuginfo" + }, // FIXME: What this runs varies depending on the native platform being apple - (true, "src/test/debuginfo", "debuginfo-XXX", "debuginfo"), - - (true, "src/test/ui-fulldeps", "ui", "ui-fulldeps"), - (true, "src/test/run-pass-fulldeps", "run-pass", "run-pass-fulldeps"), - (true, "src/test/run-fail-fulldeps", "run-fail", "run-fail-fulldeps"), - (true, "src/test/compile-fail-fulldeps", "compile-fail", "compile-fail-fulldeps"), - (true, "src/test/run-make", "run-make", "run-make"), - (true, "src/test/rustdoc", "rustdoc", "rustdoc"), - - (false, "src/test/pretty", "pretty", "pretty"), - (false, "src/test/run-pass/pretty", "pretty", "run-pass"), - (false, "src/test/run-fail/pretty", "pretty", "run-fail"), - (false, "src/test/run-pass-valgrind/pretty", "pretty", "run-pass-valgrind"), - (false, "src/test/run-pass-fulldeps/pretty", "pretty", "run-pass-fulldeps"), - (false, "src/test/run-fail-fulldeps/pretty", "pretty", "run-fail-fulldeps"), + Test { default: true, path: "src/test/debuginfo", mode: "debuginfo-XXX", suite: "debuginfo" }, + + Test { default: true, path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-fulldeps" }, + Test { + default: true, + path: "src/test/run-pass-fulldeps", + mode: "run-pass", + suite: "run-pass-fulldeps", + }, + Test { + default: true, + path: "src/test/run-fail-fulldeps", + mode: "run-fail", + suite: "run-fail-fulldeps", + }, + Test { + default: true, + path: "src/test/compile-fail-fulldeps", + mode: "compile-fail", + suite: "compile-fail-fulldeps", + }, + Test { default: true, path: "src/test/run-make", mode: "run-make", suite: "run-make" }, + Test { default: true, path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" }, + + Test { default: false, path: "src/test/pretty", mode: "pretty", suite: "pretty" }, + Test { default: false, path: "src/test/run-pass/pretty", mode: "pretty", suite: "run-pass" }, + Test { default: false, path: "src/test/run-fail/pretty", mode: "pretty", suite: "run-fail" }, + Test { + default: false, + path: "src/test/run-pass-valgrind/pretty", + mode: "pretty", + suite: "run-pass-valgrind" + }, + Test { + default: false, + path: "src/test/run-pass-fulldeps/pretty", + mode: "pretty", + suite: "run-pass-fulldeps", + }, + Test { + default: false, + path: "src/test/run-fail-fulldeps/pretty", + mode: "pretty", + suite: "run-fail-fulldeps", + }, ]; @@ -486,8 +548,8 @@ impl<'a> Step<'a> for Compiletest<'a> { // Note that this is general, while a few more cases are skipped inside // run() itself. This is to avoid duplication across should_run and // make_run. - COMPILETESTS.iter().any(|&(_, test_path, _, _)| { - path.ends_with(test_path) + COMPILETESTS.iter().any(|&test| { + path.ends_with(test.path) }) } @@ -495,8 +557,8 @@ impl<'a> Step<'a> for Compiletest<'a> { let compiler = builder.compiler(builder.top_stage, host); let test = path.map(|path| { - COMPILETESTS.iter().find(|&&(_, test_path, _, _)| { - path.ends_with(test_path) + COMPILETESTS.iter().find(|&&test| { + path.ends_with(test.path) }).unwrap_or_else(|| { panic!("make_run in compile test to receive test path, received {:?}", path); }) @@ -504,13 +566,16 @@ impl<'a> Step<'a> for Compiletest<'a> { if let Some(test) = test { // specific test builder.ensure(Compiletest { - compiler, target, mode: test.2, suite: test.3 + compiler, target, mode: test.mode, suite: test.suite }); } else { // default tests - for &(default, _, mode, suite) in COMPILETESTS { - if default { + for test in COMPILETESTS { + if test.default { builder.ensure(Compiletest { - compiler, target, mode, suite + compiler, + target, + mode: test.mode, + suite: test.suite }); } } From aa8b93bd10b12f6f3696951f0a635add882ab0d8 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Fri, 7 Jul 2017 12:31:29 -0600 Subject: [PATCH 15/51] Rework compiletest implementation. --- src/bootstrap/check.rs | 139 ++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 84 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index a847a2f47f661..bb98e26333cba 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -444,101 +444,58 @@ pub struct Compiletest<'a> { suite: &'a str, } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq)] struct Test { - default: bool, path: &'static str, mode: &'static str, suite: &'static str, } -static COMPILETESTS: &[Test] = &[ - Test { default: true, path: "src/test/codegen", mode: "codegen", suite: "codegen" }, - Test { - default: true, - path: "src/test/codegen-units", - mode: "codegen-units", - suite: "codegen-units", - }, +static DEFAULT_COMPILETESTS: &[Test] = &[ + Test { path: "src/test/ui", mode: "ui", suite: "ui" }, + Test { path: "src/test/run-pass", mode: "run-pass", suite: "run-pass" }, + Test { path: "src/test/compile-fail", mode: "compile-fail", suite: "compile-fail" }, + Test { path: "src/test/parse-fail", mode: "parse-fail", suite: "parse-fail" }, + Test { path: "src/test/run-fail", mode: "run-fail", suite: "run-fail" }, Test { - default: true, - path: "src/test/compile-fail", - mode: "compile-fail", - suite: "compile-fail", - }, - Test { default: true, path: "src/test/incremental", mode: "incremental", suite: "incremental" }, - Test { default: true, path: "src/test/mir-opt", mode: "mir-opt", suite: "mir-opt" }, - Test { default: true, path: "src/test/parse-fail", mode: "parse-fail", suite: "parse-fail" }, - Test { default: true, path: "src/test/run-fail", mode: "run-fail", suite: "run-fail" }, - Test { default: true, path: "src/test/run-pass", mode: "run-pass", suite: "run-pass" }, - Test { - default: true, path: "src/test/run-pass-valgrind", mode: "run-pass-valgrind", suite: "run-pass-valgrind" }, - Test { default: true, path: "src/test/ui", mode: "ui", suite: "ui" }, - Test { - default: false, - path: "src/test/debuginfo-lldb", - mode: "debuginfo-lldb", - suite: "debuginfo" - }, - Test { - default: false, - path: "src/test/debuginfo-gdb", - mode: "debuginfo-gdb", - suite: "debuginfo" - }, + Test { path: "src/test/mir-opt", mode: "mir-opt", suite: "mir-opt" }, + Test { path: "src/test/codegen", mode: "codegen", suite: "codegen" }, + Test { path: "src/test/codegen-units", mode: "codegen-units", suite: "codegen-units" }, + Test { path: "src/test/incremental", mode: "incremental", suite: "incremental" }, - // FIXME: What this runs varies depending on the native platform being apple - Test { default: true, path: "src/test/debuginfo", mode: "debuginfo-XXX", suite: "debuginfo" }, + // What this runs varies depending on the native platform being apple + Test { path: "src/test/debuginfo", mode: "debuginfo-XXX", suite: "debuginfo" }, +]; - Test { default: true, path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-fulldeps" }, - Test { - default: true, - path: "src/test/run-pass-fulldeps", - mode: "run-pass", - suite: "run-pass-fulldeps", - }, +// Also default, but host-only. +static HOST_COMPILETESTS: &[Test] = &[ + Test { path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-fulldeps" }, + Test { path: "src/test/run-pass-fulldeps", mode: "run-pass", suite: "run-pass-fulldeps" }, + Test { path: "src/test/run-fail-fulldeps", mode: "run-fail", suite: "run-fail-fulldeps" }, Test { - default: true, - path: "src/test/run-fail-fulldeps", - mode: "run-fail", - suite: "run-fail-fulldeps", - }, - Test { - default: true, path: "src/test/compile-fail-fulldeps", mode: "compile-fail", suite: "compile-fail-fulldeps", }, - Test { default: true, path: "src/test/run-make", mode: "run-make", suite: "run-make" }, - Test { default: true, path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" }, - - Test { default: false, path: "src/test/pretty", mode: "pretty", suite: "pretty" }, - Test { default: false, path: "src/test/run-pass/pretty", mode: "pretty", suite: "run-pass" }, - Test { default: false, path: "src/test/run-fail/pretty", mode: "pretty", suite: "run-fail" }, - Test { - default: false, - path: "src/test/run-pass-valgrind/pretty", - mode: "pretty", - suite: "run-pass-valgrind" - }, - Test { - default: false, - path: "src/test/run-pass-fulldeps/pretty", - mode: "pretty", - suite: "run-pass-fulldeps", - }, - Test { - default: false, - path: "src/test/run-fail-fulldeps/pretty", - mode: "pretty", - suite: "run-fail-fulldeps", - }, + Test { path: "src/test/run-make", mode: "run-make", suite: "run-make" }, + Test { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" }, + + Test { path: "src/test/pretty", mode: "pretty", suite: "pretty" }, + Test { path: "src/test/run-pass/pretty", mode: "pretty", suite: "run-pass" }, + Test { path: "src/test/run-fail/pretty", mode: "pretty", suite: "run-fail" }, + Test { path: "src/test/run-pass-valgrind/pretty", mode: "pretty", suite: "run-pass-valgrind" }, + Test { path: "src/test/run-pass-fulldeps/pretty", mode: "pretty", suite: "run-pass-fulldeps" }, + Test { path: "src/test/run-fail-fulldeps/pretty", mode: "pretty", suite: "run-fail-fulldeps" }, ]; +static COMPILETESTS: &[Test] = &[ + Test { path: "src/test/debuginfo-lldb", mode: "debuginfo-lldb", suite: "debuginfo" }, + Test { path: "src/test/debuginfo-gdb", mode: "debuginfo-gdb", suite: "debuginfo" }, +]; impl<'a> Step<'a> for Compiletest<'a> { type Output = (); @@ -548,7 +505,7 @@ impl<'a> Step<'a> for Compiletest<'a> { // Note that this is general, while a few more cases are skipped inside // run() itself. This is to avoid duplication across should_run and // make_run. - COMPILETESTS.iter().any(|&test| { + COMPILETESTS.iter().chain(DEFAULT_COMPILETESTS).chain(HOST_COMPILETESTS).any(|&test| { path.ends_with(test.path) }) } @@ -557,7 +514,7 @@ impl<'a> Step<'a> for Compiletest<'a> { let compiler = builder.compiler(builder.top_stage, host); let test = path.map(|path| { - COMPILETESTS.iter().find(|&&test| { + COMPILETESTS.iter().chain(DEFAULT_COMPILETESTS).chain(HOST_COMPILETESTS).find(|&&test| { path.ends_with(test.path) }).unwrap_or_else(|| { panic!("make_run in compile test to receive test path, received {:?}", path); @@ -565,15 +522,28 @@ impl<'a> Step<'a> for Compiletest<'a> { }); if let Some(test) = test { // specific test + let target = if HOST_COMPILETESTS.contains(test) { + host + } else { + target + }; builder.ensure(Compiletest { compiler, target, mode: test.mode, suite: test.suite }); } else { // default tests - for test in COMPILETESTS { - if test.default { + for test in DEFAULT_COMPILETESTS { + builder.ensure(Compiletest { + compiler, + target, + mode: test.mode, + suite: test.suite + }); + } + for test in HOST_COMPILETESTS { + if test.mode != "pretty" { builder.ensure(Compiletest { compiler, - target, + target: host, mode: test.mode, suite: test.suite }); @@ -623,6 +593,10 @@ impl<'a> Step<'a> for Compiletest<'a> { sysroot: &builder.sysroot(compiler), host: compiler.host }); + + if mode == "debuginfo-gdb" { + builder.ensure(RemoteCopyLibs { compiler, target }); + } } if suite.ends_with("fulldeps") || @@ -636,10 +610,7 @@ impl<'a> Step<'a> for Compiletest<'a> { builder.ensure(compile::Test { compiler, target }); builder.ensure(native::TestHelpers { target }); - - if mode == "debuginfo-gdb" { - builder.ensure(RemoteCopyLibs { compiler, target }); - } + builder.ensure(RemoteCopyLibs { compiler, target }); let _folder = build.fold_output(|| format!("test_{}", suite)); println!("Check compiletest suite={} mode={} ({} -> {})", From d812d430a4a90a8ed3e5cf50387ea9a25ede4e97 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Fri, 7 Jul 2017 12:37:55 -0600 Subject: [PATCH 16/51] Fix a nit. --- src/bootstrap/check.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index bb98e26333cba..3e9c02863e76a 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -191,7 +191,7 @@ impl<'a> Step<'a> for Cargo<'a> { const ONLY_HOSTS: bool = true; fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("cargo") // FIXME: Why is this not src/tools/cargo? + path.ends_with("src/tools/cargo") } fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { From d360af45bb2dda3f0f0fddbb130967dc06a2dd54 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 4 Jul 2017 07:31:05 -0600 Subject: [PATCH 17/51] Migrate to serde_json entirely --- src/bootstrap/compile.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index ab4eec0199f0b..79668efc0782b 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -26,7 +26,7 @@ use std::str; use build_helper::{output, mtime, up_to_date}; use filetime::FileTime; -use rustc_serialize::json; +use serde_json; use util::{exe, libdir, is_dylib, copy}; use {Build, Compiler, Mode}; @@ -934,18 +934,18 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) { let stdout = BufReader::new(child.stdout.take().unwrap()); for line in stdout.lines() { let line = t!(line); - let json = if line.starts_with("{") { - t!(line.parse::()) + let json: serde_json::Value = if line.starts_with("{") { + t!(serde_json::from_str(&line)) } else { // If this was informational, just print it out and continue println!("{}", line); continue }; - if json.find("reason").and_then(|j| j.as_string()) != Some("compiler-artifact") { + if json["reason"].as_str() != Some("compiler-artifact") { continue } for filename in json["filenames"].as_array().unwrap() { - let filename = filename.as_string().unwrap(); + let filename = filename.as_str().unwrap(); // Skip files like executables if !filename.ends_with(".rlib") && !filename.ends_with(".lib") && From a1fa2681cfa85c4a5513249339abbd31ff561449 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 4 Jul 2017 10:03:01 -0600 Subject: [PATCH 18/51] Update to toml 0.4 --- src/Cargo.lock | 17 ++------ src/bootstrap/Cargo.toml | 9 ++-- src/bootstrap/builder.rs | 6 ++- src/bootstrap/config.rs | 64 ++++++++++++++-------------- src/bootstrap/lib.rs | 1 - src/bootstrap/metadata.rs | 12 +++--- src/bootstrap/tool.rs | 2 +- src/tools/build-manifest/Cargo.toml | 5 ++- src/tools/build-manifest/src/main.rs | 34 ++++++--------- 9 files changed, 69 insertions(+), 81 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index c210f80431bd7..35d77eda95110 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -136,11 +136,10 @@ dependencies = [ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -156,8 +155,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "build-manifest" version = "0.1.0" dependencies = [ - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1871,14 +1871,6 @@ dependencies = [ name = "tidy" version = "0.1.0" -[[package]] -name = "toml" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "toml" version = "0.2.1" @@ -2173,7 +2165,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" -"checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" "checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7" "checksum typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index f557dcc476381..00004d71aac25 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -33,11 +33,10 @@ build_helper = { path = "../build_helper" } cmake = "0.1.23" filetime = "0.1" num_cpus = "1.0" -toml = "0.1" getopts = "0.2" -rustc-serialize = "0.3" gcc = "0.3.50" libc = "0.2" -serde = "1.0" -serde_json = "1.0" -serde_derive = "1.0" +serde = "1.0.8" +serde_derive = "1.0.8" +serde_json = "1.0.2" +toml = "0.4" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e6432e8938c1c..e284e4b9d0ac7 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -25,6 +25,7 @@ use cache::{Cache, Key}; use check; use flags::Subcommand; use doc; +use tool; pub use Compiler; @@ -144,7 +145,10 @@ impl<'a> Builder<'a> { let builder = &builder; match builder.kind { Kind::Build => check!(builder, paths, compile::Std, compile::Test, compile::Rustc, - compile::StartupObjects), + compile::StartupObjects, tool::BuildManifest, tool::Rustbook, tool::ErrorIndex, + tool::UnstableBookGen, tool::Tidy, tool::Linkchecker, tool::CargoTest, + tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient, + tool::RustInstaller, tool::Cargo, tool::Rls), Kind::Test => check!(builder, paths, check::Tidy, check::Bootstrap, check::Compiletest, check::Krate, check::KrateLibrustc, check::Linkcheck, check::Cargotest, check::Cargo, check::Docs, check::ErrorIndex, check::Distcheck), diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 34628852ab377..810a9924765d8 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -21,8 +21,7 @@ use std::path::PathBuf; use std::process; use num_cpus; -use rustc_serialize::Decodable; -use toml::{Parser, Decoder, Value}; +use toml; use util::{exe, push_exe_path}; /// Global configuration for the entire build and/or bootstrap. @@ -138,7 +137,9 @@ pub struct Target { /// This structure uses `Decodable` to automatically decode a TOML configuration /// file into this format, and then this is traversed and written into the above /// `Config` structure. -#[derive(RustcDecodable, Default)] +#[derive(Deserialize, Default)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "kebab-case")] struct TomlConfig { build: Option, install: Option, @@ -149,10 +150,14 @@ struct TomlConfig { } /// TOML representation of various global build decisions. -#[derive(RustcDecodable, Default, Clone)] +#[derive(Deserialize, Default, Clone)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "kebab-case")] struct Build { build: Option, + #[serde(default)] host: Vec, + #[serde(default)] target: Vec, cargo: Option, rustc: Option, @@ -174,7 +179,9 @@ struct Build { } /// TOML representation of various global install decisions. -#[derive(RustcDecodable, Default, Clone)] +#[derive(Deserialize, Default, Clone)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "kebab-case")] struct Install { prefix: Option, sysconfdir: Option, @@ -185,7 +192,9 @@ struct Install { } /// TOML representation of how the LLVM build is configured. -#[derive(RustcDecodable, Default)] +#[derive(Deserialize, Default)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "kebab-case")] struct Llvm { ccache: Option, ninja: Option, @@ -200,7 +209,9 @@ struct Llvm { clean_rebuild: Option, } -#[derive(RustcDecodable, Default, Clone)] +#[derive(Deserialize, Default, Clone)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "kebab-case")] struct Dist { sign_folder: Option, gpg_password_file: Option, @@ -208,7 +219,8 @@ struct Dist { src_tarball: Option, } -#[derive(RustcDecodable)] +#[derive(Deserialize)] +#[serde(untagged)] enum StringOrBool { String(String), Bool(bool), @@ -221,7 +233,9 @@ impl Default for StringOrBool { } /// TOML representation of how the Rust build is configured. -#[derive(RustcDecodable, Default)] +#[derive(Deserialize, Default)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "kebab-case")] struct Rust { optimize: Option, codegen_units: Option, @@ -243,7 +257,9 @@ struct Rust { } /// TOML representation of how each build target is configured. -#[derive(RustcDecodable, Default)] +#[derive(Deserialize, Default)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "kebab-case")] struct TomlTarget { llvm_config: Option, jemalloc: Option, @@ -273,27 +289,13 @@ impl Config { let toml = file.map(|file| { let mut f = t!(File::open(&file)); - let mut toml = String::new(); - t!(f.read_to_string(&mut toml)); - let mut p = Parser::new(&toml); - let table = match p.parse() { - Some(table) => table, - None => { - println!("failed to parse TOML configuration '{}':", file.to_str().unwrap()); - for err in p.errors.iter() { - let (loline, locol) = p.to_linecol(err.lo); - let (hiline, hicol) = p.to_linecol(err.hi); - println!("{}:{}-{}:{}: {}", loline, locol, hiline, - hicol, err.desc); - } - process::exit(2); - } - }; - let mut d = Decoder::new(Value::Table(table)); - match Decodable::decode(&mut d) { - Ok(cfg) => cfg, - Err(e) => { - println!("failed to decode TOML: {}", e); + let mut contents = String::new(); + t!(f.read_to_string(&mut contents)); + match toml::from_str(&contents) { + Ok(table) => table, + Err(err) => { + println!("failed to parse TOML configuration '{}': {}", + file.display(), err); process::exit(2); } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index d6b474ab3aff1..d4ef6613a2a5e 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -128,7 +128,6 @@ extern crate filetime; extern crate gcc; extern crate getopts; extern crate num_cpus; -extern crate rustc_serialize; extern crate toml; #[cfg(unix)] diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index 9326bb7129afa..ca0eed3ae86f8 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -13,17 +13,17 @@ use std::process::Command; use std::path::PathBuf; use build_helper::output; -use rustc_serialize::json; +use serde_json; use {Build, Crate}; -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Output { packages: Vec, resolve: Resolve, } -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Package { id: String, name: String, @@ -32,12 +32,12 @@ struct Package { manifest_path: String, } -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct Resolve { nodes: Vec, } -#[derive(RustcDecodable)] +#[derive(Deserialize)] struct ResolveNode { id: String, dependencies: Vec, @@ -61,7 +61,7 @@ fn build_krate(build: &mut Build, krate: &str) { .arg("--format-version").arg("1") .arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml")); let output = output(&mut cargo); - let output: Output = json::decode(&output).unwrap(); + let output: Output = serde_json::from_str(&output).unwrap(); let mut id2name = HashMap::new(); for package in output.packages { if package.source.is_none() { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 50e76c324c3ea..eecfbdc8b3dc7 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -238,7 +238,7 @@ tool!( // .dep(|s| s.name("maybe-clean-tools")) // .dep(|s| s.name("libstd-tool")) // .run(move |s| compile::tool(build, s.stage, s.target, "build-manifest")); - BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Libstd; + BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Librustc; // rules.build("tool-remote-test-server", "src/tools/remote-test-server") // .dep(|s| s.name("maybe-clean-tools")) // .dep(|s| s.name("libstd-tool")) diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index 4b876753b1fea..844b7aad72fde 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -4,5 +4,6 @@ version = "0.1.0" authors = ["Alex Crichton "] [dependencies] -toml = "0.1" -rustc-serialize = "0.3" +toml = "0.4" +serde = "1.0" +serde_derive = "1.0" diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index ba37863b1f62d..b8efb88acfbdc 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -9,7 +9,9 @@ // except according to those terms. extern crate toml; -extern crate rustc_serialize; +#[macro_use] +extern crate serde_derive; +extern crate serde; use std::collections::BTreeMap; use std::env; @@ -99,19 +101,21 @@ static MINGW: &'static [&'static str] = &[ "x86_64-pc-windows-gnu", ]; +#[derive(Serialize)] +#[serde(rename_all = "kebab-case")] struct Manifest { manifest_version: String, date: String, pkg: BTreeMap, } -#[derive(RustcEncodable)] +#[derive(Serialize)] struct Package { version: String, target: BTreeMap, } -#[derive(RustcEncodable)] +#[derive(Serialize)] struct Target { available: bool, url: Option, @@ -136,7 +140,7 @@ impl Target { } } -#[derive(RustcEncodable)] +#[derive(Serialize)] struct Component { pkg: String, target: String, @@ -199,28 +203,16 @@ impl Builder { self.rls_version = self.version("rls", "x86_64-unknown-linux-gnu"); self.digest_and_sign(); - let Manifest { manifest_version, date, pkg } = self.build_manifest(); - - // Unfortunately we can't use derive(RustcEncodable) here because the - // version field is called `manifest-version`, not `manifest_version`. - // In lieu of that just create the table directly here with a `BTreeMap` - // and wrap it up in a `Value::Table`. - let mut manifest = BTreeMap::new(); - manifest.insert("manifest-version".to_string(), - toml::Value::String(manifest_version)); - manifest.insert("date".to_string(), toml::Value::String(date.clone())); - manifest.insert("pkg".to_string(), toml::encode(&pkg)); - let manifest = toml::Value::Table(manifest).to_string(); - + let manifest = self.build_manifest(); let filename = format!("channel-rust-{}.toml", self.rust_release); - self.write_manifest(&manifest, &filename); + self.write_manifest(&toml::to_string(&manifest).unwrap(), &filename); let filename = format!("channel-rust-{}-date.txt", self.rust_release); - self.write_date_stamp(&date, &filename); + self.write_date_stamp(&manifest.date, &filename); if self.rust_release != "beta" && self.rust_release != "nightly" { - self.write_manifest(&manifest, "channel-rust-stable.toml"); - self.write_date_stamp(&date, "channel-rust-stable-date.txt"); + self.write_manifest(&toml::to_string(&manifest).unwrap(), "channel-rust-stable.toml"); + self.write_date_stamp(&manifest.date, "channel-rust-stable-date.txt"); } } From c7435b52a93d96c47a84e505f9eb6a505d6037b5 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Fri, 7 Jul 2017 23:00:38 -0400 Subject: [PATCH 19/51] Cherry pick changes from ce3abc5801f94292be9bc5fbe00b52f1ccb28672. Fix stage 2 builds with a custom libdir. When copying libstd for the stage 2 compiler, the builder ignores the configured libdir/libdir_relative configuration parameters. This causes the compiler to fail to find libstd, which cause any tools built with the stage 2 compiler to fail. To fix this, make the copy steps of rustbuild aware of the libdir_relative parameter when the stage >= 2. Also update the dist target to be aware of the new location of libstd. --- src/bootstrap/builder.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e284e4b9d0ac7..fbfe442d8f6f7 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -192,8 +192,13 @@ impl<'a> Builder<'a> { impl<'a> Step<'a> for Libdir<'a> { type Output = PathBuf; fn run(self, builder: &Builder) -> PathBuf { - let sysroot = builder.sysroot(self.compiler) - .join("lib").join("rustlib").join(self.target).join("lib"); + let lib = if compiler.stage >= 2 && builder.build.config.libdir_relative.is_some() { + builder.build.config.libdir_relative.cloned().unwrap() + } else { + PathBuf::from("lib") + }; + let sysroot = builder.sysroot(self.compiler).join(lib) + .join("rustlib").join(self.target).join("lib"); let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot)); sysroot From a5ab2ceef8393f94fd1aa07b35bc25f74e9f879f Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 12 Jul 2017 09:15:00 -0600 Subject: [PATCH 20/51] Fix a few errors introduced during rebase. --- src/bootstrap/builder.rs | 3 +- src/bootstrap/check.rs | 75 +++++++++++++++++++++----------- src/bootstrap/dist.rs | 93 ++++++++++++++++++++++++++++++---------- src/bootstrap/lib.rs | 14 +----- 4 files changed, 122 insertions(+), 63 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index fbfe442d8f6f7..5d7400ab9ae8a 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -192,8 +192,9 @@ impl<'a> Builder<'a> { impl<'a> Step<'a> for Libdir<'a> { type Output = PathBuf; fn run(self, builder: &Builder) -> PathBuf { + let compiler = self.compiler; let lib = if compiler.stage >= 2 && builder.build.config.libdir_relative.is_some() { - builder.build.config.libdir_relative.cloned().unwrap() + builder.build.config.libdir_relative.clone().unwrap() } else { PathBuf::from("lib") }; diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 3e9c02863e76a..e4cfe88429562 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -753,40 +753,63 @@ impl<'a> Step<'a> for Compiletest<'a> { } } +#[derive(Serialize)] +pub struct Docs<'a> { + compiler: Compiler<'a>, +} + // rules.test("check-docs", "src/doc") // .dep(|s| s.name("libtest")) // .default(true) // .host(true) // .run(move |s| check::docs(build, &s.compiler())); -/// Run `rustdoc --test` for all documentation in `src/doc`. -/// -/// This will run all tests in our markdown documentation (e.g. the book) -/// located in `src/doc`. The `rustdoc` that's run is the one that sits next to -/// `compiler`. -pub fn docs(build: &Build, compiler: &Compiler) { - // Do a breadth-first traversal of the `src/doc` directory and just run - // tests for all files that end in `*.md` - let mut stack = vec![build.src.join("src/doc")]; - let _time = util::timeit(); - let _folder = build.fold_output(|| "test_docs"); - - while let Some(p) = stack.pop() { - if p.is_dir() { - stack.extend(t!(p.read_dir()).map(|p| t!(p).path())); - continue - } +impl<'a> Step<'a> for Docs<'a> { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; - if p.extension().and_then(|s| s.to_str()) != Some("md") { - continue; - } + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/doc") + } - // The nostarch directory in the book is for no starch, and so isn't - // guaranteed to build. We don't care if it doesn't build, so skip it. - if p.to_str().map_or(false, |p| p.contains("nostarch")) { - continue; - } + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { + builder.ensure(Docs { + compiler: builder.compiler(builder.top_stage, host), + }); + } + + /// Run `rustdoc --test` for all documentation in `src/doc`. + /// + /// This will run all tests in our markdown documentation (e.g. the book) + /// located in `src/doc`. The `rustdoc` that's run is the one that sits next to + /// `compiler`. + fn run(self, builder: &Builder) { + let build = builder.build; + let compiler = self.compiler; + // Do a breadth-first traversal of the `src/doc` directory and just run + // tests for all files that end in `*.md` + let mut stack = vec![build.src.join("src/doc")]; + let _time = util::timeit(); + let _folder = build.fold_output(|| "test_docs"); - markdown_test(build, compiler, &p); + while let Some(p) = stack.pop() { + if p.is_dir() { + stack.extend(t!(p.read_dir()).map(|p| t!(p).path())); + continue + } + + if p.extension().and_then(|s| s.to_str()) != Some("md") { + continue; + } + + // The nostarch directory in the book is for no starch, and so isn't + // guaranteed to build. We don't care if it doesn't build, so skip it. + if p.to_str().map_or(false, |p| p.contains("nostarch")) { + continue; + } + + markdown_test(builder, compiler, &p); + } } } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index a2f779514a997..c419f8bb7211b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -553,29 +553,76 @@ impl<'a> Step<'a> for DebuggerScripts<'a> { // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::std(build, &s.compiler(), s.target)); - let name = pkgname(build, "rust-std"); - let image = tmpdir(build).join(format!("{}-{}-image", name, target)); - let _ = fs::remove_dir_all(&image); - - let dst = image.join("lib/rustlib").join(target); - t!(fs::create_dir_all(&dst)); - let mut src = build.sysroot_libdir(compiler, target); - src.pop(); // Remove the trailing /lib folder from the sysroot_libdir - cp_r(&src, &dst); - - let mut cmd = rust_installer(build); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=std-is-standing-at-the-ready.") - .arg("--image-dir").arg(&image) - .arg("--work-dir").arg(&tmpdir(build)) - .arg("--output-dir").arg(&distdir(build)) - .arg(format!("--package-name={}-{}", name, target)) - .arg(format!("--component-name=rust-std-{}", target)) - .arg("--legacy-manifest-dirs=rustlib,cargo"); - build.run(&mut cmd); - t!(fs::remove_dir_all(&image)); +#[derive(Serialize)] +pub struct Std<'a> { + pub compiler: Compiler<'a>, + pub target: &'a str, +} + +impl<'a> Step<'a> for Std<'a> { + type Output = (); + const DEFAULT: bool = true; + const ONLY_BUILD_TARGETS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/libstd") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + builder.ensure(Std { + compiler: builder.compiler(builder.top_stage, host), + target: target, + }); + } + + fn run(self, builder: &Builder) { + let build = builder.build; + let compiler = self.compiler; + let target = self.target; + + println!("Dist std stage{} ({} -> {})", compiler.stage, compiler.host, + target); + + // The only true set of target libraries came from the build triple, so + // let's reduce redundant work by only producing archives from that host. + if compiler.host != build.build { + println!("\tskipping, not a build host"); + return + } + + // We want to package up as many target libraries as possible + // for the `rust-std` package, so if this is a host target we + // depend on librustc and otherwise we just depend on libtest. + if build.config.host.iter().any(|t| t == target) { + builder.ensure(compile::Rustc { compiler, target }); + } else { + builder.ensure(compile::Test { compiler, target }); + } + + let name = pkgname(build, "rust-std"); + let image = tmpdir(build).join(format!("{}-{}-image", name, target)); + let _ = fs::remove_dir_all(&image); + + let dst = image.join("lib/rustlib").join(target); + t!(fs::create_dir_all(&dst)); + let mut src = builder.sysroot_libdir(compiler, target); + src.pop(); // Remove the trailing /lib folder from the sysroot_libdir + cp_r(&src, &dst); + + let mut cmd = rust_installer(builder); + cmd.arg("generate") + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=std-is-standing-at-the-ready.") + .arg("--image-dir").arg(&image) + .arg("--work-dir").arg(&tmpdir(build)) + .arg("--output-dir").arg(&distdir(build)) + .arg(format!("--package-name={}-{}", name, target)) + .arg(format!("--component-name=rust-std-{}", target)) + .arg("--legacy-manifest-dirs=rustlib,cargo"); + build.run(&mut cmd); + t!(fs::remove_dir_all(&image)); + } } /// The path to the complete rustc-src tarball diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index d4ef6613a2a5e..d7f1570ba80a0 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -114,6 +114,7 @@ //! also check out the `src/bootstrap/README.md` file for more information. #![deny(warnings)] +#![allow(stable_features)] #![feature(associated_consts)] #![feature(core_intrinsics)] @@ -441,19 +442,6 @@ impl Build { self.out.join(compiler.host).join(format!("stage{}-incremental", compiler.stage)) } - /// Returns the libdir where the standard library and other artifacts are - /// found for a compiler's sysroot. - fn sysroot_libdir(&self, compiler: &Compiler, target: &str) -> PathBuf { - if compiler.stage >= 2 { - if let Some(ref libdir_relative) = self.config.libdir_relative { - return self.sysroot(compiler).join(libdir_relative) - .join("rustlib").join(target).join("lib") - } - } - self.sysroot(compiler).join("lib").join("rustlib") - .join(target).join("lib") - } - /// Returns the root directory for all output generated in a particular /// stage when running with a particular host compiler. /// From ceecd6250f31e614c5ae86165e70ce3f09dc9008 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 12 Jul 2017 10:12:47 -0600 Subject: [PATCH 21/51] Fix more incorrectly transitioned code --- src/bootstrap/check.rs | 46 ++++++++++++++++++++++++++---------------- src/bootstrap/tool.rs | 35 +++++++++++++++++++++++++++----- 2 files changed, 59 insertions(+), 22 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index e4cfe88429562..e5e0bfa0ac90d 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -32,7 +32,7 @@ use util::{self, dylib_path, dylib_path_var}; use compile; use native; use builder::{Kind, Builder, Compiler, Step}; -use tool::Tool; +use tool::{self, Tool}; const ADB_TEST_DIR: &str = "/data/tmp/work"; @@ -151,6 +151,17 @@ impl<'a> Step<'a> for Cargotest<'a> { type Output = (); const ONLY_HOSTS: bool = true; + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/tools/cargotest") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { + builder.ensure(Cargotest { + stage: builder.top_stage, + host: host, + }); + } + /// Runs the `cargotest` tool as compiled in `stage` by the `host` compiler. /// /// This tool in `src/tools` will check out a few Rust projects and run `cargo @@ -786,6 +797,9 @@ impl<'a> Step<'a> for Docs<'a> { fn run(self, builder: &Builder) { let build = builder.build; let compiler = self.compiler; + + builder.ensure(compile::Test { compiler, target: compiler.host }); + // Do a breadth-first traversal of the `src/doc` directory and just run // tests for all files that end in `*.md` let mut stack = vec![build.src.join("src/doc")]; @@ -1106,6 +1120,7 @@ impl<'a> Step<'a> for Krate<'a> { ("libtest", "src/libtest", String::new(), "test") } Mode::Librustc => { + builder.ensure(compile::Rustc { compiler, target }); ("librustc", "src/rustc", build.rustc_features(), "rustc-main") } _ => panic!("can only test libraries"), @@ -1261,16 +1276,6 @@ fn find_tests(dir: &Path, target: &str) -> Vec { dst } -// // Some test suites are run inside emulators or on remote devices, and most -// // of our test binaries are linked dynamically which means we need to ship -// // the standard library and such to the emulator ahead of time. This step -// // represents this and is a dependency of all test suites. -// // -// // Most of the time this step is a noop (the `check::emulator_copy_libs` -// // only does work if necessary). For some steps such as shipping data to -// // QEMU we have to build our own tools so we've got conditional dependencies -// // on those programs as well. Note that the remote test client is built for -// // the build target (us) and the server is built for the target. // rules.test("remote-copy-libs", "path/to/nowhere") // .dep(|s| s.name("libtest")) // .dep(move |s| { @@ -1290,6 +1295,15 @@ fn find_tests(dir: &Path, target: &str) -> Vec { // .run(move |s| check::remote_copy_libs(build, &s.compiler(), s.target)); // +/// Some test suites are run inside emulators or on remote devices, and most +/// of our test binaries are linked dynamically which means we need to ship +/// the standard library and such to the emulator ahead of time. This step +/// represents this and is a dependency of all test suites. +/// +/// Most of the time this is a noop. For some steps such as shipping data to +/// QEMU we have to build our own tools so we've got conditional dependencies +/// on those programs as well. Note that the remote test client is built for +/// the build target (us) and the server is built for the target. #[derive(Serialize)] pub struct RemoteCopyLibs<'a> { compiler: Compiler<'a>, @@ -1312,9 +1326,7 @@ impl<'a> Step<'a> for RemoteCopyLibs<'a> { println!("REMOTE copy libs to emulator ({})", target); t!(fs::create_dir_all(build.out.join("tmp"))); - // FIXME: This builds the tool for the native build triple - // (build.build); that is probably wrong. Should build for target. - let server = builder.tool_exe(Tool::RemoteTestServer); + let server = builder.ensure(tool::RemoteTestServer { compiler, target })); // Spawn the emulator and wait for it to come online let tool = builder.tool_exe(Tool::RemoteTestClient); @@ -1356,6 +1368,9 @@ impl<'a> Step<'a> for Distcheck { fn run(self, builder: &Builder) { let build = builder.build; + builder.ensure(dist::PlainSourceTarball); + builder.ensure(dist::Src); + if build.build != "x86_64-unknown-linux-gnu" { return } @@ -1366,9 +1381,6 @@ impl<'a> Step<'a> for Distcheck { return } - builder.ensure(dist::PlainSourceTarball); - builder.ensure(dist::Src); - println!("Distcheck"); let dir = build.out.join("tmp").join("distcheck"); let _ = fs::remove_dir_all(&dir); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index eecfbdc8b3dc7..6153d37cf1a07 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -239,11 +239,6 @@ tool!( // .dep(|s| s.name("libstd-tool")) // .run(move |s| compile::tool(build, s.stage, s.target, "build-manifest")); BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Librustc; - // rules.build("tool-remote-test-server", "src/tools/remote-test-server") - // .dep(|s| s.name("maybe-clean-tools")) - // .dep(|s| s.name("libstd-tool")) - // .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-server")); - RemoteTestServer, "src/tools/remote-test-server", "remote-test-server", Mode::Libstd; // rules.build("tool-remote-test-client", "src/tools/remote-test-client") // .dep(|s| s.name("maybe-clean-tools")) // .dep(|s| s.name("libstd-tool")) @@ -256,6 +251,36 @@ tool!( RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd; ); +#[derive(Serialize)] +pub struct RemoteTestServer<'a> { + pub compiler: Compiler<'a>, + pub target: &'a str, +} + +impl<'a> Step<'a> for RemoteTestServer<'a> { + type Output = PathBuf; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/tools/remote-test-server") + } + + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + builder.ensure(RemoteTestServer { + compiler: builder.compiler(builder.top_stage, host), + target, + }); + } + + fn run(self, builder: &Builder) -> PathBuf { + builder.ensure(ToolBuild { + stage: self.stage, + target: self.target, + tool: "remote-test-server", + mode: Mode::Libstd, + }) + } +} + // rules.build("tool-cargo", "src/tools/cargo") // .host(true) // .default(build.config.extended) From 5984e70af23e24710b2e18195361e4918cf2988f Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 12 Jul 2017 18:52:31 -0600 Subject: [PATCH 22/51] Cleanups and fixes throughout --- src/bootstrap/check.rs | 11 +-- src/bootstrap/compile.rs | 9 +- src/bootstrap/dist.rs | 199 ++++++++++++++++++--------------------- src/bootstrap/doc.rs | 16 ++++ src/bootstrap/install.rs | 4 +- src/bootstrap/tool.rs | 6 +- 6 files changed, 118 insertions(+), 127 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index e5e0bfa0ac90d..acb50b5b83d24 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -602,7 +602,7 @@ impl<'a> Step<'a> for Compiletest<'a> { builder.ensure(dist::DebuggerScripts { sysroot: &builder.sysroot(compiler), - host: compiler.host + target: target }); if mode == "debuginfo-gdb" { @@ -1326,7 +1326,7 @@ impl<'a> Step<'a> for RemoteCopyLibs<'a> { println!("REMOTE copy libs to emulator ({})", target); t!(fs::create_dir_all(build.out.join("tmp"))); - let server = builder.ensure(tool::RemoteTestServer { compiler, target })); + let server = builder.ensure(tool::RemoteTestServer { stage: compiler.stage, target }); // Spawn the emulator and wait for it to come online let tool = builder.tool_exe(Tool::RemoteTestClient); @@ -1368,9 +1368,6 @@ impl<'a> Step<'a> for Distcheck { fn run(self, builder: &Builder) { let build = builder.build; - builder.ensure(dist::PlainSourceTarball); - builder.ensure(dist::Src); - if build.build != "x86_64-unknown-linux-gnu" { return } @@ -1388,7 +1385,7 @@ impl<'a> Step<'a> for Distcheck { let mut cmd = Command::new("tar"); cmd.arg("-xzf") - .arg(dist::rust_src_location(build)) + .arg(builder.ensure(dist::PlainSourceTarball)) .arg("--strip-components=1") .current_dir(&dir); build.run(&mut cmd); @@ -1408,7 +1405,7 @@ impl<'a> Step<'a> for Distcheck { let mut cmd = Command::new("tar"); cmd.arg("-xzf") - .arg(dist::rust_src_installer(build)) + .arg(builder.ensure(dist::Src)) .arg("--strip-components=1") .current_dir(&dir); build.run(&mut cmd); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 79668efc0782b..db2912e7e272b 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -364,24 +364,21 @@ impl<'a> Step<'a> for StartupObjects<'a> { return } - let compiler = builder.compiler(0, &build.build); - let compiler_path = builder.rustc(compiler); let src_dir = &build.src.join("src/rtstartup"); let dst_dir = &build.native_dir(target).join("rtstartup"); let sysroot_dir = &builder.sysroot_libdir(for_compiler, target); t!(fs::create_dir_all(dst_dir)); - t!(fs::create_dir_all(sysroot_dir)); for file in &["rsbegin", "rsend"] { let src_file = &src_dir.join(file.to_string() + ".rs"); let dst_file = &dst_dir.join(file.to_string() + ".o"); if !up_to_date(src_file, dst_file) { - let mut cmd = Command::new(&compiler_path); + let mut cmd = Command::new(&build.initial_rustc); build.run(cmd.env("RUSTC_BOOTSTRAP", "1") - .arg("--cfg").arg(format!("stage{}", compiler.stage)) + .arg("--cfg").arg("stage0") .arg("--target").arg(target) .arg("--emit=obj") - .arg("--out-dir").arg(dst_dir) + .arg("--o").arg(dst_file) .arg(src_file)); } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index c419f8bb7211b..c5d09869b2b3c 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -74,11 +74,11 @@ fn rust_installer(builder: &Builder) -> Command { #[derive(Serialize)] pub struct Docs<'a> { pub stage: u32, - pub host: &'a str, + pub target: &'a str, } impl<'a> Step<'a> for Docs<'a> { - type Output = (); + type Output = Option; const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -89,33 +89,33 @@ impl<'a> Step<'a> for Docs<'a> { fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { builder.ensure(Docs { stage: builder.top_stage, - host: target, + target: target, }); } /// Builds the `rust-docs` installer component. /// - /// Slurps up documentation from the `stage`'s `host`. - fn run(self, builder: &Builder) { + /// Slurps up documentation from the `stage`'s `target`. + fn run(self, builder: &Builder) -> Option { let build = builder.build; let stage = self.stage; - let host = self.host; + let target = self.target; builder.default_doc(None); - println!("Dist docs stage{} ({})", stage, host); + println!("Dist docs stage{} ({})", stage, target); if !build.config.docs { println!("\tskipping - docs disabled"); - return + return None; } let name = pkgname(build, "rust-docs"); - let image = tmpdir(build).join(format!("{}-{}-image", name, host)); + let image = tmpdir(build).join(format!("{}-{}-image", name, target)); let _ = fs::remove_dir_all(&image); let dst = image.join("share/doc/rust/html"); t!(fs::create_dir_all(&dst)); - let src = build.out.join(host).join("doc"); + let src = build.out.join(target).join("doc"); cp_r(&src, &dst); let mut cmd = rust_installer(builder); @@ -126,7 +126,7 @@ impl<'a> Step<'a> for Docs<'a> { .arg("--image-dir").arg(&image) .arg("--work-dir").arg(&tmpdir(build)) .arg("--output-dir").arg(&distdir(build)) - .arg(format!("--package-name={}-{}", name, host)) + .arg(format!("--package-name={}-{}", name, target)) .arg("--component-name=rust-docs") .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--bulk-dirs=share/doc/rust/html"); @@ -135,11 +135,13 @@ impl<'a> Step<'a> for Docs<'a> { // As part of this step, *also* copy the docs directory to a directory which // buildbot typically uploads. - if host == build.build { + if target == build.build { let dst = distdir(build).join("doc").join(build.rust_package_vers()); t!(fs::create_dir_all(&dst)); cp_r(&src, &dst); } + + Some(distdir(build).join(format!("{}-{}.tar.gz", name, target))) } } @@ -281,11 +283,11 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: #[derive(Serialize)] pub struct Mingw<'a> { - host: &'a str, + target: &'a str, } impl<'a> Step<'a> for Mingw<'a> { - type Output = (); + type Output = Option; const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -293,27 +295,25 @@ impl<'a> Step<'a> for Mingw<'a> { false } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { - builder.ensure(Mingw { - host: host, - }); + fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + builder.ensure(Mingw { target }); } /// Build the `rust-mingw` installer component. /// /// This contains all the bits and pieces to run the MinGW Windows targets /// without any extra installed software (e.g. we bundle gcc, libraries, etc). - fn run(self, builder: &Builder) { + fn run(self, builder: &Builder) -> Option { let build = builder.build; - let host = self.host; + let target = self.target; - if !host.contains("pc-windows-gnu") { - return; + if !target.contains("pc-windows-gnu") { + return None; } - println!("Dist mingw ({})", host); + println!("Dist mingw ({})", target); let name = pkgname(build, "rust-mingw"); - let image = tmpdir(build).join(format!("{}-{}-image", name, host)); + let image = tmpdir(build).join(format!("{}-{}-image", name, target)); let _ = fs::remove_dir_all(&image); t!(fs::create_dir_all(&image)); @@ -321,7 +321,7 @@ impl<'a> Step<'a> for Mingw<'a> { // thrown away (this contains the runtime DLLs included in the rustc package // above) and the second argument is where to place all the MinGW components // (which is what we want). - make_win_dist(&tmpdir(build), &image, host, &build); + make_win_dist(&tmpdir(build), &image, target, &build); let mut cmd = rust_installer(builder); cmd.arg("generate") @@ -331,11 +331,12 @@ impl<'a> Step<'a> for Mingw<'a> { .arg("--image-dir").arg(&image) .arg("--work-dir").arg(&tmpdir(build)) .arg("--output-dir").arg(&distdir(build)) - .arg(format!("--package-name={}-{}", name, host)) + .arg(format!("--package-name={}-{}", name, target)) .arg("--component-name=rust-mingw") .arg("--legacy-manifest-dirs=rustlib,cargo"); build.run(&mut cmd); t!(fs::remove_dir_all(&image)); + Some(distdir(build).join(format!("{}-{}.tar.gz", name, target))) } } @@ -350,11 +351,11 @@ impl<'a> Step<'a> for Mingw<'a> { #[derive(Serialize)] pub struct Rustc<'a> { pub stage: u32, - pub host: &'a str, + pub target: &'a str, } impl<'a> Step<'a> for Rustc<'a> { - type Output = (); + type Output = PathBuf; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -363,27 +364,32 @@ impl<'a> Step<'a> for Rustc<'a> { path.ends_with("src/librustc") } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { + fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { builder.ensure(Rustc { stage: builder.top_stage, - host: host, + target: target, }); } /// Creates the `rustc` installer component. - fn run(self, builder: &Builder) { + fn run(self, builder: &Builder) -> PathBuf { let build = builder.build; let stage = self.stage; - let host = self.host; - println!("Dist rustc stage{} ({})", stage, host); + let target = self.target; + + let compiler = builder.ensure(compile::Assemble { + target_compiler: builder.compiler(stage, &build.build), + }); + + println!("Dist rustc stage{} ({})", stage, target); let name = pkgname(build, "rustc"); - let image = tmpdir(build).join(format!("{}-{}-image", name, host)); + let image = tmpdir(build).join(format!("{}-{}-image", name, target)); let _ = fs::remove_dir_all(&image); - let overlay = tmpdir(build).join(format!("{}-{}-overlay", name, host)); + let overlay = tmpdir(build).join(format!("{}-{}-overlay", name, target)); let _ = fs::remove_dir_all(&overlay); // Prepare the rustc "image", what will actually end up getting installed - prepare_image(builder, stage, host, &image); + prepare_image(builder, compiler, target, &image); // Prepare the overlay which is part of the tarball but won't actually be // installed @@ -408,8 +414,8 @@ impl<'a> Step<'a> for Rustc<'a> { // anything requiring us to distribute a license, but it's likely the // install will *also* include the rust-mingw package, which also needs // licenses, so to be safe we just include it here in all MinGW packages. - if host.contains("pc-windows-gnu") { - make_win_dist(&image, &tmpdir(build), host, build); + if target.contains("pc-windows-gnu") { + make_win_dist(&image, &tmpdir(build), target, build); let dst = image.join("share/doc"); t!(fs::create_dir_all(&dst)); @@ -426,17 +432,19 @@ impl<'a> Step<'a> for Rustc<'a> { .arg("--work-dir").arg(&tmpdir(build)) .arg("--output-dir").arg(&distdir(build)) .arg("--non-installed-overlay").arg(&overlay) - .arg(format!("--package-name={}-{}", name, host)) + .arg(format!("--package-name={}-{}", name, target)) .arg("--component-name=rustc") .arg("--legacy-manifest-dirs=rustlib,cargo"); build.run(&mut cmd); t!(fs::remove_dir_all(&image)); t!(fs::remove_dir_all(&overlay)); - fn prepare_image(builder: &Builder, stage: u32, host: &str, image: &Path) { + return distdir(build).join(format!("{}-{}.tar.gz", name, target)); + + fn prepare_image(builder: &Builder, compiler: Compiler, target: &str, image: &Path) { let build = builder.build; - let src = builder.sysroot(builder.compiler(stage, host)); - let libdir = libdir(host); + let src = builder.sysroot(compiler); + let libdir = libdir(target); // Copy rustc/rustdoc binaries t!(fs::create_dir_all(image.join("bin"))); @@ -461,7 +469,7 @@ impl<'a> Step<'a> for Rustc<'a> { // Debugger scripts builder.ensure(DebuggerScripts { sysroot: &image, - host: host, + target: target, }); // Misc license info @@ -483,7 +491,7 @@ impl<'a> Step<'a> for Rustc<'a> { #[derive(Serialize)] pub struct DebuggerScripts<'a> { pub sysroot: &'a Path, - pub host: &'a str, + pub target: &'a str, } impl<'a> Step<'a> for DebuggerScripts<'a> { @@ -493,25 +501,24 @@ impl<'a> Step<'a> for DebuggerScripts<'a> { path.ends_with("src/etc/lldb_batchmode.py") } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { + fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { builder.ensure(DebuggerScripts { - // FIXME: builder.top_stage is likely wrong in some cases. sysroot: &builder.sysroot(builder.compiler(builder.top_stage, host)), - host: host, + target: target, }); } - /// Copies debugger scripts for `host` into the `sysroot` specified. + /// Copies debugger scripts for `target` into the `sysroot` specified. fn run(self, builder: &Builder) { let build = builder.build; - let host = self.host; + let target = self.target; let sysroot = self.sysroot; let dst = sysroot.join("lib/rustlib/etc"); t!(fs::create_dir_all(&dst)); let cp_debugger_script = |file: &str| { install(&build.src.join("src/etc/").join(file), &dst, 0o644); }; - if host.contains("windows-msvc") { + if target.contains("windows-msvc") { // windbg debugger scripts install(&build.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"), 0o755); @@ -560,7 +567,7 @@ pub struct Std<'a> { } impl<'a> Step<'a> for Std<'a> { - type Output = (); + type Output = Option; const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -575,7 +582,7 @@ impl<'a> Step<'a> for Std<'a> { }); } - fn run(self, builder: &Builder) { + fn run(self, builder: &Builder) -> Option { let build = builder.build; let compiler = self.compiler; let target = self.target; @@ -587,7 +594,7 @@ impl<'a> Step<'a> for Std<'a> { // let's reduce redundant work by only producing archives from that host. if compiler.host != build.build { println!("\tskipping, not a build host"); - return + return None; } // We want to package up as many target libraries as possible @@ -622,21 +629,10 @@ impl<'a> Step<'a> for Std<'a> { .arg("--legacy-manifest-dirs=rustlib,cargo"); build.run(&mut cmd); t!(fs::remove_dir_all(&image)); + Some(distdir(build).join(format!("{}-{}.tar.gz", name, target))) } } -/// The path to the complete rustc-src tarball -pub fn rust_src_location(build: &Build) -> PathBuf { - let plain_name = format!("rustc-{}-src", build.rust_package_vers()); - distdir(build).join(&format!("{}.tar.gz", plain_name)) -} - -/// The path to the rust-src component installer -pub fn rust_src_installer(build: &Build) -> PathBuf { - let name = pkgname(build, "rust-src"); - distdir(build).join(&format!("{}.tar.gz", name)) -} - // rules.dist("dist-analysis", "analysis") // .default(build.config.extended) // .dep(|s| s.name("dist-std")) @@ -651,7 +647,7 @@ pub struct Analysis<'a> { } impl<'a> Step<'a> for Analysis<'a> { - type Output = (); + type Output = Option; const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -670,7 +666,7 @@ impl<'a> Step<'a> for Analysis<'a> { } /// Creates a tarball of save-analysis metadata, if available. - fn run(self, builder: &Builder) { + fn run(self, builder: &Builder) -> Option { let build = builder.build; let compiler = self.compiler; let target = self.target; @@ -679,7 +675,7 @@ impl<'a> Step<'a> for Analysis<'a> { if compiler.host != build.build { println!("\tskipping, not a build host"); - return; + return None; } // Package save-analysis from stage1 if not doing a full bootstrap, as the @@ -715,6 +711,7 @@ impl<'a> Step<'a> for Analysis<'a> { .arg("--legacy-manifest-dirs=rustlib,cargo"); build.run(&mut cmd); t!(fs::remove_dir_all(&image)); + Some(distdir(build).join(format!("{}-{}.tar.gz", name, target))) } } @@ -770,7 +767,8 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di pub struct Src; impl<'a> Step<'a> for Src { - type Output = (); + /// The output path of the src installer tarball + type Output = PathBuf; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -785,7 +783,7 @@ impl<'a> Step<'a> for Src { } /// Creates the `rust-src` installer component - fn run(self, builder: &Builder) { + fn run(self, builder: &Builder) -> PathBuf { let build = builder.build; println!("Dist src"); @@ -848,6 +846,7 @@ impl<'a> Step<'a> for Src { build.run(&mut cmd); t!(fs::remove_dir_all(&image)); + distdir(build).join(&format!("{}.tar.gz", name)) } } @@ -865,7 +864,8 @@ const CARGO_VENDOR_VERSION: &str = "0.1.4"; pub struct PlainSourceTarball; impl<'a> Step<'a> for PlainSourceTarball { - type Output = (); + /// Produces the location of the tarball generated + type Output = PathBuf; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -884,7 +884,7 @@ impl<'a> Step<'a> for PlainSourceTarball { } /// Creates the plain source tarball - fn run(self, builder: &Builder) { + fn run(self, builder: &Builder) -> PathBuf { let build = builder.build; println!("Create plain source tarball"); @@ -947,10 +947,11 @@ impl<'a> Step<'a> for PlainSourceTarball { } // Create plain source tarball - let mut tarball = rust_src_location(build); + let plain_name = format!("rustc-{}-src", build.rust_package_vers()); + let mut tarball = distdir(build).join(&format!("{}.tar.gz", plain_name)); tarball.set_extension(""); // strip .gz tarball.set_extension(""); // strip .tar - if let Some(dir) = tarball.parent() { + if let Some(dir) = distdir(build).parent() { t!(fs::create_dir_all(dir)); } let mut cmd = rust_installer(builder); @@ -960,6 +961,7 @@ impl<'a> Step<'a> for PlainSourceTarball { .arg("--work-dir=.") .current_dir(tmpdir(build)); build.run(&mut cmd); + distdir(build).join(&format!("{}.tar.gz", plain_name)) } } @@ -1016,7 +1018,7 @@ pub struct Cargo<'a> { } impl<'a> Step<'a> for Cargo<'a> { - type Output = (); + type Output = PathBuf; const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; @@ -1031,7 +1033,7 @@ impl<'a> Step<'a> for Cargo<'a> { }); } - fn run(self, builder: &Builder) { + fn run(self, builder: &Builder) -> PathBuf { let build = builder.build; let stage = self.stage; let target = self.target; @@ -1095,6 +1097,7 @@ impl<'a> Step<'a> for Cargo<'a> { .arg("--component-name=cargo") .arg("--legacy-manifest-dirs=rustlib,cargo"); build.run(&mut cmd); + distdir(build).join(format!("{}-{}.tar.gz", name, target)) } } @@ -1111,7 +1114,7 @@ pub struct Rls<'a> { } impl<'a> Step<'a> for Rls<'a> { - type Output = (); + type Output = PathBuf; const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; @@ -1126,7 +1129,7 @@ impl<'a> Step<'a> for Rls<'a> { }); } - fn run(self, builder: &Builder) { + fn run(self, builder: &Builder) -> PathBuf { let build = builder.build; let stage = self.stage; let target = self.target; @@ -1179,6 +1182,7 @@ impl<'a> Step<'a> for Rls<'a> { .arg("--component-name=rls") .arg("--legacy-manifest-dirs=rustlib,cargo"); build.run(&mut cmd); + distdir(build).join(format!("{}-{}.tar.gz", name, target)) } } @@ -1229,38 +1233,15 @@ impl<'a> Step<'a> for Extended<'a> { let target = self.target; let compiler = builder.compiler(stage, &build.build); - builder.ensure(Std { compiler, target }); - builder.ensure(Rustc { stage, host: target }); - builder.ensure(Mingw { host: target }); - builder.ensure(Docs { stage, host: target }); - builder.ensure(Cargo { stage, target }); - builder.ensure(Rls { stage, target }); - builder.ensure(Analysis { compiler, target }); - println!("Dist extended stage{} ({})", stage, target); - let dist = distdir(build); - let rustc_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "rustc"), - target)); - let cargo_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "cargo"), - target)); - let rls_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "rls"), - target)); - let analysis_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "rust-analysis"), - target)); - let docs_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "rust-docs"), - target)); - let mingw_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "rust-mingw"), - target)); - let std_installer = dist.join(format!("{}-{}.tar.gz", - pkgname(build, "rust-std"), - target)); + let rustc_installer = builder.ensure(Rustc { stage, target }); + let cargo_installer = builder.ensure(Cargo { stage, target }); + let rls_installer = builder.ensure(Rls { stage, target }); + let analysis_installer = builder.ensure(Analysis { compiler, target }).unwrap(); + let docs_installer = builder.ensure(Docs { stage, target }).unwrap(); + let mingw_installer = builder.ensure(Mingw { target }); + let std_installer = builder.ensure(Std { compiler, target }).unwrap(); let tmp = tmpdir(build); let overlay = tmp.join("extended-overlay"); @@ -1282,7 +1263,7 @@ impl<'a> Step<'a> for Extended<'a> { let mut tarballs = vec![rustc_installer, cargo_installer, rls_installer, analysis_installer, docs_installer, std_installer]; if target.contains("pc-windows-gnu") { - tarballs.push(mingw_installer); + tarballs.push(mingw_installer.unwrap()); } let mut input_tarballs = tarballs[0].as_os_str().to_owned(); for tarball in &tarballs[1..] { diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 3493f4e66bca0..d12f93f7f6db1 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -222,6 +222,22 @@ pub struct TheBook<'a> { impl<'a> Step<'a> for TheBook<'a> { type Output = (); + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/doc/book") + } + + fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + if path.is_none() && !builder.build.config.docs { + // Not a default rule if docs are disabled. + return; + } + + builder.ensure(TheBook { + target, + name: "book", + }); + } + /// Build the book and associated stuff. /// /// We need to build: diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 4361a4d369a46..2f5d174bb3fb4 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -201,7 +201,7 @@ install!( // .dep(|s| s.name("dist-docs")) // .run(move |s| install::Installer::new(build).install_docs(s.stage, s.target)); Docs, "src/doc", builder.build.config.docs, only_hosts: false, (self, builder), { - builder.ensure(dist::Docs { stage: self.stage, host: self.host }); + builder.ensure(dist::Docs { stage: self.stage, target: self.target }); Installer::new(builder.build).install_docs(self.stage, self.target); }; // rules.install("install-std", "src/libstd") @@ -266,7 +266,7 @@ install!( // .dep(|s| s.name("dist-rustc")) // .run(move |s| install::Installer::new(build).install_rustc(s.stage, s.target)); Rustc, "src/librustc", builder.build.config.extended, only_hosts: true, (self, builder), { - builder.ensure(dist::Rustc { stage: self.stage, host: self.host }); + builder.ensure(dist::Rustc { stage: self.stage, target: self.target }); Installer::new(builder.build).install_rustc(self.stage, self.target); }; ); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 6153d37cf1a07..63404bcf50009 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -253,7 +253,7 @@ tool!( #[derive(Serialize)] pub struct RemoteTestServer<'a> { - pub compiler: Compiler<'a>, + pub stage: u32, pub target: &'a str, } @@ -264,9 +264,9 @@ impl<'a> Step<'a> for RemoteTestServer<'a> { path.ends_with("src/tools/remote-test-server") } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { builder.ensure(RemoteTestServer { - compiler: builder.compiler(builder.top_stage, host), + stage: builder.top_stage, target, }); } From 6a85193149cca28b18a7110ce187c69130f1e3d4 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 13 Jul 2017 06:25:40 -0600 Subject: [PATCH 23/51] Clean up install --- src/bootstrap/install.rs | 209 +++++++++++++++++---------------------- 1 file changed, 89 insertions(+), 120 deletions(-) diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 2f5d174bb3fb4..4ceeb3e6793db 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -20,121 +20,90 @@ use std::process::Command; use dist::{self, pkgname, sanitize_sh, tmpdir}; -use Build; use builder::{Builder, Step}; -pub struct Installer<'a> { - build: &'a Build, - prefix: PathBuf, - sysconfdir: PathBuf, - docdir: PathBuf, - bindir: PathBuf, - libdir: PathBuf, - mandir: PathBuf, - empty_dir: PathBuf, +pub fn install_docs(builder: &Builder, stage: u32, host: &str) { + install_sh(builder, "docs", "rust-docs", stage, Some(host)); } -impl<'a> Drop for Installer<'a> { - fn drop(&mut self) { - t!(fs::remove_dir_all(&self.empty_dir)); +pub fn install_std(builder: &Builder, stage: u32) { + for target in builder.build.config.target.iter() { + install_sh(builder, "std", "rust-std", stage, Some(target)); } } -impl<'a> Installer<'a> { - pub fn new(build: &'a Build) -> Installer<'a> { - let prefix_default = PathBuf::from("/usr/local"); - let sysconfdir_default = PathBuf::from("/etc"); - let docdir_default = PathBuf::from("share/doc/rust"); - let bindir_default = PathBuf::from("bin"); - let libdir_default = PathBuf::from("lib"); - let mandir_default = PathBuf::from("share/man"); - let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default); - let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default); - let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default); - let bindir = build.config.bindir.as_ref().unwrap_or(&bindir_default); - let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default); - let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default); - - let sysconfdir = prefix.join(sysconfdir); - let docdir = prefix.join(docdir); - let bindir = prefix.join(bindir); - let libdir = prefix.join(libdir); - let mandir = prefix.join(mandir); - - let destdir = env::var_os("DESTDIR").map(PathBuf::from); - - let prefix = add_destdir(&prefix, &destdir); - let sysconfdir = add_destdir(&sysconfdir, &destdir); - let docdir = add_destdir(&docdir, &destdir); - let bindir = add_destdir(&bindir, &destdir); - let libdir = add_destdir(&libdir, &destdir); - let mandir = add_destdir(&mandir, &destdir); - - let empty_dir = build.out.join("tmp/empty_dir"); - - t!(fs::create_dir_all(&empty_dir)); - - Installer { - build, - prefix, - sysconfdir, - docdir, - bindir, - libdir, - mandir, - empty_dir, - } - } - - pub fn install_docs(&self, stage: u32, host: &str) { - self.install_sh("docs", "rust-docs", stage, Some(host)); - } - - pub fn install_std(&self, stage: u32) { - for target in self.build.config.target.iter() { - self.install_sh("std", "rust-std", stage, Some(target)); - } - } - - pub fn install_cargo(&self, stage: u32, host: &str) { - self.install_sh("cargo", "cargo", stage, Some(host)); - } +pub fn install_cargo(builder: &Builder, stage: u32, host: &str) { + install_sh(builder, "cargo", "cargo", stage, Some(host)); +} - pub fn install_rls(&self, stage: u32, host: &str) { - self.install_sh("rls", "rls", stage, Some(host)); - } +pub fn install_rls(builder: &Builder, stage: u32, host: &str) { + install_sh(builder, "rls", "rls", stage, Some(host)); +} - pub fn install_analysis(&self, stage: u32, host: &str) { - self.install_sh("analysis", "rust-analysis", stage, Some(host)); - } +pub fn install_analysis(builder: &Builder, stage: u32, host: &str) { + install_sh(builder, "analysis", "rust-analysis", stage, Some(host)); +} - pub fn install_src(&self, stage: u32) { - self.install_sh("src", "rust-src", stage, None); - } - pub fn install_rustc(&self, stage: u32, host: &str) { - self.install_sh("rustc", "rustc", stage, Some(host)); - } +pub fn install_src(builder: &Builder, stage: u32) { + install_sh(builder, "src", "rust-src", stage, None); +} +pub fn install_rustc(builder: &Builder, stage: u32, host: &str) { + install_sh(builder, "rustc", "rustc", stage, Some(host)); +} - fn install_sh(&self, package: &str, name: &str, stage: u32, host: Option<&str>) { - println!("Install {} stage{} ({:?})", package, stage, host); - let package_name = if let Some(host) = host { - format!("{}-{}", pkgname(self.build, name), host) - } else { - pkgname(self.build, name) - }; +fn install_sh(builder: &Builder, package: &str, name: &str, stage: u32, host: Option<&str>) { + let build = builder.build; + println!("Install {} stage{} ({:?})", package, stage, host); + + let prefix_default = PathBuf::from("/usr/local"); + let sysconfdir_default = PathBuf::from("/etc"); + let docdir_default = PathBuf::from("share/doc/rust"); + let bindir_default = PathBuf::from("bin"); + let libdir_default = PathBuf::from("lib"); + let mandir_default = PathBuf::from("share/man"); + let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default); + let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default); + let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default); + let bindir = build.config.bindir.as_ref().unwrap_or(&bindir_default); + let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default); + let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default); + + let sysconfdir = prefix.join(sysconfdir); + let docdir = prefix.join(docdir); + let bindir = prefix.join(bindir); + let libdir = prefix.join(libdir); + let mandir = prefix.join(mandir); + + let destdir = env::var_os("DESTDIR").map(PathBuf::from); + + let prefix = add_destdir(&prefix, &destdir); + let sysconfdir = add_destdir(&sysconfdir, &destdir); + let docdir = add_destdir(&docdir, &destdir); + let bindir = add_destdir(&bindir, &destdir); + let libdir = add_destdir(&libdir, &destdir); + let mandir = add_destdir(&mandir, &destdir); + + let empty_dir = build.out.join("tmp/empty_dir"); + + t!(fs::create_dir_all(&empty_dir)); + let package_name = if let Some(host) = host { + format!("{}-{}", pkgname(build, name), host) + } else { + pkgname(build, name) + }; - let mut cmd = Command::new("sh"); - cmd.current_dir(&self.empty_dir) - .arg(sanitize_sh(&tmpdir(self.build).join(&package_name).join("install.sh"))) - .arg(format!("--prefix={}", sanitize_sh(&self.prefix))) - .arg(format!("--sysconfdir={}", sanitize_sh(&self.sysconfdir))) - .arg(format!("--docdir={}", sanitize_sh(&self.docdir))) - .arg(format!("--bindir={}", sanitize_sh(&self.bindir))) - .arg(format!("--libdir={}", sanitize_sh(&self.libdir))) - .arg(format!("--mandir={}", sanitize_sh(&self.mandir))) - .arg("--disable-ldconfig"); - self.build.run(&mut cmd); - } + let mut cmd = Command::new("sh"); + cmd.current_dir(&empty_dir) + .arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh"))) + .arg(format!("--prefix={}", sanitize_sh(&prefix))) + .arg(format!("--sysconfdir={}", sanitize_sh(&sysconfdir))) + .arg(format!("--docdir={}", sanitize_sh(&docdir))) + .arg(format!("--bindir={}", sanitize_sh(&bindir))) + .arg(format!("--libdir={}", sanitize_sh(&libdir))) + .arg(format!("--mandir={}", sanitize_sh(&mandir))) + .arg("--disable-ldconfig"); + build.run(&mut cmd); + t!(fs::remove_dir_all(&empty_dir)); } fn add_destdir(path: &Path, destdir: &Option) -> PathBuf { @@ -152,11 +121,11 @@ fn add_destdir(path: &Path, destdir: &Option) -> PathBuf { } macro_rules! install { - ($($name:ident, + (($sel:ident, $builder:ident), + $($name:ident, $path:expr, $default_cond:expr, only_hosts: $only_hosts:expr, - ($sel:ident, $builder:ident), $run_item:block $(, $c:ident)*;)+) => { $(#[derive(Serialize)] pub struct $name<'a> { @@ -194,27 +163,27 @@ macro_rules! install { } } -install!( +install!((self, builder), // rules.install("install-docs", "src/doc") // .default(build.config.docs) // .only_host_build(true) // .dep(|s| s.name("dist-docs")) // .run(move |s| install::Installer::new(build).install_docs(s.stage, s.target)); - Docs, "src/doc", builder.build.config.docs, only_hosts: false, (self, builder), { + Docs, "src/doc", builder.build.config.docs, only_hosts: false, { builder.ensure(dist::Docs { stage: self.stage, target: self.target }); - Installer::new(builder.build).install_docs(self.stage, self.target); + install_docs(builder, self.stage, self.target); }; // rules.install("install-std", "src/libstd") // .default(true) // .only_host_build(true) // .dep(|s| s.name("dist-std")) // .run(move |s| install::Installer::new(build).install_std(s.stage)); - Std, "src/libstd", true, only_hosts: true, (self, builder), { + Std, "src/libstd", true, only_hosts: true, { builder.ensure(dist::Std { compiler: builder.compiler(self.stage, self.host), target: self.target }); - Installer::new(builder.build).install_std(self.stage); + install_std(builder, self.stage); }; // rules.install("install-cargo", "cargo") // .default(build.config.extended) @@ -222,9 +191,9 @@ install!( // .only_host_build(true) // .dep(|s| s.name("dist-cargo")) // .run(move |s| install::Installer::new(build).install_cargo(s.stage, s.target)); - Cargo, "cargo", builder.build.config.extended, only_hosts: true, (self, builder), { + Cargo, "cargo", builder.build.config.extended, only_hosts: true, { builder.ensure(dist::Cargo { stage: self.stage, target: self.target }); - Installer::new(builder.build).install_cargo(self.stage, self.target); + install_cargo(builder, self.stage, self.target); }; // rules.install("install-rls", "rls") // .default(build.config.extended) @@ -232,21 +201,21 @@ install!( // .only_host_build(true) // .dep(|s| s.name("dist-rls")) // .run(move |s| install::Installer::new(build).install_rls(s.stage, s.target)); - Rls, "rls", builder.build.config.extended, only_hosts: true, (self, builder), { + Rls, "rls", builder.build.config.extended, only_hosts: true, { builder.ensure(dist::Rls { stage: self.stage, target: self.target }); - Installer::new(builder.build).install_rls(self.stage, self.target); + install_rls(builder, self.stage, self.target); }; // rules.install("install-analysis", "analysis") // .default(build.config.extended) // .only_host_build(true) // .dep(|s| s.name("dist-analysis")) // .run(move |s| install::Installer::new(build).install_analysis(s.stage, s.target)); - Analysis, "analysis", builder.build.config.extended, only_hosts: false, (self, builder), { + Analysis, "analysis", builder.build.config.extended, only_hosts: false, { builder.ensure(dist::Analysis { compiler: builder.compiler(self.stage, self.host), target: self.target }); - Installer::new(builder.build).install_analysis(self.stage, self.target); + install_analysis(builder, self.stage, self.target); }; // rules.install("install-src", "src") // .default(build.config.extended) @@ -255,9 +224,9 @@ install!( // .only_host_build(true) // .dep(|s| s.name("dist-src")) // .run(move |s| install::Installer::new(build).install_src(s.stage)); - Src, "src", builder.build.config.extended, only_hosts: true, (self, builder), { + Src, "src", builder.build.config.extended, only_hosts: true, { builder.ensure(dist::Src); - Installer::new(builder.build).install_src(self.stage); + install_src(builder, self.stage); }, ONLY_BUILD; // rules.install("install-rustc", "src/librustc") // .default(true) @@ -265,8 +234,8 @@ install!( // .only_host_build(true) // .dep(|s| s.name("dist-rustc")) // .run(move |s| install::Installer::new(build).install_rustc(s.stage, s.target)); - Rustc, "src/librustc", builder.build.config.extended, only_hosts: true, (self, builder), { + Rustc, "src/librustc", builder.build.config.extended, only_hosts: true, { builder.ensure(dist::Rustc { stage: self.stage, target: self.target }); - Installer::new(builder.build).install_rustc(self.stage, self.target); + install_rustc(builder, self.stage, self.target); }; ); From e7b1a60ad7ff6ed1051c7f0945d79c96aa8068fd Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 13 Jul 2017 11:12:57 -0600 Subject: [PATCH 24/51] Remove core_intrinsics feature gate --- src/bootstrap/builder.rs | 4 ++++ src/bootstrap/cache.rs | 28 +++++++++------------------- src/bootstrap/check.rs | 12 ++++++++++++ src/bootstrap/compile.rs | 9 +++++++++ src/bootstrap/dist.rs | 12 ++++++++++++ src/bootstrap/doc.rs | 11 +++++++++++ src/bootstrap/install.rs | 1 + src/bootstrap/lib.rs | 1 - src/bootstrap/native.rs | 3 +++ src/bootstrap/tool.rs | 6 ++++++ 10 files changed, 67 insertions(+), 20 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 5d7400ab9ae8a..72736c7611148 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -56,6 +56,9 @@ pub trait Step<'a>: Serialize + Sized { /// somewhat harder. type Output: Serialize + Deserialize<'a> + 'a; + /// This type, but with a 'static bound. Used for caching the step. + type Id: 'static; + const DEFAULT: bool = false; /// Run this rule for all hosts without cross compiling. @@ -190,6 +193,7 @@ impl<'a> Builder<'a> { target: &'a str, } impl<'a> Step<'a> for Libdir<'a> { + type Id = Libdir<'static>; type Output = PathBuf; fn run(self, builder: &Builder) -> PathBuf { let compiler = self.compiler; diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index bc69c6fcffdd8..475e3abfd4097 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -10,10 +10,11 @@ use serde_json; use serde::{Serialize, Deserialize}; +use std::any::TypeId; +use builder::Step; use std::fmt; use std::mem; -use std::intrinsics; use std::collections::HashMap; use std::cell::RefCell; @@ -29,31 +30,20 @@ use std::cell::RefCell; pub struct Cache(RefCell>>); fn to_json(element: &T) -> String { - let type_id = unsafe { - intrinsics::type_name::() - }; - - t!(serde_json::to_string(&(type_id, element))) + t!(serde_json::to_string(element)) } fn from_json<'a, O: Deserialize<'a>>(data: &'a str) -> O { - let type_id = unsafe { - intrinsics::type_name::() - }; - - let (de_type_id, element): (&'a str, O) = t!(serde_json::from_str(data)); - - assert_eq!(type_id, de_type_id); - - element + t!(serde_json::from_str(data)) } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct Key(String); +pub struct Key(TypeId, String); impl fmt::Debug for Key { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.write_str(&self.0) + fmt.write_str(&format!("{:?}; ", self.0))?; + fmt.write_str(&self.1) } } @@ -62,8 +52,8 @@ impl Cache { Cache(RefCell::new(HashMap::new())) } - pub fn to_key(key: &K) -> Key { - Key(to_json(key)) + pub fn to_key<'a, K: Step<'a>>(key: &K) -> Key { + Key(TypeId::of::(), to_json(key)) } /// Puts a value into the cache. Will panic if called more than once with diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index acb50b5b83d24..8adfed44f0187 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -99,6 +99,7 @@ pub struct Linkcheck<'a> { } impl<'a> Step<'a> for Linkcheck<'a> { + type Id = Linkcheck<'static>; type Output = (); const ONLY_HOSTS: bool = true; const DEFAULT: bool = true; @@ -148,6 +149,7 @@ pub struct Cargotest<'a> { } impl<'a> Step<'a> for Cargotest<'a> { + type Id = Cargotest<'static>; type Output = (); const ONLY_HOSTS: bool = true; @@ -198,6 +200,7 @@ pub struct Cargo<'a> { } impl<'a> Step<'a> for Cargo<'a> { + type Id = Cargo<'static>; type Output = (); const ONLY_HOSTS: bool = true; @@ -307,6 +310,7 @@ pub struct Tidy<'a> { } impl<'a> Step<'a> for Tidy<'a> { + type Id = Tidy<'static>; type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -509,6 +513,7 @@ static COMPILETESTS: &[Test] = &[ ]; impl<'a> Step<'a> for Compiletest<'a> { + type Id = Compiletest<'static>; type Output = (); const DEFAULT: bool = true; @@ -775,6 +780,7 @@ pub struct Docs<'a> { // .host(true) // .run(move |s| check::docs(build, &s.compiler())); impl<'a> Step<'a> for Docs<'a> { + type Id = Docs<'static>; type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -840,6 +846,7 @@ pub struct ErrorIndex<'a> { } impl<'a> Step<'a> for ErrorIndex<'a> { + type Id = ErrorIndex<'static>; type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -935,6 +942,7 @@ pub struct KrateLibrustc<'a> { } impl<'a> Step<'a> for KrateLibrustc<'a> { + type Id = KrateLibrustc<'static>; type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -1045,6 +1053,7 @@ pub struct Krate<'a> { } impl<'a> Step<'a> for Krate<'a> { + type Id = Krate<'static>; type Output = (); const DEFAULT: bool = true; @@ -1311,6 +1320,7 @@ pub struct RemoteCopyLibs<'a> { } impl<'a> Step<'a> for RemoteCopyLibs<'a> { + type Id = RemoteCopyLibs<'static>; type Output = (); fn run(self, builder: &Builder) { @@ -1362,6 +1372,7 @@ impl<'a> Step<'a> for RemoteCopyLibs<'a> { pub struct Distcheck; impl<'a> Step<'a> for Distcheck { + type Id = Distcheck; type Output = (); /// Run "distcheck", a 'make check' from a tarball @@ -1429,6 +1440,7 @@ impl<'a> Step<'a> for Distcheck { pub struct Bootstrap; impl<'a> Step<'a> for Bootstrap { + type Id = Bootstrap; type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index db2912e7e272b..ec08bb9db2b98 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -147,6 +147,7 @@ pub struct Std<'a> { } impl<'a> Step<'a> for Std<'a> { + type Id = Std<'static>; type Output = (); const DEFAULT: bool = true; @@ -268,6 +269,7 @@ struct StdLink<'a> { } impl<'a> Step<'a> for StdLink<'a> { + type Id = StdLink<'static>; type Output = (); /// Link all libstd rlibs/dylibs into the sysroot location. @@ -337,6 +339,7 @@ pub struct StartupObjects<'a> { } impl<'a> Step<'a> for StartupObjects<'a> { + type Id = StartupObjects<'static>; type Output = (); fn should_run(_builder: &Builder, path: &Path) -> bool { @@ -403,6 +406,7 @@ pub struct Test<'a> { } impl<'a> Step<'a> for Test<'a> { + type Id = Test<'static>; type Output = (); const DEFAULT: bool = true; @@ -485,6 +489,7 @@ pub struct TestLink<'a> { } impl<'a> Step<'a> for TestLink<'a> { + type Id = TestLink<'static>; type Output = (); /// Same as `std_link`, only for libtest @@ -519,6 +524,7 @@ pub struct Rustc<'a> { } impl<'a> Step<'a> for Rustc<'a> { + type Id = Rustc<'static>; type Output = (); const ONLY_HOSTS: bool = true; const DEFAULT: bool = true; @@ -668,6 +674,7 @@ struct RustcLink<'a> { } impl<'a> Step<'a> for RustcLink<'a> { + type Id = RustcLink<'static>; type Output = (); /// Same as `std_link`, only for librustc @@ -720,6 +727,7 @@ pub struct Sysroot<'a> { } impl<'a> Step<'a> for Sysroot<'a> { + type Id = Sysroot<'static>; type Output = PathBuf; /// Returns the sysroot for the `compiler` specified that *this build system @@ -766,6 +774,7 @@ pub struct Assemble<'a> { } impl<'a> Step<'a> for Assemble<'a> { + type Id = Assemble<'static>; type Output = Compiler<'a>; /// Prepare a new compiler from the artifacts in `stage` diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index c5d09869b2b3c..f19536e2f490b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -78,6 +78,7 @@ pub struct Docs<'a> { } impl<'a> Step<'a> for Docs<'a> { + type Id = Docs<'static>; type Output = Option; const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -287,6 +288,7 @@ pub struct Mingw<'a> { } impl<'a> Step<'a> for Mingw<'a> { + type Id = Mingw<'static>; type Output = Option; const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -355,6 +357,7 @@ pub struct Rustc<'a> { } impl<'a> Step<'a> for Rustc<'a> { + type Id = Rustc<'static>; type Output = PathBuf; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -495,6 +498,7 @@ pub struct DebuggerScripts<'a> { } impl<'a> Step<'a> for DebuggerScripts<'a> { + type Id = DebuggerScripts<'static>; type Output = (); fn should_run(_builder: &Builder, path: &Path) -> bool { @@ -567,6 +571,7 @@ pub struct Std<'a> { } impl<'a> Step<'a> for Std<'a> { + type Id = Std<'static>; type Output = Option; const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -647,6 +652,7 @@ pub struct Analysis<'a> { } impl<'a> Step<'a> for Analysis<'a> { + type Id = Analysis<'static>; type Output = Option; const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -767,6 +773,7 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di pub struct Src; impl<'a> Step<'a> for Src { + type Id = Src; /// The output path of the src installer tarball type Output = PathBuf; const DEFAULT: bool = true; @@ -864,6 +871,7 @@ const CARGO_VENDOR_VERSION: &str = "0.1.4"; pub struct PlainSourceTarball; impl<'a> Step<'a> for PlainSourceTarball { + type Id = PlainSourceTarball; /// Produces the location of the tarball generated type Output = PathBuf; const DEFAULT: bool = true; @@ -1018,6 +1026,7 @@ pub struct Cargo<'a> { } impl<'a> Step<'a> for Cargo<'a> { + type Id = Cargo<'static>; type Output = PathBuf; const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; @@ -1114,6 +1123,7 @@ pub struct Rls<'a> { } impl<'a> Step<'a> for Rls<'a> { + type Id = Rls<'static>; type Output = PathBuf; const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; @@ -1207,6 +1217,7 @@ pub struct Extended<'a> { } impl<'a> Step<'a> for Extended<'a> { + type Id = Extended<'static>; type Output = (); const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -1613,6 +1624,7 @@ fn add_env(build: &Build, cmd: &mut Command, target: &str) { pub struct HashSign; impl<'a> Step<'a> for HashSign { + type Id = HashSign; type Output = (); const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index d12f93f7f6db1..56715d284a6cd 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -40,6 +40,7 @@ macro_rules! book { } impl<'a> Step<'a> for $name<'a> { + type Id = $name<'static>; type Output = (); const DEFAULT: bool = true; @@ -99,6 +100,7 @@ pub struct Rustbook<'a> { } impl<'a> Step<'a> for Rustbook<'a> { + type Id = Rustbook<'static>; type Output = (); /// Invoke `rustbook` for `target` for the doc book `name`. @@ -134,6 +136,7 @@ pub struct UnstableBook<'a> { } impl<'a> Step<'a> for UnstableBook<'a> { + type Id = UnstableBook<'static>; type Output = (); const DEFAULT: bool = true; @@ -172,6 +175,7 @@ pub struct RustbookSrc<'a> { } impl<'a> Step<'a> for RustbookSrc<'a> { + type Id = UnstableBook<'static>; type Output = (); /// Invoke `rustbook` for `target` for the doc book `name` from the `src` path. @@ -220,6 +224,7 @@ pub struct TheBook<'a> { } impl<'a> Step<'a> for TheBook<'a> { + type Id = TheBook<'static>; type Output = (); fn should_run(_builder: &Builder, path: &Path) -> bool { @@ -341,6 +346,7 @@ pub struct Standalone<'a> { } impl<'a> Step<'a> for Standalone<'a> { + type Id = Standalone<'static>; type Output = (); const DEFAULT: bool = true; @@ -448,6 +454,7 @@ pub struct Std<'a> { } impl<'a> Step<'a> for Std<'a> { + type Id = Std<'static>; type Output = (); const DEFAULT: bool = true; @@ -559,6 +566,7 @@ pub struct Test<'a> { } impl<'a> Step<'a> for Test<'a> { + type Id = Test<'static>; type Output = (); const DEFAULT: bool = true; @@ -646,6 +654,7 @@ pub struct Rustc<'a> { } impl<'a> Step<'a> for Rustc<'a> { + type Id = Rustc<'static>; type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -746,6 +755,7 @@ pub struct ErrorIndex<'a> { } impl<'a> Step<'a> for ErrorIndex<'a> { + type Id = ErrorIndex<'static>; type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -808,6 +818,7 @@ pub struct UnstableBookGen<'a> { } impl<'a> Step<'a> for UnstableBookGen<'a> { + type Id = UnstableBookGen<'static>; type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 4ceeb3e6793db..a7d36bfa70c41 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -135,6 +135,7 @@ macro_rules! install { } impl<'a> Step<'a> for $name<'a> { + type Id = $name<'static>; type Output = (); const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index d7f1570ba80a0..68465604db6c9 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -116,7 +116,6 @@ #![deny(warnings)] #![allow(stable_features)] #![feature(associated_consts)] -#![feature(core_intrinsics)] #[macro_use] extern crate build_helper; diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 06af4ceac12e2..d8dc9f7670292 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -51,6 +51,7 @@ pub struct Llvm<'a> { } impl<'a> Step<'a> for Llvm<'a> { + type Id = Llvm<'static>; type Output = (); const ONLY_HOSTS: bool = true; @@ -250,6 +251,7 @@ pub struct TestHelpers<'a> { } impl<'a> Step<'a> for TestHelpers<'a> { + type Id = TestHelpers<'static>; type Output = (); fn should_run(_builder: &Builder, path: &Path) -> bool { @@ -310,6 +312,7 @@ pub struct Openssl<'a> { } impl<'a> Step<'a> for Openssl<'a> { + type Id = Openssl<'static>; type Output = (); fn should_run(_builder: &Builder, _path: &Path) -> bool { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 63404bcf50009..27785506eaeb0 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -52,6 +52,7 @@ pub struct CleanTools<'a> { } impl<'a> Step<'a> for CleanTools<'a> { + type Id = CleanTools<'static>; type Output = (); /// Build a tool in `src/tools` @@ -86,6 +87,7 @@ pub struct ToolBuild<'a> { } impl<'a> Step<'a> for ToolBuild<'a> { + type Id = ToolBuild<'static>; type Output = PathBuf; /// Build a tool in `src/tools` @@ -172,6 +174,7 @@ macro_rules! tool { } impl<'a> Step<'a> for $name<'a> { + type Id = $name<'static>; type Output = PathBuf; fn should_run(_builder: &Builder, path: &Path) -> bool { @@ -258,6 +261,7 @@ pub struct RemoteTestServer<'a> { } impl<'a> Step<'a> for RemoteTestServer<'a> { + type Id = RemoteTestServer<'static>; type Output = PathBuf; fn should_run(_builder: &Builder, path: &Path) -> bool { @@ -302,6 +306,7 @@ pub struct Cargo<'a> { } impl<'a> Step<'a> for Cargo<'a> { + type Id = Cargo<'static>; type Output = PathBuf; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -359,6 +364,7 @@ pub struct Rls<'a> { } impl<'a> Step<'a> for Rls<'a> { + type Id = Rls<'static>; type Output = PathBuf; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; From 528646e1275a90900179b473b204ca3ce19984b5 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 13 Jul 2017 18:48:44 -0600 Subject: [PATCH 25/51] Utilize interning to allow Copy/Clone steps --- src/Cargo.lock | 9 +- src/bootstrap/Cargo.toml | 1 + src/bootstrap/builder.rs | 99 ++++++------ src/bootstrap/cache.rs | 320 +++++++++++++++++++++++++++++++------- src/bootstrap/cc.rs | 15 +- src/bootstrap/check.rs | 234 ++++++++++++++++------------ src/bootstrap/compile.rs | 219 +++++++++++++------------- src/bootstrap/config.rs | 89 +++++------ src/bootstrap/dist.rs | 188 ++++++++++++---------- src/bootstrap/doc.rs | 179 +++++++++++---------- src/bootstrap/flags.rs | 18 ++- src/bootstrap/install.rs | 40 +++-- src/bootstrap/lib.rs | 134 ++++++++-------- src/bootstrap/metadata.rs | 9 +- src/bootstrap/native.rs | 47 +++--- src/bootstrap/sanity.rs | 10 +- src/bootstrap/tool.rs | 107 +++++++------ 17 files changed, 1012 insertions(+), 706 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 35d77eda95110..3f216b0c2f633 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -134,10 +134,11 @@ dependencies = [ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -155,8 +156,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "build-manifest" version = "0.1.0" dependencies = [ - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 00004d71aac25..daa2a3d0a0ff4 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -40,3 +40,4 @@ serde = "1.0.8" serde_derive = "1.0.8" serde_json = "1.0.2" toml = "0.4" +lazy_static = "0.2" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 72736c7611148..f217cd1dd37b2 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -8,20 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use serde::{Serialize, Deserialize}; - +use std::fmt::Debug; +use std::hash::Hash; use std::cell::RefCell; use std::path::{Path, PathBuf}; use std::process::Command; use std::fs; use std::ops::Deref; +use std::any::{TypeId, Any}; use compile; use install; use dist; use util::{exe, libdir, add_lib_path}; use {Build, Mode}; -use cache::{Cache, Key}; +use cache::{INTERNER, Interned, Cache}; use check; use flags::Subcommand; use doc; @@ -34,7 +35,7 @@ pub struct Builder<'a> { pub top_stage: u32, pub kind: Kind, cache: Cache, - stack: RefCell>, + stack: RefCell)>>, } impl<'a> Deref for Builder<'a> { @@ -45,19 +46,10 @@ impl<'a> Deref for Builder<'a> { } } -pub trait Step<'a>: Serialize + Sized { - /// The output type of this step. This is used in a few places to return a +pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { /// `PathBuf` when directories are created or to return a `Compiler` once /// it's been assembled. - /// - /// When possible, this should be used instead of implicitly creating files - /// in a prearranged directory that will later be used by the build system. - /// It's not always practical, however, since it makes avoiding rebuilds - /// somewhat harder. - type Output: Serialize + Deserialize<'a> + 'a; - - /// This type, but with a 'static bound. Used for caching the step. - type Id: 'static; + type Output: Clone; const DEFAULT: bool = false; @@ -72,13 +64,13 @@ pub trait Step<'a>: Serialize + Sized { /// Primary function to execute this rule. Can call `builder.ensure(...)` /// with other steps to run those. - fn run(self, builder: &'a Builder) -> Self::Output; + fn run(self, builder: &Builder) -> Self::Output; /// When bootstrap is passed a set of paths, this controls whether this rule /// will execute. However, it does not get called in a "default" context /// when we are not passed any paths; in that case, make_run is called /// directly. - fn should_run(_builder: &'a Builder, _path: &Path) -> bool { false } + fn should_run(_builder: &Builder, _path: &Path) -> bool { false } /// Build up a "root" rule, either as a default rule or from a path passed /// to us. @@ -87,10 +79,10 @@ pub trait Step<'a>: Serialize + Sized { /// passed. When `./x.py build` is run, for example, this rule could get /// called if it is in the correct list below with a path of `None`. fn make_run( - _builder: &'a Builder, + _builder: &Builder, _path: Option<&Path>, - _host: &'a str, - _target: &'a str, + _host: Interned, + _target: Interned, ) { unimplemented!() } } @@ -176,26 +168,27 @@ impl<'a> Builder<'a> { /// not take `Compiler` since all `Compiler` instances are meant to be /// obtained through this function, since it ensures that they are valid /// (i.e., built and assembled). - pub fn compiler(&'a self, stage: u32, host: &'a str) -> Compiler<'a> { + pub fn compiler(&self, stage: u32, host: Interned) -> Compiler { self.ensure(compile::Assemble { target_compiler: Compiler { stage, host } }) } - pub fn sysroot(&self, compiler: Compiler<'a>) -> PathBuf { + pub fn sysroot(&self, compiler: Compiler) -> Interned { self.ensure(compile::Sysroot { compiler }) } /// Returns the libdir where the standard library and other artifacts are /// found for a compiler's sysroot. - pub fn sysroot_libdir(&self, compiler: Compiler<'a>, target: &'a str) -> PathBuf { - #[derive(Serialize)] - struct Libdir<'a> { - compiler: Compiler<'a>, - target: &'a str, + pub fn sysroot_libdir( + &self, compiler: Compiler, target: Interned + ) -> Interned { + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + struct Libdir { + compiler: Compiler, + target: Interned, } - impl<'a> Step<'a> for Libdir<'a> { - type Id = Libdir<'static>; - type Output = PathBuf; - fn run(self, builder: &Builder) -> PathBuf { + impl Step for Libdir { + type Output = Interned; + fn run(self, builder: &Builder) -> Interned { let compiler = self.compiler; let lib = if compiler.stage >= 2 && builder.build.config.libdir_relative.is_some() { builder.build.config.libdir_relative.clone().unwrap() @@ -206,7 +199,7 @@ impl<'a> Builder<'a> { .join("rustlib").join(self.target).join("lib"); let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot)); - sysroot + INTERNER.intern_path(sysroot) } } self.ensure(Libdir { compiler, target }) @@ -221,7 +214,7 @@ impl<'a> Builder<'a> { if compiler.is_snapshot(self) { self.build.rustc_snapshot_libdir() } else { - self.sysroot(compiler).join(libdir(compiler.host)) + self.sysroot(compiler).join(libdir(&compiler.host)) } } @@ -243,7 +236,7 @@ impl<'a> Builder<'a> { if compiler.is_snapshot(self) { self.initial_rustc.clone() } else { - self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host)) + self.sysroot(compiler).join("bin").join(exe("rustc", &compiler.host)) } } @@ -251,7 +244,7 @@ impl<'a> Builder<'a> { pub fn rustdoc(&self, compiler: Compiler) -> PathBuf { let mut rustdoc = self.rustc(compiler); rustdoc.pop(); - rustdoc.push(exe("rustdoc", compiler.host)); + rustdoc.push(exe("rustdoc", &compiler.host)); rustdoc } @@ -265,7 +258,7 @@ impl<'a> Builder<'a> { pub fn cargo(&self, compiler: Compiler, mode: Mode, - target: &str, + target: Interned, cmd: &str) -> Command { let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); @@ -427,7 +420,7 @@ impl<'a> Builder<'a> { cargo } - fn maybe_run>(&'a self, path: Option<&Path>) { + fn maybe_run(&self, path: Option<&Path>) { let build = self.build; let hosts = if S::ONLY_BUILD_TARGETS || S::ONLY_BUILD { &build.config.host[..1] @@ -459,7 +452,7 @@ impl<'a> Builder<'a> { for host in hosts { for target in targets { - S::make_run(self, path, host, target); + S::make_run(self, path, *host, *target); } } } @@ -467,33 +460,37 @@ impl<'a> Builder<'a> { /// Ensure that a given step is built, returning it's output. This will /// cache the step, so it is safe (and good!) to call this as often as /// needed to ensure that all dependencies are built. - pub fn ensure>(&'a self, step: S) -> S::Output { - let key = Cache::to_key(&step); + pub fn ensure(&'a self, step: S) -> S::Output { + let type_id = TypeId::of::(); { let mut stack = self.stack.borrow_mut(); - if stack.contains(&key) { + for &(stack_type_id, ref stack_step) in stack.iter() { + if !(type_id == stack_type_id && step == *stack_step.downcast_ref().unwrap()) { + continue + } let mut out = String::new(); - out += &format!("\n\nCycle in build detected when adding {:?}\n", key); + out += &format!("\n\nCycle in build detected when adding {:?}\n", step); for el in stack.iter().rev() { out += &format!("\t{:?}\n", el); } panic!(out); } - if let Some(out) = self.cache.get::(&key) { - self.build.verbose(&format!("{}c {:?}", " ".repeat(stack.len()), key)); + if let Some(out) = self.cache.get(&step) { + self.build.verbose(&format!("{}c {:?}", " ".repeat(stack.len()), step)); return out; } - self.build.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), key)); - stack.push(key.clone()); + self.build.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), step)); + stack.push((type_id, Box::new(step.clone()))); } - let out = step.run(self); + let out = step.clone().run(self); { let mut stack = self.stack.borrow_mut(); - assert_eq!(stack.pop().as_ref(), Some(&key)); + let (cur_type_id, cur_step) = stack.pop().expect("step stack empty"); + assert_eq!((cur_type_id, cur_step.downcast_ref()), (type_id, Some(&step))); } - self.build.verbose(&format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), key)); - self.cache.put(key.clone(), &out); - self.cache.get::(&key).unwrap() + self.build.verbose(&format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step)); + self.cache.put(step, out.clone()); + out } } diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index 475e3abfd4097..e2576673338b8 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -8,85 +8,289 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use serde_json; -use serde::{Serialize, Deserialize}; -use std::any::TypeId; -use builder::Step; +use serde::Deserialize; +use serde::de::{self, Deserializer, Visitor}; +use std::any::{Any, TypeId}; +use std::borrow::Borrow; +use std::cell::RefCell; +use std::collections::HashMap; +use std::convert::AsRef; +use std::ffi::OsStr; use std::fmt; +use std::hash::{Hash, Hasher}; +use std::marker::PhantomData; use std::mem; -use std::collections::HashMap; -use std::cell::RefCell; +use std::ops::Deref; +use std::path::{Path, PathBuf}; +use std::sync::Mutex; -/// This is essentially a HashMap which allows storing any type in its input and -/// any type in its output. It is a write-once cache; values are never evicted, -/// which means that references to the value can safely be returned from the -/// get() method. -// -// FIXME: This type does not permit retrieving &Path from a PathBuf, primarily -// due to a lack of any obvious way to ensure that this is safe, but also not -// penalize other cases (e.g., deserializing u32 -> &u32, which is non-optimal). -#[derive(Debug)] -pub struct Cache(RefCell>>); +use builder::Step; -fn to_json(element: &T) -> String { - t!(serde_json::to_string(element)) +pub struct Interned(usize, PhantomData<*const T>); + +impl<'de> Deserialize<'de> for Interned { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + struct StrVisitor; + + impl<'de> Visitor<'de> for StrVisitor { + type Value = &'de str; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a str") + } + + fn visit_borrowed_str(self, value: &'de str) -> Result<&'de str, E> + where E: de::Error + { + Ok(value) + } + } + + Ok(INTERNER.intern_str(deserializer.deserialize_str(StrVisitor)?)) + } +} +impl Default for Interned { + fn default() -> Self { + INTERNER.intern_string(String::default()) + } } -fn from_json<'a, O: Deserialize<'a>>(data: &'a str) -> O { - t!(serde_json::from_str(data)) +impl Default for Interned { + fn default() -> Self { + INTERNER.intern_path(PathBuf::default()) + } } -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct Key(TypeId, String); +impl Copy for Interned {} +impl Clone for Interned { + fn clone(&self) -> Interned { + *self + } +} -impl fmt::Debug for Key { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.write_str(&format!("{:?}; ", self.0))?; - fmt.write_str(&self.1) +impl PartialEq for Interned { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 } } +impl Eq for Interned {} -impl Cache { - pub fn new() -> Cache { - Cache(RefCell::new(HashMap::new())) +impl PartialEq for Interned { + fn eq(&self, other: &str) -> bool { + *self == other + } +} +impl<'a> PartialEq<&'a str> for Interned { + fn eq(&self, other: &&str) -> bool { + **self == **other + } +} +impl<'a, T> PartialEq<&'a Interned> for Interned { + fn eq(&self, other: &&Self) -> bool { + self.0 == other.0 + } +} +impl<'a, T> PartialEq> for &'a Interned { + fn eq(&self, other: &Interned) -> bool { + self.0 == other.0 + } +} + +unsafe impl Send for Interned {} +unsafe impl Sync for Interned {} + +impl fmt::Display for Interned { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s: &str = &*self; + f.write_str(s) + } +} + +impl fmt::Debug for Interned { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s: &str = &*self; + f.write_fmt(format_args!("{:?}", s)) + } +} +impl fmt::Debug for Interned { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s: &Path = &*self; + f.write_fmt(format_args!("{:?}", s)) + } +} + +impl Hash for Interned { + fn hash(&self, state: &mut H) { + let l = INTERNER.strs.lock().unwrap(); + l.get(*self).hash(state) + } +} + +impl Hash for Interned { + fn hash(&self, state: &mut H) { + let l = INTERNER.paths.lock().unwrap(); + l.get(*self).hash(state) + } +} + +impl Deref for Interned { + type Target = str; + fn deref(&self) -> &'static str { + let l = INTERNER.strs.lock().unwrap(); + unsafe { mem::transmute::<&str, &'static str>(l.get(*self)) } + } +} + +impl Deref for Interned { + type Target = Path; + fn deref(&self) -> &'static Path { + let l = INTERNER.paths.lock().unwrap(); + unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self)) } + } +} + +impl AsRef for Interned { + fn as_ref(&self) -> &'static Path { + let l = INTERNER.paths.lock().unwrap(); + unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self)) } + } +} + +impl AsRef for Interned { + fn as_ref(&self) -> &'static Path { + let l = INTERNER.strs.lock().unwrap(); + unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self).as_ref()) } } +} - pub fn to_key<'a, K: Step<'a>>(key: &K) -> Key { - Key(TypeId::of::(), to_json(key)) +impl AsRef for Interned { + fn as_ref(&self) -> &'static OsStr { + let l = INTERNER.paths.lock().unwrap(); + unsafe { mem::transmute::<&OsStr, &'static OsStr>(l.get(*self).as_ref()) } } +} + +impl AsRef for Interned { + fn as_ref(&self) -> &'static OsStr { + let l = INTERNER.strs.lock().unwrap(); + unsafe { mem::transmute::<&OsStr, &'static OsStr>(l.get(*self).as_ref()) } + } +} + - /// Puts a value into the cache. Will panic if called more than once with - /// the same key. - /// - /// Returns the internal key utilized, as an opaque structure, useful only - /// for debugging. - pub fn put(&self, key: Key, value: &V) +struct TyIntern { + items: Vec, + set: HashMap>, +} + +impl TyIntern { + fn new() -> TyIntern { + TyIntern { + items: Vec::new(), + set: HashMap::new(), + } + } + + fn intern_borrow(&mut self, item: &B) -> Interned where - V: Serialize, + B: Eq + Hash + ToOwned + ?Sized, + T: Borrow, { + if let Some(i) = self.set.get(&item) { + return *i; + } + let item = item.to_owned(); + let interned = Interned(self.items.len(), PhantomData::<*const T>); + self.set.insert(item.clone(), interned); + self.items.push(item); + interned + } + + fn intern(&mut self, item: T) -> Interned { + if let Some(i) = self.set.get(&item) { + return *i; + } + let interned = Interned(self.items.len(), PhantomData::<*const T>); + self.set.insert(item.clone(), interned); + self.items.push(item); + interned + } + + fn get(&self, i: Interned) -> &T { + &self.items[i.0] + } +} + +pub struct Interner { + strs: Mutex>, + paths: Mutex>, +} + +impl Interner { + fn new() -> Interner { + Interner { + strs: Mutex::new(TyIntern::new()), + paths: Mutex::new(TyIntern::new()), + } + } + + pub fn intern_str(&self, s: &str) -> Interned { + self.strs.lock().unwrap().intern_borrow(s) + } + pub fn intern_string(&self, s: String) -> Interned { + self.strs.lock().unwrap().intern(s) + } + + pub fn intern_path(&self, s: PathBuf) -> Interned { + self.paths.lock().unwrap().intern(s) + } +} + +lazy_static! { + pub static ref INTERNER: Interner = Interner::new(); +} + +/// This is essentially a HashMap which allows storing any type in its input and +/// any type in its output. It is a write-once cache; values are never evicted, +/// which means that references to the value can safely be returned from the +/// get() method. +// +// FIXME: This type does not permit retrieving &Path from a PathBuf, primarily +// due to a lack of any obvious way to ensure that this is safe, but also not +#[derive(Debug)] +pub struct Cache( + RefCell, // actually a HashMap> + >> +); + +impl Cache { + pub fn new() -> Cache { + Cache(RefCell::new(HashMap::new())) + } + + pub fn put(&self, step: S, value: S::Output) { let mut cache = self.0.borrow_mut(); - let value = to_json(value); - assert!(!cache.contains_key(&key), "processing {:?} a second time", key); - // Store a boxed str so that it's location in memory never changes and - // it's safe for us to return references to it (so long as they live as - // long as us). - cache.insert(key, value.into_boxed_str()); + let type_id = TypeId::of::(); + let stepcache = cache.entry(type_id) + .or_insert_with(|| Box::new(HashMap::::new())) + .downcast_mut::>() + .expect("invalid type mapped"); + assert!(!stepcache.contains_key(&step), "processing {:?} a second time", step); + stepcache.insert(step, value); } - pub fn get<'a, V>(&'a self, key: &Key) -> Option - where - V: Deserialize<'a> + 'a, - { - let cache = self.0.borrow(); - cache.get(key).map(|v| { - // Change the lifetime. This borrow is valid for as long as self lives; - // the data we're accessing will live as long as us and will be in a - // stable location, since we use Box. - let v = unsafe { - mem::transmute::<&str, &'a str>(v) - }; - from_json(v) - }) + pub fn get(&self, step: &S) -> Option { + let mut cache = self.0.borrow_mut(); + let type_id = TypeId::of::(); + let stepcache = cache.entry(type_id) + .or_insert_with(|| Box::new(HashMap::::new())) + .downcast_mut::>() + .expect("invalid type mapped"); + stepcache.get(step).cloned() } } diff --git a/src/bootstrap/cc.rs b/src/bootstrap/cc.rs index 7c7161916ee2c..739904e4f7c58 100644 --- a/src/bootstrap/cc.rs +++ b/src/bootstrap/cc.rs @@ -38,6 +38,7 @@ use gcc; use Build; use config::Target; +use cache::Interned; pub fn find(build: &mut Build) { // For all targets we're going to need a C compiler for building some shims @@ -50,11 +51,11 @@ pub fn find(build: &mut Build) { cfg.cargo_metadata(false).opt_level(0).debug(false) .target(target).host(&build.build); - let config = build.config.target_config.get(target); + let config = build.config.target_config.get(&target); if let Some(cc) = config.and_then(|c| c.cc.as_ref()) { cfg.compiler(cc); } else { - set_compiler(&mut cfg, "gcc", target, config, build); + set_compiler(&mut cfg, "gcc", *target, config, build); } let compiler = cfg.get_compiler(); @@ -63,7 +64,7 @@ pub fn find(build: &mut Build) { if let Some(ref ar) = ar { build.verbose(&format!("AR_{} = {:?}", target, ar)); } - build.cc.insert(target.to_string(), (compiler, ar)); + build.cc.insert(*target, (compiler, ar)); } // For all host triples we need to find a C++ compiler as well @@ -78,20 +79,20 @@ pub fn find(build: &mut Build) { if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) { cfg.compiler(cxx); } else { - set_compiler(&mut cfg, "g++", host, config, build); + set_compiler(&mut cfg, "g++", *host, config, build); } let compiler = cfg.get_compiler(); build.verbose(&format!("CXX_{} = {:?}", host, compiler.path())); - build.cxx.insert(host.to_string(), compiler); + build.cxx.insert(*host, compiler); } } fn set_compiler(cfg: &mut gcc::Config, gnu_compiler: &str, - target: &str, + target: Interned, config: Option<&Target>, build: &Build) { - match target { + match &*target { // When compiling for android we may have the NDK configured in the // config.toml in which case we look there. Otherwise the default // compiler already takes into account the triple in question. diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 8adfed44f0187..d983e54ac0851 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -33,11 +33,12 @@ use compile; use native; use builder::{Kind, Builder, Compiler, Step}; use tool::{self, Tool}; +use cache::{INTERNER, Interned}; const ADB_TEST_DIR: &str = "/data/tmp/work"; /// The two modes of the test runner; tests or benchmarks. -#[derive(Serialize, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] pub enum TestKind { /// Run `cargo test` Test, @@ -93,13 +94,12 @@ fn try_run_quiet(build: &Build, cmd: &mut Command) { // .host(true) // .run(move |s| check::linkcheck(build, s.target)); -#[derive(Serialize)] -pub struct Linkcheck<'a> { - host: &'a str, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Linkcheck { + host: Interned, } -impl<'a> Step<'a> for Linkcheck<'a> { - type Id = Linkcheck<'static>; +impl Step for Linkcheck { type Output = (); const ONLY_HOSTS: bool = true; const DEFAULT: bool = true; @@ -125,7 +125,12 @@ impl<'a> Step<'a> for Linkcheck<'a> { path.ends_with("src/tools/linkchecker") } - fn make_run(builder: &Builder, path: Option<&Path>, host: &str, _target: &str) { + fn make_run( + builder: &Builder, + path: Option<&Path>, + host: Interned, + _target: Interned, + ) { if path.is_some() { builder.ensure(Linkcheck { host }); } else { @@ -142,14 +147,13 @@ impl<'a> Step<'a> for Linkcheck<'a> { // .host(true) // .run(move |s| check::cargotest(build, s.stage, s.target)); -#[derive(Serialize)] -pub struct Cargotest<'a> { +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Cargotest { stage: u32, - host: &'a str, + host: Interned, } -impl<'a> Step<'a> for Cargotest<'a> { - type Id = Cargotest<'static>; +impl Step for Cargotest { type Output = (); const ONLY_HOSTS: bool = true; @@ -157,7 +161,12 @@ impl<'a> Step<'a> for Cargotest<'a> { path.ends_with("src/tools/cargotest") } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { + fn make_run( + builder: &Builder, + _path: Option<&Path>, + host: Interned, + _target: Interned, + ) { builder.ensure(Cargotest { stage: builder.top_stage, host: host, @@ -193,14 +202,13 @@ impl<'a> Step<'a> for Cargotest<'a> { // .host(true) // .run(move |s| check::cargo(build, s.stage, s.target)); -#[derive(Serialize)] -pub struct Cargo<'a> { +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Cargo { stage: u32, - host: &'a str, + host: Interned, } -impl<'a> Step<'a> for Cargo<'a> { - type Id = Cargo<'static>; +impl Step for Cargo { type Output = (); const ONLY_HOSTS: bool = true; @@ -208,7 +216,12 @@ impl<'a> Step<'a> for Cargo<'a> { path.ends_with("src/tools/cargo") } - fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, + _path: Option<&Path>, + _host: Interned, + target: Interned, + ) { builder.ensure(Cargotest { stage: builder.top_stage, host: target, @@ -304,13 +317,12 @@ fn path_for_cargo(build: &Build, compiler: &Compiler) -> OsString { // .only_build(true) // .run(move |s| check::tidy(build, s.target)); -#[derive(Serialize)] -pub struct Tidy<'a> { - host: &'a str, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Tidy { + host: Interned, } -impl<'a> Step<'a> for Tidy<'a> { - type Id = Tidy<'static>; +impl Step for Tidy { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -342,14 +354,19 @@ impl<'a> Step<'a> for Tidy<'a> { path.ends_with("src/tools/tidy") } - fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, _target: &str) { + fn make_run( + builder: &Builder, + _path: Option<&Path>, + _host: Interned, + _target: Interned, + ) { builder.ensure(Tidy { - host: &builder.build.build, + host: builder.build.build, }); } } -fn testdir(build: &Build, host: &str) -> PathBuf { +fn testdir(build: &Build, host: Interned) -> PathBuf { build.out.join(host).join("test") } @@ -451,15 +468,15 @@ fn testdir(build: &Build, host: &str) -> PathBuf { // "pretty", "run-fail-fulldeps"); // } -#[derive(Serialize)] -pub struct Compiletest<'a> { - compiler: Compiler<'a>, - target: &'a str, - mode: &'a str, - suite: &'a str, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Compiletest { + compiler: Compiler, + target: Interned, + mode: &'static str, + suite: &'static str, } -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] struct Test { path: &'static str, mode: &'static str, @@ -512,8 +529,7 @@ static COMPILETESTS: &[Test] = &[ Test { path: "src/test/debuginfo-gdb", mode: "debuginfo-gdb", suite: "debuginfo" }, ]; -impl<'a> Step<'a> for Compiletest<'a> { - type Id = Compiletest<'static>; +impl Step for Compiletest { type Output = (); const DEFAULT: bool = true; @@ -526,7 +542,12 @@ impl<'a> Step<'a> for Compiletest<'a> { }) } - fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { + fn make_run( + builder: &Builder, + path: Option<&Path>, + host: Interned, + target: Interned, + ) { let compiler = builder.compiler(builder.top_stage, host); let test = path.map(|path| { @@ -591,12 +612,12 @@ impl<'a> Step<'a> for Compiletest<'a> { builder.ensure(Compiletest { mode: "debuginfo-lldb", ..self - }) + }); } else { builder.ensure(Compiletest { mode: "debuginfo-gdb", ..self - }) + }); }; } @@ -606,7 +627,7 @@ impl<'a> Step<'a> for Compiletest<'a> { } builder.ensure(dist::DebuggerScripts { - sysroot: &builder.sysroot(compiler), + sysroot: builder.sysroot(compiler), target: target }); @@ -630,7 +651,7 @@ impl<'a> Step<'a> for Compiletest<'a> { let _folder = build.fold_output(|| format!("test_{}", suite)); println!("Check compiletest suite={} mode={} ({} -> {})", - suite, mode, compiler.host, target); + suite, mode, &compiler.host, target); let mut cmd = builder.tool_cmd(Tool::Compiletest); // compiletest currently has... a lot of arguments, so let's just pass all @@ -645,8 +666,8 @@ impl<'a> Step<'a> for Compiletest<'a> { cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target)); cmd.arg("--mode").arg(mode); cmd.arg("--target").arg(target); - cmd.arg("--host").arg(compiler.host); - cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.build)); + cmd.arg("--host").arg(&*compiler.host); + cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(build.build)); if let Some(ref nodejs) = build.config.nodejs { cmd.arg("--nodejs").arg(nodejs); @@ -664,7 +685,7 @@ impl<'a> Step<'a> for Compiletest<'a> { hostflags.extend(flags.clone()); cmd.arg("--host-rustcflags").arg(hostflags.join(" ")); - let mut targetflags = build.rustc_flags(&target); + let mut targetflags = build.rustc_flags(target); targetflags.extend(flags); targetflags.push(format!("-Lnative={}", build.test_helpers_out(target).display())); @@ -735,7 +756,7 @@ impl<'a> Step<'a> for Compiletest<'a> { // Note that if we encounter `PATH` we make sure to append to our own `PATH` // rather than stomp over it. if target.contains("msvc") { - for &(ref k, ref v) in build.cc[target].0.env() { + for &(ref k, ref v) in build.cc[&target].0.env() { if k != "PATH" { cmd.env(k, v); } @@ -769,9 +790,9 @@ impl<'a> Step<'a> for Compiletest<'a> { } } -#[derive(Serialize)] -pub struct Docs<'a> { - compiler: Compiler<'a>, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Docs { + compiler: Compiler, } // rules.test("check-docs", "src/doc") @@ -779,8 +800,7 @@ pub struct Docs<'a> { // .default(true) // .host(true) // .run(move |s| check::docs(build, &s.compiler())); -impl<'a> Step<'a> for Docs<'a> { - type Id = Docs<'static>; +impl Step for Docs { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -789,7 +809,12 @@ impl<'a> Step<'a> for Docs<'a> { path.ends_with("src/doc") } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { + fn make_run( + builder: &Builder, + _path: Option<&Path>, + host: Interned, + _target: Interned, + ) { builder.ensure(Docs { compiler: builder.compiler(builder.top_stage, host), }); @@ -840,13 +865,12 @@ impl<'a> Step<'a> for Docs<'a> { // .host(true) // .run(move |s| check::error_index(build, &s.compiler())); -#[derive(Serialize)] -pub struct ErrorIndex<'a> { - compiler: Compiler<'a>, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct ErrorIndex { + compiler: Compiler, } -impl<'a> Step<'a> for ErrorIndex<'a> { - type Id = ErrorIndex<'static>; +impl Step for ErrorIndex { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -855,7 +879,12 @@ impl<'a> Step<'a> for ErrorIndex<'a> { path.ends_with("src/tools/error_index_generator") } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { + fn make_run( + builder: &Builder, + _path: Option<&Path>, + host: Interned, + _target: Interned, + ) { builder.ensure(ErrorIndex { compiler: builder.compiler(builder.top_stage, host), }); @@ -933,16 +962,15 @@ fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) { // .host(true) // .run(move |s| check::krate(build, &s.compiler(), s.target, // Mode::Librustc, TestKind::Test, None)); -#[derive(Serialize)] -pub struct KrateLibrustc<'a> { - compiler: Compiler<'a>, - target: &'a str, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct KrateLibrustc { + compiler: Compiler, + target: Interned, test_kind: TestKind, - krate: Option<&'a str>, + krate: Option>, } -impl<'a> Step<'a> for KrateLibrustc<'a> { - type Id = KrateLibrustc<'static>; +impl Step for KrateLibrustc { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -953,10 +981,15 @@ impl<'a> Step<'a> for KrateLibrustc<'a> { }) } - fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { + fn make_run( + builder: &Builder, + path: Option<&Path>, + host: Interned, + target: Interned, + ) { let compiler = builder.compiler(builder.top_stage, host); - let run = |name: Option<&str>| { + let run = |name: Option>| { let test_kind = if builder.kind == Kind::Test { TestKind::Test } else if builder.kind == Kind::Bench { @@ -1043,17 +1076,16 @@ impl<'a> Step<'a> for KrateLibrustc<'a> { // .run(move |s| check::krate(build, &s.compiler(), s.target, // Mode::Libtest, TestKind::Test, None)); -#[derive(Serialize)] -pub struct Krate<'a> { - compiler: Compiler<'a>, - target: &'a str, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Krate { + compiler: Compiler, + target: Interned, mode: Mode, test_kind: TestKind, - krate: Option<&'a str>, + krate: Option>, } -impl<'a> Step<'a> for Krate<'a> { - type Id = Krate<'static>; +impl Step for Krate { type Output = (); const DEFAULT: bool = true; @@ -1066,10 +1098,15 @@ impl<'a> Step<'a> for Krate<'a> { }) } - fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { + fn make_run( + builder: &Builder, + path: Option<&Path>, + host: Interned, + target: Interned, + ) { let compiler = builder.compiler(builder.top_stage, host); - let run = |mode: Mode, name: Option<&str>| { + let run = |mode: Mode, name: Option>| { let test_kind = if builder.kind == Kind::Test { TestKind::Test } else if builder.kind == Kind::Bench { @@ -1134,11 +1171,12 @@ impl<'a> Step<'a> for Krate<'a> { } _ => panic!("can only test libraries"), }; + let root = INTERNER.intern_string(String::from(root)); let _folder = build.fold_output(|| { format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, name) }); println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage, - compiler.host, target); + &compiler.host, target); // If we're not doing a full bootstrap but we're testing a stage2 version of // libstd, then what we're actually testing is the libstd produced in @@ -1180,12 +1218,12 @@ impl<'a> Step<'a> for Krate<'a> { // target during the bootstrap and it's just meant to be a // helper crate, not tested. If it leaks through then it ends up // messing with various mtime calculations and such. - if !name.contains("jemalloc") && name != "build_helper" { + if !name.contains("jemalloc") && *name != *"build_helper" { cargo.arg("-p").arg(&format!("{}:0.0.0", name)); } - for dep in build.crates[name].deps.iter() { + for dep in build.crates[&name].deps.iter() { if visited.insert(dep) { - next.push(dep); + next.push(*dep); } } } @@ -1198,7 +1236,7 @@ impl<'a> Step<'a> for Krate<'a> { // Note that to run the compiler we need to run with the *host* libraries, // but our wrapper scripts arrange for that to be the case anyway. let mut dylib_path = dylib_path(); - dylib_path.insert(0, builder.sysroot_libdir(compiler, target)); + dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target))); cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); if target.contains("emscripten") || build.remote_tested(target) { @@ -1228,7 +1266,7 @@ impl<'a> Step<'a> for Krate<'a> { fn krate_emscripten(build: &Build, compiler: Compiler, - target: &str, + target: Interned, mode: Mode) { let out_dir = build.cargo_out(compiler, mode, target); let tests = find_tests(&out_dir.join("deps"), target); @@ -1247,7 +1285,7 @@ fn krate_emscripten(build: &Build, fn krate_remote(builder: &Builder, compiler: Compiler, - target: &str, + target: Interned, mode: Mode) { let build = builder.build; let out_dir = build.cargo_out(compiler, mode, target); @@ -1266,7 +1304,7 @@ fn krate_remote(builder: &Builder, } } -fn find_tests(dir: &Path, target: &str) -> Vec { +fn find_tests(dir: &Path, target: Interned) -> Vec { let mut dst = Vec::new(); for e in t!(dir.read_dir()).map(|e| t!(e)) { let file_type = t!(e.file_type()); @@ -1313,14 +1351,13 @@ fn find_tests(dir: &Path, target: &str) -> Vec { /// QEMU we have to build our own tools so we've got conditional dependencies /// on those programs as well. Note that the remote test client is built for /// the build target (us) and the server is built for the target. -#[derive(Serialize)] -pub struct RemoteCopyLibs<'a> { - compiler: Compiler<'a>, - target: &'a str, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct RemoteCopyLibs { + compiler: Compiler, + target: Interned, } -impl<'a> Step<'a> for RemoteCopyLibs<'a> { - type Id = RemoteCopyLibs<'static>; +impl Step for RemoteCopyLibs { type Output = (); fn run(self, builder: &Builder) { @@ -1368,18 +1405,17 @@ impl<'a> Step<'a> for RemoteCopyLibs<'a> { // .dep(|s| s.name("dist-src")) // .run(move |_| check::distcheck(build)); -#[derive(Serialize)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Distcheck; -impl<'a> Step<'a> for Distcheck { - type Id = Distcheck; +impl Step for Distcheck { type Output = (); /// Run "distcheck", a 'make check' from a tarball fn run(self, builder: &Builder) { let build = builder.build; - if build.build != "x86_64-unknown-linux-gnu" { + if *build.build != *"x86_64-unknown-linux-gnu" { return } if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") { @@ -1436,11 +1472,10 @@ impl<'a> Step<'a> for Distcheck { // .only_build(true) // .run(move |_| check::bootstrap(build)); -#[derive(Serialize)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Bootstrap; -impl<'a> Step<'a> for Bootstrap { - type Id = Bootstrap; +impl Step for Bootstrap { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -1466,7 +1501,12 @@ impl<'a> Step<'a> for Bootstrap { path.ends_with("src/bootstrap") } - fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, _target: &str) { + fn make_run( + builder: &Builder, + _path: Option<&Path>, + _host: Interned, + _target: Interned, + ) { builder.ensure(Bootstrap); } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index ec08bb9db2b98..558ced12cfea6 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -32,6 +32,7 @@ use util::{exe, libdir, is_dylib, copy}; use {Build, Compiler, Mode}; use native; +use cache::{INTERNER, Interned}; use builder::{Step, Builder}; // @@ -140,14 +141,13 @@ use builder::{Step, Builder}; // .dep(move |s| s.name("rustc").host(&build.build).target(s.host)) // .run(move |s| compile::std(build, s.target, &s.compiler())); // } -#[derive(Serialize)] -pub struct Std<'a> { - pub target: &'a str, - pub compiler: Compiler<'a>, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Std { + pub target: Interned, + pub compiler: Compiler, } -impl<'a> Step<'a> for Std<'a> { - type Id = Std<'static>; +impl Step for Std { type Output = (); const DEFAULT: bool = true; @@ -158,11 +158,16 @@ impl<'a> Step<'a> for Std<'a> { }) } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + fn make_run( + builder: &Builder, + _path: Option<&Path>, + host: Interned, + target: Interned, + ) { builder.ensure(Std { compiler: builder.compiler(builder.top_stage, host), target, - }) + }); } /// Build the standard library. @@ -178,7 +183,7 @@ impl<'a> Step<'a> for Std<'a> { builder.ensure(StartupObjects { compiler, target }); if build.force_use_stage1(compiler, target) { - let from = builder.compiler(1, &build.build); + let from = builder.compiler(1, build.build); builder.ensure(Std { compiler: from, target: target, @@ -194,7 +199,7 @@ impl<'a> Step<'a> for Std<'a> { let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); println!("Building stage{} std artifacts ({} -> {})", compiler.stage, - compiler.host, target); + &compiler.host, target); let out_dir = build.cargo_out(compiler, Mode::Libstd, target); build.clear_if_dirty(&out_dir, &builder.rustc(compiler)); @@ -229,7 +234,7 @@ impl<'a> Step<'a> for Std<'a> { .arg("--manifest-path") .arg(build.src.join("src/libstd/Cargo.toml")); - if let Some(target) = build.config.target_config.get(target) { + if let Some(target) = build.config.target_config.get(&target) { if let Some(ref jemalloc) = target.jemalloc { cargo.env("JEMALLOC_OVERRIDE", jemalloc); } @@ -245,7 +250,7 @@ impl<'a> Step<'a> for Std<'a> { &libstd_stamp(build, compiler, target)); builder.ensure(StdLink { - compiler: builder.compiler(compiler.stage, &build.build), + compiler: builder.compiler(compiler.stage, build.build), target_compiler: compiler, target: target, }); @@ -261,15 +266,14 @@ impl<'a> Step<'a> for Std<'a> { // .dep(|s| s.name("startup-objects")) // .dep(|s| s.name("create-sysroot").target(s.host)); -#[derive(Serialize)] -struct StdLink<'a> { - pub compiler: Compiler<'a>, - pub target_compiler: Compiler<'a>, - pub target: &'a str, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +struct StdLink { + pub compiler: Compiler, + pub target_compiler: Compiler, + pub target: Interned, } -impl<'a> Step<'a> for StdLink<'a> { - type Id = StdLink<'static>; +impl Step for StdLink { type Output = (); /// Link all libstd rlibs/dylibs into the sysroot location. @@ -288,7 +292,7 @@ impl<'a> Step<'a> for StdLink<'a> { println!("Copying stage{} std from stage{} ({} -> {} / {})", target_compiler.stage, compiler.stage, - compiler.host, + &compiler.host, target_compiler.host, target); let libdir = builder.sysroot_libdir(target_compiler, target); @@ -310,7 +314,7 @@ impl<'a> Step<'a> for StdLink<'a> { /// Copies the crt(1,i,n).o startup objects /// /// Only required for musl targets that statically link to libc -fn copy_musl_third_party_objects(build: &Build, target: &str, into: &Path) { +fn copy_musl_third_party_objects(build: &Build, target: Interned, into: &Path) { for &obj in &["crt1.o", "crti.o", "crtn.o"] { copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj)); } @@ -332,25 +336,29 @@ fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) { // .dep(|s| s.name("create-sysroot").target(s.host)) // .run(move |s| compile::build_startup_objects(build, &s.compiler(), s.target)); -#[derive(Serialize)] -pub struct StartupObjects<'a> { - pub compiler: Compiler<'a>, - pub target: &'a str, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct StartupObjects { + pub compiler: Compiler, + pub target: Interned, } -impl<'a> Step<'a> for StartupObjects<'a> { - type Id = StartupObjects<'static>; +impl Step for StartupObjects { type Output = (); fn should_run(_builder: &Builder, path: &Path) -> bool { path.ends_with("src/rtstartup") } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + fn make_run( + builder: &Builder, + _path: Option<&Path>, + host: Interned, + target: Interned, + ) { builder.ensure(StartupObjects { compiler: builder.compiler(builder.top_stage, host), target, - }) + }); } /// Build and prepare startup objects like rsbegin.o and rsend.o @@ -399,14 +407,13 @@ impl<'a> Step<'a> for StartupObjects<'a> { // .dep(|s| s.name("libstd-link")) // .run(move |s| compile::test(build, s.target, &s.compiler())); // } -#[derive(Serialize)] -pub struct Test<'a> { - pub compiler: Compiler<'a>, - pub target: &'a str, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Test { + pub compiler: Compiler, + pub target: Interned, } -impl<'a> Step<'a> for Test<'a> { - type Id = Test<'static>; +impl Step for Test { type Output = (); const DEFAULT: bool = true; @@ -417,11 +424,16 @@ impl<'a> Step<'a> for Test<'a> { }) } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + fn make_run( + builder: &Builder, + _path: Option<&Path>, + host: Interned, + target: Interned, + ) { builder.ensure(Test { compiler: builder.compiler(builder.top_stage, host), target, - }) + }); } /// Build libtest. @@ -438,12 +450,12 @@ impl<'a> Step<'a> for Test<'a> { if build.force_use_stage1(compiler, target) { builder.ensure(Test { - compiler: builder.compiler(1, &build.build), + compiler: builder.compiler(1, build.build), target: target, }); println!("Uplifting stage1 test ({} -> {})", &build.build, target); builder.ensure(TestLink { - compiler: builder.compiler(1, &build.build), + compiler: builder.compiler(1, build.build), target_compiler: compiler, target: target, }); @@ -452,7 +464,7 @@ impl<'a> Step<'a> for Test<'a> { let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); println!("Building stage{} test artifacts ({} -> {})", compiler.stage, - compiler.host, target); + &compiler.host, target); let out_dir = build.cargo_out(compiler, Mode::Libtest, target); build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "build"); @@ -466,7 +478,7 @@ impl<'a> Step<'a> for Test<'a> { &libtest_stamp(build, compiler, target)); builder.ensure(TestLink { - compiler: builder.compiler(compiler.stage, &build.build), + compiler: builder.compiler(compiler.stage, build.build), target_compiler: compiler, target: target, }); @@ -481,15 +493,14 @@ impl<'a> Step<'a> for Test<'a> { // compile::test_link) // .dep(|s| s.name("libstd-link")); -#[derive(Serialize)] -pub struct TestLink<'a> { - pub compiler: Compiler<'a>, - pub target_compiler: Compiler<'a>, - pub target: &'a str, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct TestLink { + pub compiler: Compiler, + pub target_compiler: Compiler, + pub target: Interned, } -impl<'a> Step<'a> for TestLink<'a> { - type Id = TestLink<'static>; +impl Step for TestLink { type Output = (); /// Same as `std_link`, only for libtest @@ -501,7 +512,7 @@ impl<'a> Step<'a> for TestLink<'a> { println!("Copying stage{} test from stage{} ({} -> {} / {})", target_compiler.stage, compiler.stage, - compiler.host, + &compiler.host, target_compiler.host, target); add_to_sysroot(&builder.sysroot_libdir(target_compiler, target), @@ -517,14 +528,13 @@ impl<'a> Step<'a> for TestLink<'a> { // .run(move |s| compile::rustc(build, s.target, &s.compiler())); // } -#[derive(Serialize)] -pub struct Rustc<'a> { - pub compiler: Compiler<'a>, - pub target: &'a str, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Rustc { + pub compiler: Compiler, + pub target: Interned, } -impl<'a> Step<'a> for Rustc<'a> { - type Id = Rustc<'static>; +impl Step for Rustc { type Output = (); const ONLY_HOSTS: bool = true; const DEFAULT: bool = true; @@ -536,11 +546,16 @@ impl<'a> Step<'a> for Rustc<'a> { }) } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + fn make_run( + builder: &Builder, + _path: Option<&Path>, + host: Interned, + target: Interned, + ) { builder.ensure(Rustc { compiler: builder.compiler(builder.top_stage, host), target, - }) + }); } /// Build the compiler. @@ -561,12 +576,12 @@ impl<'a> Step<'a> for Rustc<'a> { if build.force_use_stage1(compiler, target) { builder.ensure(Rustc { - compiler: builder.compiler(1, &build.build), + compiler: builder.compiler(1, build.build), target: target, }); println!("Uplifting stage1 rustc ({} -> {})", &build.build, target); builder.ensure(RustcLink { - compiler: builder.compiler(1, &build.build), + compiler: builder.compiler(1, build.build), target_compiler: compiler, target, }); @@ -575,13 +590,13 @@ impl<'a> Step<'a> for Rustc<'a> { // Ensure that build scripts have a std to link against. builder.ensure(Std { - compiler: builder.compiler(self.compiler.stage, &build.build), - target: &build.build, + compiler: builder.compiler(self.compiler.stage, build.build), + target: build.build, }); let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); println!("Building stage{} compiler artifacts ({} -> {})", - compiler.stage, compiler.host, target); + compiler.stage, &compiler.host, target); let out_dir = build.cargo_out(compiler, Mode::Librustc, target); build.clear_if_dirty(&out_dir, &libtest_stamp(build, compiler, target)); @@ -627,7 +642,7 @@ impl<'a> Step<'a> for Rustc<'a> { cargo.env("LLVM_RUSTLLVM", "1"); } cargo.env("LLVM_CONFIG", build.llvm_config(target)); - let target_config = build.config.target_config.get(target); + let target_config = build.config.target_config.get(&target); if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { cargo.env("CFG_LLVM_ROOT", s); } @@ -653,7 +668,7 @@ impl<'a> Step<'a> for Rustc<'a> { &librustc_stamp(build, compiler, target)); builder.ensure(RustcLink { - compiler: builder.compiler(compiler.stage, &build.build), + compiler: builder.compiler(compiler.stage, build.build), target_compiler: compiler, target, }); @@ -666,15 +681,14 @@ impl<'a> Step<'a> for Rustc<'a> { // "build-crate-rustc-main", // compile::rustc_link) // .dep(|s| s.name("libtest-link")); -#[derive(Serialize)] -struct RustcLink<'a> { - pub compiler: Compiler<'a>, - pub target_compiler: Compiler<'a>, - pub target: &'a str, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +struct RustcLink { + pub compiler: Compiler, + pub target_compiler: Compiler, + pub target: Interned, } -impl<'a> Step<'a> for RustcLink<'a> { - type Id = RustcLink<'static>; +impl Step for RustcLink { type Output = (); /// Same as `std_link`, only for librustc @@ -686,7 +700,7 @@ impl<'a> Step<'a> for RustcLink<'a> { println!("Copying stage{} rustc from stage{} ({} -> {} / {})", target_compiler.stage, compiler.stage, - compiler.host, + &compiler.host, target_compiler.host, target); add_to_sysroot(&builder.sysroot_libdir(target_compiler, target), @@ -696,19 +710,19 @@ impl<'a> Step<'a> for RustcLink<'a> { /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. -pub fn libstd_stamp(build: &Build, compiler: Compiler, target: &str) -> PathBuf { +pub fn libstd_stamp(build: &Build, compiler: Compiler, target: Interned) -> PathBuf { build.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp") } /// Cargo's output path for libtest in a given stage, compiled by a particular /// compiler for the specified target. -pub fn libtest_stamp(build: &Build, compiler: Compiler, target: &str) -> PathBuf { +pub fn libtest_stamp(build: &Build, compiler: Compiler, target: Interned) -> PathBuf { build.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp") } /// Cargo's output path for librustc in a given stage, compiled by a particular /// compiler for the specified target. -pub fn librustc_stamp(build: &Build, compiler: Compiler, target: &str) -> PathBuf { +pub fn librustc_stamp(build: &Build, compiler: Compiler, target: Interned) -> PathBuf { build.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp") } @@ -721,14 +735,13 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf { // rules.build("create-sysroot", "path/to/nowhere") // .run(move |s| compile::create_sysroot(build, &s.compiler())); -#[derive(Serialize)] -pub struct Sysroot<'a> { - pub compiler: Compiler<'a>, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Sysroot { + pub compiler: Compiler, } -impl<'a> Step<'a> for Sysroot<'a> { - type Id = Sysroot<'static>; - type Output = PathBuf; +impl Step for Sysroot { + type Output = Interned; /// Returns the sysroot for the `compiler` specified that *this build system /// generates*. @@ -736,17 +749,17 @@ impl<'a> Step<'a> for Sysroot<'a> { /// That is, the sysroot for the stage0 compiler is not what the compiler /// thinks it is by default, but it's the same as the default for stages /// 1-3. - fn run(self, builder: &Builder) -> PathBuf { + fn run(self, builder: &Builder) -> Interned { let build = builder.build; let compiler = self.compiler; let sysroot = if compiler.stage == 0 { - build.out.join(compiler.host).join("stage0-sysroot") + build.out.join(&compiler.host).join("stage0-sysroot") } else { - build.out.join(compiler.host).join(format!("stage{}", compiler.stage)) + build.out.join(&compiler.host).join(format!("stage{}", compiler.stage)) }; let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot)); - sysroot + INTERNER.intern_path(sysroot) } } @@ -764,25 +777,24 @@ impl<'a> Step<'a> for Sysroot<'a> { // }) // .run(move |s| compile::assemble_rustc(build, s.stage, s.target)); -#[derive(Serialize)] -pub struct Assemble<'a> { +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Assemble { /// The compiler which we will produce in this step. Assemble itself will /// take care of ensuring that the necessary prerequisites to do so exist, /// that is, this target can be a stage2 compiler and Assemble will build /// previous stages for you. - pub target_compiler: Compiler<'a>, + pub target_compiler: Compiler, } -impl<'a> Step<'a> for Assemble<'a> { - type Id = Assemble<'static>; - type Output = Compiler<'a>; +impl Step for Assemble { + type Output = Compiler; /// Prepare a new compiler from the artifacts in `stage` /// /// This will assemble a compiler in `build/$host/stage$stage`. The compiler /// must have been previously produced by the `stage - 1` build.build /// compiler. - fn run(self, builder: &Builder) -> Compiler<'a> { + fn run(self, builder: &Builder) -> Compiler { let build = builder.build; let target_compiler = self.target_compiler; @@ -799,21 +811,14 @@ impl<'a> Step<'a> for Assemble<'a> { // compiler for the host platform for this because it doesn't have // the libraries we need. FIXME: Perhaps we should download those // libraries? It would make builds faster... - builder.ensure(Assemble { - target_compiler: Compiler { - // FIXME: It may be faster if we build just a stage 1 - // compiler and then use that to bootstrap this compiler - // forward. - stage: target_compiler.stage - 1, - host: &build.build - }, - }) + // FIXME: It may be faster if we build just a stage 1 + // compiler and then use that to bootstrap this compiler + // forward. + builder.compiler(target_compiler.stage - 1, build.build) } else { // Build the compiler we'll use to build the stage requested. This // may build more than one compiler (going down to stage 0). - builder.ensure(Assemble { - target_compiler: target_compiler.with_stage(target_compiler.stage - 1), - }) + builder.compiler(target_compiler.stage - 1, target_compiler.host) }; // Build the libraries for this compiler to link to (i.e., the libraries @@ -829,7 +834,7 @@ impl<'a> Step<'a> for Assemble<'a> { // Link in all dylibs to the libdir let sysroot = builder.sysroot(target_compiler); - let sysroot_libdir = sysroot.join(libdir(host)); + let sysroot_libdir = sysroot.join(libdir(&*host)); t!(fs::create_dir_all(&sysroot_libdir)); let src_libdir = builder.sysroot_libdir(build_compiler, host); for f in t!(fs::read_dir(&src_libdir)).map(|f| t!(f)) { @@ -842,7 +847,7 @@ impl<'a> Step<'a> for Assemble<'a> { let out_dir = build.cargo_out(build_compiler, Mode::Librustc, host); // Link the compiler binary itself into place - let rustc = out_dir.join(exe("rustc", host)); + let rustc = out_dir.join(exe("rustc", &*host)); let bindir = sysroot.join("bin"); t!(fs::create_dir_all(&bindir)); let compiler = builder.rustc(target_compiler); @@ -850,7 +855,7 @@ impl<'a> Step<'a> for Assemble<'a> { copy(&rustc, &compiler); // See if rustdoc exists to link it into place - let rustdoc = exe("rustdoc", host); + let rustdoc = exe("rustdoc", &*host); let rustdoc_src = out_dir.join(&rustdoc); let rustdoc_dst = bindir.join(&rustdoc); if fs::metadata(&rustdoc_src).is_ok() { diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 810a9924765d8..abb0408c4d247 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -23,6 +23,7 @@ use std::process; use num_cpus; use toml; use util::{exe, push_exe_path}; +use cache::{INTERNER, Interned}; /// Global configuration for the entire build and/or bootstrap. /// @@ -45,7 +46,7 @@ pub struct Config { pub docs: bool, pub locked_deps: bool, pub vendor: bool, - pub target_config: HashMap, + pub target_config: HashMap, Target>, pub full_bootstrap: bool, pub extended: bool, pub sanitizers: bool, @@ -77,9 +78,9 @@ pub struct Config { pub rust_debuginfo_tests: bool, pub rust_dist_src: bool, - pub build: String, - pub host: Vec, - pub target: Vec, + pub build: Interned, + pub host: Vec>, + pub target: Vec>, pub local_rebuild: bool, // dist misc @@ -282,7 +283,7 @@ impl Config { config.docs = true; config.rust_rpath = true; config.rust_codegen_units = 1; - config.build = build.to_string(); + config.build = INTERNER.intern_str(build); config.channel = "dev".to_string(); config.codegen_tests = true; config.rust_dist_src = true; @@ -302,16 +303,19 @@ impl Config { }).unwrap_or_else(|| TomlConfig::default()); let build = toml.build.clone().unwrap_or(Build::default()); - set(&mut config.build, build.build.clone()); + set(&mut config.build, build.build.clone().map(|x| INTERNER.intern_string(x))); config.host.push(config.build.clone()); for host in build.host.iter() { - if !config.host.contains(host) { - config.host.push(host.clone()); + let host = INTERNER.intern_str(host); + if !config.host.contains(&host) { + config.host.push(host); } } - for target in config.host.iter().chain(&build.target) { - if !config.target.contains(target) { - config.target.push(target.clone()); + for target in config.host.iter().cloned() + .chain(build.target.iter().map(|s| INTERNER.intern_str(s))) + { + if !config.target.contains(&target) { + config.target.push(target); } } config.nodejs = build.nodejs.map(PathBuf::from); @@ -404,7 +408,7 @@ impl Config { target.musl_root = cfg.musl_root.clone().map(PathBuf::from); target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from); - config.target_config.insert(triple.clone(), target); + config.target_config.insert(INTERNER.intern_string(triple.clone()), target); } } @@ -506,13 +510,13 @@ impl Config { } match key { - "CFG_BUILD" if value.len() > 0 => self.build = value.to_string(), + "CFG_BUILD" if value.len() > 0 => self.build = INTERNER.intern_str(value), "CFG_HOST" if value.len() > 0 => { - self.host.extend(value.split(" ").map(|s| s.to_string())); + self.host.extend(value.split(" ").map(|s| INTERNER.intern_str(s))); } "CFG_TARGET" if value.len() > 0 => { - self.target.extend(value.split(" ").map(|s| s.to_string())); + self.target.extend(value.split(" ").map(|s| INTERNER.intern_str(s))); } "CFG_EXPERIMENTAL_TARGETS" if value.len() > 0 => { self.llvm_experimental_targets = Some(value.to_string()); @@ -521,33 +525,28 @@ impl Config { self.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_X86_64" if value.len() > 0 => { - let target = "x86_64-unknown-linux-musl".to_string(); - let target = self.target_config.entry(target) - .or_insert(Target::default()); + let target = INTERNER.intern_str("x86_64-unknown-linux-musl"); + let target = self.target_config.entry(target).or_insert(Target::default()); target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_I686" if value.len() > 0 => { - let target = "i686-unknown-linux-musl".to_string(); - let target = self.target_config.entry(target) - .or_insert(Target::default()); + let target = INTERNER.intern_str("i686-unknown-linux-musl"); + let target = self.target_config.entry(target).or_insert(Target::default()); target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_ARM" if value.len() > 0 => { - let target = "arm-unknown-linux-musleabi".to_string(); - let target = self.target_config.entry(target) - .or_insert(Target::default()); + let target = INTERNER.intern_str("arm-unknown-linux-musleabi"); + let target = self.target_config.entry(target).or_insert(Target::default()); target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_ARMHF" if value.len() > 0 => { - let target = "arm-unknown-linux-musleabihf".to_string(); - let target = self.target_config.entry(target) - .or_insert(Target::default()); + let target = INTERNER.intern_str("arm-unknown-linux-musleabihf"); + let target = self.target_config.entry(target).or_insert(Target::default()); target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_ARMV7" if value.len() > 0 => { - let target = "armv7-unknown-linux-musleabihf".to_string(); - let target = self.target_config.entry(target) - .or_insert(Target::default()); + let target = INTERNER.intern_str("armv7-unknown-linux-musleabihf"); + let target = self.target_config.entry(target).or_insert(Target::default()); target.musl_root = Some(parse_configure_path(value)); } "CFG_DEFAULT_AR" if value.len() > 0 => { @@ -595,33 +594,28 @@ impl Config { target.jemalloc = Some(parse_configure_path(value).join("libjemalloc_pic.a")); } "CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { - let target = "arm-linux-androideabi".to_string(); - let target = self.target_config.entry(target) - .or_insert(Target::default()); + let target = INTERNER.intern_str("arm-linux-androideabi"); + let target = self.target_config.entry(target).or_insert(Target::default()); target.ndk = Some(parse_configure_path(value)); } "CFG_ARMV7_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { - let target = "armv7-linux-androideabi".to_string(); - let target = self.target_config.entry(target) - .or_insert(Target::default()); + let target = INTERNER.intern_str("armv7-linux-androideabi"); + let target = self.target_config.entry(target).or_insert(Target::default()); target.ndk = Some(parse_configure_path(value)); } "CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => { - let target = "i686-linux-android".to_string(); - let target = self.target_config.entry(target) - .or_insert(Target::default()); + let target = INTERNER.intern_str("i686-linux-android"); + let target = self.target_config.entry(target).or_insert(Target::default()); target.ndk = Some(parse_configure_path(value)); } "CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => { - let target = "aarch64-linux-android".to_string(); - let target = self.target_config.entry(target) - .or_insert(Target::default()); + let target = INTERNER.intern_str("aarch64-linux-android"); + let target = self.target_config.entry(target).or_insert(Target::default()); target.ndk = Some(parse_configure_path(value)); } "CFG_X86_64_LINUX_ANDROID_NDK" if value.len() > 0 => { - let target = "x86_64-linux-android".to_string(); - let target = self.target_config.entry(target) - .or_insert(Target::default()); + let target = INTERNER.intern_str("x86_64-linux-android"); + let target = self.target_config.entry(target).or_insert(Target::default()); target.ndk = Some(parse_configure_path(value)); } "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { @@ -645,9 +639,8 @@ impl Config { .collect(); } "CFG_QEMU_ARMHF_ROOTFS" if value.len() > 0 => { - let target = "arm-unknown-linux-gnueabihf".to_string(); - let target = self.target_config.entry(target) - .or_insert(Target::default()); + let target = INTERNER.intern_str("arm-unknown-linux-gnueabihf"); + let target = self.target_config.entry(target).or_insert(Target::default()); target.qemu_rootfs = Some(parse_configure_path(value)); } _ => {} diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index f19536e2f490b..e9a2fc7fc1a92 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -40,6 +40,7 @@ use util::{cp_r, libdir, is_dylib, cp_filtered, copy, exe}; use builder::{Builder, Step}; use compile; use tool::{self, Tool}; +use cache::{INTERNER, Interned}; pub fn pkgname(build: &Build, component: &str) -> String { if component == "cargo" { @@ -71,14 +72,13 @@ fn rust_installer(builder: &Builder) -> Command { // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::docs(build, s.stage, s.target)); -#[derive(Serialize)] -pub struct Docs<'a> { +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Docs { pub stage: u32, - pub target: &'a str, + pub target: Interned, } -impl<'a> Step<'a> for Docs<'a> { - type Id = Docs<'static>; +impl Step for Docs { type Output = Option; const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -87,7 +87,9 @@ impl<'a> Step<'a> for Docs<'a> { path.ends_with("src/doc") } - fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, _path: Option<&Path>, _host: Interned, target: Interned, + ) { builder.ensure(Docs { stage: builder.top_stage, target: target, @@ -165,7 +167,9 @@ fn find_files(files: &[&str], path: &[PathBuf]) -> Vec { found } -fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: &Build) { +fn make_win_dist( + rust_root: &Path, plat_root: &Path, target_triple: Interned, build: &Build +) { //Ask gcc where it keeps its stuff let mut cmd = Command::new(build.cc(target_triple)); cmd.arg("-print-search-dirs"); @@ -282,13 +286,12 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: // } // }); -#[derive(Serialize)] -pub struct Mingw<'a> { - target: &'a str, +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Mingw { + target: Interned, } -impl<'a> Step<'a> for Mingw<'a> { - type Id = Mingw<'static>; +impl Step for Mingw { type Output = Option; const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -297,7 +300,9 @@ impl<'a> Step<'a> for Mingw<'a> { false } - fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, _path: Option<&Path>, _host: Interned, target: Interned + ) { builder.ensure(Mingw { target }); } @@ -350,14 +355,13 @@ impl<'a> Step<'a> for Mingw<'a> { // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::rustc(build, s.stage, s.target)); -#[derive(Serialize)] -pub struct Rustc<'a> { +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Rustc { pub stage: u32, - pub target: &'a str, + pub target: Interned, } -impl<'a> Step<'a> for Rustc<'a> { - type Id = Rustc<'static>; +impl Step for Rustc { type Output = PathBuf; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -367,7 +371,9 @@ impl<'a> Step<'a> for Rustc<'a> { path.ends_with("src/librustc") } - fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, _path: Option<&Path>, _host: Interned, target: Interned + ) { builder.ensure(Rustc { stage: builder.top_stage, target: target, @@ -381,7 +387,7 @@ impl<'a> Step<'a> for Rustc<'a> { let target = self.target; let compiler = builder.ensure(compile::Assemble { - target_compiler: builder.compiler(stage, &build.build), + target_compiler: builder.compiler(stage, build.build), }); println!("Dist rustc stage{} ({})", stage, target); @@ -444,10 +450,12 @@ impl<'a> Step<'a> for Rustc<'a> { return distdir(build).join(format!("{}-{}.tar.gz", name, target)); - fn prepare_image(builder: &Builder, compiler: Compiler, target: &str, image: &Path) { + fn prepare_image( + builder: &Builder, compiler: Compiler, target: Interned, image: &Path + ) { let build = builder.build; let src = builder.sysroot(compiler); - let libdir = libdir(target); + let libdir = libdir(&target); // Copy rustc/rustdoc binaries t!(fs::create_dir_all(image.join("bin"))); @@ -471,7 +479,7 @@ impl<'a> Step<'a> for Rustc<'a> { // Debugger scripts builder.ensure(DebuggerScripts { - sysroot: &image, + sysroot: INTERNER.intern_path(image.to_owned()), target: target, }); @@ -491,23 +499,24 @@ impl<'a> Step<'a> for Rustc<'a> { // .run(move |s| dist::debugger_scripts(build, &builder.sysroot(&s.compiler()), // s.target)); -#[derive(Serialize)] -pub struct DebuggerScripts<'a> { - pub sysroot: &'a Path, - pub target: &'a str, +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct DebuggerScripts { + pub sysroot: Interned, + pub target: Interned, } -impl<'a> Step<'a> for DebuggerScripts<'a> { - type Id = DebuggerScripts<'static>; +impl Step for DebuggerScripts { type Output = (); fn should_run(_builder: &Builder, path: &Path) -> bool { path.ends_with("src/etc/lldb_batchmode.py") } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + fn make_run( + builder: &Builder, _path: Option<&Path>, host: Interned, target: Interned + ) { builder.ensure(DebuggerScripts { - sysroot: &builder.sysroot(builder.compiler(builder.top_stage, host)), + sysroot: builder.sysroot(builder.compiler(builder.top_stage, host)), target: target, }); } @@ -564,14 +573,13 @@ impl<'a> Step<'a> for DebuggerScripts<'a> { // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::std(build, &s.compiler(), s.target)); -#[derive(Serialize)] -pub struct Std<'a> { - pub compiler: Compiler<'a>, - pub target: &'a str, +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Std { + pub compiler: Compiler, + pub target: Interned, } -impl<'a> Step<'a> for Std<'a> { - type Id = Std<'static>; +impl Step for Std { type Output = Option; const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -580,7 +588,9 @@ impl<'a> Step<'a> for Std<'a> { path.ends_with("src/libstd") } - fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { + fn make_run( + builder: &Builder, _path: Option<&Path>, host: Interned, target: Interned + ) { builder.ensure(Std { compiler: builder.compiler(builder.top_stage, host), target: target, @@ -592,7 +602,7 @@ impl<'a> Step<'a> for Std<'a> { let compiler = self.compiler; let target = self.target; - println!("Dist std stage{} ({} -> {})", compiler.stage, compiler.host, + println!("Dist std stage{} ({} -> {})", compiler.stage, &compiler.host, target); // The only true set of target libraries came from the build triple, so @@ -617,7 +627,7 @@ impl<'a> Step<'a> for Std<'a> { let dst = image.join("lib/rustlib").join(target); t!(fs::create_dir_all(&dst)); - let mut src = builder.sysroot_libdir(compiler, target); + let mut src = builder.sysroot_libdir(compiler, target).to_path_buf(); src.pop(); // Remove the trailing /lib folder from the sysroot_libdir cp_r(&src, &dst); @@ -645,14 +655,13 @@ impl<'a> Step<'a> for Std<'a> { // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::analysis(build, &s.compiler(), s.target)); -#[derive(Serialize)] -pub struct Analysis<'a> { - pub compiler: Compiler<'a>, - pub target: &'a str, +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Analysis { + pub compiler: Compiler, + pub target: Interned, } -impl<'a> Step<'a> for Analysis<'a> { - type Id = Analysis<'static>; +impl Step for Analysis { type Output = Option; const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -661,7 +670,12 @@ impl<'a> Step<'a> for Analysis<'a> { path.ends_with("analysis") } - fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { + fn make_run( + builder: &Builder, + path: Option<&Path>, + host: Interned, + target: Interned + ) { if path.is_none() && !builder.build.config.extended { return; } @@ -679,7 +693,7 @@ impl<'a> Step<'a> for Analysis<'a> { assert!(build.config.extended); println!("Dist analysis"); - if compiler.host != build.build { + if &compiler.host != build.build { println!("\tskipping, not a build host"); return None; } @@ -769,11 +783,10 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di // .dep(move |s| tool_rust_installer(build, s)) // .run(move |_| dist::rust_src(build)); -#[derive(Serialize)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Src; -impl<'a> Step<'a> for Src { - type Id = Src; +impl Step for Src { /// The output path of the src installer tarball type Output = PathBuf; const DEFAULT: bool = true; @@ -785,7 +798,9 @@ impl<'a> Step<'a> for Src { path.ends_with("src") } - fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, _target: &str) { + fn make_run( + builder: &Builder, _path: Option<&Path>, _host: Interned, _target: Interned + ) { builder.ensure(Src); } @@ -867,11 +882,10 @@ const CARGO_VENDOR_VERSION: &str = "0.1.4"; // .dep(move |s| tool_rust_installer(build, s)) // .run(move |_| dist::plain_source_tarball(build)); -#[derive(Serialize)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct PlainSourceTarball; -impl<'a> Step<'a> for PlainSourceTarball { - type Id = PlainSourceTarball; +impl Step for PlainSourceTarball { /// Produces the location of the tarball generated type Output = PathBuf; const DEFAULT: bool = true; @@ -883,7 +897,9 @@ impl<'a> Step<'a> for PlainSourceTarball { path.ends_with("src") } - fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, _target: &str) { + fn make_run( + builder: &Builder, path: Option<&Path>, _host: Interned, _target: Interned + ) { if path.is_none() && !builder.build.config.rust_dist_src { return; } @@ -1019,14 +1035,13 @@ fn write_file(path: &Path, data: &[u8]) { // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::cargo(build, s.stage, s.target)); -#[derive(Serialize)] -pub struct Cargo<'a> { +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Cargo { pub stage: u32, - pub target: &'a str, + pub target: Interned, } -impl<'a> Step<'a> for Cargo<'a> { - type Id = Cargo<'static>; +impl Step for Cargo { type Output = PathBuf; const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; @@ -1035,7 +1050,9 @@ impl<'a> Step<'a> for Cargo<'a> { path.ends_with("cargo") } - fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, _path: Option<&Path>, _host: Interned, target: Interned + ) { builder.ensure(Cargo { stage: builder.top_stage, target: target, @@ -1050,7 +1067,7 @@ impl<'a> Step<'a> for Cargo<'a> { builder.ensure(tool::Cargo { stage, target }); println!("Dist cargo stage{} ({})", stage, target); - let compiler = builder.compiler(stage, &build.build); + let compiler = builder.compiler(stage, build.build); let src = build.src.join("src/tools/cargo"); let etc = src.join("src/etc"); @@ -1067,7 +1084,7 @@ impl<'a> Step<'a> for Cargo<'a> { t!(fs::create_dir_all(image.join("share/zsh/site-functions"))); t!(fs::create_dir_all(image.join("etc/bash_completion.d"))); let cargo = build.cargo_out(compiler, Mode::Tool, target) - .join(exe("cargo", target)); + .join(exe("cargo", &target)); install(&cargo, &image.join("bin"), 0o755); for man in t!(etc.join("man").read_dir()) { let man = t!(man); @@ -1116,14 +1133,13 @@ impl<'a> Step<'a> for Cargo<'a> { // .dep(|s| s.name("tool-rls")) // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::rls(build, s.stage, s.target)); -#[derive(Serialize)] -pub struct Rls<'a> { +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Rls { pub stage: u32, - pub target: &'a str, + pub target: Interned, } -impl<'a> Step<'a> for Rls<'a> { - type Id = Rls<'static>; +impl Step for Rls { type Output = PathBuf; const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; @@ -1132,7 +1148,9 @@ impl<'a> Step<'a> for Rls<'a> { path.ends_with("rls") } - fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, _path: Option<&Path>, _host: Interned, target: Interned + ) { builder.ensure(Rls { stage: builder.top_stage, target: target, @@ -1148,7 +1166,7 @@ impl<'a> Step<'a> for Rls<'a> { builder.ensure(tool::Rls { stage, target }); println!("Dist RLS stage{} ({})", stage, target); - let compiler = builder.compiler(stage, &build.build); + let compiler = builder.compiler(stage, build.build); let src = build.src.join("src/tools/rls"); let release_num = build.release_num("rls"); @@ -1162,7 +1180,7 @@ impl<'a> Step<'a> for Rls<'a> { // Prepare the image directory let rls = build.cargo_out(compiler, Mode::Tool, target) - .join(exe("rls", target)); + .join(exe("rls", &target)); install(&rls, &image.join("bin"), 0o755); let doc = image.join("share/doc/rls"); install(&src.join("README.md"), &doc, 0o644); @@ -1210,14 +1228,13 @@ impl<'a> Step<'a> for Rls<'a> { // .dep(move |s| tool_rust_installer(build, s)) // .run(move |s| dist::extended(build, s.stage, s.target)); -#[derive(Serialize)] -pub struct Extended<'a> { +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Extended { stage: u32, - target: &'a str, + target: Interned, } -impl<'a> Step<'a> for Extended<'a> { - type Id = Extended<'static>; +impl Step for Extended { type Output = (); const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -1227,7 +1244,9 @@ impl<'a> Step<'a> for Extended<'a> { path.ends_with("cargo") } - fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned + ) { if path.is_none() && !builder.build.config.extended { return; } @@ -1242,7 +1261,7 @@ impl<'a> Step<'a> for Extended<'a> { let build = builder.build; let stage = self.stage; let target = self.target; - let compiler = builder.compiler(stage, &build.build); + let compiler = builder.compiler(stage, build.build); println!("Dist extended stage{} ({})", stage, target); @@ -1583,7 +1602,7 @@ impl<'a> Step<'a> for Extended<'a> { } } -fn add_env(build: &Build, cmd: &mut Command, target: &str) { +fn add_env(build: &Build, cmd: &mut Command, target: Interned) { let mut parts = channel::CFG_RELEASE_NUM.split('.'); cmd.env("CFG_RELEASE_INFO", build.rust_version()) .env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM) @@ -1620,11 +1639,10 @@ fn add_env(build: &Build, cmd: &mut Command, target: &str) { // .dep(move |s| s.name("tool-build-manifest").target(&build.build).stage(0)) // .run(move |_| dist::hash_and_sign(build)); -#[derive(Serialize)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct HashSign; -impl<'a> Step<'a> for HashSign { - type Id = HashSign; +impl Step for HashSign { type Output = (); const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; @@ -1634,7 +1652,9 @@ impl<'a> Step<'a> for HashSign { path.ends_with("hash-and-sign") } - fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, _target: &str) { + fn make_run( + builder: &Builder, _path: Option<&Path>, _host: Interned, _target: Interned + ) { builder.ensure(HashSign); } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 56715d284a6cd..3c3f4bf2be73f 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -20,27 +20,27 @@ use std::fs::{self, File}; use std::io::prelude::*; use std::io; -use std::path::Path; +use std::path::{PathBuf, Path}; use std::process::Command; use Mode; -use util::{cp_r, symlink_dir}; use build_helper::up_to_date; +use util::{cp_r, symlink_dir}; use builder::{Builder, Step}; use tool::Tool; use compile; +use cache::{INTERNER, Interned}; macro_rules! book { ($($name:ident, $path:expr, $book_name:expr;)+) => { $( - #[derive(Serialize)] - pub struct $name<'a> { - target: &'a str, + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub struct $name { + target: Interned, } - impl<'a> Step<'a> for $name<'a> { - type Id = $name<'static>; + impl Step for $name { type Output = (); const DEFAULT: bool = true; @@ -48,7 +48,12 @@ macro_rules! book { path.ends_with($path) } - fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, + path: Option<&Path>, + _host: Interned, + target: Interned + ) { if path.is_none() && !builder.build.config.docs { // Not a default rule if docs are disabled. return; @@ -62,7 +67,7 @@ macro_rules! book { fn run(self, builder: &Builder) { builder.ensure(Rustbook { target: self.target, - name: $book_name, + name: INTERNER.intern_str($book_name), }) } } @@ -93,14 +98,13 @@ book!( Reference, "src/doc/reference", "reference"; ); -#[derive(Serialize)] -pub struct Rustbook<'a> { - target: &'a str, - name: &'a str, +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Rustbook { + target: Interned, + name: Interned, } -impl<'a> Step<'a> for Rustbook<'a> { - type Id = Rustbook<'static>; +impl Step for Rustbook { type Output = (); /// Invoke `rustbook` for `target` for the doc book `name`. @@ -112,7 +116,7 @@ impl<'a> Step<'a> for Rustbook<'a> { builder.ensure(RustbookSrc { target: self.target, name: self.name, - src: &src, + src: INTERNER.intern_path(src), }); } } @@ -130,13 +134,12 @@ impl<'a> Step<'a> for Rustbook<'a> { // s.target, // "unstable-book", // &build.md_doc_out(s.target))); -#[derive(Serialize)] -pub struct UnstableBook<'a> { - target: &'a str, +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct UnstableBook { + target: Interned, } -impl<'a> Step<'a> for UnstableBook<'a> { - type Id = UnstableBook<'static>; +impl Step for UnstableBook { type Output = (); const DEFAULT: bool = true; @@ -144,7 +147,9 @@ impl<'a> Step<'a> for UnstableBook<'a> { path.ends_with("src/doc/unstable-book") } - fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned + ) { if path.is_none() && !builder.build.config.docs { // Not a default rule if docs are disabled. return; @@ -161,21 +166,20 @@ impl<'a> Step<'a> for UnstableBook<'a> { }); builder.ensure(RustbookSrc { target: self.target, - name: "unstable-book", - src: &builder.build.md_doc_out(self.target), + name: INTERNER.intern_str("unstable-book"), + src: builder.build.md_doc_out(self.target), }) } } -#[derive(Serialize)] -pub struct RustbookSrc<'a> { - target: &'a str, - name: &'a str, - src: &'a Path, +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct RustbookSrc { + target: Interned, + name: Interned, + src: Interned, } -impl<'a> Step<'a> for RustbookSrc<'a> { - type Id = UnstableBook<'static>; +impl Step for RustbookSrc { type Output = (); /// Invoke `rustbook` for `target` for the doc book `name` from the `src` path. @@ -217,21 +221,22 @@ impl<'a> Step<'a> for RustbookSrc<'a> { // .default(build.config.docs) // .run(move |s| doc::book(build, s.target, "book")); -#[derive(Serialize)] -pub struct TheBook<'a> { - target: &'a str, - name: &'a str, +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct TheBook { + target: Interned, + name: &'static str, } -impl<'a> Step<'a> for TheBook<'a> { - type Id = TheBook<'static>; +impl Step for TheBook { type Output = (); fn should_run(_builder: &Builder, path: &Path) -> bool { path.ends_with("src/doc/book") } - fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned + ) { if path.is_none() && !builder.build.config.docs { // Not a default rule if docs are disabled. return; @@ -258,13 +263,13 @@ impl<'a> Step<'a> for TheBook<'a> { // build book first edition builder.ensure(Rustbook { target: target, - name: &format!("{}/first-edition", name), + name: INTERNER.intern_string(format!("{}/first-edition", name)), }); // build book second edition builder.ensure(Rustbook { target: target, - name: &format!("{}/second-edition", name), + name: INTERNER.intern_string(format!("{}/second-edition", name)), }); // build the index page @@ -284,11 +289,11 @@ impl<'a> Step<'a> for TheBook<'a> { } } -fn invoke_rustdoc(builder: &Builder, target: &str, markdown: &str) { +fn invoke_rustdoc(builder: &Builder, target: Interned, markdown: &str) { let build = builder.build; let out = build.doc_out(target); - let compiler = builder.compiler(0, &build.build); + let compiler = builder.compiler(0, build.build); let path = build.src.join("src/doc").join(markdown); @@ -340,13 +345,12 @@ fn invoke_rustdoc(builder: &Builder, target: &str, markdown: &str) { // .default(build.config.docs) // .run(move |s| doc::standalone(build, s.target)); -#[derive(Serialize)] -pub struct Standalone<'a> { - target: &'a str, +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Standalone { + target: Interned, } -impl<'a> Step<'a> for Standalone<'a> { - type Id = Standalone<'static>; +impl Step for Standalone { type Output = (); const DEFAULT: bool = true; @@ -354,7 +358,9 @@ impl<'a> Step<'a> for Standalone<'a> { path.ends_with("src/doc") } - fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned + ) { if path.is_none() && !builder.build.config.docs { // Not a default rule if docs are disabled. return; @@ -380,7 +386,7 @@ impl<'a> Step<'a> for Standalone<'a> { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = builder.compiler(0, &build.build); + let compiler = builder.compiler(0, build.build); let favicon = build.src.join("src/doc/favicon.inc"); let footer = build.src.join("src/doc/footer.inc"); @@ -447,14 +453,13 @@ impl<'a> Step<'a> for Standalone<'a> { // .run(move |s| doc::std(build, s.stage, s.target)); // } -#[derive(Serialize)] -pub struct Std<'a> { +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Std { stage: u32, - target: &'a str, + target: Interned, } -impl<'a> Step<'a> for Std<'a> { - type Id = Std<'static>; +impl Step for Std { type Output = (); const DEFAULT: bool = true; @@ -464,7 +469,9 @@ impl<'a> Step<'a> for Std<'a> { }) } - fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned + ) { let run = || { builder.ensure(Std { stage: builder.top_stage, @@ -496,7 +503,7 @@ impl<'a> Step<'a> for Std<'a> { println!("Documenting stage{} std ({})", stage, target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = builder.compiler(stage, &build.build); + let compiler = builder.compiler(stage, build.build); let compiler = if build.force_use_stage1(compiler, target) { builder.compiler(1, compiler.host) } else { @@ -559,14 +566,13 @@ impl<'a> Step<'a> for Std<'a> { // .run(move |s| doc::test(build, s.stage, s.target)); // } -#[derive(Serialize)] -pub struct Test<'a> { +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Test { stage: u32, - target: &'a str, + target: Interned, } -impl<'a> Step<'a> for Test<'a> { - type Id = Test<'static>; +impl Step for Test { type Output = (); const DEFAULT: bool = true; @@ -576,7 +582,9 @@ impl<'a> Step<'a> for Test<'a> { }) } - fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned + ) { let run = || { builder.ensure(Test { stage: builder.top_stage, @@ -608,7 +616,7 @@ impl<'a> Step<'a> for Test<'a> { println!("Documenting stage{} test ({})", stage, target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = builder.compiler(stage, &build.build); + let compiler = builder.compiler(stage, build.build); let compiler = if build.force_use_stage1(compiler, target) { builder.compiler(1, compiler.host) } else { @@ -647,14 +655,13 @@ impl<'a> Step<'a> for Test<'a> { // } // -#[derive(Serialize)] -pub struct Rustc<'a> { +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Rustc { stage: u32, - target: &'a str, + target: Interned, } -impl<'a> Step<'a> for Rustc<'a> { - type Id = Rustc<'static>; +impl Step for Rustc { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -665,7 +672,9 @@ impl<'a> Step<'a> for Rustc<'a> { }) } - fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned + ) { let run = || { builder.ensure(Rustc { stage: builder.top_stage, @@ -697,7 +706,7 @@ impl<'a> Step<'a> for Rustc<'a> { println!("Documenting stage{} compiler ({})", stage, target); let out = build.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = builder.compiler(stage, &build.build); + let compiler = builder.compiler(stage, build.build); let compiler = if build.force_use_stage1(compiler, target) { builder.compiler(1, compiler.host) } else { @@ -749,13 +758,12 @@ impl<'a> Step<'a> for Rustc<'a> { // .host(true) // .run(move |s| doc::error_index(build, s.target)); -#[derive(Serialize)] -pub struct ErrorIndex<'a> { - target: &'a str, +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct ErrorIndex { + target: Interned, } -impl<'a> Step<'a> for ErrorIndex<'a> { - type Id = ErrorIndex<'static>; +impl Step for ErrorIndex { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -764,7 +772,9 @@ impl<'a> Step<'a> for ErrorIndex<'a> { path.ends_with("src/tools/error_index_generator") } - fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned + ) { if path.is_none() && !builder.build.config.docs { // Not a default rule if docs are disabled. return; @@ -782,7 +792,7 @@ impl<'a> Step<'a> for ErrorIndex<'a> { let target = self.target; builder.ensure(compile::Rustc { - compiler: builder.compiler(0, &build.build), + compiler: builder.compiler(0, build.build), target, }); @@ -812,13 +822,12 @@ impl<'a> Step<'a> for ErrorIndex<'a> { // .host(true) // .run(move |s| doc::unstable_book_gen(build, s.target)); -#[derive(Serialize)] -pub struct UnstableBookGen<'a> { - target: &'a str, +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct UnstableBookGen { + target: Interned, } -impl<'a> Step<'a> for UnstableBookGen<'a> { - type Id = UnstableBookGen<'static>; +impl Step for UnstableBookGen { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -827,7 +836,9 @@ impl<'a> Step<'a> for UnstableBookGen<'a> { path.ends_with("src/doc/unstable-book") } - fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned, + ) { if path.is_none() && !builder.build.config.docs { // Not a default rule if docs are disabled. return; @@ -843,7 +854,7 @@ impl<'a> Step<'a> for UnstableBookGen<'a> { let target = self.target; builder.ensure(compile::Std { - compiler: builder.compiler(builder.top_stage, &build.build), + compiler: builder.compiler(builder.top_stage, build.build), target, }); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 30bc8cdef4ad2..b1ea441795e77 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -24,15 +24,17 @@ use Build; use config::Config; use metadata; +use cache::{Interned, INTERNER}; + /// Deserialized version of all flags for this compile. pub struct Flags { pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose pub on_fail: Option, pub stage: Option, pub keep_stage: Option, - pub build: String, - pub host: Vec, - pub target: Vec, + pub build: Interned, + pub host: Vec>, + pub target: Vec>, pub config: Option, pub src: PathBuf, pub jobs: Option, @@ -320,11 +322,13 @@ Arguments: stage: stage, on_fail: matches.opt_str("on-fail"), keep_stage: matches.opt_str("keep-stage").map(|j| j.parse().unwrap()), - build: matches.opt_str("build").unwrap_or_else(|| { + build: INTERNER.intern_string(matches.opt_str("build").unwrap_or_else(|| { env::var("BUILD").unwrap() - }), - host: split(matches.opt_strs("host")), - target: split(matches.opt_strs("target")), + })), + host: split(matches.opt_strs("host")) + .into_iter().map(|x| INTERNER.intern_string(x)).collect::>(), + target: split(matches.opt_strs("target")) + .into_iter().map(|x| INTERNER.intern_string(x)).collect::>(), config: cfg_file, src: src, jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()), diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index a7d36bfa70c41..6b6160f43caf3 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -21,37 +21,44 @@ use std::process::Command; use dist::{self, pkgname, sanitize_sh, tmpdir}; use builder::{Builder, Step}; +use cache::Interned; -pub fn install_docs(builder: &Builder, stage: u32, host: &str) { +pub fn install_docs(builder: &Builder, stage: u32, host: Interned) { install_sh(builder, "docs", "rust-docs", stage, Some(host)); } pub fn install_std(builder: &Builder, stage: u32) { for target in builder.build.config.target.iter() { - install_sh(builder, "std", "rust-std", stage, Some(target)); + install_sh(builder, "std", "rust-std", stage, Some(*target)); } } -pub fn install_cargo(builder: &Builder, stage: u32, host: &str) { +pub fn install_cargo(builder: &Builder, stage: u32, host: Interned) { install_sh(builder, "cargo", "cargo", stage, Some(host)); } -pub fn install_rls(builder: &Builder, stage: u32, host: &str) { +pub fn install_rls(builder: &Builder, stage: u32, host: Interned) { install_sh(builder, "rls", "rls", stage, Some(host)); } -pub fn install_analysis(builder: &Builder, stage: u32, host: &str) { +pub fn install_analysis(builder: &Builder, stage: u32, host: Interned) { install_sh(builder, "analysis", "rust-analysis", stage, Some(host)); } pub fn install_src(builder: &Builder, stage: u32) { install_sh(builder, "src", "rust-src", stage, None); } -pub fn install_rustc(builder: &Builder, stage: u32, host: &str) { +pub fn install_rustc(builder: &Builder, stage: u32, host: Interned) { install_sh(builder, "rustc", "rustc", stage, Some(host)); } -fn install_sh(builder: &Builder, package: &str, name: &str, stage: u32, host: Option<&str>) { +fn install_sh( + builder: &Builder, + package: &str, + name: &str, + stage: u32, + host: Option> +) { let build = builder.build; println!("Install {} stage{} ({:?})", package, stage, host); @@ -127,15 +134,15 @@ macro_rules! install { $default_cond:expr, only_hosts: $only_hosts:expr, $run_item:block $(, $c:ident)*;)+) => { - $(#[derive(Serialize)] - pub struct $name<'a> { + $( + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub struct $name { pub stage: u32, - pub target: &'a str, - pub host: &'a str, + pub target: Interned, + pub host: Interned, } - impl<'a> Step<'a> for $name<'a> { - type Id = $name<'static>; + impl Step for $name { type Output = (); const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; @@ -146,7 +153,12 @@ macro_rules! install { path.ends_with($path) } - fn make_run($builder: &Builder, path: Option<&Path>, host: &str, target: &str) { + fn make_run( + $builder: &Builder, + path: Option<&Path>, + host: Interned, + target: Interned, + ) { if path.is_none() && !($default_cond) { return; } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 68465604db6c9..472aea783f2d1 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -121,6 +121,8 @@ extern crate build_helper; #[macro_use] extern crate serde_derive; +#[macro_use] +extern crate lazy_static; extern crate serde; extern crate serde_json; extern crate cmake; @@ -186,16 +188,17 @@ mod job { pub use config::Config; pub use flags::{Flags, Subcommand}; +use cache::{Interned, INTERNER}; /// A structure representing a Rust compiler. /// /// Each compiler has a `stage` that it is associated with and a `host` that /// corresponds to the platform the compiler runs on. This structure is used as /// a parameter to many methods below. -#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Copy, Hash, Debug)] -pub struct Compiler<'a> { +#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)] +pub struct Compiler { stage: u32, - host: &'a str, + host: Interned, } /// Global configuration for the build system. @@ -226,9 +229,9 @@ pub struct Build { verbosity: usize, // Targets for which to build. - build: String, - hosts: Vec, - targets: Vec, + build: Interned, + hosts: Vec>, + targets: Vec>, // Stage 0 (downloaded) compiler and cargo or their local rust equivalents. initial_rustc: PathBuf, @@ -240,10 +243,10 @@ pub struct Build { // Runtime state filled in later on // target -> (cc, ar) - cc: HashMap)>, + cc: HashMap, (gcc::Tool, Option)>, // host -> (cc, ar) - cxx: HashMap, - crates: HashMap, + cxx: HashMap, gcc::Tool>, + crates: HashMap, Crate>, is_sudo: bool, ci_env: CiEnv, delayed_failures: Cell, @@ -251,9 +254,9 @@ pub struct Build { #[derive(Debug)] struct Crate { - name: String, + name: Interned, version: String, - deps: Vec, + deps: Vec>, path: PathBuf, doc_step: String, build_step: String, @@ -265,7 +268,7 @@ struct Crate { /// /// These entries currently correspond to the various output directories of the /// build system, with each mod generating output in a different directory. -#[derive(Serialize, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)] pub enum Mode { /// Build the standard library, placing output in the "stageN-std" directory. Libstd, @@ -438,7 +441,7 @@ impl Build { /// Get the directory for incremental by-products when using the /// given compiler. fn incremental_dir(&self, compiler: Compiler) -> PathBuf { - self.out.join(compiler.host).join(format!("stage{}-incremental", compiler.stage)) + self.out.join(&*compiler.host).join(format!("stage{}-incremental", compiler.stage)) } /// Returns the root directory for all output generated in a particular @@ -452,7 +455,7 @@ impl Build { Mode::Tool => "-tools", Mode::Librustc => "-rustc", }; - self.out.join(compiler.host) + self.out.join(&*compiler.host) .join(format!("stage{}{}", compiler.stage, suffix)) } @@ -462,40 +465,40 @@ impl Build { fn cargo_out(&self, compiler: Compiler, mode: Mode, - target: &str) -> PathBuf { - self.stage_out(compiler, mode).join(target).join(self.cargo_dir()) + target: Interned) -> PathBuf { + self.stage_out(compiler, mode).join(&*target).join(self.cargo_dir()) } /// Root output directory for LLVM compiled for `target` /// /// Note that if LLVM is configured externally then the directory returned /// will likely be empty. - fn llvm_out(&self, target: &str) -> PathBuf { - self.out.join(target).join("llvm") + fn llvm_out(&self, target: Interned) -> PathBuf { + self.out.join(&*target).join("llvm") } /// Output directory for all documentation for a target - fn doc_out(&self, target: &str) -> PathBuf { - self.out.join(target).join("doc") + fn doc_out(&self, target: Interned) -> PathBuf { + self.out.join(&*target).join("doc") } /// Output directory for some generated md crate documentation for a target (temporary) - fn md_doc_out(&self, target: &str) -> PathBuf { - self.out.join(target).join("md-doc") + fn md_doc_out(&self, target: Interned) -> Interned { + INTERNER.intern_path(self.out.join(&*target).join("md-doc")) } /// Output directory for all crate documentation for a target (temporary) /// /// The artifacts here are then copied into `doc_out` above. - fn crate_doc_out(&self, target: &str) -> PathBuf { - self.out.join(target).join("crate-docs") + fn crate_doc_out(&self, target: Interned) -> PathBuf { + self.out.join(&*target).join("crate-docs") } /// Returns true if no custom `llvm-config` is set for the specified target. /// /// If no custom `llvm-config` was specified then Rust's llvm will be used. - fn is_rust_llvm(&self, target: &str) -> bool { - match self.config.target_config.get(target) { + fn is_rust_llvm(&self, target: Interned) -> bool { + match self.config.target_config.get(&target) { Some(ref c) => c.llvm_config.is_none(), None => true } @@ -505,25 +508,25 @@ impl Build { /// /// If a custom `llvm-config` was specified for target then that's returned /// instead. - fn llvm_config(&self, target: &str) -> PathBuf { - let target_config = self.config.target_config.get(target); + fn llvm_config(&self, target: Interned) -> PathBuf { + let target_config = self.config.target_config.get(&target); if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { s.clone() } else { - self.llvm_out(&self.config.build).join("bin") - .join(exe("llvm-config", target)) + self.llvm_out(self.config.build).join("bin") + .join(exe("llvm-config", &*target)) } } /// Returns the path to `FileCheck` binary for the specified target - fn llvm_filecheck(&self, target: &str) -> PathBuf { - let target_config = self.config.target_config.get(target); + fn llvm_filecheck(&self, target: Interned) -> PathBuf { + let target_config = self.config.target_config.get(&target); if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { let llvm_bindir = output(Command::new(s).arg("--bindir")); - Path::new(llvm_bindir.trim()).join(exe("FileCheck", target)) + Path::new(llvm_bindir.trim()).join(exe("FileCheck", &*target)) } else { - let base = self.llvm_out(&self.config.build).join("build"); - let exe = exe("FileCheck", target); + let base = self.llvm_out(self.config.build).join("build"); + let exe = exe("FileCheck", &*target); if !self.config.ninja && self.config.build.contains("msvc") { base.join("Release/bin").join(exe) } else { @@ -533,13 +536,13 @@ impl Build { } /// Directory for libraries built from C/C++ code and shared between stages. - fn native_dir(&self, target: &str) -> PathBuf { - self.out.join(target).join("native") + fn native_dir(&self, target: Interned) -> PathBuf { + self.out.join(&*target).join("native") } /// Root output directory for rust_test_helpers library compiled for /// `target` - fn test_helpers_out(&self, target: &str) -> PathBuf { + fn test_helpers_out(&self, target: Interned) -> PathBuf { self.native_dir(target).join("rust-test-helpers") } @@ -606,16 +609,16 @@ impl Build { } /// Returns the path to the C compiler for the target specified. - fn cc(&self, target: &str) -> &Path { - self.cc[target].0.path() + fn cc(&self, target: Interned) -> &Path { + self.cc[&target].0.path() } /// Returns a list of flags to pass to the C compiler for the target /// specified. - fn cflags(&self, target: &str) -> Vec { + fn cflags(&self, target: Interned) -> Vec { // Filter out -O and /O (the optimization flags) that we picked up from // gcc-rs because the build scripts will determine that for themselves. - let mut base = self.cc[target].0.args().iter() + let mut base = self.cc[&target].0.args().iter() .map(|s| s.to_string_lossy().into_owned()) .filter(|s| !s.starts_with("-O") && !s.starts_with("/O")) .collect::>(); @@ -631,20 +634,20 @@ impl Build { // Work around an apparently bad MinGW / GCC optimization, // See: http://lists.llvm.org/pipermail/cfe-dev/2016-December/051980.html // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78936 - if target == "i686-pc-windows-gnu" { + if &*target == "i686-pc-windows-gnu" { base.push("-fno-omit-frame-pointer".into()); } base } /// Returns the path to the `ar` archive utility for the target specified. - fn ar(&self, target: &str) -> Option<&Path> { - self.cc[target].1.as_ref().map(|p| &**p) + fn ar(&self, target: Interned) -> Option<&Path> { + self.cc[&target].1.as_ref().map(|p| &**p) } /// Returns the path to the C++ compiler for the target specified. - fn cxx(&self, target: &str) -> Result<&Path, String> { - match self.cxx.get(target) { + fn cxx(&self, target: Interned) -> Result<&Path, String> { + match self.cxx.get(&target) { Some(p) => Ok(p.path()), None => Err(format!( "target `{}` is not configured as a host, only as a target", @@ -653,7 +656,7 @@ impl Build { } /// Returns flags to pass to the compiler to generate code for `target`. - fn rustc_flags(&self, target: &str) -> Vec { + fn rustc_flags(&self, target: Interned) -> Vec { // New flags should be added here with great caution! // // It's quite unfortunate to **require** flags to generate code for a @@ -670,8 +673,8 @@ impl Build { } /// Returns the "musl root" for this `target`, if defined - fn musl_root(&self, target: &str) -> Option<&Path> { - self.config.target_config.get(target) + fn musl_root(&self, target: Interned) -> Option<&Path> { + self.config.target_config.get(&target) .and_then(|t| t.musl_root.as_ref()) .or(self.config.musl_root.as_ref()) .map(|p| &**p) @@ -679,7 +682,7 @@ impl Build { /// Returns whether the target will be tested using the `remote-test-client` /// and `remote-test-server` binaries. - fn remote_tested(&self, target: &str) -> bool { + fn remote_tested(&self, target: Interned) -> bool { self.qemu_rootfs(target).is_some() || target.contains("android") || env::var_os("TEST_DEVICE_ADDR").is_some() } @@ -689,8 +692,8 @@ impl Build { /// /// If `Some` is returned then that means that tests for this target are /// emulated with QEMU and binaries will need to be shipped to the emulator. - fn qemu_rootfs(&self, target: &str) -> Option<&Path> { - self.config.target_config.get(target) + fn qemu_rootfs(&self, target: Interned) -> Option<&Path> { + self.config.target_config.get(&target) .and_then(|t| t.qemu_rootfs.as_ref()) .map(|p| &**p) } @@ -718,20 +721,20 @@ impl Build { /// /// When all of these conditions are met the build will lift artifacts from /// the previous stage forward. - fn force_use_stage1(&self, compiler: Compiler, target: &str) -> bool { + fn force_use_stage1(&self, compiler: Compiler, target: Interned) -> bool { !self.config.full_bootstrap && compiler.stage >= 2 && - self.config.host.iter().any(|h| h == target) + self.config.host.iter().any(|h| *h == target) } /// Returns the directory that OpenSSL artifacts are compiled into if /// configured to do so. - fn openssl_dir(&self, target: &str) -> Option { + fn openssl_dir(&self, target: Interned) -> Option { // OpenSSL not used on Windows if target.contains("windows") { None } else if self.config.openssl_static { - Some(self.out.join(target).join("openssl")) + Some(self.out.join(&*target).join("openssl")) } else { None } @@ -739,7 +742,7 @@ impl Build { /// Returns the directory that OpenSSL artifacts are installed into if /// configured as such. - fn openssl_install_dir(&self, target: &str) -> Option { + fn openssl_install_dir(&self, target: Interned) -> Option { self.openssl_dir(target).map(|p| p.join("install")) } @@ -842,18 +845,19 @@ impl Build { /// Get a list of crates from a root crate. /// /// Returns Vec<(crate, path to crate, is_root_crate)> - fn crates(&self, root: &str) -> Vec<(&str, &Path)> { + fn crates(&self, root: &str) -> Vec<(Interned, &Path)> { + let interned = INTERNER.intern_string(root.to_owned()); let mut ret = Vec::new(); - let mut list = vec![root]; + let mut list = vec![interned]; let mut visited = HashSet::new(); while let Some(krate) = list.pop() { - let krate = &self.crates[krate]; + let krate = &self.crates[&krate]; // If we can't strip prefix, then out-of-tree path let path = krate.path.strip_prefix(&self.src).unwrap_or(&krate.path); - ret.push((&*krate.name, path)); + ret.push((krate.name, path)); for dep in &krate.deps { if visited.insert(dep) && dep != "build_helper" { - list.push(dep); + list.push(*dep); } } } @@ -861,8 +865,8 @@ impl Build { } } -impl<'a> Compiler<'a> { - pub fn with_stage(mut self, stage: u32) -> Compiler<'a> { +impl<'a> Compiler { + pub fn with_stage(mut self, stage: u32) -> Compiler { self.stage = stage; self } diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index ca0eed3ae86f8..2b641cd8484bb 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -16,6 +16,7 @@ use build_helper::output; use serde_json; use {Build, Crate}; +use cache::Interned; #[derive(Deserialize)] struct Output { @@ -26,7 +27,7 @@ struct Output { #[derive(Deserialize)] struct Package { id: String, - name: String, + name: Interned, version: String, source: Option, manifest_path: String, @@ -65,10 +66,10 @@ fn build_krate(build: &mut Build, krate: &str) { let mut id2name = HashMap::new(); for package in output.packages { if package.source.is_none() { - id2name.insert(package.id, package.name.clone()); + id2name.insert(package.id, package.name); let mut path = PathBuf::from(package.manifest_path); path.pop(); - build.crates.insert(package.name.clone(), Crate { + build.crates.insert(package.name, Crate { build_step: format!("build-crate-{}", package.name), doc_step: format!("doc-crate-{}", package.name), test_step: format!("test-crate-{}", package.name), @@ -93,7 +94,7 @@ fn build_krate(build: &mut Build, krate: &str) { Some(dep) => dep, None => continue, }; - krate.deps.push(dep.clone()); + krate.deps.push(*dep); } } } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index d8dc9f7670292..c0ec693a17e6e 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -33,6 +33,7 @@ use Build; use util; use build_helper::up_to_date; use builder::{Builder, Step}; +use cache::Interned; // rules.build("llvm", "src/llvm") // .host(true) @@ -45,13 +46,12 @@ use builder::{Builder, Step}; // }) // .run(move |s| native::llvm(build, s.target)); -#[derive(Serialize)] -pub struct Llvm<'a> { - pub target: &'a str, +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Llvm { + pub target: Interned, } -impl<'a> Step<'a> for Llvm<'a> { - type Id = Llvm<'static>; +impl Step for Llvm { type Output = (); const ONLY_HOSTS: bool = true; @@ -61,7 +61,7 @@ impl<'a> Step<'a> for Llvm<'a> { let target = self.target; // If we're using a custom LLVM bail out here, but we can only use a // custom LLVM for the build triple. - if let Some(config) = build.config.target_config.get(target) { + if let Some(config) = build.config.target_config.get(&target) { if let Some(ref s) = config.llvm_config { return check_llvm_version(build, s); } @@ -117,7 +117,7 @@ impl<'a> Step<'a> for Llvm<'a> { let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"}; - cfg.target(target) + cfg.target(&target) .host(&build.build) .out_dir(&out_dir) .profile(profile) @@ -154,11 +154,11 @@ impl<'a> Step<'a> for Llvm<'a> { // http://llvm.org/docs/HowToCrossCompileLLVM.html if target != build.build { - builder.ensure(Llvm { target: &build.build }); + builder.ensure(Llvm { target: build.build }); // FIXME: if the llvm root for the build triple is overridden then we // should use llvm-tblgen from there, also should verify that it // actually exists most of the time in normal installs of LLVM. - let host = build.llvm_out(&build.build).join("bin/llvm-tblgen"); + let host = build.llvm_out(build.build).join("bin/llvm-tblgen"); cfg.define("CMAKE_CROSSCOMPILING", "True") .define("LLVM_TABLEGEN", &host); } @@ -245,20 +245,24 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) { //rules.build("test-helpers", "src/rt/rust_test_helpers.c") // .run(move |s| native::test_helpers(build, s.target)); -#[derive(Serialize)] -pub struct TestHelpers<'a> { - pub target: &'a str, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct TestHelpers { + pub target: Interned, } -impl<'a> Step<'a> for TestHelpers<'a> { - type Id = TestHelpers<'static>; +impl Step for TestHelpers { type Output = (); fn should_run(_builder: &Builder, path: &Path) -> bool { path.ends_with("src/rt/rust_test_helpers.c") } - fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, + _path: Option<&Path>, + _host: Interned, + target: Interned, + ) { builder.ensure(TestHelpers { target }) } @@ -290,7 +294,7 @@ impl<'a> Step<'a> for TestHelpers<'a> { cfg.cargo_metadata(false) .out_dir(&dst) - .target(target) + .target(&target) .host(&build.build) .opt_level(0) .debug(false) @@ -306,13 +310,12 @@ const OPENSSL_SHA256: &'static str = //rules.build("openssl", "path/to/nowhere") // .run(move |s| native::openssl(build, s.target)); -#[derive(Serialize)] -pub struct Openssl<'a> { - pub target: &'a str, + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Openssl { + pub target: Interned, } -impl<'a> Step<'a> for Openssl<'a> { - type Id = Openssl<'static>; +impl Step for Openssl { type Output = (); fn should_run(_builder: &Builder, _path: &Path) -> bool { @@ -385,7 +388,7 @@ impl<'a> Step<'a> for Openssl<'a> { configure.arg("no-ssl2"); configure.arg("no-ssl3"); - let os = match target { + let os = match &*target { "aarch64-linux-android" => "linux-aarch64", "aarch64-unknown-linux-gnu" => "linux-aarch64", "arm-linux-androideabi" => "android", diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index a9c1b023dd4f5..7063b28f19d01 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -122,14 +122,14 @@ pub fn check(build: &mut Build) { continue; } - cmd_finder.must_have(build.cc(target)); - if let Some(ar) = build.ar(target) { + cmd_finder.must_have(build.cc(*target)); + if let Some(ar) = build.ar(*target) { cmd_finder.must_have(ar); } } for host in build.config.host.iter() { - cmd_finder.must_have(build.cxx(host).unwrap()); + cmd_finder.must_have(build.cxx(*host).unwrap()); // The msvc hosts don't use jemalloc, turn it off globally to // avoid packaging the dummy liballoc_jemalloc on that platform. @@ -139,7 +139,7 @@ pub fn check(build: &mut Build) { } // Externally configured LLVM requires FileCheck to exist - let filecheck = build.llvm_filecheck(&build.build); + let filecheck = build.llvm_filecheck(build.build); if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests { panic!("FileCheck executable {:?} does not exist", filecheck); } @@ -153,7 +153,7 @@ pub fn check(build: &mut Build) { // Make sure musl-root is valid if specified if target.contains("musl") && !target.contains("mips") { - match build.musl_root(target) { + match build.musl_root(*target) { Some(root) => { if fs::metadata(root.join("lib/libc.a")).is_err() { panic!("couldn't find libc.a in musl dir: {}", diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 27785506eaeb0..00616caf1206e 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -19,6 +19,7 @@ use util::{exe, add_lib_path}; use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp, Rustc}; use native; use channel::GitInfo; +use cache::Interned; //// ======================================================================== //// Build tools @@ -44,15 +45,14 @@ use channel::GitInfo; // .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libstd)); // -#[derive(Serialize)] -pub struct CleanTools<'a> { +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct CleanTools { pub stage: u32, - pub target: &'a str, + pub target: Interned, pub mode: Mode, } -impl<'a> Step<'a> for CleanTools<'a> { - type Id = CleanTools<'static>; +impl Step for CleanTools { type Output = (); /// Build a tool in `src/tools` @@ -65,7 +65,7 @@ impl<'a> Step<'a> for CleanTools<'a> { let target = self.target; let mode = self.mode; - let compiler = builder.compiler(stage, &build.build); + let compiler = builder.compiler(stage, build.build); let stamp = match mode { Mode::Libstd => libstd_stamp(build, compiler, target), @@ -78,16 +78,15 @@ impl<'a> Step<'a> for CleanTools<'a> { } } -#[derive(Serialize)] -pub struct ToolBuild<'a> { +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct ToolBuild { pub stage: u32, - pub target: &'a str, - pub tool: &'a str, + pub target: Interned, + pub tool: &'static str, pub mode: Mode, } -impl<'a> Step<'a> for ToolBuild<'a> { - type Id = ToolBuild<'static>; +impl Step for ToolBuild { type Output = PathBuf; /// Build a tool in `src/tools` @@ -100,7 +99,7 @@ impl<'a> Step<'a> for ToolBuild<'a> { let target = self.target; let tool = self.tool; - let compiler = builder.compiler(stage, &build.build); + let compiler = builder.compiler(stage, build.build); builder.ensure(CleanTools { stage, target, mode: self.mode }); match self.mode { Mode::Libstd => builder.ensure(compile::Std { compiler, target }), @@ -140,7 +139,7 @@ impl<'a> Step<'a> for ToolBuild<'a> { } build.run(&mut cargo); - build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, compiler.host)) + build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, &compiler.host)) } } @@ -159,7 +158,7 @@ macro_rules! tool { $(Tool::$name => self.ensure($name { stage: 0, - target: &self.build.build, + target: self.build.build, }), )+ } @@ -167,21 +166,25 @@ macro_rules! tool { } $( - #[derive(Serialize)] - pub struct $name<'a> { + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + pub struct $name { pub stage: u32, - pub target: &'a str, + pub target: Interned, } - impl<'a> Step<'a> for $name<'a> { - type Id = $name<'static>; + impl Step for $name { type Output = PathBuf; fn should_run(_builder: &Builder, path: &Path) -> bool { path.ends_with($path) } - fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, + _path: Option<&Path>, + _host: Interned, + target: Interned + ) { builder.ensure($name { stage: builder.top_stage, target, @@ -254,21 +257,25 @@ tool!( RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd; ); -#[derive(Serialize)] -pub struct RemoteTestServer<'a> { +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct RemoteTestServer { pub stage: u32, - pub target: &'a str, + pub target: Interned, } -impl<'a> Step<'a> for RemoteTestServer<'a> { - type Id = RemoteTestServer<'static>; +impl Step for RemoteTestServer { type Output = PathBuf; fn should_run(_builder: &Builder, path: &Path) -> bool { path.ends_with("src/tools/remote-test-server") } - fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, + _path: Option<&Path>, + _host: Interned, + target: Interned + ) { builder.ensure(RemoteTestServer { stage: builder.top_stage, target, @@ -299,14 +306,13 @@ impl<'a> Step<'a> for RemoteTestServer<'a> { // .host(&build.build) // }) // .run(move |s| compile::tool(build, s.stage, s.target, "cargo")); -#[derive(Serialize)] -pub struct Cargo<'a> { +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Cargo { pub stage: u32, - pub target: &'a str, + pub target: Interned, } -impl<'a> Step<'a> for Cargo<'a> { - type Id = Cargo<'static>; +impl Step for Cargo { type Output = PathBuf; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -315,7 +321,9 @@ impl<'a> Step<'a> for Cargo<'a> { path.ends_with("src/tools/cargo") } - fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned + ) { if path.is_none() && !builder.build.config.extended { return; } @@ -332,8 +340,8 @@ impl<'a> Step<'a> for Cargo<'a> { // Cargo depends on procedural macros, which requires a full host // compiler to be available, so we need to depend on that. builder.ensure(Rustc { - compiler: builder.compiler(builder.top_stage, &builder.build.build), - target: &builder.build.build, + compiler: builder.compiler(builder.top_stage, builder.build.build), + target: builder.build.build, }); builder.ensure(ToolBuild { stage: self.stage, @@ -357,14 +365,13 @@ impl<'a> Step<'a> for Cargo<'a> { // }) // .run(move |s| compile::tool(build, s.stage, s.target, "rls")); // -#[derive(Serialize)] -pub struct Rls<'a> { +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Rls { pub stage: u32, - pub target: &'a str, + pub target: Interned, } -impl<'a> Step<'a> for Rls<'a> { - type Id = Rls<'static>; +impl Step for Rls { type Output = PathBuf; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -373,7 +380,9 @@ impl<'a> Step<'a> for Rls<'a> { path.ends_with("src/tools/rls") } - fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { + fn make_run( + builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned + ) { if path.is_none() && !builder.build.config.extended { return; } @@ -390,8 +399,8 @@ impl<'a> Step<'a> for Rls<'a> { // RLS depends on procedural macros, which requires a full host // compiler to be available, so we need to depend on that. builder.ensure(Rustc { - compiler: builder.compiler(builder.top_stage, &builder.build.build), - target: &builder.build.build, + compiler: builder.compiler(builder.top_stage, builder.build.build), + target: builder.build.build, }); builder.ensure(ToolBuild { stage: self.stage, @@ -407,7 +416,7 @@ impl<'a> Builder<'a> { /// `host`. pub fn tool_cmd(&self, tool: Tool) -> Command { let mut cmd = Command::new(self.tool_exe(tool)); - let compiler = self.compiler(0, &self.build.build); + let compiler = self.compiler(0, self.build.build); self.prepare_tool_cmd(compiler, &mut cmd); cmd } @@ -417,10 +426,10 @@ impl<'a> Builder<'a> { /// Notably this munges the dynamic library lookup path to point to the /// right location to run `compiler`. fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) { - let host = compiler.host; - let mut paths = vec![ - self.sysroot_libdir(compiler, compiler.host), - self.cargo_out(compiler, Mode::Tool, host).join("deps"), + let host = &compiler.host; + let mut paths: Vec = vec![ + PathBuf::from(&self.sysroot_libdir(compiler, compiler.host)), + self.cargo_out(compiler, Mode::Tool, *host).join("deps"), ]; // On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make @@ -429,7 +438,7 @@ impl<'a> Builder<'a> { if compiler.host.contains("msvc") { let curpaths = env::var_os("PATH").unwrap_or_default(); let curpaths = env::split_paths(&curpaths).collect::>(); - for &(ref k, ref v) in self.cc[compiler.host].0.env() { + for &(ref k, ref v) in self.cc[&compiler.host].0.env() { if k != "PATH" { continue } From 270d1d69ede6a67f607ab5dba56d0cc39a8cfe95 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 13 Jul 2017 22:37:33 -0600 Subject: [PATCH 26/51] Make the book default. --- src/bootstrap/doc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 3c3f4bf2be73f..0030b46b32e1e 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -229,6 +229,7 @@ pub struct TheBook { impl Step for TheBook { type Output = (); + const DEFAULT: bool = true; fn should_run(_builder: &Builder, path: &Path) -> bool { path.ends_with("src/doc/book") From 681b12316c16911dc95eb9923de5486b142c745a Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Fri, 14 Jul 2017 06:30:16 -0600 Subject: [PATCH 27/51] Require should_run to be implemented. --- src/bootstrap/builder.rs | 15 +++++++++++++-- src/bootstrap/check.rs | 8 ++++++++ src/bootstrap/compile.rs | 20 ++++++++++++++++++++ src/bootstrap/doc.rs | 11 +++++++++++ src/bootstrap/native.rs | 4 ++++ src/bootstrap/tool.rs | 8 ++++++++ 6 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index f217cd1dd37b2..8740d7a1eb302 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -70,7 +70,7 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { /// will execute. However, it does not get called in a "default" context /// when we are not passed any paths; in that case, make_run is called /// directly. - fn should_run(_builder: &Builder, _path: &Path) -> bool { false } + fn should_run(builder: &Builder, path: &Path) -> bool; /// Build up a "root" rule, either as a default rule or from a path passed /// to us. @@ -83,7 +83,13 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { _path: Option<&Path>, _host: Interned, _target: Interned, - ) { unimplemented!() } + ) { + // It is reasonable to not have an implementation of make_run for rules + // who do not want to get called from the root context. This means that + // they are likely dependencies (e.g., sysroot creation) or similar, and + // as such calling them from ./x.py isn't logical. + unimplemented!() + } } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -188,6 +194,11 @@ impl<'a> Builder<'a> { } impl Step for Libdir { type Output = Interned; + + fn should_run(_builder: &Builder, _path: &Path) -> bool { + false + } + fn run(self, builder: &Builder) -> Interned { let compiler = self.compiler; let lib = if compiler.stage >= 2 && builder.build.config.libdir_relative.is_some() { diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index d983e54ac0851..b5d5d6de0843e 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -1360,6 +1360,10 @@ pub struct RemoteCopyLibs { impl Step for RemoteCopyLibs { type Output = (); + fn should_run(_builder: &Builder, _path: &Path) -> bool { + false + } + fn run(self, builder: &Builder) { let build = builder.build; let compiler = self.compiler; @@ -1411,6 +1415,10 @@ pub struct Distcheck; impl Step for Distcheck { type Output = (); + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("distcheck") + } + /// Run "distcheck", a 'make check' from a tarball fn run(self, builder: &Builder) { let build = builder.build; diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 558ced12cfea6..86879454f0890 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -276,6 +276,10 @@ struct StdLink { impl Step for StdLink { type Output = (); + fn should_run(_builder: &Builder, _path: &Path) -> bool { + false + } + /// Link all libstd rlibs/dylibs into the sysroot location. /// /// Links those artifacts generated by `compiler` to a the `stage` compiler's @@ -503,6 +507,10 @@ pub struct TestLink { impl Step for TestLink { type Output = (); + fn should_run(_builder: &Builder, _path: &Path) -> bool { + false + } + /// Same as `std_link`, only for libtest fn run(self, builder: &Builder) { let build = builder.build; @@ -691,6 +699,10 @@ struct RustcLink { impl Step for RustcLink { type Output = (); + fn should_run(_builder: &Builder, _path: &Path) -> bool { + false + } + /// Same as `std_link`, only for librustc fn run(self, builder: &Builder) { let build = builder.build; @@ -743,6 +755,10 @@ pub struct Sysroot { impl Step for Sysroot { type Output = Interned; + fn should_run(_builder: &Builder, _path: &Path) -> bool { + false + } + /// Returns the sysroot for the `compiler` specified that *this build system /// generates*. /// @@ -789,6 +805,10 @@ pub struct Assemble { impl Step for Assemble { type Output = Compiler; + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/rustc") + } + /// Prepare a new compiler from the artifacts in `stage` /// /// This will assemble a compiler in `build/$host/stage$stage`. The compiler diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 0030b46b32e1e..65110dbaae95b 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -107,6 +107,12 @@ pub struct Rustbook { impl Step for Rustbook { type Output = (); + // rustbook is never directly called, and only serves as a shim for the nomicon and the + // reference. + fn should_run(_builder: &Builder, _path: &Path) -> bool { + false + } + /// Invoke `rustbook` for `target` for the doc book `name`. /// /// This will not actually generate any documentation if the documentation has @@ -182,6 +188,11 @@ pub struct RustbookSrc { impl Step for RustbookSrc { type Output = (); + fn should_run(_builder: &Builder, _path: &Path) -> bool { + // RustbookSrc is also never run directly, only as a helper to other rules + false + } + /// Invoke `rustbook` for `target` for the doc book `name` from the `src` path. /// /// This will not actually generate any documentation if the documentation has diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index c0ec693a17e6e..b60a3760eb288 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -55,6 +55,10 @@ impl Step for Llvm { type Output = (); const ONLY_HOSTS: bool = true; + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/llvm") + } + /// Compile LLVM for `target`. fn run(self, builder: &Builder) { let build = builder.build; diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 00616caf1206e..9c5592cd61bfa 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -55,6 +55,10 @@ pub struct CleanTools { impl Step for CleanTools { type Output = (); + fn should_run(_builder: &Builder, _path: &Path) -> bool { + false + } + /// Build a tool in `src/tools` /// /// This will build the specified tool with the specified `host` compiler in @@ -89,6 +93,10 @@ pub struct ToolBuild { impl Step for ToolBuild { type Output = PathBuf; + fn should_run(_builder: &Builder, _path: &Path) -> bool { + false + } + /// Build a tool in `src/tools` /// /// This will build the specified tool with the specified `host` compiler in From fc3d06ac86235301304b87d6cc73dcb738ceb98b Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Fri, 14 Jul 2017 09:28:06 -0600 Subject: [PATCH 28/51] Implement keep-stage support --- src/bootstrap/compile.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 86879454f0890..722bbda13a44c 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -23,6 +23,7 @@ use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::str; +use std::cmp::min; use build_helper::{output, mtime, up_to_date}; use filetime::FileTime; @@ -846,7 +847,18 @@ impl Step for Assemble { // link to these. (FIXME: Is that correct? It seems to be correct most // of the time but I think we do link to these for stage2/bin compilers // when not performing a full bootstrap). - builder.ensure(Rustc { compiler: build_compiler, target: target_compiler.host }); + if builder.build.flags.keep_stage.map_or(false, |s| target_compiler.stage <= s) { + builder.verbose("skipping compilation of compiler due to --keep-stage"); + let compiler = build_compiler; + for stage in 0..min(target_compiler.stage, builder.flags.keep_stage.unwrap()) { + let target_compiler = builder.compiler(stage, target_compiler.host); + builder.ensure(StdLink { compiler, target_compiler, target: target_compiler.host }); + builder.ensure(TestLink { compiler, target_compiler, target: target_compiler.host }); + builder.ensure(RustcLink { compiler, target_compiler, target: target_compiler.host }); + } + } else { + builder.ensure(Rustc { compiler: build_compiler, target: target_compiler.host }); + } let stage = target_compiler.stage; let host = target_compiler.host; From 17f4b8f0e1483d50349e1f034b4366531584c6e0 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Fri, 14 Jul 2017 09:37:30 -0600 Subject: [PATCH 29/51] Remove outdated FIXME from cache --- src/bootstrap/cache.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index e2576673338b8..cc84bf074571a 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -257,9 +257,6 @@ lazy_static! { /// any type in its output. It is a write-once cache; values are never evicted, /// which means that references to the value can safely be returned from the /// get() method. -// -// FIXME: This type does not permit retrieving &Path from a PathBuf, primarily -// due to a lack of any obvious way to ensure that this is safe, but also not #[derive(Debug)] pub struct Cache( RefCell Date: Fri, 14 Jul 2017 17:59:03 -0600 Subject: [PATCH 30/51] Fix tidy --- src/bootstrap/compile.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 722bbda13a44c..eccecc983f16e 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -852,9 +852,10 @@ impl Step for Assemble { let compiler = build_compiler; for stage in 0..min(target_compiler.stage, builder.flags.keep_stage.unwrap()) { let target_compiler = builder.compiler(stage, target_compiler.host); - builder.ensure(StdLink { compiler, target_compiler, target: target_compiler.host }); - builder.ensure(TestLink { compiler, target_compiler, target: target_compiler.host }); - builder.ensure(RustcLink { compiler, target_compiler, target: target_compiler.host }); + let target = target_compiler.host; + builder.ensure(StdLink { compiler, target_compiler, target }); + builder.ensure(TestLink { compiler, target_compiler, target }); + builder.ensure(RustcLink { compiler, target_compiler, target }); } } else { builder.ensure(Rustc { compiler: build_compiler, target: target_compiler.host }); From 828b661ae0eea533d950ea4dcc7a1c931c5c35c4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 10 Jul 2017 16:27:46 +0200 Subject: [PATCH 31/51] fail in case nothing to run was found --- src/bootstrap/builder.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 8740d7a1eb302..2338ac1a692c5 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -113,11 +113,16 @@ macro_rules! check { })+ } else { for path in paths { + let mut attempted_run = false; $({ if <$rule>::should_run($self, path) { + attempted_run = true; $self.maybe_run::<$rule>(Some(path)); } })+ + if !attempted_run { + eprintln!("Warning: no rules matched {}.", path.display()); + } } } }}; From dec44b0656da4863e46fdda0c6772c10c387ede2 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Mon, 17 Jul 2017 09:52:05 -0600 Subject: [PATCH 32/51] Resolve rebase errors --- src/Cargo.lock | 8 ++--- src/bootstrap/check.rs | 66 ++++++++++++++++++++---------------------- 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 3f216b0c2f633..2f695b4f3bd29 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -137,8 +137,8 @@ dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -156,8 +156,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "build-manifest" version = "0.1.0" dependencies = [ - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index b5d5d6de0843e..fdbc821de55ac 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -222,7 +222,7 @@ impl Step for Cargo { _host: Interned, target: Interned, ) { - builder.ensure(Cargotest { + builder.ensure(Cargo { stage: builder.top_stage, host: target, }); @@ -233,29 +233,12 @@ impl Step for Cargo { let build = builder.build; let compiler = builder.compiler(self.stage, self.host); - // Configure PATH to find the right rustc. NB. we have to use PATH - // and not RUSTC because the Cargo test suite has tests that will - // fail if rustc is not spelled `rustc`. - let path = builder.sysroot(compiler).join("bin"); - let old_path = env::var_os("PATH").unwrap_or_default(); - let newpath = env::join_paths( - iter::once(path).chain(env::split_paths(&old_path)) - ).expect(""); - let mut cargo = builder.cargo(compiler, Mode::Tool, self.host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml")); if !build.fail_fast { cargo.arg("--no-fail-fast"); } - let compiler = &Compiler::new(stage, host); - - let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); - cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml")); - if !build.fail_fast { - cargo.arg("--no-fail-fast"); - } - // Don't build tests dynamically, just a pain to work with cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); @@ -263,51 +246,66 @@ impl Step for Cargo { // available. cargo.env("CFG_DISABLE_CROSS_TESTS", "1"); - try_run(build, cargo.env("PATH", &path_for_cargo(build, compiler))); + try_run(build, cargo.env("PATH", &path_for_cargo(builder, compiler))); } } -#[derive(Serialize)] -pub struct Rls<'a> { +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Rls { stage: u32, - host: &'a str, + host: Interned, } -impl<'a> Step<'a> for Rls<'a> { +// rules.test("check-rls", "src/tools/rls") +// .dep(|s| s.name("tool-rls")) +// .host(true) +// .run(move |s| check::rls(build, s.stage, s.target)); +impl Step for Rls { type Output = (); + const ONLY_HOSTS: bool = true; + + fn should_run(_builder: &Builder, path: &Path) -> bool { + path.ends_with("src/tools/rls") + } + + fn make_run( + builder: &Builder, + _path: Option<&Path>, + _host: Interned, + target: Interned, + ) { + builder.ensure(Rls { + stage: builder.top_stage, + host: target, + }); + } /// Runs `cargo test` for the rls. fn run(self, builder: &Builder) { let build = builder.build; let stage = self.stage; let host = self.host; - let compiler = &Compiler::new(stage, host); + let compiler = builder.compiler(stage, host); - let mut cargo = build.cargo(compiler, Mode::Tool, host, "test"); + let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/rls/Cargo.toml")); // Don't build tests dynamically, just a pain to work with cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); - build.add_rustc_lib_path(compiler, &mut cargo); + builder.add_rustc_lib_path(compiler, &mut cargo); try_run(build, &mut cargo); } } -fn path_for_cargo(build: &Build, compiler: &Compiler) -> OsString { +fn path_for_cargo(builder: &Builder, compiler: Compiler) -> OsString { // Configure PATH to find the right rustc. NB. we have to use PATH // and not RUSTC because the Cargo test suite has tests that will // fail if rustc is not spelled `rustc`. - let path = build.sysroot(compiler).join("bin"); + let path = builder.sysroot(compiler).join("bin"); let old_path = env::var_os("PATH").unwrap_or_default(); env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("") -||||||| parent of adabe3889e... Move code into Step trait implementations. - try_run(build, cargo.env("PATH", newpath)); -======= - try_run(build, cargo.env("PATH", newpath)); - } ->>>>>>> adabe3889e... Move code into Step trait implementations. } //rules.test("check-tidy", "src/tools/tidy") From 28defe0fced3eb805aa4116bee356b139284831c Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Sun, 16 Jul 2017 23:46:27 +0100 Subject: [PATCH 33/51] Remove deserialize --- src/bootstrap/cache.rs | 26 -------------------------- src/bootstrap/metadata.rs | 19 ++++++++++--------- 2 files changed, 10 insertions(+), 35 deletions(-) diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index cc84bf074571a..c27493158826c 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use serde::Deserialize; -use serde::de::{self, Deserializer, Visitor}; - use std::any::{Any, TypeId}; use std::borrow::Borrow; use std::cell::RefCell; @@ -29,29 +26,6 @@ use builder::Step; pub struct Interned(usize, PhantomData<*const T>); -impl<'de> Deserialize<'de> for Interned { - fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> - { - struct StrVisitor; - - impl<'de> Visitor<'de> for StrVisitor { - type Value = &'de str; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a str") - } - - fn visit_borrowed_str(self, value: &'de str) -> Result<&'de str, E> - where E: de::Error - { - Ok(value) - } - } - - Ok(INTERNER.intern_str(deserializer.deserialize_str(StrVisitor)?)) - } -} impl Default for Interned { fn default() -> Self { INTERNER.intern_string(String::default()) diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index 2b641cd8484bb..ad555be877ae4 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -16,7 +16,7 @@ use build_helper::output; use serde_json; use {Build, Crate}; -use cache::Interned; +use cache::INTERNER; #[derive(Deserialize)] struct Output { @@ -27,7 +27,7 @@ struct Output { #[derive(Deserialize)] struct Package { id: String, - name: Interned, + name: String, version: String, source: Option, manifest_path: String, @@ -66,15 +66,16 @@ fn build_krate(build: &mut Build, krate: &str) { let mut id2name = HashMap::new(); for package in output.packages { if package.source.is_none() { - id2name.insert(package.id, package.name); + let name = INTERNER.intern_string(package.name); + id2name.insert(package.id, name); let mut path = PathBuf::from(package.manifest_path); path.pop(); - build.crates.insert(package.name, Crate { - build_step: format!("build-crate-{}", package.name), - doc_step: format!("doc-crate-{}", package.name), - test_step: format!("test-crate-{}", package.name), - bench_step: format!("bench-crate-{}", package.name), - name: package.name, + build.crates.insert(name, Crate { + build_step: format!("build-crate-{}", name), + doc_step: format!("doc-crate-{}", name), + test_step: format!("test-crate-{}", name), + bench_step: format!("bench-crate-{}", name), + name: name, version: package.version, deps: Vec::new(), path: path, From 741486885334f603f0ae4050bebdeb347c6720ff Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Mon, 17 Jul 2017 18:01:48 -0600 Subject: [PATCH 34/51] Remove TypeId from stack in Builder --- src/bootstrap/builder.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 2338ac1a692c5..50ecdeb988a01 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::fs; use std::ops::Deref; -use std::any::{TypeId, Any}; +use std::any::Any; use compile; use install; @@ -35,7 +35,7 @@ pub struct Builder<'a> { pub top_stage: u32, pub kind: Kind, cache: Cache, - stack: RefCell)>>, + stack: RefCell>>, } impl<'a> Deref for Builder<'a> { @@ -477,12 +477,12 @@ impl<'a> Builder<'a> { /// cache the step, so it is safe (and good!) to call this as often as /// needed to ensure that all dependencies are built. pub fn ensure(&'a self, step: S) -> S::Output { - let type_id = TypeId::of::(); { let mut stack = self.stack.borrow_mut(); - for &(stack_type_id, ref stack_step) in stack.iter() { - if !(type_id == stack_type_id && step == *stack_step.downcast_ref().unwrap()) { - continue + for stack_step in stack.iter() { + // should skip + if stack_step.downcast_ref::().map_or(true, |stack_step| *stack_step != step) { + continue; } let mut out = String::new(); out += &format!("\n\nCycle in build detected when adding {:?}\n", step); @@ -497,13 +497,13 @@ impl<'a> Builder<'a> { return out; } self.build.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), step)); - stack.push((type_id, Box::new(step.clone()))); + stack.push(Box::new(step.clone())); } let out = step.clone().run(self); { let mut stack = self.stack.borrow_mut(); - let (cur_type_id, cur_step) = stack.pop().expect("step stack empty"); - assert_eq!((cur_type_id, cur_step.downcast_ref()), (type_id, Some(&step))); + let cur_step = stack.pop().expect("step stack empty"); + assert_eq!(cur_step.downcast_ref(), Some(&step)); } self.build.verbose(&format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step)); self.cache.put(step, out.clone()); From ba1fc82fe4377dd7a7898b8354dcf7e2b3a0e685 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Mon, 17 Jul 2017 18:03:31 -0600 Subject: [PATCH 35/51] Remove outdated code. Relevant sys crates handle this properly. --- src/bootstrap/builder.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 50ecdeb988a01..9993392ac46e9 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -399,19 +399,6 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string()); } - // When being built Cargo will at some point call `nmake.exe` on Windows - // MSVC. Unfortunately `nmake` will read these two environment variables - // below and try to intepret them. We're likely being run, however, from - // MSYS `make` which uses the same variables. - // - // As a result, to prevent confusion and errors, we remove these - // variables from our environment to prevent passing MSYS make flags to - // nmake, causing it to blow up. - if cfg!(target_env = "msvc") { - cargo.env_remove("MAKE"); - cargo.env_remove("MAKEFLAGS"); - } - // Environment variables *required* throughout the build // // FIXME: should update code to not require this env var From 981afa52f6e3fa61074a5e295c782cd0a84f06e1 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 18 Jul 2017 15:28:53 -0600 Subject: [PATCH 36/51] Krate -> Crate --- src/bootstrap/builder.rs | 4 ++-- src/bootstrap/check.rs | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 9993392ac46e9..77f8dda251bad 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -156,9 +156,9 @@ impl<'a> Builder<'a> { tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient, tool::RustInstaller, tool::Cargo, tool::Rls), Kind::Test => check!(builder, paths, check::Tidy, check::Bootstrap, check::Compiletest, - check::Krate, check::KrateLibrustc, check::Linkcheck, check::Cargotest, + check::Crate, check::CrateLibrustc, check::Linkcheck, check::Cargotest, check::Cargo, check::Docs, check::ErrorIndex, check::Distcheck), - Kind::Bench => check!(builder, paths, check::Krate, check::KrateLibrustc), + Kind::Bench => check!(builder, paths, check::Crate, check::CrateLibrustc), Kind::Doc => builder.default_doc(Some(paths)), Kind::Dist => check!(builder, paths, dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts, dist::Std, dist::Analysis, dist::Src, diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index fdbc821de55ac..6c41a76e70f60 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -961,14 +961,14 @@ fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) { // .run(move |s| check::krate(build, &s.compiler(), s.target, // Mode::Librustc, TestKind::Test, None)); #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct KrateLibrustc { +pub struct CrateLibrustc { compiler: Compiler, target: Interned, test_kind: TestKind, krate: Option>, } -impl Step for KrateLibrustc { +impl Step for CrateLibrustc { type Output = (); const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -993,10 +993,10 @@ impl Step for KrateLibrustc { } else if builder.kind == Kind::Bench { TestKind::Bench } else { - panic!("unexpected builder.kind in Krate: {:?}", builder.kind); + panic!("unexpected builder.kind in crate: {:?}", builder.kind); }; - builder.ensure(KrateLibrustc { + builder.ensure(CrateLibrustc { compiler, target, test_kind: test_kind, @@ -1017,7 +1017,7 @@ impl Step for KrateLibrustc { fn run(self, builder: &Builder) { - builder.ensure(Krate { + builder.ensure(Crate { compiler: self.compiler, target: self.target, mode: Mode::Librustc, @@ -1075,7 +1075,7 @@ impl Step for KrateLibrustc { // Mode::Libtest, TestKind::Test, None)); #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Krate { +pub struct Crate { compiler: Compiler, target: Interned, mode: Mode, @@ -1083,7 +1083,7 @@ pub struct Krate { krate: Option>, } -impl Step for Krate { +impl Step for Crate { type Output = (); const DEFAULT: bool = true; @@ -1110,10 +1110,10 @@ impl Step for Krate { } else if builder.kind == Kind::Bench { TestKind::Bench } else { - panic!("unexpected builder.kind in Krate: {:?}", builder.kind); + panic!("unexpected builder.kind in crate: {:?}", builder.kind); }; - builder.ensure(Krate { + builder.ensure(Crate { compiler, target, mode: mode, test_kind: test_kind, From bca1e2ffd1658e800e15e730dee5d6cc02722270 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 18 Jul 2017 16:14:44 -0600 Subject: [PATCH 37/51] Use a single line for serde annotations. --- src/bootstrap/config.rs | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index abb0408c4d247..b0c58235fc31e 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -139,8 +139,7 @@ pub struct Target { /// file into this format, and then this is traversed and written into the above /// `Config` structure. #[derive(Deserialize, Default)] -#[serde(deny_unknown_fields)] -#[serde(rename_all = "kebab-case")] +#[serde(deny_unknown_fields, rename_all = "kebab-case")] struct TomlConfig { build: Option, install: Option, @@ -152,8 +151,7 @@ struct TomlConfig { /// TOML representation of various global build decisions. #[derive(Deserialize, Default, Clone)] -#[serde(deny_unknown_fields)] -#[serde(rename_all = "kebab-case")] +#[serde(deny_unknown_fields, rename_all = "kebab-case")] struct Build { build: Option, #[serde(default)] @@ -181,8 +179,7 @@ struct Build { /// TOML representation of various global install decisions. #[derive(Deserialize, Default, Clone)] -#[serde(deny_unknown_fields)] -#[serde(rename_all = "kebab-case")] +#[serde(deny_unknown_fields, rename_all = "kebab-case")] struct Install { prefix: Option, sysconfdir: Option, @@ -194,8 +191,7 @@ struct Install { /// TOML representation of how the LLVM build is configured. #[derive(Deserialize, Default)] -#[serde(deny_unknown_fields)] -#[serde(rename_all = "kebab-case")] +#[serde(deny_unknown_fields, rename_all = "kebab-case")] struct Llvm { ccache: Option, ninja: Option, @@ -211,8 +207,7 @@ struct Llvm { } #[derive(Deserialize, Default, Clone)] -#[serde(deny_unknown_fields)] -#[serde(rename_all = "kebab-case")] +#[serde(deny_unknown_fields, rename_all = "kebab-case")] struct Dist { sign_folder: Option, gpg_password_file: Option, @@ -235,8 +230,7 @@ impl Default for StringOrBool { /// TOML representation of how the Rust build is configured. #[derive(Deserialize, Default)] -#[serde(deny_unknown_fields)] -#[serde(rename_all = "kebab-case")] +#[serde(deny_unknown_fields, rename_all = "kebab-case")] struct Rust { optimize: Option, codegen_units: Option, @@ -259,8 +253,7 @@ struct Rust { /// TOML representation of how each build target is configured. #[derive(Deserialize, Default)] -#[serde(deny_unknown_fields)] -#[serde(rename_all = "kebab-case")] +#[serde(deny_unknown_fields, rename_all = "kebab-case")] struct TomlTarget { llvm_config: Option, jemalloc: Option, From 56128fb3acdbb40876d1fc8aee613792ebef3080 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Tue, 18 Jul 2017 18:03:38 -0600 Subject: [PATCH 38/51] Implement available paths list. --- src/bootstrap/builder.rs | 105 ++++++++++++++++++++++++++++++++++++--- src/bootstrap/check.rs | 66 +++++++++++------------- src/bootstrap/compile.rs | 47 +++++++----------- src/bootstrap/dist.rs | 50 +++++++++---------- src/bootstrap/doc.rs | 58 ++++++++++----------- src/bootstrap/flags.rs | 8 ++- src/bootstrap/install.rs | 6 +-- src/bootstrap/native.rs | 14 +++--- src/bootstrap/tool.rs | 26 +++++----- 9 files changed, 224 insertions(+), 156 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 77f8dda251bad..8613bc7a7ba91 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -16,6 +16,7 @@ use std::process::Command; use std::fs; use std::ops::Deref; use std::any::Any; +use std::collections::BTreeSet; use compile; use install; @@ -70,7 +71,7 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { /// will execute. However, it does not get called in a "default" context /// when we are not passed any paths; in that case, make_run is called /// directly. - fn should_run(builder: &Builder, path: &Path) -> bool; + fn should_run(run: ShouldRun) -> ShouldRun; /// Build up a "root" rule, either as a default rule or from a path passed /// to us. @@ -92,6 +93,43 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { } } +#[derive(Clone)] +pub struct ShouldRun<'a> { + builder: &'a Builder<'a>, + // use a BTreeSet to maintain sort order + paths: BTreeSet, +} + +impl<'a> ShouldRun<'a> { + fn new(builder: &'a Builder) -> ShouldRun<'a> { + ShouldRun { + builder: builder, + paths: BTreeSet::new(), + } + } + + pub fn krate(mut self, name: &str) -> Self { + for (_, krate_path) in self.builder.crates(name) { + self.paths.insert(PathBuf::from(krate_path)); + } + self + } + + pub fn path(mut self, path: &str) -> Self { + self.paths.insert(PathBuf::from(path)); + self + } + + // allows being more explicit about why should_run in Step returns the value passed to it + pub fn never(self) -> ShouldRun<'a> { + self + } + + fn run(&self, path: &Path) -> bool { + self.paths.iter().any(|p| path.ends_with(p)) + } +} + #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Kind { Build, @@ -115,7 +153,7 @@ macro_rules! check { for path in paths { let mut attempted_run = false; $({ - if <$rule>::should_run($self, path) { + if <$rule>::should_run(ShouldRun::new($self)).run(path) { attempted_run = true; $self.maybe_run::<$rule>(Some(path)); } @@ -129,6 +167,60 @@ macro_rules! check { } impl<'a> Builder<'a> { + pub fn get_help(build: &Build, subcommand: &str) -> Option { + let kind = match subcommand { + "build" => Kind::Build, + "doc" => Kind::Doc, + "test" => Kind::Test, + "bench" => Kind::Bench, + "dist" => Kind::Dist, + "install" => Kind::Install, + _ => return None, + }; + + let builder = Builder { + build: build, + top_stage: build.flags.stage.unwrap_or(2), + kind: kind, + cache: Cache::new(), + stack: RefCell::new(Vec::new()), + }; + + let builder = &builder; + let mut should_run = ShouldRun::new(builder); + macro_rules! into_shouldrun { + ($should_run:ident, $($rule:ty),+ $(,)*) => {{ + $( + $should_run = <$rule>::should_run($should_run); + )+ + }}; + } + match builder.kind { + Kind::Build => into_shouldrun!(should_run, compile::Std, compile::Test, compile::Rustc, + compile::StartupObjects, tool::BuildManifest, tool::Rustbook, tool::ErrorIndex, + tool::UnstableBookGen, tool::Tidy, tool::Linkchecker, tool::CargoTest, + tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient, + tool::RustInstaller, tool::Cargo, tool::Rls), + Kind::Test => into_shouldrun!(should_run, check::Tidy, check::Bootstrap, + check::Compiletest, check::Crate, check::CrateLibrustc, check::Linkcheck, + check::Cargotest, check::Cargo, check::Docs, check::ErrorIndex, check::Distcheck), + Kind::Bench => into_shouldrun!(should_run, check::Crate, check::CrateLibrustc), + Kind::Doc => into_shouldrun!(should_run, doc::UnstableBook, doc::UnstableBookGen, + doc::TheBook, doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, + doc::Nomicon, doc::Reference), + Kind::Dist => into_shouldrun!(should_run, dist::Docs, dist::Mingw, dist::Rustc, + dist::DebuggerScripts, dist::Std, dist::Analysis, dist::Src, + dist::PlainSourceTarball, dist::Cargo, dist::Rls, dist::Extended, dist::HashSign), + Kind::Install => into_shouldrun!(should_run, install::Docs, install::Std, + install::Cargo, install::Rls, install::Analysis, install::Src, install::Rustc), + } + let mut help = String::from("Available paths:\n"); + for path in should_run.paths { + help.push_str(format!(" ./x.py {} {}\n", subcommand, path.display()).as_str()); + } + Some(help) + } + pub fn run(build: &Build) { let (kind, paths) = match build.flags.cmd { Subcommand::Build { ref paths } => (Kind::Build, &paths[..]), @@ -170,9 +262,8 @@ impl<'a> Builder<'a> { pub fn default_doc(&self, paths: Option<&[PathBuf]>) { let paths = paths.unwrap_or(&[]); - check!(self, paths, doc::UnstableBook, doc::UnstableBookGen, doc::Rustbook, doc::TheBook, - doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, - doc::Nomicon, doc::Reference); + check!(self, paths, doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, doc::Standalone, + doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon, doc::Reference); } /// Obtain a compiler at a given stage and for a given host. Explictly does @@ -200,8 +291,8 @@ impl<'a> Builder<'a> { impl Step for Libdir { type Output = Interned; - fn should_run(_builder: &Builder, _path: &Path) -> bool { - false + fn should_run(run: ShouldRun) -> ShouldRun { + run.never() } fn run(self, builder: &Builder) -> Interned { diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 6c41a76e70f60..847307959cb8d 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -31,7 +31,7 @@ use util::{self, dylib_path, dylib_path_var}; use compile; use native; -use builder::{Kind, Builder, Compiler, Step}; +use builder::{Kind, ShouldRun, Builder, Compiler, Step}; use tool::{self, Tool}; use cache::{INTERNER, Interned}; @@ -121,8 +121,8 @@ impl Step for Linkcheck { .arg(build.out.join(host).join("doc"))); } - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/tools/linkchecker") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/linkchecker") } fn make_run( @@ -157,8 +157,8 @@ impl Step for Cargotest { type Output = (); const ONLY_HOSTS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/tools/cargotest") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/cargotest") } fn make_run( @@ -212,8 +212,8 @@ impl Step for Cargo { type Output = (); const ONLY_HOSTS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/tools/cargo") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/cargo") } fn make_run( @@ -264,8 +264,8 @@ impl Step for Rls { type Output = (); const ONLY_HOSTS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/tools/rls") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/rls") } fn make_run( @@ -348,8 +348,8 @@ impl Step for Tidy { try_run(build, &mut cmd); } - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/tools/tidy") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/tidy") } fn make_run( @@ -531,13 +531,14 @@ impl Step for Compiletest { type Output = (); const DEFAULT: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { + fn should_run(mut run: ShouldRun) -> ShouldRun { // Note that this is general, while a few more cases are skipped inside // run() itself. This is to avoid duplication across should_run and // make_run. - COMPILETESTS.iter().chain(DEFAULT_COMPILETESTS).chain(HOST_COMPILETESTS).any(|&test| { - path.ends_with(test.path) - }) + for test in COMPILETESTS.iter().chain(DEFAULT_COMPILETESTS).chain(HOST_COMPILETESTS) { + run = run.path(test.path); + } + run } fn make_run( @@ -803,8 +804,8 @@ impl Step for Docs { const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/doc") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/doc") } fn make_run( @@ -873,8 +874,8 @@ impl Step for ErrorIndex { const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/tools/error_index_generator") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/error_index_generator") } fn make_run( @@ -973,10 +974,8 @@ impl Step for CrateLibrustc { const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - fn should_run(builder: &Builder, path: &Path) -> bool { - builder.crates("rustc-main").into_iter().any(|(_, krate_path)| { - path.ends_with(krate_path) - }) + fn should_run(run: ShouldRun) -> ShouldRun { + run.krate("rustc-main") } fn make_run( @@ -1087,13 +1086,8 @@ impl Step for Crate { type Output = (); const DEFAULT: bool = true; - fn should_run(builder: &Builder, path: &Path) -> bool { - builder.crates("std").into_iter().any(|(_, krate_path)| { - path.ends_with(krate_path) - }) || - builder.crates("test").into_iter().any(|(_, krate_path)| { - path.ends_with(krate_path) - }) + fn should_run(run: ShouldRun) -> ShouldRun { + run.krate("std").krate("test") } fn make_run( @@ -1358,8 +1352,8 @@ pub struct RemoteCopyLibs { impl Step for RemoteCopyLibs { type Output = (); - fn should_run(_builder: &Builder, _path: &Path) -> bool { - false + fn should_run(run: ShouldRun) -> ShouldRun { + run.never() } fn run(self, builder: &Builder) { @@ -1413,8 +1407,8 @@ pub struct Distcheck; impl Step for Distcheck { type Output = (); - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("distcheck") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("distcheck") } /// Run "distcheck", a 'make check' from a tarball @@ -1503,8 +1497,8 @@ impl Step for Bootstrap { try_run(build, &mut cmd); } - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/bootstrap") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/bootstrap") } fn make_run( diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index eccecc983f16e..134d957220da8 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -34,7 +34,7 @@ use {Build, Compiler, Mode}; use native; use cache::{INTERNER, Interned}; -use builder::{Step, Builder}; +use builder::{Step, ShouldRun, Builder}; // // // Crates which have build scripts need to rely on this rule to ensure that @@ -152,11 +152,8 @@ impl Step for Std { type Output = (); const DEFAULT: bool = true; - fn should_run(builder: &Builder, path: &Path) -> bool { - path.ends_with("src/libstd") || - builder.crates("std").into_iter().any(|(_, krate_path)| { - path.ends_with(krate_path) - }) + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/libstd").krate("std") } fn make_run( @@ -277,8 +274,8 @@ struct StdLink { impl Step for StdLink { type Output = (); - fn should_run(_builder: &Builder, _path: &Path) -> bool { - false + fn should_run(run: ShouldRun) -> ShouldRun { + run.never() } /// Link all libstd rlibs/dylibs into the sysroot location. @@ -350,8 +347,8 @@ pub struct StartupObjects { impl Step for StartupObjects { type Output = (); - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/rtstartup") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/rtstartup") } fn make_run( @@ -422,11 +419,8 @@ impl Step for Test { type Output = (); const DEFAULT: bool = true; - fn should_run(builder: &Builder, path: &Path) -> bool { - path.ends_with("src/libtest") || - builder.crates("test").into_iter().any(|(_, krate_path)| { - path.ends_with(krate_path) - }) + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/libtest").krate("test") } fn make_run( @@ -508,8 +502,8 @@ pub struct TestLink { impl Step for TestLink { type Output = (); - fn should_run(_builder: &Builder, _path: &Path) -> bool { - false + fn should_run(run: ShouldRun) -> ShouldRun { + run.never() } /// Same as `std_link`, only for libtest @@ -548,11 +542,8 @@ impl Step for Rustc { const ONLY_HOSTS: bool = true; const DEFAULT: bool = true; - fn should_run(builder: &Builder, path: &Path) -> bool { - path.ends_with("src/librustc") || - builder.crates("rustc-main").into_iter().any(|(_, krate_path)| { - path.ends_with(krate_path) - }) + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/librustc").krate("rustc-main") } fn make_run( @@ -700,8 +691,8 @@ struct RustcLink { impl Step for RustcLink { type Output = (); - fn should_run(_builder: &Builder, _path: &Path) -> bool { - false + fn should_run(run: ShouldRun) -> ShouldRun { + run.never() } /// Same as `std_link`, only for librustc @@ -756,8 +747,8 @@ pub struct Sysroot { impl Step for Sysroot { type Output = Interned; - fn should_run(_builder: &Builder, _path: &Path) -> bool { - false + fn should_run(run: ShouldRun) -> ShouldRun { + run.never() } /// Returns the sysroot for the `compiler` specified that *this build system @@ -806,8 +797,8 @@ pub struct Assemble { impl Step for Assemble { type Output = Compiler; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/rustc") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/rustc") } /// Prepare a new compiler from the artifacts in `stage` diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index e9a2fc7fc1a92..e3d6c74ec221c 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -37,7 +37,7 @@ use build_helper::output; use {Build, Compiler, Mode}; use channel; use util::{cp_r, libdir, is_dylib, cp_filtered, copy, exe}; -use builder::{Builder, Step}; +use builder::{Builder, ShouldRun, Step}; use compile; use tool::{self, Tool}; use cache::{INTERNER, Interned}; @@ -83,8 +83,8 @@ impl Step for Docs { const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/doc") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/doc") } fn make_run( @@ -296,8 +296,8 @@ impl Step for Mingw { const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; - fn should_run(_builder: &Builder, _path: &Path) -> bool { - false + fn should_run(run: ShouldRun) -> ShouldRun { + run.never() } fn make_run( @@ -367,8 +367,8 @@ impl Step for Rustc { const ONLY_HOSTS: bool = true; const ONLY_BUILD_TARGETS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/librustc") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/librustc") } fn make_run( @@ -508,8 +508,8 @@ pub struct DebuggerScripts { impl Step for DebuggerScripts { type Output = (); - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/etc/lldb_batchmode.py") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/lldb_batchmode.py") } fn make_run( @@ -584,8 +584,8 @@ impl Step for Std { const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/libstd") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/libstd") } fn make_run( @@ -666,8 +666,8 @@ impl Step for Analysis { const DEFAULT: bool = true; const ONLY_BUILD_TARGETS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("analysis") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("analysis") } fn make_run( @@ -794,8 +794,8 @@ impl Step for Src { const ONLY_BUILD_TARGETS: bool = true; const ONLY_BUILD: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src") } fn make_run( @@ -893,8 +893,8 @@ impl Step for PlainSourceTarball { const ONLY_BUILD_TARGETS: bool = true; const ONLY_BUILD: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src") } fn make_run( @@ -1046,8 +1046,8 @@ impl Step for Cargo { const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("cargo") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("cargo") } fn make_run( @@ -1144,8 +1144,8 @@ impl Step for Rls { const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("rls") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("rls") } fn make_run( @@ -1240,8 +1240,8 @@ impl Step for Extended { const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("cargo") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("cargo") } fn make_run( @@ -1648,8 +1648,8 @@ impl Step for HashSign { const ONLY_HOSTS: bool = true; const ONLY_BUILD: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("hash-and-sign") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("hash-and-sign") } fn make_run( diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 65110dbaae95b..1fd39ba878f0d 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -27,7 +27,7 @@ use Mode; use build_helper::up_to_date; use util::{cp_r, symlink_dir}; -use builder::{Builder, Step}; +use builder::{Builder, ShouldRun, Step}; use tool::Tool; use compile; use cache::{INTERNER, Interned}; @@ -44,8 +44,8 @@ macro_rules! book { type Output = (); const DEFAULT: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with($path) + fn should_run(run: ShouldRun) -> ShouldRun { + run.path($path) } fn make_run( @@ -99,7 +99,7 @@ book!( ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Rustbook { +struct Rustbook { target: Interned, name: Interned, } @@ -109,8 +109,8 @@ impl Step for Rustbook { // rustbook is never directly called, and only serves as a shim for the nomicon and the // reference. - fn should_run(_builder: &Builder, _path: &Path) -> bool { - false + fn should_run(run: ShouldRun) -> ShouldRun { + run.never() } /// Invoke `rustbook` for `target` for the doc book `name`. @@ -149,8 +149,8 @@ impl Step for UnstableBook { type Output = (); const DEFAULT: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/doc/unstable-book") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/doc/unstable-book") } fn make_run( @@ -179,7 +179,7 @@ impl Step for UnstableBook { } #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct RustbookSrc { +struct RustbookSrc { target: Interned, name: Interned, src: Interned, @@ -188,9 +188,8 @@ pub struct RustbookSrc { impl Step for RustbookSrc { type Output = (); - fn should_run(_builder: &Builder, _path: &Path) -> bool { - // RustbookSrc is also never run directly, only as a helper to other rules - false + fn should_run(run: ShouldRun) -> ShouldRun { + run.never() } /// Invoke `rustbook` for `target` for the doc book `name` from the `src` path. @@ -242,8 +241,8 @@ impl Step for TheBook { type Output = (); const DEFAULT: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/doc/book") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/doc/book") } fn make_run( @@ -366,8 +365,8 @@ impl Step for Standalone { type Output = (); const DEFAULT: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/doc") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/doc") } fn make_run( @@ -475,12 +474,11 @@ impl Step for Std { type Output = (); const DEFAULT: bool = true; - fn should_run(builder: &Builder, path: &Path) -> bool { - builder.crates("std").into_iter().any(|(_, krate_path)| { - path.ends_with(krate_path) - }) + fn should_run(run: ShouldRun) -> ShouldRun { + run.krate("std") } + fn make_run( builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned ) { @@ -588,10 +586,8 @@ impl Step for Test { type Output = (); const DEFAULT: bool = true; - fn should_run(builder: &Builder, path: &Path) -> bool { - builder.crates("test").into_iter().any(|(_, krate_path)| { - path.ends_with(krate_path) - }) + fn should_run(run: ShouldRun) -> ShouldRun { + run.krate("test") } fn make_run( @@ -678,10 +674,8 @@ impl Step for Rustc { const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - fn should_run(builder: &Builder, path: &Path) -> bool { - builder.crates("rustc-main").into_iter().any(|(_, krate_path)| { - path.ends_with(krate_path) - }) + fn should_run(run: ShouldRun) -> ShouldRun { + run.krate("rustc-main") } fn make_run( @@ -780,8 +774,8 @@ impl Step for ErrorIndex { const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/tools/error_index_generator") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/error_index_generator") } fn make_run( @@ -844,8 +838,8 @@ impl Step for UnstableBookGen { const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/doc/unstable-book") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/unstable-book-gen") } fn make_run( diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index b1ea441795e77..1a3a008ed2614 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -23,6 +23,7 @@ use getopts::Options; use Build; use config::Config; use metadata; +use builder::Builder; use cache::{Interned, INTERNER}; @@ -248,11 +249,8 @@ Arguments: let mut build = Build::new(flags, config); metadata::build(&mut build); - // FIXME: How should this happen now? Not super clear... - // let maybe_rules_help = step::build_rules(&build).get_help(subcommand); - // if maybe_rules_help.is_some() { - // extra_help.push_str(maybe_rules_help.unwrap().as_str()); - // } + let maybe_rules_help = Builder::get_help(&build, subcommand.as_str()); + extra_help.push_str(maybe_rules_help.unwrap_or_default().as_str()); } else { extra_help.push_str(format!("Run `./x.py {} -h -v` to see a list of available paths.", subcommand).as_str()); diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 6b6160f43caf3..fac69f89dc1d1 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -20,7 +20,7 @@ use std::process::Command; use dist::{self, pkgname, sanitize_sh, tmpdir}; -use builder::{Builder, Step}; +use builder::{Builder, ShouldRun, Step}; use cache::Interned; pub fn install_docs(builder: &Builder, stage: u32, host: Interned) { @@ -149,8 +149,8 @@ macro_rules! install { const ONLY_HOSTS: bool = $only_hosts; $(const $c: bool = true;)* - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with($path) + fn should_run(run: ShouldRun) -> ShouldRun { + run.path($path) } fn make_run( diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index b60a3760eb288..af13d86649734 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -32,7 +32,7 @@ use gcc; use Build; use util; use build_helper::up_to_date; -use builder::{Builder, Step}; +use builder::{Builder, ShouldRun, Step}; use cache::Interned; // rules.build("llvm", "src/llvm") @@ -55,8 +55,8 @@ impl Step for Llvm { type Output = (); const ONLY_HOSTS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/llvm") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/llvm") } /// Compile LLVM for `target`. @@ -257,8 +257,8 @@ pub struct TestHelpers { impl Step for TestHelpers { type Output = (); - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/rt/rust_test_helpers.c") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/rt/rust_test_helpers.c") } fn make_run( @@ -322,8 +322,8 @@ pub struct Openssl { impl Step for Openssl { type Output = (); - fn should_run(_builder: &Builder, _path: &Path) -> bool { - false + fn should_run(run: ShouldRun) -> ShouldRun { + run.never() } fn run(self, builder: &Builder) { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 9c5592cd61bfa..9554eb3e2a5bd 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -14,7 +14,7 @@ use std::process::Command; use Mode; use Compiler; -use builder::{Step, Builder}; +use builder::{Step, ShouldRun, Builder}; use util::{exe, add_lib_path}; use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp, Rustc}; use native; @@ -55,8 +55,8 @@ pub struct CleanTools { impl Step for CleanTools { type Output = (); - fn should_run(_builder: &Builder, _path: &Path) -> bool { - false + fn should_run(run: ShouldRun) -> ShouldRun { + run.never() } /// Build a tool in `src/tools` @@ -93,8 +93,8 @@ pub struct ToolBuild { impl Step for ToolBuild { type Output = PathBuf; - fn should_run(_builder: &Builder, _path: &Path) -> bool { - false + fn should_run(run: ShouldRun) -> ShouldRun { + run.never() } /// Build a tool in `src/tools` @@ -183,8 +183,8 @@ macro_rules! tool { impl Step for $name { type Output = PathBuf; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with($path) + fn should_run(run: ShouldRun) -> ShouldRun { + run.path($path) } fn make_run( @@ -274,8 +274,8 @@ pub struct RemoteTestServer { impl Step for RemoteTestServer { type Output = PathBuf; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/tools/remote-test-server") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/remote-test-server") } fn make_run( @@ -325,8 +325,8 @@ impl Step for Cargo { const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/tools/cargo") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/cargo") } fn make_run( @@ -384,8 +384,8 @@ impl Step for Rls { const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; - fn should_run(_builder: &Builder, path: &Path) -> bool { - path.ends_with("src/tools/rls") + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/tools/rls") } fn make_run( From 5bdec80fe3989321c85545b4d6ee7719f1f568cb Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 19 Jul 2017 06:55:46 -0600 Subject: [PATCH 39/51] Allow iterating over step descriptions. This simplifies code and allows working mostly with normal Rust instead of macros. --- src/bootstrap/builder.rs | 220 ++++++++++++++++++++------------------- 1 file changed, 113 insertions(+), 107 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 8613bc7a7ba91..02d65289c9cf0 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -93,6 +93,89 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { } } +struct StepDescription { + default: bool, + only_hosts: bool, + only_build_targets: bool, + only_build: bool, + should_run: fn(ShouldRun) -> ShouldRun, + make_run: fn(&Builder, Option<&Path>, Interned, Interned), +} + +impl StepDescription { + fn from() -> StepDescription { + StepDescription { + default: S::DEFAULT, + only_hosts: S::ONLY_HOSTS, + only_build_targets: S::ONLY_BUILD_TARGETS, + only_build: S::ONLY_BUILD, + should_run: S::should_run, + make_run: S::make_run, + } + } + + fn maybe_run(&self, builder: &Builder, path: Option<&Path>) { + let build = builder.build; + let hosts = if self.only_build_targets || self.only_build { + &build.config.host[..1] + } else { + &build.hosts + }; + + // Determine the actual targets participating in this rule. + // NOTE: We should keep the full projection from build triple to + // the hosts for the dist steps, now that the hosts array above is + // truncated to avoid duplication of work in that case. Therefore + // the original non-shadowed hosts array is used below. + let targets = if self.only_hosts { + // If --target was specified but --host wasn't specified, + // don't run any host-only tests. Also, respect any `--host` + // overrides as done for `hosts`. + if build.flags.host.len() > 0 { + &build.flags.host[..] + } else if build.flags.target.len() > 0 { + &[] + } else if self.only_build { + &build.config.host[..1] + } else { + &build.config.host[..] + } + } else { + &build.targets + }; + + for host in hosts { + for target in targets { + (self.make_run)(builder, path, *host, *target); + } + } + } + + fn run(v: &[StepDescription], builder: &Builder, paths: &[PathBuf]) { + if paths.is_empty() { + for desc in v { + if desc.default { + desc.maybe_run(builder, None); + } + } + } else { + for path in paths { + let mut attempted_run = false; + for desc in v { + if (desc.should_run)(ShouldRun::new(builder)).run(path) { + attempted_run = true; + desc.maybe_run(builder, Some(path)); + } + } + + if !attempted_run { + eprintln!("Warning: no rules matched {}.", path.display()); + } + } + } + } +} + #[derive(Clone)] pub struct ShouldRun<'a> { builder: &'a Builder<'a>, @@ -140,33 +223,34 @@ pub enum Kind { Install, } -macro_rules! check { - ($self:ident, $paths:ident, $($rule:ty),+ $(,)*) => {{ - let paths = $paths; - if paths.is_empty() { - $({ - if <$rule>::DEFAULT { - $self.maybe_run::<$rule>(None); - } - })+ - } else { - for path in paths { - let mut attempted_run = false; - $({ - if <$rule>::should_run(ShouldRun::new($self)).run(path) { - attempted_run = true; - $self.maybe_run::<$rule>(Some(path)); - } - })+ - if !attempted_run { - eprintln!("Warning: no rules matched {}.", path.display()); - } - } +impl<'a> Builder<'a> { + fn get_step_descriptions(kind: Kind) -> Vec { + macro_rules! describe { + ($($rule:ty),+ $(,)*) => {{ + vec![$(StepDescription::from::<$rule>()),+] + }}; } - }}; -} + match kind { + Kind::Build => describe!(compile::Std, compile::Test, compile::Rustc, + compile::StartupObjects, tool::BuildManifest, tool::Rustbook, tool::ErrorIndex, + tool::UnstableBookGen, tool::Tidy, tool::Linkchecker, tool::CargoTest, + tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient, + tool::RustInstaller, tool::Cargo, tool::Rls), + Kind::Test => describe!(check::Tidy, check::Bootstrap, check::Compiletest, check::Crate, + check::CrateLibrustc, check::Linkcheck, check::Cargotest, check::Cargo, check::Docs, + check::ErrorIndex, check::Distcheck), + Kind::Bench => describe!(check::Crate, check::CrateLibrustc), + Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, + doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon, + doc::Reference), + Kind::Dist => describe!(dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts, + dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo, + dist::Rls, dist::Extended, dist::HashSign), + Kind::Install => describe!(install::Docs, install::Std, install::Cargo, install::Rls, + install::Analysis, install::Src, install::Rustc), + } + } -impl<'a> Builder<'a> { pub fn get_help(build: &Build, subcommand: &str) -> Option { let kind = match subcommand { "build" => Kind::Build, @@ -188,31 +272,8 @@ impl<'a> Builder<'a> { let builder = &builder; let mut should_run = ShouldRun::new(builder); - macro_rules! into_shouldrun { - ($should_run:ident, $($rule:ty),+ $(,)*) => {{ - $( - $should_run = <$rule>::should_run($should_run); - )+ - }}; - } - match builder.kind { - Kind::Build => into_shouldrun!(should_run, compile::Std, compile::Test, compile::Rustc, - compile::StartupObjects, tool::BuildManifest, tool::Rustbook, tool::ErrorIndex, - tool::UnstableBookGen, tool::Tidy, tool::Linkchecker, tool::CargoTest, - tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient, - tool::RustInstaller, tool::Cargo, tool::Rls), - Kind::Test => into_shouldrun!(should_run, check::Tidy, check::Bootstrap, - check::Compiletest, check::Crate, check::CrateLibrustc, check::Linkcheck, - check::Cargotest, check::Cargo, check::Docs, check::ErrorIndex, check::Distcheck), - Kind::Bench => into_shouldrun!(should_run, check::Crate, check::CrateLibrustc), - Kind::Doc => into_shouldrun!(should_run, doc::UnstableBook, doc::UnstableBookGen, - doc::TheBook, doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, - doc::Nomicon, doc::Reference), - Kind::Dist => into_shouldrun!(should_run, dist::Docs, dist::Mingw, dist::Rustc, - dist::DebuggerScripts, dist::Std, dist::Analysis, dist::Src, - dist::PlainSourceTarball, dist::Cargo, dist::Rls, dist::Extended, dist::HashSign), - Kind::Install => into_shouldrun!(should_run, install::Docs, install::Std, - install::Cargo, install::Rls, install::Analysis, install::Src, install::Rustc), + for desc in Builder::get_step_descriptions(builder.kind) { + should_run = (desc.should_run)(should_run); } let mut help = String::from("Available paths:\n"); for path in should_run.paths { @@ -240,30 +301,12 @@ impl<'a> Builder<'a> { stack: RefCell::new(Vec::new()), }; - let builder = &builder; - match builder.kind { - Kind::Build => check!(builder, paths, compile::Std, compile::Test, compile::Rustc, - compile::StartupObjects, tool::BuildManifest, tool::Rustbook, tool::ErrorIndex, - tool::UnstableBookGen, tool::Tidy, tool::Linkchecker, tool::CargoTest, - tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient, - tool::RustInstaller, tool::Cargo, tool::Rls), - Kind::Test => check!(builder, paths, check::Tidy, check::Bootstrap, check::Compiletest, - check::Crate, check::CrateLibrustc, check::Linkcheck, check::Cargotest, - check::Cargo, check::Docs, check::ErrorIndex, check::Distcheck), - Kind::Bench => check!(builder, paths, check::Crate, check::CrateLibrustc), - Kind::Doc => builder.default_doc(Some(paths)), - Kind::Dist => check!(builder, paths, dist::Docs, dist::Mingw, dist::Rustc, - dist::DebuggerScripts, dist::Std, dist::Analysis, dist::Src, - dist::PlainSourceTarball, dist::Cargo, dist::Rls, dist::Extended, dist::HashSign), - Kind::Install => check!(builder, paths, install::Docs, install::Std, install::Cargo, - install::Rls, install::Analysis, install::Src, install::Rustc), - } + StepDescription::run(&Builder::get_step_descriptions(builder.kind), &builder, paths); } pub fn default_doc(&self, paths: Option<&[PathBuf]>) { let paths = paths.unwrap_or(&[]); - check!(self, paths, doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, doc::Standalone, - doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon, doc::Reference); + StepDescription::run(&Builder::get_step_descriptions(Kind::Doc), self, paths); } /// Obtain a compiler at a given stage and for a given host. Explictly does @@ -514,43 +557,6 @@ impl<'a> Builder<'a> { cargo } - fn maybe_run(&self, path: Option<&Path>) { - let build = self.build; - let hosts = if S::ONLY_BUILD_TARGETS || S::ONLY_BUILD { - &build.config.host[..1] - } else { - &build.hosts - }; - - // Determine the actual targets participating in this rule. - // NOTE: We should keep the full projection from build triple to - // the hosts for the dist steps, now that the hosts array above is - // truncated to avoid duplication of work in that case. Therefore - // the original non-shadowed hosts array is used below. - let targets = if S::ONLY_HOSTS { - // If --target was specified but --host wasn't specified, - // don't run any host-only tests. Also, respect any `--host` - // overrides as done for `hosts`. - if build.flags.host.len() > 0 { - &build.flags.host[..] - } else if build.flags.target.len() > 0 { - &[] - } else if S::ONLY_BUILD { - &build.config.host[..1] - } else { - &build.config.host[..] - } - } else { - &build.targets - }; - - for host in hosts { - for target in targets { - S::make_run(self, path, *host, *target); - } - } - } - /// Ensure that a given step is built, returning it's output. This will /// cache the step, so it is safe (and good!) to call this as often as /// needed to ensure that all dependencies are built. From 4a21c72fb08f13e0d3a7a94a9ef7b690de3914d3 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 20 Jul 2017 06:27:13 -0600 Subject: [PATCH 40/51] Fix a few issues found by comparing past/present --- src/bootstrap/check.rs | 6 ++---- src/bootstrap/tool.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 847307959cb8d..edb84829ee219 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -233,6 +233,7 @@ impl Step for Cargo { let build = builder.build; let compiler = builder.compiler(self.stage, self.host); + builder.ensure(tool::Cargo { stage: self.stage, target: self.host }); let mut cargo = builder.cargo(compiler, Mode::Tool, self.host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml")); if !build.fail_fast { @@ -287,6 +288,7 @@ impl Step for Rls { let host = self.host; let compiler = builder.compiler(stage, host); + builder.ensure(tool::Rls { stage: self.stage, target: self.host }); let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/rls/Cargo.toml")); @@ -629,10 +631,6 @@ impl Step for Compiletest { sysroot: builder.sysroot(compiler), target: target }); - - if mode == "debuginfo-gdb" { - builder.ensure(RemoteCopyLibs { compiler, target }); - } } if suite.ends_with("fulldeps") || diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 9554eb3e2a5bd..41dc91f5a2ca8 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -16,7 +16,7 @@ use Mode; use Compiler; use builder::{Step, ShouldRun, Builder}; use util::{exe, add_lib_path}; -use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp, Rustc}; +use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp}; use native; use channel::GitInfo; use cache::Interned; @@ -347,8 +347,8 @@ impl Step for Cargo { }); // Cargo depends on procedural macros, which requires a full host // compiler to be available, so we need to depend on that. - builder.ensure(Rustc { - compiler: builder.compiler(builder.top_stage, builder.build.build), + builder.ensure(compile::Rustc { + compiler: builder.compiler(self.stage, builder.build.build), target: builder.build.build, }); builder.ensure(ToolBuild { @@ -394,7 +394,7 @@ impl Step for Rls { if path.is_none() && !builder.build.config.extended { return; } - builder.ensure(Cargo { + builder.ensure(Rls { stage: builder.top_stage, target, }); @@ -406,8 +406,8 @@ impl Step for Rls { }); // RLS depends on procedural macros, which requires a full host // compiler to be available, so we need to depend on that. - builder.ensure(Rustc { - compiler: builder.compiler(builder.top_stage, builder.build.build), + builder.ensure(compile::Rustc { + compiler: builder.compiler(self.stage, builder.build.build), target: builder.build.build, }); builder.ensure(ToolBuild { From f1d04a3434ea6a57addac9c205580d80e8b5837c Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 20 Jul 2017 09:42:18 -0600 Subject: [PATCH 41/51] Don't run host-only tests when targeting another platform --- src/bootstrap/builder.rs | 6 +- src/bootstrap/check.rs | 150 +++++++++++++++++++++++++++++---------- 2 files changed, 114 insertions(+), 42 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 02d65289c9cf0..c1dd2ad15a1e1 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -236,9 +236,9 @@ impl<'a> Builder<'a> { tool::UnstableBookGen, tool::Tidy, tool::Linkchecker, tool::CargoTest, tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient, tool::RustInstaller, tool::Cargo, tool::Rls), - Kind::Test => describe!(check::Tidy, check::Bootstrap, check::Compiletest, check::Crate, - check::CrateLibrustc, check::Linkcheck, check::Cargotest, check::Cargo, check::Docs, - check::ErrorIndex, check::Distcheck), + Kind::Test => describe!(check::Tidy, check::Bootstrap, check::DefaultCompiletest, + check::HostCompiletest, check::Crate, check::CrateLibrustc, check::Linkcheck, + check::Cargotest, check::Cargo, check::Docs, check::ErrorIndex, check::Distcheck), Kind::Bench => describe!(check::Crate, check::CrateLibrustc), Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon, diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index edb84829ee219..4be013e480e34 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -468,14 +468,6 @@ fn testdir(build: &Build, host: Interned) -> PathBuf { // "pretty", "run-fail-fulldeps"); // } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct Compiletest { - compiler: Compiler, - target: Interned, - mode: &'static str, - suite: &'static str, -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] struct Test { path: &'static str, @@ -501,8 +493,74 @@ static DEFAULT_COMPILETESTS: &[Test] = &[ // What this runs varies depending on the native platform being apple Test { path: "src/test/debuginfo", mode: "debuginfo-XXX", suite: "debuginfo" }, + Test { path: "src/test/debuginfo-lldb", mode: "debuginfo-lldb", suite: "debuginfo" }, + Test { path: "src/test/debuginfo-gdb", mode: "debuginfo-gdb", suite: "debuginfo" }, ]; +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct DefaultCompiletest { + compiler: Compiler, + target: Interned, + mode: &'static str, + suite: &'static str, +} + +impl Step for DefaultCompiletest { + type Output = (); + const DEFAULT: bool = true; + + fn should_run(mut run: ShouldRun) -> ShouldRun { + for test in DEFAULT_COMPILETESTS { + run = run.path(test.path); + } + run + } + + fn make_run( + builder: &Builder, + path: Option<&Path>, + host: Interned, + target: Interned, + ) { + let compiler = builder.compiler(builder.top_stage, host); + + let test = path.map(|path| { + DEFAULT_COMPILETESTS.iter().find(|&&test| { + path.ends_with(test.path) + }).unwrap_or_else(|| { + panic!("make_run in compile test to receive test path, received {:?}", path); + }) + }); + + if let Some(test) = test { + builder.ensure(DefaultCompiletest { + compiler, + target, + mode: test.mode, + suite: test.suite, + }); + } else { + for test in DEFAULT_COMPILETESTS { + builder.ensure(DefaultCompiletest { + compiler, + target, + mode: test.mode, + suite: test.suite + }); + } + } + } + + fn run(self, builder: &Builder) { + builder.ensure(Compiletest { + compiler: self.compiler, + target: self.target, + mode: self.mode, + suite: self.suite, + }) + } +} + // Also default, but host-only. static HOST_COMPILETESTS: &[Test] = &[ Test { path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-fulldeps" }, @@ -524,20 +582,21 @@ static HOST_COMPILETESTS: &[Test] = &[ Test { path: "src/test/run-fail-fulldeps/pretty", mode: "pretty", suite: "run-fail-fulldeps" }, ]; -static COMPILETESTS: &[Test] = &[ - Test { path: "src/test/debuginfo-lldb", mode: "debuginfo-lldb", suite: "debuginfo" }, - Test { path: "src/test/debuginfo-gdb", mode: "debuginfo-gdb", suite: "debuginfo" }, -]; +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct HostCompiletest { + compiler: Compiler, + target: Interned, + mode: &'static str, + suite: &'static str, +} -impl Step for Compiletest { +impl Step for HostCompiletest { type Output = (); const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; fn should_run(mut run: ShouldRun) -> ShouldRun { - // Note that this is general, while a few more cases are skipped inside - // run() itself. This is to avoid duplication across should_run and - // make_run. - for test in COMPILETESTS.iter().chain(DEFAULT_COMPILETESTS).chain(HOST_COMPILETESTS) { + for test in HOST_COMPILETESTS { run = run.path(test.path); } run @@ -552,44 +611,57 @@ impl Step for Compiletest { let compiler = builder.compiler(builder.top_stage, host); let test = path.map(|path| { - COMPILETESTS.iter().chain(DEFAULT_COMPILETESTS).chain(HOST_COMPILETESTS).find(|&&test| { + HOST_COMPILETESTS.iter().find(|&&test| { path.ends_with(test.path) }).unwrap_or_else(|| { panic!("make_run in compile test to receive test path, received {:?}", path); }) }); - if let Some(test) = test { // specific test - let target = if HOST_COMPILETESTS.contains(test) { - host - } else { - target - }; - builder.ensure(Compiletest { - compiler, target, mode: test.mode, suite: test.suite + if let Some(test) = test { + builder.ensure(HostCompiletest { + compiler, + target, + mode: test.mode, + suite: test.suite, }); - } else { // default tests - for test in DEFAULT_COMPILETESTS { - builder.ensure(Compiletest { + } else { + for test in HOST_COMPILETESTS { + builder.ensure(HostCompiletest { compiler, target, mode: test.mode, suite: test.suite }); } - for test in HOST_COMPILETESTS { - if test.mode != "pretty" { - builder.ensure(Compiletest { - compiler, - target: host, - mode: test.mode, - suite: test.suite - }); - } - } } } + fn run(self, builder: &Builder) { + builder.ensure(Compiletest { + compiler: self.compiler, + target: self.target, + mode: self.mode, + suite: self.suite, + }) + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +struct Compiletest { + compiler: Compiler, + target: Interned, + mode: &'static str, + suite: &'static str, +} + +impl Step for Compiletest { + type Output = (); + + fn should_run(run: ShouldRun) -> ShouldRun { + run.never() + } + /// Executes the `compiletest` tool to run a suite of tests. /// /// Compiles all tests with `compiler` for `target` with the specified From 951616cac65c8d5218ac9047bb1d6163c6cd118c Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 20 Jul 2017 11:23:29 -0600 Subject: [PATCH 42/51] Don't include lldb/gdb in default tests --- src/bootstrap/check.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 4be013e480e34..98c3df58f87e3 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -493,8 +493,6 @@ static DEFAULT_COMPILETESTS: &[Test] = &[ // What this runs varies depending on the native platform being apple Test { path: "src/test/debuginfo", mode: "debuginfo-XXX", suite: "debuginfo" }, - Test { path: "src/test/debuginfo-lldb", mode: "debuginfo-lldb", suite: "debuginfo" }, - Test { path: "src/test/debuginfo-gdb", mode: "debuginfo-gdb", suite: "debuginfo" }, ]; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -680,6 +678,11 @@ impl Step for Compiletest { } if suite == "debuginfo" { + // Skip debuginfo tests on MSVC + if build.build.contains("msvc") { + return; + } + if mode == "debuginfo-XXX" { return if build.build.contains("apple") { builder.ensure(Compiletest { @@ -694,11 +697,6 @@ impl Step for Compiletest { }; } - // Skip debuginfo tests on MSVC - if build.build.contains("msvc") { - return; - } - builder.ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), target: target From bcd73c96579e2cbe677ff5e2bf493f516436a818 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 20 Jul 2017 16:16:31 -0600 Subject: [PATCH 43/51] Change default documentation rules to correspond with previous state. --- src/bootstrap/doc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 1fd39ba878f0d..2484fc5bf8839 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -607,7 +607,7 @@ impl Step for Test { } } } else { - if builder.build.config.docs { + if builder.build.config.compiler_docs { run(); } } @@ -695,7 +695,7 @@ impl Step for Rustc { } } } else { - if builder.build.config.compiler_docs { + if builder.build.config.docs { run(); } } From 8563280bec619bca0833074657ec033e1aa0b50a Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 20 Jul 2017 16:33:04 -0600 Subject: [PATCH 44/51] Check RLS tests --- src/bootstrap/builder.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index c1dd2ad15a1e1..dd24e8705beb3 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -238,7 +238,8 @@ impl<'a> Builder<'a> { tool::RustInstaller, tool::Cargo, tool::Rls), Kind::Test => describe!(check::Tidy, check::Bootstrap, check::DefaultCompiletest, check::HostCompiletest, check::Crate, check::CrateLibrustc, check::Linkcheck, - check::Cargotest, check::Cargo, check::Docs, check::ErrorIndex, check::Distcheck), + check::Cargotest, check::Cargo, check::Rls, check::Docs, check::ErrorIndex, + check::Distcheck), Kind::Bench => describe!(check::Crate, check::CrateLibrustc), Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon, From e9c2242050cd18f10573400ea50073f5dc8153b0 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 20 Jul 2017 16:41:26 -0600 Subject: [PATCH 45/51] Remove step.rs comments --- src/bootstrap/check.rs | 231 --------------------------------------- src/bootstrap/compile.rs | 162 --------------------------- src/bootstrap/dist.rs | 110 ------------------- src/bootstrap/doc.rs | 97 ---------------- src/bootstrap/install.rs | 40 ------- src/bootstrap/native.rs | 19 +--- src/bootstrap/tool.rs | 91 --------------- 7 files changed, 1 insertion(+), 749 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 98c3df58f87e3..16f14638b51c5 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -87,13 +87,6 @@ fn try_run_quiet(build: &Build, cmd: &mut Command) { } } -// rules.test("check-linkchecker", "src/tools/linkchecker") -// .dep(|s| s.name("tool-linkchecker").stage(0)) -// .dep(|s| s.name("default:doc")) -// .default(build.config.docs) -// .host(true) -// .run(move |s| check::linkcheck(build, s.target)); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Linkcheck { host: Interned, @@ -141,12 +134,6 @@ impl Step for Linkcheck { } } -// rules.test("check-cargotest", "src/tools/cargotest") -// .dep(|s| s.name("tool-cargotest").stage(0)) -// .dep(|s| s.name("librustc")) -// .host(true) -// .run(move |s| check::cargotest(build, s.stage, s.target)); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Cargotest { stage: u32, @@ -197,11 +184,6 @@ impl Step for Cargotest { } } -//rules.test("check-cargo", "cargo") -// .dep(|s| s.name("tool-cargo")) -// .host(true) -// .run(move |s| check::cargo(build, s.stage, s.target)); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Cargo { stage: u32, @@ -257,10 +239,6 @@ pub struct Rls { host: Interned, } -// rules.test("check-rls", "src/tools/rls") -// .dep(|s| s.name("tool-rls")) -// .host(true) -// .run(move |s| check::rls(build, s.stage, s.target)); impl Step for Rls { type Output = (); const ONLY_HOSTS: bool = true; @@ -310,13 +288,6 @@ fn path_for_cargo(builder: &Builder, compiler: Compiler) -> OsString { env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("") } -//rules.test("check-tidy", "src/tools/tidy") -// .dep(|s| s.name("tool-tidy").stage(0)) -// .default(true) -// .host(true) -// .only_build(true) -// .run(move |s| check::tidy(build, s.target)); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Tidy { host: Interned, @@ -370,104 +341,6 @@ fn testdir(build: &Build, host: Interned) -> PathBuf { build.out.join(host).join("test") } -// // ======================================================================== -// // Test targets -// // -// // Various unit tests and tests suites we can run -// { -// let mut suite = |name, path, mode, dir| { -// rules.test(name, path) -// .dep(|s| s.name("libtest")) -// .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) -// .dep(|s| s.name("test-helpers")) -// .dep(|s| s.name("remote-copy-libs")) -// .default(mode != "pretty") // pretty tests don't run everywhere -// .run(move |s| { -// check::compiletest(build, &s.compiler(), s.target, mode, dir) -// }); -// }; -// -// suite("check-ui", "src/test/ui", "ui", "ui"); -// suite("check-rpass", "src/test/run-pass", "run-pass", "run-pass"); -// suite("check-cfail", "src/test/compile-fail", "compile-fail", "compile-fail"); -// suite("check-pfail", "src/test/parse-fail", "parse-fail", "parse-fail"); -// suite("check-rfail", "src/test/run-fail", "run-fail", "run-fail"); -// suite("check-rpass-valgrind", "src/test/run-pass-valgrind", -// "run-pass-valgrind", "run-pass-valgrind"); -// suite("check-mir-opt", "src/test/mir-opt", "mir-opt", "mir-opt"); -// if build.config.codegen_tests { -// suite("check-codegen", "src/test/codegen", "codegen", "codegen"); -// } -// suite("check-codegen-units", "src/test/codegen-units", "codegen-units", -// "codegen-units"); -// suite("check-incremental", "src/test/incremental", "incremental", -// "incremental"); -// } -// -// if build.build.contains("msvc") { -// // nothing to do for debuginfo tests -// } else { -// rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb") -// .dep(|s| s.name("libtest")) -// .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) -// .dep(|s| s.name("test-helpers")) -// .dep(|s| s.name("debugger-scripts")) -// .run(move |s| check::compiletest(build, &s.compiler(), s.target, -// "debuginfo-lldb", "debuginfo")); -// rules.test("check-debuginfo-gdb", "src/test/debuginfo-gdb") -// .dep(|s| s.name("libtest")) -// .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) -// .dep(|s| s.name("test-helpers")) -// .dep(|s| s.name("debugger-scripts")) -// .dep(|s| s.name("remote-copy-libs")) -// .run(move |s| check::compiletest(build, &s.compiler(), s.target, -// "debuginfo-gdb", "debuginfo")); -// let mut rule = rules.test("check-debuginfo", "src/test/debuginfo"); -// rule.default(true); -// if build.build.contains("apple") { -// rule.dep(|s| s.name("check-debuginfo-lldb")); -// } else { -// rule.dep(|s| s.name("check-debuginfo-gdb")); -// } -// } -// -// -// -// { -// let mut suite = |name, path, mode, dir| { -// rules.test(name, path) -// .dep(|s| s.name("librustc")) -// .dep(|s| s.name("test-helpers")) -// .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) -// .default(mode != "pretty") -// .host(true) -// .run(move |s| { -// check::compiletest(build, &s.compiler(), s.target, mode, dir) -// }); -// }; -// -// suite("check-ui-full", "src/test/ui-fulldeps", "ui", "ui-fulldeps"); -// suite("check-rpass-full", "src/test/run-pass-fulldeps", -// "run-pass", "run-pass-fulldeps"); -// suite("check-rfail-full", "src/test/run-fail-fulldeps", -// "run-fail", "run-fail-fulldeps"); -// suite("check-cfail-full", "src/test/compile-fail-fulldeps", -// "compile-fail", "compile-fail-fulldeps"); -// suite("check-rmake", "src/test/run-make", "run-make", "run-make"); -// suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc"); -// suite("check-pretty", "src/test/pretty", "pretty", "pretty"); -// suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty", -// "run-pass"); -// suite("check-pretty-rfail", "src/test/run-fail/pretty", "pretty", -// "run-fail"); -// suite("check-pretty-valgrind", "src/test/run-pass-valgrind/pretty", "pretty", -// "run-pass-valgrind"); -// suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps/pretty", -// "pretty", "run-pass-fulldeps"); -// suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps/pretty", -// "pretty", "run-fail-fulldeps"); -// } - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] struct Test { path: &'static str, @@ -862,11 +735,6 @@ pub struct Docs { compiler: Compiler, } -// rules.test("check-docs", "src/doc") -// .dep(|s| s.name("libtest")) -// .default(true) -// .host(true) -// .run(move |s| check::docs(build, &s.compiler())); impl Step for Docs { type Output = (); const DEFAULT: bool = true; @@ -925,13 +793,6 @@ impl Step for Docs { } } -//rules.test("check-error-index", "src/tools/error_index_generator") -// .dep(|s| s.name("libstd")) -// .dep(|s| s.name("tool-error-index").host(s.host).stage(0)) -// .default(true) -// .host(true) -// .run(move |s| check::error_index(build, &s.compiler())); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct ErrorIndex { compiler: Compiler, @@ -1013,22 +874,6 @@ fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) { } } -// for (krate, path, _default) in krates("rustc-main") { -// rules.test(&krate.test_step, path) -// .dep(|s| s.name("librustc")) -// .dep(|s| s.name("remote-copy-libs")) -// .host(true) -// .run(move |s| check::krate(build, &s.compiler(), s.target, -// Mode::Librustc, TestKind::Test, -// Some(&krate.name))); -// } -// rules.test("check-rustc-all", "path/to/nowhere") -// .dep(|s| s.name("librustc")) -// .dep(|s| s.name("remote-copy-libs")) -// .default(true) -// .host(true) -// .run(move |s| check::krate(build, &s.compiler(), s.target, -// Mode::Librustc, TestKind::Test, None)); #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct CrateLibrustc { compiler: Compiler, @@ -1095,52 +940,6 @@ impl Step for CrateLibrustc { } -// for (krate, path, _default) in krates("std") { -// rules.test(&krate.test_step, path) -// .dep(|s| s.name("libtest")) -// .dep(|s| s.name("remote-copy-libs")) -// .run(move |s| check::krate(build, &s.compiler(), s.target, -// Mode::Libstd, TestKind::Test, -// Some(&krate.name))); -// } -// rules.test("check-std-all", "path/to/nowhere") -// .dep(|s| s.name("libtest")) -// .dep(|s| s.name("remote-copy-libs")) -// .default(true) -// .run(move |s| check::krate(build, &s.compiler(), s.target, -// Mode::Libstd, TestKind::Test, None)); -// -// // std benchmarks -// for (krate, path, _default) in krates("std") { -// rules.bench(&krate.bench_step, path) -// .dep(|s| s.name("libtest")) -// .dep(|s| s.name("remote-copy-libs")) -// .run(move |s| check::krate(build, &s.compiler(), s.target, -// Mode::Libstd, TestKind::Bench, -// Some(&krate.name))); -// } -// rules.bench("bench-std-all", "path/to/nowhere") -// .dep(|s| s.name("libtest")) -// .dep(|s| s.name("remote-copy-libs")) -// .default(true) -// .run(move |s| check::krate(build, &s.compiler(), s.target, -// Mode::Libstd, TestKind::Bench, None)); -// -// for (krate, path, _default) in krates("test") { -// rules.test(&krate.test_step, path) -// .dep(|s| s.name("libtest")) -// .dep(|s| s.name("remote-copy-libs")) -// .run(move |s| check::krate(build, &s.compiler(), s.target, -// Mode::Libtest, TestKind::Test, -// Some(&krate.name))); -// } -// rules.test("check-test-all", "path/to/nowhere") -// .dep(|s| s.name("libtest")) -// .dep(|s| s.name("remote-copy-libs")) -// .default(true) -// .run(move |s| check::krate(build, &s.compiler(), s.target, -// Mode::Libtest, TestKind::Test, None)); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Crate { compiler: Compiler, @@ -1383,25 +1182,6 @@ fn find_tests(dir: &Path, target: Interned) -> Vec { dst } -// rules.test("remote-copy-libs", "path/to/nowhere") -// .dep(|s| s.name("libtest")) -// .dep(move |s| { -// if build.remote_tested(s.target) { -// s.name("tool-remote-test-client").target(s.host).stage(0) -// } else { -// Step::noop() -// } -// }) -// .dep(move |s| { -// if build.remote_tested(s.target) { -// s.name("tool-remote-test-server") -// } else { -// Step::noop() -// } -// }) -// .run(move |s| check::remote_copy_libs(build, &s.compiler(), s.target)); -// - /// Some test suites are run inside emulators or on remote devices, and most /// of our test binaries are linked dynamically which means we need to ship /// the standard library and such to the emulator ahead of time. This step @@ -1464,11 +1244,6 @@ impl Step for RemoteCopyLibs { } } -//rules.test("check-distcheck", "distcheck") -// .dep(|s| s.name("dist-plain-source-tarball")) -// .dep(|s| s.name("dist-src")) -// .run(move |_| check::distcheck(build)); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Distcheck; @@ -1534,12 +1309,6 @@ impl Step for Distcheck { } } -//rules.test("check-bootstrap", "src/bootstrap") -// .default(true) -// .host(true) -// .only_build(true) -// .run(move |_| check::bootstrap(build)); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Bootstrap; diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 134d957220da8..4453f1627ef3a 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -36,112 +36,6 @@ use native; use cache::{INTERNER, Interned}; use builder::{Step, ShouldRun, Builder}; -// -// // Crates which have build scripts need to rely on this rule to ensure that -// // the necessary prerequisites for a build script are linked and located in -// // place. -// rules.build("may-run-build-script", "path/to/nowhere") -// .dep(move |s| { -// s.name("libstd-link") -// .host(&build.build) -// .target(&build.build) -// }); - -// // ======================================================================== -// // Crate compilations -// // -// // Tools used during the build system but not shipped -// // These rules are "pseudo rules" that don't actually do any work -// // themselves, but represent a complete sysroot with the relevant compiler -// // linked into place. -// // -// // That is, depending on "libstd" means that when the rule is completed then -// // the `stage` sysroot for the compiler `host` will be available with a -// // standard library built for `target` linked in place. Not all rules need -// // the compiler itself to be available, just the standard library, so -// // there's a distinction between the two. -// rules.build("libstd", "src/libstd") -// .dep(|s| s.name("rustc").target(s.host)) -// .dep(|s| s.name("libstd-link")); -// rules.build("libtest", "src/libtest") -// .dep(|s| s.name("libstd")) -// .dep(|s| s.name("libtest-link")) -// .default(true); -// rules.build("librustc", "src/librustc") -// .dep(|s| s.name("libtest")) -// .dep(|s| s.name("librustc-link")) -// .host(true) -// .default(true); - -// Helper method to define the rules to link a crate into its place in the -// sysroot. -// -// The logic here is a little subtle as there's a few cases to consider. -// Not all combinations of (stage, host, target) actually require something -// to be compiled, but rather libraries could get propagated from a -// different location. For example: -// -// * Any crate with a `host` that's not the build triple will not actually -// compile something. A different `host` means that the build triple will -// actually compile the libraries, and then we'll copy them over from the -// build triple to the `host` directory. -// -// * Some crates aren't even compiled by the build triple, but may be copied -// from previous stages. For example if we're not doing a full bootstrap -// then we may just depend on the stage1 versions of libraries to be -// available to get linked forward. -// -// * Finally, there are some cases, however, which do indeed comiple crates -// and link them into place afterwards. -// -// The rule definition below mirrors these three cases. The `dep` method -// calculates the correct dependency which either comes from stage1, a -// different compiler, or from actually building the crate itself (the `dep` -// rule). The `run` rule then mirrors these three cases and links the cases -// forward into the compiler sysroot specified from the correct location. -// fn crate_rule<'a, 'b>(build: &'a Build, -// rules: &'b mut Rules<'a>, -// krate: &'a str, -// dep: &'a str, -// link: fn(&Build, compiler, compiler, &str)) -// -> RuleBuilder<'a, 'b> { -// let mut rule = rules.build(&krate, "path/to/nowhere"); -// rule.dep(move |s| { -// if build.force_use_stage1(&s.compiler(), s.target) { -// s.host(&build.build).stage(1) -// } else if s.host == build.build { -// s.name(dep) -// } else { -// s.host(&build.build) -// } -// }) -// .run(move |s| { -// if build.force_use_stage1(&s.compiler(), s.target) { -// link(build, -// &s.stage(1).host(&build.build).compiler(), -// &s.compiler(), -// s.target) -// } else if s.host == build.build { -// link(build, &s.compiler(), &s.compiler(), s.target) -// } else { -// link(build, -// &s.host(&build.build).compiler(), -// &s.compiler(), -// s.target) -// } -// }); -// rule -// } - -// rules.build("libstd", "src/libstd") -// .dep(|s| s.name("rustc").target(s.host)) -// .dep(|s| s.name("libstd-link")); -// for (krate, path, _default) in krates("std") { -// rules.build(&krate.build_step, path) -// .dep(|s| s.name("startup-objects")) -// .dep(move |s| s.name("rustc").host(&build.build).target(s.host)) -// .run(move |s| compile::std(build, s.target, &s.compiler())); -// } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Std { pub target: Interned, @@ -256,14 +150,6 @@ impl Step for Std { } -// crate_rule(build, -// &mut rules, -// "libstd-link", -// "build-crate-std", -// compile::std_link) -// .dep(|s| s.name("startup-objects")) -// .dep(|s| s.name("create-sysroot").target(s.host)); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] struct StdLink { pub compiler: Compiler, @@ -334,10 +220,6 @@ fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) { } } -// rules.build("startup-objects", "src/rtstartup") -// .dep(|s| s.name("create-sysroot").target(s.host)) -// .run(move |s| compile::build_startup_objects(build, &s.compiler(), s.target)); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct StartupObjects { pub compiler: Compiler, @@ -404,11 +286,6 @@ impl Step for StartupObjects { } } -// for (krate, path, _default) in krates("test") { -// rules.build(&krate.build_step, path) -// .dep(|s| s.name("libstd-link")) -// .run(move |s| compile::test(build, s.target, &s.compiler())); -// } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Test { pub compiler: Compiler, @@ -484,14 +361,6 @@ impl Step for Test { } } - -// crate_rule(build, -// &mut rules, -// "libtest-link", -// "build-crate-test", -// compile::test_link) -// .dep(|s| s.name("libstd-link")); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct TestLink { pub compiler: Compiler, @@ -523,14 +392,6 @@ impl Step for TestLink { } } -// for (krate, path, _default) in krates("rustc-main") { -// rules.build(&krate.build_step, path) -// .dep(|s| s.name("libtest-link")) -// .dep(move |s| s.name("llvm").host(&build.build).stage(0)) -// .dep(|s| s.name("may-run-build-script")) -// .run(move |s| compile::rustc(build, s.target, &s.compiler())); -// } - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Rustc { pub compiler: Compiler, @@ -675,12 +536,6 @@ impl Step for Rustc { } } -// crate_rule(build, -// &mut rules, -// "librustc-link", -// "build-crate-rustc-main", -// compile::rustc_link) -// .dep(|s| s.name("libtest-link")); #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] struct RustcLink { pub compiler: Compiler, @@ -736,9 +591,6 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf { PathBuf::from(out.trim()) } -// rules.build("create-sysroot", "path/to/nowhere") -// .run(move |s| compile::create_sysroot(build, &s.compiler())); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Sysroot { pub compiler: Compiler, @@ -771,20 +623,6 @@ impl Step for Sysroot { } } -// the compiler with no target libraries ready to go -// rules.build("rustc", "src/rustc") -// .dep(|s| s.name("create-sysroot").target(s.host)) -// .dep(move |s| { -// if s.stage == 0 { -// Step::noop() -// } else { -// s.name("librustc") -// .host(&build.build) -// .stage(s.stage - 1) -// } -// }) -// .run(move |s| compile::assemble_rustc(build, s.stage, s.target)); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Assemble { /// The compiler which we will produce in this step. Assemble itself will diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index e3d6c74ec221c..bceae8dad9794 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -18,14 +18,6 @@ //! out to `rust-installer` still. This may one day be replaced with bits and //! pieces of `rustup.rs`! -// /// Helper to depend on a stage0 build-only rust-installer tool. -// fn tool_rust_installer<'a>(build: &'a Build, step: &Step<'a>) -> Step<'a> { -// step.name("tool-rust-installer") -// .host(&build.build) -// .target(&build.build) -// .stage(0) -// } - use std::env; use std::fs::{self, File}; use std::io::{Read, Write}; @@ -65,13 +57,6 @@ fn rust_installer(builder: &Builder) -> Command { builder.tool_cmd(Tool::RustInstaller) } -// rules.dist("dist-docs", "src/doc") -// .default(true) -// .only_host_build(true) -// .dep(|s| s.name("default:doc")) -// .dep(move |s| tool_rust_installer(build, s)) -// .run(move |s| dist::docs(build, s.stage, s.target)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Docs { pub stage: u32, @@ -276,16 +261,6 @@ fn make_win_dist( } } -// rules.dist("dist-mingw", "path/to/nowhere") -// .default(true) -// .only_host_build(true) -// .dep(move |s| tool_rust_installer(build, s)) -// .run(move |s| { -// if s.target.contains("pc-windows-gnu") { -// dist::mingw(build, s.target) -// } -// }); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Mingw { target: Interned, @@ -347,14 +322,6 @@ impl Step for Mingw { } } -// rules.dist("dist-rustc", "src/librustc") -// .dep(move |s| s.name("rustc").host(&build.build)) -// .host(true) -// .only_host_build(true) -// .default(true) -// .dep(move |s| tool_rust_installer(build, s)) -// .run(move |s| dist::rustc(build, s.stage, s.target)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rustc { pub stage: u32, @@ -495,10 +462,6 @@ impl Step for Rustc { } } -//rules.test("debugger-scripts", "src/etc/lldb_batchmode.py") -// .run(move |s| dist::debugger_scripts(build, &builder.sysroot(&s.compiler()), -// s.target)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct DebuggerScripts { pub sysroot: Interned, @@ -557,22 +520,6 @@ impl Step for DebuggerScripts { } } -// rules.dist("dist-std", "src/libstd") -// .dep(move |s| { -// // We want to package up as many target libraries as possible -// // for the `rust-std` package, so if this is a host target we -// // depend on librustc and otherwise we just depend on libtest. -// if build.config.host.iter().any(|t| t == s.target) { -// s.name("librustc-link") -// } else { -// s.name("libtest-link") -// } -// }) -// .default(true) -// .only_host_build(true) -// .dep(move |s| tool_rust_installer(build, s)) -// .run(move |s| dist::std(build, &s.compiler(), s.target)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { pub compiler: Compiler, @@ -648,13 +595,6 @@ impl Step for Std { } } -// rules.dist("dist-analysis", "analysis") -// .default(build.config.extended) -// .dep(|s| s.name("dist-std")) -// .only_host_build(true) -// .dep(move |s| tool_rust_installer(build, s)) -// .run(move |s| dist::analysis(build, &s.compiler(), s.target)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Analysis { pub compiler: Compiler, @@ -775,14 +715,6 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di } } -// rules.dist("dist-src", "src") -// .default(true) -// .host(true) -// .only_build(true) -// .only_host_build(true) -// .dep(move |s| tool_rust_installer(build, s)) -// .run(move |_| dist::rust_src(build)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Src; @@ -874,14 +806,6 @@ impl Step for Src { const CARGO_VENDOR_VERSION: &str = "0.1.4"; -// rules.dist("dist-plain-source-tarball", "src") -// .default(build.config.rust_dist_src) -// .host(true) -// .only_build(true) -// .only_host_build(true) -// .dep(move |s| tool_rust_installer(build, s)) -// .run(move |_| dist::plain_source_tarball(build)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct PlainSourceTarball; @@ -1028,13 +952,6 @@ fn write_file(path: &Path, data: &[u8]) { t!(vf.write_all(data)); } -// rules.dist("dist-cargo", "cargo") -// .host(true) -// .only_host_build(true) -// .dep(|s| s.name("tool-cargo")) -// .dep(move |s| tool_rust_installer(build, s)) -// .run(move |s| dist::cargo(build, s.stage, s.target)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Cargo { pub stage: u32, @@ -1127,12 +1044,6 @@ impl Step for Cargo { } } -// rules.dist("dist-rls", "rls") -// .host(true) -// .only_host_build(true) -// .dep(|s| s.name("tool-rls")) -// .dep(move |s| tool_rust_installer(build, s)) -// .run(move |s| dist::rls(build, s.stage, s.target)); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rls { pub stage: u32, @@ -1214,20 +1125,6 @@ impl Step for Rls { } } -// rules.dist("dist-extended", "extended") -// .default(build.config.extended) -// .host(true) -// .only_host_build(true) -// .dep(|d| d.name("dist-std")) -// .dep(|d| d.name("dist-rustc")) -// .dep(|d| d.name("dist-mingw")) -// .dep(|d| d.name("dist-docs")) -// .dep(|d| d.name("dist-cargo")) -// .dep(|d| d.name("dist-rls")) -// .dep(|d| d.name("dist-analysis")) -// .dep(move |s| tool_rust_installer(build, s)) -// .run(move |s| dist::extended(build, s.stage, s.target)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Extended { stage: u32, @@ -1632,13 +1529,6 @@ fn add_env(build: &Build, cmd: &mut Command, target: Interned) { } } -// rules.dist("dist-sign", "hash-and-sign") -// .host(true) -// .only_build(true) -// .only_host_build(true) -// .dep(move |s| s.name("tool-build-manifest").target(&build.build).stage(0)) -// .run(move |_| dist::hash_and_sign(build)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct HashSign; diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 2484fc5bf8839..3d8d9e50b20ea 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -76,25 +76,7 @@ macro_rules! book { } book!( - // rules.doc("doc-nomicon", "src/doc/nomicon") - // .dep(move |s| { - // s.name("tool-rustbook") - // .host(&build.build) - // .target(&build.build) - // .stage(0) - // }) - // .default(build.config.docs) - // .run(move |s| doc::rustbook(build, s.target, "nomicon")); Nomicon, "src/doc/book", "nomicon"; - // rules.doc("doc-reference", "src/doc/reference") - // .dep(move |s| { - // s.name("tool-rustbook") - // .host(&build.build) - // .target(&build.build) - // .stage(0) - // }) - // .default(build.config.docs) - // .run(move |s| doc::rustbook(build, s.target, "reference")); Reference, "src/doc/reference", "reference"; ); @@ -127,19 +109,6 @@ impl Step for Rustbook { } } -//rules.doc("doc-unstable-book", "src/doc/unstable-book") -// .dep(move |s| { -// s.name("tool-rustbook") -// .host(&build.build) -// .target(&build.build) -// .stage(0) -// }) -// .dep(move |s| s.name("doc-unstable-book-gen")) -// .default(build.config.docs) -// .run(move |s| doc::rustbook_src(build, -// s.target, -// "unstable-book", -// &build.md_doc_out(s.target))); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct UnstableBook { target: Interned, @@ -221,16 +190,6 @@ impl Step for RustbookSrc { } } -// rules.doc("doc-book", "src/doc/book") -// .dep(move |s| { -// s.name("tool-rustbook") -// .host(&build.build) -// .target(&build.build) -// .stage(0) -// }) -// .default(build.config.docs) -// .run(move |s| doc::book(build, s.target, "book")); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct TheBook { target: Interned, @@ -346,16 +305,6 @@ fn invoke_rustdoc(builder: &Builder, target: Interned, markdown: &str) { build.run(&mut cmd); } -// rules.doc("doc-standalone", "src/doc") -// .dep(move |s| { -// s.name("rustc") -// .host(&build.build) -// .target(&build.build) -// .stage(0) -// }) -// .default(build.config.docs) -// .run(move |s| doc::standalone(build, s.target)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Standalone { target: Interned, @@ -457,13 +406,6 @@ impl Step for Standalone { } } -// for (krate, path, default) in krates("std") { -// rules.doc(&krate.doc_step, path) -// .dep(|s| s.name("libstd-link")) -// .default(default && build.config.docs) -// .run(move |s| doc::std(build, s.stage, s.target)); -// } - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { stage: u32, @@ -567,15 +509,6 @@ impl Step for Std { } } -// for (krate, path, default) in krates("test") { -// rules.doc(&krate.doc_step, path) -// .dep(|s| s.name("libtest-link")) -// // Needed so rustdoc generates relative links to std. -// .dep(|s| s.name("doc-crate-std")) -// .default(default && build.config.compiler_docs) -// .run(move |s| doc::test(build, s.stage, s.target)); -// } - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Test { stage: u32, @@ -652,17 +585,6 @@ impl Step for Test { } } -// for (krate, path, default) in krates("rustc-main") { -// rules.doc(&krate.doc_step, path) -// .dep(|s| s.name("librustc-link")) -// // Needed so rustdoc generates relative links to std. -// .dep(|s| s.name("doc-crate-std")) -// .host(true) -// .default(default && build.config.docs) -// .run(move |s| doc::rustc(build, s.stage, s.target)); -// } -// - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rustc { stage: u32, @@ -757,13 +679,6 @@ impl Step for Rustc { } } -// rules.doc("doc-error-index", "src/tools/error_index_generator") -// .dep(move |s| s.name("tool-error-index").target(&build.build).stage(0)) -// .dep(move |s| s.name("librustc-link")) -// .default(build.config.docs) -// .host(true) -// .run(move |s| doc::error_index(build, s.target)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct ErrorIndex { target: Interned, @@ -816,18 +731,6 @@ impl Step for ErrorIndex { } } -// rules.doc("doc-unstable-book-gen", "src/tools/unstable-book-gen") -// .dep(move |s| { -// s.name("tool-unstable-book-gen") -// .host(&build.build) -// .target(&build.build) -// .stage(0) -// }) -// .dep(move |s| s.name("libstd-link")) -// .default(build.config.docs) -// .host(true) -// .run(move |s| doc::unstable_book_gen(build, s.target)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct UnstableBookGen { target: Interned, diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index fac69f89dc1d1..7b2d644c7696d 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -177,20 +177,10 @@ macro_rules! install { } install!((self, builder), - // rules.install("install-docs", "src/doc") - // .default(build.config.docs) - // .only_host_build(true) - // .dep(|s| s.name("dist-docs")) - // .run(move |s| install::Installer::new(build).install_docs(s.stage, s.target)); Docs, "src/doc", builder.build.config.docs, only_hosts: false, { builder.ensure(dist::Docs { stage: self.stage, target: self.target }); install_docs(builder, self.stage, self.target); }; - // rules.install("install-std", "src/libstd") - // .default(true) - // .only_host_build(true) - // .dep(|s| s.name("dist-std")) - // .run(move |s| install::Installer::new(build).install_std(s.stage)); Std, "src/libstd", true, only_hosts: true, { builder.ensure(dist::Std { compiler: builder.compiler(self.stage, self.host), @@ -198,31 +188,14 @@ install!((self, builder), }); install_std(builder, self.stage); }; - // rules.install("install-cargo", "cargo") - // .default(build.config.extended) - // .host(true) - // .only_host_build(true) - // .dep(|s| s.name("dist-cargo")) - // .run(move |s| install::Installer::new(build).install_cargo(s.stage, s.target)); Cargo, "cargo", builder.build.config.extended, only_hosts: true, { builder.ensure(dist::Cargo { stage: self.stage, target: self.target }); install_cargo(builder, self.stage, self.target); }; - // rules.install("install-rls", "rls") - // .default(build.config.extended) - // .host(true) - // .only_host_build(true) - // .dep(|s| s.name("dist-rls")) - // .run(move |s| install::Installer::new(build).install_rls(s.stage, s.target)); Rls, "rls", builder.build.config.extended, only_hosts: true, { builder.ensure(dist::Rls { stage: self.stage, target: self.target }); install_rls(builder, self.stage, self.target); }; - // rules.install("install-analysis", "analysis") - // .default(build.config.extended) - // .only_host_build(true) - // .dep(|s| s.name("dist-analysis")) - // .run(move |s| install::Installer::new(build).install_analysis(s.stage, s.target)); Analysis, "analysis", builder.build.config.extended, only_hosts: false, { builder.ensure(dist::Analysis { compiler: builder.compiler(self.stage, self.host), @@ -230,23 +203,10 @@ install!((self, builder), }); install_analysis(builder, self.stage, self.target); }; - // rules.install("install-src", "src") - // .default(build.config.extended) - // .host(true) - // .only_build(true) - // .only_host_build(true) - // .dep(|s| s.name("dist-src")) - // .run(move |s| install::Installer::new(build).install_src(s.stage)); Src, "src", builder.build.config.extended, only_hosts: true, { builder.ensure(dist::Src); install_src(builder, self.stage); }, ONLY_BUILD; - // rules.install("install-rustc", "src/librustc") - // .default(true) - // .host(true) - // .only_host_build(true) - // .dep(|s| s.name("dist-rustc")) - // .run(move |s| install::Installer::new(build).install_rustc(s.stage, s.target)); Rustc, "src/librustc", builder.build.config.extended, only_hosts: true, { builder.ensure(dist::Rustc { stage: self.stage, target: self.target }); install_rustc(builder, self.stage, self.target); diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index af13d86649734..dc78a43d52647 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -35,17 +35,6 @@ use build_helper::up_to_date; use builder::{Builder, ShouldRun, Step}; use cache::Interned; -// rules.build("llvm", "src/llvm") -// .host(true) -// .dep(move |s| { -// if s.target == build.build { -// Step::noop() -// } else { -// s.target(&build.build) -// } -// }) -// .run(move |s| native::llvm(build, s.target)); - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Llvm { pub target: Interned, @@ -246,9 +235,6 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) { panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version) } -//rules.build("test-helpers", "src/rt/rust_test_helpers.c") -// .run(move |s| native::test_helpers(build, s.target)); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct TestHelpers { pub target: Interned, @@ -311,10 +297,7 @@ const OPENSSL_VERS: &'static str = "1.0.2k"; const OPENSSL_SHA256: &'static str = "6b3977c61f2aedf0f96367dcfb5c6e578cf37e7b8d913b4ecb6643c3cb88d8c0"; -//rules.build("openssl", "path/to/nowhere") -// .run(move |s| native::openssl(build, s.target)); - - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Openssl { pub target: Interned, } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 41dc91f5a2ca8..9db6493ba3172 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -21,30 +21,6 @@ use native; use channel::GitInfo; use cache::Interned; -//// ======================================================================== -//// Build tools -//// -//// Tools used during the build system but not shipped -//// "pseudo rule" which represents completely cleaning out the tools dir in -//// one stage. This needs to happen whenever a dependency changes (e.g. -//// libstd, libtest, librustc) and all of the tool compilations above will -//// be sequenced after this rule. -//rules.build("maybe-clean-tools", "path/to/nowhere") -// .after("librustc-tool") -// .after("libtest-tool") -// .after("libstd-tool"); -// -//rules.build("librustc-tool", "path/to/nowhere") -// .dep(|s| s.name("librustc")) -// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Librustc)); -//rules.build("libtest-tool", "path/to/nowhere") -// .dep(|s| s.name("libtest")) -// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libtest)); -//rules.build("libstd-tool", "path/to/nowhere") -// .dep(|s| s.name("libstd")) -// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libstd)); -// - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct CleanTools { pub stage: u32, @@ -213,55 +189,15 @@ macro_rules! tool { } tool!( - // rules.build("tool-rustbook", "src/tools/rustbook") - // .dep(|s| s.name("maybe-clean-tools")) - // .dep(|s| s.name("librustc-tool")) - // .run(move |s| compile::tool(build, s.stage, s.target, "rustbook")); Rustbook, "src/tools/rustbook", "rustbook", Mode::Librustc; - // rules.build("tool-error-index", "src/tools/error_index_generator") - // .dep(|s| s.name("maybe-clean-tools")) - // .dep(|s| s.name("librustc-tool")) - // .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator")); ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::Librustc; - // rules.build("tool-unstable-book-gen", "src/tools/unstable-book-gen") - // .dep(|s| s.name("maybe-clean-tools")) - // .dep(|s| s.name("libstd-tool")) - // .run(move |s| compile::tool(build, s.stage, s.target, "unstable-book-gen")); UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::Libstd; - // rules.build("tool-tidy", "src/tools/tidy") - // .dep(|s| s.name("maybe-clean-tools")) - // .dep(|s| s.name("libstd-tool")) - // .run(move |s| compile::tool(build, s.stage, s.target, "tidy")); Tidy, "src/tools/tidy", "tidy", Mode::Libstd; - // rules.build("tool-linkchecker", "src/tools/linkchecker") - // .dep(|s| s.name("maybe-clean-tools")) - // .dep(|s| s.name("libstd-tool")) - // .run(move |s| compile::tool(build, s.stage, s.target, "linkchecker")); Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::Libstd; - // rules.build("tool-cargotest", "src/tools/cargotest") - // .dep(|s| s.name("maybe-clean-tools")) - // .dep(|s| s.name("libstd-tool")) - // .run(move |s| compile::tool(build, s.stage, s.target, "cargotest")); CargoTest, "src/tools/cargotest", "cargotest", Mode::Libstd; - // rules.build("tool-compiletest", "src/tools/compiletest") - // .dep(|s| s.name("maybe-clean-tools")) - // .dep(|s| s.name("libtest-tool")) - // .run(move |s| compile::tool(build, s.stage, s.target, "compiletest")); Compiletest, "src/tools/compiletest", "compiletest", Mode::Libtest; - // rules.build("tool-build-manifest", "src/tools/build-manifest") - // .dep(|s| s.name("maybe-clean-tools")) - // .dep(|s| s.name("libstd-tool")) - // .run(move |s| compile::tool(build, s.stage, s.target, "build-manifest")); BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Librustc; - // rules.build("tool-remote-test-client", "src/tools/remote-test-client") - // .dep(|s| s.name("maybe-clean-tools")) - // .dep(|s| s.name("libstd-tool")) - // .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-client")); RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd; - // rules.build("tool-rust-installer", "src/tools/rust-installer") - // .dep(|s| s.name("maybe-clean-tools")) - // .dep(|s| s.name("libstd-tool")) - // .run(move |s| compile::tool(build, s.stage, s.target, "rust-installer")); RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd; ); @@ -300,20 +236,6 @@ impl Step for RemoteTestServer { } } -// rules.build("tool-cargo", "src/tools/cargo") -// .host(true) -// .default(build.config.extended) -// .dep(|s| s.name("maybe-clean-tools")) -// .dep(|s| s.name("libstd-tool")) -// .dep(|s| s.stage(0).host(s.target).name("openssl")) -// .dep(move |s| { -// // Cargo depends on procedural macros, which requires a full host -// // compiler to be available, so we need to depend on that. -// s.name("librustc-link") -// .target(&build.build) -// .host(&build.build) -// }) -// .run(move |s| compile::tool(build, s.stage, s.target, "cargo")); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Cargo { pub stage: u32, @@ -360,19 +282,6 @@ impl Step for Cargo { } } -// rules.build("tool-rls", "src/tools/rls") -// .host(true) -// .default(build.config.extended) -// .dep(|s| s.name("librustc-tool")) -// .dep(|s| s.stage(0).host(s.target).name("openssl")) -// .dep(move |s| { -// // rls, like cargo, uses procedural macros -// s.name("librustc-link") -// .target(&build.build) -// .host(&build.build) -// }) -// .run(move |s| compile::tool(build, s.stage, s.target, "rls")); -// #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rls { pub stage: u32, From d8aecc19d8e2d82f57e525116302455dca34016d Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 20 Jul 2017 16:41:46 -0600 Subject: [PATCH 46/51] Remove step.rs --- src/bootstrap/step.rs | 1820 ----------------------------------------- 1 file changed, 1820 deletions(-) delete mode 100644 src/bootstrap/step.rs diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs deleted file mode 100644 index a1b26f44b7de1..0000000000000 --- a/src/bootstrap/step.rs +++ /dev/null @@ -1,1820 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Definition of steps of the build system. -//! -//! This is where some of the real meat of rustbuild is located, in how we -//! define targets and the dependencies amongst them. This file can sort of be -//! viewed as just defining targets in a makefile which shell out to predefined -//! functions elsewhere about how to execute the target. -//! -//! The primary function here you're likely interested in is the `build_rules` -//! function. This will create a `Rules` structure which basically just lists -//! everything that rustbuild can do. Each rule has a human-readable name, a -//! path associated with it, some dependencies, and then a closure of how to -//! actually perform the rule. -//! -//! All steps below are defined in self-contained units, so adding a new target -//! to the build system should just involve adding the meta information here -//! along with the actual implementation elsewhere. You can find more comments -//! about how to define rules themselves below. - -use std::collections::{BTreeMap, HashSet, HashMap}; -use std::mem; -use std::path::PathBuf; -use std::process; - -use check::{self, TestKind}; -use compile; -use dist; -use doc; -use flags::Subcommand; -use install; -use native; -use {Compiler, Build, Mode}; - -pub fn run(build: &Build) { - let rules = build_rules(build); - let steps = rules.plan(); - rules.run(&steps); -} - -pub fn build_rules<'a>(build: &'a Build) -> Rules { - let mut rules = Rules::new(build); - - // This is the first rule that we're going to define for rustbuild, which is - // used to compile LLVM itself. All rules are added through the `rules` - // structure created above and are configured through a builder-style - // interface. - // - // First up we see the `build` method. This represents a rule that's part of - // the top-level `build` subcommand. For example `./x.py build` is what this - // is associating with. Note that this is normally only relevant if you flag - // a rule as `default`, which we'll talk about later. - // - // Next up we'll see two arguments to this method: - // - // * `llvm` - this is the "human readable" name of this target. This name is - // not accessed anywhere outside this file itself (e.g. not in - // the CLI nor elsewhere in rustbuild). The purpose of this is to - // easily define dependencies between rules. That is, other rules - // will depend on this with the name "llvm". - // * `src/llvm` - this is the relevant path to the rule that we're working - // with. This path is the engine behind how commands like - // `./x.py build src/llvm` work. This should typically point - // to the relevant component, but if there's not really a - // path to be assigned here you can pass something like - // `path/to/nowhere` to ignore it. - // - // After we create the rule with the `build` method we can then configure - // various aspects of it. For example this LLVM rule uses `.host(true)` to - // flag that it's a rule only for host targets. In other words, LLVM isn't - // compiled for targets configured through `--target` (e.g. those we're just - // building a standard library for). - // - // Next up the `dep` method will add a dependency to this rule. The closure - // is yielded the step that represents executing the `llvm` rule itself - // (containing information like stage, host, target, ...) and then it must - // return a target that the step depends on. Here LLVM is actually - // interesting where a cross-compiled LLVM depends on the host LLVM, but - // otherwise it has no dependencies. - // - // To handle this we do a bit of dynamic dispatch to see what the dependency - // is. If we're building a LLVM for the build triple, then we don't actually - // have any dependencies! To do that we return a dependency on the `Step::noop()` - // target which does nothing. - // - // If we're build a cross-compiled LLVM, however, we need to assemble the - // libraries from the previous compiler. This step has the same name as - // ours (llvm) but we want it for a different target, so we use the - // builder-style methods on `Step` to configure this target to the build - // triple. - // - // Finally, to finish off this rule, we define how to actually execute it. - // That logic is all defined in the `native` module so we just delegate to - // the relevant function there. The argument to the closure passed to `run` - // is a `Step` (defined below) which encapsulates information like the - // stage, target, host, etc. - rules.build("llvm", "src/llvm") - .host(true) - .dep(move |s| { - if s.target == build.build { - Step::noop() - } else { - s.target(&build.build) - } - }) - .run(move |s| native::llvm(build, s.target)); - - // Ok! After that example rule that's hopefully enough to explain what's - // going on here. You can check out the API docs below and also see a bunch - // more examples of rules directly below as well. - - // the compiler with no target libraries ready to go - rules.build("rustc", "src/rustc") - .dep(|s| s.name("create-sysroot").target(s.host)) - .dep(move |s| { - if s.stage == 0 { - Step::noop() - } else { - s.name("librustc") - .host(&build.build) - .stage(s.stage - 1) - } - }) - .run(move |s| compile::assemble_rustc(build, s.stage, s.target)); - - // Helper for loading an entire DAG of crates, rooted at `name` - let krates = |name: &str| { - let mut ret = Vec::new(); - let mut list = vec![name]; - let mut visited = HashSet::new(); - while let Some(krate) = list.pop() { - let default = krate == name; - let krate = &build.crates[krate]; - let path = krate.path.strip_prefix(&build.src) - // This handles out of tree paths - .unwrap_or(&krate.path); - ret.push((krate, path.to_str().unwrap(), default)); - for dep in krate.deps.iter() { - if visited.insert(dep) && dep != "build_helper" { - list.push(dep); - } - } - } - ret - }; - - // ======================================================================== - // Crate compilations - // - // Tools used during the build system but not shipped - rules.build("create-sysroot", "path/to/nowhere") - .run(move |s| compile::create_sysroot(build, &s.compiler())); - - // These rules are "pseudo rules" that don't actually do any work - // themselves, but represent a complete sysroot with the relevant compiler - // linked into place. - // - // That is, depending on "libstd" means that when the rule is completed then - // the `stage` sysroot for the compiler `host` will be available with a - // standard library built for `target` linked in place. Not all rules need - // the compiler itself to be available, just the standard library, so - // there's a distinction between the two. - rules.build("libstd", "src/libstd") - .dep(|s| s.name("rustc").target(s.host)) - .dep(|s| s.name("libstd-link")); - rules.build("libtest", "src/libtest") - .dep(|s| s.name("libstd")) - .dep(|s| s.name("libtest-link")) - .default(true); - rules.build("librustc", "src/librustc") - .dep(|s| s.name("libtest")) - .dep(|s| s.name("librustc-link")) - .host(true) - .default(true); - - // Helper method to define the rules to link a crate into its place in the - // sysroot. - // - // The logic here is a little subtle as there's a few cases to consider. - // Not all combinations of (stage, host, target) actually require something - // to be compiled, but rather libraries could get propagated from a - // different location. For example: - // - // * Any crate with a `host` that's not the build triple will not actually - // compile something. A different `host` means that the build triple will - // actually compile the libraries, and then we'll copy them over from the - // build triple to the `host` directory. - // - // * Some crates aren't even compiled by the build triple, but may be copied - // from previous stages. For example if we're not doing a full bootstrap - // then we may just depend on the stage1 versions of libraries to be - // available to get linked forward. - // - // * Finally, there are some cases, however, which do indeed comiple crates - // and link them into place afterwards. - // - // The rule definition below mirrors these three cases. The `dep` method - // calculates the correct dependency which either comes from stage1, a - // different compiler, or from actually building the crate itself (the `dep` - // rule). The `run` rule then mirrors these three cases and links the cases - // forward into the compiler sysroot specified from the correct location. - fn crate_rule<'a, 'b>(build: &'a Build, - rules: &'b mut Rules<'a>, - krate: &'a str, - dep: &'a str, - link: fn(&Build, &Compiler, &Compiler, &str)) - -> RuleBuilder<'a, 'b> { - let mut rule = rules.build(&krate, "path/to/nowhere"); - rule.dep(move |s| { - if build.force_use_stage1(&s.compiler(), s.target) { - s.host(&build.build).stage(1) - } else if s.host == build.build { - s.name(dep) - } else { - s.host(&build.build) - } - }) - .run(move |s| { - if build.force_use_stage1(&s.compiler(), s.target) { - link(build, - &s.stage(1).host(&build.build).compiler(), - &s.compiler(), - s.target) - } else if s.host == build.build { - link(build, &s.compiler(), &s.compiler(), s.target) - } else { - link(build, - &s.host(&build.build).compiler(), - &s.compiler(), - s.target) - } - }); - rule - } - - // Similar to the `libstd`, `libtest`, and `librustc` rules above, except - // these rules only represent the libraries being available in the sysroot, - // not the compiler itself. This is done as not all rules need a compiler in - // the sysroot, but may just need the libraries. - // - // All of these rules use the helper definition above. - crate_rule(build, - &mut rules, - "libstd-link", - "build-crate-std", - compile::std_link) - .dep(|s| s.name("startup-objects")) - .dep(|s| s.name("create-sysroot").target(s.host)); - crate_rule(build, - &mut rules, - "libtest-link", - "build-crate-test", - compile::test_link) - .dep(|s| s.name("libstd-link")); - crate_rule(build, - &mut rules, - "librustc-link", - "build-crate-rustc-main", - compile::rustc_link) - .dep(|s| s.name("libtest-link")); - - for (krate, path, _default) in krates("std") { - rules.build(&krate.build_step, path) - .dep(|s| s.name("startup-objects")) - .dep(move |s| s.name("rustc").host(&build.build).target(s.host)) - .run(move |s| compile::std(build, s.target, &s.compiler())); - } - for (krate, path, _default) in krates("test") { - rules.build(&krate.build_step, path) - .dep(|s| s.name("libstd-link")) - .run(move |s| compile::test(build, s.target, &s.compiler())); - } - for (krate, path, _default) in krates("rustc-main") { - rules.build(&krate.build_step, path) - .dep(|s| s.name("libtest-link")) - .dep(move |s| s.name("llvm").host(&build.build).stage(0)) - .dep(|s| s.name("may-run-build-script")) - .run(move |s| compile::rustc(build, s.target, &s.compiler())); - } - - // Crates which have build scripts need to rely on this rule to ensure that - // the necessary prerequisites for a build script are linked and located in - // place. - rules.build("may-run-build-script", "path/to/nowhere") - .dep(move |s| { - s.name("libstd-link") - .host(&build.build) - .target(&build.build) - }); - rules.build("startup-objects", "src/rtstartup") - .dep(|s| s.name("create-sysroot").target(s.host)) - .run(move |s| compile::build_startup_objects(build, &s.compiler(), s.target)); - - // ======================================================================== - // Test targets - // - // Various unit tests and tests suites we can run - { - let mut suite = |name, path, mode, dir| { - rules.test(name, path) - .dep(|s| s.name("libtest")) - .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) - .dep(|s| s.name("test-helpers")) - .dep(|s| s.name("remote-copy-libs")) - .default(mode != "pretty") // pretty tests don't run everywhere - .run(move |s| { - check::compiletest(build, &s.compiler(), s.target, mode, dir) - }); - }; - - suite("check-ui", "src/test/ui", "ui", "ui"); - suite("check-rpass", "src/test/run-pass", "run-pass", "run-pass"); - suite("check-cfail", "src/test/compile-fail", "compile-fail", "compile-fail"); - suite("check-pfail", "src/test/parse-fail", "parse-fail", "parse-fail"); - suite("check-rfail", "src/test/run-fail", "run-fail", "run-fail"); - suite("check-rpass-valgrind", "src/test/run-pass-valgrind", - "run-pass-valgrind", "run-pass-valgrind"); - suite("check-mir-opt", "src/test/mir-opt", "mir-opt", "mir-opt"); - if build.config.codegen_tests { - suite("check-codegen", "src/test/codegen", "codegen", "codegen"); - } - suite("check-codegen-units", "src/test/codegen-units", "codegen-units", - "codegen-units"); - suite("check-incremental", "src/test/incremental", "incremental", - "incremental"); - } - - if build.build.contains("msvc") { - // nothing to do for debuginfo tests - } else { - rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb") - .dep(|s| s.name("libtest")) - .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) - .dep(|s| s.name("test-helpers")) - .dep(|s| s.name("debugger-scripts")) - .run(move |s| check::compiletest(build, &s.compiler(), s.target, - "debuginfo-lldb", "debuginfo")); - rules.test("check-debuginfo-gdb", "src/test/debuginfo-gdb") - .dep(|s| s.name("libtest")) - .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) - .dep(|s| s.name("test-helpers")) - .dep(|s| s.name("debugger-scripts")) - .dep(|s| s.name("remote-copy-libs")) - .run(move |s| check::compiletest(build, &s.compiler(), s.target, - "debuginfo-gdb", "debuginfo")); - let mut rule = rules.test("check-debuginfo", "src/test/debuginfo"); - rule.default(true); - if build.build.contains("apple") { - rule.dep(|s| s.name("check-debuginfo-lldb")); - } else { - rule.dep(|s| s.name("check-debuginfo-gdb")); - } - } - - rules.test("debugger-scripts", "src/etc/lldb_batchmode.py") - .run(move |s| dist::debugger_scripts(build, &build.sysroot(&s.compiler()), - s.target)); - - { - let mut suite = |name, path, mode, dir| { - rules.test(name, path) - .dep(|s| s.name("librustc")) - .dep(|s| s.name("test-helpers")) - .dep(|s| s.name("tool-compiletest").target(s.host).stage(0)) - .default(mode != "pretty") - .host(true) - .run(move |s| { - check::compiletest(build, &s.compiler(), s.target, mode, dir) - }); - }; - - suite("check-ui-full", "src/test/ui-fulldeps", "ui", "ui-fulldeps"); - suite("check-rpass-full", "src/test/run-pass-fulldeps", - "run-pass", "run-pass-fulldeps"); - suite("check-rfail-full", "src/test/run-fail-fulldeps", - "run-fail", "run-fail-fulldeps"); - suite("check-cfail-full", "src/test/compile-fail-fulldeps", - "compile-fail", "compile-fail-fulldeps"); - suite("check-rmake", "src/test/run-make", "run-make", "run-make"); - suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc"); - suite("check-pretty", "src/test/pretty", "pretty", "pretty"); - suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty", - "run-pass"); - suite("check-pretty-rfail", "src/test/run-fail/pretty", "pretty", - "run-fail"); - suite("check-pretty-valgrind", "src/test/run-pass-valgrind/pretty", "pretty", - "run-pass-valgrind"); - suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps/pretty", - "pretty", "run-pass-fulldeps"); - suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps/pretty", - "pretty", "run-fail-fulldeps"); - } - - for (krate, path, _default) in krates("std") { - rules.test(&krate.test_step, path) - .dep(|s| s.name("libtest")) - .dep(|s| s.name("remote-copy-libs")) - .run(move |s| check::krate(build, &s.compiler(), s.target, - Mode::Libstd, TestKind::Test, - Some(&krate.name))); - } - rules.test("check-std-all", "path/to/nowhere") - .dep(|s| s.name("libtest")) - .dep(|s| s.name("remote-copy-libs")) - .default(true) - .run(move |s| check::krate(build, &s.compiler(), s.target, - Mode::Libstd, TestKind::Test, None)); - - // std benchmarks - for (krate, path, _default) in krates("std") { - rules.bench(&krate.bench_step, path) - .dep(|s| s.name("libtest")) - .dep(|s| s.name("remote-copy-libs")) - .run(move |s| check::krate(build, &s.compiler(), s.target, - Mode::Libstd, TestKind::Bench, - Some(&krate.name))); - } - rules.bench("bench-std-all", "path/to/nowhere") - .dep(|s| s.name("libtest")) - .dep(|s| s.name("remote-copy-libs")) - .default(true) - .run(move |s| check::krate(build, &s.compiler(), s.target, - Mode::Libstd, TestKind::Bench, None)); - - for (krate, path, _default) in krates("test") { - rules.test(&krate.test_step, path) - .dep(|s| s.name("libtest")) - .dep(|s| s.name("remote-copy-libs")) - .run(move |s| check::krate(build, &s.compiler(), s.target, - Mode::Libtest, TestKind::Test, - Some(&krate.name))); - } - rules.test("check-test-all", "path/to/nowhere") - .dep(|s| s.name("libtest")) - .dep(|s| s.name("remote-copy-libs")) - .default(true) - .run(move |s| check::krate(build, &s.compiler(), s.target, - Mode::Libtest, TestKind::Test, None)); - for (krate, path, _default) in krates("rustc-main") { - rules.test(&krate.test_step, path) - .dep(|s| s.name("librustc")) - .dep(|s| s.name("remote-copy-libs")) - .host(true) - .run(move |s| check::krate(build, &s.compiler(), s.target, - Mode::Librustc, TestKind::Test, - Some(&krate.name))); - } - rules.test("check-rustc-all", "path/to/nowhere") - .dep(|s| s.name("librustc")) - .dep(|s| s.name("remote-copy-libs")) - .default(true) - .host(true) - .run(move |s| check::krate(build, &s.compiler(), s.target, - Mode::Librustc, TestKind::Test, None)); - - rules.test("check-linkchecker", "src/tools/linkchecker") - .dep(|s| s.name("tool-linkchecker").stage(0)) - .dep(|s| s.name("default:doc")) - .default(build.config.docs) - .host(true) - .run(move |s| check::linkcheck(build, s.target)); - rules.test("check-cargotest", "src/tools/cargotest") - .dep(|s| s.name("tool-cargotest").stage(0)) - .dep(|s| s.name("librustc")) - .host(true) - .run(move |s| check::cargotest(build, s.stage, s.target)); - rules.test("check-cargo", "src/tools/cargo") - .dep(|s| s.name("tool-cargo")) - .host(true) - .run(move |s| check::cargo(build, s.stage, s.target)); - rules.test("check-rls", "src/tools/rls") - .dep(|s| s.name("tool-rls")) - .host(true) - .run(move |s| check::rls(build, s.stage, s.target)); - rules.test("check-tidy", "src/tools/tidy") - .dep(|s| s.name("tool-tidy").stage(0)) - .default(true) - .host(true) - .only_build(true) - .run(move |s| check::tidy(build, s.target)); - rules.test("check-error-index", "src/tools/error_index_generator") - .dep(|s| s.name("libstd")) - .dep(|s| s.name("tool-error-index").host(s.host).stage(0)) - .default(true) - .host(true) - .run(move |s| check::error_index(build, &s.compiler())); - rules.test("check-docs", "src/doc") - .dep(|s| s.name("libtest")) - .default(true) - .host(true) - .run(move |s| check::docs(build, &s.compiler())); - rules.test("check-distcheck", "distcheck") - .dep(|s| s.name("dist-plain-source-tarball")) - .dep(|s| s.name("dist-src")) - .run(move |_| check::distcheck(build)); - - rules.build("test-helpers", "src/rt/rust_test_helpers.c") - .run(move |s| native::test_helpers(build, s.target)); - rules.build("openssl", "path/to/nowhere") - .run(move |s| native::openssl(build, s.target)); - - // Some test suites are run inside emulators or on remote devices, and most - // of our test binaries are linked dynamically which means we need to ship - // the standard library and such to the emulator ahead of time. This step - // represents this and is a dependency of all test suites. - // - // Most of the time this step is a noop (the `check::emulator_copy_libs` - // only does work if necessary). For some steps such as shipping data to - // QEMU we have to build our own tools so we've got conditional dependencies - // on those programs as well. Note that the remote test client is built for - // the build target (us) and the server is built for the target. - rules.test("remote-copy-libs", "path/to/nowhere") - .dep(|s| s.name("libtest")) - .dep(move |s| { - if build.remote_tested(s.target) { - s.name("tool-remote-test-client").target(s.host).stage(0) - } else { - Step::noop() - } - }) - .dep(move |s| { - if build.remote_tested(s.target) { - s.name("tool-remote-test-server") - } else { - Step::noop() - } - }) - .run(move |s| check::remote_copy_libs(build, &s.compiler(), s.target)); - - rules.test("check-bootstrap", "src/bootstrap") - .default(true) - .host(true) - .only_build(true) - .run(move |_| check::bootstrap(build)); - - // ======================================================================== - // Build tools - // - // Tools used during the build system but not shipped - rules.build("tool-rustbook", "src/tools/rustbook") - .dep(|s| s.name("maybe-clean-tools")) - .dep(|s| s.name("librustc-tool")) - .run(move |s| compile::tool(build, s.stage, s.target, "rustbook")); - rules.build("tool-error-index", "src/tools/error_index_generator") - .dep(|s| s.name("maybe-clean-tools")) - .dep(|s| s.name("librustc-tool")) - .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator")); - rules.build("tool-unstable-book-gen", "src/tools/unstable-book-gen") - .dep(|s| s.name("maybe-clean-tools")) - .dep(|s| s.name("libstd-tool")) - .run(move |s| compile::tool(build, s.stage, s.target, "unstable-book-gen")); - rules.build("tool-tidy", "src/tools/tidy") - .dep(|s| s.name("maybe-clean-tools")) - .dep(|s| s.name("libstd-tool")) - .run(move |s| compile::tool(build, s.stage, s.target, "tidy")); - rules.build("tool-linkchecker", "src/tools/linkchecker") - .dep(|s| s.name("maybe-clean-tools")) - .dep(|s| s.name("libstd-tool")) - .run(move |s| compile::tool(build, s.stage, s.target, "linkchecker")); - rules.build("tool-cargotest", "src/tools/cargotest") - .dep(|s| s.name("maybe-clean-tools")) - .dep(|s| s.name("libstd-tool")) - .run(move |s| compile::tool(build, s.stage, s.target, "cargotest")); - rules.build("tool-compiletest", "src/tools/compiletest") - .dep(|s| s.name("maybe-clean-tools")) - .dep(|s| s.name("libtest-tool")) - .run(move |s| compile::tool(build, s.stage, s.target, "compiletest")); - rules.build("tool-build-manifest", "src/tools/build-manifest") - .dep(|s| s.name("maybe-clean-tools")) - .dep(|s| s.name("libstd-tool")) - .run(move |s| compile::tool(build, s.stage, s.target, "build-manifest")); - rules.build("tool-remote-test-server", "src/tools/remote-test-server") - .dep(|s| s.name("maybe-clean-tools")) - .dep(|s| s.name("libstd-tool")) - .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-server")); - rules.build("tool-remote-test-client", "src/tools/remote-test-client") - .dep(|s| s.name("maybe-clean-tools")) - .dep(|s| s.name("libstd-tool")) - .run(move |s| compile::tool(build, s.stage, s.target, "remote-test-client")); - rules.build("tool-rust-installer", "src/tools/rust-installer") - .dep(|s| s.name("maybe-clean-tools")) - .dep(|s| s.name("libstd-tool")) - .run(move |s| compile::tool(build, s.stage, s.target, "rust-installer")); - rules.build("tool-cargo", "src/tools/cargo") - .host(true) - .default(build.config.extended) - .dep(|s| s.name("maybe-clean-tools")) - .dep(|s| s.name("libstd-tool")) - .dep(|s| s.stage(0).host(s.target).name("openssl")) - .dep(move |s| { - // Cargo depends on procedural macros, which requires a full host - // compiler to be available, so we need to depend on that. - s.name("librustc-link") - .target(&build.build) - .host(&build.build) - }) - .run(move |s| compile::tool(build, s.stage, s.target, "cargo")); - rules.build("tool-rls", "src/tools/rls") - .host(true) - .default(build.config.extended) - .dep(|s| s.name("librustc-tool")) - .dep(|s| s.stage(0).host(s.target).name("openssl")) - .dep(move |s| { - // rls, like cargo, uses procedural macros - s.name("librustc-link") - .target(&build.build) - .host(&build.build) - }) - .run(move |s| compile::tool(build, s.stage, s.target, "rls")); - - // "pseudo rule" which represents completely cleaning out the tools dir in - // one stage. This needs to happen whenever a dependency changes (e.g. - // libstd, libtest, librustc) and all of the tool compilations above will - // be sequenced after this rule. - rules.build("maybe-clean-tools", "path/to/nowhere") - .after("librustc-tool") - .after("libtest-tool") - .after("libstd-tool"); - - rules.build("librustc-tool", "path/to/nowhere") - .dep(|s| s.name("librustc")) - .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Librustc)); - rules.build("libtest-tool", "path/to/nowhere") - .dep(|s| s.name("libtest")) - .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libtest)); - rules.build("libstd-tool", "path/to/nowhere") - .dep(|s| s.name("libstd")) - .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libstd)); - - // ======================================================================== - // Documentation targets - rules.doc("doc-book", "src/doc/book") - .dep(move |s| { - s.name("tool-rustbook") - .host(&build.build) - .target(&build.build) - .stage(0) - }) - .default(build.config.docs) - .run(move |s| doc::book(build, s.target, "book")); - rules.doc("doc-nomicon", "src/doc/nomicon") - .dep(move |s| { - s.name("tool-rustbook") - .host(&build.build) - .target(&build.build) - .stage(0) - }) - .default(build.config.docs) - .run(move |s| doc::rustbook(build, s.target, "nomicon")); - rules.doc("doc-reference", "src/doc/reference") - .dep(move |s| { - s.name("tool-rustbook") - .host(&build.build) - .target(&build.build) - .stage(0) - }) - .default(build.config.docs) - .run(move |s| doc::rustbook(build, s.target, "reference")); - rules.doc("doc-unstable-book", "src/doc/unstable-book") - .dep(move |s| { - s.name("tool-rustbook") - .host(&build.build) - .target(&build.build) - .stage(0) - }) - .dep(move |s| s.name("doc-unstable-book-gen")) - .default(build.config.docs) - .run(move |s| doc::rustbook_src(build, - s.target, - "unstable-book", - &build.md_doc_out(s.target))); - rules.doc("doc-standalone", "src/doc") - .dep(move |s| { - s.name("rustc") - .host(&build.build) - .target(&build.build) - .stage(0) - }) - .default(build.config.docs) - .run(move |s| doc::standalone(build, s.target)); - rules.doc("doc-error-index", "src/tools/error_index_generator") - .dep(move |s| s.name("tool-error-index").target(&build.build).stage(0)) - .dep(move |s| s.name("librustc-link")) - .default(build.config.docs) - .host(true) - .run(move |s| doc::error_index(build, s.target)); - rules.doc("doc-unstable-book-gen", "src/tools/unstable-book-gen") - .dep(move |s| { - s.name("tool-unstable-book-gen") - .host(&build.build) - .target(&build.build) - .stage(0) - }) - .dep(move |s| s.name("libstd-link")) - .default(build.config.docs) - .host(true) - .run(move |s| doc::unstable_book_gen(build, s.target)); - for (krate, path, default) in krates("std") { - rules.doc(&krate.doc_step, path) - .dep(|s| s.name("libstd-link")) - .default(default && build.config.docs) - .run(move |s| doc::std(build, s.stage, s.target)); - } - for (krate, path, default) in krates("test") { - rules.doc(&krate.doc_step, path) - .dep(|s| s.name("libtest-link")) - // Needed so rustdoc generates relative links to std. - .dep(|s| s.name("doc-crate-std")) - .default(default && build.config.compiler_docs) - .run(move |s| doc::test(build, s.stage, s.target)); - } - for (krate, path, default) in krates("rustc-main") { - rules.doc(&krate.doc_step, path) - .dep(|s| s.name("librustc-link")) - // Needed so rustdoc generates relative links to std. - .dep(|s| s.name("doc-crate-std")) - .host(true) - .default(default && build.config.docs) - .run(move |s| doc::rustc(build, s.stage, s.target)); - } - - // ======================================================================== - // Distribution targets - rules.dist("dist-rustc", "src/librustc") - .dep(move |s| s.name("rustc").host(&build.build)) - .host(true) - .only_host_build(true) - .default(true) - .dep(move |s| tool_rust_installer(build, s)) - .run(move |s| dist::rustc(build, s.stage, s.target)); - rules.dist("dist-std", "src/libstd") - .dep(move |s| { - // We want to package up as many target libraries as possible - // for the `rust-std` package, so if this is a host target we - // depend on librustc and otherwise we just depend on libtest. - if build.config.host.iter().any(|t| t == s.target) { - s.name("librustc-link") - } else { - s.name("libtest-link") - } - }) - .default(true) - .only_host_build(true) - .dep(move |s| tool_rust_installer(build, s)) - .run(move |s| dist::std(build, &s.compiler(), s.target)); - rules.dist("dist-mingw", "path/to/nowhere") - .default(true) - .only_host_build(true) - .dep(move |s| tool_rust_installer(build, s)) - .run(move |s| { - if s.target.contains("pc-windows-gnu") { - dist::mingw(build, s.target) - } - }); - rules.dist("dist-plain-source-tarball", "src") - .default(build.config.rust_dist_src) - .host(true) - .only_build(true) - .only_host_build(true) - .dep(move |s| tool_rust_installer(build, s)) - .run(move |_| dist::plain_source_tarball(build)); - rules.dist("dist-src", "src") - .default(true) - .host(true) - .only_build(true) - .only_host_build(true) - .dep(move |s| tool_rust_installer(build, s)) - .run(move |_| dist::rust_src(build)); - rules.dist("dist-docs", "src/doc") - .default(true) - .only_host_build(true) - .dep(|s| s.name("default:doc")) - .dep(move |s| tool_rust_installer(build, s)) - .run(move |s| dist::docs(build, s.stage, s.target)); - rules.dist("dist-analysis", "analysis") - .default(build.config.extended) - .dep(|s| s.name("dist-std")) - .only_host_build(true) - .dep(move |s| tool_rust_installer(build, s)) - .run(move |s| dist::analysis(build, &s.compiler(), s.target)); - rules.dist("dist-rls", "rls") - .host(true) - .only_host_build(true) - .dep(|s| s.name("tool-rls")) - .dep(move |s| tool_rust_installer(build, s)) - .run(move |s| dist::rls(build, s.stage, s.target)); - rules.dist("dist-cargo", "cargo") - .host(true) - .only_host_build(true) - .dep(|s| s.name("tool-cargo")) - .dep(move |s| tool_rust_installer(build, s)) - .run(move |s| dist::cargo(build, s.stage, s.target)); - rules.dist("dist-extended", "extended") - .default(build.config.extended) - .host(true) - .only_host_build(true) - .dep(|d| d.name("dist-std")) - .dep(|d| d.name("dist-rustc")) - .dep(|d| d.name("dist-mingw")) - .dep(|d| d.name("dist-docs")) - .dep(|d| d.name("dist-cargo")) - .dep(|d| d.name("dist-rls")) - .dep(|d| d.name("dist-analysis")) - .dep(move |s| tool_rust_installer(build, s)) - .run(move |s| dist::extended(build, s.stage, s.target)); - - rules.dist("dist-sign", "hash-and-sign") - .host(true) - .only_build(true) - .only_host_build(true) - .dep(move |s| s.name("tool-build-manifest").target(&build.build).stage(0)) - .run(move |_| dist::hash_and_sign(build)); - - rules.install("install-docs", "src/doc") - .default(build.config.docs) - .only_host_build(true) - .dep(|s| s.name("dist-docs")) - .run(move |s| install::Installer::new(build).install_docs(s.stage, s.target)); - rules.install("install-std", "src/libstd") - .default(true) - .only_host_build(true) - .dep(|s| s.name("dist-std")) - .run(move |s| install::Installer::new(build).install_std(s.stage)); - rules.install("install-cargo", "cargo") - .default(build.config.extended) - .host(true) - .only_host_build(true) - .dep(|s| s.name("dist-cargo")) - .run(move |s| install::Installer::new(build).install_cargo(s.stage, s.target)); - rules.install("install-rls", "rls") - .default(build.config.extended) - .host(true) - .only_host_build(true) - .dep(|s| s.name("dist-rls")) - .run(move |s| install::Installer::new(build).install_rls(s.stage, s.target)); - rules.install("install-analysis", "analysis") - .default(build.config.extended) - .only_host_build(true) - .dep(|s| s.name("dist-analysis")) - .run(move |s| install::Installer::new(build).install_analysis(s.stage, s.target)); - rules.install("install-src", "src") - .default(build.config.extended) - .host(true) - .only_build(true) - .only_host_build(true) - .dep(|s| s.name("dist-src")) - .run(move |s| install::Installer::new(build).install_src(s.stage)); - rules.install("install-rustc", "src/librustc") - .default(true) - .host(true) - .only_host_build(true) - .dep(|s| s.name("dist-rustc")) - .run(move |s| install::Installer::new(build).install_rustc(s.stage, s.target)); - - rules.verify(); - return rules; - - /// Helper to depend on a stage0 build-only rust-installer tool. - fn tool_rust_installer<'a>(build: &'a Build, step: &Step<'a>) -> Step<'a> { - step.name("tool-rust-installer") - .host(&build.build) - .target(&build.build) - .stage(0) - } -} - -#[derive(PartialEq, Eq, Hash, Clone, Debug)] -struct Step<'a> { - /// Human readable name of the rule this step is executing. Possible names - /// are all defined above in `build_rules`. - name: &'a str, - - /// The stage this step is executing in. This is typically 0, 1, or 2. - stage: u32, - - /// This step will likely involve a compiler, and the target that compiler - /// itself is built for is called the host, this variable. Typically this is - /// the target of the build machine itself. - host: &'a str, - - /// The target that this step represents generating. If you're building a - /// standard library for a new suite of targets, for example, this'll be set - /// to those targets. - target: &'a str, -} - -impl<'a> Step<'a> { - fn noop() -> Step<'a> { - Step { name: "", stage: 0, host: "", target: "" } - } - - /// Creates a new step which is the same as this, except has a new name. - fn name(&self, name: &'a str) -> Step<'a> { - Step { name: name, ..*self } - } - - /// Creates a new step which is the same as this, except has a new stage. - fn stage(&self, stage: u32) -> Step<'a> { - Step { stage: stage, ..*self } - } - - /// Creates a new step which is the same as this, except has a new host. - fn host(&self, host: &'a str) -> Step<'a> { - Step { host: host, ..*self } - } - - /// Creates a new step which is the same as this, except has a new target. - fn target(&self, target: &'a str) -> Step<'a> { - Step { target: target, ..*self } - } - - /// Returns the `Compiler` structure that this step corresponds to. - fn compiler(&self) -> Compiler<'a> { - Compiler::new(self.stage, self.host) - } -} - -struct Rule<'a> { - /// The human readable name of this target, defined in `build_rules`. - name: &'a str, - - /// The path associated with this target, used in the `./x.py` driver for - /// easy and ergonomic specification of what to do. - path: &'a str, - - /// The "kind" of top-level command that this rule is associated with, only - /// relevant if this is a default rule. - kind: Kind, - - /// List of dependencies this rule has. Each dependency is a function from a - /// step that's being executed to another step that should be executed. - deps: Vec) -> Step<'a> + 'a>>, - - /// How to actually execute this rule. Takes a step with contextual - /// information and then executes it. - run: Box) + 'a>, - - /// Whether or not this is a "default" rule. That basically means that if - /// you run, for example, `./x.py test` whether it's included or not. - default: bool, - - /// Whether or not this is a "host" rule, or in other words whether this is - /// only intended for compiler hosts and not for targets that are being - /// generated. - host: bool, - - /// Whether this rule is only for steps where the host is the build triple, - /// not anything in hosts or targets. - only_host_build: bool, - - /// Whether this rule is only for the build triple, not anything in hosts or - /// targets. - only_build: bool, - - /// A list of "order only" dependencies. This rules does not actually - /// depend on these rules, but if they show up in the dependency graph then - /// this rule must be executed after all these rules. - after: Vec<&'a str>, -} - -#[derive(PartialEq)] -enum Kind { - Build, - Test, - Bench, - Dist, - Doc, - Install, -} - -impl<'a> Rule<'a> { - fn new(name: &'a str, path: &'a str, kind: Kind) -> Rule<'a> { - Rule { - name: name, - deps: Vec::new(), - run: Box::new(|_| ()), - path: path, - kind: kind, - default: false, - host: false, - only_host_build: false, - only_build: false, - after: Vec::new(), - } - } -} - -/// Builder pattern returned from the various methods on `Rules` which will add -/// the rule to the internal list on `Drop`. -struct RuleBuilder<'a: 'b, 'b> { - rules: &'b mut Rules<'a>, - rule: Rule<'a>, -} - -impl<'a, 'b> RuleBuilder<'a, 'b> { - fn dep(&mut self, f: F) -> &mut Self - where F: Fn(&Step<'a>) -> Step<'a> + 'a, - { - self.rule.deps.push(Box::new(f)); - self - } - - fn after(&mut self, step: &'a str) -> &mut Self { - self.rule.after.push(step); - self - } - - fn run(&mut self, f: F) -> &mut Self - where F: Fn(&Step<'a>) + 'a, - { - self.rule.run = Box::new(f); - self - } - - fn default(&mut self, default: bool) -> &mut Self { - self.rule.default = default; - self - } - - fn host(&mut self, host: bool) -> &mut Self { - self.rule.host = host; - self - } - - fn only_build(&mut self, only_build: bool) -> &mut Self { - self.rule.only_build = only_build; - self - } - - fn only_host_build(&mut self, only_host_build: bool) -> &mut Self { - self.rule.only_host_build = only_host_build; - self - } -} - -impl<'a, 'b> Drop for RuleBuilder<'a, 'b> { - fn drop(&mut self) { - let rule = mem::replace(&mut self.rule, Rule::new("", "", Kind::Build)); - let prev = self.rules.rules.insert(rule.name, rule); - if let Some(prev) = prev { - panic!("duplicate rule named: {}", prev.name); - } - } -} - -pub struct Rules<'a> { - build: &'a Build, - sbuild: Step<'a>, - rules: BTreeMap<&'a str, Rule<'a>>, -} - -impl<'a> Rules<'a> { - fn new(build: &'a Build) -> Rules<'a> { - Rules { - build: build, - sbuild: Step { - stage: build.flags.stage.unwrap_or(2), - target: &build.build, - host: &build.build, - name: "", - }, - rules: BTreeMap::new(), - } - } - - /// Creates a new rule of `Kind::Build` with the specified human readable - /// name and path associated with it. - /// - /// The builder returned should be configured further with information such - /// as how to actually run this rule. - fn build<'b>(&'b mut self, name: &'a str, path: &'a str) - -> RuleBuilder<'a, 'b> { - self.rule(name, path, Kind::Build) - } - - /// Same as `build`, but for `Kind::Test`. - fn test<'b>(&'b mut self, name: &'a str, path: &'a str) - -> RuleBuilder<'a, 'b> { - self.rule(name, path, Kind::Test) - } - - /// Same as `build`, but for `Kind::Bench`. - fn bench<'b>(&'b mut self, name: &'a str, path: &'a str) - -> RuleBuilder<'a, 'b> { - self.rule(name, path, Kind::Bench) - } - - /// Same as `build`, but for `Kind::Doc`. - fn doc<'b>(&'b mut self, name: &'a str, path: &'a str) - -> RuleBuilder<'a, 'b> { - self.rule(name, path, Kind::Doc) - } - - /// Same as `build`, but for `Kind::Dist`. - fn dist<'b>(&'b mut self, name: &'a str, path: &'a str) - -> RuleBuilder<'a, 'b> { - self.rule(name, path, Kind::Dist) - } - - /// Same as `build`, but for `Kind::Install`. - fn install<'b>(&'b mut self, name: &'a str, path: &'a str) - -> RuleBuilder<'a, 'b> { - self.rule(name, path, Kind::Install) - } - - fn rule<'b>(&'b mut self, - name: &'a str, - path: &'a str, - kind: Kind) -> RuleBuilder<'a, 'b> { - RuleBuilder { - rules: self, - rule: Rule::new(name, path, kind), - } - } - - /// Verify the dependency graph defined by all our rules are correct, e.g. - /// everything points to a valid something else. - fn verify(&self) { - for rule in self.rules.values() { - for dep in rule.deps.iter() { - let dep = dep(&self.sbuild.name(rule.name)); - if self.rules.contains_key(&dep.name) || dep.name.starts_with("default:") { - continue - } - if dep == Step::noop() { - continue - } - panic!("\ - -invalid rule dependency graph detected, was a rule added and maybe typo'd? - - `{}` depends on `{}` which does not exist - -", rule.name, dep.name); - } - } - } - - pub fn get_help(&self, command: &str) -> Option { - let kind = match command { - "build" => Kind::Build, - "doc" => Kind::Doc, - "test" => Kind::Test, - "bench" => Kind::Bench, - "dist" => Kind::Dist, - "install" => Kind::Install, - _ => return None, - }; - let rules = self.rules.values().filter(|r| r.kind == kind); - let rules = rules.filter(|r| !r.path.contains("nowhere")); - let mut rules = rules.collect::>(); - rules.sort_by_key(|r| r.path); - - let mut help_string = String::from("Available paths:\n"); - for rule in rules { - help_string.push_str(format!(" ./x.py {} {}\n", command, rule.path).as_str()); - } - Some(help_string) - } - - /// Construct the top-level build steps that we're going to be executing, - /// given the subcommand that our build is performing. - fn plan(&self) -> Vec> { - // Ok, the logic here is pretty subtle, and involves quite a few - // conditionals. The basic idea here is to: - // - // 1. First, filter all our rules to the relevant ones. This means that - // the command specified corresponds to one of our `Kind` variants, - // and we filter all rules based on that. - // - // 2. Next, we determine which rules we're actually executing. If a - // number of path filters were specified on the command line we look - // for those, otherwise we look for anything tagged `default`. - // Here we also compute the priority of each rule based on how early - // in the command line the matching path filter showed up. - // - // 3. Finally, we generate some steps with host and target information. - // - // The last step is by far the most complicated and subtle. The basic - // thinking here is that we want to take the cartesian product of - // specified hosts and targets and build rules with that. The list of - // hosts and targets, if not specified, come from the how this build was - // configured. If the rule we're looking at is a host-only rule the we - // ignore the list of targets and instead consider the list of hosts - // also the list of targets. - // - // Once the host and target lists are generated we take the cartesian - // product of the two and then create a step based off them. Note that - // the stage each step is associated was specified with the `--step` - // flag on the command line. - let (kind, paths) = match self.build.flags.cmd { - Subcommand::Build { ref paths } => (Kind::Build, &paths[..]), - Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]), - Subcommand::Test { ref paths, .. } => (Kind::Test, &paths[..]), - Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]), - Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]), - Subcommand::Install { ref paths } => (Kind::Install, &paths[..]), - Subcommand::Clean => panic!(), - }; - - let mut rules: Vec<_> = self.rules.values().filter_map(|rule| { - if rule.kind != kind { - return None; - } - - if paths.len() == 0 && rule.default { - Some((rule, 0)) - } else { - paths.iter() - .position(|path| path.ends_with(rule.path)) - .map(|priority| (rule, priority)) - } - }).collect(); - - if rules.is_empty() && - !paths.get(0).unwrap_or(&PathBuf::new()) - .ends_with("nonexistent/path/to/trigger/cargo/metadata") { - println!("\nNothing to run...\n"); - process::exit(1); - } - - rules.sort_by_key(|&(_, priority)| priority); - - rules.into_iter().flat_map(|(rule, _)| { - let hosts = if rule.only_host_build || rule.only_build { - self.build.build_slice() - } else { - &self.build.hosts - }; - // Determine the actual targets participating in this rule. - // NOTE: We should keep the full projection from build triple to - // the hosts for the dist steps, now that the hosts array above is - // truncated to avoid duplication of work in that case. Therefore - // the original non-shadowed hosts array is used below. - let arr = if rule.host { - // If --target was specified but --host wasn't specified, - // don't run any host-only tests. - if self.build.flags.host.len() > 0 { - &self.build.hosts - } else if self.build.flags.target.len() > 0 { - &[] - } else if rule.only_build { - self.build.build_slice() - } else { - &self.build.hosts - } - } else { - &self.build.targets - }; - - hosts.iter().flat_map(move |host| { - arr.iter().map(move |target| { - self.sbuild.name(rule.name).target(target).host(host) - }) - }) - }).collect() - } - - /// Execute all top-level targets indicated by `steps`. - /// - /// This will take the list returned by `plan` and then execute each step - /// along with all required dependencies as it goes up the chain. - fn run(&self, steps: &[Step<'a>]) { - self.build.verbose("bootstrap top targets:"); - for step in steps.iter() { - self.build.verbose(&format!("\t{:?}", step)); - } - - // Using `steps` as the top-level targets, make a topological ordering - // of what we need to do. - let order = self.expand(steps); - - // Print out what we're doing for debugging - self.build.verbose("bootstrap build plan:"); - for step in order.iter() { - self.build.verbose(&format!("\t{:?}", step)); - } - - // And finally, iterate over everything and execute it. - for step in order.iter() { - if self.build.flags.keep_stage.map_or(false, |s| step.stage <= s) { - self.build.verbose(&format!("keeping step {:?}", step)); - continue; - } - self.build.verbose(&format!("executing step {:?}", step)); - (self.rules[step.name].run)(step); - } - - // Check for postponed failures from `test --no-fail-fast`. - let failures = self.build.delayed_failures.get(); - if failures > 0 { - println!("\n{} command(s) did not execute successfully.\n", failures); - process::exit(1); - } - } - - /// From the top level targets `steps` generate a topological ordering of - /// all steps needed to run those steps. - fn expand(&self, steps: &[Step<'a>]) -> Vec> { - // First up build a graph of steps and their dependencies. The `nodes` - // map is a map from step to a unique number. The `edges` map is a - // map from these unique numbers to a list of other numbers, - // representing dependencies. - let mut nodes = HashMap::new(); - nodes.insert(Step::noop(), 0); - let mut edges = HashMap::new(); - edges.insert(0, HashSet::new()); - for step in steps { - self.build_graph(step.clone(), &mut nodes, &mut edges); - } - - // Now that we've built up the actual dependency graph, draw more - // dependency edges to satisfy the `after` dependencies field for each - // rule. - self.satisfy_after_deps(&nodes, &mut edges); - - // And finally, perform a topological sort to return a list of steps to - // execute. - let mut order = Vec::new(); - let mut visited = HashSet::new(); - visited.insert(0); - let idx_to_node = nodes.iter().map(|p| (*p.1, p.0)).collect::>(); - for idx in 0..nodes.len() { - self.topo_sort(idx, &idx_to_node, &edges, &mut visited, &mut order); - } - order - } - - /// Builds the dependency graph rooted at `step`. - /// - /// The `nodes` and `edges` maps are filled out according to the rule - /// described by `step.name`. - fn build_graph(&self, - step: Step<'a>, - nodes: &mut HashMap, usize>, - edges: &mut HashMap>) -> usize { - use std::collections::hash_map::Entry; - - let idx = nodes.len(); - match nodes.entry(step.clone()) { - Entry::Vacant(e) => { e.insert(idx); } - Entry::Occupied(e) => return *e.get(), - } - - let mut deps = Vec::new(); - for dep in self.rules[step.name].deps.iter() { - let dep = dep(&step); - if dep.name.starts_with("default:") { - let kind = match &dep.name[8..] { - "doc" => Kind::Doc, - "dist" => Kind::Dist, - kind => panic!("unknown kind: `{}`", kind), - }; - let host = self.build.config.host.iter().any(|h| h == dep.target); - let rules = self.rules.values().filter(|r| r.default); - for rule in rules.filter(|r| r.kind == kind && (!r.host || host)) { - deps.push(self.build_graph(dep.name(rule.name), nodes, edges)); - } - } else { - deps.push(self.build_graph(dep, nodes, edges)); - } - } - - edges.entry(idx).or_insert(HashSet::new()).extend(deps); - idx - } - - /// Given a dependency graph with a finished list of `nodes`, fill out more - /// dependency `edges`. - /// - /// This is the step which satisfies all `after` listed dependencies in - /// `Rule` above. - fn satisfy_after_deps(&self, - nodes: &HashMap, usize>, - edges: &mut HashMap>) { - // Reverse map from the name of a step to the node indices that it - // appears at. - let mut name_to_idx = HashMap::new(); - for (step, &idx) in nodes { - name_to_idx.entry(step.name).or_insert(Vec::new()).push(idx); - } - - for (step, idx) in nodes { - if *step == Step::noop() { - continue - } - for after in self.rules[step.name].after.iter() { - // This is the critical piece of an `after` dependency. If the - // dependency isn't actually in our graph then no edge is drawn, - // only if it's already present do we draw the edges. - if let Some(idxs) = name_to_idx.get(after) { - edges.get_mut(idx).unwrap() - .extend(idxs.iter().cloned()); - } - } - } - } - - fn topo_sort(&self, - cur: usize, - nodes: &HashMap>, - edges: &HashMap>, - visited: &mut HashSet, - order: &mut Vec>) { - if !visited.insert(cur) { - return - } - for dep in edges[&cur].iter() { - self.topo_sort(*dep, nodes, edges, visited, order); - } - order.push(nodes[&cur].clone()); - } -} - -#[cfg(test)] -mod tests { - use std::env; - - use Build; - use config::Config; - use flags::Flags; - - fn build(args: &[&str], - extra_host: &[&str], - extra_target: &[&str]) -> Build { - build_(args, extra_host, extra_target, true) - } - - fn build_(args: &[&str], - extra_host: &[&str], - extra_target: &[&str], - docs: bool) -> Build { - let mut args = args.iter().map(|s| s.to_string()).collect::>(); - args.push("--build".to_string()); - args.push("A".to_string()); - let flags = Flags::parse(&args); - - let mut config = Config::default(); - config.docs = docs; - config.build = "A".to_string(); - config.host = vec![config.build.clone()]; - config.host.extend(extra_host.iter().map(|s| s.to_string())); - config.target = config.host.clone(); - config.target.extend(extra_target.iter().map(|s| s.to_string())); - - let mut build = Build::new(flags, config); - let cwd = env::current_dir().unwrap(); - build.crates.insert("std".to_string(), ::Crate { - name: "std".to_string(), - deps: Vec::new(), - path: cwd.join("src/std"), - doc_step: "doc-crate-std".to_string(), - build_step: "build-crate-std".to_string(), - test_step: "test-crate-std".to_string(), - bench_step: "bench-crate-std".to_string(), - version: String::new(), - }); - build.crates.insert("test".to_string(), ::Crate { - name: "test".to_string(), - deps: Vec::new(), - path: cwd.join("src/test"), - doc_step: "doc-crate-test".to_string(), - build_step: "build-crate-test".to_string(), - test_step: "test-crate-test".to_string(), - bench_step: "bench-crate-test".to_string(), - version: String::new(), - }); - build.crates.insert("rustc-main".to_string(), ::Crate { - name: "rustc-main".to_string(), - deps: Vec::new(), - version: String::new(), - path: cwd.join("src/rustc-main"), - doc_step: "doc-crate-rustc-main".to_string(), - build_step: "build-crate-rustc-main".to_string(), - test_step: "test-crate-rustc-main".to_string(), - bench_step: "bench-crate-rustc-main".to_string(), - }); - return build - } - - #[test] - fn dist_baseline() { - let build = build(&["dist"], &[], &[]); - let rules = super::build_rules(&build); - let plan = rules.plan(); - println!("rules: {:#?}", plan); - assert!(plan.iter().all(|s| s.stage == 2)); - assert!(plan.iter().all(|s| s.host == "A" )); - assert!(plan.iter().all(|s| s.target == "A" )); - - let step = super::Step { - name: "", - stage: 2, - host: &build.build, - target: &build.build, - }; - - assert!(plan.contains(&step.name("dist-docs"))); - assert!(plan.contains(&step.name("dist-mingw"))); - assert!(plan.contains(&step.name("dist-rustc"))); - assert!(plan.contains(&step.name("dist-std"))); - assert!(plan.contains(&step.name("dist-src"))); - } - - #[test] - fn dist_with_targets() { - let build = build(&["dist"], &[], &["B"]); - let rules = super::build_rules(&build); - let plan = rules.plan(); - println!("rules: {:#?}", plan); - assert!(plan.iter().all(|s| s.stage == 2)); - assert!(plan.iter().all(|s| s.host == "A" )); - - let step = super::Step { - name: "", - stage: 2, - host: &build.build, - target: &build.build, - }; - - assert!(plan.contains(&step.name("dist-docs"))); - assert!(plan.contains(&step.name("dist-mingw"))); - assert!(plan.contains(&step.name("dist-rustc"))); - assert!(plan.contains(&step.name("dist-std"))); - assert!(plan.contains(&step.name("dist-src"))); - - assert!(plan.contains(&step.target("B").name("dist-docs"))); - assert!(plan.contains(&step.target("B").name("dist-mingw"))); - assert!(!plan.contains(&step.target("B").name("dist-rustc"))); - assert!(plan.contains(&step.target("B").name("dist-std"))); - assert!(!plan.contains(&step.target("B").name("dist-src"))); - } - - #[test] - fn dist_with_hosts() { - let build = build(&["dist"], &["B"], &[]); - let rules = super::build_rules(&build); - let plan = rules.plan(); - println!("rules: {:#?}", plan); - assert!(plan.iter().all(|s| s.stage == 2)); - - let step = super::Step { - name: "", - stage: 2, - host: &build.build, - target: &build.build, - }; - - assert!(!plan.iter().any(|s| s.host == "B")); - - assert!(plan.contains(&step.name("dist-docs"))); - assert!(plan.contains(&step.name("dist-mingw"))); - assert!(plan.contains(&step.name("dist-rustc"))); - assert!(plan.contains(&step.name("dist-std"))); - assert!(plan.contains(&step.name("dist-src"))); - - assert!(plan.contains(&step.target("B").name("dist-docs"))); - assert!(plan.contains(&step.target("B").name("dist-mingw"))); - assert!(plan.contains(&step.target("B").name("dist-rustc"))); - assert!(plan.contains(&step.target("B").name("dist-std"))); - assert!(!plan.contains(&step.target("B").name("dist-src"))); - } - - #[test] - fn dist_with_targets_and_hosts() { - let build = build(&["dist"], &["B"], &["C"]); - let rules = super::build_rules(&build); - let plan = rules.plan(); - println!("rules: {:#?}", plan); - assert!(plan.iter().all(|s| s.stage == 2)); - - let step = super::Step { - name: "", - stage: 2, - host: &build.build, - target: &build.build, - }; - - assert!(!plan.iter().any(|s| s.host == "B")); - assert!(!plan.iter().any(|s| s.host == "C")); - - assert!(plan.contains(&step.name("dist-docs"))); - assert!(plan.contains(&step.name("dist-mingw"))); - assert!(plan.contains(&step.name("dist-rustc"))); - assert!(plan.contains(&step.name("dist-std"))); - assert!(plan.contains(&step.name("dist-src"))); - - assert!(plan.contains(&step.target("B").name("dist-docs"))); - assert!(plan.contains(&step.target("B").name("dist-mingw"))); - assert!(plan.contains(&step.target("B").name("dist-rustc"))); - assert!(plan.contains(&step.target("B").name("dist-std"))); - assert!(!plan.contains(&step.target("B").name("dist-src"))); - - assert!(plan.contains(&step.target("C").name("dist-docs"))); - assert!(plan.contains(&step.target("C").name("dist-mingw"))); - assert!(!plan.contains(&step.target("C").name("dist-rustc"))); - assert!(plan.contains(&step.target("C").name("dist-std"))); - assert!(!plan.contains(&step.target("C").name("dist-src"))); - } - - #[test] - fn dist_target_with_target_flag() { - let build = build(&["dist", "--target=C"], &["B"], &["C"]); - let rules = super::build_rules(&build); - let plan = rules.plan(); - println!("rules: {:#?}", plan); - assert!(plan.iter().all(|s| s.stage == 2)); - - let step = super::Step { - name: "", - stage: 2, - host: &build.build, - target: &build.build, - }; - - assert!(!plan.iter().any(|s| s.target == "A")); - assert!(!plan.iter().any(|s| s.target == "B")); - assert!(!plan.iter().any(|s| s.host == "B")); - assert!(!plan.iter().any(|s| s.host == "C")); - - assert!(plan.contains(&step.target("C").name("dist-docs"))); - assert!(plan.contains(&step.target("C").name("dist-mingw"))); - assert!(!plan.contains(&step.target("C").name("dist-rustc"))); - assert!(plan.contains(&step.target("C").name("dist-std"))); - assert!(!plan.contains(&step.target("C").name("dist-src"))); - } - - #[test] - fn dist_host_with_target_flag() { - let build = build(&["dist", "--host=B", "--target=B"], &["B"], &["C"]); - let rules = super::build_rules(&build); - let plan = rules.plan(); - println!("rules: {:#?}", plan); - assert!(plan.iter().all(|s| s.stage == 2)); - - let step = super::Step { - name: "", - stage: 2, - host: &build.build, - target: &build.build, - }; - - assert!(!plan.iter().any(|s| s.target == "A")); - assert!(!plan.iter().any(|s| s.target == "C")); - assert!(!plan.iter().any(|s| s.host == "B")); - assert!(!plan.iter().any(|s| s.host == "C")); - - assert!(plan.contains(&step.target("B").name("dist-docs"))); - assert!(plan.contains(&step.target("B").name("dist-mingw"))); - assert!(plan.contains(&step.target("B").name("dist-rustc"))); - assert!(plan.contains(&step.target("B").name("dist-std"))); - assert!(plan.contains(&step.target("B").name("dist-src"))); - - let all = rules.expand(&plan); - println!("all rules: {:#?}", all); - assert!(!all.contains(&step.name("rustc"))); - assert!(!all.contains(&step.name("build-crate-test").stage(1))); - - // all stage0 compiles should be for the build target, A - for step in all.iter().filter(|s| s.stage == 0) { - if !step.name.contains("build-crate") { - continue - } - println!("step: {:?}", step); - assert!(step.host != "B"); - assert!(step.target != "B"); - assert!(step.host != "C"); - assert!(step.target != "C"); - } - } - - #[test] - fn build_default() { - let build = build(&["build"], &["B"], &["C"]); - let rules = super::build_rules(&build); - let plan = rules.plan(); - println!("rules: {:#?}", plan); - assert!(plan.iter().all(|s| s.stage == 2)); - - let step = super::Step { - name: "", - stage: 2, - host: &build.build, - target: &build.build, - }; - - // rustc built for all for of (A, B) x (A, B) - assert!(plan.contains(&step.name("librustc"))); - assert!(plan.contains(&step.target("B").name("librustc"))); - assert!(plan.contains(&step.host("B").target("A").name("librustc"))); - assert!(plan.contains(&step.host("B").target("B").name("librustc"))); - - // rustc never built for C - assert!(!plan.iter().any(|s| { - s.name.contains("rustc") && (s.host == "C" || s.target == "C") - })); - - // test built for everything - assert!(plan.contains(&step.name("libtest"))); - assert!(plan.contains(&step.target("B").name("libtest"))); - assert!(plan.contains(&step.host("B").target("A").name("libtest"))); - assert!(plan.contains(&step.host("B").target("B").name("libtest"))); - assert!(plan.contains(&step.host("A").target("C").name("libtest"))); - assert!(plan.contains(&step.host("B").target("C").name("libtest"))); - - let all = rules.expand(&plan); - println!("all rules: {:#?}", all); - assert!(all.contains(&step.name("rustc"))); - assert!(all.contains(&step.name("libstd"))); - } - - #[test] - fn build_filtered() { - let build = build(&["build", "--target=C"], &["B"], &["C"]); - let rules = super::build_rules(&build); - let plan = rules.plan(); - println!("rules: {:#?}", plan); - assert!(plan.iter().all(|s| s.stage == 2)); - - assert!(!plan.iter().any(|s| s.name.contains("rustc"))); - assert!(plan.iter().all(|s| { - !s.name.contains("test") || s.target == "C" - })); - } - - #[test] - fn test_default() { - let build = build(&["test"], &[], &[]); - let rules = super::build_rules(&build); - let plan = rules.plan(); - println!("rules: {:#?}", plan); - assert!(plan.iter().all(|s| s.stage == 2)); - assert!(plan.iter().all(|s| s.host == "A")); - assert!(plan.iter().all(|s| s.target == "A")); - - assert!(plan.iter().any(|s| s.name.contains("-ui"))); - assert!(plan.iter().any(|s| s.name.contains("cfail"))); - assert!(plan.iter().any(|s| s.name.contains("cfail-full"))); - assert!(plan.iter().any(|s| s.name.contains("codegen-units"))); - assert!(plan.iter().any(|s| s.name.contains("debuginfo"))); - assert!(plan.iter().any(|s| s.name.contains("docs"))); - assert!(plan.iter().any(|s| s.name.contains("error-index"))); - assert!(plan.iter().any(|s| s.name.contains("incremental"))); - assert!(plan.iter().any(|s| s.name.contains("linkchecker"))); - assert!(plan.iter().any(|s| s.name.contains("mir-opt"))); - assert!(plan.iter().any(|s| s.name.contains("pfail"))); - assert!(plan.iter().any(|s| s.name.contains("rfail"))); - assert!(plan.iter().any(|s| s.name.contains("rfail-full"))); - assert!(plan.iter().any(|s| s.name.contains("rmake"))); - assert!(plan.iter().any(|s| s.name.contains("rpass"))); - assert!(plan.iter().any(|s| s.name.contains("rpass-full"))); - assert!(plan.iter().any(|s| s.name.contains("rustc-all"))); - assert!(plan.iter().any(|s| s.name.contains("rustdoc"))); - assert!(plan.iter().any(|s| s.name.contains("std-all"))); - assert!(plan.iter().any(|s| s.name.contains("test-all"))); - assert!(plan.iter().any(|s| s.name.contains("tidy"))); - assert!(plan.iter().any(|s| s.name.contains("valgrind"))); - } - - #[test] - fn test_with_a_target() { - let build = build(&["test", "--target=C"], &[], &["C"]); - let rules = super::build_rules(&build); - let plan = rules.plan(); - println!("rules: {:#?}", plan); - assert!(plan.iter().all(|s| s.stage == 2)); - assert!(plan.iter().all(|s| s.host == "A")); - assert!(plan.iter().all(|s| s.target == "C")); - - assert!(plan.iter().any(|s| s.name.contains("-ui"))); - assert!(!plan.iter().any(|s| s.name.contains("ui-full"))); - assert!(plan.iter().any(|s| s.name.contains("cfail"))); - assert!(!plan.iter().any(|s| s.name.contains("cfail-full"))); - assert!(plan.iter().any(|s| s.name.contains("codegen-units"))); - assert!(plan.iter().any(|s| s.name.contains("debuginfo"))); - assert!(!plan.iter().any(|s| s.name.contains("docs"))); - assert!(!plan.iter().any(|s| s.name.contains("error-index"))); - assert!(plan.iter().any(|s| s.name.contains("incremental"))); - assert!(!plan.iter().any(|s| s.name.contains("linkchecker"))); - assert!(plan.iter().any(|s| s.name.contains("mir-opt"))); - assert!(plan.iter().any(|s| s.name.contains("pfail"))); - assert!(plan.iter().any(|s| s.name.contains("rfail"))); - assert!(!plan.iter().any(|s| s.name.contains("rfail-full"))); - assert!(!plan.iter().any(|s| s.name.contains("rmake"))); - assert!(plan.iter().any(|s| s.name.contains("rpass"))); - assert!(!plan.iter().any(|s| s.name.contains("rpass-full"))); - assert!(!plan.iter().any(|s| s.name.contains("rustc-all"))); - assert!(!plan.iter().any(|s| s.name.contains("rustdoc"))); - assert!(plan.iter().any(|s| s.name.contains("std-all"))); - assert!(plan.iter().any(|s| s.name.contains("test-all"))); - assert!(!plan.iter().any(|s| s.name.contains("tidy"))); - assert!(plan.iter().any(|s| s.name.contains("valgrind"))); - } - - #[test] - fn test_disable_docs() { - let build = build_(&["test"], &[], &[], false); - let rules = super::build_rules(&build); - let plan = rules.plan(); - println!("rules: {:#?}", plan); - assert!(!plan.iter().any(|s| { - s.name.contains("doc-") || s.name.contains("default:doc") - })); - // none of the dependencies should be a doc rule either - assert!(!plan.iter().any(|s| { - rules.rules[s.name].deps.iter().any(|dep| { - let dep = dep(&rules.sbuild.name(s.name)); - dep.name.contains("doc-") || dep.name.contains("default:doc") - }) - })); - } -} From b05af49086d50bf9f325070746975868f8c16f0f Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 20 Jul 2017 17:24:11 -0600 Subject: [PATCH 47/51] Add an optional condition to constrain defaults. Utilized primarily to not be a default rule unless some configuration is given (e.g., compiler docs are enabled). --- src/bootstrap/builder.rs | 23 ++++++-- src/bootstrap/check.rs | 11 ++-- src/bootstrap/dist.rs | 19 +++---- src/bootstrap/doc.rs | 111 ++++++++++----------------------------- src/bootstrap/install.rs | 6 +-- src/bootstrap/tool.rs | 12 ++--- 6 files changed, 61 insertions(+), 121 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index dd24e8705beb3..bb68ba15ebc57 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -152,17 +152,20 @@ impl StepDescription { } fn run(v: &[StepDescription], builder: &Builder, paths: &[PathBuf]) { + let should_runs = v.iter().map(|desc| { + (desc.should_run)(ShouldRun::new(builder)) + }).collect::>(); if paths.is_empty() { - for desc in v { - if desc.default { + for (desc, should_run) in v.iter().zip(should_runs) { + if desc.default && should_run.is_really_default { desc.maybe_run(builder, None); } } } else { for path in paths { let mut attempted_run = false; - for desc in v { - if (desc.should_run)(ShouldRun::new(builder)).run(path) { + for (desc, should_run) in v.iter().zip(&should_runs) { + if should_run.run(path) { attempted_run = true; desc.maybe_run(builder, Some(path)); } @@ -178,9 +181,13 @@ impl StepDescription { #[derive(Clone)] pub struct ShouldRun<'a> { - builder: &'a Builder<'a>, + pub builder: &'a Builder<'a>, // use a BTreeSet to maintain sort order paths: BTreeSet, + + // If this is a default rule, this is an additional constraint placed on + // it's run. Generally something like compiler docs being enabled. + is_really_default: bool, } impl<'a> ShouldRun<'a> { @@ -188,9 +195,15 @@ impl<'a> ShouldRun<'a> { ShouldRun { builder: builder, paths: BTreeSet::new(), + is_really_default: true, // by default no additional conditions } } + pub fn default_condition(mut self, cond: bool) -> Self { + self.is_really_default = cond; + self + } + pub fn krate(mut self, name: &str) -> Self { for (_, krate_path) in self.builder.crates(name) { self.paths.insert(PathBuf::from(krate_path)); diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 16f14638b51c5..7e9c83d1f76be 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -115,7 +115,8 @@ impl Step for Linkcheck { } fn should_run(run: ShouldRun) -> ShouldRun { - run.path("src/tools/linkchecker") + let builder = run.builder; + run.path("src/tools/linkchecker").default_condition(builder.build.config.docs) } fn make_run( @@ -124,13 +125,7 @@ impl Step for Linkcheck { host: Interned, _target: Interned, ) { - if path.is_some() { - builder.ensure(Linkcheck { host }); - } else { - if builder.build.config.docs { - builder.ensure(Linkcheck { host }); - } - } + builder.ensure(Linkcheck { host }); } } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index bceae8dad9794..b6ab4540ff42b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -607,7 +607,8 @@ impl Step for Analysis { const ONLY_BUILD_TARGETS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.path("analysis") + let builder = run.builder; + run.path("analysis").default_condition(builder.build.config.extended) } fn make_run( @@ -616,9 +617,6 @@ impl Step for Analysis { host: Interned, target: Interned ) { - if path.is_none() && !builder.build.config.extended { - return; - } builder.ensure(Analysis { compiler: builder.compiler(builder.top_stage, host), target: target, @@ -818,16 +816,13 @@ impl Step for PlainSourceTarball { const ONLY_BUILD: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.path("src") + let builder = run.builder; + run.path("src").default_condition(builder.config.rust_dist_src) } fn make_run( builder: &Builder, path: Option<&Path>, _host: Interned, _target: Interned ) { - if path.is_none() && !builder.build.config.rust_dist_src { - return; - } - builder.ensure(PlainSourceTarball); } @@ -1138,15 +1133,13 @@ impl Step for Extended { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.path("cargo") + let builder = run.builder; + run.path("cargo").default_condition(builder.config.extended) } fn make_run( builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned ) { - if path.is_none() && !builder.build.config.extended { - return; - } builder.ensure(Extended { stage: builder.top_stage, target: target, diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 3d8d9e50b20ea..59991e7798ed2 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -45,7 +45,8 @@ macro_rules! book { const DEFAULT: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.path($path) + let builder = run.builder; + run.path($path).default_condition(builder.build.config.docs) } fn make_run( @@ -119,17 +120,13 @@ impl Step for UnstableBook { const DEFAULT: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.path("src/doc/unstable-book") + let builder = run.builder; + run.path("src/doc/unstable-book").default_condition(builder.build.config.docs) } fn make_run( builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned ) { - if path.is_none() && !builder.build.config.docs { - // Not a default rule if docs are disabled. - return; - } - builder.ensure(UnstableBook { target, }); @@ -201,17 +198,13 @@ impl Step for TheBook { const DEFAULT: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.path("src/doc/book") + let builder = run.builder; + run.path("src/doc/book").default_condition(builder.build.config.docs) } fn make_run( builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned ) { - if path.is_none() && !builder.build.config.docs { - // Not a default rule if docs are disabled. - return; - } - builder.ensure(TheBook { target, name: "book", @@ -417,31 +410,17 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.krate("std") + let builder = run.builder; + run.krate("std").default_condition(builder.build.config.docs) } - fn make_run( builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned ) { - let run = || { - builder.ensure(Std { - stage: builder.top_stage, - target - }); - }; - - if let Some(path) = path { - for (_, krate_path) in builder.crates("std") { - if path.ends_with(krate_path) { - run(); - } - } - } else { - if builder.build.config.docs { - run(); - } - } + builder.ensure(Std { + stage: builder.top_stage, + target + }); } /// Compile all standard library documentation. @@ -520,30 +499,17 @@ impl Step for Test { const DEFAULT: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.krate("test") + let builder = run.builder; + run.krate("test").default_condition(builder.config.compiler_docs) } fn make_run( builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned ) { - let run = || { - builder.ensure(Test { - stage: builder.top_stage, - target - }); - }; - - if let Some(path) = path { - for (_, krate_path) in builder.crates("test") { - if path.ends_with(krate_path) { - run(); - } - } - } else { - if builder.build.config.compiler_docs { - run(); - } - } + builder.ensure(Test { + stage: builder.top_stage, + target + }); } /// Compile all libtest documentation. @@ -597,30 +563,17 @@ impl Step for Rustc { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.krate("rustc-main") + let builder = run.builder; + run.krate("rustc-main").default_condition(builder.build.config.docs) } fn make_run( builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned ) { - let run = || { - builder.ensure(Rustc { - stage: builder.top_stage, - target - }); - }; - - if let Some(path) = path { - for (_, krate_path) in builder.crates("rustc-main") { - if path.ends_with(krate_path) { - run(); - } - } - } else { - if builder.build.config.docs { - run(); - } - } + builder.ensure(Rustc { + stage: builder.top_stage, + target + }); } /// Generate all compiler documentation. @@ -690,17 +643,13 @@ impl Step for ErrorIndex { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.path("src/tools/error_index_generator") + let builder = run.builder; + run.path("src/tools/error_index_generator").default_condition(builder.build.config.docs) } fn make_run( builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned ) { - if path.is_none() && !builder.build.config.docs { - // Not a default rule if docs are disabled. - return; - } - builder.ensure(ErrorIndex { target, }); @@ -742,17 +691,13 @@ impl Step for UnstableBookGen { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.path("src/tools/unstable-book-gen") + let builder = run.builder; + run.path("src/tools/unstable-book-gen").default_condition(builder.build.config.docs) } fn make_run( builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned, ) { - if path.is_none() && !builder.build.config.docs { - // Not a default rule if docs are disabled. - return; - } - builder.ensure(UnstableBookGen { target, }); diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 7b2d644c7696d..d2870832086e8 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -150,7 +150,8 @@ macro_rules! install { $(const $c: bool = true;)* fn should_run(run: ShouldRun) -> ShouldRun { - run.path($path) + let $builder = run.builder; + run.path($path).default_condition($default_cond) } fn make_run( @@ -159,9 +160,6 @@ macro_rules! install { host: Interned, target: Interned, ) { - if path.is_none() && !($default_cond) { - return; - } $builder.ensure($name { stage: $builder.top_stage, target, diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 9db6493ba3172..07763d519c880 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -248,15 +248,13 @@ impl Step for Cargo { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.path("src/tools/cargo") + let builder = run.builder; + run.path("src/tools/cargo").default_condition(builder.build.config.extended) } fn make_run( builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned ) { - if path.is_none() && !builder.build.config.extended { - return; - } builder.ensure(Cargo { stage: builder.top_stage, target, @@ -294,15 +292,13 @@ impl Step for Rls { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.path("src/tools/rls") + let builder = run.builder; + run.path("src/tools/rls").default_condition(builder.build.config.extended) } fn make_run( builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned ) { - if path.is_none() && !builder.build.config.extended { - return; - } builder.ensure(Rls { stage: builder.top_stage, target, From 6a67a050c62a14c75a314b498ab6dcf6620b29c7 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 20 Jul 2017 17:51:07 -0600 Subject: [PATCH 48/51] Change make_run signature to taking a RunConfig struct for refactorability. --- src/bootstrap/builder.rs | 24 ++++-- src/bootstrap/check.rs | 175 +++++++++++++-------------------------- src/bootstrap/compile.rs | 54 ++++-------- src/bootstrap/dist.rs | 109 +++++++++--------------- src/bootstrap/doc.rs | 96 ++++++++------------- src/bootstrap/install.rs | 35 ++++---- src/bootstrap/lib.rs | 2 +- src/bootstrap/native.rs | 11 +-- src/bootstrap/tool.rs | 50 ++++------- 9 files changed, 203 insertions(+), 353 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index bb68ba15ebc57..7be391e542027 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -79,12 +79,7 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { /// When path is `None`, we are executing in a context where no paths were /// passed. When `./x.py build` is run, for example, this rule could get /// called if it is in the correct list below with a path of `None`. - fn make_run( - _builder: &Builder, - _path: Option<&Path>, - _host: Interned, - _target: Interned, - ) { + fn make_run(_run: RunConfig) { // It is reasonable to not have an implementation of make_run for rules // who do not want to get called from the root context. This means that // they are likely dependencies (e.g., sysroot creation) or similar, and @@ -93,13 +88,20 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { } } +pub struct RunConfig<'a> { + pub builder: &'a Builder<'a>, + pub host: Interned, + pub target: Interned, + pub path: Option<&'a Path>, +} + struct StepDescription { default: bool, only_hosts: bool, only_build_targets: bool, only_build: bool, should_run: fn(ShouldRun) -> ShouldRun, - make_run: fn(&Builder, Option<&Path>, Interned, Interned), + make_run: fn(RunConfig), } impl StepDescription { @@ -146,7 +148,13 @@ impl StepDescription { for host in hosts { for target in targets { - (self.make_run)(builder, path, *host, *target); + let run = RunConfig { + builder, + path, + host: *host, + target: *target, + }; + (self.make_run)(run); } } } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 7e9c83d1f76be..a07505edc2eb8 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -31,7 +31,7 @@ use util::{self, dylib_path, dylib_path_var}; use compile; use native; -use builder::{Kind, ShouldRun, Builder, Compiler, Step}; +use builder::{Kind, RunConfig, ShouldRun, Builder, Compiler, Step}; use tool::{self, Tool}; use cache::{INTERNER, Interned}; @@ -119,13 +119,8 @@ impl Step for Linkcheck { run.path("src/tools/linkchecker").default_condition(builder.build.config.docs) } - fn make_run( - builder: &Builder, - path: Option<&Path>, - host: Interned, - _target: Interned, - ) { - builder.ensure(Linkcheck { host }); + fn make_run(run: RunConfig) { + run.builder.ensure(Linkcheck { host: run.host }); } } @@ -143,15 +138,10 @@ impl Step for Cargotest { run.path("src/tools/cargotest") } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - host: Interned, - _target: Interned, - ) { - builder.ensure(Cargotest { - stage: builder.top_stage, - host: host, + fn make_run(run: RunConfig) { + run.builder.ensure(Cargotest { + stage: run.builder.top_stage, + host: run.host, }); } @@ -193,15 +183,10 @@ impl Step for Cargo { run.path("src/tools/cargo") } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - _host: Interned, - target: Interned, - ) { - builder.ensure(Cargo { - stage: builder.top_stage, - host: target, + fn make_run(run: RunConfig) { + run.builder.ensure(Cargo { + stage: run.builder.top_stage, + host: run.target, }); } @@ -242,15 +227,10 @@ impl Step for Rls { run.path("src/tools/rls") } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - _host: Interned, - target: Interned, - ) { - builder.ensure(Rls { - stage: builder.top_stage, - host: target, + fn make_run(run: RunConfig) { + run.builder.ensure(Rls { + stage: run.builder.top_stage, + host: run.target, }); } @@ -320,14 +300,9 @@ impl Step for Tidy { run.path("src/tools/tidy") } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - _host: Interned, - _target: Interned, - ) { - builder.ensure(Tidy { - host: builder.build.build, + fn make_run(run: RunConfig) { + run.builder.ensure(Tidy { + host: run.builder.build.build, }); } } @@ -382,15 +357,10 @@ impl Step for DefaultCompiletest { run } - fn make_run( - builder: &Builder, - path: Option<&Path>, - host: Interned, - target: Interned, - ) { - let compiler = builder.compiler(builder.top_stage, host); + fn make_run(run: RunConfig) { + let compiler = run.builder.compiler(run.builder.top_stage, run.host); - let test = path.map(|path| { + let test = run.path.map(|path| { DEFAULT_COMPILETESTS.iter().find(|&&test| { path.ends_with(test.path) }).unwrap_or_else(|| { @@ -399,17 +369,17 @@ impl Step for DefaultCompiletest { }); if let Some(test) = test { - builder.ensure(DefaultCompiletest { + run.builder.ensure(DefaultCompiletest { compiler, - target, + target: run.target, mode: test.mode, suite: test.suite, }); } else { for test in DEFAULT_COMPILETESTS { - builder.ensure(DefaultCompiletest { + run.builder.ensure(DefaultCompiletest { compiler, - target, + target: run.target, mode: test.mode, suite: test.suite }); @@ -468,15 +438,10 @@ impl Step for HostCompiletest { run } - fn make_run( - builder: &Builder, - path: Option<&Path>, - host: Interned, - target: Interned, - ) { - let compiler = builder.compiler(builder.top_stage, host); + fn make_run(run: RunConfig) { + let compiler = run.builder.compiler(run.builder.top_stage, run.host); - let test = path.map(|path| { + let test = run.path.map(|path| { HOST_COMPILETESTS.iter().find(|&&test| { path.ends_with(test.path) }).unwrap_or_else(|| { @@ -485,17 +450,17 @@ impl Step for HostCompiletest { }); if let Some(test) = test { - builder.ensure(HostCompiletest { + run.builder.ensure(HostCompiletest { compiler, - target, + target: run.target, mode: test.mode, suite: test.suite, }); } else { for test in HOST_COMPILETESTS { - builder.ensure(HostCompiletest { + run.builder.ensure(HostCompiletest { compiler, - target, + target: run.target, mode: test.mode, suite: test.suite }); @@ -739,14 +704,9 @@ impl Step for Docs { run.path("src/doc") } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - host: Interned, - _target: Interned, - ) { - builder.ensure(Docs { - compiler: builder.compiler(builder.top_stage, host), + fn make_run(run: RunConfig) { + run.builder.ensure(Docs { + compiler: run.builder.compiler(run.builder.top_stage, run.host), }); } @@ -802,14 +762,9 @@ impl Step for ErrorIndex { run.path("src/tools/error_index_generator") } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - host: Interned, - _target: Interned, - ) { - builder.ensure(ErrorIndex { - compiler: builder.compiler(builder.top_stage, host), + fn make_run(run: RunConfig) { + run.builder.ensure(ErrorIndex { + compiler: run.builder.compiler(run.builder.top_stage, run.host), }); } @@ -886,15 +841,11 @@ impl Step for CrateLibrustc { run.krate("rustc-main") } - fn make_run( - builder: &Builder, - path: Option<&Path>, - host: Interned, - target: Interned, - ) { - let compiler = builder.compiler(builder.top_stage, host); + fn make_run(run: RunConfig) { + let builder = run.builder; + let compiler = builder.compiler(builder.top_stage, run.host); - let run = |name: Option>| { + let make = |name: Option>| { let test_kind = if builder.kind == Kind::Test { TestKind::Test } else if builder.kind == Kind::Bench { @@ -905,20 +856,20 @@ impl Step for CrateLibrustc { builder.ensure(CrateLibrustc { compiler, - target, + target: run.target, test_kind: test_kind, krate: name, }); }; - if let Some(path) = path { + if let Some(path) = run.path { for (name, krate_path) in builder.crates("rustc-main") { if path.ends_with(krate_path) { - run(Some(name)); + make(Some(name)); } } } else { - run(None); + make(None); } } @@ -952,15 +903,11 @@ impl Step for Crate { run.krate("std").krate("test") } - fn make_run( - builder: &Builder, - path: Option<&Path>, - host: Interned, - target: Interned, - ) { - let compiler = builder.compiler(builder.top_stage, host); + fn make_run(run: RunConfig) { + let builder = run.builder; + let compiler = builder.compiler(builder.top_stage, run.host); - let run = |mode: Mode, name: Option>| { + let make = |mode: Mode, name: Option>| { let test_kind = if builder.kind == Kind::Test { TestKind::Test } else if builder.kind == Kind::Bench { @@ -970,27 +917,28 @@ impl Step for Crate { }; builder.ensure(Crate { - compiler, target, + compiler, + target: run.target, mode: mode, test_kind: test_kind, krate: name, }); }; - if let Some(path) = path { + if let Some(path) = run.path { for (name, krate_path) in builder.crates("std") { if path.ends_with(krate_path) { - run(Mode::Libstd, Some(name)); + make(Mode::Libstd, Some(name)); } } for (name, krate_path) in builder.crates("test") { if path.ends_with(krate_path) { - run(Mode::Libtest, Some(name)); + make(Mode::Libtest, Some(name)); } } } else { - run(Mode::Libstd, None); - run(Mode::Libtest, None); + make(Mode::Libstd, None); + make(Mode::Libtest, None); } } @@ -1333,12 +1281,7 @@ impl Step for Bootstrap { run.path("src/bootstrap") } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - _host: Interned, - _target: Interned, - ) { - builder.ensure(Bootstrap); + fn make_run(run: RunConfig) { + run.builder.ensure(Bootstrap); } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 4453f1627ef3a..ddb2b27d60f91 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -34,7 +34,7 @@ use {Build, Compiler, Mode}; use native; use cache::{INTERNER, Interned}; -use builder::{Step, ShouldRun, Builder}; +use builder::{Step, RunConfig, ShouldRun, Builder}; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Std { @@ -50,15 +50,10 @@ impl Step for Std { run.path("src/libstd").krate("std") } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - host: Interned, - target: Interned, - ) { - builder.ensure(Std { - compiler: builder.compiler(builder.top_stage, host), - target, + fn make_run(run: RunConfig) { + run.builder.ensure(Std { + compiler: run.builder.compiler(run.builder.top_stage, run.host), + target: run.target, }); } @@ -233,15 +228,10 @@ impl Step for StartupObjects { run.path("src/rtstartup") } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - host: Interned, - target: Interned, - ) { - builder.ensure(StartupObjects { - compiler: builder.compiler(builder.top_stage, host), - target, + fn make_run(run: RunConfig) { + run.builder.ensure(StartupObjects { + compiler: run.builder.compiler(run.builder.top_stage, run.host), + target: run.target, }); } @@ -300,15 +290,10 @@ impl Step for Test { run.path("src/libtest").krate("test") } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - host: Interned, - target: Interned, - ) { - builder.ensure(Test { - compiler: builder.compiler(builder.top_stage, host), - target, + fn make_run(run: RunConfig) { + run.builder.ensure(Test { + compiler: run.builder.compiler(run.builder.top_stage, run.host), + target: run.target, }); } @@ -407,15 +392,10 @@ impl Step for Rustc { run.path("src/librustc").krate("rustc-main") } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - host: Interned, - target: Interned, - ) { - builder.ensure(Rustc { - compiler: builder.compiler(builder.top_stage, host), - target, + fn make_run(run: RunConfig) { + run.builder.ensure(Rustc { + compiler: run.builder.compiler(run.builder.top_stage, run.host), + target: run.target, }); } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index b6ab4540ff42b..9719b2472c63c 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -29,7 +29,7 @@ use build_helper::output; use {Build, Compiler, Mode}; use channel; use util::{cp_r, libdir, is_dylib, cp_filtered, copy, exe}; -use builder::{Builder, ShouldRun, Step}; +use builder::{Builder, RunConfig, ShouldRun, Step}; use compile; use tool::{self, Tool}; use cache::{INTERNER, Interned}; @@ -72,12 +72,10 @@ impl Step for Docs { run.path("src/doc") } - fn make_run( - builder: &Builder, _path: Option<&Path>, _host: Interned, target: Interned, - ) { - builder.ensure(Docs { - stage: builder.top_stage, - target: target, + fn make_run(run: RunConfig) { + run.builder.ensure(Docs { + stage: run.builder.top_stage, + target: run.target, }); } @@ -275,10 +273,8 @@ impl Step for Mingw { run.never() } - fn make_run( - builder: &Builder, _path: Option<&Path>, _host: Interned, target: Interned - ) { - builder.ensure(Mingw { target }); + fn make_run(run: RunConfig) { + run.builder.ensure(Mingw { target: run.target }); } /// Build the `rust-mingw` installer component. @@ -338,12 +334,10 @@ impl Step for Rustc { run.path("src/librustc") } - fn make_run( - builder: &Builder, _path: Option<&Path>, _host: Interned, target: Interned - ) { - builder.ensure(Rustc { - stage: builder.top_stage, - target: target, + fn make_run(run: RunConfig) { + run.builder.ensure(Rustc { + stage: run.builder.top_stage, + target: run.target, }); } @@ -475,12 +469,10 @@ impl Step for DebuggerScripts { run.path("src/lldb_batchmode.py") } - fn make_run( - builder: &Builder, _path: Option<&Path>, host: Interned, target: Interned - ) { - builder.ensure(DebuggerScripts { - sysroot: builder.sysroot(builder.compiler(builder.top_stage, host)), - target: target, + fn make_run(run: RunConfig) { + run.builder.ensure(DebuggerScripts { + sysroot: run.builder.sysroot(run.builder.compiler(run.builder.top_stage, run.host)), + target: run.target, }); } @@ -535,12 +527,10 @@ impl Step for Std { run.path("src/libstd") } - fn make_run( - builder: &Builder, _path: Option<&Path>, host: Interned, target: Interned - ) { - builder.ensure(Std { - compiler: builder.compiler(builder.top_stage, host), - target: target, + fn make_run(run: RunConfig) { + run.builder.ensure(Std { + compiler: run.builder.compiler(run.builder.top_stage, run.host), + target: run.target, }); } @@ -611,15 +601,10 @@ impl Step for Analysis { run.path("analysis").default_condition(builder.build.config.extended) } - fn make_run( - builder: &Builder, - path: Option<&Path>, - host: Interned, - target: Interned - ) { - builder.ensure(Analysis { - compiler: builder.compiler(builder.top_stage, host), - target: target, + fn make_run(run: RunConfig) { + run.builder.ensure(Analysis { + compiler: run.builder.compiler(run.builder.top_stage, run.host), + target: run.target, }); } @@ -728,10 +713,8 @@ impl Step for Src { run.path("src") } - fn make_run( - builder: &Builder, _path: Option<&Path>, _host: Interned, _target: Interned - ) { - builder.ensure(Src); + fn make_run(run: RunConfig) { + run.builder.ensure(Src); } /// Creates the `rust-src` installer component @@ -820,10 +803,8 @@ impl Step for PlainSourceTarball { run.path("src").default_condition(builder.config.rust_dist_src) } - fn make_run( - builder: &Builder, path: Option<&Path>, _host: Interned, _target: Interned - ) { - builder.ensure(PlainSourceTarball); + fn make_run(run: RunConfig) { + run.builder.ensure(PlainSourceTarball); } /// Creates the plain source tarball @@ -962,12 +943,10 @@ impl Step for Cargo { run.path("cargo") } - fn make_run( - builder: &Builder, _path: Option<&Path>, _host: Interned, target: Interned - ) { - builder.ensure(Cargo { - stage: builder.top_stage, - target: target, + fn make_run(run: RunConfig) { + run.builder.ensure(Cargo { + stage: run.builder.top_stage, + target: run.target, }); } @@ -1054,12 +1033,10 @@ impl Step for Rls { run.path("rls") } - fn make_run( - builder: &Builder, _path: Option<&Path>, _host: Interned, target: Interned - ) { - builder.ensure(Rls { - stage: builder.top_stage, - target: target, + fn make_run(run: RunConfig) { + run.builder.ensure(Rls { + stage: run.builder.top_stage, + target: run.target, }); } @@ -1137,12 +1114,10 @@ impl Step for Extended { run.path("cargo").default_condition(builder.config.extended) } - fn make_run( - builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned - ) { - builder.ensure(Extended { - stage: builder.top_stage, - target: target, + fn make_run(run: RunConfig) { + run.builder.ensure(Extended { + stage: run.builder.top_stage, + target: run.target, }); } @@ -1535,10 +1510,8 @@ impl Step for HashSign { run.path("hash-and-sign") } - fn make_run( - builder: &Builder, _path: Option<&Path>, _host: Interned, _target: Interned - ) { - builder.ensure(HashSign); + fn make_run(run: RunConfig) { + run.builder.ensure(HashSign); } fn run(self, builder: &Builder) { diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 59991e7798ed2..8834fa24d6983 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -27,7 +27,7 @@ use Mode; use build_helper::up_to_date; use util::{cp_r, symlink_dir}; -use builder::{Builder, ShouldRun, Step}; +use builder::{Builder, RunConfig, ShouldRun, Step}; use tool::Tool; use compile; use cache::{INTERNER, Interned}; @@ -49,19 +49,9 @@ macro_rules! book { run.path($path).default_condition(builder.build.config.docs) } - fn make_run( - builder: &Builder, - path: Option<&Path>, - _host: Interned, - target: Interned - ) { - if path.is_none() && !builder.build.config.docs { - // Not a default rule if docs are disabled. - return; - } - - builder.ensure($name { - target, + fn make_run(run: RunConfig) { + run.builder.ensure($name { + target: run.target, }); } @@ -124,11 +114,9 @@ impl Step for UnstableBook { run.path("src/doc/unstable-book").default_condition(builder.build.config.docs) } - fn make_run( - builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned - ) { - builder.ensure(UnstableBook { - target, + fn make_run(run: RunConfig) { + run.builder.ensure(UnstableBook { + target: run.target, }); } @@ -202,11 +190,9 @@ impl Step for TheBook { run.path("src/doc/book").default_condition(builder.build.config.docs) } - fn make_run( - builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned - ) { - builder.ensure(TheBook { - target, + fn make_run(run: RunConfig) { + run.builder.ensure(TheBook { + target: run.target, name: "book", }); } @@ -308,19 +294,13 @@ impl Step for Standalone { const DEFAULT: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { - run.path("src/doc") + let builder = run.builder; + run.path("src/doc").default_condition(builder.build.config.docs) } - fn make_run( - builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned - ) { - if path.is_none() && !builder.build.config.docs { - // Not a default rule if docs are disabled. - return; - } - - builder.ensure(Standalone { - target, + fn make_run(run: RunConfig) { + run.builder.ensure(Standalone { + target: run.target, }); } @@ -414,12 +394,10 @@ impl Step for Std { run.krate("std").default_condition(builder.build.config.docs) } - fn make_run( - builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned - ) { - builder.ensure(Std { - stage: builder.top_stage, - target + fn make_run(run: RunConfig) { + run.builder.ensure(Std { + stage: run.builder.top_stage, + target: run.target }); } @@ -503,12 +481,10 @@ impl Step for Test { run.krate("test").default_condition(builder.config.compiler_docs) } - fn make_run( - builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned - ) { - builder.ensure(Test { - stage: builder.top_stage, - target + fn make_run(run: RunConfig) { + run.builder.ensure(Test { + stage: run.builder.top_stage, + target: run.target, }); } @@ -567,12 +543,10 @@ impl Step for Rustc { run.krate("rustc-main").default_condition(builder.build.config.docs) } - fn make_run( - builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned - ) { - builder.ensure(Rustc { - stage: builder.top_stage, - target + fn make_run(run: RunConfig) { + run.builder.ensure(Rustc { + stage: run.builder.top_stage, + target: run.target, }); } @@ -647,11 +621,9 @@ impl Step for ErrorIndex { run.path("src/tools/error_index_generator").default_condition(builder.build.config.docs) } - fn make_run( - builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned - ) { - builder.ensure(ErrorIndex { - target, + fn make_run(run: RunConfig) { + run.builder.ensure(ErrorIndex { + target: run.target, }); } @@ -695,11 +667,9 @@ impl Step for UnstableBookGen { run.path("src/tools/unstable-book-gen").default_condition(builder.build.config.docs) } - fn make_run( - builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned, - ) { - builder.ensure(UnstableBookGen { - target, + fn make_run(run: RunConfig) { + run.builder.ensure(UnstableBookGen { + target: run.target, }); } diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index d2870832086e8..85402e875d9ad 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -20,7 +20,7 @@ use std::process::Command; use dist::{self, pkgname, sanitize_sh, tmpdir}; -use builder::{Builder, ShouldRun, Step}; +use builder::{Builder, RunConfig, ShouldRun, Step}; use cache::Interned; pub fn install_docs(builder: &Builder, stage: u32, host: Interned) { @@ -128,7 +128,7 @@ fn add_destdir(path: &Path, destdir: &Option) -> PathBuf { } macro_rules! install { - (($sel:ident, $builder:ident), + (($sel:ident, $builder:ident, $_config:ident), $($name:ident, $path:expr, $default_cond:expr, @@ -150,20 +150,15 @@ macro_rules! install { $(const $c: bool = true;)* fn should_run(run: ShouldRun) -> ShouldRun { - let $builder = run.builder; + let $_config = &run.builder.config; run.path($path).default_condition($default_cond) } - fn make_run( - $builder: &Builder, - path: Option<&Path>, - host: Interned, - target: Interned, - ) { - $builder.ensure($name { - stage: $builder.top_stage, - target, - host, + fn make_run(run: RunConfig) { + run.builder.ensure($name { + stage: run.builder.top_stage, + target: run.target, + host: run.host, }); } @@ -174,8 +169,8 @@ macro_rules! install { } } -install!((self, builder), - Docs, "src/doc", builder.build.config.docs, only_hosts: false, { +install!((self, builder, _config), + Docs, "src/doc", _config.docs, only_hosts: false, { builder.ensure(dist::Docs { stage: self.stage, target: self.target }); install_docs(builder, self.stage, self.target); }; @@ -186,26 +181,26 @@ install!((self, builder), }); install_std(builder, self.stage); }; - Cargo, "cargo", builder.build.config.extended, only_hosts: true, { + Cargo, "cargo", _config.extended, only_hosts: true, { builder.ensure(dist::Cargo { stage: self.stage, target: self.target }); install_cargo(builder, self.stage, self.target); }; - Rls, "rls", builder.build.config.extended, only_hosts: true, { + Rls, "rls", _config.extended, only_hosts: true, { builder.ensure(dist::Rls { stage: self.stage, target: self.target }); install_rls(builder, self.stage, self.target); }; - Analysis, "analysis", builder.build.config.extended, only_hosts: false, { + Analysis, "analysis", _config.extended, only_hosts: false, { builder.ensure(dist::Analysis { compiler: builder.compiler(self.stage, self.host), target: self.target }); install_analysis(builder, self.stage, self.target); }; - Src, "src", builder.build.config.extended, only_hosts: true, { + Src, "src", _config.extended, only_hosts: true, { builder.ensure(dist::Src); install_src(builder, self.stage); }, ONLY_BUILD; - Rustc, "src/librustc", builder.build.config.extended, only_hosts: true, { + Rustc, "src/librustc", _config.extended, only_hosts: true, { builder.ensure(dist::Rustc { stage: self.stage, target: self.target }); install_rustc(builder, self.stage, self.target); }; diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 472aea783f2d1..5b5ef3f07f98e 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -96,7 +96,7 @@ //! provide those libraries for it; they are mostly equivalent to constructing //! the stage1/bin compiler so we don't go through them individually. //! -//! ## Uplifiting stage1 {std,test,rustc} +//! ## Uplifting stage1 {std,test,rustc} //! //! This step copies the libraries from the stage1 compiler sysroot into the //! stage2 compiler. This is done to avoid rebuilding the compiler; libraries diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index dc78a43d52647..f0dfd857ab619 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -32,7 +32,7 @@ use gcc; use Build; use util; use build_helper::up_to_date; -use builder::{Builder, ShouldRun, Step}; +use builder::{Builder, RunConfig, ShouldRun, Step}; use cache::Interned; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] @@ -247,13 +247,8 @@ impl Step for TestHelpers { run.path("src/rt/rust_test_helpers.c") } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - _host: Interned, - target: Interned, - ) { - builder.ensure(TestHelpers { target }) + fn make_run(run: RunConfig) { + run.builder.ensure(TestHelpers { target: run.target }) } /// Compiles the `rust_test_helpers.c` library which we used in various diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 07763d519c880..b31d891051cf7 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -9,12 +9,12 @@ // except according to those terms. use std::env; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::process::Command; use Mode; use Compiler; -use builder::{Step, ShouldRun, Builder}; +use builder::{Step, RunConfig, ShouldRun, Builder}; use util::{exe, add_lib_path}; use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp}; use native; @@ -163,15 +163,10 @@ macro_rules! tool { run.path($path) } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - _host: Interned, - target: Interned - ) { - builder.ensure($name { - stage: builder.top_stage, - target, + fn make_run(run: RunConfig) { + run.builder.ensure($name { + stage: run.builder.top_stage, + target: run.target, }); } @@ -214,15 +209,10 @@ impl Step for RemoteTestServer { run.path("src/tools/remote-test-server") } - fn make_run( - builder: &Builder, - _path: Option<&Path>, - _host: Interned, - target: Interned - ) { - builder.ensure(RemoteTestServer { - stage: builder.top_stage, - target, + fn make_run(run: RunConfig) { + run.builder.ensure(RemoteTestServer { + stage: run.builder.top_stage, + target: run.target, }); } @@ -252,12 +242,10 @@ impl Step for Cargo { run.path("src/tools/cargo").default_condition(builder.build.config.extended) } - fn make_run( - builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned - ) { - builder.ensure(Cargo { - stage: builder.top_stage, - target, + fn make_run(run: RunConfig) { + run.builder.ensure(Cargo { + stage: run.builder.top_stage, + target: run.target, }); } @@ -296,12 +284,10 @@ impl Step for Rls { run.path("src/tools/rls").default_condition(builder.build.config.extended) } - fn make_run( - builder: &Builder, path: Option<&Path>, _host: Interned, target: Interned - ) { - builder.ensure(Rls { - stage: builder.top_stage, - target, + fn make_run(run: RunConfig) { + run.builder.ensure(Rls { + stage: run.builder.top_stage, + target: run.target, }); } From d302c189378b2ee057c14589c2a5d5722b9d4933 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Sat, 22 Jul 2017 05:50:55 -0600 Subject: [PATCH 49/51] Fix StartupObject build --- src/bootstrap/compile.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index ddb2b27d60f91..cbe2be2d26ad7 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -263,7 +263,7 @@ impl Step for StartupObjects { .arg("--cfg").arg("stage0") .arg("--target").arg(target) .arg("--emit=obj") - .arg("--o").arg(dst_file) + .arg("-o").arg(dst_file) .arg(src_file)); } From 8f2e576cb31208de574c783b468ce5503ad8db2d Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Sat, 22 Jul 2017 07:35:42 -0600 Subject: [PATCH 50/51] Add make_run to distcheck. --- src/bootstrap/check.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index a07505edc2eb8..fe24a666de2bb 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -1197,6 +1197,10 @@ impl Step for Distcheck { run.path("distcheck") } + fn make_run(run: RunConfig) { + run.builder.ensure(Distcheck); + } + /// Run "distcheck", a 'make check' from a tarball fn run(self, builder: &Builder) { let build = builder.build; From 1c118231adaa941899773420b21bc6b55ca3014f Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Sat, 22 Jul 2017 10:48:29 -0600 Subject: [PATCH 51/51] Make distcheck work again. --- src/bootstrap/check.rs | 4 ++++ src/bootstrap/dist.rs | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index fe24a666de2bb..ee58926175291 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -1220,6 +1220,10 @@ impl Step for Distcheck { let _ = fs::remove_dir_all(&dir); t!(fs::create_dir_all(&dir)); + // Guarantee that these are built before we begin running. + builder.ensure(dist::PlainSourceTarball); + builder.ensure(dist::Src); + let mut cmd = Command::new("tar"); cmd.arg("-xzf") .arg(builder.ensure(dist::PlainSourceTarball)) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 9719b2472c63c..cdaab9d9c8d9e 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -875,9 +875,10 @@ impl Step for PlainSourceTarball { let mut tarball = distdir(build).join(&format!("{}.tar.gz", plain_name)); tarball.set_extension(""); // strip .gz tarball.set_extension(""); // strip .tar - if let Some(dir) = distdir(build).parent() { + if let Some(dir) = tarball.parent() { t!(fs::create_dir_all(dir)); } + println!("running installer"); let mut cmd = rust_installer(builder); cmd.arg("tarball") .arg("--input").arg(&plain_name)