L18: Linux Kernel Configuration: make menuconfig Explained


📖 Linux Kernel Programming — Free Course
Chapter 2 — Kernel Configuration
Lecture 18 of Series

Free Linux Kernel Development Course — Chapter 2

Linux Kernel Configuration:
make menuconfig Explained

Understand how the Linux kernel configuration system works — what Kconfig and Kbuild do,
what every menuconfig symbol means, and how the .config file drives your kernel build.
Updated for Linux 6.x.

⚙ Kbuild & Kconfig
💻 menuconfig UI
📝 .config file
🔧 Boolean & Tristate


🎯 What You Will Learn

  • Why the Linux kernel needs a configuration step before building
  • What Kbuild and Kconfig are and how they work together
  • How to run make menuconfig and fix the most common errors
  • What every symbol in the menuconfig UI means — [*], <M>, {.} and more
  • The exact difference between built-in, module, and disabled
  • How the .config file is generated and how the kernel uses it
  • All other config targets: make defconfig, make oldconfig, and more

📌 Keywords for This Lecture

make menuconfig
Kconfig
Kbuild
.config file
linux kernel build system
CONFIG_XXX=y
kernel module .ko
tristate boolean
make defconfig
make oldconfig
free linux kernel course



1. Why Does the Linux Kernel Need Configuration?

The Linux kernel runs on everything from a tiny Raspberry Pi to a 128-core cloud server to
an automotive infotainment system. The same source code tree covers all of them — but no single
build can blindly include every driver, every filesystem, every networking protocol for every
possible platform. That would produce a kernel image too large to boot on small devices and
full of drivers for hardware that does not exist on a given system.

This is the reason for the configuration step. Before you compile, you tell the
build system exactly which features, drivers, and subsystems you want. The output of this step
is a plain text file called .config. Every compile-time decision the kernel makes
flows from that single file.

How Kernel Configuration Fits Into the Build Flow

┌─────────────────────────────────────────────────────────────────────┐
│ LINUX KERNEL BUILD PIPELINE │
└─────────────────────────────────────────────────────────────────────┘┌──────────────┐ ┌────────────────┐ ┌──────────────┐
│ Kernel │ │ make │ │ .config │
│ Source Code │───▶│ menuconfig │───▶│ (choices │
│ (C files, │ │ (you choose │ │ saved as │
│ Kconfig, │ │ options) │ │ text file) │
│ Makefiles) │ └────────────────┘ └──────┬───────┘
└──────────────┘ │

┌──────────────────┐
│ make │
│ (Kbuild reads │
│ .config and │
│ compiles only │
│ what you want) │
└────────┬─────────┘


┌─────────────────────────┐
│ bzImage / vmlinux │
│ (your bootable kernel) │
└─────────────────────────┘



2. Meet Kconfig and Kbuild — The Two Pillars

These two names look similar but do completely different jobs. Confusing them is one of
the most common mistakes beginners make.

📝 Kconfig — The Configuration System

Kconfig reads special files named Kconfig that exist in almost every
directory of the kernel source tree. Each file describes available options — their
names, types (boolean or tristate), default values, dependencies, and the help text
you see when you press H in menuconfig.

The menuconfig, nconfig, and xconfig programs
all read these Kconfig files to build the menus you interact with.

Over 1,700 Kconfig files in Linux 6.x

🔧 Kbuild — The Build System

Once your choices are saved in .config, Kbuild takes over. It reads
.config and the Makefile in every source directory to
decide what to compile and what to skip. Kbuild is what turns your configuration
choices into actual object files and links them into the final kernel binary.

Kbuild is also reused by many other open source projects outside the Linux kernel
because it is so well designed.

Reads .config → produces vmlinux

Simple analogy: Kconfig is the restaurant menu — it lists everything
available. Kbuild is the kitchen — it cooks exactly what you ordered. You cannot skip
either step.



3. Running make menuconfig — and Fixing Common Errors

Go into your kernel source directory and run:

make menuconfig

This compiles a small ncurses-based host program called mconf, then launches
it. You get a full-screen text UI in your terminal. Arrow keys to navigate, Space to
toggle, Enter to go into a sub-menu, Escape to go back.

⚠️ Common Error on Fresh Ubuntu / Debian

If you run make menuconfig on a fresh system, the build will fail with:

/bin/sh: 1: bison: not found
scripts/Makefile.lib: recipe for target '...' failed
make[1]: *** Error 127

Root cause: Building mconf requires bison
(a parser generator) and flex (a lexer), which are not installed by default.
The ncurses UI also needs libncurses-dev.

