@typecad/framework-zephyr 1.0.0-alpha.15 → 1.0.0-alpha.18

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.
Files changed (132) hide show
  1. package/LICENSE +202 -21
  2. package/README.md +49 -87
  3. package/dist/as-built.d.ts +2 -2
  4. package/dist/as-built.js +2 -2
  5. package/dist/boardgen.d.ts +1 -9
  6. package/dist/boardgen.js +228 -45
  7. package/dist/chips/types.d.ts +1 -1
  8. package/dist/debug-codegen.js +1 -1
  9. package/dist/display/touch-adapter.js +1 -1
  10. package/dist/display/ui-adapter.js +549 -549
  11. package/dist/doctor.js +4 -4
  12. package/dist/dt-config/custom-board.js +2 -2
  13. package/dist/dt-config/kconfig.js +18 -12
  14. package/dist/dt-config/overlay.d.ts +2 -2
  15. package/dist/dt-config/overlay.js +2 -2
  16. package/dist/framework.manifest.d.ts +3 -3
  17. package/dist/framework.manifest.js +10 -7
  18. package/dist/index.js +5 -5
  19. package/dist/licenses.d.ts +2 -2
  20. package/dist/licenses.js +8 -8
  21. package/dist/lowering/fs.js +1 -1
  22. package/dist/lowering/gpio.js +0 -32
  23. package/dist/lowering/http.js +264 -32
  24. package/dist/lowering/i2c.js +0 -8
  25. package/dist/lowering/interrupts.js +6 -0
  26. package/dist/lowering/mqtt.js +110 -8
  27. package/dist/lowering/usb.js +11 -11
  28. package/dist/lowering/wdt.js +2 -29
  29. package/dist/sdk/board-catalog-sync.d.ts +1 -3
  30. package/dist/sdk/board-catalog-sync.js +4 -10
  31. package/dist/strategy.d.ts +22 -44
  32. package/dist/strategy.js +152 -155
  33. package/dist/tmp-probe.d.ts +2 -0
  34. package/dist/tmp-probe.js +9 -0
  35. package/dist/toolchain/debug-config.d.ts +50 -90
  36. package/dist/toolchain/debug-config.js +241 -502
  37. package/dist/toolchain/env-check.d.ts +1 -3
  38. package/dist/toolchain/env-check.js +2 -7
  39. package/dist/toolchain/index.d.ts +65 -2
  40. package/dist/toolchain/index.js +432 -55
  41. package/dist/toolchain/runners.d.ts +16 -0
  42. package/dist/toolchain/runners.js +75 -0
  43. package/dist/toolchain/scaffold.d.ts +1 -1
  44. package/dist/toolchain/scaffold.js +12 -12
  45. package/dist/toolchain/west-discover.d.ts +6 -0
  46. package/dist/toolchain/west-discover.js +36 -13
  47. package/dist/toolchain/west-spawn.js +8 -2
  48. package/installer/README.md +328 -328
  49. package/installer/install.sh +2 -2
  50. package/installer/templates/project/.typecad/activate-zephyr.ps1 +1 -1
  51. package/installer/templates/project/.typecad/activate-zephyr.sh +1 -1
  52. package/installer/templates/project/.vscode/settings.json +1 -1
  53. package/installer/templates/project/README.md +2 -2
  54. package/package.json +5 -5
  55. package/src/as-built.ts +206 -206
  56. package/src/boardgen.ts +214 -48
  57. package/src/chips/types.ts +567 -567
  58. package/src/display/touch-adapter.ts +204 -204
  59. package/src/display/ui-adapter.ts +781 -781
  60. package/src/doctor.ts +4 -4
  61. package/src/dt-config/custom-board.ts +2 -2
  62. package/src/dt-config/kconfig.ts +18 -12
  63. package/src/dt-config/overlay.ts +1058 -1058
  64. package/src/framework.manifest.ts +538 -535
  65. package/src/index.ts +5 -5
  66. package/src/licenses.ts +425 -425
  67. package/src/lowering/fs.ts +135 -135
  68. package/src/lowering/gpio.ts +0 -33
  69. package/src/lowering/http.ts +264 -32
  70. package/src/lowering/i2c.ts +0 -9
  71. package/src/lowering/interrupts.ts +6 -0
  72. package/src/lowering/mqtt.ts +109 -8
  73. package/src/lowering/usb.ts +221 -221
  74. package/src/lowering/wdt.ts +2 -25
  75. package/src/sdk/board-catalog-sync.ts +4 -25
  76. package/src/strategy.ts +2265 -2309
  77. package/src/toolchain/debug-config.ts +264 -514
  78. package/src/toolchain/env-check.ts +279 -285
  79. package/src/toolchain/index.ts +1703 -1286
  80. package/src/toolchain/runners.ts +80 -0
  81. package/src/toolchain/scaffold.ts +296 -296
  82. package/src/toolchain/west-discover.ts +35 -13
  83. package/src/toolchain/west-spawn.ts +174 -168
  84. package/dist/async/timer-polyfill.d.ts +0 -10
  85. package/dist/async/timer-polyfill.js +0 -95
  86. package/dist/chips/board-overrides.d.ts +0 -7
  87. package/dist/chips/board-overrides.js +0 -11
  88. package/dist/chips/esp32.d.ts +0 -2
  89. package/dist/chips/esp32.js +0 -71
  90. package/dist/chips/esp32s3.d.ts +0 -2
  91. package/dist/chips/esp32s3.js +0 -103
  92. package/dist/chips/soc/.d.ts +0 -2
  93. package/dist/chips/soc/.js +0 -129
  94. package/dist/chips/soc/esp32.d.ts +0 -2
  95. package/dist/chips/soc/esp32.js +0 -120
  96. package/dist/chips/soc/esp32c3.d.ts +0 -2
  97. package/dist/chips/soc/esp32c3.js +0 -90
  98. package/dist/chips/soc/esp32c6.d.ts +0 -2
  99. package/dist/chips/soc/esp32c6.js +0 -109
  100. package/dist/chips/soc/esp32s3.d.ts +0 -2
  101. package/dist/chips/soc/esp32s3.js +0 -189
  102. package/dist/chips/soc/index.d.ts +0 -2
  103. package/dist/chips/soc/index.js +0 -23
  104. package/dist/chips/soc/nrf52840.d.ts +0 -2
  105. package/dist/chips/soc/nrf52840.js +0 -130
  106. package/dist/chips/soc/rp2040.d.ts +0 -2
  107. package/dist/chips/soc/rp2040.js +0 -141
  108. package/dist/chips/soc/rp2350a.d.ts +0 -2
  109. package/dist/chips/soc/rp2350a.js +0 -145
  110. package/dist/chips/soc/samd21g18a.d.ts +0 -2
  111. package/dist/chips/soc/samd21g18a.js +0 -143
  112. package/dist/chips/soc/stm32f411xe.d.ts +0 -2
  113. package/dist/chips/soc/stm32f411xe.js +0 -251
  114. package/dist/chips/xiao-ble.d.ts +0 -2
  115. package/dist/chips/xiao-ble.js +0 -100
  116. package/dist/lowering/power.d.ts +0 -9
  117. package/dist/lowering/power.js +0 -60
  118. package/dist/lowering/pulse.d.ts +0 -7
  119. package/dist/lowering/pulse.js +0 -51
  120. package/dist/lowering/tone.d.ts +0 -10
  121. package/dist/lowering/tone.js +0 -63
  122. package/dist/lowering/worker-backing.d.ts +0 -14
  123. package/dist/lowering/worker-backing.js +0 -79
  124. package/dist/lowering/worker.d.ts +0 -6
  125. package/dist/lowering/worker.js +0 -14
  126. package/dist/sdk/board-data.generated.d.ts +0 -2
  127. package/dist/sdk/board-data.generated.js +0 -4
  128. package/dist/sdk/catalog-walker.d.ts +0 -90
  129. package/dist/sdk/catalog-walker.js +0 -682
  130. package/dist/sdk/dts-reader.d.ts +0 -83
  131. package/dist/sdk/dts-reader.js +0 -596
  132. package/src/debug-codegen.ts +0 -207
