From 6aeb1cfb64ea04e334d296bf9a47c659116c96bf Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Mon, 15 Jan 2018 10:44:00 -0700 Subject: [PATCH] Add ./x.py check src/{libstd,libtest,rustc}. This currently only supports a limited subset of the full compilation, but is likely 90% of what people will want and is possible without building a full compiler (i.e., running LLVM). In theory, this means that contributors who don't want to build LLVM now have an easy way to compile locally, though running tests won't work. --- src/bootstrap/bin/rustc.rs | 5 -- src/bootstrap/bootstrap.py | 1 + src/bootstrap/builder.rs | 23 +++--- src/bootstrap/check.rs | 163 +++++++++++++++++++++++++++++++++++++ src/bootstrap/compile.rs | 16 ++-- src/bootstrap/flags.rs | 23 ++++++ src/bootstrap/lib.rs | 7 +- 7 files changed, 211 insertions(+), 27 deletions(-) create mode 100644 src/bootstrap/check.rs diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 37336a56d76..55d104b1826 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -125,11 +125,6 @@ fn main() { cmd.arg(format!("-Clinker={}", target_linker)); } - // Pass down incremental directory, if any. - if let Ok(dir) = env::var("RUSTC_INCREMENTAL") { - cmd.arg(format!("-Zincremental={}", dir)); - } - let crate_name = args.windows(2) .find(|a| &*a[0] == "--crate-name") .unwrap(); diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 93c3694bc0c..ecf9c0a7590 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -602,6 +602,7 @@ class RustBuild(object): env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ (os.pathsep + env["LIBRARY_PATH"]) \ if "LIBRARY_PATH" in env else "" + env["RUSTFLAGS"] = "-Cdebuginfo=2" env["PATH"] = os.path.join(self.bin_root(), "bin") + \ os.pathsep + env["PATH"] if not os.path.isfile(self.cargo()): diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 7655097681b..79058984b13 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -26,6 +26,7 @@ use util::{exe, libdir, add_lib_path}; use {Build, Mode}; use cache::{INTERNER, Interned, Cache}; use check; +use test; use flags::Subcommand; use doc; use tool; @@ -230,6 +231,7 @@ impl<'a> ShouldRun<'a> { #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Kind { Build, + Check, Test, Bench, Dist, @@ -251,13 +253,13 @@ 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), - Kind::Test => describe!(check::Tidy, check::Bootstrap, check::DefaultCompiletest, - check::HostCompiletest, check::Crate, check::CrateLibrustc, check::Rustdoc, - check::Linkcheck, check::Cargotest, check::Cargo, check::Rls, check::Docs, - check::ErrorIndex, check::Distcheck, check::Rustfmt, check::Miri, check::Clippy, - check::RustdocJS), - - Kind::Bench => describe!(check::Crate, check::CrateLibrustc), + Kind::Check => describe!(check::Std, check::Test, check::Rustc), + Kind::Test => describe!(test::Tidy, test::Bootstrap, test::DefaultCompiletest, + test::HostCompiletest, test::Crate, test::CrateLibrustc, test::Rustdoc, + test::Linkcheck, test::Cargotest, test::Cargo, test::Rls, test::Docs, + test::ErrorIndex, test::Distcheck, test::Rustfmt, test::Miri, test::Clippy, + test::RustdocJS), + Kind::Bench => describe!(test::Crate, test::CrateLibrustc), Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon, doc::Reference, doc::Rustdoc, doc::RustByExample, doc::CargoBook), @@ -304,6 +306,7 @@ impl<'a> Builder<'a> { pub fn run(build: &Build) { let (kind, paths) = match build.config.cmd { Subcommand::Build { ref paths } => (Kind::Build, &paths[..]), + Subcommand::Check { ref paths } => (Kind::Check, &paths[..]), Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]), Subcommand::Test { ref paths, .. } => (Kind::Test, &paths[..]), Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]), @@ -493,13 +496,14 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_CODEGEN_UNITS", n.to_string()); } + if let Some(host_linker) = self.build.linker(compiler.host) { cargo.env("RUSTC_HOST_LINKER", host_linker); } if let Some(target_linker) = self.build.linker(target) { cargo.env("RUSTC_TARGET_LINKER", target_linker); } - if cmd != "build" { + if cmd != "build" && cmd != "check" { cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.build.build))); } @@ -566,8 +570,7 @@ impl<'a> Builder<'a> { // not guaranteeing correctness across builds if the compiler // is changing under your feet.` if self.config.incremental && compiler.stage == 0 { - let incr_dir = self.incremental_dir(compiler); - cargo.env("RUSTC_INCREMENTAL", incr_dir); + cargo.env("CARGO_INCREMENTAL", "1"); } if let Some(ref on_fail) = self.config.on_fail { diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs new file mode 100644 index 00000000000..0bc82c4f9f2 --- /dev/null +++ b/src/bootstrap/check.rs @@ -0,0 +1,163 @@ +// Copyright 2018 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. + +//! 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 builder::{RunConfig, Builder, ShouldRun, Step}; +use {Build, Compiler, Mode}; +use cache::Interned; +use std::path::PathBuf; + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Std { + pub target: Interned, +} + +impl Step for Std { + type Output = (); + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/libstd").krate("std") + } + + fn make_run(run: RunConfig) { + run.builder.ensure(Std { + target: run.target, + }); + } + + fn run(self, builder: &Builder) { + let build = builder.build; + let target = self.target; + let compiler = builder.compiler(0, build.build); + + let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); + println!("Checking std artifacts ({} -> {})", &compiler.host, target); + + let out_dir = build.stage_out(compiler, Mode::Libstd); + build.clear_if_dirty(&out_dir, &builder.rustc(compiler)); + let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "check"); + std_cargo(build, &compiler, target, &mut cargo); + run_cargo(build, + &mut cargo, + &libstd_stamp(build, compiler, target), + true); + let libdir = builder.sysroot_libdir(compiler, target); + add_to_sysroot(&libdir, &libstd_stamp(build, compiler, target)); + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Rustc { + pub target: Interned, +} + +impl Step for Rustc { + type Output = (); + const ONLY_HOSTS: bool = true; + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/librustc").krate("rustc-main") + } + + fn make_run(run: RunConfig) { + run.builder.ensure(Rustc { + target: run.target, + }); + } + + /// 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 = builder.compiler(0, build.build); + let target = self.target; + + let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); + println!("Checking compiler artifacts ({} -> {})", &compiler.host, target); + + let stage_out = builder.stage_out(compiler, Mode::Librustc); + build.clear_if_dirty(&stage_out, &libstd_stamp(build, compiler, target)); + build.clear_if_dirty(&stage_out, &libtest_stamp(build, compiler, target)); + + let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check"); + rustc_cargo(build, target, &mut cargo); + run_cargo(build, + &mut cargo, + &librustc_stamp(build, compiler, target), + true); + let libdir = builder.sysroot_libdir(compiler, target); + add_to_sysroot(&libdir, &librustc_stamp(build, compiler, target)); + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Test { + pub target: Interned, +} + +impl Step for Test { + type Output = (); + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + run.path("src/libtest").krate("test") + } + + fn make_run(run: RunConfig) { + run.builder.ensure(Test { + target: run.target, + }); + } + + fn run(self, builder: &Builder) { + let build = builder.build; + let target = self.target; + let compiler = builder.compiler(0, build.build); + + let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); + println!("Checking test artifacts ({} -> {})", &compiler.host, target); + let out_dir = build.stage_out(compiler, Mode::Libtest); + build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); + let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "check"); + test_cargo(build, &compiler, target, &mut cargo); + run_cargo(build, + &mut cargo, + &libtest_stamp(build, compiler, target), + true); + let libdir = builder.sysroot_libdir(compiler, target); + add_to_sysroot(&libdir, &libtest_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: Interned) -> PathBuf { + build.cargo_out(compiler, Mode::Libstd, target).join(".libstd-check.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: Interned) -> PathBuf { + build.cargo_out(compiler, Mode::Libtest, target).join(".libtest-check.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: Interned) -> PathBuf { + build.cargo_out(compiler, Mode::Librustc, target).join(".librustc-check.stamp") +} + diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index c6adfc7ffae..21bbd82dd33 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -108,7 +108,8 @@ impl Step for Std { std_cargo(build, &compiler, target, &mut cargo); run_cargo(build, &mut cargo, - &libstd_stamp(build, compiler, target)); + &libstd_stamp(build, compiler, target), + false); builder.ensure(StdLink { compiler: builder.compiler(compiler.stage, build.build), @@ -360,7 +361,8 @@ impl Step for Test { test_cargo(build, &compiler, target, &mut cargo); run_cargo(build, &mut cargo, - &libtest_stamp(build, compiler, target)); + &libtest_stamp(build, compiler, target), + false); builder.ensure(TestLink { compiler: builder.compiler(compiler.stage, build.build), @@ -488,7 +490,8 @@ impl Step for Rustc { rustc_cargo(build, target, &mut cargo); run_cargo(build, &mut cargo, - &librustc_stamp(build, compiler, target)); + &librustc_stamp(build, compiler, target), + false); builder.ensure(RustcLink { compiler: builder.compiler(compiler.stage, build.build), @@ -755,7 +758,7 @@ impl Step for Assemble { /// /// For a particular stage this will link the file listed in `stamp` into the /// `sysroot_dst` provided. -fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) { +pub fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) { t!(fs::create_dir_all(&sysroot_dst)); for path in read_stamp_file(stamp) { copy(&path, &sysroot_dst.join(path.file_name().unwrap())); @@ -785,7 +788,7 @@ fn stderr_isatty() -> bool { } } -fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) { +pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: bool) { // Instruct Cargo to give us json messages on stdout, critically leaving // stderr as piped so we can get those pretty colors. cargo.arg("--message-format").arg("json") @@ -836,7 +839,8 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) { // Skip files like executables if !filename.ends_with(".rlib") && !filename.ends_with(".lib") && - !is_dylib(&filename) { + !is_dylib(&filename) && + !(is_check && filename.ends_with(".rmeta")) { continue } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 0816c4dfe3d..478e496078a 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -48,6 +48,9 @@ pub enum Subcommand { Build { paths: Vec, }, + Check { + paths: Vec, + }, Doc { paths: Vec, }, @@ -88,6 +91,7 @@ Usage: x.py [options] [...] Subcommands: build Compile either the compiler or libraries + check Compile either the compiler or libraries, using cargo check test Build and run some test suites bench Build and run some benchmarks doc Build documentation @@ -128,6 +132,7 @@ To learn more about a subcommand, run `./x.py -h`"); // there on out. let subcommand = args.iter().find(|&s| (s == "build") + || (s == "check") || (s == "test") || (s == "bench") || (s == "doc") @@ -217,6 +222,21 @@ Arguments: arguments would), and then use the compiler built in stage 0 to build src/libtest and its dependencies. Once this is done, build/$ARCH/stage1 contains a usable compiler."); + } + "check" => { + subcommand_help.push_str("\n +Arguments: + This subcommand accepts a number of paths to directories to the crates + and/or artifacts to compile. For example: + + ./x.py check src/libcore + ./x.py check src/libcore src/libproc_macro + + If no arguments are passed then the complete artifacts are compiled: std, test, and rustc. Note + also that since we use `cargo check`, by default this will automatically enable incremental + compilation, so there's no need to pass it separately, though it won't hurt. We also completely + ignore the stage passed, as there's no way to compile in non-stage 0 without actually building + the compiler."); } "test" => { subcommand_help.push_str("\n @@ -286,6 +306,9 @@ Arguments: "build" => { Subcommand::Build { paths: paths } } + "check" => { + Subcommand::Check { paths: paths } + } "test" => { Subcommand::Test { paths, diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 3738828a4ba..565320c9521 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -150,6 +150,7 @@ use util::{exe, libdir, OutputFolder, CiEnv}; mod cc_detect; mod channel; mod check; +mod test; mod clean; mod compile; mod metadata; @@ -449,12 +450,6 @@ impl Build { out } - /// 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)) - } - /// Returns the root directory for all output generated in a particular /// stage when running with a particular host compiler. ///