介绍
------------
配置数据库即组织成树状结构的配置选项的集合:
 +- Code maturity level options
 |  +- Prompt for development and/or incomplete code/drivers
 +- General setup
 |  +- Networking support
 |  +- System V IPC
 |  +- BSD Process Accounting
 |  +- Sysctl support
 +- Loadable module support
 |  +- Enable loadable module support
 |     +- Set version information on all module symbols
 |     +- Kernel module loader
 +- ...
每个配置项都有它自己的依赖。
这些依赖用于决定一个配置项是否可视。
每个子配置项只有在它的父配置项可视的时候才可视。

菜单项
------------
大多数菜单项定义一个配置项;所有其他选项都用来帮助组织它们。
一个简单的配置项定义如下:

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"开始一个新的配置项。
下面的几行为这个配置项定义属性。
属性可以是配置项的类型,输入提示,依赖,帮助文档和缺省值。
一个配置项可以用同一个名字定义多次,但是每个定义必须有一个单独的输入提示并且类型不能冲突。

菜单属性
---------------
菜单项可以有许多属性。
不是所有的可以应用于任何地方(参见语法)。
- 类型定义:"bool"/"tristate"/"string"/"hex"/"int"
  每个配置项都必须有个类型。
  只有两种基本类型:tristate和string;
  其他类型都基于这两种。
  类型定义可选择接受一个输入提示,因此下面2个例子是相同的:
 bool "Networking support" and
 bool prompt "Networking support"
- 输入提示:"prompt" <prompt> ["if" <expr>]
  每个菜单项可以有最多一个提示,用于显示给用户。
  可选的,只有这个提示的依赖才能加上"if"。
- 缺省值:"default" <expr> ["if" <expr>]
  配置项可以有许多缺省值。
  如果有多个缺省值可视,只有第一个定义的值是活跃的。
  缺省值不限于菜单项被定义的地方。这意味着缺省值可以在其他某个地方定义或者
  被早些的定义所覆盖。
  缺省值只能分配给配置符号,如果用户(通过上面的输入提示)没有设置其他值。
  如果输入提示可视,用户看到的是缺省值并且可以覆盖它。
  可选的,只有这个缺省值的依赖才能加上"if"。
- 类型定义+缺省值
  "def_bool"/"def_tristate" <expr> ["if" <expr>]
  类型定义加上值的速记符号。
  可选的,只有这个缺省值的依赖才能加上"if"。
- 依赖:"depends on" <expr>
  为菜单项定义依赖。如果定义多个依赖,用'&&'连接。
  依赖应用于菜单项内所有其他选项(同样接受"if"表达式),因此下面2个例子是等价的:
  bool "foo" if BAR
 default y if BAR
 和
 depends on BAR
 bool "foo"
 default y
- 反向依赖:"select" <symbol> ["if" <expr>]
 正常的依赖减小符号的上限(参见下面),反向依赖用于强制(提升)另一个符号的下限。
 当前菜单符号值用作<symbol>设定值的最小值。如果多次选择了<symbol>,取最大值为下限。
 反向依赖只能用于boolean或tristate符号。
 注意:
     select要谨慎使用。select会强制某个符号使用某值而不访问依赖。滥用select会导致
     选择符号FOO,即使FOO所依赖的BAR并没有被设置。
     通常只能为非可视符号(在任何地方都没有提示)和那些没有依赖的符号。
     这会限制符号的用途,但是另一方面避免了非法配置。
     kconfig应该在将来某一天对这种情况提出警告。
- 数字范围:"range" <symbol> <symbol> ["if" <expr>]
  允许限制int和hex符号的可能输入的范围。
  用户只能输入大于等于第一个符号并且小于等于第二个符号的值。
- 帮助文档:"help" or "---help---"
  定义一个帮助文档。帮助文档的结尾取决于缩进层次,这意味着
  比帮助文档第一行缩进还小的一行就是帮助文档的结尾。
  "---help---"和"help"在行为上没有区别,"---help---"用于在开发人员的辅助文件内
  显示的分开配置逻辑和帮助文档。
- 杂项:"option" <symbol>[=<value>]
  各种少见的选项可以通过这种选项语法来定义,以修改菜单项和它的配置符号的行为。
  当前可能存在下面这些选项:
  - "defconfig_list"
    声明一个默认配置项列表,在查找缺省配置时使用(当主配置文件.config不存在时使用。)
  - "modules"
    声明作为MODULES符号使用的符号,为所有配置符号打开第三个模块状态。
  - "env"=<value>
    将环境变量导入Kconfig。它作为缺省值出现,除非值来自于环境,这同时意味着
    这种行为和通常的缺省值混合使用是未定义的。符号不会导回环境(如果希望这样做,
    可以通过另一个符号来实现)。

菜单依赖
-----------------
依赖定义了一个菜单项是否可视,同样也可以减小tristate符号的输入范围。
用于表达式的tristate逻辑使用多于正常Boolean逻辑的状态来表示模块状态。
依赖表达式有下面的语法:
<expr> ::= <symbol>                             (1)
           <symbol> '=' <symbol>                (2)
           <symbol> '!=' <symbol>               (3)
           '(' <expr> ')'                       (4)
           '!' <expr>                           (5)
           <expr> '&&' <expr>                   (6)
           <expr> '||' <expr>                   (7)
表达式以降序排列。
(1)将符号转换成表达式。
    Boolean和tristate符号只是简单的转换成相应的表达式的值。
    所有其他符号类型被转换成'n'。
