Cocoapods: No 'Embed Pods frameworks' build phase when building custom framework ?

Created on 2 Nov 2016  路  23Comments  路  Source: CocoaPods/CocoaPods

Report

I use CocoaPods in a project where we separate core material from app material.
Inside our workspace there are 3 projects (not counting Pods project), one for the core, and 2 others, one for the iOS version and another macOS version of the app.

The core project builds a framework which as dependencies. Those dependencies should be copied into a folder named Frameworks, but are not.
Indeed, there is no 'Embed Pods Frameworks' build phase for the core framework target.
(There is one however for the core framework test target).

Everything builds fine, but when I launch the app, the loader complains it can't load frameworks :

dyld: Library not loaded: @rpath/Alamofire.framework/Versions/A/Alamofire
  Referenced from: /Users/vince/Library/Developer/Xcode/DerivedData/App-ggigklukffxidydygewgkvwmfwbl/Build/Products/Debug/AppCore.framework/Versions/A/AppCore
  Reason: image not found

I'm looking for a way to copy those dependencies inside the framework bundle.

What did you do?

Run pod install inside the directory where the Podfile file is.
Open the workspace, build and run the macOS target (same crash for iOS)

If I copy the script inside the 'Embed Pods Frameworks' build phase for the tests target, into a new script build phase for the core framework, it does work (dependencies are copied, no loading error).

What did you expect to happen?

I expected the app to run, without error.

What happened instead?

The loader cannot locate and load a framework dependency inside my core framework.

CocoaPods Environment

Stack

   CocoaPods : 1.1.1
        Ruby : ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14]
    RubyGems : 2.4.8
        Host : Mac OS X 10.12.1 (16B2555)
       Xcode : 8.1 (8B62)
         Git : git version 2.9.3 (Apple Git-75)
Ruby lib dir : /Users/vince/.rvm/rubies/ruby-2.2.2/lib
Repositories : master - https://github.com/CocoaPods/Specs.git @ d006285cac32ca0ec77dafe98114de840ace76a3

Installation Source

Executable Path: /Users/vince/.rvm/gems/ruby-2.2.2/bin/pod

Plugins

cocoapods-deintegrate : 1.0.1
cocoapods-plugins     : 1.0.0
cocoapods-search      : 1.0.0
cocoapods-stats       : 1.0.0
cocoapods-trunk       : 1.1.1
cocoapods-try         : 1.1.0

Podfile

source 'https://github.com/CocoaPods/Specs.git'
workspace './App.xcworkspace'

use_frameworks!
inhibit_all_warnings!

abstract_target 'App Core' do

pod 'LzmaSDK-ObjC'
pod 'Moya', '~> 8.0.0-beta.3'

target :'App Core macOS' do
    project './App Core/App Core.xcodeproj'
    platform :osx, '10.11'

    target 'App Core macOSTests' do
        inherit! :search_paths
    end
end

target :'App Core iOS' do
    project './App Core/App Core.xcodeproj'
    platform :ios, '9.0'

    target 'AppCore Core iOSTests' do
        inherit! :search_paths
    end
end

end

abstract_target 'App Apps' do

    pod 'Fabric'
    pod 'Crashlytics'

  target :'App macOS' do
    project './App macOS/App macOS.xcodeproj'
    platform :osx, '10.11'

    target 'App macOSTests' do
      inherit! :search_paths
    end
  end

  target :'App iOS' do
    project './App iOS/App iOS.xcodeproj'
    platform :ios, '9.0'

    target 'App iOSTests' do
      inherit! :search_paths
    end
  end

end
moderate frameworks confirmed defect

Most helpful comment

@piercifani @vincedev I finally got some time to put together a frameworks sample project. In doing this, I discovered that I definitely broke framework support when the framework target exists in another project (still needs to be a sub-project of the app project though). I have a fix in the works, and I plan on having a PR聽up today. I'm also going to try to get the sample project up today as well.

All 23 comments

