XCFrameworks — New Format for Packaging Frameworks in iOS

Roberto Frontado
Nov 2 · 4 min read
Image for post
Image for post

At WWDC 2019, Apple introduced a new format for packaging frameworks called XCFrameworks, which allows developers to conveniently distribute binary libraries for multiple platforms and architectures in a single bundle.

This means we no longer need to merge multiple architectures into a single binary (also known as Fat Frameworks) only to have to remove the Simulator slice later during the archive phase before uploading to App Store Connect.

Why Embrace XCFrameworks?

With the release of Xcode 12 and Apple moving to Apple Silicon (which established a common architecture across all Apple products), we were forced to change how we distributed our frameworks.

We were creating Fat Frameworks using lipo, like this:

lipo \
-create \
./path/to/ios-arm64/MyFramework.framework/MyFramework \
./path/to/ios-x86_64-simulator/MyFramework.framework/MyFramework \
-output ./MyFramework

Since the release of Xcode 12, it started to throw the following error:

fatal error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: ./path/to/ios-arm64/MyFramework.framework/MyFramework and ./path/to/ios-x86_64-simulator/MyFramework.framework/MyFramework have the same architectures (arm64) and can't be in the same fat output file

The error occurs because the simulator and iPhone now run using the same architecture (arm64), which was not included before.

The solution is to distribute those frameworks as XCFrameworks.

Note: We tried to switch to XCFrameworks a couple of months ago. However, we faced some issues while using CocoaPods as our dependency manager, since it didn’t fully support XCFrameworks, especially with frameworks. You can read more about it here:

Fortunately, the issue was fixed in CocoaPods v1.10 (perfect timing, due to the release of Xcode 12), which made it possible for us to switch to XCFrameworks.

At the time of this article, the latest CocoaPods version available was v1.10.0.rc.1.

How to Build an XCFramework

Building an XCFramework is a two-step process:

  1. Archive the slices for each platform you want to support. In this case, we archived iOS Device and iOS Simulator.
# Archive device slicexcodebuild archive \
-workspace 'MyFramework.xcworkspace' \
-scheme 'MyFramework' \
-configuration Release \
-destination 'generic/platform=iOS' \
-archivePath '/path/to/archives/MyFramework-iphoneos' \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
# Archive simulator slicexcodebuild archive \
-workspace 'MyFramework.xcworkspace' \
-scheme 'MyFramework' \
-configuration Release \
-destination 'generic/platform=iOS Simulator' \
-archivePath '/path/to/archives/MyFramework-iphonesimulator' \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES

It is important to set BUILD_LIBRARY_FOR_DISTRIBUTION to YES; this was introduced with Xcode 11. This helps Xcode avoid version-locking, so modules can be used when newer versions of Xcode or the Swift compiler are released.

This will generate the following XCArchives:

Image for post
Image for post
XCArchives generated per platform

2. Create the XCFramework containing all the slices previously generated.

xcodebuild -create-xcframework 
-framework '/path/to/archives/MyFramework-iphoneos.xcarchive/Products/Library/Frameworks/MyFramework.framework'
-framework '/path/to/archives/MyFramework-iphonesimulator.xcarchive/Products/Library/Frameworks/MyFramework.framework'

This will generate the following files:

Image for post
Image for post
XCFramework generated

The generated XCFramework contains two different frameworks (iOS and iOS Simulator) with their respective architectures, so it is no longer required to bundle all the architectures from all the platforms together in the same framework.

Note: There is a known issue related to the generated .swiftinterface files, which is caused by having the namespace and a class with the same name. Read more about this issue here:

Conclusions

Despite the short notice from Apple about the release of the stable version of Xcode 12 and iOS 14 and the difficulties we had while migrating all of our frameworks to XCFrameworks, I’m glad we did it. I think XCFrameworks is the format of the future for distributing binary libraries in the Apple ecosystem. 🚀

Dev Jam

DevJam is a community that aims to enable software…

Thanks to Andrés Pesate

Roberto Frontado

Written by

Mobile developer

Dev Jam

Dev Jam

DevJam is a community that aims to enable software professionals to explore new technologies and to stay on top of every thing development.

Roberto Frontado

Written by

Mobile developer

Dev Jam

Dev Jam

DevJam is a community that aims to enable software professionals to explore new technologies and to stay on top of every thing development.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store