test_led_strip/zbuild.py

161 lines
5.3 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Zephyr build helper for app_i_core_link.
Usage:
python zbuild.py dr2501a_g070rb
python zbuild.py dr2501a_g070rb -p auto
python zbuild.py -p always (auto-detect board from west.yml)
Options:
board Board name (optional, auto-detected from west.yml if omitted)
-p PURSE Pristine option: auto / always / never
-t TARGET CMake target to run after build, e.g. test / flash
Steps:
1. west topdir → find Zephyr workspace root
2. west config --local manifest.file <this_script_dir>/west.yml
3. west build [-p PURSE] -b BOARD [-t TARGET] <this_script_dir>
"""
import argparse
import os
import re
import subprocess
import sys
def get_script_dir() -> str:
"""Absolute path to the directory containing this script."""
return os.path.dirname(os.path.abspath(__file__))
def run(cmd: list[str], cwd: str | None = None) -> str:
"""Run a command and return stdout. Exit on failure."""
proc = subprocess.run(cmd, capture_output=True, text=True, cwd=cwd)
if proc.returncode != 0:
print(f"{' '.join(cmd)}", file=sys.stderr)
print(f" {proc.stderr.strip()}", file=sys.stderr)
sys.exit(proc.returncode)
return proc.stdout.strip()
def discover_boards(manifest_path: str) -> list[str]:
"""Parse west.yml and return board names whose path starts with 'boards/'."""
if not os.path.exists(manifest_path):
return []
with open(manifest_path) as f:
content = f.read()
# Match entries like:
# - name: <board_name>
# path: boards/<something>
boards = re.findall(r"name:\s*(\S+)\s*\n\s+path:\s*boards/\S+", content)
return boards
def main():
parser = argparse.ArgumentParser(
description="Zephyr build helper for app_i_core_link"
)
parser.add_argument(
"board",
nargs="?",
default=None,
help="Board name (optional, auto-detected from west.yml if omitted)",
)
parser.add_argument(
"-p",
"--pristine",
default=None,
choices=["auto", "always", "never"],
help="Pristine build option",
)
parser.add_argument(
"-t",
"--target",
default=None,
help="CMake target to run after build (e.g. test, flash)",
)
parser.add_argument(
"--update",
action="store_true",
help="Run west update after setting manifest",
)
args = parser.parse_args()
# ── 0. Auto-detect board from west.yml when not specified ───
if args.board is None:
script_dir = get_script_dir()
manifest = os.path.join(script_dir, "west.yml")
boards = discover_boards(manifest)
if len(boards) == 0:
print(
" ✗ No board specified and no board found in west.yml "
"(no entry with path: boards/...)",
file=sys.stderr,
)
sys.exit(1)
elif len(boards) == 1:
args.board = boards[0]
print(f" → Auto-detected board: {args.board}")
else:
print(
" ✗ No board specified. Multiple boards found in west.yml:",
", ".join(boards),
"\n Please specify one explicitly.",
file=sys.stderr,
)
sys.exit(1)
script_dir = get_script_dir()
manifest = os.path.join(script_dir, "west.yml")
print(f" script dir : {script_dir}")
print(f" board : {args.board}")
print(f" pristine : {args.pristine or '(none)'}")
print(f" target : {args.target or '(none)'}")
print(f" update : {'yes' if args.update else 'no'}")
# ── 1. Find workspace root ───────────────────────────────
print("\n [1/3] Finding west workspace root...")
topdir = run(["west", "topdir"])
print(f"{topdir}")
# ── 2. Set local manifest ────────────────────────────────
print("\n [2/3] Setting local manifest...")
if not os.path.exists(manifest):
print(f" ✗ manifest not found: {manifest}", file=sys.stderr)
sys.exit(1)
run(["west", "config", "--local", "manifest.file", manifest], cwd=topdir)
print(f" → manifest.file = {manifest}")
# ── 2.5. Run west update (optional) ───────────────────────
if args.update:
print("\n [2.5/3] Running west update...")
run(["west", "update", "--fetch", "smart"], cwd=topdir)
print(" → update done")
# ── 3. Run west build ─────────────────────────────────────
print("\n [3/3] Running west build...")
build_cmd = ["west", "build"]
if args.pristine:
build_cmd += ["-p", args.pristine]
build_cmd += ["-b", args.board]
if args.target:
build_cmd += ["-t", args.target]
build_cmd += [script_dir]
print(f" $ {' '.join(build_cmd)}")
proc = subprocess.run(build_cmd, cwd=topdir)
if proc.returncode != 0:
print(f"\n ✗ Build failed (exit code {proc.returncode})")
sys.exit(proc.returncode)
print("\n ✓ Build succeeded")
if __name__ == "__main__":
main()