zephyr 配置系统


交互式 Kconfig 接口 设置 Kconfig 配置值 Kconfig-技巧和最佳实践 自定义 Kconfig 预处理器函数 Kconfig 扩展

  • 交互式 Kconfig 接口
  • 设置 Kconfig 配置值
  • Kconfig-技巧和最佳实践
  • 自定义 Kconfig 预处理器函数
  • Kconfig 扩展

Configuration System (Kconfig) 配置系统(Kconfig)

The Zephyr kernel and subsystems can be configured at build time to adapt them for specific application and platform needs. Configuration is handled through Kconfig, which is the same configuration system used by the Linux kernel. The goal is to support configuration without having to change any source code.

可以在构建时配置 Zephyr 内核和子系统,以使其适应特定的应用程序和平台需求。配置是通过 Kconfig 处理的,这是 Linux 内核使用的相同配置系统。目标是支持配置,而不必更改任何源代码。

Configuration options (often called symbols) are defined in Kconfig files, which also specify dependencies between symbols that determine what configurations are valid. Symbols can be grouped into menus and sub-menus to keep the interactive configuration interfaces organized.

配置选项(通常称为符号)定义在 Kconfig 文件中,这些文件还指定符号之间的依赖关系,以确定哪些配置是有效的。符号可以分组为菜单和子菜单,以保持交互式配置接口的组织。

The output from Kconfig is a header file autoconf.h with macros that can be tested at build time. Code for unused features can be compiled out to save space.

Kconfig 的输出是一个带有宏的 autoconf.h 头文件,可以在构建时进行测试。未使用特性的代码可以编译出来以节省空间。

The following sections explain how to set Kconfig configuration options, go into detail on how Kconfig is used within the Zephyr project, and have some tips and best practices for writing Kconfig files.

下面的部分解释如何设置 Kconfig 配置选项,详细介绍如何在 Zephyr 项目中使用 Kconfig,以及编写 Kconfig 文件的一些技巧和最佳实践。

Users interested in optimizing their configuration for security should refer to the Zephyr Security Guide’s section on the Hardening Tool.

对优化其安全配置感兴趣的用户应该参考 Zephyr 安全指南中关于硬化工具的部分。

Interactive Kconfig interfaces 交互式 Kconfig 接口

There are two interactive configuration interfaces available for exploring the available Kconfig options and making temporary changes: menuconfig and guiconfig. menuconfig is a curses-based interface that runs in the terminal, while guiconfig is a graphical configuration interface.

有两个交互式配置界面可用于探索可用的 Kconfig 选项并进行临时更改: menuconfig 和 guiconfig。Menuconfig 是一个基于 curses 的界面,在终端中运行,而 guiconfig 是一个图形化的配置界面。


The configuration can also be changed by editing zephyr/.config in the application build directory by hand. Using one of the configuration interfaces is often handier, as they correctly handle dependencies between configuration symbols.

还可以通过在应用程序生成目录中手动编辑 zephyr/.config 修改配置。使用其中一个配置接口通常更方便,因为它们可以正确处理配置符号之间的依赖关系。

If you try to enable a symbol with unsatisfied dependencies in zephyr/.config, the assignment will be ignored and overwritten when re-configuring.

如果尝试在 zephyr/.config中启用具有未满足依赖项的符号。重新配置时,这个设置将被忽略和覆盖。

To make a setting permanent, you should set it in a *.conf file, as described in Setting Kconfig configuration values.

要使设置永久化,您应该在 *.conf 文件中设置它,如设置 Kconfig 配置值中所述。


Saving a minimal configuration file (with e.g. D in menuconfig) and inspecting it can be handy when making settings permanent. The minimal configuration file only lists symbols that differ from their default value.

保存一个最小的配置文件(例如,在 menuconfig 中使用 D)并检查它可以方便地使设置永久化。最小配置文件只列出与默认值不同的符号。

To run one of the configuration interfaces, do this:


  1. Build your application as usual using either west or cmake:

    像往常一样使用 west 或 cmake 构建应用程序:

    Using west:

    west build -b <board>

    Using CMake and ninja:

    mkdir build && cd build
    cmake -GNinja -DBOARD=<board> ..
  2. To run the terminal-based menuconfig interface, use either of these commands:

    要运行基于终端的 menuconfig 接口,请使用以下命令之一:

    west build -t menuconfig
    ninja menuconfig

    To run the graphical guiconfig, use either of these commands:

    要运行图形化 guiconfig,可以使用以下命令之一:

    west build -t guiconfig
    ninja guiconfig


    If you get an import error for tkinter when trying to run guiconfig, you are missing required packages. See Install Linux Host Dependencies. The package you need is usually called something like python3-tk/python3-tkinter.

    如果您在尝试运行 guiconfig 时得到 tkinter 的导入错误,那么您就丢失了所需的包。请参见安装 Linux 主机依赖项。您需要的包通常称为 python3-tk/python3-tkinter。

    tkinter is not included by default in many Python installations, despite being part of the standard library.

    尽管 tkinter 是标准库的一部分,但在许多 Python 安装中缺省情况下并不包含 tkinter。

    The two interfaces are shown below:


    menuconfig interface

    guiconfig interface

    guiconfig always shows the help text and other information related to the currently selected item in the bottom window pane. In the terminal interface, press ? to view the same information.

    Guiconfig 始终在底部窗格中显示与当前选定项相关的帮助文本和其他信息。在终端界面,按?查看相同的信息。


    If you prefer to work in the guiconfig interface, then it’s a good idea to check any changes to Kconfig files you make in single-menu mode, which is toggled via a checkbox at the top. Unlike full-tree mode, single-menu mode will distinguish between symbols defined with config and symbols defined with menuconfig, showing you what things would look like in the menuconfig interface.

    如果你喜欢在 guiconfig 界面上工作,那么最好在单菜单模式下检查你对 Kconfig 文件所做的任何更改,这是通过顶部的复选框进行切换的。与完整树模式不同,单菜单模式将区分用配置定义的符号和用 menuconfig 定义的符号,向您显示在 menuconfig 接口中的情况。

  3. Change configuration values in the menuconfig interface as follows:

    在 menuconfig 接口中更改配置值,如下所示:

    • Navigate the menu with the arrow keys. Common Vim key bindings are supported as well.

      使用箭头键导航菜单。也支持常见的 Vim 键绑定。

    • Use Space and Enter to enter menus and toggle values. Menus appear with ---> next to them. Press ESC to return to the parent menu.

      使用 Space 和 Enter 输入菜单并切换值。菜单出现在——-> 旁边。按 ESC 返回到父菜单。

      Boolean configuration options are shown with [ ] brackets, while numeric and string-valued configuration symbols are shown with ( ) brackets. Symbol values that can’t be changed are shown as - - or -*-.


      You can also press Y or N to set a boolean configuration symbol to the corresponding value.

      还可以按 Y 或 N 将布尔配置符号设置为相应的值。

    • Press ? to display information about the currently selected symbol, including its help text. Press ESC or Q to return from the information display to the menu.

      按下 ?显示有关当前选定符号的信息,包括其帮助文本。按 ESC 或 Q 从信息显示返回到菜单。

    In the guiconfig interface, either click on the image next to the symbol to change its value, or double-click on the row with the symbol (this only works if the symbol has no children, as double-clicking a symbol with children open/closes its menu instead).

    在 guiconfig 界面中,要么单击符号旁边的图像来更改其值,要么双击带有符号的行(这只在符号没有子元素的情况下有效,因为双击带有子元素的符号会打开/关闭其菜单)。

    guiconfig also supports keyboard controls, which are similar to menuconfig.

    Guiconfig 还支持类似于 menuconfig 的键盘控件。

  4. Pressing Q in the menuconfig interface will bring up the save-and-quit dialog (if there are changes to save):

    在 menuconfig 界面中按 Q 会显示保存和退出对话框(如果有要保存的更改) :

    Save and Quit Dialog

    Press Y to save the kernel configuration options to the default filename (zephyr/.config). You will typically save to the default filename unless you are experimenting with different configurations.

    按 Y 将内核配置选项保存到默认文件名(zephyr/。配置)。您通常会保存到默认的文件名,除非您正在尝试不同的配置。

    The guiconfig interface will also prompt for saving the configuration on exit if it has been modified.

    如果配置已被修改,guiconfig 接口还会提示在出口时保存配置。


    The configuration file used during the build is always zephyr/.config. If you have another saved configuration that you want to build with, copy it to zephyr/.config. Make sure to back up your original configuration file.

    构建过程中使用的配置文件总是 zephyr/。配置。如果您有另一个保存的配置要用来构建,请将其复制到 zephyr/。配置。确保备份原始配置文件。

    Also note that filenames starting with . are not listed by ls by default on Linux and macOS. Use the -a flag to see them.

    还要注意,在 Linux 和 macOS 上文件名以 . 开始,默认情况下不是由 ls 列出的。用 -a

