I Xcode 9.x, I was using the below script which worked fine :
######################
# Options
######################
REVEAL_ARCHIVE_IN_FINDER=false
FRAMEWORK_NAME="${PROJECT_NAME}"
SIMULATOR_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework"
DEVICE_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FRAMEWORK_NAME}.framework"
UNIVERSAL_LIBRARY_DIR="${BUILD_DIR}/${CONFIGURATION}-iphoneuniversal"
FRAMEWORK="${UNIVERSAL_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework"
######################
# Build Frameworks
######################
xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}"
ONLY_ACTIVE_ARCH=NO -configuration "${CONFIGURATION}" -sdk iphonesimulator
BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}"
CONFIGURATION_BUILD_DIR="${IPHONE_SIMULATOR_BUILD_DIR}" SYMROOT="${SYMROOT}"
ARCHS="i386 x86_64" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" $ACTION 2>&1
xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}"
ONLY_ACTIVE_ARCH=NO -configuration "${CONFIGURATION}" -sdk iphoneos
BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}"
CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}" SYMROOT="${SYMROOT}"
ARCHS="armv7 armv7s arm64" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" $ACTION 2>&1
######################
# Create directory for universal
######################
rm -rf "${UNIVERSAL_LIBRARY_DIR}"
mkdir "${UNIVERSAL_LIBRARY_DIR}"
mkdir "${FRAMEWORK}"
######################
# Copy files Framework
######################
cp -r "${DEVICE_LIBRARY_PATH}/." "${FRAMEWORK}"
######################
# Make an universal binary
######################
lipo "${SIMULATOR_LIBRARY_PATH}/${FRAMEWORK_NAME}" "${DEVICE_LIBRARY_PATH}/${FRAMEWORK_NAME}" -create -output "${FRAMEWORK}/${FRAMEWORK_NAME}" | echo
# For Swift framework, Swiftmodule needs to be copied in the universal framework
if [ -d "${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then
cp -f ${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo
fi
if [ -d "${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then
cp -f ${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo
fi
######################
# On Release, copy the result to release directory
######################
OUTPUT_DIR="${PROJECT_DIR}/Output/${FRAMEWORK_NAME}-${CONFIGURATION}-iphoneuniversal/"
rm -rf "$OUTPUT_DIR"
mkdir -p "$OUTPUT_DIR"
cp -r "${FRAMEWORK}" "$OUTPUT_DIR"
if [ ${REVEAL_ARCHIVE_IN_FINDER} = true ]; then
open "${OUTPUT_DIR}/"
fi
This didn't for Xcode 10. Later I saw that there was some modification required in the script. So I followed this answer to set the script. But after setting this script, when I try to build the Universal framework, Xcode hangs on Building script 1 of 1.
I have been trying to look for the right solution but failing each time.
What is the correct run script for a universal framework (covering all architectures) on Xcode 10 ?
Adding -UseModernBuildSystem=NO to xcodebuild command should work.
xcodebuild -workspace ${PROJECT_NAME}.xcworkspace -scheme ${PROJECT_NAME} -sdk iphonesimulator -configuration ${CONFIGURATION} -UseModernBuildSystem=NO clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator 2>&1
xcodebuild -workspace ${PROJECT_NAME}.xcworkspace -scheme ${PROJECT_NAME} -sdk iphoneos -configuration ${CONFIGURATION} -UseModernBuildSystem=NO clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos 2>&1
It should fix your problem.
This is the entire script I'm currently using and which successfully builds universal framework with Xcode 10. Link to gist
Currently, working to make use of latest build system to build universal framework. Shall update the answer soon.
echo "project"
#open "${PROJECT_DIR}"
if [ "true" == ${ALREADYINVOKED:-false} ]
then
echo "RECURSION: Detected, stopping"
else
export ALREADYINVOKED="true"
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-iosuniversal
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# Step 1. Build Device and Simulator versions
echo "iphone"
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
echo "iphonesim"
xcodebuild -target "${TARGET_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
## Step 2. Copy the framework structure (from iphoneos build) to the universal folder
echo "universal"
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
# Step 3. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory
echo "iphone simulator path"
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_OUTPUTFOLDER}/${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
echo "lipo create"
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"
echo "end"
fi
First Generate the Separate build for both simulator and device
while opening your Products folder you will Find the separate build for both
And then use this Run script in your project
After Generating the Script you Find the Folder IOS-Universal in Same product Folder
For me Working fine.
The screenshots below image
Open Terminal, navigate root directory of project and Replace YourUniversalFramework with your project Name and Scheme name(if Required), run the command after successful, It will generate universal folder inside build.
Framework from universal folder is now ready to be consumed by devices and simulators!
Note: Paste whole script on Terminal after changes and Run
Command/Script For .xcodeproj Project
mkdir build
;
xcodebuild clean build \
-project YourUniversalFramework.xcodeproj \
-scheme YourUniversalFramework \
-configuration Release \
-sdk iphoneos \
-derivedDataPath derived_data \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
;
mkdir build/devices
;
cp -r derived_data/Build/Products/Release-iphoneos/YourUniversalFramework.framework build/devices
;
xcodebuild clean build \
-project YourUniversalFramework.xcodeproj \
-scheme YourUniversalFramework \
-configuration Release \
-sdk iphonesimulator \
-derivedDataPath derived_data \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
;
mkdir build/simulator
;
cp -r derived_data/Build/Products/Release-iphonesimulator/ build/simulator/
;
mkdir build/universal
;
cp -r build/devices/YourUniversalFramework.framework build/universal/
;
lipo -create \
build/simulator/YourUniversalFramework.framework/YourUniversalFramework \
build/devices/YourUniversalFramework.framework/YourUniversalFramework \
-output build/universal/YourUniversalFramework.framework/YourUniversalFramework
;
cp -r \
build/simulator/YourUniversalFramework.framework/Modules/YourUniversalFramework.swiftmodule/* \
build/universal/YourUniversalFramework.framework/Modules/YourUniversalFramework.swiftmodule/YourUniversalFramework
Command/Script For .xcworkspace Project
mkdir build
;
xcodebuild clean build \
-workspace YourUniversalFramework.xcworkspace \
-scheme YourUniversalFramework \
-configuration Release \
-sdk iphoneos \
-derivedDataPath derived_data \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
;
mkdir build/devices
;
cp -r derived_data/Build/Products/Release-iphoneos/YourUniversalFramework.framework build/devices
;
xcodebuild clean build \
-workspace YourUniversalFramework.xcworkspace \
-scheme YourUniversalFramework \
-configuration Release \
-sdk iphonesimulator \
-derivedDataPath derived_data \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
;
mkdir build/simulator
;
cp -r derived_data/Build/Products/Release-iphonesimulator/ build/simulator/
;
mkdir build/universal
;
cp -r build/devices/YourUniversalFramework.framework build/universal/
;
lipo -create \
build/simulator/YourUniversalFramework.framework/YourUniversalFramework \
build/devices/YourUniversalFramework.framework/YourUniversalFramework \
-output build/universal/YourUniversalFramework.framework/YourUniversalFramework
;
cp -r \
build/simulator/YourUniversalFramework.framework/Modules/YourUniversalFramework.swiftmodule/* \
build/universal/YourUniversalFramework.framework/Modules/YourUniversalFramework.swiftmodule/YourUniversalFramework
Related
I'm working with an iOS project that produces a Framework directory at the root of the project when I execute Product -> Build For -> Running in Xcode. I need to be able to automate this process on the command line presumably using xcodebuild. However, I can't seem to determine the correct set of parameters to make this happen. Any insight into how to run this same scenario without the GUI? Do I have to look at using lipo?
This is the generic script I created. It creates a framework with combined device and simulator binaries.
#!/bin/bash
while getopts s:w: flag
do
case "${flag}" in
s) scheme=${OPTARG};;
w) workspace="-workspace ${OPTARG}.xcworkspace";;
esac
done
if [ -z "$scheme" ]
then
echo "$(basename $BASH_SOURCE) -- build XCFramework"
echo ""
echo "$(basename $BASH_SOURCE) -s scheme-name [ -w workspace0-name ]"
echo ""
echo "Run this script from the top-level directory of your framework."
echo "The build result will be here: archives/<scheme-name>.xcframework"
exit
fi
rm -rf archives/$scheme.xcframework
xcodebuild archive \
$workspace \
-scheme $scheme \
-destination "generic/platform=iOS Simulator" \
-archivePath "archives/$scheme-Simulator" \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
xcodebuild archive \
$workspace \
-scheme $scheme \
-destination "generic/platform=iOS" \
-archivePath "archives/$scheme" \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
cp -r archives/$scheme-Simulator.xcarchive/Products/Library/Frameworks/. archives/simulator
cp -r archives/$scheme.xcarchive/Products/Library/Frameworks/. archives/ios
function GetUUID() {
local arch=$1
local binary=$2
local dwarfdump_result=$(dwarfdump -u ${binary})
local regex="UUID: (.*) \((.*)\)"
if [[ $dwarfdump_result =~ $regex ]]; then
local result_uuid="${BASH_REMATCH[1]}"
local result_arch="${BASH_REMATCH[2]}"
if [ "$result_arch" == "$arch" ]; then
echo $result_uuid
fi
fi
}
BCSYMBOLMAP_UUID=$(GetUUID "arm64" "archives/$scheme.xcarchive/Products/Library/Frameworks/$scheme.framework/$scheme")
xcodebuild -create-xcframework \
-framework archives/ios/$scheme.framework \
-debug-symbols ${PWD}/archives/$scheme.xcarchive/dSYMs/$scheme.framework.dSYM \
-debug-symbols "${PWD}/archives/$scheme.xcarchive/BCSymbolMaps/${BCSYMBOLMAP_UUID}.bcsymbolmap" \
-framework archives/simulator/$scheme.framework \
-debug-symbols ${PWD}/archives/$scheme-Simulator.xcarchive/dSYMs/$scheme.framework.dSYM \
-output archives/$scheme.xcframework
cd archives
rm -rf $scheme-Simulator.xcarchive $scheme.xcarchive ios simulator
I try create binary universal framework, with next steps
mkdir build
xcodebuild clean build \
-project Target/TestTarget.xcodeproj \
-scheme TestTarget \
-configuration Release \
-sdk iphonesimulator \
-derivedDataPath derived_data
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
mkdir build/simulator
cp -r derived_data/Build/Products/Release-iphonesimulator/TestTarget.framework build/simulator
xcodebuild clean build \
-project Target/TestTarget.xcodeproj \
-scheme TestTarget \
-configuration Release \
-sdk iphoneos \
-derivedDataPath derived_data
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
mkdir build/devices
cp -r derived_data/Build/Products/Release-iphoneos/TestTarget.framework build/devices
mkdir build/universal
cp -r build/devices/TestTarget.framework build/universal/
lipo -create \
build/simulator/TestTarget.framework/TestTarget \
build/devices/TestTarget.framework/TestTarget \
-output build/universal/TestTarget.framework/TestTarget
cp build/simulator/TestTarget.framework/Modules/TestTarget.swiftmodule/* build/universal/TestTarget.framework/Modules/TestTarget.swiftmodule
but have ERROR
..../TestTarget have the same architectures (arm64) and can't be in the same fat output file
As Apple support described here
Scripts like that -- anything that tries to manipulate the output with commands like lipo -- still produces an unsupported configuration in the binary.
And the way to go is distribute the framework as a xcframework. Here you have Apple docs how to do that.
xcodebuild -create-xcframework -framework <path> [-framework <path>...] -output <path>
xcodebuild -create-xcframework -library <path> [-headers <path>] [-library <path> [-headers <path>]...] -output <path>
How to Create Custom Universal Framework in Xcode 11.3 and iOS 13, Any run script?
Step 1:
Add new Target from Cross-platform->Aggregate
Step 2:
From build phrases add following as run script:
Type a script or drag a script file from your workspace to insert its path.
FRAMEWORK_NAME=${PROJECT_NAME}
SIMULATOR_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework"
DEVICE_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FRAMEWORK_NAME}.framework"
DEVICE_BCSYMBOLMAP_PATH="${BUILD_DIR}/${CONFIGURATION}-iphoneos"
DEVICE_DSYM_PATH="${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FRAMEWORK_NAME}.framework.dSYM"
SIMULATOR_DSYM_PATH="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework.dSYM"
UNIVERSAL_LIBRARY_DIR="${BUILD_DIR}/${CONFIGURATION}-iphoneuniversal"
FRAMEWORK="${UNIVERSAL_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework"
OUTPUT_DIR="./Build-Framework"
DRPBOX_DIR="/Users/$USER/Dropbox/Frameworks/iTelMessagingKit"
This builds your framework for the target simulator.
Xcodebuild -project ${PROJECT_NAME}.Xcodeproj -UseModernBuildSystem=NO -scheme ${FRAMEWORK_NAME} -sdk iphonesimulator -configuration ${CONFIGURATION} clean install CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator
This builds your framework for the device.
Xcodebuild -project ${PROJECT_NAME}.Xcodeproj -UseModernBuildSystem=NO -scheme ${FRAMEWORK_NAME} -sdk iphoneos -configuration ${CONFIGURATION} clean install CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos
Let’s clean up the final directories:
rm -rf "${UNIVERSAL_LIBRARY_DIR}"
mkdir "${UNIVERSAL_LIBRARY_DIR}"
mkdir "${FRAMEWORK}"
rm -rf "$OUTPUT_DIR"
mkdir -p "$OUTPUT_DIR"
Now, we take one of the framework files to our universal folder:
cp -r "${DEVICE_LIBRARY_PATH}/." "${FRAMEWORK}"
Now for the real magic, lipo, add this snippet:
lipo "${SIMULATOR_LIBRARY_PATH}/${FRAMEWORK_NAME}" "${DEVICE_LIBRARY_PATH}/${FRAMEWORK_NAME}" -create -output "${FRAMEWORK}/${FRAMEWORK_NAME}" | echo
cp -r "${FRAMEWORK}" "$OUTPUT_DIR"
cp -r "${FRAMEWORK}" "$DRPBOX_DIR"
These are the requirements I want to meet :
Dynamic fat framework with aggregate
Architectures supported for both device and simulator
Support for bitcode - enabled and disabled
I am able to achieve all these but with different binaries. Currently I am having 2 sets of binaries - bitcode enabled and bitcode disabled.
Now, for bitcode enabled, the framework should be archived. When I do that, I loose the hand on second requirement i.e. build fails for simulator (MyClass is unavailable).
I can't have more than 2 binaries. All the requirements should be met in a max of two.
For reference, this is the aggregate script :
######################
# Options
######################
REVEAL_ARCHIVE_IN_FINDER=false
FRAMEWORK_NAME="${PROJECT_NAME}"
SIMULATOR_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework"
DEVICE_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FRAMEWORK_NAME}.framework"
UNIVERSAL_LIBRARY_DIR="${BUILD_DIR}/${CONFIGURATION}-iphoneuniversal"
FRAMEWORK="${UNIVERSAL_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework"
######################
# Build Frameworks
######################
xcodebuild -project "${PROJECT_FILE_PATH}" -target "${AN_TARGET}"
ONLY_ACTIVE_ARCH=NO -configuration "${CONFIGURATION}" -sdk iphonesimulator
BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}"
CONFIGURATION_BUILD_DIR="${IPHONE_SIMULATOR_BUILD_DIR}" SYMROOT="${SYMROOT}"
ARCHS="i386 x86_64" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" $ACTION 2>&1
xcodebuild -project "${PROJECT_FILE_PATH}" -target "${AN_TARGET}"
ONLY_ACTIVE_ARCH=NO -configuration "${CONFIGURATION}" -sdk iphoneos
BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}"
CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}" SYMROOT="${SYMROOT}"
ARCHS="armv7 armv7s arm64" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" $ACTION 2>&1
######################
# Create directory for universal
######################
rm -rf "${UNIVERSAL_LIBRARY_DIR}"
mkdir "${UNIVERSAL_LIBRARY_DIR}"
mkdir "${FRAMEWORK}"
######################
# Copy files Framework
######################
cp -r "${DEVICE_LIBRARY_PATH}/." "${FRAMEWORK}"
######################
# Make an universal binary
######################
lipo "${SIMULATOR_LIBRARY_PATH}/${FRAMEWORK_NAME}" "${DEVICE_LIBRARY_PATH}/${FRAMEWORK_NAME}" -create -output "${FRAMEWORK}/${FRAMEWORK_NAME}" | echo
# For Swift framework, Swiftmodule needs to be copied in the universal framework
if [ -d "${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then
cp -f ${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo
fi
if [ -d "${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then
cp -f ${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo
fi
######################
# On Release, copy the result to release directory
######################
OUTPUT_DIR="${PROJECT_DIR}/Output/${FRAMEWORK_NAME}-${CONFIGURATION}-iphoneuniversal/"
rm -rf "$OUTPUT_DIR"
mkdir -p "$OUTPUT_DIR"
cp -r "${FRAMEWORK}" "$OUTPUT_DIR"
if [ ${REVEAL_ARCHIVE_IN_FINDER} = true ]; then
open "${OUTPUT_DIR}/"
fi
This issue has been following me since quite a bit of time, so I am aware of the hacks like Build active archs and enable bitcode which do not seem to work.
I recently switched to Xcode 10 and compiled my universal framework. Got this error :
fatal error: lipo: can't open input file:
/Users/testing/Library/Developer/Xcode/DerivedData/MyFramework-darbltkqlhuhbcfjavjyczodjneq/Build/Products/Debug-iphonesimulator/MyFramework.framework/MyFramework
(No such file or directory)
Getting this second error as well :
xcodebuild: error: The project
'/Users/testing/Documents/workspace/MyFramework/MyFramework.xcodeproj'
does not contain a target named ''.
This is the Run Script I have with me :
######################
# Options
######################
REVEAL_ARCHIVE_IN_FINDER=false
FRAMEWORK_NAME="${PROJECT_NAME}"
SIMULATOR_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework"
DEVICE_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FRAMEWORK_NAME}.framework"
UNIVERSAL_LIBRARY_DIR="${BUILD_DIR}/${CONFIGURATION}-iphoneuniversal"
FRAMEWORK="${UNIVERSAL_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework"
######################
# Build Frameworks
######################
xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}"
ONLY_ACTIVE_ARCH=NO -configuration "${CONFIGURATION}" -sdk iphonesimulator
BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}"
CONFIGURATION_BUILD_DIR="${IPHONE_SIMULATOR_BUILD_DIR}" SYMROOT="${SYMROOT}"
ARCHS="i386 x86_64" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" $ACTION 2>&1
xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}"
ONLY_ACTIVE_ARCH=NO -configuration "${CONFIGURATION}" -sdk iphoneos
BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}"
CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}" SYMROOT="${SYMROOT}"
ARCHS="armv7 armv7s arm64" ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" $ACTION 2>&1
######################
# Create directory for universal
######################
rm -rf "${UNIVERSAL_LIBRARY_DIR}"
mkdir "${UNIVERSAL_LIBRARY_DIR}"
mkdir "${FRAMEWORK}"
######################
# Copy files Framework
######################
cp -r "${DEVICE_LIBRARY_PATH}/." "${FRAMEWORK}"
######################
# Make an universal binary
######################
lipo "${SIMULATOR_LIBRARY_PATH}/${FRAMEWORK_NAME}" "${DEVICE_LIBRARY_PATH}/${FRAMEWORK_NAME}" -create -output "${FRAMEWORK}/${FRAMEWORK_NAME}" | echo
# For Swift framework, Swiftmodule needs to be copied in the universal framework
if [ -d "${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then
cp -f ${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo
fi
if [ -d "${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then
cp -f ${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo
fi
######################
# On Release, copy the result to release directory
######################
OUTPUT_DIR="${PROJECT_DIR}/Output/${FRAMEWORK_NAME}-${CONFIGURATION}-iphoneuniversal/"
rm -rf "$OUTPUT_DIR"
mkdir -p "$OUTPUT_DIR"
cp -r "${FRAMEWORK}" "$OUTPUT_DIR"
if [ ${REVEAL_ARCHIVE_IN_FINDER} = true ]; then
open "${OUTPUT_DIR}/"
fi
Note : Build Active Architecture solution is not what I want.
Finally, below is the script that worked for me on Xcode 10 :
# Typ######################
# Options
######################
REVEAL_ARCHIVE_IN_FINDER=false
FRAMEWORK_NAME="${PROJECT_NAME}"
SIMULATOR_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework"
DEVICE_LIBRARY_PATH="${BUILD_DIR}/${CONFIGURATION}-iphoneos/${FRAMEWORK_NAME}.framework"
UNIVERSAL_LIBRARY_DIR="${BUILD_DIR}/${CONFIGURATION}-iphoneuniversal"
FRAMEWORK="${UNIVERSAL_LIBRARY_DIR}/${FRAMEWORK_NAME}.framework"
######################
# Build Frameworks
######################
xcodebuild -project ${PROJECT_NAME}.xcodeproj -scheme ${PROJECT_NAME} -sdk iphonesimulator -configuration ${CONFIGURATION} -UseModernBuildSystem=NO clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator 2>&1
xcodebuild -project ${PROJECT_NAME}.xcodeproj -scheme ${PROJECT_NAME} -sdk iphoneos -configuration ${CONFIGURATION} -UseModernBuildSystem=NO clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos 2>&1
######################
# Create directory for universal
######################
rm -rf "${UNIVERSAL_LIBRARY_DIR}"
mkdir "${UNIVERSAL_LIBRARY_DIR}"
mkdir "${FRAMEWORK}"
######################
# Copy files Framework
######################
cp -r "${DEVICE_LIBRARY_PATH}/." "${FRAMEWORK}"
######################
# Make an universal binary
######################
lipo "${SIMULATOR_LIBRARY_PATH}/${FRAMEWORK_NAME}" "${DEVICE_LIBRARY_PATH}/${FRAMEWORK_NAME}" -create -output "${FRAMEWORK}/${FRAMEWORK_NAME}" | echo
# For Swift framework, Swiftmodule needs to be copied in the universal framework
if [ -d "${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then
cp -f ${SIMULATOR_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo
fi
if [ -d "${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/" ]; then
cp -f ${DEVICE_LIBRARY_PATH}/Modules/${FRAMEWORK_NAME}.swiftmodule/* "${FRAMEWORK}/Modules/${FRAMEWORK_NAME}.swiftmodule/" | echo
fi
######################
# On Release, copy the result to release directory
######################
OUTPUT_DIR="${PROJECT_DIR}/Output/${FRAMEWORK_NAME}-${CONFIGURATION}-iphoneuniversal/"
rm -rf "$OUTPUT_DIR"
mkdir -p "$OUTPUT_DIR"
cp -r "${FRAMEWORK}" "$OUTPUT_DIR"
if [ ${REVEAL_ARCHIVE_IN_FINDER} = true ]; then
open "${OUTPUT_DIR}/"
fi