配置系统

Kconfig 介绍

组织结构

本项目的配置系统采用 Kconfig 组织,通过 Kconfig 的层级引用,将各个组件的配置结构化到 amebaxxx_gcc_project/Kconfig 中,最终生成供 CMake 使用的文件。

../../_images/kconfig_tree.svg

Kconfig 文件之间的相互引用可以采用下列语法:

  1. source :

    source 语句可以引用相对于顶层 Kconfig 的路径。例如位于 ${top_kconfig_path} 的顶层 Kconfig 使用如下语句:

    source "subdir/Kconfig"
    

    这将会把 {top_kconfig_path}/subdir/Kconfig 文件纳入到顶层 Kconfig 的引用。若 {top_kconfig_path}/subdir/Kconfig 文件不存在, 会导致 Kconfig 报错。

    备注

    不能通过 if 语句去避免引用不存在的文件,在下面的示例中,即使 DEP 没有被选中,Kconfig 仍然会尝试读取 Kconfig.other 的内容, Kconfig.other 不存在会报错。

    if DEP
       source "Kconfig.other"
    endif
    
  2. osource :

    osource 引用的文件路径即使不存在,也不会导致报错。

  3. rsource :

    通过 rsource 语句引用的路径,是相对于使用该 rsource 语句的 Kconfig 文件的路径,而不是相对顶层 Kconfig 的路径。

  4. orsource :

    该语句基于 rsource ,同时允许后面引用的文件路径不存在。

下面介绍一些 Kconfig 常见的用法和注意事项,关于 Kconfig 更详细的信息可参见: https://docs.kernel.org/kbuild/kconfig-language.html

定义 Kconfig 符号

定义一个 Kconfig 符号需要遵循下面格式:

config FOO
   bool "choose FOO"
   default n

上述 Kconfig 结构定义了一个 bool 类型的 config 符号,该符号被加载到可视化界面中显示为:

[ ]  choose FOO
  • "choose FOO" 为提示词,其将显示在可视化配置界面中,若删除 "choose FOO" ,那么可视化界面中将不会显示该配置项。除 bool 类型外,还可以定义 string, hex, int 等其他类型的配置项。

  • default n 表示 no, 代表该项默认不会被选中, default n 可缺省。注意,通过 default 定义的默认值,只有在用户没有设置过该 config 项时才会生效。

  • 如果同一个 config 中定义了多重 default 值,那么将以首次出现的有效 default 值为准。

  • 进一步地,还可以通过条件表达式丰富 Kconfig 的功能,例如下面的写法表示。当 BAR 被选中时,菜单中才会显示 FOO 项,且当 BARTIZ 同时被选中时, FOO 的默认值为 y

    config FOO
       bool "choose FOO" if BAR
       default y if BAR && TIZ
    

Kconfig 的依赖

  1. 通过 depends on 添加依赖

    通过 depends on,可以为此 config 项下的所有条目都添加依赖,即下面两种写法是等价的

    config FOO
       depends on BAR
       bool "choose FOO"
       default y
    
    ## equal to
    
    config FOO
       bool "choose FOO" if BAR
       default y if BAR
    
  2. 通过 select 添加反向依赖

    select 可以在一个 config 被选中后,强制指定另一个 config 也被选中,无论这个 config 有没有其他依赖关系。例如下面这个例子,当 BUZZ 被选中,无论 BAR 为何值, FOO 也一定会被选中,也无法通过可视化界面取消。

    config BUZZ
       bool "choose BUZZ"
       select FOO
    
    config FOO
       depends on BAR
       bool "choose FOO"
    

    备注

    • select 只能选中 bool 型的config。

    • select 常用于不可见的 config ,或没有依赖的 config。

不可见的 config 项

当 config 下未定义提示词时,此 config 项是不可见的,意味其不可被用户手动选中或取消,其值一般通过依赖项选中,或通过 default 值定义。例如:

config BAR
   bool "BAR"
   select FOO

config FOO
   bool
   default n

##equal to

config FOO
   bool
   default y if BAR

##also equal to

config FOO
   depends on BAR
   bool
   default y

如果是非 bool 类型:

config NUM
   int
   default 255 if BAR
   default 65535 if !BAR

config 项的多重定义

在 Kconfig 语法中,可以允许同名 config 在多处定义,这些定义最终会解析合并成一个 config 值并被输出到 .config 文件中。 通过两个示例说明这种用法:

示例一:

config FOO
   bool "FOO"
   select BAR
...

config FOO
   bool # this line can be deleted
   select TIZ

示例一的写法中,两处的 FOO 表示的是同一个 config 项,当 FOO 被选中时, BARTIZ 也会被选中。第二个 bool 关键字也可以被省略。

示例二:

config FOO
   bool
   depends on BAR
   default n

...

config FOO
   bool
   depends on TIZ
   default y

