Skip to content

Comparisons ​

The toolchains people use for the jobs xclang does, what each does, and where xclang differs, in both directions. Facts are as of 2026-10-06, from the documentation of each project, linked. Corrections are welcome as issues.

In One Table ​

what it istargets out of the boxsysroots and SDKsC++ runtime in programsLinux programs run onbuild systemscompiler built with PGO
xclangclang, lld and six targets' runtimes, prebuiltLinux x64/arm64, Windows x64/arm64 (MinGW, MSVC), macOS x64/arm64bundled; Apple's and Microsoft's SDKs fetched by the user from the vendor, or Xcode'slibc++, static; for MSVC targets, Microsoft's STL, staticglibc 2.17+CMake package, Bazel module, condayes, PGO + ThinLTO, every host
zig cc 0.17Zig's driver around its clangdozens: glibc, musl, MinGW, macOS, BSDs, WASIlibc sources and stubs bundled, built on first uselibc++, staticany glibc version chosen per target; 2.31 by defaultzig build; CC="zig cc"not stated
cargo-zigbuildzig cc as cargo's linkerLinux, macOS, as its README liststhrough zig; macOS SDK from the userthrough zigglibc version chosen per targetcargoas zig
cross-rscargo in Docker images with GCC cross toolchainsmost of Rust's Linux, Windows and other targetsper-target images; Apple and MSVC images built by the userlibstdc++2.31; 2.17 in :centos imagescargono; GCC
llvm-mingwclang, lld, mingw-w64 and LLVM's runtimesWindows i686, x86_64, armv7, arm64bundledlibc++ DLL by default, static with -staticno Linux targetsany, through <target>-clang namesyes, PGO + ThinLTO
conda-forge compilersGCC, clang, MSVC activation packagesthe conda platforms, in recipessysroot_linux-* packagesshared, from libstdcxx/libcxx packages via run_exportsglibc 2.17+, or 2.28 by opt-inconda-build, rattler-buildnot stated
LLVM releasesupstream binariesthe host onlynonehost runtimes onlythe host's glibc; the toolchain is built on Ubuntu 22.04noneLinux, macOS: PGO + ThinLTO; Windows: PGO
distro clang + GCC crossOS packagesone package set per targetdistro packages per targetlibstdc++, sharedthe distribution's glibcanydepends on the distribution
Android NDKclang and bionic sysrootsAndroid ABIs × API levelsbundledlibc++, static or sharedAndroidCMake, ndk-buildyes, with BOLT
wasi-sdkclang and wasi-libcwasm32-wasip1, wasip2bundledlibc++, staticWASICMake toolchain filenot stated
toolchains_llvm (Bazel)rules around LLVM's release binariesthe host; cross with a user sysrootthe user'slibc++ static natively, the sysroot's libstdc++ when crossthe sysroot'sBazelas LLVM
hermetic_cc_toolchain (Bazel)rules around zig ccLinux glibc and musl, windows-gnu, macOS "not well tested"through ziglibc++, staticchosen per targetBazelas zig

zig cc ​