@vincedev can you provide a project that reproduces the issue? I have a general/vague idea of what's going on from your description but having a repro case would be super helpful for debugging and fixing. Thanks!

@benasher44 : Sure, please check out the zip file, which contains a minimal project to reproduce the issue.
CocoaPodsSample.zip

I have a general idea of what's going on here. There are a few frameworks issues that are related to this one. I'm going to try to fix them all at once, but it's going to take some time. In the meantime, you can work around this by making your core project a sub-project in your app project and then adding your core.framework as a dependency in your target dependency build phase. Does that make sense? This is a bit of a heavy work around (in terms of big changes you might not want to make to your project), but I believe it'll work.

@benasher44 : Thanks for the quick reply.
I gave a try to the workaround, but unfortunately it didn't fix the issue. Dependant frameworks still aren't copied into my core framework structure, and dynamic loader fails to load them at runtime.

What I did to work around this is add a build phase to the core framework build process, by copying the 'Embed Pods Frameworks' from the corresponding test target.

Did you pod install again after you did my suggested workaround? That's important, but I forgot to mention it initially sorry

@benasher44 : Yes I did.

Confirming that @vincedev's workaround works, but it's only temporary, because you end up with nested frameworks so this shouldn't be a valid binary to submit to the AppStore.

On the Cocoapods 1.1.0 Release Notes it specifies that framework targets are supported, but no sample Podfile or xcodeproj are posted to help us out.

How does this feature work?

Thanks a lot for your help!

@piercifani most cases that I was presented with during the 1.1.0 betas worked by having a project with an app target, and that project had a sub-project with a framework target. The framework target in the sub-project was then added as a target dependency in the Target Dependencies build phase of the app target. This scenario has been well-tested, but the scenario here shouldn't be difficult to support. I'm working on it, but it's slow going mostly because CocoaPods isn't my day job :)

@piercifani @vincedev is there a reason why the framework project can't be a sub-project of the app project in either of your cases? I've been working on trying to implement matching up a framework dependency across projects, but it's proving to be impossible. The UUID of the framework in the app project doesn't match the UUID of the framework target in the framework project. Because of this, it's not possible for CocoaPods to know where the framework target in the framework project is going to be embedded.

Hi @benasher44,

First of all, thanks for your time, really appreciate it!

Second of all: I have no issue doing just that; I guess what I need here is a way of _knowing what to do_ to make it work, since the release notes seem to include no examples on this feature.

What I think would be valuable for the CP community is a sample workspace setup of an App + Framework and a Podfile that links Pods to both the app and the framework, since this is the most common scenario.

Do you think that this would be useful?

@benasher44 what about if the framework is also dependant of another framework project ? Do you think it would work in that scenario ?

In our case we have workspace setup like that :

  • Foo (Project)

    • Foo (app target) (Depends of FooUIKit)

    • FooUITests (acceptance tests)

  • FooUIKit (Project)

    • FootUIKit (framework target) (Depends of FooKit)

    • FootUIKitTests (unit test target)

  • FooKit (Project) (Depends of Alamofire)

    • FooKit (framework target)

    • FooKitTests (unit test target)

Cheers

@benasher44 : Retried the suggested workaround today to no avail.
I then tried it also on the sample project I gave you, with the same result.
Did you try it with the sample ? Did it work for you ?

It has worked for me and others. I'll put up a sample project to better illustrate in the next week.

Yeah, I don't think it's working correctly either.

I have followed your steps (I deintegrated Cocoapods from all xcodeproj first), and now the project looks like this .

But still, the *-frameworks-.sh script doesn't install any framework on the main target, making the app crash on launch.

Any ETAs on the sample project?

Thanks!

@piercifani @vincedev I finally got some time to put together a frameworks sample project. In doing this, I discovered that I definitely broke framework support when the framework target exists in another project (still needs to be a sub-project of the app project though). I have a fix in the works, and I plan on having a PR聽up today. I'm also going to try to get the sample project up today as well.