(2)如果符号值相等,返回'y',否则返回'n'。
(3)如果符号值相等,返回'n',否则返回'y'。
(4)返回表达式的值。用于覆盖优先级。
(5)返回(2-/expr/)。
(6)返回min(/expr/, /expr/)。
(7)返回max(/expr/, /expr/)。
表达式可以是'n', 'm'或者'y'(或者是0, 1, 2用于相应的计算)。
当表达式等于'm'或'y'时菜单项可视。
符号有两种类型:常量和非常量符号。
非常量符号比较常见,定义在'config'语句中。
非常量符号完全由字母、数字和下划线组成。
常量符号只是表达式的一部分。
常量符号总是在单引号或双引号之间。
在引号内,可以是任何其他的字符,引号可以用'\'来转义。

菜单结构
--------------
菜单项在配置树中的位置由2种方式决定。
首先,可以显示的指定:
menu "Network device support" depends on NET
config NETDEVICES ...
endmenu
所有在"menu" ... "endmenu"块内的配置项都成为"Network device support"的子菜单。
所有子配置项从菜单项那里继承依赖。例如:
这意味着依赖"NET"被加到了配置项NETDEVICES的依赖列表中。
另一种产生菜单结构的方式是分析依赖。
如果一个菜单项某种程度上依赖于前一个配置项,它可能是前一个配置项的子菜单。
首先,前一个(父)符号必须是依赖列表的一部分并且必须满足下面两个条件之一必须:
- 如果父配置项设置成'n',子配置项变成可视
- 如果父配置项可视,子配置项必须且只能可视
config MODULES bool "Enable loadable module support"
config MODVERSIONS bool "Set version information on all module symbols"
 depends on MODULES
comment "module support disabled" depends on !MODULES
MODVERSIONS直接依赖于MODULES,这意味着只有MODULES不同于'n'时,它才可视。
另一方面,批注在MODULES可视时总是不可见(原文档为可见,疑有误)。
(MODULES(空)依赖也是批注依赖的一部分)。

Kconfig语法
--------------
配置文件描述了一系列的菜单项,每行以一个关键字开始(帮助文档除外)。
下面的关键字结束一个菜单项:
- config
- menuconfig
- choice/endchoice
- comment
- menu/endmenu
- if/endif
- source
前面5个也是菜单项定义的开始。
config:
 "config" <symbol>
 <config options>
定义一个配置符号<symbol>并且接受上面的任何属性作为选项。
menuconfig: "menuconfig" <symbol>
 <config options>
与上面的简单配置项类似,但是它同时给了前面结尾一个提示,即所有的子项应该作为一个
单独的选项列表来显示。
choices:
 "choice"
 <choice options>
 <choice block>
 "endchoice"
定义一个可选组并且接受上面的任何属性作为选项。
可选项只能是bool或tristate类型,单选可选项只允许选择一个配置项,三态可选项允许
任意数量的配置项设置成'm'。这种情况适用于:一个硬件有多个驱动程序并且只能有一个
编译进内核,但是所有驱动都可以编译成模块。可选项接受另一个选项"optional",允许
把可选项设置成'n'并且可以不选择任何项。
comment:
 "comment" <prompt>
 <comment options>
定义一个在配置内核过程中显示的内容,同时也被输出到输出文件。
唯一可能的选项就是依赖。
menu:
 "menu" <prompt>
 <menu options>
 <menu block>
 "endmenu"
定义一个菜单块,更多的信息参见上面的"Menu structure"。
唯一可能的选项就是依赖。
if:
 "if" <expr>
 <if block>
 "endif"
定义一个if块。
依赖表达式<expr>附加到所有包括的菜单项。
source:
 "source" <prompt>
读指定的配置文件。该文件总被解析。
mainmenu:
 "mainmenu" <prompt>
如果配置程序选择使用标题栏,设置配置内核程序的标题栏。

Kconfig提示
-------------
这是Kconfig提示的集合,它们中大多数在第一眼看来不是那么明显,
大多数已经成了几个Kconfig文件中的惯用法。

增加常用特性并且让它可配置
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
只为某些架构而不是所有架构实现相关的特性/功能是一种常见的做法。
一种推荐的方式就是使用一个名为HAVE_*的配置变量,该变量定义在一个普通的Kconfig
文件中并且由相关架构来选择。
一个例子就是通用IOMAP功能。
在lib/Kconfig中我们能看到:
# Generic IOMAP is used to ...
config HAVE_GENERIC_IOMAP
config GENERIC_IOMAP depends on HAVE_GENERIC_IOMAP && FOO
在lib/Makefile中我们能够看到:
obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
对于每个使用通用IOMAP功能的架构来说,我们看到:
config X86 select ...
 select HAVE_GENERIC_IOMAP
 select ...
注意:我们用了已经存在配置项,避免了创建一个新的配置变量来选择HAVE_GENERIC_IOMAP。
注意:使用内部配置变量HAVE_GENERIC_IOMAP,被推荐用来克服select的限制,即
强制一个配置项为'y',不管依赖是什么。
依赖被移到了符号GENERIC_IOMAP上,避免了select强制一个符号等于'y'的情况。

只编译成模块
~~~~~~~~~~~~~~~~~~~~
如果想限制一个组件只能编译成模块,可以让它的配置符号满足"depends on m"。例如:
config FOO depends on BAR && m
limits FOO to module (=m) or disabled (=n).