示例二的写法中,两处的 FOO 分别依赖了 BARTIZ, 这两个依赖项只会作用于当前位置的表达式,即等价于:

config FOO
   bool
   default n if BAR

...

config FOO
   bool
   default y if TIZ

仅有 BAR 被选中时, FOO 的值为 n;仅有 TIZ 被选中, FOO 的值为 y。当 BARTIZ 同时被选中时,根据 default 取首个有效值的规则, FOO 的值为 n

conf 文件介绍

conf 文件格式

conf 文件通过将用户需要设置的配置项写入其中,代替可视化界面的 menuconfig 方式。conf 文件由多行配置项组成,这些配置项遵循以下格式:

CONFIG_<name1>=<value>

CONFIG_<name2>=<value>

...

= 号左右不允许有空格。

conf 文件写法

  • conf 文件的写法基本类似于 .config 文件,但需要注意的是, .config 文件中包含了所有 config 项,无论其是否对用户可见。但 conf 文件中只允许设置对用户可见的 config 项。

  • 和 menuconfig 交互式配置的方式类似,这种直接配置的方式本质上也是选中/取消选中一些 Kconfig 文件中定义的项,只是用参数输入的方式代替了交互的的输入。

例如有这样的 Kconfig:

config SUPPORT_ATCMD
   bool "Enable ATCMD"
   default n
if SUPPORT_ATCMD
   choice
      default ATCMD_MANUAL_TEST
      prompt "ATCMD Mode"
      config ATCMD_MANUAL_TEST
            bool "Manual Test Mode"
      config ATCMD_HOST_CONTROL
            bool "Host Control Mode"
   endchoice
   config ATCMD_NETWORK
      bool "Enable Network"
      default n
   config ATCMD_SOCKET
      bool "Enable Socket"
endif
[*] Enable ATCMD
   ATCMD Mode (Manual Test Mode)  --->
[ ]     Enable Longer CMD
[*]     Enable Network
[ ]     Enable Socket

对应的 conf 文件应写为:

CONFIG_SUPPORT_ATCMD=y

CONFIG_ATCMD_NETWORK=y

由于 ATCMD_MANUAL_TEST 是默认的 choice 值,因此 conf 文件中可省略 CONFIG_ATCMD_MANUAL_TEST=y

{SDK}/amebaxxx_gcc_project/utils/confs_daily_build 目录下,还提供了各种常见的配置集合文件,用户可参考这些示例创建自己的 conf 文件。

备注

用户可通过 menuconfig.py -s 将当前配置保存为 conf 文件。

default.conf

  • {SDK}/amebaxxx_gcc_project 目录下,提供了一个名为 default.conf 的配置集合文件,定义了编译本 SOC 项目的 初始配置

  • 特殊地, menuconfig.py -f 隐含了 menuconfig.py -f default.conf 的规则,这样在编写其它 conf 文件时,可省略 default.conf 文件中已经配置过的配置项,即只需编写 default.conf 的增量配置即可。如果需要关闭 default.conf 中的某些选项,请将对应的配置项赋值为 n

  • Kconfig 中的 default 值只有在未设定某个配置项时才会生效, 而 default.conf 文件相当于一系列默认的输入项,因此 default.conf 的优先级要高于 Kconfig 中的 default 值。

prj.conf

  • prj.conf 存放在 example 下或用户创建的 工程路径 下,记录此 example 或外部工程需要的配置项。 用户可通过 menuconfig.py -f /.../prj.conf 对项目进行配置。当用户未通过可视化配置或指定其他 conf 文件时, prj.conf 会作为 初始配置 生效。

  • prj.conf 的优先级高于 default.conf

Kconfig 自动检查更新

有这样一种情况, Kconfig 文件或 default.conf 文件更新后(例如从远程仓库中拉取),但 menuconfig 文件夹下的文件仍是基于更新前 Kconfig 生成,这时候直接运行 build.py 命令可能会出现预期外的效果。为避免这种情况发生,每次进行编译前都会对 Kconfig 的更新状态进行检查。

检查的锚定文件为 menuconfig/.config_default ,该文件每次编译前都会基于 default.conf 生成,内容为该 SOC 的默认配置值。如果某次生成 menuconfig/.config_default 后,发现 menuconfig 文件夹下已经存在同名文件并且内容和本次生成的内容不一致。控制台将打印两个文件的 diff 差异,并让用户根据差异内容进行选择:

  • 如果用户判断此次 Kconfig 更新可以忽略,那么可以按下 Enter,本次编译将继续使用当前的 .config 配置。

  • 如果用户认为忽略此次 Kconfig 内容可能会对编译结果造成影响,那么可以按下 Ctrl+C 退出。退出后,用户可以通过可视化配置或 menuconfig.py -f 的方式重新进行配置,亦或通过 menuconfig.py -cbuild.py -p 等方式清理 menuconfig 文件夹后采用默认配置编译。