diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 479327d6369..44469da1e64 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -17,6 +17,7 @@ use std::{env, fs, str}; use serde_derive::Deserialize; +use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags}; use crate::core::build_steps::tool::SourceType; use crate::core::build_steps::{dist, llvm}; use crate::core::builder; @@ -1500,6 +1501,14 @@ impl Step for CodegenBackend { .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml"))); rustc_cargo_env(builder, &mut cargo, target, compiler.stage); + // 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" { + 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); diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index 98b8635132b..3edca8834e0 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -9,13 +9,13 @@ //! ensure that they're always in place if needed. use std::fs; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::sync::OnceLock; use build_helper::ci::CiEnv; use crate::Kind; -use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::core::builder::{Builder, Cargo, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; use crate::utils::build_stamp::{BuildStamp, generate_smart_stamp_hash}; use crate::utils::exec::command; @@ -29,7 +29,8 @@ pub struct Meta { } pub enum GccBuildStatus { - AlreadyBuilt, + /// libgccjit is already built at this path + AlreadyBuilt(PathBuf), ShouldBuild(Meta), } @@ -41,9 +42,6 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc // Initialize the gcc submodule if not initialized already. builder.config.update_submodule("src/gcc"); - // FIXME (GuillaumeGomez): To be done once gccjit has been built in the CI. - // builder.config.maybe_download_ci_gcc(); - let root = builder.src.join("src/gcc"); let out_dir = builder.gcc_out(target).join("build"); let install_dir = builder.gcc_out(target).join("install"); @@ -70,19 +68,37 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc stamp.path().display() )); } - return GccBuildStatus::AlreadyBuilt; + let path = libgccjit_built_path(&install_dir); + if path.is_file() { + return GccBuildStatus::AlreadyBuilt(path); + } else { + builder.info(&format!( + "GCC stamp is up-to-date, but the libgccjit.so file was not found at `{}`", + path.display(), + )); + } } GccBuildStatus::ShouldBuild(Meta { stamp, out_dir, install_dir, root }) } +/// Returns the path to a libgccjit.so file in the install directory of GCC. +fn libgccjit_built_path(install_dir: &Path) -> PathBuf { + install_dir.join("lib/libgccjit.so") +} + #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Gcc { pub target: TargetSelection, } +#[derive(Clone)] +pub struct GccOutput { + pub libgccjit: PathBuf, +} + impl Step for Gcc { - type Output = bool; + type Output = GccOutput; const ONLY_HOSTS: bool = true; @@ -94,14 +110,14 @@ impl Step for Gcc { run.builder.ensure(Gcc { target: run.target }); } - /// Compile GCC for `target`. - fn run(self, builder: &Builder<'_>) -> bool { + /// Compile GCC (specifically `libgccjit`) for `target`. + fn run(self, builder: &Builder<'_>) -> Self::Output { let target = self.target; // If GCC has already been built, we avoid building it again. let Meta { stamp, out_dir, install_dir, root } = match prebuilt_gcc_config(builder, target) { - GccBuildStatus::AlreadyBuilt => return true, + GccBuildStatus::AlreadyBuilt(path) => return GccOutput { libgccjit: path }, GccBuildStatus::ShouldBuild(m) => m, }; @@ -110,8 +126,9 @@ impl Step for Gcc { let _time = helpers::timeit(builder); t!(fs::create_dir_all(&out_dir)); + let libgccjit_path = libgccjit_built_path(&install_dir); if builder.config.dry_run() { - return true; + return GccOutput { libgccjit: libgccjit_path }; } // GCC creates files (e.g. symlinks to the downloaded dependencies) @@ -173,11 +190,17 @@ impl Step for Gcc { let lib_alias = install_dir.join("lib/libgccjit.so.0"); if !lib_alias.exists() { - t!(builder.symlink_file(install_dir.join("lib/libgccjit.so"), lib_alias,)); + t!(builder.symlink_file(&libgccjit_path, lib_alias)); } t!(stamp.write()); - true + GccOutput { libgccjit: libgccjit_path } } } + +/// Configures a Cargo invocation so that it can build the GCC codegen backend. +pub fn add_cg_gcc_cargo_flags(cargo: &mut Cargo, gcc: &GccOutput) { + // Add the path to libgccjit.so to the linker search paths. + cargo.rustflag(&format!("-L{}", gcc.libgccjit.parent().unwrap().display())); +} diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 26ed0e5deaa..c3eceda0d1a 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -12,6 +12,7 @@ use clap_complete::shells; use crate::core::build_steps::compile::run_cargo; use crate::core::build_steps::doc::DocumentationFormat; +use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags}; use crate::core::build_steps::llvm::get_llvm_version; use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget; use crate::core::build_steps::tool::{self, SourceType, Tool}; @@ -3520,6 +3521,8 @@ impl Step for CodegenGCC { let compiler = self.compiler; let target = self.target; + let gcc = builder.ensure(Gcc { target }); + builder.ensure( compile::Std::new(compiler, target) .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]), @@ -3546,6 +3549,7 @@ impl Step for CodegenGCC { .arg("--manifest-path") .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml")); compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage); + add_cg_gcc_cargo_flags(&mut cargo, &gcc); // Avoid incremental cache issues when changing rustc cargo.env("CARGO_BUILD_INCREMENTAL", "false"); @@ -3578,9 +3582,10 @@ impl Step for CodegenGCC { .env("CG_RUSTFLAGS", "-Alinker-messages") .arg("--") .arg("test") - .arg("--use-system-gcc") .arg("--use-backend") .arg("gcc") + .arg("--gcc-path") + .arg(gcc.libgccjit.parent().unwrap()) .arg("--out-dir") .arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_gcc")) .arg("--release")