The LLVMLinux team made quite some progress in enabling LLVM/clang to build the Linux kernel. There has also been a talk at the Collaboration Summit 2015 in Santa Rosa (slides). So I thought, give it a try and compile a kernel for my ARM based board of choice. The upstream kernel.org Linux kernel is not yet ready to be built using LLVM/clang, some patches are still required. Therefor I used the kernel from the LLVMLinux git server.
The nice thing about LLVM/clang is that it supports multiple targets. The binaries provided by the Arch repositories support several ARM targets:
$ pacman -S clang ... $ llc --version LLVM (http://llvm.org/): LLVM version 3.5.1 Optimized build. Built Jan 14 2015 (03:18:15). Default target: x86_64-unknown-linux-gnu Host CPU: core-avx-i Registered Targets: aarch64 - AArch64 (little endian) aarch64_be - AArch64 (big endian) arm - ARM arm64 - AArch64 (little endian) arm64_be - AArch64 (big endian) armeb - ARM (big endian) ...
There is no need to compile a cross compile version of LLVM/clang! Neat! However, as a prerequisite a GNU GCC cross compiler toolchain is still required: The current state of affairs still requires GCC binaries, for instance the GNU linker or assembler (at least for ARM). For a quick test, I used Linaro’s toolchain (in my case the 2014.09 release based on GCC 4.9.2). To make sure clang picks up the assembler, create a symlink to clang within your GCC toolchain:
$ tar xvJf ~/Downloads/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux.tar.xz ... $ ln -s /usr/bin/clang ~/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/clang $ git clone git://git.linuxfoundation.org/llvmlinux/kernel.git -b llvmlinux-latest ...
After adding the toolchain to my path environment variable, I could successfully build the Linux kernel
$ export PATH=~/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/:$PATH $ make ARCH=arm multi_v7_defconfig ... $ make -j 4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- HOSTCC=clang CC=clang ...
The build time was not really faster on my Laptop. But what I find more interesting is the fact that LLVM/clang reports more warnings and its error and warning output is much more readable:
And, it actually booted!
[ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Linux version 3.19.0-rc4-00183-g230b22d (ags@trochilidae) (clang version 3.5.1 (tags/RELEASE_351/final)) #3 SMP Tue Mar 3 00:12:04 CET 2015 [ 0.000000] CPU: ARMv7 Processor [410fc051] revision 1 (ARMv7), cr=10c5387d [ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache [ 0.000000] Machine model: Toradex Colibri VF61 on Colibri Evaluation Board ...
Pitfalls
Wrong assembler
/usr/bin/as: unrecognized option '-mfloat-abi=soft' clang: error: assembler command failed with exit code 1 (use -v to see invocation)
To compile the kernel, clang does not use its internal assembler but uses the GNU assembler (by using the -no-integrated-as option). In this case the build system picked your hosts assembler (x86_64) instead of the one provided by the cross compiler toolchain. The simplest way to work around this is creating a symlink to clang in the cross compiler toolchains directory:
$ ln -s /usr/bin/clang ~/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/clang
Unsupported ARM assembly
/tmp/traps-3da78a.s: Assembler messages: /tmp/traps-3da78a.s:407: Error: selected processor does not support ARM mode `wfe' /tmp/traps-3da78a.s:647: Error: selected processor does not support ARM mode `sev' clang: error: assembler command failed with exit code 1 (use -v to see invocation) scripts/Makefile.build:271: recipe for target 'arch/arm/kernel/traps.o' failed
This happend to me whent trying to build for ARMv6 architecture too. After revising the kernel configuration (removing CONFIG_ARCH_MULTI_V6) I could successfully build the kernel.
Non-relocatable link
error: multiple SHT_ARM_EXIDX sections .ARM.exidx.init.text and .ARM.exidx.ref.text in a non-relocatable link
This is actually not related to the LLVM/clang build itself. It happened to me when using the default cross compiler toolchain from my Ångström distribution build. This toolchain uses the gold linker by default, which does not work with the Linux kernel, the standard BFD linker is required. You can either append the Linker explicitly or symlink the correct assembler. arm-linux-gnueabihf-ld.gold
$ make ... LD=${CROSS_COMPILE}ld.bfd - or - $ cd path/to/toolchain/bin/ $ ln -sf arm-linux-gnueabihf-ld.bfd arm-linux-gnueabihf-ld
The latter might break your OpenEmbedded/Ångström builds and is hence not recommended if you use the toolchain located in your OpenEmbedded sysroots…