splicer 2.4.1

Plan and generate middleware splice operations for WebAssembly component composition graphs.
Documentation
REPO_ROOT     := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
BUILTINS_DIR  := builtins
ASSETS_DIR    := assets/builtins
ADAPTER       := $(BUILTINS_DIR)/wasi_snapshot_preview1.reactor.wasm

# Every dir under builtins/ that has both a Cargo.toml and a wit/
# directory is a builtin crate; the output goes to
# assets/builtins/<name>.wasm. Host-side helper crates (e.g.
# builtin-protocol) live alongside but lack wit/, so they're excluded.
BUILTIN_NAMES := $(patsubst $(BUILTINS_DIR)/%/wit,%,$(wildcard $(BUILTINS_DIR)/*/wit))
BUILTIN_WASMS := $(addprefix $(ASSETS_DIR)/,$(addsuffix .wasm,$(BUILTIN_NAMES)))

# wkg.toml [overrides] resolves splicer:tier1 / splicer:common from
# these dirs, so any change in here invalidates every builtin.
CANONICAL_WIT := $(wildcard wit/tier1/*.wit wit/common/*.wit)

.PHONY: build-builtins check-env clean-builtins
build-builtins: check-env $(BUILTIN_WASMS)

# Verify the toolchain is installed before invoking it. Quiet on
# success; on failure, lists every missing tool with an install hint
# and exits non-zero so the build doesn't proceed into a confusing
# downstream error.
#
# To keep the success path silent (so a no-op `make build-builtins`
# still prints "Nothing to be done"), all output goes through a single
# shell that only prints when something is wrong.
check-env:
	@missing=0; out=""; \
	for tool in cargo wkg wasm-tools; do \
	  if ! command -v $$tool >/dev/null 2>&1; then \
	    out="$$out\n  - $$tool"; \
	    case $$tool in \
	      cargo)      out="$$out (install via rustup: https://rustup.rs)" ;; \
	      wkg)        out="$$out (cargo install wkg)" ;; \
	      wasm-tools) out="$$out (cargo install wasm-tools)" ;; \
	    esac; \
	    missing=1; \
	  fi; \
	done; \
	if ! rustup target list --installed 2>/dev/null | grep -q '^wasm32-wasip1$$'; then \
	  out="$$out\n  - rustup target wasm32-wasip1 (rustup target add wasm32-wasip1)"; \
	  missing=1; \
	fi; \
	if [ $$missing -eq 1 ]; then \
	  printf 'check-env: missing required tools:%b\n' "$$out" >&2; \
	  exit 1; \
	fi

# Pattern rule — `$*` is the builtin name (e.g. `hello-tier1`).
# `.SECONDEXPANSION` lets the source list be a `find` over the crate
# dir at rule-evaluation time (so adding a new .rs/.wit file is picked
# up without editing the Makefile). wit/deps/ + target/ are excluded:
# the first is regenerated by `wkg wit fetch`, the second by cargo.
.SECONDEXPANSION:
$(ASSETS_DIR)/%.wasm: \
    $$(shell find $(BUILTINS_DIR)/$$* -type f \
        \( -name '*.rs' -o -name '*.wit' -o -name '*.toml' \) \
        -not -path '*/target/*' -not -path '*/wit/deps/*' 2>/dev/null) \
    $(CANONICAL_WIT) \
    $(ADAPTER)
	@mkdir -p $(@D)
	@echo "── Building builtin: $* ──"
	cd $(BUILTINS_DIR)/$* && wkg wit fetch
	cd $(BUILTINS_DIR)/$* && cargo build --release --target wasm32-wasip1
	wasm-tools component new \
	  $(BUILTINS_DIR)/$*/target/wasm32-wasip1/release/$(subst -,_,$*).wasm \
	  --adapt $(ADAPTER) \
	  --skip-validation \
	  -o $@
	@echo "$@"

clean-builtins:
	rm -rf $(ASSETS_DIR)
	@for d in $(BUILTINS_DIR)/*/; do \
	  [ -f "$$d/Cargo.toml" ] || continue; \
	  rm -rf "$$d/target" "$$d/wit/deps" "$$d/wkg.lock"; \
	done