about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorLeón Orell Valerian Liehr <me@fmease.dev>2025-03-15 00:18:23 +0100
committerGitHub <noreply@github.com>2025-03-15 00:18:23 +0100
commitfc7ac81979bb0ed2f7cea33926bb33c7b143c6d9 (patch)
tree1b59c9019292e6a1a24cebb7db8a8890c1bd18b4 /src
parent10055fb03ab2c7cbb9d7da4833963f631d82ec03 (diff)
parentbf095f6ecee956b3942625d9480e3a2f13666a67 (diff)
downloadrust-fc7ac81979bb0ed2f7cea33926bb33c7b143c6d9.tar.gz
rust-fc7ac81979bb0ed2f7cea33926bb33c7b143c6d9.zip
Rollup merge of #138451 - Kobzol:gcc-ci-build-gcc, r=GuillaumeGomez
Build GCC on CI with GCC, not Clang

It seems that GCC built with Clang misbehaves. I have tested that cg_gcc tests [pass](https://github.com/rust-lang/rust/actions/runs/13842365913/job/38732750617?pr=138451) on CI with a downloaded GCC that was built in this way.

Prerequisite for https://github.com/rust-lang/rust/pull/138395.

r? ```@ghost```
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/gcc.rs38
-rw-r--r--src/bootstrap/src/lib.rs11
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile4
-rw-r--r--src/tools/opt-dist/src/tests.rs81
5 files changed, 91 insertions, 45 deletions
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index c393eb55c62..2354fe1ebaf 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -2481,7 +2481,7 @@ impl Step for Gcc {
     fn run(self, builder: &Builder<'_>) -> Self::Output {
         let tarball = Tarball::new(builder, "gcc", &self.target.triple);
         let output = builder.ensure(super::gcc::Gcc { target: self.target });
-        tarball.add_file(output.libgccjit, ".", 0o644);
+        tarball.add_file(output.libgccjit, "lib", 0o644);
         tarball.generate()
     }
 }
diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs
index 5a4bc9bdbcb..0aa2a332531 100644
--- a/src/bootstrap/src/core/build_steps/gcc.rs
+++ b/src/bootstrap/src/core/build_steps/gcc.rs
@@ -63,11 +63,7 @@ impl Step for Gcc {
         }
 
         build_gcc(&metadata, builder, target);
-
-        let lib_alias = metadata.install_dir.join("lib/libgccjit.so.0");
-        if !lib_alias.exists() {
-            t!(builder.symlink_file(&libgccjit_path, lib_alias));
-        }
+        create_lib_alias(builder, &libgccjit_path);
 
         t!(metadata.stamp.write());
 
@@ -75,6 +71,15 @@ impl Step for Gcc {
     }
 }
 
+/// Creates a libgccjit.so.0 alias next to libgccjit.so if it does not
+/// already exist
+fn create_lib_alias(builder: &Builder<'_>, libgccjit: &PathBuf) {
+    let lib_alias = libgccjit.parent().unwrap().join("libgccjit.so.0");
+    if !lib_alias.exists() {
+        t!(builder.symlink_file(libgccjit, lib_alias));
+    }
+}
+
 pub struct Meta {
     stamp: BuildStamp,
     out_dir: PathBuf,
@@ -109,8 +114,10 @@ fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option<Pa
         builder.config.download_ci_gcc(&sha, &root);
         t!(gcc_stamp.write());
     }
-    // FIXME: put libgccjit.so into a lib directory in dist::Gcc
-    Some(root.join("libgccjit.so"))
+
+    let libgccjit = root.join("lib").join("libgccjit.so");
+    create_lib_alias(builder, &libgccjit);
+    Some(libgccjit)
 }
 
 #[cfg(test)]
@@ -177,6 +184,14 @@ fn libgccjit_built_path(install_dir: &Path) -> PathBuf {
 }
 
 fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) {
+    if builder.build.cc_tool(target).is_like_clang()
+        || builder.build.cxx_tool(target).is_like_clang()
+    {
+        panic!(
+            "Attempting to build GCC using Clang, which is known to misbehave. Please use GCC as the host C/C++ compiler. "
+        );
+    }
+
     let Meta { stamp: _, out_dir, install_dir, root } = metadata;
 
     t!(fs::create_dir_all(out_dir));
@@ -203,18 +218,13 @@ fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) {
     let mut configure_cmd = command(src_dir.join("configure"));
     configure_cmd
         .current_dir(out_dir)
-        // On CI, we compile GCC with Clang.
-        // The -Wno-everything flag is needed to make GCC compile with Clang 19.
-        // `-g -O2` are the default flags that are otherwise used by Make.
-        // FIXME(kobzol): change the flags once we have [gcc] configuration in config.toml.
-        .env("CXXFLAGS", "-Wno-everything -g -O2")
-        .env("CFLAGS", "-Wno-everything -g -O2")
         .arg("--enable-host-shared")
-        .arg("--enable-languages=jit")
+        .arg("--enable-languages=c,jit,lto")
         .arg("--enable-checking=release")
         .arg("--disable-bootstrap")
         .arg("--disable-multilib")
         .arg(format!("--prefix={}", install_dir.display()));
+
     let cc = builder.build.cc(target).display().to_string();
     let cc = builder
         .build
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 8dfd1bbfd60..91574f8bf5d 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -27,6 +27,7 @@ use std::{env, fs, io, str};
 
 use build_helper::ci::gha;
 use build_helper::exit;
+use cc::Tool;
 use termcolor::{ColorChoice, StandardStream, WriteColor};
 use utils::build_stamp::BuildStamp;
 use utils::channel::GitInfo;
@@ -1218,6 +1219,16 @@ Executed at: {executed_at}"#,
         self.cc.borrow()[&target].path().into()
     }
 
+    /// Returns the internal `cc::Tool` for the C compiler.
+    fn cc_tool(&self, target: TargetSelection) -> Tool {
+        self.cc.borrow()[&target].clone()
+    }
+
+    /// Returns the internal `cc::Tool` for the C++ compiler.
+    fn cxx_tool(&self, target: TargetSelection) -> Tool {
+        self.cxx.borrow()[&target].clone()
+    }
+
     /// Returns C flags that `cc-rs` thinks should be enabled for the
     /// specified target by default.
     fn cc_handled_clags(&self, target: TargetSelection, c: CLang) -> Vec<String> {
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index f54ecef1e30..ae5bf8946dd 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -101,7 +101,9 @@ ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \
     ./build/$HOSTS/stage0-tools-bin/opt-dist linux-ci -- python3 ../x.py dist \
     --host $HOSTS --target $HOSTS \
     --include-default-paths \
-    build-manifest bootstrap gcc
+    build-manifest bootstrap && \
+    # Use GCC for building GCC, as it seems to behave badly when built with Clang
+    CC=/rustroot/bin/cc CXX=/rustroot/bin/c++ python3 ../x.py dist gcc
 ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang
 
 # This is the only builder which will create source tarballs
diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs
index 8b3bd77141b..c8759bb6ff6 100644
--- a/src/tools/opt-dist/src/tests.rs
+++ b/src/tools/opt-dist/src/tests.rs
@@ -1,3 +1,5 @@
+use std::path::Path;
+
 use anyhow::Context;
 use camino::{Utf8Path, Utf8PathBuf};
 
@@ -86,36 +88,57 @@ llvm-config = "{llvm_config}"
     log::info!("Using following `config.toml` for running tests:\n{config_content}");
 
     // Simulate a stage 0 compiler with the extracted optimized dist artifacts.
-    std::fs::write("config.toml", config_content)?;
-
-    let x_py = env.checkout_path().join("x.py");
-    let mut args = vec![
-        env.python_binary(),
-        x_py.as_str(),
-        "test",
-        "--build",
-        env.host_tuple(),
-        "--stage",
-        "0",
-        "tests/assembly",
-        "tests/codegen",
-        "tests/codegen-units",
-        "tests/incremental",
-        "tests/mir-opt",
-        "tests/pretty",
-        "tests/run-make/glibc-symbols-x86_64-unknown-linux-gnu",
-        "tests/ui",
-        "tests/crashes",
-    ];
-    for test_path in env.skipped_tests() {
-        args.extend(["--skip", test_path]);
+    with_backed_up_file(Path::new("config.toml"), &config_content, || {
+        let x_py = env.checkout_path().join("x.py");
+        let mut args = vec![
+            env.python_binary(),
+            x_py.as_str(),
+            "test",
+            "--build",
+            env.host_tuple(),
+            "--stage",
+            "0",
+            "tests/assembly",
+            "tests/codegen",
+            "tests/codegen-units",
+            "tests/incremental",
+            "tests/mir-opt",
+            "tests/pretty",
+            "tests/run-make/glibc-symbols-x86_64-unknown-linux-gnu",
+            "tests/ui",
+            "tests/crashes",
+        ];
+        for test_path in env.skipped_tests() {
+            args.extend(["--skip", test_path]);
+        }
+        cmd(&args)
+            .env("COMPILETEST_FORCE_STAGE0", "1")
+            // Also run dist-only tests
+            .env("COMPILETEST_ENABLE_DIST_TESTS", "1")
+            .run()
+            .context("Cannot execute tests")
+    })
+}
+
+/// Backup `path` (if it exists), then write `contents` into it, and then restore the original
+/// contents of the file.
+fn with_backed_up_file<F>(path: &Path, contents: &str, func: F) -> anyhow::Result<()>
+where
+    F: FnOnce() -> anyhow::Result<()>,
+{
+    let original_contents =
+        if path.is_file() { Some(std::fs::read_to_string(path)?) } else { None };
+
+    // Overwrite it with new contents
+    std::fs::write(path, contents)?;
+
+    let ret = func();
+
+    if let Some(original_contents) = original_contents {
+        std::fs::write(path, original_contents)?;
     }
-    cmd(&args)
-        .env("COMPILETEST_FORCE_STAGE0", "1")
-        // Also run dist-only tests
-        .env("COMPILETEST_ENABLE_DIST_TESTS", "1")
-        .run()
-        .context("Cannot execute tests")
+
+    ret
 }
 
 /// Tries to find the version of the dist artifacts (either nightly, beta, or 1.XY.Z).