Finding a symbol in the menu tree and navigating to it can be tedious. To jump directly to a symbol, press the / key (this also works in guiconfig). This brings up the following dialog, where you can search for symbols by name and jump to them. In guiconfig, you can also change symbol values directly within the dialog.

在菜单树中找到一个符号并导航到它可能是乏味的。要直接跳转到一个符号,请按/键(这在 guiconfig 中也可以使用)。这将打开下面的对话框,您可以在其中按名称搜索符号并跳转到它们。在 guiconfig 中,还可以直接在对话框中更改符号值。

menuconfig jump-to dialog

guiconfig jump-to dialog

If you jump to a symbol that isn’t currently visible (e.g., due to having unsatisfied dependencies), then show-all mode will be enabled. In show-all mode, all symbols are displayed, including currently invisible symbols. To turn off show-all mode, press A in menuconfig or Ctrl-A in guiconfig.

如果您跳转到当前不可见的符号(例如,由于有不满意的依赖关系) ,则将启用 show-all 模式。在 show-all 模式下,将显示所有符号,包括当前不可见的符号。要关闭 show-all 模式,请在 menuconfig 中按 A 或在 guiconfig 中按 Ctrl-A。


Show-all mode can’t be turned off if there are no visible items in the current menu.


To figure out why a symbol you jumped to isn’t visible, inspect its dependencies, either by pressing ? in menuconfig or in the information pane at the bottom in guiconfig. If you discover that the symbol depends on another symbol that isn’t enabled, you can jump to that symbol in turn to see if it can be enabled.

为了弄清楚为什么跳转到的符号不可见,检查它的依赖关系,也可以按 ?在 menuconfig 中或在 guiconfig 底部的信息窗格中。如果您发现该符号依赖于另一个未启用的符号,则可以依次跳转到该符号以查看是否可以启用该符号。


In menuconfig, you can press Ctrl-F to view the help of the currently selected item in the jump-to dialog without leaving the dialog.

在 menuconfig 中,可以按 Ctrl-F 查看跳转到对话框中当前选定项的帮助,而不必离开对话框。

For more information on menuconfig and guiconfig, see the Python docstrings at the top of menuconfig.py and guiconfig.py.

有关 menuconfig 和 guiconfig 的更多信息,请参见 menuconfig.py 和 guiconfig.py 顶部的 Python docstring。

Setting Kconfig configuration values 设置 Kconfig 配置值

The menuconfig and guiconfig interfaces can be used to test out configurations during application development. This page explains how to make settings permanent.

Menuconfig 和 guiconfig 接口可用于在应用程序开发期间测试配置。本页解释如何使设置永久化。

All Kconfig options can be searched in the Kconfig search page.

可以在 Kconfig 搜索页面中搜索所有 Kconfig 选项。


Before making changes to Kconfig files, it’s a good idea to also go through the Kconfig - Tips and Best Practices page.

在修改 Kconfig 文件之前,最好先浏览一下 Kconfig-Tips and Best Practices 页面。

Visible and invisible Kconfig symbols 可见和不可见的 Kconfig 符号

When making Kconfig changes, it’s important to understand the difference between visible and invisible symbols.

在更改 Kconfig 时,了解可见符号和不可见符号之间的区别是很重要的。

  • A visible symbol is a symbol defined with a prompt. Visible symbols show up in the interactive configuration interfaces (hence visible), and can be set in configuration files.

    可见符号是用提示符定义的符号。可见符号显示在交互式配置接口中(因此是可见的) ,并且可以在配置文件中设置。

    Here’s an example of a visible symbol:


    config FPU
       bool "Support floating point operations"
       depends on HAS_FPU

    The symbol is shown like this in menuconfig, where it can be toggled:

    该符号在 menuconfig 中如下所示,可以在其中进行切换:

    [ ] Support floating point operations
  • An invisible symbol is a symbol without a prompt. Invisible symbols are not shown in the interactive configuration interfaces, and users have no direct control over their value. They instead get their value from defaults or from other symbols.


    Here’s an example or an invisible symbol:


    config CPU_HAS_FPU
         This symbol is y if the CPU has a hardware floating point unit.

    In this case, CPU_HAS_FPU is enabled through other symbols having select CPU_HAS_FPU.

    在这种情况下,CPU _ HAS _ FPU 通过选择 CPU _ HAS _ FPU 的其他符号启用。

Setting symbols in configuration files 在配置文件中设置符号

Visible symbols can be configured by setting them in configuration files. The initial configuration is produced by merging a *_defconfig file for the board with application settings, usually from prj.conf. See The Initial Configuration below for more details.

可见符号可以通过在配置文件中设置它们来配置。初始配置是通过将主板上的 *_defconfig 文件与应用程序设置(通常来自 prj.conf)合并而生成的。有关详细信息,请参阅下面的初始配置。

Assignments in configuration files use this syntax:


CONFIG_<symbol name>=<value>

There should be no spaces around the equals sign.


bool symbols can be enabled or disabled by setting them to y or n, respectively. The FPU symbol from the example above could be enabled like this:

Bool 符号可以通过分别设置为 y 或 n 来启用或禁用。上面示例中的 FPU 符号可以这样启用:



A boolean symbol can also be set to n with a comment formatted like this:

布尔符号也可以通过注释设置为 n:


This is the format you will see in the merged configuration in zephyr/.config.

这是您将在 zephyr/.config中的合并配置中看到的格式。

This style is accepted for historical reasons: Kconfig configuration files can be parsed as makefiles (though Zephyr doesn’t use this). Having n-valued symbols correspond to unset variables simplifies tests in Make.

由于历史原因,这种风格是可以接受的: Kconfig 配置文件可以解析为 makefile (尽管 Zephyr 不使用这种风格)。使 n 值符号对应于未设置的变量可以简化 Make 中的测试。

Other symbol types are assigned like this:



Comments use a #:

# This is a comment

Assignments in configuration files are only respected if the dependencies for the symbol are satisfied. A warning is printed otherwise. To figure out what the dependencies of a symbol are, use one of the interactive configuration interfaces (you can jump directly to a symbol with /), or look up the symbol in the Kconfig search page.

只有符号的依赖项得到满足时,配置文件中的赋值才受到尊重。否则将打印警告。要弄清楚符号的依赖关系,可以使用交互式配置接口之一(您可以通过/直接跳转到符号) ,或者在 Kconfig 搜索页面中查找符号。

The Initial Configuration 初始配置

The initial configuration for an application comes from merging configuration settings from three sources:


  1. A BOARD-specific configuration file stored in boards/<architecture>/<BOARD>/<BOARD>_defconfig

    存储在 boards/<architecture>/<BOARD>/<BOARD>_defconfig 中的特定于 BOARD 的配置文件

  2. Any CMake cache entries prefix with CONFIG_

    任何 CMake 前缀为 CONFIG_ 的缓存条目

  3. The application configuration


The application configuration can come from the sources below. By default, prj.conf is used.

应用程序配置可以来自下面的源代码,默认情况下使用 prj.conf。

  1. If CONF_FILE is set, the configuration file(s) specified in it are merged and used as the application configuration. CONF_FILE can be set in various ways:

    如果设置了 CONF_FILE,则合并其中指定的配置文件并将其用作应用程序配置。CONF_FILE 可以通过多种方式设置:

    1. In CMakeLists.txt, before calling find_package(Zephyr)

      在 CMakeLists.txt 中,在调用 find_package(Zephyr)之前

    2. By passing -DCONF_FILE=<conf file(s)>, either directly or via west

      通过传递 -DCONF_FILE=<conf file(s)>,可以直接传递,也可以通过 west 传递

    3. From the CMake variable cache

      从 CMake 变量缓存

  2. Otherwise if CONF_FILE is set, and a single configuration file of the form prj_<build>.conf is used, then if file boards/<BOARD>_<build>.conf exists in same folder as file prj_<build>.conf, the result of merging prj_<build>.conf and boards/<BOARD>_<build>.conf is used.

    否则,如果设置了CONF_FILE,并且使用了形式为prj_<build>.conf的单个配置文件,那么如果文件 boards/<BOARD>_<build>.conf与文件prj_<build>.conf存在于同一文件夹中,则使用合并prj_<build>.confboards/<BOARD>_<build>.conf的结果。

  3. Otherwise, prj_<BOARD>.conf is used if it exists in the application configuration directory.

    否则,如果 prj_<BOARD>.conf 存在于应用程序配置目录中,则使用它。

  4. Otherwise, if boards/<BOARD>.conf exists in the application configuration directory, the result of merging it with prj.conf is used.

    否则,如果 boards/<BOARD>.conf 存在于应用程序配置目录中,则使用将其与 prj.conf 合并的结果。

  5. Otherwise, if board revisions are used and boards/<BOARD>_<revision>.conf exists in the application configuration directory, the result of merging it with prj.conf and boards/<BOARD>.conf is used.

    否则,如果使用主板修订版,并且boards/<BOARD>_<revision>.conf存在于应用程序配置目录中,使用的是将其与 prj.conf 和 boards/<BOARD>.conf 合并的结果。

  6. Otherwise, prj.conf is used if it exists in the application configuration directory

    否则,如果 prj.conf 存在于应用程序配置目录中,则使用它

