GNU/Linux - Kconfig Language - 2

Kconfig syntax

配置文件描述了一系列菜单条目,每一行都以一个关键字开头(帮助文本除外)。以下关键字可结束一个菜单条目:

The configuration file describes a series of menu entries, where every line starts with a keyword (except help texts). The following keywords end a menu entry:

* config

* menuconfig

* choice/endchoice

* comment

* menu/endmenu

* if/endif

* source

前五个也是菜单项定义的开始。

The first five also start the definition of a menu entry.

config:

"config" <symbol>

<config options>

它定义了一个配置符号 <symbol>,并接受上述任何属性作为选项。

This defines a config symbol <symbol> and accepts any of above attributes as options.

menuconfig:

"menuconfig" <symbol>

<config options>

这与上面的简单配置条目类似,但也给前端一个提示,即所有子选项都应显示为单独的选项列表。为确保所有子选项都显示在 menuconfig 条目之下而不是之外,<config options> 列表中的每个项目都必须依赖于 menuconfig 符号。在实践中,可以使用以下两种结构之一来实现这一目标:

This is similar to the simple config entry above, but it also gives a hint to front ends, that all suboptions should be displayed as a separate list of options. To make sure all the suboptions will really show up under the menuconfig entry and not outside of it, every item from the <config options> list must depend on the menuconfig symbol. In practice, this is achieved by using one of the next two constructs:

(1):

menuconfig M

if M

config C1

config C2

endif

(2):

menuconfig M

config C1

depends on M

config C2

depends on M

在下面的示例 (3) 和 (4) 中,C1 和 C2 仍然与 M 有关,但由于 C0 与 M 无关,因此不会再出现在 menuconfig M 中:

In the following examples (3) and (4), C1 and C2 still have the M dependency, but will not appear under menuconfig M anymore, because of C0, which doesn't depend on M:

(3):

menuconfig M

config C0

if M

config C1

config C2

endif

(4):

menuconfig M

config C0

config C1

depends on M

config C2

depends on M

choices:

"choice"

<choice options>

<choice block>

"endchoice"

这将定义一个选择组,并接受上述任何属性作为选项。

选择组只允许选择一个配置项。

This defines a choice group and accepts any of the above attributes as options.

A choice only allows a single config entry to be selected.

comment:

"comment" <prompt>

<comment options>

这将定义一个注释,在配置过程中显示给用户,并在输出文件中显示。唯一可能的选项是依赖关系。

This defines a comment which is displayed to the user during the configuration process and is also echoed to the output files. The only possible options are dependencies.

menu:

"menu" <prompt>

<menu options>

<menu block>

"endmenu"

这将定义一个菜单块,更多信息请参阅上文 "菜单结构"。唯一可能的选项是依赖关系和 "可见 "属性。

This defines a menu block, see "Menu structure" above for more information. The only possible options are dependencies and "visible" attributes.

if:

"if" <expr>

<if block>

"endif"

这定义了一个 if 块。依赖表达式 <expr> 将附加到所有被括入的菜单项中。

This defines an if block. The dependency expression <expr> is appended to all enclosed menu entries.

source:

"source" <prompt>

读取指定的配置文件。该文件始终会被解析。

This reads the specified configuration file. This file is always parsed.

mainmenu:

"mainmenu" <prompt>

如果配置程序选择使用标题栏,则设置配置程序的标题栏。它应放在配置文件的顶部,任何其他语句之前。

This sets the config program's title bar if the config program chooses to use it. It should be placed at the top of the configuration, before any other statement.

'#' Kconfig source file comment:

源文件行中任何未加引号的 "#"字符表示源文件注释的开始。该行的其余部分为注释。

An unquoted '#' character anywhere in a source file line indicates the beginning of a source file comment. The remainder of that line is a comment.

Kconfig hints

这是 Kconfig 提示集,其中大部分提示乍一看并不明显,但在多个 Kconfig 文件中已成为习惯用语。

This is a collection of Kconfig tips, most of which aren't obvious at first glance and most of which have become idioms in several Kconfig files.

Adding common features and make the usage configurable

