文章目录
前言
其实不管在kernel还是其他项目,Kconfig文件给我们最直观的体验就是用于make menuconfig
时的可视化配置。接下来主要可以分为两部分:了解Kconfig语法、添加自己的选项。如果想快速添加自己的菜单,那么可以直接跳过第1部分直接按照第2部的步骤来操作即可。
1、Kconfig简介
1.1 Kconfig与Makefile、.config的联系
在内核文档Documentation/kbuild/makefiles.txt
中有介绍:
Makefile包含5部分:
Makefile:顶层Makefile
.config:内核配置文件
arch/$(ARCH)/Makefile:CPU架构目录的Makefile
scripts/Makefile.*:普通的kbuild、Makefiles规则
kbuild Makefiles:等等文件
顶层Makefile会读取从内核配置的程序得到的.config文件。
现以i2c的配置为例看下三者的语法:
① drivers/i2c/Kconfig:
config I2C
tristate "I2C support"
select RT_MUTEXES
---help---
I2C (pronounce: I-squared-C) is a slow serial bus protocol used in
...
② .config:(相比于Kconfig文件中的配置,可以看到I2C前面多了“CONFIG_”前缀)
CONFIG_I2C=y
③ drivers/i2c/Makefile:(根据“CONFIG_I2C”的值是“y”、“m”或“没被设置”来决定将源码的编译)
obj-$(CONFIG_I2C) += i2c-core.o
相信从上面三者的语法可以很容易猜想到它们之间的联系,但具体是如何建立起联系的这里就不做研究了,简单了解即可。
1.2 make menuconfig 流程
既然使用了make命令,那么很理所当然地可以从Makefile文件查找目标,发现有如下定义:
%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
其中,以上使用的变量定义及所在文件如下:
# $(Q):顶层Makefile
ifeq ("$(origin V)", "command line")
KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
KBUILD_VERBOSE = 0
endif
ifeq ($(KBUILD_VERBOSE),1)
quiet =
Q =
else
quiet=quiet_
Q = @
endif
# $(MAKE)
MAKE=make
# $(build):scripts/Kbuild.include
build := -f $(srctree)/scripts/Makefile.build obj
如果make时没有指定参数“V”,展开后就是:
%config: scripts_basic outputmakefile FORCE
@ make -f ./scripts/Makefile.build obj=scripts/kconfig menuconfig
而在scripts/Makefile.build文件中又继续包含其他目录的文件:
src := $(obj)
...
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)
最后,在scripts/kconfig/Makefile就可以看到:
menuconfig: $(obj)/mconf
$< $(silent) $(Kconfig)
将变量代替进去简化一下就是:
menuconfig: scripts/kconfig/mconf
scripts/kconfig/mconf Kconfig
可以看到,最终就是scripts/kconfig/mconf这个可执行文件去解析Kconfig文件,它的源码(mconf.c等)就在同一个目录下。
1.3 内核中的Kconfig关键字
事实上,Kconfig是不需要我们自己从0开始写起,只需要大概了解语法,因为在使用时最多也就是需要添加某个菜单而已。Kconfig的语法可以从内核文档Documentation/kbuild/kconfig-language.txt
中查看,这里就看看经常会碰到以下关键字:
1.3.1 菜单相关
- mainmenu:顶部主菜单说明;
- menu/endmenu:两者搭配使用,选项后面显示 “—>”,里面会再包含一系列的具体选项;
- menuconfig:里面包含一系列的菜单,选项前面显示 “[ ]”,而且后面还显示 “ —>”。
1.3.2 选项相关
- config:需要配置的选项,不需要加“CONFIG_”前缀;
- tristate:三态:编进内核、编成模块、不编译;选项前面显示 “< >”;
- bool:布尔型,只有选择或不选择,选项前面显示 “[ ]”;
- int/hex:整型数值,选项前面显示 “( )”;
- range:用于限定前面int/hex整型数值的取值范围,不在范围内无法设置成功,语法为“rang 最小值 最大值”;
- string:设置字符串,选项前面显示 “( )”;
- depends on:依赖的选项,只有依赖的选项被配置了,才能配置该选项,可以通过逻辑运算符“&&”、“||”或“!”取反配置多个选项;
- default:默认取值;
- select:当前选项被选中后,select对应的选项也同时被选中;
- help:帮助信息,按下“?”键或选择“< Help >”菜单时的描述。
1.3.3 其他
- source:执行其他目录下的Kconfig文件,如:source “arch/$SRCARCH/Kconfig”;
- comment:注释,解析;选项前后显示“***”;
2、在make menuconfig中添加自己的选项
以最简单的驱动为例,把它归类到字符设备(根据自己需求),所以放到内核的drivers/char
目录下,修改和添加的内容如下(如果没有特殊说明,都是在前面所说的drivers/char
目录下操作):
2.1 先准备好自己的源码test.c
#include <linux/ide.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/device.h>
static int __init test_init(void)
{
printk("test_init!\n");
return 0;
}
static void __exit test_exit(void)
{
printk("test_exit!\n");
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
2.2 修改Kconfig
source "drivers/char/imx_amp/Kconfig"
# add
config TEST_DRV
tristate "My test driver"
help
This is my test driver!
2.3 修改Makefile
obj-$(CONFIG_XILLYBUS) += xillybus/
# add
obj-$(CONFIG_TEST_DRV) += test.o
2.4 查看效果
保存之后查看.config文件即可看到“CONFIG_TEST_DRV”选项是否被设置了。
以上为本人见解,如有错误,希望大家不吝赐教,感谢!