rust-lang/rust · error
LTO object in C static library is not supported
Error message
LTO object in C static library is not supported
What it means
Returned by add_c_staticlib_symbols after parsing each archive member with object::File::parse: if any section's name starts with '.gnu.lto_' or equals '.llvm.lto', the member is a GCC/Clang ELF or Mach-O LTO object rather than a normal relocatable object. Like the raw-bitcode case, Rust cannot merge these into its symbol export set and cannot drive cross-language LTO through the plain native-lib path, so the library is rejected.
Source
Thrown at compiler/rustc_codegen_ssa/src/back/link.rs:2826
.data(&*archive_map)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
// clang LTO: raw LLVM bitcode
if data.starts_with(b"BC\xc0\xde") {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"LLVM bitcode object in C static library (LTO not supported)",
));
}
let object = object::File::parse(&*data)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
// gcc / clang ELF / Mach-O LTO
if object.sections().any(|s| {
s.name().map(|n| n.starts_with(".gnu.lto_") || n == ".llvm.lto").unwrap_or(false)
}) {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"LTO object in C static library is not supported",
));
}
for symbol in object.symbols() {
// The `object` crate returns `Dynamic` for ELF/Mach-O global symbols,
// but always returns `Linkage` for COFF external symbols.
// Accept both for COFF (Windows and UEFI).
let scope = symbol.scope();
if scope != object::SymbolScope::Dynamic
&& !(sess.target.binary_format == BinaryFormat::Coff
&& scope == object::SymbolScope::Linkage)
{
continue;
}
let name = match symbol.name() {View on GitHub (pinned to 22057b88b0)
Solutions
- Rebuild the C static library without -flto so it contains ordinary relocatable object files.
- If cross-language LTO is desired, align on a single LLVM toolchain and enable -Clinker-plugin-lto on the Rust side, passing the C objects through the linker rather than as a scanned native staticlib.
- Replace the LTO-built artifact with a non-LTO build from source (e.g. via cc::Build in build.rs).
Example fix
# before gcc -flto -c lib.c -o lib.o && ar rcs libfoo.a lib.o # after gcc -c lib.c -o lib.o && ar rcs libfoo.a lib.o
Defensive patterns
Strategy: fallback
Validate before calling
use std::process::Command;
// Detect LTO objects (bitcode-only or llvm-lto wrapped) inside a `.a`.
fn archive_contains_lto_objects(path: &str) -> bool {
let Ok(o) = Command::new("llvm-objdump").args(["-a", path]).output() else {
return archive_contains_llvm_bitcode(path);
};
String::from_utf8_lossy(&o.stdout).contains("LLVM IR")
|| archive_contains_llvm_bitcode(path)
}
// caller: if archive_contains_lto_objects("libfoo.a") { swap_to_plain_archive()?; } Type guard
fn is_native_objects_only_archive(path: &str) -> bool {
!archive_contains_lto_objects(path)
} Try / catch
let stderr = String::from_utf8_lossy(&output.stderr);
if stderr.contains("LTO object in C static library is not supported") {
// Fallback: link the same dependency as a dynamic lib or a rebuilt non-LTO `.a`.
link_dynamic_variant_of("foo")?;
} Prevention
- Re-export C deps with `-fno-lto` so the archive holds ELF/Mach-O objects only.
- Prefer dynamic linking for C deps you cannot rebuild without LTO.
- In `build.rs`, prefer `cargo:rustc-link-lib=dylib=` over `static=` when LTO provenance is uncertain.
When it happens
Trigger: Linking a native C/C++ static library that was compiled with `gcc -flto` or `clang -flto` (ELF or Mach-O flavor) into a Rust crate. Detection happens post-parse by scanning section names for the LTO markers.
Common situations: Distro-provided static libraries built with -flto by default. C dependencies built by a build.rs or external Makefile that injects -flto. Mixing GCC LTO objects into a Rust link that is not configured for linker-plugin LTO.
Related errors
- LLVM bitcode object in C static library (LTO not supported)
- staticlibs not supported
- failed to mmap LTO bitcode file `{}`: {}
- not implemented
- function ptr
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/3c7e04bcbf349e84.json.
Report an issue: GitHub.