Skip to content

Commit 6e5a6e0

Browse files
committed
Install libgccjit into the compiler's sysroot when the GCC codegen backend is enabled
1 parent 1553adf commit 6e5a6e0

File tree

2 files changed

+82
-55
lines changed

2 files changed

+82
-55
lines changed

src/bootstrap/src/core/build_steps/compile.rs

Lines changed: 69 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use serde_derive::Deserialize;
1818
#[cfg(feature = "tracing")]
1919
use tracing::{instrument, span};
2020

21-
use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
21+
use crate::core::build_steps::gcc::{Gcc, GccOutput, add_cg_gcc_cargo_flags};
2222
use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts};
2323
use crate::core::build_steps::{dist, llvm};
2424
use crate::core::builder;
@@ -1543,13 +1543,22 @@ impl Step for RustcLink {
15431543
}
15441544
}
15451545

1546+
/// Output of the `compile::GccCodegenBackend` step.
1547+
/// It includes the path to the libgccjit library on which this backend depends.
1548+
#[derive(Clone)]
1549+
pub struct GccCodegenBackendOutput {
1550+
stamp: BuildStamp,
1551+
gcc: GccOutput,
1552+
}
1553+
15461554
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15471555
pub struct GccCodegenBackend {
15481556
compilers: RustcPrivateCompilers,
15491557
}
15501558

