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

  1. Rebuild the C static library without -flto so it contains ordinary relocatable object files.
  2. 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.
  3. 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

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


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/3c7e04bcbf349e84.json. Report an issue: GitHub.