| Inline the babashka scripts into the justfile 76dcc6c nandi 11d ago | 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. |
| Take glimmer-vidya from gitlab, so a stranger can build this 5c40e75 nandi 19d ago | 11 | |
| Write the build in babashka, and pin the babashka 34832a8 nandi 18d ago | 12 | set shell := ["bash", "-euo", "pipefail", "-c"] |
| A freeq client in jolt, as glimmer components on Vidya 4719d6f nandi 20d ago | 13 | |
| Inline the babashka scripts into the justfile 76dcc6c nandi 11d ago | 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 | |
| A freeq client in jolt, as glimmer components on Vidya 4719d6f nandi 20d ago | 26 | default: |
| 27 | @just --list |
| 28 | |
| Inline the babashka scripts into the justfile 76dcc6c nandi 11d ago | 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 | # |
| Build the APK as derivations only, and retire the buck2 graph 3bc3aaa nandi 16d ago | 49 | # The APK, out of the flake. `just apk install` puts it on the device. |
| Build the APK with buck2, from pins rather than from a second checkout a71ef8f nandi 19d ago | 50 | apk action="build": |
| Inline the babashka scripts into the justfile 76dcc6c nandi 11d ago | 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; } |
| Write the build in babashka, and pin the babashka 34832a8 nandi 18d ago | 78 | |
| Inline the babashka scripts into the justfile 76dcc6c nandi 11d ago | 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 | # |
| Run this tree on a native half the builders made a32699e nandi 17d ago | 108 | # The app: this tree's source on the flake's everything-else, in the dev shell. |
| A freeq client in jolt, as glimmer components on Vidya 4719d6f nandi 20d ago | 109 | run *args: |
| Inline the babashka scripts into the justfile 76dcc6c nandi 11d ago | 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}" |
| Paint the same screens into a terminal ab83b42 nandi 17d ago | 125 | |
| Inline the babashka scripts into the justfile 76dcc6c nandi 11d ago | 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 | # |
| Paint the same screens into a terminal ab83b42 nandi 17d ago | 141 | # The same screens in a terminal. `just tui --headless` prints one screenshot. |
| 142 | tui *args: |
| Inline the babashka scripts into the justfile 76dcc6c nandi 11d ago | 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}" |
| Build the desktop libraries rather than fetching a release of them 0b81161 nandi 15d ago | 155 | |
| Inline the babashka scripts into the justfile 76dcc6c nandi 11d ago | 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 | # |
| Build the desktop libraries rather than fetching a release of them 0b81161 nandi 15d ago | 164 | # A jolt with the native libraries under it: a REPL, or `just repl nrepl-server`. |
| 165 | repl *args: |
| Inline the babashka scripts into the justfile 76dcc6c nandi 11d ago | 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" "$@" |