Building the Linux Kernel (Ubuntu)

Published on September 18, 2022

Introduction

These are my notes on how to build your own Linux kernel for Ubuntu, as the information online is scattered all over the place and dated. Fortunately, Canonical recently followed suit and it is now possible to simply build a mainline Linux kernel, rather than having to build Canonical's fork. While this may be useful if you need more recents drivers, because drivers such as amdgpu are typically behind on Ubuntu, this guide is targeted at users who want to either write their own drivers or modify existing drivers in the Linux kernel.

Installing build dependencies

There are number of dependencies that need to be installed before we can build the Linux kernel. They can be installed by running the following command on Ubuntu:

sudo apt-get install libncurses-dev gawk flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf llvm

Building the kernel

Now that we have all the dependencies required to build the kernel, we can either download a tarball with the Linux source code from https://kernel.org or clone the appropriate tag from the Linux kernel repository. For instance, we can clone the source code of the Linux kernel for version 6.5 as follows:

git clone -b v6.5 --depth=1 https://github.com/torvalds/linux

Once we have downloaded the source code, we can simply cd into the directory as follows:

cd linux

Before we can build the Linux kernel, we need to configure the kernel. Fortunately, we can simply copy the kernel configuration from an existing installation:

cp -v /boot/config-$(uname -r) .config

However, we have to tune a few configuration options before we can actually build the kernel 1:

scripts/config --disable SYSTEM_TRUSTED_KEYS
scripts/config --disable SYSTEM_REVOCATION_KEYS

In addition, the kernel configuration we copied may be from an older version than the kernel version we are trying to compile. We can update the kernel configuration to be compatible with the version of the forked Linux kernel tree as follows:

make olddefconfig

The above command will simply pick the default option for any newly introduced configuration option. To build the Linux kernel and the kernel modules we can simply invoke make. However, make will by default only use one CPU core/thread, so we have to specify the jobs option or -j followed by the number of threads that we want to use. For example, to use 16 CPU cores/threads, we can invoke make as follows:

make -j16

If the above command was successful, we can now install the kernel modules:

sudo make INSTALL_MOD_STRIP=1 modules_install

As well as the Linux kernel:

sudo make install

The above command will also update the initramfs and regenerate the GRUB configuration file automatically on Ubuntu. However, it is also possible to update the initramfs or regenerate the GRUB configuration file yourself.

The commands that get passed to the kernel by GRUB during boot are located in /etc/default/grub. You can modify the kernel command line in /etc/default/grub, then you can run the following to update the GRUB configuration file:

sudo update-grub

If you want to rebuild the initramfs, you can run the following:

sudo update-initramfs -u

Finally, after installing the Linux kernel, the kernel modules and updating the initramfs and GRUB configuration, you can reboot your system:

sudo reboot

GRUB should now present you with the option to boot the newly installed kernel. However, depending on your installation, GRUB may not present you with a boot menu at all, e.g. on Ubuntu this is the default behavior. To change this, you can edit the /etc/default/grub file. More specifically, comment out the GRUB_TIMEOUT_STYLE variable and set GRUB_TIMEOUT to a non-zero value as follows:

#GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=10

Then run the following command to regenerate the GRUB configuration file:

sudo update-grub

If you like my work or if my work has been useful to you in any way, then feel free to donate me a cup of coffee. Any donation is much appreciated!