Build xcframework using Aggregated Targets in xcode

Ahmed Fathi
Level Up Coding
Published in
5 min readSep 12, 2020

--

If you’re already familiar with how to build xcframworks using command line tools, then this article is how you take that to the next level.

If you haven’t built or don’t know how to build xcframeworks, I’ve already explained that in details in my previous article here.

Aggregated Targets

Aggregated Targets is used when we need to build multiple targets together somehow.

We will start by our example FruitBasket from the previous article and you can download it from this git repo, here is a preview of the code we have in there.

Open up xcode and start by adding new target to you project from this little + icon at the bottom.

Choose Cross platform and then Aggregate.

Choose the name you want, In my case I’ll name it AggregatedFramework

Change the scheme to AggregatedFramework Scheme.

Then click on Edit Scheme…

Choose Run tab from the left panel then change the build configuration to release.

Go back and choose AggregatedFramework from the targets then choose Build Phases then click on the little + to add a dependency, and choose FruitBasket Framework Target.

Then click on the other + above dependancies word to add a New Run Script Phase

You can rename the script to what it will do, for example Create Aggregated Framework

Let’s start typing in the script area.
I’ll start by creating some variable for the things that I’m going to use through out the script so it stays neat, clean, readable for others and easy to change later.

Start by creating the scheme and framework name variables as below

SCHEME_NAME="FruitBasket"
FRAMEWORK_NAME="FruitBasket"

If you have multiple schemes in your project for iOS & macOS then create all those variables as you’re going to need them, for our case we one have one scheme.

Then I’ll create some variables to hold the paths for the xcarchives and the output.

SIMULATOR_ARCHIVE_PATH="${BUILD_DIR}/${CONFIGURATION}/${FRAMEWORK_NAME}-iphonesimulator.xcarchive"DEVICE_ARCHIVE_PATH="${BUILD_DIR}/${CONFIGURATION}/${FRAMEWORK_NAME}-iphoneos.xcarchive"OUTPUT_DIC="./xcframework/"

Then I’ll add the xcodebuild command to generate the simulator xcarchive with the scheme name and path we created for the simulator archive

# Simulator xcarchieve
xcodebuild archive \
-scheme ${SCHEME_NAME} \
-archivePath ${SIMULATOR_ARCHIVE_PATH} \
-sdk iphonesimulator \
SKIP_INSTALL=NO

and the command to generate the iphoneos xcarchive for devices

# Device xcarchieve
xcodebuild archive \
-scheme ${SCHEME_NAME} \
-archivePath ${DEVICE_ARCHIVE_PATH} \
-sdk iphoneos \
SKIP_INSTALL=NO

Time to generate the output but first we’ll clean the old output directory if exists

# Clean up old output directory
rm -rf "${OUTPUT_DIC}"
# Create xcframwork combine of all frameworks
xcodebuild -create-xcframework \
-framework ${SIMULATOR_ARCHIVE_PATH}/Products/Library/Frameworks/${FRAMEWORK_NAME}.framework \
-framework ${DEVICE_ARCHIVE_PATH}/Products/Library/Frameworks/${FRAMEWORK_NAME}.framework \
-output ${OUTPUT_DIC}/${FRAMEWORK_NAME}.xcframework

Full script