Fix — Ubuntu / Debian:

sudo apt install build-essential bison flex libncurses-dev libssl-dev libelf-dev

Fix — Fedora / RHEL / Rocky:

sudo dnf install gcc make bison flex ncurses-devel openssl-devel elfutils-libelf-devel
💡 Install these once before any kernel work — they cover all chapter exercises



4. menuconfig Symbols — What Every Character Means

When menuconfig opens, every line starts with a small symbol. These are not decoration —
each symbol tells you the type of an option and its current state.
Learning them is the most important skill for navigating the kernel config UI.

There are two fundamental option types:

  • Boolean — only two states: ON or OFF
  • Tristate — three states: built-in (y), module (m), or off (n)

menuconfig Symbol Quick Reference

SYMBOL TYPE MEANING .config VALUE
─────────────────────────────────────────────────────────────────────────[*] Boolean ON → feature compiled into CONFIG_XXX=y
the kernel image (built-in)[ ] Boolean OFF → not compiled at all # CONFIG_XXX is not set

<*> Tristate ON → compiled into kernel image CONFIG_XXX=y

<M> Tristate MODULE → compiled as a .ko file CONFIG_XXX=m
loaded with modprobe on demand

< > Tristate OFF → not compiled at all # CONFIG_XXX is not set

{.} Any Dependency forces this ON. y or m
Another selected option needs
this one — you cannot disable it.

-*- Any Dependency forces BUILT-IN. y (locked)
Must be in the kernel image,
cannot be a module.

(…) String Text input prompt. Press Enter CONFIG_XXX=”your-text”
to type a value (e.g. version
string, custom name).

—> n/a Sub-menu follows. (navigation only)
Press Enter to go deeper.

─────────────────────────────────────────────────────────────────────────
TOGGLE: Press SPACE to cycle through available states for an option.
HELP: Press H or select < Help > to see full description + CONFIG name.



5. Built-in vs Module vs Disabled — The Core Choice

This decision comes up for nearly every driver and subsystem you configure.
Getting it right is the difference between a lean, fast kernel and a bloated
one — or worse, a kernel that panics because a critical driver was not present
at the right time.

Built-in vs Module vs Disabled — Side by Side

┌─────────────────────────┬──────────────────────────────┬─────────────────────────┐
│ BUILT-IN (y) │ MODULE (m) │ DISABLED (n) │
│ Symbol: [*] or <*> │ Symbol: <M> │ Symbol: [ ] or < > │
├─────────────────────────┼──────────────────────────────┼─────────────────────────┤
│ Code is PART of the │ Code compiled to a separate │ Code is NOT compiled. │
│ kernel image (vmlinux) │ .ko file on disk │ No binary produced. │
│ │ │ │
│ Available from first │ Loaded on demand via │ Feature does not exist │
│ instruction of boot │ modprobe or auto by udev │ at all in this build │
│ │ │ │
│ Cannot be unloaded │ Can be loaded AND unloaded │ Saves build time and │
│ │ without rebooting │ kernel image size │
│ │ │ │
│ .config: │ .config: │ .config: │
│ CONFIG_FOO=y │ CONFIG_FOO=m │ # CONFIG_FOO is not set │
├─────────────────────────┼──────────────────────────────┼─────────────────────────┤
│ USE WHEN: │ USE WHEN: │ USE WHEN: │
│ • Root filesystem driver│ • Optional hardware drivers │ • Hardware never used │
│ • Early boot hardware │ • Rarely used features │ • Minimising attack │
│ • Core networking stack │ • Features you test/toggle │ surface │
│ • Security subsystems │ • VirtualBox, Wi-Fi, sound │ • Minimal embedded build│
└─────────────────────────┴──────────────────────────────┴─────────────────────────┘KEY RULE: If a driver is needed BEFORE the root filesystem mounts → must be BUILT-IN.
Everything else can safely be a MODULE.



6. The .config File — Where All Your Choices Live

Every selection you make in make menuconfig is written to a plain text file
called .config in your kernel source root. This file is the only input
Kbuild needs. You can open it with any editor — it is human-readable.

#
# .config — Linux Kernel Configuration
# Generated by make menuconfig
#

#
# General setup
#
CONFIG_LOCALVERSION="-mydevice"
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y

# CONFIG_PROFILING is not set
# CONFIG_HAMRADIO is not set

CONFIG_VBOXGUEST=m
CONFIG_UIO=m

# CONFIG_SECURITY is not set  ← WARNING: never do this on real systems

CONFIG_DEBUG_STACK_USAGE=y

