Free Linux Kernel Development Course — Chapter 2
Configuring the Linux Kernel
Master kbuild, .config, localmodconfig and menuconfig — Updated for Kernel 6.x
Welcome to Lecture 14 of the free Linux kernel development course on EmbeddedPathashala. This lecture covers one of the most important steps in kernel development — configuring the Linux kernel. Before you can compile a single line of kernel code, you must tell the build system exactly what to include. This is done through the kbuild configuration system. Whether you are pursuing a free embedded Linux course, a free Linux device drivers course, or a broader free embedded systems course, understanding kernel configuration is a foundational skill you cannot skip.
The kernel is not a monolithic fixed binary. It supports hundreds of CPU architectures, thousands of devices, and thousands of optional features. Configuration lets you build exactly what you need — nothing more, nothing less.
Keywords Covered in This Lecture
.config file
make menuconfig
localmodconfig
Kconfig
make defconfig
make olddefconfig
CONFIG_=y/m/n
embedded Linux
BSP config
make mrproper
kernel modules
🎓 What You Will Learn
- Why the Linux kernel must be configured before building
- What the
.configfile is and how it controls everything - The three states of any kernel config option: Y, M, and N
- How to generate a lean starting config using
make localmodconfig - How to browse and fine-tune the config using
make menuconfig - All available kernel configuration tools compared side by side
- Cross-machine config techniques for embedded Linux development
- Common mistakes beginners make during kernel configuration
- Best practices for managing kernel configs in real projects
✅ Prerequisites
- Basic Linux command line knowledge (
ls,cd,make) - Completed Lectures 1–13 of this free Linux kernel development course, or equivalent familiarity with the kernel source tree
- A Linux machine (Ubuntu 22.04+ or Fedora 38+ recommended) with build tools installed
- Kernel source downloaded and extracted (see previous lecture)
1. Why Does the Linux Kernel Need to Be Configured?
The Linux kernel source tree contains over 30 million lines of code. It supports everything from tiny embedded microcontrollers to massive server machines with hundreds of CPU cores. Every driver, every protocol, every optional feature is present in the source. But you do not want all of it compiled into every kernel image — that would be enormous and impractical.
Configuration is how you tell the kbuild system what to include. If you are taking this free Linux kernel development course to build drivers for a specific piece of hardware, you need to know which config options enable your target subsystem. If you are on a free embedded Linux course, you need a lean kernel with only what your board needs. Configuration is the first step toward both goals.
Think of it like ordering a custom-built PC — you pick exactly which components go in, and everything else stays out. The output of this selection process is a file called .config.
Kconfig files
C source
generates
.config
compiles only
what you chose
bzImage
+ modules.ko
2. The .config File — How the Kernel Knows What to Build
The .config file is a plain text file that lives in the root of the kernel source tree. It contains hundreds or thousands of lines, one for each configuration option. Every option is prefixed with CONFIG_ and assigned a value. Here is what a real snippet looks like:
#
# General setup
#
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_USB_SERIAL=m
There are exactly three possible states for any kernel config option:
.ko file. Can be loaded and unloaded at runtime using modprobe. Stored in /lib/modules/$(uname -r)/. Ideal for optional hardware support.💡 Embedded Developer Note
On embedded systems, it is common to build critical drivers as built-in (=y) rather than modules (=m). The reason: modules require a filesystem to be mounted before they can be loaded, but some drivers — like the storage driver for the root filesystem — must be available before any filesystem is mounted. If you are studying a free embedded systems course, this Y vs M distinction will come up repeatedly in your device driver work.
3. Start Clean — Preparing the Kernel Source Tree
Before generating a config, especially if you are working in a source tree that was previously built, you should start from a clean state. The kernel provides commands for this:
# Removes ALL generated files including .config
# Use when starting completely from scratch
make mrproper
# Even more thorough — also removes editor backup files
make distclean
# Lighter clean — keeps .config but removes compiled objects
make clean
⚠️ Warning: mrproper Deletes Your .config
Both make mrproper and make distclean will delete your existing .config file permanently. Always back it up first:
cp .config ~/backup-kernel.config
4. Generating Your First Config with make localmodconfig
If you are building the kernel for your own development machine, the fastest and most practical way to generate a starting .config is make localmodconfig. This target looks at what kernel modules are currently loaded on your running system and generates a config that includes only those — nothing unnecessary.
Your running system already knows exactly what hardware it needs. localmodconfig captures that knowledge as a config file.
Step 1 — Capture the Currently Loaded Modules
# lsmod lists all currently loaded kernel modules
# Save this list to a file
lsmod > /tmp/lsmod.now
# Verify it captured something
wc -l /tmp/lsmod.now
Step 2 — Generate the Config from Your Module List
# Point kbuild at your module list and generate .config
make LSMOD=/tmp/lsmod.now localmodconfig
When you run this, kbuild reads the running kernel’s existing config (found at /boot/config-$(uname -r)) and trims it down to match your loaded modules. For any new options that did not exist in the old config, it prompts you with a (NEW) marker. Simply press Enter to accept the default.
Here is a representative sample of the output you will see. The full output is much longer — this shows the important patterns:
$ make LSMOD=/tmp/lsmod.now localmodconfig
*
* General setup
*
Compile also drivers which will not load (COMPILE_TEST) [N/y/?] n
Local version (LOCALVERSION) []
Kernel compression mode
1. Gzip (KERNEL_GZIP)
2. Bzip2 (KERNEL_BZIP2)
3. XZ (KERNEL_XZ)
4. LZ4 (KERNEL_LZ4)
choice[1-4?]: 1
...
Enable userfaultfd() system call (USERFAULTFD) [Y/n/?] y
Enable rseq() system call (RSEQ) [Y/n/?] (NEW) <-- press Enter
...
#
# configuration written to .config
#
$ ls -lh .config
-rw-r--r-- 1 user user 140K Jun 20 10:31 .config
📋 Tip: What Does (NEW) Mean?
When you see a prompt ending with (NEW), it means this config option did not exist in the running kernel’s config. For most new options, pressing Enter accepts the default value, which is safe for a first build.
Cross-Machine localmodconfig for Embedded Targets
A powerful feature for embedded Linux developers: you can generate a localmodconfig for a different target board. Run lsmod on the target, transfer the file to your build host, and generate a matching config there.
# On the target board:
lsmod > /tmp/target-modules.txt
scp /tmp/target-modules.txt buildhost:/tmp/
# On the build host (cross-compile scenario):
make LSMOD=/tmp/target-modules.txt localmodconfig
# Preserve specific subsystems even if not in the lsmod list:
make LSMOD=/tmp/target-modules.txt \
LMC_KEEP="drivers/usb:drivers/gpu:fs" \
localmodconfig
5. All Kernel Configuration Tools Compared
The kernel provides five different ways to view and edit the .config file. They all produce the same .config output — they just offer different user interfaces. As a student of this free Linux kernel development course, you should know all of them.
| Command | Interface | Requires | Best For |
|---|---|---|---|
| make config | Plain text Q&A | Nothing | Scripting / automation |
| make menuconfig | Text color menus (ncurses) | libncurses-dev |
SSH & headless servers — most popular |
| make nconfig | Enhanced text + F-keys | libncurses-dev |
Cleaner terminal with shortcuts |
| make xconfig | Graphical GUI (Qt) | qtbase5-dev |
Desktop users, easy visual search |
| make gconfig | Graphical GUI (GTK) | libgtk-3-dev |
GNOME desktop users |
6. Fine-Tuning Kernel Config with make menuconfig
Once you have a starting .config from localmodconfig or another source, use make menuconfig to browse and modify it visually. This is the core workflow skill for anyone doing Linux kernel development or writing Linux device drivers.
Install the Required Dependency
# Debian / Ubuntu / Linux Mint:
sudo apt-get install libncurses-dev
# Fedora / RHEL / Rocky Linux:
sudo dnf install ncurses-devel
# Arch Linux:
sudo pacman -S ncurses
Launch menuconfig
# From the root of the kernel source tree:
make menuconfig
# For a specific architecture (cross-compile / embedded):
make ARCH=arm64 menuconfig
make ARCH=arm menuconfig
The first time you run this, kbuild compiles a helper C program called mconf inside the kernel tree. This only happens once:
UPD scripts/kconfig/.mconf-cfg
HOSTCC scripts/kconfig/mconf.o
HOSTCC scripts/kconfig/lxdialog/checklist.o
HOSTCC scripts/kconfig/lxdialog/menubox.o
HOSTCC scripts/kconfig/lxdialog/inputbox.o
HOSTLD scripts/kconfig/mconf
scripts/kconfig/mconf Kconfig
After that, the colorful menu screen appears immediately. Here is a representation of what the top-level menu looks like:
<Exit>
<Help>
<Save>
<Load>
Keyboard Navigation Reference
| Key | Action |
|---|---|
| ↑ ↓ Arrow | Move up / down through the menu list |
| Enter | Enter a submenu (items shown with --->) |
| Y | Set selected option to built-in (=y) |
| M | Set selected option to module (=m) |
| N | Disable the selected option |
| Space | Toggle between Y / M / N |
| ? | Show help text for the highlighted option |
| / | Open search dialog — find any config symbol by name |
| Esc Esc | Go back to previous menu or exit menuconfig |
How to Search for a Config Option in menuconfig
This is one of the most useful skills in the entire free Linux kernel development course. When you know the name of a config symbol but not which submenu it lives under, use the built-in search:
# While inside menuconfig, press the / key
# Type your search term — example: USB_SERIAL
# menuconfig shows the option, its current value,
# its exact menu location, and all its dependencies
Search results show you the exact path through the menu tree where the option lives, so you can navigate directly to it. This saves enormous time when dealing with the thousands of options a real kernel has.
7. Other Important Config Targets Every Developer Should Know
Beyond localmodconfig and menuconfig, the kbuild system provides many more configuration targets essential for real-world free Linux device drivers development and embedded work.
# Start from the architecture's default configuration
make defconfig
# Like localmodconfig but sets all modules to built-in (=y)
# Ideal for embedded systems where you want everything baked in
make localyesconfig
# Update an existing .config for a new kernel version interactively
# Asks you about each NEW option added since your old config was made
make oldconfig
# Same as oldconfig but automatically accepts the default
# Best for automated CI builds or quick upgrades
make olddefconfig
# Produce the absolute smallest possible kernel (research/testing only)
make tinyconfig
# Add settings optimized for running Linux inside a KVM virtual machine
make kvm_guest.config
localmodconfig
OR
make ARCH=arm64 defconfigmenuconfig
Disable unused options
8. Common Mistakes Beginners Make in Kernel Configuration
❌ Mistake 1: Running make before creating .config
If you run make without a .config file present, the build fails immediately with: *** Configuration file ".config" not found! Always generate or copy a config first.
❌ Mistake 2: Setting a boot-critical driver to =m
If you set the driver for your root filesystem or storage controller to module (=m), the kernel cannot mount root during boot. The system hangs with a kernel panic. Storage drivers and the root filesystem driver must always be =y.
❌ Mistake 3: Using make allyesconfig carelessly
make allyesconfig enables everything as built-in. The resulting kernel is hundreds of megabytes and will not boot on most real hardware due to conflicts. Use it only for compile-testing, never for a real machine.
❌ Mistake 4: Not backing up a working .config
Many students run make mrproper while troubleshooting and lose their carefully crafted configuration. Always back it up: cp .config ~/configs/working-$(uname -r)-$(date +%Y%m%d).config
❌ Mistake 5: Skipping make olddefconfig when upgrading kernel version
When you upgrade from kernel 6.6 to 6.12 with the same .config, new options from the newer kernel may be missing. Always run make olddefconfig first when reusing a config across different kernel versions.
9. Best Practices for Kernel Configuration
✅ Always start from a known-good base config
In production and embedded projects, your hardware vendor or BSP team provides a tested .config. In a learning build, start from localmodconfig or defconfig. Never start from scratch by manually editing .config — the dependency chains are too complex.
✅ Version-control your kernel configs
Treat your .config like source code. Keep it in a git repository. Name it clearly, for example rpi4-6.12-production.config. When a config produces a working kernel, tag that commit in git.
✅ Use make olddefconfig for kernel upgrades
Do not take a .config from kernel 6.6 and compile kernel 6.12 with it directly. Always run make olddefconfig first to populate all new symbols with safe defaults.
✅ Document your deliberate config changes
When you enable or disable a specific option for a reason (for example, enabling CONFIG_KGDB for kernel debugging), note it in your project README. Future-you will be grateful when debugging six months later.
10. Under the Hood — How Kconfig Works Internally
Every directory in the kernel source tree contains a Kconfig file. These files define the configuration options for that subsystem, their names, types, descriptions, dependencies, and defaults. When you run make menuconfig, kbuild reads all these files recursively and assembles the menu tree you see on screen.
When you save and exit, your choices go into .config. Before compilation starts, the build system generates two intermediate files that the C compiler and Makefiles actually use:
include/generated/autoconf.h
# C header auto-included in every kernel C file.
# CONFIG_SYSVIPC=y in .config becomes:
# #define CONFIG_SYSVIPC 1
include/config/auto.conf
# Makefile fragment used by the build system.
# CONFIG_USB_SERIAL=m expands to: obj-m += usb-serial.o
This is how kernel developers write conditionally compiled code:
#ifdef CONFIG_SYSVIPC
ipc_init(); /* only compiled when CONFIG_SYSVIPC=y */
#endif
/* IS_ENABLED() works for both =y and =m */
if (IS_ENABLED(CONFIG_USB_SERIAL)) {
/* runs when USB serial is configured */
}
CONFIG_ABC=m
#define CONFIG_USB_SERIAL_MODULE 1
obj-$(CONFIG_USB_SERIAL) += …
11. Quick Command Reference Card
# CLEAN THE SOURCE TREE
make mrproper # Full clean, removes .config too
make distclean # mrproper + removes editor backup files
make clean # Remove objects only, keep .config
# GENERATE A STARTING .config
lsmod > /tmp/lsmod.now
make LSMOD=/tmp/lsmod.now localmodconfig # Based on running system
make defconfig # Architecture defaults
make tinyconfig # Absolute minimum kernel
# BROWSE AND EDIT THE .config
make menuconfig # Text menus (ncurses) — recommended
make nconfig # Enhanced text menus with F-key shortcuts
make xconfig # Qt-based graphical UI
make gconfig # GTK-based graphical UI
# UPDATE .config FOR A NEWER KERNEL VERSION
make oldconfig # Interactive — asks about new options
make olddefconfig # Auto-accept defaults for new options
# SPECIAL TARGETS
make localyesconfig # Like localmodconfig but =y instead of =m
make kvm_guest.config # Optimized for KVM guest kernel
make xen.config # Optimized for Xen dom0 guest
12. Summary and Key Takeaways
Kernel configuration is not just a setup step — it is a core skill for anyone in Linux kernel development, embedded Linux, or device driver writing. In this lecture from our free Linux kernel development course, you learned:
- The
.configfile controls every aspect of what gets compiled. It is the most important file in your build. - Every option is either built-in (
=y), a loadable module (=m), or disabled. Choosing correctly — especially for boot-critical drivers — determines whether your system boots at all. make localmodconfigis the fastest way to get a lean, working starting config for your development machine.make menuconfigis the standard tool for browsing and editing config. It works over SSH and has a powerful search function.- For embedded Linux work, the BSP vendor’s config is your starting point. Use
make ARCH=arm64 menuconfigto tailor it for your board. - Always run
make olddefconfigbefore building a newer kernel version with an existing config. - Back up any config that produces a working kernel. Treat it like source code.
🔗 Authoritative References and Further Reading
- Official Linux Kernel Kconfig Documentation: docs.kernel.org/kbuild/kconfig.html
- Linux Kernel 6.x README: www.kernel.org/doc/html/latest/admin-guide/README.html
- Kernel Build System (kbuild) Documentation: docs.kernel.org/kbuild/index.html
- Linux Kernel Makefiles Reference: docs.kernel.org/kbuild/makefiles.html
- Kconfig Language Specification: docs.kernel.org/kbuild/kconfig-language.html
Frequently Asked Questions — Linux Kernel Configuration
Q1. What is the .config file and why is it needed in Linux kernel development?
The .config file is the kernel’s master configuration file. It is a plain text file containing hundreds of CONFIG_ options, each set to y (built-in), m (module), or left unset (disabled). Without it, the kernel cannot be compiled. Every free Linux kernel development course teaches this as the very first step before building.
Q2. What does make localmodconfig do and when should I use it?
make localmodconfig generates a .config based on the kernel modules currently loaded on your running system. It produces a lean config that includes only what your hardware actually needs. Use it when setting up a development kernel build on your own machine for a much faster build and smaller kernel image.
Q3. What is the difference between CONFIG_=y (built-in) and CONFIG_=m (module)?
A built-in option (=y) is compiled directly into the kernel image and is always available from boot. A module (=m) is compiled as a separate .ko file and can be loaded or unloaded at runtime. For boot-critical drivers like storage controllers, you must use =y. For optional hardware, =m gives flexibility without bloating the kernel image.
Q4. What is make menuconfig and why is it the most popular kernel configuration tool?
make menuconfig is a terminal-based color menu system for browsing and editing the kernel configuration. It is the most popular tool because it works in any terminal including SSH sessions to remote servers, and requires no graphical desktop. It also features a search function — press / — to find any config option by name instantly.
Q5. What is make mrproper and when should I use it?
make mrproper removes all generated files from the kernel source tree including the .config file and all compiled objects. Use it when starting a completely fresh build from scratch. Always back up your .config before running it since the deletion is permanent.
Q6. How do I update my .config when upgrading to a newer kernel version?
Run make olddefconfig from the root of the new kernel source tree with your existing .config in place. This automatically accepts default values for all new config options introduced in the newer kernel. If you want to manually review each new option, use make oldconfig instead.
Q7. Where do Kconfig files live and what do they do?
Kconfig files are present in almost every directory of the kernel source tree. Each one defines the configuration options for that subsystem, including their names, types, descriptions, default values, and dependencies on other options. When you run make menuconfig, kbuild reads all these files recursively to build the menu tree.
Q8. In embedded Linux development, where does the initial kernel config come from?
In embedded projects, the initial .config typically comes from the hardware vendor or BSP team. It is a tested, known-good configuration for the specific platform. If no vendor config is available, start with make ARCH=arm64 defconfig to get architecture defaults, then use make ARCH=arm64 menuconfig to enable board-specific drivers.
Q9. What is the difference between make nconfig and make menuconfig?
Both use an ncurses-based terminal interface. nconfig displays function key shortcuts at the bottom of the screen making navigation more discoverable, and has a slightly cleaner layout. For most purposes they are equivalent and both require libncurses-dev to be installed.
Q10. Is this free Linux kernel development course suitable for complete beginners?
Yes. EmbeddedPathashala’s free Linux kernel development course starts from fundamentals — setting up the build environment, downloading kernel source, understanding the source tree structure — and progressively builds up to writing actual kernel modules and device drivers. Basic Linux command line familiarity is expected, but no prior kernel experience is required.
Free Linux Kernel Development Course — Lecture 14 — Updated for Kernel 6.x
