Roadmap
What xclang supports today, and the status of everything it does not. Every item that no release carries has one row here, with one status word. Other pages link to that row instead of restating the status. Nothing here has a date. What each release changed is in the CHANGELOG.
| status | meaning |
|---|---|
| Supported | In a release. |
| Unreleased | On main and tested by CI, but no release carries it. |
| Planned | Decided, and in no release yet. It may be in progress on a branch. |
| In research | Wanted. Whether it can be done well is still open. |
| Considered | Wanted. Its form or its cost is still open. |
| Not planned | Out of scope by design. |
The Vision
xclang's vision is what rustup, cross-rs and cargo-zigbuild do for Rust, for clang: one compiler for every target.
- The common targets come with the toolchain, as the six of today do.
- Every other target is an archive of its own, fetched when a build needs it: its sysroot, its prebuilt runtimes and its config file.
- Vendor SDKs that no one may redistribute (Apple's, Microsoft's) are fetched from the vendor by the user, who accepts their license. xclang never redistributes them.
- Runtimes can also be built from source on demand, for options the prebuilt ones lack.
Today, the first and the third are in a release: the six targets, and since 23.1.2.7 Microsoft's and Apple's SDKs, which the user fetches with the xclang command. The rest is planned, in research or considered, item by item, in the tables below.
Every target keeps the hermeticity rule. A program depends at run time only on the libraries of its OS that cannot be redistributed, and links everything else statically.
Targets
A target's tier says how it is tested (tiers). For the targets here, tier 1 can also mean a runner that runs the target's programs: Windows x64 runs x86 programs, wasmtime WebAssembly ones. A tier 3 target may get its runtimes built on demand instead of prebuilt. "The user (SDK)" means the target needs a vendor SDK that the user fetches, accepting its license.
What sets these targets apart:
- MSVC targets. First-class targets, as the MinGW ones are, since 23.1.2.7. The default C runtime is Microsoft's "hybrid CRT": the VC runtime and the STL static, UCRT dynamic. xclang builds their compiler-rt: the builtins, the profile runtime and UBSan, and for x64 AddressSanitizer, whose runtime is a DLL, and libFuzzer. The MSVC and Windows SDK versions are pinned to ones the shipped clang accepts, and the user fetches them with the
xclangcommand, which every toolchain archive carries (Windows). CMake builds them; the Bazel module does not yet (below). - macOS from any host. Since 23.1.2.7. Apple's macOS SDK is in the Command Line Tools package on Apple's update servers, and needs no Apple ID to download. The user fetches it with the
xclangcommand into the toolchain, whose config files then use it on Linux and Windows hosts; on macOS, Xcode's SDK stays the one in use. The programs are those of a macOS host: xclang's libc++ linked in, ld64.lld, dSYMs, the sanitizers (macOS). CMake builds them; the Bazel module does not yet (below). - musl. Static programs that take nothing from the system they run on.
- A newer glibc. The same targets for programs that need what glibc 2.17 lacks, such as
-static-pieand newer functions, with the same runtimes. - Other Linux architectures. Each gets the oldest glibc it has; riscv64 and loongarch64 have nothing as old as 2.17. Their sanitizers are the ones compiler-rt supports on them.
- WebAssembly.
wasm32-wasip2links withwasm-component-ld, which each host's toolchain needs to carry. C++ exceptions are opt-in. - Android. The NDK's sysroot, with xclang's static libc++ in the NDK's ABI namespace (
__ndk1). - iOS and Apple's other devices. Their SDKs come only with full Xcode, downloaded with an Apple ID; xclang cannot remove that limit. Their runtimes are likely to be built on demand.
- Windows 7 and XP. The MSVC target with the CRT linked statically, and YY-Thunks for the functions the old systems lack. MinGW with libc++ cannot reach XP. The goal is to find out how far hermeticity reaches there; Windows 9x is out of scope.
- msvcrt. The MinGW targets use UCRT, which is part of Windows 10 and later. A MinGW variant on the older msvcrt is not planned.
- Emscripten. emsdk is its toolchain, so it is not an xclang target.
The xclang Command
xclang is a program in Rust (cli/), built for every host with xclang as its C compiler and linker. Every toolchain archive carries it, as bin/xclang, since 23.1.2.7 (the xclang command).
xclang sdk fetchdownloads a vendor SDK from the vendor, by version and sha256, once the user accepts its license. It is in every release since 23.1.2.7.xclang target addunpacks a target's archive of the same release into the toolchain: its sysroot, its runtimes, compiler-rt, its config files and the licenses of its C runtime. No release publishes target archives yet, so it has nothing to add.- Each release gets an index of its target archives, as rustup's channel manifests are: archive, sha256, size, tier and the SDK it needs.
- The CMake package and the Bazel module take fetched targets as they come. Today their toolchains build for the six targets of the host's archive, and the CMake package also for the MSVC targets, and for macOS from Linux and Windows hosts, with the fetched SDKs.
- The plan for the MSVC targets in the Bazel module: a repository rule fetches the Windows SDK once the user accepts its license in
MODULE.bazel, and the targets build with the GNU-style clang of the other toolchains. - The plan for macOS from Linux and Windows hosts in the Bazel module: the same repository rule fetches the macOS SDK, which stands in for the one a macOS host's rule finds with
xcrun, and the macOS toolchains are registered on every host.
Runtimes and Tools
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. It covers what the prebuilt runtimes cannot be:
- MemorySanitizer, which needs every library instrumented, libc++ too. ThreadSanitizer also reports better 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.
The prebuilt runtimes stay the default.
Rust and cargo work with xclang today as a recipe of environment variables (Rust and Cargo). A helper that sets them, as cargo-zigbuild's wrapper does, is considered. So is making libgcc_s.a a linker script, INPUT(-lunwind), instead of an empty archive: Rust's Linux targets then link without -l:libunwind.a. A test with 23.1.2.5's arm64 sysroot linked Rust, and C++ programs and shared libraries that name -lgcc_s.
libc++ for MSVC targets gives them the C++ library of every other target, its import std included, and becomes their default. Microsoft's STL stays a choice: C++ types passed between a program and libraries built with MSVC need the same library on both sides.
The not-planned items follow from what xclang is. It is a compiler toolchain, and libclang has the libraries that tools on clang link. Its runtimes are linked into every program (one libc++ per shared object). conda-forge's compilers link packaged runtimes dynamically, which xclang does not do. libclang is there for clice, which builds for MinGW on Windows, so no libclang is built with the MSVC ABI.
Speed
| item | status |
|---|---|
| A PGO training that covers Objective-C, clang-cl, Mach-O links and clang-tidy's checks | Planned |
| BOLT for the Linux hosts' clang and lld, on top of PGO and ThinLTO | In research |
The training is widened between releases, not while one is pending (PGO).
Reproducibility and Supply Chain
- CMake builds write the build tree's absolute paths into debug information. Bazel builds already use paths relative to the execution root (debugging).
- GSYM files from llvm-gsymutil's default threads differ run to run, with the same lookups. One thread is deterministic, about 1.4 times as slow;
xclang_debug_symbolspasses--num-threads=1by default since 23.1.2.7. - Immutable releases keep an archive and its
SHA256SUMSfrom being replaced together (releases). - Reproducible archives, since 23.1.2.7: sorted entries, the commit's time and no owner in the
.tar.xzfiles, xz in fixed blocks whatever its threads; each host's archives are made twice, on two machines, and compared (build). The toolchain builds themselves are not compared. - License notices, since 23.1.2.7: every archive has
share/licenses, each component's license files and an SPDX document (layout).
Following LLVM
| item | status |
|---|---|
| LLVM 23.1.3 and 24.x, each as it is released | Planned |
Each LLVM release is built with the patches checked against it. 23.1.3 has the fix for the macOS 27 SDK's arm64e.x1 stubs, which xclang carries as patch 0009 since 23.1.2.6.
Documentation
| item | status |
|---|---|
| The docs in Chinese | Planned |
The docs are in English only for now. The README has a Chinese version.
Open Questions
Questions inside the items above, not items of their own:
- Android's sysroot: fetched by the user from Google's NDK (only the files it needs), or redistributed by xclang.
- The runtimes of Apple's devices: published prebuilt, or only built on demand. Apple's license treats libraries for those platforms apart from macOS ones.
- A glibc other than 2.17: chosen with a named config file (
--config=), or with a spelling of the target. - Where fetched targets go: into the toolchain directory only, or also into a directory of the user's.
- musl and the sanitizers: none, or a dynamically linked variant (Alpine's way) that has them.
