Xcode 7 introduces Bitcode, which is some sort of LLVM intermediate binary that means Apple's servers can recompile my app for different architectures without my involvement.
At Lookback, I distribute a static archive framework with our library. It seems that when you build with anything but a "Build & Archive", bitcode is not actually emitted into my library, and anyone who links with my library in their app and tries to do a Build & Archive with Bitcode enabled will get one of two warnings:
ld: 'Lookback(Lookback.o)' 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.
(if lib is built with Xcode 6)ld: warning: full bitcode bundle could not be generated because 'Lookback(Lookback.o)' was built only with bitcode marker. The library must be generated from Xcode archive build with bitcode enabled (Xcode setting ENABLE_BITCODE)
(if lib is built with Xcode 7 with a normal xcodebuild)
I have a build script that builds a device+simulator universal binary, so I can't use Build & Archive, but rather, I run xcodebuild
from commandline from my script. How can I make xcodebuild
generate a proper bitcode-enabled library?
With Xcode 8, I couldn't get
OTHER_CFLAGS="-fembed-bitcode"
to work. I kept running into something along the lines ofwas built without full bitcode. All frameworks and dylibs for bitcode must be generated from Xcode Archive or Install build
when I tried to create an Archive build of an app containing my static framework.What I was really looking for was this:
I'm actually using a Run Script inside of an aggregate target, the full xcodebuild line looks like this (just for reference):
xcodebuild BITCODE_GENERATION_MODE=bitcode OTHER_CFLAGS="-fembed-bitcode" -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
Once you add bitcode support for the static lib, it won't be compatible with Xcode 6. The app won't archive.
I would like to clearly mention the setting for bitcode as @nevyn's answer confused me a little.
Go to Build settings, search for "custom compiler flags". Add
-fembed-bitcode
. This will build your lib with bitcode.select project On Build Settings -> Other C flags, set Debug to -fembed-bitcode-marker and Release to -fembed-bitcode
On Build Settings, click on the + sign at the top to add a user-defined build setting with the name BITCODE_GENERATION_MODE, and set Debug to marker, Release to bitcode
Edit schema as Release Then lick the library.a file and get the build path get the library form Release folder
Bitcode is a compile-time feature (not a link-time feature) which means that every .o file should contain an extra section called __bitcode when built with bitcode. You can confirm whether your binary is bitcode-compatible by running
otool -l (my .o or .a file) | grep __LLVM
.When you build normally, Xcode adds the build flag
-fembed-bitcode-marker
to any clang invocation. This seems to be some sort of 'this is where bitcode would go, if bitcode was enabled' thing, and doesn't actually enable bitcode.When you "Build & Archive", this flag is replaced by
-fembed-bitcode
, which really does build a Bitcode-enabled binary.There seems to be two ways to make
xcodebuild
use-fembed-bitcode
:xcodebuild -target LookbackSDK archive
instead ofxcodebuild -target LookbackSDK build
. This has the side-effect of putting binaries in your Xcode Organizer instead of thebuild/
folder, though you can work around that by using-exportArchive -archivePath ./build
(thanks @JensAyton)OTHER_CFLAGS="-fembed-bitcode"
. Yourxcodebuild
invocation would look something likexcodebuild OTHER_CFLAGS="-fembed-bitcode" -target LookbackSDK build
.The latter is what I chose so that I don't have to change my build system, but it will generate warnings for every file, since now both
-fembed-bitcode-marker
and-fembed-bitcode
are sent to clang. Luckilly the latter wins, generating a Bitcode-enabled library!Resources