diff options
| author | Ulf Magnusson <ulfalizer@gmail.com> | 2017-10-09 23:05:00 +0200 |
|---|---|---|
| committer | Ulf Magnusson <ulfalizer@gmail.com> | 2017-10-24 19:24:08 +0200 |
| commit | dd0e227216e247d2040cdd40bf7397702880cdc4 (patch) | |
| tree | 4c76ebb2e7555d28214cddecf32ffb424fa1732b /examples | |
| parent | f64aaf971176305233f16a11911a660fa6f99561 (diff) | |
Kconfiglib 2 backup
WIP
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/allnoconfig.py | 87 | ||||
| -rw-r--r-- | examples/allnoconfig_simpler.py | 47 | ||||
| -rw-r--r-- | examples/allyesconfig.py | 133 | ||||
| -rw-r--r-- | examples/defconfig.py | 13 | ||||
| -rw-r--r-- | examples/defconfig_oldconfig.py | 12 | ||||
| -rw-r--r-- | examples/eval_expr.py | 20 | ||||
| -rw-r--r-- | examples/help_grep.py | 109 | ||||
| -rw-r--r-- | examples/print_refs.py | 13 | ||||
| -rw-r--r-- | examples/print_sym_info.py | 56 | ||||
| -rw-r--r-- | examples/print_tree.py | 80 | ||||
| -rw-r--r-- | examples/print_undefined.py | 15 |
11 files changed, 376 insertions, 209 deletions
diff --git a/examples/allnoconfig.py b/examples/allnoconfig.py index 9423352..edc473d 100644 --- a/examples/allnoconfig.py +++ b/examples/allnoconfig.py @@ -1,40 +1,57 @@ -# Works like allnoconfig. Automatically verified by the testsuite to generate -# identical output to 'make allnoconfig' for all ARCHes. The looping is done in -# case setting one symbol to "n" allows other symbols to be set to "n" (due to -# dependencies). +# Works like 'make allnoconfig'. Verified by the test suite to generate +# identical output to 'make allnoconfig' for all ARCHes. +# +# See allnoconfig_simpler.py for a much simpler version. This version +# demonstrates some tree walking and value processing. +# +# Usage: +# +# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/allnoconfig.py -import kconfiglib +from kconfiglib import Config, Symbol, tri_less import sys -conf = kconfiglib.Config(sys.argv[1]) - -# Do an initial pass to give allnoconfig_y symbols the user value 'y'. It might -# be possible to handle this through "successive raising" similarly to the -# "successive lowering" below too, but keep it simple. -for sym in conf: - if sym.get_type() in (kconfiglib.BOOL, kconfiglib.TRISTATE) and \ - sym.is_allnoconfig_y(): - sym.set_user_value('y') - -done = False -while not done: - done = True - - for sym in conf: - # Choices take care of themselves for allnoconfig, so we only need to - # worry about non-choice symbols - if not sym.is_choice_symbol() and not sym.is_allnoconfig_y(): - # If we can assign a value to the symbol (where "n", "m" and "y" - # are ordered from lowest to highest), then assign the lowest - # value. lower_bound() returns None for symbols whose values cannot - # (currently) be changed, as well as for non-bool/tristate symbols. - lower_bound = sym.get_lower_bound() - if lower_bound is not None and \ - kconfiglib.tri_less(lower_bound, sym.get_value()): - - sym.set_user_value(lower_bound) - # We just changed the value of some symbol. As this may affect - # other symbols, keep going. - done = False +def do_allnoconfig(node): + global no_changes + + # 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 is not None: + if isinstance(node.item, Symbol): + sym = node.item + + # Is the symbol a non-choice symbol that can be set to a lower + # value than its current value? + if sym.choice is None and sym.assignable and \ + tri_less(sym.assignable[0], sym.value): + + # Yup, lower it + sym.set_value(sym.assignable[0]) + no_changes = False + + # Recursively lower children + if node.list is not None: + do_allnoconfig(node.list) + + node = node.next + +conf = Config(sys.argv[1]) + +while 1: + # For tricky dependencies involving '!', setting later symbols to 'n' might + # actually raise the value of earlier symbols. To be super safe, we do + # additional passes until a pass no longer changes the value of any symbol. + # + # This isn't actually needed for any ARCH in the kernel as of 4.14. A + # single pass gives the correct result. + no_changes = True + + do_allnoconfig(conf.top_menu) + + # Did the pass change any symbols? + if no_changes: + break conf.write_config(".config") diff --git a/examples/allnoconfig_simpler.py b/examples/allnoconfig_simpler.py index f3cfe9a..e732669 100644 --- a/examples/allnoconfig_simpler.py +++ b/examples/allnoconfig_simpler.py @@ -1,28 +1,35 @@ # This is a simpler version of allnoconfig.py, corresponding to how the C -# implementation does it. Setting a user value that's not in the assignable -# range of the symbol (between get_lower_bound() and get_upper_bound(), or, -# equivalently, not in get_assignable_values()) is OK; the value will simply -# get truncated downwards or upwards as determined by the visibility and -# selects. +# implementation does it. Verified by the test suite to produce identical +# output to 'make allnoconfig' for all ARCHes. +# +# Usage: +# +# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/allnoconfig_simpler.py +# +# Implementation/performance note +# =============================== +# +# Kconfiglib immediately invalidates (flags for recalculation) all (possibly) +# dependent symbols when a value is assigned to a symbol, which slows this down +# a bit (due to tons of redundant invalidation), but makes any assignment +# pattern safe ("just works"). Config.load_config() instead invalidates all +# symbols up front, making it much faster. If you really need to eke out +# performance, look at how load_config() does things (which involves internal +# APIs that don't invalidate symbols). This has been fast enough for all cases +# I've seen so far though (around 3 seconds for this particular script on my +# Core i7 2600K, including the initial Kconfig parsing). -# This version is a bit slower compared allnoconfig.py since Kconfiglib -# invalidates all dependent symbols for each set_user_value() call. This does not -# happen for load_config(), which instead invalidates all symbols once after -# the configuration has been loaded. This is OK for load_config() since nearly -# all symbols will tend to be affected anyway. - -import kconfiglib +from kconfiglib import Config, BOOL, TRISTATE import sys -conf = kconfiglib.Config(sys.argv[1]) +conf = Config(sys.argv[1]) -# Avoid warnings printed by Kconfiglib when assigning a user value with -# set_user_value() to a symbol that has no prompt (such assignments never have -# an effect) -conf.set_print_warnings(False) +# Avoid warnings printed by Kconfiglib when assigning a value to a symbol that +# has no prompt. Such assignments never have an effect. +conf.disable_warnings() -for sym in conf: - if sym.get_type() in (kconfiglib.BOOL, kconfiglib.TRISTATE): - sym.set_user_value("y" if sym.is_allnoconfig_y() else "n") +for sym in conf.defined_syms: + if sym.type in (BOOL, TRISTATE): + sym.set_value("y" if sym.is_allnoconfig_y else "n") conf.write_config(".config") diff --git a/examples/allyesconfig.py b/examples/allyesconfig.py index 906343c..4847c05 100644 --- a/examples/allyesconfig.py +++ b/examples/allyesconfig.py @@ -1,65 +1,112 @@ -# Works like allyesconfig. This is a bit more involved than allnoconfig as we -# need to handle choices in two different modes: +# Works like 'make allyesconfig'. Verified by the test suite to generate +# identical output to 'make allyesconfig' for all ARCHES. # -# "y": One symbol is "y", the rest are "n". -# "m": Any number of symbols are "m", the rest are "n". +# This could be implemented as a straightforward tree walk just like +# allnoconfig.py (or even simpler like allnoconfig_simpler.py), but do it a bit +# differently (roundabout) just to demonstrate some other possibilities. # -# Only tristate choices can be in "m" mode. It is safe since the code for two -# conflicting options will appear as separate modules instead of simultaneously -# in the kernel. +# allyesconfig is a bit more involved than allnoconfig as we need to handle +# choices in two different modes: # -# If a choice can be in "y" mode, it will be. If it can only be in "m" mode -# (due to dependencies), then all the options will be set to "m". +# y: One symbol is "y", the rest are "n" +# m: Any number of symbols are "m", the rest are "n" # -# The looping is in case setting one symbol to "y" (or "m") allows the value of -# other symbols to be raised. +# Only tristate choices can be in "m" mode. No "m" mode choices seem to appear +# for allyesconfig on the kernel Kconfigs as of 4.14, but we still handle it. +# +# Usage: +# +# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/allyesconfig.py -import kconfiglib +from kconfiglib import Config, Choice, tri_less import sys -conf = kconfiglib.Config(sys.argv[1]) +conf = Config(sys.argv[1]) + +# Collect all the choices in the configuration. Demonstrates how the menu node +# tree can be walked iteratively by using the parent pointers. + +choices = [] +node = conf.top_menu + +while 1: + if isinstance(node.item, Choice): + choices.append(node.item) + + # Iterative tree walking by using parent pointers. + # + # Recursing on next pointers can blow the Python stack. Recursing on child + # pointers is safe (as is done in the other examples). This gives a + # template for how you can avoid recursing on both. The same logic is found + # in the C implementation. + + if node.list is not None: + # Jump to child node if available + node = node.list + + elif node.next is not None: + # Otherwise, jump to next node if available + node = node.next -# Get a list of all symbols that are not in choices -non_choice_syms = [sym for sym in conf.get_symbols() if - not sym.is_choice_symbol()] + else: + # Otherwise, look for parents with next nodes to jump to + while node.parent is not None: + node = node.parent + if node.next is not None: + node = node.next + break + else: + # No parents with next nodes, all nodes visited + break -done = False -while not done: - done = True +# Collect all symbols that are not in choices +non_choice_syms = [sym for sym in conf.defined_syms if sym.choice is None] + +while 1: + no_changes = True # Handle symbols outside of choices for sym in non_choice_syms: - upper_bound = sym.get_upper_bound() - - # See corresponding comment for allnoconfig implementation - if upper_bound is not None and \ - kconfiglib.tri_less(sym.get_value(), upper_bound): - sym.set_user_value(upper_bound) - done = False + # See allnoconfig example. [-1] gives the last (highest) assignable + # value. + if sym.assignable and tri_less(sym.value, sym.assignable[-1]): + sym.set_value(sym.assignable[-1]) + no_changes = False - # Handle symbols within choices + # Handle choices - for choice in conf.get_choices(): + for choice in choices: + # Handle a choice whose visibility allows it to be in "y" mode - # Handle choices whose visibility allow them to be in "y" mode + if choice.visibility == "y": + selection = choice.default_selection - if choice.get_visibility() == "y": - selection = choice.get_selection_from_defaults() + # Does the choice have a default selection that we haven't already + # selected? if selection is not None and \ - selection is not choice.get_user_selection(): - selection.set_user_value("y") - done = False + selection is not choice.user_value: - # Handle choices whose visibility only allow them to be in "m" mode. + # Yup, select it + selection.set_value("y") + no_changes = False + + # Handle a choice whose visibility only allows it to be in "m" mode. # This might happen if a choice depends on a symbol that can only be - # "m" for example. - - elif choice.get_visibility() == "m": - for sym in choice.get_symbols(): - if sym.get_value() != "m" and \ - sym.get_upper_bound() != "n": - sym.set_user_value("m") - done = False + # "m", for example. + + elif choice.visibility == "m": + for sym in choice.symbols: + + # Does the choice have a symbol that can be "m" that we haven't + # already set to "m"? + if sym.user_value != "m" and "m" in sym.assignable: + + # Yup, set it + sym.set_value("m") + no_changes = False + + if no_changes: + break conf.write_config(".config") diff --git a/examples/defconfig.py b/examples/defconfig.py index 3e958e2..ce2bf6e 100644 --- a/examples/defconfig.py +++ b/examples/defconfig.py @@ -1,4 +1,8 @@ # Works like entering "make menuconfig" and immediately saving and exiting +# +# Usage: +# +# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/allyesconfig.py import kconfiglib import os @@ -7,11 +11,12 @@ import sys conf = kconfiglib.Config(sys.argv[1]) if os.path.exists(".config"): + print("using existing .config") conf.load_config(".config") else: - defconfig = conf.get_defconfig_filename() - if defconfig is not None: - print("Using" + defconfig) - conf.load_config(defconfig) + if conf.defconfig_filename is not None: + print("using " + conf.defconfig_filename) + conf.load_config(conf.defconfig_filename) conf.write_config(".config") +print("configuration written to .config") diff --git a/examples/defconfig_oldconfig.py b/examples/defconfig_oldconfig.py index 9a85440..98173e7 100644 --- a/examples/defconfig_oldconfig.py +++ b/examples/defconfig_oldconfig.py @@ -7,6 +7,10 @@ # 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 kconfiglib import sys @@ -19,15 +23,15 @@ conf.write_config(".config") # Mirrors the first oldconfig conf.load_config(".config") -conf["ETHERNET"].set_user_value('n') +conf.syms["ETHERNET"].set_value('n') conf.write_config(".config") # Mirrors the second oldconfig conf.load_config(".config") -conf["ETHERNET"].set_user_value('y') +conf.syms["ETHERNET"].set_value('y') for s in conf: - if s.get_user_value() is None and 'n' in s.get_assignable_values(): - s.set_user_value('n') + if s.user_value is None and 'n' in s.assignable: + s.set_value('n') # Write the final configuration conf.write_config(".config") diff --git a/examples/eval_expr.py b/examples/eval_expr.py index edb33e6..a907f35 100644 --- a/examples/eval_expr.py +++ b/examples/eval_expr.py @@ -1,8 +1,22 @@ -# Evaluates an expression in the context of a configuration. (Here we could -# load a .config as well.) +# 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 kconfiglib import sys +if len(sys.argv) < 3: + print('Pass symbol name (without "CONFIG_" prefix) with SCRIPT_ARG=NAME') + sys.exit(1) + conf = kconfiglib.Config(sys.argv[1]) -print(conf.eval("(TRACE_IRQFLAGS_SUPPORT || PPC32) && STACKTRACE_SUPPORT")) + +# Enable modules so that 'm' doesn't get demoted to 'n' +conf.syms["MODULES"].set_value("y") + +print("the expression '{}' evaluates to {}" + .format(sys.argv[2], conf.eval_string(sys.argv[2]))) diff --git a/examples/help_grep.py b/examples/help_grep.py index 61ac936..fed1731 100644 --- a/examples/help_grep.py +++ b/examples/help_grep.py @@ -1,49 +1,72 @@ -# Does a case-insensitive search for a string in the help texts for symbols and -# choices and the titles of menus and comments. Prints the matching items -# together with their locations and the matching text. Used like +# 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. # -# $ make [ARCH=<arch>] scriptconfig SCRIPT=Kconfiglib/examples/help_grep.py SCRIPT_ARG=<search 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 kconfiglib +from kconfiglib import Config, Symbol, Choice, MENU, COMMENT +import re import sys if len(sys.argv) < 3: - print('Pass search string with SCRIPT_ARG="search string"') + print('Pass the regex with SCRIPT_ARG=regex') sys.exit(1) -search_string = sys.argv[2].lower() - -conf = kconfiglib.Config(sys.argv[1]) - -for item in conf.get_symbols() + \ - conf.get_choices() + conf.get_menus() + conf.get_comments(): - if item.is_symbol() or item.is_choice(): - text = item.get_help() - elif item.is_menu(): - text = item.get_title() - else: - # Comment - text = item.get_text() - - # Case-insensitive search - if text is not None and search_string in text.lower(): - if item.is_symbol() or item.is_choice(): - # Indent lines in help text. (There might be a nicer way. :) - text = "\n".join([" " + s for s in text.splitlines()]) - - # Don't worry about symbols/choices defined in multiple locations to - # keep things simple - fname, linenr = item.get_def_locations()[0] - if item.is_symbol(): - print("config {0} at {1}:{2}:\n{3}" - .format(item.get_name(), fname, linenr, text)) - elif item.is_choice(): - print("choice at {0}:{1}:\n{2}".format(fname, linenr, text)) - - else: - # Menu or comment - fname, linenr = item.get_location() - if item.is_menu(): - print('menu "{0}" at {1}:{2}'.format(text, fname, linenr)) - else: - # Comment - print('comment "{0}" at {1}:{2}'.format(text, fname, linenr)) + +search = re.compile(sys.argv[2], re.IGNORECASE).search + +def search_tree(node): + while node is not None: + 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)) + + if node.list is not None: + search_tree(node.list) + + node = node.next + +conf = Config(sys.argv[1]) +search_tree(conf.top_menu) diff --git a/examples/print_refs.py b/examples/print_refs.py deleted file mode 100644 index ea62223..0000000 --- a/examples/print_refs.py +++ /dev/null @@ -1,13 +0,0 @@ -# Prints the names of all symbols that reference a particular symbol. (There's -# also a method get_selected_symbols() for determining just selection -# relations.) - -import kconfiglib -import sys - -conf = kconfiglib.Config(sys.argv[1]) - -x86 = conf["X86"] -for sym in conf: - if x86 in sym.get_referenced_symbols(): - print(sym.get_name()) diff --git a/examples/print_sym_info.py b/examples/print_sym_info.py index c913358..2c1b0f0 100644 --- a/examples/print_sym_info.py +++ b/examples/print_sym_info.py @@ -1,18 +1,52 @@ -# Loads a Kconfig and a .config and prints information about a symbol. +# 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: +# +# config 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:1678 import kconfiglib import sys -# Create a Config object representing a Kconfig configuration. (Any number of -# these can be created -- the library has no global state.) +if len(sys.argv) < 3: + print('Pass symbol name (without "CONFIG_" prefix) with SCRIPT_ARG=<name>') + sys.exit(1) + conf = kconfiglib.Config(sys.argv[1]) +sym = conf.syms[sys.argv[2]] -# Load values from a .config file. 'srctree' is an environment variable set by -# the Linux makefiles to the top-level directory of the kernel tree. It needs -# to be used here for the script to work with alternative build directories -# (specified e.g. with O=). -conf.load_config("$srctree/arch/x86/configs/i386_defconfig") +print(sym) +print("value = " + sym.value) +print("visibility = " + sym.visibility) +print("currently assignable values: " + ", ".join(sym.assignable)) -# Print some information about a symbol. (The Config class implements -# __getitem__() to provide a handy syntax for getting symbols.) -print(conf["SERIAL_UARTLITE_CONSOLE"]) +for node in sym.nodes: + print("defined at {}:{}".format(node.filename, node.linenr)) diff --git a/examples/print_tree.py b/examples/print_tree.py index 1405ed5..da795c9 100644 --- a/examples/print_tree.py +++ b/examples/print_tree.py @@ -1,23 +1,67 @@ -# Prints a tree of all items in the configuration +# 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. +# +# 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 kconfiglib +from kconfiglib import Config, Symbol, Choice, MENU, COMMENT import sys -def print_with_indent(s, indent): +def indent_print(s, indent): print((" " * indent) + s) -def print_items(items, indent): - for item in items: - if item.is_symbol(): - print_with_indent("config {0}".format(item.get_name()), indent) - elif item.is_menu(): - print_with_indent('menu "{0}"'.format(item.get_title()), indent) - print_items(item.get_items(), indent + 2) - elif item.is_choice(): - print_with_indent('choice', indent) - print_items(item.get_items(), indent + 2) - elif item.is_comment(): - print_with_indent('comment "{0}"'.format(item.get_text()), indent) - -conf = kconfiglib.Config(sys.argv[1]) -print_items(conf.get_top_level_items(), 0) +def print_items(node, indent): + while node is not None: + 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 "{0}"'.format(node.prompt[0]), indent) + + elif node.item == COMMENT: + indent_print('comment "{0}"'.format(node.prompt[0]), indent) + + if node.list is not None: + print_items(node.list, indent + 2) + + node = node.next + +conf = Config(sys.argv[1]) +print_items(conf.top_menu, 0) diff --git a/examples/print_undefined.py b/examples/print_undefined.py deleted file mode 100644 index fb8120b..0000000 --- a/examples/print_undefined.py +++ /dev/null @@ -1,15 +0,0 @@ -# Prints the names of all symbols that are referenced but never defined in the -# current configuration together with the locations where they are referenced. -# Integers being included in the list is not a bug, as these need to be treated -# as symbols per the design of Kconfig. - -import kconfiglib -import sys - -conf = kconfiglib.Config(sys.argv[1]) - -for sym in conf.get_symbols(): - if not sym.is_defined(): - print(sym.get_name()) - for (filename, linenr) in sym.get_ref_locations(): - print(" {0}:{1}".format(filename, linenr)) |