实现与某些架构而非所有架构相关的特性/功能是一种常见的习惯做法。推荐的方法是使用名为 HAVE_* 的配置变量,该变量在通用 Kconfig 文件中定义,并由相关架构选择。通用 IOMAP 功能就是一个例子。

It is a common idiom to implement a feature/functionality that are relevant for some architectures but not all. The recommended way to do so is to use a config variable named HAVE_* that is defined in a common Kconfig file and selected by the relevant architectures. An example is the generic IOMAP functionality.

We would in lib/Kconfig see:

Generic IOMAP is used to ...

config HAVE_GENERIC_IOMAP

config GENERIC_IOMAP

depends on HAVE_GENERIC_IOMAP && FOO

And in lib/Makefile we would see:

obj-$(CONFIG_GENERIC_IOMAP) += iomap.o

对于使用 IOMAP 通用功能的每个架构,我们可以看到:

For each architecture using the generic IOMAP functionality we would see:

config X86

select ...

select HAVE_GENERIC_IOMAP

select ...

注意:我们使用现有的配置选项,避免创建新的配置变量来选择 HAVE_GENERIC_IOMAP。

Note: we use the existing config option and avoid creating a new config variable to select HAVE_GENERIC_IOMAP.

注意:使用内部配置变量 HAVE_GENERIC_IOMAP,是为了克服 select 的限制,即无论依赖关系如何,它都会强制配置选项为 "y"。我们将依赖关系移至 GENERIC_IOMAP 符号中,从而避免了选择时强制符号等于 "y "的情况。

Note: the use of the internal config variable HAVE_GENERIC_IOMAP, it is introduced to overcome the limitation of select which will force a config option to 'y' no matter the dependencies. The dependencies are moved to the symbol GENERIC_IOMAP and we avoid the situation where select forces a symbol equals to 'y'.

Adding features that need compiler support

有几项功能需要编译器的支持。描述对编译器功能的依赖性时,建议使用 "依赖于"(depend on),后面跟一个测试宏:

There are several features that need compiler support. The recommended way to describe the dependency on the compiler feature is to use "depends on" followed by a test macro:

config STACKPROTECTOR

bool "Stack Protector buffer overflow detection"

depends on $(cc-option,-fstack-protector)

...

如果需要在 makefile 和/或 C 源文件中公开编译器功能,建议使用 CC_HAS_ 作为配置选项的前缀:

If you need to expose a compiler capability to makefiles and/or C source files, CC_HAS_ is the recommended prefix for the config option:

config CC_HAS_FOO

def_bool (success,(srctree)/scripts/cc-check-foo.sh $(CC))

Build as module only

要限制组件的构建仅限于模块,可使用 "依赖于 m "来限定其配置符号。例如

To restrict a component build to module-only, qualify its config symbol with "depends on m". E.g.:

config FOO

depends on BAR && m

limits FOO to module (=m) or disabled (=n).

Compile-testing

如果配置符号有依赖关系,但如果不满足依赖关系,配置符号所控制的代码仍可编译,则鼓励通过在依赖关系中添加"|| COMPILE_TEST "子句来增加编译覆盖率。这对更特殊硬件的驱动程序尤其有用,因为它允许持续集成系统在更常见的系统上编译测试代码,并通过这种方式检测错误。请注意,经过编译测试的代码在不符合依赖关系的系统上运行时应避免崩溃。

If a config symbol has a dependency, but the code controlled by the config symbol can still be compiled if the dependency is not met, it is encouraged to increase build coverage by adding an "|| COMPILE_TEST" clause to the dependency. This is especially useful for drivers for more exotic hardware, as it allows continuous-integration systems to compile-test the code on a more common system, and detect bugs that way. Note that compile-tested code should avoid crashing when run on a system where the dependency is not met.

Architecture and platform dependencies

由于存根的存在,大多数驱动程序现在都可以在大多数体系结构上编译。但是,这并不意味着所有驱动程序都可以随处使用,因为实际硬件可能只存在于特定的架构和平台上。对于 SoC IP 内核来说尤其如此,因为它可能仅限于特定的供应商或 SoC 系列。

Due to the presence of stubs, most drivers can now be compiled on most architectures. However, this does not mean it makes sense to have all drivers available everywhere, as the actual hardware may only exist on specific architectures and platforms. This is especially true for on-SoC IP cores, which may be limited to a specific vendor or SoC family.

为了避免向用户询问无法在用户编译内核的系统上使用的驱动程序,如果合理的话,控制驱动程序编译的配置符号应包含适当的依赖关系,将符号的可见性限制在驱动程序可使用的平台(超集)上。依赖关系可以是架构依赖关系(如 ARM)或平台依赖关系(如 ARCH_OMAP4)。这不仅简化了发行版配置所有者的工作,也简化了每个开发人员或配置内核的用户的工作。

To prevent asking the user about drivers that cannot be used on the system(s) the user is compiling a kernel for, and if it makes sense, config symbols controlling the compilation of a driver should contain proper dependencies, limiting the visibility of the symbol to (a superset of) the platform(s) the driver can be used on. The dependency can be an architecture (e.g. ARM) or platform (e.g. ARCH_OMAP4) dependency. This makes life simpler not only for distro config owners, but also for every single developer or user who configures a kernel.

将这种依赖性与上述编译测试规则结合起来,就可以放宽这种依赖性:

Such a dependency can be relaxed by combining it with the compile-testing rule above, leading to:

config FOO

bool "Support for foo hardware" depends on ARCH_FOO_VENDOR || COMPILE_TEST

Optional dependencies

某些驱动程序可以选择使用另一个模块的功能,或在禁用该模块的情况下顺利构建,但在尝试使用内置驱动程序中的可加载模块时会导致链接失败。

Some drivers are able to optionally use a feature from another module or build cleanly with that module disabled, but cause a link failure when trying to use that loadable module from a built-in driver.

在 Kconfig 逻辑中,表达这种可选依赖关系的最常见方式是使用略微违反直觉的方法:

The most common way to express this optional dependency in Kconfig logic uses the slightly counterintuitive:

config FOO

tristate "Support for foo hardware"

depends on BAR || !BAR

这意味着,要么 BAR 的依赖关系不允许 FOO=y 与 BAR=m 的组合,要么 BAR 被完全禁用。如果有多个驱动程序具有相同的依赖关系,则可以使用辅助符号,例如

This means that there is either a dependency on BAR that disallows the combination of FOO=y with BAR=m, or BAR is completely disabled. For a more formalized approach if there are multiple drivers that have the same dependency, a helper symbol can be used, like:

config FOO

tristate "Support for foo hardware"

depends on BAR_OPTIONAL

config BAR_OPTIONAL

def_tristate BAR || !BAR

Kconfig recursive dependency limitations

如果您遇到 Kconfig 错误: "检测到递归依赖关系"(recursive dependency detected),那么你就遇到了 Kconfig 的递归依赖关系问题,递归依赖关系可以概括为循环依赖关系。kconfig 工具需要确保 Kconfig 文件符合指定的配置要求。为此,kconfig 必须确定所有 Kconfig 符号的可能值,但如果两个或多个 Kconfig 符号之间存在循环关系,目前还无法做到这一点。详情请参阅下面的 "简单 Kconfig 递归问题 "小节。Kconfig 不做递归依赖关系解析;这对 Kconfig 文件编写者有一些影响。我们将首先解释这个问题存在的原因,然后举例说明它给 Kconfig 开发人员带来的技术限制。希望尝试解决这一限制的热心开发者请阅读接下来的小节。

If you've hit the Kconfig error: "recursive dependency detected" you've run into a recursive dependency issue with Kconfig, a recursive dependency can be summarized as a circular dependency. The kconfig tools need to ensure that Kconfig files comply with specified configuration requirements. In order to do that kconfig must determine the values that are possible for all Kconfig symbols, this is currently not possible if there is a circular relation between two or more Kconfig symbols. For more details refer to the "Simple Kconfig recursive issue" subsection below. Kconfig does not do recursive dependency resolution; this has a few implications for Kconfig file writers. We'll first explain why this issues exists and then provide an example technical limitation which this brings upon Kconfig developers. Eager developers wishing to try to address this limitation should read the next subsections.

Simple Kconfig recursive issue

Read: Documentation/kbuild/Kconfig.recursion-issue-01

Test with:

