Reputation: 55705
I am looking to create a closed source CocoaPod. From my research the recommendation seems to be to distribute it as an XCFramework. (source) It seems it should also be possible to make your framework dependent upon other CocoaPods by specifying them in your Podspec file. (source) (source) That will ensure when someone adds this pod to their Podfile and runs pod install
, it will install this framework and its dependencies.
I have created a framework Xcode project and have been developing it inside our app's workspace as a subproject. So at this time, the app has all of the dependencies installed via CocoaPods, which allows the framework in it to utilize them. Now I am ready to prepare the framework for distribution so it can be used in other apps.
From what I understand, I need to create an XCFramework first and then can create a CocoaPod for it. When I go to archive the framework project, I get an error because it cannot find the dependencies, which makes sense. At this point I don't understand how this is supposed to work, because it seems the framework needs the dependencies included in itself in order to successfully create the XCFramework, but I anticipated from my research this would be handled by CocoaPods and not included in the framework itself.
xcodebuild archive \
-scheme MyFramework \
-configuration Release \
-destination 'generic/platform=iOS' \
-archivePath './build/MyFramework.framework-iphoneos.xcarchive' \
SKIP_INSTALL=NO \
BUILD_LIBRARIES_FOR_DISTRIBUTION=YES
/Users/.../AppName/MyFramework/Helpers/Extensions.swift:10:8: error: no such module 'Kingfisher'
import Kingfisher
^
** ARCHIVE FAILED **
Upvotes: 5
Views: 4070
Reputation: 36287
Jordan's answer is correct.
Suppose Foo depends on Bar and Baz frameworks. Before you archive, you have to build a target. And because Foo depends on Bar and Baz Frameworks, then the compiler needs to makes sure that you can actually fulfill that promise.
There are two ways to build your pod alongs it dependencies
Podfile
Set your scheme to the Example app and perform archive
You install the dependencies using a project with a Podfile. Jordan is also correct that, while Foo has lines that call functions from Bar, Baz, the Foo framework is a just a binary of Foo, it won't include Bar, Baz frameworks. The final app that installs Foo, will then link (pull and install) Bar, Baz frameworks...
Beware: If you're using the Podfile
and the Podfile
has included some post install hook to change build settings, then obviously your build will be impacted by them.
Podfile
Set your scheme to the pod's scheme, not the example app and archive that.
The archive is just a compressed form of the build. The build will include all dependencies.
FWIW you can invoke/create archives either from command line tool or from Xcode, however it's better to do it from command line tool, so you have a more explicit control over the flags passed to xcodebuild
.
To create a framework, you only use your desired framework within the archives.
When you do:
xcodebuild -create-xcframework \
-framework "archives/StarWarsKit-iOS.xcarchive/Products/Library/Frameworks/StarWarsKit.framework" \
-framework "archives/StarWarsKit-iOS-simulator.xcarchive/Products/Library/Frameworks/StarWarsKit.framework" \
-output "StarWarsKit.xcframework"
You're doing two important things:
/Products/Library/Frameworks
you're only attempting to create an xcframework for StarWarsKit
. You're not creating an xcframework for other frameworks in the workspace. All others are libraries get excluded — if the dependencies of StarWarsKit
are dynamically linked. However the dependencies may become part of the binary if they're linked statically, i.e. they get absorbed and linked into the final product/binary of StarWarsKit
.With some oversimplification, Xcode's build process works a bit like this:
Upvotes: 0
Reputation: 55705
To resolve this, what I did is create a Podfile for the framework project and run pod install
so it has its own workspace. I verified I was able to successfully build the framework in Xcode when opening that workspace. Then to create the archive, specify it should build the workspace rather than the project like so:
xcodebuild archive \
-workspace MyFramework.xcworkspace \
-scheme MyFramework \
-configuration Release \
-destination 'generic/platform=iOS' \
-archivePath './build/MyFramework.framework-iphoneos.xcarchive' \
SKIP_INSTALL=NO \
BUILD_LIBRARIES_FOR_DISTRIBUTION=YES
From what I understand, when you create the XCFramework, the dependencies won't be included it will only be your own framework. However the dependencies have to be accessible in order to successfully build the archive.
This understanding resolves the confusion I had when asking this question. Now I can proceed to create a CocoaPod for my XCFramework and specify its dependencies in the Podspec file.
Upvotes: 7