rust-lang/rust · critical
Could not load libgccjit.so. Attempted paths: {:#?}
Error message
Could not load libgccjit.so. Attempted paths: {:#?} What it means
`panic!("Could not load libgccjit.so. Attempted paths: {:#?}")` in `GccCodegenBackend::init`, reached after the backend iterated every `--sysroot` path (via `sysroot.all_paths()`), checked for the existence of `rustlib/codegen-backends/lib/<target>/libgccjit.so`, and found none. The panic lists the exact paths tried so the user can see where the backend expected the library. Unlike error 156, here the file was never found at all.
Source
Thrown at compiler/rustc_codegen_gcc/src/lib.rs:228
// We use all_paths() instead of only path() in case the path specified by --sysroot is
// invalid.
// This is the case for instance in Rust for Linux where they specify --sysroot=/dev/null.
for path in sess.opts.sysroot.all_paths() {
let libgccjit_target_lib_file = file_path(path, sess);
if let Ok(true) = fs::exists(&libgccjit_target_lib_file) {
load_libgccjit_if_needed(&libgccjit_target_lib_file);
break;
}
}
if !gccjit::is_loaded() {
let mut paths = vec![];
for path in sess.opts.sysroot.all_paths() {
let libgccjit_target_lib_file = file_path(path, sess);
paths.push(libgccjit_target_lib_file);
}
panic!("Could not load libgccjit.so. Attempted paths: {:#?}", paths);
}
#[cfg(feature = "master")]
{
gccjit::set_lang_name(c"GNU Rust");
let target_cpu = target_cpu(sess);
// Get the second TargetInfo with the correct CPU features by setting the arch.
let context = Context::default();
if target_cpu != "generic" {
context.add_command_line_option(format!("-march={}", target_cpu));
}
*self.target_info.info.lock().expect("lock") =
IntoDynSyncSend(Some(context.get_target_info()));
}
View on GitHub (pinned to 22057b88b0)
Solutions
- Install/place `libgccjit.so` under `<sysroot>/lib/rustlib/<host>/codegen-backends/lib/<target>/libgccjit.so` exactly as the panic's path list shows.
- Drop the `--sysroot` override (or `RUST_SYSROOT`) so the default toolchain sysroot is used.
- Install the rustc_codegen_gcc toolchain / component that ships the runtime library.
- Verify `rustc --print sysroot` resolves to the directory that actually contains the listed subpath.
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check all candidate sysroot paths the backend would search
use std::path::Path;
fn find_libgccjit(sysroots: &[&str], host_triple: &str, target_triple: &str) -> Result<String, String> {
let mut attempted: Vec<String> = Vec::new();
for sysroot in sysroots {
let p = format!(
"{}/lib/rustlib/{}/codegen-backends/lib/{}/libgccjit.so",
sysroot, host_triple, target_triple
);
attempted.push(p.clone());
if Path::new(&p).exists() {
return Ok(p);
}
}
// Check GCC_BACKEND_PATH override
if let Ok(override_path) = std::env::var("GCC_BACKEND_PATH") {
if Path::new(&override_path).exists() {
return Ok(override_path);
}
attempted.push(override_path);
}
// Check ldconfig
let ldc = std::process::Command::new("sh")
.args(["-c", "ldconfig -p 2>/dev/null | grep libgccjit | head -1"])
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())
.unwrap_or_default();
if !ldc.trim().is_empty() {
return Ok(ldc.trim().to_string());
}
Err(format!("Could not find libgccjit.so. Attempted paths: {:#?}", attempted))
}
// Usage in build.rs:
// let sysroot = std::process::Command::new("rustc").arg("--print").arg("sysroot").output().unwrap();
// let sr = String::from_utf8_lossy(&sysroot.stdout).trim().to_string();
// find_libgccjit(&[&sr], std::env::consts::ARCH, std::env::consts::ARCH)?; Try / catch
// Catch exhaustive-load failure and provide actionable diagnostics
use std::process::Command;
fn build_with_gcc_backend(crate_path: &str) -> Result<(), String> {
let out = Command::new("rustc")
.args(["-Z", "codegen-backend=gcc"])
.arg(crate_path)
.output()
.map_err(|e| e.to_string())?;
if !out.status.success() {
let stderr = String::from_utf8_lossy(&out.stderr);
if stderr.contains("Could not load libgccjit") {
// Provide remediation
return Err(format!(
"libgccjit.so not found in any sysroot. Fix:\n\
1. Install libgccjit-dev\n\
2. Or set GCC_BACKEND_PATH=/path/to/libgccjit.so\n\
3. Or use the LLVM backend instead\n\
Original error: {}",
stderr.lines().find(|l| l.contains("Could not load")).unwrap_or("unknown")
));
}
return Err(stderr.to_string());
}
Ok(())
} Prevention
- Run: rustc --print sysroot to find where rustc expects libgccjit.so, then verify the full path exists
- If --sysroot is overridden (e.g. Rust-for-Linux uses --sysroot=/dev/null), set GCC_BACKEND_PATH to an absolute path
- Symlink the versioned file to the unversioned name: ln -s libgccjit.so.0 libgccjit.so
- Add the libgccjit directory to /etc/ld.so.conf.d/ and run ldconfig so the dynamic linker can resolve it
- In Dockerfiles, install libgccjit in the same RUN layer as the Rust toolchain to avoid layer ordering issues
When it happens
Trigger: Compiling with `-Ccodegen-backend=gcc` when the libgccjit target library is absent from every sysroot, e.g. the GCC backend component was never installed, or `--sysroot` was overridden to a path that lacks the codegen-backends directory (Rust for Linux passes `--sysroot=/dev/null`).
Common situations: Fresh rustc_codegen_gcc setup where the backend crate is built but the runtime `libgccjit.so` was not placed under `rustlib/codegen-backends/lib/<target>/`; cross-compiling to a target with no matching triplet directory; rust-toolchain override pointing at a minimal sysroot.
Related errors
- Cannot load libgccjit.so: {}
- Called extract_element on a non-vector type
- func
- struct type
- `static_addr_of_mut` did not add the global to `self.global_
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/9e0e78db241d140f.json.
Report an issue: GitHub.