Faster Mix-and-Match Builds with Precompiled Bridging Headers

An examination of build times of Xcode projects that mix Objective-C and Swift, which can contain large bridging headers, shows that the Swift compiler spends a lot of time re-processing the same bridging headers for all the Swift files in a project. In certain projects, each additional Swift file increases the overall build time noticeably, even when the Swift file is quite modest.

This post will discuss this compile-time cost, and how it is being addressed in Swift 3.1.

The Problem

Every time a Swift file in a mixed-language target is compiled, the Swift compiler parses the project’s bridging header in order to make Objective-C code visible to Swift code. When the bridging header is large and the Swift compiler runs many times – as in a debug configuration – the cost of repeatedly parsing the bridging header can be a substantial part of the overall build time.

The Solution

In Swift 3.1, the compiler has gained a new mode to reduce this cost: precompiling bridging headers. When this mode is enabled, instead of repeatedly parsing the bridging header for each Swift file in a mixed-language target, the bridging header is parsed only once, and the result (a temporary “precompiled header” or “PCH” file) is cached and reused across all Swift files in the target. This leverages the same precompiled header technology that is used to precompile prefix headers in Objective-C and C++ code.

In the Swift project this mode was developed and tested against, it reduced debug build time by 30%. The speedup depends on the size of a project’s bridging header, and the mode does not affect whole-module-optimization builds. But it can significantly improve compile times when iterating in debug configuration.

Trying it out

This mode is part of Swift 3.1 and is available in nightly snapshots on swift.org, as well as in Xcode 8.3 beta. It is currently experimental and must be manually enabled; in future releases, if developer feedback indicates it’s working well and providing significant speedup, it will be enabled by default. To try it out in the meantime, install a compiler that supports it, open the build settings for your project and set “Other Swift Flags” to contain the option -enable-bridging-pch:

Enabling bridging PCH

Reporting feedback

If you have a project with a large bridging header, please try using this new mode. If you encounter problems, please file a bug in either Swift.org’s bug-tracking system or Apple’s. General feedback is also welcome by emailing the swift-users@swift.org mailing list, or on Twitter (mention #SwiftBridgingPCH).