[Add] 打通Kconfiglib配置操作
This commit is contained in:
102
scripts/kconfig/Kconfiglib/examples/Kmenuconfig
Normal file
102
scripts/kconfig/Kconfiglib/examples/Kmenuconfig
Normal file
@ -0,0 +1,102 @@
|
||||
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
|
||||
66
scripts/kconfig/Kconfiglib/examples/allnoconfig_walk.py
Normal file
66
scripts/kconfig/Kconfiglib/examples/allnoconfig_walk.py
Normal file
@ -0,0 +1,66 @@
|
||||
# This is tree-walking version of allnoconfig.py, for demonstration purposes.
|
||||
# Verified by the test suite to generate identical output to 'make allnoconfig'
|
||||
# for all ARCHes.
|
||||
#
|
||||
# Note: A more practical version would use Kconfig.node_iter(). The manual tree
|
||||
# walking is for demonstration purposes.
|
||||
#
|
||||
# Usage for the Linux kernel:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/allnoconfig_walk.py
|
||||
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, Symbol
|
||||
|
||||
|
||||
def do_allnoconfig(node):
|
||||
global changed
|
||||
|
||||
# Walk the tree of menu nodes. You can imagine this as going down/into menu
|
||||
# entries in the menuconfig interface, setting each to n (or the lowest
|
||||
# assignable value).
|
||||
|
||||
while node:
|
||||
if isinstance(node.item, Symbol):
|
||||
sym = node.item
|
||||
|
||||
# Is the symbol a non-allnoconfig_y symbol that can be set to a
|
||||
# lower value than its current value?
|
||||
if (not sym.is_allnoconfig_y and
|
||||
sym.assignable and
|
||||
sym.assignable[0] < sym.tri_value):
|
||||
|
||||
# Yup, lower it
|
||||
sym.set_value(sym.assignable[0])
|
||||
changed = True
|
||||
|
||||
# Recursively lower children
|
||||
if node.list:
|
||||
do_allnoconfig(node.list)
|
||||
|
||||
node = node.next
|
||||
|
||||
|
||||
# Parse the Kconfig files
|
||||
kconf = Kconfig(sys.argv[1])
|
||||
|
||||
# Do an initial pass to set 'option allnoconfig_y' symbols to y
|
||||
for sym in kconf.unique_defined_syms:
|
||||
if sym.is_allnoconfig_y:
|
||||
sym.set_value(2)
|
||||
|
||||
while True:
|
||||
# Changing later symbols in the configuration can sometimes allow earlier
|
||||
# symbols to be lowered, e.g. if a later symbol 'select's an earlier
|
||||
# symbol. To handle such situations, we do additional passes over the tree
|
||||
# until we're no longer able to change the value of any symbol in a pass.
|
||||
changed = False
|
||||
|
||||
do_allnoconfig(kconf.top_node)
|
||||
|
||||
# Did the pass change any symbols?
|
||||
if not changed:
|
||||
break
|
||||
|
||||
print(kconf.write_config())
|
||||
39
scripts/kconfig/Kconfiglib/examples/defconfig_oldconfig.py
Normal file
39
scripts/kconfig/Kconfiglib/examples/defconfig_oldconfig.py
Normal file
@ -0,0 +1,39 @@
|
||||
# Produces exactly the same output as the following script:
|
||||
#
|
||||
# make defconfig
|
||||
# echo CONFIG_ETHERNET=n >> .config
|
||||
# make oldconfig
|
||||
# echo CONFIG_ETHERNET=y >> .config
|
||||
# yes n | make oldconfig
|
||||
#
|
||||
# This came up in https://github.com/ulfalizer/Kconfiglib/issues/15.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/defconfig_oldconfig.py
|
||||
|
||||
import sys
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
kconf = kconfiglib.Kconfig(sys.argv[1])
|
||||
|
||||
# Mirrors defconfig
|
||||
kconf.load_config("arch/x86/configs/x86_64_defconfig")
|
||||
kconf.write_config()
|
||||
|
||||
# Mirrors the first oldconfig
|
||||
kconf.load_config()
|
||||
kconf.syms["ETHERNET"].set_value(0)
|
||||
kconf.write_config()
|
||||
|
||||
# Mirrors the second oldconfig
|
||||
kconf.load_config()
|
||||
kconf.syms["ETHERNET"].set_value(2)
|
||||
for s in kconf.unique_defined_syms:
|
||||
if s.user_value is None and 0 in s.assignable:
|
||||
s.set_value(0)
|
||||
|
||||
# Write the final configuration
|
||||
print(kconf.write_config())
|
||||
15
scripts/kconfig/Kconfiglib/examples/dumpvars.py
Normal file
15
scripts/kconfig/Kconfiglib/examples/dumpvars.py
Normal file
@ -0,0 +1,15 @@
|
||||
# Prints all (set) environment variables referenced in the Kconfig files
|
||||
# together with their values, as a list of assignments.
|
||||
#
|
||||
# Note: This only works for environment variables referenced via the $(FOO)
|
||||
# preprocessor syntax. The older $FOO syntax is maintained for backwards
|
||||
# compatibility.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
print(" ".join("{}='{}'".format(var, os.environ[var])
|
||||
for var in kconfiglib.Kconfig(sys.argv[1]).env_vars))
|
||||
24
scripts/kconfig/Kconfiglib/examples/eval_expr.py
Normal file
24
scripts/kconfig/Kconfiglib/examples/eval_expr.py
Normal file
@ -0,0 +1,24 @@
|
||||
# Evaluates an expression (e.g. "X86_64 || (X86_32 && X86_LOCAL_APIC)") in the
|
||||
# context of a configuration. Note that this always yields a tristate value (n,
|
||||
# m, or y).
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/eval_expr.py SCRIPT_ARG=<expr>
|
||||
|
||||
import sys
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
sys.exit("Pass the expression to evaluate with SCRIPT_ARG=<expression>")
|
||||
|
||||
kconf = kconfiglib.Kconfig(sys.argv[1])
|
||||
expr = sys.argv[2]
|
||||
|
||||
# Enable modules so that m doesn't get demoted to n
|
||||
kconf.modules.set_value(2)
|
||||
|
||||
print("the expression '{}' evaluates to {}"
|
||||
.format(expr, kconf.eval_string(expr)))
|
||||
112
scripts/kconfig/Kconfiglib/examples/find_symbol.py
Normal file
112
scripts/kconfig/Kconfiglib/examples/find_symbol.py
Normal file
@ -0,0 +1,112 @@
|
||||
# Prints all menu nodes that reference a given symbol any of their properties
|
||||
# or property conditions, along with their parent menu nodes.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/find_symbol.py SCRIPT_ARG=<name>
|
||||
#
|
||||
# Example output for SCRIPT_ARG=X86:
|
||||
#
|
||||
# Found 470 locations that reference X86:
|
||||
#
|
||||
# ========== Location 1 (init/Kconfig:1108) ==========
|
||||
#
|
||||
# config SGETMASK_SYSCALL
|
||||
# bool
|
||||
# prompt "sgetmask/ssetmask syscalls support" if EXPERT
|
||||
# default PARISC || M68K || PPC || MIPS || X86 || SPARC || MICROBLAZE || SUPERH
|
||||
# help
|
||||
# sys_sgetmask and sys_ssetmask are obsolete system calls
|
||||
# no longer supported in libc but still enabled by default in some
|
||||
# architectures.
|
||||
#
|
||||
# If unsure, leave the default option here.
|
||||
#
|
||||
# ---------- Parent 1 (init/Kconfig:1077) ----------
|
||||
#
|
||||
# menuconfig EXPERT
|
||||
# bool
|
||||
# prompt "Configure standard kernel features (expert users)"
|
||||
# select DEBUG_KERNEL
|
||||
# help
|
||||
# This option allows certain base kernel options and settings
|
||||
# to be disabled or tweaked. This is for specialized
|
||||
# environments which can tolerate a "non-standard" kernel.
|
||||
# Only use this if you really know what you are doing.
|
||||
#
|
||||
# ---------- Parent 2 (init/Kconfig:39) ----------
|
||||
#
|
||||
# menu "General setup"
|
||||
#
|
||||
# ========== Location 2 (arch/Kconfig:29) ==========
|
||||
#
|
||||
# config OPROFILE_EVENT_MULTIPLEX
|
||||
# bool
|
||||
# prompt "OProfile multiplexing support (EXPERIMENTAL)"
|
||||
# default "n"
|
||||
# depends on OPROFILE && X86
|
||||
# help
|
||||
# The number of hardware counters is limited. The multiplexing
|
||||
# feature enables OProfile to gather more events than counters
|
||||
# are provided by the hardware. This is realized by switching
|
||||
# between events at a user specified time interval.
|
||||
#
|
||||
# If unsure, say N.
|
||||
#
|
||||
# ---------- Parent 1 (arch/Kconfig:16) ----------
|
||||
#
|
||||
# config OPROFILE
|
||||
# tristate
|
||||
# prompt "OProfile system profiling"
|
||||
# select RING_BUFFER
|
||||
# select RING_BUFFER_ALLOW_SWAP
|
||||
# depends on PROFILING && HAVE_OPROFILE
|
||||
# help
|
||||
# OProfile is a profiling system capable of profiling the
|
||||
# whole system, include the kernel, kernel modules, libraries,
|
||||
# and applications.
|
||||
#
|
||||
# If unsure, say N.
|
||||
#
|
||||
# ---------- Parent 2 (init/Kconfig:39) ----------
|
||||
#
|
||||
# menu "General setup"
|
||||
#
|
||||
# ... (tons more)
|
||||
|
||||
import sys
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
sys.exit('Pass symbol name (without "CONFIG_" prefix) with SCRIPT_ARG=<name>')
|
||||
|
||||
kconf = kconfiglib.Kconfig(sys.argv[1])
|
||||
sym_name = sys.argv[2]
|
||||
if sym_name not in kconf.syms:
|
||||
print("No symbol {} exists in the configuration".format(sym_name))
|
||||
sys.exit(0)
|
||||
|
||||
referencing = [node for node in kconf.node_iter()
|
||||
if kconf.syms[sym_name] in node.referenced]
|
||||
if not referencing:
|
||||
print("No references to {} found".format(sym_name))
|
||||
sys.exit(0)
|
||||
|
||||
print("Found {} locations that reference {}:\n"
|
||||
.format(len(referencing), sym_name))
|
||||
|
||||
for i, node in enumerate(referencing, 1):
|
||||
print("========== Location {} ({}:{}) ==========\n\n{}"
|
||||
.format(i, node.filename, node.linenr, node))
|
||||
|
||||
# Print the parents of the menu node too
|
||||
|
||||
node = node.parent
|
||||
parent_i = 1
|
||||
while node is not kconf.top_node:
|
||||
print("---------- Parent {} ({}:{}) ----------\n\n{}"
|
||||
.format(parent_i, node.filename, node.linenr, node))
|
||||
node = node.parent
|
||||
parent_i += 1
|
||||
64
scripts/kconfig/Kconfiglib/examples/help_grep.py
Normal file
64
scripts/kconfig/Kconfiglib/examples/help_grep.py
Normal file
@ -0,0 +1,64 @@
|
||||
# Does a case-insensitive search for a regular expression in the help texts of
|
||||
# symbols and choices and the prompts of menus and comments. Prints the
|
||||
# matching items together with their locations and the matching text.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG=<regex>
|
||||
#
|
||||
# Shortened example output for SCRIPT_ARG=general:
|
||||
#
|
||||
# menu "General setup"
|
||||
# location: init/Kconfig:39
|
||||
#
|
||||
# config SYSVIPC
|
||||
# bool
|
||||
# prompt "System V IPC"
|
||||
# help
|
||||
# ...
|
||||
# exchange information. It is generally considered to be a good thing,
|
||||
# ...
|
||||
#
|
||||
# location: init/Kconfig:233
|
||||
#
|
||||
# config BSD_PROCESS_ACCT
|
||||
# bool
|
||||
# prompt "BSD Process Accounting" if MULTIUSER
|
||||
# help
|
||||
# ...
|
||||
# information. This is generally a good idea, so say Y.
|
||||
#
|
||||
# location: init/Kconfig:403
|
||||
#
|
||||
# ...
|
||||
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, Symbol, Choice, MENU, COMMENT
|
||||
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
sys.exit("Pass the regex with SCRIPT_ARG=<regex>")
|
||||
|
||||
search = re.compile(sys.argv[2], re.IGNORECASE).search
|
||||
|
||||
for node in Kconfig(sys.argv[1]).node_iter():
|
||||
match = False
|
||||
|
||||
if isinstance(node.item, (Symbol, Choice)) and \
|
||||
node.help is not None and search(node.help):
|
||||
print(node.item)
|
||||
match = True
|
||||
|
||||
elif node.item == MENU and search(node.prompt[0]):
|
||||
print('menu "{}"'.format(node.prompt[0]))
|
||||
match = True
|
||||
|
||||
elif node.item == COMMENT and search(node.prompt[0]):
|
||||
print('comment "{}"'.format(node.prompt[0]))
|
||||
match = True
|
||||
|
||||
if match:
|
||||
print("location: {}:{}\n".format(node.filename, node.linenr))
|
||||
1
scripts/kconfig/Kconfiglib/examples/kconfiglib.py
Symbolic link
1
scripts/kconfig/Kconfiglib/examples/kconfiglib.py
Symbolic link
@ -0,0 +1 @@
|
||||
../kconfiglib.py
|
||||
156
scripts/kconfig/Kconfiglib/examples/list_undefined.py
Normal file
156
scripts/kconfig/Kconfiglib/examples/list_undefined.py
Normal file
@ -0,0 +1,156 @@
|
||||
# Prints a list of symbols that are referenced in the Kconfig files of some
|
||||
# architecture but not defined by the Kconfig files of any architecture.
|
||||
#
|
||||
# A Kconfig file might be shared between many architectures and legitimately
|
||||
# reference undefined symbols for some of them, but if no architecture defines
|
||||
# the symbol, it usually indicates a problem or potential cleanup.
|
||||
#
|
||||
# This script could be sped up a lot if needed. See the comment near the
|
||||
# referencing_nodes() call.
|
||||
#
|
||||
# Run with the following command in the kernel root:
|
||||
#
|
||||
# $ python(3) Kconfiglib/examples/list_undefined.py
|
||||
#
|
||||
# Example output:
|
||||
#
|
||||
# Registering defined and undefined symbols for all arches
|
||||
# Processing mips
|
||||
# Processing ia64
|
||||
# Processing metag
|
||||
# ...
|
||||
#
|
||||
# Finding references to each undefined symbol
|
||||
# Processing mips
|
||||
# Processing ia64
|
||||
# Processing metag
|
||||
# ...
|
||||
#
|
||||
# The following globally undefined symbols were found, listed here
|
||||
# together with the locations of the items that reference them.
|
||||
# References might come from enclosing menus and ifs.
|
||||
#
|
||||
# ARM_ERRATA_753970: arch/arm/mach-mvebu/Kconfig:56, arch/arm/mach-mvebu/Kconfig:39
|
||||
# SUNXI_CCU_MP: drivers/clk/sunxi-ng/Kconfig:14
|
||||
# SUNXI_CCU_DIV: drivers/clk/sunxi-ng/Kconfig:14
|
||||
# AC97: sound/ac97/Kconfig:6
|
||||
# ...
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from kconfiglib import Kconfig
|
||||
|
||||
|
||||
# Referenced inside the Kconfig files
|
||||
os.environ["KERNELVERSION"] = str(
|
||||
subprocess.check_output(("make", "kernelversion")).decode("utf-8").rstrip()
|
||||
)
|
||||
|
||||
|
||||
def all_arch_srcarch_pairs():
|
||||
"""
|
||||
Generates all valid (ARCH, SRCARCH) tuples for the kernel, corresponding to
|
||||
different architectures. SRCARCH holds the arch/ subdirectory.
|
||||
"""
|
||||
for srcarch in os.listdir("arch"):
|
||||
# Each subdirectory of arch/ containing a Kconfig file corresponds to
|
||||
# an architecture
|
||||
if os.path.exists(os.path.join("arch", srcarch, "Kconfig")):
|
||||
yield (srcarch, srcarch)
|
||||
|
||||
# Some architectures define additional ARCH settings with ARCH != SRCARCH
|
||||
# (search for "Additional ARCH settings for" in the top-level Makefile)
|
||||
|
||||
yield ("i386", "x86")
|
||||
yield ("x86_64", "x86")
|
||||
|
||||
yield ("sparc32", "sparc")
|
||||
yield ("sparc64", "sparc")
|
||||
|
||||
yield ("sh64", "sh")
|
||||
|
||||
yield ("um", "um")
|
||||
|
||||
|
||||
def all_arch_srcarch_kconfigs():
|
||||
"""
|
||||
Generates Kconfig instances for all the architectures in the kernel
|
||||
"""
|
||||
|
||||
os.environ["srctree"] = "."
|
||||
os.environ["HOSTCC"] = "gcc"
|
||||
os.environ["HOSTCXX"] = "g++"
|
||||
os.environ["CC"] = "gcc"
|
||||
os.environ["LD"] = "ld"
|
||||
|
||||
for arch, srcarch in all_arch_srcarch_pairs():
|
||||
print(" Processing " + arch)
|
||||
|
||||
os.environ["ARCH"] = arch
|
||||
os.environ["SRCARCH"] = srcarch
|
||||
|
||||
# um (User Mode Linux) uses a different base Kconfig file
|
||||
yield Kconfig("Kconfig" if arch != "um" else "arch/x86/um/Kconfig",
|
||||
warn=False)
|
||||
|
||||
|
||||
print("Registering defined and undefined symbols for all arches")
|
||||
|
||||
# Sets holding the names of all defined and undefined symbols, for all
|
||||
# architectures
|
||||
defined = set()
|
||||
undefined = set()
|
||||
|
||||
for kconf in all_arch_srcarch_kconfigs():
|
||||
for name, sym in kconf.syms.items():
|
||||
if sym.nodes:
|
||||
# If the symbol has a menu node, it is defined
|
||||
defined.add(name)
|
||||
else:
|
||||
# Undefined symbol. We skip some of the uninteresting ones.
|
||||
|
||||
# Due to how Kconfig works, integer literals show up as symbols
|
||||
# (from e.g. 'default 1'). Skip those.
|
||||
try:
|
||||
int(name, 0)
|
||||
continue
|
||||
except ValueError:
|
||||
# Interesting undefined symbol
|
||||
undefined.add(name)
|
||||
|
||||
|
||||
print("\nFinding references to each undefined symbol")
|
||||
|
||||
def referencing_nodes(kconf, name):
|
||||
# Returns a list of all menu nodes that reference a symbol named 'name' in
|
||||
# any of their properties or property conditions
|
||||
res = []
|
||||
|
||||
for node in kconf.node_iter():
|
||||
for ref in node.referenced:
|
||||
if ref.name == name:
|
||||
res.append(node)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
# Maps each globally undefined symbol to the menu nodes that reference it
|
||||
undef_sym_refs = [(name, set()) for name in undefined - defined]
|
||||
|
||||
for kconf in all_arch_srcarch_kconfigs():
|
||||
for name, refs in undef_sym_refs:
|
||||
# This means that we search the entire configuration tree for each
|
||||
# undefined symbol, which is terribly inefficient. We could speed
|
||||
# things up by tweaking referencing_nodes() to compare each symbol to
|
||||
# multiple symbols while walking the configuration tree.
|
||||
for node in referencing_nodes(kconf, name):
|
||||
refs.add("{}:{}".format(node.filename, node.linenr))
|
||||
|
||||
|
||||
print("\nThe following globally undefined symbols were found, listed here\n"
|
||||
"together with the locations of the items that reference them.\n"
|
||||
"References might come from enclosing menus and ifs.\n")
|
||||
|
||||
for name, refs in undef_sym_refs:
|
||||
print(" {}: {}".format(name, ", ".join(refs)))
|
||||
341
scripts/kconfig/Kconfiglib/examples/menuconfig_example.py
Executable file
341
scripts/kconfig/Kconfiglib/examples/menuconfig_example.py
Executable file
@ -0,0 +1,341 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Implements a simple configuration interface on top of Kconfiglib to
|
||||
# demonstrate concepts for building a menuconfig-like. Emulates how the
|
||||
# standard menuconfig prints menu entries.
|
||||
#
|
||||
# Always displays the entire Kconfig tree to keep things as simple as possible
|
||||
# (all symbols, choices, menus, and comments).
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ python(3) Kconfiglib/examples/menuconfig.py <Kconfig file>
|
||||
#
|
||||
# A sample Kconfig is available in Kconfiglib/examples/Kmenuconfig.
|
||||
#
|
||||
# Here's a notation guide. The notation matches the one used by menuconfig
|
||||
# (scripts/kconfig/mconf):
|
||||
#
|
||||
# [ ] prompt - Bool
|
||||
# < > prompt - Tristate
|
||||
# {M} prompt - Tristate selected to m. Can only be set to m or y.
|
||||
# -*- prompt - Bool/tristate selected to y, pinning it
|
||||
# -M- prompt - Tristate selected to m that also has m visibility,
|
||||
# pinning it to m
|
||||
# (foo) prompt - String/int/hex symbol with value "foo"
|
||||
# --> prompt - The selected symbol in a choice in y mode. This
|
||||
# syntax is unique to this example.
|
||||
#
|
||||
# When modules are disabled, the .type attribute of TRISTATE symbols and
|
||||
# choices automatically changes to BOOL. This trick is used by the C
|
||||
# implementation as well, and gives the expected behavior without having to do
|
||||
# anything extra here. The original type is available in .orig_type if needed.
|
||||
#
|
||||
# The Kconfiglib/examples/Kmenuconfig example uses named choices to be able to
|
||||
# refer to choices by name. Named choices are supported in the C tools too, but
|
||||
# I don't think I've ever seen them used in the wild.
|
||||
#
|
||||
# Sample session:
|
||||
#
|
||||
# $ python Kconfiglib/examples/menuconfig.py Kconfiglib/examples/Kmenuconfig
|
||||
#
|
||||
# ======== Example Kconfig configuration ========
|
||||
#
|
||||
# [*] Enable loadable module support (MODULES)
|
||||
# Bool and tristate symbols
|
||||
# [*] Bool symbol (BOOL)
|
||||
# [ ] Dependent bool symbol (BOOL_DEP)
|
||||
# < > Dependent tristate symbol (TRI_DEP)
|
||||
# [ ] First prompt (TWO_MENU_NODES)
|
||||
# < > Tristate symbol (TRI)
|
||||
# [ ] Second prompt (TWO_MENU_NODES)
|
||||
# *** These are selected by TRI_DEP ***
|
||||
# < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP)
|
||||
# < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP)
|
||||
# String, int, and hex symbols
|
||||
# (foo) String symbol (STRING)
|
||||
# (747) Int symbol (INT)
|
||||
# (0xABC) Hex symbol (HEX)
|
||||
# Various choices
|
||||
# -*- Bool choice (BOOL_CHOICE)
|
||||
# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1)
|
||||
# Bool choice sym 2 (BOOL_CHOICE_SYM_2)
|
||||
# {M} Tristate choice (TRI_CHOICE)
|
||||
# < > Tristate choice sym 1 (TRI_CHOICE_SYM_1)
|
||||
# < > Tristate choice sym 2 (TRI_CHOICE_SYM_2)
|
||||
# [ ] Optional bool choice (OPT_BOOL_CHOICE)
|
||||
#
|
||||
# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): BOOL
|
||||
# Value for BOOL (available: n, y): n
|
||||
#
|
||||
# ======== Example Kconfig configuration ========
|
||||
#
|
||||
# [*] Enable loadable module support (MODULES)
|
||||
# Bool and tristate symbols
|
||||
# [ ] Bool symbol (BOOL)
|
||||
# < > Tristate symbol (TRI)
|
||||
# [ ] Second prompt (TWO_MENU_NODES)
|
||||
# *** These are selected by TRI_DEP ***
|
||||
# < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP)
|
||||
# < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP)
|
||||
# String, int, and hex symbols
|
||||
# (foo) String symbol (STRING)
|
||||
# (747) Int symbol (INT)
|
||||
# (0xABC) Hex symbol (HEX)
|
||||
# Various choices
|
||||
# -*- Bool choice (BOOL_CHOICE)
|
||||
# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1)
|
||||
# Bool choice sym 2 (BOOL_CHOICE_SYM_2)
|
||||
# {M} Tristate choice (TRI_CHOICE)
|
||||
# < > Tristate choice sym 1 (TRI_CHOICE_SYM_1)
|
||||
# < > Tristate choice sym 2 (TRI_CHOICE_SYM_2)
|
||||
# [ ] Optional bool choice (OPT_BOOL_CHOICE)
|
||||
#
|
||||
# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): MODULES
|
||||
# Value for MODULES (available: n, y): n
|
||||
#
|
||||
# ======== Example Kconfig configuration ========
|
||||
#
|
||||
# [ ] Enable loadable module support (MODULES)
|
||||
# Bool and tristate symbols
|
||||
# [ ] Bool symbol (BOOL)
|
||||
# [ ] Tristate symbol (TRI)
|
||||
# [ ] Second prompt (TWO_MENU_NODES)
|
||||
# *** These are selected by TRI_DEP ***
|
||||
# [ ] Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP)
|
||||
# [ ] Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP)
|
||||
# String, int, and hex symbols
|
||||
# (foo) String symbol (STRING)
|
||||
# (747) Int symbol (INT)
|
||||
# (0xABC) Hex symbol (HEX)
|
||||
# Various choices
|
||||
# -*- Bool choice (BOOL_CHOICE)
|
||||
# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1)
|
||||
# Bool choice sym 2 (BOOL_CHOICE_SYM_2)
|
||||
# -*- Tristate choice (TRI_CHOICE)
|
||||
# --> Tristate choice sym 1 (TRI_CHOICE_SYM_1)
|
||||
# Tristate choice sym 2 (TRI_CHOICE_SYM_2)
|
||||
# [ ] Optional bool choice (OPT_BOOL_CHOICE)
|
||||
#
|
||||
# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): ^D
|
||||
|
||||
from __future__ import print_function
|
||||
import readline
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, \
|
||||
Symbol, MENU, COMMENT, \
|
||||
BOOL, TRISTATE, STRING, INT, HEX, UNKNOWN, \
|
||||
expr_value, \
|
||||
TRI_TO_STR
|
||||
|
||||
|
||||
# Python 2/3 compatibility hack
|
||||
if sys.version_info[0] < 3:
|
||||
input = raw_input
|
||||
|
||||
|
||||
def indent_print(s, indent):
|
||||
print(indent*" " + s)
|
||||
|
||||
|
||||
def value_str(sc):
|
||||
"""
|
||||
Returns the value part ("[*]", "<M>", "(foo)" etc.) of a menu entry.
|
||||
|
||||
sc: Symbol or Choice.
|
||||
"""
|
||||
if sc.type in (STRING, INT, HEX):
|
||||
return "({})".format(sc.str_value)
|
||||
|
||||
# BOOL or TRISTATE
|
||||
|
||||
# The choice mode is an upper bound on the visibility of choice symbols, so
|
||||
# we can check the choice symbols' own visibility to see if the choice is
|
||||
# in y mode
|
||||
if isinstance(sc, Symbol) and sc.choice and sc.visibility == 2:
|
||||
# For choices in y mode, print '-->' next to the selected symbol
|
||||
return "-->" if sc.choice.selection is sc else " "
|
||||
|
||||
tri_val_str = (" ", "M", "*")[sc.tri_value]
|
||||
|
||||
if len(sc.assignable) == 1:
|
||||
# Pinned to a single value
|
||||
return "-{}-".format(tri_val_str)
|
||||
|
||||
if sc.type == BOOL:
|
||||
return "[{}]".format(tri_val_str)
|
||||
|
||||
if sc.type == TRISTATE:
|
||||
if sc.assignable == (1, 2):
|
||||
# m and y available
|
||||
return "{" + tri_val_str + "}" # Gets a bit confusing with .format()
|
||||
return "<{}>".format(tri_val_str)
|
||||
|
||||
|
||||
def node_str(node):
|
||||
"""
|
||||
Returns the complete menu entry text for a menu node, or "" for invisible
|
||||
menu nodes. Invisible menu nodes are those that lack a prompt or that do
|
||||
not have a satisfied prompt condition.
|
||||
|
||||
Example return value: "[*] Bool symbol (BOOL)"
|
||||
|
||||
The symbol name is printed in parentheses to the right of the prompt. This
|
||||
is so that symbols can easily be referred to in the configuration
|
||||
interface.
|
||||
"""
|
||||
if not node.prompt:
|
||||
return ""
|
||||
|
||||
# Even for menu nodes for symbols and choices, it's wrong to check
|
||||
# Symbol.visibility / Choice.visibility here. The reason is that a symbol
|
||||
# (and a choice, in theory) can be defined in multiple locations, giving it
|
||||
# multiple menu nodes, which do not necessarily all have the same prompt
|
||||
# visibility. Symbol.visibility / Choice.visibility is calculated as the OR
|
||||
# of the visibility of all the prompts.
|
||||
prompt, prompt_cond = node.prompt
|
||||
if not expr_value(prompt_cond):
|
||||
return ""
|
||||
|
||||
if node.item == MENU:
|
||||
return " " + prompt
|
||||
|
||||
if node.item == COMMENT:
|
||||
return " *** {} ***".format(prompt)
|
||||
|
||||
# Symbol or Choice
|
||||
|
||||
sc = node.item
|
||||
|
||||
if sc.type == UNKNOWN:
|
||||
# Skip symbols defined without a type (these are obscure and generate
|
||||
# a warning)
|
||||
return ""
|
||||
|
||||
# {:3} sets the field width to three. Gives nice alignment for empty string
|
||||
# values.
|
||||
res = "{:3} {}".format(value_str(sc), prompt)
|
||||
|
||||
# Don't print the name for unnamed choices (the normal kind)
|
||||
if sc.name is not None:
|
||||
res += " ({})".format(sc.name)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def print_menuconfig_nodes(node, indent):
|
||||
"""
|
||||
Prints a tree with all the menu entries rooted at 'node'. Child menu
|
||||
entries are indented.
|
||||
"""
|
||||
while node:
|
||||
string = node_str(node)
|
||||
if string:
|
||||
indent_print(string, indent)
|
||||
|
||||
if node.list:
|
||||
print_menuconfig_nodes(node.list, indent + 8)
|
||||
|
||||
node = node.next
|
||||
|
||||
|
||||
def print_menuconfig(kconf):
|
||||
"""
|
||||
Prints all menu entries for the configuration.
|
||||
"""
|
||||
# Print the expanded mainmenu text at the top. This is the same as
|
||||
# kconf.top_node.prompt[0], but with variable references expanded.
|
||||
print("\n======== {} ========\n".format(kconf.mainmenu_text))
|
||||
|
||||
print_menuconfig_nodes(kconf.top_node.list, 0)
|
||||
print("")
|
||||
|
||||
|
||||
def get_value_from_user(sc):
|
||||
"""
|
||||
Prompts the user for a value for the symbol or choice 'sc'. For
|
||||
bool/tristate symbols and choices, provides a list of all the assignable
|
||||
values.
|
||||
"""
|
||||
if not sc.visibility:
|
||||
print(sc.name + " is not currently visible")
|
||||
return False
|
||||
|
||||
prompt = "Value for {}".format(sc.name)
|
||||
if sc.type in (BOOL, TRISTATE):
|
||||
prompt += " (available: {})" \
|
||||
.format(", ".join(TRI_TO_STR[val] for val in sc.assignable))
|
||||
prompt += ": "
|
||||
|
||||
val = input(prompt)
|
||||
|
||||
# Automatically add a "0x" prefix for hex symbols, like the menuconfig
|
||||
# interface does. This isn't done when loading .config files, hence why
|
||||
# set_value() doesn't do it automatically.
|
||||
if sc.type == HEX and not val.startswith(("0x", "0X")):
|
||||
val = "0x" + val
|
||||
|
||||
# Let Kconfiglib itself print a warning here if the value is invalid. We
|
||||
# could also disable warnings temporarily with 'kconf.warn = False' and
|
||||
# print our own warning.
|
||||
return sc.set_value(val)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
sys.exit("usage: menuconfig.py <Kconfig file>")
|
||||
|
||||
# Load Kconfig configuration files
|
||||
kconf = Kconfig(sys.argv[1])
|
||||
|
||||
# Print the initial configuration tree
|
||||
print_menuconfig(kconf)
|
||||
|
||||
while True:
|
||||
try:
|
||||
cmd = input('Enter a symbol/choice name, "load_config", or '
|
||||
'"write_config" (or press CTRL+D to exit): ').strip()
|
||||
except EOFError:
|
||||
print("")
|
||||
break
|
||||
|
||||
if cmd == "load_config":
|
||||
config_filename = input(".config file to load: ")
|
||||
try:
|
||||
# Returns a message telling which file got loaded
|
||||
print(kconf.load_config(config_filename))
|
||||
except EnvironmentError as e:
|
||||
print(e, file=sys.stderr)
|
||||
|
||||
print_menuconfig(kconf)
|
||||
continue
|
||||
|
||||
if cmd == "write_config":
|
||||
config_filename = input("To this file: ")
|
||||
try:
|
||||
# Returns a message telling which file got saved
|
||||
print(kconf.write_config(config_filename))
|
||||
except EnvironmentError as e:
|
||||
print(e, file=sys.stderr)
|
||||
|
||||
continue
|
||||
|
||||
# Assume 'cmd' is the name of a symbol or choice if it isn't one of the
|
||||
# commands above, prompt the user for a value for it, and print the new
|
||||
# configuration tree
|
||||
|
||||
if cmd in kconf.syms:
|
||||
if get_value_from_user(kconf.syms[cmd]):
|
||||
print_menuconfig(kconf)
|
||||
|
||||
continue
|
||||
|
||||
if cmd in kconf.named_choices:
|
||||
if get_value_from_user(kconf.named_choices[cmd]):
|
||||
print_menuconfig(kconf)
|
||||
|
||||
continue
|
||||
|
||||
print("No symbol/choice named '{}' in the configuration".format(cmd),
|
||||
file=sys.stderr)
|
||||
121
scripts/kconfig/Kconfiglib/examples/merge_config.py
Executable file
121
scripts/kconfig/Kconfiglib/examples/merge_config.py
Executable file
@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# This script functions similarly to scripts/kconfig/merge_config.sh from the
|
||||
# kernel tree, merging multiple configurations fragments to produce a complete
|
||||
# .config, with unspecified values filled in as for alldefconfig.
|
||||
#
|
||||
# The generated .config respects symbol dependencies, and a warning is printed
|
||||
# if any symbol gets a different value from the assigned value.
|
||||
#
|
||||
# For a real-world merging example based on this script, see
|
||||
# https://github.com/zephyrproject-rtos/zephyr/blob/master/scripts/kconfig/kconfig.py.
|
||||
#
|
||||
# Here's a demo:
|
||||
#
|
||||
# Kconfig contents:
|
||||
#
|
||||
# config FOO
|
||||
# bool "FOO"
|
||||
#
|
||||
# config BAR
|
||||
# bool "BAR"
|
||||
#
|
||||
# config BAZ
|
||||
# string "BAZ"
|
||||
#
|
||||
# config QAZ
|
||||
# bool "QAZ" if n
|
||||
#
|
||||
#
|
||||
# conf1 contents:
|
||||
#
|
||||
# CONFIG_FOO=y
|
||||
#
|
||||
#
|
||||
# conf2 contents:
|
||||
#
|
||||
# CONFIG_BAR=y
|
||||
#
|
||||
#
|
||||
# conf3 contents:
|
||||
#
|
||||
# # Assigned twice (would generate warning if 'warn_assign_override' was
|
||||
# # True)
|
||||
# # CONFIG_FOO is not set
|
||||
#
|
||||
# # Ops... this symbol doesn't exist
|
||||
# CONFIG_OPS=y
|
||||
#
|
||||
# CONFIG_BAZ="baz string"
|
||||
#
|
||||
#
|
||||
# conf4 contents:
|
||||
#
|
||||
# CONFIG_QAZ=y
|
||||
#
|
||||
#
|
||||
# Running:
|
||||
#
|
||||
# $ python(3) merge_config.py Kconfig merged conf1 conf2 conf3 conf4
|
||||
# Merged configuration 'conf1'
|
||||
# Merged configuration 'conf2'
|
||||
# conf3:5: warning: attempt to assign the value 'y' to the undefined symbol OPS
|
||||
# Merged configuration 'conf3'
|
||||
# Merged configuration 'conf4'
|
||||
# Configuration saved to 'merged'
|
||||
# warning: QAZ (defined at Kconfig:10) was assigned the value 'y' but got the value 'n' -- check dependencies
|
||||
# $ cat merged
|
||||
# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)
|
||||
# # CONFIG_FOO is not set
|
||||
# CONFIG_BAR=y
|
||||
# CONFIG_BAZ="baz string"
|
||||
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, BOOL, TRISTATE, TRI_TO_STR
|
||||
|
||||
|
||||
if len(sys.argv) < 4:
|
||||
sys.exit("usage: merge_config.py Kconfig merged_config config1 [config2 ...]")
|
||||
|
||||
kconf = Kconfig(sys.argv[1], suppress_traceback=True)
|
||||
|
||||
# Enable warnings for assignments to undefined symbols
|
||||
kconf.warn_assign_undef = True
|
||||
|
||||
# (This script uses alldefconfig as the base. Other starting states could be
|
||||
# set up here as well. The approach in examples/allnoconfig_simpler.py could
|
||||
# provide an allnoconfig starting state for example.)
|
||||
|
||||
# Disable warnings generated for multiple assignments to the same symbol within
|
||||
# a (set of) configuration files. Assigning a symbol multiple times might be
|
||||
# done intentionally when merging configuration files.
|
||||
kconf.warn_assign_override = False
|
||||
kconf.warn_assign_redun = False
|
||||
|
||||
# Create a merged configuration by loading the fragments with replace=False.
|
||||
# load_config() and write_config() returns a message to print.
|
||||
for config in sys.argv[3:]:
|
||||
print(kconf.load_config(config, replace=False))
|
||||
|
||||
# Write the merged configuration
|
||||
print(kconf.write_config(sys.argv[2]))
|
||||
|
||||
# Print warnings for symbols whose actual value doesn't match the assigned
|
||||
# value
|
||||
for sym in kconf.defined_syms:
|
||||
# Was the symbol assigned to?
|
||||
if sym.user_value is not None:
|
||||
# Tristate values are represented as 0, 1, 2. Having them as
|
||||
# "n", "m", "y" is more convenient here, so convert.
|
||||
if sym.type in (BOOL, TRISTATE):
|
||||
user_value = TRI_TO_STR[sym.user_value]
|
||||
else:
|
||||
user_value = sym.user_value
|
||||
|
||||
if user_value != sym.str_value:
|
||||
print("warning: {} was assigned the value '{}' but got the "
|
||||
"value '{}' -- check dependencies".format(
|
||||
sym.name_and_loc, user_value, sym.str_value),
|
||||
file=sys.stderr)
|
||||
199
scripts/kconfig/Kconfiglib/examples/print_config_tree.py
Normal file
199
scripts/kconfig/Kconfiglib/examples/print_config_tree.py
Normal file
@ -0,0 +1,199 @@
|
||||
# Prints menu entries as a tree with its value in the .config file. This can be
|
||||
# handy e.g. for diffing between different .config files or versions of Kconfig files.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=print_config_tree.py [SCRIPT_ARG=<.config>]
|
||||
#
|
||||
# If the variable WITH_HELP_DESC is modified to 'True', the help is added
|
||||
# to the symbols.
|
||||
#
|
||||
# Here's a notation guide. The notation matches the one used by menuconfig
|
||||
# (scripts/kconfig/mconf):
|
||||
#
|
||||
# [ ] prompt - Bool
|
||||
# < > prompt - Tristate
|
||||
# {M} prompt - Tristate selected to m. Can only be set to m or y.
|
||||
# -*- prompt - Bool/tristate selected to y, pinning it
|
||||
# -M- prompt - Tristate selected to m that also has m visibility,
|
||||
# pinning it to m
|
||||
# (foo) prompt - String/int/hex symbol with value "foo"
|
||||
# --> prompt - The selected symbol in a choice in y mode. This
|
||||
# syntax is unique to this example.
|
||||
#
|
||||
# When modules are disabled, the .type attribute of TRISTATE symbols and
|
||||
# choices automatically changes to BOOL. This trick is used by the C
|
||||
# implementation as well, and gives the expected behavior without having to do
|
||||
# anything extra here. The original type is available in .orig_type if needed.
|
||||
#
|
||||
# Example output:
|
||||
#
|
||||
# $ make scriptconfig SCRIPT=Kconfiglib/examples/print_config_tree.py [SCRIPT_ARG=<.config file>]
|
||||
#
|
||||
# ======== Linux/x86 4.9.82 Kernel Configuration ========
|
||||
#
|
||||
# [*] 64-bit kernel (64BIT)
|
||||
# General setup
|
||||
# () Cross-compiler tool prefix (CROSS_COMPILE)
|
||||
# [ ] Compile also drivers which will not load (COMPILE_TEST)
|
||||
# () Local version - append to kernel release (LOCALVERSION)
|
||||
# [*] Automatically append version information to the version string (LOCALVERSION_AUTO)
|
||||
# -*- Kernel compression mode
|
||||
# ...
|
||||
#
|
||||
# With the variable WITH_HELP_DESC modified to 'True':
|
||||
#
|
||||
# ======== Linux/x86 4.9.82 Kernel Configuration ========
|
||||
#
|
||||
# [*] 64-bit kernel - 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 (64BIT)
|
||||
# General setup
|
||||
# () Cross-compiler tool prefix - Same as running 'make CROSS_COMPILE=prefix-' but stored for default make runs in this kernel build directory. You don't need to set this unless you want the configured kernel build directory to select the cross-compiler automatically. (CROSS_COMPILE)
|
||||
# [ ] Compile also drivers which will not load - Some drivers can be compiled on a different platform than they are intended to be run on. Despite they cannot be loaded there (or even when they load they cannot be used due to missing HW support), developers still, opposing to distributors, might want to build such drivers to compile-test them. If you are a developer and want to build everything available, say Y here. If you are a user/distributor, say N here to exclude useless drivers to be distributed. (COMPILE_TEST)
|
||||
# ...
|
||||
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, \
|
||||
Symbol, MENU, COMMENT, \
|
||||
BOOL, TRISTATE, STRING, INT, HEX, UNKNOWN, \
|
||||
expr_value
|
||||
|
||||
|
||||
# Add help description to output
|
||||
WITH_HELP_DESC = False
|
||||
|
||||
|
||||
def indent_print(s, indent):
|
||||
print(indent*" " + s)
|
||||
|
||||
|
||||
def value_str(sc):
|
||||
"""
|
||||
Returns the value part ("[*]", "<M>", "(foo)" etc.) of a menu entry.
|
||||
|
||||
sc: Symbol or Choice.
|
||||
"""
|
||||
if sc.type in (STRING, INT, HEX):
|
||||
return "({})".format(sc.str_value)
|
||||
|
||||
# BOOL or TRISTATE
|
||||
|
||||
# The choice mode is an upper bound on the visibility of choice symbols, so
|
||||
# we can check the choice symbols' own visibility to see if the choice is
|
||||
# in y mode
|
||||
if isinstance(sc, Symbol) and sc.choice and sc.visibility == 2:
|
||||
# For choices in y mode, print '-->' next to the selected symbol
|
||||
return "-->" if sc.choice.selection is sc else " "
|
||||
|
||||
tri_val_str = (" ", "M", "*")[sc.tri_value]
|
||||
|
||||
if len(sc.assignable) == 1:
|
||||
# Pinned to a single value
|
||||
return "-{}-".format(tri_val_str)
|
||||
|
||||
if sc.type == BOOL:
|
||||
return "[{}]".format(tri_val_str)
|
||||
|
||||
if sc.type == TRISTATE:
|
||||
if sc.assignable == (1, 2):
|
||||
# m and y available
|
||||
return "{" + tri_val_str + "}" # Gets a bit confusing with .format()
|
||||
return "<{}>".format(tri_val_str)
|
||||
|
||||
|
||||
def node_str(node):
|
||||
"""
|
||||
Returns the complete menu entry text for a menu node, or "" for invisible
|
||||
menu nodes. Invisible menu nodes are those that lack a prompt or that do
|
||||
not have a satisfied prompt condition.
|
||||
|
||||
Example return value: "[*] Bool symbol (BOOL)"
|
||||
|
||||
The symbol name is printed in parentheses to the right of the prompt.
|
||||
"""
|
||||
if not node.prompt:
|
||||
return ""
|
||||
|
||||
# Even for menu nodes for symbols and choices, it's wrong to check
|
||||
# Symbol.visibility / Choice.visibility here. The reason is that a symbol
|
||||
# (and a choice, in theory) can be defined in multiple locations, giving it
|
||||
# multiple menu nodes, which do not necessarily all have the same prompt
|
||||
# visibility. Symbol.visibility / Choice.visibility is calculated as the OR
|
||||
# of the visibility of all the prompts.
|
||||
prompt, prompt_cond = node.prompt
|
||||
if not expr_value(prompt_cond):
|
||||
return ""
|
||||
|
||||
if node.item == MENU:
|
||||
return " " + prompt
|
||||
|
||||
if node.item == COMMENT:
|
||||
return " *** {} ***".format(prompt)
|
||||
|
||||
# Symbol or Choice
|
||||
|
||||
sc = node.item
|
||||
|
||||
if sc.type == UNKNOWN:
|
||||
# Skip symbols defined without a type (these are obscure and generate
|
||||
# a warning)
|
||||
return ""
|
||||
|
||||
# Add help text
|
||||
if WITH_HELP_DESC:
|
||||
prompt += ' - ' + str(node.help).replace('\n', ' ').replace('\r', '')
|
||||
|
||||
# {:3} sets the field width to three. Gives nice alignment for empty string
|
||||
# values.
|
||||
res = "{:3} {}".format(value_str(sc), prompt)
|
||||
|
||||
# Don't print the name for unnamed choices (the normal kind)
|
||||
if sc.name is not None:
|
||||
res += " ({})".format(sc.name)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def print_menuconfig_nodes(node, indent):
|
||||
"""
|
||||
Prints a tree with all the menu entries rooted at 'node'. Child menu
|
||||
entries are indented.
|
||||
"""
|
||||
while node:
|
||||
string = node_str(node)
|
||||
if string:
|
||||
indent_print(string, indent)
|
||||
|
||||
if node.list:
|
||||
print_menuconfig_nodes(node.list, indent + 8)
|
||||
|
||||
node = node.next
|
||||
|
||||
|
||||
def print_menuconfig(kconf):
|
||||
"""
|
||||
Prints all menu entries for the configuration.
|
||||
"""
|
||||
# Print the expanded mainmenu text at the top. This is the same as
|
||||
# kconf.top_node.prompt[0], but with variable references expanded.
|
||||
print("\n======== {} ========\n".format(kconf.mainmenu_text))
|
||||
|
||||
print_menuconfig_nodes(kconf.top_node.list, 0)
|
||||
print("")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# Load Kconfig configuration files
|
||||
kconf = Kconfig(sys.argv[1])
|
||||
|
||||
# Set default .config file or load it from argv
|
||||
if len(sys.argv) == 2:
|
||||
config_filename = '.config'
|
||||
else:
|
||||
config_filename = sys.argv[2]
|
||||
|
||||
kconf.load_config(config_filename)
|
||||
|
||||
# Print the configuration tree
|
||||
print_menuconfig(kconf)
|
||||
54
scripts/kconfig/Kconfiglib/examples/print_sym_info.py
Normal file
54
scripts/kconfig/Kconfiglib/examples/print_sym_info.py
Normal file
@ -0,0 +1,54 @@
|
||||
# Loads a Kconfig and a .config and prints a symbol.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/print_sym_info.py SCRIPT_ARG=<name>
|
||||
#
|
||||
# Example output for SCRIPT_ARG=MODULES:
|
||||
#
|
||||
# menuconfig MODULES
|
||||
# bool
|
||||
# prompt "Enable loadable module support"
|
||||
# option modules
|
||||
# help
|
||||
# Kernel modules are small pieces of compiled code which can
|
||||
# be inserted in the running kernel, rather than being
|
||||
# permanently built into the kernel. You use the "modprobe"
|
||||
# tool to add (and sometimes remove) them. If you say Y here,
|
||||
# many parts of the kernel can be built as modules (by
|
||||
# answering M instead of Y where indicated): this is most
|
||||
# useful for infrequently used options which are not required
|
||||
# for booting. For more information, see the man pages for
|
||||
# modprobe, lsmod, modinfo, insmod and rmmod.
|
||||
#
|
||||
# If you say Y here, you will need to run "make
|
||||
# modules_install" to put the modules under /lib/modules/
|
||||
# where modprobe can find them (you may need to be root to do
|
||||
# this).
|
||||
#
|
||||
# If unsure, say Y.
|
||||
#
|
||||
# value = n
|
||||
# visibility = y
|
||||
# currently assignable values: n, y
|
||||
# defined at init/Kconfig:1674
|
||||
|
||||
import sys
|
||||
|
||||
from kconfiglib import Kconfig, TRI_TO_STR
|
||||
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
sys.exit('Pass symbol name (without "CONFIG_" prefix) with SCRIPT_ARG=<name>')
|
||||
|
||||
kconf = Kconfig(sys.argv[1])
|
||||
sym = kconf.syms[sys.argv[2]]
|
||||
|
||||
print(sym)
|
||||
print("value = " + sym.str_value)
|
||||
print("visibility = " + TRI_TO_STR[sym.visibility])
|
||||
print("currently assignable values: " +
|
||||
", ".join([TRI_TO_STR[v] for v in sym.assignable]))
|
||||
|
||||
for node in sym.nodes:
|
||||
print("defined at {}:{}".format(node.filename, node.linenr))
|
||||
75
scripts/kconfig/Kconfiglib/examples/print_tree.py
Normal file
75
scripts/kconfig/Kconfiglib/examples/print_tree.py
Normal file
@ -0,0 +1,75 @@
|
||||
# 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.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/print_tree.py
|
||||
#
|
||||
# Example output:
|
||||
#
|
||||
# ...
|
||||
# config HAVE_KERNEL_LZO
|
||||
# config HAVE_KERNEL_LZ4
|
||||
# choice
|
||||
# config KERNEL_GZIP
|
||||
# config KERNEL_BZIP2
|
||||
# config KERNEL_LZMA
|
||||
# config KERNEL_XZ
|
||||
# config KERNEL_LZO
|
||||
# config KERNEL_LZ4
|
||||
# config DEFAULT_HOSTNAME
|
||||
# config SWAP
|
||||
# config SYSVIPC
|
||||
# config SYSVIPC_SYSCTL
|
||||
# config POSIX_MQUEUE
|
||||
# config POSIX_MQUEUE_SYSCTL
|
||||
# config CROSS_MEMORY_ATTACH
|
||||
# config FHANDLE
|
||||
# config USELIB
|
||||
# config AUDIT
|
||||
# config HAVE_ARCH_AUDITSYSCALL
|
||||
# config AUDITSYSCALL
|
||||
# config AUDIT_WATCH
|
||||
# config AUDIT_TREE
|
||||
# menu "IRQ subsystem"
|
||||
# config MAY_HAVE_SPARSE_IRQ
|
||||
# config GENERIC_IRQ_LEGACY
|
||||
# config GENERIC_IRQ_PROBE
|
||||
# ...
|
||||
|
||||
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
|
||||
|
||||
|
||||
kconf = Kconfig(sys.argv[1])
|
||||
print_items(kconf.top_node, 0)
|
||||
Reference in New Issue
Block a user