SCHEME_NAME="FruitBasket"
FRAMEWORK_NAME="FruitBasket"
SIMULATOR_ARCHIVE_PATH="${BUILD_DIR}/${CONFIGURATION}/${FRAMEWORK_NAME}-iphonesimulator.xcarchive"
DEVICE_ARCHIVE_PATH="${BUILD_DIR}/${CONFIGURATION}/${FRAMEWORK_NAME}-iphoneos.xcarchive"
OUTPUT_DIC="./xcframework/"
# Simulator xcarchieve
xcodebuild archive \
-scheme ${SCHEME_NAME} \
-archivePath ${SIMULATOR_ARCHIVE_PATH} \
-sdk iphonesimulator \
SKIP_INSTALL=NO
# Device xcarchieve
xcodebuild archive \
-scheme ${SCHEME_NAME} \
-archivePath ${DEVICE_ARCHIVE_PATH} \
-sdk iphoneos \
SKIP_INSTALL=NO
# Clean up old output directory
rm -rf "${OUTPUT_DIC}"
# Create xcframwork combine of all frameworks
xcodebuild -create-xcframework \
-framework ${SIMULATOR_ARCHIVE_PATH}/Products/Library/Frameworks/${FRAMEWORK_NAME}.framework \
-framework ${DEVICE_ARCHIVE_PATH}/Products/Library/Frameworks/${FRAMEWORK_NAME}.framework \
-output ${OUTPUT_DIC}/${FRAMEWORK_NAME}.xcframework

Now that everything is set, make sure you still choose the AggregatedTarget and run you project.

Once it builds successfully check your project directory, you should be able to see a new directory named xcframework which contains your framework and if you look inside you should see both simulator and iphone architectures are in there.

In case you have macOS target also…

In case you have macOS target also then you’ll adjust the script to be as follows

IOS_SCHEME_NAME="YOUR_SCHEME_NAME_FOR_IOS"
MACOS_SCHEME_NAME="YOUR_SCHEME_NAME_FOR_MACOS"
FRAMEWORK_NAME="FruitBasket"
SIMULATOR_ARCHIVE_PATH="${BUILD_DIR}/${CONFIGURATION}/${FRAMEWORK_NAME}-iphonesimulator.xcarchive"
DEVICE_ARCHIVE_PATH="${BUILD_DIR}/${CONFIGURATION}/${FRAMEWORK_NAME}-iphoneos.xcarchive"
MACOS_ARCHIVE_PATH="${BUILD_DIR}/${CONFIGURATION}/${FRAMEWORK_NAME}-macos.xcarchive"

OUTPUT_DIC="./xcframework/"
# Simulator xcarchieve
xcodebuild archive \
-scheme ${IOS_SCHEME_NAME} \
-archivePath ${SIMULATOR_ARCHIVE_PATH} \
-sdk iphonesimulator \
SKIP_INSTALL=NO

# Device xcarchieve
xcodebuild archive \
-scheme ${IOS_SCHEME_NAME} \
-archivePath ${DEVICE_ARCHIVE_PATH} \
-sdk iphoneos \
SKIP_INSTALL=NO

# MacOS xcarchieve
xcodebuild archive \
-scheme ${MACOS_SCHEME_NAME} \
-archivePath ${MACOS_ARCHIVE_PATH} \
SKIP_INSTALL=NO

# Clean up old output directory
rm -rf "${OUTPUT_DIC}"

# Create xcframwork combine of all frameworks
xcodebuild -create-xcframework \
-framework ${SIMULATOR_ARCHIVE_PATH}/Products/Library/Frameworks/${FRAMEWORK_NAME}.framework \
-framework ${DEVICE_ARCHIVE_PATH}/Products/Library/Frameworks/${FRAMEWORK_NAME}.framework \
-framework ${MACOS_ARCHIVE_PATH}/Products/Library/Frameworks/${FRAMEWORK_NAME}.framework \
-output ${OUTPUT_DIC}/${FRAMEWORK_NAME}.xcframework

Don’t forget to change the schemes names to match yours, then run your aggregated target and check the results.

Testing the framework

Create a new project from xcode, single view app is okay for testing.

Add your xcframework file you have just created by dragging and dropping it in Framworks, Libraries, and Embedded Content

Now switch over to your view controller and import the framework and start testing it.

Run it on both simulator and real device and it should run and give you the same results.

Complete code are on this github repo and make sure you’re on aggregated-target branch.

Thank you for taking the time.
All you comments and ideas are welcomed.
AhmedFathi680@gmail.com
LinkedIn
Github

--

--