What is a Makefile?
A Makefile is a build script used by the make utility to automate the compilation and linking of software. The Linux kernel build system — known as Kbuild — is built on top of GNU Make and uses an intricate hierarchy of Makefiles to compile one of the largest software projects in existence from source. Understanding Kbuild is essential for every Linux device driver developer, since writing a driver Makefile is required to compile your module.
The Five Components of the Kernel Build System
- Makefile — the top-level Makefile at the root of the kernel source tree. It reads the
.configfile and orchestrates the overall build, producing the two primary outputs:vmlinux(the resident kernel image) and module (.ko) files. - .config — the kernel configuration file generated by
make menuconfig,make defconfig, or similar tools. It defines which features, drivers, and subsystems are compiled in, compiled as modules, or excluded entirely. - arch/$(ARCH)/Makefile — the architecture-specific Makefile. For ARM builds it lives at
arch/arm/Makefile; for x86 atarch/x86/Makefile. It provides architecture-specific compiler flags, linker scripts, and boot image recipes. - scripts/Makefile.* — a collection of common rules, pattern rules, and helper functions shared across all Kbuild Makefiles. These handle tasks like dependency tracking, module versioning, and header installation.
- Kbuild Makefiles — approximately 500 individual Makefiles distributed throughout the kernel source tree, one per subdirectory. Each tells Kbuild which object files to compile and how to link them into the kernel or into a module.
Writing a Driver Makefile
When you write a Linux kernel module (device driver), you need a Makefile to build it. A minimal out-of-tree module Makefile looks like this:
obj-m += my_driver.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
The obj-m variable tells Kbuild to build my_driver.c as a loadable module (.ko file). The -C flag changes directory to the kernel build tree, and M=$(PWD) tells Kbuild to look for the module sources in the current directory.
How the Top Makefile Uses .config
The top Makefile reads .config to determine the build scope. Each configuration symbol (like CONFIG_USB=y or CONFIG_USB=m) is translated into Makefile variables. y means compile into the kernel; m means compile as a module; absence means exclude entirely. The top Makefile then recursively descends into subdirectories listed in the relevant Kbuild Makefiles, building only the components selected by the configuration.
Conclusion
The Linux kernel Makefile system is sophisticated but logical once you understand its layered structure. For embedded developers, knowing how to write and debug Makefiles — and how to navigate the kernel build system for cross-compilation targeting ARM boards like Beaglebone or Raspberry Pi — is a practical day-to-day skill. Embisyslabs covers Kbuild in depth as part of our Linux Device Drivers training.
Interested in learning more about Linux Kernel and Driver development training?
Enquire Now Back to Blogs