A runnable mini project: .BUFA makes Nushell the project-wide shell (shell = "nu", an alias from its
[shells] catalogue — shell = "/build/nu" would work too). build/nu, build/pwsh, build/elvish, and
build/shell (prefix-dev/shell, a bash-compatible shell that runs natively on Windows) are hermetic shell
provider dirs (pinned archive → unpacked binary + BUFA.shell definition); build/powershell is a
definition-only provider for OS-installed powershell.exe. hello/ declares one virtual consumer unit per flavor:
| Shell | Example | shell setting |
What it shows |
|---|---|---|---|
| Nushell | hello/default |
inherited | one cross-platform cmd under the default |
| Nushell | hello/raw |
inherited | the file is the script; can't open with NAME=… |
| PowerShell 7 | hello/pwsh-alias |
"pwsh" (alias) |
a dir naming its shell through the catalogue |
| PowerShell 7 | hello/pwsh-path |
"/build/pwsh" (path) |
a dir naming its provider dir directly |
| Windows PowerShell | hello/powershell |
"powershell" (alias) |
OS-installed, downloads nothing; Windows only |
| Elvish | hello/elvish |
"elvish" (alias) |
--post-shell feeds the script as the rc file |
| prefix-dev/shell | hello/shell |
"shell" (alias) |
one bash-like body, native on every platform |
build/java.BUFA, build/clj/, build/go.BUFA, and build/rust.BUFA are hermetic toolchain providers, the
same shape minus the BUFA.shell: a pinned archive unpacked once (largeOutput = true) plus a BUFA.env the script
writes. A consumer lists the provider in deps.bld and finds the tools on PATH, with nothing else to declare:
| Language | Example | Provider | What it shows |
|---|---|---|---|
| Java | java/ |
build/java.BUFA |
virtual provider: one file, no dir, only a pinned archive |
| Clojure | clj/ |
build/clj/, build/java.BUFA |
two providers: BUFA.env reaches direct dependents only |
| Go | go/ |
build/go.BUFA |
deps.cacheDir: one persistent cache shared by all consumers |
| Rust | rust/ |
build/rust.BUFA |
three pins merged into one prefix; filters.bld trims output |
build/clj/also shows anexport = trueext dep (a pinned file published as is) and a[windows.filters]rule dropping a Unix-only source file.build/clj/'s cache dir holds~/.m2: the firstclj/build fetches Clojure from Maven Central.build/rustis the one provider with an ambient requirement: Rust links with the platform's own linker (Visual Studio Build Tools on Windows,ccon Linux and macOS). Sobuildallleavesrust/out unlessBUFA_TEST_EXAMPLES_REQUIREDis set, as in CI; build it withbufa rust.rust/.cargo/config.tomlpasses/Breproto MSVC'slink.exefor a reproducible binary; afilters.srcrule brings.cargo/in, since dot entries are excluded by default.- The tool-specific settings are explained in each provider's own comments.
all.BUFA and hello/all.BUFA are virtual aggregators: cmd = false plus a deps.bld list — no script, no
source, nothing published. Building one builds every dep it lists, and a cached dep costs nothing:
| Aggregator | Builds |
|---|---|
hello/all |
every hello/* shell flavor |
all |
hello/all plus java/, clj/, go/ and rust/ |
hello/alllistshello/powershellunder[windows]: that unit has a[windows]cmd alone, and a dep with no command on the platform fails the build. Platformdeps.bldentries append to the root list.alltakesrust/unconditionally, so it needs the platform's linker — unlikebuildall, which leavesrust/out by default.
deploy/ holds one virtual task per shell (task = ["out", "*rest"], see 'task'): a
deploy step that runs on every invocation, publishes nothing, and takes its destination from the command line. The
tokens after a task's dir are its arguments, handed to the script as plain environment variables:
bufa deploy/nu C:\Drop builds hello/default (cached as usual) and copies its hello.txt into C:\Drop; anything
after the path lands space-joined in rest, which is absent when there is nothing.
| Shell | Example | Reads |
|---|---|---|
| Nushell | deploy/nu |
$env.out, $env.rest? |
| PowerShell 7 | deploy/pwsh |
$env:out, $env:rest |
| Elvish | deploy/elvish |
$E:out, has-env rest |
- A task is the only dir on its command line: every token after it is an argument, never another dir.
- Pass an absolute
out: the script's cwd is its sandbox, not yours, and a relative path would land there. - A token starting with
-is a bufa flag. To hand one to the task, put the whole dir list after--:bufa -o -- deploy/nu C:\Drop --dry-run. bufa deploy/nuwith no token takesoutfrom your environment instead, and fails when it is unset there too.
Run everything from Examples/. Build outputs land in the sibling Examples.BUFA/ store (git-ignored).
bufa hello/default # downloads + unpacks nu once, then runs the cmd under it
bufa hello/pwsh-alias # same with PowerShell 7
bufa hello/powershell # uses OS-installed powershell.exe; downloads nothing
bufa hello/elvish # same with Elvish
bufa hello/shell # same with prefix-dev/shell (a conda package: zip → zstd tarball; see below)
bufa java # downloads + unpacks the JDK once, then javac + java under nu
bufa go # same with the Go distribution: go build, then the binary
bufa clj # same with the Clojure CLI, on the same JDK; first run fetches Clojure from Maven
bufa rust # same with rustc + cargo: cargo build, then the binary; needs a linker installed
bufa deploy/nu C:\Drop # a task: builds hello/default, copies its hello.txt to C:\Drop; runs every time
bufa deploy/pwsh C:\Drop v2 final # same under PowerShell 7, with "v2 final" in $env:restbufa hello/all # every hello/* unit, in one invocation
bufa all # the same plus java, clj, go, and rust; needs a linker installedbuildall.cmd # every hello/* unit plus java, go, and clj (Windows)
bash buildall.sh # same on Linux and macOS
nu buildall.nu # same on any platform, if you have Nushell installed
elvish buildall.elv # same on any platform, if you have Elvish installedbufa --shell hello/default # an interactive nu session in its build environment
bufa --shell java # same, with the JDK on PATHEvery provider pins its archives per platform — Windows x64, Linux x64, macOS arm64 — as
[[windows.deps.ext]]/[[linux.deps.ext]]/[[macos.deps.ext]] entries, while Linux and macOS share one [unix]
script. Where the platforms differ, a [linux.env]/[macos.env] value carries the difference into that shared
script: the conda build string in build/shell, the macOS app-bundle Contents/Home in build/java.
build/shell shows a tool pinned only to unpack another: a conda package is a zip of zstd tarballs, which Windows'
native tar opens but no stock Linux or macOS tool does. So on Unix the dir pins a second artifact — the static
micromamba binary — and its script runs micromamba package extract. Neither artifact is published: only the
shell and its BUFA.shell are.