Kconfig 是最初为了 Linux 内核开发的基于选择的配置系统。作为一套先进的编译选项配置系统,不止 Linux 内核项目,U-Boot、BusyBox、Buildroot、KDE 等众多项目也在使用 Kconfig。
大多数用户通过图形菜单界面与 Kconfig 交互,通常通过运行 make menuconfig 来运行。在此界面中,用户选择所需要的选项,并保存配置文件,然后将其作为编译过程的输入。
菜单和配置选项由散布在源代码树中的 KConfig 文件定义。Kconfig 文件的格式在 Kconfig Language 中有详细描述。
组成
Kconfig 系统实际上由两个部分组成,KConfigCore 和 KConfigGui。
KConfigCore 提供对配置文件本身的访问。包含了以下功能:
- 代码生成:在 XML 文件中描述配置,并使用 kconfig_compiler 生成读取和写入配置条目的类。
- 级联配置文件(全局设置被本地设置覆盖)。
- 可选的 shell 扩展支持。
- 锁定配置选项的能力。
KConfigGui 提供了一种将 交互层 与配置挂钩的方法,这样它们就能从配置中自动初始化,并自动将更改写入到各自的配置文件中。
KConfigGui 提供了众多的交互形式,如下所示:
| make xxx | explain |
|---|---|
| config | Update current config utilizing a line-oriented program |
| nconfig | Update current config utilizing a ncurses menu-based program |
| menuconfig | Update current config utilizing a menu-based program |
| xconfig | Update current config utilizing a Qt-based frontend |
| gconfig | Update current config utilizing a GTK+ based frontend |
| oldconfig | Update current config utilizing a provided .config as base |
| localmodconfig | Update current config disabling modules not loaded |
| localyesconfig | Update current config converting local mods to core |
| defconfig | New config with default from Arch-supplied defconfig |
| savedefconfig | Save current config as ./defconfig (minimal config) |
| allnoconfig | New config where all options are answered with ‘no’ |
| allyesconfig | New config where all options are accepted with ‘yes’ |
| allmodconfig | New config selecting modules when possible |
| alldefconfig | New config with all symbols set to default |
| randconfig | New config with a random answer to all options |
| listnewconfig | List new options |
| olddefconfig | Same as oldconfig but sets new symbols to their default value without prompting |
| kvmconfig | Enable additional options for KVM guest kernel support |
| xenconfig | Enable additional options for xen dom0 and guest kernel support |
| tinyconfig | Configure the tiniest possible kernel |
具体支持使用 make help 查看:
1 | linux-4.19.296$ make help |
其中,make menuconfig 应该是使用最多的交互形式,可根据实际情况自行选择。
代码调用流程
Kconfig 相关的工具和源码主要位于内核源码中的 scripts/kconfig/ 下。
以 make menuconfig 为例,这句话会调用 scripts/kconfig/Makefile
1 | menuconfig: $(obj)/mconf |
翻译一下:
1 | menuconfig: scripts/kconfig/mconf |
.mconf.o.cmd
1 | cmd_scripts/kconfig/mconf.o := cc -Wp,-MD,scripts/kconfig/.mconf.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DCURSES_LOC="<ncurses.h>" -DNCURSES_WIDECHAR=1 -DLOCALE -c -o scripts/kconfig/mconf.o scripts/kconfig/mconf.c |
.mconf.cmd
1 | cmd_scripts/kconfig/mconf := cc -o scripts/kconfig/mconf scripts/kconfig/mconf.o scripts/kconfig/zconf.tab.o scripts/kconfig/lxdialog/checklist.o scripts/kconfig/lxdialog/util.o scripts/kconfig/lxdialog/inputbox.o scripts/kconfig/lxdialog/textbox.o scripts/kconfig/lxdialog/yesno.o scripts/kconfig/lxdialog/menubox.o -Wl,-Bsymbolic-functions -lncursesw -ltinfo |
实际运行时,可以看到以上的编译和启动过程:
1 | linux-4.19.296$ make menuconfig ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- |
至此,我们大致知道了,Kconfig 是一个源码位于 scripts/kconfig,现编译运行的,基于 lxdialog(Linux 维护的一个精简的dialog, 基于 ncurses 字符图形界面库) 的工具。(所以需要安装依赖 sudo apt-get install libncurses5-dev)
对于系统移植来说,源码分析到这个程度已经够了,我们的重点是使用,而对于项目中想要使用这套选择系统的小伙伴可以自行研究。
语法
有关配置文件语法的描述,见 Kconfig Language,或 linux 项目中的 Documentation/kbuild/kconfig-language.txt。
整理如下:
从根目录的
Kconfig文件开始解析#:单行注释符mainmenu "str":声明菜单标题,居中显示在界面的最上方comment "str":声明注释,显示在第一行source "dir":用于链接其它源文件menu "str":声明菜单入口,endmenu声明菜单终止,一般会在其后加上# "str"注释是哪个入口的结束。通过menu的多级嵌套,实现子菜单-子子菜单的功能。子选项只有在其父选项可见时可见 。
config声明选项,同一选项可以被多次定义,但是每次定义只能包含单个输入提示,类型需要保持一致。具体格式如下:1
2
3
4
5
6
7
8config <宏>
<type> "输入提示" [if <条件>]
depends on <宏> [宏运算]
default <值> [if <条件>]
[default <值> if <条件>]
[range <symbol> <symbol> [if <expr>]]
help
<str>type:类型必须声明。类型可选项:tristate、string、bool、hex、int。输入提示可以显示表示,所以以下两种写法是等价的:
1
bool "Networking support"
and
1
2bool
prompt "Networking support"在类型前加上 def_,快速声明类型和默认值,语法:
def_bool/def_tristate <value> [if <expr>]输入提示可以根据条件显示
依赖关系:可以通过
depends on、select、imply来表示。Adepends onB,那么只有在 B 选中才能选 A。select又叫反向依赖,同样的关系可以用 BselectA 表示。imply是弱反向依赖,用于指示关系,但是依赖项不影响选项的可选项。选项可以具有任意数量的默认值。如果多个默认值是可见的,默认使用第一个定义的值
tristate,可以设置为y、m或n。range仅当类型为 int 或 hex 时可用,边界都为闭区间(可相等)
menuconfig:和config类似, 唯一不同的是该选项除了能设置y/m/n外,还可以实现菜单效果(能回车进入该项内部)。常用格式有2种:1
2
3
4
5menuconfig M
if M
config C1
config C2
endifor
1
2
3
4
5menuconfig M
config C1
depends on M
config C2
depends on M
choice/endchoice:列表选项。具体格式如下:1
2
3
4
5
6
7
8
9
10
11
12
13choice [宏]
prompt "提示说明"
depends on <宏> [宏运算]
default <值> [if <条件>]
[default <值> if <条件>]
help
<str>
config ...
config ...
endchoiceif/endif块。具体格式如下:1
2
3if <expr>
...
endif
界面操作
选项开头显示说明
| 括号 | 说明 |
|---|---|
| [ ] | 可设置为 内置或不包含 |
| < > | 可设置为 内置、模块化、不包含 |
| { } | 可设置为 内置、模块化(由其它选项选择) |
| - - | 由其它选项选择 |
*、M、空格 被包含在括号内,分别代表 内置、模块化、不包含。
括号 ( ) 用于包含 数字/字符 输入,或者作为单选框,(X) 代表被选中。
菜单操作说明
| 操作 | 说明 |
|---|---|
| 上下方向键 | 上下选中选项 |
| Page Up/Down | 翻页 |
| Tab/左右方向键 | 在下方选项(<Select> <Exit> <Help> <Save> <Load>)中进行选择 |
| Enter | 执行下方选项,默认用于进入(<Select>)子选项(带有 --->/---- 的选项) |
| 字母 | 高亮的字母是快捷键(字母相同时会在同一字母选项中滚动),大小写通用 |
| y/Y | 包含此选项 |
| n/N | 不包含此选项 |
| m/M | 模块化 |
| Esc Esc | 返回 |
| h/? | 帮助信息 |
| / | 搜索 |
| 空格 | 在可选项中循环切换。在单选菜单中用于选择 |
帮助界面操作说明
| 操作 | 按键 |
|---|---|
| 上下左右移动 | 方向键:up/down/left/right 或者使用 VI 操作键:h/j/k/l |
| 上下翻页 | Page Up/Down 或者 b/Space 或者 u/d |
| 退出 | E/X/q/Enter/Esc Esc |