The -f (find) option calls read_database() directly, which crashes if the database does not exist and silently returns stale data if Kconfig or defconfig files have changed since the last build.
Add a db_is_current() check that compares the database timestamp against all Kconfig and defconfig files, similar to output_is_new() in buildman/boards.py. Use this in ensure_database() so that both -f and buildman's callers get automatic rebuilds when the database is stale. Wire do_find_config() through ensure_database() instead of read_database() so that -f benefits from this. Signed-off-by: Simon Glass <[email protected]> --- tools/qconfig.py | 45 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/tools/qconfig.py b/tools/qconfig.py index 2a594ea0200..0b8f14d3e65 100755 --- a/tools/qconfig.py +++ b/tools/qconfig.py @@ -1286,9 +1286,11 @@ def find_config(dbase, config_list): return result -def do_find_config(config_list, list_format): +def do_find_config(config_list, list_format, jobs): """Find boards with a given combination of CONFIGs + Rebuilds the database automatically if it is missing or stale. + Args: config_list (list of str): List of CONFIG options to check (each a regex consisting of a config option, with or without a CONFIG_ prefix. If @@ -1296,11 +1298,12 @@ def do_find_config(config_list, list_format): otherwise it must be true) list_format (bool): True to write in 'list' format, one board name per line + jobs (int): Number of threads to use if the database needs rebuilding Returns: int: exit code (0 for success) """ - dbase = read_database() + dbase = ensure_database(jobs) out = find_config(dbase, config_list) if not list_format: print(f'{len(out)} matches') @@ -1837,11 +1840,37 @@ def do_tests(): return 0 +def db_is_current(): + """Check if the CONFIG database is up to date + + Returns: + bool: True if the database exists and is newer than all Kconfig and + defconfig files + """ + if not os.path.exists(CONFIG_DATABASE): + return False + + db_time = os.path.getctime(CONFIG_DATABASE) + + for dirpath, _, filenames in os.walk('configs'): + for fname in fnmatch.filter(filenames, '*_defconfig'): + if db_time < os.path.getctime(os.path.join(dirpath, fname)): + return False + + for dirpath, _, filenames in os.walk('.'): + for fname in filenames: + if fname.startswith('Kconfig'): + if db_time < os.path.getctime(os.path.join(dirpath, fname)): + return False + + return True + + def ensure_database(threads): - """Return a qconfig database so that Kconfig options can be queried + """Return a qconfig database, rebuilding it if stale or missing - If a database exists, it is assumed to be up-to-date. If not, one is built, - which can take a few minutes. + Checks whether the database is newer than all Kconfig and defconfig files. + If not, it is rebuilt automatically. Args: threads (int): Number of threads to use when processing @@ -1859,8 +1888,8 @@ def ensure_database(threads): key: CONFIG option value: set of boards using that option """ - if not os.path.exists(CONFIG_DATABASE): - print(f'Building {CONFIG_DATABASE} database') + if not db_is_current(): + print(f'Building {CONFIG_DATABASE} database...') args = Namespace(build_db=True, verbose=False, force_sync=False, dry_run=False, exit_on_error=False, jobs=threads, git_ref=None, defconfigs=None, defconfiglist=None, @@ -1890,7 +1919,7 @@ def main(): sys.exit(1) return 0 if args.find: - return do_find_config(args.configs, args.list) + return do_find_config(args.configs, args.list, args.jobs) if args.build_db: config_db, progress = do_build_db(args) -- 2.43.0

