| # Copyright 2026 The Pigweed Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| # use this file except in compliance with the License. You may obtain a copy of |
| # the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations under |
| # the License. |
| |
| import os |
| import sys |
| import argparse |
| import subprocess |
| import json |
| import re |
| from pathlib import Path |
| |
| import kconfig_utils |
| |
| SUPPORTED_ARCHITECTURES = ["arc", "arm", "arm64", "mips", "posix", "riscv", "sparc", "xtensa", "x86", "rx"] |
| |
| # Add Zephyr's kconfiglib to sys.path |
| def parse_args(): |
| parser = argparse.ArgumentParser() |
| parser.add_argument("--zephyr-base", required=True) |
| parser.add_argument("--app-dir", required=True) |
| parser.add_argument("--board", required=True) |
| parser.add_argument("--board-dir", required=True) |
| parser.add_argument("--parent-platform", required=True) |
| parser.add_argument("--modules", nargs="+", default=[]) |
| parser.add_argument("--output-dir", required=True) |
| parser.add_argument("--oot-dts-roots", nargs="+", default=[]) |
| parser.add_argument("--app-name", default="zephyr_app") |
| parser.add_argument("--toolchain-variant", default=None) |
| parser.add_argument("--conf-fragments", nargs="+", default=[]) |
| return parser.parse_args() |
| |
| def setup_environment(args, zephyr_base, output_dir, board_dir): |
| os.environ["srctree"] = zephyr_base |
| os.environ["ZEPHYR_BASE"] = zephyr_base |
| os.environ["KCONFIG_BINARY_DIR"] = output_dir |
| |
| # Replicate Zephyr SDK compiler capabilities for Kconfig |
| os.environ["TOOLCHAIN_HAS_PICOLIBC"] = "y" |
| os.environ["TOOLCHAIN_HAS_NEWLIB"] = "y" |
| |
| if "/" in args.board: |
| board_name, board_qualifiers = args.board.split("/", 1) |
| os.environ["BOARD"] = board_name |
| os.environ["BOARD_QUALIFIERS"] = board_qualifiers |
| else: |
| os.environ["BOARD"] = args.board |
| os.environ["BOARD_QUALIFIERS"] = "" |
| |
| os.environ["ARCH"] = "*" |
| os.environ["HWM_SCHEME"] = "v2" |
| os.environ["KCONFIG_FUNCTIONS"] = "kconfigfunctions" |
| os.environ["TOOLCHAIN_HAS_PICOLIBC"] = "y" |
| os.environ["TOOLCHAIN_HAS_NEWLIB"] = "y" |
| os.environ["ZEPHYR_TOOLCHAIN_VARIANT"] = "zephyr" |
| |
| # Determine toolchain variant similar to Zephyr's FindHostTools.cmake |
| toolchain_variant = args.toolchain_variant |
| if not toolchain_variant: |
| board_dir_lower = board_dir.lower() |
| if "native" in args.board or "boards/native" in board_dir_lower or "posix" in board_dir_lower: |
| toolchain_variant = "host" |
| else: |
| toolchain_variant = "zephyr" |
| |
| os.environ["TOOLCHAIN_KCONFIG_DIR"] = os.path.join(zephyr_base, "cmake", "toolchain", toolchain_variant) |
| os.environ["KCONFIG_BOARD_DIR"] = board_dir |
| os.environ["SOC_NAME"] = "none" # Will be overridden by defconfig |
| |
| kconfig_env_file = os.path.join(output_dir, "kconfig_module_dirs.env") |
| os.makedirs(output_dir, exist_ok=True) |
| with open(kconfig_env_file, "w") as f: |
| if args.modules: |
| for m in args.modules: |
| if os.path.isdir(m): |
| module_name = os.path.basename(m.rstrip('/')).split('+')[-1].replace('-', '_').upper() |
| m_abs = os.path.abspath(m) |
| f.write(f"ZEPHYR_{module_name}_MODULE_DIR={m_abs}\n") |
| os.environ[f"ZEPHYR_{module_name}_MODULE_DIR"] = m_abs |
| os.environ["KCONFIG_ENV_FILE"] = kconfig_env_file |
| |
| def generate_kconfig_aggregations(zephyr_base, args, output_dir, board_dir): |
| # Generate aggregation Kconfig files |
| soc_dirs = [] |
| |
| # Try to find SoC name from board.yml |
| soc_names = [] |
| for board_file in ["board.yml", "board.yaml"]: |
| board_yml_path = os.path.join(board_dir, board_file) |
| if os.path.exists(board_yml_path): |
| with open(board_yml_path, 'r') as f: |
| content = f.read() |
| # Simple heuristic to find soc name in board.yml |
| # It looks like: |
| # socs: |
| # - name: same70q21b |
| matches = re.findall(r"-\s*name:\s*(\S+)", content) |
| if matches: |
| soc_names.extend(matches) |
| break |
| |
| soc_roots = [Path(zephyr_base)] + ([Path(m) for m in args.modules] if args.modules else []) |
| for sroot in soc_roots: |
| if not sroot.exists(): |
| continue |
| for root, _, files in os.walk(sroot, followlinks=True): |
| if "soc.yml" in files: |
| soc_dirs.append(root) |
| |
| kconfig_utils.generate_aggregation_file(os.path.join(output_dir, "soc", "Kconfig.defconfig"), soc_dirs, "SoC defconfigs") |
| kconfig_utils.generate_aggregation_file(os.path.join(output_dir, "soc", "Kconfig"), soc_dirs, "SoC Kconfigs") |
| kconfig_utils.generate_aggregation_file(os.path.join(output_dir, "soc", "Kconfig.soc"), soc_dirs, "SoC Kconfigs") |
| kconfig_utils.generate_aggregation_file(os.path.join(output_dir, "soc", "Kconfig.sysbuild"), soc_dirs, "SoC sysbuild Kconfigs") |
| |
| shield_defconfig = os.path.join(output_dir, "Kconfig.shield.defconfig") |
| os.makedirs(os.path.dirname(shield_defconfig), exist_ok=True) |
| with open(shield_defconfig, "w") as f: |
| f.write("# Empty shield defconfig\n") |
| |
| arch_dirs = [] |
| arch_root = os.path.join(zephyr_base, "arch") |
| for d in os.listdir(arch_root): |
| if os.path.isdir(os.path.join(arch_root, d)): |
| arch_dirs.append(os.path.join(arch_root, d)) |
| kconfig_utils.generate_aggregation_file(os.path.join(output_dir, "arch", "Kconfig"), arch_dirs, "Arch Kconfigs") |
| |
| board_dirs = [board_dir] |
| kconfig_utils.generate_aggregation_file(os.path.join(output_dir, "boards", "Kconfig.defconfig"), board_dirs, "Board defconfigs") |
| kconfig_utils.generate_aggregation_file(os.path.join(output_dir, "boards", "Kconfig"), board_dirs, "Board Kconfigs") |
| kconfig_utils.generate_aggregation_file(os.path.join(output_dir, "boards", "Kconfig.sysbuild"), board_dirs, "Board sysbuild Kconfigs") |
| |
| board_name = os.environ["BOARD"] |
| board_kconfig_agg = os.path.join(output_dir, "boards", f"Kconfig.{board_name}") |
| os.makedirs(os.path.dirname(board_kconfig_agg), exist_ok=True) |
| with open(board_kconfig_agg, "w") as f: |
| board_kconfig = os.path.join(board_dir, "Kconfig") |
| if not os.path.exists(board_kconfig): |
| board_kconfig = os.path.join(board_dir, f"Kconfig.{board_name}") |
| if os.path.exists(board_kconfig): |
| f.write(f'osource "{os.path.abspath(board_kconfig)}"\n') |
| |
| kconfig_modules = os.path.join(output_dir, "Kconfig.modules") |
| kconfig_utils.generate_kconfig_modules(zephyr_base, args.modules, kconfig_modules) |
| |
| def discover_overlays(app_dir, board_name, board_qualifiers): |
| board_qualifiers = board_qualifiers.lstrip("/") |
| overlays = [] |
| |
| # 1. Board-specific overlays in app |
| if board_qualifiers: |
| safe_q = board_qualifiers.replace("/", "_") |
| soc_board_overlay = os.path.join( |
| app_dir, "boards", f"{board_name}_{safe_q}.overlay" |
| ) |
| if os.path.exists(soc_board_overlay): |
| overlays.append(soc_board_overlay) |
| |
| board_overlay = os.path.join(app_dir, "boards", f"{board_name}.overlay") |
| if os.path.exists(board_overlay): |
| overlays.append(board_overlay) |
| |
| # 2. Default app overlay |
| app_overlay = os.path.join(app_dir, "app.overlay") |
| if os.path.exists(app_overlay): |
| overlays.append(app_overlay) |
| |
| return overlays |
| |
| def preprocess_dts(args, zephyr_base, output_dir, board_dir): |
| # Determine input DTS file |
| board_name = os.environ["BOARD"] |
| board_qualifiers = os.environ.get("BOARD_QUALIFIERS", "") |
| |
| candidates = [ |
| os.path.join(board_dir, f"{args.board.replace('/', '_')}.dts"), |
| os.path.join(board_dir, f"{board_name}.dts"), |
| ] |
| |
| # In HWM v2, try to find a DTS file matching any SoC in board.yml |
| for board_file in ["board.yml", "board.yaml"]: |
| board_yml_path = os.path.join(board_dir, board_file) |
| if os.path.exists(board_yml_path): |
| with open(board_yml_path, 'r') as f: |
| content = f.read() |
| matches = re.findall(r"-\s*name:\s*(\S+)", content) |
| for soc in matches: |
| candidates.append(os.path.join(board_dir, f"{board_name}_{soc}.dts")) |
| break |
| |
| dts_file = None |
| for candidate in candidates: |
| if os.path.exists(candidate): |
| dts_file = candidate |
| break |
| |
| if not dts_file: |
| raise RuntimeError(f"Could not find DTS file for board {args.board} in {board_dir}. Tried: {candidates}") |
| |
| overlays = discover_overlays(args.app_dir, board_name, board_qualifiers) |
| |
| dts_input_path = os.path.join(output_dir, "dts_input.c") |
| os.makedirs(output_dir, exist_ok=True) |
| with open(dts_input_path, "w") as f: |
| f.write("/* Generated by zephyr-bazel - do not edit! */\n") |
| f.write(f'#include "{os.path.abspath(dts_file)}"\n') |
| for overlay in overlays: |
| f.write(f'#include "{os.path.abspath(overlay)}"\n') |
| |
| merged_dts_path = os.path.join(output_dir, "zephyr.dts") |
| |
| # Preprocess DTS using pcpp |
| import pcpp |
| pcmd_path = os.path.join(os.path.dirname(pcpp.__file__), "pcmd.py") |
| pcpp_args = [ |
| sys.executable, |
| pcmd_path, |
| dts_input_path, |
| ] |
| |
| raw_roots = [Path(r) for r in args.oot_dts_roots] + [Path(m) for m in args.modules] + [Path(zephyr_base)] |
| dts_roots = [] |
| for r in raw_roots: |
| if r not in dts_roots: |
| dts_roots.append(r) |
| for dts_root in dts_roots: |
| directories = [ |
| "include", |
| "include/zephyr", |
| "dts", |
| "dts/common", |
| ] + ["dts/" + a for a in SUPPORTED_ARCHITECTURES] + ["dts/vendor"] |
| for directory in directories: |
| path = dts_root / directory |
| if path.exists(): |
| pcpp_args.append("-I" + str(path.resolve())) |
| pcpp_args.extend(["-o", merged_dts_path]) |
| |
| subprocess.run(pcpp_args, check=True) |
| return merged_dts_path, dts_roots |
| |
| def generate_edt_pickle(zephyr_base, output_dir, dts_roots, merged_dts_path): |
| output_edt_pickle_path = os.path.join(output_dir, "edt.pickle") |
| |
| bindings_dirs = [] |
| for dts_root in dts_roots: |
| bdir = dts_root / "zephyr" / "dts" / "bindings" |
| if bdir.exists(): |
| if str(bdir.resolve()) not in bindings_dirs: |
| bindings_dirs.append(str(bdir.resolve())) |
| else: |
| bdir = dts_root / "dts" / "bindings" |
| if bdir.exists(): |
| if str(bdir.resolve()) not in bindings_dirs: |
| bindings_dirs.append(str(bdir.resolve())) |
| |
| gen_edt_args = [ |
| sys.executable, |
| os.path.join(zephyr_base, "scripts", "dts", "gen_edt.py"), |
| "--edt-pickle-out", |
| output_edt_pickle_path, |
| "--dts", |
| merged_dts_path, |
| "--bindings-dirs", |
| ] |
| gen_edt_args.extend(bindings_dirs) |
| gen_edt_args.extend([ |
| "--dts-out", |
| os.path.join(output_dir, "zephyr.dts.debug"), |
| "--dtc-flags", |
| "Wno-simple_bus_reg", |
| ]) |
| |
| # Add PYTHONPATH for edtlib |
| env = os.environ.copy() |
| env["PYTHONPATH"] = os.path.join(zephyr_base, "scripts", "dts") + ":" + os.path.join(zephyr_base, "scripts", "dts", "python-devicetree", "src") + ":" + env.get("PYTHONPATH", "") |
| print(f"DEBUG PYTHONPATH: {env['PYTHONPATH']}") |
| |
| subprocess.run(gen_edt_args, env=env, check=True) |
| os.environ["EDT_PICKLE"] = output_edt_pickle_path |
| |
| def generate_dts_headers(zephyr_base, output_dir, edt_pickle_path): |
| gen_defines_py = os.path.join(zephyr_base, "scripts", "dts", "gen_defines.py") |
| output_header = os.path.join(output_dir, "zephyr", "devicetree_generated.h") |
| os.makedirs(os.path.dirname(output_header), exist_ok=True) |
| |
| cmd = [ |
| sys.executable, |
| gen_defines_py, |
| "--edt-pickle", edt_pickle_path, |
| "--header-out", output_header, |
| ] |
| |
| # Ensure edtlib is in PYTHONPATH (portable using os.pathsep) |
| env = os.environ.copy() |
| env["PYTHONPATH"] = os.pathsep.join([ |
| os.path.join(zephyr_base, "scripts", "dts"), |
| os.path.join(zephyr_base, "scripts", "dts", "python-devicetree", "src"), |
| env.get("PYTHONPATH", ""), |
| ]) |
| |
| subprocess.run(cmd, env=env, check=True) |
| |
| def get_conf_files(args, board_dir): |
| board_name = os.environ["BOARD"] |
| board_qualifiers = os.environ.get("BOARD_QUALIFIERS", "").lstrip("/") |
| |
| conf_files = [] |
| |
| # Try qualified defconfig (HWM v2) |
| if board_qualifiers: |
| safe_qualifiers = board_qualifiers.replace("/", "_") |
| qualified_defconfig = os.path.join(board_dir, f"{board_name}_{safe_qualifiers}_defconfig") |
| if os.path.exists(qualified_defconfig): |
| conf_files.append(qualified_defconfig) |
| |
| # Fallback to base defconfig |
| if not conf_files: |
| board_defconfig = os.path.join(board_dir, f"{board_name}_defconfig") |
| if os.path.exists(board_defconfig): |
| conf_files.append(board_defconfig) |
| |
| prj_conf = os.path.join(args.app_dir, "prj.conf") |
| if os.path.exists(prj_conf): |
| conf_files.append(prj_conf) |
| |
| # Also try board-specific conf in app dir |
| if board_qualifiers: |
| soc_board_conf = os.path.join(args.app_dir, "boards", f"{board_name}_{board_qualifiers}.conf") |
| if os.path.exists(soc_board_conf): |
| conf_files.append(soc_board_conf) |
| |
| board_conf = os.path.join(args.app_dir, "boards", f"{board_name}.conf") |
| if os.path.exists(board_conf): |
| conf_files.append(board_conf) |
| |
| return conf_files |
| |
| def generate_config_c(kconf, output_dir, args): |
| os.makedirs(os.path.join(output_dir, "zephyr"), exist_ok=True) |
| with open(os.path.join(output_dir, "zephyr", "config.c"), "w") as f: |
| f.write("/* AUTO-GENERATED by kconfig_gen_values.py, do not edit! */\n\n") |
| f.write("#include <zephyr/toolchain.h>\n\n") |
| f.write("GEN_ABS_SYM_BEGIN (_ConfigAbsSyms)\n") |
| |
| # Call scripts/build/generate_configs_dot_c.py methodology |
| for sym in kconf.unique_defined_syms: |
| if not sym.nodes: |
| continue |
| |
| val = None |
| # Import here because it's not available at the top level due to path setup. |
| import kconfiglib |
| if sym.type in [kconfiglib.BOOL, kconfiglib.TRISTATE]: |
| if sym.str_value == "y": |
| val = "1" |
| elif sym.type == kconfiglib.INT: |
| if sym.str_value: |
| val = sym.str_value |
| elif sym.type == kconfiglib.HEX: |
| if sym.str_value: |
| val = "0x" + sym.str_value.replace("0x", "") |
| elif sym.type == kconfiglib.STRING: |
| if sym.str_value: |
| val = "1" |
| |
| if val is not None: |
| f.write(f"GEN_ABSOLUTE_SYM_KCONFIG(CONFIG_{sym.name}, {val});\n") |
| |
| f.write("GEN_ABS_SYM_END\n") |
| |
| def generate_bazel_build(args, kconf, output_dir, kconfiglib): |
| resolved_arch = "arm" |
| for a in SUPPORTED_ARCHITECTURES: |
| sym_name = "ARCH_POSIX" if a == "posix" else a.upper() |
| sym = kconf.syms.get(sym_name) |
| if sym and sym.str_value == "y": |
| resolved_arch = a |
| break |
| |
| if resolved_arch == "arm": |
| # Fallback check for ARC if standard symbol is missing |
| sym = kconf.syms.get("DT_HAS_SNPS_ARCEM_ENABLED") |
| if sym and sym.str_value == "y": |
| resolved_arch = "arc" |
| |
| arch_macro = "__arm__" |
| if resolved_arch == "arm64": |
| arch_macro = "__aarch64__" |
| elif resolved_arch == "x86": |
| arch_macro = "__i386__" |
| elif resolved_arch == "riscv": |
| arch_macro = "__riscv" |
| |
| soc_name = kconf.syms.get("SOC").str_value |
| if not soc_name: |
| # Try SOC_SERIES or other fallbacks if SOC is empty |
| soc_name = kconf.syms.get("SOC_SERIES").str_value |
| if not soc_name: |
| soc_name = os.environ.get("BOARD", "unknown") |
| |
| target_name = kconfig_utils.sanitize_name_for_target(soc_name) |
| print(f"DEBUG: soc_name={soc_name}, target_name={target_name}") |
| |
| with open(os.path.join(output_dir, "BUILD.bazel"), "w") as f: |
| f.write('load("@rules_cc//cc:defs.bzl", "cc_library")\n') |
| f.write('load("@zephyr//:cc.bzl", "zephyr_cc_library")\n') |
| f.write('package(default_visibility = ["//visibility:public"])\n\n') |
| f.write('exports_files(["zephyr/autoconf.h", "zephyr/devicetree_generated.h", ".config"])\n\n') |
| |
| f.write('cc_library(\n') |
| f.write(' name = "devicetree_generated",\n') |
| f.write(' hdrs = ["zephyr/devicetree_generated.h"],\n') |
| f.write(' includes = ["."],\n') |
| f.write(')\n\n') |
| |
| f.write('cc_library(\n') |
| f.write(' name = "autoconf_library",\n') |
| f.write(' hdrs = ["zephyr/autoconf.h"],\n') |
| f.write(' includes = ["."],\n') |
| f.write(' deps = [":devicetree_generated"],\n') |
| f.write(')\n\n') |
| |
| f.write('zephyr_cc_library(\n') |
| f.write(' name = "autoconf_symbols",\n') |
| f.write(' srcs = ["zephyr/config.c"],\n') |
| f.write(' copts = ["-D%s"],\n' % arch_macro) |
| f.write(' deps = [\n') |
| f.write(' ":autoconf_library",\n') |
| f.write(' "@zephyr//include:zephyr",\n') |
| f.write(' ],\n') |
| f.write(')\n\n') |
| |
| f.write('platform(\n') |
| f.write(' name = "%s",\n' % target_name) |
| f.write(' parents = ["%s"],\n' % args.parent_platform) |
| f.write(' flags = [\n') |
| for sym in kconf.unique_defined_syms: |
| if not sym.nodes: |
| continue |
| |
| sname = kconfig_utils.sanitize_name_for_target(sym.name) |
| full_name = "CONFIG_" + sname |
| |
| if sym.type in [kconfiglib.BOOL, kconfiglib.TRISTATE]: |
| val = "true" if sym.str_value == "y" else "false" |
| f.write(' "--@zephyr_kconfig//:%s=%s",\n' % (full_name, val)) |
| elif sym.type == kconfiglib.INT: |
| if sym.str_value: |
| f.write(' "--@zephyr_kconfig//:%s=%s",\n' % (full_name, sym.str_value)) |
| elif sym.type == kconfiglib.HEX: |
| if sym.str_value: |
| try: |
| val = int(sym.str_value, 16) |
| f.write(' "--@zephyr_kconfig//:%s=%d",\n' % (full_name, val)) |
| except: |
| pass |
| elif sym.type == kconfiglib.STRING: |
| if sym.str_value: |
| f.write(' "--@zephyr_kconfig//:%s=%s",\n' % (full_name, sym.str_value)) |
| |
| # Resolve board DTS target |
| board_label = args.parent_platform |
| board_pkg = board_label.split(":")[0] |
| f.write(' "--@zephyr//:autoconf_file=@zc_target//:zephyr/autoconf.h",\n') |
| f.write(' "--@zephyr//:autoconf_library=@zc_target//:autoconf_library",\n') |
| f.write(' "--@zephyr//:autoconf_symbols_to_link=@zc_target//:autoconf_symbols",\n') |
| f.write(' "--@zephyr//:dts_cc_library=@zc_target//:devicetree_generated",\n') |
| f.write(' ],\n') |
| f.write(')\n\n') |
| f.write('alias(name = "platform", actual = ":%s")\n' % target_name) |
| |
| def main(): |
| args = parse_args() |
| kconfig_utils.setup_kconfiglib(args.zephyr_base) |
| # kconfiglib is in Zephyr's scripts/kconfig directory, which is added to path by setup_kconfiglib above. |
| import kconfiglib |
| |
| zephyr_base = os.path.abspath(args.zephyr_base) |
| output_dir = os.path.abspath(args.output_dir) |
| board_dir = os.path.abspath(args.board_dir) |
| |
| board_name = args.board.split("/")[0] |
| if not os.path.exists(os.path.join(board_dir, "board.yml")) and not os.path.exists(os.path.join(board_dir, f"{board_name}.dts")): |
| found = False |
| for root in [board_dir] + args.oot_dts_roots: |
| for dirpath, _, filenames in os.walk(root, followlinks=True): |
| if f"{board_name}.dts" in filenames: |
| board_dir = os.path.abspath(dirpath) |
| found = True |
| break |
| if found: break |
| |
| setup_environment(args, zephyr_base, output_dir, board_dir) |
| |
| generate_kconfig_aggregations(zephyr_base, args, output_dir, board_dir) |
| |
| merged_dts_path, dts_roots = preprocess_dts(args, zephyr_base, output_dir, board_dir) |
| generate_edt_pickle(zephyr_base, output_dir, dts_roots, merged_dts_path) |
| generate_dts_headers(zephyr_base, output_dir, os.path.join(output_dir, "edt.pickle")) |
| kconfig_utils.generate_kconfig_dts(zephyr_base, os.path.join(output_dir, "Kconfig.dts"), dts_roots) |
| |
| # Re-verify environment for kconfiglib |
| os.environ["ARCH"] = "*" |
| os.environ["ZEPHYR_BASE"] = zephyr_base |
| |
| conf_files = get_conf_files(args, board_dir) |
| conf_files.extend(args.conf_fragments) |
| |
| os.makedirs(os.path.join(output_dir, "zephyr"), exist_ok=True) |
| |
| # Call Zephyr's kconfig.py |
| kconfig_py = os.path.join(zephyr_base, "scripts", "kconfig", "kconfig.py") |
| cmd = [ |
| sys.executable, |
| kconfig_py, |
| "--handwritten-input-configs", |
| os.path.join(zephyr_base, "Kconfig"), |
| os.path.join(output_dir, ".config"), |
| os.path.join(output_dir, "zephyr", "autoconf.h"), |
| os.path.join(output_dir, "kconfig_list.txt"), |
| ] + conf_files |
| |
| env = os.environ.copy() |
| |
| res = subprocess.run(cmd, env=env, capture_output=True, text=True) |
| |
| if res.stderr: |
| print(res.stderr, file=sys.stderr) |
| |
| if res.returncode != 0: |
| sys.exit(f"Kconfig generation failed with exit code {res.returncode}") |
| |
| # Add the app name to the autoconf.h since bazel does not propagate build flags to dependencies. |
| with open(os.path.join(output_dir, "zephyr", "autoconf.h"), "a") as f: |
| f.write(f'#define APP_NAME "{args.app_name}"\n') |
| |
| # Load generated .config with kconfiglib |
| kconf = kconfiglib.Kconfig(os.path.join(zephyr_base, "Kconfig")) |
| kconf.load_config(os.path.join(output_dir, ".config")) |
| |
| generate_config_c(kconf, output_dir, args) |
| generate_bazel_build(args, kconf, output_dir, kconfiglib) |
| |
| if __name__ == "__main__": |
| main() |