From 65d7fcec5a05be15694613c6db709ede19bce85b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 18 Dec 2021 08:09:46 -0700 Subject: [PATCH] moveconfig: Allow querying board configuration It is useful to be able to find out which boards define a particular option, or combination of options. This is not as easy as grepping the defconfig files since many options are implied by others. Add a -f option to the moveconfig tool to permit this. Update the documentation to cover this, including a better title for the doc page. Signed-off-by: Simon Glass --- doc/develop/moveconfig.rst | 25 ++++++++++++-- tools/moveconfig.py | 86 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 105 insertions(+), 6 deletions(-) diff --git a/doc/develop/moveconfig.rst b/doc/develop/moveconfig.rst index dcd4d92..2f53ea5 100644 --- a/doc/develop/moveconfig.rst +++ b/doc/develop/moveconfig.rst @@ -1,7 +1,7 @@ .. SPDX-License-Identifier: GPL-2.0+ -moveconfig -========== +moveconfig - Migrating and querying CONFIG options +================================================== Since Kconfig was introduced to U-Boot, we have worked on moving config options from headers to Kconfig (defconfig). @@ -129,6 +129,24 @@ To process CONFIG_CMD_FPGAD only for a subset of configs based on path match:: ./tools/moveconfig.py -Cy CONFIG_CMD_FPGAD -d - +Finding boards with particular CONFIG combinations +-------------------------------------------------- + +You can use `moveconfig.py` to figure out which boards have a CONFIG enabled, or +which do not. To use it, first build a database:: + + ./tools/moveconfig.py -b + +Then you can run queries using the `-f` flag followed by a list of CONFIG terms. +Each term is CONFIG name, with or without a tilde (~) prefix. The tool searches +for boards which match the CONFIG name, or do not match if tilde is used. For +example, to find boards which enabled CONFIG_SCSI but not CONFIG_BLK:: + + tools/moveconfig.py -f SCSI ~BLK + 3 matches + pg_wcom_seli8_defconfig highbank_defconfig pg_wcom_expu1_defconfig + + Finding implied CONFIGs ----------------------- @@ -235,6 +253,9 @@ Available options Specify a file containing a list of defconfigs to move. The defconfig files can be given with shell-style wildcards. Use '-' to read from stdin. + -f, --find + Find boards with a given config combination + -n, --dry-run Perform a trial run that does not make any changes. It is useful to see what is going to happen before one actually runs it. diff --git a/tools/moveconfig.py b/tools/moveconfig.py index 71a7736..a86c07c 100755 --- a/tools/moveconfig.py +++ b/tools/moveconfig.py @@ -1569,6 +1569,79 @@ def do_imply_config(config_list, add_imply, imply_flags, skip_added, add_imply_rule(config[CONFIG_LEN:], fname, linenum) +def do_find_config(config_list): + """Find boards with a given combination of CONFIGs + + Params: + config_list: List of CONFIG options to check (each a string consisting + of a config option, with or without a CONFIG_ prefix. If an option + is preceded by a tilde (~) then it must be false, otherwise it must + be true) + """ + all_configs, all_defconfigs, config_db, defconfig_db = read_database() + + # Get the whitelist + with open('scripts/config_whitelist.txt') as inf: + adhoc_configs = set(inf.read().splitlines()) + + # Start with all defconfigs + out = all_defconfigs + + # Work through each config in turn + adhoc = [] + for item in config_list: + # Get the real config name and whether we want this config or not + cfg = item + want = True + if cfg[0] == '~': + want = False + cfg = cfg[1:] + + if cfg in adhoc_configs: + adhoc.append(cfg) + continue + + # Search everything that is still in the running. If it has a config + # that we want, or doesn't have one that we don't, add it into the + # running for the next stage + in_list = out + out = set() + for defc in in_list: + has_cfg = cfg in config_db[defc] + if has_cfg == want: + out.add(defc) + if adhoc: + print(f"Error: Not in Kconfig: %s" % ' '.join(adhoc)) + else: + print(f'{len(out)} matches') + print(' '.join(out)) + + +def prefix_config(cfg): + """Prefix a config with CONFIG_ if needed + + This handles ~ operator, which indicates that the CONFIG should be disabled + + >>> prefix_config('FRED') + 'CONFIG_FRED' + >>> prefix_config('CONFIG_FRED') + 'CONFIG_FRED' + >>> prefix_config('~FRED') + '~CONFIG_FRED' + >>> prefix_config('~CONFIG_FRED') + '~CONFIG_FRED' + >>> prefix_config('A123') + 'CONFIG_A123' + """ + op = '' + if cfg[0] == '~': + op = cfg[0] + cfg = cfg[1:] + if not cfg.startswith('CONFIG_'): + cfg = 'CONFIG_' + cfg + return op + cfg + + def main(): try: cpu_count = multiprocessing.cpu_count() @@ -1596,6 +1669,8 @@ def main(): parser.add_option('-e', '--exit-on-error', action='store_true', default=False, help='exit immediately on any error') + parser.add_option('-f', '--find', action='store_true', default=False, + help='Find boards with a given config combination') parser.add_option('-H', '--headers-only', dest='cleanup_headers_only', action='store_true', default=False, help='only cleanup the headers') @@ -1631,13 +1706,12 @@ def main(): unittest.main() if len(configs) == 0 and not any((options.force_sync, options.build_db, - options.imply)): + options.imply, options.find)): parser.print_usage() sys.exit(1) # prefix the option name with CONFIG_ if missing - configs = [ config if config.startswith('CONFIG_') else 'CONFIG_' + config - for config in configs ] + configs = [prefix_config(cfg) for cfg in configs] check_top_directory() @@ -1663,6 +1737,10 @@ def main(): options.skip_added) return + if options.find: + do_find_config(configs) + return + config_db = {} db_queue = queue.Queue() t = DatabaseThread(config_db, db_queue) @@ -1705,4 +1783,4 @@ def main(): fd.write('\n') if __name__ == '__main__': - main() + sys.exit(main()) -- 2.7.4