All configuration files will be taken from the application’s configuration directory except for files with an absolute path that are given with the CONF_FILE argument.

所有的配置文件都将从应用程序的配置目录中获取,除了带有 CONF_FILE 参数给出的绝对路径的文件。

See Application Configuration Directory on how the application configuration directory is defined.


If a symbol is assigned both in <BOARD>_defconfig and in the application configuration, the value set in the application configuration takes precedence.

如果在 <BOARD>_defconfig 和应用程序配置中都分配了符号,则应用程序配置中设置的值优先。

The merged configuration is saved to zephyr/.config in the build directory.

合并的配置保存到构建目录中的 zephyr/.config。

As long as zephyr/.config exists and is up-to-date (is newer than any BOARD and application configuration files), it will be used in preference to producing a new merged configuration. zephyr/.config is also the configuration that gets modified when making changes in the interactive configuration interfaces.

只要 zephyr/.config 已经存在并且是最新的(比任何 BOARD 和应用程序配置文件都要新) ,它将优先用于生成新的合并配置。Zephyr/.Config 也是在交互式配置接口中进行更改时修改的配置。

Configuring invisible Kconfig symbols 配置不可见的 Kconfig 符号

When making changes to the default configuration for a board, you might have to configure invisible symbols. This is done in boards/<architecture>/<BOARD>/Kconfig.defconfig, which is a regular Kconfig file.

在更改板的默认配置时,可能必须配置不可见符号。这是在 boards/<architecture>/<BOARD>/Kconfig.defconfig 中完成的,它是一个常规的 Kconfig 文件。


Assignments in .config files have no effect on invisible symbols, so this scheme is not just an organizational issue.

.config 文件中的赋值对不可见的符号没有影响,所以这个方案不仅仅是一个组织问题。

Assigning values in Kconfig.defconfig relies on defining a Kconfig symbol in multiple locations. As an example, say we want to set FOO_WIDTH below to 32:


config FOO_WIDTH

To do this, we extend the definition of FOO_WIDTH as follows, in Kconfig.defconfig:

为此,我们在 Kconfig.defconfig 中扩展 FOO_WIDTH 的定义如下:


config FOO_WIDTH
    default 32



Since the type of the symbol (int) has already been given at the first definition location, it does not need to be repeated here. Only giving the type once at the “base” definition of the symbol is a good idea for reasons explained in Common Kconfig shorthands.

因为符号(int)的类型已经在第一个定义位置给出,所以不需要在这里重复。只在符号的“基本”定义处给出类型一次是一个好主意,原因在 Common Kconfig 简写中有解释。

default values in Kconfig.defconfig files have priority over default values given on the “base” definition of a symbol. Internally, this is implemented by including the Kconfig.defconfig files first. Kconfig uses the first default with a satisfied condition, where an empty condition corresponds to if y (is always satisfied).

Kconfig.defconfig 文件中的默认值优先于符号的“基本”定义中给定的默认值。在内部,这是通过首先包含 Kconfig.defconfig 文件来实现的。Kconfig 使用带有满足条件的第一个默认值,其中一个空条件对应于 y (始终满足)。

Note that conditions from surrounding top-level ifs are propagated to symbol properties, so the above default is equivalent to default 32 if BOARD_MY_BOARD.

注意,来自周围顶级 if 的条件被传播到符号属性,所以上面的默认值等效于default 32 if BOARD_MY_BOARD.

Warning 警告

When defining a symbol in multiple locations, dependencies are ORed together rather than ANDed together. It is not possible to make the dependencies of a symbol more restrictive by defining it in multiple locations.

在多个位置定义符号时,依赖项是一起进行 OR 操作,而不是一起进行 AND 操作。通过在多个位置定义符号,不可能使符号的依赖关系更具限制性。

For example, the direct dependencies of the symbol below becomes DEP1 || DEP2:

例如,下面的符号的直接依赖关系变成 DEP1 || DEP2:

config FOO
  depends on DEP1

config FOO
  depends on DEP2

When making changes to Kconfig.defconfig files, always check the symbol’s direct dependencies in one of the interactive configuration interfaces afterwards. It is often necessary to repeat dependencies from the base definition of the symbol to avoid weakening a symbol’s dependencies.

在对 Kconfig.defconfig 文件进行更改时,事后总是在一个交互式配置接口中检查符号的直接依赖项。通常需要从符号的基本定义重复依赖项,以避免削弱符号的依赖项。

Motivation for Kconfig.defconfig files 对 Kconfig.defconfig 文件的激励

One motivation for this configuration scheme is to avoid making fixed BOARD-specific settings configurable in the interactive configuration interfaces. If all board configuration were done via <BOARD>_defconfig, all symbols would have to be visible, as values given in <BOARD>_defconfig have no effect on invisible symbols.

此配置方案的一个动机是避免在交互式配置接口中使固定的特定于 BOARD 的设置可配置。如果所有的电路板配置都是通过 <BOARD>_defconfig 完成的,那么所有的符号都必须是可见的,因为 <BOARD>_defconfig 中给出的值对不可见的符号没有影响。

Having fixed settings be user-configurable would clutter up the configuration interfaces and make them harder to understand, and would make it easier to accidentally create broken configurations.


When dealing with fixed board-specific settings, also consider whether they should be handled via devicetree instead.

在处理固定板的特定设置时,还要考虑是否应该通过 devicetree 来处理它们。

Configuring choices 配置选项

There are two ways to configure a Kconfig choice:

配置 Kconfig 选项有两种方式:

  1. By setting one of the choice symbols to y in a configuration file.

    通过在配置文件中将选择符号之一设置为 y。

    Setting one choice symbol to y automatically gives all other choice symbols the value n.

    将一个选择符号设置为 y 会自动给出所有其他选择符号的值 n。

    If multiple choice symbols are set to y, only the last one set to y will be honored (the rest will get the value n). This allows a choice selection from a board defconfig file to be overridden from an application prj.conf file.

    如果多项选择符号被设置为 y,那么只有最后一个被设置为 y 的符号才会被执行(其余的将得到值 n)。这允许在应用程序 prj.conf 文件中覆盖来自主板 defconfig 文件的选择。

  2. By changing the default of the choice in Kconfig.defconfig.

    通过更改 Kconfig.defconfig 中的 default 默认选项。

    As with symbols, changing the default for a choice is done by defining the choice in multiple locations. For this to work, the choice must have a name.


    As an example, assume that a choice has the following base definition (here, the name of the choice is FOO):

    例如,假设一个选项具有以下基本定义(在这里,选项的名称是 FOO) :

    choice FOO
        bool "Foo choice"
        default B
    config A
        bool "A"
    config B
        bool "B"

    To change the default symbol of FOO to A, you would add the following definition to Kconfig.defconfig:

    要将 FOO 的默认符号更改为 A,需要向 Kconfig.defconfig 添加以下定义:

    choice FOO
        default A

The Kconfig.defconfig method should be used when the dependencies of the choice might not be satisfied. In that case, you’re setting the default selection whenever the user makes the choice visible.

当选择的依赖项可能无法满足时,应该使用 Kconfig.defconfig 方法。在这种情况下,只要用户使选项可见,就设置默认选项。

More Kconfig resources 更多 Kconfig 资源

The Kconfig - Tips and Best Practices page has some tips for writing Kconfig files.

Kconfig-Tips 和 Best Practices 页面有一些编写 Kconfig 文件的提示。

The kconfiglib.py docstring docstring (at the top of the file) goes over how symbol values are calculated in detail.

kconfiglib.py docstring docstring (位于文件的顶部)详细介绍了如何计算符号值。

Kconfig - Tips and Best Practices Kconfig-技巧和最佳实践

This page covers some Kconfig best practices and explains some Kconfig behaviors and features that might be cryptic or that are easily overlooked.

本页涵盖了一些 Kconfig 最佳实践,并解释了一些 Kconfig 行为和特性,这些行为和特性可能比较隐晦或容易被忽视。

The official Kconfig documentation is kconfig-language.rst and kconfig-macro-language.rst.

