| ================================================== |
| Capturing configuration information in the headers |
| ================================================== |
| |
| .. contents:: |
| :local: |
| |
| 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: |
| |
| .. code-block:: 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``. |