From 6b3413d825fa61a16fcfaa37a114eaf3efe88eb3 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 5 Jul 2017 06:41:27 -0600 Subject: [PATCH] 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 0278b8d5dbf..2fd02d3d7c4 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { } 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { } 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { // 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 cf1e11f7ac8..07a0f63e6cb 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 @@ 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)); + + 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { // 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { // .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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { // 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 @@ fn run(self, builder: &Builder) { /// 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 @@ fn run(self, builder: &Builder) { #[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 8aa9ad7021e..da513b1f2f6 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &builder) { 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 @@ fn run(self, builder: &builder) { 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 @@ fn prepare_image(build: &Build, stage: u32, host: &str, image: &Path) { 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 @@ fn prepare_image(build: &Build, stage: u32, host: &str, image: &Path) { } } - - //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 @@ fn run(self, builder: &Builder) { // 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 @@ fn run(self, builder: &Builder) { 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 @@ fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn add_env(build: &Build, cmd: &mut Command, target: &str) { 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 466d63a15ac..11edee62344 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -27,27 +27,70 @@ 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 @@ fn run(self, builder: &Builder) { // 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { 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 638b0613bf2..3e895bbe900 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 6ae5c03bfeb..2b44f33db8e 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -33,7 +33,7 @@ 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 @@ fn run(self, builder: &Builder) { // 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 @@ fn run(self, builder: &Builder) { #[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 52ec273c3e8..442ca7aadbc 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -15,7 +15,7 @@ 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 @@ fn run(self, builder: &Builder) { 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 @@ fn run(self, builder: &Builder) { } } -// 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 @@ fn run(self, builder: &Builder) { } 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, + }) } } -- 2.44.0