mirror of
https://github.com/torlando-tech/pyxis.git
synced 2026-08-14 14:50:01 +00:00
99 lines
4.0 KiB
Python
99 lines
4.0 KiB
Python
"""
|
|
PlatformIO pre-build: mirror file:// lib_deps from their source trees
|
|
into .pio/libdeps before each build.
|
|
|
|
PlatformIO copies a `file://...` lib_dep into `.pio/libdeps/<env>/<lib>`
|
|
once on first install and never re-syncs even when the source changes.
|
|
That silently masks fixes — `pio run` succeeds and the device flashes,
|
|
but the firmware contains the OLD version of the source. Bit us hard
|
|
on a microReticulum security fix that lived in source for a full test
|
|
session before anyone noticed it hadn't deployed.
|
|
|
|
For each registered file:// dep below, this script rsyncs the source
|
|
tree into the libdep cache, preserving timestamps so the linker sees
|
|
fresh source on every build.
|
|
"""
|
|
Import("env")
|
|
import os
|
|
import sys
|
|
import shutil
|
|
import filecmp
|
|
from pathlib import Path
|
|
sys.path.insert(0, env.get("PROJECT_DIR", "."))
|
|
from _build_helpers import env_libdeps_dir # per-env libdeps path; never hardcode the env
|
|
|
|
# (source_dir, libdep_subdir_name) — populated from env vars so the
|
|
# script doesn't bake any contributor's local checkout path into the
|
|
# committed source. Since microReticulum is now consumed as a pinned
|
|
# git URL in platformio.ini (not a file:// dep), this script no-ops
|
|
# for everyone by default. Set PYXIS_MICRORETICULUM_DIR to opt in to
|
|
# a local-override workflow (mirrors that source tree into
|
|
# .pio/libdeps/<env>/microReticulum on each build).
|
|
FILE_DEPS = []
|
|
_micro_reticulum_dir = os.environ.get("PYXIS_MICRORETICULUM_DIR", "").strip()
|
|
if _micro_reticulum_dir:
|
|
FILE_DEPS.append((_micro_reticulum_dir, "microReticulum"))
|
|
|
|
PROJECT_DIR = Path(env.get("PROJECT_DIR", "."))
|
|
LIBDEPS_BASE = Path(env_libdeps_dir(env))
|
|
|
|
|
|
def mirror(src: Path, dst: Path):
|
|
if not src.exists():
|
|
print(f"SYNC: {src} missing, skipping")
|
|
return False
|
|
if not dst.exists():
|
|
# Let PIO do the first install; we only refresh after that.
|
|
print(f"SYNC: {dst} not yet installed, skipping (PIO will fetch)")
|
|
return False
|
|
src_files = 0
|
|
copied = 0
|
|
removed = 0
|
|
mirrored_paths = set()
|
|
for root, dirs, files in os.walk(src):
|
|
# Skip git, build artifacts.
|
|
dirs[:] = [d for d in dirs if d not in (".git", ".pio", "__pycache__", "build")]
|
|
rel = Path(root).relative_to(src)
|
|
for fn in files:
|
|
if fn.endswith((".pyc", ".o", ".a", ".elf", ".bin")):
|
|
continue
|
|
sp = Path(root) / fn
|
|
dp = dst / rel / fn
|
|
mirrored_paths.add((rel / fn).as_posix())
|
|
src_files += 1
|
|
# A freshly fetched dependency can have a newer mtime than an older
|
|
# local checkout even when the local bytes contain the intended fix.
|
|
# Compare content so the explicit local override always wins.
|
|
if not dp.exists() or not filecmp.cmp(sp, dp, shallow=False):
|
|
dp.parent.mkdir(parents=True, exist_ok=True)
|
|
shutil.copy2(sp, dp)
|
|
# copy2 preserves the source mtime. Touch the mirrored file so
|
|
# incremental PlatformIO builds recompile changed dependency code.
|
|
dp.touch()
|
|
copied += 1
|
|
|
|
# A mirror must also remove source files deleted from the explicit local
|
|
# checkout. Otherwise PlatformIO can continue compiling stale translation
|
|
# units that no longer exist in the dependency being tested.
|
|
for root, dirs, files in os.walk(dst):
|
|
dirs[:] = [d for d in dirs if d not in (".git", ".pio", "__pycache__", "build")]
|
|
rel = Path(root).relative_to(dst)
|
|
for fn in files:
|
|
if fn == ".piopm" or fn.endswith((".pyc", ".o", ".a", ".elf", ".bin")):
|
|
continue
|
|
relative_path = (rel / fn).as_posix()
|
|
if relative_path not in mirrored_paths:
|
|
(Path(root) / fn).unlink()
|
|
removed += 1
|
|
|
|
if copied > 0 or removed > 0:
|
|
print(
|
|
f"SYNC: {dst.name}: refreshed {copied}/{src_files} files, "
|
|
f"removed {removed} stale files from {src}"
|
|
)
|
|
return True
|
|
|
|
|
|
for src, name in FILE_DEPS:
|
|
mirror(Path(src), LIBDEPS_BASE / name)
|