Skip to content

feat(xcframework): embed .dSYM bundles via --debug-symbols#103

Open
pblazej wants to merge 2 commits into
antoniusnaumann:mainfrom
livekit:feature/dsyms
Open

feat(xcframework): embed .dSYM bundles via --debug-symbols#103
pblazej wants to merge 2 commits into
antoniusnaumann:mainfrom
livekit:feature/dsyms

Conversation

@pblazej

@pblazej pblazej commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a --debug-symbols flag to cargo swift package that embeds .dSYM bundles into the
generated xcframework, so crash reports against a release (stripped) dynamic framework can be
symbolicated.

  • Per-slice dSYMs. Single-arch slices reuse the per-arch .dSYM Cargo emits; universal
    slices get a fresh .dSYM whose DWARF Mach-O is the lipo-combined fat binary of the
    per-arch DWARFs (per-arch UUIDs preserved). Each is renamed to <framework>.framework.dSYM
    so xcodebuild -create-xcframework -debug-symbols drops it into <slice>/dSYMs/ under the
    name Xcode and App Store Connect expect.
  • Canonical bundle identifier. Rewrites the staged dSYM Info.plist CFBundleIdentifier
    from dsymutil's com.apple.xcode.dsym.<lib>.dylib to the …<framework>.framework form that
    Xcode-built frameworks use and crash-reporter vendors (Sentry, Crashlytics, Bugsnag) match
    on. Done with plutil (ships with macOS, no new crate).

Requires the consuming Cargo profile to actually emit debug info (e.g. debug = "limited" +
split-debuginfo = "packed" on macOS).

Testing

New testing/end-to-end/debug-symbols.swift, wired into the end-to-end.yml matrix: builds a
cdylib with the dSYM-producing profile knobs and --debug-symbols, then asserts every slice
has a dSYMs/<fw>.framework.dSYM whose UUIDs are a superset of the framework binary's UUIDs
(so lldb can symbolicate at runtime), plus the rewritten identifier and
CFBundlePackageType=dSYM.

pblazej added 2 commits June 26, 2026 11:07
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.
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