Table of contents
- Getting started
- Library documentation
- Library features
- Other features
- Menuconfig interfaces
- Test suite
Kconfiglib is a Kconfig implementation in Python 2/3. It started out as a helper library, but now has a enough functionality to also work well as a standalone Kconfig implementation (including menuconfig interfaces and Kconfig extensions).
The entire library is contained in kconfiglib.py. The bundled scripts are implemented on top of it. Implementing your own scripts should be relatively easy, if needed.
Since Kconfiglib is based around a library, it can be used e.g. to generate a Kconfig cross-reference (note: heavy page), using the same robust Kconfig parser used for other Kconfig tools, instead of brittle ad-hoc parsing. The documentation generation script can be found here.
Kconfiglib implements the recently added Kconfig preprocessor.
For backwards compatibility, environment variables can be referenced both as
$(FOO) (the new syntax) and as
$FOO (the old syntax). The old syntax is
deprecated, but will probably be supported for a very long time (the major
version would be increased if support is ever dropped). Using the old syntax
with an undefined environment variable keeps the string as is.
Note: See this issue if you run into a "macro expanded to blank string" error with kernel 4.18+.
See this page for some Kconfig tips and best practices.
Installation with pip
Kconfiglib is available on PyPI and can be installed with e.g.
$ pip(3) install kconfiglib
Microsoft Windows is supported.
pip installation will give you both the base library and the following
executables. All but two (
setconfig) mirror functionality
available in the C tools.
genconfig is intended to be run at build time. It generates a C header from
the configuration and (optionally) information that can be used to rebuild only
files that reference Kconfig symbols that have changed value.
menuconfig implementation requires Python 3. It uses
which is needed for Unicode input support. Unfortunately,
available in the Python 2 version of the standard
Note: If you install Kconfiglib with
--user flag, make sure
PATH includes the directory where the executables end up. You can
list the installed files with
pip(3) show -f kconfiglib.
All releases have a corresponding tag in the git repository, e.g.
(the latest version).
Semantic versioning is used. There's been eight small changes (1, 2, 3, 4, 5, 6, 7, 8) to the behavior of the API, which is why the major version is at 10 rather than 2. I do major version bumps for all behavior changes, even tiny ones, and most of these were fixes for baby issues in the early days of the Kconfiglib 2 API.
kconfiglib.py and the scripts you want somewhere. There are no
third-party dependencies (except for the windows-curses package on Windows,
when running the terminal
Installation for the Linux kernel
See the module docstring at the top of kconfiglib.py.
Install the library and the utilities. Use
pip3if you want to use the terminal
Write Kconfig files that describe the available configuration options.
Generate an initial configuration with e.g.
alldefconfig. The configuration is saved as
genconfigto generate a header file. By default, it is saved as
genconfigwould be run automatically as part of the build.
Adding new configuration output formats should be relatively straightforward. See the implementation of
write_config()in kconfiglib.py. The documentation for the
Symbol.config_stringproperty has some tips as well.
To update an old
.configfile 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).
Due to Kconfig semantics, simply loading an old
.configfile performs an implicit
olddefconfig, so building will normally not be affected by having an outdated configuration.
For some general Kconfig advice, see this page.
.config files as Make input
.config files use Make syntax and can be included directly in Makefiles to
read configuration values from there. This is why
tristate values are written out as
# CONFIG_FOO is not set (a
Make comment) in
.config, allowing them to be tested with
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
.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
menuconfig before rebuilding with an outdated
If you use
--sync-deps to generate incremental build information, you can
deps/auto.conf instead, which is also a full configuration file.
Useful helper macros
The include/linux/kconfig.h header in the Linux kernel defines some useful helper macros for testing Kconfig configuration values.
IS_ENABLED() is generally useful, allowing configuration values to be
if statements with no runtime overhead.
See the docstring for
Kconfig.sync_deps() in kconfiglib.py for hints
on implementing incremental builds (rebuilding just source files that reference
changed configuration values).
scripts/basic/fixdep.c tool from the kernel on the output of
gcc -MD <source file> might give you an idea of how it all fits together.
Kconfiglib comes with extensive documentation in the form of docstrings. To view it, run e.g. the following command:
$ pydoc(3) kconfiglib
For HTML output, add
$ pydoc(3) -w kconfiglib
This will also work after installing Kconfiglib with
Documentation for the
menuconfig interface can be viewed in the same way:
$ pydoc3 menuconfig
A good starting point for learning the library is to read the module docstring (which you could also just read directly at the beginning of kconfiglib.py). It gives an introduction to symbol values, the menu tree, and expressions.
After reading the module docstring, a good next step is to read the
class documentation, and then the documentation for the
Please tell me if something is unclear or can be explained better.
Kconfiglib can do the following, among other things:
Programmatically get and set symbol values
Read and write .config and defconfig files
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.
Write C headers
The generated headers use the same format as
include/generated/autoconf.hfrom the Linux kernel.
Implement incremental builds
This uses the same scheme as the
include/configdirectory 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.
sync_deps()function for more information.
Printing a symbol or other item (which calls
__str__()) returns its definition in Kconfig format. This also works for symbols defined in multiple locations.
__repr__()is on all objects too.
__repr__()methods are deliberately implemented with just public APIs, so all symbol information can be fetched separately as well.
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.
The following Kconfig extensions are available:
sourcesupports glob patterns and includes each matching file. A pattern is required to match at least one file.
osourcestatement is available for cases where it's okay for the pattern to match no files (in which case
osourceturns into a no-op).
rsource) is available, where file paths are specified relative to the directory of the current Kconfig file. An
orsourcestatement is available as well, analogous to
Preprocessor user functions can be defined in Python, which makes it simple to integrate information from existing Python tools into Kconfig (e.g. to have Kconfig symbols depend on hardware information stored in some other format).
See the Kconfig extensions section in the kconfiglib.py module docstring for more information.
def_stringare available in addition to
stringsymbols to be given a type and a default at the same time.
These can be useful in projects that make use of symbols defined in multiple locations, and remove some Kconfig inconsistency.
Environment variables are expanded directly in e.g.
option envsymbols are redundant.
This is the standard behavior with the new Kconfig preprocessor, which Kconfiglib implements.
option envsymbols are supported for backwards compatibility, with the caveat that they must have the same name as the environment variables they reference. A warning is printed if the names differ.
Two extra optional warnings can be enabled by setting environment variables, covering cases that are easily missed when making changes to Kconfig files:
KCONFIG_WARN_UNDEF: If set to
y, warnings will be generated for all references to undefined symbols within Kconfig files. The only gotcha is that all hex literals must be prefixed with
0X, to make it possible to distinguish them from symbol references.
Some projects (e.g. the Linux kernel) use multiple Kconfig trees with many shared Kconfig files, leading to some safe undefined symbol references.
KCONFIG_WARN_UNDEFis useful in projects that only have a single Kconfig tree though.
KCONFIG_STRICTis an older alias for this environment variable, supported for backwards compatibility.
KCONFIG_WARN_UNDEF_ASSIGN: If set to
y, warnings will be generated for all assignments to undefined symbols within
.configfiles. By default, no such warnings are generated.
This warning can also be enabled/disabled via
The entire library is contained in kconfiglib.py.
The tools implemented on top of it are one file each.
Runs unmodified under both Python 2 and Python 3
The code mostly uses basic Python features and has no third-party dependencies. The most advanced things used are probably
A recent Python 3 version is recommended if you have a choice. Python 3.7 finally has parsing performance on par with Python 2.7 (and Python 3.6 is just a bit slower).
Robust and highly compatible with the C Kconfig tools
The test suite automatically compares output from Kconfiglib and the C tools by diffing the generated
.configfiles for the real kernel Kconfig and defconfig files, for all ARCHes.
This currently involves comparing the output for 36 ARCHes and 498 defconfig files (or over 18000 ARCH/defconfig combinations in "obsessive" test suite mode). All tests are expected to pass.
A comprehensive suite of selftests is included as well.
Not horribly slow despite being a pure Python implementation
The allyesconfig.py script currently runs in about 1.3 seconds on the Linux kernel on a Core i7 2600K (with a warm file cache), including the
make scriptconfig. Note that the Linux kernel Kconfigs are absolutely massive (over 14k symbols for x86) compared to most projects, and also have overhead from running shell commands via the Kconfig preprocessor.
Kconfiglib is especially speedy in cases where multiple
.configfiles need to be processed, because the
Kconfigfiles will only need to be parsed once.
For long-running jobs, PyPy gives a big performance boost. CPython is faster for short-running jobs as PyPy needs some time to warm up.
Kconfiglib also works well with the multiprocessing module. No global state is kept.
Generates more warnings than the C implementation
Generates the same warnings as the C implementation, plus additional ones. Also detects dependency and
All warnings point out the location(s) in the
Kconfigfiles where a symbol is defined, where applicable.
Unicode characters in string literals in
.configfiles are correctly handled. This support mostly comes for free from Python.
Nothing Linux-specific is used. Universal newlines mode is used for both Python 2 and Python 3.
The Zephyr project uses Kconfiglib to generate
.configfiles and C headers on Linux as well as Windows.
Internals that (mostly) mirror the C implementation
While being simpler to understand and tweak.
Two configuration interfaces are currently available:
menuconfig.py is a terminal-based configuration interface implemented using the standard Python
xconfigfeatures 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).
There is now also a show-help mode that shows the help text of the currently selected symbol in the help window at the bottom.
menuconfig.pycurrently only supports Python 3, mostly due to
curses.get_wch()not being available on Python 2. It is needed for Unicode support.
There are no third-party dependencies on *nix. On Windows, the
cursesmodules is not available by default, but support can be added by installing the
windows-cursespackage (which is installed automatically when Kconfiglib is installed via
$ pip install windows-curses
See the docstring at the top of menuconfig.py for more information about the terminal menuconfig implementation.
See the pymenuconfig project for more information.
While working on the terminal menuconfig implementation, I added a few APIs to Kconfiglib that turned out to be handy.
pymenuconfigpredates the terminal menuconfig, and so didn't have them available. Blame me for any workarounds.
The examples/ directory contains some simple example scripts. Among these are the following ones. Make sure you run them with the latest version of Kconfiglib, as they might make use of newly added features.
- eval_expr.py evaluates an expression in the context of a configuration.
- find_symbol.py searches through expressions to find references to a symbol, also printing a "backtrace" with parents for each reference found.
- help_grep.py searches for a string in all help texts.
- print_tree.py prints a tree of all configuration items.
- print_config_tree.py is similar to
print_tree.py, but dumps the tree as it would appear in
menuconfig, including values. This can be handy for visually diffing between
.configfiles and different versions of
- list_undefined.py finds references to symbols that are not defined by any architecture in the Linux kernel.
- merge_config.py merges configuration fragments to produce a complete .config, similarly to
scripts/kconfig/merge_config.shfrom the kernel.
- menuconfig_example.py implements a configuration interface that uses notation similar to
make menuconfig. It's deliberately kept as simple as possible to demonstrate just the core concepts.
- kconfig.py from the Zephyr project handles
.configand header file generation, also doing configuration fragment merging.
- genrest.py generates a Kconfig symbol cross-reference, which can be viewed here.
- Various utilities from the ACRN project.
These use the older Kconfiglib 1 API, which was clunkier and not as general (functions instead of properties, no direct access to the menu structure or properties, uglier
- genboardscfg.py from Das U-Boot generates some sort of legacy board database by pulling information from a newly added Kconfig-based configuration system (as far as I understand it :).
- gen-manual-lists.py generated listings for an appendix in the Buildroot manual. (The listing has since been removed.)
- gen_kconfig_doc.py from the esp-idf project generates documentation from Kconfig files.
- SConf builds an interactive configuration interface (like
menuconfig) on top of Kconfiglib, for use e.g. with SCons.
- kconfig-diff.py -- a script by dubiousjim that compares kernel configurations.
- Originally, Kconfiglib was used in chapter 4 of my master's thesis to automatically generate a "minimal" kernel for a given system. Parts of it bother me a bit now, but that's how it goes with old work.
make iscriptconfig session
The following log should give some idea of the functionality available in the API:
$ make iscriptconfig A Kconfig instance 'kconf' for the architecture x86 has been created. >>> kconf # Calls Kconfig.__repr__() <configuration with 13711 symbols, main menu prompt "Linux/x86 4.14.0-rc7 Kernel Configuration", srctree ".", config symbol prefix "CONFIG_", warnings enabled, undef. symbol assignment warnings disabled> >>> kconf.mainmenu_text # Expanded main menu text 'Linux/x86 4.14.0-rc7 Kernel Configuration' >>> kconf.top_node # The implicit top-level menu <menu node for menu, prompt "Linux/$ARCH $KERNELVERSION Kernel Configuration" (visibility y), deps y, 'visible if' deps y, has child, Kconfig:5> >>> kconf.top_node.list # First child menu node <menu node for symbol SRCARCH, deps y, has next, Kconfig:7> >>> print(kconf.top_node.list) # Calls MenuNode.__str__() config SRCARCH string option env="SRCARCH" default "x86" >>> sym = kconf.top_node.list.next.item # Item contained in next menu node >>> print(sym) # Calls Symbol.__str__() config 64BIT bool prompt "64-bit kernel" if ARCH = "x86" default ARCH != "i386" help Say yes to build a 64-bit kernel - formerly known as x86_64 Say no to build a 32-bit kernel - formerly known as i386 >>> sym # Calls Symbol.__repr__() <symbol 64BIT, bool, "64-bit kernel", value y, visibility y, direct deps y, arch/x86/Kconfig:2> >>> sym.assignable # Currently assignable values (0, 1, 2 = n, m, y) (0, 2) >>> sym.set_value(0) # Set it to n True >>> sym.tri_value # Check the new value 0 >>> sym = kconf.syms["X86_MPPARSE"] # Look up symbol by name >>> print(sym) config X86_MPPARSE bool prompt "Enable MPS table" if (ACPI || SFI) && X86_LOCAL_APIC default "y" if X86_LOCAL_APIC help For old smp systems that do not have proper acpi support. Newer systems (esp with 64bit cpus) with acpi support, MADT and DSDT will override it >>> default = sym.defaults # Fetch its first default >>> sym = default # Fetch the default's condition (just a Symbol here) >>> print(sym) # Print it. Dependencies are propagated to properties, like in the C implementation. config X86_LOCAL_APIC bool default "y" if X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI select IRQ_DOMAIN_HIERARCHY if X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI select PCI_MSI_IRQ_DOMAIN if PCI_MSI && (X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI) >>> sym.nodes # Show the MenuNode(s) associated with it [<menu node for symbol X86_LOCAL_APIC, deps n, has next, arch/x86/Kconfig:1015>] >>> kconfiglib.expr_str(sym.defaults) # Print the default's condition 'X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI' >>> kconfiglib.expr_value(sym.defaults) # Evaluate it (0 = n) 0 >>> kconf.syms["64BIT"].set_value(2) True >>> kconfiglib.expr_value(sym.defaults) # Evaluate it again (2 = y) 2 >>> kconf.write_config("myconfig") # Save a .config >>> ^D $ cat myconfig # Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) CONFIG_64BIT=y CONFIG_X86_64=y CONFIG_X86=y CONFIG_INSTRUCTION_DECODER=y CONFIG_OUTPUT_FORMAT="elf64-x86-64" CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" CONFIG_LOCKDEP_SUPPORT=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_MMU=y ...
The test suite is run with
$ python(3) Kconfiglib/testsuite.py
pypy works too, and is much speedier for everything except
allyesconfig.py, where it doesn't have time to warm up since
the scripts are run via
The test suite must be run from the top-level kernel directory. It requires that the Kconfiglib git repository has been cloned into it and that the makefile patch has been applied.
To get rid of warnings generated for the kernel
Kconfig files, add
2>/dev/null to the command to
NOTE: Forgetting to apply the Makefile patch will cause some tests that compare generated configurations to fail
NOTE: The test suite overwrites .config in the kernel root, so make sure to back it up.
The test suite consists of a set of selftests and a set of compatibility tests that compare configurations generated by Kconfiglib with configurations generated by the C tools, for a number of cases. See testsuite.py for the available options.
The tests/reltest script runs the test suite and all the example scripts for both Python 2 and Python 3, verifying that everything works.
Rarely, the output from the C tools is changed slightly (most recently due to a change I added). If you get test suite failures, try running the test suite again against the linux-next tree, which has all the latest changes. I will make it clear if any non-backwards-compatible changes appear.
A lot of time is spent waiting around for
make and the C utilities (which need to reparse all the
Kconfig files for each defconfig test). Adding some multiprocessing to the test suite would make sense
This is version 2 of Kconfiglib, which is not backwards-compatible with Kconfiglib 1. For a summary of changes between Kconfiglib 1 and Kconfiglib 2, see kconfiglib-2-changes.txt.
I sometimes see people add custom output formats, which is pretty straightforward to do (see the implementations of
write_config()for a template, and also the documentation of the
Symbol.config_stringproperty). If you come up with something you think might be useful to other people, I'm happy to take it in upstream. Batteries included and all that.
Kconfiglib assumes the modules symbol is
MODULES, which is backwards-compatible. A warning is printed by default if
option modulesis set on some other symbol.
Let me know if you need proper
option modulessupport. It wouldn't be that hard to add.
The test suite failures (should be the only ones) for the following Blackfin defconfigs on e.g. Linux 3.7.0-rc8 are due to a bug in the C implementation:
- To RomaVis, for making
pymenuconfig and suggesting
- To Mitja Horvat, for adding support for user-defined styles to the terminal menuconfig.
- To Philip Craig for adding
support for the
allnoconfig_yoption and fixing an obscure issue with
choices (that didn't affect correctness but made outputs differ).
allnoconfig_yis used to force certain symbols to
make allnoconfigto improve coverage.
See LICENSE.txt. SPDX license identifiers are used in the source code.