官方的 Kconfig 文档是 kconfig-language.rstkconfig-macro-language.rst

What to turn into Kconfig options如何转变为 Kconfig 的选项

When deciding whether something belongs in Kconfig, it helps to distinguish between symbols that have prompts and symbols that don’t.

在决定某物是否属于 Kconfig 时,有助于区分有提示符号和没有提示符号的符号。

If a symbol has a prompt (e.g. bool "Enable foo"), then the user can change the symbol’s value in the menuconfig or guiconfig interface (see Interactive Kconfig interfaces), or by manually editing configuration files. Conversely, a symbol without a prompt can never be changed directly by the user, not even by manually editing configuration files.

如果一个符号有一个提示符(例如 bool“ Enable foo”) ,那么用户可以在 menuconfig 或 guiconfig 界面(参见 Interactive Kconfig 界面)中更改该符号的值,或者手动编辑配置文件。相反,没有提示符的符号永远不能由用户直接更改,甚至不能手动编辑配置文件。

Only put a prompt on a symbol if it makes sense for the user to change its value.


Symbols without prompts are called hidden or invisible symbols, because they don’t show up in menuconfig and guiconfig. Symbols that have prompts can also be invisible, when their dependencies are not satisfied.

没有提示符的符号称为隐藏符号或不可见符号,因为它们不显示在 menuconfig 和 guiconfig 中。具有提示符的符号如果不满足其依赖关系,也可以是不可见的。

Symbols without prompts can’t be configured directly by the user (they derive their value from other symbols), so less restrictions apply to them. If some derived setting is easier to calculate in Kconfig than e.g. during the build, then do it in Kconfig, but keep the distinction between symbols with and without prompts in mind.

没有提示符的符号不能由用户直接配置(它们的值来自其他符号) ,因此对它们的限制较少。如果某些派生设置在 Kconfig 比在构建期间更容易计算,那么在 Kconfig 进行,但要记住有提示符号和无提示符号之间的区别。

See the optional prompts section for a way to deal with settings that are fixed on some machines and configurable on other machines.


Options that specify a device in the system by name按名称指定系统中设备的选项

For example, if you are writing an I2C device driver, avoid creating an option named MY_DEVICE_I2C_BUS_NAME for specifying the bus node your device is controlled by. See Device drivers that depend on other devices for alternatives.

例如,如果您正在编写一个 I2C 设备驱动程序,请避免创建一个名为 MY_DEVICE_I2C_BUS_NAME 的选项来指定控制设备的总线节点。请参阅依赖于其他设备的设备驱动程序以获得替代方案。

Similarly, if your application depends on a hardware-specific PWM device to control an RGB LED, avoid creating an option like MY_PWM_DEVICE_NAME. See Applications that depend on board-specific devices for alternatives.

类似地,如果您的应用程序依赖于特定硬件的 PWM 设备来控制 RGB LED,请避免创建像 MY_PWM_DEVICE_NAME 这样的选项。请参阅依赖于特定板设备的应用程序以获得替代方案。

Options that specify fixed hardware configuration指定固定硬件配置的选项

For example, avoid Kconfig options specifying a GPIO pin.

例如,避免指定 GPIO 引脚的 Kconfig 选项。

An alternative applicable to device drivers is to define a GPIO specifier with type phandle-array in the device binding, and using the GPIO devicetree API from C. Similar advice applies to other cases where devicetree.h provides Hardware specific APIs for referring to other nodes in the system. Search the source code for drivers using these APIs for examples.

另一种适用于设备驱动程序的方法是在设备绑定中定义一个带有句柄阵列类型的 GPIO 说明符,并使用来自 C 的 GPIO 设备树 API。类似的建议也适用于 devicetree.h 为引用系统中的其他节点提供特定于硬件的 API 的其他情况。例如,在源代码中搜索使用这些 API 的驱动程序。

An application-specific devicetree binding to identify board specific properties may be appropriate. See tests/drivers/gpio/gpio_basic_api for an example.


For applications, see Blinky for a devicetree-based alternative.

有关应用程序,请参见 Blinky 了解基于设备树的替代方案。

select statements选择语句

The select statement is used to force one symbol to y whenever another symbol is y. For example, the following code forces CONSOLE to y whenever USB_CONSOLE is y:

Select 语句用于一个符号为 y 时强制另一个符号为 y。例如,下面的代码在 USB_CONSOLE 为 y 时强制 CONSOLE 为 y:

config CONSOLE
     bool "Console support"


     bool "USB console support"
     select CONSOLE

This section covers some pitfalls and good uses for select.


select pitfalls选择陷阱

select might seem like a generally useful feature at first, but can cause configuration issues if overused.

Select 一开始似乎是一个通常有用的特性,但是如果过度使用,可能会导致配置问题。

For example, say that a new dependency is added to the CONSOLE symbol above, by a developer who is unaware of the USB_CONSOLE symbol (or simply forgot about it):

例如,假设一个不知道 USB_CONSOLE 符号的开发人员(或者干脆忘记了它)向上面的 CONSOLE 符号添加了一个新的依赖项:

config CONSOLE
     bool "Console support"
     depends on STRING_ROUTINES

Enabling USB_CONSOLE now forces CONSOLE to y, even if STRING_ROUTINES is n.


To fix the problem, the STRING_ROUTINES dependency needs to be added to USB_CONSOLE as well:

要解决这个问题,还需要将 STRING_ROUTINES 依赖项添加到 USB_CONSOLE:

     bool "USB console support"
     select CONSOLE
     depends on STRING_ROUTINES


     bool "Include string routines"

More insidious cases with dependencies inherited from if and menu statements are common.

从 if 和菜单语句继承的依赖关系更加隐蔽,这种情况很常见。

An alternative attempt to solve the issue might be to turn the depends on into another select:


config CONSOLE
     bool "Console support"


     bool "USB console support"
     select CONSOLE

In practice, this often amplifies the problem, because any dependencies added to STRING_ROUTINES now need to be copied to both CONSOLE and USB_CONSOLE.

实际上,这通常会放大问题,因为任何添加到 STRING _ ROUTINES 的依赖项现在都需要复制到 CONSOLE 和 USB _ CONSOLE。

In general, whenever the dependencies of a symbol are updated, the dependencies of all symbols that (directly or indirectly) select it have to be updated as well. This is very often overlooked in practice, even for the simplest case above.


Chains of symbols selecting each other should be avoided in particular, except for simple helper symbols, as covered below in Using select for helper symbols.


Liberal use of select also tends to make Kconfig files harder to read, both due to the extra dependencies and due to the non-local nature of select, which hides ways in which a symbol might get enabled.

随意的使用 select 还会使 Kconfig 文件更难阅读,这既是由于额外的依赖关系,也是由于 select 的非本地性质,这隐藏了可能启用符号的方式。

Alternatives to select可供选择的备选方案

For the example in the previous section, a better solution is usually to turn the select into a depends on:

对于上一节中的示例,一个更好的解决方案通常是将 select 转换为depends on:

config CONSOLE
     bool "Console support"


     bool "USB console support"
     depends on CONSOLE

This makes it impossible to generate an invalid configuration, and means that dependencies only ever have to be updated in a single spot.


An objection to using depends on here might be that configuration files that enable USB_CONSOLE now also need to enable CONSOLE:

反对使用depends on这里可能是启用 USB _ CONSOLE 的配置文件现在也需要启用 CONSOLE:


This comes down to a trade-off, but if enabling CONSOLE is the norm, then a mitigation is to make CONSOLE default to y:

这可以归结为一种权衡,但是如果启用 CONSOLE 是一种规范,那么一种缓解就是使 CONSOLE 默认为 y:

config CONSOLE
     bool "Console support"
     default y

This gives just a single assignment in configuration files:



Note that configuration files that do not want CONSOLE enabled now have to explicitly disable it:

注意,不希望启用 CONSOLE 的配置文件现在必须显式禁用它:


Using select for helper symbols使用辅助符号 select

A good and safe use of select is for setting “helper” symbols that capture some condition. Such helper symbols should preferably have no prompt or dependencies.

Select 的一个好用且安全的用法是设置捕获某些条件的辅助符号。这种帮助器符号最好没有提示符或依赖项。

For example, a helper symbol for indicating that a particular CPU/SoC has an FPU could be defined as follows:

例如,用于指示特定 CPU/SoC 具有 FPU 的辅助符号可以定义如下:

config CPU_HAS_FPU
       If y, the CPU has an FPU


config SOC_FOO
     bool "FOO SoC"
     select CPU_HAS_FPU


config SOC_BAR
     bool "BAR SoC"
     select CPU_HAS_FPU

This makes it possible for other symbols to check for FPU support in a generic way, without having to look for particular architectures:

