How Jumbo Builds Work in the Chromium Source Code

This article explains the mechanics of jumbo builds—commonly known in C++ development as unity builds—within the Chromium web browser project. It covers the fundamental problem of redundant header parsing in standard C++ compilation, how Chromium's build system merges source files into large translation units to drastically reduce compile times, and the code collision challenges developers face when implementing this technique.

The Bottleneck of Traditional C++ Compilation

To understand jumbo builds, you first need to understand how C++ compiles code. A single source file (.cc or .cpp), along with all the header files (.h) it includes, is called a translation unit.

Chromium consists of tens of thousands of source files. In a standard build, the compiler processes each translation unit independently. If 5,000 different .cc files include the same complex header file, the compiler must open, read, and parse that exact same header file 5,000 times. This creates a massive bottleneck in CPU usage, memory allocation, and disk I/O, resulting in build times that can take hours on a single machine.

The Jumbo Build Mechanism

A jumbo build solves the redundant parsing problem by concatenating multiple small translation units into a single, massive translation unit before handing it off to the compiler.

Instead of compiling file_a.cc, file_b.cc, and file_c.cc separately, the build system generates a temporary wrapper file—often named something like jumbo_1.cc—that contains the following code:

#include "path/to/file_a.cc"
#include "path/to/file_b.cc"
#include "path/to/file_c.cc"

When the compiler processes jumbo_1.cc, the C++ preprocessor pulls the contents of all the included .cc files into one continuous stream of code. Because of include guards (like #pragma once or #ifndef) inside the header files, any shared headers used by file_a.cc, file_b.cc, and file_c.cc are only read and parsed once for the entire group.

Implementation in Chromium's Build System

Chromium uses GN (Generate Ninja) to generate its build files. When jumbo builds are enabled in the GN configuration, the build system alters how targets like static libraries and source sets are processed.

  1. Chunking: GN takes the list of .cc files in a given build target and divides them into chunks. A standard chunk size in Chromium is typically around 50 source files, though this can be tuned based on available system memory.
  2. Generation: GN writes out the wrapper .cc files to the build output directory, with each wrapper #include-ing its assigned chunk of source files.
  3. Compilation: The Ninja build tool is instructed to compile only the generated wrapper files rather than the original individual source files.
  4. Linking: Because the compiler outputs one object file (.o or .obj) per jumbo wrapper instead of one per original source file, the linker has significantly fewer files to stitch together, speeding up the final linking phase of the build.

Technical Challenges and Symbol Collisions

While compiling large translation units greatly increases build speed, it alters the scope of the code in ways the original authors may not have intended. In standard C++, symbols inside a .cc file are isolated from other .cc files. In a jumbo build, several .cc files share the exact same translation unit, leading to three main problems:

  • Anonymous Namespace Collisions: Developers frequently use anonymous namespaces (namespace { ... }) or the static keyword to create helper functions or variables that are strictly local to one .cc file. If two files in the same jumbo chunk define a local function with the exact same name and signature (e.g., void LogError()), the compiler will throw a redefinition error because both functions now exist in the same translation unit.
  • Macro Bleeding: Preprocessor macros (#define) do not respect C++ namespaces or scopes. If file_a.cc defines a macro and does not #undef it at the end of the file, that macro remains active when the compiler moves on to file_b.cc within the same jumbo file. This can accidentally alter code or cause syntax errors in subsequent files.
  • Header Pollution: file_a.cc might include a platform-specific header (like <windows.h>) that defines broad, generic types or macros, which then conflict with specific class or variable names used in file_b.cc.

Resolving Jumbo Build Issues in Chromium

To maintain a working jumbo build, Chromium relies on strict coding practices and build system workarounds:

  • Renaming Symbols: Developers must give unique names to functions and variables inside anonymous namespaces across the same module, even though standard C++ does not require it.
  • Cleaning Up Macros: Every #define inside a .cc file must have a corresponding #undef at the bottom of that same file.
  • Exclusion Lists: If a specific .cc file is too difficult to make compatible with a jumbo build (often due to third-party headers or complex macro usage), the GN build file allows developers to add it to a jumbo_excluded_sources list. GN will remove that specific file from the jumbo wrapper and compile it as a traditional, isolated translation unit.