chromium/docs/modules.md

# 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](https://commondatastorage.googleapis.com/chromium-browser-clang/include-analysis.html)
and with modules could be reduced to the order of 10 times.

Clang supports two types of modules:
[Clang header modules](https://clang.llvm.org/docs/Modules.html) and
[C++20 modules](https://clang.llvm.org/docs/StandardCPlusPlusModules.html) (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`. 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

We're 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](https://gn-review.googlesource.com/c/gn/+/9601),
[CL2](https://gn-review.googlesource.com/c/gn/+/9602),
[CL3](https://gn-review.googlesource.com/c/gn/+/9680), and
[crbug.com/gn/373](https://crbug.com/gn/373)).

### 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](https://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](https://crbug.com/351865290)).