nandi/frqpublic Fork 0
76dcc6c
Commits
Clone
git clone https://git.rickub.com/nandi/frq.git
git clone ssh://git@rickub.com/nandi/frq.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Inline the babashka scripts into the justfile

scripts/ was six files and a bootstrap to find a babashka, wrapping what
is four shell recipes: re-enter the dev shell, hand jolt its deps
overrides and a library path, and for the APK ask nix for a store path
and give it to adb. The recipes re-exec 'just <recipe>' inside the shell
rather than themselves, so there is one code path either way.

paths/nix survives as the 'nix' variable -- reaching a nix that lives in
a container is the one thing the indirection was buying. The flake loses
its .#bb output and babashka from the dev shell; both existed only for
scripts/bb.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandi committed 2026-09-07T22:32:03-07:00 Browse files
76dcc6c parent: 4f38d68
modified README.md +4 -4
@@ -40,10 +40,10 @@ The app:
4040 just run
4141 ```
4242
43-The scripts under `scripts/` are babashka, reached through `scripts/bb`: a bb
44-on `PATH` if there is one — the dev shell puts one there — and otherwise the
45-flake's `.#bb`, built once and kept under `build/`. Nothing has to be installed
46-for that but Nix.
43+Every recipe lives in the `justfile` itself. Each one that runs frq re-enters
44+`nix develop` and comes back to the same recipe, so `just run` and
45+`nix develop --command just run` are one code path rather than two. Nothing has
46+to be installed for that but Nix.
4747
4848 `just run` is `jolt -M:frq` inside `nix develop`, with `LD_LIBRARY_PATH`
4949 pointed at the shell's `JOLT_NATIVE_LIB` — the flake's build of
@@ -40,10 +40,10 @@ The app:
40 just run40 just run
41 ```41 ```
42 42
43-The scripts under `scripts/` are babashka, reached through `scripts/bb`: a bb43+Every recipe lives in the `justfile` itself. Each one that runs frq re-enters
44-on `PATH` if there is one — the dev shell puts one there — and otherwise the44+`nix develop` and comes back to the same recipe, so `just run` and
45-flake's `.#bb`, built once and kept under `build/`. Nothing has to be installed45+`nix develop --command just run` are one code path rather than two. Nothing has
46-for that but Nix.46+to be installed for that but Nix.
47 47
48 `just run` is `jolt -M:frq` inside `nix develop`, with `LD_LIBRARY_PATH`48 `just run` is `jolt -M:frq` inside `nix develop`, with `LD_LIBRARY_PATH`
49 pointed at the shell's `JOLT_NATIVE_LIB` — the flake's build of49 pointed at the shell's `JOLT_NATIVE_LIB` — the flake's build of
modified flake.nix +9 -17
@@ -339,12 +339,6 @@
339339 jolt = joltRuntime;
340340 default = frq;
341341
342- # The interpreter scripts/ is written in, named here so that
343- # scripts/bb can build it. Nothing else in this flake uses it: it is
344- # an output because a shell script cannot ask for `nixpkgs#babashka`
345- # at the version this tree pins, and `.#bb` is exactly that.
346- bb = pkgs.babashka;
347-
348342 # frq and everything it loads, squashed into one runnable file for
349343 # hosts without Nix. The whole closure rides along — Mesa included,
350344 # which is not waste: off NixOS the launcher goes through nixGL, and
@@ -380,7 +374,7 @@
380374 # this shell hands a builder are the same derivation.
381375 #
382376 # Nothing here says "nixbuild", though: it is a plain derivation, and
383- # where it gets built is the machine's business. scripts/run.bb asks for
377+ # where it gets built is the machine's business. The `run` recipe asks for
384378 # the shell with --max-jobs 0, which is what sends it to the `builders`
385379 # entry rather than compiling egui on a laptop.
386380 devShells = forEachSystem (pkgs:
@@ -394,17 +388,15 @@
394388
395389 # jolt, because the runtime frq is run by should be the flake's
396390 # too. nixGL for the same reason the launcher reaches for it — see
397- # frqScript. babashka because scripts/bb prefers one on PATH, and
398- # inside here that should be this one rather than a second copy
399- # built through `.#bb`. just so the recipe runner comes from here
400- # too rather than the host — `nix develop` and then `just run` is
401- # the whole of what a machine with nix needs.
402- packages = [ jolt pkgs.babashka pkgs.just (nixGLFor pkgs) ];
403-
404- # Read by scripts/run.bb rather than baked into a wrapper: the frq
391+ # frqScript. just so the recipe runner comes from here too rather
392+ # than the host — `nix develop` and then `just run` is the whole of
393+ # what a machine with nix needs.
394+ packages = [ jolt pkgs.just (nixGLFor pkgs) ];
395+
396+ # Read by the recipes rather than baked into a wrapper: the frq
405397 # source `just run` runs is the working tree, so the launcher has
406- # to be a script in that tree and the shell has to hand it its
407- # answers. Naming these is also what makes the shell build them.
398+ # to live in that tree and the shell has to hand it its answers.
399+ # Naming these is also what makes the shell build them.
408400 JOLT_NATIVE_LIB = "${native}/lib";
409401 GLIMMER_SRC = glimmer;
410402 GLIMMER_VIDYA_SRC = "${jolt-native}/glimmer-backends/glimmer-vidya";
@@ -339,12 +339,6 @@
339 jolt = joltRuntime;339 jolt = joltRuntime;
340 default = frq;340 default = frq;
341 341
342- # The interpreter scripts/ is written in, named here so that
343- # scripts/bb can build it. Nothing else in this flake uses it: it is
344- # an output because a shell script cannot ask for `nixpkgs#babashka`
345- # at the version this tree pins, and `.#bb` is exactly that.
346- bb = pkgs.babashka;
347-
348 # frq and everything it loads, squashed into one runnable file for342 # frq and everything it loads, squashed into one runnable file for
349 # hosts without Nix. The whole closure rides along — Mesa included,343 # hosts without Nix. The whole closure rides along — Mesa included,
350 # which is not waste: off NixOS the launcher goes through nixGL, and344 # which is not waste: off NixOS the launcher goes through nixGL, and
@@ -380,7 +374,7 @@
380 # this shell hands a builder are the same derivation.374 # this shell hands a builder are the same derivation.
381 #375 #
382 # Nothing here says "nixbuild", though: it is a plain derivation, and376 # Nothing here says "nixbuild", though: it is a plain derivation, and
383- # where it gets built is the machine's business. scripts/run.bb asks for377+ # where it gets built is the machine's business. The `run` recipe asks for
384 # the shell with --max-jobs 0, which is what sends it to the `builders`378 # the shell with --max-jobs 0, which is what sends it to the `builders`
385 # entry rather than compiling egui on a laptop.379 # entry rather than compiling egui on a laptop.
386 devShells = forEachSystem (pkgs:380 devShells = forEachSystem (pkgs:
@@ -394,17 +388,15 @@
394 388
395 # jolt, because the runtime frq is run by should be the flake's389 # jolt, because the runtime frq is run by should be the flake's
396 # too. nixGL for the same reason the launcher reaches for it — see390 # too. nixGL for the same reason the launcher reaches for it — see
397- # frqScript. babashka because scripts/bb prefers one on PATH, and391+ # frqScript. just so the recipe runner comes from here too rather
398- # inside here that should be this one rather than a second copy392+ # than the host — `nix develop` and then `just run` is the whole of
399- # built through `.#bb`. just so the recipe runner comes from here393+ # what a machine with nix needs.
400- # too rather than the host — `nix develop` and then `just run` is394+ packages = [ jolt pkgs.just (nixGLFor pkgs) ];
401- # the whole of what a machine with nix needs.395+
402- packages = [ jolt pkgs.babashka pkgs.just (nixGLFor pkgs) ];396+ # Read by the recipes rather than baked into a wrapper: the frq
403-
404- # Read by scripts/run.bb rather than baked into a wrapper: the frq
405 # source `just run` runs is the working tree, so the launcher has397 # source `just run` runs is the working tree, so the launcher has
406- # to be a script in that tree and the shell has to hand it its398+ # to live in that tree and the shell has to hand it its answers.
407- # answers. Naming these is also what makes the shell build them.399+ # Naming these is also what makes the shell build them.
408 JOLT_NATIVE_LIB = "${native}/lib";400 JOLT_NATIVE_LIB = "${native}/lib";
409 GLIMMER_SRC = glimmer;401 GLIMMER_SRC = glimmer;
410 GLIMMER_VIDYA_SRC = "${jolt-native}/glimmer-backends/glimmer-vidya";402 GLIMMER_VIDYA_SRC = "${jolt-native}/glimmer-backends/glimmer-vidya";
modified justfile +161 -8
@@ -1,25 +1,178 @@
1-# Every recipe here is one line, because the work is in scripts/ — babashka
2-# scripts, run through scripts/bb, which finds a bb the way this tree finds
3-# everything else. A recipe body is a shell script nobody can run on its own;
4-# a script in scripts/ is a script.
1+# The work is here now, in recipe bodies, where it used to be in scripts/ —
2+# babashka scripts run through a scripts/bb that went looking for a babashka.
3+# That indirection bought one thing worth having, a shared way to reach nix on
4+# a host that keeps it in a container, and `nix` below is the whole of it.
5+#
6+# Every recipe that runs frq has the same shape: outside the dev shell, re-enter
7+# it and come back to this same recipe; inside, hand jolt the deps overrides and
8+# the library path the shell exported. The re-entry test is JOLT_NATIVE_LIB,
9+# which only the shell sets — no flag to forget, and no second code path for
10+# someone who runs `nix develop --command just run` by hand.
511
612 set shell := ["bash", "-euo", "pipefail", "-c"]
713
14+# nix is not on every host this runs on: on the machine these recipes were
15+# written for it lives in an Arch distrobox, at the same path — which is why
16+# the container is entered rather than the tree copied into it. See CLAUDE.md.
17+nix := `command -v nix >/dev/null 2>&1 && echo nix || echo "distrobox enter arch -- nix"`
18+
19+# --max-jobs 0 is what sends the work to the `builders` entry rather than
20+# compiling it here. Left to the default, nix prefers the local machine, and a
21+# cold jolt-native is egui, openh264 and quinn on a laptop — for a derivation a
22+# remote builder has likely built already. FRQ_MAX_JOBS=auto is the way out on
23+# a machine with no builder configured.
24+jobs := env("FRQ_MAX_JOBS", "0")
25+
826 default:
927 @just --list
1028
29+# The build itself is nix/android.nix, reached as `.#apk`; this only asks nix
30+# for the file and then does what was asked with it. Nothing here names an
31+# Android SDK, an NDK, a Chez cross target or an OpenSSL: the derivation builds
32+# or fetches every one of them.
33+#
34+# The APK is signed with a debug key generated inside the derivation, so the
35+# output is installable and not reproducible; anything meant for a store gets
36+# signed from `.#apk-unsigned` instead. See nix/android.nix.
37+#
38+# FRQ_NIX_STORE builds the whole graph somewhere else rather than here —
39+#
40+# FRQ_NIX_STORE=ssh-ng://eu.nixbuild.net just apk
41+#
42+# which is the shape android.nix asks for: with a `builders` entry instead, nix
43+# copies every remotely-built output back, and androidenv's NDK is both
44+# preferLocalBuild and absent from cache.nixos.org, so 3.1 GB of toolchain is
45+# built here and uploaded. With the remote as the *store* only .drv files go
46+# up. An install then needs the file here, so it is fetched back at the end —
47+# one APK rather than the closure that made it.
48+#
1149 # The APK, out of the flake. `just apk install` puts it on the device.
1250 apk action="build":
13- scripts/apk.bb {{action}}
51+ #!/usr/bin/env bash
52+ set -euo pipefail
53+ cd "{{justfile_directory()}}"
54+ adb="${ADB:-$HOME/.local/share/android-sdk/platform-tools/adb}"
55+ package="uk.nandi.frq"
56+
57+ # --eval-store auto goes with a remote store and only with one: evaluation
58+ # wants this tree, which is here.
59+ store=()
60+ [ -n "${FRQ_NIX_STORE:-}" ] && store=(--store "$FRQ_NIX_STORE" --eval-store auto)
61+
62+ build() {
63+ # The Android objects come from jolt-native's CI under a "latest" alias,
64+ # and a flake input is locked once and then stays put — so without this
65+ # an APK is built against whatever flake.lock recorded the first time,
66+ # however old. Only this input: a bare `nix flake update` would move
67+ # jolt, nixpkgs and glimmer too, and the point of their pins is that
68+ # they move when someone decides they should.
69+ {{nix}} flake update jolt-native-android --flake . >&2
70+
71+ # Built without a `result` symlink: the path is what the caller wants,
72+ # and a symlink into a store that may not be this one is not a useful
73+ # thing to leave in the tree.
74+ local out
75+ out=$({{nix}} build .#apk --no-link --print-out-paths "${store[@]}" \
76+ | grep '^/nix/store/' | tail -1)
77+ [ -n "$out" ] || { echo "nix build printed no store path" >&2; exit 1; }
1478
79+ # Off a remote store the path names a file on the builder, so adb has
80+ # nothing to open. `nix copy --from` brings just that one path here.
81+ if [ -n "${FRQ_NIX_STORE:-}" ]; then
82+ {{nix}} copy --no-check-sigs --from "$FRQ_NIX_STORE" "$out" >&2
83+ fi
84+ echo "$out"
85+ }
86+
87+ case "{{action}}" in
88+ build) build ;;
89+ install) "$adb" install -r "$(build)" ;;
90+ run) file=$(build)
91+ "$adb" install -r "$file"
92+ "$adb" shell am force-stop "$package"
93+ "$adb" shell am start -n "$package/.FrqActivity" ;;
94+ log) "$adb" logcat -s VidyaJolt Vidya ;;
95+ *) echo "usage: just apk [build|install|run|log]" >&2; exit 1 ;;
96+ esac
97+
98+# Two halves, and the split is the point. The frq source is the files on disk,
99+# uncommitted edits and all. Everything under it — jolt, glimmer, glimmer-vidya,
100+# both native objects — is the flake's, built rather than fetched.
101+#
102+# Deliberately not `nix run .#frq`. That builds the flake's own copy of the
103+# source, which is the tree as git has it — so an edit that has not been
104+# committed, or committed on a branch the command was not pointed at, runs as
105+# whatever was there before, silently. A run meant to answer "does my change
106+# work" has to be the files on disk.
107+#
15108 # The app: this tree's source on the flake's everything-else, in the dev shell.
16109 run *args:
17- scripts/run.bb {{args}}
110+ #!/usr/bin/env bash
111+ set -euo pipefail
112+ cd "{{justfile_directory()}}"
113+ if [ -z "${JOLT_NATIVE_LIB:-}" ]; then
114+ exec {{nix}} develop . --max-jobs {{jobs}} --command just run "$@"
115+ fi
116+
117+ # The Jolt halves that have to match those objects. glimmer-vidya lives
118+ # inside jolt-native and binds libvidya's ABI, so it comes out of the same
119+ # input that was built rather than deps.edn's git sha — the pin drifting
120+ # from the library is exactly what the flake input's comment describes.
121+ deps="{:deps {jolt-lang/glimmer {:local/root \"$GLIMMER_SRC\"}"
122+ deps="$deps nandi/glimmer-vidya {:local/root \"$GLIMMER_VIDYA_SRC\"}}}"
123+
124+ export LD_LIBRARY_PATH="$JOLT_NATIVE_LIB:$FRQ_LIB_PATH${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
18125
126+ # On NixOS the store's Mesa is the system's and the window opens. Anywhere
127+ # else — a bare host, or the distrobox above — the real driver is the
128+ # host's, so defer to nixGL, which prepends it.
129+ runner=()
130+ [ -e /run/current-system ] || runner=("$NIXGL")
131+
132+ exec "${runner[@]}" jolt -Sdeps "$deps" -M:frq "$@"
133+
134+# `run` with the other backend under it. It still loads libvidya as well as
135+# libjolttui: `frq.app` requires glimmer-vidya, and `frq.tui` requires
136+# glimmer-tui after it so the backend installed last is the terminal.
137+#
138+# No nixGL here, unlike `run`: a terminal wants nothing from the host's GL
139+# driver, which is the reason this output exists on machines that have none.
140+#
19141 # The same screens in a terminal. `just tui --headless` prints one screenshot.
20142 tui *args:
21- scripts/tui.bb {{args}}
143+ #!/usr/bin/env bash
144+ set -euo pipefail
145+ cd "{{justfile_directory()}}"
146+ if [ -z "${JOLT_NATIVE_LIB:-}" ]; then
147+ exec {{nix}} develop . --max-jobs {{jobs}} --command just tui "$@"
148+ fi
149+
150+ deps="{:deps {jolt-lang/glimmer {:local/root \"$GLIMMER_SRC\"}"
151+ deps="$deps nandi/glimmer-vidya {:local/root \"$GLIMMER_VIDYA_SRC\"}"
152+ deps="$deps nandi/glimmer-tui {:local/root \"$GLIMMER_TUI_SRC\"}}}"
153+
154+ export LD_LIBRARY_PATH="$JOLT_NATIVE_LIB${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
22155
156+ exec jolt -Sdeps "$deps" -m frq.tui "$@"
157+
158+# `jolt` in the repo root does not work on its own: deps.edn carries
159+# :jolt/native, so every invocation here loads libvidya and libjoltmoq before it
160+# reads a line, and dies naming the library if the loader cannot find them. So
161+# this is `run` without the app — and `run` is this with a window's worth of
162+# extra care about the GL driver.
163+#
23164 # A jolt with the native libraries under it: a REPL, or `just repl nrepl-server`.
24165 repl *args:
25- scripts/repl.bb {{args}}
166+ #!/usr/bin/env bash
167+ set -euo pipefail
168+ cd "{{justfile_directory()}}"
169+ if [ -z "${JOLT_NATIVE_LIB:-}" ]; then
170+ exec {{nix}} develop . --max-jobs {{jobs}} --command just repl "$@"
171+ fi
172+
173+ deps="{:deps {jolt-lang/glimmer {:local/root \"$GLIMMER_SRC\"}"
174+ deps="$deps nandi/glimmer-vidya {:local/root \"$GLIMMER_VIDYA_SRC\"}}}"
175+
176+ export LD_LIBRARY_PATH="$JOLT_NATIVE_LIB:$FRQ_LIB_PATH${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
177+
178+ exec jolt -Sdeps "$deps" "$@"
@@ -1,25 +1,178 @@
1-# Every recipe here is one line, because the work is in scripts/ — babashka1+# The work is here now, in recipe bodies, where it used to be in scripts/ —
2-# scripts, run through scripts/bb, which finds a bb the way this tree finds2+# babashka scripts run through a scripts/bb that went looking for a babashka.
3-# everything else. A recipe body is a shell script nobody can run on its own;3+# That indirection bought one thing worth having, a shared way to reach nix on
4-# a script in scripts/ is a script.4+# a host that keeps it in a container, and `nix` below is the whole of it.
5+#
6+# Every recipe that runs frq has the same shape: outside the dev shell, re-enter
7+# it and come back to this same recipe; inside, hand jolt the deps overrides and
8+# the library path the shell exported. The re-entry test is JOLT_NATIVE_LIB,
9+# which only the shell sets — no flag to forget, and no second code path for
10+# someone who runs `nix develop --command just run` by hand.
5 11
6 set shell := ["bash", "-euo", "pipefail", "-c"]12 set shell := ["bash", "-euo", "pipefail", "-c"]
7 13
14+# nix is not on every host this runs on: on the machine these recipes were
15+# written for it lives in an Arch distrobox, at the same path — which is why
16+# the container is entered rather than the tree copied into it. See CLAUDE.md.
17+nix := `command -v nix >/dev/null 2>&1 && echo nix || echo "distrobox enter arch -- nix"`
18+
19+# --max-jobs 0 is what sends the work to the `builders` entry rather than
20+# compiling it here. Left to the default, nix prefers the local machine, and a
21+# cold jolt-native is egui, openh264 and quinn on a laptop — for a derivation a
22+# remote builder has likely built already. FRQ_MAX_JOBS=auto is the way out on
23+# a machine with no builder configured.
24+jobs := env("FRQ_MAX_JOBS", "0")
25+
8 default:26 default:
9 @just --list27 @just --list
10 28
29+# The build itself is nix/android.nix, reached as `.#apk`; this only asks nix
30+# for the file and then does what was asked with it. Nothing here names an
31+# Android SDK, an NDK, a Chez cross target or an OpenSSL: the derivation builds
32+# or fetches every one of them.
33+#
34+# The APK is signed with a debug key generated inside the derivation, so the
35+# output is installable and not reproducible; anything meant for a store gets
36+# signed from `.#apk-unsigned` instead. See nix/android.nix.
37+#
38+# FRQ_NIX_STORE builds the whole graph somewhere else rather than here —
39+#
40+# FRQ_NIX_STORE=ssh-ng://eu.nixbuild.net just apk
41+#
42+# which is the shape android.nix asks for: with a `builders` entry instead, nix
43+# copies every remotely-built output back, and androidenv's NDK is both
44+# preferLocalBuild and absent from cache.nixos.org, so 3.1 GB of toolchain is
45+# built here and uploaded. With the remote as the *store* only .drv files go
46+# up. An install then needs the file here, so it is fetched back at the end —
47+# one APK rather than the closure that made it.
48+#
11 # The APK, out of the flake. `just apk install` puts it on the device.49 # The APK, out of the flake. `just apk install` puts it on the device.
12 apk action="build":50 apk action="build":
13- scripts/apk.bb {{action}}51+ #!/usr/bin/env bash
52+ set -euo pipefail
53+ cd "{{justfile_directory()}}"
54+ adb="${ADB:-$HOME/.local/share/android-sdk/platform-tools/adb}"
55+ package="uk.nandi.frq"
56+
57+ # --eval-store auto goes with a remote store and only with one: evaluation
58+ # wants this tree, which is here.
59+ store=()
60+ [ -n "${FRQ_NIX_STORE:-}" ] && store=(--store "$FRQ_NIX_STORE" --eval-store auto)
61+
62+ build() {
63+ # The Android objects come from jolt-native's CI under a "latest" alias,
64+ # and a flake input is locked once and then stays put — so without this
65+ # an APK is built against whatever flake.lock recorded the first time,
66+ # however old. Only this input: a bare `nix flake update` would move
67+ # jolt, nixpkgs and glimmer too, and the point of their pins is that
68+ # they move when someone decides they should.
69+ {{nix}} flake update jolt-native-android --flake . >&2
70+
71+ # Built without a `result` symlink: the path is what the caller wants,
72+ # and a symlink into a store that may not be this one is not a useful
73+ # thing to leave in the tree.
74+ local out
75+ out=$({{nix}} build .#apk --no-link --print-out-paths "${store[@]}" \
76+ | grep '^/nix/store/' | tail -1)
77+ [ -n "$out" ] || { echo "nix build printed no store path" >&2; exit 1; }
14 78
79+ # Off a remote store the path names a file on the builder, so adb has
80+ # nothing to open. `nix copy --from` brings just that one path here.
81+ if [ -n "${FRQ_NIX_STORE:-}" ]; then
82+ {{nix}} copy --no-check-sigs --from "$FRQ_NIX_STORE" "$out" >&2
83+ fi
84+ echo "$out"
85+ }
86+
87+ case "{{action}}" in
88+ build) build ;;
89+ install) "$adb" install -r "$(build)" ;;
90+ run) file=$(build)
91+ "$adb" install -r "$file"
92+ "$adb" shell am force-stop "$package"
93+ "$adb" shell am start -n "$package/.FrqActivity" ;;
94+ log) "$adb" logcat -s VidyaJolt Vidya ;;
95+ *) echo "usage: just apk [build|install|run|log]" >&2; exit 1 ;;
96+ esac
97+
98+# Two halves, and the split is the point. The frq source is the files on disk,
99+# uncommitted edits and all. Everything under it — jolt, glimmer, glimmer-vidya,
100+# both native objects — is the flake's, built rather than fetched.
101+#
102+# Deliberately not `nix run .#frq`. That builds the flake's own copy of the
103+# source, which is the tree as git has it — so an edit that has not been
104+# committed, or committed on a branch the command was not pointed at, runs as
105+# whatever was there before, silently. A run meant to answer "does my change
106+# work" has to be the files on disk.
107+#
15 # The app: this tree's source on the flake's everything-else, in the dev shell.108 # The app: this tree's source on the flake's everything-else, in the dev shell.
16 run *args:109 run *args:
17- scripts/run.bb {{args}}110+ #!/usr/bin/env bash
111+ set -euo pipefail
112+ cd "{{justfile_directory()}}"
113+ if [ -z "${JOLT_NATIVE_LIB:-}" ]; then
114+ exec {{nix}} develop . --max-jobs {{jobs}} --command just run "$@"
115+ fi
116+
117+ # The Jolt halves that have to match those objects. glimmer-vidya lives
118+ # inside jolt-native and binds libvidya's ABI, so it comes out of the same
119+ # input that was built rather than deps.edn's git sha — the pin drifting
120+ # from the library is exactly what the flake input's comment describes.
121+ deps="{:deps {jolt-lang/glimmer {:local/root \"$GLIMMER_SRC\"}"
122+ deps="$deps nandi/glimmer-vidya {:local/root \"$GLIMMER_VIDYA_SRC\"}}}"
123+
124+ export LD_LIBRARY_PATH="$JOLT_NATIVE_LIB:$FRQ_LIB_PATH${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
18 125
126+ # On NixOS the store's Mesa is the system's and the window opens. Anywhere
127+ # else — a bare host, or the distrobox above — the real driver is the
128+ # host's, so defer to nixGL, which prepends it.
129+ runner=()
130+ [ -e /run/current-system ] || runner=("$NIXGL")
131+
132+ exec "${runner[@]}" jolt -Sdeps "$deps" -M:frq "$@"
133+
134+# `run` with the other backend under it. It still loads libvidya as well as
135+# libjolttui: `frq.app` requires glimmer-vidya, and `frq.tui` requires
136+# glimmer-tui after it so the backend installed last is the terminal.
137+#
138+# No nixGL here, unlike `run`: a terminal wants nothing from the host's GL
139+# driver, which is the reason this output exists on machines that have none.
140+#
19 # The same screens in a terminal. `just tui --headless` prints one screenshot.141 # The same screens in a terminal. `just tui --headless` prints one screenshot.
20 tui *args:142 tui *args:
21- scripts/tui.bb {{args}}143+ #!/usr/bin/env bash
144+ set -euo pipefail
145+ cd "{{justfile_directory()}}"
146+ if [ -z "${JOLT_NATIVE_LIB:-}" ]; then
147+ exec {{nix}} develop . --max-jobs {{jobs}} --command just tui "$@"
148+ fi
149+
150+ deps="{:deps {jolt-lang/glimmer {:local/root \"$GLIMMER_SRC\"}"
151+ deps="$deps nandi/glimmer-vidya {:local/root \"$GLIMMER_VIDYA_SRC\"}"
152+ deps="$deps nandi/glimmer-tui {:local/root \"$GLIMMER_TUI_SRC\"}}}"
153+
154+ export LD_LIBRARY_PATH="$JOLT_NATIVE_LIB${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
22 155
156+ exec jolt -Sdeps "$deps" -m frq.tui "$@"
157+
158+# `jolt` in the repo root does not work on its own: deps.edn carries
159+# :jolt/native, so every invocation here loads libvidya and libjoltmoq before it
160+# reads a line, and dies naming the library if the loader cannot find them. So
161+# this is `run` without the app — and `run` is this with a window's worth of
162+# extra care about the GL driver.
163+#
23 # A jolt with the native libraries under it: a REPL, or `just repl nrepl-server`.164 # A jolt with the native libraries under it: a REPL, or `just repl nrepl-server`.
24 repl *args:165 repl *args:
25- scripts/repl.bb {{args}}166+ #!/usr/bin/env bash
167+ set -euo pipefail
168+ cd "{{justfile_directory()}}"
169+ if [ -z "${JOLT_NATIVE_LIB:-}" ]; then
170+ exec {{nix}} develop . --max-jobs {{jobs}} --command just repl "$@"
171+ fi
172+
173+ deps="{:deps {jolt-lang/glimmer {:local/root \"$GLIMMER_SRC\"}"
174+ deps="$deps nandi/glimmer-vidya {:local/root \"$GLIMMER_VIDYA_SRC\"}}}"
175+
176+ export LD_LIBRARY_PATH="$JOLT_NATIVE_LIB:$FRQ_LIB_PATH${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
177+
178+ exec jolt -Sdeps "$deps" "$@"
modified nix/android.nix +1 -1
@@ -9,7 +9,7 @@
99 # nix build .#apk
1010 #
1111 # `just apk` is the same build with the store path handed to adb afterwards;
12-# see scripts/apk.bb.
12+# see the `apk` recipe in the justfile.
1313 #
1414 # On a machine with a remote builder configured, prefer
1515 #
@@ -9,7 +9,7 @@
9 # nix build .#apk9 # nix build .#apk
10 #10 #
11 # `just apk` is the same build with the store path handed to adb afterwards;11 # `just apk` is the same build with the store path handed to adb afterwards;
12-# see scripts/apk.bb.12+# see the `apk` recipe in the justfile.
13 #13 #
14 # On a machine with a remote builder configured, prefer14 # On a machine with a remote builder configured, prefer
15 #15 #
deleted scripts/apk.bb +0 -98
deleted file mode 100755
@@ -1,98 +0,0 @@
1-#!/bin/sh
2-#_(
3-exec "$(dirname "$0")/bb" "$0" "$@"
4-)
5-
6-;; The APK, out of the flake.
7-;;
8-;; apk.bb [build|install|run|log]
9-;;
10-;; The build itself is nix/android.nix, reached as `.#apk`; this only asks nix
11-;; for the file and then does what was asked with it. Nothing here names an
12-;; Android SDK, an NDK, a Chez cross target or an OpenSSL: the derivation
13-;; builds or fetches every one of them, which is the difference between this
14-;; and the buck2 graph it replaces — that one was handed four hand-built paths
15-;; from the machine and stopped if any was missing.
16-;;
17-;; The APK is signed with a debug key generated inside the derivation, so the
18-;; output is installable and not reproducible; anything meant for a store gets
19-;; signed from `.#apk-unsigned` instead. See nix/android.nix.
20-;;
21-;; FRQ_NIX_STORE builds the whole graph somewhere else rather than here —
22-;;
23-;; FRQ_NIX_STORE=ssh-ng://eu.nixbuild.net scripts/apk.bb
24-;;
25-;; which is the shape android.nix asks for: with a `builders` entry instead,
26-;; nix copies every remotely-built output back, and androidenv's NDK is both
27-;; `preferLocalBuild` and absent from cache.nixos.org, so 3.1 GB of toolchain
28-;; is built here and uploaded. With the remote as the *store* only .drv files
29-;; go up. An install then needs the file here, so it is fetched back at the
30-;; end — one APK rather than the closure that made it.
31-(require '[babashka.classpath :as cp])
32-(cp/add-classpath (str (babashka.fs/parent *file*)))
33-(require '[frq.paths :as paths]
34- '[babashka.fs :as fs]
35- '[babashka.process :as p]
36- '[clojure.string :as str])
37-
38-(def root (str (fs/canonicalize (fs/path (fs/parent *file*) ".."))))
39-(def action (or (first *command-line-args*) "build"))
40-(def adb (paths/env "ADB" (str (fs/path (fs/home) ".local" "share" "android-sdk"
41- "platform-tools" "adb"))))
42-(def package "uk.nandi.frq")
43-
44-;; --eval-store auto goes with a remote store and only with one: evaluation
45-;; wants this tree, which is here.
46-(def store
47- (when-let [s (paths/env "FRQ_NIX_STORE" nil)]
48- ["--store" s "--eval-store" "auto"]))
49-
50-;; The Android objects come from jolt-native's CI under a "latest" alias, and a
51-;; flake input is locked once and then stays put — so without this an APK is
52-;; built against whatever `flake.lock` recorded the first time, however old.
53-;; Re-resolving that one input before every build is what makes "latest" mean
54-;; latest; the lock still records which bytes this APK was built from, so a
55-;; build remains reproducible after the fact.
56-;;
57-;; Only this input: `nix flake update` with no argument would move jolt,
58-;; nixpkgs and glimmer too, and the whole point of their pins is that they move
59-;; when someone decides they should.
60-(defn refresh-native []
61- (apply paths/out (paths/nix root ["nix" "flake" "update" "jolt-native-android"
62- "--flake" (str root)])))
63-
64-;; Built without a `result` symlink: the path is what the caller wants, and a
65-;; symlink into a store that may not be this one is not a useful thing to leave
66-;; in the tree.
67-(defn build []
68- (refresh-native)
69- (let [out (->> (paths/nix root (concat ["nix" "build" (str root "#apk")
70- "--no-link" "--print-out-paths"]
71- store))
72- (apply paths/out)
73- str/split-lines
74- (filter #(str/starts-with? % "/nix/store/"))
75- last)]
76- (when-not out
77- (paths/die "nix build printed no store path"))
78- out))
79-
80-;; Off a remote store the path names a file on the builder, so adb has nothing
81-;; to open. `nix copy --no-check-sigs --from` brings just that one path here.
82-(defn local-file []
83- (let [out (build)]
84- (when store
85- (apply p/shell (paths/nix root (concat ["nix" "copy" "--no-check-sigs"
86- "--from" (paths/env "FRQ_NIX_STORE" nil)
87- out]))))
88- out))
89-
90-(case action
91- "build" (println (build))
92- "install" (p/shell adb "install" "-r" (local-file))
93- "run" (let [file (local-file)]
94- (p/shell adb "install" "-r" file)
95- (p/shell adb "shell" "am" "force-stop" package)
96- (p/shell adb "shell" "am" "start" "-n" (str package "/.FrqActivity")))
97- "log" (p/shell adb "logcat" "-s" "VidyaJolt" "Vidya")
98- (paths/die "usage: apk.bb [build|install|run|log]"))
deleted file mode 100755
@@ -1,98 +0,0 @@
1-#!/bin/sh
2-#_(
3-exec "$(dirname "$0")/bb" "$0" "$@"
4-)
5-
6-;; The APK, out of the flake.
7-;;
8-;; apk.bb [build|install|run|log]
9-;;
10-;; The build itself is nix/android.nix, reached as `.#apk`; this only asks nix
11-;; for the file and then does what was asked with it. Nothing here names an
12-;; Android SDK, an NDK, a Chez cross target or an OpenSSL: the derivation
13-;; builds or fetches every one of them, which is the difference between this
14-;; and the buck2 graph it replaces — that one was handed four hand-built paths
15-;; from the machine and stopped if any was missing.
16-;;
17-;; The APK is signed with a debug key generated inside the derivation, so the
18-;; output is installable and not reproducible; anything meant for a store gets
19-;; signed from `.#apk-unsigned` instead. See nix/android.nix.
20-;;
21-;; FRQ_NIX_STORE builds the whole graph somewhere else rather than here —
22-;;
23-;; FRQ_NIX_STORE=ssh-ng://eu.nixbuild.net scripts/apk.bb
24-;;
25-;; which is the shape android.nix asks for: with a `builders` entry instead,
26-;; nix copies every remotely-built output back, and androidenv's NDK is both
27-;; `preferLocalBuild` and absent from cache.nixos.org, so 3.1 GB of toolchain
28-;; is built here and uploaded. With the remote as the *store* only .drv files
29-;; go up. An install then needs the file here, so it is fetched back at the
30-;; end — one APK rather than the closure that made it.
31-(require '[babashka.classpath :as cp])
32-(cp/add-classpath (str (babashka.fs/parent *file*)))
33-(require '[frq.paths :as paths]
34- '[babashka.fs :as fs]
35- '[babashka.process :as p]
36- '[clojure.string :as str])
37-
38-(def root (str (fs/canonicalize (fs/path (fs/parent *file*) ".."))))
39-(def action (or (first *command-line-args*) "build"))
40-(def adb (paths/env "ADB" (str (fs/path (fs/home) ".local" "share" "android-sdk"
41- "platform-tools" "adb"))))
42-(def package "uk.nandi.frq")
43-
44-;; --eval-store auto goes with a remote store and only with one: evaluation
45-;; wants this tree, which is here.
46-(def store
47- (when-let [s (paths/env "FRQ_NIX_STORE" nil)]
48- ["--store" s "--eval-store" "auto"]))
49-
50-;; The Android objects come from jolt-native's CI under a "latest" alias, and a
51-;; flake input is locked once and then stays put — so without this an APK is
52-;; built against whatever `flake.lock` recorded the first time, however old.
53-;; Re-resolving that one input before every build is what makes "latest" mean
54-;; latest; the lock still records which bytes this APK was built from, so a
55-;; build remains reproducible after the fact.
56-;;
57-;; Only this input: `nix flake update` with no argument would move jolt,
58-;; nixpkgs and glimmer too, and the whole point of their pins is that they move
59-;; when someone decides they should.
60-(defn refresh-native []
61- (apply paths/out (paths/nix root ["nix" "flake" "update" "jolt-native-android"
62- "--flake" (str root)])))
63-
64-;; Built without a `result` symlink: the path is what the caller wants, and a
65-;; symlink into a store that may not be this one is not a useful thing to leave
66-;; in the tree.
67-(defn build []
68- (refresh-native)
69- (let [out (->> (paths/nix root (concat ["nix" "build" (str root "#apk")
70- "--no-link" "--print-out-paths"]
71- store))
72- (apply paths/out)
73- str/split-lines
74- (filter #(str/starts-with? % "/nix/store/"))
75- last)]
76- (when-not out
77- (paths/die "nix build printed no store path"))
78- out))
79-
80-;; Off a remote store the path names a file on the builder, so adb has nothing
81-;; to open. `nix copy --no-check-sigs --from` brings just that one path here.
82-(defn local-file []
83- (let [out (build)]
84- (when store
85- (apply p/shell (paths/nix root (concat ["nix" "copy" "--no-check-sigs"
86- "--from" (paths/env "FRQ_NIX_STORE" nil)
87- out]))))
88- out))
89-
90-(case action
91- "build" (println (build))
92- "install" (p/shell adb "install" "-r" (local-file))
93- "run" (let [file (local-file)]
94- (p/shell adb "install" "-r" file)
95- (p/shell adb "shell" "am" "force-stop" package)
96- (p/shell adb "shell" "am" "start" "-n" (str package "/.FrqActivity")))
97- "log" (p/shell adb "logcat" "-s" "VidyaJolt" "Vidya")
98- (paths/die "usage: apk.bb [build|install|run|log]"))
deleted scripts/bb +0 -57
deleted file mode 100755
@@ -1,57 +0,0 @@
1-#!/bin/sh
2-# babashka, which the scripts here are written in.
3-#
4-# A build script wants the things a shell is bad at — reading deps.edn, hashing
5-# a file set, holding a path in a variable without quoting it three times — and
6-# Clojure is already the language this repo is written in.
7-#
8-# This used to be a DotSlash manifest, pinning a release of babashka the way
9-# the desktop libraries were pinned. It is the flake's now, for the reason the
10-# flake exists: a bb from `nixpkgs` is one this tree already names a version
11-# of, so a checkout needs nix and nothing else. Nothing is fetched by digest
12-# here any more — the libraries a run loads are the flake's too, and the only
13-# release pins left are the APK's, in nix/android.nix.
14-#
15-# Three answers, in order:
16-#
17-# bb on PATH the dev shell puts one there, and so does a machine that
18-# has its own; either is what the caller meant — as long as
19-# it is babashka. `bb` is also what bazel's own launcher
20-# calls itself, and a host with one of those ahead of the
21-# shell's answered every recipe here with "Command
22-# 'scripts/tui.bb' not found. Try 'bb help'", which reads as
23-# a missing script rather than the wrong program
24-# the flake built once and kept alive by the symlink under build/,
25-# which is a gc root as well as a cache
26-# the container nix is not on every host this runs on — see CLAUDE.md —
27-# so a host without one re-enters this script where nix is,
28-# which is where the scripts want to be anyway
29-set -e
30-
31-root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
32-
33-# Asking it who it is, rather than trusting the name: the version line is the
34-# cheapest question babashka answers and the one nothing else answers the same
35-# way.
36-if command -v bb >/dev/null 2>&1 && bb --version 2>/dev/null | grep -qi '^babashka'; then
37- exec bb "$@"
38-fi
39-
40-link="$root/build/bb"
41-
42-if command -v nix >/dev/null 2>&1; then
43- # --out-link rather than --no-link: the path has to survive a gc, and the
44- # symlink is what roots it. Rebuilt only when it is gone or dangling, so
45- # the usual case is one readlink.
46- [ -x "$link/bin/bb" ] || nix build "$root#bb" --out-link "$link" >&2
47- exec "$link/bin/bb" "$@"
48-fi
49-
50-if [ -n "$FRQ_BB_REENTERED" ]; then
51- echo "scripts/bb: no bb and no nix, inside the container too." >&2
52- echo "Install babashka, or put a nix on this machine." >&2
53- exit 1
54-fi
55-
56-exec distrobox enter arch -- bash -lc \
57- "cd $root && FRQ_BB_REENTERED=1 exec scripts/bb \"\$@\"" -- "$@"
deleted file mode 100755
@@ -1,57 +0,0 @@
1-#!/bin/sh
2-# babashka, which the scripts here are written in.
3-#
4-# A build script wants the things a shell is bad at — reading deps.edn, hashing
5-# a file set, holding a path in a variable without quoting it three times — and
6-# Clojure is already the language this repo is written in.
7-#
8-# This used to be a DotSlash manifest, pinning a release of babashka the way
9-# the desktop libraries were pinned. It is the flake's now, for the reason the
10-# flake exists: a bb from `nixpkgs` is one this tree already names a version
11-# of, so a checkout needs nix and nothing else. Nothing is fetched by digest
12-# here any more — the libraries a run loads are the flake's too, and the only
13-# release pins left are the APK's, in nix/android.nix.
14-#
15-# Three answers, in order:
16-#
17-# bb on PATH the dev shell puts one there, and so does a machine that
18-# has its own; either is what the caller meant — as long as
19-# it is babashka. `bb` is also what bazel's own launcher
20-# calls itself, and a host with one of those ahead of the
21-# shell's answered every recipe here with "Command
22-# 'scripts/tui.bb' not found. Try 'bb help'", which reads as
23-# a missing script rather than the wrong program
24-# the flake built once and kept alive by the symlink under build/,
25-# which is a gc root as well as a cache
26-# the container nix is not on every host this runs on — see CLAUDE.md —
27-# so a host without one re-enters this script where nix is,
28-# which is where the scripts want to be anyway
29-set -e
30-
31-root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
32-
33-# Asking it who it is, rather than trusting the name: the version line is the
34-# cheapest question babashka answers and the one nothing else answers the same
35-# way.
36-if command -v bb >/dev/null 2>&1 && bb --version 2>/dev/null | grep -qi '^babashka'; then
37- exec bb "$@"
38-fi
39-
40-link="$root/build/bb"
41-
42-if command -v nix >/dev/null 2>&1; then
43- # --out-link rather than --no-link: the path has to survive a gc, and the
44- # symlink is what roots it. Rebuilt only when it is gone or dangling, so
45- # the usual case is one readlink.
46- [ -x "$link/bin/bb" ] || nix build "$root#bb" --out-link "$link" >&2
47- exec "$link/bin/bb" "$@"
48-fi
49-
50-if [ -n "$FRQ_BB_REENTERED" ]; then
51- echo "scripts/bb: no bb and no nix, inside the container too." >&2
52- echo "Install babashka, or put a nix on this machine." >&2
53- exit 1
54-fi
55-
56-exec distrobox enter arch -- bash -lc \
57- "cd $root && FRQ_BB_REENTERED=1 exec scripts/bb \"\$@\"" -- "$@"
deleted scripts/frq/paths.clj +0 -41
deleted file mode 100644
@@ -1,41 +0,0 @@
1-;; Where the other halves of this build are, and how to ask a program a
2-;; question without writing the same three lines of shell each time.
3-;;
4-;; Every script here loads this; nothing else does.
5-(ns frq.paths
6- (:require [babashka.fs :as fs]
7- [babashka.process :as p]
8- [clojure.string :as str]))
9-
10-(defn die [& lines]
11- (binding [*out* *err*] (run! println lines))
12- (System/exit 1))
13-
14-(defn out
15- "Run a command and return its standard output, trimmed. Throws if it fails."
16- [& args]
17- (str/trim (:out (apply p/shell {:out :string} (map str args)))))
18-
19-(defn env [k default] (or (not-empty (System/getenv k)) default))
20-
21-(defn require-paths!
22- "Every path must exist, or say which one did not and stop."
23- [label paths & hint]
24- (doseq [p paths]
25- (when-not (fs/exists? (str p))
26- (apply die (str "missing " label ": " p) hint))))
27-
28-;; A nix command, as an argv to run where nix is.
29-;;
30-;; nix is not on every host this runs on: on the machine these scripts were
31-;; written for it lives in an Arch distrobox, at the same path — which is why
32-;; the container is entered rather than the tree copied into it. See CLAUDE.md.
33-;; Trailing arguments are passed through `"$@"` rather than pasted into the
34-;; command line, so a value with a space in it survives the shell in between.
35-(defn nix [root args & [trailing]]
36- (if (fs/which "nix")
37- (concat args trailing)
38- (concat ["distrobox" "enter" "arch" "--" "bash" "-lc"
39- (str "cd " root " && exec " (str/join " " args) " \"$@\"")
40- "--"]
41- trailing)))
deleted file mode 100644
@@ -1,41 +0,0 @@
1-;; Where the other halves of this build are, and how to ask a program a
2-;; question without writing the same three lines of shell each time.
3-;;
4-;; Every script here loads this; nothing else does.
5-(ns frq.paths
6- (:require [babashka.fs :as fs]
7- [babashka.process :as p]
8- [clojure.string :as str]))
9-
10-(defn die [& lines]
11- (binding [*out* *err*] (run! println lines))
12- (System/exit 1))
13-
14-(defn out
15- "Run a command and return its standard output, trimmed. Throws if it fails."
16- [& args]
17- (str/trim (:out (apply p/shell {:out :string} (map str args)))))
18-
19-(defn env [k default] (or (not-empty (System/getenv k)) default))
20-
21-(defn require-paths!
22- "Every path must exist, or say which one did not and stop."
23- [label paths & hint]
24- (doseq [p paths]
25- (when-not (fs/exists? (str p))
26- (apply die (str "missing " label ": " p) hint))))
27-
28-;; A nix command, as an argv to run where nix is.
29-;;
30-;; nix is not on every host this runs on: on the machine these scripts were
31-;; written for it lives in an Arch distrobox, at the same path — which is why
32-;; the container is entered rather than the tree copied into it. See CLAUDE.md.
33-;; Trailing arguments are passed through `"$@"` rather than pasted into the
34-;; command line, so a value with a space in it survives the shell in between.
35-(defn nix [root args & [trailing]]
36- (if (fs/which "nix")
37- (concat args trailing)
38- (concat ["distrobox" "enter" "arch" "--" "bash" "-lc"
39- (str "cd " root " && exec " (str/join " " args) " \"$@\"")
40- "--"]
41- trailing)))
deleted scripts/repl.bb +0 -60
deleted file mode 100755
@@ -1,60 +0,0 @@
1-#!/bin/sh
2-#_(
3-exec "$(dirname "$0")/bb" "$0" "$@"
4-)
5-
6-;; A jolt against this tree, with the native libraries under it.
7-;;
8-;; repl.bb a REPL
9-;; repl.bb nrepl-server the same thing for an editor to connect to
10-;; repl.bb -e '(+ 1 1)' or any other jolt command line
11-;;
12-;; This exists because `jolt` in the repo root does not work on its own.
13-;; deps.edn carries :jolt/native, so every jolt invocation here — a REPL, an
14-;; nREPL server, `jolt -M:frq` — loads libvidya and libjoltmoq before it reads
15-;; a line, and dies naming the library if the loader cannot find them. The
16-;; libraries are the flake's, which means an LD_LIBRARY_PATH nobody should have
17-;; to remember.
18-;;
19-;; So it is run.bb without the app: the same re-exec into `nix develop`, the
20-;; same deps overrides for the Jolt halves that bind those objects, and then
21-;; whatever jolt command line the caller asked for. run.bb is `repl.bb -M:frq`
22-;; with a window's worth of extra care about the GL driver; this is the rest of
23-;; the time.
24-(require '[babashka.classpath :as cp])
25-(cp/add-classpath (str (babashka.fs/parent *file*)))
26-(require '[frq.paths :as paths]
27- '[babashka.fs :as fs]
28- '[babashka.process :as p]
29- '[clojure.string :as str])
30-
31-(def root (str (fs/canonicalize (fs/path (fs/parent *file*) ".."))))
32-(def self (str (fs/path root "scripts" "repl.bb")))
33-
34-;; Outside the shell, get inside it and come back — the test, the flag and the
35-;; reasoning are run.bb's.
36-(when-not (System/getenv "JOLT_NATIVE_LIB")
37- (let [cmd (paths/nix root
38- ["nix" "develop" root
39- "--max-jobs" (paths/env "FRQ_MAX_JOBS" "0")
40- "--command" self]
41- *command-line-args*)]
42- (System/exit (:exit @(apply p/process {:inherit true :dir root} cmd)))))
43-
44-;; The Jolt halves that have to match those objects, for run.bb's reason: the
45-;; pin in deps.edn is a release, and what the shell built is the flake input.
46-(def overrides
47- (str "{:deps {jolt-lang/glimmer {:local/root \"" (System/getenv "GLIMMER_SRC") "\"}"
48- " nandi/glimmer-vidya {:local/root \"" (System/getenv "GLIMMER_VIDYA_SRC") "\"}}}"))
49-
50-(System/exit
51- (:exit @(apply p/process
52- {:inherit true
53- :dir root
54- :extra-env {"LD_LIBRARY_PATH"
55- (->> [(System/getenv "JOLT_NATIVE_LIB")
56- (System/getenv "FRQ_LIB_PATH")
57- (System/getenv "LD_LIBRARY_PATH")]
58- (remove str/blank?)
59- (str/join ":"))}}
60- (concat ["jolt" "-Sdeps" overrides] *command-line-args*))))
deleted file mode 100755
@@ -1,60 +0,0 @@
1-#!/bin/sh
2-#_(
3-exec "$(dirname "$0")/bb" "$0" "$@"
4-)
5-
6-;; A jolt against this tree, with the native libraries under it.
7-;;
8-;; repl.bb a REPL
9-;; repl.bb nrepl-server the same thing for an editor to connect to
10-;; repl.bb -e '(+ 1 1)' or any other jolt command line
11-;;
12-;; This exists because `jolt` in the repo root does not work on its own.
13-;; deps.edn carries :jolt/native, so every jolt invocation here — a REPL, an
14-;; nREPL server, `jolt -M:frq` — loads libvidya and libjoltmoq before it reads
15-;; a line, and dies naming the library if the loader cannot find them. The
16-;; libraries are the flake's, which means an LD_LIBRARY_PATH nobody should have
17-;; to remember.
18-;;
19-;; So it is run.bb without the app: the same re-exec into `nix develop`, the
20-;; same deps overrides for the Jolt halves that bind those objects, and then
21-;; whatever jolt command line the caller asked for. run.bb is `repl.bb -M:frq`
22-;; with a window's worth of extra care about the GL driver; this is the rest of
23-;; the time.
24-(require '[babashka.classpath :as cp])
25-(cp/add-classpath (str (babashka.fs/parent *file*)))
26-(require '[frq.paths :as paths]
27- '[babashka.fs :as fs]
28- '[babashka.process :as p]
29- '[clojure.string :as str])
30-
31-(def root (str (fs/canonicalize (fs/path (fs/parent *file*) ".."))))
32-(def self (str (fs/path root "scripts" "repl.bb")))
33-
34-;; Outside the shell, get inside it and come back — the test, the flag and the
35-;; reasoning are run.bb's.
36-(when-not (System/getenv "JOLT_NATIVE_LIB")
37- (let [cmd (paths/nix root
38- ["nix" "develop" root
39- "--max-jobs" (paths/env "FRQ_MAX_JOBS" "0")
40- "--command" self]
41- *command-line-args*)]
42- (System/exit (:exit @(apply p/process {:inherit true :dir root} cmd)))))
43-
44-;; The Jolt halves that have to match those objects, for run.bb's reason: the
45-;; pin in deps.edn is a release, and what the shell built is the flake input.
46-(def overrides
47- (str "{:deps {jolt-lang/glimmer {:local/root \"" (System/getenv "GLIMMER_SRC") "\"}"
48- " nandi/glimmer-vidya {:local/root \"" (System/getenv "GLIMMER_VIDYA_SRC") "\"}}}"))
49-
50-(System/exit
51- (:exit @(apply p/process
52- {:inherit true
53- :dir root
54- :extra-env {"LD_LIBRARY_PATH"
55- (->> [(System/getenv "JOLT_NATIVE_LIB")
56- (System/getenv "FRQ_LIB_PATH")
57- (System/getenv "LD_LIBRARY_PATH")]
58- (remove str/blank?)
59- (str/join ":"))}}
60- (concat ["jolt" "-Sdeps" overrides] *command-line-args*))))
deleted scripts/run.bb +0 -83
deleted file mode 100755
@@ -1,83 +0,0 @@
1-#!/bin/sh
2-#_(
3-exec "$(dirname "$0")/bb" "$0" "$@"
4-)
5-
6-;; The app, from this working tree.
7-;;
8-;; run.bb [args...]
9-;;
10-;; Two halves, and the split is the point. The frq source is the files on disk,
11-;; uncommitted edits and all. Everything under it — jolt, glimmer,
12-;; glimmer-vidya, both native objects — is the flake's, built rather than
13-;; fetched: this re-execs itself inside `nix develop`, and that shell is the
14-;; jolt-native input compiled and the Jolt halves that bind it, at the revs
15-;; flake.lock names.
16-;;
17-;; Deliberately not `nix run .#frq`. That builds the flake's own copy of the
18-;; source, which is the tree as git has it — so an edit that has not been
19-;; committed, or has been committed on a branch the command was not pointed at,
20-;; runs as whatever was there before, silently. A run that is meant to answer
21-;; "does my change work" has to be the files on disk.
22-;;
23-;; And deliberately not a release either, which is what this used to do: it
24-;; resolved the scripts/*.dotslash pins, and those name a release — a change to
25-;; jolt-native is by definition not in one yet. The APK still takes released
26-;; bytes, through nix/android.nix — but a run does not.
27-(require '[babashka.classpath :as cp])
28-(cp/add-classpath (str (babashka.fs/parent *file*)))
29-(require '[frq.paths :as paths]
30- '[babashka.fs :as fs]
31- '[babashka.process :as p]
32- '[clojure.string :as str])
33-
34-(def root (str (fs/canonicalize (fs/path (fs/parent *file*) ".."))))
35-(def self (str (fs/path root "scripts" "run.bb")))
36-
37-;; Outside the shell, get inside it and come back to this same script. The
38-;; shell is what sets JOLT_NATIVE_LIB, so its absence is the test — no flag to
39-;; forget, and `nix develop --command scripts/run.bb` by hand is not a second
40-;; code path.
41-;;
42-;; --max-jobs 0 is what sends the work to the `builders` entry rather than
43-;; compiling it here. Left to the default, nix prefers the local machine, and a
44-;; cold jolt-native is egui, openh264 and quinn on a laptop — for a derivation
45-;; a remote builder has likely built already. FRQ_MAX_JOBS is the way out on a
46-;; machine with no builder configured: FRQ_MAX_JOBS=auto.
47-(when-not (System/getenv "JOLT_NATIVE_LIB")
48- ;; Getting to a nix on a host that may not have one is paths/nix's problem,
49- ;; and scripts/apk.bb has the same one.
50- (let [cmd (paths/nix root
51- ["nix" "develop" root
52- "--max-jobs" (paths/env "FRQ_MAX_JOBS" "0")
53- "--command" self]
54- *command-line-args*)]
55- (System/exit (:exit @(apply p/process {:inherit true :dir root} cmd)))))
56-
57-;; The Jolt halves that have to match those objects. glimmer-vidya lives inside
58-;; jolt-native and binds libvidya's ABI, so it comes out of the same input that
59-;; was built rather than deps.edn's git sha — the pin drifting from the library
60-;; is exactly what the flake input's comment describes. glimmer is the flake's
61-;; for the same reason.
62-(def overrides
63- (str "{:deps {jolt-lang/glimmer {:local/root \"" (System/getenv "GLIMMER_SRC") "\"}"
64- " nandi/glimmer-vidya {:local/root \"" (System/getenv "GLIMMER_VIDYA_SRC") "\"}}}"))
65-
66-;; On NixOS the store's Mesa is the system's and the window opens. Anywhere
67-;; else — a bare host, or the distrobox above — the real driver is the host's,
68-;; so defer to nixGL, which prepends it. Same rule the flake's launcher uses.
69-(def runner
70- (when-not (fs/exists? "/run/current-system")
71- (some-> (System/getenv "NIXGL") not-empty vector)))
72-
73-(System/exit
74- (:exit @(apply p/process
75- {:inherit true
76- :dir root
77- :extra-env {"LD_LIBRARY_PATH"
78- (->> [(System/getenv "JOLT_NATIVE_LIB")
79- (System/getenv "FRQ_LIB_PATH")
80- (System/getenv "LD_LIBRARY_PATH")]
81- (remove str/blank?)
82- (str/join ":"))}}
83- (concat runner ["jolt" "-Sdeps" overrides "-M:frq"] *command-line-args*))))
deleted file mode 100755
@@ -1,83 +0,0 @@
1-#!/bin/sh
2-#_(
3-exec "$(dirname "$0")/bb" "$0" "$@"
4-)
5-
6-;; The app, from this working tree.
7-;;
8-;; run.bb [args...]
9-;;
10-;; Two halves, and the split is the point. The frq source is the files on disk,
11-;; uncommitted edits and all. Everything under it — jolt, glimmer,
12-;; glimmer-vidya, both native objects — is the flake's, built rather than
13-;; fetched: this re-execs itself inside `nix develop`, and that shell is the
14-;; jolt-native input compiled and the Jolt halves that bind it, at the revs
15-;; flake.lock names.
16-;;
17-;; Deliberately not `nix run .#frq`. That builds the flake's own copy of the
18-;; source, which is the tree as git has it — so an edit that has not been
19-;; committed, or has been committed on a branch the command was not pointed at,
20-;; runs as whatever was there before, silently. A run that is meant to answer
21-;; "does my change work" has to be the files on disk.
22-;;
23-;; And deliberately not a release either, which is what this used to do: it
24-;; resolved the scripts/*.dotslash pins, and those name a release — a change to
25-;; jolt-native is by definition not in one yet. The APK still takes released
26-;; bytes, through nix/android.nix — but a run does not.
27-(require '[babashka.classpath :as cp])
28-(cp/add-classpath (str (babashka.fs/parent *file*)))
29-(require '[frq.paths :as paths]
30- '[babashka.fs :as fs]
31- '[babashka.process :as p]
32- '[clojure.string :as str])
33-
34-(def root (str (fs/canonicalize (fs/path (fs/parent *file*) ".."))))
35-(def self (str (fs/path root "scripts" "run.bb")))
36-
37-;; Outside the shell, get inside it and come back to this same script. The
38-;; shell is what sets JOLT_NATIVE_LIB, so its absence is the test — no flag to
39-;; forget, and `nix develop --command scripts/run.bb` by hand is not a second
40-;; code path.
41-;;
42-;; --max-jobs 0 is what sends the work to the `builders` entry rather than
43-;; compiling it here. Left to the default, nix prefers the local machine, and a
44-;; cold jolt-native is egui, openh264 and quinn on a laptop — for a derivation
45-;; a remote builder has likely built already. FRQ_MAX_JOBS is the way out on a
46-;; machine with no builder configured: FRQ_MAX_JOBS=auto.
47-(when-not (System/getenv "JOLT_NATIVE_LIB")
48- ;; Getting to a nix on a host that may not have one is paths/nix's problem,
49- ;; and scripts/apk.bb has the same one.
50- (let [cmd (paths/nix root
51- ["nix" "develop" root
52- "--max-jobs" (paths/env "FRQ_MAX_JOBS" "0")
53- "--command" self]
54- *command-line-args*)]
55- (System/exit (:exit @(apply p/process {:inherit true :dir root} cmd)))))
56-
57-;; The Jolt halves that have to match those objects. glimmer-vidya lives inside
58-;; jolt-native and binds libvidya's ABI, so it comes out of the same input that
59-;; was built rather than deps.edn's git sha — the pin drifting from the library
60-;; is exactly what the flake input's comment describes. glimmer is the flake's
61-;; for the same reason.
62-(def overrides
63- (str "{:deps {jolt-lang/glimmer {:local/root \"" (System/getenv "GLIMMER_SRC") "\"}"
64- " nandi/glimmer-vidya {:local/root \"" (System/getenv "GLIMMER_VIDYA_SRC") "\"}}}"))
65-
66-;; On NixOS the store's Mesa is the system's and the window opens. Anywhere
67-;; else — a bare host, or the distrobox above — the real driver is the host's,
68-;; so defer to nixGL, which prepends it. Same rule the flake's launcher uses.
69-(def runner
70- (when-not (fs/exists? "/run/current-system")
71- (some-> (System/getenv "NIXGL") not-empty vector)))
72-
73-(System/exit
74- (:exit @(apply p/process
75- {:inherit true
76- :dir root
77- :extra-env {"LD_LIBRARY_PATH"
78- (->> [(System/getenv "JOLT_NATIVE_LIB")
79- (System/getenv "FRQ_LIB_PATH")
80- (System/getenv "LD_LIBRARY_PATH")]
81- (remove str/blank?)
82- (str/join ":"))}}
83- (concat runner ["jolt" "-Sdeps" overrides "-M:frq"] *command-line-args*))))
deleted scripts/tui.bb +0 -58
deleted file mode 100755
@@ -1,58 +0,0 @@
1-#!/bin/sh
2-#_(
3-exec "$(dirname "$0")/bb" "$0" "$@"
4-)
5-
6-;; frq's screens in a terminal, from this working tree.
7-;;
8-;; tui.bb [--headless] [--demo] [--cols=N] [--rows=N] [--wait=MS] [--dump]
9-;;
10-;; run.bb with the other backend under it, and the same two halves: the frq
11-;; source is the files on disk, and everything below it is the flake's. The
12-;; dev shell builds jolt-native and names both Jolt sides of it — glimmer-vidya
13-;; for the window, glimmer-tui for the terminal — so this needs no checkout
14-;; beside the tree and no library fetched by digest.
15-;;
16-;; It still loads libvidya as well as libjolttui. `frq.app` requires
17-;; glimmer-vidya, and `frq.tui` requires glimmer-tui after it so the backend
18-;; installed last is the terminal; the window's library is resolved and then
19-;; asked for nothing.
20-;;
21-;; No nixGL here, unlike run.bb: a terminal wants nothing from the host's GL
22-;; driver, which is the reason this output exists on machines that have none.
23-(require '[babashka.classpath :as cp])
24-(cp/add-classpath (str (babashka.fs/parent *file*)))
25-(require '[frq.paths :as paths]
26- '[babashka.fs :as fs]
27- '[babashka.process :as p]
28- '[clojure.string :as str])
29-
30-(def root (str (fs/canonicalize (fs/path (fs/parent *file*) ".."))))
31-(def self (str (fs/path root "scripts" "tui.bb")))
32-
33-;; Outside the shell, get inside it and come back to this same script — the
34-;; test, the flag and the reasoning are run.bb's.
35-(when-not (System/getenv "JOLT_NATIVE_LIB")
36- (let [cmd (paths/nix root
37- ["nix" "develop" root
38- "--max-jobs" (paths/env "FRQ_MAX_JOBS" "0")
39- "--command" self]
40- *command-line-args*)]
41- (System/exit (:exit @(apply p/process {:inherit true :dir root} cmd)))))
42-
43-(def overrides
44- (str "{:deps {jolt-lang/glimmer {:local/root \"" (System/getenv "GLIMMER_SRC") "\"}"
45- " nandi/glimmer-vidya {:local/root \"" (System/getenv "GLIMMER_VIDYA_SRC") "\"}"
46- " nandi/glimmer-tui {:local/root \"" (System/getenv "GLIMMER_TUI_SRC") "\"}}}"))
47-
48-(System/exit
49- (:exit @(apply p/process
50- {:inherit true
51- :dir root
52- :extra-env {"LD_LIBRARY_PATH"
53- (->> [(System/getenv "JOLT_NATIVE_LIB")
54- (System/getenv "LD_LIBRARY_PATH")]
55- (remove str/blank?)
56- (str/join ":"))}}
57- (concat ["jolt" "-Sdeps" overrides "-m" "frq.tui"]
58- *command-line-args*))))
deleted file mode 100755
@@ -1,58 +0,0 @@
1-#!/bin/sh
2-#_(
3-exec "$(dirname "$0")/bb" "$0" "$@"
4-)
5-
6-;; frq's screens in a terminal, from this working tree.
7-;;
8-;; tui.bb [--headless] [--demo] [--cols=N] [--rows=N] [--wait=MS] [--dump]
9-;;
10-;; run.bb with the other backend under it, and the same two halves: the frq
11-;; source is the files on disk, and everything below it is the flake's. The
12-;; dev shell builds jolt-native and names both Jolt sides of it — glimmer-vidya
13-;; for the window, glimmer-tui for the terminal — so this needs no checkout
14-;; beside the tree and no library fetched by digest.
15-;;
16-;; It still loads libvidya as well as libjolttui. `frq.app` requires
17-;; glimmer-vidya, and `frq.tui` requires glimmer-tui after it so the backend
18-;; installed last is the terminal; the window's library is resolved and then
19-;; asked for nothing.
20-;;
21-;; No nixGL here, unlike run.bb: a terminal wants nothing from the host's GL
22-;; driver, which is the reason this output exists on machines that have none.
23-(require '[babashka.classpath :as cp])
24-(cp/add-classpath (str (babashka.fs/parent *file*)))
25-(require '[frq.paths :as paths]
26- '[babashka.fs :as fs]
27- '[babashka.process :as p]
28- '[clojure.string :as str])
29-
30-(def root (str (fs/canonicalize (fs/path (fs/parent *file*) ".."))))
31-(def self (str (fs/path root "scripts" "tui.bb")))
32-
33-;; Outside the shell, get inside it and come back to this same script — the
34-;; test, the flag and the reasoning are run.bb's.
35-(when-not (System/getenv "JOLT_NATIVE_LIB")
36- (let [cmd (paths/nix root
37- ["nix" "develop" root
38- "--max-jobs" (paths/env "FRQ_MAX_JOBS" "0")
39- "--command" self]
40- *command-line-args*)]
41- (System/exit (:exit @(apply p/process {:inherit true :dir root} cmd)))))
42-
43-(def overrides
44- (str "{:deps {jolt-lang/glimmer {:local/root \"" (System/getenv "GLIMMER_SRC") "\"}"
45- " nandi/glimmer-vidya {:local/root \"" (System/getenv "GLIMMER_VIDYA_SRC") "\"}"
46- " nandi/glimmer-tui {:local/root \"" (System/getenv "GLIMMER_TUI_SRC") "\"}}}"))
47-
48-(System/exit
49- (:exit @(apply p/process
50- {:inherit true
51- :dir root
52- :extra-env {"LD_LIBRARY_PATH"
53- (->> [(System/getenv "JOLT_NATIVE_LIB")
54- (System/getenv "LD_LIBRARY_PATH")]
55- (remove str/blank?)
56- (str/join ":"))}}
57- (concat ["jolt" "-Sdeps" overrides "-m" "frq.tui"]
58- *command-line-args*))))