Skip to content

Instantly share code, notes, and snippets.

@P1N2O
Last active April 29, 2024 01:29
Show Gist options
  • Star 63 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save P1N2O/b9b2604c58aa4d7486e2fc0d327d23dc to your computer and use it in GitHub Desktop.
Save P1N2O/b9b2604c58aa4d7486e2fc0d327d23dc to your computer and use it in GitHub Desktop.
Guide to Compile an Android Kernel with Clang

Android Kernel Compilation Guide

This gist is intended to assist beginners, like myself, in getting started with Android Kernel Compilation. Please note that while I'm sharing my setup and process, this guide may not be entirely accurate, and I welcome suggestions from experienced developers to improve it.

Installing Build Tools

I am on Arch, so I will be using pacman to install the base-devel package group.

sudo pacman -S base-devel

On a Debian based distro, you can use apt and install the build-essential package.

sudo apt install build-essential

If you are on a different distro, you will need to use your package manager to install the equivalent package.

Downloading the Kernel Source

It's advisable to create a dedicated build directory for your kernel(s).

In my case, I use "~/dev/kernel": mkdir -p ~/dev/kernel

Background

Google compiles the Pixel 2 kernel with Clang. They shipped the device on Android 8.0 with a kernel compiled with Clang 4.0 (build.config commit and prebuilt kernel commit) and upgraded to Android 8.1 with a kernel compiled with Clang 5.0 (build.config commit and prebuilt kernel commit).

Google uses Clang's link-time optimization and control flow integrity in the Pixel 3 kernel, hardening it against return oriented programming attacks (LTO commit, CFI commit).

Google started compiling all Chromebook 4.4 kernels with Clang in R67 (commit, LKML) and going forward, Clang is the default compiler for all future versions of the kernel (commit).

Further information including videos of talks on the motive behind compiling with Clang can be found in the ClangBuiltLinux wiki.

TL;DR: Helps find bugs, easier for Google since all of AOSP is compiled with Clang, compiler specific features such as link-time optimization, and better static analysis for higher code quality.

Requirements

  • A compatible kernel (4.4 or 4.9 LTS work best)
  • arm64 or x86_64
  • Patience

msm-4.14 and newer uses clang by default so there is no need for a patch stack.

How to compile the kernel with Clang (standalone)

NOTE: I am not going to write this for beginnings. I assume if you are smart enough to pick some commits, you are smart enough to know how to run git clone and know the paths of your system.

  1. Add the Clang commits to your kernel source
  2. Download/build a compatible Clang toolchain
  3. Download/build a copy of binutils
  4. Compile the kernel (for arm64, x86_64 is similar - example using AOSP's toolchains):
make O=out ARCH=arm64 <defconfig>

PATH="<path to clang folder>/bin:<path to gcc folder>/bin:${PATH}" \
make -j$(nproc --all) O=out \
                      ARCH=arm64 \
                      CC=clang \
                      CLANG_TRIPLE=aarch64-linux-gnu- \
                      CROSS_COMPILE=aarch64-linux-android-

After compiling, you can verify the toolchain used by opening out/include/generated/compile.h and looking at the LINUX_COMPILER option.

A couple of notes:

  1. CLANG_TRIPLE is only needed when using AOSP's version of Clang
  2. export CC=clang does not work. You need to pass CC=clang to make like above.

How to compile the kernel with Clang (inline with a custom ROM)

  1. Add the Clang commits to your kernel source
  2. Make sure your ROM has this commit
  3. Add the following to your BoardConfig.mk file in your device tree: TARGET_KERNEL_CLANG_COMPILE := true

To test and verify everything is working:

  1. Build a kernel image: m kernel or m bootimage
  2. Open the out/target/product/*/obj/KERNEL_OBJ/include/generated/compile.h file and look at the LINUX_COMPILER option.

Getting the Clang patchset

The core Clang patchset comes from mainline. It has been backported to three places:

If your kernel has 4.4.165 or 4.9.139 and newer, you automatically have the patchset and can start building with Clang!

Branch information

The branches in this repository will be dedicated to adding this patchset when it does not exist and enhancing it by fixing all of the warnings from Clang (from mainline, the Pixel 2 and 3, msm-4.9/msm-4.14, and my own knowledge).

The general structure of these commits is as follows:

  1. The core compilation support (if needed)
  2. Fixing Qualcomm specific drivers to compile with Clang
  3. Fixing warnings that come from code in mainline
  4. Fixing warnings that come from code outside of mainline

You should pick nathanchances commits.

Additionally, there are fixes for:

Every time there is a branch update upstream, the branch will be rebased, there is no stable history.

How to get a Clang toolchain

You can either use a prebuilt version of Clang (like from AOSP) or build a version yourself from the upstream sources.

For prebuilts, I recommend AOSP's Clang, which is used for both the kernel and the platform so it is highly tested. You can git clone that repo to always have access to the latest version available, which is what I recommend. That is currently Clang 17.0.4. If you would like to just download the minimum version of Clang supported for the branches in this repo, direct tarball links are provided below:

If you would like to build the latest version of Clang, you can do so with tc-build. There are a lot of fixes for the Linux kernel that happen in LLVM/Clang so staying up to date is critical. If you experience any issues with Clang and an Android kernel, please report them to this repo.

How to get binutils

binutils are used for assembling (and usually linking) the Linux kernel right now. When using AOSP Clang, you should use AOSP's GCC to avoid weird incompatibility issues. If you want source-built binutils, there is a build-binutils.py script available in tc-build

Getting help

Join the Linux kernel newbies chat on Telegram.

@Massipou
Copy link

Hi, thanks for your tutorial.
I met an issue with your binutils part, the shared repo for AOSP's GCC is empty.
Nick Desaulniers said :
" No one should be using these any more; instead llvm generally provides
substitutes for these. Please contact android-llvm@googlegroups.com for
questions or support. "
Do you have a way to substitute it ?
https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/+/f0d812a6a9e0c8a84770b3f417e4064ab8814c84

@17314642
Copy link

17314642 commented Nov 9, 2022

@Massipou sorry if too late, but I personally fixed it for me by using Lineage OS's prebuilt gcc (https://github.com/LineageOS/android_prebuilts_gcc_linux-x86_aarch64_aarch64-linux-android-4.9)

@zpvk
Copy link

zpvk commented Sep 19, 2023

ERROR: Input tree has errors, aborting (use -f to force output)
do you guys have any idea related to this kind of error?

this is the CMD I used to build kernel
make -j$(nproc --all) O=out ARCH=arm64 CC=clang CROSS_COMPILE=/home/rohan/kernel/GCC/bin/aarch64-linux-android-

@RadioactivePlays
Copy link

@zpvk I think you should run a make mrproper before starting the process

@zpvk
Copy link

zpvk commented Sep 22, 2023

Thank you I'll try and get back to you

@zpvk
Copy link

zpvk commented Sep 22, 2023

No rule to make target 'arch/arm64/boot/dts/vendor/qcom/bengal-rumi.dtb', needed by '__build'. Stop.
@RadioactivePlays do you have any help for this error

@GildedHonour
Copy link

How long does it take?

I need to compile only one module or driver - wifi. For now I want to compile it as is, to then make a few tweaks in it and recompile it. How to do it? Where to start? Is there an instruction?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment