Skip to content

CLI: build the embedded components from source in build.rs - #92

Merged
lann merged 1 commit into
mainfrom
embedded-components-buildrs
Aug 12, 2026
Merged

CLI: build the embedded components from source in build.rs#92
lann merged 1 commit into
mainfrom
embedded-components-buildrs

Conversation

@lannbot

@lannbot lannbot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Closes #88 — by construction rather than by gating: the compose-runner/run defaults (runner-cli + provider) are now built from their sources by the CLI's build.rs at compile time. Staleness is impossible, verify-cli becomes a pure behavior gate, and the unreviewable binary blobs (plus embed-update and the .gitignore negation) leave the repo.

Mechanics

  • Nested cargo, separate target dir under OUT_DIR (sharing the outer target dir deadlocks on cargo's build-dir lock); the inner graph is small and cargo's own fingerprinting caches it.
  • Broad rerun-if-changed (components/, crates/, wit/, root manifests): over-firing costs a ~0.1s inner no-op; a curated file list would silently go stale as the dependency closure grows — the exact failure mode this PR deletes.
  • Curated environment: host-targeted RUSTFLAGS/RUSTC and cargo bookkeeping scrubbed; CARGO_HOME + network/registry knobs kept (offline/vendored setups); RUSTC_WRAPPER kept (sccache).
  • --locked --profile embed: workspace lockfile governs the inner graph; components ship size-optimized regardless of outer profile.
  • New default feature embedded-components; --no-default-features = host-only CLI (no wasm target needed), compose-runner/run error naming the missing flag. actions/aggregate's fallback install uses it — reporting-only consumers keep working on runners without wasm32-wasip2.

Measured

path time
cold CLI build 15.8s
no-op rebuild 0.08s
CLI-edit rebuild 5.0s
runner-cli-edit rebuild (inner wasm + relink) 9.3s
cargo install --locked --git (default features) 47.6s vs 47.7s committed-blob baseline — zero delta
slim install (--no-default-features) 45.9s

The inner wasm graph builds entirely in the shadow of the wasmtime compile. Installed binaries reproduce expected/verify-compose-sample.jsonl byte-for-byte; wizen works from the installed bin; the slim build's error UX verified.

Notes

  • bindeps (cargo artifact-dependencies) is the principled replacement once stable; build.rs is the stable-Rust approximation and says so.
  • crates.io publication would need vendor-at-package or fetch-prebuilt layered on the same seam; consumption is git-pinned-only today (CLI: pins — one-rev-everywhere gate for downstream pin trios #54), unchanged.
  • Review (independent): non-blocking verdict; its three advisories (stale profile comment, env-scrub doc line, copy-loop shape) are folded in.

Verified: just check, just all, just test-wasm, clippy under both feature sets, three real cargo install shapes from a file:// clone. The actions-setup-smoke job on this PR exercises the --path install route with build.rs live.

The compose-runner/run defaults (runner-cli + provider) were committed
size-optimized artifacts, refreshed by hand (`just embed-update`) and
freshness-gated only through sample-suite-visible behavior — #88's
gap. Now the CLI's build.rs builds them from their sources at compile
time, so staleness is impossible by construction: verify-cli becomes a
pure behavior gate, and the unreviewable binary blobs leave the repo.

Mechanics (each documented in build.rs): nested cargo into a target
dir under OUT_DIR (sharing the outer target dir would deadlock on
cargo's build-dir lock; cargo's own fingerprinting caches the inner
graph there), broad rerun-if-changed over components//crates//wit/
(over-firing costs a ~0.1s inner no-op, while a curated file list
would silently go stale when the dependency closure grows — the
failure mode this exists to delete), a curated environment (the outer
build's host-targeted RUSTFLAGS/RUSTC and cargo bookkeeping must not
leak into the wasm build; CARGO_HOME and network/registry knobs
survive for offline and vendored setups; RUSTC_WRAPPER survives for
sccache), and --locked --profile embed (workspace lockfile governs the
inner graph; components ship size-optimized regardless of the outer
profile).

New default feature `embedded-components`: --no-default-features
yields a host-only CLI needing no wasm target — compose-runner/run
then require explicit --runner/--provider with an error naming the
cause. The aggregate action's fallback install uses it (aggregation
never composes), so reporting-only consumers keep working on runners
without wasm32-wasip2. Everything else installing the CLI (setup
action, _ct-tools) runs in repos that build suites, where the target
is already present.

Measured (17-core linux): cold CLI build 15.8s; no-op rebuild 0.08s;
CLI-edit rebuild 5.0s; runner-cli-edit rebuild 9.3s (inner wasm
rebuild + relink). cargo install --locked --git: 47.6s vs 47.7s at
the committed-blob baseline — zero delta, the inner wasm graph builds
entirely in the shadow of the wasmtime compile. Installed binaries
reproduce expected/verify-compose-sample.jsonl byte-for-byte and
wizen works; slim install 45.9s with the documented error UX.

When cargo's artifact-dependencies (bindeps) stabilize, build.rs
becomes two [build-dependencies] entries; this is the stable-Rust
approximation. Publishing to crates.io would need vendoring or
fetching prebuilt artifacts at package time — consumption is
git-pinned-only today (#54), unchanged.

Verified: just check, just all, just test-wasm; clippy under both
feature sets; the three install shapes above from a file:// clone.
@lann
lann enabled auto-merge August 12, 2026 14:26
@lann
lann merged commit 11f9150 into main Aug 12, 2026
3 checks passed
@lann
lann deleted the embedded-components-buildrs branch August 12, 2026 14:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Embedded CLI components: freshness gate only sees sample-suite-visible behavior

2 participants