bspctl 0.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
bspctl-0.0.2/PKG-INFO ADDED
@@ -0,0 +1,337 @@
1
+ Metadata-Version: 2.4
2
+ Name: bspctl
3
+ Version: 0.0.2
4
+ Summary: One-command kas-based BSP build orchestrator with observability
5
+ Keywords: yocto,bsp,variscite,kas,bitbake,embedded
6
+ Author: Javier Tia
7
+ License-Expression: Apache-2.0
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Software Development :: Build Tools
11
+ Classifier: Topic :: System :: Operating System Kernels :: Linux
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Requires-Dist: typer>=0.12.0
17
+ Requires-Dist: rich>=13.0.0
18
+ Requires-Dist: pyyaml>=6.0
19
+ Requires-Python: >=3.11, <3.14
20
+ Project-URL: Homepage, https://github.com/jetm/bspctl
21
+ Project-URL: Repository, https://github.com/jetm/bspctl
22
+ Project-URL: Bug Tracker, https://github.com/jetm/bspctl/issues
23
+ Description-Content-Type: text/markdown
24
+
25
+ # bspctl
26
+
27
+ NXP i.MX and TI Sitara BSP build orchestrator powered by kas,
28
+ with a generic fallback for any kas YAML. Layers a static tuning overlay
29
+ (ccache wiring, MIRRORS, PREMIRRORS, FETCHCMD_wget, plus
30
+ fork-PREMIRRORs and the renderdoc CMake-launcher fix on NXP) on top of
31
+ either a user-supplied kas YAML (BYO) or a YAML it generates from the
32
+ repo-tool manifest (NXP) / oe-layertool config (TI). Runs a
33
+ pre-flight diagnosis before every build, captures structured per-run
34
+ telemetry under `<bsp_root>/build/runs/<ts>/`, and ships a `bspctl triage`
35
+ post-mortem that keys suggestions off the failure pattern.
36
+
37
+ ## BSP scope
38
+
39
+ `bspctl` supports two BSP families plus a generic mode:
40
+
41
+ - **NXP i.MX** (i.MX6/7, i.MX8, i.MX8M, i.MX9x, i.MX95) - manifest is
42
+ `imx-A.B.C-X.Y.Z.xml` from `varigit/variscite-bsp-platform`. Layers
43
+ `bspctl-tuning-nxp.yml` (ccache + MIRRORS + ACCEPT_FSL_EULA + renderdoc
44
+ fix + linux-imx fork PREMIRROR + meta-varis-overrides).
45
+ - **TI Sitara** (AM62x, AM62Px, ...) - config is
46
+ `processor-sdk-<poky>-<flavour>-<sdk>-config_var<N>.txt` from
47
+ `varigit/oe-layersetup`. Layers `bspctl-tuning-ti.yml` (ccache + MIRRORS
48
+ + ti-linux-kernel + ti-u-boot fork PREMIRRORs + meta-varis-overrides-ti).
49
+ - **Generic** (any non-NXP/TI kas YAML, e.g. `qemuarm64` + `poky` +
50
+ `meta-arm`) - no manifest, BYO only. Layers `bspctl-tuning-generic.yml`
51
+ (the BSP-agnostic subset: ccache, MIRRORS, PREMIRRORS, FETCHCMD_wget,
52
+ PYTHONMALLOC). NXP/TI-specific knobs are deliberately excluded.
53
+
54
+ The dispatched code path branches on the manifest filename (or the BYO YAML's
55
+ machine prefix / repos block) at the top of `bspctl build`.
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ uv tool install bspctl
61
+ ```
62
+
63
+ Or with pip:
64
+
65
+ ```bash
66
+ pip install bspctl
67
+ ```
68
+
69
+ ### From source (for contributors)
70
+
71
+ ```bash
72
+ git clone https://github.com/jetm/bspctl
73
+ cd bspctl
74
+ uv tool install --editable .
75
+ ```
76
+
77
+ ## Quickstart
78
+
79
+ Install `bspctl` as a uv tool from this directory:
80
+
81
+ ```bash
82
+ cd ~/repos/personal/bspctl
83
+ uv tool install .
84
+ ```
85
+
86
+ `bspctl` lands on PATH. Re-run with `--reinstall` after local edits.
87
+
88
+ ### Python version pinning
89
+
90
+ `bspctl` declares `requires-python = ">=3.11,<3.14"`. uv resolves to the
91
+ newest interpreter in that range, which on most hosts means 3.13. Some
92
+ workflows need to match bitbake's effective production floor (3.11/3.12
93
+ on poky walnascar; kas-container ships CPython 3.12.10) - in
94
+ particular, the `bspctl stress-parse --host` mode runs bitbake on the
95
+ host's interpreter, and bitbake's in-tree `test_parser_fork_race`
96
+ auto-skips on 3.14.
97
+
98
+ Pin the interpreter at install time via `--python <version>`:
99
+
100
+ ```bash
101
+ uv python install 3.12
102
+ cd ~/repos/personal/bspctl
103
+ uv tool install --python 3.12 --reinstall --editable .
104
+ ```
105
+
106
+ Verify the shebang of the installed entry point points at 3.12:
107
+
108
+ ```bash
109
+ head -1 "$(which bspctl)"
110
+ # /home/user/.local/share/uv/tools/bspctl/bin/python3
111
+ "$(head -1 "$(which bspctl)" | sed 's|^#!||')" --version
112
+ # Python 3.12.x
113
+ ```
114
+
115
+ Now jump into the workspace and run a default build:
116
+
117
+ ```bash
118
+ cd ~/bsp-workspace
119
+ bspctl build
120
+ ```
121
+
122
+ Defaults are `imx8mp-var-dart` / `fsl-imx-xwayland` / `core-image-minimal` off
123
+ the `imx-6.6.52-2.2.2.xml` manifest. On a clean workspace the first run
124
+ populates `nxp/sources/` via `repo sync` and takes hours; subsequent runs
125
+ skip the sync step and go straight to bitbake.
126
+
127
+ ## The three forms of `bspctl build`
128
+
129
+ `bspctl build` accepts three input shapes that all converge on the same
130
+ `kas-container build <yml>:<overlay>` invocation. The optimization stack
131
+ applied is the BSP-appropriate slice; the topology comes from your YAML
132
+ or from the manifest.
133
+
134
+ ```bash
135
+ # Form A: BYO YAML (positional). Skips sync/setup-env/gen-kas.
136
+ cp bspctl/examples/kas-imx95-var-dart.yml nxp/my-build.yml
137
+ # (edit nxp/my-build.yml as you wish)
138
+ bspctl bitbake-override --apply
139
+ bspctl build nxp/my-build.yml
140
+
141
+ # Form A also handles generic kas YAMLs - the YAML's bsp_root is
142
+ # its own parent directory. Generic mode skips bitbake-override.
143
+ bspctl build pilots/0005-hardening/kas.yml
144
+
145
+ # Form B: manifest-driven, one shot. NXP/TI only.
146
+ bspctl bitbake-override --apply
147
+ bspctl build -f imx-6.12.49-2.2.0.xml -m imx95-var-dart
148
+ # TI equivalent
149
+ bspctl build -f processor-sdk-scarthgap-chromium-11.00.09.04-config_var01.txt -m am62x-var-som
150
+
151
+ # Form C: manifest-driven, staged. Useful when you want to inspect the
152
+ # generated YAML before kicking off the build.
153
+ bspctl sync --manifest imx-6.12.49-2.2.0.xml
154
+ bspctl gen-kas --manifest imx-6.12.49-2.2.0.xml -o nxp/my-build.yml
155
+ bspctl build nxp/my-build.yml
156
+ ```
157
+
158
+ The user's YAML must live under its `bsp_root` so kas-container can read
159
+ it through the `KAS_WORK_DIR` bind mount. For NXP/TI builds that means
160
+ under `nxp/` or `ti/`; for generic builds the YAML's own parent
161
+ directory is the bsp_root, so any path works. `bspctl build` errors out
162
+ with a clear message if the path is unreachable.
163
+
164
+ ## Overlay model
165
+
166
+ Every `bspctl build` invocation - BYO or manifest-driven - applies the
167
+ BSP tuning by layering a static overlay onto the kas YAML at build
168
+ time. Your YAML file is not modified on disk; kas merges the overlay in
169
+ when it parses the build.
170
+
171
+ `bspctl build` copies the overlay shipped under `overlays/` in this
172
+ repo into `<bsp_root>/.bspctl/overlays/bspctl-tuning-<bsp>.yml` (a real
173
+ file, refreshed on every invocation so it tracks the source) and then
174
+ runs:
175
+
176
+ ```text
177
+ kas-container build <user-yml-rel>:<overlay-rel>
178
+ ```
179
+
180
+ The copy lands inside whatever git repo (or no repo) hosts your YAML,
181
+ so kas's "all concatenated config files must share a repo" check is
182
+ satisfied, and kas-container reads it directly through the
183
+ `KAS_WORK_DIR` bind mount with no symlink to dereference.
184
+
185
+ kas merges `local_conf_header.<key>` and `repos.<name>` by name, so your
186
+ `machine:`, `distro:`, `target:`, and own `repos:` stay intact while the
187
+ overlay unions in:
188
+
189
+ - ccache wiring (`CCACHE_DIR`, `INHERIT += "ccache"`)
190
+ - thread/parallelism knobs (`BB_NUMBER_THREADS`, `PARALLEL_MAKE`)
191
+ - `IMAGE_FEATURES:remove` for dev/dbg packages
192
+ - `BB_FETCH_TIMEOUT = "600"` (raise the per-URI timeout)
193
+ - `MIRRORS` (replace scarthgap's dead mirror with the Yocto Project mirror)
194
+ - `PREMIRRORS:prepend` for github.com (silent fallbacks instead of build blockers)
195
+ - `FETCHCMD_wget` (crates.io 403 workaround)
196
+ - NXP-only: `ACCEPT_FSL_EULA`, the renderdoc CMake-launcher fix
197
+ - Per-BSP fork PREMIRRORs (`forks/linux-imx` on NXP; `forks/ti-linux-kernel`
198
+ + `forks/ti-u-boot` on TI)
199
+ - The `meta-varis-overrides` (NXP) / `meta-varis-overrides-ti` (TI) carry
200
+ layer
201
+
202
+ Edit `overlays/bspctl-tuning-<bsp>.yml` directly when you need to tweak the
203
+ optimization stack. The change applies to BYO and manifest flows alike, with
204
+ zero risk of drift between the two outputs.
205
+
206
+ ## BSP detection rules
207
+
208
+ `bspctl build` classifies the input as NXP, TI, or generic before doing
209
+ any work:
210
+
211
+ - **Form A (BYO YAML)**: inspect the YAML's `machine:` value first
212
+ (`imx*` -> NXP; `am*`, `k3-*`, `j7-*` -> TI), then the `repos:` block
213
+ (`meta-imx`, `meta-freescale*`, `meta-nxp*` -> NXP; `meta-ti-bsp`,
214
+ `meta-ti`, `meta-arago` -> TI). A parseable YAML with a machine or
215
+ repos block but no NXP/TI markers falls through to **generic**,
216
+ which selects `bspctl-tuning-generic.yml` and skips the
217
+ bitbake-override step.
218
+ - **Form B (manifest)**: regex on the filename (`imx-*.xml` -> NXP;
219
+ `processor-sdk-*-config_var*.txt` or `arago-*.txt` -> TI). Generic
220
+ mode does not apply here - it is BYO-only.
221
+
222
+ A YAML that lacks both `machine:` and `repos:` (empty / unparseable /
223
+ shape-incomplete) exits non-zero with a hint instead of guessing.
224
+
225
+ ## Common invocations
226
+
227
+ ```bash
228
+ bspctl build nxp/my-build.yml # BYO form (positional YAML)
229
+ bspctl build pilots/0005/kas.yml # BYO generic mode
230
+ bspctl build --image fsl-image-gui # heavier image (Wayland, Qt6, Chromium)
231
+ bspctl build --machine imx93-var-dart # different SoM (still NXP)
232
+ bspctl build --dry-run # apply overlay, skip kas-container
233
+ bspctl build --skip-sync # don't touch sources/, even if stale
234
+ bspctl build --skip-doctor # bypass pre-flight (not recommended)
235
+ bspctl sync --manifest imx-6.12.49-2.2.0.xml # repo init+sync, no build
236
+ bspctl doctor # standalone diagnosis, no build
237
+ bspctl triage # post-mortem the most recent run (workspace BSPs)
238
+ bspctl triage 20260423-091014 # post-mortem a named run
239
+ bspctl triage -k pilots/0005/kas.yml # post-mortem latest BYO run for that YAML
240
+ bspctl log # tail the latest run's kas.log live
241
+ bspctl log pilots/0005/kas.yml # tail the latest BYO run for that YAML
242
+ bspctl shell # drop into a kas-container shell
243
+ bspctl gen-kas -o nxp/my-build.yml # write topology-only YAML, do nothing else
244
+ bspctl clean # remove <bsp>/build/
245
+ ```
246
+
247
+ `bspctl build` is idempotent. Re-running it after a mid-pipeline failure
248
+ picks up where it left off - repo sync is skipped if `sources/` is
249
+ populated, `setup_env` is skipped if `build/conf/bblayers.conf` exists,
250
+ and the topology YAML is regenerated in case flags changed.
251
+
252
+ ## Environment variables
253
+
254
+ Every `--flag` has a `BSPCTL_*` env equivalent so CI jobs and shell profiles can
255
+ pin defaults without passing args every invocation. Explicit CLI flags
256
+ override env vars; env vars override built-in defaults.
257
+
258
+ | Env var | Field (BuildConfig) | Default |
259
+ |---------|---------------------|---------|
260
+ | `BSPCTL_MACHINE` | `machine` | `imx8mp-var-dart` |
261
+ | `BSPCTL_DISTRO` | `distro` | `fsl-imx-xwayland` |
262
+ | `BSPCTL_IMAGE` | `image` | `core-image-minimal` |
263
+ | `BSPCTL_MANIFEST` | `manifest` | `imx-6.6.52-2.2.2.xml` |
264
+ | `BSPCTL_REPO_URL` | `repo_url` | `https://github.com/varigit/variscite-bsp-platform.git` |
265
+ | `BSPCTL_REPO_BRANCH` | `repo_branch` | `scarthgap` |
266
+ | `KAS_CONTAINER_IMAGE` | `container_image` | `jetm/kas-build-env:latest` |
267
+
268
+ `--workspace` has no env var - it is resolved from the current working
269
+ directory by walking up to find a `.bspctl.toml` marker file or `nxp/`/`ti/`
270
+ subdirectories. The walk is skipped entirely for generic BYO builds
271
+ (`bspctl build my.yml` where the YAML does not target an NXP/TI SoM);
272
+ `bsp_root` falls back to the YAML's own parent directory so generic builds
273
+ run from any location.
274
+
275
+ Cache locations (`SSTATE_DIR`, `DL_DIR`) are read from the environment and
276
+ should be pinned in your shell profile.
277
+
278
+ ## Pre-flight checks reference
279
+
280
+ `bspctl doctor` and the automatic pre-flight gate at the top of `bspctl build`
281
+ run the same checks. BLOCK-severity failures halt the build; WARN prints
282
+ and continues; INFO is purely informational. Per-BSP extras
283
+ (`check_forks_linux_imx` on NXP; `check_ti_layertool_*` on TI) load via
284
+ `BspModel.doctor_extras`; the shared set runs unconditionally. Generic
285
+ BYO mode runs only the shared set - the family-specific gates would
286
+ always fail outside an NXP/TI workspace and are skipped.
287
+
288
+ ## Observability
289
+
290
+ Each `bspctl build` invocation creates `<bsp>/build/runs/<YYYYMMDD-HHMMSS>/`
291
+ containing:
292
+
293
+ | File | Contents |
294
+ |------|----------|
295
+ | `events.jsonl` | One JSON object per step start/end/error (machine-readable) |
296
+ | `console.log` | The same stream in human-readable lines |
297
+ | `env.txt` | Snapshot of `BSPCTL_*`, `KAS_*`, `BB_*`, `DL_*`, `SSTATE_*`, `NPROC`, `MACHINE`, `DISTRO` at run start |
298
+ | `kas.log` | `kas-container build` stdout + stderr |
299
+ | `time.log` | `/usr/bin/time -v` output (when `time` is available) |
300
+ | `du.tsv` | `<unix-ts>\t<bytes>` samples of `build/tmp/` every 30 s |
301
+ | `diagnosis.txt` | The pre-flight diagnosis as plain text |
302
+
303
+ Events use the key `event` (not `event_type`), with values like `run_start`,
304
+ `step_start`, `step_ok`, `step_skip`, `step_fail`, `run_end`, `run_error`.
305
+
306
+ ## Triage workflow
307
+
308
+ By default, `bspctl triage` searches both `nxp/build/runs/` and
309
+ `ti/build/runs/` under the workspace. Pass `-k <my.yml>` (or
310
+ `--kas-yaml`) for a BYO build whose runs live next to the YAML at
311
+ `<yaml-parent>/build/runs/`. In either mode, it finds the named run
312
+ (or the most recent), reads `events.jsonl` to locate the first
313
+ `step_fail` event, tails `kas.log`, extracts the container path of
314
+ bitbake's "Logfile of failure stored in: ..." line and rewrites it to
315
+ the host path, tails that recipe log, and matches the combined output
316
+ against a keyed suggestion table (fetch failure, parser deadlock, OOM,
317
+ disk full, GitHub fetch flake, missing EULA, stale bitbake cache,
318
+ kas/container version skew).
319
+
320
+ `bspctl log` follows the same convention: pass a positional kas YAML to
321
+ tail the latest run for a BYO build, or run from inside an NXP/TI
322
+ workspace to tail the latest run for the dispatched BSP.
323
+
324
+ ## Troubleshooting
325
+
326
+ | Symptom | Resolution |
327
+ |---------|-----------|
328
+ | `Not inside a workspace (no .bspctl.toml found, and no nxp/ or ti/ subdirectory)` | cd into a workspace that contains `nxp/` or `ti/`, or add a `.bspctl.toml` marker file, or pass a positional kas YAML: `bspctl build|log|triage -k pilots/0005/kas.yml` works from anywhere (generic mode treats the YAML's parent as `bsp_root`). |
329
+ | `kas YAML <path> is outside bsp_root <bsp_root>` | NXP/TI builds need the YAML under `nxp/` or `ti/`. Copy `bspctl/examples/kas-*.yml` under `<bsp_root>/` and re-run. Generic BYO is exempt - the YAML's own directory is `bsp_root`. |
330
+ | `Could not parse <path> as a kas build` | YAML lacks both `machine:` and a `repos:` block. Add at least one before re-running. |
331
+ | `All concatenated config files must belong to the same repository ...` (kas) | Pre-fix error from the symlinked-overlay era. Reinstall bspctl at a build that ships the copy-based overlay materializer. |
332
+ | `parser thread killed/died` mid-parse | Container Python is 3.13+, which deadlocks the bitbake parser fork. Rebuild `jetm/kas-build-env` on `ubuntu:24.04` (Python 3.12). `bspctl doctor` flags this. |
333
+ | `wget: sources.openembedded.org: NXDOMAIN` noise | Dead mirror hardcoded by scarthgap's `mirrors.bbclass`. The overlay's `MIRRORS =` line suppresses it. |
334
+ | `No space left on device` | `bspctl doctor` blocks below 50 GiB free on workspace, sstate, and downloads. |
335
+ | `do_fetch: Fetcher failure` for `linux-imx` | Populate `nxp/forks/linux-imx/` so the local PREMIRROR handles the fetch without going external. |
336
+ | `Config file validation Error` from kas | Version skew between host `kas` and the kas-container image. Align both to the same kas release. |
337
+ | General fetch flake | Retry. Transient GitHub timeouts are common; `repo sync` and `do_fetch` are idempotent. |
bspctl-0.0.2/README.md ADDED
@@ -0,0 +1,313 @@
1
+ # bspctl
2
+
3
+ NXP i.MX and TI Sitara BSP build orchestrator powered by kas,
4
+ with a generic fallback for any kas YAML. Layers a static tuning overlay
5
+ (ccache wiring, MIRRORS, PREMIRRORS, FETCHCMD_wget, plus
6
+ fork-PREMIRRORs and the renderdoc CMake-launcher fix on NXP) on top of
7
+ either a user-supplied kas YAML (BYO) or a YAML it generates from the
8
+ repo-tool manifest (NXP) / oe-layertool config (TI). Runs a
9
+ pre-flight diagnosis before every build, captures structured per-run
10
+ telemetry under `<bsp_root>/build/runs/<ts>/`, and ships a `bspctl triage`
11
+ post-mortem that keys suggestions off the failure pattern.
12
+
13
+ ## BSP scope
14
+
15
+ `bspctl` supports two BSP families plus a generic mode:
16
+
17
+ - **NXP i.MX** (i.MX6/7, i.MX8, i.MX8M, i.MX9x, i.MX95) - manifest is
18
+ `imx-A.B.C-X.Y.Z.xml` from `varigit/variscite-bsp-platform`. Layers
19
+ `bspctl-tuning-nxp.yml` (ccache + MIRRORS + ACCEPT_FSL_EULA + renderdoc
20
+ fix + linux-imx fork PREMIRROR + meta-varis-overrides).
21
+ - **TI Sitara** (AM62x, AM62Px, ...) - config is
22
+ `processor-sdk-<poky>-<flavour>-<sdk>-config_var<N>.txt` from
23
+ `varigit/oe-layersetup`. Layers `bspctl-tuning-ti.yml` (ccache + MIRRORS
24
+ + ti-linux-kernel + ti-u-boot fork PREMIRRORs + meta-varis-overrides-ti).
25
+ - **Generic** (any non-NXP/TI kas YAML, e.g. `qemuarm64` + `poky` +
26
+ `meta-arm`) - no manifest, BYO only. Layers `bspctl-tuning-generic.yml`
27
+ (the BSP-agnostic subset: ccache, MIRRORS, PREMIRRORS, FETCHCMD_wget,
28
+ PYTHONMALLOC). NXP/TI-specific knobs are deliberately excluded.
29
+
30
+ The dispatched code path branches on the manifest filename (or the BYO YAML's
31
+ machine prefix / repos block) at the top of `bspctl build`.
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ uv tool install bspctl
37
+ ```
38
+
39
+ Or with pip:
40
+
41
+ ```bash
42
+ pip install bspctl
43
+ ```
44
+
45
+ ### From source (for contributors)
46
+
47
+ ```bash
48
+ git clone https://github.com/jetm/bspctl
49
+ cd bspctl
50
+ uv tool install --editable .
51
+ ```
52
+
53
+ ## Quickstart
54
+
55
+ Install `bspctl` as a uv tool from this directory:
56
+
57
+ ```bash
58
+ cd ~/repos/personal/bspctl
59
+ uv tool install .
60
+ ```
61
+
62
+ `bspctl` lands on PATH. Re-run with `--reinstall` after local edits.
63
+
64
+ ### Python version pinning
65
+
66
+ `bspctl` declares `requires-python = ">=3.11,<3.14"`. uv resolves to the
67
+ newest interpreter in that range, which on most hosts means 3.13. Some
68
+ workflows need to match bitbake's effective production floor (3.11/3.12
69
+ on poky walnascar; kas-container ships CPython 3.12.10) - in
70
+ particular, the `bspctl stress-parse --host` mode runs bitbake on the
71
+ host's interpreter, and bitbake's in-tree `test_parser_fork_race`
72
+ auto-skips on 3.14.
73
+
74
+ Pin the interpreter at install time via `--python <version>`:
75
+
76
+ ```bash
77
+ uv python install 3.12
78
+ cd ~/repos/personal/bspctl
79
+ uv tool install --python 3.12 --reinstall --editable .
80
+ ```
81
+
82
+ Verify the shebang of the installed entry point points at 3.12:
83
+
84
+ ```bash
85
+ head -1 "$(which bspctl)"
86
+ # /home/user/.local/share/uv/tools/bspctl/bin/python3
87
+ "$(head -1 "$(which bspctl)" | sed 's|^#!||')" --version
88
+ # Python 3.12.x
89
+ ```
90
+
91
+ Now jump into the workspace and run a default build:
92
+
93
+ ```bash
94
+ cd ~/bsp-workspace
95
+ bspctl build
96
+ ```
97
+
98
+ Defaults are `imx8mp-var-dart` / `fsl-imx-xwayland` / `core-image-minimal` off
99
+ the `imx-6.6.52-2.2.2.xml` manifest. On a clean workspace the first run
100
+ populates `nxp/sources/` via `repo sync` and takes hours; subsequent runs
101
+ skip the sync step and go straight to bitbake.
102
+
103
+ ## The three forms of `bspctl build`
104
+
105
+ `bspctl build` accepts three input shapes that all converge on the same
106
+ `kas-container build <yml>:<overlay>` invocation. The optimization stack
107
+ applied is the BSP-appropriate slice; the topology comes from your YAML
108
+ or from the manifest.
109
+
110
+ ```bash
111
+ # Form A: BYO YAML (positional). Skips sync/setup-env/gen-kas.
112
+ cp bspctl/examples/kas-imx95-var-dart.yml nxp/my-build.yml
113
+ # (edit nxp/my-build.yml as you wish)
114
+ bspctl bitbake-override --apply
115
+ bspctl build nxp/my-build.yml
116
+
117
+ # Form A also handles generic kas YAMLs - the YAML's bsp_root is
118
+ # its own parent directory. Generic mode skips bitbake-override.
119
+ bspctl build pilots/0005-hardening/kas.yml
120
+
121
+ # Form B: manifest-driven, one shot. NXP/TI only.
122
+ bspctl bitbake-override --apply
123
+ bspctl build -f imx-6.12.49-2.2.0.xml -m imx95-var-dart
124
+ # TI equivalent
125
+ bspctl build -f processor-sdk-scarthgap-chromium-11.00.09.04-config_var01.txt -m am62x-var-som
126
+
127
+ # Form C: manifest-driven, staged. Useful when you want to inspect the
128
+ # generated YAML before kicking off the build.
129
+ bspctl sync --manifest imx-6.12.49-2.2.0.xml
130
+ bspctl gen-kas --manifest imx-6.12.49-2.2.0.xml -o nxp/my-build.yml
131
+ bspctl build nxp/my-build.yml
132
+ ```
133
+
134
+ The user's YAML must live under its `bsp_root` so kas-container can read
135
+ it through the `KAS_WORK_DIR` bind mount. For NXP/TI builds that means
136
+ under `nxp/` or `ti/`; for generic builds the YAML's own parent
137
+ directory is the bsp_root, so any path works. `bspctl build` errors out
138
+ with a clear message if the path is unreachable.
139
+
140
+ ## Overlay model
141
+
142
+ Every `bspctl build` invocation - BYO or manifest-driven - applies the
143
+ BSP tuning by layering a static overlay onto the kas YAML at build
144
+ time. Your YAML file is not modified on disk; kas merges the overlay in
145
+ when it parses the build.
146
+
147
+ `bspctl build` copies the overlay shipped under `overlays/` in this
148
+ repo into `<bsp_root>/.bspctl/overlays/bspctl-tuning-<bsp>.yml` (a real
149
+ file, refreshed on every invocation so it tracks the source) and then
150
+ runs:
151
+
152
+ ```text
153
+ kas-container build <user-yml-rel>:<overlay-rel>
154
+ ```
155
+
156
+ The copy lands inside whatever git repo (or no repo) hosts your YAML,
157
+ so kas's "all concatenated config files must share a repo" check is
158
+ satisfied, and kas-container reads it directly through the
159
+ `KAS_WORK_DIR` bind mount with no symlink to dereference.
160
+
161
+ kas merges `local_conf_header.<key>` and `repos.<name>` by name, so your
162
+ `machine:`, `distro:`, `target:`, and own `repos:` stay intact while the
163
+ overlay unions in:
164
+
165
+ - ccache wiring (`CCACHE_DIR`, `INHERIT += "ccache"`)
166
+ - thread/parallelism knobs (`BB_NUMBER_THREADS`, `PARALLEL_MAKE`)
167
+ - `IMAGE_FEATURES:remove` for dev/dbg packages
168
+ - `BB_FETCH_TIMEOUT = "600"` (raise the per-URI timeout)
169
+ - `MIRRORS` (replace scarthgap's dead mirror with the Yocto Project mirror)
170
+ - `PREMIRRORS:prepend` for github.com (silent fallbacks instead of build blockers)
171
+ - `FETCHCMD_wget` (crates.io 403 workaround)
172
+ - NXP-only: `ACCEPT_FSL_EULA`, the renderdoc CMake-launcher fix
173
+ - Per-BSP fork PREMIRRORs (`forks/linux-imx` on NXP; `forks/ti-linux-kernel`
174
+ + `forks/ti-u-boot` on TI)
175
+ - The `meta-varis-overrides` (NXP) / `meta-varis-overrides-ti` (TI) carry
176
+ layer
177
+
178
+ Edit `overlays/bspctl-tuning-<bsp>.yml` directly when you need to tweak the
179
+ optimization stack. The change applies to BYO and manifest flows alike, with
180
+ zero risk of drift between the two outputs.
181
+
182
+ ## BSP detection rules
183
+
184
+ `bspctl build` classifies the input as NXP, TI, or generic before doing
185
+ any work:
186
+
187
+ - **Form A (BYO YAML)**: inspect the YAML's `machine:` value first
188
+ (`imx*` -> NXP; `am*`, `k3-*`, `j7-*` -> TI), then the `repos:` block
189
+ (`meta-imx`, `meta-freescale*`, `meta-nxp*` -> NXP; `meta-ti-bsp`,
190
+ `meta-ti`, `meta-arago` -> TI). A parseable YAML with a machine or
191
+ repos block but no NXP/TI markers falls through to **generic**,
192
+ which selects `bspctl-tuning-generic.yml` and skips the
193
+ bitbake-override step.
194
+ - **Form B (manifest)**: regex on the filename (`imx-*.xml` -> NXP;
195
+ `processor-sdk-*-config_var*.txt` or `arago-*.txt` -> TI). Generic
196
+ mode does not apply here - it is BYO-only.
197
+
198
+ A YAML that lacks both `machine:` and `repos:` (empty / unparseable /
199
+ shape-incomplete) exits non-zero with a hint instead of guessing.
200
+
201
+ ## Common invocations
202
+
203
+ ```bash
204
+ bspctl build nxp/my-build.yml # BYO form (positional YAML)
205
+ bspctl build pilots/0005/kas.yml # BYO generic mode
206
+ bspctl build --image fsl-image-gui # heavier image (Wayland, Qt6, Chromium)
207
+ bspctl build --machine imx93-var-dart # different SoM (still NXP)
208
+ bspctl build --dry-run # apply overlay, skip kas-container
209
+ bspctl build --skip-sync # don't touch sources/, even if stale
210
+ bspctl build --skip-doctor # bypass pre-flight (not recommended)
211
+ bspctl sync --manifest imx-6.12.49-2.2.0.xml # repo init+sync, no build
212
+ bspctl doctor # standalone diagnosis, no build
213
+ bspctl triage # post-mortem the most recent run (workspace BSPs)
214
+ bspctl triage 20260423-091014 # post-mortem a named run
215
+ bspctl triage -k pilots/0005/kas.yml # post-mortem latest BYO run for that YAML
216
+ bspctl log # tail the latest run's kas.log live
217
+ bspctl log pilots/0005/kas.yml # tail the latest BYO run for that YAML
218
+ bspctl shell # drop into a kas-container shell
219
+ bspctl gen-kas -o nxp/my-build.yml # write topology-only YAML, do nothing else
220
+ bspctl clean # remove <bsp>/build/
221
+ ```
222
+
223
+ `bspctl build` is idempotent. Re-running it after a mid-pipeline failure
224
+ picks up where it left off - repo sync is skipped if `sources/` is
225
+ populated, `setup_env` is skipped if `build/conf/bblayers.conf` exists,
226
+ and the topology YAML is regenerated in case flags changed.
227
+
228
+ ## Environment variables
229
+
230
+ Every `--flag` has a `BSPCTL_*` env equivalent so CI jobs and shell profiles can
231
+ pin defaults without passing args every invocation. Explicit CLI flags
232
+ override env vars; env vars override built-in defaults.
233
+
234
+ | Env var | Field (BuildConfig) | Default |
235
+ |---------|---------------------|---------|
236
+ | `BSPCTL_MACHINE` | `machine` | `imx8mp-var-dart` |
237
+ | `BSPCTL_DISTRO` | `distro` | `fsl-imx-xwayland` |
238
+ | `BSPCTL_IMAGE` | `image` | `core-image-minimal` |
239
+ | `BSPCTL_MANIFEST` | `manifest` | `imx-6.6.52-2.2.2.xml` |
240
+ | `BSPCTL_REPO_URL` | `repo_url` | `https://github.com/varigit/variscite-bsp-platform.git` |
241
+ | `BSPCTL_REPO_BRANCH` | `repo_branch` | `scarthgap` |
242
+ | `KAS_CONTAINER_IMAGE` | `container_image` | `jetm/kas-build-env:latest` |
243
+
244
+ `--workspace` has no env var - it is resolved from the current working
245
+ directory by walking up to find a `.bspctl.toml` marker file or `nxp/`/`ti/`
246
+ subdirectories. The walk is skipped entirely for generic BYO builds
247
+ (`bspctl build my.yml` where the YAML does not target an NXP/TI SoM);
248
+ `bsp_root` falls back to the YAML's own parent directory so generic builds
249
+ run from any location.
250
+
251
+ Cache locations (`SSTATE_DIR`, `DL_DIR`) are read from the environment and
252
+ should be pinned in your shell profile.
253
+
254
+ ## Pre-flight checks reference
255
+
256
+ `bspctl doctor` and the automatic pre-flight gate at the top of `bspctl build`
257
+ run the same checks. BLOCK-severity failures halt the build; WARN prints
258
+ and continues; INFO is purely informational. Per-BSP extras
259
+ (`check_forks_linux_imx` on NXP; `check_ti_layertool_*` on TI) load via
260
+ `BspModel.doctor_extras`; the shared set runs unconditionally. Generic
261
+ BYO mode runs only the shared set - the family-specific gates would
262
+ always fail outside an NXP/TI workspace and are skipped.
263
+
264
+ ## Observability
265
+
266
+ Each `bspctl build` invocation creates `<bsp>/build/runs/<YYYYMMDD-HHMMSS>/`
267
+ containing:
268
+
269
+ | File | Contents |
270
+ |------|----------|
271
+ | `events.jsonl` | One JSON object per step start/end/error (machine-readable) |
272
+ | `console.log` | The same stream in human-readable lines |
273
+ | `env.txt` | Snapshot of `BSPCTL_*`, `KAS_*`, `BB_*`, `DL_*`, `SSTATE_*`, `NPROC`, `MACHINE`, `DISTRO` at run start |
274
+ | `kas.log` | `kas-container build` stdout + stderr |
275
+ | `time.log` | `/usr/bin/time -v` output (when `time` is available) |
276
+ | `du.tsv` | `<unix-ts>\t<bytes>` samples of `build/tmp/` every 30 s |
277
+ | `diagnosis.txt` | The pre-flight diagnosis as plain text |
278
+
279
+ Events use the key `event` (not `event_type`), with values like `run_start`,
280
+ `step_start`, `step_ok`, `step_skip`, `step_fail`, `run_end`, `run_error`.
281
+
282
+ ## Triage workflow
283
+
284
+ By default, `bspctl triage` searches both `nxp/build/runs/` and
285
+ `ti/build/runs/` under the workspace. Pass `-k <my.yml>` (or
286
+ `--kas-yaml`) for a BYO build whose runs live next to the YAML at
287
+ `<yaml-parent>/build/runs/`. In either mode, it finds the named run
288
+ (or the most recent), reads `events.jsonl` to locate the first
289
+ `step_fail` event, tails `kas.log`, extracts the container path of
290
+ bitbake's "Logfile of failure stored in: ..." line and rewrites it to
291
+ the host path, tails that recipe log, and matches the combined output
292
+ against a keyed suggestion table (fetch failure, parser deadlock, OOM,
293
+ disk full, GitHub fetch flake, missing EULA, stale bitbake cache,
294
+ kas/container version skew).
295
+
296
+ `bspctl log` follows the same convention: pass a positional kas YAML to
297
+ tail the latest run for a BYO build, or run from inside an NXP/TI
298
+ workspace to tail the latest run for the dispatched BSP.
299
+
300
+ ## Troubleshooting
301
+
302
+ | Symptom | Resolution |
303
+ |---------|-----------|
304
+ | `Not inside a workspace (no .bspctl.toml found, and no nxp/ or ti/ subdirectory)` | cd into a workspace that contains `nxp/` or `ti/`, or add a `.bspctl.toml` marker file, or pass a positional kas YAML: `bspctl build|log|triage -k pilots/0005/kas.yml` works from anywhere (generic mode treats the YAML's parent as `bsp_root`). |
305
+ | `kas YAML <path> is outside bsp_root <bsp_root>` | NXP/TI builds need the YAML under `nxp/` or `ti/`. Copy `bspctl/examples/kas-*.yml` under `<bsp_root>/` and re-run. Generic BYO is exempt - the YAML's own directory is `bsp_root`. |
306
+ | `Could not parse <path> as a kas build` | YAML lacks both `machine:` and a `repos:` block. Add at least one before re-running. |
307
+ | `All concatenated config files must belong to the same repository ...` (kas) | Pre-fix error from the symlinked-overlay era. Reinstall bspctl at a build that ships the copy-based overlay materializer. |
308
+ | `parser thread killed/died` mid-parse | Container Python is 3.13+, which deadlocks the bitbake parser fork. Rebuild `jetm/kas-build-env` on `ubuntu:24.04` (Python 3.12). `bspctl doctor` flags this. |
309
+ | `wget: sources.openembedded.org: NXDOMAIN` noise | Dead mirror hardcoded by scarthgap's `mirrors.bbclass`. The overlay's `MIRRORS =` line suppresses it. |
310
+ | `No space left on device` | `bspctl doctor` blocks below 50 GiB free on workspace, sstate, and downloads. |
311
+ | `do_fetch: Fetcher failure` for `linux-imx` | Populate `nxp/forks/linux-imx/` so the local PREMIRROR handles the fetch without going external. |
312
+ | `Config file validation Error` from kas | Version skew between host `kas` and the kas-container image. Align both to the same kas release. |
313
+ | General fetch flake | Retry. Transient GitHub timeouts are common; `repo sync` and `do_fetch` are idempotent. |