The three patterns you must memorise:

  • CONFIG_XXX=y  →  built into kernel image
  • CONFIG_XXX=m  →  compiled as a loadable module
  • # CONFIG_XXX is not set  →  disabled, not compiled


📌 Reading Your Running Kernel’s Config — Linux 6.x

You do not always have to build from scratch to see a kernel’s config. On modern systems:

# Method 1 — most distros store it here (Ubuntu, Fedora, Arch):
cat /boot/config-$(uname -r)

# Method 2 — if CONFIG_IKCONFIG_PROC=y was set at build time:
zcat /proc/config.gz | less

# Method 3 — Linux 6.x stores config here too:
cat /lib/modules/$(uname -r)/config

# Method 4 — extract from kernel image directly:
./scripts/extract-ikconfig /boot/vmlinuz-$(uname -r) > recovered.config
💡 Tip: grep it! e.g. cat /boot/config-$(uname -r) | grep CONFIG_USB



7. How menuconfig Works Internally — Step by Step

When you type make menuconfig, several things happen before you even see
the first screen. Understanding this removes the mystery from error messages.

What Happens When You Run make menuconfig

Step 1 — Compile mconf
──────────────────────────────────────────────────────────────────────────
make compiles scripts/kconfig/mconf.c into a host binary called mconf.
This requires: bison (parser), flex (lexer), libncurses (terminal UI).
If any of these are missing → you see the “not found” error here.Step 2 — Parse all Kconfig files
──────────────────────────────────────────────────────────────────────────
mconf starts at the root Kconfig file.
That file uses “source” statements to pull in every sub-directory’s
Kconfig. This builds up a complete tree of 10,000+ possible options.Kconfig (root)
├── source init/Kconfig
├── source drivers/Kconfig
│ ├── source drivers/net/Kconfig
│ ├── source drivers/usb/Kconfig
│ └── …
├── source fs/Kconfig
└── … (1700+ files in Linux 6.x)

Step 3 — Load existing .config (if found)
──────────────────────────────────────────────────────────────────────────
If .config already exists in your source dir, your previous choices
are pre-loaded into the menu. If not, architecture defaults are used.

Step 4 — You interact with the menu
──────────────────────────────────────────────────────────────────────────
You navigate, toggle, and change options.
Dependencies are enforced in real time:
→ Enable feature A that needs feature B → B is auto-selected.
→ Try to disable B while A still needs it → not allowed.

Step 5 — Save to .config on exit
──────────────────────────────────────────────────────────────────────────
On exit → “Save configuration?” → Yes → .config written to disk.
The kernel build (make) then reads this file. Done.



8. All Configuration Targets — Linux 6.x Reference

make menuconfig is just one of many config targets. Here are all the
important ones — every kernel developer should know these:

Kernel Configuration Targets Reference (Linux 6.x)

TARGET INTERFACE DESCRIPTION
──────────────────────────────────────────────────────────────────────────make menuconfig ncurses TUI Full-screen text menu.
✓ Works in any SSH terminal.
✓ Best for daily use.make nconfig ncurses TUI Alternative text menu with F-key
shortcuts (F1=help, F6=save etc).
Slightly faster to navigate.

make xconfig Qt GUI Mouse-driven graphical interface.
Needs Qt5 dev libraries.
Good for exploring option trees.

make gconfig GTK GUI GTK-based GUI. Needs gtk2-devel.
Less commonly used today.

make defconfig None (auto) Generates a default .config for
your current architecture.
✓ Best starting point for a build.

make oldconfig Prompt only Loads existing .config and prompts
ONLY for options new in this kernel
version. Everything else unchanged.
✓ Use when upgrading kernel version.

make olddefconfig None (auto) Like oldconfig but silently sets
all new options to their defaults.
✓ Use in scripts / CI builds.

make allmodconfig None (auto) Sets ALL tristate options to module.
Good for testing module builds.

make allyesconfig None (auto) Sets ALL options to yes (built-in).
Warning: produces huge kernel image.

make allnoconfig None (auto) Sets ALL options to no/off.
Minimal possible kernel — mostly
used for testing and CI.

make localmodconfig None (auto) Reads currently LOADED modules on
your running system and sets only
those to =m. Everything else off.
✓ Great for lean custom builds.

──────────────────────────────────────────────────────────────────────────
Where to learn more: Documentation/kbuild/kconfig.rst (in kernel source)



✅ Key Takeaways — Lecture 18

  • The kernel must be configured before building — .config drives everything
  • Kconfig describes options  |  Kbuild compiles based on them
  • Install bison flex libncurses-dev before running make menuconfig
  • [*] / <*> = built-in (y)   |   <M> = module (m)   |   empty = off (n)
  • Built-in = always present from boot; Module = loaded on demand with modprobe
  • All choices are plain text in .config — readable and portable
  • Use make olddefconfig when upgrading kernel version to keep existing choices



