{"id":"3c7e04bcbf349e84","repo":"rust-lang/rust","slug":"lto-object-in-c-static-library-is-not-supported","errorCode":null,"errorMessage":"LTO object in C static library is not supported","messagePattern":"LTO object in C static library is not supported","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_codegen_ssa/src/back/link.rs","lineNumber":2826,"sourceCode":"            .data(&*archive_map)\n            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;\n\n        // clang LTO: raw LLVM bitcode\n        if data.starts_with(b\"BC\\xc0\\xde\") {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                \"LLVM bitcode object in C static library (LTO not supported)\",\n            ));\n        }\n\n        let object = object::File::parse(&*data)\n            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;\n\n        // gcc / clang ELF / Mach-O LTO\n        if object.sections().any(|s| {\n            s.name().map(|n| n.starts_with(\".gnu.lto_\") || n == \".llvm.lto\").unwrap_or(false)\n        }) {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                \"LTO object in C static library is not supported\",\n            ));\n        }\n\n        for symbol in object.symbols() {\n            // The `object` crate returns `Dynamic` for ELF/Mach-O global symbols,\n            // but always returns `Linkage` for COFF external symbols.\n            // Accept both for COFF (Windows and UEFI).\n            let scope = symbol.scope();\n            if scope != object::SymbolScope::Dynamic\n                && !(sess.target.binary_format == BinaryFormat::Coff\n                    && scope == object::SymbolScope::Linkage)\n            {\n                continue;\n            }\n\n            let name = match symbol.name() {","sourceCodeStart":2808,"sourceCodeEnd":2844,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_codegen_ssa/src/back/link.rs#L2808-L2844","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"# before\ngcc -flto -c lib.c -o lib.o && ar rcs libfoo.a lib.o\n# after\ngcc -c lib.c -o lib.o && ar rcs libfoo.a lib.o","handlingStrategy":"fallback","validationCode":"use std::process::Command;\n\n// Detect LTO objects (bitcode-only or llvm-lto wrapped) inside a `.a`.\nfn archive_contains_lto_objects(path: &str) -> bool {\n    let Ok(o) = Command::new(\"llvm-objdump\").args([\"-a\", path]).output() else {\n        return archive_contains_llvm_bitcode(path);\n    };\n    String::from_utf8_lossy(&o.stdout).contains(\"LLVM IR\")\n        || archive_contains_llvm_bitcode(path)\n}\n\n// caller: if archive_contains_lto_objects(\"libfoo.a\") { swap_to_plain_archive()?; }","typeGuard":"fn is_native_objects_only_archive(path: &str) -> bool {\n    !archive_contains_lto_objects(path)\n}","tryCatchPattern":"let stderr = String::from_utf8_lossy(&output.stderr);\nif stderr.contains(\"LTO object in C static library is not supported\") {\n    // Fallback: link the same dependency as a dynamic lib or a rebuilt non-LTO `.a`.\n    link_dynamic_variant_of(\"foo\")?;\n}","preventionTips":["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."],"tags":["lto","static-library","gcc","clang","linking"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}