Skip to content

Commit 3d8896e

Browse files
Xeratecclaude
andcommitted
Auto-bootstrap GAP9 venv + board config in runners
Add `testUtils/gap9Bootstrap.py` exporting `bootstrap_gap9_env()`, which replaces the manual `source .gap9-venv/bin/activate`, `source configs/gap9_evk_audio.sh`, and `export GVSOC_INSTALL_DIR` dance documented in `README_GAP9.md`. The helper: - runs `bash -c 'source gap9_evk_audio.sh && env -0'` to capture the board config's exports and merges them into a fresh env; - sets `VIRTUAL_ENV` and prepends the venv's `bin/` to `PATH` so subprocesses (gapy, etc.) also pick up the venv; - `os.execve`s under the venv's python (skipped if `sys.executable` is already the venv interpreter); - is idempotent via a `DEEPLOY_GAP9_BOOTSTRAPPED` recursion guard; - is a no-op outside the GAP9 container, when the SDK paths don't exist. `GAP_SDK_HOME` overrides the default `/app/install/gap9-sdk`. Wire `bootstrap_gap9_env()` into both `deeployRunner_gap9.py` and `deeployRunner_tiled_gap9.py` before the rest of the imports run. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3b011bb commit 3d8896e

3 files changed

Lines changed: 74 additions & 2 deletions

File tree

DeeployTest/deeployRunner_gap9.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55

66
import sys
77

8-
from testUtils.deeployRunner import main
8+
from testUtils.gap9Bootstrap import bootstrap_gap9_env
9+
10+
bootstrap_gap9_env()
11+
12+
from testUtils.deeployRunner import main # noqa: E402
913

1014
if __name__ == "__main__":
1115

DeeployTest/deeployRunner_tiled_gap9.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55

66
import sys
77

8-
from testUtils.deeployRunner import main
8+
from testUtils.gap9Bootstrap import bootstrap_gap9_env
9+
10+
bootstrap_gap9_env()
11+
12+
from testUtils.deeployRunner import main # noqa: E402
913

1014
if __name__ == "__main__":
1115

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# SPDX-FileCopyrightText: 2025 ETH Zurich and University of Bologna
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
import os
6+
import shlex
7+
import subprocess
8+
import sys
9+
from pathlib import Path
10+
11+
__all__ = ["bootstrap_gap9_env"]
12+
13+
_BOOTSTRAP_FLAG = "DEEPLOY_GAP9_BOOTSTRAPPED"
14+
_DEFAULT_SDK_HOME = "/app/install/gap9-sdk"
15+
16+
17+
def bootstrap_gap9_env() -> None:
18+
"""Re-exec under the GAP9 venv with `gap9_evk_audio.sh` already sourced.
19+
20+
Replaces the manual ``source .gap9-venv/bin/activate`` /
21+
``source gap9_evk_audio.sh`` / ``export GVSOC_INSTALL_DIR=...`` dance
22+
documented in ``README_GAP9.md``. Idempotent (guarded by the
23+
``DEEPLOY_GAP9_BOOTSTRAPPED`` env flag) and a no-op outside the GAP9
24+
container, where the SDK paths don't exist. Override the SDK location
25+
with ``GAP_SDK_HOME``.
26+
27+
Call this BEFORE importing anything that depends on the GAP9 venv's
28+
site-packages — once we re-exec, the new interpreter starts from
29+
scratch.
30+
"""
31+
if os.environ.get(_BOOTSTRAP_FLAG) == "1":
32+
return
33+
34+
sdk = Path(os.environ.get("GAP_SDK_HOME", _DEFAULT_SDK_HOME))
35+
venv_dir = sdk / ".gap9-venv"
36+
venv_py = venv_dir / "bin" / "python"
37+
board_cfg = sdk / "configs" / "gap9_evk_audio.sh"
38+
gvsoc_install = sdk / "install" / "workstation"
39+
40+
if not venv_py.exists() or not board_cfg.exists():
41+
return
42+
43+
# Capture the env after sourcing the board config; suppress any chatter
44+
# so it can't be mistaken for env entries.
45+
out = subprocess.check_output(["bash", "-c", f"source {shlex.quote(str(board_cfg))} >/dev/null 2>&1 && env -0"])
46+
new_env = dict(os.environ)
47+
for entry in out.split(b"\x00"):
48+
if not entry:
49+
continue
50+
key, _, value = entry.decode().partition("=")
51+
new_env[key] = value
52+
53+
# Mimic what `activate` does so anything we shell out to (gapy, etc.)
54+
# also picks up the venv.
55+
new_env["VIRTUAL_ENV"] = str(venv_dir)
56+
new_env["PATH"] = f"{venv_dir / 'bin'}{os.pathsep}{new_env.get('PATH', '')}"
57+
new_env["GVSOC_INSTALL_DIR"] = str(gvsoc_install)
58+
new_env[_BOOTSTRAP_FLAG] = "1"
59+
60+
if Path(sys.executable).resolve() == venv_py.resolve():
61+
os.environ.update(new_env)
62+
return
63+
64+
os.execve(str(venv_py), [str(venv_py), *sys.argv], new_env)

0 commit comments

Comments
 (0)