How Chromium Strips Debug Symbols and Compresses PAK Files

This article explains the final stages of the Chromium build process, focusing on how the browser reduces its file size for end-user distribution. It covers the automated stripping of bulky debugging symbols from compiled binaries and the aggregation and compression of static assets—such as user interface elements, strings, and images—into optimized PAK files before packaging everything into a final installer.

Configuring the Release Build

Chromium uses GN (Generate Ninja) to generate its build files and Ninja to execute the build. When preparing Chromium for final distribution, developers configure GN with specific release flags, most notably is_official_build = true and is_debug = false.

These flags instruct the compiler (Clang) and the linker (LLD) to optimize the code for size and speed, while simultaneously triggering the post-processing pipelines responsible for stripping symbols and compressing resources.

Stripping Unneeded Debug Symbols

When Chromium's C++ source code is compiled, the resulting binaries contain massive amounts of debugging information. This data maps compiled machine code back to the original source code lines, variable names, and function calls. While essential for developers, this data can make a binary several gigabytes in size, which is impractical for end-user downloads.

Chromium separates and removes this data differently depending on the target operating system, ensuring the final executable remains small while preserving the symbols separately for crash reporting tools like Crashpad.

Linux and Android

On Linux and Android, debugging information is stored directly inside the compiled ELF binaries using the DWARF format. During an official build, Ninja runs a two-step extraction and stripping process using LLVM toolchain utilities:

  1. Extraction: The build system uses llvm-objcopy (or eu-strip) to copy the debugging sections out of the main binary (e.g., chrome or libchrome.so) and into a separate symbol file (e.g., chrome.debug).
  2. Stripping: The build system then runs llvm-strip on the main binary. This removes all .debug_* sections and unneeded symbol tables, reducing the binary size by up to 90%. A small build ID is left behind so crash reports can later be matched to the external .debug file on a symbol server.

Windows

On Windows, Chromium avoids embedding debug symbols into the main executables (.exe and .dll) altogether. When lld-link links the binaries, it automatically generates Program Database (.pdb) files alongside the executables.

Because the symbols are already separated into .pdb files, no explicit "stripping" tool needs to be run on the executable. The build system simply excludes the .pdb files when gathering files for the final installer.

macOS

On macOS, the compiler embeds DWARF debug data into the object files. During the build process, a tool called dsymutil links these debug sections into an external .dSYM bundle. Afterward, the standard strip command is executed on the main Chromium Mach-O binary to remove the local symbol table entries before the .app bundle is finalized.

Compressing Resources into PAK Files

A web browser requires thousands of static files to function, including HTML, CSS, and JavaScript for internal pages (like chrome://settings), UI icons, and localized text strings for dozens of languages. Reading thousands of individual files from the hard drive at startup would severely degrade performance. Chromium solves this by packing these assets into single-file archives with the .pak extension.

The Role of GRIT

Chromium uses a custom Python-based tool called GRIT (Google Resource and Internationalization Tool) to manage and compile static resources.

  1. Resource Definitions: Developers list all required assets in XML-based .grd (GRIT Resource Description) files. These files define where an asset is located, its unique ID, and how it should be processed.
  2. Inlining and Minification: When the build starts, GRIT reads the .grd files. If an HTML file references external CSS or JavaScript files, GRIT flattens them by inlining the code into a single file. It also strips out comments and unnecessary whitespace to reduce file size.
  3. Individual Asset Compression: Before packing the files together, GRIT compresses individual text and web assets. In the .grd file, assets are tagged with compression attributes (such as compress="brotli" or compress="gzip"). GRIT compresses these specific files in memory using Brotli (preferred for its high compression ratio and fast decompression) or Gzip. Images like PNGs are also optimized using internal build scripts to strip metadata and reduce color palettes without losing quality.
  4. Header Generation: GRIT generates C++ header files (.h) that map human-readable resource names (e.g., IDR_NEW_TAB_HTML) to numerical IDs. The Chromium C++ code uses these IDs to request the exact resource at runtime.

The Repack Step

During the compilation of Chromium's various sub-components (like the Blink rendering engine, the V8 JavaScript engine, and the browser UI), GRIT generates dozens of intermediate .pak files.

To optimize file system performance, the build system executes a repack step near the end of the build. A script merges these dozens of smaller .pak files into a few master files:

  • resources.pak: Contains non-image resources like internal HTML, JS, and CSS.
  • chrome_100_percent.pak and chrome_200_percent.pak: Contain UI images and icons scaled for standard and high-DPI displays.
  • locales/[lang].pak: Contains translated strings for specific languages (e.g., en-US.pak).

The .pak format itself is a simple binary structure consisting of a file header, an index mapping numerical IDs to byte offsets, and the contiguous block of raw (or pre-compressed Brotli/Gzip) data. Because the .pak container itself is not compressed as a whole, Chromium can memory-map the file at startup, jump directly to a specific byte offset using the index, and read a single resource into memory instantly without decompressing the entire archive.

Final Installer Distribution

Once the binaries are stripped of their debug symbols and the static resources are repacked into .pak files, the build system stages the required files into a clean directory.

As a final step, a platform-specific packaging script compresses this entire directory into a distributable installer. On Windows, for example, the staged files are archived into chrome.7z using LZMA compression and bundled into mini_installer.exe. When a user runs the installer, it extracts the clean binaries and the .pak files directly to the user's hard drive, resulting in a fast, lightweight installation.