about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJakub Beránek <berykubik@gmail.com>2025-01-30 15:07:24 +0100
committerJakub Beránek <berykubik@gmail.com>2025-02-15 16:48:37 +0100
commit17472a9f80e6143538f5c29d9bbc0f1acf8dae4a (patch)
tree753ece5ae89530d3e4fc825da994e9ec668ffec0
parenta0cf0f2eb42252f58729ce30b13eec9fd0716a21 (diff)
downloadrust-17472a9f80e6143538f5c29d9bbc0f1acf8dae4a.tar.gz
rust-17472a9f80e6143538f5c29d9bbc0f1acf8dae4a.zip
Improve GCC build in bootstrap
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs9
-rw-r--r--src/bootstrap/src/core/build_steps/gcc.rs51
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs7
3 files changed, 52 insertions, 15 deletions
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")