Build a GNU-free C++ program on Gentoo

This post is a following-up of my previous one: Build a freestanding libc++. Here I’ll demonstrate how to link a C++ program with the freestanding libc++ we just built. The resulting executable will have no dependence on glibc or any GCC component, thus is GNU-free.

As the libc++ in use is linked with musl, the C++ program to be linked with libc++ need also be linked with musl. In the previous post we already got a musl-based toolchain via crossdev, but its C++ compiler is g++, which unfortunately doesn’t support libc++. We’ll have to use a vanilla clang++ instead to compile our C++ program then.

The problem with using a vanilla clang++ is that it’s not musl-aware, i.e. it doesn’t know where to find musl’s headers and libraries. Such information can only be fed to clang++ via some cumbersome command-line arguments. Assume our C++ runtime libraries (including libc++) built in previous post are installed under directory $LOCAL; the complete command for compiling a GNU-free C++ program looks like this:

clang++ hello.cc \
-nostdinc -isystem /usr/x86_64-pc-linux-musl/usr/include \
-I $LOCAL/include/c++/v1 \
-L /usr/x86_64-pc-linux-musl/usr/lib -L $LOCAL/lib \
-nostartfiles /usr/x86_64-pc-linux-musl/usr/lib/crt1.o \
-Wl,-dynamic-linker,/usr/x86_64-pc-linux-musl/lib/ld-musl-x86_64.so.1 \
-Wl,-rpath,/usr/x86_64-pc-linux-musl/usr/lib,-rpath,$LOCAL/lib \
-nodefaultlibs -stdlib=libc++ -lc -lc++

This is indeed a long command. Because clang doesn’t have something like GCC’s specs file, we have to elaborately specify every configuration on the command line. This is also what I’m going to improve this summer. Hopefully we’ll make clang more friendly to musl, so we don’t have to issue such obscure commands when clang is eventually deployed as Gentoo’s default compiler.

Now let me explain these command options in some detail:

  • nostdinc tells clang not to include the standard headers, following by two arguments specifying location of C and C++ headers, then another two specifying location of shared libraries. This is necessary because clang is not configured with musl and thus has no way to find the correct headers and libs.
  • nostartfiles tells clang to link the program with musl’s version of start files instead of glibc’s.
  • dynamic-linker and –rpath are options passed to the linker. They tell the program what dynamic linker to use and where to find necessary dynamic libraries at runtime.
  • nodefaultlibs, like -stdinc, tells clang to link with musl and the C++ runtime libraries we specify, instead of the default ones.

For convenience, I put this really long command in a shell script named musl-clang++ and replace “hello.cc” with “$@” for general use. Let’s see if it works:

$ musl-clang++ hello.cc -o hello
$ readelf -d hello | grep NEEDED
0x0000000000000001 (NEEDED) Shared library: [libc.so]
0x0000000000000001 (NEEDED) Shared library: [libc++.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc++abi.so.1]
$ ./hello
Hello

Yay!

2 thoughts on “Build a GNU-free C++ program on Gentoo”

    1. Yeah, I’ve heard of it. Thanks for pointing it out!

      Hopefully I could borrow some useful stuff from it during my project 🙂

Comments are closed.