A crate on top finds its own benilla-config/ through config_dir (#809)

A crate built on benilla through `run_with` has its own `benilla-config/`, but could not ask where it is: `local_state::home` is crate-private. A crate that ships an addon has to write it into that folder's `AddOns/`, where benilla discovers addons and resolves their art and fonts, so without the path it needed a fork.

- `benilla_app::config_dir()` answers `local_state::home()`, asked from `run_with` on, since a dev build resolves it from the launcher's folder set there.
- CONTRIBUTING's "Building on top" says a crate's files and addons go there, and names `run_with` and this folder as the two seams opened for crates alone.
- The example launcher logs its `AddOns/` folder through it, so the example, which clippy and the tests build, is the outside caller that keeps it public.

No 1.12.1 behaviour changes.

Fixes #807

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Sam Sung
2026-10-06 09:12:02 +07:00
committed by GitHub
co-authored by Claude Opus 5.5
parent f8493febb0
commit 85980939f5
3 changed files with 23 additions and 7 deletions
@@ -6,7 +6,8 @@
//! cargo run -p benilla-app --example extended_launcher
//! ```
//!
//! The banner reads `benilla build … · extended`, and the plugin logs one line at `Startup`.
//! The banner reads `benilla build … · extended`, and the plugin logs one line at `Startup`: the
//! `AddOns/` folder in [`benilla_app::config_dir`], where an addon the crate ships is written.
//!
//! A crate of its own copies the `benilla` launcher (`crates/benilla`): a build script that stamps
//! its commit, a `main` like this one that reads the stamp back as `crates/benilla/src/main.rs`
@@ -55,12 +56,16 @@
use benilla_app::{AppExit, BuildId};
use bevy::prelude::*;
/// The crate's own plugin: one line at `Startup`, to show it runs inside the client.
/// The crate's own plugin: one line at `Startup`, to show it runs inside the client and where its
/// addons go.
struct HelloPlugin;
impl Plugin for HelloPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, || info!("a plugin on top of benilla is running"));
app.add_systems(Startup, || {
let addons = benilla_app::config_dir().map(|dir| dir.join("AddOns"));
info!("a plugin on top of benilla is running; its addons go in {addons:?}");
});
}
}
+9
View File
@@ -215,6 +215,15 @@ pub fn run_with(build: BuildId, extend: impl FnOnce(&mut App)) -> AppExit {
launch(build, Some(Box::new(extend)))
}
/// The state folder, `benilla-config/`, where a crate on top keeps its own files: an addon it ships
/// goes in its `AddOns/`, where benilla finds addons and their art and fonts. `None` when
/// persistence is off (a capture run, or no executable path), and it may not exist yet. A dev
/// build resolves it from the launcher's folder, which [`run_with`] sets, so ask from `extend` or
/// a system, never before.
pub fn config_dir() -> Option<std::path::PathBuf> {
local_state::home()
}
/// What a crate on top of benilla adds to the built app ([`run_with`]).
type Extension<'a> = Box<dyn FnOnce(&mut App) + 'a>;
+6 -4
View File
@@ -40,11 +40,13 @@ A feature 1.12.1 does not have lives in a crate of its own that adds its Bevy pl
`benilla_app::run_with`, as `crates/benilla-app/examples/extended_launcher.rs` shows, or in a
fork. A client started through `run_with` says `extended` in its build line, so its reports read
apart from stock benilla's. The crate keeps its own settings, never rows in benilla's CVar table,
which every addon reads.
which every addon reads, and its files go under `benilla_app::config_dir()`, its own
`benilla-config/`: an addon it ships is written into that folder's `AddOns/` and loads as any
addon does.
benilla opens a piece of itself to such a crate only when its own 1.12.1 work creates that piece,
never for the crate alone, and promises no stable API: a crate pins the benilla revision it
builds on. What a crate cannot reach stays a fork's.
Past `run_with` and that folder, benilla opens a piece of itself to such a crate only when its own
1.12.1 work creates that piece, never for the crate alone, and promises no stable API: a crate
pins the benilla revision it builds on. What a crate cannot reach stays a fork's.
## How a change is judged