rust/src/bootstrap/check.rs

409 lines
14 KiB
Rust
Raw Normal View History

2018-12-04 19:26:54 +01:00
//! Implementation of compiling the compiler and standard library, in "check"-based modes.
2020-10-10 06:47:15 +02:00
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::cache::Interned;
use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo};
use crate::config::TargetSelection;
2018-12-07 13:21:05 +01:00
use crate::tool::{prepare_tool_cargo, SourceType};
use crate::INTERNER;
2020-09-30 02:24:14 +02:00
use crate::{Compiler, Mode, Subcommand};
use std::path::PathBuf;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Std {
pub target: TargetSelection,
}
2020-09-30 02:24:14 +02:00
/// Returns args for the subcommand itself (not for cargo)
fn args(builder: &Builder<'_>) -> Vec<String> {
fn strings<'a>(arr: &'a [&str]) -> impl Iterator<Item = String> + 'a {
arr.iter().copied().map(String::from)
}
2020-09-30 02:24:14 +02:00
if let Subcommand::Clippy { fix, .. } = builder.config.cmd {
// disable the most spammy clippy lints
let ignored_lints = vec![
"many_single_char_names", // there are a lot in stdarch
"collapsible_if",
"type_complexity",
"missing_safety_doc", // almost 3K warnings
"too_many_arguments",
"needless_lifetimes", // people want to keep the lifetimes
"wrong_self_convention",
];
let mut args = vec![];
2020-09-30 02:24:14 +02:00
if fix {
#[rustfmt::skip]
args.extend(strings(&[
"--fix", "-Zunstable-options",
// FIXME: currently, `--fix` gives an error while checking tests for libtest,
// possibly because libtest is not yet built in the sysroot.
// As a workaround, avoid checking tests and benches when passed --fix.
"--lib", "--bins", "--examples",
]));
2020-09-30 02:24:14 +02:00
}
args.extend(strings(&["--", "--cap-lints", "warn"]));
args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint)));
2020-09-30 02:24:14 +02:00
args
} else {
vec![]
2018-12-04 19:26:54 +01:00
}
}
fn cargo_subcommand(kind: Kind) -> &'static str {
match kind {
Kind::Check => "check",
Kind::Clippy => "clippy",
Kind::Fix => "fix",
2019-12-22 23:42:04 +01:00
_ => unreachable!(),
2018-12-04 19:26:54 +01:00
}
}
impl Step for Std {
type Output = ();
const DEFAULT: bool = true;
2019-02-25 11:30:32 +01:00
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2019-08-27 17:32:21 +02:00
run.all_krates("test")
}
2019-02-25 11:30:32 +01:00
fn make_run(run: RunConfig<'_>) {
2019-12-22 23:42:04 +01:00
run.builder.ensure(Std { target: run.target });
}
2019-02-25 11:30:32 +01:00
fn run(self, builder: &Builder<'_>) {
let target = self.target;
2021-01-16 03:43:23 +01:00
let compiler = builder.compiler(builder.top_stage, builder.config.build);
let mut cargo = builder.cargo(
compiler,
Mode::Std,
SourceType::InTree,
target,
cargo_subcommand(builder.kind),
);
std_cargo(builder, target, compiler.stage, &mut cargo);
builder.info(&format!(
"Checking stage{} std artifacts ({} -> {})",
builder.top_stage, &compiler.host, target
));
2019-12-22 23:42:04 +01:00
run_cargo(
builder,
cargo,
2020-09-30 02:24:14 +02:00
args(builder),
2019-12-22 23:42:04 +01:00
&libstd_stamp(builder, compiler, target),
vec![],
true,
);
2021-01-16 03:43:23 +01:00
// We skip populating the sysroot in non-zero stage because that'll lead
// to rlib/rmeta conflicts if std gets built during this session.
if compiler.stage == 0 {
let libdir = builder.sysroot_libdir(compiler, target);
let hostdir = builder.sysroot_libdir(compiler, compiler.host);
add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
}
// Then run cargo again, once we've put the rmeta files for the library
// crates into the sysroot. This is needed because e.g., core's tests
// depend on `libtest` -- Cargo presumes it will exist, but it doesn't
// since we initialize with an empty sysroot.
//
// Currently only the "libtest" tree of crates does this.
if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
let mut cargo = builder.cargo(
compiler,
Mode::Std,
SourceType::InTree,
target,
cargo_subcommand(builder.kind),
);
std_cargo(builder, target, compiler.stage, &mut cargo);
cargo.arg("--all-targets");
// Explicitly pass -p for all dependencies krates -- this will force cargo
// to also check the tests/benches/examples for these crates, rather
// than just the leaf crate.
for krate in builder.in_tree_crates("test", Some(target)) {
cargo.arg("-p").arg(krate.name);
}
builder.info(&format!(
"Checking stage{} std test/bench/example targets ({} -> {})",
builder.top_stage, &compiler.host, target
));
run_cargo(
builder,
cargo,
2020-09-30 02:24:14 +02:00
args(builder),
&libstd_test_stamp(builder, compiler, target),
vec![],
true,
);
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Rustc {
pub target: TargetSelection,
}
impl Step for Rustc {
type Output = ();
const ONLY_HOSTS: bool = true;
const DEFAULT: bool = true;
2019-02-25 11:30:32 +01:00
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2018-02-11 17:51:58 +01:00
run.all_krates("rustc-main")
}
2019-02-25 11:30:32 +01:00
fn make_run(run: RunConfig<'_>) {
2019-12-22 23:42:04 +01:00
run.builder.ensure(Rustc { target: run.target });
}
2019-02-08 14:53:55 +01:00
/// Builds 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.
2019-02-25 11:30:32 +01:00
fn run(self, builder: &Builder<'_>) {
2021-01-16 03:43:23 +01:00
let compiler = builder.compiler(builder.top_stage, builder.config.build);
let target = self.target;
2021-01-16 03:43:23 +01:00
if compiler.stage != 0 {
// If we're not in stage 0, then we won't have a std from the beta
// compiler around. That means we need to make sure there's one in
// the sysroot for the compiler to find. Otherwise, we're going to
// fail when building crates that need to generate code (e.g., build
// scripts and their dependencies).
builder.ensure(crate::compile::Std { target: compiler.host, compiler });
builder.ensure(crate::compile::Std { target, compiler });
} else {
builder.ensure(Std { target });
}
2018-08-02 20:01:04 +02:00
let mut cargo = builder.cargo(
compiler,
Mode::Rustc,
SourceType::InTree,
target,
cargo_subcommand(builder.kind),
);
rustc: Link LLVM directly into rustc again This commit builds on #65501 continue to simplify the build system and compiler now that we no longer have multiple LLVM backends to ship by default. Here this switches the compiler back to what it once was long long ago, which is linking LLVM directly to the compiler rather than dynamically loading it at runtime. The `codegen-backends` directory of the sysroot no longer exists and all relevant support in the build system is removed. Note that `rustc` still supports a dynamically loaded codegen backend as it did previously, it just no longer supports dynamically loaded codegen backends in its own sysroot. Additionally as part of this the `librustc_codegen_llvm` crate now once again explicitly depends on all of its crates instead of implicitly loading them through the sysroot. This involved filling out its `Cargo.toml` and deleting all the now-unnecessary `extern crate` annotations in the header of the crate. (this in turn required adding a number of imports for names of macros too). The end results of this change are: * Rustbuild's build process for the compiler as all the "oh don't forget the codegen backend" checks can be easily removed. * Building `rustc_codegen_llvm` is much simpler since it's simply another compiler crate. * Managing the dependencies of `rustc_codegen_llvm` is much simpler since it's "just another `Cargo.toml` to edit" * The build process should be a smidge faster because there's more parallelism in the main rustc build step rather than splitting `librustc_codegen_llvm` out to its own step. * The compiler is expected to be slightly faster by default because the codegen backend does not need to be dynamically loaded. * Disabling LLVM as part of rustbuild is still supported, supporting multiple codegen backends is still supported, and dynamic loading of a codegen backend is still supported.
2019-10-22 17:51:35 +02:00
rustc_cargo(builder, &mut cargo, target);
if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
cargo.arg("--all-targets");
}
// Explicitly pass -p for all compiler krates -- this will force cargo
// to also check the tests/benches/examples for these crates, rather
// than just the leaf crate.
for krate in builder.in_tree_crates("rustc-main", Some(target)) {
cargo.arg("-p").arg(krate.name);
}
builder.info(&format!(
"Checking stage{} compiler artifacts ({} -> {})",
builder.top_stage, &compiler.host, target
));
2019-12-22 23:42:04 +01:00
run_cargo(
builder,
cargo,
2020-09-30 02:24:14 +02:00
args(builder),
2019-12-22 23:42:04 +01:00
&librustc_stamp(builder, compiler, target),
vec![],
true,
);
let libdir = builder.sysroot_libdir(compiler, target);
2018-12-02 21:47:41 +01:00
let hostdir = builder.sysroot_libdir(compiler, compiler.host);
add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct CodegenBackend {
pub target: TargetSelection,
pub backend: Interned<String>,
}
impl Step for CodegenBackend {
type Output = ();
const ONLY_HOSTS: bool = true;
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.paths(&["compiler/rustc_codegen_cranelift", "rustc_codegen_cranelift"])
}
fn make_run(run: RunConfig<'_>) {
for &backend in &[INTERNER.intern_str("cranelift")] {
run.builder.ensure(CodegenBackend { target: run.target, backend });
}
}
fn run(self, builder: &Builder<'_>) {
2021-01-16 03:43:23 +01:00
let compiler = builder.compiler(builder.top_stage, builder.config.build);
let target = self.target;
let backend = self.backend;
builder.ensure(Rustc { target });
let mut cargo = builder.cargo(
compiler,
Mode::Codegen,
SourceType::Submodule,
target,
cargo_subcommand(builder.kind),
);
cargo
.arg("--manifest-path")
.arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
rustc_cargo_env(builder, &mut cargo, target);
Print 'checking cranelift artifacts' to easily separate it from other artifacts Before: ``` Checking rustdoc artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu) Checking rustdoc v0.0.0 (/home/joshua/rustc/src/librustdoc) Checking rustdoc-tool v0.0.0 (/home/joshua/rustc/src/tools/rustdoc) Finished release [optimized] target(s) in 2.08s Checking regalloc v0.0.31 Checking gimli v0.22.0 Checking object v0.21.1 Checking cranelift-codegen v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) Checking cranelift-module v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) Checking cranelift-native v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) Checking cranelift-frontend v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) Checking cranelift-object v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) Checking cranelift-simplejit v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) Checking rustc_codegen_cranelift v0.1.0 (/home/joshua/rustc/compiler/rustc_codegen_cranelift) Finished release [optimized] target(s) in 10.55s ``` After: ``` Checking rustdoc artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu) Checking rustdoc v0.0.0 (/home/joshua/rustc/src/librustdoc) Checking rustdoc-tool v0.0.0 (/home/joshua/rustc/src/tools/rustdoc) Finished release [optimized] target(s) in 2.08s Checking cranelift artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu) Checking cranelift-codegen v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) ```
2020-11-14 23:35:50 +01:00
builder.info(&format!(
"Checking stage{} {} artifacts ({} -> {})",
builder.top_stage, backend, &compiler.host.triple, target.triple
Print 'checking cranelift artifacts' to easily separate it from other artifacts Before: ``` Checking rustdoc artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu) Checking rustdoc v0.0.0 (/home/joshua/rustc/src/librustdoc) Checking rustdoc-tool v0.0.0 (/home/joshua/rustc/src/tools/rustdoc) Finished release [optimized] target(s) in 2.08s Checking regalloc v0.0.31 Checking gimli v0.22.0 Checking object v0.21.1 Checking cranelift-codegen v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) Checking cranelift-module v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) Checking cranelift-native v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) Checking cranelift-frontend v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) Checking cranelift-object v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) Checking cranelift-simplejit v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) Checking rustc_codegen_cranelift v0.1.0 (/home/joshua/rustc/compiler/rustc_codegen_cranelift) Finished release [optimized] target(s) in 10.55s ``` After: ``` Checking rustdoc artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu) Checking rustdoc v0.0.0 (/home/joshua/rustc/src/librustdoc) Checking rustdoc-tool v0.0.0 (/home/joshua/rustc/src/tools/rustdoc) Finished release [optimized] target(s) in 2.08s Checking cranelift artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu) Checking cranelift-codegen v0.67.0 (https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdece) ```
2020-11-14 23:35:50 +01:00
));
run_cargo(
builder,
cargo,
2020-09-30 02:24:14 +02:00
args(builder),
&codegen_backend_stamp(builder, compiler, target, backend),
vec![],
true,
);
}
}
2020-04-01 15:57:48 +02:00
macro_rules! tool_check_step {
($name:ident, $path:expr, $source_type:expr) => {
2020-04-01 15:57:48 +02:00
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct $name {
pub target: TargetSelection,
2020-04-01 15:57:48 +02:00
}
impl Step for $name {
type Output = ();
const ONLY_HOSTS: bool = true;
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path($path)
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure($name { target: run.target });
}
fn run(self, builder: &Builder<'_>) {
2021-01-16 03:43:23 +01:00
let compiler = builder.compiler(builder.top_stage, builder.config.build);
2020-04-01 15:57:48 +02:00
let target = self.target;
builder.ensure(Rustc { target });
let mut cargo = prepare_tool_cargo(
2020-04-01 15:57:48 +02:00
builder,
compiler,
Mode::ToolRustc,
target,
cargo_subcommand(builder.kind),
$path,
$source_type,
2020-04-01 15:57:48 +02:00
&[],
);
if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
cargo.arg("--all-targets");
}
2021-01-22 04:51:58 +01:00
// Enable internal lints for clippy and rustdoc
// NOTE: this intentionally doesn't enable lints for any other tools,
// see https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776
if $path == "src/tools/rustdoc" || $path == "src/tools/clippy" {
cargo.rustflag("-Zunstable-options");
}
builder.info(&format!(
"Checking stage{} {} artifacts ({} -> {})",
builder.top_stage,
2020-04-01 15:57:48 +02:00
stringify!($name).to_lowercase(),
&compiler.host.triple,
target.triple
));
2020-04-01 15:57:48 +02:00
run_cargo(
builder,
cargo,
2020-09-30 02:24:14 +02:00
args(builder),
2020-04-01 15:57:48 +02:00
&stamp(builder, compiler, target),
vec![],
true,
);
let libdir = builder.sysroot_libdir(compiler, target);
let hostdir = builder.sysroot_libdir(compiler, compiler.host);
add_to_sysroot(&builder, &libdir, &hostdir, &stamp(builder, compiler, target));
/// Cargo's output path in a given stage, compiled by a particular
/// compiler for the specified target.
fn stamp(
builder: &Builder<'_>,
compiler: Compiler,
target: TargetSelection,
2020-04-01 15:57:48 +02:00
) -> PathBuf {
builder
.cargo_out(compiler, Mode::ToolRustc, target)
.join(format!(".{}-check.stamp", stringify!($name).to_lowercase()))
}
}
}
};
}
tool_check_step!(Rustdoc, "src/tools/rustdoc", SourceType::InTree);
// Clippy is a hybrid. It is an external tool, but uses a git subtree instead
// of a submodule. Since the SourceType only drives the deny-warnings
// behavior, treat it as in-tree so that any new warnings in clippy will be
// rejected.
tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);
tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree);
/// Cargo's output path for the standard library in a given stage, compiled
/// by a particular compiler for the specified target.
fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
2018-05-19 22:04:41 +02:00
builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check.stamp")
}
/// Cargo's output path for the standard library in a given stage, compiled
/// by a particular compiler for the specified target.
fn libstd_test_stamp(
builder: &Builder<'_>,
compiler: Compiler,
target: TargetSelection,
) -> PathBuf {
builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check-test.stamp")
}
/// Cargo's output path for librustc in a given stage, compiled by a particular
/// compiler for the specified target.
fn librustc_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
2018-05-19 22:04:41 +02:00
builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp")
}
/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
/// compiler for the specified target and backend.
fn codegen_backend_stamp(
builder: &Builder<'_>,
compiler: Compiler,
target: TargetSelection,
backend: Interned<String>,
) -> PathBuf {
builder
.cargo_out(compiler, Mode::Codegen, target)
.join(format!(".librustc_codegen_{}-check.stamp", backend))
}