Compiling Linux Kernel with Clang

Hi everyone. This is my first ‘technical’ blog post. I saw some people saying it helps growing your explanation skills which I sincerely lack. Thus, I decided next I struggle doing something because I feel it’s quite undocumented, I’ll try to make a post and explain how I did it. If even one person reads this and it’s even remotely useful to them, I’ll consider the job done. Ask any question, I’ll be happy to answer.

Now down to the topic. I have trying to compile the kernel with clang ever since I have seen the LWN.net article on the topic. It says that you ‘just’ need to go and compile your kernel with make CC=clang. So I went into the linux sources I had at this time (something around 4.9.60) and type the command. Obviously it didn’t work.

Turns out, it’s not that much complicated. There are two requirements to compiling your kernel with clang:

  1. Get the right source and configuration.
  2. Get the right version of clang.

Everything is very well summarized on a LKML post from last November: https://lkml.org/lkml/2017/11/22/943.

Concerning the source, I went for the simplest path: getting the latest stable version of the kernel with default configuration:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
cd linux-stable
git checkout v4.14.15
make defconfig

Here I’m on x86. If you want to compile for ARM64, it seems a bit more complicated. I didn’t try it but you might want to look for the android source that have not been upstreamed yet. Posting here because it’s not linked in the Matthias Kaehlcke’s LKML post:

There also other documentation made by Google here which shows how to compile the kernel with KASAN and KCOV. Didn’t dig into that but could be useful to someone.

If you are looking for other configuration than just the default one, I didn’t try that and I think it’s really and a case by case basis. You are going to have to dig a little bit more.

And for the version of clang, you need clang 5 or more. I on Debian Stretch for which LLVM has precompiled binary (see here if you are on another OS version). So add them to your source list:

sudo vim /etc/apt/sources.list 

And then add:

deb http://apt.llvm.org/stretch/ llvm-toolchain-stretch-6.0 main
deb-src http://apt.llvm.org/stretch/ llvm-toolchain-stretch-6.0 main

Now you can install clang:

sudo apt-get update
sudo apt-get install clang-6.0

If you are not on Debian/Ubuntu, I am not sure whether or not there is another solution than just compiling LLVM directly (see here).

Finally, we have the source and the compiler, so we are ready to compile. Go in your linux-stable/ folder and:

make CC=clang-6.0 -j4 bzImage

I just wanted the bzImage to boot, but you remove it if you want to compile everything. -j4 because gain time by making compilation parallel… Now I don’t know how you plan to use your clang compiled kernel, but just to check it’s usable, I run it with qemu:

qemu-system-x86_64 -kernel arch/x86/boot/bzImage -nographic -serial mon:stdio -append 'console=ttyS0'

And since we didn’t provide the -initrd option, it will crash at the end with something like:

---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

There are plenty of guides on how to use your kernel, not the goal here.

That will conclude my first post. Hopefully it was clear enough. Don’t hesitate to contact me by any mean if you have any question or problems.