Cross-Compiling Android Linux Kernel

When you use your Android device, you're interacting with a complex system that relies heavily on the Linux kernel at its core. But what exactly is the Android Linux kernel, and how does it work?

What is Linux Kernel?

The Linux kernel is the core component of the Linux operating system, responsible for managing hardware resources (such as the CPU, memory, and devices), providing essential services to software applications, and ensuring secure and efficient operation of the entire system.

What is the Android Linux Kernel?

The Android Linux kernel is a version of the Linux kernel, based on Long Term Stable (LTS). At Google, LTS kernels are combined with Android-specific patches to form what are known as Android Common Kernels (ACKs).

For the tutorial, I’m using Ubuntu 22.04 running inside a 8 Core, 16GB RAM machine. However, the steps should be the same independent of whether you’re using a virtual machine, running a different version of Linux, etc.

Prerequisites

Certain requirements are to be met before compiling the Linux Kernel.

  • Ability to understand basic editing/writing of files and text, familiarity with the linux command line interface and some basic git knowledge.

Establishing a Build Environment

To build the Kernel, a Linux build machine is recommended, with some minimal specifications as long as it can configure make.

To setup the Linux build environment , you can directly run this command on your linux machine with elevated permissions:

curl https://raw.githubusercontent.com/akhilnarang/scripts/master/setup/android_build_env.sh | sudo sh

1. Set up the cross-compiling toolchain

In order to compile source code into machine code that is not native to the build machine, a cross-compiler has to be used.

$ git clone --depth=1 -b 11.x https://gitlab.com/stormbreaker-project/google-clang clang-11
$ git clone --depth=1 https://github.com/stormbreaker-project/aarch64-linux-android-4.9 gcc64
$ git clone --depth=1 https://github.com/stormbreaker-project/arm-linux-androideabi-4.9 gcc32
$ export PATH=$PATH:$PWD/clang-11/bin:$PWD/gcc64/bin:$PWD/gcc32/bin

2. Download the Source Code

We are going to pickup a source that is already being worked on, you can take sources from ODM pages of various android devices that are launched.

So after hovering around, download your favorite source code in a directory

$ git clone https://github.com/stormbreaker-project/linux-asus-X00P-4.19
cd linux-asus-X00P-4.19

We generally do not require the commit history, so to speed up the process, use the --depth argument to only clone the most recent version of all the files:

$ git clone --depth=1 https://github.com/stormbreaker-project/linux-asus-X00P-4.19

This can take a few minutes.

3. Configure the Build

Next, we need to configure the kernel build. The easiest option is to just build with the default configuration

cd linux-asus-X00P-4.19
make O=out ARCH=arm64 vendor/X00P_defconfig

Alternatively, we can also copy the configuration from an existing build.

$ adb pull /proc/config.gz
$ gunzip -c config.gz > out/.config

This will use adb to establish a connection with the device and copy the configuration from the default location at /proc/config.gz. This is a virtual location provided by a kernel module.

4. Build the Kernel

Now that everything is configured, we can start the build process. Run the following command to build the kernel image. Modify the -j parameter to approximately correspond with the number of CPU cores your host machine has. Higher values will lead to fast build times.

make -j14 O=out ARCH=arm64 CROSS_COMPILE=aarch64-linux-android- CROSS_COMPILE_ARM32=arm-linux-androideabi- CC=clang CLANG_TRIPLE=aarch64-linux-gnu- 

The build machine will now take a while to compile the kernel. This might vary as per machine configuration, it took me about 10-15 minutes until the build was finished.

5. Booting the Kernel

All that's left now is to flash the kernel Image. There are various methods to install a kernel image on android devices.

Here we will use LiveBoot, since the other methods requires many more device-side features, so let's keep that aside.
To Live Boot the Kernel image, reboot your device to bootloader.

fastboot boot out/arch/arm64/boot/Image.gz

The device will reboot automatically, and run the freshly installed kernel.

Note:

  • Flash methods vary for each device and manufacturer, so I used a generic method in the process which MIGHT NOT work for some devices.
  • For AnyKernel3 to work, one needs to make device specific recovery changes, like defining boot partition path and device spec name, for it to work.
  • Not all Flash methods are mentioned here. Refer to your ODM guides on how to install the kernel image.

Let me know your new experiences at my email.