#!/usr/bin/env python3 from __future__ import annotations import json import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] if hasattr(sys.stdout, "reconfigure"): sys.stdout.reconfigure(encoding="utf-8", errors="replace") if hasattr(sys.stderr, "reconfigure"): sys.stderr.reconfigure(encoding="utf-8", errors="replace") BASELINE_PATH = ROOT / "docs" / "engineering" / "size-baseline.json" ENVS = ["production", "debug", "test"] def file_size(path: Path) -> int: return path.stat().st_size if path.exists() else -1 def main() -> int: if not BASELINE_PATH.exists(): print(f"Missing size baseline: {BASELINE_PATH.relative_to(ROOT)}") return 1 baseline = json.loads(BASELINE_PATH.read_text(encoding="utf-8")) baseline_envs = baseline.get("environments", {}) errors: list[str] = [] print("Firmware size report:") for env in ENVS: build_dir = ROOT / ".pio" / "build" / env bin_path = build_dir / "firmware.bin" elf_path = build_dir / "firmware.elf" bin_size = file_size(bin_path) elf_size = file_size(elf_path) if bin_size < 0 or elf_size < 0: errors.append(f"{env}: missing firmware artifacts; run python -m platformio run -e {env}") continue entry = baseline_envs.get(env) if not entry: errors.append(f"{env}: missing baseline entry") continue baseline_bin = int(entry["firmware_bin_bytes"]) max_bin = int(entry.get("max_firmware_bin_bytes", baseline_bin)) delta = bin_size - baseline_bin print( f"- {env}: firmware.bin={bin_size} bytes " f"(baseline {baseline_bin}, delta {delta:+}), firmware.elf={elf_size} bytes" ) if bin_size > max_bin: errors.append(f"{env}: firmware.bin {bin_size} exceeds limit {max_bin}") if errors: for error in errors: print(f"ERROR: {error}") return 1 return 0 if __name__ == "__main__": raise SystemExit(main())