From 3808030d98dd983e24e5449dc856c421af16ef43 Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Sun, 22 Feb 2026 18:34:22 +0300 Subject: [PATCH] cpp_build: disable LTO to preserve metadata in .data section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cpp crate communicates type metadata (sizes, alignments, trait flags) from the build script to the proc-macro by embedding a struct with a magic byte pattern in the .data section of the compiled static library. The proc-macro then scans the .a file for this pattern using aho-corasick. When LTO is enabled via environment CXXFLAGS (e.g. -flto=auto, as is the default on Arch Linux's makepkg), the C++ compiler emits GIMPLE intermediate representation instead of native machine code. This leaves the .data and .text sections empty — all content lives in .gnu.lto_* sections as serialized IR. The magic bytes are no longer visible to the byte-level scan, causing the proc-macro to panic with: "Struct metadata not present in target library file." Fix this by passing -fno-lto when compiling the generated C++ library. This ensures the metadata struct is always present as raw bytes in .data, regardless of the environment's LTO settings. Fixes builds on distributions that enable LTO by default (Arch Linux, Fedora, Gentoo with LTO profiles). --- cpp_build/src/lib.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cpp_build/src/lib.rs b/cpp_build/src/lib.rs index 299290b..e4f6e40 100644 --- a/cpp_build/src/lib.rs +++ b/cpp_build/src/lib.rs @@ -654,6 +654,15 @@ In order to provide a better error message, the build script will exit successfu if !self.std_flag_set { self.cc.flag_if_supported("-std=c++11"); } + // Disable LTO for the generated C++ library. The cpp crate embeds + // metadata as raw bytes in the .data section of the compiled object, + // which the cpp_macros proc-macro later locates via byte pattern + // matching. When LTO is enabled (e.g. -flto=auto from environment + // CXXFLAGS), the compiler emits GIMPLE IR instead of native code, + // leaving the .data section empty and making the metadata invisible + // to the proc-macro. + self.cc.flag_if_supported("-fno-lto"); + // Build the C++ library if let Err(e) = self.cc.file(filename).try_compile(LIB_NAME) { let _ = writeln!(std::io::stderr(), "\n\nerror occurred: {}\n\n", e);