Manjaro Linux kernel build with Clang/LLVM(and ccache)

参考サイト
llvm、clangでkernelをビルドする

https://www.kernel.org/doc/html/latest/kbuild/llvm.html

Manjaroで、clangでkernelをビルドする場合、リンカーlldもインストールする。

```sh
sudo pacman -S clang llvm lld
```

kernelビルドの時間短縮について、以下に網羅されています。

https://mongonta.com/f277-howto-shorten-linux-kernel-build-time/


ManjaroのkernelのPKGBUILDに若干修正を加えて、ccacheを利用するためのMakefile.patchを用意しています。
以下は、clang(Clang/llvm and linker is lld.)を利用する場合です。

```diff
diff --git a/PKGBUILD b/PKGBUILD
index 06ba6bd..07b92ed 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -60,7 +60,8 @@ source=("https://www.kernel.org/pub/linux/kernel/v5.x/linux-${_basekernel}.tar.x
         '0510-bootsplash.patch'
         '0511-bootsplash.patch'
         '0512-bootsplash.patch'
-        '0513-bootsplash.gitpatch')
+        '0513-bootsplash.gitpatch'
+	'Makefile.patch')
 sha256sums=('7e068b5e0d26a62b10e5320b25dce57588cbbc6f781c090442138c9c9c3271b2'
             'e96f1d8ea64bf66cd2e01e54e0929117feafe443161bc665af1ef48474cb45e2'
             '5e18e915aa406ad1548c2cdf0a1485657bf582c5aff64076882b9572af65673e'
@@ -88,7 +89,8 @@ sha256sums=('7e068b5e0d26a62b10e5320b25dce57588cbbc6f781c090442138c9c9c3271b2'
             'e9f22cbb542591087d2d66dc6dc912b1434330ba3cd13d2df741d869a2c31e89'
             '27471eee564ca3149dd271b0817719b5565a9594dc4d884fe3dc51a5f03832bc'
             '60e295601e4fb33d9bf65f198c54c7eb07c0d1e91e2ad1e0dd6cd6e142cb266d'
-            '035ea4b2a7621054f4560471f45336b981538a40172d8f17285910d4e0e0b3ef')
+            '035ea4b2a7621054f4560471f45336b981538a40172d8f17285910d4e0e0b3ef'
+            'f1b209cd65fd198e33f86570a84d5310936bbc2bbafa7a64d3a34270cf9433bd')
 
 prepare() {
   cd "linux-${_basekernel}"
@@ -129,10 +131,16 @@ prepare() {
   sed -i '2iexit 0' scripts/depmod.sh
 
   msg "get kernel version"
+  LLVM=1
+  LLVM_IAS=1
+  CC='ccache clang'
+  CXX='ccache clang++'
   make prepare
 
   msg "rewrite configuration"
-  yes "" | make config >/dev/null
+  make oldconfig
+  #lsmod > `pwd`/lsmod.txt && LSMOD=`pwd`/lsmod.txt make localmodconfig
+  make menuconfig
 }
 
 build() {
```

