diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 20c89f99b2b0c..872271c453ecc 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -310,7 +310,7 @@ impl<'a> Builder<'a> { tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient, tool::RustInstaller, tool::Cargo, tool::Rls, tool::Rustdoc, tool::Clippy, native::Llvm, tool::Rustfmt, tool::Miri, native::Lld), - Kind::Check => describe!(check::Std, check::Test, check::Rustc), + Kind::Check => describe!(check::Std, check::Test, check::Rustc, check::CodegenBackend), Kind::Test => describe!(test::Tidy, test::Bootstrap, test::Ui, test::RunPass, test::CompileFail, test::ParseFail, test::RunFail, test::RunPassValgrind, test::MirOpt, test::Codegen, test::CodegenUnits, test::Incremental, test::Debuginfo, @@ -552,6 +552,12 @@ impl<'a> Builder<'a> { .arg("--target") .arg(target); + // Set a flag for `check` so that certain build scripts can do less work + // (e.g. not building/requiring LLVM). + if cmd == "check" { + cargo.env("RUST_CHECK", "1"); + } + // If we were invoked from `make` then that's already got a jobserver // set up for us so no need to tell Cargo about jobs all over again. if env::var_os("MAKEFLAGS").is_none() && env::var_os("MFLAGS").is_none() { @@ -834,7 +840,7 @@ impl<'a> Builder<'a> { cargo } - /// Ensure that a given step is built, returning it's output. This will + /// Ensure that a given step is built, returning its 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 { diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index adebd424d7eb6..e7c6ec888dfb1 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -10,10 +10,10 @@ //! Implementation of compiling the compiler and standard library, in "check" mode. -use compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, add_to_sysroot}; +use compile::{run_cargo, std_cargo, test_cargo, rustc_cargo, rustc_cargo_env, add_to_sysroot}; use builder::{RunConfig, Builder, ShouldRun, Step}; use {Compiler, Mode}; -use cache::Interned; +use cache::{INTERNER, Interned}; use std::path::PathBuf; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -104,6 +104,52 @@ impl Step for Rustc { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct CodegenBackend { + pub target: Interned, + pub backend: Interned, +} + +impl Step for CodegenBackend { + type Output = (); + const ONLY_HOSTS: bool = true; + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + run.all_krates("rustc_trans") + } + + fn make_run(run: RunConfig) { + let backend = run.builder.config.rust_codegen_backends.get(0); + let backend = backend.cloned().unwrap_or_else(|| { + INTERNER.intern_str("llvm") + }); + run.builder.ensure(CodegenBackend { + target: run.target, + backend, + }); + } + + fn run(self, builder: &Builder) { + let compiler = builder.compiler(0, builder.config.build); + let target = self.target; + let backend = self.backend; + + let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check"); + let features = builder.rustc_features().to_string(); + cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_trans/Cargo.toml")); + rustc_cargo_env(builder, &mut cargo); + + // We won't build LLVM if it's not available, as it shouldn't affect `check`. + + let _folder = builder.fold_output(|| format!("stage{}-rustc_trans", compiler.stage)); + run_cargo(builder, + cargo.arg("--features").arg(features), + &codegen_backend_stamp(builder, compiler, target, backend), + true); + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Test { pub target: Interned, @@ -161,3 +207,13 @@ pub fn libtest_stamp(builder: &Builder, compiler: Compiler, target: Interned) -> PathBuf { builder.cargo_out(compiler, Mode::Librustc, target).join(".librustc-check.stamp") } + +/// Cargo's output path for librustc_trans in a given stage, compiled by a particular +/// compiler for the specified target and backend. +fn codegen_backend_stamp(builder: &Builder, + compiler: Compiler, + target: Interned, + backend: Interned) -> PathBuf { + builder.cargo_out(compiler, Mode::Librustc, target) + .join(format!(".librustc_trans-{}-check.stamp", backend)) +} diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 07bce77af8d24..1248c2b50be5e 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -519,7 +519,7 @@ pub fn rustc_cargo(builder: &Builder, cargo: &mut Command) { rustc_cargo_env(builder, cargo); } -fn rustc_cargo_env(builder: &Builder, cargo: &mut Command) { +pub fn rustc_cargo_env(builder: &Builder, cargo: &mut Command) { // Set some configuration variables picked up by build scripts and // the compiler alike cargo.env("CFG_RELEASE", builder.rust_release()) @@ -614,13 +614,14 @@ impl Step for CodegenBackend { run.builder.ensure(CodegenBackend { compiler: run.builder.compiler(run.builder.top_stage, run.host), target: run.target, - backend + backend, }); } fn run(self, builder: &Builder) { let compiler = self.compiler; let target = self.target; + let backend = self.backend; builder.ensure(Rustc { compiler, target }); @@ -628,7 +629,7 @@ impl Step for CodegenBackend { builder.ensure(CodegenBackend { compiler: builder.compiler(1, builder.config.build), target, - backend: self.backend, + backend, }); return; } @@ -639,52 +640,7 @@ impl Step for CodegenBackend { .arg(builder.src.join("src/librustc_trans/Cargo.toml")); rustc_cargo_env(builder, &mut cargo); - match &*self.backend { - "llvm" | "emscripten" => { - // Build LLVM for our target. This will implicitly build the - // host LLVM if necessary. - let llvm_config = builder.ensure(native::Llvm { - target, - emscripten: self.backend == "emscripten", - }); - - if self.backend == "emscripten" { - features.push_str(" emscripten"); - } - - builder.info(&format!("Building stage{} codegen artifacts ({} -> {}, {})", - compiler.stage, &compiler.host, target, self.backend)); - - // Pass down configuration from the LLVM build into the build of - // librustc_llvm and librustc_trans. - if builder.is_rust_llvm(target) { - cargo.env("LLVM_RUSTLLVM", "1"); - } - cargo.env("LLVM_CONFIG", &llvm_config); - if self.backend != "emscripten" { - let target_config = builder.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 builder.config.llvm_static_stdcpp && - !target.contains("freebsd") && - !target.contains("windows") && - !target.contains("apple") { - let file = compiler_file(builder, - builder.cxx(target).unwrap(), - target, - "libstdc++.a"); - cargo.env("LLVM_STATIC_STDCPP", file); - } - if builder.config.llvm_link_shared { - cargo.env("LLVM_LINK_SHARED", "1"); - } - } - _ => panic!("unknown backend: {}", self.backend), - } + features += &build_codegen_backend(&builder, &mut cargo, &compiler, target, backend); let tmp_stamp = builder.cargo_out(compiler, Mode::Librustc, target) .join(".tmp.stamp"); @@ -711,12 +667,69 @@ impl Step for CodegenBackend { codegen_backend.display(), f.display()); } - let stamp = codegen_backend_stamp(builder, compiler, target, self.backend); + let stamp = codegen_backend_stamp(builder, compiler, target, backend); let codegen_backend = codegen_backend.to_str().unwrap(); t!(t!(File::create(&stamp)).write_all(codegen_backend.as_bytes())); } } +pub fn build_codegen_backend(builder: &Builder, + cargo: &mut Command, + compiler: &Compiler, + target: Interned, + backend: Interned) -> String { + let mut features = String::new(); + + match &*backend { + "llvm" | "emscripten" => { + // Build LLVM for our target. This will implicitly build the + // host LLVM if necessary. + let llvm_config = builder.ensure(native::Llvm { + target, + emscripten: backend == "emscripten", + }); + + if backend == "emscripten" { + features.push_str(" emscripten"); + } + + builder.info(&format!("Building stage{} codegen artifacts ({} -> {}, {})", + compiler.stage, &compiler.host, target, backend)); + + // Pass down configuration from the LLVM build into the build of + // librustc_llvm and librustc_trans. + if builder.is_rust_llvm(target) { + cargo.env("LLVM_RUSTLLVM", "1"); + } + cargo.env("LLVM_CONFIG", &llvm_config); + if backend != "emscripten" { + let target_config = builder.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 builder.config.llvm_static_stdcpp && + !target.contains("freebsd") && + !target.contains("windows") && + !target.contains("apple") { + let file = compiler_file(builder, + builder.cxx(target).unwrap(), + target, + "libstdc++.a"); + cargo.env("LLVM_STATIC_STDCPP", file); + } + if builder.config.llvm_link_shared { + cargo.env("LLVM_LINK_SHARED", "1"); + } + } + _ => panic!("unknown backend: {}", backend), + } + + features +} + /// Creates the `codegen-backends` folder for a compiler that's about to be /// assembled as a complete compiler. /// @@ -795,6 +808,8 @@ pub fn librustc_stamp(builder: &Builder, compiler: Compiler, target: Interned, @@ -803,7 +818,7 @@ fn codegen_backend_stamp(builder: &Builder, .join(format!(".librustc_trans-{}.stamp", backend)) } -fn compiler_file(builder: &Builder, +pub fn compiler_file(builder: &Builder, compiler: &Path, target: Interned, file: &str) -> PathBuf { diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 54e3f544acb68..1619637b827df 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -28,6 +28,12 @@ fn detect_llvm_link() -> (&'static str, &'static str) { } fn main() { + if env::var_os("RUST_CHECK").is_some() { + // If we're just running `check`, there's no need for LLVM to be built. + println!("cargo:rerun-if-env-changed=RUST_CHECK"); + return; + } + let target = env::var("TARGET").expect("TARGET was not set"); let llvm_config = env::var_os("LLVM_CONFIG") .map(PathBuf::from)