@@ -1,328 +1,328 @@
1
- # Zephyr installer (bundled with @typecad/framework-zephyr)
2
-
3
- A one-command, cross-platform installer for a working **Zephyr RTOS** build
4
- environment, built on [micromamba](https://mamba.readthedocs.io/) and the
5
- official Zephyr SDK. It produces an activatable environment with `west` + host
6
- build tools, the Zephyr SDK cross-toolchains, and a vanilla Zephyr `west`
7
- workspace — wired so [`framework-zephyr`](../framework-zephyr) finds everything
8
- automatically.
9
-
10
- - **No prerequisites** — no preinstalled conda, Python, or toolchain. micromamba
11
- is fetched as a single static binary.
12
- - **Cross-platform** — Linux, macOS, and Windows-native (PowerShell). No WSL.
13
- - **Just works** — the default installs every toolchain platform, so any board in
14
- the Zephyr data pack compiles as-is with no follow-up installs (~1.5 GB download,
15
- ~11 GB extracted). Space-conscious users can opt into a subset (~150-300 MB).
16
- - **Reproducible** — SDK version, Zephyr manifest revision, and per-platform
17
- SHA256s are pinned in [`versions.env`](./versions.env).
18
-
19
- ## Commands
20
-
21
- All commands work identically on Linux, macOS, and Windows (Node ≥ 18 required —
22
- already a dependency of this repo):
23
-
24
- ```sh
25
- npx --package @typecad/framework-zephyr zephyr-installer # install everything (interactive; Enter = All)
26
- npx --package @typecad/framework-zephyr zephyr-installer --platforms arm,esp32 # space-saver: subset only
27
- npx --package @typecad/framework-zephyr zephyr-installer --modify --yes # later: add any missing toolchains (additive)
28
- npx --package @typecad/framework-zephyr zephyr-installer --modify --prune --yes # ...and also remove unselected ones
29
- npx --package @typecad/framework-zephyr zephyr-installer --delete # uninstall everything
30
- npx --package @typecad/framework-zephyr zephyr-installer --help # full usage reference
31
- npx --package @typecad/framework-zephyr zephyr-installer --dry-run # preview the resolved plan
32
- ```
33
-
34
- (From a repo checkout, `node packages/framework-zephyr/installer/install.mjs` is the same
35
- entry point. The OS-native `bash install.sh` / `pwsh -File install.ps1` remain
36
- usable directly for power users.)
37
-
38
- ## Flags
39
-
40
- | Flag | Description |
41
- | ---- | ----------- |
42
- | *(none)* | Interactive install: platform checklist → summary → Enter → install. |
43
- | `--platforms IDS` | Space-saving, non-interactive platform selection: comma-separated group ids (`arm,esp32,riscv,arc,rx,x86,aarch64`) or `all`. Default: `all` — recommended, so every board in the data pack builds as-is. |
44
- | `--modify` | Re-run the SDK platform step on an existing install: **adds** the selected groups' missing toolchains (idempotent per-toolchain). Purely additive — nothing is deleted unless `--prune` is also given. SDK-only — skips the env and workspace steps. |
45
- | `--prune` | With `--modify`: also **delete** toolchains of platforms not in the selection (reclaim disk space). |
46
- | `--delete` | **Uninstall everything**: conda env, Zephyr SDK, west workspace, and micromamba itself (only when it has no other envs). Shows exact paths + sizes and requires typing `yes` to confirm. |
47
- | `--yes`, `-y` | Skip confirmation prompts (CI / scripting). With `--delete` this is the only non-interactive way to proceed. |
48
- | `--dry-run` | Print the resolved plan — URLs, paths, versions, platform selection — and exit. Downloads/creates nothing. |
49
- | `--no-sdk` | Skip the Zephyr SDK download entirely (env + workspace only). |
50
- | `--no-workspace` | Skip `west init`/`west update` (env + SDK only). |
51
- | `--env-name NAME` | Override the conda env name (default: `zephyr`). |
52
- | `--sdk-version VER` | Override the Zephyr SDK version (default: pinned in `versions.env`). |
53
- | `-h`, `--help` | Print the full usage reference and exit. |
54
-
55
- Short forms: `-m` = `--modify`, `-d` = `--delete`, `-y` = `--yes`.
56
-
57
- ### Environment overrides
58
-
59
- | Variable | Default | Controls |
60
- | -------- | ------- | -------- |
61
- | `MAMBA_ROOT_PREFIX` | `~/micromamba` | micromamba root (binary, envs, pkgs cache) |
62
- | `WORKSPACE_DIR` | `~/zephyrproject` | west workspace location (`ZEPHYR_BASE` is `<dir>/zephyr`) |
63
- | `SDK_INSTALL_PARENT` | `$MAMBA_ROOT_PREFIX/zephyr-sdk` | where the SDK extracts |
64
- | `TYPECAD_ZEPHYR_ENV` | *(unset)* | env-name override honored by the framework's west discovery |
65
-
66
- ## Platform selection
67
-
68
- A full install downloads the 1.5 GB SDK bundle (all 25+ toolchains — hours on a
69
- slow connection). Most users need one or two platforms. The installer instead
70
- downloads the ~10 MB minimal bundle (cmake config + `sdk_version`) plus only the
71
- selected toolchains:
72
-
73
- | Group | Toolchain(s) | Covers | ~Download |
74
- | ----- | ------------ | ------ | --------- |
75
- | `arm` | `arm-zephyr-eabi` | nRF, RP2040, STM32, SAMD, all Cortex-M | ~150 MB |
76
- | `esp32` | `xtensa-espressif_esp32{,s2,s3}_zephyr-elf` | ESP32, ESP32-S2, ESP32-S3 | ~300 MB |
77
- | `riscv` | `riscv64-zephyr-elf` | ESP32-C3/C6, generic RISC-V | ~120 MB |
78
- | `x86` | `x86_64-zephyr-elf` | native_sim, x86 boards | ~100 MB |
79
- | `aarch64` | `aarch64-zephyr-elf` | ARM64 boards | ~100 MB |
80
- | `all` | *(full bundle)* | everything | ~1.5 GB |
81
-
82
- Board support beyond toolchains is universal — `west update` fetches every HAL
83
- module (they're small), so `rp2040`, `samd`, `nrf`, `stm32`, etc. all build with
84
- the `arm` group alone. Only ESP32 adds Python tooling (`esptool`), installed
85
- automatically from the espressif HAL's own requirements.
86
-
87
- The interactive checklist accepts numbers (`1 2`), group ids (`arm,esp32`), or
88
- `all`, and marks already-installed groups:
89
-
90
- ```
91
- Select platform toolchains to install:
92
-
93
- [1] ARM Cortex-M (nRF, RP2040, STM32, SAMD, ...) ~150 MB installed
94
- [2] ESP32 / ESP32-S2 / ESP32-S3 (Xtensa) ~300 MB
95
- [3] RISC-V (ESP32-C3/C6, generic RISC-V) ~120 MB
96
- [4] x86 / native_sim ~100 MB
97
- [a] All (full bundle, ~1.5 GB download / ~11 GB extracted)
98
-
99
- Enter selection (e.g. '1 2', 'arm,esp32', or 'all'):
100
- ```
101
-
102
- The selection persists in `$SDK_INSTALL_DIR/.typecad-platforms`.
103
-
104
- ### `--modify` (reconfigure)
105
-
106
- Re-runs the checklist with installed toolchains marked, then applies the delta:
107
- new selections download (existing toolchains are skipped — no re-download),
108
- deselections **delete their toolchain directories**. A warning is shown before
109
- the checklist; re-adding a removed platform later re-downloads it. Use
110
- `--platforms` with `--modify` to script it, e.g.
111
- `--modify --platforms arm,riscv`.
112
-
113
- ### `--delete` (uninstall)
114
-
115
- Shows every path that will be removed with its on-disk size, then requires
116
- typing `yes`:
117
-
118
- - the conda env (`$MAMBA_ROOT_PREFIX/envs/<name>`)
119
- - the Zephyr SDK (`$MAMBA_ROOT_PREFIX/zephyr-sdk/`)
120
- - the west workspace (`~/zephyrproject`)
121
- - micromamba itself — **only when no other conda envs exist**; otherwise the
122
- root is kept and surviving envs are named
123
-
124
- Non-interactive stdin without `--yes` **refuses** (destructive default-deny).
125
- The shell-profile hook (from `micromamba shell init`) is never auto-edited; the
126
- summary names the file to trim by hand.
127
-
128
- ## What an install does
129
-
130
- 1. Downloads the micromamba static binary (no preinstalled conda/Python needed)
131
- and registers its shell hook (`~/.bashrc` / PowerShell `$PROFILE`).
132
- 2. Creates a `zephyr` conda env from [`environment.yml`](./environment.yml)
133
- (python, west, cmake `<4`, ninja, gperf, pyelftools), plus platform extras:
134
- `dtc` + `openocd` on POSIX, `7zip` on Windows.
135
- 3. Installs activation hooks that export `ZEPHYR_BASE` + `ZEPHYR_SDK_INSTALL_DIR`.
136
- 4. Fetches + verifies + extracts the Zephyr SDK (minimal + selected toolchains,
137
- or the full bundle).
138
- 5. Runs `west init --mr <rev>` + `west update`, then installs Zephyr's Python
139
- build requirements (`requirements-base.txt` + build-relevant per-module
140
- requirements such as `esptool`).
141
-
142
- No `sudo`, no Zephyr SDK `setup.sh` — the SDK is used in place via
143
- `ZEPHYR_SDK_INSTALL_DIR`.
144
-
145
- ## Activate
146
-
147
- The installer runs `micromamba shell init` for you, so in a **new** shell you
148
- only need to activate the env — and `framework-zephyr` then discovers `west`
149
- automatically:
150
-
151
- ```sh
152
- micromamba activate zephyr
153
-
154
- # verify
155
- west --version
156
- echo $ZEPHYR_BASE # -> ~/zephyrproject/zephyr
157
- ```
158
-
159
- In fact, with `@typecad/framework-zephyr` ≥ alpha.11 you don't even need to
160
- activate to **build** — cuttlefish discovers the micromamba env and invokes
161
- `micromamba run -n zephyr west …` itself. Activation matters for your own
162
- interactive use (`west`, `gdb`, serial monitors).
163
-
164
- For the **current** session (without a new shell):
165
-
166
- ```sh
167
- # bash / zsh
168
- eval "$(micromamba shell hook --shell bash)"
169
- micromamba activate zephyr
170
- ```
171
-
172
- ```powershell
173
- # PowerShell — NB: the `micromamba shell hook ... | Invoke-Expression` pipe
174
- # form does NOT work (it parses the multi-line hook line-by-line and fails).
175
- Invoke-Expression ((& "$env:MAMBA_EXE" shell hook -s powershell) -join [char]10)
176
- micromamba activate zephyr
177
- ```
178
-
179
- ## What lands where
180
-
181
- | Thing | Default location | Override |
182
- | ---------------- | ------------------------------------------------ | ------------------- |
183
- | micromamba root | `~/micromamba` (`%USERPROFILE%\micromamba`) | `MAMBA_ROOT_PREFIX` |
184
- | conda env | `$MAMBA_ROOT_PREFIX/envs/zephyr` | `--env-name` |
185
- | Zephyr SDK | `$MAMBA_ROOT_PREFIX/zephyr-sdk/zephyr-sdk-<ver>` | `SDK_INSTALL_PARENT`|
186
- | west workspace | `~/zephyrproject` | `WORKSPACE_DIR` |
187
-
188
- The SDK lives **outside** the conda env prefix on purpose: `micromamba create`
189
- needs the prefix empty, and a failed env-create must not trap a multi-GB
190
- download. `micromamba env remove -n zephyr` removes the env but leaves the SDK —
191
- delete `$MAMBA_ROOT_PREFIX/zephyr-sdk` separately to reclaim that space (or just
192
- use `--delete`).
193
-
194
- ## How it integrates with `framework-zephyr`
195
-
196
- `framework-zephyr` resolves `west` via a discovery cascade
197
- ([`src/toolchain/west-discover.ts`](../src/toolchain/west-discover.ts)):
198
-
199
- 1. `west` on PATH (activated shell)
200
- 2. `$ZEPHYR_BASE` venv
201
- 3. **micromamba env from this installer** — invoked via `micromamba run`, which
202
- sets up the full PATH + activation hooks with no manual activation
203
- 4. Well-known workspace dirs (`~/zephyrproject`, …)
204
- 5. System pythons
205
-
206
- So a plain `npx cuttlefish build` works in any project after install, activated
207
- or not. The compat check reads the Zephyr version from the installer env's
208
- env-vars file when `ZEPHYR_BASE` isn't set.
209
-
210
- ### Pre-existing Zephyr install on the same machine
211
-
212
- If you already had a west/SDK install, **activation is the switch** — the
213
- activated env is prepended to PATH, so its `west` and the hook's
214
- `ZEPHYR_SDK_INSTALL_DIR` win. Unactivated, cuttlefish prefers the installer env
215
- (cascade order 3 before 4), falling back to a pre-existing `~/zephyrproject/.venv`.
216
-
217
- ## Per-project auto-activation
218
-
219
- Drop [`templates/project/`](./templates/project) into a cuttlefish Zephyr project
220
- so opening a terminal there auto-activates the env — machine-agnostic activators
221
- (`.typecad/activate-zephyr.{ps1,sh}`) plus a VS Code terminal profile. See
222
- [`templates/project/README.md`](./templates/project/README.md).
223
-
224
- ## Customizing
225
-
226
- All version + URL pinning lives in [`versions.env`](./versions.env):
227
-
228
- - `ZEPHYR_SDK_VERSION` — currently **1.0.1** (the Zephyr 4.4-compatible line;
229
- 1.0.x dropped "full" bundles — `_gnu` = all GNU toolchains + host tools).
230
- Building against Zephyr 4.3.x instead? Use `--sdk-version 0.17.4`.
231
- - `ZEPHYR_SDK_BUNDLE_SUFFIX` — the bundle flavor (`_gnu` on 1.0.x, empty on
232
- 0.17.x). Individual toolchain tarballs carry it as an infix
233
- (`toolchain_gnu_<plat>_<target>`).
234
- - `ZEPHYR_MANIFEST_REV` — bump and re-run to upgrade. Re-running re-pins the
235
- manifest revision on an existing workspace (`west config manifest.revision`),
236
- so a workspace adopted from a pre-existing install — or one tracking `main` —
237
- converges onto the pinned tag instead of drifting out of sync with the SDK.
238
- - `SHA256_<platform>` — per-platform bundle hashes from the release's official
239
- `sha256.sum`. `TODO` = not yet pinned (the installer prints the computed hash
240
- on first download for you to pin); `NONE` = no build exists for that platform
241
- (**macOS Intel has no 1.0.x SDK** — the installer fails with guidance there).
242
- - `PLATFORM_<group>` — the platform-group → toolchain mapping behind the
243
- checklist and `--platforms`.
244
-
245
- `--env-name` / `--sdk-version` override ad-hoc without editing the file.
246
-
247
- ## Platform-specific tools
248
-
249
- `environment.yml` lists only packages available on conda-forge for *every*
250
- platform (micromamba's solver ignores `# [not win]` selectors). Platform-limited
251
- tools are added by the install scripts in a follow-up `micromamba install`:
252
-
253
- | Tool | Source | Platforms |
254
- | -------------------------------- | ----------------------------- | ------------------------------------------ |
255
- | `dtc` (device tree compiler) | conda-forge via `install.sh` | linux-64, linux-aarch64, osx-64, osx-arm64 |
256
- | `openocd` (JTAG/SWD flash+debug) | conda-forge via `install.sh` | linux-64, osx-64 only (no arm64, no win) |
257
- | `7zip` (extract the `.7z` SDK) | conda-forge via `install.ps1` | win-64 |
258
- | `dfu-util` (USB DFU flashing) | MSYS2 mingw64 via `install.ps1` (pinned in `versions.env`); system package manager hint on POSIX | win-64 (installed into the env); POSIX prints the install command |
259
- | `bossac` (SAMD SAM-BA flashing) | official BOSSA MSI via `install.ps1` (pinned in `versions.env`); system package manager hint on POSIX | win-64 (installed into the env); POSIX prints the install command |
260
-
261
- **Windows `dtc`** — conda-forge has no win-64 build and the SDK bundle ships no
262
- standalone `dtc` binary there. This rarely blocks builds (Zephyr's Python
263
- `edtlib` does the devicetree work); if a board needs the C `dtc`, install it via
264
- chocolatey (`choco install dtc`) or the SDK's `setup.cmd`.
265
-
266
- ## Troubleshooting
267
-
268
- - **`npx --package @typecad/framework-zephyr zephyr-installer` does nothing** — fixed in alpha.11 (the
269
- entry-point guard now follows symlinks). If on an older alpha, run
270
- `node node_modules/@typecad/framework-zephyr/installer/install.mjs` directly.
271
- - **`west: command not recognized` / empty `ZEPHYR_BASE`** — the env isn't
272
- activated in *this* session. Run `micromamba activate zephyr`. Note that
273
- `cuttlefish build` works without activation (see integration above).
274
- - **`micromamba: command not found`** in a new shell — the installer ran
275
- `micromamba shell init`; reload with `. $PROFILE` (PowerShell) or
276
- `source ~/.bashrc`, or open a new terminal.
277
- - **PowerShell: `micromamba shell hook ... | Invoke-Expression` fails** — that
278
- pipe form parses the multi-line hook line-by-line and breaks. Use the
279
- array-join form shown in [Activate](#activate).
280
- - **`env: '…\envs\zephyr' exists but is not a valid conda env (no conda-meta)`**
281
- — residue from a prior failed run. Remove it and re-run.
282
- - **`west update` → `MalformedConfig: local configuration file not found`** —
283
- a broken `.west/`; the installer now re-initializes it automatically (alpha.11).
284
- - **CMake error at `FindZephyr-sdk.cmake` (`Unknown arguments specified`)** —
285
- cmake 4.x vs Zephyr 4.3.x; the env pins `cmake<4` (alpha.11). On an env
286
- created before that pin: `micromamba install -n zephyr 'cmake>=3.20,<4'`.
287
- - **ESP32 build: `esptool: error: unrecognized arguments`** — missing esptool
288
- in the env; fixed by the per-module requirements step (alpha.11). Retroactively:
289
- `pip install -r ~/zephyrproject/modules/hal/espressif/zephyr/requirements.txt`
290
- (with the env's python).
291
- - **Windows C++ compile: `bits/c++config.h: No such file or directory`** —
292
- Windows MAX_PATH (260) exceeded by a deeply nested SDK path. Keep the SDK path
293
- short (junction a shallow path to it and point `ZEPHYR_SDK_INSTALL_DIR` at the
294
- junction), then wipe the build dir so CMake re-configures with the new path.
295
- - **`warning libmamba Windows version found:10.0.<build> - Not setting long
296
- path registry key…`** — a known micromamba bug misreading modern Windows 11
297
- builds. Cosmetic on machines with long paths enabled; check with
298
- `(Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name LongPathsEnabled).LongPathsEnabled`.
299
- - **Linux: flashing requires root / udev rules** — install the upstream udev
300
- rules once (the SDK `setup.sh` that installs them is deliberately skipped);
301
- see the [Zephyr Linux setup docs](https://docs.zephyrproject.org/latest/develop/getting_started/installation_linux.html).
302
- - **`west update` is slow** — it clones zephyr + all manifest projects on the
303
- first run. Subsequent runs are incremental.
304
-
305
- ## Layout
306
-
307
- ```
308
- packages/framework-zephyr/installer/
309
- install.mjs entry point: checklist, confirmations, --delete, dispatch
310
- install.sh / install.ps1 OS-native installers (POSIX / PowerShell)
311
- environment.yml conda-forge host tools (cross-platform base)
312
- versions.env pinned versions, URLs, SHA256s, platform groups
313
- lib/
314
- detect-platform.sh uname → conda + SDK platform tokens
315
- fetch-sdk.sh full-bundle or minimal+toolchains download/verify/extract
316
- init-workspace.sh west init --mr <rev> + west update + Python requirements
317
- write-activation.sh drop activate.d/deactivate.d hooks into the env
318
- etc/conda/
319
- activate.d/zephyr.{sh,bat,ps1} export ZEPHYR_BASE + ZEPHYR_SDK_INSTALL_DIR
320
- deactivate.d/zephyr.{sh,bat,ps1} unset them
321
- templates/project/ per-project auto-activation template
322
- ```
323
-
324
- Line endings are enforced LF for all POSIX-executed files via `.gitattributes`
325
- (`*.sh`, `*.mjs`, `*.env`, `environment.yml`) — CRLF would break bash on Linux.
326
-
327
- Tests live at `tests/packages/framework-zephyr/installer-tests/` (run via
328
- the repo-root `npm test`).
1
+ # Zephyr installer (bundled with @typecad/framework-zephyr)
2
+
3
+ A one-command, cross-platform installer for a working **Zephyr RTOS** build
4
+ environment, built on [micromamba](https://mamba.readthedocs.io/) and the
5
+ official Zephyr SDK. It produces an activatable environment with `west` + host
6
+ build tools, the Zephyr SDK cross-toolchains, and a vanilla Zephyr `west`
7
+ workspace — wired so [`framework-zephyr`](../framework-zephyr) finds everything
8
+ automatically.
9
+
10
+ - **No prerequisites** — no preinstalled conda, Python, or toolchain. micromamba
11
+ is fetched as a single static binary.
12
+ - **Cross-platform** — Linux, macOS, and Windows-native (PowerShell). No WSL.
13
+ - **Just works** — the default installs every toolchain platform, so any board in
14
+ the Zephyr data pack compiles as-is with no follow-up installs (~1.5 GB download,
15
+ ~11 GB extracted). Space-conscious users can opt into a subset (~150-300 MB).
16
+ - **Reproducible** — SDK version, Zephyr manifest revision, and per-platform
17
+ SHA256s are pinned in [`versions.env`](./versions.env).
18
+
19
+ ## Commands
20
+
21
+ All commands work identically on Linux, macOS, and Windows (Node ≥ 18 required —
22
+ already a dependency of this repo):
23
+
24
+ ```sh
25
+ npx --package @typecad/framework-zephyr zephyr-installer # install everything (interactive; Enter = All)
26
+ npx --package @typecad/framework-zephyr zephyr-installer --platforms arm,esp32 # space-saver: subset only
27
+ npx --package @typecad/framework-zephyr zephyr-installer --modify --yes # later: add any missing toolchains (additive)
28
+ npx --package @typecad/framework-zephyr zephyr-installer --modify --prune --yes # ...and also remove unselected ones
29
+ npx --package @typecad/framework-zephyr zephyr-installer --delete # uninstall everything
30
+ npx --package @typecad/framework-zephyr zephyr-installer --help # full usage reference
31
+ npx --package @typecad/framework-zephyr zephyr-installer --dry-run # preview the resolved plan
32
+ ```
33
+
34
+ (From a repo checkout, `node packages/framework-zephyr/installer/install.mjs` is the same
35
+ entry point. The OS-native `bash install.sh` / `pwsh -File install.ps1` remain
36
+ usable directly for power users.)
37
+
38
+ ## Flags
39
+
40
+ | Flag | Description |
41
+ | ---- | ----------- |
42
+ | *(none)* | Interactive install: platform checklist → summary → Enter → install. |
43
+ | `--platforms IDS` | Space-saving, non-interactive platform selection: comma-separated group ids (`arm,esp32,riscv,arc,rx,x86,aarch64`) or `all`. Default: `all` — recommended, so every board in the data pack builds as-is. |
44
+ | `--modify` | Re-run the SDK platform step on an existing install: **adds** the selected groups' missing toolchains (idempotent per-toolchain). Purely additive — nothing is deleted unless `--prune` is also given. SDK-only — skips the env and workspace steps. |
45
+ | `--prune` | With `--modify`: also **delete** toolchains of platforms not in the selection (reclaim disk space). |
46
+ | `--delete` | **Uninstall everything**: conda env, Zephyr SDK, west workspace, and micromamba itself (only when it has no other envs). Shows exact paths + sizes and requires typing `yes` to confirm. |
47
+ | `--yes`, `-y` | Skip confirmation prompts (CI / scripting). With `--delete` this is the only non-interactive way to proceed. |
48
+ | `--dry-run` | Print the resolved plan — URLs, paths, versions, platform selection — and exit. Downloads/creates nothing. |
49
+ | `--no-sdk` | Skip the Zephyr SDK download entirely (env + workspace only). |
50
+ | `--no-workspace` | Skip `west init`/`west update` (env + SDK only). |
51
+ | `--env-name NAME` | Override the conda env name (default: `zephyr`). |
52
+ | `--sdk-version VER` | Override the Zephyr SDK version (default: pinned in `versions.env`). |
53
+ | `-h`, `--help` | Print the full usage reference and exit. |
54
+
55
+ Short forms: `-m` = `--modify`, `-d` = `--delete`, `-y` = `--yes`.
56
+
57
+ ### Environment overrides
58
+
59
+ | Variable | Default | Controls |
60
+ | -------- | ------- | -------- |
61
+ | `MAMBA_ROOT_PREFIX` | `~/micromamba` | micromamba root (binary, envs, pkgs cache) |
62
+ | `WORKSPACE_DIR` | `~/zephyrproject` | west workspace location (`ZEPHYR_BASE` is `<dir>/zephyr`) |
63
+ | `SDK_INSTALL_PARENT` | `$MAMBA_ROOT_PREFIX/zephyr-sdk` | where the SDK extracts |
64
+ | `TYPECAD_ZEPHYR_ENV` | *(unset)* | env-name override honored by the framework's west discovery |
65
+
66
+ ## Platform selection
67
+
68
+ A full install downloads the 1.5 GB SDK bundle (all 25+ toolchains — hours on a
69
+ slow connection). Most users need one or two platforms. The installer instead
70
+ downloads the ~10 MB minimal bundle (cmake config + `sdk_version`) plus only the
71
+ selected toolchains:
72
+
73
+ | Group | Toolchain(s) | Covers | ~Download |
74
+ | ----- | ------------ | ------ | --------- |
75
+ | `arm` | `arm-zephyr-eabi` | nRF, RP2040, STM32, SAMD, all Cortex-M | ~150 MB |
76
+ | `esp32` | `xtensa-espressif_esp32{,s2,s3}_zephyr-elf` | ESP32, ESP32-S2, ESP32-S3 | ~300 MB |
77
+ | `riscv` | `riscv64-zephyr-elf` | ESP32-C3/C6, generic RISC-V | ~120 MB |
78
+ | `x86` | `x86_64-zephyr-elf` | native_sim, x86 boards | ~100 MB |
79
+ | `aarch64` | `aarch64-zephyr-elf` | ARM64 boards | ~100 MB |
80
+ | `all` | *(full bundle)* | everything | ~1.5 GB |
81
+
82
+ Board support beyond toolchains is universal — `west update` fetches every HAL
83
+ module (they're small), so `rp2040`, `samd`, `nrf`, `stm32`, etc. all build with
84
+ the `arm` group alone. Only ESP32 adds Python tooling (`esptool`), installed
85
+ automatically from the espressif HAL's own requirements.
86
+
87
+ The interactive checklist accepts numbers (`1 2`), group ids (`arm,esp32`), or
88
+ `all`, and marks already-installed groups:
89
+
90
+ ```
91
+ Select platform toolchains to install:
92
+
93
+ [1] ARM Cortex-M (nRF, RP2040, STM32, SAMD, ...) ~150 MB installed
94
+ [2] ESP32 / ESP32-S2 / ESP32-S3 (Xtensa) ~300 MB
95
+ [3] RISC-V (ESP32-C3/C6, generic RISC-V) ~120 MB
96
+ [4] x86 / native_sim ~100 MB
97
+ [a] All (full bundle, ~1.5 GB download / ~11 GB extracted)
98
+
99
+ Enter selection (e.g. '1 2', 'arm,esp32', or 'all'):
100
+ ```
101
+
102
+ The selection persists in `$SDK_INSTALL_DIR/.typecad-platforms`.
103
+
104
+ ### `--modify` (reconfigure)
105
+
106
+ Re-runs the checklist with installed toolchains marked, then applies the delta:
107
+ new selections download (existing toolchains are skipped — no re-download),
108
+ deselections **delete their toolchain directories**. A warning is shown before
109
+ the checklist; re-adding a removed platform later re-downloads it. Use
110
+ `--platforms` with `--modify` to script it, e.g.
111
+ `--modify --platforms arm,riscv`.
112
+
113
+ ### `--delete` (uninstall)
114
+
115
+ Shows every path that will be removed with its on-disk size, then requires
116
+ typing `yes`:
117
+
118
+ - the conda env (`$MAMBA_ROOT_PREFIX/envs/<name>`)
119
+ - the Zephyr SDK (`$MAMBA_ROOT_PREFIX/zephyr-sdk/`)
120
+ - the west workspace (`~/zephyrproject`)
121
+ - micromamba itself — **only when no other conda envs exist**; otherwise the
122
+ root is kept and surviving envs are named
123
+
124
+ Non-interactive stdin without `--yes` **refuses** (destructive default-deny).
125
+ The shell-profile hook (from `micromamba shell init`) is never auto-edited; the
126
+ summary names the file to trim by hand.
127
+
128
+ ## What an install does
129
+
130
+ 1. Downloads the micromamba static binary (no preinstalled conda/Python needed)
131
+ and registers its shell hook (`~/.bashrc` / PowerShell `$PROFILE`).
132
+ 2. Creates a `zephyr` conda env from [`environment.yml`](./environment.yml)
133
+ (python, west, cmake `<4`, ninja, gperf, pyelftools), plus platform extras:
134
+ `dtc` + `openocd` on POSIX, `7zip` on Windows.
135
+ 3. Installs activation hooks that export `ZEPHYR_BASE` + `ZEPHYR_SDK_INSTALL_DIR`.
136
+ 4. Fetches + verifies + extracts the Zephyr SDK (minimal + selected toolchains,
137
+ or the full bundle).
138
+ 5. Runs `west init --mr <rev>` + `west update`, then installs Zephyr's Python
139
+ build requirements (`requirements-base.txt` + build-relevant per-module
140
+ requirements such as `esptool`).
141
+
142
+ No `sudo`, no Zephyr SDK `setup.sh` — the SDK is used in place via
143
+ `ZEPHYR_SDK_INSTALL_DIR`.
144
+
145
+ ## Activate
146
+
147
+ The installer runs `micromamba shell init` for you, so in a **new** shell you
148
+ only need to activate the env — and `framework-zephyr` then discovers `west`
149
+ automatically:
150
+
151
+ ```sh
152
+ micromamba activate zephyr
153
+
154
+ # verify
155
+ west --version
156
+ echo $ZEPHYR_BASE # -> ~/zephyrproject/zephyr
157
+ ```
158
+
159
+ In fact, with `@typecad/framework-zephyr` ≥ alpha.11 you don't even need to
160
+ activate to **build** — typecad-hal discovers the micromamba env and invokes
161
+ `micromamba run -n zephyr west …` itself. Activation matters for your own
162
+ interactive use (`west`, `gdb`, serial monitors).
163
+
164
+ For the **current** session (without a new shell):
165
+
166
+ ```sh
167
+ # bash / zsh
168
+ eval "$(micromamba shell hook --shell bash)"
169
+ micromamba activate zephyr
170
+ ```
171
+
172
+ ```powershell
173
+ # PowerShell — NB: the `micromamba shell hook ... | Invoke-Expression` pipe
174
+ # form does NOT work (it parses the multi-line hook line-by-line and fails).
175
+ Invoke-Expression ((& "$env:MAMBA_EXE" shell hook -s powershell) -join [char]10)
176
+ micromamba activate zephyr
177
+ ```
178
+
179
+ ## What lands where
180
+
181
+ | Thing | Default location | Override |
182
+ | ---------------- | ------------------------------------------------ | ------------------- |
183
+ | micromamba root | `~/micromamba` (`%USERPROFILE%\micromamba`) | `MAMBA_ROOT_PREFIX` |
184
+ | conda env | `$MAMBA_ROOT_PREFIX/envs/zephyr` | `--env-name` |
185
+ | Zephyr SDK | `$MAMBA_ROOT_PREFIX/zephyr-sdk/zephyr-sdk-<ver>` | `SDK_INSTALL_PARENT`|
186
+ | west workspace | `~/zephyrproject` | `WORKSPACE_DIR` |
187
+
188
+ The SDK lives **outside** the conda env prefix on purpose: `micromamba create`
189
+ needs the prefix empty, and a failed env-create must not trap a multi-GB
190
+ download. `micromamba env remove -n zephyr` removes the env but leaves the SDK —
191
+ delete `$MAMBA_ROOT_PREFIX/zephyr-sdk` separately to reclaim that space (or just
192
+ use `--delete`).
193
+
194
+ ## How it integrates with `framework-zephyr`
195
+
196
+ `framework-zephyr` resolves `west` via a discovery cascade
197
+ ([`src/toolchain/west-discover.ts`](../src/toolchain/west-discover.ts)):
198
+
199
+ 1. `west` on PATH (activated shell)
200
+ 2. `$ZEPHYR_BASE` venv
201
+ 3. **micromamba env from this installer** — invoked via `micromamba run`, which
202
+ sets up the full PATH + activation hooks with no manual activation
203
+ 4. Well-known workspace dirs (`~/zephyrproject`, …)
204
+ 5. System pythons
205
+
206
+ So a plain `npx typecad-hal build` works in any project after install, activated
207
+ or not. The compat check reads the Zephyr version from the installer env's
208
+ env-vars file when `ZEPHYR_BASE` isn't set.
209
+
210
+ ### Pre-existing Zephyr install on the same machine
211
+
212
+ If you already had a west/SDK install, **activation is the switch** — the
213
+ activated env is prepended to PATH, so its `west` and the hook's
214
+ `ZEPHYR_SDK_INSTALL_DIR` win. Unactivated, typecad-hal prefers the installer env
215
+ (cascade order 3 before 4), falling back to a pre-existing `~/zephyrproject/.venv`.
216
+
217
+ ## Per-project auto-activation
218
+
219
+ Drop [`templates/project/`](./templates/project) into a typecad-hal Zephyr project
220
+ so opening a terminal there auto-activates the env — machine-agnostic activators
221
+ (`.typecad/activate-zephyr.{ps1,sh}`) plus a VS Code terminal profile. See
222
+ [`templates/project/README.md`](./templates/project/README.md).
223
+
224
+ ## Customizing
225
+
226
+ All version + URL pinning lives in [`versions.env`](./versions.env):
227
+
228
+ - `ZEPHYR_SDK_VERSION` — currently **1.0.1** (the Zephyr 4.4-compatible line;
229
+ 1.0.x dropped "full" bundles — `_gnu` = all GNU toolchains + host tools).
230
+ Building against Zephyr 4.3.x instead? Use `--sdk-version 0.17.4`.
231
+ - `ZEPHYR_SDK_BUNDLE_SUFFIX` — the bundle flavor (`_gnu` on 1.0.x, empty on
232
+ 0.17.x). Individual toolchain tarballs carry it as an infix
233
+ (`toolchain_gnu_<plat>_<target>`).
234
+ - `ZEPHYR_MANIFEST_REV` — bump and re-run to upgrade. Re-running re-pins the
235
+ manifest revision on an existing workspace (`west config manifest.revision`),
236
+ so a workspace adopted from a pre-existing install — or one tracking `main` —
237
+ converges onto the pinned tag instead of drifting out of sync with the SDK.
238
+ - `SHA256_<platform>` — per-platform bundle hashes from the release's official
239
+ `sha256.sum`. `TODO` = not yet pinned (the installer prints the computed hash
240
+ on first download for you to pin); `NONE` = no build exists for that platform
241
+ (**macOS Intel has no 1.0.x SDK** — the installer fails with guidance there).
242
+ - `PLATFORM_<group>` — the platform-group → toolchain mapping behind the
243
+ checklist and `--platforms`.
244
+
245
+ `--env-name` / `--sdk-version` override ad-hoc without editing the file.
246
+
247
+ ## Platform-specific tools
248
+
249
+ `environment.yml` lists only packages available on conda-forge for *every*
250
+ platform (micromamba's solver ignores `# [not win]` selectors). Platform-limited
251
+ tools are added by the install scripts in a follow-up `micromamba install`:
252
+
253
+ | Tool | Source | Platforms |
254
+ | -------------------------------- | ----------------------------- | ------------------------------------------ |
255
+ | `dtc` (device tree compiler) | conda-forge via `install.sh` | linux-64, linux-aarch64, osx-64, osx-arm64 |
256
+ | `openocd` (JTAG/SWD flash+debug) | conda-forge via `install.sh` | linux-64, osx-64 only (no arm64, no win) |
257
+ | `7zip` (extract the `.7z` SDK) | conda-forge via `install.ps1` | win-64 |
258
+ | `dfu-util` (USB DFU flashing) | MSYS2 mingw64 via `install.ps1` (pinned in `versions.env`); system package manager hint on POSIX | win-64 (installed into the env); POSIX prints the install command |
259
+ | `bossac` (SAMD SAM-BA flashing) | official BOSSA MSI via `install.ps1` (pinned in `versions.env`); system package manager hint on POSIX | win-64 (installed into the env); POSIX prints the install command |
260
+
261
+ **Windows `dtc`** — conda-forge has no win-64 build and the SDK bundle ships no
262
+ standalone `dtc` binary there. This rarely blocks builds (Zephyr's Python
263
+ `edtlib` does the devicetree work); if a board needs the C `dtc`, install it via
264
+ chocolatey (`choco install dtc`) or the SDK's `setup.cmd`.
265
+
266
+ ## Troubleshooting
267
+
268
+ - **`npx --package @typecad/framework-zephyr zephyr-installer` does nothing** — fixed in alpha.11 (the
269
+ entry-point guard now follows symlinks). If on an older alpha, run
270
+ `node node_modules/@typecad/framework-zephyr/installer/install.mjs` directly.
271
+ - **`west: command not recognized` / empty `ZEPHYR_BASE`** — the env isn't
272
+ activated in *this* session. Run `micromamba activate zephyr`. Note that
273
+ `typecad-hal build` works without activation (see integration above).
274
+ - **`micromamba: command not found`** in a new shell — the installer ran
275
+ `micromamba shell init`; reload with `. $PROFILE` (PowerShell) or
276
+ `source ~/.bashrc`, or open a new terminal.
277
+ - **PowerShell: `micromamba shell hook ... | Invoke-Expression` fails** — that
278
+ pipe form parses the multi-line hook line-by-line and breaks. Use the
279
+ array-join form shown in [Activate](#activate).
280
+ - **`env: '…\envs\zephyr' exists but is not a valid conda env (no conda-meta)`**
281
+ — residue from a prior failed run. Remove it and re-run.
282
+ - **`west update` → `MalformedConfig: local configuration file not found`** —
283
+ a broken `.west/`; the installer now re-initializes it automatically (alpha.11).
284
+ - **CMake error at `FindZephyr-sdk.cmake` (`Unknown arguments specified`)** —
285
+ cmake 4.x vs Zephyr 4.3.x; the env pins `cmake<4` (alpha.11). On an env
286
+ created before that pin: `micromamba install -n zephyr 'cmake>=3.20,<4'`.
287
+ - **ESP32 build: `esptool: error: unrecognized arguments`** — missing esptool
288
+ in the env; fixed by the per-module requirements step (alpha.11). Retroactively:
289
+ `pip install -r ~/zephyrproject/modules/hal/espressif/zephyr/requirements.txt`
290
+ (with the env's python).
291
+ - **Windows C++ compile: `bits/c++config.h: No such file or directory`** —
292
+ Windows MAX_PATH (260) exceeded by a deeply nested SDK path. Keep the SDK path
293
+ short (junction a shallow path to it and point `ZEPHYR_SDK_INSTALL_DIR` at the
294
+ junction), then wipe the build dir so CMake re-configures with the new path.
295
+ - **`warning libmamba Windows version found:10.0.<build> - Not setting long
296
+ path registry key…`** — a known micromamba bug misreading modern Windows 11
297
+ builds. Cosmetic on machines with long paths enabled; check with
298
+ `(Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name LongPathsEnabled).LongPathsEnabled`.
299
+ - **Linux: flashing requires root / udev rules** — install the upstream udev
300
+ rules once (the SDK `setup.sh` that installs them is deliberately skipped);
301
+ see the [Zephyr Linux setup docs](https://docs.zephyrproject.org/latest/develop/getting_started/installation_linux.html).
302
+ - **`west update` is slow** — it clones zephyr + all manifest projects on the
303
+ first run. Subsequent runs are incremental.
304
+
305
+ ## Layout
306
+
307
+ ```
308
+ packages/framework-zephyr/installer/
309
+ install.mjs entry point: checklist, confirmations, --delete, dispatch
310
+ install.sh / install.ps1 OS-native installers (POSIX / PowerShell)
311
+ environment.yml conda-forge host tools (cross-platform base)
312
+ versions.env pinned versions, URLs, SHA256s, platform groups
313
+ lib/
314
+ detect-platform.sh uname → conda + SDK platform tokens
315
+ fetch-sdk.sh full-bundle or minimal+toolchains download/verify/extract
316
+ init-workspace.sh west init --mr <rev> + west update + Python requirements
317
+ write-activation.sh drop activate.d/deactivate.d hooks into the env
318
+ etc/conda/
319
+ activate.d/zephyr.{sh,bat,ps1} export ZEPHYR_BASE + ZEPHYR_SDK_INSTALL_DIR
320
+ deactivate.d/zephyr.{sh,bat,ps1} unset them
321
+ templates/project/ per-project auto-activation template
322
+ ```
323
+
324
+ Line endings are enforced LF for all POSIX-executed files via `.gitattributes`
325
+ (`*.sh`, `*.mjs`, `*.env`, `environment.yml`) — CRLF would break bash on Linux.
326
+
327
+ Tests live at `tests/packages/framework-zephyr/installer-tests/` (run via
328
+ the repo-root `npm test`).