Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 9 additions & 49 deletions src/bootstrap/src/core/build_steps/check.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
//! Implementation of compiling the compiler and standard library, in "check"-based modes.

use std::fs;
use std::path::{Path, PathBuf};

use crate::core::build_steps::compile::{
add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
};
use crate::core::build_steps::tool;
use crate::core::build_steps::tool::{
Expand All @@ -16,7 +13,7 @@ use crate::core::builder::{
};
use crate::core::config::TargetSelection;
use crate::utils::build_stamp::{self, BuildStamp};
use crate::{CodegenBackendKind, Compiler, Mode, Subcommand, t};
use crate::{BuiltArtifactsDir, CodegenBackendKind, Compiler, Mode, Subcommand};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Std {
Expand Down Expand Up @@ -162,43 +159,6 @@ impl Step for Std {
}
}

/// Represents a proof that rustc was **checked**.
/// Contains directories with .rmeta files generated by checking rustc for a specific
/// target.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct RmetaSysroot {
host_dir: PathBuf,
target_dir: PathBuf,
}

impl RmetaSysroot {
/// Copy rmeta artifacts from the given `stamp` into a sysroot located at `directory`.
fn from_stamp(
builder: &Builder<'_>,
stamp: BuildStamp,
target: TargetSelection,
directory: &Path,
) -> Self {
let host_dir = directory.join("host");
let target_dir = directory.join(target);
let _ = fs::remove_dir_all(directory);
t!(fs::create_dir_all(directory));
add_to_sysroot(builder, &target_dir, &host_dir, &stamp);

Self { host_dir, target_dir }
}

/// Configure the given cargo invocation so that the compiled crate will be able to use
/// rustc .rmeta artifacts that were previously generated.
fn configure_cargo(&self, cargo: &mut Cargo) {
cargo.append_to_env(
"RUSTC_ADDITIONAL_SYSROOT_PATHS",
format!("{},{}", self.host_dir.to_str().unwrap(), self.target_dir.to_str().unwrap()),
",",
);
}
}

/// Checks rustc using the given `build_compiler` for the given `target`, and produces
/// a sysroot in the build directory that stores the generated .rmeta files.
///
Expand All @@ -218,7 +178,7 @@ impl PrepareRustcRmetaSysroot {
}

impl Step for PrepareRustcRmetaSysroot {
type Output = RmetaSysroot;
type Output = BuiltArtifactsDir;

fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.never()
Expand All @@ -239,7 +199,7 @@ impl Step for PrepareRustcRmetaSysroot {
.out
.join(build_compiler.host)
.join(format!("stage{}-rustc-rmeta-artifacts", build_compiler.stage + 1));
RmetaSysroot::from_stamp(builder, stamp, self.target, &dir)
BuiltArtifactsDir::from_stamp(builder, stamp, self.target, &dir)
}
}

Expand All @@ -262,7 +222,7 @@ impl PrepareStdRmetaSysroot {
}

impl Step for PrepareStdRmetaSysroot {
type Output = RmetaSysroot;
type Output = BuiltArtifactsDir;

fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.never()
Expand All @@ -282,7 +242,7 @@ impl Step for PrepareStdRmetaSysroot {
.join(self.build_compiler.host)
.join(format!("stage{}-std-rmeta-artifacts", self.build_compiler.stage));

RmetaSysroot::from_stamp(builder, stamp, self.target, &dir)
BuiltArtifactsDir::from_stamp(builder, stamp, self.target, &dir)
}
}

