HCN DEV

한국어로 보기

Introducing Bitcode

Introducing Bitcode feature image

In this post, I’ve compiled information about what you need to know to introduce Bitcode.

About Bitcode

Bitcode Upload Process

Bitcode is an intermediate representation of a compiled program.
  • Bitcode is an IR (Intermediate Representation) included in binary builds for App Thinning in the App Store. When the uploaded binary includes bitcode, the App Store recompiles and links the binary, generating optimized binaries for each device architecture.
  • App users only download the binary for their device’s architecture when bitcode is enabled, reducing the app size they need to download.
  • To summarize, when uploading a binary to the App Store, the following process occurs:
  1. Upload a single binary with bitcode to the App Store.
  2. The App Store recompiles the binary to generate binaries for different architectures (e.g., arm64, armv7).
  3. App users download the binary for their device’s architecture. (Before bitcode, only a single “fat binary” was used.)

Symbolication for Apps with Bitcode Enabled

  • Recompilation by the App Store during archiving makes dSYM generated during app development unusable. Matching dSYM with the app binary is based on the UUID included in the binary. Hence, when a rebuild occurs (even if there are no code changes), the dSYM from the previous build cannot match the subsequent one. Therefore, dSYMs generated during archiving cannot be used to symbolicate Crash Reports in the App Store.
  • Therefore, when uploading dSYMs to Third Party Crash Analysis platforms after enabling bitcode, it is essential to download the files from Xcode Organizer or iTunes Connect.

bcsymbolmap

  • During archiving, a checkbox in iTunes Connect decides whether to upload the app’s Symbols. Turning off this checkbox causes Xcode to obfuscate the symbols included in the dSYM of the app before binary upload (e.g., “_hidden#109”). These obfuscated symbols are decrypted using a file called .bcsymbolmap. Therefore, dSYM files for bitcode-enabled binaries always include the corresponding .bcsymbolmap.
  • When uploading dSYMs to Third Party Crash Analysis platforms, dSYMs downloaded from Xcode are decrypted and can be uploaded directly. However, dSYMs downloaded directly from iTunes Connect need to be decrypted manually.
xcrun dsymutil -symbol-map <path to BCSymbolMaps in xcarchive> <path to downloaded dSYM directory>

Xcode Build Settings for Bitcode

Xcode has options to include full bitcode or markers indicating bitcode during binary builds.

ENABLE_BITCODE

Setting ENABLE_BITCODE to YES adds flags related to bitcode during source code build and archiving. During the build, the -embed-bitcode-marker flag is added, and during archiving, the -embed-bitcode flag is added. You can see this in the build and archive logs.

  • Build Log
// Build log excerpt
CompileSwift normal arm64 TestObj.swift (in target 'SomeProject' from project 'SomeProject')
...
/Debug-iphoneos/SomeProject.build/Objects-normal/arm64/TestObj.o -embed-bitcode-marker 
...
  • Archive Log
// Archive log excerpt
SwiftCodeGeneration normal arm64 (in target 'SomeProject' from project 'SomeProject')
...
/Release-iphoneos/SomeProject.build/Objects-normal/arm64/TestObj.bc -embed-bitcode -target arm64-apple-ios11.0 -Xllvm -aarch64-use-tbi -O -disable-llvm-optzns -module-name
...

BITCODE_GENERATION_MODE

You can achieve the same effect as ENABLE_BITCODE using BITCODE_GENERATION_MODE in User-Defined Settings. Setting the value to marker adds the -embed-bitcode-marker compile flag, and setting it to bitcode adds the -embed-bitcode flag. You can change this setting to build with full bitcode for certain cases.

Screenshot 2020-05-22 12 59 59

Note: You can also enable bitcode by adding -fembed-bitcode directly to Other C Flags.

Bitcode Support for Library

  • The main drawback of bitcode is that if any library you are using does not support bitcode, you cannot enable bitcode in your app.
  • Here are some considerations for library bitcode support:

Checking if Binary Support Bitcode

To check if a specific library supports bitcode, you can examine whether the library binary contains LLVM Symbols. However, there can be some confusion about which symbols to check, as there are various issues regarding this. In general, you can use the following command to check if a binary supports bitcode:

$ otool -arch arm64 -l MyFramework/MyFramework | grep __LLVM
$ otool -arch armv7 -l myLib.a | grep __LLVM

Bitcode Support for Library distributed via Cocoapods

  • Bitcode is handled during compilation, not linking. Therefore, whether a library binary supports bitcode or not determines whether bitcode can be enabled in your app. For libraries distributed as built binaries or frameworks, if they previously did not support bitcode, you must allow bitcode and rebuild them before redistributing.
  • In the case of CocoaPods, libraries marked as vendored_framework or vendored_libraries fall into this category. If any one library in your app does not support bitcode, your app cannot use bitcode.
  • However, libraries built from source via CocoaPods are built during your app’s build process. Therefore, if you don’t explicitly set ENABLE_BITCODE to NO in your app’s PodFile or PodSpec, these libraries will support bitcode.

References