```diff
--- src/linux-5.14/Makefile	2021-11-05 16:58:25.293406677 +0900
+++ ./Makefile	2021-11-05 16:42:13.026766134 +0900
@@ -425,11 +425,11 @@
 HOST_LFS_LIBS := $(shell getconf LFS_LIBS 2>/dev/null)
 
 ifneq ($(LLVM),)
-HOSTCC	= clang
-HOSTCXX	= clang++
+HOSTCC	= ccache clang
+HOSTCXX	= ccache clang++
 else
-HOSTCC	= gcc
-HOSTCXX	= g++
+HOSTCC	= ccache gcc
+HOSTCXX	= ccache g++
 endif
 
 export KBUILD_USERCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \
@@ -444,7 +444,7 @@
 # Make variables (CC, etc...)
 CPP		= $(CC) -E
 ifneq ($(LLVM),)
-CC		= clang
+CC		= ccache clang
 LD		= ld.lld
 AR		= llvm-ar
 NM		= llvm-nm
@@ -453,7 +453,7 @@
 READELF		= llvm-readelf
 STRIP		= llvm-strip
 else
-CC		= $(CROSS_COMPILE)gcc
+CC		= ccache $(CROSS_COMPILE)gcc
 LD		= $(CROSS_COMPILE)ld
 AR		= $(CROSS_COMPILE)ar
 NM		= $(CROSS_COMPILE)nm
```
[DKMS:Support CC=clang and LD=ld.lld](https://github.com/dell/dkms/pull/169/commits/6ddb09145930b03c88e63f5930e718a33501024d)
Dynamic Kernel Module Supportでカーネルモジュールをコンパイルする際、clang/llvm,ld.lldを用いるようにしておきます。
上記の修正を取り込み、clang,lldでビルドしたカーネルの場合、dkmsでカーネルモジュールをコンパイルする場合、clang,lldを用いるようにします。

**dkms-3.0.1**

```diff
diff --git a/dkms.in b/dkms.in
index 9c98a89..ce213e1 100644
--- a/dkms.in
+++ b/dkms.in
@@ -575,6 +575,23 @@ read_conf()
     [[ ! $make_command ]] && make_command="make -C $kernel_source_dir M=$dkms_tree/$module/$module_version/build"
     [[ ! $clean ]] && clean="make -C $kernel_source_dir M=$dkms_tree/$module/$module_version/build clean"

+    # Check if clang was used to compile or lld was used to link the kernel.
+    if [[ -e $kernel_source_dir/vmlinux ]]; then
+      if  readelf -p .comment $kernel_source_dir/vmlinux | grep -q clang; then
+        make_command="${make_command} CC=clang"
+      fi
+      if  readelf -p .comment $kernel_source_dir/vmlinux | grep -q LLD; then
+        make_command="${make_command} LD=ld.lld"
+      fi
+    elif [[ -e $kernel_source_dir/.config ]]; then
+      if grep -q CONFIG_CC_IS_CLANG=y $kernel_source_dir/.config; then
+        make_command="${make_command} CC=clang"
+      fi
+      if grep -q CONFIG_LD_IS_LLD=y $kernel_source_dir/.config; then
+        make_command="${make_command} LD=ld.lld"
+      fi
+    fi
+
     # Set patch_array (including kernel specific patches)
     count=0
     for ((index=0; index < ${#PATCH[@]}; index++)); do```
```



カーネルオプションを調整して様子を見たい場合などに便利です。
私がオプション調整で使うのは、デフォルトで使うファイルシステムをモジュールでなく、カーネル埋め込みにするなどしています。

追記
余談ですが、makepkgコマンドではなく、[manjaro-tools](https://wiki.manjaro.org/index.php/Manjaro-tools)のbuildpkgコマンドを使う際は、chroot下の環境にclangが含まれていないので、PKGBUILDのmakedependsにclang,llvm,lldを加えておくとmanjaro-toolsのbuildpkgでも、clangを用いてカーネルをビルドできます。

```diff
diff --git a/PKGBUILD b/PKGBUILD
index ad28275..623d53d 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -25,6 +25,9 @@ makedepends=('bc'
     'cpio'
     'perl'
     'tar'
+    'clang'
+    'llvm'
+    'lld'
     'xz')
 options=('!strip')
 source=("https://www.kernel.org/pub/linux/kernel/v5.x/linux-${_basekernel}.tar.xz"
@@ -93,6 +96,11 @@ sha256sums=('57b2cf6991910e3b67a1b3490022e8a0674b6965c74c12da1e99d138d1991ee8'
             '60e295601e4fb33d9bf65f198c54c7eb07c0d1e91e2ad1e0dd6cd6e142cb266d'
             '035ea4b2a7621054f4560471f45336b981538a40172d8f17285910d4e0e0b3ef')
 
+export set LLVM=1
+export set LLVM_IAS=1
+export set CC='ccache clang'
+export set CXX='ccache clang++'
+
 prepare() {
   cd "linux-${_basekernel}"
 
```

https://wiki.manjaro.org/index.php/Manjaro-tools