Compiling an Android Kernel

In this tutorial I'm going I recommend any Debian/Ubuntu based distribution due to the extensive availability of the clang package versions, for this instance to be using Linux Mint. As for the android phone I'm going to be using a Xiaomi Redmi Note 9 (merlin) while running the crDroid custom rom.

What is the Android Kernel

"The Android kernel is based on an upstream Linux Long Term Supported (LTS) kernel. At Google, LTS kernels are combined with Android-specific patches to form what are known as Android Common Kernels (ACKs)." - Android Open Source Project

First steps: Prepping the environment

In order to customize and compile your own kernel, you must first meet a couple requirements:

Installing dependencies

If you have a Debian/Ubuntu based distribution, you must install the below packages:

sudo apt install git ccache automake lzop bison gperf build-essential zip curl zlib1g-dev zlib1g-dev:i386 g++-multilib python-networkx libxml2-utils bzip2 libbz2-dev libbz2-1.0 libghc-bzlib-dev squashfs-tools pngcrush schedtool dpkg-dev liblz4-tool make optipng libssl-dev clang

If you have a Arch based distribution, you must install the below packages:

sudo pacman -S base-devel git clang

WARNING: Depending on the kernel you are compiling you might need use a different version of clang according to your device. Most of the current kernels don't yet support the clang current compiler so in this instance I'm going to be using clang-13 available as a package named clang-13.

Prepping the folders (Optional, but convenient if using the helper script below)

I recommend creating a empty folder where all the operations will handled within itself.

Grabbing the Sources

Kernel Source Code

In this stage we are going to clone the kernel source code according to my device and OS, in this case, for the crDroid Xiaomi Redmi Note 9 running official crDroid, the kernel is located over at https://github.com/crdroidandroid/android_kernel_xiaomi_mt6768. If you intend to use the helper script below I recommend cloning your kernel source code into the recently created folder, otherwise, just clone the source code anywhere you want.

We can clone the kernel using git clone https://github.com/crdroidandroid/android_kernel_xiaomi_mt6768 command.

After cloning, proceed to change directory into the cloned kernel source code.

Compiler and Toolchains (Skippable if using helper script)

In todays android devices, in order to compile the kernel source code, you need multiple toolchains(the android arm64, and the arm compiling toolchains respectively), and you also need a C/ASM compiler, in this instance, we are going to be using the most used compiler, the clang compiler.

Both of these toolchains I usually tend to get them from the LineageOS source tree:

If you are using the helper script you don't need to clone them, the script already does that and adds them to your PATH variable, otherwise, do these things yourself.

Compilation Process

The compilation is tha last stage of the entire process, this stage is divided in 3 phases, the selection of a default kernel configuration, the modification of this configuration and the kernel compilation process.

Finding the default configuration

Under the kernel source repository we just cloned, you can follow one of the next paths to your default configuration according to your cpu architecture:

arch/arm64/configs or arch/arm/configs

Under one of these folders you should find your device default kernel configuration file, it'll be probably have a name like DEVICECODENAME_defconfig.

Ex: merlin_defconfig

After finding this configuration file, take note of the file name, it's very important for later use.

Modifying the Default Configuration (Skippable if using helper script)

In order to customize your kernel configurations you must first prepare the kernel modification/compilation environment. To achieve this, we can type the next commands:

mkdir -p modout

In the below command you must replace the PREVIOUSLYSTATEDFILENAME with the file name stated previously.

make ARCH=arm64 \
	CC=clang-13 \
	CLANG_TRIPLE=aarch64-linux-gnu- \
	CROSS_COMPILE=aarch64-linux-android- \
	CROSS_COMPILE_ARM32=arm-linux-androideabi- \
	PREVIOUSLYSTATEDFILENAME

Example:

make ARCH=arm64 \
	CC=clang-13 \
	CLANG_TRIPLE=aarch64-linux-gnu- \
	CROSS_COMPILE=aarch64-linux-android- \
	CROSS_COMPILE_ARM32=arm-linux-androideabi- \
	merlin_defconfig

After this, you environment will be prepared and you current configuration will be saved in a file .config which you can either edit manually with your favourite text editor or you can type in the next command in order to edit the configurations with a ncurses based menu:

make ARCH=arm64 \
	CC=clang-13 \
	CLANG_TRIPLE=aarch64-linux-gnu- \
	CROSS_COMPILE=aarch64-linux-android- \
	CROSS_COMPILE_ARM32=arm-linux-androideabi- \
	menuconfig

Inside of this menu you will have the option to allow some kernel functionalities with Y, disable the functionalities with N and modularize them with M.

