build: pin rust 1.98.1 so macOS 27 loads our stripped dylibs - #3904
Conversation
82e8d23 to
fc2b259
Compare
8f3fca8 to
4c880b1
Compare
|
No issues found. |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: Your plan provides up to 4 included reviews per hour; 0 remain after this review. WalkthroughThe build toolchain is updated from Rust 1.95.0 to 1.98.1 in Priority: ➖ Normal Severity of issue fixed: Medium Merge Risk: ⚪ Minimal · up to The pinned toolchain and targeted lint/test updates do not show an actionable merge-blocking risk. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Cargo passes `-C strip=debuginfo` by default in the release profile, and
below 1.98 rustc strips Mach-O with an llvm-objcopy that writes the symbol
string table straight after the 4-byte-per-entry indirect symbol table with
no padding. Whenever that table has an odd entry count the LINKEDIT string
pool lands 4-byte aligned, and macOS 27's dyld refuses to load the image:
rustc 1.95 -> stroff=345252 stroff%8=4 (rejected)
rustc 1.98 -> stroff=328880 stroff%8=0
Every release-profile proc macro is a coin flip, which is what breaks the
macOS OBS plugin build (rustc can't dlopen a derive macro), and so is every
cdylib we ship there: moq-ffi behind the Python/Kotlin/Dart bindings, and
the moq-gst plugin.
Fixed upstream in 1.98.0 by rust-lang/rust#158410, so the build toolchain
pin moves above the relay's 1.95 MSRV. The crates keep their own floors.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
320fe74 to
63f3893
Compare
|
No issues found. |
|
No issues found. |
|
Merged current Why: the branch predated #3898 (merged), which fixed the moq-gst flake Result: the diff against CI on (Written by DeepSeek V4.1 Flash) |



The bug
A contributor could not build the OBS plugin on macOS 27: the build failed with
mis-aligned LINKEDIT string pool. Their workaround was a[profile.release.build-override]block, which works but only covers build scripts and proc macros.The root cause is upstream. Cargo passes
-C strip=debuginfoby default in the release profile, and below 1.98 rustc strips Mach-O with an llvm-objcopy that writes the symbol string table straight after the 4-byte-per-entry indirect symbol table with no padding. Whenever that table has an odd entry count,LC_SYMTAB.strofflands 4-byte aligned, and macOS 27's dyld refuses the image. Reproduced on a stock proc-macro crate:That is rust-lang/rust#157750, fixed in 1.98.0 by rust-lang/rust#158410 (an LLVM bump).
Why the pin moves, rather than a profile hack
Every release-profile proc macro is a coin flip, which is what breaks the macOS plugin build: rustc cannot dlopen a derive macro, so the crate using it fails to compile. But so is every release cdylib we ship there, which
build-overridedoes not touch:rs/moq-ffi's cdylib, loaded at runtime by the Python, Kotlin, and Dart bindingsrs/moq-gst's plugin, dlopen'd by GStreamerrs/libmoqis a staticlib, so the OBS plugin itself links fine once the build gets that far.The pin therefore sits above the relay's 1.95 MSRV for a reason of its own. Crate
rust-versionfloors are unchanged: libraries stay at 1.91,moq-relayandmoq-cliat 1.95. The rust-overlay inflake.lockalready serves 1.98.1, so no flake update is needed.Lint attributes
Two 1.98 lints have no fix, so they carry an
#[expect]. They could not ride along with #3899 because on 1.95manual_noop_wakeris an unknown lint andresult_large_errdoes not fire, so both attributes would warn on the old pin.kio'spark_retires_a_waiter_for_another_taskbuilds two no-op wakers that must be distinct. Clippy suggestsWaker::noop(), which is a singleton, so taking the suggestion would make both wakers name the same task and the assertion would pass without testing anything.axum::response::Result, whoseErris axum's ownErrorResponse. There is nothing on our side to box.The
as_chunksrewrites the same lint pass required landed separately in #3899.Public API and wire impact
None. No exported signature, catalog field, or wire format moves. The only consumer-visible change is the toolchain a source build needs, which
rust-toolchain.tomlpins for them.Testing
On 1.98.1:
cargo clippy --locked --all-targets -- -D warnings,cargo fmt --all --check, andRUSTDOCFLAGS="-D warnings" cargo docare all clean, andnix developresolves 1.98.1 without a lock change. Linux CICheckpassed on the previous push.Note for reviewers: this PR touches the root manifest, so the diff-scoped
just testselects the whole workspace rather than the usual handful of crates, and the run above is 4848 tests rather than the couple of thousand a typical PR selects.On an earlier push that selection surfaced a failure in
moq_gst::a_subscription_resolving_after_cancellation_creates_no_pad, which passed on the clean re-run here. It looks like a latent race in the test rather than anything this PR does: the test clears the catalog to cancel a pump and then immediately accepts the request, with nothing ordering the cancellation first, and its 500ms sleep falls after the accept. It also passes 30+ consecutive local runs on 1.98 including under parallelism. Worth tightening on its own, since a moq-gst suite is rarely selected by PR CI and the race can sit unexercised.(Written by claude-opus-5)
🤖 Generated with Claude Code