这使得其他符号以通用方式检查 FPU 支持成为可能,而不必寻找特定的体系结构:

config FPU
     bool "Support floating point operations"
     depends on CPU_HAS_FPU

The alternative would be to have dependencies like the following, possibly duplicated in several spots:


config FPU
     bool "Support floating point operations"
     depends on SOC_FOO || SOC_BAR || ...

Invisible helper symbols can also be useful without select. For example, the following code defines a helper symbol that has the value y if the machine has some arbitrarily-defined “large” amount of memory:

不使用 select 的隐形助手符号也可以很有用。例如,下面的代码定义了一个辅助符号,如果机器具有任意定义的“大”内存量,则该符号的值为 y:

config LARGE_MEM
     def_bool MEM_SIZE >= 64



This is short for the following:


config LARGE_MEM
  default MEM_SIZE >= 64

select recommendations选择建议

In summary, here are some recommended practices for select:


  • Avoid selecting symbols with prompts or dependencies. Prefer depends on. If depends on causes annoying bloat in configuration files, consider adding a Kconfig default for the most common value.

    避免选择带有提示或依赖项的符号。使用 depends on。如果在配置文件中depends on导致恼人的膨胀,可以考虑为最常见的值添加一个 Kconfig 默认值。

    Rare exceptions might include cases where you’re sure that the dependencies of the selecting and selected symbol will never drift out of sync, e.g. when dealing with two simple symbols defined close to one another within the same if.


    Common sense applies, but be aware that select often causes issues in practice. depends on is usually a cleaner and safer solution.


  • Select simple helper symbols without prompts and dependencies however much you like. They’re a great tool for simplifying Kconfig files.

    选择没有提示符和依赖项的简单助手符号,这是简化 Kconfig 文件的一个很好的工具。

(Lack of) conditional includes (缺乏)有条件的包括

if blocks add dependencies to each item within the if, as if depends on was used.

If 块将依赖项添加到 if 中的每个项,就像使用了 depends on。

A common misunderstanding related to if is to think that the following code conditionally includes the file Kconfig.other:

与 if 有关的一个常见误解是认为下面的代码有条件地包含 Kconfig.other 文件:

if DEP
source "Kconfig.other"

In reality, there are no conditional includes in Kconfig. if has no special meaning around a source.

事实上,在 Kconfig 没有条件包含,if 在source周围并没有特殊意义。



Conditional includes would be impossible to implement, because if conditions may contain (either directly or indirectly) forward references to symbols that haven’t been defined yet.


Say that Kconfig.other above contains this definition:

假设上面的 Kconfig.other 包含这个定义:

config FOO
     bool "Support foo"

In this case, FOO will end up with this definition:

在这种情况下,FOO 最终会得到这个定义:

config FOO
     bool "Support foo"
     depends on DEP

Note that it is redundant to add depends on DEP to the definition of FOO in Kconfig.other, because the DEP dependency has already been added by if DEP.

注意,在 Kconfig.other 中将 DEP 依赖项添加到 FOO 的定义中是多余的,因为 DEP 依赖项已经由 if DEP 添加。

In general, try to avoid adding redundant dependencies. They can make the structure of the Kconfig files harder to understand, and also make changes more error-prone, since it can be hard to spot that the same dependency is added twice.

一般来说,尽量避免添加多余的依赖项。它们可以使 Kconfig 文件的结构更加难以理解,也使更改更容易出错,因为很难发现相同的依赖项被添加了两次。

“Stuck” symbols in menuconfig and guiconfigMenuconfig 和 guiconfig 中的“ Stuck”符号

There is a common subtle gotcha related to interdependent configuration symbols with prompts. Consider these symbols:


config FOO
     bool "Foo"

     hex "Stack size"
     default 0x200 if FOO
     default 0x100

Assume that the intention here is to use a larger stack whenever FOO is enabled, and that the configuration initially has FOO disabled. Also, remember that Zephyr creates an initial configuration in zephyr/.config in the build directory by merging configuration files (including e.g. prj.conf). This configuration file exists before menuconfig or guiconfig is run.

假设这里的目的是在启用 FOO 时使用更大的堆栈,并且配置最初禁用了 FOO。另外,记住Zephyr通过合并配置文件(包括例如prj.conf)在构建目录的Zephyr/.config中创建初始配置。此配置文件在运行 menuconfig 或 guiconfig 之前存在。

When first entering the configuration interface, the value of STACK_SIZE is 0x100, as expected. After enabling FOO, you might reasonably expect the value of STACK_SIZE to change to 0x200, but it stays as 0x100.

当第一次进入配置接口时,如预期的那样,STACK _ SIZE 的值为0x100。启用 FOO 之后,您可以合理地期望 STACK _ SIZE 的值更改为0x200,但是它保持为0x100。

To understand what’s going on, remember that STACK_SIZE has a prompt, meaning it is user-configurable, and consider that all Kconfig has to go on from the initial configuration is this:

要理解发生了什么,请记住 STACK _ SIZE 有一个提示符,这意味着它是用户可配置的,并且考虑到所有 Kconfig 都必须从初始配置开始:


Since Kconfig can’t know if the 0x100 value came from a default or was typed in by the user, it has to assume that it came from the user. Since STACK_SIZE is user-configurable, the value from the configuration file is respected, and any symbol defaults are ignored. This is why the value of STACK_SIZE appears to be “frozen” at 0x100 when toggling FOO.

由于 Kconfig 无法知道0x100值是来自默认值还是由用户键入的,因此它必须假设它来自用户。由于 STACK _ SIZE 是用户可配置的,因此尊重配置文件中的值,并忽略任何符号默认值。这就是为什么在切换 FOO 时,STACK _ SIZE 的值似乎被“冻结”在0x100。

The right fix depends on what the intention is. Here’s some different scenarios with suggestions:


  • If STACK_SIZE can always be derived automatically and does not need to be user-configurable, then just remove the prompt:

    如果 STACK _ SIZE 始终可以自动派生,并且不需要用户可配置,那么只需删除提示:

    config STACK_SIZE
       default 0x200 if FOO
       default 0x100

    Symbols without prompts ignore any value from the saved configuration.


  • If STACK_SIZE should usually be user-configurable, but needs to be set to 0x200 when FOO is enabled, then disable its prompt when FOO is enabled, as described in optional prompts:

    如果 STACK _ SIZE 通常是用户可配置的,但在启用 FOO 时需要设置为0x200,那么在启用 FOO 时禁用其提示符,如可选提示符中所述:

    config STACK_SIZE
       hex "Stack size" if !FOO
       default 0x200 if FOO
       default 0x100
  • If STACK_SIZE should usually be derived automatically, but needs to be set to a custom value in rare circumstances, then add another option for making STACK_SIZE user-configurable:

    如果 STACK _ SIZE 通常应该是自动派生的,但在极少数情况下需要设置为自定义值,那么添加另一个选项,使 STACK _ SIZE 成为用户可配置的:

       bool "Use a custom stack size"
         Enable this if you need to use a custom stack size. When disabled, a
         suitable stack size is calculated automatically.
    config STACK_SIZE
       hex "Stack size" if CUSTOM_STACK_SIZE
       default 0x200 if FOO
       default 0x100

    As long as CUSTOM_STACK_SIZE is disabled, STACK_SIZE will ignore the value from the saved configuration.

    只要禁用 CUSTOM _ STACK _ SIZE,STACK _ SIZE 就会忽略保存配置中的值。

It is a good idea to try out changes in the menuconfig or guiconfig interface, to make sure that things behave the way you expect. This is especially true when making moderately complex changes like these.

尝试在 menuconfig 或 guiconfig 接口中进行更改是一个好主意,可以确保事情按照您预期的方式运行。在进行像这样适度复杂的变更时尤其如此。

Assignments to promptless symbols in configuration files对配置文件中非提示符号的赋值

Assignments to hidden (promptless, also called invisible) symbols in configuration files are always ignored. Hidden symbols get their value indirectly from other symbols, via e.g. default and select.


A common source of confusion is opening the output configuration file (zephyr/.config), seeing a bunch of assignments to hidden symbols, and assuming that those assignments must be respected when the configuration is read back in by Kconfig. In reality, all assignments to hidden symbols in zephyr/.config are ignored by Kconfig, like for other configuration files.


To understand why zephyr/.config still includes assignments to hidden symbols, it helps to realize that zephyr/.config serves two separate purposes:

要理解为什么 zephyr/. config 仍然包含对隐藏符号的赋值,可以认识到 zephyr/. config 有两个不同的用途:

  1. It holds the saved configuration, and


  2. it holds configuration output. zephyr/.config is parsed by the CMake files to let them query configuration settings, for example.

    它保存配置输出. zephyr/. config 由 CMake 文件解析,让它们查询配置设置,例如。

