Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/znippy-zoomies

xtask/src/main.rs

//! **znippy-zoomies' ONE build path** — `cargo xtask build --suite ORIGINAL
//! [--atom <a>]`.
//!
//! The entire body of the verb is
//! [`nornir_build_thing::suite_cli::run`](nornir_build_thing::suite_cli::run). This
//! file names no package, no bin, no feature string and no profile: everything it
//! builds comes from `.nornir/build-variants.toml`, so the declaration and the build
//! cannot drift apart the way `holger-build` (three hardcoded tiers, blind to the
//! other ten variants on disk) and `dwarves/src/service.rs` (a hand-written
//! `--features embed-nornir,server` against a declaration saying `embed-all,read-fat`)
//! did.
//!
//! ## What was here before: nothing
//!
//! Measured 2026-08-03: znippy-zoomies had **no xtask at all** and **no
//! `.nornir/build-variants.toml`**, while shipping five real CLI binaries
//! (`osm-katana`, `lbunzip2`, `lgz`, `ljar`, `lzip`). They were built by hand cargo,
//! spelled differently in whichever `.nornir/*.md` last mentioned them, and
//! `dwarves buildthing znippy-zoomies` had no delivery to ask for. Prose that names
//! a cargo invocation IS a declaration; the fix is one verb that reads the real one.
//!
//! ## Invoking it
//!
//! This crate is SELF-ROOTING (its own `[workspace]`), so `-p xtask` cannot see it
//! from the repo root and the `.cargo/config.toml` alias uses `--manifest-path`:
//!
//! ```text
//! cargo xtask build --suite ORIGINAL --list      # resolve + print, build nothing
//! cargo xtask build --suite ORIGINAL             # build all five atoms
//! cargo xtask build --suite ORIGINAL --atom lgz  # build one
//! ```
//!
//! ## The gate: `cargo xtask buildgate`
//!
//! The build verb above builds what the declaration names. It cannot tell you about a
//! bin the declaration FORGOT — and MEASURED at `49c7bc6` this repo has the sharpest
//! case of that in the constellation: the root manifest is a `[package]` **and** a
//! `[workspace]` with no `default-members`, so cargo selects the root package alone,
//! the root package declares no bins, and a bare `cargo build --bins` at the repo root
//! builds **0 of 11** bin targets and exits 0.
//!
//! `cargo xtask buildgate` compiles every declared atom at its own features and goes
//! red *with the numbers*: bins declared vs bins actually built, and every
//! `tests/*.rs` that compiled to a binary holding zero tests. Its whole body is
//! [`nornir_build_thing::buildgate::cli::run`], shared with korp and facett.
//!
//! ```text
//! cargo xtask buildgate --list                    # the numbers, compiling nothing
//! cargo xtask buildgate                           # both arms, every atom
//! cargo xtask buildgate --atom lgz --arms bins    # one atom while iterating
//! ```

use std::path::{Path, PathBuf};

use anyhow::{bail, Result};
use nornir_build_thing::suite_cli;

/// The repo root — the parent of this crate's directory.
///
/// Taken from `CARGO_MANIFEST_DIR` rather than the current directory so the verb
/// resolves the same declaration whether it is invoked through the `cargo xtask`
/// alias from the repo root or by path from anywhere else. A build verb that reads a
/// different file depending on where you stood is a second declaration again.
fn repo_root() -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR"))
        .parent()
        .expect("xtask/ always has a parent")
        .to_path_buf()
}

fn main() -> Result<()> {
    let argv: Vec<String> = std::env::args().skip(1).collect();
    match argv.first().map(String::as_str) {
        Some("build") => {
            let args = suite_cli::parse(&argv[1..])?;
            let built = suite_cli::run(&repo_root(), &args)?;
            if !args.list {
                eprintln!("built: {}", built.join(", "));
            }
            Ok(())
        }
        // `cargo xtask buildgate` — THE build gate. Three lines here on purpose: the
        // whole verb is `nornir_build_thing::buildgate::cli::run`, shared verbatim
        // with korp and facett, so the gate cannot drift between the three repos that
        // needed it (LAW 5).
        Some("buildgate") => {
            std::process::exit(nornir_build_thing::buildgate::cli::run(&repo_root(), &argv[1..]));
        }
        Some(other) => bail!("unknown verb '{other}'\n\n{}", suite_cli::USAGE),
        None => bail!("{}", suite_cli::USAGE),
    }
}