Skip to content
clice-ioPublic

About

Cross-compiling with clang: one PGO+ThinLTO toolchain, six targets' sysroots and static runtimes in every archive, programs that depend only on the OS. CMake package, Bazel module, conda.

Topics

Resources

Contributing

Security policy

Stars

8 stars

Watchers

0 watching

Forks

Repository files navigation

xclang

中文 · Documentation

Cross-compiling with clang the way rustup, cross-rs and cargo-zigbuild let Rust do it: one compiler for every target. Today every toolchain carries six common targets, prebuilt, and cross-compiling to them is a --target flag. Its xclang command fetches the vendor SDKs that cannot be redistributed, Microsoft's and Apple's, for the MSVC targets and for macOS targets on Linux and Windows hosts. Where it is going: more targets, fetched when a build needs them, and runtimes built from source on demand. None of that is in a release yet; the roadmap gives each item's status.

It aims to be close to the current best practice for hermetic, modern C++ builds: why xclang makes that case angle by angle.

One directory holds the compiler, the linker, the binary tools and, for the six targets, the sysroot and the runtimes:

xclang/bin/clang++ --target=aarch64-w64-mingw32 main.cpp -o main.exe

No --sysroot, no -L, no SDK to install: bin/aarch64-w64-mingw32.cfg, which clang reads for that target, points it at xclang/aarch64-w64-mingw32/, and it links the libc++, libunwind and compiler-rt built for that exact target.

Targets

Every host toolchain (Linux, Windows and macOS, x64 and arm64) carries the six common targets: Linux x64 and arm64 with glibc 2.17, Windows x64 and arm64 with MinGW-w64 (UCRT), and macOS arm64 and x64, with Xcode's SDK on macOS hosts.

With the SDKs the user fetches with the toolchain's xclang command (xclang sdk fetch), from 23.1.2.7 on:

  • MSVC-ABI targets, Windows x64 and arm64 against Microsoft's CRT, STL and Windows SDK, from every host (MSVC targets).
  • macOS targets from Linux and Windows, with Apple's SDK (macOS).

Not supported yet, each with its status in the roadmap:

  • musl targets (Linux x64, arm64): planned. Other Linux architectures, WebAssembly, Android, FreeBSD and bare metal: considered.
  • Target archives for xclang target add, to fetch targets beyond these: planned.

Who it is for

People who want a toolchain they can pin, ship and reproduce, and binaries that run wherever they are copied:

  • Hermetic. A program depends at run time only on the system libraries every installation of its OS has and no one may redistribute: glibc on Linux (2.17 or later), libSystem and the system frameworks it uses on macOS, the OS's DLLs on Windows, UCRT included (Windows 10 and later). Everything else, libc++, libc++abi, libunwind and the builtins among them, is linked statically. At build time the only inputs from outside the toolchain are the vendor SDKs: the installed Xcode's on macOS hosts, and those the user fetches with the xclang command. Sanitizer runtimes are the exception (hermeticity).
  • Every piece is usable on its own. The sysroots and runtimes are plain directories laid out the way clang's drivers expect.
  • Fast. clang and lld are built with PGO and ThinLTO, and linked statically against xclang's own libc++ on every host.
  • Small. clang, lld and most tools are one program, llvm, 86 to 94 MB an archive.
  • For tools on clang too: each release has the libclang it was built from and the option tables.

It is not a compiler for building conda-forge packages: conda-forge's clang/gcc stacks link dynamically against packaged runtimes and integrate with run_exports; xclang deliberately does neither.

Install

From the clice conda channel, with pixi:

[workspace]
name = "hello"
channels = ["conda-forge", "https://conda.clice.io"]
platforms = ["linux-64", "linux-aarch64", "osx-64", "osx-arm64", "win-64", "win-arm64"]

[dependencies]
xclang = "*"

"*" is the newest release, which pixi.lock keeps until pixi update. The environment puts xclang's bin/ first in PATH and leaves conda-forge's compilers alone. Or take the archives from the GitHub release and unpack them anywhere. The quick start goes from here to programs for every target and a CMake project with import std.

Use

clang++ main.cpp -o main                                # this host
clang++ --target=x86_64-w64-mingw32 main.cpp -o main.exe  # another target

CMake, with import std from the toolchain's libc++ (from 23.1.2.6 on):

cmake_minimum_required(VERSION 3.28)
project(app LANGUAGES CXX)
find_package(xclang REQUIRED CONFIG)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE xclang::std)

Bazel, from the clice registry bazel.clice.io:

bazel_dep(name = "xclang", version = "23.1.2.8")  # or newer

and, from 23.1.2.6 on, another target is a platform:

bazel build --platforms=@xclang//platforms:x86_64-w64-mingw32 //...

Documentation

At docs.clice.io/xclang, from docs/en:

xclang is developed for clice, whose release builds are its first user; catter builds with it too.

About

Cross-compiling with clang: one PGO+ThinLTO toolchain, six targets' sysroots and static runtimes in every archive, programs that depend only on the OS. CMake package, Bazel module, conda.

Topics

Resources

Contributing

Security policy

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages