#!/usr/bin/env python3 # # Copyright (c) 2022 Kumar Gala # Copyright (c) 2025 Nordic Semiconductor ASA # # SPDX-License-Identifier: Apache-2.0 import argparse import os import yaml try: # Use the C LibYAML parser if available, rather than the Python parser. from yaml import CSafeLoader as SafeLoader except ImportError: from yaml import SafeLoader # type: ignore HEADER = """\ # Generated devicetree Kconfig # # SPDX-License-Identifier: Apache-2.0""" KCONFIG_TEMPLATE = """ DT_COMPAT_{COMPAT} := {compat} config DT_HAS_{COMPAT}_ENABLED \tdef_bool $(dt_compat_enabled,$(DT_COMPAT_{COMPAT}))""" # Character translation table used to derive Kconfig symbol names TO_UNDERSCORES = str.maketrans("-,.@/+", "______") def binding_paths(bindings_dirs): # Yields paths to all bindings (.yaml files) in 'bindings_dirs' for bindings_dir in bindings_dirs: for root, _, filenames in os.walk(bindings_dir): for filename in filenames: if filename.endswith((".yaml", ".yml")): yield os.path.join(root, filename) def parse_args(): # Returns parsed command-line arguments parser = argparse.ArgumentParser(allow_abbrev=False) parser.add_argument("--kconfig-out", required=True, help="path to write the Kconfig file") parser.add_argument("--bindings-dirs", nargs='+', required=True, help="directory with bindings in YAML format, " "we allow multiple") return parser.parse_args() def main(): args = parse_args() compats = set() for binding_path in binding_paths(args.bindings_dirs): with open(binding_path, encoding="utf-8") as f: try: # Parsed PyYAML representation graph. For our purpose, # we don't need the whole file converted into a dict. root = yaml.compose(f, Loader=SafeLoader) except yaml.YAMLError as e: print(f"WARNING: '{binding_path}' appears in binding " f"directories but isn't valid YAML: {e}") continue if not isinstance(root, yaml.MappingNode): continue for key, node in root.value: if key.value == "compatible" and isinstance(node, yaml.ScalarNode): compats.add(node.value) break with open(args.kconfig_out, "w", encoding="utf-8") as kconfig_file: print(HEADER, file=kconfig_file) for c in sorted(compats): out = KCONFIG_TEMPLATE.format( compat=c, COMPAT=c.upper().translate(TO_UNDERSCORES) ) print(out, file=kconfig_file) if __name__ == "__main__": main()