make KBUILD_KCONFIG=Documentation/kbuild/Kconfig.recursion-issue-01 allnoconfig

Cumulative Kconfig recursive issue

Read: Documentation/kbuild/Kconfig.recursion-issue-02

Test with:

make KBUILD_KCONFIG=Documentation/kbuild/Kconfig.recursion-issue-02 allnoconfig

Practical solutions to kconfig recursive issue

Future kconfig work

我们欢迎在澄清语义和评估是否使用完整的 SAT 求解器这两个方面就 kconfig 开展工作。完整的 SAT 求解器可以实现更复杂的依赖关系映射和/或查询,例如,SAT 求解器的一个可能用例就是处理当前已知的递归依赖关系问题。目前还不知道这是否能解决此类问题,但这种评估是可取的。如果对完整 SAT 求解器的支持证明过于复杂或无法解决递归依赖性问题,那么 Kconfig 至少应具有清晰和明确定义的语义,并能解决和记录诸如处理递归依赖性的限制或要求。

我们欢迎 Kconfig 在这两个领域开展进一步的工作。我们将在接下来的两个小节中详细阐述这两方面的问题。

Work on kconfig is welcomed on both areas of clarifying semantics and on evaluating the use of a full SAT solver for it. A full SAT solver can be desirable to enable more complex dependency mappings and / or queries, for instance one possible use case for a SAT solver could be that of handling the current known recursive dependency issues. It is not known if this would address such issues but such evaluation is desirable. If support for a full SAT solver proves too complex or that it cannot address recursive dependency issues Kconfig should have at least clear and well defined semantics which also addresses and documents limitations or requirements such as the ones dealing with recursive dependencies.

Further work on both of these areas is welcomed on Kconfig. We elaborate on both of these in the next two subsections.

Semantics of Kconfig

Kconfig 的使用范围很广,Linux 现在只是 Kconfig 的用户之一:一项研究完成了对 12 个项目中 Kconfig 使用情况的广泛分析。尽管 Kconfig 被广泛使用,尽管本文档在记录 Kconfig 基本语法方面做得不错,但我们还是欢迎对 Kconfig 语义进行更精确的定义。有一个项目通过使用 xconfig 配置器推导出了 Kconfig 语义。我们应努力确认推导出的语义是否与我们预期的 Kconfig 设计目标相匹配。另一个项目将 Kconfig 语言核心子集的指称语义形式化。

The use of Kconfig is broad, Linux is now only one of Kconfig's users: one study has completed a broad analysis of Kconfig use in 12 projects. Despite its widespread use, and although this document does a reasonable job in documenting basic Kconfig syntax a more precise definition of Kconfig semantics is welcomed. One project deduced Kconfig semantics through the use of the xconfig configurator 1. Work should be done to confirm if the deduced semantics matches our intended Kconfig design goals. Another project formalized a denotational semantics of a core subset of the Kconfig language.

拥有定义明确的语义对于实际评估依赖关系的工具非常有用,例如,有一项工作就是用布尔抽象表达 Kconfig 的推断语义,将 Kconfig 逻辑转化为布尔公式,并在此基础上运行 SAT 求解器来查找死代码/死特征(始终处于非活动状态),使用这种方法在 Linux 中发现了 114 个死特征。基于 语义的 kismet 工具可发现反向依赖的滥用,并已对 Linux Kconfig 文件进行了数十次修复。

Having well defined semantics can be useful for tools for practical evaluation of dependencies, for instance one such case was work to express in boolean abstraction of the inferred semantics of Kconfig to translate Kconfig logic into boolean formulas and run a SAT solver on this to find dead code / features (always inactive), 114 dead features were found in Linux using this methodology (Section 8: Threats to validity). The kismet tool, based on the semantics, finds abuses of reverse dependencies and has led to dozens of committed fixes to Linux Kconfig files.

由于 Kconfig 是领先的工业可变性建模语言之一,因此证实这一点可能会很有用。对它的研究将有助于评估此类语言的实际使用情况,因为它们的使用只是理论上的,对现实世界的要求并不十分了解。目前,只有逆向工程技术被用于从 Kconfig 等可变性建模语言中推导语义。

