nandi/frqpublic Fork 0
f2e12af
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.

Seed the ClojureDart caches out of the flake

cljd-deps already fetches and hashes everything `clojure -M:cljd compile`
reaches the network for, but only the sandbox build consumed it: both
`just apk` and `just flutter-desktop` re-resolved Maven, gitlibs and pub
from upstream on every run, into the real ~/.m2 and ~/.gitlibs — neither
of which follows HOME, because the JVM reads user.home out of /etc/passwd.

Both shells name the output now, and both recipes seed from it once into
flutter/.home the way `apk` already seeds ANDROID_HOME, then leave it
alone. One cache between the two frontends: same compiler, same deps.edn,
so a second copy would be a second answer to what it resolved against.

Not --offline, unlike the sandbox build. These are a warm start rather
than a pin, and a pin would mean re-hashing cljd-deps before a new line
in flutter/deps.edn compiled at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandi committed 2026-09-12T09:20:59-07:00 Browse files
f2e12af parent: 553469e
modified flake.nix +29 -1
@@ -891,7 +891,13 @@
891891 # than as a version mismatch.
892892 flutter = pkgs.mkShellNoCC {
893893 name = "frq-flutter";
894- packages = [ pkgs.clojure pkgs.jdk17 pkgs.flutter pkgs.just ];
894+
895+ # git, because tools.deps resolves the ClojureDart dependency
896+ # through tools.gitlibs even when every byte of it is already in
897+ # the seeded cache — the same reason flutter-desktop-unwrapped
898+ # names it. The host's git has always been there to answer; naming
899+ # it means the shell does not depend on that.
900+ packages = [ pkgs.clojure pkgs.jdk17 pkgs.flutter pkgs.just pkgs.git ];
895901
896902 # Where the recipe copies from. Naming it here is also what makes
897903 # entering the shell build it, so the first `just apk` does not
@@ -899,6 +905,19 @@
899905 # why.
900906 FRQ_ANDROID_SDK =
901907 "${androidSdkFor pkgs.stdenv.hostPlatform.system}/libexec/android-sdk";
908+
909+ # The Maven, gitlibs and pub caches the ClojureDart compile would
910+ # otherwise fetch, plus the analyzer project it writes under
911+ # .clojuredart. Here for both of FRQ_ANDROID_SDK's reasons: it is
912+ # where the recipe copies from, and naming it is what makes
913+ # entering the shell build it.
914+ #
915+ # The compile still runs online. These are a warm start and not a
916+ # pin — `--offline` would be, and would turn adding a line to
917+ # flutter/deps.edn into a re-hash of cljd-deps before anything
918+ # compiled again. The sandbox build takes that trade because it
919+ # has no network; the loop someone edits in should not.
920+ FRQ_CLJD_DEPS = "${self.packages.${pkgs.stdenv.hostPlatform.system}.cljd-deps}";
902921 };
903922
904923 # The other desktop GUI. Same ClojureDart half as the APK — one
@@ -945,6 +964,15 @@
945964 # the store's. The recipe reads this exactly as `run` does.
946965 NIXGL = "${nixGLFor pkgs}/bin/nixGLIntel";
947966
967+ # The `flutter` shell's, deliberately the same one and for the
968+ # same reason clojure and flutter are: the ClojureDart half of
969+ # both builds is one compile over one deps.edn, so a second set of
970+ # caches would be a second answer to what it resolved against.
971+ # This recipe reads the variable directly — it is inside this
972+ # shell before it does any of the work — where `just apk` reaches
973+ # for the flake output itself.
974+ FRQ_CLJD_DEPS = "${self.packages.${pkgs.stdenv.hostPlatform.system}.cljd-deps}";
975+
948976 # The recipe's re-entry test, the way JOLT_NATIVE_LIB is the
949977 # default shell's. Nothing else sets it, so `just flutter-desktop`
950978 # outside the shell re-enters and lands back on the same recipe —
@@ -891,7 +891,13 @@
891 # than as a version mismatch.891 # than as a version mismatch.
892 flutter = pkgs.mkShellNoCC {892 flutter = pkgs.mkShellNoCC {
893 name = "frq-flutter";893 name = "frq-flutter";
894- packages = [ pkgs.clojure pkgs.jdk17 pkgs.flutter pkgs.just ];894+
895+ # git, because tools.deps resolves the ClojureDart dependency
896+ # through tools.gitlibs even when every byte of it is already in
897+ # the seeded cache — the same reason flutter-desktop-unwrapped
898+ # names it. The host's git has always been there to answer; naming
899+ # it means the shell does not depend on that.
900+ packages = [ pkgs.clojure pkgs.jdk17 pkgs.flutter pkgs.just pkgs.git ];
895 901
896 # Where the recipe copies from. Naming it here is also what makes902 # Where the recipe copies from. Naming it here is also what makes
897 # entering the shell build it, so the first `just apk` does not903 # entering the shell build it, so the first `just apk` does not
@@ -899,6 +905,19 @@
899 # why.905 # why.
900 FRQ_ANDROID_SDK =906 FRQ_ANDROID_SDK =
901 "${androidSdkFor pkgs.stdenv.hostPlatform.system}/libexec/android-sdk";907 "${androidSdkFor pkgs.stdenv.hostPlatform.system}/libexec/android-sdk";
908+
909+ # The Maven, gitlibs and pub caches the ClojureDart compile would
910+ # otherwise fetch, plus the analyzer project it writes under
911+ # .clojuredart. Here for both of FRQ_ANDROID_SDK's reasons: it is
912+ # where the recipe copies from, and naming it is what makes
913+ # entering the shell build it.
914+ #
915+ # The compile still runs online. These are a warm start and not a
916+ # pin — `--offline` would be, and would turn adding a line to
917+ # flutter/deps.edn into a re-hash of cljd-deps before anything
918+ # compiled again. The sandbox build takes that trade because it
919+ # has no network; the loop someone edits in should not.
920+ FRQ_CLJD_DEPS = "${self.packages.${pkgs.stdenv.hostPlatform.system}.cljd-deps}";
902 };921 };
903 922
904 # The other desktop GUI. Same ClojureDart half as the APK — one923 # The other desktop GUI. Same ClojureDart half as the APK — one
@@ -945,6 +964,15 @@
945 # the store's. The recipe reads this exactly as `run` does.964 # the store's. The recipe reads this exactly as `run` does.
946 NIXGL = "${nixGLFor pkgs}/bin/nixGLIntel";965 NIXGL = "${nixGLFor pkgs}/bin/nixGLIntel";
947 966
967+ # The `flutter` shell's, deliberately the same one and for the
968+ # same reason clojure and flutter are: the ClojureDart half of
969+ # both builds is one compile over one deps.edn, so a second set of
970+ # caches would be a second answer to what it resolved against.
971+ # This recipe reads the variable directly — it is inside this
972+ # shell before it does any of the work — where `just apk` reaches
973+ # for the flake output itself.
974+ FRQ_CLJD_DEPS = "${self.packages.${pkgs.stdenv.hostPlatform.system}.cljd-deps}";
975+
948 # The recipe's re-entry test, the way JOLT_NATIVE_LIB is the976 # The recipe's re-entry test, the way JOLT_NATIVE_LIB is the
949 # default shell's. Nothing else sets it, so `just flutter-desktop`977 # default shell's. Nothing else sets it, so `just flutter-desktop`
950 # outside the shell re-enters and lands back on the same recipe —978 # outside the shell re-enters and lands back on the same recipe —
modified justfile +79 -2
@@ -99,12 +99,52 @@ apk action="build":
9999 chmod -R u+w "$ANDROID_HOME"
100100 fi
101101
102+ # The compile's three caches, same flake-output-and-copy shape as the SDK
103+ # and for the same reason: tools.deps and pub both write into theirs, and
104+ # the store is read-only. What this buys is the "Resolving dependencies…
105+ # Downloading packages…" that used to open every run.
106+ deps="$(nix build --no-link --print-out-paths \
107+ "{{justfile_directory()}}#cljd-deps")"
108+
109+ # Neither of these follows HOME. Both are read off the JVM's user.home,
110+ # which comes from /etc/passwd rather than the environment — so moving
111+ # HOME below is not enough to move them, and left alone they would be the
112+ # real ~/.m2 and ~/.gitlibs, shared with every other project on the box.
113+ export GITLIBS="$HOME/gitlibs"
114+ m2="$HOME/m2"
115+ export PUB_CACHE="$HOME/.pub-cache"
116+
117+ # Seeded once each and then left alone, exactly as ANDROID_HOME is: after
118+ # the first compile these hold whatever the working tree has asked for
119+ # since, and re-copying would throw that away.
120+ seed() {
121+ [ -e "$2" ] && return 0
122+ mkdir -p "$(dirname "$2")"
123+ cp -r "$deps/$1" "$2"
124+ chmod -R u+w "$2"
125+ }
126+ seed m2 "$m2"
127+ seed gitlibs "$GITLIBS"
128+ seed pub-cache "$PUB_CACHE"
129+ seed clojuredart/cache "$PWD/.clojuredart/cache"
130+
102131 # Also the flake's. `nix shell nixpkgs#...` read the registry, which is a
103132 # different and unlocked nixpkgs — the Flutter that built the APK could
104133 # move under it without flake.lock changing a line.
105134 flutter="nix develop {{justfile_directory()}}#flutter --command"
106135
107- $flutter clojure -M:cljd compile
136+ # cljd-deps ships the analyzer project unresolved — a fixed-output
137+ # derivation may not name the store, and a resolved pub project is
138+ # nothing but store paths. So it is resolved here instead, offline,
139+ # against the cache that derivation did fetch. ClojureDart reaches for the
140+ # network only when bin/analyzer.dart is missing, and after this it is not.
141+ for helper in .clojuredart/cache/*/cljd_helper; do
142+ [ -d "$helper" ] || continue
143+ [ -e "$helper/.dart_tool/package_config.json" ] && continue
144+ ( cd "$helper" && $flutter flutter pub get --offline )
145+ done
146+
147+ $flutter clojure -Sdeps "{:mvn/local-repo \"$m2\"}" -M:cljd compile
108148
109149 # Rewritten every run: it carries absolute store paths, and the flutter
110150 # one moves whenever nixpkgs does.
@@ -311,7 +351,44 @@ flutter-desktop action="build":
311351 fi
312352 cd flutter
313353
314- clojure -M:cljd compile
354+ # The same three caches `just apk` seeds, in the same place and out of the
355+ # same flake output — one compiler, one set of dependencies, and no reason
356+ # for the two frontends to keep a copy each. `.home/` is `apk`'s directory
357+ # by name and this is the only thing put there from here, which is the
358+ # point: whichever recipe runs first pays for the copy and the other finds
359+ # it warm.
360+ #
361+ # No `nix build` here, unlike `apk`: this recipe is already inside the
362+ # shell that names FRQ_CLJD_DEPS by the time it gets this far, and `apk`
363+ # needs the path before it enters anything.
364+ #
365+ # m2 and gitlibs are set here for the reason they are set there — the JVM
366+ # reads user.home out of /etc/passwd, so neither follows HOME and left
367+ # alone they are the real ~/.m2 and ~/.gitlibs.
368+ export PUB_CACHE="$PWD/.home/.pub-cache"
369+ export GITLIBS="$PWD/.home/gitlibs"
370+ m2="$PWD/.home/m2"
371+
372+ seed() {
373+ [ -e "$2" ] && return 0
374+ mkdir -p "$(dirname "$2")"
375+ cp -r "$FRQ_CLJD_DEPS/$1" "$2"
376+ chmod -R u+w "$2"
377+ }
378+ seed m2 "$m2"
379+ seed gitlibs "$GITLIBS"
380+ seed pub-cache "$PUB_CACHE"
381+ seed clojuredart/cache "$PWD/.clojuredart/cache"
382+
383+ # Resolved here rather than in cljd-deps, which was not allowed to name
384+ # the store — see the same loop in `apk`.
385+ for helper in .clojuredart/cache/*/cljd_helper; do
386+ [ -d "$helper" ] || continue
387+ [ -e "$helper/.dart_tool/package_config.json" ] && continue
388+ ( cd "$helper" && flutter pub get --offline )
389+ done
390+
391+ clojure -Sdeps "{:mvn/local-repo \"$m2\"}" -M:cljd compile
315392 flutter build linux --debug
316393
317394 # x64/arm64 is Flutter's own name for the host arch, not uname's.
@@ -99,12 +99,52 @@ apk action="build":
99 chmod -R u+w "$ANDROID_HOME"99 chmod -R u+w "$ANDROID_HOME"
100 fi100 fi
101 101
102+ # The compile's three caches, same flake-output-and-copy shape as the SDK
103+ # and for the same reason: tools.deps and pub both write into theirs, and
104+ # the store is read-only. What this buys is the "Resolving dependencies…
105+ # Downloading packages…" that used to open every run.
106+ deps="$(nix build --no-link --print-out-paths \
107+ "{{justfile_directory()}}#cljd-deps")"
108+
109+ # Neither of these follows HOME. Both are read off the JVM's user.home,
110+ # which comes from /etc/passwd rather than the environment — so moving
111+ # HOME below is not enough to move them, and left alone they would be the
112+ # real ~/.m2 and ~/.gitlibs, shared with every other project on the box.
113+ export GITLIBS="$HOME/gitlibs"
114+ m2="$HOME/m2"
115+ export PUB_CACHE="$HOME/.pub-cache"
116+
117+ # Seeded once each and then left alone, exactly as ANDROID_HOME is: after
118+ # the first compile these hold whatever the working tree has asked for
119+ # since, and re-copying would throw that away.
120+ seed() {
121+ [ -e "$2" ] && return 0
122+ mkdir -p "$(dirname "$2")"
123+ cp -r "$deps/$1" "$2"
124+ chmod -R u+w "$2"
125+ }
126+ seed m2 "$m2"
127+ seed gitlibs "$GITLIBS"
128+ seed pub-cache "$PUB_CACHE"
129+ seed clojuredart/cache "$PWD/.clojuredart/cache"
130+
102 # Also the flake's. `nix shell nixpkgs#...` read the registry, which is a131 # Also the flake's. `nix shell nixpkgs#...` read the registry, which is a
103 # different and unlocked nixpkgs — the Flutter that built the APK could132 # different and unlocked nixpkgs — the Flutter that built the APK could
104 # move under it without flake.lock changing a line.133 # move under it without flake.lock changing a line.
105 flutter="nix develop {{justfile_directory()}}#flutter --command"134 flutter="nix develop {{justfile_directory()}}#flutter --command"
106 135
107- $flutter clojure -M:cljd compile136+ # cljd-deps ships the analyzer project unresolved — a fixed-output
137+ # derivation may not name the store, and a resolved pub project is
138+ # nothing but store paths. So it is resolved here instead, offline,
139+ # against the cache that derivation did fetch. ClojureDart reaches for the
140+ # network only when bin/analyzer.dart is missing, and after this it is not.
141+ for helper in .clojuredart/cache/*/cljd_helper; do
142+ [ -d "$helper" ] || continue
143+ [ -e "$helper/.dart_tool/package_config.json" ] && continue
144+ ( cd "$helper" && $flutter flutter pub get --offline )
145+ done
146+
147+ $flutter clojure -Sdeps "{:mvn/local-repo \"$m2\"}" -M:cljd compile
108 148
109 # Rewritten every run: it carries absolute store paths, and the flutter149 # Rewritten every run: it carries absolute store paths, and the flutter
110 # one moves whenever nixpkgs does.150 # one moves whenever nixpkgs does.
@@ -311,7 +351,44 @@ flutter-desktop action="build":
311 fi351 fi
312 cd flutter352 cd flutter
313 353
314- clojure -M:cljd compile354+ # The same three caches `just apk` seeds, in the same place and out of the
355+ # same flake output — one compiler, one set of dependencies, and no reason
356+ # for the two frontends to keep a copy each. `.home/` is `apk`'s directory
357+ # by name and this is the only thing put there from here, which is the
358+ # point: whichever recipe runs first pays for the copy and the other finds
359+ # it warm.
360+ #
361+ # No `nix build` here, unlike `apk`: this recipe is already inside the
362+ # shell that names FRQ_CLJD_DEPS by the time it gets this far, and `apk`
363+ # needs the path before it enters anything.
364+ #
365+ # m2 and gitlibs are set here for the reason they are set there — the JVM
366+ # reads user.home out of /etc/passwd, so neither follows HOME and left
367+ # alone they are the real ~/.m2 and ~/.gitlibs.
368+ export PUB_CACHE="$PWD/.home/.pub-cache"
369+ export GITLIBS="$PWD/.home/gitlibs"
370+ m2="$PWD/.home/m2"
371+
372+ seed() {
373+ [ -e "$2" ] && return 0
374+ mkdir -p "$(dirname "$2")"
375+ cp -r "$FRQ_CLJD_DEPS/$1" "$2"
376+ chmod -R u+w "$2"
377+ }
378+ seed m2 "$m2"
379+ seed gitlibs "$GITLIBS"
380+ seed pub-cache "$PUB_CACHE"
381+ seed clojuredart/cache "$PWD/.clojuredart/cache"
382+
383+ # Resolved here rather than in cljd-deps, which was not allowed to name
384+ # the store — see the same loop in `apk`.
385+ for helper in .clojuredart/cache/*/cljd_helper; do
386+ [ -d "$helper" ] || continue
387+ [ -e "$helper/.dart_tool/package_config.json" ] && continue
388+ ( cd "$helper" && flutter pub get --offline )
389+ done
390+
391+ clojure -Sdeps "{:mvn/local-repo \"$m2\"}" -M:cljd compile
315 flutter build linux --debug392 flutter build linux --debug
316 393
317 # x64/arm64 is Flutter's own name for the host arch, not uname's.394 # x64/arm64 is Flutter's own name for the host arch, not uname's.