Repository navigation
Build Tool
Tools/CommandPlan/controller-command.mjs is the shared board, artifact, and
Controller-command policy behind both build.mjs and the firmware studio.
The root build.cmd/build.sh and firmware.cmd/firmware.sh launchers only
bootstrap Node and forward argv unchanged, so Windows and Bash produce the
same plans, failures, canonical artifact routes, and explicit programming
method selection. None of these launchers invokes PowerShell.
The canonical Tools/Controller/toolchain-profile.json owns the FQBN, MCU,
clock, programmer baud, bootloader description, and flash/EEPROM geometry.
Its generator embeds the same policy and compile-time capacities in the Go
Controller. Build dry-runs and real execution both call the same command
builder; neither reconstructs USBasp or Urclock argv independently.
Interactive output uses Chalk-managed VT-100 color, clear emoji-labelled
stages, elapsed timing, and cli-table3 Unicode tables with centered headers
and width-aware alignment. Compact utilization gauges and visible hashes come
from validated host and firmware manifests, so the summary is an auditable
account of the exact artifacts that were built. No table border, column
padding, or ANSI sequence is assembled by an ad-hoc renderer.
Define NO_COLOR (even with an empty value) or pass --no-color for plain
logs and automation. Define FORCE_COLOR to retain VT-100 styling in a
non-interactive CI stream; NO_COLOR always wins when both are present.
The visible product label comes from
Tools/Controller/web/package.json (productName) rather than a build-script
literal. APP_TITLE may override it for one build invocation.
The default is hardware-free: the current Controller source first compiles and
validates AVR firmware, the packager stages that exact application image plus
the same validated full default EEPROM image, then it installs the exact web dependency
lock with npm ci, type-checks/tests/builds the embedded web application, and
tests, vets, resource-stamps, packages, and UPX-tests the native host. It never
selects or opens a serial/USB device.
Before the WebUI input identity is frozen, the build regenerates the canonical
256 px product mark and its seven-size ICO from the same project-owned source.
The native Windows resource and embedded browser therefore cannot silently
drift to different icons. The packaged host also applies the named APP
resource explicitly to attached classic conhost windows, so a parent build
shell or Windows icon cache cannot leave the running app with the generic
console icon.
build.cmd --dry-run
build.cmd --plan-json
build.cmd --host-only
build.cmd --firmware-only
build.cmd --toolchain-sync
build.cmd --firmware-only --toolchain-cli C:\path\to\arduino-cli.exe --toolchain-config C:\path\to\firmware-cli.yaml
build.cmd --cleanOn Bash, use the identical options with ./build.sh.
Generated outputs have one canonical location per product:
-
Tools/Controller/bin/containscontroller.exe(orcontroller), the optional C ABI library/header, dependency notices, andhost-manifest.json. - Windows output also contains
installation-package.json, whose canonical root SHA-256 binds every installable file and the validated host/resource identity used by install, repair, and uninstall. -
.build/firmware/contains Controller-validated AVR images andfirmware-manifest.json.
When a validated application/default-EEPROM pair exists, the host executable
embeds both exact Intel HEX files from the firmware manifest. The EEPROM gate
requires all 1,024 addressable bytes, and host-manifest.json records separate
enabled flags, SHA-256 values, container sizes, and EEPROM data bytes. A
host-only build reuses an existing validated firmware manifest when present;
otherwise the embedded recovery feature is disabled. It never substitutes the
compiler's empty .eep file and never grants an automatic device write.
Reusable CI cleans generated host output before downloading the same-run
firmware artifact into .build/firmware. It then builds without a second
cleanup and independently asserts that both embedded-default flags are true.
--firmware-only --clean intentionally removes only .build/firmware; it
does not touch a running canonical host in Tools/Controller/bin. A bare
--clean remains the explicit full generated-output cleanup.
After a host package passes validation, the publisher removes known stale
host output directories and loose Tools/Controller/controller[.exe]
artifacts so they cannot shadow or be mistaken for the canonical package.
The host package embeds and then verifies its version, UTC build time, and
SHA-256 source identity. That identity covers Go sources, the web package and
lockfile, web source/public assets, and the exact Vite dist bytes embedded by
Go. The host manifest records the lock-based install, web type-check/test
status, exact input/dist SHA-256 values, and copied license files for bundled
runtime npm packages (build-only dependencies are excluded). Windows packaging
also verifies
the PE resource section before UPX, runs upx -t, re-runs the packed executable
identity check, and smoke-tests PCControllerInvoke/PCControllerFree in the
generated C ABI library. The manifest records exact artifact sizes and SHA-256
hashes.
Only after every validation succeeds does the publisher atomically swap the
staged directory into the canonical bin location; a failed swap restores
the previous package.
For a repeatable identity, pass all three values explicitly:
build.cmd --version 0.5.0 --build-time 2026-08-01T16:12:58Z --build-timestamp 35019D5DPCCONTROLLER_VERSION, PCCONTROLLER_HOST_BUILD_TIME,
PCCONTROLLER_BUILD_TIMESTAMP, and SOURCE_DATE_EPOCH are also supported.
An explicit packed timestamp takes precedence for the firmware.
Programming exists only behind explicit switches and is delegated to the
canonical Controller command. Direct arduino-cli upload is disabled.
build.cmd --upload --port COM18
build.cmd --upload --method usbasp --port COM18
build.cmd --install-bootloader --method usbaspUrclock programming requires a device selector. USBasp is an advanced recovery
path selected explicitly through --method usbasp; --programmer is only an
optional backend-ID override for different ISP hardware. Controller owns
pre-flash backup, artifact validation, write/verify, and application
reauthentication. On standalone USBasp writes, --port supplies the separate
application lifecycle selector and is never sent to ISP. The advanced
--allow-incomplete-backup override is never implied.
Use --dry-run to inspect the full ordered plan without starting a
subprocess, changing a file, or opening a device. --plan-json is intended
for wrapper parity and automation tests. The firmware studio exposes the same
machine-readable boundary, for example:
firmware.cmd upload --method usbasp --plan-jsonPlan JSON includes the canonical target/FQBN, Controller path, application, complete-flash, default-EEPROM, and manifest paths. Emitting a plan never requires a device to be opened or a Controller subprocess to be started.
- Node.js 22.12 or newer must already be visible to the thin launcher. The
launcher bootstraps Chalk and
cli-table3from the reviewedTools/Build/package-lock.jsonwhen needed; host builds independently use the embedded web application's exact lock withnpm ci. - Go 1.26 or newer is required for the host and for
--firmware-only, which runs the current Controller source directly. - Firmware compile requires the Controller-supported dependency CLI/MiniCore
installation. Run
controller toolchain bootstrapon a clean machine to resolve the latest compatible profile into an exact, hash-verified local lock without replacing unrelated global tools. - A build can select that managed CLI and its adjacent profile explicitly with
--toolchain-cliand--toolchain-config. The equivalent build-only environment variables arePCCONTROLLER_TOOLCHAIN_CLIandPCCONTROLLER_TOOLCHAIN_CONFIG; command-line values take precedence. These values are forwarded through the shared Controller command plan, so compile never falls back to a different global CLI after a portable bootstrap. - Windows host packaging requires
go-winresunless--skip-resourcesis explicit, and UPX unless--no-upxis explicit. - The C ABI package requires a native target-matching C compiler unless
--no-shared-libraryis explicit. On Windows the resolver inspects both the target triple and predefined macros, rejects Cygwin/MSYS impostors, and picks the newest compatible MinGW-w64 compiler it can discover. If none exists, it installs the exact latest-resolved user-scoped toolchain fromTools/Dependencies/resolved-tools-lock.jsonthrough Windows Package Manager; the scheduled dependency resolver advances that lock to the latest stable release.--no-compiler-bootstrapchanges installation to a clear failure.HTTP_PROXY,HTTPS_PROXY, andALL_PROXYremain in the child environment, and the selected proxy is also supplied through the package manager's native proxy option without logging its value.
On Windows, the Node tool merges current process PATH with the machine and
user PATH read through reg.exe. This picks up newly installed UPX and build
tools without a PowerShell refresh. It cannot bootstrap Node itself because
Node is needed to start the orchestrator.
The root and Controller-local PowerShell build scripts were removed. The project-owned CMD/Bash workflow is the sole launcher surface and both wrappers execute this same Node plan.
node --check Tools/Build/build.mjs
node --check Tools/Build/go-tests.mjs
node --check Tools/CommandPlan/controller-command.mjs
node --test Tools/Build/build.test.mjs
node --test Tools/Firmware/firmware.test.mjs
npm --prefix Tools/Controller/web ci --no-audit --no-fund
npm --prefix Tools/Controller/web run typecheck
npm --prefix Tools/Controller/web run build
build.cmd --dry-run --no-color
bash.exe build.sh --dry-run --no-colorThe integration suite freezes identity values and asserts that both CMD/Bash launcher pairs emit byte-equivalent JSON plans, compile/program through Controller, preserve the explicit USBasp method-selection boundary, and never introduce a PowerShell or direct dependency-upload action.
Go tests are compiled to stable names under .build/tests/go/ and then run
from those project-owned paths. A content/toolchain identity reuses an existing
passing result; --retest runs the same binaries again without inventing new
temporary executable names. This keeps IPC/network test identities stable and
avoids repeated Windows Firewall prompts.
- π Getting started and operations
- πΊοΈ Repository and file map
- ποΈ Front panel and menus
- π§ Hardware initialization and tuning
- βοΈ Host configuration and integrations
- π§ Hosted front-panel menus
- π Portable WebUI
- π Protocol and network API
- π§© C library API
βοΈ Control-surface capability matrix
- ποΈ Build and packaging tool
- πΎ Firmware tool
- π₯οΈ Host Controller
- π§ͺ Virtual Board
- π¦ Dependency maintenance
- π‘οΈ Toolchain bootstrap and safe programming
- π§ Memory and feature tradeoffs
- π¦ CI/CD and releases
- π© Urboot-Custom reproducible fork
- π Audit and traceability tools
- β Project acceptance
- π Requirements backlog
- 𧬠Local-library variant comparison