15511559
impl Step for GccCodegenBackend {
1552-
type Output = BuildStamp;
1560+
type Output = GccCodegenBackendOutput;
1561+
15531562
const ONLY_HOSTS: bool = true;
15541563

15551564
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -1584,6 +1593,8 @@ impl Step for GccCodegenBackend {
15841593
&CodegenBackendKind::Gcc,
15851594
);
15861595

1596+
let gcc = builder.ensure(Gcc { target });
1597+
15871598
if builder.config.keep_stage.contains(&build_compiler.stage) {
15881599
trace!("`keep-stage` requested");
15891600
builder.info(
@@ -1592,7 +1603,7 @@ impl Step for GccCodegenBackend {
15921603
);
15931604
// Codegen backends are linked separately from this step today, so we don't do
15941605
// anything here.
1595-
return stamp;
1606+
return GccCodegenBackendOutput { stamp, gcc };
15961607
}
15971608

15981609
let mut cargo = builder::Cargo::new(
@@ -1606,13 +1617,16 @@ impl Step for GccCodegenBackend {
16061617
cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
16071618
rustc_cargo_env(builder, &mut cargo, target);
16081619

1609-
let gcc = builder.ensure(Gcc { target });
16101620
add_cg_gcc_cargo_flags(&mut cargo, &gcc);
16111621

16121622
let _guard =
16131623
builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target);
16141624
let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1615-
write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1625+
1626+
GccCodegenBackendOutput {
1627+
stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1628+
gcc,
1629+
}
16161630
}
16171631

16181632
fn metadata(&self) -> Option<StepMetadata> {
@@ -2191,53 +2205,6 @@ impl Step for Assemble {
21912205
);
21922206
build_compiler.stage = actual_stage;
21932207

2194-
let mut codegen_backend_stamps = vec![];
2195-
{
2196-
#[cfg(feature = "tracing")]
2197-
let _codegen_backend_span =
2198-
span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2199-
2200-
for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2201-
// FIXME: this is a horrible hack used to make `x check` work when other codegen
2202-
// backends are enabled.
2203-
// `x check` will check stage 1 rustc, which copies its rmetas to the stage0 sysroot.
2204-
// Then it checks codegen backends, which correctly use these rmetas.
2205-
// Then it needs to check std, but for that it needs to build stage 1 rustc.
2206-
// This copies the build rmetas into the stage0 sysroot, effectively poisoning it,
2207-
// because we then have both check and build rmetas in the same sysroot.
2208-
// That would be fine on its own. However, when another codegen backend is enabled,
2209-
// then building stage 1 rustc implies also building stage 1 codegen backend (even if
2210-
// it isn't used for anything). And since that tries to use the poisoned
2211-
// rmetas, it fails to build.
2212-
// We don't actually need to build rustc-private codegen backends for checking std,
2213-
// so instead we skip that.
2214-
// Note: this would be also an issue for other rustc-private tools, but that is "solved"
2215-
// by check::Std being last in the list of checked things (see
2216-
// `Builder::get_step_descriptions`).
2217-
if builder.kind == Kind::Check && builder.top_stage == 1 {
2218-
continue;
2219-
}
2220-
2221-
let prepare_compilers = || {
2222-
RustcPrivateCompilers::from_build_and_target_compiler(
2223-
build_compiler,
2224-
target_compiler,
2225-
)
2226-
};
2227-
2228-
let stamp = match backend {
2229-
CodegenBackendKind::Cranelift => {
2230-
builder.ensure(CraneliftCodegenBackend { compilers: prepare_compilers() })
2231-
}
2232-
CodegenBackendKind::Gcc => {
2233-
builder.ensure(GccCodegenBackend { compilers: prepare_compilers() })
2234-
}
2235-
CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2236-
};
2237-
codegen_backend_stamps.push(stamp);
2238-
}
2239-
}
2240-
22412208
let stage = target_compiler.stage;
22422209
let host = target_compiler.host;
22432210
let (host_info, dir_name) = if build_compiler.host == host {
@@ -2296,9 +2263,56 @@ impl Step for Assemble {
22962263
}
22972264
}
22982265

2299-
debug!("copying codegen backends to sysroot");
2300-
for stamp in codegen_backend_stamps {
2301-
copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2266+
{
2267+
#[cfg(feature = "tracing")]
2268+
let _codegen_backend_span =
2269+
span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2270+
2271+
for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2272+
// FIXME: this is a horrible hack used to make `x check` work when other codegen
2273+
// backends are enabled.
2274+
// `x check` will check stage 1 rustc, which copies its rmetas to the stage0 sysroot.
2275+
// Then it checks codegen backends, which correctly use these rmetas.
2276+
// Then it needs to check std, but for that it needs to build stage 1 rustc.
2277+
// This copies the build rmetas into the stage0 sysroot, effectively poisoning it,
2278+
// because we then have both check and build rmetas in the same sysroot.
2279+
// That would be fine on its own. However, when another codegen backend is enabled,
2280+
// then building stage 1 rustc implies also building stage 1 codegen backend (even if
2281+
// it isn't used for anything). And since that tries to use the poisoned
2282+
// rmetas, it fails to build.
2283+
// We don't actually need to build rustc-private codegen backends for checking std,
2284+
// so instead we skip that.
2285+
// Note: this would be also an issue for other rustc-private tools, but that is "solved"
2286+
// by check::Std being last in the list of checked things (see
2287+
// `Builder::get_step_descriptions`).
2288+
if builder.kind == Kind::Check && builder.top_stage == 1 {
2289+
continue;
2290+
}
2291+
2292+
let prepare_compilers = || {
2293+
RustcPrivateCompilers::from_build_and_target_compiler(
2294+
build_compiler,
2295+
target_compiler,
2296+
)
2297+
};
2298+
2299+
match backend {
2300+
CodegenBackendKind::Cranelift => {
2301+
let stamp = builder
2302+
.ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2303+
copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2304+
}
2305+
CodegenBackendKind::Gcc => {
2306+
let output =
2307+
builder.ensure(GccCodegenBackend { compilers: prepare_compilers() });
2308+
copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler);
2309+
// Also copy libgccjit to the library sysroot, so that it is available for
2310+
// the codegen backend.
2311+
output.gcc.install_to(builder, &rustc_libdir);
2312+
}
2313+
CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2314+
}
2315+
}
23022316
}
23032317

23042318
if builder.config.lld_enabled {

src/bootstrap/src/core/build_steps/gcc.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::fs;
1212
use std::path::{Path, PathBuf};
1313
use std::sync::OnceLock;
1414

15+
use crate::FileType;
1516
use crate::core::builder::{Builder, Cargo, Kind, RunConfig, ShouldRun, Step};
1617
use crate::core::config::TargetSelection;
1718
use crate::utils::build_stamp::{BuildStamp, generate_smart_stamp_hash};
@@ -28,6 +29,18 @@ pub struct GccOutput {
2829
pub libgccjit: PathBuf,
2930
}
3031

32+
impl GccOutput {
33+
/// Install the required libgccjit library file(s) to the specified `path`.
34+
pub fn install_to(&self, builder: &Builder<'_>, directory: &Path) {
35+
let dst = directory.join(self.libgccjit.file_name().unwrap());
36+
builder.install(&self.libgccjit, directory, FileType::NativeLibrary);
37+
// FIXME: try to remove the alias, it shouldn't be needed
38+
// We just have to teach rustc_codegen_gcc to link to libgccjit.so directly, instead of
39+
// linking to libgccjit.so.0.
40+
create_lib_alias(builder, &dst);
41+
}
42+
}
43+
3144
impl Step for Gcc {
3245
type Output = GccOutput;
3346

0 commit comments

Comments
 (0)