From dd1be546016b227411e50376515956ed381ee270 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Thu, 6 Jun 2019 19:08:34 +0200 Subject: genconfig: Support generating lists of files and environment vars. This can be useful to avoid needless reconfiguration, by checking if any Kconfig file or environment variable has changed value before running genconfig. --- genconfig.py | 92 ++++++++++++++++++++++++++++++++++++++++++----------------- kconfiglib.py | 6 ++-- 2 files changed, 69 insertions(+), 29 deletions(-) diff --git a/genconfig.py b/genconfig.py index aebff35..e298b14 100755 --- a/genconfig.py +++ b/genconfig.py @@ -10,19 +10,20 @@ format of include/generated/autoconf.h in the Linux kernel. Optionally, also writes the configuration output as a .config file. See --config-out. -Optionally, creates/updates a directory structure with one file per symbol that -can be used to implement incremental builds. See the docstring for -Kconfig.sync_deps() in kconfiglib.py. +The --sync-deps, --file-list, and --env-list options generate information that +can be used to avoid needless rebuilds/reconfigurations. -Before writing a header file or other configuration output, Kconfiglib compares -the old contents of the file against the new contents. If there's no change, -the write is skipped. This avoids updating file metadata like the modification -time, and might save work depending on your build setup. +Before writing a header or configuration file, Kconfiglib compares the old +contents of the file against the new contents. If there's no change, the write +is skipped. This avoids updating file metadata like the modification time, and +might save work depending on your build setup. By default, the configuration is generated from '.config'. A different configuration file can be passed in the KCONFIG_CONFIG environment variable. """ import argparse +import os +import sys import kconfiglib @@ -43,28 +44,48 @@ def main(): help="Path for the generated header file (default: {})" .format(DEFAULT_HEADER_PATH)) + parser.add_argument( + "--config-out", + metavar="CONFIG_FILE", + help=""" +Write the configuration to CONFIG_FILE. This is useful if you include .config +files in Makefiles, as the generated configuration file will be a full .config +file even if .config is outdated. The generated configuration matches what +olddefconfig would produce. If you use sync-deps, you can include +deps/auto.conf instead. --config-out is meant for cases where incremental build +information isn't needed. +""") + parser.add_argument( "--sync-deps", - dest="sync_deps_path", metavar="OUTPUT_DIR", nargs="?", const=DEFAULT_SYNC_DEPS_PATH, - help="Enable generation of build dependency information for " - "incremental builds, optionally specifying the output path " - "(default: {})".format(DEFAULT_SYNC_DEPS_PATH)) + help=""" +Enable generation of symbol dependency information for incremental builds, +optionally specifying the output directory (default: {}). See the docstring of +Kconfig.sync_deps() in Kconfiglib for more information. +""".format(DEFAULT_SYNC_DEPS_PATH)) parser.add_argument( - "--config-out", - dest="config_path", - metavar="CONFIG_FILE", - help="Write the configuration to the specified filename. " - "This is useful if you include .config files in Makefiles, as " - "the generated configuration file will be a full .config file " - "even if .config is outdated. The generated configuration " - "matches what olddefconfig would produce. If you use " - "--sync-deps, you can include deps/auto.conf instead. " - "--config-out is meant for cases where incremental build " - "information isn't needed.") + "--file-list", + metavar="OUTPUT_FILE", + help=""" +Write a list of all Kconfig files to OUTPUT_FILE, with one file per line. The +paths are relative to $srctree (or to the current directory if $srctree is +unset). Files appear in the order they're 'source'd. +""") + + parser.add_argument( + "--env-list", + metavar="OUTPUT_FILE", + help=""" +Write a list of all environment variables referenced in Kconfig files to +OUTPUT_FILE, with one variable per line. Each line has the format NAME=VALUE. +Only environment variables referenced with the preprocessor $(VAR) syntax are +included, and not variables referenced with the older $VAR syntax (which is +only supported for backwards compatibility). +""") parser.add_argument( "kconfig_filename", @@ -81,11 +102,30 @@ def main(): kconf.write_autoconf(args.header_path) - if args.sync_deps_path is not None: - kconf.sync_deps(args.sync_deps_path) + if args.config_out is not None: + kconf.write_config(args.config_out, save_old=False) + + if args.file_list is not None: + with _open_write(args.file_list) as f: + for path in kconf.kconfig_filenames: + f.write(path + "\n") + + if args.env_list is not None: + with _open_write(args.env_list) as f: + for env_var in kconf.env_vars: + f.write("{}={}\n".format(env_var, os.environ[env_var])) + + if args.sync_deps is not None: + kconf.sync_deps(args.sync_deps) + + +def _open_write(path): + # Python 2/3 compatibility. io.open() is available on both, but makes + # write() expect 'unicode' strings on Python 2. - if args.config_path is not None: - kconf.write_config(args.config_path, save_old=False) + if sys.version_info[0] < 3: + return open(path, "w") + return open(path, "w", encoding="utf-8") if __name__ == "__main__": diff --git a/kconfiglib.py b/kconfiglib.py index f4fe90e..c24e724 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -3771,9 +3771,9 @@ class Kconfig(object): # The "U" flag would currently work for both Python 2 and 3, but it's # deprecated on Python 3, so play it future-safe. # - # A simpler solution would be to use io.open(), which defaults to - # universal newlines on both Python 2 and 3 (and is an alias for - # open() on Python 3), but it's appreciably slower on Python 2: + # io.open() defaults to universal newlines on Python 2 (and is an + # alias for open() on Python 3), but it returns 'unicode' strings and + # slows things down: # # Parsing x86 Kconfigs on Python 2 # -- cgit v1.2.3