Linking your embedded framework with other framework and don't link other framework with your app cause required code signature missing
when Build & Run on device.
Setup:
My setup is pretty simple (Swift 2.3 & Xcode Xcode 8.0; Build version 8S162m):
xcodebuild
8.0 and TOOLCHAINS=com.apple.dt.toolchain.Swift_2_3 carthage build --platform iOS
Problem:
Everything seems to work fine, until I Build & Run the app on the device. The app launched and than the process is aborted with the following Xcode error:
dyld: Library not loaded: @rpath/Other.framework/Other
Referenced from: /private/var/containers/Bundle/Application/DCF0331F-FF23-43CF-AE79-B3857D5A6EE3/MyApp.app/Frameworks/My.framework/My
Reason: no suitable image found. Did find:
/private/var/containers/Bundle/Application/DCF0331F-FF23-43CF-AE79-B3857D5A6EE3/MyApp.app/Frameworks/My.framework/Frameworks/Other.framework/Other: required code signature missing for '/private/var/containers/Bundle/Application/DCF0331F-FF23-43CF-AE79-B3857D5A6EE3/MyApp.app/Frameworks/My.framework/Frameworks/Other.framework/Other'
I have checked the signature of Other.framework and it looked OK to me. Moreover,
Solution (workaround)
Link MyApp with Other.framework. Horrible... This feels broken.
Linking the very same binary Other.framework to MyApp and solving the issue this way, points out, the Other.framework is built OK and able to be re-signed correctly. Possibly, nothing to do with Carthage.
NOTE: There is a similar problem iOS 8+ framework with nested embedded framework, however, mine has slightly other reason.
Discussing this issue on the Carthage github page, it's become clear that the workaround mentioned in the question, is actually an expected behaviour:
Carthage doesn't support nested frameworks.
Nesting frameworks doesn't let you reuse those frameworks. For instance, if
A.framework
andB.framework
both depend onOther.framework
, then neither of them can nestOther.framework
—otherwise you might end up with 2 different versions, and the correct one might not be chosen at runtime.The correct way to do this is to list it as a dependency, but link it into the app target.
Full discussion: Linking only embedded framework with other dynamic framework fails when build & run on device: "required code signature missing"
This was unclear from the README, so I raised another issue, requesting to update the documentation:
This is resolved and closed in the scope of the PR:
#1427 README upd: link dependencies from embedded frameworks to the app target