🌟 Frequently Asked Questions

What is make menuconfig in Linux kernel?

make menuconfig is the most widely used interface for configuring the
Linux kernel before compiling it. It launches a full-screen, text-based menu in your
terminal (powered by the ncurses library) that lets you browse thousands of kernel
options, enable or disable features, and choose whether drivers are built into the
kernel image or compiled as loadable modules. Your selections are saved to a file
called .config, which the Kbuild system reads when you run make
to actually compile the kernel.

What is the difference between Kconfig and Kbuild?

Kconfig is the configuration system — it defines every available
kernel option using special text files named Kconfig scattered across
the source tree. Programs like menuconfig read these files to build
the interactive menus. Kbuild is the build system — it reads the
resulting .config file and uses Makefile rules in every
source directory to compile and link only the selected components into the final
kernel binary. Put simply: Kconfig is about choosing what to build; Kbuild is about
actually building it.

What is the .config file in Linux kernel compilation?

The .config file is a plain text file placed at the root of your kernel
source directory. It contains one line per configuration option in one of three forms:
CONFIG_XXX=y (built-in), CONFIG_XXX=m (loadable module), or
# CONFIG_XXX is not set (disabled). Kbuild reads this file to determine
which C source files to compile, which to skip, and how to link the final kernel. It
is the single source of truth for your entire kernel build.

What does tristate mean in Linux kernel configuration?

A tristate option can take three values: y (built into the kernel image),
m (compiled as a loadable kernel module), or n (not compiled
at all). Tristate options appear with angle brackets in menuconfig — <*>
for built-in, <M> for module, < > for off. Boolean
options only have two states (on or off) and appear with square brackets. Most device
drivers are tristate because you often want the flexibility to load the driver only when
the hardware is present.

Why does make menuconfig fail with “bison not found”?

Before menuconfig can display its UI, the kernel build system compiles a small host
program called mconf from C source. Building mconf requires
bison (a parser generator) and flex (a lexer) to be installed
on your host machine. If either is missing, the build fails with the “not found” error.
Fix it on Ubuntu/Debian with:
sudo apt install bison flex libncurses-dev.
On Fedora/RHEL: sudo dnf install bison flex ncurses-devel.

What is the difference between make oldconfig and make olddefconfig?

Both targets are used when you want to carry an existing .config to a new
kernel version. make oldconfig reads your existing choices and
interactively prompts you for any options that are new in the updated kernel —
you must answer each one manually. make olddefconfig does the same but
silently sets all new options to their default values without prompting.
Use oldconfig when you want control over new options; use
olddefconfig in scripts and CI pipelines where interactive input is not
possible.

How do I view my running kernel’s configuration in Linux?

There are several ways. Most Linux distributions store the kernel config at
/boot/config-$(uname -r) — run cat /boot/config-$(uname -r)
to read it. If the kernel was built with CONFIG_IKCONFIG_PROC=y, the
config is also exposed at /proc/config.gz — read it with
zcat /proc/config.gz. On Linux 6.x, many distributions also place it at
/lib/modules/$(uname -r)/config. If you have the kernel image file, you
can use the scripts/extract-ikconfig script to extract the embedded config
(only if CONFIG_IKCONFIG=y was set at build time).



📷 Suggested Images for This Post

  • Hero image: Terminal screenshot of make menuconfig
    running on Ubuntu 24.04 with the Linux 6.8 kernel source — General Setup menu
    open. Alt text: “make menuconfig Linux kernel configuration menu on Ubuntu”
  • Section 5: Two-panel image — left panel shows the kernel image
    size with everything built-in, right panel shows the same kernel with most
    drivers as modules. Highlights the size difference visually.
    Alt text: “Linux kernel built-in vs module size comparison”
  • Section 6: Text editor screenshot of an actual .config
    file with CONFIG_XXX=y, =m, and is-not-set lines highlighted in different colours.
    Alt text: “Linux kernel .config file showing CONFIG_XXX=y and CONFIG_XXX=m”
  • Section 8: Comparison grid of menuconfig vs nconfig vs xconfig
    screenshots side by side. Alt text: “Linux kernel menuconfig nconfig xconfig comparison”



📖 Linux Kernel Programming — Free Course
Lecture 18

EmbeddedPathashala — Free Embedded Systems & Linux Kernel Education — embeddedpathashala.com

Leave a Reply

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