Atlas - print_config_tree.py

Home / ext / kconfiglib / examples Lines: 4 | Size: 7161 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1# Prints menu entries as a tree with its value in the .config file. This can be 2# handy e.g. for diffing between different .config files or versions of Kconfig files. 3# 4# Usage: 5# 6# $ make [ARCH=<arch>] scriptconfig SCRIPT=print_config_tree.py [SCRIPT_ARG=<.config>] 7# 8# If the variable WITH_HELP_DESC is modified to 'True', the help is added 9# to the symbols. 10# 11# Here's a notation guide. The notation matches the one used by menuconfig 12# (scripts/kconfig/mconf): 13# 14# [ ] prompt - Bool 15# < > prompt - Tristate 16# {M} prompt - Tristate selected to m. Can only be set to m or y. 17# -*- prompt - Bool/tristate selected to y, pinning it 18# -M- prompt - Tristate selected to m that also has m visibility, 19# pinning it to m 20# (foo) prompt - String/int/hex symbol with value "foo" 21# --> prompt - The selected symbol in a choice in y mode. This 22# syntax is unique to this example. 23# 24# When modules are disabled, the .type attribute of TRISTATE symbols and 25# choices automatically changes to BOOL. This trick is used by the C 26# implementation as well, and gives the expected behavior without having to do 27# anything extra here. The original type is available in .orig_type if needed. 28# 29# Example output: 30# 31# $ make scriptconfig SCRIPT=Kconfiglib/examples/print_config_tree.py [SCRIPT_ARG=<.config file>] 32# 33# ======== Linux/x86 4.9.82 Kernel Configuration ======== 34# 35# [*] 64-bit kernel (64BIT) 36# General setup 37# () Cross-compiler tool prefix (CROSS_COMPILE) 38# [ ] Compile also drivers which will not load (COMPILE_TEST) 39# () Local version - append to kernel release (LOCALVERSION) 40# [*] Automatically append version information to the version string (LOCALVERSION_AUTO) 41# -*- Kernel compression mode 42# ... 43# 44# With the variable WITH_HELP_DESC modified to 'True': 45# 46# ======== Linux/x86 4.9.82 Kernel Configuration ======== 47# 48# [*] 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) 49# General setup 50# () 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) 51# [ ] 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) 52# ... 53 54import sys 55 56from kconfiglib import Kconfig, \ 57 Symbol, MENU, COMMENT, \ 58 BOOL, TRISTATE, STRING, INT, HEX, UNKNOWN, \ 59 expr_value 60 61 62# Add help description to output 63WITH_HELP_DESC = False 64 65 66def indent_print(s, indent): 67 print(indent*" " + s) 68 69 70def value_str(sc): 71 """ 72 Returns the value part ("[*]", "<M>", "(foo)" etc.) of a menu entry. 73 74 sc: Symbol or Choice. 75 """ 76 if sc.type in (STRING, INT, HEX): 77 return "({})".format(sc.str_value) 78 79 # BOOL or TRISTATE 80 81 # The choice mode is an upper bound on the visibility of choice symbols, so 82 # we can check the choice symbols' own visibility to see if the choice is 83 # in y mode 84 if isinstance(sc, Symbol) and sc.choice and sc.visibility == 2: 85 # For choices in y mode, print '-->' next to the selected symbol 86 return "-->" if sc.choice.selection is sc else " " 87 88 tri_val_str = (" ", "M", "*")[sc.tri_value] 89 90 if len(sc.assignable) == 1: 91 # Pinned to a single value 92 return "-{}-".format(tri_val_str) 93 94 if sc.type == BOOL: 95 return "[{}]".format(tri_val_str) 96 97 if sc.type == TRISTATE: 98 if sc.assignable == (1, 2): 99 # m and y available 100 return "{" + tri_val_str + "}" # Gets a bit confusing with .format() 101 return "<{}>".format(tri_val_str) 102 103 104def node_str(node): 105 """ 106 Returns the complete menu entry text for a menu node, or "" for invisible 107 menu nodes. Invisible menu nodes are those that lack a prompt or that do 108 not have a satisfied prompt condition. 109 110 Example return value: "[*] Bool symbol (BOOL)" 111 112 The symbol name is printed in parentheses to the right of the prompt. 113 """ 114 if not node.prompt: 115 return "" 116 117 # Even for menu nodes for symbols and choices, it's wrong to check 118 # Symbol.visibility / Choice.visibility here. The reason is that a symbol 119 # (and a choice, in theory) can be defined in multiple locations, giving it 120 # multiple menu nodes, which do not necessarily all have the same prompt 121 # visibility. Symbol.visibility / Choice.visibility is calculated as the OR 122 # of the visibility of all the prompts. 123 prompt, prompt_cond = node.prompt 124 if not expr_value(prompt_cond): 125 return "" 126 127 if node.item == MENU: 128 return " " + prompt 129 130 if node.item == COMMENT: 131 return " *** {} ***".format(prompt) 132 133 # Symbol or Choice 134 135 sc = node.item 136 137 if sc.type == UNKNOWN: 138 # Skip symbols defined without a type (these are obscure and generate 139 # a warning) 140 return "" 141 142 # Add help text 143 if WITH_HELP_DESC: 144 prompt += ' - ' + str(node.help).replace('\n', ' ').replace('\r', '') 145 146 # {:3} sets the field width to three. Gives nice alignment for empty string 147 # values. 148 res = "{:3} {}".format(value_str(sc), prompt) 149 150 # Don't print the name for unnamed choices (the normal kind) 151 if sc.name is not None: 152 res += " ({})".format(sc.name) 153 154 return res 155 156 157def print_menuconfig_nodes(node, indent): 158 """ 159 Prints a tree with all the menu entries rooted at 'node'. Child menu 160 entries are indented. 161 """ 162 while node: 163 string = node_str(node) 164 if string: 165 indent_print(string, indent) 166 167 if node.list: 168 print_menuconfig_nodes(node.list, indent + 8) 169 170 node = node.next 171 172 173def print_menuconfig(kconf): 174 """ 175 Prints all menu entries for the configuration. 176 """ 177 # Print the expanded mainmenu text at the top. This is the same as 178 # kconf.top_node.prompt[0], but with variable references expanded. 179 print("\n======== {} ========\n".format(kconf.mainmenu_text)) 180 181 print_menuconfig_nodes(kconf.top_node.list, 0) 182 print("") 183 184 185if __name__ == "__main__": 186 187 # Load Kconfig configuration files 188 kconf = Kconfig(sys.argv[1]) 189 190 # Set default .config file or load it from argv 191 if len(sys.argv) == 2: 192 config_filename = '.config' 193 else: 194 config_filename = sys.argv[2] 195 196 kconf.load_config(config_filename) 197 198 # Print the configuration tree 199 print_menuconfig(kconf) 200
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.