# Building Plasmite
## What gets built
- Rust crate: `plasmite` (CLI, library, tests, bindings support)
- Native C dependency: vendored Lite3 sources under `vendor/lite3/`
- C shim: `c/lite3_shim.c` exports the narrow ABI used by Rust FFI
`Cargo.toml` declares `build = "build.rs"`, so Cargo always runs the build script when needed.
## Native build model (Lite3 vendoring)
`build.rs` does three things:
1. Declares `cargo:rerun-if-changed` for shim and vendored Lite3 files.
2. Compiles vendored Lite3 C units plus `c/lite3_shim.c` into one static archive (`liblite3.a`) via `cc`.
3. Leaves native-link metadata to Cargo/rustc default integration from `cc`.
Key inputs:
- `vendor/lite3/src/lite3.c`
- `vendor/lite3/src/json_dec.c`
- `vendor/lite3/src/json_enc.c`
- `vendor/lite3/src/ctx_api.c`
- `vendor/lite3/src/debug.c`
- `vendor/lite3/lib/yyjson/yyjson.c`
- `vendor/lite3/lib/nibble_base64/base64.c`
- `c/lite3_shim.c`
If these vendored files are missing or empty, link failures will surface as unresolved `lite3_*` symbols.
## Local validation gates
Run the same core gates used for CI hygiene:
```bash
cargo fmt --all
cargo clippy --all-targets -- -D warnings
cargo test
```
For full CI-parity checks in this repo, run:
```bash
just ci
```
Packaging smoke (npm pack + wheel install) is covered in CI pull requests by
the `dist-smoke` job in `.github/workflows/ci.yml`.
## Python tooling policy
Use `uv` for Python environment and package operations in this project.
- Use `uv venv`, `uv pip`, and `uv tool` for local and CI automation.
- Do not add direct `pip`-based commands to docs or release runbooks.
## Release artifact matrix
`.github/workflows/release.yml` (build stage) builds and packages binaries for:
- `x86_64-unknown-linux-gnu` (`linux_amd64`)
- `x86_64-apple-darwin` (`darwin_amd64`)
- `aarch64-apple-darwin` (`darwin_arm64`)
- `x86_64-pc-windows-msvc` (`windows_amd64` for Python and `win32-x64` for Node)
Each release tarball now follows the SDK layout contract:
```text
bin/plasmite
bin/pls
include/plasmite.h
lib/pkgconfig/plasmite.pc
```
## Source SDK build (C `libplasmite` consumers)
If you want to link a C program against `include/plasmite.h` and `libplasmite`,
build a local SDK tarball from source in release-style layout:
```bash
just sdk-from-source
```
Default output:
```text
dist/plasmite_<version>_linux_amd64.tar.gz
```
This command builds `plasmite` + `pls`, builds shared/static `libplasmite`,
packages `bin/`, `include/`, `lib/`, `lib/pkgconfig/plasmite.pc`, and runs
artifact smoke checks.
Use the SDK from your C build via `pkg-config`:
```bash
tar -xzf dist/plasmite_<version>_linux_amd64.tar.gz -C /path/to/sdk
export PKG_CONFIG_PATH=/path/to/sdk/lib/pkgconfig
pkg-config --cflags --libs plasmite
```
For static linking on Linux:
```bash
pkg-config --cflags --static --libs plasmite
```
You can override target/platform tags:
```bash
just sdk-from-source aarch64-apple-darwin darwin_arm64
```
`release.yml` uploads build artifacts only (SDK tarballs, Python dist artifacts, npm tarball, and release metadata).
`.github/workflows/release-publish.yml` (publish stage) consumes a successful build run's artifacts, runs registry preflight checks, syncs/verifies the Homebrew tap formula, publishes crates/npm/PyPI, and then creates/updates the GitHub release with SDK tarballs + `sha256sums.txt`.
Before any registry publish steps run, `release-publish.yml` updates `sandover/homebrew-tap` from build artifacts and verifies alignment (version + URLs + checksums). Live publish requires `HOMEBREW_TAP_TOKEN` so the workflow can commit/push tap updates.
For low-risk workflow validation after release workflow changes, run a no-publish rehearsal:
```bash
gh workflow run release-publish.yml -f release_tag=<vX.Y.Z> -f rehearsal=true
```
If publish fails due to registry credentials, rerun only publish without rebuilding matrix artifacts:
```bash
gh workflow run release-publish.yml -f release_tag=<vX.Y.Z> -f rehearsal=false
```
If you need to force a specific build run (for example, during incident recovery), you can still pass `build_run_id` instead of `release_tag`.
## Performance monitoring policy
- Release-blocking performance checks are local-only and run on the maintainer host with the same power/runtime conditions for baseline and candidate.
- Use:
- `bash skills/plasmite-release-manager/scripts/compare_local_benchmarks.sh --base-tag <vX.Y.Z> --runs 3`
- Multi-platform performance sweeps are optional and should be run when platform-sensitive code changes (I/O, mmap, locking, FFI/bindings), not required for every patch release.
## Linux arm64 policy
- `aarch64-unknown-linux-gnu` is currently best-effort.
- It is not a release-gating target in `release.yml` or `release-publish.yml`.
- ARM64 Linux users should build from source unless/until gated support is reintroduced.
## Windows support policy
- Windows (`x86_64-pc-windows-msvc`) is now an official release channel for:
- Python wheel delivery (`windows_amd64`)
- Node native delivery (`win32-x64`)
- These channels are built and smoke-tested in `release.yml` and published through `release-publish.yml`.
- Windows rollback-only fallback workflows have been removed; official Windows delivery is via Python/Node release channels.
## Windows troubleshooting
- **Source build fails with `cl.exe` errors (`__builtin_expect`, `__attribute__`, parsing errors in `lite3.h`)**
- Prefer official install channels (`uv tool install plasmite`, `npm i -g plasmite`) over local source builds.
- **Source build fails with Lite3 parse errors near `case` labels**
- Vendored Lite3 requires a C23-capable C compiler (it uses declarations immediately after labels).
- Install a newer compiler and retry (for example by setting `CC` explicitly), then rebuild.
- **`feed` fails with `failed to encode json as lite3`**
- Use remote refs (`http://host:port/<pool>`) so encoding occurs on the remote server.
- **Emergency fallback artifact integrity**
- PowerShell: `Get-FileHash .\\plasmite_<version>_windows_amd64_preview.zip -Algorithm SHA256`
- Compare with the accompanying `.sha256` file.