rust-lang/rust · critical
Cannot load libgccjit.so: {}
Error message
Cannot load libgccjit.so: {} What it means
`panic!("Cannot load libgccjit.so: {}")` in `load_libgccjit_if_needed`, reached when `gccjit::load(&path)` returns `Err`. The backend located a candidate `libgccjit.so` under `<sysroot>/rustlib/codegen-backends/lib/<target>/libgccjit.so` and tried to dlopen it, but loading failed. The formatted `{}` is the underlying load error (missing symbol, ABI mismatch, missing transitive shared library, corrupt file).
Source
Thrown at compiler/rustc_codegen_gcc/src/lib.rs:189
#[derive(Clone)]
pub struct GccCodegenBackend {
target_info: LockedTargetInfo,
lto_supported: Arc<AtomicBool>,
}
fn load_libgccjit_if_needed(libgccjit_target_lib_file: &Path) {
if gccjit::is_loaded() {
// Do not load a libgccjit second time.
return;
}
let path = libgccjit_target_lib_file.to_str().expect("libgccjit path");
let string = CString::new(path).expect("string to libgccjit path");
if let Err(error) = gccjit::load(&string) {
panic!("Cannot load libgccjit.so: {}", error);
}
}
impl CodegenBackend for GccCodegenBackend {
fn name(&self) -> &'static str {
"gcc"
}
fn init(&self, sess: &Session) {
fn file_path(sysroot_path: &Path, sess: &Session) -> PathBuf {
let rustlib_path =
rustc_target::relative_target_rustlib_path(sysroot_path, &sess.host.llvm_target);
sysroot_path
.join(rustlib_path)
.join("codegen-backends")
.join("lib")
.join(sess.target.llvm_target.as_ref())
.join("libgccjit.so")View on GitHub (pinned to 22057b88b0)
Solutions
- Run `ldd <sysroot>/.../libgccjet.so` to find the missing transitive dependency and install it.
- Reinstall the rustc_codegen_gcc toolchain (or `rustup component add`-equivalent) so the bundled libgccjit and its deps match.
- Confirm the file is not corrupt: `file libgccjit.so` and `nm -D libgccjit.so | grep gccjit_create_context`.
- If you set `--sysroot`, point it at the toolchain root that actually ships libgccjit.so for your target.
Defensive patterns
Strategy: validation
Validate before calling
// Validate libgccjit.so is loadable BEFORE invoking the GCC backend
use std::path::Path;
fn libgccjit_loadable(sysroot: &str, host_triple: &str, target_triple: &str) -> Result<(), String> {
// The backend looks for: sysroot/lib/rustlib/{host}/codegen-backends/lib/{target}/libgccjit.so
let candidate = format!(
"{}/lib/rustlib/{}/codegen-backends/lib/{}/libgccjit.so",
sysroot, host_triple, target_triple
);
if Path::new(&candidate).exists() {
// Verify it is actually dlopen-able (not a broken symlink)
let probe = std::process::Command::new("sh")
.args(["-c", &format!("ldd '{}' 2>&1", candidate)])
.output()
.map_err(|e| format!("Cannot run ldd: {}", e))?;
let out = String::from_utf8_lossy(&probe.stdout);
if out.contains("not found") {
return Err(format!("libgccjit.so exists at {} but has unresolved dependencies: {}", candidate, out));
}
return Ok(());
}
// Fall back to system-wide ldconfig lookup
let ldc = std::process::Command::new("sh")
.args(["-c", "ldconfig -p 2>/dev/null | grep libgccjit"])
.output()
.map_err(|e| format!("Cannot run ldconfig: {}", e))?;
if ldc.stdout.is_empty() {
return Err("libgccjit.so not found. Install libgccjit-dev (apt) or gccjit-devel (dnf), or set GCC_BACKEND_PATH.".into());
}
Ok(())
} Try / catch
// Catch libgccjit load failure at the build-script / CI level and fall back
use std::process::Command;
fn compile_with_gcc_or_fallback(crate_path: &str) -> Result<(), String> {
let gcc_result = Command::new("rustc")
.args(["-Z", "codegen-backend=gcc"])
.arg(crate_path)
.output()
.map_err(|e| format!("Failed to invoke rustc: {}", e))?;
if !gcc_result.status.success() {
let stderr = String::from_utf8_lossy(&gcc_result.stderr);
if stderr.contains("Cannot load libgccjit") {
eprintln!("Warning: GCC backend unavailable, falling back to LLVM");
let llvm_result = Command::new("rustc")
.arg(crate_path)
.output()
.map_err(|e| e.to_string())?;
if !llvm_result.status.success() {
return Err(String::from_utf8_lossy(&llvm_result.stderr).to_string());
}
} else {
return Err(stderr.to_string());
}
}
Ok(())
} Prevention
- Install the libgccjit development package: apt install libgccjit-dev (Debian/Ubuntu) or dnf install gccjit-devel (Fedora)
- Verify with: ldd $(rustc --print sysroot)/lib/rustlib/*/codegen-backends/*/*/libgccjit.so to check for unresolved dependencies
- Pin a GCC version compatible with your rustc build — libgccjit ABI changes between major GCC releases
- In CI, add a pre-build step that runs: rustc -Z codegen-backend=gcc --version as a smoke test before the real compilation
When it happens
Trigger: Using `-Ccodegen-backend=gcc` (or a rustc configured with the GCC backend as default) when the discovered libgccjit.so fails to dlopen: e.g. built against libstdc++.so.N that is not installed, or built for a different libgccjit soname, or compiled with a conflicting `-Ctarget-cpu`/ABI.
Common situations: A rustc_codegen_gcc toolchain installed without its runtime dependency libraries; a system upgrade that removed or bumped libstdc++/libgmp; a manually copied libgccjit.so with a broken DT_NEEDED; cross-target sysroot pointing at the wrong triplet.
Related errors
- Could not load libgccjit.so. Attempted paths: {:#?}
- 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/76edd8027086261d.json.
Report an issue: GitHub.