Skip to content

Comments

cpp_build: disable LTO to preserve metadata in .data section#116

Open
okhsunrog wants to merge 1 commit intomystor:masterfrom
okhsunrog:fix/disable-lto-for-metadata
Open

cpp_build: disable LTO to preserve metadata in .data section#116
okhsunrog wants to merge 1 commit intomystor:masterfrom
okhsunrog:fix/disable-lto-for-metadata

Conversation

@okhsunrog
Copy link

Summary

  • Fix proc-macro panic "Struct metadata not present in target library file" when building with LTO enabled

Problem

The cpp crate communicates type metadata (sizes, alignments, trait flags) from cpp_build to cpp_macros by embedding a struct with a magic byte pattern in the .data section of the compiled static library. The proc-macro scans the .a file for this pattern using aho_corasick.

When LTO is enabled via environment CXXFLAGS (e.g. -flto=auto), the C++ compiler emits GIMPLE intermediate representation instead of native machine code. The .data section is empty — all content lives in .gnu.lto_* sections. The magic bytes become invisible to the byte-level scan, causing the proc-macro to panic:

-- rust-cpp fatal error --

Struct metadata not present in target library file.
NOTE: Double-check that the version of cpp_build and cpp_macros match

This affects distributions that enable LTO by default in their build systems:

  • Arch Linux (makepkg sets -flto=auto via CXXFLAGS)
  • Fedora (LTO enabled by default since F33)
  • Gentoo (with LTO profiles)

Currently broken downstream packages include LibrePCB (via qttypes/Slint) and anything else using the cpp crate.

Fix

Pass -fno-lto when compiling the generated C++ library, ensuring the metadata struct is always present as raw bytes in .data regardless of environment LTO settings.

Test plan

  • Verified that LibrePCB builds successfully on Arch Linux with this fix (previously failed with 697 errors from qttypes proc-macro panics)
  • Existing tests should continue to pass since -fno-lto only affects the small generated metadata library, not the final binary linkage

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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant