#!/usr/bin/env python3 # This script functions similarly to scripts/kconfig/merge_config.sh from the # kernel tree, merging multiple configurations fragments to produce a complete # .config, with unspecified values filled in as for alldefconfig. # # The generated .config respects symbol dependencies, and a warning is printed # if any symbol gets a different value from the assigned value. # # For a real-world merging example based on this script, see # https://github.com/zephyrproject-rtos/zephyr/blob/master/scripts/kconfig/kconfig.py. # # Here's a demo: # # Kconfig contents: # # config FOO # bool "FOO" # # config BAR # bool "BAR" # # config BAZ # string "BAZ" # # config QAZ # bool "QAZ" if n # # # conf1 contents: # # CONFIG_FOO=y # # # conf2 contents: # # CONFIG_BAR=y # # # conf3 contents: # # # Assigned twice (would generate warning if 'warn_assign_override' was # # True) # # CONFIG_FOO is not set # # # Ops... this symbol doesn't exist # CONFIG_OPS=y # # CONFIG_BAZ="baz string" # # # conf4 contents: # # CONFIG_QAZ=y # # # Running: # # $ python(3) merge_config.py Kconfig merged conf1 conf2 conf3 conf4 # Merged configuration 'conf1' # Merged configuration 'conf2' # conf3:5: warning: attempt to assign the value 'y' to the undefined symbol OPS # Merged configuration 'conf3' # Merged configuration 'conf4' # Configuration saved to 'merged' # warning: QAZ (defined at Kconfig:10) was assigned the value 'y' but got the value 'n' -- check dependencies # $ cat merged # Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) # # CONFIG_FOO is not set # CONFIG_BAR=y # CONFIG_BAZ="baz string" from __future__ import print_function import sys import re import pprint def _re_match(regex): return re.compile(regex, re.ASCII).match from kconfiglib import Kconfig, BOOL, TRISTATE, TRI_TO_STR def main(kconfig_file, config1, config2): kconf = Kconfig(kconfig_file, suppress_traceback=True) # Enable warnings for assignments to undefined symbols kconf.warn_assign_undef = False # (This script uses alldefconfig as the base. Other starting states could be # 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.warn_assign_override = False kconf.warn_assign_redun = False # Create a merged configuration by loading the fragments with replace=False. # load_config() and write_config() returns a message to print. print(kconf.load_config(config1, replace=False)) print(kconf.load_config(config2, replace=False)) # Modification for PX4 unset all symbols (INT,HEX etc) from 2nd config f = open(config2, 'r') unset_match = re.compile(r"# {}([^ ]+) is not set".format("CONFIG_"), re.ASCII).match for line in f: match = unset_match(line) #pprint.pprint(line) if match is not None: sym_name = match.group(1) kconf.syms[sym_name].unset_value() if kconf.syms[sym_name].type is BOOL: for default, cond in kconf.syms[sym_name].orig_defaults: if(cond.str_value == 'y'): # Default is y, our diff is unset thus we've set it to no kconf.syms[sym_name].set_value(0) f.close() # Print warnings for symbols whose actual value doesn't match the assigned # value for sym in kconf.defined_syms: # Was the symbol assigned to? if sym.user_value is not None: # Tristate values are represented as 0, 1, 2. Having them as # "n", "m", "y" is more convenient here, so convert. if sym.type in (BOOL, TRISTATE): user_value = TRI_TO_STR[sym.user_value] else: user_value = sym.user_value if user_value != sym.str_value: print("warning: {} was assigned the value '{}' but got the " "value '{}' -- check dependencies".format( sym.name_and_loc, user_value, sym.str_value), file=sys.stderr) return kconf if __name__ == '__main__': if len(sys.argv) < 4: sys.exit("usage: merge_config.py Kconfig merged_config config1 config2]") # Write the merged configuration print(main(sys.argv[1],sys.argv[3],sys.argv[4]).write_config(sys.argv[2]))