From what I understood, bitcode allows to generate binaries with an intermediary binary format. So it is the step before compiling to an ARM or x64 architecture.
It is possible to create "real" .framework
file for iOS since iOS 8. However, framework files are compiled for only one architecture by default (emulator, iPhone). When one wants to distribute a .framework
file, it is better to provide a file compatible with the iOS emulator and also deployable to an iPhone. Different examples of scripts can be found to create such a fat file using lipo
.
However, would it be possible to only distribute a .framework
compiled as bitcode without having to create a fat file with different architectures?
Unfortunately, even with bitcode enabled for my .framework
:
Do I misunderstand something in the concept of bitcode, or do I miss something?
I spend many hours fixing / changing the setup of xfaid's answer to have finaly a universal package with bitcode working with XCode 10.
I couldn't get the "xcodebuild archive" command work, so I used build with the settings described at this link: http://iosre.com/t/enable-bitcode-for-frameworks-in-xcode/12581
I then changed a little the script to:
# Fix for bitcode:
unset TOOLCHAINS
######################
# Options
######################
#verbose
#set -x
REVEAL_ARCHIVE_IN_FINDER=true
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
######################
# Build for simulator
xcodebuild -target ${PROJECT_NAME} -sdk iphonesimulator -configuration ${CONFIGURATION} ARCHS="i386 x86_64" ONLY_ACTIVE_ARCH=NO clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator
# Build for device
xcodebuild -scheme ${PROJECT_NAME} -sdk iphoneos -configuration ${CONFIGURATION} ARCHS="armv7 armv7s arm64" ONLY_ACTIVE_ARCH=NO build ENABLE_BITCODE=YES OTHER_CFLAGS="-fembed-bitcode" OBJROOT="${OBJROOT}/DependantBuilds" CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos
######################
# 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}/build/${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
Just in case it can helps some of you :)
You need to provide a universal flat framework. Which is created by lipo
.
Targets->Build Setting->Enable Bitcode
to Yes
Add build target to create universal framework
Create a Aggregate
target and copy following script to Build Phrase -> Run Script
:
###################### # Options ###################### #verbose set -x 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 ###################### # Build for simulator xcodebuild -target ${PROJECT_NAME} -sdk iphonesimulator -configuration ${CONFIGURATION} ARCHS="i386 x86_64" ONLY_ACTIVE_ARCH=NO clean build CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator # Build for device xcodebuild -scheme ${PROJECT_NAME} -sdk iphoneos -configuration ${CONFIGURATION} ARCHS="armv7 armv7s arm64" ONLY_ACTIVE_ARCH=NO clean archive CONFIGURATION_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos ###################### # 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}/build/${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
bitcode is only packed on archive
build for iphoneos sdk
otool -l -arch arm64 <yourframework_binary>|grep __LLVM
to check whether bitcode is included, if you don't specify the arch
parameter, there will be no __LLVM
, since otool
just print one host arch(simulator).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With