| # Capturing configuration information in the headers | |
| ```{contents} | |
| :local: true | |
| ``` | |
| ## The Problem | |
| libc++ supports building the library with a number of different configuration options. | |
| In order to support persistent configurations and reduce arbitrary preprocessor logic | |
| in the headers, libc++ has a mechanism to capture configuration options in the | |
| installed headers so they can be used in the rest of the code. | |
| ## Design Goals | |
| - The solution should be simple, consistent and robust to avoid subtle bugs. | |
| - Developers should test the code the same way it will be deployed -- in other words, | |
| the headers used to run tests should be the same that we install in order | |
| to avoid bugs creeping up. | |
| - It should allow different targets or flavors of the library to use a different | |
| configuration without having to duplicate all the libc++ headers. | |
| ## The Solution | |
| When you first configure libc++ using CMake, a `__config_site` file is generated | |
| to capture the various configuration options you selected. The `__config` header | |
| used by all other headers includes this `__config_site` header first in order to | |
| get the correct configuration. | |
| The `__config_site` header is hence the only place where persistent configuration | |
| is stored in the library. That header essentially reflects how the vendor configured | |
| the library. As we evolve the library, we can lift configuration options into that | |
| header in order to reduce arbitrary hardcoded choices elsewhere in the code. For | |
| example, instead of assuming that a specific platform doesn't provide some functionality, | |
| we can create a generic macro to guard it and vendors can define the macro when | |
| configuring the library on that platform. This makes the "carve off" reusable in | |
| other circumstances instead of tying it tightly to a single platform. | |
| Furthermore, the Clang driver now looks for headers in a target-specific directory | |
| for libc++. By installing the `__config_site` header (and only that header) to | |
| this target-specific directory, it is possible to share the libc++ headers for | |
| multiple targets, and only duplicate the persistent information located in the | |
| `__config_site` header. For example: | |
| ```bash | |
| include/c++/v1/ | |
| vector | |
| map | |
| etc... | |
| include/<targetA>/c++/v1/ | |
| __config_site | |
| include/<targetB>/c++/v1/ | |
| __config_site | |
| ``` | |
| When compiling for `targetA`, Clang will use the `__config_site` inside | |
| `include/<targetA>/c++/v1/`, and the corresponding `__config_site` for | |
| `targetB`. |