Skip to content

feat(xcframework): --debug-symbols on top of the multi-crate framework fix - #4

Open
pblazej wants to merge 2 commits into
fix/multi-crate-frameworkfrom
blaze/dsyms-on-multi-crate
Open

pblazej wants to merge 2 commits into
fix/multi-crate-frameworkfrom
blaze/dsyms-on-multi-crate

Conversation

@pblazej

@pblazej pblazej commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Rebases the two feature/dsyms commits (14c9c20, f695194, previously #3) onto fix/multi-crate-framework (439269c, the rev livekit/rust-sdks pins) so a single rev carries both the multi-crate framework fix and --debug-symbols. Nothing else changes.

Tracking issue: livekit/client-sdk-swift#1149

Why

rust-sdks #1034 moved its pin from feature/dsyms to fix/multi-crate-framework, which never had --debug-symbols, so RustLiveKitUniFFI has shipped without dSYMs since. Repinning to this branch restores them without losing the multi-crate fix.

What

  • --debug-symbols on cargo swift package: lipo the per-arch .dSYMs rustc/dsymutil emit into one per xcframework slice and pass them to xcodebuild -create-xcframework -debug-symbols, so they land under <slice>/dSYMs/.
  • Rewrite the dSYM CFBundleIdentifier to the framework form so Xcode archives pick them up.
  • testing/end-to-end/debug-symbols.swift + matrix entry: asserts a .dSYM per slice with UUIDs matching the framework binary.

git log fix/multi-crate-framework..HEAD is exactly the two dSYM commits and the reverse range is empty, so this is a strict superset of the pin; the flag threads through run_for_crate, so multi-component packages get a dSYM per component. Verified via the e2e test locally and via livekit/rust-sdks#1525.

Adds a --debug-symbols flag to `cargo swift package`. When set,
cargo-swift locates the per-arch .dSYM Cargo emits at
target/<arch>/<mode>/deps/lib<name>.dylib.dSYM (requires the user's
Cargo profile to enable debug info — typically debug = "limited" +
split-debuginfo = "packed" on macOS), then for each xcframework
slice:

- single-arch slices reuse the per-arch dSYM,
- universal slices get a fresh dSYM whose DWARF Mach-O is the
  lipo-combined fat binary of the per-arch DWARFs (UUIDs preserved
  per arch).

The staged bundle is renamed to <framework_name>.framework.dSYM and
the inner DWARF binary is renamed to <framework_name> so xcodebuild's
-create-xcframework -debug-symbols drops it into <slice>/dSYMs/ with
the canonical name Xcode and App Store Connect expect.

E2E test (debug-symbols.swift) creates a cdylib project, enables
the dSYM-producing profile knobs, builds with --debug-symbols, then
asserts every slice has a dSYMs/<fw>.framework.dSYM bundle whose
UUIDs are a superset of the framework binary's UUIDs (so lldb can
symbolicate at runtime). Wired into the end-to-end.yml matrix.

If --debug-symbols is passed without dSYMs on disk, the build fails
with a clear error pointing at the profile knobs to enable, rather
than silently producing a symbol-less xcframework.
cargo's dsymutil emits the dSYM Info.plist with CFBundleIdentifier
"com.apple.xcode.dsym.<lib>.dylib" because it sees the raw .dylib
build artifact. Xcode's own archive-built frameworks land at
"com.apple.xcode.dsym.<framework_name>.framework", and crash-
reporter vendors (Sentry, Crashlytics, Bugsnag) match on that form.
Symbolication itself keys on Mach-O LC_UUID, so the identifier is
cosmetic — but it's a visible mismatch from what consumers expect.

Rewrite the staged Info.plist with plutil after copying the dSYM
bundle. plutil ships with every macOS install, no extra crate.

Extend debug-symbols.swift to assert both the new identifier and
CFBundlePackageType=dSYM.
pblazej added a commit to livekit/rust-sdks that referenced this pull request Oct 19, 2026
Restores embedded dSYMs in the published
`RustLiveKitUniFFI.xcframework`.

Tracking issue: livekit/client-sdk-swift#1149

## Why

#1034 moved the cargo-swift pin from `feature/dsyms` to
`fix/multi-crate-framework` for the multi-crate framework fix. That
branch never had `--debug-symbols`, so `${SWIFT_DSYMS_FLAG}` was dropped
from the `cargo swift package` call and every UniFFI release since has
shipped without dSYMs. The `CARGO_PROFILE_RELEASE_DEBUG=limited` /
`SPLIT_DEBUGINFO=packed` env was kept, so CI has been running dsymutil
and throwing the result away.

## What

- `livekit-uniffi/Makefile.toml`: bump the cargo-swift `--rev` to
`c92be034` (livekit/cargo-swift#4: `feature/dsyms` rebased onto
`fix/multi-crate-framework`, a strict superset of the current pin) and
pass `${SWIFT_DSYMS_FLAG}` again.
- `livekit-uniffi/Makefile.toml`: install cargo-swift with `cargo
install --rev` in the task script instead of cargo-make's
`install_crate`, whose `--help` probe accepts a stale cached binary;
`cargo install` compares the recorded source+rev, so an old rev is
reinstalled and a matching rev is a fast no-op (both paths verified
locally).
- `.changeset/uniffi_swift_dsyms.md`: `livekit-uniffi: patch`.

No workflow change: `swift-zip-xcframework` already zips the whole
xcframework, which now contains
`<slice>/dSYMs/RustLiveKitUniFFI.framework.dSYM`; Xcode archives pick
embedded dSYMs up automatically. The size gate measures the framework
binary only, so it is unaffected.

Verified locally (`cargo make --profile release swift-package`, macOS +
iOS): a dSYM per slice, UUIDs match the framework binaries, real Rust
DWARF. Zip grows ~3.3 MB per arch (~40 MB for all 11 archs); if that is
too big, the alternative is a separate `*.dSYMs.zip` release asset like
WebRTC.

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: omnigent <noreply@omnigent.ai>
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