L5: Building the Linux Kernel from Source

                                  Chapter 2 •Free linux development course

Building the Linux Kernel from Source

The complete 7-step overview and Step 1: How to obtain the kernel source code

🐦 Kernel 6.x Updated
⏰ 20 min read
💻 Hands-on

What You Will Learn

✅ All 7 steps to build a kernel
✅ Two ways to obtain the source
✅ Tarball download vs Git clone
✅ Which method is right for you

1. The Big Picture — 7 Steps to Build a Kernel

Building the Linux kernel from source is not as hard as it sounds. It is a well-defined sequence of steps. Once you do it once, you will understand exactly what is happening at each stage. Let us look at the complete process first so you have the full picture before going into the details.

Linux Kernel Build — Complete 7-Step Process
1
Obtain the source
Download a tarball from kernel.org or clone the Git repository
2
Extract the source tree
Unpack the .tar.xz file into a directory in your home folder (skip if you used git clone)
3
Configure the kernel
Use make menuconfig to select which features and drivers to include or exclude
4
Build the kernel
Run make -j$(nproc) all to compile the kernel image, modules, and DTBs
5
Install kernel modules
Run sudo make modules_install to copy .ko files into /lib/modules/
6
Set up bootloader and initramfs
Run sudo make install to create the initramfs image and update GRUB
7
Customize GRUB (optional)
Adjust boot menu entries, default kernel, timeout settings if needed
Note: This lecture covers Step 1 in detail. The remaining steps will each get their own dedicated lecture so nothing feels rushed. Think of the 7-step overview as your map — you always know where you are in the journey.

2. What Does the Build Actually Produce?

Before we dive into Step 1, it helps to know what you are building towards. After the entire process is complete, here is what gets created:

Build Outputs — What make produces
Output File Location What It Is
bzImage arch/x86/boot/ The compressed kernel image the bootloader loads
vmlinux source root Uncompressed kernel binary, used for debugging with gdb/perf
System.map source root Symbol table mapping function names to memory addresses
*.ko files scattered in tree Loadable kernel modules, copied to /lib/modules/ at install time
*.dtb files arch/arm/boot/dts/ Device Tree Blobs, used on ARM/embedded boards (not needed on x86)

3. Step 1 — Obtaining the Linux Kernel Source

Before you can build anything, you need the source code. There are two main ways to get it. The right choice depends entirely on what you plan to do with it.

Two Ways to Get the Kernel Source
📦 Option A — Download a Tarball

Download a .tar.xz compressed file from kernel.org for a specific kernel version.

Best for: Developers working on a product or project that needs a fixed, specific kernel version.

Disk size: About 100-130 MB compressed, ~1.3 GB after extraction.

🌿 Option B — Clone via Git

Clone the full Git repository to get the latest mainline kernel with complete history.

Best for: Developers who want to contribute patches upstream and need to track the latest changes.

Disk size: 3+ GB for a full clone. Use –depth to reduce this.

Simple rule: If you are learning or working on a product, go with Option A (tarball). It is faster, predictable, and you know exactly which version you have. If you want to contribute code to the community, go with Option B (Git clone).

Option A: Downloading a Specific Kernel Tarball

The kernel source is hosted at kernel.org. From there you can download any version you need. The files are in .tar.xz format, which is a tar archive compressed with XZ compression. This format gives very good compression ratios, which is why the kernel source at ~1.3 GB compresses down to around 110-130 MB.

First, install the prerequisites your system needs to build the kernel:

sudo apt update
sudo apt install -y build-essential libncurses-dev bison flex \
    libssl-dev libelf-dev bc dwarves zstd
Why dwarves? Modern kernels from version 5.2 onwards require the pahole tool (part of the dwarves package) to generate BTF (BPF Type Format) debug information. This was not needed in older kernels. If you skip this, the build will fail with a confusing error about BTF.

Now download your chosen LTS kernel. Always verify the download with the checksum file to make sure the file was not corrupted in transit:

# Create a folder for your kernels
mkdir -p ~/kernels
cd ~/kernels

# Download the kernel tarball (replace 6.6.34 with the version you need)
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.34.tar.xz

# Download the checksum file alongside it
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.34.tar.xz.sha256

# Verify the download integrity
sha256sum -c linux-6.6.34.tar.xz.sha256

If the verification shows OK, you are good to go. If it shows FAILED, the download is corrupted and you should delete it and try again. Never build a kernel from a corrupted source — you will get strange build failures that are very difficult to debug.

Option B: Cloning the Git Repository

