To manage and reduce this complexity, software developers organize code in small files that link to specific modules. Developers can compile each of these files separately and then link them together to create a final software executable.
An example of this is C projects made up of source code files in .c extensions and software interfaces in .h extensions. Each source file gets compiled together with the header files to create. o objects linked together using libraries, thereby creating executable files.
To perform this process, software developers use tools, such as Make, to automate the build process and required file dependencies. Make uses Makefiles to manage the behavior of the compilation process.
The GNU Make tools provide a set of rules and conventions used to create Makefiles and reduce the complexity in improving efficiency.
In this tutorial, we will discuss the Linux Kernel Makefiles, specifically Kconfig and Kbuild.
Before we begin, it is good to note that this article does not pretend to teach everything about the Kernel Build system. However, we provide a high-level overview of building a vmlinux image and modules.
If you’d like information beyond the scope of this tutorial, we recommend the following resource for better information:
https://linkfy.to/goMakefilesDocs
Kernel Makefiles: An Overview
The Kernel Build System, also called the config system, is an essential tool—for those who need it—that has been around for a while. However, not everyone will use this system; even drivers and other low-level software developers rarely use it. Since you’re reading this, it means you want to know more about the Kernel Build System.
Thus, we’ll discuss how the Kernel gets compiled and discuss the Kbuild and Kconfig system so you can understand them better.
The Kernel Makefile has five core components:
- Makefile: This is the top make file located in the source root.
- arch/$(ARCH) Makefile: This is the arch Makefile; it acts as a supplement to the top Makefile.
- .config: This is the Kernel configuration file.
- Scripts/Makefile.*: This defines set rules for all kbuild Makefiles.
- Kbuild Makefiles: There are about 500 kbuild Makefiles, and they are not very easy to read. Consider a file such as:
https://elixir.bootlin.com/linux/latest/source/scripts/Kbuild.include
Kconfig
The Kconfig file contains modules that assist when using the make *config. It helps the Kernel make selective configurations, creating modularity and customizability for the Kernel build process.
There are various config targets specified by the Kconfig system. You can use the make help to view the available targets. These targets are processed by various programs provided by the Kernel during the build process.
Some of Kconfig targets include:
- Config: This is used to update the kernel config file using the line program.
- Menuconfig: This is a Kconfig feature or mechanism that offers menu-based access to Kernel options. To launch menuconfig and other Kconfig features, you should be inside the platform project directory. You can use the following to launch the Kconfig menuconfig feature. However, you can also launch menuconfig with other GUI Linux Kernel config features such as xconfig and gconfig.
- gconfig and xconfig: Gconfig activates GUI-based Linux Kernel features. Gconfig employs the GTK or (X based) based UI. On the other hand, Xconfig utilizes Qt-based UI. Use the following commands to launch gconfig and xconfig, respectively:
make linux-windriver.xconfig
NOTE: To use gconfig and xconfig, you should have the QT development tools installed on the host system.
- Nconfig: Nconfig feature runs the current configuration (Buildtools) and applies for the Ncurses menu-driven program. This allows you to select the packages to build, such as CPU, drivers, and filesystem when building the Kernel. Use the command: make nconfig.
- Oldconfig: The oldconfig feature allows you to apply newer .config files to older kernel config files. For instance, an old .config file and a newer .config file (newer kernel version) will have differences, meaning you need to update the current config before the kernel build. You can use make oldconfig to update the old config interactively by applying options missing in the old config file.
- Defconfig: This feature allows the kernel build system to add a new config supplied by defconfig to the .config file. More precisely, the Kbuild system checks all the Kconfig files. If defconfig specifies an option in the file, the Kbuild system uses the specified value to add the option to the .config. If the defconfig does not mention the option, Kbuild uses default values in the .config.
Consider the following:
Defconfig code snapshot from the following resource:
https://elixir.bootlin.com/linux/v5.9/source/scripts/kconfig/Makefile#L98
2. ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)),)
3. @$(kecho) "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"
4. $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
5. else
6. @$(kecho) "*** Default configuration is based on target '$(KBUILD_DEFCONFIG)'"
7. $(Q)$(MAKE) -f $(srctree)/Makefile $(KBUILD_DEFCONFIG)
8. endif
9.
10. %_defconfig: $(obj)/conf
11. $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
12.
13. configfiles=$(wildcard $(srctree)/kernel/configs/$@ $(srctree)/arch/$(SRCARCH)/configs/$@)
14.
15. %.config: $(obj)/conf
16. $(if $(call configfiles),, $(error No configuration exists for this target on this architecture))
17. $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(configfiles)
18. $(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
Oldconfig code snapshot from the following resource:
https://elixir.bootlin.com/linux/v5.9/source/scripts/kconfig/conf.c#L694
2. default:
3. break;
4. }
5.
6. if (input_mode == savedefconfig) {
7. if (conf_write_defconfig(defconfig_file)) {
8. fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n",
9. defconfig_file);
10. return 1;
11. }
12. } else if (input_mode != listnewconfig && input_mode != helpnewconfig) {
13. if (!no_conf_write && conf_write(NULL)) {
14. fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
15. exit(1);
16. }
17.
18. /*
19. * Create auto.conf if it does not exist.
20. * This prevents GNU Make 4.1 or older from emitting
21. * "include/config/auto.conf: No such file or directory"
22. * in the top-level Makefile
23. *
24. * syncconfig always creates or updates auto.conf because it is
25. * used during the build.
26. */
27. if (conf_write_autoconf(sync_kconfig) && sync_kconfig) {
28. fprintf(stderr,
29. "\n*** Error during sync of the configuration.\n\n");
30. return 1;
31. }
32. }
33. return 0;
34. }
- Savedefconfig: This rule saves the current .config in the form of ./defconfig, which is regarded as a minimal config file. Use the command: make savedefconfig
- Listnewconfig: This is used to list new options.
- Kvmconfig: This enables options for KVM support. Use the command: make kvm_guest.config
- Allyesconfig: This builds a new kernel config file with all options set to yes. It’s the opposite of allnoconfig.
- Allmodconfig: This builds a new kernel config with which modules are enabled by default.
- Randconfig: This builds a new kernel config file with random answers to all options.
- Tinyconfig: This makes the tiniest Kernel possible.
There are a lot of targets in the Kconfig system. Some common ones include config and menuconfig.
As mentioned, the targets are processed by various programs in the host systems, either providing a GUI or command line. You can find Kconfig tools in /scripts/Kconfig in the kernel source.
https://elixir.bootlin.com/linux/latest/source/scripts/kconfig
https://elixir.bootlin.com/linux/latest/source/scripts/kconfig/Makefile
The first process is usually to read the Kconfig file in the root directory, which is used to build an initial config database. As the process continues, the database is updated when reading files in the following order:
/lib/modules/$(shell,uname-r)/.config
/etc/kernel-config
/boot/config-$(shell,uname-r)
ARCH_DEFCONFIG
arch/$(ARCH)/defconfig
.config file is then dropped to syncconfig, which accepts the .config file as input. It processes the file and outputs files, which are then classified into various categories such as:
- autoconf.h: This is used for C language source files.
- auto.conf and tristate.conf: These are used for Makefile text processing.
- /includes/config: These are empty header files used in dependency tracking.
Kbuild Files
Almost all Kernel files are Kbuild Makefiles that use the Kbuild infrastructure, which is a recursive make feature. Recursive Make is a way of using the Make tool as a command in a Makefile. Recursion is very useful when compiling a large project.
Kbuild works by referring to all the files we mentioned in the above section.
The Kbuild system builds its components using the top Makefile that includes the arch Makefiles with the name arch/$(ARCH)/Makefile in the config files. It recursively descends into subdirectories invoking Make on the components using the routines in scripts/Makefile.*. Kbuild then builds upon the adjacent object and links them into objects, creating vmlinux.
To learn more about the syntax used in Kbuild Makefiles, refer to the documentation.
Consider the following script.
https://github.com/torvalds/linux/blob/master/scripts/link-vmlinux.sh
The o object files used to create the vmlinux are compiled first in their respective built-in .a files as the var KBUILD_VMLINUX_INIT,MAIN,LIBS. These are composed in vmlinux.
https://github.com/torvalds/linux/blob/master/scripts/Makefile.build
Conclusion
In this guide, we took a look at Kbuild and Kconfig systems in the Kernel build system and how it works. As we mentioned at the beginning of the tutorial, the topics discussed are broad and cannot be covered in a single tutorial.