Week 1 — Environment Setup and First Kernel Build¶
Goal¶
By the end of this week you will have the kernel source cloned, all build dependencies installed, and your first custom kernel compiled. You won't boot it yet — that's next weeks — but you'll understand what the build produces and how long it takes on your machine.
Why This Matters¶
Everything in kernel development starts with being able to build the kernel. If you can't build it, you can't test changes, you can't generate patches, you can't contribute. Your 32-core VM is excellent for this — a full kernel build should take under 5 minutes.
Step 1: Install Build Dependencies¶
The kernel builds with GCC (or Clang), GNU Make, and a handful of tools. On Debian 13:
sudo apt update
sudo apt install -y \
build-essential \
bc \
bison \
flex \
libssl-dev \
libelf-dev \
libncurses-dev \
dwarves \
git \
fakeroot \
cpio \
rsync \
kmod \
zstd
What these are:
build-essential— GCC, make, libc headers. The compiler toolchain.bc,bison,flex— used by the kernel's build scripts and Kconfig parser.libssl-dev— needed if module signing is enabled (it is by default in most configs).libelf-dev,dwarves— for BTF (BPF Type Format) generation. Modern kernels want this.libncurses-dev— formake menuconfig, the TUI configuration tool.kmod— formodprobe,lsmod, etc.
Step 2: Clone the Kernel Source¶
You want two remotes: Linus's mainline tree and the netdev tree (the networking subsystem).
This clones the full history (~4 GB). It will take a while. Once done, add the net-next tree — this is where networking development happens:
git remote add net-next https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
git fetch net-next
There are two networking trees:
- net — bug fixes for the current release cycle
- net-next — new features targeting the next merge window
As a new contributor, most of your work will target net-next.
Verify:
You should see recent commits from Linus's tree.
Step 3: Create a Build Configuration¶
The kernel has thousands of configurable options. You need a .config file that tells the
build system what to include. Start with your running kernel's config:
Then update it for the source tree version:
This takes your existing config, keeps all your answers, and sets new options to their defaults. It's the safest way to get a working config for a new kernel version.
Expect: A few lines of output showing options being set to defaults.
Step 4: Build the Kernel¶
-j$(nproc) runs one job per CPU core. With 32 cores, this is make -j32.
Expect: A wall of output like:
Build time: On your 32-core VM, roughly 3-8 minutes for the first build. Subsequent builds after small changes take seconds because make only recompiles changed files.
What gets produced:
vmlinux— the uncompressed kernel ELF binary (~hundreds of MB). Used for debugging.arch/x86/boot/bzImage— the compressed, bootable kernel image (~10-12 MB). This is what the bootloader loads.*.kofiles throughout the tree — kernel modules.
Step 5: Build Modules¶
This builds all the loadable kernel modules (drivers, filesystems, etc.) that your .config
marked as =m (module) rather than =y (built-in).
Step 6: Understand What You Just Built¶
Run these commands and think about what they tell you:
# Size of the compressed kernel
ls -lh arch/x86/boot/bzImage
# How many modules were built
find . -name '*.ko' | wc -l
# Your kernel version string
make kernelversion
# The full version with local version
cat include/config/kernel.release
Step 7: Set Up Your Editor¶
Since you use neovim, set up a compile_commands.json for LSP support:
# Install bear if you want compilation database
sudo apt install -y bear
# Generate compile_commands.json
make clean
bear -- make -j$(nproc)
This gives you go-to-definition, autocompletion, and diagnostics in neovim if you have an LSP client configured (clangd works well with the kernel).
Alternatively, the kernel has a built-in script:
Exercises¶
- Run
make helpand read through the available targets. Note the ones related to configuration (*configtargets) and cleaning (clean,mrproper,distclean). - Look at the top-level
Makefile. Find whereVERSION,PATCHLEVEL,SUBLEVELare defined. This is how the kernel version string is built. - Run
wc -l .config— how many configuration lines does your kernel have?
What's Next¶
Next week we dive into the configuration system (Kconfig) and menuconfig. You'll learn
how to enable/disable features, what =y, =m, =n mean, and how to create a minimal
config for QEMU instead of the bloated distro config.