How We Cut iOS Build Times by 66%: Real-World Xcode Compilation Optimizations

This article details a comprehensive set of practical techniques—ranging from Xcode project configuration tweaks and CocoaPods packaging to CCache, distcc, hardware tricks, PCH usage, and deep Clang/LLVM analysis—that together reduced a massive iOS build from over 27 minutes to under 10 minutes.

WeChat Client Technology Team
WeChat Client Technology Team
WeChat Client Technology Team
How We Cut iOS Build Times by 66%: Real-World Xcode Compilation Optimizations

Preface

Time feels like a pig farm; over the years both my weight and the WeChat codebase have grown. In 2014, compiling the WeChat project on a laptop took about ten minutes; now on a 2017 27‑inch iMac it nears half an hour, and occasional full recompiles appear mysteriously. The low compilation efficiency hurt developer morale, so I requested and received approval to optimize the build process.

Existing Solutions

Before acting, I surveyed current approaches and identified several optimization points:

1. Optimize Project Configuration

1) Change Debug Information Format to DWARF

Debug builds do not need full symbol tables; ensure sub‑projects (especially third‑party libraries) use the correct setting.

2) Set Build Active Architecture Only to Yes

Debug builds do not need to compile all architectures; verify sub‑projects are configured accordingly.

3) Optimize Header Search Paths

Avoid recursive Header Search Paths that cause excessive -I arguments and slow preprocessing. The same applies to Framework Search Paths.

2. Use CocoaPods to Manage Third‑Party Libraries

Package any pod into a static library with cocoapods-packager to avoid repeated compilation, though debugging source code becomes harder.

3. CCache

CCache caches intermediate compilation artifacts without major project changes. It solved an Xcode 9 bug that triggered full recompiles even when sources were unchanged, but Xcode 10 fixed that issue, reducing CCache’s relevance.

4. distcc

distcc distributes compilation tasks across multiple machines, returning object files for final linking.

5. Hardware Solutions

Place the Derived Data directory on a RAM‑disk or upgrade to the latest iMac Pro.

Practical Process

1. Optimize Compilation Options

1) Refine Header Search Paths

Removing recursive paths saved about 20 seconds overall.

2) Disable Enable Index‑While‑Building Functionality

This Xcode 9 feature builds code indexes during compilation, slowing it down. Turning it off shaved roughly 80 seconds.

2. Optimize "kinda" Framework

The cross‑platform C++ payment framework "kinda" compiled extremely slowly (≈30 s per source file) and produced large binaries. Analysis of the LinkMap revealed two main issues:

Excessive code generated from protobuf files.

Heavy template usage in a base class/macros.

For the first issue, set protobuf option optimize_for=CODE_SIZE to generate slimmer code (my own tool produces even fewer lines).

For the second, replace template‑based polymorphism with runtime polymorphism via virtual base classes and use hyper_function instead of std::function. Example before and after:

template <typename Request, typename Response>
class BaseCgi {
public:
    BaseCgi(Request request, std::function<void(Response &)> &callback) {
        _request = request;
        _callback = callback;
    }
    // ...
    Request _request;
    std::function<void(Response &)> _callback;
};

class CgiA : public BaseCgi<RequestA, ResponseA> { /* ... */ };
class BaseRequest { public: virtual void toData(std::vector<uint8_t> &outData) = 0; };
class BaseResponse { public: virtual void fromData(std::vector<uint8_t> &outData) = 0; };

class BaseCgi {
public:
    template <typename Request, typename Response>
    BaseCgi(Request &request, hyper_function<void(Response &)> callback) {
        _request = new Request(request);
        _response = new Response;
        _callback = callback;
    }
    // ...
    BaseRequest *_request;
    BaseResponse *_response;
    hyper_function<void(BaseResponse &)> _callback;
};

class CgiA : public BaseCgi { /* ... */ };

After these changes, compilation speed improved by 70 seconds and the binary size shrank by 60 %.

3. Use Precompiled Header (PCH)

PCH files contain common macros and headers, speeding up subsequent compilations. In Xcode, set Prefix Header and enable Precompile Prefix Header.

WeChat’s build time dropped by roughly 280 seconds after adding PCH.

Ultimate Optimization

Overall, the build time fell from 1,626.4 s to 1,182.8 s , a gain of about 450 seconds, yet still around 20 minutes. Further gains require compiler‑level improvements.

1. Compilation Theory

Compilers translate high‑level code to low‑level code and consist of three parts: Frontend (parses source, builds AST), Optimizer (architecture‑agnostic optimizations), and Backend (generates machine code). LLVM provides a modular framework with an intermediate representation (LLVM IR). In Xcode, Clang serves as the frontend and LLVM as the backend.

Clang’s compilation phases:

➜ clang -ccc-print-phases main.m
0: input, "main.m", objective-c
1: preprocessor, {0}, objective-c-cpp-output
2: compiler, {1}, ir
3: backend, {2}, assembler
4: assembler, {3}, object
5: linker, {4}, image
6: bind-arch, "x86_64", {5}, image

Preprocessing

Handles header inclusion, macro expansion, directives, and comment removal.

Compilation

Performs lexical analysis, syntax analysis (AST generation), static analysis, and IR generation.

Assembly Generation

LLVM optimizes IR according to the selected optimization level (e.g., -O0 for Debug, -Os for Release) and emits platform‑specific assembly.

Object File Generation

The assembler converts assembly to object files (.o).

Linking

The linker combines object files into an executable.

2. Analyzing Bottlenecks

Using Clang’s -ftime-trace option (added by Aras Pranckevičius) we generated Chrome‑compatible JSON traces showing that the Frontend consumed 5,307.9 ms of the total 8,423.8 ms, with header processing dominating.

Further analysis showed that the top‑10 header files accounted for the majority of preprocessing time; optimizing them (reducing recursive includes, using forward declarations) saved additional seconds.

3. Solving the Bottleneck

Replace unnecessary #include directives with forward declarations wherever possible. This required extensive manual work (five days) but yielded an extra 80‑second reduction.

To automate the process, we built a Clang‑based tool that traverses the AST, identifies symbols, and decides whether an #include is truly needed or a forward declaration suffices. The tool builds on Google’s open‑source include‑what‑you‑use (IWYU) and adds Objective‑C support and result pruning.

After applying the tool, the total build time dropped to 710 s . Further profiling identified WCDB header processing as a remaining hotspot; solutions include moving WCDB includes to PCH or isolating them in category headers.

Ultimately, the build time fell below 540 seconds—about one‑third of the original duration.

Optimization Summary

A) Optimize header search paths.

B) Disable Enable Index‑While‑Building Functionality.

C) Reduce protobuf/template bloat.

D) Use precompiled headers (PCH).

E) Employ tools to prune unnecessary includes and avoid embedding the C++ standard library in headers.

Future Outlook

We look forward to the company’s distributed ObjC compilation system and further modularization of business code, as demonstrated by the "kinda", mini‑program, and Mars modules.

References

How to Speed Up iOS Project Build Times by 5×

Deep Dive into iOS Compilation with Clang/LLVM

Clang AST Overview

time‑trace: Timeline/Flame Chart Profiler for Clang

Introduction to the Clang AST

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

iOSCXcodeLLVMClangprecompiled headers
WeChat Client Technology Team
Written by

WeChat Client Technology Team

Official account of the WeChat mobile client development team, sharing development experience, cutting‑edge tech, and little‑known stories across Android, iOS, macOS, Windows Phone, and Windows.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.