The Linux kernel source code is extensive, and it can be confusing to understand the relationship between Makefile, Kconfig, and .config. Not knowing how the kernel compilation system works can lead to issues when trying to modify the kernel, integrate your own drivers, or configure the kernel. These problems are all related to Makefile, Kconfig, and .config. Below is a brief discussion on these three components. I hope it inspires you.
The Roles of the Three:
In simple terms, it’s like ordering food at a restaurant: Kconfig is the menu, Makefile is the recipe, and .config is your order.
Makefile: A text file that defines how to compile source files.
Kconfig: A text file that serves as the kernel’s configuration menu.
.config: The configuration file that the kernel compilation relies on.
The Syntax of the Three
Makefile
Reference: linux-3.4.2/drivers/Makefile
Purpose: To define which components are compiled as modules, and under what conditions. Subdirectory Makefile is included by the top-level Makefile.
(1) Direct Compilation
obj-y += xxx.o
This indicates that xxx.c or xxx.s is compiled to produce xxx.o and is directly included in the kernel.
(2) Conditional Compilation
obj -$(CONFIG_HELLO) += xxx.o
This decides whether the file is included in the kernel based on the CONFIG_XXX in the .config file.
(3) Module Compilation
obj-m +=xxx.o
This indicates that xxx is compiled as a module, meaning it will only be compiled when executing make modules.
2. Kconfig
Each config menu item has a type definition: bool (boolean), tristate (built-in, module, removed), string, hex, and integer.
Purpose: To determine which menu items are displayed during make menuconfig.
Reference: linux-3.4.2/drivers/leds/kconfig:
config LEDS_S3C24XX
tristate “LED Support for Samsung S3C24XX GPIO LEDs”
depends on LEDS_CLASS
depends on ARCH_S3C24XX
help
This option enables support for LEDs connected to GPIO lines
on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
LEDS_S3C24XX: The name of the configuration option, omitting the prefix “CONFIG_”
Tristate:
Indicates whether the item is included in the kernel or compiled as a module. It is displayed as < > . If compiled as a kernel module, a CONFIG_HELLO_MODULE=m configuration will be generated in .config, while selecting Y means it will be directly included in the kernel, resulting in CONFIG_HELLO_MODULE=y in .config. The string after tristate is the name displayed during make menuconfig.
bool:
This type can only be selected or not selected, displayed as [ ] during make menuconfig, indicating it cannot be configured as a module.
dependon:
This option depends on another option; the current configuration option’s prompt will only appear when the dependency is selected, allowing the current option to be set.
select:
Reverse dependency; when this option is selected, the item defined after select will also be selected.
help:
Help information.
Directory Hierarchy Iteration:
In Kconfig, there are statements like: source “drivers/usb/Kconfig” to include (or nest) new Kconfig files, allowing each directory to manage its own configuration without writing all configurations in a single file, making it easier to modify and manage.
3. .config
Reference: linux-3.4.2/.config
From the analysis of the previous two files, the meaning of .config is clear: it is the reference file for kernel compilation. By examining its contents, one can see which drivers have been compiled into the kernel.
There are three ways to configure the kernel (choose any one):
(1) make menuconfig
(2) make xxx_defconfig
(3) Directly modify .config
Note: Directly modifying .config may not be effective, as some configurations may have dependencies. During make, checks will be performed based on these dependencies. Therefore, direct modification is not recommended.
The above may seem a bit abstract; let’s illustrate with an example:
Write a simple entry function that outputs hello world as a driver and compile it into the kernel.
Steps:
(1) Create a hello folder under the drivers directory, and implement hello.c, Makefile, and Kconfig inside.
hello.c:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
static int first_drv_init(void)
{
printk(“——————hello world !——————–“);
return 0;
}
static void first_drv_exit(void)
{
printk(“——————exit hello world !——————–“);
}
module_init(first_drv_init);
module_exit(first_drv_exit);
MODULE_LICENSE(“GPL”);
Makefile:
obj-$(CONFIG_HELLO) += hello.o
Kconfig:
config HELLO
tristate “Hello World for fengyuwuzu”
help
Hello for fengyuwuzu
The config HELLO determines the name: CONFIG_HELLO.
Hello World for fengyuwuzu: This determines the name displayed during make menuconfig
(2) Modify the parent Makefile and Kconfig (in Linux-3.4.2/drivers).
Makefile:
obj-y += hello/
Kconfig:
source “drivers/hello/Kconfig”
(3) make menuconfig
(4) make uImage and then burn it onto the development board.
Check the kernel boot log, and the great hello world appears! This indicates that hello.c has been successfully compiled into the kernel.
Feel free to refer to this experiment, and I believe you will have a clearer understanding of the kernel’s organizational structure.
The end.
Works that please oneself can also please others. The Wei Dongshan brand news provides centralized information to help you get started with embedded Linux faster.