diff --git a/firmware/Cargo.toml b/firmware/Cargo.toml index eef300d..0a30651 100644 --- a/firmware/Cargo.toml +++ b/firmware/Cargo.toml @@ -76,15 +76,16 @@ esp-idf-hal = { git = "https://github.com/esp-rs/esp-idf-hal.git" } esp-idf-svc = { git = "https://github.com/esp-rs/esp-idf-svc.git" } [features] -# OFF by default so the nominal `just build`/`just flash` is a LIGHT editor -# build. Enabling it (a) pulls the git2 safe API and (b) gates on the firmware's -# `:sync` publish path in main.rs (see `publish()`), so git code is only ever -# compiled with `--features git`. libgit2 itself is built by the esp-idf -# component (firmware/components/libgit2/) with mbedTLS — but ONLY when the -# justfile also sets LIBGIT2_SRC (the git recipes do; the light recipes don't, -# so the component is an empty no-op). git2/libgit2-sys run in system mode -# (LIBGIT2_NO_VENDOR=1) purely for the Rust bindings, with default features off -# to avoid dragging in openssl-sys/libssh2-sys. +# A Cargo feature, OFF by default — so a bare `cargo build` (and `just +# build-light`) is a LIGHT editor build. The justfile's nominal `build`/`flash` +# opt in via `--features git`. Enabling it (a) pulls the git2 safe API and (b) +# turns on the `#[cfg(feature = "git")]` publish path in main.rs (see +# `publish()`), so git code is only ever compiled with `--features git`. libgit2 +# itself is built by the esp-idf component (firmware/components/libgit2/) with +# mbedTLS — but ONLY when the justfile also sets LIBGIT2_SRC (the full recipes +# do; `build-light` doesn't, so the component is an empty no-op). git2/libgit2-sys +# run in system mode (LIBGIT2_NO_VENDOR=1) purely for the Rust bindings, with +# default features off to avoid dragging in openssl-sys/libssh2-sys. git = ["dep:git2"] [dependencies] diff --git a/firmware/README.md b/firmware/README.md index d5f5a56..6684e10 100644 --- a/firmware/README.md +++ b/firmware/README.md @@ -61,8 +61,8 @@ need `CONFIG_SPIRAM` turned on first. Credentials are build-time: copy [`.env.example`](.env.example) to `.env`, set `TW_WIFI_SSID` / `TW_WIFI_PASS`, and `just` loads them (dotenv) so `build.rs` -bakes them in. `.env` is gitignored; the editor build (`just flash`) needs none -of it. `sdkconfig.defaults` gains the full certificate bundle and a bigger main +bakes them in. `.env` is gitignored; the light editor build (`just flash-light`) +needs none of it. `sdkconfig.defaults` gains the full certificate bundle and a bigger main task stack for the mbedtls handshake — a one-time esp-idf reconfigure on the next build. @@ -173,42 +173,48 @@ the Xtensa GCC to `PATH`): . ~/export-esp.sh ``` -Then from this directory: +Then from this directory, `just build` (the nominal product build) or, for fast +iteration without git, `just build-light`: ```sh -cargo build --release +just build # full: firmware + git publishing (libgit2 + git2) +just build-light # light: editor only, no git — much faster ``` +(A bare `cargo build --release` with no env is equivalent to `build-light` — the +`git` feature is off by default.) + The first build is slow (the esp-idf C sources are checked out and built -under `.embuild/`). Subsequent builds are incremental. +under `.embuild/`; the full build also compiles libgit2 + mbedTLS). Subsequent +builds are incremental. -### Build modes — light (default) vs git +### Build modes — git (default) vs light -The editor firmware builds **light by default** — no git. Publishing (`:sync` → -git push) is expensive to build: it drags in libgit2 + mbedTLS (compiled as an -esp-idf component) and the `git2` crate. So it sits behind a switch, and the -nominal build leaves it off — ideal for iterating on the editor, EPD, USB, or -SD without paying for libgit2: +Publishing (`:sync` → git push) is expensive to build: it drags in libgit2 + +mbedTLS (compiled as an esp-idf component) and the `git2` crate. It sits behind +a switch. The nominal build turns it on (it's the product); a **light** build +leaves it off — ideal for iterating on the editor, EPD, USB, or SD without +paying for libgit2: | Build | Command | libgit2 component | `git2` crate | `:sync` | | ----- | ------- | ----------------- | ------------ | ------- | -| **Light** (default) | `just build` / `just flash` | not compiled (empty no-op) | not linked | saves locally, skips push | -| **Full (git)** | `just build-firmware-git` / `just flash-firmware-git` | compiled | linked | save → push | +| **Full / git** (default) | `just build` / `just flash` | compiled | linked | save → push | +| **Light** | `just build-light` / `just flash-light` | not compiled (empty no-op) | not linked | saves locally, skips push | Two independent switches make this work, and the justfile flips them together: 1. **`git` Cargo feature** (`--features git`) — pulls the `git2` crate and turns on the `#[cfg(feature = "git")]` publish path in - [`src/main.rs`](src/main.rs) (`publish()`). Off by default. + [`src/main.rs`](src/main.rs) (`publish()`). Off by default; the full recipes + pass it. 2. **`LIBGIT2_SRC` env** — the [libgit2 component](components/libgit2/CMakeLists.txt) only compiles its sources when this points at the vendored tree; unset, it - registers an *empty* component. Only the `*-git` justfile recipes set it. + registers an *empty* component. Only the full recipes set it. Because git code in the firmware binary is only ever compiled under -`--features git`, an ordinary `just build` can never accidentally drag libgit2 -in. (Git isn't wired into `main.rs` yet, so `flash-firmware-git` currently just -builds slower and behaves like the light build — the seam is in place ahead of -the integration.) +`--features git`, `just build-light` can never drag libgit2 in. (Git isn't wired +into `main.rs` yet, so the full `just build` currently just builds slower and +behaves like the light build — the seam is in place ahead of the integration.) ## Flash (when hardware is on the bench) diff --git a/firmware/src/main.rs b/firmware/src/main.rs index 8c12beb..432a5a1 100644 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -256,14 +256,15 @@ fn save_note(storage: &Storage, ed: &Editor) { } /// `:sync` — persist, then publish. Publishing (git push) is gated behind the -/// `git` Cargo feature so the default build stays a **light editor build**: no -/// `git2` crate and, because the justfile only sets `LIBGIT2_SRC` for git -/// recipes, no libgit2/mbedTLS component either (`just build`/`just flash`). -/// A full build turns both on together: `just flash-firmware-git`. +/// `git` Cargo feature. The nominal build (`just build`/`just flash`) turns it +/// on (libgit2 + git2). A **light** build (`just build-light`/`just flash-light`) +/// leaves it off — no `git2` crate and, since the justfile only sets +/// `LIBGIT2_SRC` for the full recipes, no libgit2/mbedTLS component either — so +/// `:sync` just saves locally. /// -/// This is the seam that keeps the light build light — the git-only code path -/// is only ever compiled under `--features git`, so an ordinary `:sync` in the -/// light build simply saves locally. +/// This `#[cfg]` is the seam that keeps the light build light: the git-only code +/// path is only ever compiled under `--features git`, so wiring publish in later +/// can never drag libgit2 into a light build. fn publish(storage: &Storage, ed: &Editor) { // Publishing an unsaved buffer is meaningless, so save first in both builds. save_note(storage, ed);