PR was posted yesterday. I've finished work on the sample project for dynamic frameworks this morning, and it's now posted here: https://github.com/benasher44/CocoaPodsLibExample

Thanks everyone for being patient here! I've been quite busy lately :)

@benasher44 , I forket your example to reproduce a case when a local framework project is dependant on another local framework project

Demo : https://github.com/dagio/CocoaPodsLibExample

In that case, SampleFramework is dependant of SampleFramework2. SampleFramework2 itself is dependant of an external framework : MDWamp

It looks like this :

screen shot 2016-11-24 at 12 16 56

And the Podfile looks like that :

platform :ios, '9.0'
use_frameworks!

workspace 'SampleApp.xcworkspace'

target 'SampleApp' do
  project 'SampleApp.xcodeproj'
  pod 'AFNetworking'
end

target 'SampleFramework' do
  project 'SampleFramework/SampleFramework.xcodeproj'
  pod 'CocoaLumberjack'
end

target 'SampleFramework2' do
  project 'SampleFramework2/SampleFramework2.xcodeproj'
  pod 'MDWamp'
end

When the app start, the dynamic loader can not find "CocoaAsyncSocket" (one of the dependencies of SampleFramework2) :

dyld: Library not loaded: @rpath/CocoaAsyncSocket.framework/CocoaAsyncSocket
  Referenced from: /Users/damiengavard/Library/Developer/Xcode/DerivedData/SampleApp-dalejtiajrnfbyfeuyaqvunmoptd/Build/Products/Debug-iphonesimulator/SampleFramework2.framework/SampleFramework2
  Reason: image not found
(lldb) 

The copy framework step file (Pods-SampleApp-frameworks.sh) does not include these frameworks :

if [[ "$CONFIGURATION" == "Debug" ]]; then
  install_framework "$BUILT_PRODUCTS_DIR/AFNetworking/AFNetworking.framework"
  install_framework "$BUILT_PRODUCTS_DIR/CocoaLumberjack/CocoaLumberjack.framework"
fi
if [[ "$CONFIGURATION" == "Release" ]]; then
  install_framework "$BUILT_PRODUCTS_DIR/AFNetworking/AFNetworking.framework"
  install_framework "$BUILT_PRODUCTS_DIR/CocoaLumberjack/CocoaLumberjack.framework"
fi

@dagio thanks for bringing up this interesting scenario! Do you mind filing a new issue? I'll likely need to work on this scenario separately (handling frameworks from a sub-projoect that depend on a framework from another sub-project), since the fix for this issue is ready to go in soon.

@benasher44, I opened a new issues as you asked with all the details : #6245

Thanks @benasher44. Adding MyFramework.framework as a Target Dependency of MyApp was the key part for me that resolved the dyld: Library not loaded error. To do this, I had to add MyFramework.project as a sub-project of MyApp.project like you suggested.

It's odd that this is required, to cause the Target Dependency picker to see the framework dependency; I would expect this to still work with both projects living at the top-level in the workspace. I wonder if there is a way to manually edit the App's project file's Target Dependencies section to point to a sibling project's framework target.

@JakeSc we (CocoaPods) can't otherwise know for sure that the framework in your project needs to be integrated into that specific target. In a more extreme case, if you had lots of targets and frameworks, this linkage is important so that CocoaPods doesn't make assumptions about how targets in your project depends on frameworks in your project.

Sorry for bringing up an older post, however I'm having a problem which is easily replicated with the CocoaPodsLibExample that you created @benasher44 . When adding certain pods to the podspec (such as pod 'GoogleSignIn'), I get:

Class GIDTokenFetchDelegate is implemented in both .../SampleFramework.framework/SampleFramework and ...SampleApp.app/SampleApp. One of the two will be used. Which one is undefined.

Note that this happens with other pods, I'm just using 'GoogleSignIn' as an example. I've posted a sample here:

CocoaPodsLibExample-master 2.zip

This is Cocoapods version 1.3.1. Could you help?

Was this page helpful?
0 / 5 - 0 ratings