Enable Bitcode in iOS Framework - ios

I am building an iOS Framework via a build script. It builds fine. When I include it to my project, archive it and try to publish it for Enterprise I get the following error in the logs
NSLocalizedDescription=Failed to verify bitcode in...
I am building via a script
xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk iphoneos BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}" CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}/arm64" SYMROOT="${SYMROOT}" BITCODE_GENERATION_MODE=bitcode OTHER_CFLAGS="-fembed-bitcode" ARCHS='arm64' VALID_ARCHS='arm64' $ACTION
xcodebuild -project "${PROJECT_FILE_PATH}" -target "${TARGET_NAME}" -configuration "${CONFIGURATION}" -sdk iphoneos BUILD_DIR="${BUILD_DIR}" OBJROOT="${OBJROOT}" BUILD_ROOT="${BUILD_ROOT}" CONFIGURATION_BUILD_DIR="${IPHONE_DEVICE_BUILD_DIR}/armv7" SYMROOT="${SYMROOT}" BITCODE_GENERATION_MODE=bitcode OTHER_CFLAGS="-fembed-bitcode" ARCHS='armv7 armv7s' VALID_ARCHS='armv7 armv7s' $ACTION
rm -rf "${UNIVERSAL_OUTPUTFOLDER}"
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework"
lipo -create "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/arm64/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/armv7/${PROJECT_NAME}.framework/${PROJECT_NAME}" -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}"
defaults write "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Info.plist" CFBundleSupportedPlatforms -array 'iPhoneOS'
The last line is there to change the key in the plist to iPhoneOS (I was getting another error without it).
I am enabling OTHER_CFLAGS="-fembed-bitcode" but I still get the error. Any ideas?

Related

Build framework with bitcode

Im trying to create an universal framework from one of the targets in my project. I have used a few scripts, I have found on the internet, but I have one problem - the final framework, doesn't seem to include bitcode. This is the script, that I'm using to create this framework:
UNIVERSAL_OUTPUT_DIR=${BUILD_DIR}/${CONFIGURATION}-universal
RELEASE_DIR=${PROJECT_DIR}/build
TARGET="Observation"
mkdir -p "${UNIVERSAL_OUTPUT_DIR}"
xcodebuild BITCODE_GENERATION_MODE=bitcode -target "${TARGET}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build -sdk iphoneos
xcodebuild BITCODE_GENERATION_MODE=bitcode -target "${TARGET}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build -sdk iphonesimulator
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET}.framework" "${UNIVERSAL_OUTPUT_DIR}/"
SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET}.framework/Modules/${TARGET}.swiftmodule/."
if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then
cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUT_DIR}/${TARGET}.framework/Modules/${TARGET}.swiftmodule"
fi
lipo -create -output "${UNIVERSAL_OUTPUT_DIR}/${TARGET}.framework/${TARGET}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET}.framework/${TARGET}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET}.framework/${TARGET}"
cp -R "${UNIVERSAL_OUTPUT_DIR}/${TARGET}.framework" "${RELEASE_DIR}"
open "${RELEASE_DIR}"
And when I try to use it, I get this error:
ld: '/Users/homedudycz/Desktop/Test/Test/Observation.framework/Observation' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. file '/Users/homedudycz/Desktop/Test/Test/Observation.framework/Observation' for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Can someone help me with this?

is there any change with ios static library run script with xcode 10?

I have created a static ios library, and I have created Aggregate target to get an universal library as output for that i have included shell script in the build phase section:
# define output folder environment variable
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
# Step 1. Build Device and Simulator versions
xcodebuild -target OffsetCalLib-Universal ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
xcodebuild -target OffsetCalLib-Universal -configuration ${CONFIGURATION} -sdk iphonesimulator -arch i386 BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# Step 2. Create universal binary file using lipo
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/lib${PROJECT_NAME}.a"
# Last touch. copy the header files. Just for convenience
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/include" "${UNIVERSAL_OUTPUTFOLDER}/"
But on build it throws error like:

iPhoneSimulator11.4.sdk/usr/include/sys/cdefs.h:763:2: error: Unsupported architecture

I am creating a universal framework by taking reference from https://agilewarrior.wordpress.com/2016/12/22/how-to-create-universal-static-library-ios/ but while running i am getting
Shell Script Invocation Error like below :
here is my configuration:
Here is my script for creating universal framework:
# define output folder environment variable
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
# Step 1. Build Device and Simulator versions
xcodebuild -target ${PROJECT_NAME} ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
xcodebuild -target ${PROJECT_NAME} -configuration ${CONFIGURATION} -sdk iphonesimulator -arch x86_64 -arch i386 -arch armv7 -arch armv7s -arch arm64 BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# Step 2. Create universal binary file using lipo
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/lib${PROJECT_NAME}.a"
echo "Universal library can be found here:"
echo ${UNIVERSAL_OUTPUTFOLDER}/lib${PROJECT_NAME}.a
# Last touch. copy the header files. Just for convenience
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/include" "${UNIVERSAL_OUTPUTFOLDER}/"
The above script is working in my another framework.but in current project it is giving error.

Creating iOS Framework for device and Universal configuration with bitcode enable and bitcode disable from Command Line terminal

#!/bin/sh
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# Step 1. Build Device and Simulator versions
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO \
-configuration ${CONFIGURATION} -sdk iphoneos \
BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${PROJECT_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
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory
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}"
# Step 5. Convenience step to copy the framework to the project's directory
cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"
# Step 6. Convenience step to open the project's directory in Finder
open "${PROJECT_DIR}"
I have above shell script to create framework for device and universal from Xcode build options.
Is is possible to create/Generate iOS Framework from Command terminal with above shell script with below configuration???
1) Create framework for device bitcode disable
2) Create framework for device bitcode enable
3) Create framework for Universal bitcode disable
4) Create framework for Universal bitcode enable
Please let me know the steps to create/generate iOS Framework from
command terminal. Must appreciate for the best explanation
Just add the argument to your xcodebuild
ENABLE_BITCODE=NO for disabling bitcode
ENABLE_BITCODE=YES for enabling bitcode
For example
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build ENABLE_BITCODE=NO
In the shell script you posted, replace the code under # Step 1. Build Device and Simulator versions with the following appropriately.
1) Create framework for device bitcode disable:
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO \
-configuration ${CONFIGURATION} -sdk iphoneos \
BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build ENABLE_BITCODE=NO
xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} \
-sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" \
BUILD_ROOT="${BUILD_ROOT}" clean build ENABLE_BITCODE=YES
2) Create framework for device bitcode enable
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO \
-configuration ${CONFIGURATION} -sdk iphoneos \
BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build ENABLE_BITCODE=YES
xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} \
-sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" \
BUILD_ROOT="${BUILD_ROOT}" clean build ENABLE_BITCODE=YES
3) Create framework for Universal bitcode disable
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO \
-configuration ${CONFIGURATION} -sdk iphoneos \
BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build ENABLE_BITCODE=NO
xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} \
-sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" \
BUILD_ROOT="${BUILD_ROOT}" clean build ENABLE_BITCODE=NO
4) Create framework for Universal bitcode enable
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO \
-configuration ${CONFIGURATION} -sdk iphoneos \
BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build ENABLE_BITCODE=YES
xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} \
-sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" \
BUILD_ROOT="${BUILD_ROOT}" clean build ENABLE_BITCODE=YES
EDIT:
To build the framework, you can do either of the below:
1. Replacing the code for each config, go to terminal and run the shell script by navigating to the folder containing the shell script and running ./<nameOfTheShellScriptFile>.sh. But make sure you have the build settings available there. That will create the framework with the appropriate configuration in the directory ${BUILD_DIR}/${CONFIGURATION}-universal.
2. Add a run script in the Xcode. Open your project in Xcode, click on the schemes dropdown (beside Stop button) and choose your framework scheme. Open the dropdown again and click on "Edit Scheme...". You see 6 actions to the left. You choose which action makes more sense to add the script to (do you want to create this universal framework on every Run action or only when you archive?). Drop down that action and click on Post-actions. Click on + button to add a new action and click on "New Run Script Action". Set the "Provide build settings from" to your framework target to get the appropriate build settings. Paste the script in the text area and click close. Now after every time you perform the action you put the script under, the script runs and builds the framework again for both device and simulator architectures and puts the universal framework in your project directory. It takes some time for this to complete especially if your project is big so wait patiently until the finder opens up to reveal your project directory containing the framework. Now you can either change the code in the script every time you want a different config (bitcode enabled or disabled), or add different schemes for different config and follow this whole step for each of the schemes with appropriate script.

