Compare commits

...

3 Commits

Author SHA1 Message Date
Julien Calixte
830701e670 docs(firmware): document light vs git build modes 2026-07-11 12:39:24 +02:00
Julien Calixte
235c7e4d24 build(firmware): add git-enabled firmware just recipes 2026-07-11 12:39:24 +02:00
Julien Calixte
4c8c557e7b feat(firmware): gate :sync publish behind the git feature
Route :sync through publish(), whose git-push path is #[cfg(feature =
"git")]. Git code in the firmware binary is now only ever compiled with
--features git, so the default build stays a light editor build with no
git2 crate and (since the justfile only sets LIBGIT2_SRC for git recipes)
no libgit2 component. Feature is off by default; :sync saves locally.
2026-07-11 12:39:24 +02:00
4 changed files with 82 additions and 16 deletions

View File

@@ -76,10 +76,15 @@ 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]
# Pulls the git2 safe API. libgit2 itself is built by the esp-idf component
# (firmware/components/libgit2/) with mbedTLS; git2/libgit2-sys are used in
# system mode (LIBGIT2_NO_VENDOR=1) purely for the Rust bindings, so we disable
# their default features to avoid dragging in openssl-sys/libssh2-sys.
# 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.
git = ["dep:git2"]
[dependencies]

View File

@@ -182,6 +182,34 @@ cargo build --release
The first build is slow (the esp-idf C sources are checked out and built
under `.embuild/`). Subsequent builds are incremental.
### Build modes — light (default) vs git
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:
| 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 |
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.
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.
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.)
## Flash (when hardware is on the bench)
`cargo run --release` triggers `espflash flash --monitor` via the runner

View File

@@ -39,6 +39,20 @@ build:
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:
{{esp_env}} {{git_env}} cargo run --release --bin firmware --features git
# serial monitor only, with decoded backtraces
monitor:
espflash monitor --elf {{elf}}

View File

@@ -99,21 +99,13 @@ fn main() -> anyhow::Result<()> {
}
// Carry out any host-side effect a `:` command asked for. The SD save is
// wired (fast, inline). The git-push half of `:sync` is not yet: it must
// run off this task on a dedicated git thread with on-demand Wi-Fi (see
// src/bin/git_sync.rs for the persistent-clone push, git_push.rs for the
// TLS trust store), which is its own integration step — for now `:sync`
// saves and logs that push is pending.
// wired (fast, inline). Publishing (`:sync` → git push) lives behind the
// `git` Cargo feature via `publish()`, so the default light build carries
// no libgit2 / git2 at all — see the note on `publish`.
match effect {
Effect::None => {}
Effect::Save => save_note(&storage, &ed),
Effect::Publish => {
save_note(&storage, &ed);
log::info!(
":sync — note saved; git push not wired yet (needs git_sync \
graduated into a module + on-demand Wi-Fi on the git thread)"
);
}
Effect::Publish => publish(&storage, &ed),
}
// Keyboard attach/detach feeds the panel's disconnect flag.
@@ -263,6 +255,33 @@ 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`.
///
/// 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.
fn publish(storage: &Storage, ed: &Editor) {
// Publishing an unsaved buffer is meaningless, so save first in both builds.
save_note(storage, ed);
#[cfg(feature = "git")]
{
// TODO(v0.1): signal the dedicated git thread here (channel, not an
// inline blocking push) once `git_sync` is graduated from its spike bin
// into a module. The feature is on but that integration hasn't landed,
// so for now this still just saves.
log::info!(":sync — saved; `git` feature ON, but the publish module isn't wired yet");
}
#[cfg(not(feature = "git"))]
{
log::info!(":sync — saved; built without the `git` feature (light build) — push skipped");
}
}
/// First and last (inclusive) framebuffer rows that differ between two frames,
/// or `None` if identical. Lets the partial refresh target just the band a
/// keystroke touched instead of all 272 rows.