Kconfig
简介
Kconfig 严格来讲是一种编程语言,它拥有自己的语法及结构。正是这些语法和结构组成了menuconfig在用户眼前不同的表现形式。
- Kconfig 文件用于定义各种配置选项,例如是否启用某个设备驱动、特定的文件系统支持、网络协议等。
- 每个选项都有一个唯一的标识符和一个描述,描述清楚了该选项的作用和影响。
- Kconfig 允许定义选项之间的依赖关系和冲突关系。例如,某个功能可能依赖于另一个功能或硬件支持,Kconfig 可以确保这些依赖关系在配置时得到正确处理。
- 使用条件语句和选项依赖,Kconfig 可以根据不同的硬件平台或用户需求,动态地决定编译哪些部分的内核。
- Kconfig 文件通常分布在 Linux 内核源代码树的不同目录中,每个目录下的 Kconfig 文件负责配置该目录下的特定功能或模块。
- 每个 Kconfig 文件由一系列配置语句组成,包括
config
、menuconfig
、choice
、bool
、tristate
等命令,用于定义选项、菜单、选择项和选项的数据类型。
Kconfig 菜单结构
配置文件内是一组按树结构组织的配置选项集合。
+- 菜单块
| +- 菜单条目1 (选项(config)、菜单(menu)、菜单结束(endmenu)、菜单选择(choice))
| +- 菜单条目2 (选项(config)、菜单(menu)、菜单结束(endmenu)、菜单选择(choice))
| +- ...
具体案例如下:
menu "Network device support"
depends on NET
config NETDEVICES
...
endmenu
菜单条目
Kconfig 文件由多个菜单条目组成,这些条目可以包含配置选项(config)、菜单(menu)、注释(comment)、菜单选择(choice)等
单个配置选项定义示例如下:
config MODVERSIONS
bool "Set version information on all module symbols"
depends on MODULES
help
Usually, modules have to be recompiled whenever you switch to a new kernel.
每一行以关键词开始,并可以跟随多个参数。“config”开始一个新的配置条目。接下来的行定义了该配置选项的属性。属性可以包括配置选项的类型、输入提示、依赖关系、帮助文本和默认值。
可以在多个地方定义同一个配置选项,但每个定义只能有一个输入提示,并且所有定义中的选项类型必须一致。
配置选项可以多次定义同一名称:
1、你可以在不同的 Kconfig 文件或同一个文件的不同位置,重复定义一个配置选项,只要它们的名称相同。
2、这种重复定义通常是为了在不同的上下文中提供不同的选项描述或依赖关系。
但每个定义只能有一个输入提示:
1、虽然你可以多次定义同一个配置选项,但在每个定义中,这个选项只能有一个输入提示。
2、输入提示是配置界面上显示给用户的描述文本,用于说明该选项的功能。
且类型不能冲突:
1、每个配置选项的类型(例如 bool
、int
、string
等)在所有定义中必须一致,不能有冲突。
2、这意味着你不能在一个地方定义 config MODVERSIONS
为 bool
类型,然后在另一个地方定义它为 int
类型。
Kconfig 语法
配置文件描述了一系列菜单条目,每行以一个关键字开头(帮助文本除外)。以下关键字会结束一个菜单条目:
config
menuconfig
choice
/endchoice
comment
menu
/endmenu
if
/endif
source
前五个关键字也用于递归定义菜单条目。
config
config <symbol>
<config options>
定义一个配置符号 <symbol>
,并接受任何条目属性作为选项。
menuconfig
menuconfig <symbol>
<config options>
类似于上述的简单配置条目,但它还向前端提供一个提示,即所有子选项应显示为单独的选项列表。为了确保所有子选项都显示在 menuconfig
条目下而不是外部,需要确保 <config options>
列表中的每个条目都依赖于 menuconfig
符号。这可以通过以下两种构造之一实现:
-
menuconfig M if M config C1 config C2 endif
-
menuconfig M config C1 depends on M config C2 depends on M
在以下示例 (3) 和 (4) 中,虽然 C1 和 C2 仍然依赖于 M,但它们将不再出现在 menuconfig M
之下,因为 C0 不依赖于 M:
-
menuconfig M config C0 if M config C1 config C2 endif
-
menuconfig M config C0 config C1 depends on M config C2 depends on M
choices
choice
<choice options>
<choice block>
endchoice
定义一个选择组,并接受上述任何属性作为选项。一个选择组只允许选择一个配置条目。
comment
comment <prompt>
<comment options> # 只能是依赖项
定义一个注释,在配置过程中显示给用户,并回显到输出文件中。唯一可以添加的属性是依赖项。
menu
menu <prompt>
<menu options>
<menu block>
endmenu
定义一个菜单块,参见上文的“菜单结构”部分了解更多信息。唯一可能的选项是依赖项和“可视选项”属性。
菜单依赖
先看下文:
menu "Network device support"
depends on NET
config NETDEVICES
...
endmenu
所有在menu...endmenu
块中的条目成为 Network device support 的子菜单。所有子条目继承菜单条目的依赖关系,例如,这意味着 NET 依赖关系被添加到配置选项 NETDEVICES 的依赖列表中(NETDEVICES 也依赖 NET)。
if
if <expr>
<if block> # 菜单条目
endif
定义一个 if
块。依赖表达式 <expr>
将附加到所有包含的菜单条目。
source
source <path>
读取指定的配置文件(Kconfig 文件)。该文件总是被解析。
mainmenu
mainmenu <prompt>
如果配置程序选择使用它,则设置配置程序的标题栏。它应放置在配置的顶部,在任何其他语句之前。
# 单行注释
在源文件行中的任意位置,未引用的 #
字符表示源文件注释的开始。该行的其余部分为注释。
条目属性
配置类型
类型定义:bool
/ tristate
/ string
/ hex
/ int
基本类型只有两种:tristate(三态)
和 string
,其他类型基于这两种类型。
输入提示
输入提示定义语法:prompt <expr> [if <expr> ]
,每个菜单条目最多可以有一个提示,用于显示给用户。可选地,可以通过“if”添加仅适用于该提示的依赖关系。
也可以在类型定义后选择接受一个输入提示,以下两个对输入提示的定义是等价的:
方式一:
bool "Networking support"
方式二:
bool
prompt "Networking support"
默认取值
默认取值定义语法:default <expr> [if <expr>]
一个配置选项可以有任意数量的默认值。如果多个默认值可见,则只有第一个定义的默认值生效。默认值不限于其定义的菜单条目。这意味着默认值可以在其他地方定义或被更早的定义覆盖。只有当用户没有通过上述输入提示设置其他值时,默认值才会分配给配置符号。如果输入提示可见,默认值会呈现给用户,用户可以覆盖它。可选地,可以通过“if”添加仅适用于该默认值的依赖关系。
依赖关系
依赖关系定义语法:depends on <expr>
如果定义了多个依赖关系, 需要使用&&
或||
来连接。
因为依赖关系也接受if
表达式,所以以下两个例子是等价的:
bool "foo" if BAR
default y if BAR
depends on BAR
bool "foo"
default y
反向依赖
反向依赖定义语法:select <symbol> [if <expr>]
反向依赖关系的意思,即当前配置选项被选中,则 <symbol>
就会被选中。
数值范围
数值范围定义语法:range <symbol1> <symbol2> [if <expr>]
这将限制 int 和 hex 符号的可能输入值范围。用户只能输入[symbol1, symbol2]范围内的值(大于等于第一个符号且小于等于第二个符号)。
帮助文本
帮助文本定义语法:help <message>
可视选项
限制菜单显示语法:visible if <expr>
此属性仅适用于菜单块,如果条件为假,则不向用户显示菜单块(其中包含的符号仍然可以被其他符号选择)。