From b65baa47f69ae4c3993876a7edf0da0075aa70ff Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Sat, 17 Nov 2018 09:21:13 +0100 Subject: Add support for KCONFIG_ALLCONFIG This allows some symbol values to be forced while running all{def,no,yes,mod}config.py. See Documentation/kbuild/kconfig.txt in the Linux kernel. Add a helper function load_allconfig() to Kconfiglib to avoid code duplication in the tools. Also add functions for enabling/disabling the warning that's generated when a symbol is assigned multiple times in a (set of) .config files and the values differ. It should be disabled when merging the KCONFIG_ALLCONFIG configuration file. Previously, only the warning generated when the assigned values are identical could be disabled. Disable all warnings related to assigning a symbol multiple times in examples/merge_config.py as well. --- alldefconfig.py | 5 +-- allmodconfig.py | 4 +++ allnoconfig.py | 4 ++- allyesconfig.py | 4 +++ examples/merge_config.py | 10 ++++-- kconfiglib.py | 91 ++++++++++++++++++++++++++++++++++++++++++++---- 6 files changed, 107 insertions(+), 11 deletions(-) diff --git a/alldefconfig.py b/alldefconfig.py index 8b5d105..2c0b3fb 100755 --- a/alldefconfig.py +++ b/alldefconfig.py @@ -16,8 +16,9 @@ import kconfiglib def main(): - kconfiglib.standard_kconfig().write_config( - kconfiglib.standard_config_filename()) + kconf = kconfiglib.standard_kconfig() + kconfiglib.load_allconfig(kconf, "alldef.config") + kconf.write_config(kconfiglib.standard_config_filename()) if __name__ == "__main__": main() diff --git a/allmodconfig.py b/allmodconfig.py index 92a00e1..d1e64f6 100755 --- a/allmodconfig.py +++ b/allmodconfig.py @@ -38,6 +38,10 @@ def main(): for choice in kconf.unique_choices: choice.set_value(2 if choice.orig_type == BOOL else 1) + kconf.enable_warnings() + + kconfiglib.load_allconfig(kconf, "allmod.config") + kconf.write_config(kconfiglib.standard_config_filename()) if __name__ == "__main__": diff --git a/allnoconfig.py b/allnoconfig.py index 4e1c228..1ef6e27 100755 --- a/allnoconfig.py +++ b/allnoconfig.py @@ -30,9 +30,11 @@ def main(): # accept 0/1/2, for n/m/y). The assignments will be ignored for other # symbol types, which is what we want. kconf.disable_warnings() - for sym in kconf.unique_defined_syms: sym.set_value(2 if sym.is_allnoconfig_y else 0) + kconf.enable_warnings() + + kconfiglib.load_allconfig(kconf, "allno.config") kconf.write_config(kconfiglib.standard_config_filename()) diff --git a/allyesconfig.py b/allyesconfig.py index d9b799e..87ba9c6 100755 --- a/allyesconfig.py +++ b/allyesconfig.py @@ -55,6 +55,10 @@ def main(): for choice in kconf.unique_choices: choice.set_value(2) + kconf.enable_warnings() + + kconfiglib.load_allconfig(kconf, "allyes.config") + kconf.write_config(kconfiglib.standard_config_filename()) if __name__ == "__main__": diff --git a/examples/merge_config.py b/examples/merge_config.py index bcc627b..4b56cb8 100644 --- a/examples/merge_config.py +++ b/examples/merge_config.py @@ -77,6 +77,12 @@ kconf.enable_undef_warnings() # set up here as well. The approach in examples/allnoconfig_simpler.py could # provide an allnoconfig starting state for example.) +# Disable warnings generated for multiple assignments to the same symbol within +# a (set of) configuration files. Assigning a symbol multiple times might be +# done intentionally when merging configuration files. +kconf.disable_override_warnings() +kconf.disable_redun_warnings() + # Create a merged configuration by loading the fragments with replace=False for config in sys.argv[3:]: kconf.load_config(config, replace=False) @@ -109,6 +115,6 @@ for sym in kconf.defined_syms: user_value = sym.user_value if user_value != sym.str_value: - print('warning: {} was assigned the value "{}" but got the ' - 'value "{}" -- check dependencies' + print("warning: {} was assigned the value '{}' but got the " + "value '{}' -- check dependencies" .format(name_and_loc(sym), user_value, sym.str_value)) diff --git a/kconfiglib.py b/kconfiglib.py index 6ce3ab7..7c06eb4 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -731,6 +731,7 @@ class Kconfig(object): "_set_match", "_unset_match", "_warn_for_no_prompt", + "_warn_for_override", "_warn_for_redun_assign", "_warn_for_undef_assign", "_warn_to_stderr", @@ -852,7 +853,7 @@ class Kconfig(object): self._warn_to_stderr = warn_to_stderr self._warn_for_undef_assign = \ os.environ.get("KCONFIG_WARN_UNDEF_ASSIGN") == "y" - self._warn_for_redun_assign = True + self._warn_for_redun_assign = self._warn_for_override = True self._encoding = encoding @@ -1179,14 +1180,14 @@ class Kconfig(object): else: display_user_val = sym.user_value - warn_msg = '{} set more than once. Old value: "{}", new value: "{}".'.format( + msg = '{} set more than once. Old value: "{}", new value: "{}".'.format( _name_and_loc(sym), display_user_val, val ) if display_user_val == val: - self._warn_redun_assign(warn_msg, filename, linenr) + self._warn_redun_assign(msg, filename, linenr) else: - self._warn( warn_msg, filename, linenr) + self._warn_override(msg, filename, linenr) sym.set_value(val) @@ -1648,6 +1649,23 @@ class Kconfig(object): """ self._warn_for_undef_assign = False + def enable_override_warnings(self): + """ + Enables warnings for duplicated assignments in .config files that set + different values (e.g. CONFIG_FOO=m followed by CONFIG_FOO=y, where + the last value set is used). + + These warnings are enabled by default. Disabling them might be helpful + in certain cases when merging configurations. + """ + self._warn_for_override = True + + def disable_override_warnings(self): + """ + See enable_override_warnings(). + """ + self._warn_for_override = False + def enable_redun_warnings(self): """ Enables warnings for duplicated assignments in .config files that all @@ -3520,7 +3538,7 @@ class Kconfig(object): if self._warn_to_stderr: sys.stderr.write(msg + "\n") - def _warn_undef_assign(self, msg, filename=None, linenr=None): + def _warn_undef_assign(self, msg, filename, linenr): # See the class documentation if self._warn_for_undef_assign: @@ -3533,7 +3551,13 @@ class Kconfig(object): 'attempt to assign the value "{}" to the undefined symbol {}' .format(val, name), filename, linenr) - def _warn_redun_assign(self, msg, filename=None, linenr=None): + def _warn_override(self, msg, filename, linenr): + # See the class documentation + + if self._warn_for_override: + self._warn(msg, filename, linenr) + + def _warn_redun_assign(self, msg, filename, linenr): # See the class documentation if self._warn_for_redun_assign: @@ -5619,6 +5643,61 @@ def standard_config_filename(): """ return os.environ.get("KCONFIG_CONFIG", ".config") +def load_allconfig(kconf, filename): + """ + Helper for all*config. Loads (merges) the configuration file specified by + KCONFIG_ALLCONFIG, if any. See Documentation/kbuild/kconfig.txt in the + Linux kernel. + + Disables warnings for duplicated assignments within configuration files for + the duration of the call (disable_override_warnings() + + disable_redun_warnings()), and enables them at the end. The + KCONFIG_ALLCONFIG configuration file is expected to override symbols. + + Exits with sys.exit() (which raises a SystemExit exception) and prints an + error to stderr if KCONFIG_ALLCONFIG is set but the configuration file + can't be opened. + + kconf: + Kconfig instance to load the configuration in. + + filename: + Command-specific configuration filename - "allyes.config", + "allno.config", etc. + """ + def std_msg(e): + # "Upcasts" a _KconfigIOError to an IOError, removing the custom + # __str__() message. The standard message is better here. + return IOError(e.errno, e.strerror, e.filename) + + kconf.disable_override_warnings() + kconf.disable_redun_warnings() + + allconfig = os.environ.get("KCONFIG_ALLCONFIG") + if allconfig is not None: + if allconfig in ("", "1"): + try: + kconf.load_config(filename, False) + except IOError as e1: + try: + kconf.load_config("all.config", False) + except IOError as e2: + sys.exit("error: KCONFIG_ALLCONFIG is set, but neither {} " + "nor all.config could be opened: {}, {}" + .format(filename, std_msg(e1), std_msg(e2))) + else: + try: + kconf.load_config(allconfig, False) + except IOError as e: + sys.exit("error: KCONFIG_ALLCONFIG is set to '{}', which " + "could not be opened: {}" + .format(allconfig, std_msg(e))) + + # API wart: It would be nice if there was a way to query and/or push/pop + # warning settings + kconf.enable_override_warnings() + kconf.enable_redun_warnings() + # # Internal functions # -- cgit v1.2.3