The assignments to hidden symbols in zephyr/.config are just configuration output. Kconfig itself ignores assignments to hidden symbols when calculating symbol values.




A minimal configuration, which can be generated from within the menuconfig and guiconfig interfaces, could be considered closer to just a saved configuration, without the full configuration output.

可以认为,可以从 menuconfig 和 guiconfig 接口中生成的最小配置更接近于保存的配置,而不需要完整的配置输出。

depends on and string/int/hex symbols取决于和字符串/int/十六进制符号

depends on works not just for bool symbols, but also for string, int, and hex symbols (and for choices).

depends on不仅适用于bool符号,还适用于string, int和hex符号(以及选项)。

The Kconfig definitions below will hide the FOO_DEVICE_FREQUENCY symbol and disable any configuration output for it when FOO_DEVICE is disabled.

下面的 Kconfig 定义将隐藏 FOO_DEVICE_FREQUENCY 符号,并在禁用 FOO_DEVICE 时禁用该符号的任何配置输出。

     bool "Foo device"

     int "Foo device frequency"
     depends on FOO_DEVICE

In general, it’s a good idea to check that only relevant symbols are ever shown in the menuconfig/guiconfig interface. Having FOO_DEVICE_FREQUENCY show up when FOO_DEVICE is disabled (and possibly hidden) makes the relationship between the symbols harder to understand, even if code never looks at FOO_DEVICE_FREQUENCY when FOO_DEVICE is disabled.

通常,检查 menuconfig/guiconfig 界面中是否只显示相关符号是一个好主意。当 FOO_DEVICE 被禁用(可能隐藏)时,FOO_DEVICE_FREQUENCY 的出现使得符号之间的关系更加难以理解,即使当 FOO_DEVICE 被禁用时代码从不查看 FOO_DEVICE_FREQUENCY

If the definition of a symbol FOO is immediately followed by other symbols that depend on FOO, then those symbols become children of FOO. If FOO is defined with config FOO, then the children are shown indented relative to FOO. Defining FOO with menuconfig FOO instead puts the children in a separate menu rooted at FOO.

如果一个符号FOO的定义紧跟着其他依赖于 FOO 的符号,那么这些符号就会成为FOO的子符号。如果FOO是用config FOO 定义的,那么子元素相对于FOO显示缩进。用menuconfig FOO定义FOO会把子菜单放在一个独立的以FOO为根的菜单中。

menuconfig has no effect on evaluation. It’s just a display option.

Menuconfig 对计算没有影响,它只是一个显示选项。

menuconfig can cut down on the number of menus and make the menu structure easier to navigate. For example, say you have the following definitions:

menuconfig 可以减少菜单的数量,使菜单结构更容易导航。例如,假设您有以下定义:

menu "Foo subsystem"

     bool "Foo subsystem"


config FOO_FEATURE_1
     bool "Foo feature 1"

config FOO_FEATURE_2
     bool "Foo feature 2"

     int "Foo frequency"

... lots of other FOO-related symbols



In this case, it’s probably better to get rid of the menu and turn FOO_SUBSYSTEM into a menuconfig symbol:

在这种情况下,最好去掉菜单,将 FOO_SUBSYSTEM 转换为 menuconfig 符号:

menuconfig FOO_SUBSYSTEM
     bool "Foo subsystem"


config FOO_FEATURE_1
     bool "Foo feature 1"

config FOO_FEATURE_2
     bool "Foo feature 2"

     int "Foo frequency"

... lots of other FOO-related symbols


In the menuconfig interface, this will be displayed as follows:

在 menuconfig 界面中,这将显示如下:

[*] Foo subsystem  --->

Note that making a symbol without children a menuconfig is meaningless. It should be avoided, because it looks identical to a symbol with all children invisible:


[*] I have no children  ----
[*] All my children are invisible  ----

Checking changes in menuconfig/guiconfig 检查 menuconfig/guiconfig 中的更改

When adding new symbols or making other changes to Kconfig files, it is a good idea to look up the symbols in menuconfig or guiconfig afterwards. To get to a symbol quickly, use the jump-to feature (press /).


Here are some things to check:


  • Are the symbols placed in a good spot? Check that they appear in a menu where they make sense, close to related symbols.


    If one symbol depends on another, then it’s often a good idea to place it right after the symbol it depends on. It will then be shown indented relative to the symbol it depends on in the menuconfig interface, and in a separate menu rooted at the symbol in guiconfig. This also works if several symbols are placed after the symbol they depend on.

    如果一个符号依赖于另一个符号,那么把它放在它所依赖的符号之后通常是一个好主意。然后,它将在 menuconfig 界面中显示相对于它所依赖的符号的缩进,并在根植于 guiconfig 中的符号的单独菜单中显示。如果将多个符号放在它们所依赖的符号之后,也可以这样做。

  • Is it easy to guess what the symbols do from their prompts?


  • If many symbols are added, do all combinations of values they can be set to make sense?


    For example, if two symbols FOO_SUPPORT and NO_FOO_SUPPORT are added, and both can be enabled at the same time, then that makes a nonsensical configuration. In this case, it’s probably better to have a single FOO_SUPPORT symbol.


  • Are there any duplicated dependencies?


    This can be checked by selecting a symbol and pressing ? to view the symbol information. If there are duplicated dependencies, then use the Included via ... path shown in the symbol information to figure out where they come from.

    这可以通过选择一个符号并按?查看符号信息。如果有重复的依赖,那么使用include via…在符号信息中显示的路径可以找出它们来自哪里。

Checking changes with scripts/kconfig/lint.py使用脚本/kconfig/lint.py 检查更改

After you make Kconfig changes, you can use the scripts/kconfig/lint.py script to check for some potential issues, like unused symbols and symbols that are impossible to enable. Use --help to see available options.

更改 Kconfig 之后,可以使用 scripts/kconfig/lint.py检查一些潜在的问题,比如无法启用的未使用的符号和符号。使用–help 查看可用选项。

