Mobile Development 24 min read

Migrating ByteDance's iOS Build System to Bazel: Challenges, Architecture, and Outcomes

The article details ByteDance's transition from CocoaPods‑based component management to a Bazel‑driven monorepo build system, describing the problems faced, the two‑stage migration process, the BitSky build service architecture, custom plugin mechanisms, and the performance gains achieved after the migration.

ByteDance Terminal Technology
ByteDance Terminal Technology
ByteDance Terminal Technology
Migrating ByteDance's iOS Build System to Bazel: Challenges, Architecture, and Outcomes

In recent years ByteDance's iOS engineering team (referred to as "TouTiao") has evolved through several stages: starting in 2016 with CocoaPods and a monolithic repository, moving to multi‑repo and binary components in 2017, and finally reducing CI build time by 50% in early 2021 using a CC macro to integrate Dolphin's clang wrapper.

These improvements introduced side effects such as the need for highly standardized binary components (preventing custom macros), network‑dependent component downloads (over 30% of build time for 500+ components), and low cache reuse due to missing context when using the CC macro.

To address these issues, ByteDance explored a Monorepo + Bazel solution. The advantages of Bazel include code reuse, shared dependency management, unified builds, and simplified version control.

The migration is divided into two phases. Phase 1 focuses on business components, converting roughly 10,000 source files to Bazel (3.x) and achieving noticeable build‑time reductions. Phase 2 targets third‑party components, converting about 18,000 files to Bazel (5.x), removing CocoaPods entirely, and improving build stability.

BitSky Build Service

BitSky is the core of the build system, using Bazel to manage compilation, linking, testing, and custom toolchains. The article first introduces Bazel concepts before describing BitSky's layered architecture.

Bazel Concepts

Bazel, originally Google’s internal Blaze, supports client and server software builds (including iOS and Android) and offers extensible Rules written in Starlark (a Python subset). Hermeticity ensures reproducible builds by isolating the environment and dependencies.

Key Bazel entities include:

BUILD files – describe build rules and dependencies (similar to .podspec files).

WORKSPACE – manages external dependencies (analogous to a Podfile).

Packages – directories containing BUILD files.

Targets – individual build rules such as libraries or binaries.

Labels – identifiers for rules and dependencies.

BitSky Architecture

The system consists of five layers:

Engineering Configuration : Makefile defines semantic commands; plugins provide hook functions and custom toolchain configuration.

Software Services : BitSky, Tulsi, and BuildService tools enable Bazel‑based Xcode project generation and IDE integration.

Build System : Bazel engine, Dep Server (dependency correction), and Remote Execution Services for distributed builds.

Build Rules : Embedded Rules (objc_library, cc_library), Apple Rules (apple_binary, apple_library), and a bazel_generator that converts .podspec files into BUILD files.

Build Tools : Wrapped Tools (portable compiler/linker binaries) and Custom Toolchains (host‑specific toolchain definitions).

Component Migration Details

During migration, each .podspec is parsed, a corresponding BUILD file is generated (including name , srcs , deps , and copts ), dependencies are translated from CocoaPods to Bazel, resources are mapped to the data attribute, and other configuration items (e.g., header search paths) are handled.

Business components are fully source‑coded under a Module directory, while third‑party components reside in External and are managed via monorepo_config.yml and deps.yml for version and dependency tracking.

Plugin‑Based Engineering Configuration

BitSky uses a plugin system to inject custom build options without coupling the host project to Bazel. Four hook functions are provided in hook.py :

pre_generate_material_hook(obj) / post_generate_material_hook(obj) – run before/after generating WORKSPACE and BUILD files.

pre_build_hook(obj) / post_build_hook(obj) – run before/after the actual build (e.g., for cleanup or packaging).

Custom build parameters are centralized in defs.bzl , allowing per‑target copts to be passed to Bazel rules such as ios_application . The .bazelrc file is used to propagate runtime options, including Xcode version configuration via --xcode_version_config=//conditions:host_xcodes .

Conditions ( //conditions:default , //conditions:debug , //conditions:release , etc.) enable selective rule application based on build configuration, mirroring Xcode's Debug/Release settings.

Challenges and Solutions

Key challenges during migration included third‑party dependency governance, artifact consistency verification, and build‑environment unification. ByteDance employed internal tools to resolve version conflicts, added .podspec dependency information, and used a Mach‑O and .linkmap based verification tool to compare pre‑ and post‑migration binaries. Build‑environment differences across Xcode versions were mitigated by defining supported Xcode versions in conditions/BUILD and referencing them in .bazelrc .

Results

After Phase 1, build‑time PCT50 dropped by 38% and average time by 45%. Following Phase 2, PCT50 decreased by 20%, PCT90 by 50%, and overall build time was cut in half. The monorepo approach also streamlined dependency management and accelerated architectural evolution.

In summary, migrating to Bazel and adopting a monorepo strategy significantly improved build performance, stability, and developer productivity for ByteDance's iOS projects, while laying the groundwork for further tooling and workflow enhancements.

iOSci/cdautomationMonorepoBuild SystemBazel
ByteDance Terminal Technology
Written by

ByteDance Terminal Technology

Official account of ByteDance Terminal Technology, sharing technical insights and team updates.

0 followers
Reader feedback

How this landed with the community

login 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.