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.
This commit is contained in:
Mark Simulacrum 2018-01-15 10:44:00 -07:00
parent 734ee0fb43
commit 6aeb1cfb64
7 changed files with 211 additions and 27 deletions

View File

@ -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();

View File

@ -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()):

View File

@ -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 {

163
src/bootstrap/check.rs Normal file
View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<String>,
}
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<String>,
}
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<String>,
}
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<String>) -> 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<String>) -> 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<String>) -> PathBuf {
build.cargo_out(compiler, Mode::Librustc, target).join(".librustc-check.stamp")
}

View File

@ -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
}

View File

@ -48,6 +48,9 @@ pub enum Subcommand {
Build {
paths: Vec<PathBuf>,
},
Check {
paths: Vec<PathBuf>,
},
Doc {
paths: Vec<PathBuf>,
},
@ -88,6 +91,7 @@ Usage: x.py <subcommand> [options] [<paths>...]
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 <subcommand> -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,

View File

@ -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.
///