Confirming this could prove useful as Kconfig stands as one of the leading industrial variability modeling languages. Its study would help evaluate practical uses of such languages, their use was only theoretical and real world requirements were not well understood. As it stands though only reverse engineering techniques have been used to deduce semantics from variability modeling languages such as Kconfig.

引用:

https://www.eng.uwaterloo.ca/~shshe/kconfig_semantics.pdf

https://gsd.uwaterloo.ca/sites/default/files/vm-2013-berger.pdf

https://gsd.uwaterloo.ca/sites/default/files/ase241-berger_0.pdf

https://gsd.uwaterloo.ca/sites/default/files/icse2011.pdf

Full SAT solver for Kconfig

虽然 SAT 求解器还没有被 Kconfig 直接使用(如上一小节所述),但已经有人在布尔抽象中表达 Kconfig 的推断语义,将 Kconfig 逻辑转换为布尔公式,并在其上运行 SAT 求解器。另一个已知的相关项目是 CADOS(前 VAMOS)及其工具,主要是首先介绍的 undertaker。undertaker 的基本概念是从 Kconfig 中提取可变性模型,并将其与从 CPP #ifdefs 和构建规则中提取的命题式一起放入 SAT 求解器,以查找死代码、死文件和死符号。如果在 Kconfig 上使用 SAT 解算器是可取的,那么一种方法就是评估在 Kconfig 上以某种方式重新利用此类工作的效果。现有项目的指导者对这项工作有足够的兴趣,他们不仅可以为如何将这项工作整合到上游提供建议,还可以帮助长期维护这项工作。感兴趣的开发者请访问:

Although SAT solvers haven't yet been used by Kconfig directly, as noted in the previous subsection, work has been done however to express in boolean abstraction the inferred semantics of Kconfig to translate Kconfig logic into boolean formulas and run a SAT solver on it. Another known related project is CADOS (former VAMOS) and the tools, mainly undertaker, which has been introduced first. The basic concept of undertaker is to extract variability models from Kconfig and put them together with a propositional formula extracted from CPP #ifdefs and build-rules into a SAT solver in order to find dead code, dead files, and dead symbols. If using a SAT solver is desirable on Kconfig one approach would be to evaluate repurposing such efforts somehow on Kconfig. There is enough interest from mentors of existing projects to not only help advise how to integrate this work upstream but also help maintain it long term. Interested developers should visit:

KernelProjects/kconfig-sat - Linux Kernel Newbies

https://www.cs.cornell.edu/~sabhar/chapters/SATSolvers-KR-Handbook.pdf

https://gsd.uwaterloo.ca/sites/default/files/vm-2013-berger.pdf

https://cados.cs.fau.de

https://vamos.cs.fau.de

https://undertaker.cs.fau.de

https://www4.cs.fau.de/Publications/2011/tartler_11_eurosys.pdf

https://paulgazzillo.com/papers/esecfse21.pdf

https://github.com/paulgazz/kmax

参考:

Kconfig Language --- The Linux Kernel documentation

相关推荐
C++忠实粉丝9 分钟前
计算机网络socket编程(3)_UDP网络编程实现简单聊天室
linux·网络·c++·网络协议·计算机网络·udp
量子网络27 分钟前
debian 如何进入root
linux·服务器·debian
我们的五年35 分钟前
【Linux课程学习】:进程描述---PCB(Process Control Block)
linux·运维·c++
我言秋日胜春朝★1 小时前
【Linux】进程地址空间
linux·运维·服务器
C-cat.2 小时前
Linux|环境变量
linux·运维·服务器
yunfanleo2 小时前
docker run m3e 配置网络,自动重启,GPU等 配置渠道要点
linux·运维·docker
糖豆豆今天也要努力鸭2 小时前
torch.__version__的torch版本和conda list的torch版本不一致
linux·pytorch·python·深度学习·conda·torch
烦躁的大鼻嘎3 小时前
【Linux】深入理解GCC/G++编译流程及库文件管理
linux·运维·服务器
ac.char3 小时前
在 Ubuntu 上安装 Yarn 环境
linux·运维·服务器·ubuntu
敲上瘾3 小时前
操作系统的理解
linux·运维·服务器·c++·大模型·操作系统·aigc