123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- import argparse
- import os
- import sys
- import textwrap
- from kconfiglib import Kconfig, split_expr, expr_value, expr_str, BOOL, \
- TRISTATE, TRI_TO_STR, AND
- def main():
- args = parse_args()
- if args.zephyr_base:
- os.environ['ZEPHYR_BASE'] = args.zephyr_base
- print("Parsing " + args.kconfig_file)
- kconf = Kconfig(args.kconfig_file, warn_to_stderr=False,
- suppress_traceback=True)
- if args.handwritten_input_configs:
-
-
-
- kconf.warn_assign_undef = True
-
-
- kconf.warn_assign_override = False
- kconf.warn_assign_redun = False
-
- print(kconf.load_config(args.configs_in[0]))
- for config in args.configs_in[1:]:
-
- print(kconf.load_config(config, replace=False))
- if args.handwritten_input_configs:
-
-
-
-
-
-
- check_no_promptless_assign(kconf)
-
-
-
- check_assigned_sym_values(kconf)
- check_assigned_choice_values(kconf)
-
-
-
-
-
-
- kconf.write_config(os.devnull)
- if kconf.warnings:
-
- for warning in kconf.warnings:
- print("\n" + warning, file=sys.stderr)
-
-
-
-
-
-
- err("Aborting due to Kconfig warnings")
-
- print(kconf.write_config(args.config_out))
- print(kconf.write_autoconf(args.header_out))
-
- write_kconfig_filenames(kconf, args.kconfig_list_out)
- def check_no_promptless_assign(kconf):
-
- for sym in kconf.unique_defined_syms:
- if sym.user_value is not None and promptless(sym):
- err(f"""\
- {sym.name_and_loc} is assigned in a configuration file, but is not directly
- user-configurable (has no prompt). It gets its value indirectly from other
- symbols. """ + SYM_INFO_HINT.format(sym))
- def check_assigned_sym_values(kconf):
-
-
-
- for sym in kconf.unique_defined_syms:
- if sym.choice:
- continue
- user_value = sym.user_value
- if user_value is None:
- continue
-
-
- if sym.type in (BOOL, TRISTATE):
- user_value = TRI_TO_STR[user_value]
- if user_value != sym.str_value:
- msg = f"{sym.name_and_loc} was assigned the value '{user_value}'" \
- f" but got the value '{sym.str_value}'. "
-
- mdeps = missing_deps(sym)
- if mdeps:
- expr_strs = []
- for expr in mdeps:
- estr = expr_str(expr)
- if isinstance(expr, tuple):
-
-
-
- estr = f"({estr})"
- expr_strs.append(f"{estr} "
- f"(={TRI_TO_STR[expr_value(expr)]})")
- msg += "Check these unsatisfied dependencies: " + \
- ", ".join(expr_strs) + ". "
- warn(msg + SYM_INFO_HINT.format(sym))
- def missing_deps(sym):
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- deps = split_expr(sym.direct_dep, AND)
- if sym.type in (BOOL, TRISTATE):
- return [dep for dep in deps if expr_value(dep) < sym.user_value]
-
- return [dep for dep in deps if expr_value(dep) == 0]
- def check_assigned_choice_values(kconf):
-
-
-
-
-
-
-
-
-
-
-
- for choice in kconf.unique_choices:
- if choice.user_selection and \
- choice.user_selection is not choice.selection:
- warn(f"""\
- The choice symbol {choice.user_selection.name_and_loc} was selected (set =y),
- but {choice.selection.name_and_loc if choice.selection else "no symbol"} ended
- up as the choice selection. """ + SYM_INFO_HINT.format(choice.user_selection))
- SYM_INFO_HINT = """\
- See http://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_{0.name}.html
- and/or look up {0.name} in the menuconfig/guiconfig interface. The Application
- Development Primer, Setting Configuration Values, and Kconfig - Tips and Best
- Practices sections of the manual might be helpful too.\
- """
- def promptless(sym):
-
-
- return not any(node.prompt for node in sym.nodes)
- def write_kconfig_filenames(kconf, kconfig_list_path):
-
-
-
-
- with open(kconfig_list_path, 'w') as out:
- for path in sorted({os.path.realpath(os.path.join(kconf.srctree, path))
- for path in kconf.kconfig_filenames}):
- print(path, file=out)
- def parse_args():
- parser = argparse.ArgumentParser()
- parser.add_argument("--handwritten-input-configs",
- action="store_true",
- help="Assume the input configuration fragments are "
- "handwritten fragments and do additional checks "
- "on them, like no promptless symbols being "
- "assigned")
- parser.add_argument("--zephyr-base",
- help="Path to current Zephyr installation")
- parser.add_argument("kconfig_file",
- help="Top-level Kconfig file")
- parser.add_argument("config_out",
- help="Output configuration file")
- parser.add_argument("header_out",
- help="Output header file")
- parser.add_argument("kconfig_list_out",
- help="Output file for list of parsed Kconfig files")
- parser.add_argument("configs_in",
- nargs="+",
- help="Input configuration fragments. Will be merged "
- "together.")
- return parser.parse_args()
- def warn(msg):
-
-
-
-
- print("\n" + textwrap.fill("warning: " + msg, 100) + "\n", file=sys.stderr)
- def err(msg):
- sys.exit("\n" + textwrap.fill("error: " + msg, 100) + "\n")
- if __name__ == "__main__":
- main()
|