Skip to content

fix(ios): re-signed Xcode debug builds crash at launch (unsigned .debug.dylib) - #433

Merged
gmegidish merged 1 commit into
mainfrom
fix/ios-resign-loose-dylibs
Sep 19, 2026
Merged

gmegidish merged 1 commit into
mainfrom
fix/ios-resign-loose-dylibs

Conversation

@gmegidish

@gmegidish gmegidish commented Sep 19, 2026

Copy link
Copy Markdown
Member

Summary

mobilecli apps install --force-resign broke every Xcode debug build. The app installed fine and then died at launch, straight back to the home screen:

Library not loaded: @rpath/Runner.debug.dylib
Reason: … code signature … not valid for use in process: mapped file has no cdhash,
completely unsigned? Code has to be at least ad-hoc signed.

Since Xcode 15 (ENABLE_DEBUG_DYLIB), debug builds keep the app's code in <Name>.debug.dylib next to a stub executable, plus __preview.dylib, in the bundle root. ResignIPA signed Frameworks/*.framework, Frameworks/*.dylib and PlugIns/*.appex|*.xctest, then the app bundle — and signing a bundle does not sign loose dylibs inside it.

signLooseDylibs now signs the .dylib files directly in a bundle's root before that bundle is signed (code is signed inside-out). It runs for the app and for each app extension, which get their own <Name>.debug.dylib.

Release and profile builds have no loose dylibs, so nothing changes for them.

Test plan

  • Unit tests for looseDylibs: finds only the root dylibs of a debug app layout (not Frameworks/, not an extension's), works on an .appex, empty for a release layout
  • go vet ./... && go test ./... -race
  • Real iPhone (iOS 26.5): Flutter debug build from flutter build ios --debug --no-codesign, codesign -dv Runner.debug.dylibcode object is not signed at all. Before: launch → SpringBoard + the crash report above. After: apps install --force-resign → app stays in the foreground (FlutterViewController), 0 new crash reports
  • Not covered: frameworks nested inside an app extension or inside another framework are still not walked

Summary by CodeRabbit

  • Bug Fixes

    • App bundles and extensions now correctly sign loose dynamic libraries before signing completes.
    • Improves signing reliability for debug and preview builds while preserving existing release-build behavior.
    • Signing failures now provide clearer context to help identify the affected app component.
  • Tests

    • Added coverage for dynamic libraries in app bundles and extensions, including verification that nested framework libraries are handled separately.

`apps install --force-resign` signed Frameworks/ and PlugIns/ but not dylibs in
a bundle's root. Xcode debug builds keep the app's code there
(<Name>.debug.dylib next to a stub executable, plus __preview.dylib), and
signing the bundle does not sign them, so every re-signed debug build died at
launch:

  Library not loaded: @rpath/Runner.debug.dylib ... mapped file has no cdhash,
  completely unsigned? Code has to be at least ad-hoc signed.

Sign them before the bundle that contains them, for the app and for each app
extension.
@coderabbitai

coderabbitai Bot commented Sep 19, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: mobile-next/mobilecli/.coderabbit.yaml

Review profile: CHILL

Plan: Essentials

Run ID: 89b66718-54bd-4741-837b-3b85f3608eae

📥 Commits

Reviewing files that changed from the base of the PR and between 3683dbb and 754e6c6.

📒 Files selected for processing (2)
  • utils/resign.go
  • utils/resign_test.go

Included review availability: 2 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour.


📝 Walkthrough

Walkthrough

ResignIPA now discovers and signs root-level .dylib files in app extensions, XCTest bundles, and the main app before signing each bundle. Tests cover debug, extension, nested framework, and release layouts.

Changes

Loose dylib signing

Layer / File(s) Summary
Dylib discovery and signing
utils/resign.go
looseDylibs finds root-level .dylib files. signLooseDylibs signs them without entitlements. App, extension, and XCTest signing propagates discovery and signing errors.
Dylib discovery coverage
utils/resign_test.go
Tests cover Xcode debug app roots, app-extension dylibs, exclusion of nested framework dylibs, and empty results for release builds.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant ResignIPA
  participant looseDylibs
  participant signLooseDylibs
  ResignIPA->>looseDylibs: discover root-level .dylib files
  looseDylibs-->>ResignIPA: return dylib paths
  ResignIPA->>signLooseDylibs: sign dylibs without entitlements
  signLooseDylibs-->>ResignIPA: return result
  ResignIPA->>ResignIPA: sign the app or extension bundle
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the iOS fix for Xcode debug builds that crash at launch because an unsigned .debug.dylib is present. It accurately summarizes the main change.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@gmegidish
gmegidish merged commit f712a21 into main Sep 19, 2026
17 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.

1 participant