Clang and C++ Modules in Chromium

Overview

Modules in C++ have the potential to significantly speed up building Chromium. With textual inclusion, many headers are re-parsed over 35000 times and with modules could be reduced to the order of 10 times.

Clang supports two types of modules: Clang header modules and C++20 modules (also called Clang Modules and Standard C++ Modules). We're currently exploring Clang header modules because:

  1. Other projects (e.g. internally at Google) have had success deploying them to their code bases with large performance wins.
  2. They can be experimented with without rewrites to the code base or changes to the build system.

We're currently experimenting with modules for libc++ and they can be enabled with the GN arg use_libcxx_modules and use_implicit_libcxx_modules. Using this arg is not currently recommended, due to the limitations mentioned below. It is only interesting to people working on the feature.

Current limitations

Implicit vs explicit modules

use_implicit_libcxx_modules is using implicit modules, which are created on-the-fly when Clang doesn‘t see them in the module cache. This doesn’t work with remote execution since the cached modules aren't known to the build system.

The module cache is set to <outdir>/gen/libcxx/module_cache. Since the modules aren‘t known to ninja they aren’t cleaned with ninja -t clean and need to be manually deleted for a clean build.

We will eventually switch to explicit modules to address these issues, which will require support in GN and has been partially implemented (CL1, CL2, CL3, and crbug.com/gn/373).

use_libcxx_modules enables explicit modules using existing features.

Duplicate modules

Multiple pcm files are created per module. For correctness, Clang header modules default to using a hash of command line args in the module path. For compiling base, we have 19 different flag combinations and ~700 pcm files are created per flag combination for 13483 total pcms.

Some flag combinations produce incompatible modules, like whether RTTI is turned on or off. For most others, we expect that the resulting modules from slight flag variations (e.g. setting include preprocessor defines unrelated to libc++) are compatible with each other and can be reused.

Performance

With Chrome's Clang plugins turned on, modules perform worse than without modules even if fully cached (crbug.com/351909443).

Building with modules and a cold module cache is much slower than without modules. This seems unexpected since Clang should still be doing less work.

Correctness

When the module cache is cold, there are occasional build failures when ninja parallelism is high enough. I don't see it with 20 jobs but see it with 130 jobs (crbug.com/351865290).