Carthage: Linking only embedded framework with other dynamic framework fails when build & run on device: "required code signature missing"

Created on 22 Jul 2016  路  17Comments  路  Source: Carthage/Carthage

  • carthage version: 0.17.2
  • xcodebuild -version: Xcode 8.0; Build version 8S162m
  • Are you using --no-build? YES, but just because I build the framework with Swift 2.3 toolchain
  • Are you using --no-use-binaries? NO
  • Are you using --use-submodules? NO

Cartfile

github "johnsundell/unbox" ~> 1.8 #this is my Other.framework

Carthage Output


Setup:

My setup is pretty simple (Swift 2.3 & Xcode 8B2):

  • Using Carthage I have build Other.framework
  • MyApp has embeded My.framework framework.
  • The app and framework projects are under one Xcode workspace.
  • I hade linked Other.framework to My.framework ONLY (that means, MyApp is not linked to Other.framework at all). The point here is that, MyApp does not need to use Other.framework API.

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,

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.

Most helpful comment

@evgeniyd Today I came across the same problem and solved it by recursively code-signing all frameworks embedded in my app (including the nested ones).

Basically, I added the following script to my app build phases:

for f in $(find $CODESIGNING_FOLDER_PATH -name '*.framework')
do
    codesign --force --sign "${CODE_SIGN_IDENTITY}" --preserve-metadata=identifier,entitlements --timestamp=none "$f"
done

I'm afraid that @mdiep is right about the frameworks being non-reusable with this setup. However, in my case, I can't have a proper Carthage setup as long as the only supported origins are GitHub/Git repositories.

All 17 comments

Seems related to #1394

MyApp.app/Frameworks/My.framework/Frameworks/Other.framework/Other

Carthage doesn't support nested frameworks.

Nesting frameworks doesn't let you reuse those frameworks. For instance, if A.framework and B.framework both depend on Other.framework, then neither of them can nest Other.framework鈥攐therwise 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.

Hi, thank you very much for feedback.

The correct way to do this is to list it as a dependency, but link it into the app target.

Could you please clarify what do you mean by "list it as a dependency"? Does it mean, I don't have to link embedded framework (My.framework) with Other.framework in My.framework build settings?

So far, I repeated the procedure of adding Other.framework to My.framework as I did for the app target (linking and Carthage copy-framework).

This is spelled out in the documentation. If that's not clear, please raise specific questions so we can improve the documentation. Thanks!

I got it. Thanks again.

There is a separate issue #1427 suggesting to mention this type of setup in README.

@evgeniyd Today I came across the same problem and solved it by recursively code-signing all frameworks embedded in my app (including the nested ones).

Basically, I added the following script to my app build phases:

for f in $(find $CODESIGNING_FOLDER_PATH -name '*.framework')
do
    codesign --force --sign "${CODE_SIGN_IDENTITY}" --preserve-metadata=identifier,entitlements --timestamp=none "$f"
done

I'm afraid that @mdiep is right about the frameworks being non-reusable with this setup. However, in my case, I can't have a proper Carthage setup as long as the only supported origins are GitHub/Git repositories.

@bejo You might be interested in the --deep command line argument to codesign

Also, what do you mean by "I have checked the signature of Other.framework and it looked OK to me"? Can you please be a bit more specific? What is the output of:

codesign -vvv /path/to/MyApp.app
codesign -vvv /path/to/MyApp.app/Frameworks/My.framework/Frameworks/Other.framework

hi @jeremyhu thank you for your feedback!

Unfortunatelly, I cannot check the signature now once again via the commands you provided. And I cannot remember the exact output of these commands when I first encountered the issue.

I will post the output as soon as possible.

I have the same problem with SocketRocket framework since a full day and i don't find a solution...

My app use a A.framework imported in the workspace by adding the .xcodeproj to modify this A.framework while working with my app. A.framework need SocketRocket.framework.

There is no problem on simulator but on the device it say code signature missing exaclty like in this issue.

What i have do in A.framework:

  • SoketRocket.framework is in targets->general->linked frameworks and libraries
  • SoketRocket.framework is in targets->Build phases->link Binary with libraries
  • A run script with copy-framework for SocketRocket.framework

What i have do in my app:

  • A.framework is in targets->general->Embedded binaries and linked frameworks and libraries
  • A.framework is in targets->Build phases->Target dependencies
  • A.framework is in targets->Build phases->link Binary with libraries
  • A.framework is in targets->Build phases->Embed Frameworks
  • A run script with copy-framework for A.framework

If i add the bejo's script and uncheck the Code sign on copy it run on the device.

But i now get a Itunes connect error when i try to submit the app, it say "contains disallowed nested bundles". Some post on stackoverflow say to remove the framework from embed section but then the framework image is not found.

Can someone make a clear answer to help me (i have read the doc and all other related issues) ?

Finnaly get it working !
If it can help other, here is what i do, it's very simple, no need to use the script.

What i have do in A.framework:

  • SoketRocket.framework is in targets->general->linked frameworks and libraries
  • SoketRocket.framework is in targets->Build phases->link Binary with libraries

What i have do in my app:

  • A.framework is in targets->general->Embedded binaries and linked frameworks and libraries
  • SocketRocket.framework in targets->general->linked frameworks and libraries dropped from my app carthage folder
  • A.framework is in targets->Build phases->Target dependencies
  • A.framework is in targets->Build phases->link Binary with libraries
  • A.framework is in targets->Build phases->Embed Frameworks
  • A run script with copy-framework for A.framework (with now a extra line SocketRocket.framework, my app don't use it directly but it's in the app package now and well signed)

The weird thing is that i have to build SocketRocket in both A.framework and in my app. That can result in some problem if they don't use the same version (maybe ?). At least it works and the build is send to the Apple store.

If someone has a better solution...

@linked67 your solution looks quite close to what mine (which is a year-old now). However, I linked the frameworks (e.g. Other.framework) to both, my A.framework and my application target. This worked. See my project with this setup.

@evgeniyd I agreed. But doesn't it looks bad, that if an App includes 4 frameworks and those 4 frameworks includes another 2 framework each. Than App has to include these 4 + 8 others dependencies.
If someone have better solution please tell..As I dont want my App to know and tell all these steps to import my framework..

@evgeniyd Your solution helped me. Thanks for sharing your project setup!

I also encountered the problem 'contains disallowed nested' and 'code signature missing' because use nested dependencies.

My incorrect example:

    App
            # use copy-frameworks script for MyLib and AFNetworking
            MyLib.framework
                    # use copy-frameworks script for AFNetworking
                    AFNetworking.framework

The problem is the copy-frameworks script in MyLib.framework. It will copy AFNetworking.framework to MyLib.framework/Frameworks/ when you run carthage build in App, It will cause that app store report 'contains disallowed nested'. So I need remove the copy-frameworks script in MyLib.framework.

The finally correct example:

        App
            # use copy-frameworks script for MyLib and AFNetworking
            MyLib.framework //Linked Frameworks
                    AFNetworking.framework


    MyLibExample
            # use copy-frameworks script for AFNetworking
            MyLib.framework # Embeded Binaries
                    AFNetworking.framework

@mdiep your explanation helped in my case, thanks.
Key things are:

Carthage doesn't support nested frameworks.
The correct way to do this is to list it as a dependency, but link it into the app target.

Was this page helpful?
0 / 5 - 0 ratings