From eaf7b2a7e78a8e600bb6a8013d7358a7435057a1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 25 Feb 2026 21:26:01 +0100 Subject: [PATCH 1/2] Add new `--with-llvm-sysroot` option for `test` commands --- build_system/src/build.rs | 27 ++++++++++++++++++--------- build_system/src/config.rs | 22 +++++++++++++++------- build_system/src/rust_tools.rs | 4 +++- build_system/src/test.rs | 27 +++++++++++++++++++++------ build_system/src/utils.rs | 10 ++++++++++ 5 files changed, 67 insertions(+), 23 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 839c762fed7..e52518ab387 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -106,12 +106,9 @@ fn cleanup_sysroot_previous_build(library_dir: &Path) { ); } -pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Result<(), String> { - let start_dir = get_sysroot_dir(); - - // Symlink libgccjit.so to sysroot. - let lib_path = start_dir.join("sysroot").join("lib"); - let rustlib_target_path = lib_path +pub fn link_libgccjit_in_sysroot(config: &ConfigInfo, sysroot_path: &Path) -> Result<(), String> { + let rustlib_target_path = sysroot_path + .join("lib") .join("rustlib") .join(&config.host_triple) .join("codegen-backends") @@ -124,8 +121,18 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu // First remove the file to be able to create the symlink even when the file already exists. let _ = fs::remove_file(&libgccjit_in_sysroot_path); create_dir(&rustlib_target_path)?; - symlink(libgccjit_path, &libgccjit_in_sysroot_path) + symlink(&libgccjit_path, &libgccjit_in_sysroot_path) .map_err(|error| format!("Cannot create symlink for libgccjit.so: {}", error))?; + println!("Created symlink of `libgccjit.so` at {libgccjit_in_sysroot_path:?}"); + Ok(()) +} + +pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Result<(), String> { + let start_dir = get_sysroot_dir(); + + // Symlink libgccjit.so to sysroot. + let sysroot_path = start_dir.join("sysroot"); + link_libgccjit_in_sysroot(config, &sysroot_path)?; let library_dir = start_dir.join("sysroot_src").join("library"); cleanup_sysroot_previous_build(&library_dir); @@ -179,7 +186,7 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu run_command_with_output_and_env(&args, Some(&sysroot_dir), Some(&env))?; // Copy files to sysroot - let sysroot_path = lib_path.join(format!("rustlib/{}/lib/", config.target_triple)); + let sysroot_path = sysroot_path.join(format!("lib/rustlib/{}/lib/", config.target_triple)); // To avoid errors like "multiple candidates for `rmeta` dependency `core` found", we clean the // sysroot directory before copying the sysroot build artifacts. let _ = fs::remove_dir_all(&sysroot_path); @@ -227,7 +234,9 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> { } run_command_with_output_and_env(&command, None, Some(&env))?; - args.config_info.setup(&mut env, false)?; + // We always build the sysroot with `cg_gcc` so we don't need to build the sysroot with + // `cg_llvm` since it's already distributed by rustup. + args.config_info.setup(&mut env, false, false)?; // We voluntarily ignore the error. let _ = fs::remove_dir_all("target/out"); diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 8eb6d8f019e..a8e2054a392 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -6,9 +6,10 @@ use std::{env as std_env, fs}; use boml::Toml; use boml::types::TomlValue; +use crate::build::link_libgccjit_in_sysroot; use crate::utils::{ - create_dir, create_symlink, get_os_name, get_sysroot_dir, run_command_with_output, - rustc_version_info, split_args, + create_dir, create_symlink, get_os_name, get_rustup_sysroot_dir, get_sysroot_dir, + run_command_with_output, rustc_version_info, split_args, }; #[derive(Default, PartialEq, Eq, Clone, Copy, Debug)] @@ -314,6 +315,7 @@ impl ConfigInfo { &mut self, env: &mut HashMap, use_system_gcc: bool, + with_llvm_sysroot: bool, ) -> Result<(), String> { env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); @@ -393,11 +395,10 @@ impl ConfigInfo { // by its build system directly so no need to set it ourselves. rustflags.push(format!("-Zcodegen-backend={backend}")); } else { - rustflags.extend_from_slice(&[ - "--sysroot".to_string(), - self.sysroot_path.clone(), - format!("-Zcodegen-backend={}", self.cg_backend_path), - ]); + if !with_llvm_sysroot { + rustflags.extend_from_slice(&["--sysroot".to_string(), self.sysroot_path.clone()]); + } + rustflags.push(format!("-Zcodegen-backend={}", self.cg_backend_path)); } // This environment variable is useful in case we want to change options of rustc commands. @@ -454,6 +455,13 @@ impl ConfigInfo { if !env.contains_key("RUSTC_LOG") { env.insert("RUSTC_LOG".to_string(), "warn".to_string()); } + + // In this case, it means we need to symlink `libgccjit.so` into the rustup sysroot. + if with_llvm_sysroot { + let sysroot_path = get_rustup_sysroot_dir()?; + link_libgccjit_in_sysroot(self, &sysroot_path)?; + } + Ok(()) } diff --git a/build_system/src/rust_tools.rs b/build_system/src/rust_tools.rs index b1faa27acc4..8473de49565 100644 --- a/build_system/src/rust_tools.rs +++ b/build_system/src/rust_tools.rs @@ -72,7 +72,9 @@ impl RustcTools { let mut env: HashMap = std::env::vars().collect(); let mut config = ConfigInfo::default(); - config.setup(&mut env, false)?; + // We always build the sysroot with `cg_gcc` so we don't need to build the sysroot with + // `cg_llvm` since it's already distributed by rustup. + config.setup(&mut env, false, false)?; let toolchain = get_toolchain()?; let toolchain_version = rustc_toolchain_version_info(&toolchain)?; diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 096f8c98376..682505f732f 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -68,7 +68,8 @@ fn show_usage() { --use-system-gcc : Use system installed libgccjit --build-only : Only build rustc_codegen_gcc then exits --nb-parts : Used to split rustc_tests (for CI needs) - --current-part : Used with `--nb-parts`, allows you to specify which parts to test"# + --current-part : Used with `--nb-parts`, allows you to specify which parts to test + --with-llvm-sysroot : Use the LLVM sysroot instead of the GCC one"# ); ConfigInfo::show_usage(); for (option, (doc, _)) in get_runners() { @@ -93,6 +94,7 @@ struct TestArg { config_info: ConfigInfo, sysroot_features: Vec, keep_lto_tests: bool, + with_llvm_sysroot: bool, } impl TestArg { @@ -136,6 +138,9 @@ impl TestArg { return Err(format!("Expected an argument after `{arg}`, found nothing")); } }, + "--with-llvm-sysroot" => { + test_arg.with_llvm_sysroot = true; + } "--help" => { show_usage(); return Ok(None); @@ -559,9 +564,14 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { let extra = if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" }; + let sysroot_arg = if args.with_llvm_sysroot { + String::new() + } else { + format!(" --sysroot {}", args.config_info.sysroot_path) + }; + let rustc_args = format!( - "-Zpanic-abort-tests -Zcodegen-backend={codegen_backend_path} --sysroot {} -Cpanic=abort{extra}", - args.config_info.sysroot_path + "-Zpanic-abort-tests -Zcodegen-backend={codegen_backend_path}{sysroot_arg} -Cpanic=abort{extra}", ); run_command_with_env( @@ -1028,11 +1038,16 @@ where let extra = if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" }; + let sysroot_arg = if args.with_llvm_sysroot { + String::new() + } else { + format!(" --sysroot {}", args.config_info.sysroot_path) + }; + let rustc_args = format!( - "{test_flags} -Zcodegen-backend={backend} --sysroot {sysroot}{extra}", + "{test_flags} -Zcodegen-backend={backend}{sysroot_arg}{extra}", test_flags = env.get("TEST_FLAGS").unwrap_or(&String::new()), backend = args.config_info.cg_backend_path, - sysroot = args.config_info.sysroot_path, extra = extra, ); @@ -1270,7 +1285,7 @@ pub fn run() -> Result<(), String> { return Ok(()); } - args.config_info.setup(&mut env, args.use_system_gcc)?; + args.config_info.setup(&mut env, args.use_system_gcc, args.with_llvm_sysroot)?; if args.runners.is_empty() { run_all(&env, &args)?; diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 112322f8688..af040572ff1 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -419,6 +419,16 @@ pub fn get_sysroot_dir() -> PathBuf { Path::new(crate::BUILD_DIR).join("build_sysroot") } +pub fn get_rustup_sysroot_dir() -> Result { + let output = run_command(&[&"rustc", &"--print=sysroot"], None)?; + + Ok(PathBuf::from( + String::from_utf8(output.stdout) + .map_err(|error| format!("`rustc --print=sysroot` failed: {error}"))? + .trim(), + )) +} + #[cfg(test)] mod tests { use super::*; From 3f1d43c6475a1636995c0c294ae64181efd3204a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 25 Feb 2026 21:26:21 +0100 Subject: [PATCH 2/2] Add CI checks with LLVM sysroot --- .github/workflows/ci.yml | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 840c09409bb..b008af33a80 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,16 +26,19 @@ jobs: - { gcc: "gcc-15.deb" } - { gcc: "gcc-15-without-int128.deb" } commands: [ - "--std-tests", + "--build-sysroot --std-tests", # FIXME: re-enable asm tests when GCC can emit in the right syntax. - # "--asm-tests", - "--test-libcore", - "--extended-rand-tests", - "--extended-regex-example-tests", - "--extended-regex-tests", - "--test-successful-rustc --nb-parts 2 --current-part 0", - "--test-successful-rustc --nb-parts 2 --current-part 1", - "--projects", + # "--build-sysroot --asm-tests", + "--build-sysroot --test-libcore", + "--build-sysroot --extended-rand-tests", + "--build-sysroot --extended-regex-example-tests", + "--build-sysroot --extended-regex-tests", + "--build-sysroot --test-successful-rustc --nb-parts 2 --current-part 0", + "--build-sysroot --test-successful-rustc --nb-parts 2 --current-part 1", + "--build-sysroot --projects", + "--test-successful-rustc --nb-parts 2 --current-part 0 --with-llvm-sysroot", + "--test-successful-rustc --nb-parts 2 --current-part 1 --with-llvm-sysroot", + "--projects --with-llvm-sysroot", ] steps: @@ -119,7 +122,7 @@ jobs: - name: Run tests run: | - ./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} + ./y.sh test --release --clean ${{ matrix.commands }} duplicates: runs-on: ubuntu-24.04