iosxcode

How to create a static framework which contains another framework?


I want to create a static framework A which contains another framework B, but when using it within an app I get an error message about being unable to find a bundle with name B. Its possible create a minimal app/framework that demonstrates the issue:

1)In XCode,choose new project, type iOS Framework template

2)Set Mach-O type to Static Library

3)Within XCode add a package dependency. I'm adding https://github.com/marmelroy/PhoneNumberKit with exact version 4.0.2. This offers the following packages:

enter image description here

I add the static one to TheFramework target, but not the other two.

  1. I then build the XCode project to create the framework
  2. In XCode create an iOS app template
  3. Drag and drop the .framework from step 4 from the build products folder into the app's folder and into the XCode project.
  4. Edit the AppDelegate.swift file and add import TheFramework
  5. Build and run.

It generates the following error:

PhoneNumberKit/resource_bundle_accessor.swift:44: Fatal error: unable to find bundle named PhoneNumberKit_PhoneNumberKit

The framework is set as follows in the app:

enter image description here

enter image description here

I've tried the same thing with the PhoneNumberKit package instead of the PhoneNumberKit-Static package, and have tried setting TheFramework to Embed And Sign, but I still keep getting the error.

Is there a step or build setting that needs setting that I am not doing?

I've also tried adding all 3 of the PhoneNumberKit packages at the same time, but that makes no difference either.

enter image description here


Solution

  • Is there a step or build setting that needs setting that I am not doing?

    First it's necessary to understand what you have done by adding "PhoneNumberKit*" library into the "Link Binary With Libraries" list of TheFramework:

    1. You made APIs of PhoneNumberKit available to the linker when it links TheFramework and verifies the existence of the PhoneNumberKit APIs used by TheFramework.

    2. Because TheFramework is a static framework, you DID NOT merge PhoneNumberKit binary into TheFramework binary. When you add just TheFramework into the "Frameworks, Libraries, and Embedded Content" list of "TheApp" target, the PhoneNumberKit APIs are not available to "TheApp".

    If your goal is to launch "TheApp", then you would need to add PhoneNumberKit library into the "Frameworks, Libraries, and Embedded Content" list of "TheApp" target as well.

    If your goal is to distribute TheFramework as prebuilt static framework, you can still specify PhoneNumberKit cocoapod or swift package as a dependency requirement without the necessity to embed it into the binary, and it should be enough to distribute TheFramework this way, however there are downsides to this approach (module stability not supported for static libraries / frameworks).

    If your goal is to distribute prebuilt TheFramework having PhoneNumberKit APIs in its binary, then you can only achieve this by making TheFramework a dynamic framework.