What's the difference between `-fembed-bitcode` and BITCODE_GENERATION_MODE?
Asked Answered
R

1

46

I've been updating a static library to support bitcode, and from my research I found two ways to achieve that:

  • Adding the fembed-bitcode flag to the Other C flags option in my project Build Settings (link)
  • Adding a User-defined Setting with the key BITCODE_GENERATION_MODE set to bitcode (link)

Is there any difference between these two options?

The only difference I noted is that by using fembed-bitcode, the resulting static library for iphonesimulator will be built with full bitcode enabled (in my case, binary size changes from 5MB to 13MB, and I can check bitcode support using otool), which doesn't seem to make any difference in its usage.

Rusty answered 23/1, 2016 at 4:53 Comment(0)
F
65

When you build the library normally, with ENABLE_BITCODE=YES, Xcode adds the build flag -fembed-bitcode-marker to any clang invocation, placing an "empty" bitcode in the final o file.

So, if you look to the compile action in the build phase, it will look something like:

CompileC {build_path}/StaticBitcode/StaticLogger.o StaticBitcode/StaticLogger.m normal armv7 objective-c com.apple.compilers.llvm.clang.1_0.compiler cd {path}/StaticBitcode export LANG=en_US.US-ASCII export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c -arch armv7 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=gnu99 -fobjc-arc -fmodules -gmodules -fmodules-cache- [...] -fembed-bitcode-marker [...]

This is true to the build action (independent of the target).

When you Build & Archive, the -fembed flag is replaced by -fembed-bitcode, which really does build a Bitcode enabled binary:

CompileC {build_path}/StaticBitcode/StaticLogger.o StaticBitcode/StaticLogger.m normal armv7 objective-c com.apple.compilers.llvm.clang.1_0.compiler cd {path}/StaticBitcode export LANG=en_US.US-ASCII export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c -arch armv7 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=gnu99 -fobjc-arc -fmodules -gmodules -fmodules-cache- [...] -fembed-bitcode [...]


fembed-bitcode flag

Given that, if you add the -fembed-bitcode flag to the Other C flags, you will be sending two flags to the compiler during the compile time. It maybe silence some warnings that you can receive when using the library linked on another project. But, you need to check if you get the expected behavior. :)

(When I tested using the -fembed-bitcode on the Other C flags, Xcode gave the warning clang: warning: argument unused during compilation: '-fembed-bitcode-marker')


BITCODE_GENERATION_MODE

On the other hand,

If you set BITCODE_GENERATION_MODE=bitcode on your User-defined Setting, even during the build phase, the files will be compiled using the flag -fembed-bitcode.

And, if you set BITCODE_GENERATION_MODE=marker, the files will be compiled using the flag -fembed-bitcode-marker, independent of the action phase.

So, if you want to enable the bitcode to every action (build and archive), the better way to do so is using the BITCODE_GENERATION_MODE setting.


Resources

Fascicule answered 23/1, 2016 at 15:18 Comment(8)
So, in the end, they really are just two different ways of achieving the same result, forcing Xcode to build with bitcode support without using the Archive action? Except that apparently fembed-bitcode will throw a warning along with it.Rusty
Basically, yes. But, I recommend you to use BITCODE_GENERATION_MODE, if you really want to enable bit code to all actions. The duplicated flag may cause more than a warning.Circumvallate
For anyone rusty on how to add User-defined Settings: developer.apple.com/library/ios/recipes/…Bernardo
Is it possible to remove the bitcode after compilation? For instance in a case where a framework has bitcode but the consumer doesn't compile with bitcode enabled support? In that case the bitcode would need to be removed before the consumer would be able to succesfully compile. In a case where the framework wasn't compiled with bitcode and the consumer would have bitcode enabled they wouldn't be able to compile their project as well. So basically the question is how to strip bitcode from the binary :)Burgundy
@AvnerBarr the "over information" was is easy! You don't need to strip the bit code. If you build a framework with bit code enabled and the client app have bit code disabled, the final product will not be affected by the extra content on the framework. The other way around is impossible. The framework need to have bit code to the used in a project with bit code enabled. An example of the bit code behaviour can be seen on this project: github.com/igorcferreira/BitcodeLibraryCircumvallate
I'll try again then. I remember getting errors "Framework was compiled with bitcode enabled". Also , having the bitcode wouldn't bloat the final product?Burgundy
@IgorCastañedaFerreira this was the perfect fix for me. I had a situation where both flags were being set and on Xcode 8.3.2 (possibly earlier) this no longer generated bitcode in the output. Thanks!Lynnettelynnworth
Anybody looking for the Apple forum resource: the link to the new forum is developer.apple.com/forums/thread/3971Valeta

© 2022 - 2024 — McMap. All rights reserved.