diff --git a/cmake/kconfig.cmake b/cmake/kconfig.cmake index 560f5dc94edb7..d0982d23f6ae5 100644 --- a/cmake/kconfig.cmake +++ b/cmake/kconfig.cmake @@ -112,9 +112,8 @@ endif() if(CREATE_NEW_DOTCONFIG) execute_process( COMMAND + ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/kconfig/merge_config.py - -m - -q -O ${PROJECT_BINARY_DIR} ${merge_config_files} WORKING_DIRECTORY ${APPLICATION_SOURCE_DIR} diff --git a/scripts/kconfig/merge_config.py b/scripts/kconfig/merge_config.py index 115bd10a1c17c..95553b91dade6 100755 --- a/scripts/kconfig/merge_config.py +++ b/scripts/kconfig/merge_config.py @@ -7,12 +7,6 @@ def arguments_parse(): parser = argparse.ArgumentParser() parser.add_argument('-q', dest="quiet", action='store_true') - parser.add_argument( - '-m', dest='runmake', action='store_false', - help='only merge the fragments, do not execute the make command') - parser.add_argument( - '-n', dest='alltarget', action='store_const', const='allnoconfig', - default='alldefconfig', help='use allnoconfig instead of alldefconfig') parser.add_argument('-r', dest='warnredun', action='store_true', help='list redundant entries when merging fragments') parser.add_argument('-O', dest='output_dir', @@ -22,70 +16,78 @@ def arguments_parse(): return parser.parse_args() -def get_config_list(config_file): - cfg_list = [] - pattern = re.compile('^(# ){0,1}(CONFIG_[a-zA-Z0-9_]*)[= ].*') - with open(config_file, 'r') as file: - for line in file: - match = pattern.match(line) - if match: - if match.group(2): - config_name = match.group(2) - else: - config_name = match.group(1) - cfg_list.append((config_name, match.group(0), )) - return cfg_list +def get_config_name(line): + # '# CONFIG_FOO is not set' should be treated by merge_config as a + # state like any other + is_not_set_pattern = re.compile('^# (CONFIG_[a-zA-Z0-9_]*) is not set.*') + pattern = re.compile('^(CONFIG_[a-zA-Z0-9_]*)[= ].*') -def remove_config(initfile_content, cfg): - pattern = re.compile("{}[ =]".format(cfg)) - lines = initfile_content.split("\n") - new_lines = [] + match = pattern.match(line) + match_is_not_set = is_not_set_pattern.match(line) - for line in lines: - match = pattern.match(line) - if not match: - new_lines.append(line) - initfile_content = "\n".join(new_lines) - return initfile_content - - -def append_files(f1, initfile_content): - fin = open(f1, "r") - data2 = fin.read() - fin.close() - return(initfile_content + data2) + if match_is_not_set: + return match_is_not_set.group(1) + elif match: + return match.group(1) + return "" # No match def main(): args = arguments_parse() - init_file = open(args.config[0]) - initfile_content = init_file.read() - init_file.close() - print("-- Using %s as base" % args.config[0]) - - for config_file in args.config[1:]: - print("-- Merging %s" % config_file) - cfg_list = get_config_list(config_file) - - for cfg, full in cfg_list: - prev=list(filter(lambda x: cfg in x, initfile_content.split("\n"))) - if len(prev) > 0 and prev[0] != full and not args.quiet: - print("-- Value of {} is redefined by fragment {}".format(cfg, config_file)) - print("-- Previous value: {}".format(prev[0])) - print("-- New value: {}".format(full)) - elif args.warnredun: - print("Value of %s is redundant by fragment %s" % (cfg, config_file)) - - initfile_content = remove_config(initfile_content, cfg) - - initfile_content = append_files(config_file, initfile_content) - - if args.runmake: - print("Running make not yet supported") - else: - with open('%s/.config' % args.output_dir, 'w') as file: - file.write(initfile_content) + + # Create a datastructure in 'conf' that looks like this: + # [ + # ("CONFIG_UART", "CONFIG_UART=y"), + # ("CONFIG_ARM", "# CONFIG_ARM is not set") + # ] + # In other words [(config_name, config_line), ... ] + # + # Note that "# CONFIG_ARM is not set" is not the same as a + # comment, it has meaning (for now). + # https://github.com/zephyrproject-rtos/zephyr/issues/5443 + conf = [] + for i, fragment_path in enumerate(args.config): + with open(fragment_path, "r") as f: + fragment = f.read() + fragment_list = fragment.split("\n") + + fragment_conf = [] + for line in fragment_list: + config_name = get_config_name(line) + if config_name: + fragment_conf.append( (config_name, line) ) + + if i == 0: + print("-- Using {} as base".format(fragment_path)) + else: + print("-- Merging {}".format(fragment_path)) + + for config_name, line in fragment_conf: + for (i, (prev_config_name, prev_line)) in enumerate(list(conf)): + if config_name == prev_config_name: + # The fragment is defining a config that has + # already been defined, the fragment has + # priority, so we remove the existing entry + # and then possibly issue a warning. + conf.pop(i) + + is_redundant = line == prev_line + is_redefine = line != prev_line + if not args.quiet: + if is_redefine: + print("-- Value of {} is redefined by fragment {}".format(config_name, fragment_path)) + print("-- Previous value: {}".format(prev_line)) + print("-- New value: {}".format(line)) + + if is_redundant and args.warnredun: + print("-- Value of {} is redundant by fragment {}".format(config_name, fragment_path)) + + conf.extend(fragment_conf) + + with open('{}/.config'.format(args.output_dir), 'w') as f: + for (config_name, line) in conf: + f.write("{}\n".format(line)) if __name__ == "__main__": main()