Skip to content

Instantly share code, notes, and snippets.

@ptvandi
Last active March 2, 2022 20:11
Show Gist options
  • Save ptvandi/58927f4b25368b85ff100628343a8109 to your computer and use it in GitHub Desktop.
Save ptvandi/58927f4b25368b85ff100628343a8109 to your computer and use it in GitHub Desktop.
Create universal frameworks that include binaries for use in an iOS simulator or device.
#!/bin/sh
######################################################################
#
# Create universal frameworks that include binaries for use in an iOS
# simulator or device.
#
#
# Author: Andi Wilson
# Created: 03/01/2018
# Updated: 03/19/2020
#
# Adapted from:
# https://stackoverflow.com/a/28806747/612493
#
######################################################################
######################
# Options
######################
APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
FRAMEWORK_NAME="$PROJECT_NAME"
OUTPUT_DIR="${SRCROOT}/build/Frameworks/iOS"
OUTPUT_DEVICE_DIR="${OUTPUT_DIR}/release"
OUTPUT_SIMULATOR_DIR="${OUTPUT_DIR}/simulator"
OUTPUT_UNIVERSAL_DIR="${OUTPUT_DIR}/fat"
DEVICE_APPENDIX="iphoneos"
SIMULATOR_APPENDIX="iphonesimulator"
UNIVERSAL_APPENDIX="iphoneuniversal"
DEVICE_LIBRARY_DIR="${BUILD_DIR}/${CONFIGURATION}-${DEVICE_APPENDIX}"
SIMULATOR_LIBRARY_DIR="${BUILD_DIR}/${CONFIGURATION}-${SIMULATOR_APPENDIX}"
UNIVERSAL_LIBRARY_DIR="${BUILD_DIR}/${CONFIGURATION}-${UNIVERSAL_APPENDIX}"
DEVICE_LIBRARY_PATH="${DEVICE_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework"
SIMULATOR_LIBRARY_PATH="${SIMULATOR_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework"
UNIVERSAL_LIBRARY_PATH="${UNIVERSAL_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework"
DEVICE_SWIFTMODULE_PATH="${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/"
SIMULATOR_SWIFTMODULE_PATH="${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/"
UNIVERSAL_SWIFTMODULE_PATH="${UNIVERSAL_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/"
DEVICE_SWIFT_HEADER="${DEVICE_LIBRARY_PATH}/Headers/${FRAMEWORK_NAME}-Swift.h"
SIMULATOR_SWIFT_HEADER="${SIMULATOR_LIBRARY_PATH}/Headers/${FRAMEWORK_NAME}-Swift.h"
UNIVERSAL_SWIFT_HEADER="${UNIVERSAL_LIBRARY_PATH}/Headers/${FRAMEWORK_NAME}-Swift.h"
######################
# Recursion detection
######################
if [ "$ALREADY_INVOKED" = true ]; then
echo "Recursion detected. Stopping build."
exit 1
fi
# Export for next run
export ALREADY_INVOKED=true
######################
# Build frameworks
######################
xcodebuild \
BITCODE_GENERATION_MODE=bitcode \
OTHER_CFLAGS="-fembed-bitcode" \
ONLY_ACTIVE_ARCH=NO \
-target "${PROJECT_NAME}" \
-project "${PROJECT_NAME}.xcodeproj" \
-sdk iphonesimulator \
-configuration ${CONFIGURATION} \
clean build \
CONFIGURATION_BUILD_DIR=${SIMULATOR_LIBRARY_DIR} \
OBJROOT="${OBJROOT}/DependentBuilds" 2>&1
xcodebuild \
BITCODE_GENERATION_MODE=bitcode \
OTHER_CFLAGS="-fembed-bitcode" \
ONLY_ACTIVE_ARCH=NO \
-target "${PROJECT_NAME}" \
-project "${PROJECT_NAME}.xcodeproj" \
-sdk iphoneos \
-configuration ${CONFIGURATION} \
build \
CONFIGURATION_BUILD_DIR=${DEVICE_LIBRARY_DIR} \
OBJROOT="${OBJROOT}/DependentBuilds" 2>&1
######################
# Create universal directory
######################
rm -rf "$UNIVERSAL_LIBRARY_DIR"
mkdir "$UNIVERSAL_LIBRARY_DIR"
######################
# Make an universal binary
######################
# Loop through embedded frameworks and create universal binaries
find "$APP_PATH" -name '*.framework' -type d | while read -r THIS_FILE_PATH; do
THIS_NAME=$(echo "$THIS_FILE_PATH" | sed 's/.*\///' | sed 's/\.[^.]*$//')
THIS_FILE="${THIS_NAME}.framework"
THIS_DEVICE_PATH="${DEVICE_LIBRARY_DIR}/${THIS_FILE}"
THIS_SIMULATOR_PATH="${SIMULATOR_LIBRARY_DIR}/${THIS_FILE}"
THIS_UNIVERSAL_PATH="${UNIVERSAL_LIBRARY_DIR}/${THIS_FILE}"
# Create framework directory
mkdir "$THIS_UNIVERSAL_PATH"
# Copy framework files
cp -r "${THIS_DEVICE_PATH}/." "$THIS_UNIVERSAL_PATH" | echo
# Make universal binary
lipo "${THIS_SIMULATOR_PATH}/${THIS_NAME}" "${THIS_DEVICE_PATH}/${THIS_NAME}" -create -output "${THIS_UNIVERSAL_PATH}/${THIS_NAME}" | echo
done
# For Swift frameworks, swiftmodule needs to be copied to the universal framework
if [ -d "$SIMULATOR_SWIFTMODULE_PATH" ]; then
cp -Rf "${SIMULATOR_SWIFTMODULE_PATH}/." "${UNIVERSAL_SWIFTMODULE_PATH}" | echo
fi
if [ -d "$DEVICE_SWIFTMODULE_PATH" ]; then
cp -Rf "${DEVICE_SWIFTMODULE_PATH}/." "${UNIVERSAL_SWIFTMODULE_PATH}" | echo
fi
# Modify swiftinterface files for compatability
# https://forums.developer.apple.com/thread/123253
find "${UNIVERSAL_SWIFTMODULE_PATH}" \
-name "*.swiftinterface" \
-exec sed -i -e "s/${FRAMEWORK_NAME}\.//g" {} \;
# Combine PTVSDK-Swift.h from device and simulator architectures
# (Xcode 10.2 issue: 48635615)
> ${UNIVERSAL_SWIFT_HEADER}
echo "#if TARGET_OS_SIMULATOR" >> ${UNIVERSAL_SWIFT_HEADER}
cat ${SIMULATOR_SWIFT_HEADER} >> ${UNIVERSAL_SWIFT_HEADER}
echo "#else" >> ${UNIVERSAL_SWIFT_HEADER}
cat ${DEVICE_SWIFT_HEADER} >> ${UNIVERSAL_SWIFT_HEADER}
echo "#endif" >> ${UNIVERSAL_SWIFT_HEADER}
######################
# Create final copies
######################
# If remnants from a previous build exist, delete them.
if [ -d "${OUTPUT_DIR}" ]; then
rm -rf "${OUTPUT_DIR}"
fi
mkdir -p $OUTPUT_DEVICE_DIR $OUTPUT_SIMULATOR_DIR $OUTPUT_UNIVERSAL_DIR
cp -Rf "${DEVICE_LIBRARY_PATH}" "$OUTPUT_DEVICE_DIR"
cp -Rf "${SIMULATOR_LIBRARY_PATH}" "$OUTPUT_SIMULATOR_DIR"
cp -Rf "${UNIVERSAL_LIBRARY_PATH}" "$OUTPUT_UNIVERSAL_DIR"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment