Building WebRTC with Bitcode

Back in June, Apple introduced bitcode as a part of their app thinning strategy, which allows them to implement some optimizations in the future without developers having to resubmit their apps. Unfortunately, bitcode must be enabled for the whole app, including third-party libraries. This is a problem if you use WebRTC as it does not currently have a build option to enable bitcode.

Because the Talky iOS app uses WebRTC, I decided to investigate what it would take to enable bitcode when building WebRTC. For this post, I assume that you're building a Release build of WebRTC with the steps outlined at http://www.webrtc.org/native-code/ios.

Step 1: Get the code

If you haven't already downloaded the WebRTC source, open a terminal window and follow the steps for "Getting the code".

Warning: Due to the size of the repository and its dependencies, this could take a while.

Step 2: Point to the right version of Xcode

Only Xcode 7 and above can produce bitcode. If you only have Xcode 7 installed, you can skip this step. I tend to have a few versions of Xcode installed, so I like to make sure I'm using the right one for command-line builds.

In a terminal window, run the following command to set the path to a copy of Xcode 7:

sudo xcode-select -s "/Applications/Xcode-beta.app/"

In this case, I'm pointing to my copy of Xcode 7.1 Beta.

Step 3: Link libicucore (can skip if you're on commit fd4df46 or above of WebRTC)

If you're on commit fd4df46fc6dbb4fd5aeb3ae4a7275cb65b02933c (r9866) from 2015-09-05 or above of WebRTC, you can skip this step.

Due to some changes in Xcode 7, you'll need to change how the icucore library is linked. Open webrtc/libjingle_example.gyp in your editor of choice and change the section (line 339 as of this writing) that looks like

'link_settings': {
  'xcode_settings': {
    'OTHER_LDFLAGS': [
      '-framework CFNetwork',
    ],
  },
  'libraries': [
    '$(SDKROOT)/usr/lib/libicucore.dylib',
  ],
}

to look like

'link_settings': {
  'xcode_settings': {
    'OTHER_LDFLAGS': [
      '-framework CFNetwork',
      '-licucore',
    ],
  },
}

Note: If you need to follow this step, you'll need to repeat this anytime you update WebRTC until you've passed the commit mentioned above or your local changes may be overwritten.

Step 4: Enable bitcode

To actually enable bitcode, we need to add a flag to the build configuration. I added it to build/common.gypi to make sure it was applied to every dependency. Open build/common.gypi in your editor of choice and change the section (line 3469 as of this writing) that looks like

'xcode_settings': {
  'DEAD_CODE_STRIPPING': 'YES',  # -Wl,-dead_strip
  'GCC_OPTIMIZATION_LEVEL': '<(mac_release_optimization)',
  'OTHER_CFLAGS': [ '<@(release_extra_cflags)', ],
},

to look like

'xcode_settings': {
  'DEAD_CODE_STRIPPING': 'YES',  # -Wl,-dead_strip
  'GCC_OPTIMIZATION_LEVEL': '<(mac_release_optimization)',
  'OTHER_CFLAGS': [ '<@(release_extra_cflags)', '-fembed-bitcode', ],
},

Note: You'll need to repeat this anytime you update WebRTC or your local changes may be overwritten.

Step 5: Use the right compiler

By default, the build process for WebRTC uses a bundled version of Clang which does not support bitcode. So we need to tell it to use the version of Clang included with Xcode (specifically Xcode 7; see Step 2) instead.

When following the steps for "Compiling the code", add clang_xcode=1 to your GYP_DEFINES environment variable. As an example, here's the full value for a 32-bit iOS build:

export GYP_DEFINES="OS=ios target_arch=arm clang_xcode=1"

Step 6: Compile

Follow the steps for "Compiling the code" remembering to adjust the instructions as per Step 5.

Step 7: Verify

To verify that the build actually includes bitcode, open the out_ios/Release-iphoneos directory. In a terminal window, run otool -l <static-library> | grep __LLVM. As an example:

otool -l libjingle_peerconnection.a | grep __LLVM

According to this forum post, the presence of the __LLVM segment is the best way to determine if the files you just built contain bitcode.

Step 8: Done!

You now have a build of WebRTC that include bitcode.

Enjoy this post? We'd love to invite you to join our mailing list, &you, where we connect with our community and share the latest we're learning.

You might also enjoy reading: