A new Gentoo stage4: musl + clang

I’m glad to announce that I just successfully deployed the GNU-free toolchain, which I’ve been working on so far, into a musl-based Gentoo stage4. Everything in this stage4, except for the kernel, is built by clang with non-GNU runtime libs. I’m now using this as my main Linux system, and luckily nothing breaks so far 🙂

To be more specific, the runtime environments of this stage4 is composed of the following components:

  • C runtime: musl
  • C++ runtime
    • C++ stdlib: libc++
    • C++ ABI lib: libcxxrt [1]
    • stack unwinding lib: libunwind
  • compiler: clang

Let’s take program /usr/bin/ld.gold for example, which is written in C++, and see its runtime dependencies:

$ ldd /usr/bin/ld.gold
	/lib/ld-musl-x86_64.so.1 (0x559f8b598000)
	libz.so.1 => /lib/libz.so.1 (0x7f5a5b7a9000)
	libc++.so.1 => /usr/lib/libc++.so.1 (0x7f5a5b6ea000)
	libcxxrt.so.1 => /usr/lib/libcxxrt.so.1 (0x7f5a5b4cd000)
	libunwind.so.1 => /usr/lib/libunwind.so.1 (0x7f5a5b4c4000)
	libc.so => /lib/ld-musl-x86_64.so.1 (0x559f8b598000)

Apparently none of the above libs is related to gcc. So this program is just free from gcc!

Actually I’ve already figured out how to glue clang and those non-GNU C++ runtime libs together weeks ago; but this is the first time I put it into serious use. The most challenging part is to rebuild @world with this toolchain; I’m really nervous that countless packages get broken after I issue the command emerge -e @world. Surprisingly enough, only two packages are broken.

The first broken package is iproute2, which depends on libmnl and libmnl is mis-compiled by clang. libmnl has an unpleasant past with clang [2], but its new versions are fine. So the fix is simple: just upgrade libmnl to the latest version available (use ~amd64).

The second broken package, ironically, is clang/llvm itself. It turned out the libunwind I’m using lacks a few functions essential to llvm. Actually there’re two versions of libunwind available: one is from nongnu [3] which already exists in Gentoo’s repo for a while; the other one is developed by LLVM and is almost functionally equivalent to the former. Initially I just used the nongnu version, since there’s no package for LLVM’s libunwind yet. Unfortunately, the nongnu one works fine with everything else except for llvm itself. I just had to stop being lazy and wrote an ebuild for LLVM’s libunwind. Luckily again, it has everything we need, including those functions missing in the other libunwind.

After that, while I’m using this new system, I encountered a few other broken packages. But they’re either incompatible with musl, or the gold linker (yes, it’s the /usr/bin/ld.gold I just showed you). There’s nothing wrong with clang or the C++ runtime libs.

I also found an interesting fact: the building of gcc involves several steps of bootstrapping and the final executable has no dependence on any external C++ runtime libs, though gcc itself written in C++. This means gcc still works even clang or the C++ runtime gets broken. So I don’t need to worry about breaking packages since I can still rebuild them with gcc 🙂

Now that I have a working stage4, the next step is to make gcc-config support clang, so clang can act like a real native compiler.

Stay tuned!

 

[1] libcxxrt is functionally equivalent to libc++abi, and is planned to be replaced by the latter later in this project
[2] https://bugs.chromium.org/p/chromium/issues/detail?id=548786
[3] http://www.nongnu.org/libunwind/