Louis Dionne | b126981 | 2022-03-23 13:40:15 -0400 | [diff] [blame] | 1 | ================================================== |
| 2 | Capturing configuration information in the headers |
| 3 | ================================================== |
Eric Fiselier | 5cf9a82 | 2015-10-13 22:12:02 +0000 | [diff] [blame] | 4 | |
| 5 | .. contents:: |
| 6 | :local: |
| 7 | |
| 8 | The Problem |
| 9 | =========== |
| 10 | |
Louis Dionne | b126981 | 2022-03-23 13:40:15 -0400 | [diff] [blame] | 11 | libc++ supports building the library with a number of different configuration options. |
| 12 | In order to support persistent configurations and reduce arbitrary preprocessor logic |
| 13 | in the headers, libc++ has a mechanism to capture configuration options in the |
| 14 | installed headers so they can be used in the rest of the code. |
Eric Fiselier | 5cf9a82 | 2015-10-13 22:12:02 +0000 | [diff] [blame] | 15 | |
| 16 | |
| 17 | Design Goals |
| 18 | ============ |
| 19 | |
Louis Dionne | b126981 | 2022-03-23 13:40:15 -0400 | [diff] [blame] | 20 | * The solution should be simple, consistent and robust to avoid subtle bugs. |
Eric Fiselier | 5cf9a82 | 2015-10-13 22:12:02 +0000 | [diff] [blame] | 21 | |
Louis Dionne | b126981 | 2022-03-23 13:40:15 -0400 | [diff] [blame] | 22 | * Developers should test the code the same way it will be deployed -- in other words, |
| 23 | the headers used to run tests should be the same that we install in order |
| 24 | to avoid bugs creeping up. |
Eric Fiselier | 5cf9a82 | 2015-10-13 22:12:02 +0000 | [diff] [blame] | 25 | |
Louis Dionne | b126981 | 2022-03-23 13:40:15 -0400 | [diff] [blame] | 26 | * It should allow different targets or flavors of the library to use a different |
| 27 | configuration without having to duplicate all the libc++ headers. |
Eric Fiselier | 5cf9a82 | 2015-10-13 22:12:02 +0000 | [diff] [blame] | 28 | |
| 29 | |
| 30 | The Solution |
| 31 | ============ |
| 32 | |
Louis Dionne | b126981 | 2022-03-23 13:40:15 -0400 | [diff] [blame] | 33 | When you first configure libc++ using CMake, a ``__config_site`` file is generated |
| 34 | to capture the various configuration options you selected. The ``__config`` header |
| 35 | used by all other headers includes this ``__config_site`` header first in order to |
| 36 | get the correct configuration. |
Eric Fiselier | 5cf9a82 | 2015-10-13 22:12:02 +0000 | [diff] [blame] | 37 | |
Louis Dionne | b126981 | 2022-03-23 13:40:15 -0400 | [diff] [blame] | 38 | The ``__config_site`` header is hence the only place where persistent configuration |
| 39 | is stored in the library. That header essentially reflects how the vendor configured |
| 40 | the library. As we evolve the library, we can lift configuration options into that |
| 41 | header in order to reduce arbitrary hardcoded choices elsewhere in the code. For |
| 42 | example, instead of assuming that a specific platform doesn't provide some functionality, |
| 43 | we can create a generic macro to guard it and vendors can define the macro when |
| 44 | configuring the library on that platform. This makes the "carve off" reusable in |
| 45 | other circumstances instead of tying it tightly to a single platform. |
Eric Fiselier | 5cf9a82 | 2015-10-13 22:12:02 +0000 | [diff] [blame] | 46 | |
Louis Dionne | b126981 | 2022-03-23 13:40:15 -0400 | [diff] [blame] | 47 | Furthermore, the Clang driver now looks for headers in a target-specific directory |
| 48 | for libc++. By installing the ``__config_site`` header (and only that header) to |
| 49 | this target-specific directory, it is possible to share the libc++ headers for |
| 50 | multiple targets, and only duplicate the persistent information located in the |
| 51 | ``__config_site`` header. For example: |
Eric Fiselier | 5cf9a82 | 2015-10-13 22:12:02 +0000 | [diff] [blame] | 52 | |
Louis Dionne | b126981 | 2022-03-23 13:40:15 -0400 | [diff] [blame] | 53 | .. code-block:: bash |
Eric Fiselier | 5cf9a82 | 2015-10-13 22:12:02 +0000 | [diff] [blame] | 54 | |
Louis Dionne | b126981 | 2022-03-23 13:40:15 -0400 | [diff] [blame] | 55 | include/c++/v1/ |
| 56 | vector |
| 57 | map |
| 58 | etc... |
Eric Fiselier | 5cf9a82 | 2015-10-13 22:12:02 +0000 | [diff] [blame] | 59 | |
Louis Dionne | b126981 | 2022-03-23 13:40:15 -0400 | [diff] [blame] | 60 | include/<targetA>/c++/v1/ |
| 61 | __config_site |
Eric Fiselier | 5cf9a82 | 2015-10-13 22:12:02 +0000 | [diff] [blame] | 62 | |
Louis Dionne | b126981 | 2022-03-23 13:40:15 -0400 | [diff] [blame] | 63 | include/<targetB>/c++/v1/ |
| 64 | __config_site |
Eric Fiselier | 5cf9a82 | 2015-10-13 22:12:02 +0000 | [diff] [blame] | 65 | |
Louis Dionne | b126981 | 2022-03-23 13:40:15 -0400 | [diff] [blame] | 66 | When compiling for ``targetA``, Clang will use the ``__config_site`` inside |
| 67 | ``include/<targetA>/c++/v1/``, and the corresponding ``__config_site`` for |
| 68 | ``targetB``. |