Expand Down Expand Up @@ -398,8 +358,8 @@ impl Step for Rustc {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CompilerForCheck {
build_compiler: Compiler,
rustc_rmeta_sysroot: Option<RmetaSysroot>,
std_rmeta_sysroot: Option<RmetaSysroot>,
rustc_rmeta_sysroot: Option<BuiltArtifactsDir>,
std_rmeta_sysroot: Option<BuiltArtifactsDir>,
}

impl CompilerForCheck {
Expand All @@ -425,7 +385,7 @@ fn prepare_std(
builder: &Builder<'_>,
build_compiler: Compiler,
target: TargetSelection,
) -> Option<RmetaSysroot> {
) -> Option<BuiltArtifactsDir> {
// We need to build the host stdlib even if we only check, to compile build scripts and proc
// macros
builder.std(build_compiler, builder.host_target);
Expand Down
147 changes: 57 additions & 90 deletions src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ use crate::utils::helpers::{
exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
};
use crate::{
CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode,
debug, trace,
BuiltArtifactsDir, CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo,
LLVM_TOOLS, Mode, debug, trace,
};

/// Build a standard library for the given `target` using the given `build_compiler`.
Expand Down Expand Up @@ -955,6 +955,11 @@ pub struct BuiltRustc {
/// This can be different from the *build_compiler* passed to the `Rustc` step because of
/// uplifting.
pub build_compiler: Compiler,
/// Build stamp that stores the rustc rlibs that were built by `build_compiler`.
///
/// FIXME: this shouldn't be an option, ideally get rid of the Option once download-ci-rustc
/// is refactored.
pub stamp: Option<BuildStamp>,
}

/// Build rustc using the passed `build_compiler`.
Expand Down Expand Up @@ -1028,6 +1033,8 @@ impl Step for Rustc {
let build_compiler = self.build_compiler;
let target = self.target;

let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);

// NOTE: the ABI of the stage0 compiler is different from the ABI of the downloaded compiler,
// so its artifacts can't be reused.
if builder.download_rustc() && build_compiler.stage != 0 {
Expand All @@ -1040,7 +1047,7 @@ impl Step for Rustc {
&sysroot,
builder.config.ci_rustc_dev_contents(),
);
return BuiltRustc { build_compiler };
return BuiltRustc { build_compiler, stamp: None };
}

// Build a standard library for `target` using the `build_compiler`.
Expand All @@ -1052,9 +1059,11 @@ impl Step for Rustc {

builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
builder.ensure(RustcLink::from_rustc(self));

return BuiltRustc { build_compiler };
return BuiltRustc {
build_compiler,
stamp: Some(stamp.load_from_disk().expect("Rustc stamp was not found on disk")),
};
}

// The stage of the compiler that we're building
Expand All @@ -1072,25 +1081,16 @@ impl Step for Rustc {
// be uplifting. We cannot uplift stage 1, as it has a different ABI than stage 2+,
// so we always uplift the stage2 compiler (compiled with stage 1).
let uplift_build_compiler = builder.compiler(1, build_compiler.host);
let stamp = build_stamp::librustc_stamp(builder, uplift_build_compiler, target)
.load_from_disk()
.expect("Rustc stamp was not found on disk");

let msg = format!("Uplifting rustc from stage2 to stage{stage})");
builder.info(&msg);

// Here the compiler that built the rlibs (`uplift_build_compiler`) can be different
// from the compiler whose sysroot should be modified in this step. So we need to copy
// the (previously built) rlibs into the correct sysroot.
builder.ensure(RustcLink::from_build_compiler_and_sysroot(
// This is the compiler that actually built the rustc rlibs
uplift_build_compiler,
// We copy the rlibs into the sysroot of `build_compiler`
build_compiler,
target,
self.crates,
));

// Here we have performed an uplift, so we return the actual build compiler that "built"
// this rustc.
return BuiltRustc { build_compiler: uplift_build_compiler };
return BuiltRustc { build_compiler: uplift_build_compiler, stamp: Some(stamp) };
}

// Build a standard library for the current host target using the `build_compiler`.
Expand Down Expand Up @@ -1133,7 +1133,6 @@ impl Step for Rustc {
build_compiler,
target,
);
let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
run_cargo(
builder,
cargo,
Expand Down Expand Up @@ -1163,8 +1162,7 @@ impl Step for Rustc {
strip_debug(builder, target, &target_root_dir.join("rustc-main"));
}

builder.ensure(RustcLink::from_rustc(self));
BuiltRustc { build_compiler }
BuiltRustc { build_compiler, stamp: Some(stamp) }
}

fn metadata(&self) -> Option<StepMetadata> {
Expand Down Expand Up @@ -1471,74 +1469,6 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect
}
}

/// `RustcLink` copies compiler rlibs from a rustc build into a compiler sysroot.
/// It works with (potentially up to) three compilers:
/// - `build_compiler` is a compiler that built rustc rlibs
/// - `sysroot_compiler` is a compiler into whose sysroot we will copy the rlibs
/// - In most situations, `build_compiler` == `sysroot_compiler`
/// - `target_compiler` is the compiler whose rlibs were built. It is not represented explicitly
/// in this step, rather we just read the rlibs from a rustc build stamp of `build_compiler`.
///
/// This is necessary for tools using `rustc_private`, where the previous compiler will build
/// a tool against the next compiler.
/// To build a tool against a compiler, the rlibs of that compiler that it links against
/// must be in the sysroot of the compiler that's doing the compiling.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct RustcLink {
/// This compiler **built** some rustc, whose rlibs we will copy into a sysroot.
build_compiler: Compiler,
/// This is the compiler into whose sysroot we want to copy the built rlibs.
/// In most cases, it will correspond to `build_compiler`.
sysroot_compiler: Compiler,
target: TargetSelection,
/// Not actually used; only present to make sure the cache invalidation is correct.
crates: Vec<String>,
}

impl RustcLink {
/// Copy rlibs from the build compiler that build this `rustc` into the sysroot of that
/// build compiler.
fn from_rustc(rustc: Rustc) -> Self {
Self {
build_compiler: rustc.build_compiler,
sysroot_compiler: rustc.build_compiler,
target: rustc.target,
crates: rustc.crates,
}
}

/// Copy rlibs **built** by `build_compiler` into the sysroot of `sysroot_compiler`.
fn from_build_compiler_and_sysroot(
build_compiler: Compiler,
sysroot_compiler: Compiler,
target: TargetSelection,
crates: Vec<String>,
) -> Self {
Self { build_compiler, sysroot_compiler, target, crates }
}
}

impl Step for RustcLink {
type Output = ();

fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.never()
}

/// Same as `std_link`, only for librustc
fn run(self, builder: &Builder<'_>) {
let build_compiler = self.build_compiler;
let sysroot_compiler = self.sysroot_compiler;
let target = self.target;
add_to_sysroot(
builder,
&builder.sysroot_target_libdir(sysroot_compiler, target),
&builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
&build_stamp::librustc_stamp(builder, build_compiler, target),
);
}
}

