Skip to content

Commit 33dc207

Browse files
committed
bazel: switch rust LTO from fat to thin
Fixes the `--config=lto` / `--config=pgo-instrument` link, which started failing with the wasmtime 42 upgrade (rust 1.91) with errors like: ld.lld: error: undefined symbol: __rustc::__rust_no_alloc_shim_is_unstable_v2 The empty `allocator_library` staticlib used by rules_rust's `experimental_use_allocator_libraries_with_mangled_symbols` exists only so rustc auto-injects the `__rustc::__rust_*` allocator shims with GLOBAL binding, satisfying the rust stdlib's GLOBAL undefined refs to those symbols. Under fat LTO, rustc runs LLVM's Internalize pass over the staticlib before emitting it; nothing inside the empty crate references the shims, so they get downgraded GLOBAL -> LOCAL and ELF then refuses to bind the stdlib's GLOBAL refs to LOCAL defs across object files. Thin LTO doesn't run that whole-crate internalization, so the symbols stay GLOBAL and the link succeeds. No measurable cost: with --config=pgo-instrument the resulting //:redpanda binary is bit-identical (md5) before and after this change. Every wasmtime crate is a `rust_library` (rlib), and for rlibs rules_rust emits `-Clinker-plugin-lto` regardless of the -Clto mode, so the rlib bitcode is the same either way -- the actual cross-language LTO happens later at the C++ thin-LTO link step.
1 parent 38d10c2 commit 33dc207

1 file changed

Lines changed: 16 additions & 1 deletion

File tree

.bazelrc

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,22 @@ build:san-all --linkopt=-fsanitize=address,undefined,vptr,function,alignment
149149
# PGO + release, but should work with any.
150150
build:lto --copt -flto=thin
151151
build:lto --linkopt -flto=thin
152-
build:lto --@rules_rust//rust/settings:lto=fat
152+
# Use thin LTO for Rust to match the C++ side. With fat LTO, rustc's
153+
# LLVM Internalize pass downgrades the auto-injected `__rustc::*`
154+
# allocator shim symbols from GLOBAL to LOCAL binding when emitting the
155+
# empty staticlib provided by rules_rust's
156+
# `experimental_use_allocator_libraries_with_mangled_symbols`. Nothing
157+
# inside the empty crate references those symbols, so LTO assumes
158+
# they're internal. The rust stdlib rlibs still emit GLOBAL undefined
159+
# refs to them, and ELF won't bind a GLOBAL ref to a LOCAL def across
160+
# object files, so the cc_binary link fails with:
161+
# ld.lld: error: undefined symbol: __rustc::__rust_no_alloc_shim_is_unstable_v2
162+
# Thin LTO doesn't run Internalize across the crate the way fat LTO
163+
# does, so the symbols stay GLOBAL and the link succeeds. We don't
164+
# lose any wasm performance: every wasmtime crate is an rlib (rules_rust
165+
# emits `-Clinker-plugin-lto` regardless of -Clto mode) and the actual
166+
# cross-language LTO happens at the C++ link step, which is thin too.
167+
build:lto --@rules_rust//rust/settings:lto=thin
153168
build:lto --@rules_rust//rust/settings:extra_rustc_flag=-Ccodegen-units=1
154169
# I've seen others claim these flags help with LTO and the final binary, but these also
155170
# require a specific version of clang and I don't really want to tie rustc version with

0 commit comments

Comments
 (0)