{"id":"e7ec1d37c646bb5a","repo":"rust-lang/rust","slug":"llvm-bitcode-object-in-c-static-library-lto-not-s","errorCode":null,"errorMessage":"LLVM bitcode object in C static library (LTO not supported)","messagePattern":"LLVM bitcode object in C static library \\(LTO not supported\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_codegen_ssa/src/back/link.rs","lineNumber":2813,"sourceCode":"    out: &mut Vec<SymbolExport>,\n) -> io::Result<()> {\n    let file_path = find_native_static_library(lib.name.as_str(), lib.verbatim, sess);\n\n    let archive_map = unsafe { Mmap::map(File::open(&file_path)?)? };\n\n    let archive = object::read::archive::ArchiveFile::parse(&*archive_map)\n        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;\n\n    for member in archive.members() {\n        let member = member.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;\n\n        let data = member\n            .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","sourceCodeStart":2795,"sourceCodeEnd":2831,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_codegen_ssa/src/back/link.rs#L2795-L2831","documentation":"Returned by add_c_staticlib_symbols when scanning a native C static library (.a) to collect exported symbols and it encounters an archive member whose first bytes are the raw LLVM bitcode magic (BC 0xC0 0xDE). This means the .a was built with clang -flto, so its members are bitcode rather than machine object files. Rust's symbol-collector cannot parse bitcode and cannot feed such objects to the native linker for LTO, so it refuses the library.","triggerScenarios":"Linking a C/C++ static library compiled with `clang -flto` (or `-flto=thin`) into a Rust crate via #[link(name=...)] / -L native search. The member object is raw LLVM bitcode rather than a relocatable .o.","commonSituations":"A system or vendored C library shipped pre-built with LTO enabled (common in some distro packages). A build.rs or Makefile that adds -flto to CFLAGS for the C dependency. Mixing a clang-LTO-built C lib into a Rust project that does not use matching LLVM LTO.","solutions":["Rebuild the C static library without -flto (plain relocatable objects) and link that instead.","If you need LTO across the C code, use the same Clang/LLVM toolchain and enable Rust-side -Clinker-plugin-lto so the linker handles bitcode, rather than passing the .a as a plain native lib.","Vendor a non-LTO build of the dependency (e.g. via a build script that compiles sources with cc::Build without lto)."],"exampleFix":"# before: C lib built with LTO\nclang -flto -c lib.c -o lib.o && ar rcs libfoo.a lib.o\n# after: relocatable objects, no LTO\nclang -c lib.c -o lib.o && ar rcs libfoo.a lib.o","handlingStrategy":"fallback","validationCode":"use std::process::Command;\n\n// Returns true if the static archive embeds LLVM bitcode sections.\nfn archive_contains_llvm_bitcode(path: &str) -> bool {\n    // Bitcode magic: 'BC' 0xC0 0xDE, or a wrapped __bitcode section.\n    let out = Command::new(\"nm\").args([path]).output();\n    match out {\n        Ok(o) => String::from_utf8_lossy(&o.stdout)\n            .lines()\n            .any(|l| l.contains(\"BC\") || l.contains(\"__bitcode\") || l.contains(\"__llvmbc\")),\n        Err(_) => false,\n    }\n}\n\n// caller: if archive_contains_llvm_bitcode(\"libfoo.a\") { rebuild_without_lto()?; }","typeGuard":"fn is_machine_code_only_archive(path: &str) -> bool {\n    !archive_contains_llvm_bitcode(path)\n}","tryCatchPattern":"let stderr = String::from_utf8_lossy(&output.stderr);\nif stderr.contains(\"LLVM bitcode object in C static library\") {\n    // Fallback: rebuild the C lib without -flto, then relink.\n    rebuild_c_lib_no_lto()?;\n    return retry_link();\n}","preventionTips":["Build C/C++ dependencies with machine code, not `-emit-llvm`/`-flto=thin` bitcode, when shipping a `.a`.","Ship two artifacts: a bitcode variant for LTO consumers and a plain `.a` for normal links.","Detect bitcode magic (`BC\\xC0\\xDE`) or `__bitcode` sections before adding the lib to `cargo:rustc-link-lib=static`."],"tags":["lto","static-library","clang","linking","bitcode"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}