/// Output of the `compile::GccCodegenBackend` step.
/// It includes the path to the libgccjit library on which this backend depends.
#[derive(Clone)]
Expand Down Expand Up @@ -1601,6 +1531,7 @@ impl Step for GccCodegenBackend {
);
cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
rustc_cargo_env(builder, &mut cargo, target);
self.compilers.configure_cargo(&mut cargo);

add_cg_gcc_cargo_flags(&mut cargo, &gcc);

Expand Down Expand Up @@ -1675,6 +1606,7 @@ impl Step for CraneliftCodegenBackend {
.arg("--manifest-path")
.arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
rustc_cargo_env(builder, &mut cargo, target);
self.compilers.configure_cargo(&mut cargo);

let _guard = builder.msg(
Kind::Build,
Expand Down Expand Up @@ -2190,7 +2122,7 @@ impl Step for Assemble {
);

// It is possible that an uplift has happened, so we override build_compiler here.
let BuiltRustc { build_compiler } =
let BuiltRustc { build_compiler, stamp: _ } =
builder.ensure(Rustc::new(build_compiler, target_compiler.host));

let stage = target_compiler.stage;
Expand Down Expand Up @@ -2279,6 +2211,7 @@ impl Step for Assemble {

let prepare_compilers = || {
RustcPrivateCompilers::from_build_and_target_compiler(
builder,
build_compiler,
target_compiler,
)
Expand Down Expand Up @@ -2374,6 +2307,40 @@ impl Step for Assemble {
}
}

/// Compiles rustc using `build_compiler` for the given `target`, and
/// outputs a directory with the generated compiler rlibs.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PrepareRlibSysroot {
build_compiler: Compiler,
target: TargetSelection,
}

impl PrepareRlibSysroot {
pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
Self { build_compiler, target }
}
}

impl Step for PrepareRlibSysroot {
type Output = Option<BuiltArtifactsDir>;

fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.never()
}

fn run(self, builder: &Builder<'_>) -> Self::Output {
// Build rustc
let rustc = builder.ensure(Rustc::new(self.build_compiler, self.target));

// Copy the generated rlib artifacts to a separate directory
let dir = builder
.out
.join(self.build_compiler.host)
.join(format!("stage{}-rustc-rlib-artifacts", self.build_compiler.stage + 1));
rustc.stamp.map(|stamp| BuiltArtifactsDir::from_stamp(builder, stamp, self.target, &dir))
}
}

/// Link some files into a rustc sysroot.
///
/// For a particular stage this will link the file listed in `stamp` into the
Expand Down
Loading
Loading