Last active
September 16, 2024 07:56
-
-
Save sundeepgupta/3ad9c6106e2cd9f51c68cf9f475191fa to your computer and use it in GitHub Desktop.
Script to create a universal or "fat" binary for an iOS framework.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Adapted from http://stackoverflow.com/questions/24039470/xcode-6-ios-creating-a-cocoa-touch-framework-architectures-issues/26691080#26691080 | |
# and https://gist.github.com/cromandini/1a9c4aeab27ca84f5d79 | |
# Create a new aggregate target. | |
# For the automatically generated scheme, change its build config to "release". | |
# Ensure this target's "product name" build setting matches the framework's. | |
# Add a run script with `source "${PROJECT_DIR}/path_to_this_script` | |
UNIVERSAL_OUTPUT_DIR=${BUILD_DIR}/${CONFIGURATION}-universal | |
RELEASE_DIR=${PROJECT_DIR}/build | |
# make sure the output directory exists | |
mkdir -p "${UNIVERSAL_OUTPUT_DIR}" | |
# Step 1. Build Device and Simulator versions | |
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build -sdk iphoneos | |
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build -sdk iphonesimulator | |
# Step 2. Copy the framework structure (from iphoneos build) to the universal folder | |
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PRODUCT_NAME}.framework" "${UNIVERSAL_OUTPUT_DIR}/" | |
# Step 3. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory | |
SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/." | |
if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then | |
cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUT_DIR}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule" | |
fi | |
# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory | |
lipo -create -output "${UNIVERSAL_OUTPUT_DIR}/${PRODUCT_NAME}.framework/${PRODUCT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PRODUCT_NAME}.framework/${PRODUCT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PRODUCT_NAME}.framework/${PRODUCT_NAME}" | |
# Step 5. Convenience step to copy the framework to the project's directory | |
cp -R "${UNIVERSAL_OUTPUT_DIR}/${PRODUCT_NAME}.framework" "${RELEASE_DIR}" | |
# Step 6. Convenience step to open the project's directory in Finder | |
open "${RELEASE_DIR}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@presscorp I don't recommend doing that, or you won't be able to run your library on 64-bit iPhones or M1 Macs running the simulator. The issue you're having is that you're trying to make a universal binary that supports the same architecture twice (once for iphoneos and once for iphonesimulator), which isn't allowed. I'm guessing that you're using an M1 Mac, so you're trying to make a universal binary for arm64 on iphoneos and arm64 on iphonesimulator (your computer).
XCFrameworks are a new framework format meant to solve this problem. Replace the
lipo
command at line 31 with this:Then you can use the generated xcframework pretty much exactly like you'd use a framework.
(You might to add
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
on the xcodebuild commands on lines 18 and 19 if your library has Swift code, or the Swift modules won't be generated and my new code above will fail to find the module maps.)