Understanding Kconfig And Kbuild-Best Embedded Linux Training Online

PREV_LEC NEXT_LEC

Understanding Kconfig And Kbuild
Free Embedded Linux Course — Chapter 4: Porting And Configuring The Kernel
Part of: Free Linux Kernel Development Course
Level: Intermediate
Reading Time: ~13 min

Every one of the thousands of options that decide what goes into your kernel build — from which filesystems are compiled in to which drivers are built as modules — is driven by a system called Kconfig, paired with a build system called Kbuild. This lecture in our free linux kernel development course demystifies both, and walks through writing your own Kconfig entry for an original demo driver so you can see the mechanism end to end.

Kconfig
Kbuild
menuconfig
kernel configuration
ARCH variable
free linux device drivers course

What You Will Learn

What Kconfig and Kbuild each actually do
How the ARCH variable shapes the whole config menu
Reading and writing a Kconfig menu entry
The difference between y, m, and unset config values
Adding your own driver’s config option from scratch

Prerequisites

You should already know your way around the kernel source tree’s top-level layout (covered in the previous lecture of this free embedded linux course) and be comfortable running basic shell commands inside a checked-out kernel tree.

Why Configuration Exists

Linux runs on everything from a smart thermostat with kilobytes of flash to a rack server with terabytes of RAM. A single build can’t sensibly include every driver, filesystem, and subsystem for every possible target — that would be enormous, slow to build, and full of code that’s simply irrelevant on most boards. Kconfig is the mechanism that lets you select, out of many thousands of options, exactly the subset relevant to your hardware and use case.

Kconfig vs Kbuild: Two Different Jobs

System Job
Kconfig Declares configuration options and their dependencies/relationships; produces the .config file describing what’s enabled
Kbuild The actual build system (an extension of GNU Make) that reads .config and decides which files to compile, and whether each is built into the kernel image or as a loadable module

Both are documented in Documentation/kbuild/ inside every kernel tree, and both are reused well beyond Linux itself — U-Boot, Barebox, BusyBox, and crosstool-NG all adopt the same Kconfig language for their own configuration menus, so learning it here pays off elsewhere too.

The Role of ARCH

Kconfig files are declared in a hierarchy, starting from a single top-level Kconfig file that sources an architecture-specific one based on the ARCH environment variable:

$ make ARCH=arm64 menuconfig

If you omit ARCH=, the build system defaults to your local host’s architecture — almost never what you want for embedded cross-compilation. Always set it explicitly. Note the one well-known oddity: both ARCH=i386 and ARCH=x86_64 resolve to the same source directory, arch/x86/Kconfig.

How ARCH Selects Your Config Menu
make ARCH=arm64 menuconfig
|
v
top-level Kconfig
|
| sources arch/$ARCH/Kconfig
v
arch/arm64/Kconfig
|
| pulls in driver/subsystem Kconfig files
v
drivers/*/Kconfig, fs/Kconfig, net/Kconfig, …
|
v
final menuconfig UI shown to you

Anatomy of a Kconfig Entry

Kconfig files are built from menu / endmenu blocks containing individual config entries. Here’s an original, simplified example modeled on real kernel style — a hypothetical option for an EmbeddedPathashala demo driver:

menu "EmbeddedPathashala demo drivers"

config EP_DEMO_GPIO_BLINKER
	tristate "EP GPIO blinker demo driver"
	depends on GPIOLIB
	default n
	help
	  Say Y or M here to build the EmbeddedPathashala GPIO blinker
	  demo driver, used in the free linux device drivers course to
	  illustrate basic Kconfig and Kbuild integration.

	  If unsure, say N.

endmenu

Breaking this down field by field:

Field Meaning
config EP_DEMO_GPIO_BLINKER Declares a variable named CONFIG_EP_DEMO_GPIO_BLINKER
tristate "..." The option can be y (built-in), m (module), or unset — the quoted string is the menu label shown to the user
depends on GPIOLIB This option is only offered if the GPIO subsystem is also enabled
default n Disabled unless the user explicitly enables it
help Longer description shown when the user requests help text in the menu

A simpler alternative is bool instead of tristate, which only allows y or unset — no module option. The kernel’s own drivers/char/Kconfig has a good real example of this, the DEVMEM option controlling /dev/mem support.

Wiring It Into Kbuild

Declaring the option in Kconfig alone doesn’t build anything — Kbuild’s Makefile in the same directory decides what to actually compile based on the resulting CONFIG_* value:

# drivers/gpio-demo/Makefile (example, not a real kernel path)
obj-$(CONFIG_EP_DEMO_GPIO_BLINKER) += ep_gpio_blinker.o

This one line is the entire integration: if the option resolves to y, the object file is linked into the kernel image; if m, it’s built as a standalone .ko module; if unset, Kbuild skips it entirely. No conditional compilation logic needed elsewhere — Kbuild handles it purely from the variable’s value.

Trying It: Running menuconfig

With any real driver’s Kconfig entry in place, launch the interactive configuration menu to see it appear:

$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig

Navigate to “EmbeddedPathashala demo drivers” in the menu tree, press Y or M to select it, then save and exit. Confirm it landed in the generated config:

$ grep EP_DEMO_GPIO_BLINKER .config
CONFIG_EP_DEMO_GPIO_BLINKER=m

Real-World Use Case: Trimming a Product Config

A very common embedded task is taking a vendor’s sprawling default config — often built for a development board with every peripheral wired up — and trimming it down for a specific product SKU. Understanding Kconfig dependencies matters here: disabling GPIOLIB, for instance, will silently disable every driver that depends on it, including ones you might still need. Always check dependency chains with menuconfig‘s search feature (press / and type the symbol name) before mass-disabling subsystems.

Common Mistakes and Troubleshooting

  • Forgetting ARCH= and cross-compiling against the wrong menu — always set it explicitly for embedded targets, even if it matches your host by coincidence today.
  • Writing a Kconfig entry but forgetting the matching obj-$(CONFIG_...) line — the option appears in the menu and sets a variable, but nothing actually gets compiled.
  • Using tabs vs spaces inconsistently in Kconfig files — the Kconfig parser is sensitive to this; help text and property lines conventionally use a single tab of indentation.
  • Not checking depends on chains before disabling a subsystem — you can silently lose drivers you still need.

Best Practices

  • Always set ARCH= (and CROSS_COMPILE= where relevant) explicitly for embedded builds.
  • Use tristate rather than bool when there’s any chance your driver should be loadable as a module.
  • Write meaningful help text — it’s what future engineers (including future you) will read when deciding whether to enable an option.
  • Use menuconfig’s built-in symbol search before disabling shared subsystems in a product config.

Performance Considerations

Every built-in (y) option increases your kernel image size and boot-time initialization work, even for hardware that’s never present on a given board. For embedded targets with tight boot-time or flash-size budgets, prefer trimming unused options to n rather than leaving defaults from a generic development config.

Summary / Key Takeaways

  • Kconfig declares configuration options and their dependencies; Kbuild is the Make-based system that actually compiles based on those choices.
  • Always set ARCH= explicitly — it selects which architecture-specific Kconfig menu you see.
  • A config option needs both a Kconfig declaration and a matching obj-$(CONFIG_...) line in the Makefile to actually build anything.
  • tristate options can be built-in (y), a module (m), or disabled entirely.

Conclusion

Kconfig and Kbuild together are what turn “the entire Linux kernel source tree” into “exactly the kernel your product needs” — no more, no less. With source, tree layout, and now configuration covered, you have the full foundation this free linux kernel development course needs before moving on to actually building and flashing a kernel image in the lectures ahead.

Frequently Asked Questions

What’s the difference between Kconfig and Kbuild?

Kconfig declares configuration options and produces the .config file; Kbuild is the actual Make-based build system that reads .config and decides what to compile.

What happens if I forget to set ARCH=?

The build defaults to your host machine’s architecture, which is almost never correct for embedded cross-compilation — always set it explicitly.

What’s the difference between bool and tristate in Kconfig?

bool only allows y (built-in) or unset. tristate additionally allows m (built as a loadable module), giving more flexibility for optional drivers.

My Kconfig option shows up in menuconfig but nothing builds — why?

You likely declared the config symbol but forgot the matching obj-$(CONFIG_YOUR_OPTION) line in the relevant Makefile — both are required.

Is Kconfig only used by the Linux kernel?

No — the same Kconfig language and tooling is reused by other projects including U-Boot, Barebox, BusyBox, and crosstool-NG.

Continue the Free Linux Kernel Development Course

Explore more free lectures on embedded Linux, kernel internals, and device drivers.

PREV_LEC NEXT_LEC

 

Leave a Reply

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