Using Clang With Musl

Hello. I’m using Linux. I installed both the Clang compiler and the Musl standard C library through the repository. I tried to compile a “hello world” program through Clang using the Musl stdio.h, but it failed. I put the following line at the beginning of the program:

#include </usr/include/x86_64-linux-musl/stdio.h>

But at the compiling time (in verbose mode) it returned the following error:

==============================

(…)
#include “…” search starts here:
#include <…> search starts here:
/usr/local/include
/usr/lib/llvm-11/lib/clang/11.0.1/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
In file included from /home/pureos/hello.c:1:
/usr/include/x86_64-linux-musl/stdio.h:26:10: error: ‘bits/alltypes.h’ file not found with include; use “quotes” instead
#include <bits/alltypes.h>
^~~~~~~~~~~~~~~~~
“bits/alltypes.h”

==============================

It appears that it doesn’t recognize the “bits” directory inside the “x86_64-linux-musl” directory, but I saw that it DOES exist.

Well, using “clang hello.c -I /usr/include/x86_64-linux-musl/” compiled but didn’t worked. After all, an analysis of the compiled program via the “hexdump -C a.out” command strangely showed that it keeps using the Glibc library, and that’s the thing I want to avoid.

There’s no clear reason for the compiler to have used the Glibc, since I clear specified in the source code the absolute path /usr/include/x86_64-linux-musl/stdio.h; I tried both the angled (<>) include and quotes (“”), and none of these worked.

Running the “ldd” command in the resulting “a.out” file, it shows that it’s linked against the “/lib/x86_64-linux-gnu/libc.so.6” file; however, I wonder if it shouldn’t be linked against the “/lib/x86_64-linux-musl/libc.so” or perhaps “/lib/ld-musl-x86_64.so.1” files if everything ran as expected.

Any help is welcome, regards.

Make sure your clang targets musl with --target=x86_64-unknown-linux-musl

It’s strange… running “clang hello.c -I /usr/include/x86_64-linux-musl/ --target=x86_64-unknown-linux-musl” and running the ldd command in the resulting file shows that it’s linked both against “libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6” and “/lib/ld-musl-x86_64.so.1 => /lib64/ld-linux-x86-64.so.2”. A “hexdump -C” command also shows that the name “GLIBC” appears at several points of the file.

This looks very wrong to me. Surely you should be including <stdio.h> and compiling with -I /usr/include/x86_64-linux-musl instead. Then clang will be able to find the bits directory.

You probably want -nostdlib or whatever the clang equivalent is.

I tried your suggestion of using just “<stdio.h>”, and it didn’t made any difference at all. After all, the compiler wouldn’t be able to distinguish between the stdio.h file provided by the GNU project and the one provided by the Musl project.

Compiling it with the “-nostdlib” option gives the following error:

linker command failed with exit code 1 (use -v to see invocation)

That’s why you use -I as well.

It tells the compiler where to look for the headers, including the bits directory. If you don’t tell it, how do you expect it to find anything except the one file named by an absolute path?

As a starter you may consider a rootfs with a musl-based Linux distribution, then use clang --sysroot=$sysroot to select GCC and musl headers/library files/start files from it. I have some notes on https://maskray.me/blog/2021-03-28-compiler-driver-and-cross-compilation

In reality the sysroot directory just needs to contain libc and GCC. The GCC pieces can be replaced with llvm-project components (compiler-rt, libunwind, libc++, libc++abi) but such a setup requires more familiarity with the llvm toolchain.