Skip to content

snmalloc-rs: keep LTCG library out of the rlib with build_cc on MSVC - #898

Merged
Matthew Parkinson (mjp41) merged 1 commit into
microsoft:mainfrom
ck0i:fix-msvc-build-cc-lto
Nov 8, 2026
Merged

Matthew Parkinson (mjp41) merged 1 commit into
microsoft:mainfrom
ck0i:fix-msvc-build-cc-lto

Conversation

@ck0i

Copy link
Copy Markdown
Contributor

Fixes #889

Root cause

With the build_cc and lto features on MSVC, snmalloc is compiled with /GL and cc bundles the static library into the snmalloc-sys rlib. rustc can't read symbols from LTCG objects (rust-lang/rust#26003), so the bundled copy exports nothing and the final link fails with LNK2019 on the sn_rust_* symbols. The CMake build doesn't run into this. It emits a plain rustc-link-lib line, the library isn't bundled, and link.exe gets the original .lib and restarts with /LTCG.

Fix

  • When lto is on with MSVC and the library is built with cc, set link_lib_modifier("-bundle") so the .lib goes to link.exe directly.
  • Skip the second rustc-link-lib line in main() for build_cc on MSVC, since rustc rejects a duplicate entry for the same library when one of them carries modifiers.
  • link_lib_modifier needs cc 1.0.74, so the minimum cc version is bumped to that.
  • Add a build_cc-lto entry (--features "build_cc lto") to the Rust CI matrix.

Testing

Windows 11, MSVC 14.51 (Visual Studio 2026), Rust 1.98.1, rebased on current main. cargo test --all in snmalloc-rs, debug and release.

  • Without the fix: with --features "build_cc lto", the snmalloc-rs lib tests and memory_stats fail to link with LNK2019 on sn_rust_* symbols such as sn_rust_statistics, in both debug and release.
  • With the fix: --features "build_cc lto" passes in debug and release, and so do the other feature sets in the CI matrix (default, debug, check, build_cc usecxx17, native-cpu, local_dynamic_tls, lto).

With build_cc and lto on MSVC the library is compiled with /GL and cc
bundles it into the snmalloc-sys rlib. rustc cannot read the symbol
table of LTCG objects, so the bundled copy exports nothing and the final
link fails with unresolved sn_rust_* symbols. Mark the library -bundle
so it is passed to link.exe directly, as the CMake build does, and skip
the duplicate link-lib line that rustc would reject.

Add a build_cc lto job to the Rust CI matrix.

Fixes microsoft#889

@mjp41 Matthew Parkinson (mjp41) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues block the MSVC LTO linking changes.

No open issues 🎉

What changed in this PR

Fixes #889 by keeping MSVC link-time-optimized native libraries outside the Rust archive when build_cc and lto are enabled, allowing the final linker to resolve the sn_rust_* symbols.

Changes:

  • Disables native-library bundling for this configuration and avoids duplicate MSVC link-library directives.
  • Raises the minimum cc version to 1.0.74 for link_lib_modifier support.
  • Adds build_cc with lto to the Rust CI matrix.
File Description
snmalloc-rs/​snmalloc-sys/​Cargo.toml Raises the minimum supported cc version.
snmalloc-rs/​snmalloc-sys/​build.rs Adjusts MSVC library bundling and link directives.
.github/​workflows/​rust.yml Adds CI coverage for combined build_cc and lto features.

Review effort: Balanced

@mjp41
Matthew Parkinson (mjp41) merged commit a1c7a13 into microsoft:main Nov 8, 2026
342 of 343 checks passed
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.

snmalloc-rs: build_cc + lto causes unresolved sn_rust_* symbols on MSVC

3 participants