Skip to content

apple: ship dSYMs and preserve macOS framework structure#614

Open
powerworr wants to merge 1 commit into
cactus-compute:mainfrom
powerworr:fix/apple-xcframework-dsyms-and-structure
Open

apple: ship dSYMs and preserve macOS framework structure#614
powerworr wants to merge 1 commit into
cactus-compute:mainfrom
powerworr:fix/apple-xcframework-dsyms-and-structure

Conversation

@powerworr
Copy link
Copy Markdown

Summary

Two distinct bugs in apple/build.sh cause App Store / TestFlight distribution to fail or warn when the cactus xcframeworks are embedded into a Mac app archive. Both are root-caused and fixed in this PR.

Bug 1 — Malformed macOS framework bundle (blocks archive)

build_framework copies the cmake-built framework with cp -R. On macOS, cmake's Xcode generator produces a proper bundle layout:

cactus.framework/
├── cactus            -> Versions/Current/cactus    (symlink)
├── Resources         -> Versions/Current/Resources (symlink)
└── Versions/
    ├── Current       -> A                          (symlink)
    └── A/
        ├── cactus
        └── Resources/

cp -R resolves symlinks, so the destination ends up with two real binaries — one at the top level and one inside Versions/A/. Apple's archive validator rejects this with:

Multiple binaries share the same codesign path:
/Applications/.app/Contents/Frameworks/cactus.framework/Versions/Current
Binaries:
.../Versions/Current/cactus
.../cactus
This can happen if your build process copies frameworks by following symlinks.

Fix: switch to ditto, which is bundle-aware on macOS and preserves the symlink layout intact. cp_headers was also writing top-level Headers/ regardless of platform; updated it to write Versions/A/Headers and create the top-level symlink on macOS while keeping iOS's flat layout.

Bug 2 — No dSYMs in the xcframeworks (warnings, unsymbolicated crashes)

cmake's Xcode generator defaults DEBUG_INFORMATION_FORMAT to dwarf for Release configurations. The shipped binary is stripped of debug info — confirmed via dwarfdump --uuid + dsymutil (warning: no debug symbols in executable). Consumers see two warnings during App Store upload:

Upload Symbols Failed
The archive did not include a dSYM for the cactus with the UUIDs [...].
Ensure that the archive's dSYM folder includes a DWARF file for cactus with the expected UUIDs.

Crash reports inside cactus frames also show unsymbolicated hex addresses.

Fix:

  • Add -DCMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT=dwarf-with-dsym so cmake emits cactus.framework.dSYM next to each built framework.
  • Copy the resulting .dSYM into each xcframework slice under <slice>/dSYMs/cactus.framework.dSYM/.
  • Declare DebugSymbolsPath in the xcframework Info.plist for every AvailableLibraries entry. Without this key, xcodebuild ignores dSYMs sitting in the xcframework even when present.

Resulting xcframework layout

cactus-macos.xcframework/
├── Info.plist          # AvailableLibraries[].DebugSymbolsPath = "dSYMs"
└── macos-arm64/
    ├── cactus.framework/   # proper symlinks preserved by ditto
    └── dSYMs/
        └── cactus.framework.dSYM/

Test plan

  • Run bash apple/build.sh on macOS arm64 with Xcode + cmake installed
  • Verify cactus-macos.xcframework/macos-arm64/cactus.framework/Versions/Current is a symlink to A
  • Verify cactus-macos.xcframework/macos-arm64/dSYMs/cactus.framework.dSYM/ exists and contains DWARF data
  • Embed the xcframework in a sample Mac app, archive, and confirm App Store validation passes (no "Multiple binaries share the same codesign path" error, no "Upload Symbols Failed" warnings for cactus)
  • Same checks against cactus-ios.xcframework for an iOS app

Notes

  • I have not been able to test the build end-to-end locally (would need full cmake + vendored libcurl setup). The shell changes are bash-syntax-clean and the cmake/Info.plist patterns are standard. Happy to iterate if CI surfaces anything.
  • The published cactus Flutter package on pub.dev also bundles a separate cactus_util.xcframework with the same structural bug. That binary is built somewhere outside this repo (I couldn't locate the source) — if the same patterns can be applied to wherever it's built, that would resolve the issue end-to-end for Flutter consumers.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings April 28, 2026 18:42
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes Apple distribution issues for the generated cactus XCFrameworks by ensuring macOS framework bundles retain their symlinked Versions/ structure and by shipping/declaring dSYMs so Xcode/App Store tooling can find debug symbols.

Changes:

  • Preserve macOS framework bundle structure by copying frameworks with ditto (instead of cp -R, which resolves symlinks).
  • Adjust header placement to respect versioned framework layouts (Versions/A/Headers + top-level Headers symlink when applicable).
  • Emit, bundle, and declare dSYMs in XCFramework slices (CMake Xcode attribute + copying .dSYM into dSYMs/ + DebugSymbolsPath in Info.plist).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Two issues caused App Store distribution warnings/errors when the
cactus xcframeworks were embedded into a Mac app archive.

1. Malformed macOS framework bundle. `cp -R` follows symlinks, so it
   flattened cmake's properly-symlinked Versions/A layout into duplicate
   real files at both the top level and inside Versions/A. Apple's
   archive validator rejects this with: "Multiple binaries share the
   same codesign path". Switched to `ditto`, which preserves bundles
   correctly. `cp_headers` now writes to Versions/A/Headers on macOS
   and adds the matching top-level Headers symlink when missing; iOS
   continues to use the flat layout.

2. No dSYMs. cmake's Xcode generator defaults DEBUG_INFORMATION_FORMAT
   to `dwarf` for Release, so the binary ships stripped of debug info.
   This produces "Upload Symbols Failed: archive did not include a
   dSYM" warnings and unsymbolicated crash reports for cactus frames.
   Added DEBUG_INFORMATION_FORMAT=dwarf-with-dsym, copy the resulting
   .dSYM next to the framework inside each xcframework slice, and
   declare DebugSymbolsPath in the xcframework Info.plist so xcodebuild
   recognizes the dSYM bundle.

The Info.plist change is required: without DebugSymbolsPath, Xcode
ignores any dSYMs sitting in the xcframework even if they're present.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: viktorstojanov <powerworr@gmail.com>
@HenryNdubuaku
Copy link
Copy Markdown
Collaborator

@powerworr thanks for this! Just cleanup the comments in your code and I'll merge

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.

3 participants