Compiling the Mainline Linux Kernel on Ubuntu: A Comprehensive Guide
Introduction:
Compiling the Linux Kernel in Ubuntu can be a rewarding but challenging task. This guide aims to simplify the process and help you configure the kernel to your specific hardware. Don't be discouraged if your first few attempts don't work; it's all part of the learning process. You can always revert to your last working Kernel using Grub Customizer.Why would I need to compile the Kernel?
It is rare that a distro will lack any necessary hardware driver but when a driver is missing from the stock Kernel, and the driver has support through the mainline Kernel from kernel.org, you will be able to compile that driver back into the Kernel.
Other reasons may be to streamline the Kernel removing unnecessary features, debugging, tracing, profiling, scaling, even some security features. This will lower the resources necessary to run the Kernel and it may even speed up your system especially for embedded systems with low memory.
Other reasons may be to streamline the Kernel removing unnecessary features, debugging, tracing, profiling, scaling, even some security features. This will lower the resources necessary to run the Kernel and it may even speed up your system especially for embedded systems with low memory.
Your Linux distribution is designed to operate on a broad range of PCs and therefore the Kernel is configured to support many devices and features that you do not use. Therefore, you can craft a Kernel perfectly suited for your specific hardware.
Section 1: Setting Up Your Environment
- Using the Terminal:
- Locate your terminal application through the search or menu.
- If you prefer a lightweight GUI, Xubuntu is a great choice. It comes with a terminal in the Accessories menu.
- Create a directory for the kernel source code in your home directory:
mkdir source
Section 2: Downloading the Kernel Source
Visit kernel.org to choose the appropriate Linux Kernel version. If you're new to kernel compilation, consider using the latest stable release.
You can download the source directly to your compilation directory with:
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.5.5.tar.xz
Move the downloaded kernel source to your source directory:
mv linux-6.5.5.tar.xz source
cd source
tar -xvf linux-6.5.5.tar.xz
cd linux-6.5.5
Section 3: Install the necessary dependencies for compiling the kernel:
Before proceeding, all of the dependencies must be met first:
sudo apt-get install libqt5x11extras5-dev pkg-config libncurses-dev gawk flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf debhelper make lzop liblzo2-dev libzstd-dev vim curl
For Ubuntu 23.10+
sudo apt-get install qt6-base-dev qt6-tools-dev pkg-config libncurses-dev gawk flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf debhelper make lzop liblzo2-dev libzstd-dev vim curl
Also, any Linux version specific dependencies
sudo apt-get build-dep linux linux-image-$(uname -r)
We're going to use a tool called xconfig but that requires libqt5x11extras5-dev while menuconfig requires libncurses-dev. There's yet another tool called gconfig. This guide uses xconfig as it appears to be the most complete and easiest to use.
Section 4: Configuring Your Kernel
Create a new .config file based on your current kernel configuration:
sudo make oldconfig
If you want to add modules for your currently loaded hardware, use:
sudo make localmodconfig
To fine-tune your configuration interactively, use:
sudo make xconfig
The xconfig menu is huge but you can search for features to easily find and remove or add them. I search for keywords trace, profile, debug, symbols, virt, xen, and kvm. I remove these features from my build. You can also search for hardware that your PC uses like AMD, Intel, etc. Perhaps a network adapter such as RealTek. This will take time to learn but using the make localmodconfig should make this process much faster and easier.
Briefly, here are the other options that you may find useful:
Command | Description |
---|---|
make config | Text based configuration. The options are prompted one after another. All options need to be answered, and out-of-order access to former options is not possible. |
make menuconfig | An ncurses-based pseudo-graphical menu (only text input). Navigate through the menu to modify the desired options. |
make defconfig | Generates a new config with default from the ARCH supplied defconfig file. Use this option to get back the default configuration file that came with the sources. |
make nconfig | Pseudo-graphical menu based on ncurses. Requires sys-libs/ncurses to be installed. |
make xconfig | Graphical menu using Qt5. Requires dev-qt/qtwidgets to be installed. |
make gconfig | Graphical menu using GTK. Requires x11-libs/gtk+, dev-libs/glib, and gnome-base/libglade to be installed. |
make oldconfig | Review changes between kernel versions and update to create a new .config for the kernel. |
make olddefconfig | Generates a new configuration with default values from the ARCH supplied defconfig file while, at the same time, maintaining all the previous options set in the .config file found at /usr/src/linux/.config. This is a fast and safe method for upgrading a config file that has all the configuration options it needs for hardware support while at the same time gaining bug fixes and security patches. |
make localmodconfig | Creates a config based on the current config and the currently loaded modules, as viewable via the lsmod command. |
make allyesconfig | Enables all configuration options in the kernel. It will set all kernel options to * . Make sure a backup of the current kernel configuration is acquired before using this option! |
make allmodconfig | Enables all modules in kernel. Note that this operation will consume quite a bit of disk space. |
SOURCE: https://wiki.gentoo.org/wiki/Kernel/Configuration
Section 5: Compiling the Kernel
Compile the kernel with the following command, adjusting the flags as needed:
CFLAGS="-O3 -march=native -mtune=native -fno-omit-frame-pointer -g0" CXXFLAGS="-O3 -march=native -mtune=native -fno-omit-frame-pointer -g0" CPPFLAGS="-O3 -march=native -mtune=native -fno-omit-frame-pointer -g0" RUSTFLAGS="-C opt-level=3 -C target-cpu=native -C debuginfo=0" sudo make -j$(nproc) LOCALVERSION=joel bindeb-pkg
Replace `your_version` with a name that identifies your customized kernel.
I replaced "native" with znver5 and it worked but doing this in other projects breaks things. Weird. Well, it works for the Kernel so off we go.
Section 5: Installing the New Kernel
Navigate to the directory containing the generated .deb files:
cd ..
Install the new kernel and headers in the following order:
sudo dpkg -i linux-headers*.deb
sudo dpkg -i linux-image*.deb
Section 6: Managing Boot Options with Grub Customizer
Install Grub Customizer to manage your boot options:
sudo add-apt-repository ppa:danielrichter2007/grub-customizer
sudo apt-get update
sudo apt-get install grub-customizer
Use Grub Customizer to set your new kernel as the default boot option and ensure the boot menu is displayed.
Don't forget to save your configuration. It's important to enable the boot menu as well. If the newly install Kernel fails then the system can be rebooted and you can choose the last working Kernel from the menu.
Conclusion
Restart your system and cross your fingers! If any issues arise, you can start over by cleaning the compilation files and modifying the .config file as needed.
If your Kernel fails to boot, or is missing a feature or hardware support that you forgot, simply open a Bash terminal in the directory where your source code is and type:
sudo make clean
Then go to section 4 and modify the .config using xconfig tool.
By following this guide, you'll be able to compile and customize your Linux Kernel to better suit your hardware and preferences. Remember, it's a learning process, and each attempt will bring you closer to a perfectly tailored kernel. Good luck!