zig cc is the closest in spirit: one download, -target, and nothing else. It is where a cross-compiling clang without a sysroot to install was shown to work. It differs from xclang in how it gets there:

  • It builds the runtimes on first use. Zig ships the sources of libc++, libc++abi, libunwind, compiler-rt and several C libraries. It builds what a target needs the first time, then caches it (overview). That is how it fits dozens of targets in a 55 MB download. xclang ships the runtimes of its six targets prebuilt: no first-build delay, and the same bytes for everyone. Fetching other targets as prebuilt archives is planned.
  • It has more targets today: musl, any glibc version per target (x86_64-linux-gnu.2.17), the BSDs and WASI. It also builds for macOS from any host, with Apple's libc headers and a libSystem stub (0.17.0 release notes). In xclang, musl targets are planned, and a newer glibc and the BSDs are considered. xclang builds for macOS from any host too, with Apple's own SDK, which the user fetches (macOS).
  • Its clang is Zig's. 0.17.0 has LLVM 22, with loop vectorization disabled to work around a regression since 0.16.0. xclang follows LLVM's releases with stock clang, built with PGO and ThinLTO.
  • Runtimes. zig links libc++ statically, as xclang does, and has open issues with libc++ in more than one shared object (#24831). It ships no ASan runtime (#11403), and its windows-msvc target uses an installed Visual Studio. xclang has ASan, TSan, LSan, UBSan and libFuzzer for Linux and macOS, and its MSVC targets build from every host against an SDK the user fetches, with UBSan, and ASan and libFuzzer for x64.
  • Integration. zig cc is a drop-in CC. xclang adds a CMake package with import std, a Bazel module, and libclang.

Zig's issue tracker moved to Codeberg in November 2025; the GitHub issues above are as they were then.

cargo-zigbuild and cross-rs ​

cargo-zigbuild makes zig cc the C compiler and linker of cargo. Its README lists Linux and macOS targets, and a glibc version per target.

cross-rs runs cargo inside Docker or Podman images that hold a GCC cross toolchain per target. cross test runs tests under QEMU. Its default images have glibc 2.31, or 2.17 in the :centos ones. It provides no images for Apple targets "due to licensing reasons".

xclang works with cargo as zig does for cargo-zigbuild, with stock clang and xclang's runtimes. Today that is a documented recipe (Rust and Cargo); a helper like cargo-zigbuild is considered. Unlike cross-rs, xclang needs no container, and runs natively on Windows and macOS hosts. It also runs no tests under emulation.

llvm-mingw ​

llvm-mingw is clang, lld, mingw-w64 and the LLVM runtimes for Windows, from Linux, macOS and Windows hosts. xclang's MinGW targets are the same idea, and their sysroots use mingw-w64 too.

  • llvm-mingw has more Windows architectures: i686, armv7, and arm64ec in its scripts. It has an msvcrt variant for older Windows, ASan on x86, and Control Flow Guard.
  • It links libc++ and libunwind as DLLs unless -static is given (#333). xclang links them in.
  • Its releases are built with PGO and ThinLTO too.
  • It has no Linux or macOS targets.

conda-forge's Compilers ​

The cxx-compiler of conda-forge is GCC on Linux, clang on macOS and MSVC on Windows, made to build conda packages. The C++ runtime is a shared library from a package, libstdcxx or libcxx, which run_exports adds to every package built with it. The Linux baseline is glibc 2.17, through the sysroot_linux-* packages (knowledge base).

That is right for an environment where conda provides the runtimes, and wrong for a program that leaves it. xclang is a conda package too, but not a compiler for conda-forge packages. It links its runtimes into every program, and has no run_exports.

LLVM's Release Binaries ​

LLVM's releases are clang, lld and the runtimes for the host. They are built with PGO and ThinLTO on Linux and macOS (clang/cmake/caches/Release.cmake), and with PGO but no LTO on Windows. They carry no sysroot for another target, so a cross build needs one from elsewhere. An archive is 0.9 to 2 GB.

xclang 23.1.2.1 was built by them. xclang's archives are 86 to 94 MB, carry six targets, and run on glibc 2.17. On compile speed they are close on Linux and macOS (PGO has the numbers).

Distribution Clang and GCC Cross Toolchains ​

On Debian, crossbuild-essential-arm64 brings aarch64-linux-gnu-g++ and an arm64 glibc of the version of the distribution (packages.debian.org). g++-mingw-w64 is a MinGW GCC, and apt.llvm.org has every clang version. They are the default on a Linux machine, and well maintained. But:

  • Their programs need the glibc of the distribution or newer, and libstdc++.so.6.
  • The programs of a MinGW GCC need libstdc++-6.dll and libgcc_s_seh-1.dll, unless linked with -static.
  • Each target is another set of packages.
  • They exist on Linux only.

Android NDK and wasi-sdk: The Precedents ​

Both are one clang with bundled sysroots, the shape xclang has for desktop targets.

  • The NDK takes the target and API level in --target=aarch64-linux-android21, and its libc++ is static by default in CMake. Its C++ library support page states a rule that xclang's static runtimes also follow. "You can only use a static variant of the C++ runtime if you have one and only one shared library in your application." Android's own clang is built with PGO, LTO and BOLT.
  • wasi-sdk is "builds configured to set the default target and sysroot", which is what a config file per target does in xclang.

Bazel Toolchains ​

toolchains_llvm downloads LLVM's release for the host. It cross-compiles with a sysroot the user brings, and then links the libstdc++ of that sysroot. hermetic_cc_toolchain is built on zig cc and has its targets. Its macOS support is "not well tested", without a macOS SDK.

xclang's Bazel module brings the sysroots itself, and registers a toolchain per host and target. Its actions hold no absolute paths, and it adds import std, sanitizer features and libclang.

Not Yet Supported ​

statuswho has it
musl targetsPlannedzig cc
Android, WebAssembly, the BSDs, bare metalConsideredthe NDK, wasi-sdk, zig cc
iOS and Apple's other devicesIn researchXcode
Windows 7 and XPIn researchllvm-mingw's msvcrt variant
Runtimes built from source with other options: MemorySanitizer, libc++ hardening, an ABI of one's ownPlannedzig cc builds its runtimes on first use

Known Limitations ​

  • No tests under emulation. Programs built for another target run on a machine of that target; xclang has nothing like cross test.
  • No msvcrt. The MinGW targets use UCRT, which needs Windows 10 or later; an msvcrt variant is not planned.
  • No shared C++ runtime across shared libraries. It is not planned.