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>
76dcc6c parent: 4f38d68 modified
README.md +4 -4 | @@ -40,10 +40,10 @@ The app: | ||
| 40 | 40 | just run |
| 41 | 41 | ``` |
| 42 | 42 | |
| 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. | |
| 47 | 47 | |
| 48 | 48 | `just run` is `jolt -M:frq` inside `nix develop`, with `LD_LIBRARY_PATH` |
| 49 | 49 | pointed at the shell's `JOLT_NATIVE_LIB` — the flake's build of |
| @@ -40,10 +40,10 @@ The app: | |||
| 40 | just run | 40 | just run |
| 41 | ``` | 41 | ``` |
| 42 | 42 | ||
| 43 | -The scripts under `scripts/` are babashka, reached through `scripts/bb`: a bb | 43 | +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 the | 44 | +`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 installed | 45 | +`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 of | 49 | pointed at the shell's `JOLT_NATIVE_LIB` — the flake's build of |
modified
flake.nix +9 -17 | @@ -339,12 +339,6 @@ | ||
| 339 | 339 | jolt = joltRuntime; |
| 340 | 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 | 342 | # frq and everything it loads, squashed into one runnable file for |
| 349 | 343 | # hosts without Nix. The whole closure rides along — Mesa included, |
| 350 | 344 | # which is not waste: off NixOS the launcher goes through nixGL, and |
| @@ -380,7 +374,7 @@ | ||
| 380 | 374 | # this shell hands a builder are the same derivation. |
| 381 | 375 | # |
| 382 | 376 | # 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 | |
| 384 | 378 | # the shell with --max-jobs 0, which is what sends it to the `builders` |
| 385 | 379 | # entry rather than compiling egui on a laptop. |
| 386 | 380 | devShells = forEachSystem (pkgs: |
| @@ -394,17 +388,15 @@ | ||
| 394 | 388 | |
| 395 | 389 | # jolt, because the runtime frq is run by should be the flake's |
| 396 | 390 | # 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 | |
| 405 | 397 | # 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. | |
| 408 | 400 | JOLT_NATIVE_LIB = "${native}/lib"; |
| 409 | 401 | GLIMMER_SRC = glimmer; |
| 410 | 402 | 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 for | 342 | # 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, and | 344 | # 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, and | 376 | # 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 |
| 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's | 389 | # 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 — see | 390 | # too. nixGL for the same reason the launcher reaches for it — see |
| 397 | - # frqScript. babashka because scripts/bb prefers one on PATH, and | 391 | + # frqScript. just so the recipe runner comes from here too rather |
| 398 | - # inside here that should be this one rather than a second copy | 392 | + # than the host — `nix develop` and then `just run` is the whole of |
| 399 | - # built through `.#bb`. just so the recipe runner comes from here | 393 | + # what a machine with nix needs. |
| 400 | - # too rather than the host — `nix develop` and then `just run` is | 394 | + 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 has | 397 | # 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 | 398 | + # 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. | |
| 5 | 11 | |
| 6 | 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 | 26 | default: |
| 9 | 27 | @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 | 49 | # The APK, out of the flake. `just apk install` puts it on the device. |
| 12 | 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 | 108 | # The app: this tree's source on the flake's everything-else, in the dev shell. |
| 16 | 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 | 141 | # The same screens in a terminal. `just tui --headless` prints one screenshot. |
| 20 | 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 | 164 | # A jolt with the native libraries under it: a REPL, or `just repl nrepl-server`. |
| 24 | 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" "$@" | |
| @@ -1,25 +1,178 @@ | |||
| 1 | -# Every recipe here is one line, because the work is in scripts/ — babashka | 1 | +# 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 finds | 2 | +# 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 --list | 27 | @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 @@ | ||
| 9 | 9 | # nix build .#apk |
| 10 | 10 | # |
| 11 | 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 | 14 | # On a machine with a remote builder configured, prefer |
| 15 | 15 | # |
| @@ -9,7 +9,7 @@ | |||
| 9 | # nix build .#apk | 9 | # 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, prefer | 14 | # 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*)))) | ||