What is xclang?
xclang is a clang toolchain for cross-compiling, the way rustup, cross-rs and cargo-zigbuild let Rust do it: one compiler for every target. One directory holds the compiler, the linker and the binary tools. It also holds, for six targets, the sysroot (the C library's headers and libraries) and the runtimes. Cross-compiling is a --target flag and nothing else:
clang++ --target=aarch64-w64-mingw32 hello.cpp -o hello.exeThe compiler is stock LLVM, with a few patches on their way upstream, built with PGO and ThinLTO for six hosts. The six common targets come with the toolchain, and its xclang command fetches the vendor SDKs that no one may redistribute. xclang's vision goes further: more targets, fetched when a build needs them. None of that is in a release; the roadmap gives each item's status.
What Is in It
- clang and lld, and the LLVM binary tools, as one program (
llvm), linked statically against xclang's own libc++. An archive is 86 to 94 MB. - Six targets in every archive: Linux x64 and arm64 (glibc 2.17), Windows x64 and arm64 (MinGW-w64 with UCRT), macOS arm64 and x64. The macOS targets use Apple's SDK: Xcode's on macOS hosts, and on Linux and Windows hosts the one the
xclangcommand fetches from Apple. Each target has its sysroot, libc++, libc++abi, libunwind and compiler-rt, prebuilt, and a config file that points clang at them. - The MSVC targets, Windows x64 and arm64 with Microsoft's CRT and STL, from every host, against the SDK that the
xclangcommand fetches from Microsoft (MSVC targets). - Programs that run where they are copied. Everything but the OS's own libraries is linked in (hermeticity).
- A CMake package and a Bazel module: the toolchain for the host or any target, and
import stdbuilt for the build. - libclang: the static libraries the clang of the release was linked from, for tools built on clang (libclang).
Who It Is For
People who want a toolchain they can pin, ship and reproduce, and programs that run wherever they are copied:
- Projects that ship programs to many machines: command-line tools, language servers, build tools. A Linux program runs on glibc 2.17 and later. A Windows one needs no redistributable, and a macOS one no Homebrew.
- CI that builds for several targets from one kind of runner, with one compiler version for all of them.
- Teams that want one toolchain on every developer machine and in CI, pinned by version and digest, the same in CMake, Bazel and plain commands.
- C++20 modules with
import std, in CMake and Bazel. - Tools on clang, which link libclang built with PGO.
xclang is developed for clice, whose release builds are its first user. catter builds with it too. xclang's CI builds the tests of kotatsu for Windows from Linux, and runs them on Windows.
Comparisons puts xclang next to the toolchains people use for the same jobs, with what each does better.
Not Yet Supported
Each has its status in the roadmap. Until then, other toolchains serve these:
| status | today, use | |
|---|---|---|
| musl targets | Planned | zig cc, or a musl cross toolchain |
| Android, WebAssembly, bare metal, more Linux architectures | Considered | the NDK, wasi-sdk, zig cc, or a GCC cross toolchain |
| iOS and Apple's other devices | In research | Xcode |
| MemorySanitizer | Planned | |
| Sanitizers for MinGW targets | Considered |
Known Limitations
These follow from what xclang is. Where they do not fit, another toolchain is the better one.
- C++ libraries from another toolchain do not link. xclang's C++ library is libc++, linked into every program. A library built with GCC's libstdc++ (a distribution's Qt or Boost) or with MSVC's STL has another ABI; only the MSVC targets, whose C++ library is Microsoft's STL, link the latter. Build C++ dependencies with xclang for the target, through CMake, Bazel or vcpkg's chain-loaded toolchain file. C libraries are fine.
- C++ objects should not cross shared libraries. Each shared library carries its own libc++. On Linux and macOS, a standard exception from one is caught in another only by
catch (...)(one libc++ per shared object). A plugin system with C++ interfaces needs a shared C++ runtime, which is not planned. - No OpenMP runtime. One is not planned.
- No clang-format, clang-tidy or clangd programs. xclang is a compiler toolchain; they are not planned.
- Not for conda-forge packages. Use conda-forge's compilers, which link its runtime packages; xclang deliberately does not.
Next
- Quick Start: programs for every target, then a CMake project with
import std. - Installation: pixi, archives, FetchContent, Bazel.
- Why xclang?: the case for it.
