Skip to content
5 changes: 3 additions & 2 deletions src/bootstrap/src/core/build_steps/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use crate::core::build_steps::compile::{
};
use crate::core::build_steps::tool;
use crate::core::build_steps::tool::{
COMPILETEST_ALLOW_FEATURES, SourceType, get_compiler_for_target, prepare_tool_cargo,
COMPILETEST_ALLOW_FEATURES, SourceType, ToolTargetBuildMode, get_tool_target_compiler,
prepare_tool_cargo,
};
use crate::core::builder::{
self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
Expand Down Expand Up @@ -252,7 +253,7 @@ fn prepare_compiler_for_check(

match mode {
Mode::ToolBootstrap => builder.compiler(0, host),
Mode::ToolTarget => get_compiler_for_target(builder, target),
Mode::ToolTarget => get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target)),
Mode::ToolStd => {
// These tools require the local standard library to be checked
let build_compiler = builder.compiler(builder.top_stage, host);
Expand Down
14 changes: 6 additions & 8 deletions src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2286,15 +2286,13 @@ impl Step for Assemble {
}

// In addition to `rust-lld` also install `wasm-component-ld` when
// LLD is enabled. This is a relatively small binary that primarily
// delegates to the `rust-lld` binary for linking and then runs
// logic to create the final binary. This is used by the
// `wasm32-wasip2` target of Rust.
// is enabled. This is used by the `wasm32-wasip2` target of Rust.
if builder.tool_enabled("wasm-component-ld") {
let wasm_component = builder.ensure(crate::core::build_steps::tool::WasmComponentLd {
compiler: build_compiler,
target: target_compiler.host,
});
let wasm_component =
builder.ensure(crate::core::build_steps::tool::WasmComponentLd::for_compiler(
builder,
target_compiler,
));
builder.copy_link(
&wasm_component.tool_path,
&libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
Expand Down
107 changes: 101 additions & 6 deletions src/bootstrap/src/core/build_steps/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,12 +365,36 @@ pub(crate) fn get_tool_rustc_compiler(
builder.compiler(target_compiler.stage.saturating_sub(1), builder.config.host_target)
}

/// Returns the smallest stage compiler that is able to compile code for the given `target`.
pub(crate) fn get_compiler_for_target(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
/// Determines how to build a `ToolTarget`, i.e. which compiler should be used to compile it.
/// The compiler stage is automatically auto-bumped if we need to cross-compile a stage 1 tool.
pub enum ToolTargetBuildMode {
/// Build the tool using rustc that corresponds to the selected CLI stage.
Build(TargetSelection),
/// Build the tool so that it can be attached to the sysroot of the passed compiler.
/// Since we always dist stage 2+, the compiler that builds the tool in this case has to be
/// stage 1+.
Dist(Compiler),
}

/// Returns compiler that is able to compile a `ToolTarget` tool with the given `mode`.
pub(crate) fn get_tool_target_compiler(
builder: &Builder<'_>,
mode: ToolTargetBuildMode,
) -> Compiler {
let (target, min_build_compiler_stage) = match mode {
ToolTargetBuildMode::Build(target) => {
assert!(builder.top_stage > 0);
(target, builder.top_stage - 1)
}
ToolTargetBuildMode::Dist(target_compiler) => {
assert!(target_compiler.stage > 0);
(target_compiler.host, target_compiler.stage - 1)
}
};
let compiler = if builder.host_target == target {
builder.compiler(0, builder.host_target)
builder.compiler(min_build_compiler_stage, builder.host_target)
} else {
builder.compiler(1, builder.host_target)
builder.compiler(min_build_compiler_stage.max(1), builder.host_target)
};
builder.std(compiler, target);
compiler
Expand Down Expand Up @@ -533,7 +557,6 @@ bootstrap_tool!(
// rustdoc-gui-test has a crate dependency on compiletest, so it needs the same unstable features.
RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = COMPILETEST_ALLOW_FEATURES;
CoverageDump, "src/tools/coverage-dump", "coverage-dump";
WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization";
UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator";
FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump";
OptimizedDist, "src/tools/opt-dist", "opt-dist", submodules = &["src/tools/rustc-perf"];
Expand Down Expand Up @@ -661,7 +684,10 @@ impl Step for RemoteTestServer {

fn make_run(run: RunConfig<'_>) {
run.builder.ensure(RemoteTestServer {
build_compiler: get_compiler_for_target(run.builder, run.target),
build_compiler: get_tool_target_compiler(
run.builder,
ToolTargetBuildMode::Build(run.target),
),
target: run.target,
});
}
Expand Down Expand Up @@ -935,6 +961,75 @@ impl Step for LldWrapper {
}
}

/// Builds the `wasm-component-ld` linker wrapper, which is shipped with rustc to be executed on the
/// host platform where rustc runs.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct WasmComponentLd {
build_compiler: Compiler,
target: TargetSelection,
}

impl WasmComponentLd {
/// Returns `WasmComponentLd` that should be **used** by the passed compiler.
pub fn for_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
Self {
build_compiler: get_tool_target_compiler(
builder,
ToolTargetBuildMode::Dist(target_compiler),
),
target: target_compiler.host,
}
}
}

impl Step for WasmComponentLd {
type Output = ToolBuildResult;

const ONLY_HOSTS: bool = true;

fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path("src/tools/wasm-component-ld")
}

fn make_run(run: RunConfig<'_>) {
run.builder.ensure(WasmComponentLd {
build_compiler: get_tool_target_compiler(
run.builder,
ToolTargetBuildMode::Build(run.target),
),
target: run.target,
});
}

#[cfg_attr(
feature = "tracing",
instrument(
level = "debug",
name = "WasmComponentLd::run",
skip_all,
fields(build_compiler = ?self.build_compiler),
),
)]
fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
builder.ensure(ToolBuild {
build_compiler: self.build_compiler,
target: self.target,
tool: "wasm-component-ld",
mode: Mode::ToolTarget,
path: "src/tools/wasm-component-ld",
source_type: SourceType::InTree,
extra_features: vec![],
allow_features: "min-specialization",
cargo_args: vec![],
artifact_kind: ToolArtifactKind::Binary,
})
}

fn metadata(&self) -> Option<StepMetadata> {
Some(StepMetadata::build("WasmComponentLd", self.target).built_by(self.build_compiler))
}
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct RustAnalyzer {
pub compiler: Compiler,
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/src/core/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,7 @@ impl<'a> Builder<'a> {
tool::CoverageDump,
tool::LlvmBitcodeLinker,
tool::RustcPerf,
tool::WasmComponentLd
),
Kind::Clippy => describe!(
clippy::Std,
Expand Down