kconfiglib庫官方介紹:kconfiglib · PyPI
Kconfiglib原始碼:GitHub - ulfalizer/Kconfiglib: A flexible Python 2/3 Kconfig implementation and library
Kconfig語法:Kconfig Language — The Linux Kernel documentation
其它參考:
【華為雲技術分享】STM32L476移植華為LiteOS系列教學---Kconfig 6 - zhy_learn - 部落格園 (cnblogs.com)
menuconfig 和、Kconfig 介紹及例子解析! (qq.com)
驅動模組(6)_Kconfig語法 - Hello-World3 - 部落格園 (cnblogs.com)
Kconfig語法簡介 - schips - 部落格園 (cnblogs.com)
簡介:Kconfiglib is a Python 2/3 library for scripting and extracting information from Kconfig (https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt) configuration systems.(Kconfiglib是一個從Kconfig設定系統中編寫指令碼提取資訊的庫,Kconfig設定系統是Linux核心提出的一個設定資料庫,關於Kconfig的語法可參考核心檔案)。
幾個概念:
本文除了介紹python Kconfiglib庫之外,還要重點學習Kconfig的語法規則,瞭解了語法就知道如何用menuconfig進行設定項的選擇。以下章節來自官方的介紹說明。
Install the library and the utilities.(安裝庫和相關的工具)
Write Kconfig files that describe the available configuration options. See Kconfig Language — The Linux Kernel documentation for some general Kconfig advice.(編寫Kconfig檔案,用來描述設定選項,可以參考核心的Kconfig語言來學習)
Generate an initial configuration with e.g. menuconfig
/guiconfig
or alldefconfig
. The configuration is saved as .config
by default.(使用menuconfig
/guiconfig
或者alldefconfig
生成一個最初的設定,預設儲存為.config
檔案)
For more advanced projects, the defconfig
utility can be used to generate the initial configuration from an existing configuration file. Usually, this existing configuration file would be a minimal configuration file, as generated by e.g. savedefconfig
.(對於更高階的用法,defconfig
可以從一個已存在的組態檔中生成一個初始化設定,通常已存在的組態檔作為一個最小的組態檔,使用savedefconfig
生成組態檔)
Run genconfig
to generate a header file. By default, it is saved as config.h
.(genconfig
用於生成一個標頭檔案,預設儲存為config.h)
Normally, genconfig
would be run automatically as part of the build.(通常,genconfig
作為build的一部分自動執行)
Before writing a header file or other configuration output, Kconfiglib compares the old contents of the file against the new contents. If there's no change, the write is skipped. This avoids updating file metadata like the modification time, and might save work depending on your build setup.(在輸出一個標頭檔案或其它組態檔之前,會先比較舊的輸出檔案,如果沒有改變,直接跳過不輸出)
Adding new configuration output formats should be relatively straightforward. See the implementation of write_config()
in kconfiglib.py. The documentation for the Symbol.config_string
property has some tips as well.(新增新的設定輸出格式時應該相對簡單,可以檢視write_config
的用法,Symbol.config_string
屬性也有一些提示)
To update an old .config
file after the Kconfig files have changed (e.g. to add new options), run oldconfig
(prompts for values for new options) or olddefconfig
(gives new options their default value). Entering the menuconfig
or guiconfig
interface and saving the configuration will also update it (the configuration interfaces always prompt for saving on exit if it would modify the contents of the .config
file).(當執行oldconfig
或者olddefconfig
時,如果Kconfig檔案改變時,會更新.config
。執行menuconfig
或者guiconfig
時,也會更新.config
)
Due to Kconfig semantics, simply loading an old .config
file performs an implicit olddefconfig
, so building will normally not be affected by having an outdated configuration.
.config
files use Make syntax and can be included directly in Makefiles to read configuration values from there. This is why n
-valued bool
/tristate
values are written out as # CONFIG_FOO is not set
(a Make comment) in .config
, allowing them to be tested with ifdef
in Make.(輸出的.config
檔案使用的是Make語法,可以直接在Makefile中包含這個檔案讀取設定值。bool
/tristate
型別的n
輸出為# CONFIG_FOO is not set
,Makefile中使用 ifdef
方式使用)
.config
檔案一般格式為:
# LOSCFG_DEBUG_KERNEL is not set
LOSCFG_SHELL=y
Makefile中一般的使用方式:
ifeq ($(LOSCFG_SHELL), y)
LITEOS_SHELL_INCLUDE += -I $(LITEOSTOPDIR)/shell/include
endif
If you make use of this, you might want to pass --config-out <filename>
to genconfig
and include the configuration file it generates instead of including .config
directly. This has the advantage that the generated configuration file will always be a "full" configuration file, even if .config
is outdated. Otherwise, it might be necessary to run old(def)config
or menuconfig
/guiconfig
before rebuilding with an outdated .config
.
If you use --sync-deps
to generate incremental build information, you can include deps/auto.conf
instead, which is also a full configuration file.
Kconfiglib can do the following, among other things:(Kconfiglib庫可以完成以下事情)
Programmatically get and set symbol values(以程式設計方式獲取和設定符合值)
See allnoconfig.py and allyesconfig.py, which are automatically verified to produce identical output to the standard make allnoconfig
and make allyesconfig
.
Read and write .config and defconfig files(讀寫.config和deconfig檔案)
The generated .config
and defconfig
(minimal configuration) files are character-for-character identical to what the C implementation would generate (except for the header comment). The test suite relies on this, as it compares the generated files.(通過庫生成的.config
和deconfig
檔案和C語言生成的是一樣的,除了標頭檔案註釋)
Write C headers(寫C標頭檔案)
The generated headers use the same format as include/generated/autoconf.h
from the Linux kernel. Output for symbols appears in the order that they're defined, unlike in the C tools (where the order depends on the hash table implementation).(生成的標頭檔案格式和核心的include/generated/autoconf.h
檔案一樣,輸出的符號按它們的定義順序顯示)
Implement incremental builds(實現增量構建)
This uses the same scheme as the include/config
directory in the kernel: Symbols are translated into files that are touched when the symbol's value changes between builds, which can be used to avoid having to do a full rebuild whenever the configuration is changed.
See the sync_deps()
function for more information.
Inspect symbols
Printing a symbol or other item (which calls __str__()
) returns its definition in Kconfig format. This also works for symbols defined in multiple locations.
A helpful __repr__()
is on all objects too.
All __str__()
and __repr__()
methods are deliberately implemented with just public APIs, so all symbol information can be fetched separately as well.
Inspect expressions
Expressions use a simple tuple-based format that can be processed manually if needed. Expression printing and evaluation functions are provided, implemented with public APIs.
Inspect the menu tree
The underlying menu tree is exposed, including submenus created implicitly from symbols depending on preceding symbols. This can be used e.g. to implement menuconfig-like functionality.
See menuconfig.py/guiconfig.py and the minimalistic menuconfig_example.py example.
Three configuration interfaces are currently available:(有三種設定介面,可以看作是三種不同的設定介面)
menuconfig.py is a terminal-based configuration interface implemented using the standard Python curses
module. xconfig
features like showing invisible symbols and showing symbol names are included, and it's possible to jump directly to a symbol in the menu tree (even if it's currently invisible).(menuconfig.py
是一個基於終端設定介面)
See the docstring at the top of menuconfig.py for more information about the terminal menuconfig implementation.(更多資訊可以檢視menuconfig.py
檔案的頂部的說明)
guiconfig.py is a graphical configuration interface written in Tkinter. Like menuconfig.py
, it supports showing all symbols (with invisible symbols in red) and jumping directly to symbols. Symbol values can also be changed directly from the jump-to dialog.
pymenuconfig, built by RomaVis, is an older portable Python 2/3 TkInter menuconfig implementation.
官網參考:
linux/kconfig-language.rst at master · torvalds/linux · GitHub
Kconfig Language — The Linux Kernel documentation
注:以下出現entry
的地方,可以理解為一個選單項或者一個設定項。
簡介:The configuration database is a collection of configuration options organized in a tree structure:(Kconfig就是以樹形結構來組織設定選項的一個集合)
Every entry has its own dependencies. These dependencies are used to determine the visibility of an entry. Any child entry is only visible if its parent entry is also visible.(每一個設定都有自己的依賴,這些依賴關係確定了一個設定的可見性,任何子設定只有在父設定可見時才可見。)
Most entries define a config option; all other entries help to organize them. A single configuration option is defined like this:(大部分設定項都定義了一個設定選項,其它設定項可用來組織它們,一個簡單的設定選項如下)
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. ...
Every line starts with a key word and can be followed by multiple arguments. 「config」starts a new config entry. The following lines define attributes for this config option. Attributes can be the type of the config option, input prompt, dependencies, help text and default values. A config option can be defined multiple times with the same name, but every definition can have only a single input prompt and the type must not conflict.(每一行都以一個關鍵字開始,後面可以跟多個引數。config
關鍵字表示一個設定項的開始,緊跟著的定義了一些設定項的屬性。可以有以下屬性:設定項型別、輸入提示、依賴關係、幫助資訊、預設值。一個設定項可以使用相同設定名被定義多次,但是每個定義只能有一個輸入提示,並且型別不不能衝突。)
A menu entry can have a number of attributes. Not all of them are applicable everywhere (see syntax).(一個選單項可以有多個屬性,具體使用參考語法)
type definition: bool
/tristate
/string
/hex
/int
(型別定義:布林值/三態/字串/十六進位制/整數)
Every config option must have a type. There are only two basic types: tristate and string; the other types are based on these two. The type definition optionally accepts an input prompt, so these two examples are equivalent:(每一個設定項必須有一種型別。有兩種基礎型別:三態和字串。其他的型別都是基於這兩種型別。型別定義的輸入提示prompt
是可選的,因此下面的兩種定義是等效的)
bool "Networking support"
and:
bool
prompt "Networking support"
三態:3種狀態,對應Y、N、M三種選擇方式,就是這個設定項可以被三種選擇。如果=y則會被編入(built-in)核心,如果=m會被單獨連線成一個」.ko」模組。
input prompt: "prompt" <prompt> ["if" <expr>]
(輸入提示)
Every menu entry can have at most one prompt, which is used to display to the user. Optionally dependencies only for this prompt can be added with "if".(每一個選單項至少有一個輸入提示,用於顯示給使用者,可以通過新增if
判斷來僅提示某一種提示)
default value: "default" <expr> ["if" <expr>]
(預設值)
A config option can have any number of default values. If multiple default values are visible, only the first defined one is active. Default values are not limited to the menu entry where they are defined. This means the default can be defined somewhere else or be overridden by an earlier definition. The default value is only assigned to the config symbol if no other value was set by the user (via the input prompt above). If an input prompt is visible the default value is presented to the user and can be overridden by him. Optionally, dependencies only for this default value can be added with "if".(設定項可以有任意多個預設值,如果有多個預設值,僅保留第一個預設值。預設值不限於在定義它的選單項中定義,也可以在其他地方定義。預設值僅在使用者沒有分配設定值的時候使用,如果輸入可見,預設值就呈現給使用者。)
The default value deliberately defaults to 'n' in order to avoid bloating the build. With few exceptions, new config options should not change this. The intent is for 「make oldconfig」 to add as little as possible to the config from release to release.(為了避免編譯膨脹,預設值預設為'n'。)
Note:
Things that merit 「default y/m」 include:A new Kconfig option for something that used to always be built should be 「default y」.A new gatekeeping Kconfig option that hides/shows other Kconfig options (but does not generate any code of its own), should be 「default y」 so people will see those other options.Sub-driver behavior or similar options for a driver that is 「default n」. This allows you to provide sane defaults.Hardware or infrastructure that everybody expects, such as CONFIG_NET or CONFIG_BLOCK. These are rare exceptions.
type definition + default value:(型別定義+預設值)
"def_bool"/"def_tristate" <expr> ["if" <expr>]
This is a shorthand notation for a type definition plus a value. Optionally dependencies for this default value can be added with "if".(這是型別定義+值的簡寫方式)
dependencies: "depends on" <expr>
(依賴)
This defines a dependency for this menu entry. If multiple dependencies are defined, they are connected with ‘&&’. Dependencies are applied to all other options within this menu entry (which also accept an 「if」 expression), so these two examples are equivalent:(定義選單項的依賴。如果要定義多個依賴,可以使用"&&"連線,依賴應用於當前選單項的所有選項,也可以使用if表示式,下面的兩種定義是等價的)
bool "foo" if BAR
default y if BAR
and:
depends on BAR
bool "foo"
default y
reverse dependencies: "select" <symbol> ["if" <expr>]
(反向依賴)
While normal dependencies reduce the upper limit of a symbol (see below), reverse dependencies can be used to force a lower limit of another symbol. The value of the current menu symbol is used as the minimal value <symbol>
can be set to. If <symbol>
is selected multiple times, the limit is set to the largest selection. Reverse dependencies can only be used with boolean or tristate symbols.(正常的依賴是符號在設定項的上面,反向依賴可以讓符號在設定項的下面。當前選單符號的值被用作符號設定的最小值。如果符號被選擇多次,這個限制是符號被選擇的最大次數。反向依賴只能和布林符號或三態符號使用)
Note:
select should be used with care. select will force a symbol to a value without visiting the dependencies. By abusing select you are able to select a symbol FOO even if FOO depends on BAR that is not set. In general use select only for non-visible symbols (no prompts anywhere) and for symbols with no dependencies. That will limit the usefulness but on the other hand avoid the illegal configurations all over.(反向依賴應該小心使用,反向依賴將強制設定符號沒有可見的依賴項。通常僅對不可見的符號使用反向依賴。)
weak reverse dependencies: "imply" <symbol> ["if" <expr>]
(弱反向依賴)
This is similar to 「select」 as it enforces a lower limit on another symbol except that the "implied"
symbol’s value may still be set to n from a direct dependency or with a visible prompt.(類似於反向依賴,強制另一個符號在它的下面,但是根據一個可見的提示項,符號仍然可能設定為'n')
Given the following example:
config FOO
tristate "foo"
imply BAZ
config BAZ
tristate "baz"
depends on BAR
The following values are possible:
FOO BAR BAZ’s default choice for BAZ n y n N/m/y m y m M/y/n y y y Y/m/n n m n N/m m m m M/n y m m M/n y n N
This is useful e.g. with multiple drivers that want to indicate their ability to hook into a secondary subsystem while allowing the user to configure that subsystem out without also having to unset these drivers.
Note: If the combination of FOO=y and BAR=m causes a link error, you can guard the function call with IS_REACHABLE():
foo_init()
{
if (IS_REACHABLE(CONFIG_BAZ))
baz_register(&foo);
...
}
Note: If the feature provided by BAZ is highly desirable for FOO, FOO should imply not only BAZ, but also its dependency BAR:
config FOO
tristate "foo"
imply BAR
imply BAZ
limiting menu display: "visible if" <expr>
(限制選單顯示)
This attribute is only applicable to menu blocks, if the condition is false, the menu block is not displayed to the user (the symbols contained there can still be selected by other symbols, though). It is similar to a conditional 「prompt」 attribute for individual menu entries. Default value of 「visible」 is true.(這個屬性僅作用於選單塊,如果條件為false,選單塊對使用者不顯示,類似於選單項的prompt
屬性,預設為true)
numerical ranges: "range" <symbol> <symbol> ["if" <expr>]
(數值範圍)
This allows to limit the range of possible input values for int and hex symbols. The user can only input a value which is larger than or equal to the first symbol and smaller than or equal to the second symbol.(對應int和hex型別,可以限制輸入值的範圍,使用者只能輸入範圍內的值)
help text: "help"
(幫助資訊)
This defines a help text. The end of the help text is determined by the indentation level, this means it ends at the first line which has a smaller indentation than the first line of the help text.(定義幫助資訊,幫助資訊由縮排表示一行的結束)
module attribute: "modules"(模組屬性)
This declares the symbol to be used as the MODULES symbol, which enables the third modular state for all config symbols. At most one symbol may have the 「modules」 option set.
Dependencies define the visibility of a menu entry and can also reduce the input range of tristate symbols. The tristate logic used in the expressions uses one more state than normal boolean logic to express the module state. Dependency expressions have the following syntax:(依賴項定義了選單項的可見性,也可以減少三態的輸入範圍。三態的邏輯表示式比布林表示式多了一種模組狀態,依賴的表示式語法如下)
<expr> ::= <symbol> (1)
<symbol> '=' <symbol> (2)
<symbol> '!=' <symbol> (3)
<symbol1> '<' <symbol2> (4)
<symbol1> '>' <symbol2> (4)
<symbol1> '<=' <symbol2> (4)
<symbol1> '>=' <symbol2> (4)
'(' <expr> ')' (5)
'!' <expr> (6)
<expr> '&&' <expr> (7)
<expr> '||' <expr> (8)
Expressions are listed in decreasing order of precedence.
<symbol1>
is respectively lower, greater, lower-or-equal, or greater-or-equal than value of <symbol1>
小於等於<symbol2>
,返回'y',否則為'n')An expression can have a value of ‘n’, ‘m’ or ‘y’ (or 0, 1, 2 respectively for calculations). A menu entry becomes visible when its expression evaluates to ‘m’ or ‘y’.(一個表示式的值可以為'n'/'m'/'y',或者0/1/2用於計算,當表示式的結果為'm'/'y',選單項才可見)
There are two types of symbols: constant and non-constant symbols. Non-constant symbols are the most common ones and are defined with the ‘config’ statement. Non-constant symbols consist entirely of alphanumeric characters or underscores. Constant symbols are only part of expressions. Constant symbols are always surrounded by single or double quotes. Within the quote, any other character is allowed and the quotes can be escaped using ''.(有兩種型別符號:常數和非常數符號,非常數符號比較常見,非常數符號完全由字母和下劃線組成,常數符號只是表示式的一部分,常數符號通常使用雙引號或單引號括起來。)
menu條目用於生成選單。
The position of a menu entry in the tree is determined in two ways. First it can be specified explicitly:(選單項的位置有兩種方式,第一種可以顯示的指定。)
menu "Network device support"
depends on NET
config NETDEVICES
...
endmenu
All entries within the 「menu」 … 「endmenu」
block become a submenu of 「Network device support」. All subentries inherit the dependencies from the menu entry, e.g. this means the dependency 「NET」 is added to the dependency list of the config option NETDEVICES.(所有在"menu" … "endmenu"
結構中的選單項,都成為"Network device support"
的一個子選單,所有的子選單都繼承自選單項,比如"NET"
也是子選單項"NETDEVICES"
的依賴項)
The other way to generate the menu structure is done by analyzing the dependencies. If a menu entry somehow depends on the previous entry, it can be made a submenu of it. First, the previous (parent) symbol must be part of the dependency list and then one of these two conditions must be true:(生成選單結構的另一種方式是解析依賴,如果一個選單項依賴前一個選單項,那麼它就成為了子選單,之前的選單(父選單)必須成為依賴的一部分)
the child entry must become invisible, if the parent is set to 'n'(如果父選單項設定為'n',子選單就不可見)
the child entry must only be visible, if the parent is visible:(如果父選單可見,則子選單必須可見)
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 directly depends on MODULES, this means it’s only visible if MODULES is different from 'n'. The comment on the other hand is only visible when MODULES is set to 'n'.()
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:(組態檔描述了一系列設定項,每一個設定項都以一個關鍵字開頭,幫助資訊除外,以關鍵字結束)
The first five also start the definition of a menu entry.(前5條用於開始定義選單項)
"config" <symbol>
<config options>
This defines a config symbol <symbol>
and accepts any of above attributes as options.(定義一個config符號)
"menuconfig" <symbol>
<config options>
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
類似,但menuconfig
給出了一個提示端,它所有的子選項都顯示為一個單獨的選項顯示在選單設定項下)
(1):
menuconfig M
if M
config C1
config C2
endif
(2):
menuconfig M
config C1
depends on M
config C2
depends on 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:(以下範例中,C1和C2依賴於M,但不會出現在選單M下面,因為C0不依賴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
choice條目將多個類似的設定選項組合在一起,供使用者單選或者多選。
"choice" [symbol]
<choice options>
<choice block>
"endchoice"
This defines a choice group and accepts any of the above attributes as options. A choice can only be of type bool or tristate. If no type is specified for a choice, its type will be determined by the type of the first choice element in the group or remain unknown if none of the choice elements have a type specified, as well.(定義一個選項組,使用上述的任何屬性作為輸入。一個選項只能是布林型或三態型,如果沒有定義型別,它的型別由組內第一個元素指定)
While a boolean choice only allows a single config entry to be selected, a tristate choice also allows any number of config entries to be set to 'm'. This can be used if multiple drivers for a single hardware exists and only a single driver can be compiled/loaded into the kernel, but all drivers can be compiled as modules.(一個布林選項僅允許一個設定項選擇,一個三態選項可以允許選擇任意多個設定項設定為'm',適用於一個硬體有多個驅動程式的情況並且僅一個驅動可以被編譯進核心,但是所有的驅動可以被編譯為模組)
A choice accepts another option "optional", which allows to set the choice to 'n' and no entry needs to be selected. If no [symbol] is associated with a choice, then you can not have multiple definitions of that choice. If a [symbol] is associated to the choice, then you may define the same choice (i.e. with the same entries) in another place.(一個選擇項接受另一個可選項"optional"
,這種情況允許設定為'n'並且沒有設定項需要被選擇,如果沒有[symbol]與另一個選擇項關聯,則不能有對這個選擇項有多種定義。如果一個[symbol]關聯一個選擇項,那你可以在另一個地方定義相同的選擇項。)
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" <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.(定義一個選單塊,可以參考「Menu structure」
,可選擇項可能是依賴或者visible
屬性)
"if" <expr>
<if block>
"endif"
This defines an if block. The dependency expression <expr>
is appended to all enclosed menu entries.(定義一個if塊,依賴表示式<expr>
附加到所有附帶選單項)
"source" <prompt>
This reads the specified configuration file. This file is always parsed.(讀取指定的組態檔,讀取的檔案也會被解析)
"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.(設定設定選單的標籤欄,這個應該放在組態檔的開頭)
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.(在原始檔開頭,不帶引號的'#'表示註釋)
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.(Kconfig提示,大部分提示已經在kconfig檔案中)
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.(實現一個跟某架構不緊密關聯的特定/功能,推薦的方式是使用以HAVE_*開頭的設定變數,並在kconfig檔案中來選擇架構,以IOMAP為例說明)
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
For each architecture using the generic IOMAP functionality we would see:
config X86
select ...
select HAVE_GENERIC_IOMAP
select ...
Note: we use the existing config option and avoid creating a new config variable to select HAVE_GENERIC_IOMAP.
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'.
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:(有幾個特性需要編譯器支援,推薦在對編譯器的依賴時使用"depends on"+測試宏的方式)
config STACKPROTECTOR
bool "Stack Protector buffer overflow detection"
depends on $(cc-option,-fstack-protector)
...
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:(如果需要將編譯器相關功能提供給Makefile/C檔案使用,建議使用CC_HAS_字首)
config CC_HAS_FOO
def_bool $(success,$(srctree)/scripts/cc-check-foo.sh $(CC))
To restrict a component build to module-only, qualify its config symbol with "depends on m". E.g.:(將元件限制為僅編譯為模組,可以使用設定符號"depends on m")
config FOO
depends on BAR && m
limits FOO to module (=m) or disabled (=n).(將FOO限制為模組(=m),或者不使用(=n))
Linux下測試,版本:Centos7(如果是在Windows下測試,除了安裝kconfiglib外,還需要安裝windows_curses庫。)
使用的Python版本:3.8 https://www.python.org/ftp/python/3.8.5/Python-3.8.5.tgz
使用的Kconfiglib庫版本:14.1.0
需要用到以下檔案:
輸出檔案:
config.in:Kconfig組態檔在後續測試過程中會一直更改,這裡就不進行說明。
Makefile檔案中的內容(根據不同的設定項執行指令碼輸入不同的引數):
.PHONY: menuconfig savemenuconfig defconfig allyesconfig allnoconfig
# 進入設定選單
menuconfig:
python menu_main.py
# 儲存設定選單,如果之前通過設定選單更改了設定值,將儲存修改後的值
savemenuconfig:
python menu_main.py savemenuconfig
# 根據組態檔中的結構,輸出預設設定,同時會覆蓋menuconfig設定介面中之前的設定資訊
defconfig:
python menu_main.py defconfig
# 將盡可能多的設定項設定為'y’
allyesconfig:
python menu_main.py allyesconfig
# 將盡可能多的設定項設定為'n’
allnoconfig:
python menu_main.py allnoconfig
menu_main.py檔案中的內容,
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import os, sys
from kconfiglib import Kconfig
from menuconfig import menuconfig
# 設定Kconfig環境變數
def mconf_set_env():
os.environ["MENUCONFIG_STYLE"] = "default selection=fg:white,bg:red" # 設定menuconfig的顏色主題
os.environ["KCONFIG_CONFIG"] = os.path.join(".config") # 輸出的組態檔名
os.environ["KCONFIG_CONFIG_HEADER"] = "# Generated by Kconfig Tool\n" # 設定生成的組態檔開頭的字串,會在生成的組態檔開頭的第一行進行顯示。
os.environ["KCONFIG_AUTOHEADER"] = os.path.join("autoconfig.h") # 指定輸出符號到C標頭檔案的檔名
# os.environ["CONFIG_"] = "MYTEST"
def mconfig(argv):
mconf_set_env()
kconfig = os.path.join("config.in") # menuconfig組態檔
kconf = Kconfig(filename=kconfig)
if len(argv) == 2 and argv[1] == 'savemenuconfig':
kconf.load_config() # 載入設定
print(kconf.write_config()) # 儲存設定到組態檔
elif len(argv) == 2 and argv[1] == 'defconfig':
kconf.load_allconfig("alldef.config") # 載入預設設定
print(kconf.write_config())
elif len(argv) == 2 and argv[1] == 'allyesconfig':
kconf.warn = False
for sym in kconf.unique_defined_syms:
sym.set_value(1 if sym.choice else 2)
for choice in kconf.unique_choices:
choice.set_value(2)
kconf.warn = True
kconf.load_allconfig("allyes.config") # 儘可能設定多的設定為'y'
print(kconf.write_config())
elif len(argv) == 2 and argv[1] == 'allnoconfig':
kconf.warn = False
for sym in kconf.unique_defined_syms:
sym.set_value(2 if sym.is_allnoconfig_y else 0)
kconf.warn = True
kconf.load_allconfig("allno.config") # 儘可能設定多的設定為'n'
print(kconf.write_config())
else:
print("python menuconfig ... \n")
menuconfig(kconf)
# 儲存autoconfig.h
kconf.write_autoconf()
if __name__ == "__main__":
print("start ... \n")
mconfig(sys.argv)
參考:https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py
功能:建立一個Kconfig設定系統,預設的組態檔名為kconfig,使用者可以通過filename更改組態檔名。
class Kconfig(object):
def __init__(self, filename="Kconfig", warn=True, warn_to_stderr=True, encoding="utf-8", suppress_traceback=False):
引數filename:載入的Kconfig檔名。
引數warn:為True(預設)表示解析組態檔過程中產生可能的警告。可以參考 Kconfig.warn_*
變數,用於在使能警告時啟用或禁止某些警告。所有生成的警告都會新增到Kconfig.warnings
列表中。
引數warn_to_stderr:解析組態檔過程中,產生的警告是否列印到標準輸出stderr(預設為True)。
功能:從.config
格式檔案中載入符號值。等同於呼叫Symbol.set_value()
函數設定每個值。在.config檔案中 "# CONFIG_FOO is not set"
將設定符號'FOO'的值為'n'。呼叫這個函數同時會更新Kconfig.missing_syms
屬性,其中包括組態檔中未定義符號的所有賦值。如果replace
為真,Kconfig.missing_syms
被清除,否則被追加。請參考Kconfig.missing_syms
設定檔案。
def load_config(self, filename=None, replace=True, verbose=None):
引數filename:指定載入組態檔名。如果filename為空(預設),組態檔將自動載入,載入方式如下:
KCONFIG_CONFIG
環境變數設定了,它指定了載入組態檔的路徑。否則,.config
被當作預設檔名。kconf.defconfig_filename
指定的檔案,這是由'option defconfig_list'
符號派生的。功能:向.config格式的組態檔中輸出符號值。符號生成順序和kconfig檔案中出現一樣。對於在多個地方定義的符號,將在符號第一個地方定義的地方輸出符號。
def write_config(self, filename=None, header=None, save_old=True, verbose=None):
引數filename:指定輸出組態檔名。如果為空(預設),檔名將由環境變數KCONFIG_CONFIG
指定,否則預設為.config
。
引數header:在組態檔中的開頭插入的字串,應該使用"#"開頭的註釋,並以換行符結束。如果為空(預設),可通過環境變數KCONFIG_CONFIG_HEADER
指定,否則為空。
引數save_old:如果當前指定的組態檔名已經存在,在寫入新的組態檔前,是否在當前目錄重新拷貝一份並命名為<filename>.old
。預設為"TRUE"。如果<filename>.old
不能寫,將返回錯誤。
返回值:返回一個字串,說明檔案已經儲存或者檔案沒有改變。可以直接使用print(kconf.write_config()).
方式呼叫。
功能:針對所有all*config,載入(合併)由KCONFIG_ALLCONFIG
指定的組態檔,可參考Linux核心Documentation/kbuild/kconfig.txt
。
def load_allconfig(self, filename):
引數filename:特定的組態檔名,比如:"allyes.config"、"allno.config"
(1)設定設定項的值為預設值
kconf.load_allconfig("alldef.config")
(2)將盡可能多的設定項值設為'y'
Kconfiglib/allyesconfig.py at master · ulfalizer/Kconfiglib · GitHub中的範例:
def main():
kconf = kconfiglib.standard_kconfig(__doc__)
# Avoid warnings that would otherwise get printed by Kconfiglib for the
# following: (避免Kconfiglib列印以下警告)
#
# 1. Assigning a value to a symbol without a prompt, which never has any
# effect (在沒有提示符的情況下對符號賦值,該符號從沒有提示符)
#
# 2. Assigning values invalid for the type (only bool/tristate symbols
# accept 0/1/2, for n/m/y). The assignments will be ignored for other
# symbol types, which is what we want. (對某型別賦無效值,只有布林和三態型別可以賦值為0/1/2,表示n/m/y。對於其它型別符號,賦的值會被忽略。)
kconf.warn = False
# Try to set all symbols to 'y'. Dependencies might truncate the value down
# later, but this will at least give the highest possible value.(試著對所有符號賦值為'y'。依賴關係可能在後面會被截斷,但這至少會給出最多的值。)
#
# Assigning 0/1/2 to non-bool/tristate symbols has no effect (int/hex
# symbols still take a string, because they preserve formatting).(對於非布林/三態型別的符號賦值為0/1/2沒有作用,因為它們保留了格式)
for sym in kconf.unique_defined_syms:
# Set choice symbols to 'm'. This value will be ignored for choices in
# 'y' mode (the "normal" mode), which will instead just get their
# default selection, but will set all symbols in m-mode choices to 'm',
# which is as high as they can go.(設定choice符號依賴為'm'。對於'y'模式(正常模式)下的choices,這個值會被忽略,
# 它只會得到它們預設的選擇,但會將'm'模式中的所有符號設定為'm',這是它們可以設定的最大值。)
# Here's a convoluted example of how you might get an m-mode choice
# even during allyesconfig:(下面是一個範例,說明設定為allyesconfig,如何獲得'm'模式的choice)
#
# choice OPT_BOOL_CHOICE
# tristate "weird choice"
# depends on m
#
# config OPT_BOOL_CHOICE_SYM_1
# tristate "Optional bool choice sym 1"
#
# config OPT_BOOL_CHOICE_SYM_2
# tristate "Optional bool choice sym 2"
#
# endchoice
#
# 輸出為:
# OPT_BOOL_CHOICE_SYM_1=m
# OPT_BOOL_CHOICE_SYM_2=m
sym.set_value(1 if sym.choice else 2)
# Set all choices to the highest possible mode(設定所有選項值為最高模式,也就是最大值'y')
for choice in kconf.unique_choices:
choice.set_value(2)
kconf.warn = True
kconf.load_allconfig("allyes.config")
print(kconf.write_config())
(3)設定儘可能多的設定項值設為'n':
Kconfiglib/allnoconfig.py at master · ulfalizer/Kconfiglib · GitHub的範例:
def main():
kconf = kconfiglib.standard_kconfig(__doc__)
# Avoid warnings that would otherwise get printed by Kconfiglib for the
# following: (避免Kconfiglib列印以下警告)
#
# 1. Assigning a value to a symbol without a prompt, which never has any
# effect (在沒有提示符的情況下對符號賦值,該符號從沒有提示符)
#
# 2. Assigning values invalid for the type (only bool/tristate symbols
# accept 0/1/2, for n/m/y). The assignments will be ignored for other
# symbol types, which is what we want. (對某型別賦無效值,只有布林和三態型別可以賦值為0/1/2,表示n/m/y。對於其它型別符號,賦的值會被忽略。)
kconf.warn = False
for sym in kconf.unique_defined_syms:
sym.set_value(2 if sym.is_allnoconfig_y else 0)
kconf.warn = True
kconf.load_allconfig("allno.config")
print(kconf.write_config())
參考:Kconfiglib/menuconfig.py at master · ulfalizer/Kconfiglib · GitHub
說明:menuconfig.py
既可以作為獨立的可執行檔案執行,也可以呼叫menuconfig()函數時傳入Kconfig範例來執行。第二個選項有點不靈活,因為它仍然會載入和儲存.config等。
當以獨立模式執行時,要載入的kconfig組態檔可以通過引數傳遞,如果沒有引數,則預設的"Kconfig"檔案。環境變數KCONFIG_CONFIG
指定了載入和儲存的.config
檔名,如果沒有設定,預設為.config
檔名。當覆蓋一個組態檔時,舊的檔案可以指定<filename>.old
儲存檔名。
def menuconfig(kconf):
函數說明:啟動使用者設定介面,使用者退出後返回。
引數kconf:設定的Kconfig類的範例。
設定系統中的使用到的一些按鍵及其作用:
J/K : Down/Up
L : Enter menu/Toggle item
H : Leave menu
Ctrl-D/U: Page Down/Page Up
G/End : Jump to end of list
g/Home : Jump to beginning of list
[Space] toggles values if possible, and enters menus otherwise.
[Enter] works the other way around.
def write_autoconf(self, filename=None, header=None):
函數說明:輸出符號值作為C標頭檔案,與核心的include/generated/autoconf.h
檔案的格式匹配。#define的順序和write_config()生成的一致。如果檔名'filename'
存在,並且它的內容和要寫入的內容一致,則將保持不變。
引數filename:寫入標頭檔案路徑,如果為空(預設),則檔名由環境變數KCONFIG_AUTOHEADER
指定,否則為include/generated/autoconf.h
。
引數header:在檔案的開頭插入的文字,通常是一些格式為/* ... */
的註釋,並且以換行符結束。如果為空(預設),它的值可以由環境變數KCONFIG_AUTOHEADER_HEADER
指定,否則不新增檔案頭註釋。
返回值:返回一個字串,說明標頭檔案已經儲存或者標頭檔案沒有改變。可以直接使用print(kconf.write_autoconf()).
方式呼叫。
MENUCONFIG_STYLE
:設定menuconfig的顏色主題,使用方式可以檢視庫原始檔menuconfig.py
中的描述。比如:os.environ["MENUCONFIG_STYLE"] = "default selection=fg:white,bg:blue"
default
:表示主題型別,支援三種:
- default classic Kconfiglib theme with a yellow accent
- monochrome colorless theme (uses only bold and standout) attributes, this style is used if the terminal doesn't support colors
- aquatic blue-tinted style loosely resembling the lxdialog theme
selection=fg:white,bg:blue
:設定選項的樣式
fg:white
表示設定前景色和背景色為白色。
bg:blue
表示設定背景色為藍色。
其它使用舉例:
MENUCONFIG_STYLE="aquatic selection=fg:white,bg:red"
MENUCONFIG_STYLE="default selection=fg:white,bg:red"
KCONFIG_CONFIG_HEADER
:設定生成的組態檔開頭的字串,會在生成的組態檔開頭的第一行進行顯示。KCONFIG_CONFIG
:輸出的組態檔名,如果不設定,預設輸出.config
。KCONFIG_AUTOHEADER
:指定輸出符號到C標頭檔案的檔名,否則預設輸出到include/generated/autoconf.h
。CONFIG_
:指定輸出組態檔中字串的字首,比如設定為os.environ["CONFIG_"] = "MYTEST"
,則輸出字串的格式為MYTEST_XXXX
,不設定預設格式為CONFIG_XXXX
組態檔config.in如下,這裡直接使用的是庫中的範例(Kconfiglib/Kmenuconfig at master · ulfalizer/Kconfiglib · GitHub):
mainmenu "Example Kconfig configuration"
config MODULES
bool "Enable loadable module support"
option modules
default y
menu "Bool and tristate symbols"
config BOOL
bool "Bool symbol"
default y
config BOOL_DEP
bool "Dependent bool symbol"
depends on BOOL
# Mix it up a bit with an 'if' instead of a 'depends on'
if BOOL
config TRI_DEP
tristate "Dependent tristate symbol"
select SELECTED_BY_TRI_DEP
imply IMPLIED_BY_TRI_DEP
endif
config TWO_MENU_NODES
bool "First prompt"
depends on BOOL
config TRI
tristate "Tristate symbol"
config TWO_MENU_NODES
bool "Second prompt"
comment "These are selected by TRI_DEP"
config SELECTED_BY_TRI_DEP
tristate "Tristate selected by TRI_DEP"
config IMPLIED_BY_TRI_DEP
tristate "Tristate implied by TRI_DEP"
endmenu
menu "String, int, and hex symbols"
config STRING
string "String symbol"
default "foo"
config INT
int "Int symbol"
default 747
config HEX
hex "Hex symbol"
default 0xABC
endmenu
menu "Various choices"
choice BOOL_CHOICE
bool "Bool choice"
config BOOL_CHOICE_SYM_1
bool "Bool choice sym 1"
config BOOL_CHOICE_SYM_2
bool "Bool choice sym 2"
endchoice
choice TRI_CHOICE
tristate "Tristate choice"
config TRI_CHOICE_SYM_1
tristate "Tristate choice sym 1"
config TRI_CHOICE_SYM_2
tristate "Tristate choice sym 2"
endchoice
choice OPT_BOOL_CHOICE
bool "Optional bool choice"
optional
config OPT_BOOL_CHOICE_SYM_1
bool "Optional bool choice sym 1"
config OPT_BOOL_CHOICE_SYM_2
bool "Optional bool choice sym 2"
endchoice
endmenu
執行命令make defconfig
輸出預設設定。
$ more autoconfig.h
#define CONFIG_MODULES 1
#define CONFIG_BOOL 1
#define CONFIG_STRING "foo"
#define CONFIG_INT 747
#define CONFIG_HEX 0xABC
#define CONFIG_BOOL_CHOICE_SYM_1 1
$ more .config
# Generated by Kconfig Tool
CONFIG_MODULES=y
#
# Bool and tristate symbols
#
CONFIG_BOOL=y
# CONFIG_BOOL_DEP is not set
# CONFIG_TRI_DEP is not set
# CONFIG_TWO_MENU_NODES is not set
# CONFIG_TRI is not set
#
# These are selected by TRI_DEP
#
# CONFIG_SELECTED_BY_TRI_DEP is not set
# CONFIG_IMPLIED_BY_TRI_DEP is not set
# end of Bool and tristate symbols
#
# String, int, and hex symbols
#
CONFIG_STRING="foo"
CONFIG_INT=747
CONFIG_HEX=0xABC
# end of String, int, and hex symbols
#
# Various choices
#
CONFIG_BOOL_CHOICE_SYM_1=y
# CONFIG_BOOL_CHOICE_SYM_2 is not set
# CONFIG_TRI_CHOICE_SYM_1 is not set
# CONFIG_TRI_CHOICE_SYM_2 is not set
# end of Various choices
下面分開進行學習。
設定項為布林型別,預設為'y'。
mainmenu "Example Kconfig configuration"
config MODULES
bool "Enable loadable module support" # 布林型別
option modules # 宣告將符號編譯為MODULES符號
default y # 預設為'y'
輸入的kconfig檔案型別值:
mainmenu "Example Kconfig configuration"
menu "Bool and tristate symbols"
config BOOL
bool "Bool symbol"
default y
config BOOL_DEP
bool "Dependent bool symbol"
depends on BOOL
# Mix it up a bit with an 'if' instead of a 'depends on'
if BOOL
config TRI_DEP
tristate "Dependent tristate symbol"
select SELECTED_BY_TRI_DEP # 反向依賴
imply IMPLIED_BY_TRI_DEP # 弱反向依賴
endif
config TWO_MENU_NODES
bool "First prompt"
depends on BOOL
config TRI
tristate "Tristate symbol"
config TWO_MENU_NODES
bool "Second prompt"
comment "These are selected by TRI_DEP"
config SELECTED_BY_TRI_DEP
tristate "Tristate selected by TRI_DEP"
config IMPLIED_BY_TRI_DEP
tristate "Tristate implied by TRI_DEP"
endmenu
輸入的kconfig檔案中的設定項:
mainmenu "Example Kconfig configuration"
menu "String, int, and hex symbols"
config STRING
string "String symbol"
default "foo"
config INT
int "Int symbol"
default 747
config HEX
hex "Hex symbol"
default 0xABC
endmenu
輸出的預設值:
$ make defconfig
python menu_main.py defconfig
start ...
Configuration saved to '.config'
$ more .config
# Generated by Kconfig Tool
#
# String, int, and hex symbols
#
CONFIG_STRING="foo"
CONFIG_INT=747
CONFIG_HEX=0xABC
# end of String, int, and hex symbols
$ more autoconfig.h
#define CONFIG_STRING "foo"
#define CONFIG_INT 747
#define CONFIG_HEX 0xABC
更改設定值,更改字串為"test",int型別為1000,hex型別為0x789:
$ more .config
# Generated by Huawei LiteOS Kconfig Tool
#
# String, int, and hex symbols
#
STRING="test"
INT=1000
HEX=0x789
# end of String, int, and hex symbols
$ more autoconfig.h
/*
Generated by Huawei LiteOS Kconfig Tool
*/
#define STRING "test"
#define INT 1000
#define HEX 0x789
輸入的kconfig組態檔:
mainmenu "Example Kconfig configuration"
menu "Various choices"
config MODULES
bool "Enable loadable module support"
option modules
default y
choice BOOL_CHOICE
bool "Bool choice"
config BOOL_CHOICE_SYM_1
bool "Bool choice sym 1"
config BOOL_CHOICE_SYM_2
bool "Bool choice sym 2"
endchoice
choice TRI_CHOICE
tristate "Tristate choice"
config TRI_CHOICE_SYM_1
tristate "Tristate choice sym 1"
config TRI_CHOICE_SYM_2
tristate "Tristate choice sym 2"
endchoice
choice OPT_BOOL_CHOICE
bool "Optional bool choice"
optional
config OPT_BOOL_CHOICE_SYM_1
bool "Optional bool choice sym 1"
config OPT_BOOL_CHOICE_SYM_2
bool "Optional bool choice sym 2"
endchoice
endmenu
預設的設定項的值:
$ make defconfig
python usr_config.py defconfig
Configuration saved to '.config'
Kconfig header saved to 'autoconfig.h'
$ more .config
# Generated by Huawei LiteOS Kconfig Tool
#
# Various choices
#
BOOL_CHOICE_SYM_1=y
# BOOL_CHOICE_SYM_2 is not set
TRI_CHOICE_SYM_1=y
# TRI_CHOICE_SYM_2 is not set
# end of Various choices
$ more autoconfig.h
/*
Generated by Huawei LiteOS Kconfig Tool
*/
#define BOOL_CHOICE_SYM_1 1
#define TRI_CHOICE_SYM_1 1
更改設定項的值:
(1)預設'optional'設定項OPT_BOOL_CHOICE不會被選擇,因為optional
屬性。
(2)BOOL_CHOICE設定項選擇第二個設定。
(3)(4)當'MODULES'設定項選擇為y,表示可以設定為'm','TRI_CHOICE'設定項這時可以同時設定多個設定項為'm'或者'n'。
(5)當'MODULES'設定項選擇為n,'TRI_CHOICE'被當作bool型別,僅能從多個設定項中選擇一個,預設選擇第一個。
(6)選擇OPT_BOOL_CHOICE設定項,預設會選擇其子項的第一個設定項;
(5)OPT_BOOL_CHOICE設定項選擇第二個設定。
$ more .config
# Generated by Huawei LiteOS Kconfig Tool
#
# Various choices
#
# BOOL_CHOICE_SYM_1 is not set
BOOL_CHOICE_SYM_2=y
# TRI_CHOICE_SYM_1 is not set
TRI_CHOICE_SYM_2=y
# OPT_BOOL_CHOICE_SYM_1 is not set
OPT_BOOL_CHOICE_SYM_2=y
# end of Various choices
$ more autoconfig.h
/*
Generated by Huawei LiteOS Kconfig Tool
*/
#define BOOL_CHOICE_SYM_2 1
#define TRI_CHOICE_SYM_2 1
#define OPT_BOOL_CHOICE_SYM_2 1
總結:
Kconfiglib庫中給的範例,用於列印Kconfig檔案的樹形關係:Kconfiglib/print_tree.py at master · ulfalizer/Kconfiglib · GitHub
原始碼實現:
# Prints the menu tree of the configuration. Dependencies between symbols can
# sometimes implicitly alter the menu structure (see kconfig-language.txt), and
# that's implemented too.
#
# Note: See the Kconfig.node_iter() function as well, which provides a simpler
# interface for walking the menu tree.
import sys
from kconfiglib import Kconfig, Symbol, Choice, MENU, COMMENT
def indent_print(s, indent):
print(indent*" " + s)
def print_items(node, indent):
while node:
if isinstance(node.item, Symbol):
indent_print("config " + node.item.name, indent)
elif isinstance(node.item, Choice):
indent_print("choice", indent)
elif node.item == MENU:
indent_print('menu "{}"'.format(node.prompt[0]), indent)
elif node.item == COMMENT:
indent_print('comment "{}"'.format(node.prompt[0]), indent)
if node.list:
print_items(node.list, indent + 2)
node = node.next
if __name__ == "__main__":
kconf = Kconfig(sys.argv[1])
print_items(kconf.top_node, 0)
測試的Kconfig組態檔:
mainmenu "Example Kconfig configuration"
menu "Various choices"
choice BOOL_CHOICE
bool "Bool choice"
config BOOL_CHOICE_SYM_1
bool "Bool choice sym 1"
config BOOL_CHOICE_SYM_2
bool "Bool choice sym 2"
endchoice
choice TRI_CHOICE
tristate "Tristate choice"
config TRI_CHOICE_SYM_1
tristate "Tristate choice sym 1"
config TRI_CHOICE_SYM_2
tristate "Tristate choice sym 2"
endchoice
choice OPT_BOOL_CHOICE
bool "Optional bool choice"
optional
config OPT_BOOL_CHOICE_SYM_1
bool "Optional bool choice sym 1"
config OPT_BOOL_CHOICE_SYM_2
bool "Optional bool choice sym 2"
endchoice
endmenu
執行,測試:
$ python print_tree.py kconfig
menu "Example Kconfig configuration"
menu "Various choices"
choice
config BOOL_CHOICE_SYM_1
config BOOL_CHOICE_SYM_2
choice
config TRI_CHOICE_SYM_1
config TRI_CHOICE_SYM_2
choice
config OPT_BOOL_CHOICE_SYM_1
config OPT_BOOL_CHOICE_SYM_2
使用Kconfiglib/Kchoice at master · ulfalizer/Kconfiglib · GitHub中的kconfig檔案來進行測試:
choice BOOL
bool "bool"
config B_1
tristate "B_1"
config B_2
tristate "B_2"
endchoice
choice BOOL_OPT
bool "bool optional"
optional
config BO_1
tristate "BO_1"
config BO_2
tristate "BO_2"
endchoice
choice TRISTATE
tristate "tristate"
config T_1
tristate "T_1"
config T_2
tristate "T_2"
endchoice
choice TRISTATE_OPT
tristate "tristate optional"
optional
config TO_1
tristate "TO_1"
config TO_2
tristate "TO_2"
endchoice
config MODULES
bool "modules"
choice BOOL_M
bool "bool m" if m
config BM_1
tristate "BM_1"
config BM_2
tristate "BM_2"
endchoice
config MODULES
bool "modules"
choice BOOL_M
bool "bool m" if m
config BM_1
tristate "BM_1"
config BM_2
tristate "BM_2"
endchoice
config TRISTATE_SYM
tristate "tristate"
choice DEFAULTS
bool "defaults"
default OPT_1 if n
default OPT_2 if TRISTATE_SYM
default OPT_4
config OPT_1
tristate "OPT_1"
config OPT_2
tristate "OPT_2"
config OPT_3
tristate "OPT_3"
config OPT_4
tristate "OPT_4"
endchoice
choice DEFAULTS_NOT_VISIBLE
bool "defaults not visible"
# Skipped due to condition
default OPT_6 if n
# Skipped because OPT_7 is not visible
default OPT_7
# This one should apply
default OPT_8
config OPT_5
tristate "OPT_5"
config OPT_6
tristate "OPT_6"
config OPT_7
tristate "OPT_7" if n
config OPT_8
tristate "OPT_8"
config OPT_9
tristate "OPT_9"
endchoice
# Choices without an explicitly specified type should get the type of the first symbol with a type
choice NO_TYPE_BOOL
prompt "no type bool"
config NTB_1
bool "NTB_1"
config NTB_2
tristate "NTB_2"
endchoice
choice NO_TYPE_TRISTATE
prompt "no type tristate"
config NTT_1
config NTT_2
tristate "NTB_2"
config NTT_3
bool "NTT_3"
endchoice
# Choice items without an explicitly specified type should get the type of the choice
choice MISSING_MEMBER_TYPES_1
bool "missing member types"
config MMT_1
config MMT_2
config MMT_3
tristate "mmt1/2/3"
endchoice
choice MISSING_MEMBER_TYPES_2
config MMT_4
config MMT_5
bool "mmt4/5"
endchoice
# Choice where the default selection (the first symbol) depends on another symbol.
# If that symbol becomes 'n', the default selection should change to the first visible symbol in the choice.
choice DEFAULT_WITH_DEP
bool "default with dep"
config A
bool "A"
depends on DEP
config B
bool "B"
endchoice
config DEP
bool "dep"
# Choice with symbols that shouldn't be considered choice symbols because they depend on the preceding symbol.
# This might be a kconfig bug, but some things use it, so we need to emulate it.
choice WEIRD_SYMS
bool "weird symbols that aren't considered part of the choice"
# Only WS1 is part of the choice
config WS1
bool "WS1"
config WS2
bool "WS2"
depends on WS1
config WS3
bool
depends on WS2
config WS4
bool
depends on WS1
config WS5
bool "WS5" if WS1
# 'if' has the same effect, so only WS6 is part of the choice
config WS6
bool "WS6"
if WS6
config WS7
bool
config WS8
bool "WS8"
endif
# Should also be part of the choice
config WS9
bool "WS9"
endchoice
參考:Kconfiglib/guiconfig.py at master · ulfalizer/Kconfiglib (github.com)
guiconfig.py介紹(檔案開頭的介紹):一個基於tkinter的選單設定實現,基於樹檢視控制元件和幫助顯示。顯示可以在顯示完整的樹和僅顯示單個選單(如menuconfig.py)之間進行切換。
Ctrl-S : Save configuration
Ctrl-O : Open configuration
Ctrl-A : Toggle show-all mode
Ctrl-N : Toggle show-name mode
Ctrl-M : Toggle single-menu mode
Ctrl-F, /: Open jump-to dialog
ESC : Close
以載入庫中預設的Kmenuconfig組態檔為例進行舉例說明:
kconfig組態檔:Kconfiglib/Kmenuconfig at master · ulfalizer/Kconfiglib (github.com)
執行,可以直接使用滑鼠操作,也可以使用鍵盤快捷鍵操作,可以看出在Windows下用這種方式設定還是比較人性話:
python .\guiconfig.py .\examples\Kmenuconfig
使用menuconfig方式載入這個kconfig檔案:
可以看出,使用guiconfig.py的方式設定,樹形結構更加直觀。
官方實現:Kconfiglib/alldefconfig.py at master · ulfalizer/Kconfiglib (github.com)
import kconfiglib
def main():
kconf = kconfiglib.standard_kconfig(__doc__)
kconf.load_allconfig("alldef.config")
print(kconf.write_config())
if __name__ == "__main__":
main()
使用方式:
python .\alldefconfig.py .\examples\Kmenuconfig
官方:Kconfiglib/allmodconfig.py at master · ulfalizer/Kconfiglib (github.com)
說明:寫入一個組態檔,將盡可能多的符號被設定為"m"。
import kconfiglib
def main():
kconf = kconfiglib.standard_kconfig(__doc__)
# See allnoconfig.py
kconf.warn = False
for sym in kconf.unique_defined_syms:
if sym.orig_type == kconfiglib.BOOL:
# 'bool' choice symbols get their default value, as determined by
# e.g. 'default's on the choice
if not sym.choice:
# All other bool symbols get set to 'y', like for allyesconfig
sym.set_value(2)
elif sym.orig_type == kconfiglib.TRISTATE:
sym.set_value(1)
for choice in kconf.unique_choices:
choice.set_value(2 if choice.orig_type == kconfiglib.BOOL else 1)
kconf.warn = True
kconf.load_allconfig("allmod.config")
print(kconf.write_config())
if __name__ == "__main__":
main()
使用方式:
python .\alldefconfig.py .\examples\Kmenuconfig
官方:Kconfiglib/allnoconfig.py at master · ulfalizer/Kconfiglib (github.com)
說明:寫入一個組態檔,將盡可能多的符號被設定為"n"。
import kconfiglib
def main():
kconf = kconfiglib.standard_kconfig(__doc__)
# Avoid warnings that would otherwise get printed by Kconfiglib for the
# following:
#
# 1. Assigning a value to a symbol without a prompt, which never has any
# effect
#
# 2. Assigning values invalid for the type (only bool/tristate symbols
# accept 0/1/2, for n/m/y). The assignments will be ignored for other
# symbol types, which is what we want.
kconf.warn = False
for sym in kconf.unique_defined_syms:
sym.set_value(2 if sym.is_allnoconfig_y else 0)
kconf.warn = True
kconf.load_allconfig("allno.config")
print(kconf.write_config())
if __name__ == "__main__":
main()
使用方式:
python .\alldefconfig.py .\examples\Kmenuconfig
官方:Kconfiglib/allyesconfig.py at master · ulfalizer/Kconfiglib (github.com)
說明:寫入一個組態檔,將盡可能多的符號被設定為"y"。
import kconfiglib
def main():
kconf = kconfiglib.standard_kconfig(__doc__)
# See allnoconfig.py
kconf.warn = False
# Try to set all symbols to 'y'. Dependencies might truncate the value down
# later, but this will at least give the highest possible value.
#
# Assigning 0/1/2 to non-bool/tristate symbols has no effect (int/hex
# symbols still take a string, because they preserve formatting).
for sym in kconf.unique_defined_syms:
# Set choice symbols to 'm'. This value will be ignored for choices in
# 'y' mode (the "normal" mode), which will instead just get their
# default selection, but will set all symbols in m-mode choices to 'm',
# which is as high as they can go.
#
# Here's a convoluted example of how you might get an m-mode choice
# even during allyesconfig:
#
# choice
# tristate "weird choice"
# depends on m
sym.set_value(1 if sym.choice else 2)
# Set all choices to the highest possible mode
for choice in kconf.unique_choices:
choice.set_value(2)
kconf.warn = True
kconf.load_allconfig("allyes.config")
print(kconf.write_config())
if __name__ == "__main__":
main()
使用方式:
python .\alldefconfig.py .\examples\Kmenuconfig