Skip to content

Create a typed wrapper for codegen backends in bootstrap #144730

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 1, 2025
Merged
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
19 changes: 11 additions & 8 deletions src/bootstrap/src/core/build_steps/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::core::builder::{
};
use crate::core::config::TargetSelection;
use crate::utils::build_stamp::{self, BuildStamp};
use crate::{Compiler, Mode, Subcommand};
use crate::{CodegenBackendKind, Compiler, Mode, Subcommand};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Std {
Expand Down Expand Up @@ -312,7 +312,7 @@ fn prepare_compiler_for_check(
pub struct CodegenBackend {
pub build_compiler: Compiler,
pub target: TargetSelection,
pub backend: &'static str,
pub backend: CodegenBackendKind,
}

impl Step for CodegenBackend {
Expand All @@ -327,14 +327,14 @@ impl Step for CodegenBackend {
fn make_run(run: RunConfig<'_>) {
// FIXME: only check the backend(s) that were actually selected in run.paths
let build_compiler = prepare_compiler_for_check(run.builder, run.target, Mode::Codegen);
for &backend in &["cranelift", "gcc"] {
for backend in [CodegenBackendKind::Cranelift, CodegenBackendKind::Gcc] {
run.builder.ensure(CodegenBackend { build_compiler, target: run.target, backend });
}
}

fn run(self, builder: &Builder<'_>) {
// FIXME: remove once https://github.com/rust-lang/rust/issues/112393 is resolved
if builder.build.config.vendor && self.backend == "gcc" {
if builder.build.config.vendor && self.backend.is_gcc() {
println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
return;
}
Expand All @@ -354,19 +354,22 @@ impl Step for CodegenBackend {

cargo
.arg("--manifest-path")
.arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
.arg(builder.src.join(format!("compiler/{}/Cargo.toml", backend.crate_name())));
rustc_cargo_env(builder, &mut cargo, target);

let _guard = builder.msg_check(format!("rustc_codegen_{backend}"), target, None);
let _guard = builder.msg_check(backend.crate_name(), target, None);

let stamp = build_stamp::codegen_backend_stamp(builder, build_compiler, target, backend)
let stamp = build_stamp::codegen_backend_stamp(builder, build_compiler, target, &backend)
.with_prefix("check");

run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
}

fn metadata(&self) -> Option<StepMetadata> {
Some(StepMetadata::check(self.backend, self.target).built_by(self.build_compiler))
Some(
StepMetadata::check(&self.backend.crate_name(), self.target)
.built_by(self.build_compiler),
)
}
}

Expand Down
24 changes: 14 additions & 10 deletions src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ use crate::utils::exec::command;
use crate::utils::helpers::{
exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
};
use crate::{CLang, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode, debug, trace};
use crate::{
CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode,
debug, trace,
};

/// Build a standard library for the given `target` using the given `compiler`.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
Expand Down Expand Up @@ -1330,7 +1333,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
}

if let Some(backend) = builder.config.default_codegen_backend(target) {
cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend);
cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend.name());
}

let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
Expand Down Expand Up @@ -1543,7 +1546,7 @@ impl Step for RustcLink {
pub struct CodegenBackend {
pub target: TargetSelection,
pub compiler: Compiler,
pub backend: String,
pub backend: CodegenBackendKind,
}

fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
Expand All @@ -1568,7 +1571,7 @@ fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
if path.contains(CODEGEN_BACKEND_PREFIX) {
let mut needs_codegen_backend_config = true;
for backend in run.builder.config.codegen_backends(run.target) {
if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend)) {
if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend.name())) {
needs_codegen_backend_config = false;
}
}
Expand Down Expand Up @@ -1602,7 +1605,7 @@ impl Step for CodegenBackend {
}

for backend in run.builder.config.codegen_backends(run.target) {
if backend == "llvm" {
if backend.is_llvm() {
continue; // Already built as part of rustc
}

Expand Down Expand Up @@ -1663,20 +1666,21 @@ impl Step for CodegenBackend {
);
cargo
.arg("--manifest-path")
.arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
.arg(builder.src.join(format!("compiler/{}/Cargo.toml", backend.crate_name())));
rustc_cargo_env(builder, &mut cargo, target);

// Ideally, we'd have a separate step for the individual codegen backends,
// like we have in tests (test::CodegenGCC) but that would require a lot of restructuring.
// If the logic gets more complicated, it should probably be done.
if backend == "gcc" {
if backend.is_gcc() {
let gcc = builder.ensure(Gcc { target });
add_cg_gcc_cargo_flags(&mut cargo, &gcc);
}

let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp");

let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target);
let _guard =
builder.msg_build(compiler, format_args!("codegen backend {}", backend.name()), target);
let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
if builder.config.dry_run() {
return;
Expand Down Expand Up @@ -1731,7 +1735,7 @@ fn copy_codegen_backends_to_sysroot(
}

for backend in builder.config.codegen_backends(target) {
if backend == "llvm" {
if backend.is_llvm() {
continue; // Already built as part of rustc
}

Expand Down Expand Up @@ -2161,7 +2165,7 @@ impl Step for Assemble {
let _codegen_backend_span =
span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
for backend in builder.config.codegen_backends(target_compiler.host) {
if backend == "llvm" {
if backend.is_llvm() {
debug!("llvm codegen backend is already built as part of rustc");
continue; // Already built as part of rustc
}
Expand Down
30 changes: 16 additions & 14 deletions src/bootstrap/src/core/build_steps/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use crate::utils::helpers::{
exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit,
};
use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
use crate::{Compiler, DependencyType, FileType, LLVM_TOOLS, Mode, trace};
use crate::{CodegenBackendKind, Compiler, DependencyType, FileType, LLVM_TOOLS, Mode, trace};

pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
format!("{}-{}", component, builder.rust_package_vers())
Expand Down Expand Up @@ -1372,10 +1372,10 @@ impl Step for Miri {
}
}

#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct CodegenBackend {
pub compiler: Compiler,
pub backend: String,
pub backend: CodegenBackendKind,
}

impl Step for CodegenBackend {
Expand All @@ -1389,7 +1389,7 @@ impl Step for CodegenBackend {

fn make_run(run: RunConfig<'_>) {
for backend in run.builder.config.codegen_backends(run.target) {
if backend == "llvm" {
if backend.is_llvm() {
continue; // Already built as part of rustc
}

Expand All @@ -1412,28 +1412,30 @@ impl Step for CodegenBackend {
return None;
}

if !builder.config.codegen_backends(self.compiler.host).contains(&self.backend.to_string())
{
if !builder.config.codegen_backends(self.compiler.host).contains(&self.backend) {
return None;
}

if self.backend == "cranelift" && !target_supports_cranelift_backend(self.compiler.host) {
if self.backend.is_cranelift() && !target_supports_cranelift_backend(self.compiler.host) {
builder.info("target not supported by rustc_codegen_cranelift. skipping");
return None;
}

let compiler = self.compiler;
let backend = self.backend;

let mut tarball =
Tarball::new(builder, &format!("rustc-codegen-{backend}"), &compiler.host.triple);
if backend == "cranelift" {
let mut tarball = Tarball::new(
builder,
&format!("rustc-codegen-{}", backend.name()),
&compiler.host.triple,
);
if backend.is_cranelift() {
tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
} else {
panic!("Unknown backend rustc_codegen_{backend}");
panic!("Unknown codegen backend {}", backend.name());
}
tarball.is_preview(true);
tarball.add_legal_and_readme_to(format!("share/doc/rustc_codegen_{backend}"));
tarball.add_legal_and_readme_to(format!("share/doc/{}", backend.crate_name()));

let src = builder.sysroot(compiler);
let backends_src = builder.sysroot_codegen_backends(compiler);
Expand All @@ -1445,7 +1447,7 @@ impl Step for CodegenBackend {
// Don't use custom libdir here because ^lib/ will be resolved again with installer
let backends_dst = PathBuf::from("lib").join(backends_rel);

let backend_name = format!("rustc_codegen_{backend}");
let backend_name = backend.crate_name();
let mut found_backend = false;
for backend in fs::read_dir(&backends_src).unwrap() {
let file_name = backend.unwrap().file_name();
Expand Down Expand Up @@ -1575,7 +1577,7 @@ impl Step for Extended {
add_component!("analysis" => Analysis { compiler, target });
add_component!("rustc-codegen-cranelift" => CodegenBackend {
compiler: builder.compiler(stage, target),
backend: "cranelift".to_string(),
backend: CodegenBackendKind::Cranelift,
});
add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
build_compiler: compiler,
Expand Down
4 changes: 2 additions & 2 deletions src/bootstrap/src/core/build_steps/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::core::config::{Config, TargetSelection};
use crate::utils::exec::command;
use crate::utils::helpers::t;
use crate::utils::tarball::GeneratedTarball;
use crate::{Compiler, Kind};
use crate::{CodegenBackendKind, Compiler, Kind};

#[cfg(target_os = "illumos")]
const SHELL: &str = "bash";
Expand Down Expand Up @@ -276,7 +276,7 @@ install!((self, builder, _config),
RustcCodegenCranelift, alias = "rustc-codegen-cranelift", Self::should_build(_config), only_hosts: true, {
if let Some(tarball) = builder.ensure(dist::CodegenBackend {
compiler: self.compiler,
backend: "cranelift".to_string(),
backend: CodegenBackendKind::Cranelift,
}) {
install_sh(builder, "rustc-codegen-cranelift", self.compiler.stage, Some(self.target), &tarball);
} else {
Expand Down
10 changes: 6 additions & 4 deletions src/bootstrap/src/core/build_steps/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use crate::utils::helpers::{
linker_flags, t, target_supports_cranelift_backend, up_to_date,
};
use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
use crate::{CLang, DocTests, GitRepo, Mode, PathSet, debug, envify};
use crate::{CLang, CodegenBackendKind, DocTests, GitRepo, Mode, PathSet, debug, envify};

const ADB_TEST_DIR: &str = "/data/local/tmp/work";

Expand Down Expand Up @@ -1786,7 +1786,9 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));

if let Some(codegen_backend) = builder.config.default_codegen_backend(compiler.host) {
cmd.arg("--codegen-backend").arg(&codegen_backend);
// Tells compiletest which codegen backend is used by default by the compiler.
// It is used to e.g. ignore tests that don't support that codegen backend.
cmd.arg("--codegen-backend").arg(codegen_backend.name());
}

if builder.build.config.llvm_enzyme {
Expand Down Expand Up @@ -3406,7 +3408,7 @@ impl Step for CodegenCranelift {
return;
}

if !builder.config.codegen_backends(run.target).contains(&"cranelift".to_owned()) {
if !builder.config.codegen_backends(run.target).contains(&CodegenBackendKind::Cranelift) {
builder.info("cranelift not in rust.codegen-backends. skipping");
return;
}
Expand Down Expand Up @@ -3533,7 +3535,7 @@ impl Step for CodegenGCC {
return;
}

if !builder.config.codegen_backends(run.target).contains(&"gcc".to_owned()) {
if !builder.config.codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
builder.info("gcc not in rust.codegen-backends. skipping");
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/src/core/builder/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1286,7 +1286,7 @@ impl Builder<'_> {

if let Some(limit) = limit
&& (build_compiler_stage == 0
|| self.config.default_codegen_backend(target).unwrap_or_default() == "llvm")
|| self.config.default_codegen_backend(target).unwrap_or_default().is_llvm())
{
rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={limit}"));
}
Expand Down
16 changes: 8 additions & 8 deletions src/bootstrap/src/core/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash {
#[allow(unused)]
#[derive(Debug, PartialEq, Eq)]
pub struct StepMetadata {
name: &'static str,
name: String,
kind: Kind,
target: TargetSelection,
built_by: Option<Compiler>,
Expand All @@ -151,28 +151,28 @@ pub struct StepMetadata {
}

impl StepMetadata {
pub fn build(name: &'static str, target: TargetSelection) -> Self {
pub fn build(name: &str, target: TargetSelection) -> Self {
Self::new(name, target, Kind::Build)
}

pub fn check(name: &'static str, target: TargetSelection) -> Self {
pub fn check(name: &str, target: TargetSelection) -> Self {
Self::new(name, target, Kind::Check)
}

pub fn doc(name: &'static str, target: TargetSelection) -> Self {
pub fn doc(name: &str, target: TargetSelection) -> Self {
Self::new(name, target, Kind::Doc)
}

pub fn dist(name: &'static str, target: TargetSelection) -> Self {
pub fn dist(name: &str, target: TargetSelection) -> Self {
Self::new(name, target, Kind::Dist)
}

pub fn test(name: &'static str, target: TargetSelection) -> Self {
pub fn test(name: &str, target: TargetSelection) -> Self {
Self::new(name, target, Kind::Test)
}

fn new(name: &'static str, target: TargetSelection, kind: Kind) -> Self {
Self { name, kind, target, built_by: None, stage: None, metadata: None }
fn new(name: &str, target: TargetSelection, kind: Kind) -> Self {
Self { name: name.to_string(), kind, target, built_by: None, stage: None, metadata: None }
}

pub fn built_by(mut self, compiler: Compiler) -> Self {
Expand Down
Loading
Loading