From f5bc5c8acf5839cdee95596bf57d2ff0f159a8ae Mon Sep 17 00:00:00 2001
From: clice-bot <306533837+clice-bot@users.noreply.github.com>
Date: Fri, 9 Oct 2026 21:03:56 +0000
Subject: [PATCH] docs: sync xclang
---
en/xclang/design/roadmap.md | 33 +++--
en/xclang/dev/testing.md | 28 +++-
en/xclang/features/runtimes-from-source.md | 152 +++++++++++++++++++++
en/xclang/features/sanitizers.md | 11 +-
en/xclang/guide/comparisons.md | 2 +-
en/xclang/guide/why-xclang.md | 2 +-
en/xclang/integrations/bazel.md | 7 +
en/xclang/integrations/cmake.md | 10 ++
en/xclang/reference/bazel-api.md | 26 +++-
en/xclang/reference/cmake-api.md | 39 +++++-
en/xclang/reference/layout.md | 14 ++
en/xclang/sidebar.yaml | 2 +
12 files changed, 307 insertions(+), 19 deletions(-)
create mode 100644 en/xclang/features/runtimes-from-source.md
diff --git a/en/xclang/design/roadmap.md b/en/xclang/design/roadmap.md
index 540fae9ae..df29ad944 100644
--- a/en/xclang/design/roadmap.md
+++ b/en/xclang/design/roadmap.md
@@ -171,8 +171,10 @@ its C compiler and linker. Every toolchain archive carries it, as
| item | status |
|---|---|
-| libc++, libc++abi and libunwind built from source on demand | Planned |
-| MemorySanitizer, through libc++ built on demand | Planned |
+| libc++, libc++abi and libunwind built from source on demand | Unreleased |
+| MemorySanitizer, through libc++ built on demand | Unreleased |
+| Runtimes from source for the MSVC targets | Planned |
+| LTO of the runtimes from source with the program, in Bazel | Considered |
| Sanitizers for MinGW targets | Considered |
| ASan, TSan, LSan and libFuzzer for musl targets, with a dynamically linked musl (Alpine's way) | Considered |
| `@xclang//bazel:llvm-gsymutil`, the toolchain's llvm-gsymutil for `bazel run` | Supported |
@@ -187,16 +189,29 @@ its C compiler and linker. Every toolchain archive carries it, as
**libc++ built on demand** means libc++, libc++abi and libunwind built from
source inside a CMake or Bazel build, from LLVM's runtime sources of the
-release, with its [patches](../reference/patches.md). It covers what the
-prebuilt runtimes cannot be:
-
-- **MemorySanitizer**, which needs every library instrumented, libc++ too.
- ThreadSanitizer also reports better through an instrumented libc++.
+release, with its [patches](../reference/patches.md), which every toolchain
+carries in `libc++/src`
+([runtimes from source](../features/runtimes-from-source.md)). On `main`,
+the CMake package's toolchain file (`XCLANG_RUNTIMES=source`) and the Bazel
+module (`--@xclang//runtimes:source`) build them for every target but the
+MSVC ones. They cover what the prebuilt runtimes cannot be:
+
+- **MemorySanitizer**, which needs every library instrumented, libc++ too,
+ and compiler-rt's runtime of it, built with them. ThreadSanitizer and
+ AddressSanitizer also report through an instrumented libc++.
- **Hardening and ABI options**: a hardening mode checked inside the
library, libc++'s ABI version 2, bounded iterators, an ABI namespace of
one's own, and builds without exceptions or RTTI.
-- **LTO and PGO** of libc++ together with the program.
-- **Targets without prebuilt runtimes**: tier 3 ones and Apple's devices.
+- **LTO** of libc++ together with the program, in CMake builds. Bazel runs
+ ThinLTO's backends only for the objects of the libraries it knows, which
+ the runtimes, linked by the toolchain, are not: making them such
+ libraries is considered.
+- **Targets without prebuilt runtimes**: tier 3 ones and Apple's devices,
+ once they are targets.
+
+The MSVC targets' libc++ builds on Microsoft's C++ ABI library with
+clang-cl, against the fetched SDK; building it from source there is
+planned.
The prebuilt runtimes stay the default.
diff --git a/en/xclang/dev/testing.md b/en/xclang/dev/testing.md
index 33ed1462b..33ce9fef8 100644
--- a/en/xclang/dev/testing.md
+++ b/en/xclang/dev/testing.md
@@ -44,8 +44,8 @@ rest are called by them, by release.yml, or started by hand.
|---|---|---|---|---|---|
| docs.yml | every push and pull request, by itself | | | | `tests/docs/docs.ts` and the types (`npm run check`); on `main`, then publishing to docs.clice.io |
| test-archives.yml | `tests/toolchain`, `tests/libclang`, `toolchain/config` | stage `test` | | | `tests/toolchain/smoke.ts` and `tests/libclang/libclang.ts` on a machine of each host; the programs the smoke test builds for other targets run on those (on-target.yml); with `repack-of`, `tests/release/repack.ts`: each host's archives against those of the release repacked (or of an earlier run of the same revision, which a full rebuild must give again), file by file, only the packaging's files differ |
-| test-cmake.yml | `packages/cmake`, `tests/cmake`, `tests/libclang` | stage `cmake` | the tag fetched from GitHub | | `tests/cmake/cmake.ts`: the package by `PATH`, through the toolchain file, and from FetchContent |
-| test-bazel.yml | `packages/bazel`, `tests/bazel` | stage `bazel`: `tests/bazel` only | ✓ | ✓ | `tests/bazel` with the module, `tests/bazel/bazel.ts`, and cross builds run on the target (`tests/bazel/cross.ts`) |
+| test-cmake.yml | `packages/cmake`, `tests/cmake`, `tests/libclang`, `toolchain/runtimes-src.ts`, `toolchain/cmake/caches` | stage `cmake` | the tag fetched from GitHub | | `tests/cmake/cmake.ts`: the package by `PATH`, through the toolchain file, from FetchContent, and with the runtimes from source; their programs for other targets run there (on-target.yml) |
+| test-bazel.yml | `packages/bazel`, `tests/bazel`, `toolchain/runtimes-src.ts` | stage `bazel`: `tests/bazel` and the runtimes from source | ✓ | ✓ | `tests/bazel` with the module, `tests/bazel/bazel.ts`, the runtimes from source (`tests/bazel/runtimes.ts`), and cross builds run on the target (`tests/bazel/cross.ts`) |
| test-sdk.yml | `tests/sdk`, `toolchain/config`, `packages/cmake` | stage `sdk`; needs `cli`, as the archives' `xclang` fetches the SDKs | | | the MSVC targets (`tests/sdk/msvc.ts`) and the macOS targets from Linux and Windows hosts (`tests/sdk/macos.ts`); their programs on Windows and Macs |
| cli.yml | `xclang`, `tests/cli`, `tests/sdk` | the build, for stage `package`; stage `cli` | | ✓ | the `xclang` command: rustfmt, clippy, unit tests, `tests/cli/cli.ts`, `tests/cli/cargo.ts` |
| examples.yml | `examples` | | once conda.clice.io has the release and `latest` names it | ✓ | the commands and `examples/` of the docs, as written; the programs for other targets on their runners |
@@ -164,6 +164,19 @@ Ninja 1.11, and with the newest of both:
downloads `SHA256SUMS` and the host toolchain.
4. `tests/libclang` with the ThinLTO cache. A second link takes every
module's code from the cache, and the program is the same.
+5. **The runtimes from source**, with a toolchain that has their sources
+ (the archives action adds this checkout's to a release before them):
+ `tests/cmake/runtimes` once per variant, through the toolchain file.
+ With no options they are the prebuilt runtimes again: the same
+ `__config_site` and module sources, and for Linux and MinGW the same
+ code. A hardening mode traps on a read past a vector's end; an ABI
+ namespace and ABI macros of its own, without exceptions and RTTI, name
+ the code of `import std` in the program; on Linux x64, MemorySanitizer
+ reports a use of uninitialized memory inside libc++ and nothing of what
+ libc++ itself writes, and libc++ of ThinLTO is bitcode. From Linux x64
+ (to Linux arm64 and both MinGW targets) and arm64 macOS (to x86_64
+ macOS), with the newest CMake, the hardening variant's programs run on a
+ machine of the target (on-target.yml).
`tests/cmake` covers a C++ module of partitions, `xclang::std` with
`std.compat`, `xclang_add_std` with `-fno-exceptions`, and
@@ -216,6 +229,17 @@ and libclang; a Linux host runs the musl tests of its architecture
`modules_embed_all_files`, an importer cannot open the source of the
module it imports.
+`tests/bazel/runtimes.ts`, after them, builds `tests/bazel/runtimes` with the
+runtimes from source (`--@xclang//runtimes:source`), with a toolchain that
+has their sources, once per variant: with no options, the prebuilt
+`__config_site` again; a hardening mode that traps; an ABI namespace and
+ABI macros without exceptions and RTTI, which the code of `import std` is
+named with; on Linux x64, `--features=msan` reporting inside libc++ and not
+on what it writes, and `--features=thin_lto`. From Linux x64 and arm64
+macOS, the hardening variant for other targets runs on their machines.
+`packages/bazel/runtimes.ts check` (by hand) says whether
+`runtimes_sources.bzl` is still what LLVM's CMake build compiles.
+
test-bazel.yml's cross jobs build `tests/bazel` on every host for every
other target, and run its tests on a runner of that target. Its sdk jobs do
the same for the targets of the vendor SDKs, the module accepting their
diff --git a/en/xclang/features/runtimes-from-source.md b/en/xclang/features/runtimes-from-source.md
new file mode 100644
index 000000000..ebaf9c550
--- /dev/null
+++ b/en/xclang/features/runtimes-from-source.md
@@ -0,0 +1,152 @@
+# C++ Runtimes from Source
+
+xclang's prebuilt C++ runtimes are one build of libc++, libc++abi and
+libunwind per target: no hardening mode, ABI version 1, exceptions and
+RTTI, no instrumentation but the ASan libc++
+([sanitizers](sanitizers.md)). A CMake or Bazel build can instead compile
+them from the sources every toolchain carries, with options of its own, and
+link its programs against those. This is for what the prebuilt runtimes
+cannot be:
+
+- **MemorySanitizer**, which needs every library instrumented, libc++ too,
+ and compiler-rt's runtime of it, which the toolchain does not carry.
+ ThreadSanitizer and AddressSanitizer report through an instrumented
+ libc++ too.
+- **libc++'s hardening modes**, checked inside the library as well as in
+ its headers.
+- **ABI options**: libc++'s ABI version 2, bounded iterators, an inline
+ namespace of one's own.
+- **No exceptions, no RTTI** in libc++ and libc++abi.
+- **LTO of libc++ with the program** (CMake).
+
+The prebuilt runtimes stay the default. Runtimes from source are in no
+release yet ([Unreleased](../design/roadmap.md#libc-on-demand)); the
+toolchains of the release after 23.1.2.10 carry the sources.
+
+## Usage
+
+### CMake
+
+The option is the toolchain file's, `XCLANG_RUNTIMES=source`, with
+libc++'s options next to it:
+
+
+```sh
+cmake -G Ninja -B build --toolchain "$XCLANG/lib/cmake/xclang/toolchain.cmake" \
+ -DXCLANG_RUNTIMES=source -DXCLANG_LIBCXX_HARDENING=fast
+cmake --build build
+```
+
+The first configure builds the variant, about half a minute on four cores,
+into `build/xclang-runtimes/-`; later configures use it, and
+other options make another variant beside it. Every compile and link of the
+build is against it, CMake's own checks too, and `xclang::std` is built
+from its modules. A MemorySanitizer build, which builds compiler-rt's
+runtime of it first:
+
+
+```sh
+cmake -G Ninja -B build-msan --toolchain "$XCLANG/lib/cmake/xclang/toolchain.cmake" \
+ -DXCLANG_RUNTIMES=source -DXCLANG_SANITIZER=memory -DCMAKE_BUILD_TYPE=RelWithDebInfo
+```
+
+`XCLANG_SANITIZER` gives the whole build its `-fsanitize=` and runtimes
+that suit it, so the project's flags need no `-fsanitize=` of their own.
+With the prebuilt runtimes it works too, for the sanitizers they have:
+`address` then links the prebuilt ASan libc++.
+
+For another target, add `-DXCLANG_TARGET=`: the variant is built for
+it, by the same toolchain file.
+
+### Bazel
+
+The flags of the whole build are in `@xclang//runtimes`, and the
+sanitizers are the features they always were:
+
+
+```sh
+bazel build --@xclang//runtimes:source --@xclang//runtimes:hardening=fast //...
+bazel test --@xclang//runtimes:source --features=msan //...
+```
+
+The runtimes are libraries of the toolchain's repository, compiled for the
+target platform with the build's features (a sanitizer's instrumentation)
+and `--copt`, and cached as any other action. A `.bazelrc` names the
+variants a project uses:
+
+```text
+build:msan --@xclang//runtimes:source --features=msan
+build:hardened --@xclang//runtimes:source --@xclang//runtimes:hardening=extensive
+```
+
+## Options
+
+| | CMake (toolchain file) | Bazel |
+|---|---|---|
+| runtimes from source | `XCLANG_RUNTIMES=source` | `--@xclang//runtimes:source` |
+| libc++'s hardening mode: `none`, `fast`, `extensive`, `debug` | `XCLANG_LIBCXX_HARDENING` | `--@xclang//runtimes:hardening` |
+| libc++'s ABI version, `1` or `2` | `XCLANG_LIBCXX_ABI_VERSION` | `--@xclang//runtimes:abi_version` |
+| libc++'s inline namespace, `__` | `XCLANG_LIBCXX_ABI_NAMESPACE` | `--@xclang//runtimes:abi_namespace` |
+| libc++'s ABI macros, `_LIBCPP_ABI_*` | `XCLANG_LIBCXX_ABI_DEFINES` (a list) | `--@xclang//runtimes:abi_defines` (comma-separated) |
+| libc++ and libc++abi without exceptions | `XCLANG_RUNTIMES_EXCEPTIONS=OFF` | `--@xclang//runtimes:exceptions=false` |
+| libc++ without RTTI (and without exceptions) | `XCLANG_RUNTIMES_RTTI=OFF` | `--@xclang//runtimes:rtti=false` |
+| sanitizers: `address`, `memory`, `thread`, `undefined`, `leak` | `XCLANG_SANITIZER` | `--features=asan`, `msan`, `tsan`, `ubsan`, `lsan` |
+| more compile options of libc++ and libc++abi | `XCLANG_RUNTIMES_FLAGS` | the build's `--copt` |
+| LTO of libc++ with the program | `XCLANG_RUNTIMES_FLAGS=-flto=thin` | not available |
+| more options of LLVM's CMake build | `XCLANG_RUNTIMES_CMAKE_ARGS` | |
+| where the variants are built | `XCLANG_RUNTIMES_DIR` | Bazel's output base and caches |
+
+The program's own options are its own: a build without exceptions passes
+`-fno-exceptions` (`CMAKE_CXX_FLAGS`, `--copt`) as well. The
+[CMake API](../reference/cmake-api.md#runtimes-from-source) and the
+[Bazel API](../reference/bazel-api.md#runtimes-from-source) list them again.
+
+## Behavior
+
+- **The same build as the prebuilt runtimes.** CMake builds LLVM's
+ `runtimes/` with the CMake cache and options of xclang's own build of
+ the runtimes, by the toolchain file and the config file of the target.
+ With no options, the result is the prebuilt runtimes: the same
+ `__config_site`, and the same code. Bazel compiles the same translation
+ units with the same flags, which `packages/bazel/runtimes.ts` takes from
+ LLVM's CMake build of every target.
+- **What is built**: libc++ with libc++abi in it, libc++experimental, and
+ libunwind (none for macOS, which unwinds with the system's). With
+ MemorySanitizer, compiler-rt's runtime of it.
+- **In place of the prebuilt ones.** The variant's `__config_site` comes
+ before libc++'s other headers, and its libraries are linked instead of
+ the prebuilt ones (`-nostdlib++`). `import std` follows the variant:
+ `xclang::std` and `@xclang//bazel:std` are built from it.
+- **libunwind stays uninstrumented** with sanitizers, as in the prebuilt
+ ASan libc++: the sanitizers' runtimes unwind with it, and MemorySanitizer
+ would report the registers it reads.
+- **MemorySanitizer is for the Linux targets** (glibc), x64 and arm64. Its
+ runtime is linked into executables as clang links the others, whole, with
+ its interface exported.
+- **Every library of a program must use the same variant.** A library
+ built against the prebuilt runtimes, with another ABI namespace, ABI
+ version or set of ABI macros, does not link, or breaks at run time; under
+ MemorySanitizer, its code reports what it was not instrumented to see.
+- **Bazel does not run ThinLTO on the runtimes**: `--features=thin_lto`
+ links programs of ThinLTO against runtimes of native code. Bazel's ThinLTO
+ backends compile the objects of the libraries it knows, and the toolchain
+ links the runtimes' by their paths.
+- **CMake needs Python 3**, as LLVM's build of the runtimes does. Bazel
+ needs nothing more.
+
+## The Sources
+
+Every toolchain directory has the sources once, for every target, in
+`libc++/src`, next to libc++'s headers: llvm-project's own layout
+(`runtimes/`, `cmake/`, `llvm/cmake/`, `libcxx/`, `libcxxabi/`,
+`libunwind/`, `compiler-rt/`, and the headers of LLVM's libc that libc++
+includes), without tests and documentation, with xclang's
+[patches](../reference/patches.md) of libc++ applied. They are 35 MB
+unpacked, 2.3 MB of each archive.
+
+## Not Yet Supported
+
+| | status |
+|---|---|
+| [Runtimes from source for the MSVC targets](../design/roadmap.md#runtimes-msvc) | Planned |
+| [LTO of the runtimes with the program in Bazel](../design/roadmap.md#runtimes-bazel-lto) | Considered |
diff --git a/en/xclang/features/sanitizers.md b/en/xclang/features/sanitizers.md
index 36923b4af..d1d823dfd 100644
--- a/en/xclang/features/sanitizers.md
+++ b/en/xclang/features/sanitizers.md
@@ -281,9 +281,12 @@ clang++ --target=x86_64-unknown-linux-musl -fsanitize=undefined -O1 ubsan.cpp -o
|---|---|
| [Sanitizers for MinGW targets](../design/roadmap.md#mingw-sanitizers) | Considered |
| [ASan, TSan, LSan and libFuzzer for musl targets](../design/roadmap.md#musl-sanitizers) | Considered |
-| [MemorySanitizer](../design/roadmap.md#msan) | Planned |
+| [MemorySanitizer](../design/roadmap.md#msan) | Unreleased |
MemorySanitizer needs every library instrumented, libc++ too, and
-ThreadSanitizer reports better through an instrumented libc++. Both need
-libc++ built from source with the options of the program, which is
-[planned](../design/roadmap.md#libc-on-demand).
+compiler-rt's runtime of it, which the toolchain does not carry. On `main`,
+the runtimes built from source give it both, for the Linux targets
+([runtimes from source](runtimes-from-source.md)): `XCLANG_RUNTIMES=source`
+with `XCLANG_SANITIZER=memory` in CMake, `--@xclang//runtimes:source` with
+`--features=msan` in Bazel. ThreadSanitizer and AddressSanitizer report
+through runtimes from source as well, instrumented like the program.
diff --git a/en/xclang/guide/comparisons.md b/en/xclang/guide/comparisons.md
index 43e563bc9..cd01f719c 100644
--- a/en/xclang/guide/comparisons.md
+++ b/en/xclang/guide/comparisons.md
@@ -180,7 +180,7 @@ libclang.
| [Android](../design/roadmap.md#android), [WebAssembly](../design/roadmap.md#wasm), [the BSDs](../design/roadmap.md#freebsd), [bare metal](../design/roadmap.md#bare-metal) | Considered | the NDK, wasi-sdk, zig cc |
| [iOS and Apple's other devices](../design/roadmap.md#ios) | In research | Xcode |
| [Windows 7 and XP](../design/roadmap.md#windows-7) | In research | llvm-mingw's msvcrt variant |
-| [Runtimes built from source with other options: MemorySanitizer, libc++ hardening, an ABI of one's own](../design/roadmap.md#libc-on-demand) | Planned | zig cc builds its runtimes on first use |
+| [Runtimes built from source with other options: MemorySanitizer, libc++ hardening, an ABI of one's own](../design/roadmap.md#libc-on-demand) | Unreleased | zig cc builds its runtimes on first use |
## Known Limitations
diff --git a/en/xclang/guide/why-xclang.md b/en/xclang/guide/why-xclang.md
index e936538fb..3e4f7f3d8 100644
--- a/en/xclang/guide/why-xclang.md
+++ b/en/xclang/guide/why-xclang.md
@@ -123,7 +123,7 @@ FetchContent or the Bazel registry.
| | status |
|---|---|
| [More Linux architectures, WebAssembly, Android, BSDs, bare metal](../design/roadmap.md#targets) | Considered |
-| [MemorySanitizer, through libc++ built on demand](../design/roadmap.md#msan) | Planned |
+| [MemorySanitizer, through libc++ built on demand](../design/roadmap.md#msan) | Unreleased |
| [Sanitizers for MinGW targets](../design/roadmap.md#mingw-sanitizers) | Considered |
| [Relative debug paths in CMake builds](../design/roadmap.md#cmake-relative-paths) | Planned |
| [Immutable releases](../design/roadmap.md#immutable-releases) | Planned |
diff --git a/en/xclang/integrations/bazel.md b/en/xclang/integrations/bazel.md
index 25d793377..a1638980a 100644
--- a/en/xclang/integrations/bazel.md
+++ b/en/xclang/integrations/bazel.md
@@ -228,6 +228,13 @@ sanitizers. The MSVC targets have `ubsan`, and x64 also has `asan`. ASan's
runtime there is a DLL, which a program finds beside itself or on `PATH`
([MSVC targets](../features/sanitizers.md#msvc-targets)).
+With `--@xclang//runtimes:source`, libc++, libc++abi and libunwind are
+built from the toolchain's sources, instrumented by the build's sanitizer
+features, and `msan` works too, for the Linux targets
+([runtimes from source](../features/runtimes-from-source.md#bazel)); the
+same flag takes libc++'s hardening and ABI options. It is in no release
+yet.
+
## Debug in gdb, lldb and VS Code
Every path in the debug information is relative to the execution root
diff --git a/en/xclang/integrations/cmake.md b/en/xclang/integrations/cmake.md
index b6a1d906d..7ec116f99 100644
--- a/en/xclang/integrations/cmake.md
+++ b/en/xclang/integrations/cmake.md
@@ -257,6 +257,16 @@ importer's ([matching options](../features/modules.md#behavior)). So:
Before putting ccache in front of the compiler, read
[build caches and modules](../features/modules.md#build-caches-and-modules).
+## Build the C++ Runtimes from Source
+
+With the toolchain file, `-DXCLANG_RUNTIMES=source` builds libc++,
+libc++abi and libunwind from the toolchain's sources at the first
+configure, with options the prebuilt ones lack: MemorySanitizer
+(`-DXCLANG_SANITIZER=memory`), libc++'s hardening modes, ABI options, no
+exceptions. The whole build, `xclang::std` included, is then against
+them. It is in no release yet
+([runtimes from source](../features/runtimes-from-source.md#cmake)).
+
## Ship Debug Symbols
`xclang_debug_symbols()` makes the debug symbols of a program
diff --git a/en/xclang/reference/bazel-api.md b/en/xclang/reference/bazel-api.md
index 523d8c949..c8339fabd 100644
--- a/en/xclang/reference/bazel-api.md
+++ b/en/xclang/reference/bazel-api.md
@@ -58,7 +58,8 @@ Windows unless it names one of those.
| feature | default | |
|---|---|---|
-| `asan`, `tsan`, `ubsan`, `lsan` | off | sanitizers, for the whole build (`--features=asan`); `asan` compiles and links with the ASan libc++. None for the MinGW targets; for the MSVC targets `ubsan`, and `asan` for x64 |
+| `asan`, `tsan`, `ubsan`, `lsan` | off | sanitizers, for the whole build (`--features=asan`); `asan` compiles and links with the ASan libc++, or with the runtimes from source instrumented by it. None for the MinGW targets; for the MSVC targets `ubsan`, and `asan` for x64 |
+| `msan` | off | MemorySanitizer, for the whole build, with the runtimes from source (`--@xclang//runtimes:source`), which then include its runtime; Linux targets (glibc). In no release yet |
| `cpp_modules` | off | C++20 modules: `module_interfaces` of a `cc_library`/`cc_binary`, scanned by clang-scan-deps; needs `--experimental_cpp_modules` |
| `gc_sections` | Linux targets: on in `opt`; Windows targets: off | lld's `--gc-sections`, lld-link's `/opt:ref` for the MSVC targets ([why not for Windows](../design/windows.md#gc-sections-and-static-initializers)) |
| `thinlto_cache` | on | the linker's ThinLTO cache, with flags only when `XCLANG_THINLTO_CACHE` names a directory |
@@ -76,6 +77,29 @@ A feature is turned on for a build with `--features=`, off with
`--features=-`, and for one target with `features = [""]` or
`["-"]`.
+## Runtimes from Source
+
+In no release yet ([Unreleased](../design/roadmap.md#libc-on-demand)).
+Flags of the whole build, in `@xclang//runtimes`
+([runtimes from source](../features/runtimes-from-source.md)):
+
+| flag | default | |
+|---|---|---|
+| `--@xclang//runtimes:source` | `false` | libc++ (with libc++abi), libc++experimental and libunwind built from the toolchain's `libc++/src` for the target platform, with the build's features and `--copt`, and every compile and link against them in place of the prebuilt ones. Not for the MSVC targets |
+| `--@xclang//runtimes:hardening` | `none` | libc++'s hardening mode: `none`, `fast`, `extensive`, `debug` |
+| `--@xclang//runtimes:abi_version` | `1` | libc++'s ABI version, `1` or `2` |
+| `--@xclang//runtimes:abi_namespace` | `__` | libc++'s inline namespace, `__` |
+| `--@xclang//runtimes:abi_defines` | none | libc++'s ABI macros, `_LIBCPP_ABI_*`, comma-separated |
+| `--@xclang//runtimes:exceptions` | `true` | `false`: libc++ and libc++abi without exceptions |
+| `--@xclang//runtimes:rtti` | `true` | `false`: libc++ without RTTI; needs `exceptions=false` |
+
+The runtimes are libraries of the host toolchain's repository, compiled as
+LLVM's CMake build compiles them (`bazel/runtimes_sources.bzl`) in a
+configuration of their own, the build's with `@xclang//runtimes:building`
+set, whose toolchain is the same without them. The build's sanitizer
+features instrument libc++ and libc++abi, not libunwind or
+MemorySanitizer's runtime. No runtime is compiled with ThinLTO.
+
## Targets and Rules
| label | |
diff --git a/en/xclang/reference/cmake-api.md b/en/xclang/reference/cmake-api.md
index 7af2eefbc..01c9ed68b 100644
--- a/en/xclang/reference/cmake-api.md
+++ b/en/xclang/reference/cmake-api.md
@@ -15,6 +15,8 @@ Ninja Multi-Config generator, with Ninja 1.11 or later.
| `xclang-config.cmake` | `find_package(xclang)`: `xclang::std`, `xclang_add_std()`, `xclang_debug_symbols()`, `XCLANG_ROOT`, the ThinLTO cache |
| `xclang-config-version.cmake` | the release, for `find_package(xclang 23.1)` (toolchain archives only) |
| `toolchain.cmake` | the toolchain directory as the toolchain of a build, for the host or `XCLANG_TARGET` |
+| `runtimes.cmake` | included by `toolchain.cmake`: the runtimes built from source, and the build's sanitizers (from the release after 23.1.2.10) |
+| `runtimes-cxx.cmake`, `runtimes-compiler-rt.cmake` | the CMake caches of xclang's own builds of libc++ and compiler-rt, which `runtimes.cmake` builds with |
| `xclang.cmake` | in `packages/cmake/` only: included before `project()` from a FetchContent checkout, it downloads the toolchain |
## `find_package(xclang)`
@@ -33,7 +35,9 @@ must be xclang's `clang++`. It finds the package through `PATH`
| `XCLANG_THINLTO_CACHE` | cache variable | an absolute directory for the ThinLTO cache of the linker; its first value comes from the environment variable of the same name ([the ThinLTO cache](../features/thinlto-cache.md#usage)) |
`xclang::std` asks its importers for C++23, or for the `CMAKE_CXX_STANDARD`
-it was built with if that is 20 or later.
+it was built with if that is 20 or later. With `XCLANG_RUNTIMES=source`, it
+is built from the variant's modules and headers; that option needs the
+toolchain file, and `find_package(xclang)` fails without it.
## `toolchain.cmake`
@@ -46,6 +50,7 @@ cmake -G Ninja -B build --toolchain $XCLANG/lib/cmake/xclang/toolchain.cmake [-D
| `XCLANG_TARGET` | `x86_64-unknown-linux-gnu`, `aarch64-unknown-linux-gnu`, `x86_64-unknown-linux-musl`, `aarch64-unknown-linux-musl`, `x86_64-w64-mingw32`, `aarch64-w64-mingw32`, `aarch64-apple-darwin`, `x86_64-apple-darwin`, `x86_64-pc-windows-msvc` or `aarch64-pc-windows-msvc`; the host's by default. The MSVC targets, and the macOS targets on Linux and Windows hosts, build with the SDK that the toolchain's `xclang` fetched. The musl targets, from 23.1.2.10 on, are no cross build on a Linux host of their architecture, which runs their static programs (`try_run`, tests) |
| `XCLANG_ROOT` | the toolchain directory, when the file is used from outside one |
| `XCLANG_MSVC_STL` | `ON`: an MSVC target's C++ library is Microsoft's STL, not libc++ (`-stdlib=platform` in `CMAKE_CXX_FLAGS`), and `xclang::std` the STL's; ignored for other targets |
+| `XCLANG_RUNTIMES`, `XCLANG_SANITIZER`, ... | the runtimes built from source and the build's sanitizers ([below](#runtimes-from-source)) |
It sets the C, C++ and ASM compilers, and the binary tools, to those of the
toolchain directory: `llvm-ar`, `llvm-ranlib`, `llvm-nm`, `llvm-objcopy`,
@@ -81,6 +86,38 @@ stops if that has no SDK. It sets `CMAKE_SYSTEM_NAME` to `Darwin`,
`x86_64`, `CMAKE__COMPILER_TARGET` (C, C++, ASM, Objective-C), and
the SDK as `CMAKE_FIND_ROOT_PATH`, with the modes above.
+### Runtimes from Source
+
+In no release yet ([Unreleased](../design/roadmap.md#libc-on-demand)).
+`runtimes.cmake`, which the toolchain file includes, reads these
+variables ([runtimes from source](../features/runtimes-from-source.md)):
+
+| variable | |
+|---|---|
+| `XCLANG_RUNTIMES` | `prebuilt`, the default: the toolchain's runtimes. `source`: libc++ (with libc++abi), libc++experimental and libunwind built from the toolchain's `libc++/src` for the target, with the options below, at the first configure that asks for the variant; every compile and link of the build is against them in place of the prebuilt ones, `try_compile`'s too. Not for the MSVC targets |
+| `XCLANG_SANITIZER` | a list of `address`, `memory`, `thread`, `undefined`, `leak`: `-fsanitize=` on every compile and link of the build, and runtimes that suit it. With the prebuilt runtimes, `address` adds the ASan libc++ where the target has one, and `memory` stops the configure; with `source`, the runtimes are built with the sanitizers (`LLVM_USE_SANITIZER`), and `memory` builds compiler-rt's MemorySanitizer runtime too, linked into executables |
+| `XCLANG_LIBCXX_HARDENING` | `none`, `fast`, `extensive` or `debug`: libc++'s hardening mode (`LIBCXX_HARDENING_MODE`), of the library and the default of its headers |
+| `XCLANG_LIBCXX_ABI_VERSION` | `1` or `2` (`LIBCXX_ABI_VERSION`) |
+| `XCLANG_LIBCXX_ABI_NAMESPACE` | libc++'s inline namespace, `__` (`LIBCXX_ABI_NAMESPACE`) |
+| `XCLANG_LIBCXX_ABI_DEFINES` | a list of libc++'s ABI macros, such as `_LIBCPP_ABI_BOUNDED_ITERATORS` (`LIBCXX_ABI_DEFINES`) |
+| `XCLANG_RUNTIMES_EXCEPTIONS` | `OFF`: libc++ and libc++abi without exceptions |
+| `XCLANG_RUNTIMES_RTTI` | `OFF`: libc++ without RTTI; needs `XCLANG_RUNTIMES_EXCEPTIONS=OFF` |
+| `XCLANG_RUNTIMES_FLAGS` | more compile options of libc++ and libc++abi, such as `-flto=thin` |
+| `XCLANG_RUNTIMES_CMAKE_ARGS` | more arguments of the runtimes' CMake build, LLVM's `runtimes/`, `-D=` each |
+| `XCLANG_RUNTIMES_DIR` | where the variants are built, `-` each; `${CMAKE_BINARY_DIR}/xclang-runtimes` by default |
+
+The options but `XCLANG_RUNTIMES` and `XCLANG_SANITIZER` need
+`XCLANG_RUNTIMES=source`. A variant's directory holds its CMake builds
+(`runtimes`, and with MemorySanitizer `compiler-rt`), their logs, and
+`install`: `include/c++/v1`, the headers, `__config_site` among them, which
+come before the config file's with `-nostdinc++`; `lib`, the libraries,
+linked with `-nostdlib++` and, but for macOS and with sanitizers,
+`--unwindlib=none`; `lib/libc++.modules.json` and `share/libc++/v1`, the
+modules of `xclang::std`. Its name is a digest of the options, the target
+and the toolchain, so a variant is built once per build directory, and
+another set of options builds another beside it. The build needs Python
+3, as LLVM's does.
+
## `xclang.cmake`
Included before `project()`, from a FetchContent checkout of the tag of a
diff --git a/en/xclang/reference/layout.md b/en/xclang/reference/layout.md
index 6d0916b34..3db7d2e88 100644
--- a/en/xclang/reference/layout.md
+++ b/en/xclang/reference/layout.md
@@ -24,6 +24,9 @@ xclang/
libc++/include//c++/v1/
each target's own __config_site, as
clang spells it (x86_64-w64-windows-gnu)
+ libc++/src/ the runtimes' sources, the same for every target,
+ in llvm-project's layout, patched (below); in the
+ releases after 23.1.2.10
mingw-w64/include/ mingw-w64's headers, the same for both Windows
targets
share/licenses/ the license notices of everything in the archive
@@ -81,6 +84,17 @@ SDK's, so `--no-default-config` would find xclang's headers without a
`__config_site` there instead of the system's. Before 23.1.2.7 each target
directory had its own copies, 155 MB of the 800 MB unpacked.
+## The Runtimes' Sources
+
+`libc++/src` holds what the runtimes of every target are built from, once:
+llvm-project's `runtimes/`, `cmake/`, `llvm/cmake/`, `libcxx/`,
+`libcxxabi/`, `libunwind/` and `compiler-rt/`, without tests and
+documentation, and the headers of LLVM's libc that libc++ includes, with
+xclang's patches of them applied. The CMake package and the Bazel module
+build the runtimes from them ([runtimes from source](../features/runtimes-from-source.md)),
+LLVM's `runtimes/` as from a checkout. They are 35 MB unpacked, in the
+releases after 23.1.2.10.
+
## Licenses
Every archive, the toolchain, libclang, the ASan libclang and the option
diff --git a/en/xclang/sidebar.yaml b/en/xclang/sidebar.yaml
index a19137a9d..817b53173 100644
--- a/en/xclang/sidebar.yaml
+++ b/en/xclang/sidebar.yaml
@@ -32,6 +32,8 @@ features:
- file: modules
label: Modules
- sanitizers
+ - file: runtimes-from-source
+ label: Runtimes from Source
- file: debugging
label: Debugging
- file: libclang