Compare commits

...

2 Commits

Author SHA1 Message Date
Julien Calixte
ee00fecdc8 docs(firmware): flip build-mode docs to git-default 2026-07-11 12:47:57 +02:00
Julien Calixte
9101d61045 build(firmware): default to the git build, add build-light
Make `just build`/`just flash` the nominal product build (--features git
+ LIBGIT2_SRC), and move the fast editor-only build to `build-light`/
`flash-light`. Verified the git default links libgit2 into the firmware
ELF (1.2 MB) cleanly.
2026-07-11 12:47:57 +02:00
4 changed files with 58 additions and 52 deletions

View File

@@ -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]

View File

@@ -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)

View File

@@ -31,28 +31,26 @@ git_env := "LIBGIT2_SRC=" + libgit2_src + " LIBGIT2_NO_VENDOR=1 PKG_CONFIG_ALLOW
default:
@just --list
# compile (release)
# compile (release) — the nominal product build: full firmware WITH git
# publishing (compiles libgit2 + mbedTLS, links git2). For fast iteration on the
# editor / EPD / USB / SD without paying for libgit2, use `build-light`.
build:
{{esp_env}} cargo build --release --bin firmware
# build + flash + open serial monitor
flash:
{{esp_env}} cargo run --release --bin firmware
# Full editor firmware WITH git publishing — the HEAVY build: compiles libgit2 +
# mbedTLS and links git2. The `build`/`flash` recipes above stay light (no
# libgit2 component — LIBGIT2_SRC unset — and no git2 crate, `git` feature off),
# so use those for iterating on the editor / EPD / USB / SD. Only reach for this
# to exercise `:sync`'s push. Bakes the TW_* creds into flash like the git
# spikes (ADR-005: not for a shipping image). NB: git isn't wired into main.rs
# yet, so today this just builds slower and behaves like the light build.
build-firmware-git:
{{esp_env}} {{git_env}} cargo build --release --bin firmware --features git
# Full firmware — build + flash + monitor (see build-firmware-git).
flash-firmware-git:
# build + flash + open serial monitor (full firmware, see `build`)
flash:
{{esp_env}} {{git_env}} cargo run --release --bin firmware --features git
# LIGHT editor build — no git: no libgit2 component (LIBGIT2_SRC unset) and no
# git2 crate (`git` feature off), so it builds much faster. `:sync` saves locally
# and skips the push. Use for anything but exercising publish.
build-light:
{{esp_env}} cargo build --release --bin firmware
# light build + flash + open serial monitor (see `build-light`)
flash-light:
{{esp_env}} cargo run --release --bin firmware
# serial monitor only, with decoded backtraces
monitor:
espflash monitor --elf {{elf}}

View File

@@ -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);