WARNING: Some of this functionalities may break during the kernel compilation process.

Compiling the kernel (Skippable if using helper script)

After setting up the kernel configuration, the file .config will be changed after you click the SAVE button. To start compiling the kernel type in the next command:

make -jNUMBEROFCORES ARCH=arm64 \
			CC=clang \
			CLANG_TRIPLE=aarch64-linux-gnu- \
			CROSS_COMPILE=aarch64-linux-android- \
			CROSS_COMPILE_ARM32=arm-linux-androideabi-

If the kernel fails to compile, it's either a problem related to the kernel code you have to fix or either a clang version incompatibility. If the kernel manages to compile sucessfully you must now generate the kernel modules with the command:

make ARCH=arm64 \
	CC=clang-13 \
	CLANG_TRIPLE=aarch64-linux-gnu- \
	CROSS_COMPILE=aarch64-linux-android- \
	CROSS_COMPILE_ARM32=arm-linux-androideabi- \
	INSTALL_MOD_PATH="modout" \
	INSTALL_MOD_STRIP=1 \
	modules_install

Using the compile script instead of manual setup

If you decided to use a compile script to setup the environment and compile the kernel, then, just after grabbing the kernel sources, at the root level of the kernel source code create a shell script with any name you want and paste the below code inside of it:

#!/bin/sh

# Defining Vars
COMPILERS_DIR=$(cd .. && pwd)
COMPILER="https://github.com/LineageOS/android_prebuilts_gcc_linux-x86_aarch64_aarch64-linux-android-4.9"
COMPILER32="https://github.com/LineageOS/android_prebuilts_gcc_linux-x86_arm_arm-linux-androideabi-4.9"
DEFCONFIG="DEVICECODENAME_defconfig"
KERNEL_DIR=$(pwd)
PATH="${COMPILERS_DIR}/gcc/bin:${COMPILERS_DIR}/gcc32/bin:${PATH}"

# Grabbing Compilers
cd "$COMPILERS_DIR" || exit
git clone "$COMPILER" gcc
git clone "$COMPILER32" gcc32
cd "$KERNEL_DIR" || exit

# Compiling Kernel
mkdir -p build/modout
make O=build ARCH=arm64 CC=clang CLANG_TRIPLE=aarch64-linux-gnu- CROSS_COMPILE=aarch64-linux-android- CROSS_COMPILE_ARM32=arm-linux-androideabi- "$DEFCONFIG"
make O=build ARCH=arm64 CC=clang CLANG_TRIPLE=aarch64-linux-gnu- CROSS_COMPILE=aarch64-linux-android- CROSS_COMPILE_ARM32=arm-linux-androideabi- menuconfig
make -jNUMBEROFCORES O=build ARCH=arm64 CC=clang CLANG_TRIPLE=aarch64-linux-gnu- CROSS_COMPILE=aarch64-linux-android- CROSS_COMPILE_ARM32=arm-linux-androideabi-
make O=build ARCH=arm64 CC=clang CLANG_TRIPLE=aarch64-linux-gnu- CROSS_COMPILE=aarch64-linux-android- CROSS_COMPILE_ARM32=arm-linux-androideabi- INSTALL_MOD_PATH="modout" INSTALL_MOD_STRIP=1 modules_install

After saving the script, change the field with DEVICECODENAME a codename present inside of the folder arch/arm64/configs or the folder arch/arm/configs, and change the field where it says NUMBEROFCORES to the number of cores you want to allocate for compilation.

WARNING: You might need to change the CC variable to clang-13 if you're not compiling with the clang default compiler version.

Now just run the script and make the necessary changes to the kernel. After that, the script will automatically start compiling and the kernel image and modules will be built inside a build folder in the root of the kernel sources.

Finding the kernel image and modules

After generating the kernel modules, you'll have them available inside the folder modout, and the kernel image will be compile inside the folder arch/arm64/boot.

Commands recap using the compile script in Linux Mint

  1. sudo apt install git ccache automake lzop bison gperf build-essential zip curl zlib1g-dev zlib1g-dev:i386 g++-multilib python-networkx libxml2-utils bzip2 libbz2-dev libbz2-1.0 libghc-bzlib-dev squashfs-tools pngcrush schedtool dpkg-dev liblz4-tool make optipng libssl-dev clang
  2. mkdir kernel
  3. cd kernel
  4. git clone https://github.com/crdroidandroid/android_kernel_xiaomi_mt6768
  5. cd android_kernel_xiaomi_mt6768
  6. *Put the script inside the kernel source root folder*
  7. *Edit the script according to your device and your computer cores*
  8. *Run the script*
  9. Done

References