How do I xcodebuild a static library with Bitcode enabled?
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
:
- Use the 'archive' action, as in
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) - Force usage of the flag by adding Other C Flags with
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
- Apple DevForums: Bitcode and Assembly?
- SO: iOS library to BitCode
iOS library to BitCode
When building static libraries you must add the following for bitcode generation:
-fembed-bitcode
for a dynamic library you need to additionally link with
-fembed-bitcode
Note: This command is only available with Xcode7+
In regards to the accepted answer of using -fembed-bitcode-marker
You should be aware that a normal build with the
-fembed-bitcode-marker option will produce minimal size embedded bitcode sections without any real content. This is done as a way of
testing the bitcode-related aspects of your build without slowing down
the build process. The actual bitcode content is included when you do
an Archive build.
bwilson Apple Staff.
https://forums.developer.apple.com/thread/3971#12225
To be more specific:
-fembed-bitcode-marker
simply marks where the bitcode would be in the binary after an archive build.-fembed-bitcode
actually does the full bitcode generation and embedding, so this is what you need to use for building static libraries.- Xcode itself builds with
-fembed-bitcode-marker
for regular builds (like deploy to simulator) - Xcode only builds with
-fembed-bitcode
for archive builds / production builds (as this is only needed for Apple).
Compiling iOS library with bitcode enabled
AFAIK, when you build app with Xcode it includes Bitcode only when you make archive, the reason - decrease compile time when just want to debug or test the app/library.
To ensure that Xcode emits bitcode at each build you can add -fembed-bitcode
flag to Other C flags
and Other linker flags
:
Also, the easiest way to check if the binary contains bitcode is to use otool
and grep
:
otool -l binary_name | grep __LLVM
you will see one or more segname __LLVM
entries if it does have bitcode or empty output if does not.
xcodebuild 7.3 can't enable bitcode
I ran into a similar issue yesterday. After some investigation, the problem, that appears when running xcodebuild
from a "Run Script" build phase in any Xcode target, seems related with the explicit specification of the toolchain to be used, done with the ENV variable TOOLCHAINS
.
Therefore, until Apple releases a fixed version of Xcode 7.3, you can try to add the following command at the beginning of your script:
# workaround for bitcode generation problem with Xcode 7.3
unset TOOLCHAINS
This should be harmless, as this env variable is not set by default when you run xcodebuild from the command line, and this workaround works just fine in my case.
ENABLE_BITCODE in static library
Traditionally I'm answering my own question)
Hopefully this will be useful for someone in future.
The problem was actually not in my own third-party framework. I had old version of FacebookSDK linked to my host project, and in fact the linker required to recompile it (or request a new version from vendor) instead of my own library.
That's definitely strange and confusing why linker was reporting an error in one of my library modules.
There is no connection between my library and FacebookSDK.
Bitcode not being included in my Framework
Okey finally I found the solution. In my case I had some library imported in my project which didn't have bitcode added.
You have to check that every library you use has bitcode and, if not, update to a version that has it (or download the code and compile it yourself with bitcode enabled as I've done).
You can check if a lib has bitcode enabled with the link in my question, but I'll paste it here again.
Hope this help somebody.
Related Topics
How to Prevent iOS 13 Dark Mode from Breaking Emails
If No Table View Results, Display "No Results" on Screen
Fetching All Contacts in iOS Swift
Format Uilabel with Bullet Points
Swift: How to Refresh Uicollectionview Layout After Rotation of the Device
Wireless iPhone App Distribution - Problem with Itms-Services Protocol
Find List of Local Notification the App Has Already Set
How to Verify That I am Running on a Given Gcd Queue Without Using Dispatch_Get_Current_Queue()
Input Field iOS Safari Bug - Can't Type in Any Text
iOS Swift Multiple Dimension Arrays - Compiliing Takes Ages. What Should I Change
Ask for User Permission to Receive Uilocalnotifications in iOS 8
Swift Modal View Controller with Transparent Background
Add Left/Right Horizontal Padding to Uilabel