If your goal is to contribute patches to the kernel community, you need to work on the very latest version of the source. The mainline kernel repository is maintained by Linus Torvalds on kernel.org. Cloning it gives you the complete Git history and lets you create branches for your work.

# Clone Linus Torvalds' mainline kernel tree
# Warning: this is 3+ GB, takes time and bandwidth
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

The full clone includes the entire Git history of the project going back years. If you just want to explore the code or do a quick build, you can save time and disk space with a shallow clone. A shallow clone gives you only the most recent commits instead of the full history:

# Shallow clone with only the last 3 commits
# Much faster, much smaller download
git clone --depth=3 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
What is a shallow clone? Normally git clone downloads every commit ever made to the repository. With –depth=3, you only get the 3 most recent commits. The code is identical, but you have almost no history. This is fine for building and learning, but if you want to do git blame or git log far back in history, you will need the full clone.

After cloning, you already have the source tree extracted in a directory called linux. There is no need to run tar — git clone handles the extraction automatically. So if you used Option B, you can skip Step 2 (extracting) and go directly to Step 3 (configuration).

Decision Flow — Which Method to Use
Are you contributing patches upstream?
|
YES ─── Clone with git (Option B)
| You need the latest mainline tree
|
NO
|
Does your project require a specific kernel version?
|
YES ─── Download the tarball (Option A)
| Pick the LTS version for your project
|
NO (just learning)
|
Download the latest LTS tarball (Option A)
Fastest way to get a stable working base

🧠 Key Takeaways

Building a kernel is a 7-step process
Step 1 is about getting the source code
Tarball = fixed version, fast, best for products
Git clone = latest mainline, best for contributors
Always verify tarball with sha256sum
–depth=3 keeps Git clone small and fast
Git clone skips Step 2 (extraction)
Install dwarves for modern kernel builds

🎯 Interview Questions

Q1. What are the high-level steps to build a Linux kernel from source?

The process has 7 steps: (1) obtain the source via tarball download or git clone, (2) extract the tarball if downloaded as a compressed file, (3) configure the kernel using make menuconfig, (4) build the kernel and modules with make -j all, (5) install the modules with sudo make modules_install, (6) set up the bootloader and initramfs with sudo make install, and (7) optionally customize the GRUB menu. This chapter covers Steps 1 to 3 in detail.

Q2. When should you use a tarball download versus a Git clone to get the kernel source?

Use a tarball download when you need a specific, fixed kernel version for a product or learning project. It is faster and gives you a known-good snapshot. Use a Git clone when you want to contribute patches upstream, since you need to work on the very latest mainline code and be able to create branches and track history. For most beginners and embedded product developers, the tarball approach is the better starting point.

Q3. What is a shallow Git clone and when is it useful?

A shallow clone (using git clone –depth=n) downloads only the most recent n commits instead of the full project history. This dramatically reduces the download size and time. For a full Git clone of the Linux kernel, you need 3+ GB. A shallow clone with –depth=3 can bring that down significantly. It is useful when you just want to build the latest kernel or explore the source without needing the full history. However, if you need to investigate old commits, do git blame across many files, or bisect a bug, you need the full clone.

Q4. What is bzImage and how is it different from vmlinux?

bzImage is the compressed kernel image that the bootloader (like GRUB) loads when the system starts. The “bz” stands for big-zipped. vmlinux is the raw, uncompressed kernel binary generated during the build. The bootloader uses bzImage because it is smaller and fits in memory more easily. vmlinux is used by kernel debugging tools like gdb, perf, and crash for analyzing kernel internals and crash dumps. You need vmlinux when debugging, but the system boots from bzImage.

Q5. Why should you verify the downloaded kernel tarball before using it?

Verifying the tarball with sha256sum ensures the downloaded file is not corrupted. A partially downloaded or corrupted tarball can cause strange and difficult-to-diagnose build failures. In the worst case, a tampered tarball (if you downloaded from an untrusted source) could introduce malicious code into your kernel. Always download from the official kernel.org CDN and verify the checksum before extracting.

Q6. What is a Device Tree Blob (DTB) and which platforms need it?

A Device Tree Blob is a binary file that describes the hardware layout of a system to the Linux kernel — things like which peripherals are connected, their base memory addresses, interrupt numbers, and so on. DTBs are needed on ARM and other embedded architectures where hardware is not self-discoverable. On x86 PCs, hardware discovery happens through ACPI and PCI enumeration, so DTBs are not required. If you are doing embedded Linux work on a custom board or an ARM single-board computer, compiling and providing the correct DTB is an essential part of the build process.

Leave a Reply

Your email address will not be published. Required fields are marked *