Some checks are necessarily a bit heuristic, so a symbol being flagged by a check does not necessarily mean there’s a problem. If a check returns a false positive e.g. due to token pasting in C (CONFIG_FOO_##index##_BAR), just ignore it.

有些检查必然带有一点启发性,因此检查标记的符号并不一定意味着存在问题。如果检查返回一个假阳性,例如由于 C (CONFIG_FOO_##index##_BAR)中的token粘贴,那么忽略它。

When investigating an unknown symbol FOO_BAR, it is a good idea to run git grep FOO_BAR to look for references. It is also a good idea to search for some components of the symbol name with e.g. git grep FOO and git grep BAR, as it can help uncover token pasting.

当研究一个未知的符号FOO_BAR时,运行git grep FOO_BAR来查找引用是一个好主意。用git grep FOO和git grep BAR来搜索符号名的一些组件也是一个好主意,因为它可以帮助发现标记粘贴。

Style recommendations and shorthands 风格推荐和速记

This section gives some style recommendations and explains some common Kconfig shorthands.

本节提供一些样式建议,并解释一些常见的 Kconfig 简写。

Factoring out common dependencies 分解出公共依赖项

If a sequence of symbols/choices share a common dependency, the dependency can be factored out with an if.

如果一系列符号/选项共享一个共同的依赖项,那么可以使用一个 If 来分解这个依赖项。

As an example, consider the following code:


config FOO
     bool "Foo"
     depends on DEP

config BAR
     bool "Bar"
     depends on DEP

     prompt "Choice"
     depends on DEP

config BAZ
     bool "Baz"

config QAZ
     bool "Qaz"


Here, the DEP dependency can be factored out like this:

在这里,DEP 依赖性可以像下面这样分解:

if DEP

config FOO
     bool "Foo"

config BAR
     bool "Bar"

     prompt "Choice"

config BAZ
     bool "Baz"

config QAZ
     bool "Qaz"


endif # DEP



Internally, the second version of the code is transformed into the first.


If a sequence of symbols/choices with shared dependencies are all in the same menu, the dependency can be put on the menu itself:


menu "Foo features"
     depends on FOO_SUPPORT

config FOO_FEATURE_1
     bool "Foo feature 1"

config FOO_FEATURE_2
     bool "Foo feature 2"


If FOO_SUPPORT is n, the entire menu disappears.

如果 FOO _ SUPPORT 为 n,则整个菜单将消失。

Redundant defaults 多余的默认值

bool symbols implicitly default to n, and string symbols implicitly default to the empty string. Therefore, default n and default "" are (almost) always redundant.

Bool 符号隐式默认为 n,字符串符号隐式默认为空字符串。因此,默认 n 和默认“”(几乎)总是多余的。

The recommended style in Zephyr is to skip redundant defaults for bool and string symbols. That also generates clearer documentation: (Implicitly defaults to n instead of n if <dependencies, possibly inherited>).

在Zephyr中,推荐的风格是跳过 bool 和字符串符号的冗余默认值。这也会产生更清晰的文档: (隐式默认为n而不是 <dependencies, prossible inherited>)。


The one case where default n/default "" is not redundant is when defining a symbol in multiple locations and wanting to override e.g. a default y on a later definition.

default n/default“”不是多余的情况是,在多个位置定义一个符号并想覆盖,例如在后面的定义中覆盖默认值 y。

Defaults should always be given for int and hex symbols, however, as they implicitly default to the empty string. This is partly for compatibility with the C Kconfig tools, though an implicit 0 default might be less likely to be what was intended compared to other symbol types as well.

但是,应该始终为 int 和hex符号提供默认值,因为它们隐式默认为空字符串。这在一定程度上是为了与 C Kconfig 工具兼容,尽管与其他符号类型相比,隐式的0默认值不太可能是我们想要的。

Common Kconfig shorthands 常用 Kconfig 简写

Kconfig has two shorthands that deal with prompts and defaults.

Kconfig 有两个处理提示和缺省值的简写。

  • <type> "prompt" is a shorthand for giving a symbol/choice a type and a prompt at the same time. These two definitions are equal:

    <type> “prompt”是同时给一个符号/选择一个类型和一个命令行的简写。这两个定义是相等的:

    config FOO
       bool "foo"
    config FOO
       prompt "foo"

    The first style, with the shorthand, is preferred in Zephyr.

    第一种风格,用速记法,在 Zephyr更受欢迎。

  • def_<type> <value> is a shorthand for giving a type and a value at the same time. These two definitions are equal:

    def_<type> <value> 是同时给出类型和值的简写。这两个定义是相等的:

    config FOO
       def_bool BAR && BAZ
    config FOO
       default BAR && BAZ

Using both the <type> "prompt" and the def_<type> <value> shorthand in the same definition is redundant, since it gives the type twice.

在同一个定义中同时使用<type> "prompt"def_<type> <value> 速记是多余的,因为它给出了两次类型。

The def_<type> <value> shorthand is generally only useful for symbols without prompts, and somewhat obscure.

def_<type> <value> 速记通常只对没有提示符的符号有用,而且有些模糊。


For a symbol defined in multiple locations (e.g., in a Kconfig.defconfig file in Zephyr), it is best to only give the symbol type for the “base” definition of the symbol, and to use default (instead of def_<type> value) for the remaining definitions. That way, if the base definition of the symbol is removed, the symbol ends up without a type, which generates a warning that points to the other definitions. That makes the extra definitions easier to discover and remove.

对于在多个位置定义的符号(例如,在 Zephyr 中的 Kconfig.defconfig 文件中) ,最好只为该符号的“基本”定义提供符号类型,并对其余定义使用 default (而不是def_ value)。这样,如果删除了该符号的基本定义,则该符号最终将没有类型,该类型将生成指向其他定义的警告。这使得额外的定义更容易发现和删除。

Prompt strings 提示字符串

For a Kconfig symbol that enables a driver/subsystem FOO, consider having just “Foo” as the prompt, instead of “Enable Foo support” or the like. It will usually be clear in the context of an option that can be toggled on/off, and makes things consistent.

对于启用驱动程序/子系统 FOO 的 Kconfig 符号,可以考虑只使用“ FOO”作为提示,而不是“ Enable FOO support”或类似的命令。它通常在一个选项的上下文中是清晰的,这个选项可以打开/关闭,并使事情一致。

Header comments and other nits 标题注释和其他细节

A few formatting nits, to help keep things consistent:


  • Use this format for any header comments at the top of Kconfig files:

    对于 Kconfig 文件顶部的任何头注释,请使用此格式:

    # <Overview of symbols defined in the file, preferably in plain English>
    (Blank line)
    # Copyright (c) 2019 ...
    # SPDX-License-Identifier: <License>
    (Blank line)
    (Kconfig definitions)
  • Format comments as # Comment rather than #Comment

    将评论格式设置为 # Comment 而不是 #Comment

  • Put a blank line before/after each top-level if and endif

    在每个顶级 if 和 endf 之前/之后放一个空行

  • Use a single tab for each indentation


  • Indent help text with two extra spaces


Lesser-known/used Kconfig features 鲜为人知/使用的 Kconfig 特性

This section lists some more obscure Kconfig behaviors and features that might still come in handy.

本节列出了一些更加晦涩的 Kconfig 行为和特性,它们可能仍然派得上用场。

The imply statement暗示性陈述

The imply statement is similar to select, but respects dependencies and doesn’t force a value. For example, the following code could be used to enable USB keyboard support by default on the FOO SoC, while still allowing the user to turn it off:

暗示语句与 select 类似,但是尊重依赖关系,并且不强制使用值。例如,下面的代码可以用来在 FOO SoC 上默认启用 USB 键盘支持,同时仍然允许用户关闭它:

config SOC_FOO
     bool "FOO SoC"
     imply USB_KEYBOARD


     bool "USB keyboard support"

imply acts like a suggestion, whereas select forces a value.


Optional prompts 可选提示

A condition can be put on a symbol’s prompt to make it optionally configurable by the user. For example, a value MASK that’s hardcoded to 0xFF on some boards and configurable on others could be expressed as follows:

可以在符号提示符上放置一个条件,使用户可以选择配置该条件。例如,一个在某些板上硬编码为0xFF 并在其他板上可配置的值 MASK 可以表示如下:

config MASK
     hex "Bitmask" if HAS_CONFIGURABLE_MASK
     default 0xFF


This is short for the following:


config MASK
  prompt "Bitmask" if HAS_CONFIGURABLE_MASK
  default 0xFF

The HAS_CONFIGURABLE_MASK helper symbol would get selected by boards to indicate that MASK is configurable. When MASK is configurable, it will also default to 0xFF.

HAS_CONFIGURABLE_MASK 辅助符号将由主板选择,以指示 MASK 是可配置的。当 MASK 可配置时,它也将默认为0xFF。

Optional choices 可供选择

Defining a choice with the optional keyword allows the whole choice to be toggled off to select none of the symbols:


     prompt "Use legacy protocol"

     bool "Legacy protocol 1"

     bool "Legacy protocol 2"


In the menuconfig interface, this will be displayed e.g. as [*] Use legacy protocol (Legacy protocol 1) --->, where the choice can be toggled off to enable neither of the symbols.

在 menuconfig 接口中,这将显示为[*] Use legacy protocol (Legacy protocol 1) —>,其中可以关闭选项以不启用任何一个符号。

visible if conditions可见,如果条件

Putting a visible if condition on a menu hides the menu and all the symbols within it, while still allowing symbol default values to kick in.

在菜单上放置一个可见的 if 条件可以隐藏菜单及其中的所有符号,同时仍然允许符号默认值生效。

As a motivating example, consider the following code:


menu "Foo subsystem"
     depends on HAS_CONFIGURABLE_FOO

config FOO_SETTING_1
     int "Foo setting 1"
     default 1

config FOO_SETTING_2
     int "Foo setting 2"
     default 2


When HAS_CONFIGURABLE_FOO is n, no configuration output is generated for FOO_SETTING_1 and FOO_SETTING_2, as the code above is logically equivalent to the following code:

当 HAS_CONFIGURABLE_FOO 为 n 时,不会为 FOO_SETTING_1和 FOO_SETTING_2生成任何配置输出,因为上面的代码在逻辑上等价于下面的代码:

config FOO_SETTING_1
     int "Foo setting 1"
     default 1
     depends on HAS_CONFIGURABLE_FOO

config FOO_SETTING_2
     int "Foo setting 2"
     default 2
     depends on HAS_CONFIGURABLE_FOO

If we want the symbols to still get their default values even when HAS_CONFIGURABLE_FOO is n, but not be configurable by the user, then we can use visible if instead:

如果我们希望这些符号仍然获得它们的默认值,即使 HAS_CONFIGURABLE_FOO 是 n,但是用户不能配置它们,那么我们可以使用可见的 If:

menu "Foo subsystem"
     visible if HAS_CONFIGURABLE_FOO

config FOO_SETTING_1
     int "Foo setting 1"
     default 1

config FOO_SETTING_2
     int "Foo setting 2"
     default 2


This is logically equivalent to the following:


config FOO_SETTING_1
     int "Foo setting 1" if HAS_CONFIGURABLE_FOO
     default 1

config FOO_SETTING_2
     int "Foo setting 2" if HAS_CONFIGURABLE_FOO
     default 2


See the optional prompts section for the meaning of the conditions on the prompts.


When HAS_CONFIGURABLE is n, we now get the following configuration output for the symbols, instead of no output:

当 HAS_CONFIGURABLE 为 n 时,我们现在得到符号的以下配置输出,而不是没有输出:


Other resources 其他资源

The Intro to symbol values section in the Kconfiglib docstring goes over how symbols values are calculated in more detail.

Kconfiglib 文档字符串中的符号值入门部分将详细介绍如何计算符号值。

Custom Kconfig Preprocessor Functions 自定义 Kconfig 预处理器函数

Kconfiglib supports custom Kconfig preprocessor functions written in Python. These functions are defined in scripts/kconfig/kconfigfunctions.py.

Kconfiglib 支持用 Python 编写的自定义 Kconfig 预处理器函数,这些函数在scripts/kconfig/kconfigfunctions.py 中定义。



The official Kconfig preprocessor documentation can be found here.

官方的 Kconfig 预处理器文档可以在这里找到。

Most of the custom preprocessor functions are used to get devicetree information into Kconfig. For example, the default value of a Kconfig symbol can be fetched from a devicetree reg property.

大多数自定义预处理器功能都用于将设备树信息导入 Kconfig。例如,可以从设备树 reg 属性获取 Kconfig 符号的默认值。

The functions listed below are used to get devicetree information into Kconfig. See the Python docstrings in scripts/kconfig/kconfigfunctions.py for detailed documentation.

下面列出的函数用于将设备树信息导入 Kconfig。有关详细文档,请参阅 script/kconfig/ kconfigfunctions.py 中的 Python docstring。

The *_int version of each function returns the value as a decimal integer, while the *_hex version returns a hexadecimal value starting with 0x.

每个函数的 * _ int 版本返回十进制整数值,而 * _ hex 版本返回以0x 开头的十六进制值。

$(dt_has_compat,<compatible string>)
$(dt_compat_enabled,<compatible string>)
$(dt_compat_on_bus,<compatible string>,<bus>)
$(dt_chosen_label,<property in /chosen>)
$(dt_chosen_enabled,<property in /chosen>)
$(dt_chosen_path,<property in /chosen>)
$(dt_chosen_has_compat,<property in /chosen>)
$(dt_path_enabled,<node path>)
$(dt_alias_enabled,<node alias>)
$(dt_nodelabel_enabled,<node label>)
$(dt_nodelabel_enabled_with_compat,<node label>,<compatible string>)
$(dt_chosen_reg_addr_int,<property in /chosen>[,<index>,<unit>])
$(dt_chosen_reg_addr_hex,<property in /chosen>[,<index>,<unit>])
$(dt_chosen_reg_size_int,<property in /chosen>[,<index>,<unit>])
$(dt_chosen_reg_size_hex,<property in /chosen>[,<index>,<unit>])
$(dt_node_reg_addr_int,<node path>[,<index>,<unit>])
$(dt_node_reg_addr_hex,<node path>[,<index>,<unit>])
$(dt_node_reg_size_int,<node path>[,<index>,<unit>])
$(dt_node_reg_size_hex,<node path>[,<index>,<unit>])
$(dt_compat_enabled,<compatible string>)
$(dt_chosen_enabled,<property in /chosen>)
$(dt_node_bool_prop,<node path>,<prop>)
$(dt_nodelabel_bool_prop,<node label>,<prop>)
$(dt_node_has_prop,<node path>,<prop>)
$(dt_nodelabel_has_prop,<node label>,<prop>)
$(dt_node_int_prop_int,<node path>,<prop>[,<unit>])
$(dt_node_int_prop_hex,<node path>,<prop>[,<unit>])
$(dt_node_str_prop_equals,<node path>,<prop>,<value>)
$(dt_nodelabel_has_compat,<node label>,<compatible string>)
$(dt_nodelabel_path,<node label>)
$(shields_list_contains,<shield name>)

Example Usage 示例用法

Assume that the devicetree for some board looks like this:


     soc {
             #address-cells = <1>;
             #size-cells = <1>;

             spi0: spi@10014000 {
                     compatible = "sifive,spi0";
                     reg = <0x10014000 0x1000 0x20010000 0x3c0900>;
                     reg-names = "control", "mem";

The second entry in reg in spi@1001400 (<0x20010000 0x3c0900>) corresponds to mem, and has the address 0x20010000. This address can be inserted into Kconfig as follows:

Spi@1001400(< 0x200100000x3c0900 >)中 reg 中的第二个条目对应于 mem,并且具有地址0x20010000。这个地址可以插入到 Kconfig 中,如下所示:

     default $(dt_node_reg_addr_hex,/soc/spi@1001400,1)

After preprocessor expansion, this turns into the definition below:


     default 0x20010000

Kconfig extensions Kconfig 扩展

Zephyr uses the Kconfiglib implementation of Kconfig, which includes some Kconfig extensions:

Zephyr 使用 Kconfig 的 Kconfiglib 实现,其中包括一些 Kconfig 扩展:

  • Environment variables in source statements are expanded directly, meaning no “bounce” symbols with option env="ENV_VAR" need to be defined.

    source 语句中的环境变量是直接展开的,这意味着不需要定义 option env="ENV_VAR" 的“反弹”符号。



    option env has been removed from the C tools as of Linux 4.18 as well.

    从 Linux 4.18开始,也从 C 工具中删除了 env 选项。

    The recommended syntax for referencing environment variables is $(FOO) rather than $FOO. This uses the new Kconfig preprocessor. The $FOO syntax for expanding environment variables is only supported for backwards compatibility.

    引用环境变量的推荐语法是 $(FOO)而不是 $FOO。这将使用新的 Kconfig 预处理器。扩展环境变量的 $FOO 语法只支持向后兼容性。

  • The source statement supports glob patterns and includes each matching file. A pattern is required to match at least one file.

    Source 语句支持 globb 模式,并包含每个匹配的文件。至少需要一个模式来匹配一个文件。

    Consider the following example:


    source "foo/bar/*/Kconfig"

    If the pattern foo/bar/*/Kconfig matches the files foo/bar/baz/Kconfig and foo/bar/qaz/Kconfig, the statement above is equivalent to the following two source statements:

    如果模式 foo/bar/*/Kconfig 匹配 foo/bar/baz/Kconfig 和 foo/bar/qaz/Kconfig 文件,则上面的语句等效于以下两个源语句:

    source "foo/bar/baz/Kconfig"
    source "foo/bar/qaz/Kconfig"

    If no files match the pattern, an error is generated.


    The wildcard patterns accepted are the same as for the Python glob module.

    接受的通配符模式与 Python globb 模块相同。

    For cases where it’s okay for a pattern to match no files (or for a plain filename to not exist), a separate osource (optional source) statement is available. osource is a no-op if no file matches.

    对于模式不匹配任何文件(或纯文件名不存在)的情况,可以使用单独的 osource (可选源)语句。如果没有匹配的文件,则osource为 no-op。



    source and osource are analogous to include and -include in Make.

    Source 和 osource 类似于 Make 中的 include 和-include。

  • An rsource statement is available for including files specified with a relative path. The path is relative to the directory of the Kconfig file that contains the rsource statement.

    可以使用 rsource 语句来包含用相对路径指定的文件。该路径相对于包含 rsource 语句的 Kconfig 文件的目录。

    As an example, assume that foo/Kconfig is the top-level Kconfig file, and that foo/bar/Kconfig has the following statements:

    例如,假设 foo/Kconfig 是顶级 Kconfig 文件,并且 foo/bar/Kconfig 具有以下语句:

    source "qaz/Kconfig1"
    rsource "qaz/Kconfig2"

    This will include the two files foo/qaz/Kconfig1 and foo/bar/qaz/Kconfig2.

    这将包括两个文件 foo/qaz/Kconfig1和 foo/bar/qaz/Kconfig2。

    rsource can be used to create Kconfig “subtrees” that can be moved around freely.

    可以使用 rsource 创建可以自由移动的 Kconfig“子树”。

    rsource also supports glob patterns.

    rsource 还支持 glob 模式。

    A drawback of rsource is that it can make it harder to figure out where a file gets included, so only use it if you need it.

    rsource 的一个缺点是,它可能使得找出文件包含在哪里变得更加困难,所以只有在需要的时候才使用它。

  • An orsource statement is available that combines osource and rsource.

    可以使用结合了orsource和rsource的 orsource 语句。

    For example, the following statement will include Kconfig1 and Kconfig2 from the current directory (if they exist):

    例如,下面的语句将包括来自工作目录的 kconfig1和 Kconfig2(如果存在的话) :

    orsource "Kconfig[12]"
  • def_int, def_hex, and def_string keywords are available, analogous to def_bool. These set the type and add a default at the same time.

    def_int、 def_hex 和 def_string 关键字是可用的,类似于 def_bool。它们可以同时设置类型和添加默认值。