Unable to create iOS static library .a file using make command

My Makefile is as the following and it gives error as make:
No targets specified and no makefile found. Stop.
XBUILD=/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild
PROJECT_ROOT=/Users/AshrafMac/Desktop/iOSSDK/
PROJECT=$(PROJECT_ROOT)/InfColorPicker.xcodeproj
TARGET=/Users/AshrafMac/Desktop/iOSSDK/
all: libInfColorPickerSDK.a
libInfColorPicker-i386.a:
$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphonesimulator -configuration Release clean build
-mv $(PROJECT_ROOT)/build/Release-iphonesimulator/lib$(TARGET).a $#
libInfColorPicker-armv7.a:
$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphoneos -arch armv7 -configuration Release clean build
-mv $(PROJECT_ROOT)/build/Release-iphoneos/lib$(TARGET).a $#
libInfColorPickerSDK.a: libInfColorPicker-i386.a libInfColorPicker-armv7.a
xcrun -sdk iphoneos lipo -create -output $# $^
clean:
-rm -f *.a *.dll
Unable to create ios static library .a file using make command.
xcodebuild -project 'MyProject.xcodeproj' -configuration 'Release'
-sdk 'iphoneos9.3' clean build ARCHS='armv7 armv7s' IPHONEOS_DEPLOYMENT_TARGET='5.0' TARGET_BUILD_DIR='./build-arm'
BUILT_PRODUCTS_DIR='./build-arm'
xcodebuild -project 'MyProject.xcodeproj' -configuration 'Release'
-sdk 'iphoneos9.3' clean build ARCHS='arm64' IPHONEOS_DEPLOYMENT_TARGET='6.0' TARGET_BUILD_DIR='./build-arm64'
BUILT_PRODUCTS_DIR='./build-arm64'
xcodebuild -project 'MyProject.xcodeproj' -configuration 'Release'
-sdk 'iphonesimulator9.3' clean build ARCHS='i386' IPHONEOS_DEPLOYMENT_TARGET='5.0' TARGET_BUILD_DIR='./build-i386'
BUILT_PRODUCTS_DIR='./build-i386'
xcodebuild -project 'MyProject.xcodeproj' -configuration 'Release'
-sdk 'iphonesimulator9.3' clean build ARCHS='x86_64' VALID_ARCHS='x86_64' IPHONEOS_DEPLOYMENT_TARGET='6.0'
TARGET_BUILD_DIR='./build-x86_64' BUILT_PRODUCTS_DIR='./build-x86_64'
lipo -create './build-arm/MyProject.a'
'./build-arm64/MyProject.a' './build-i386/MyProject.a'
'./build-x86_64/MyProject.a' -output 'Mylibrary.a'
EXECUTE the above code in TERMINAL.
In the above code MyProject.xcodeproj should be replaced with your Xcode project name and iphoneos9.3 should be replaced by maximum supported deployment target by your Xcode (For Example I am using Xcode 7.3.1 and maximum supported deployment by it is 9.3 see in: YourProject >> target >>> General Tab)

Resources