crate2nix (IFD) experiment
A comparison experiment to the crane-based `your-first-flake` branch: builds
bombadil with **crate2nix in IFD mode** (`generatedCargoNix`) — **per-crate
derivations, no committed `Cargo.nix`**.
## What it shows
- **Finest-grained caching.** One derivation per crate: editing one workspace
crate rebuilds only that crate and its dependents, never the ~377 external
dependency crates.
- **The cost for this repo.** It needs a patch to crate2nix itself
(`nix/crate2nix-git-workspace.patch`) so that `boa_engine` — a git dependency
that is a member of the boa monorepo's workspace — vendors with a
self-contained, de-inherited manifest. Without it, generation fails with
`failed to find a workspace root`. Plus a `bombadil-cli` build-script override
for the workspace-relative inspect path, and IFD at eval time.
## crane vs crate2nix
| | crane (`your-first-flake`) | crate2nix (this branch) |
| --- | --- | --- |
| Dependency caching | one shared derivation; source edits never rebuild it | one derivation **per crate** |
| Committed generated file | none | none (IFD) |
| IFD | no | **yes** |
| git workspace-member deps (boa_engine) | handled natively by cargo | needs the patch here |
| Custom build.rs (ghostty, inspect) | handled in the build derivation | needs per-crate overrides |
For bombadil, crane is the lower-maintenance choice; this branch shows the
trade-off concretely.
## Verify per-crate caching yourself
Records the external dependency-crate derivations in the build closure of the
default package, edits a real workspace `.rs` file, and asserts they are all
byte-for-byte identical afterwards (only the edited crate and its dependents
change). Reverts the edit afterwards.
```bash
#!/usr/bin/env bash
set -euo pipefail
cd "$(git rev-parse --show-toplevel)"
ATTR='.#default'
VICTIM='lib/bombadil/src/lib.rs'
external_crate_drvs() {
nix-store --query --requisites "$(nix eval --raw "${ATTR}.drvPath")" \
| grep -E '\.drv$' | grep -E -- '-rust_' \
| grep -vE -- '-rust_(bombadil|small-string)' | sort
}
before="$(external_crate_drvs)"
echo "external dependency-crate derivations: $(echo "${before}" | wc -l)"
cleanup() { git checkout -- "${VICTIM}" 2>/dev/null || true; }
trap cleanup EXIT
printf '\n// experiment: rebuilds only this crate, not the deps.\npub fn _marker() {}\n' >>"${VICTIM}"
git --no-pager diff --stat -- "${VICTIM}"
after="$(external_crate_drvs)"
[ "${before}" = "${after}" ] && echo "PASS — no external dependency-crate rebuilds." || { echo "FAIL"; diff <(echo "${before}") <(echo "${after}"); exit 1; }
```
## CI
Passing on NixCI (production):
https://nix-ci.com/gh:NorfairKing:bombadil/crate2nix-experiment