CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
76 lines
3.8 KiB
ReStructuredText
76 lines
3.8 KiB
ReStructuredText
=====================
|
|
Header Removal Policy
|
|
=====================
|
|
|
|
Policy
|
|
------
|
|
|
|
Libc++ is in the process of splitting larger headers into smaller modular
|
|
headers. This makes it possible to remove these large headers from other
|
|
headers. For example, instead of including ``<algorithm>`` entirely it is
|
|
possible to only include the headers for the algorithms used. When the
|
|
Standard indirectly adds additional header includes, using the smaller headers
|
|
aids reducing the growth of top-level headers. For example ``<atomic>`` uses
|
|
``std::chrono::nanoseconds`` and included ``<chrono>``. In C++20 ``<chrono>``
|
|
requires ``<format>`` which adds several other headers (like ``<string>``,
|
|
``<optional>``, ``<tuple>``) which are not needed in ``<atomic>``.
|
|
|
|
The benefit of using minimal headers is that the size of libc++'s top-level
|
|
headers becomes smaller. This improves the compilation time when users include
|
|
a top-level header. It also avoids header inclusion cycles and makes it easier
|
|
to port headers to platforms with reduced functionality.
|
|
|
|
A disadvantage is that users unknowingly depend on these transitive includes.
|
|
Thus removing an include might break their build after upgrading a newer
|
|
version of libc++ by reducing the set of declarations provided by a header.
|
|
For example, ``<algorithm>`` is often forgotten but using algorithms will
|
|
still work through those transitive includes. This problem is solved by modules,
|
|
however in practice most people do not use modules (yet).
|
|
|
|
To ease the removal of transitive includes in libc++, libc++ will remove
|
|
unnecessary transitive includes in newly supported C++ versions. This means
|
|
that users will have to fix their missing includes in order to upgrade to a
|
|
newer version of the Standard. Libc++ also reserves the right to remove
|
|
transitive includes at any other time, however new language versions will be
|
|
used as a convenient way to perform bulk removals of transitive includes.
|
|
|
|
However, libc++ intends not to gratuitously break users on stable versions of
|
|
the Standard. Hence, we intend to maintain backwards compatibility of the
|
|
declarations we provide in a header, within reason. We reserve the right to
|
|
break such backwards compatibility in the future, however we will strive to
|
|
do it in a user-friendly way, again within reason. For libc++ developers, this
|
|
means that any transitive include removal of a public header must be guarded by
|
|
something of the form:
|
|
|
|
.. code-block:: cpp
|
|
|
|
#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 23
|
|
# include <algorithm>
|
|
# include <iterator>
|
|
# include <utility>
|
|
#endif
|
|
|
|
Occasionally, private headers may also be included transitively for backwards
|
|
compatibility in the same manner. We currently strive to provide backwards
|
|
compatibility on the set of declarations provided by a header in all Standard
|
|
modes starting with **C++23**. Note that this is very difficult to actually
|
|
enforce, so this is done only on a best effort basis.
|
|
|
|
When users define ``_LIBCPP_REMOVE_TRANSITIVE_INCLUDES``, libc++ will not include
|
|
transitive headers, regardless of the language version. This can be useful for users
|
|
to aid the transition to a newer language version, or by users who simply want to
|
|
make sure they include what they use in their code. However, note that defining this
|
|
macro means that the set of declarations and transitive includes provided by the library
|
|
may change from release to release, which can break your code.
|
|
|
|
|
|
Rationale
|
|
---------
|
|
|
|
Removing headers is not only an issue for software developers, but also for
|
|
vendors. When a vendor updates libc++ several of their upstream packages might
|
|
fail to compile, forcing them to fix these packages or file a bug with their
|
|
upstream packages. Usually upgrading software to a new language standard is
|
|
done explicitly by software developers. This means they most likely will
|
|
discover and fix the missing includes, lessening the burden for the vendors.
|