Working in this repo
Nix
STOP BUILDING LOCALLY. Build on Modal. This machine is for editing and for
evaluating — nix flake check, nix eval, nix build --dry-run, nix repl
— and not for realising a derivation. A local nix build .#frq gets killed for
memory long before it finishes, and the minutes spent finding that out are
minutes not spent on the change. So:
modal run containers/frq/container.py # nix build .#frq, on Modal
--dry-run locally to see what would be built, then hand the build to Modal.
The one exception is a derivation you already know is trivial and already
substitutable; if you are unsure, it is not the exception.
modal app logs is no substitute for watching that command: it resolves
deployed apps by name, not the ephemeral one a modal run creates, and carries
nothing until the Sandbox starts — the image build streams to the client and
nowhere else.
You are already running inside the Arch distrobox, where nix lives, so run
the evaluating commands directly — do not wrap them in distrobox enter.
The container runs as a Modal Sandbox on a real VM, which is what makes
nix build work out there at all: the ptyshim that used to stand in for a
working pty under gVisor is deprecated, and nothing here should reintroduce it.
Substitution comes from the nix-cache Modal Volume plus cache.nixos.org and
nix-cache.wasix.org — libjoltcosmic's dependency tree is the one that makes
that cache worth having.
A remote builder (eu.nixbuild.net) is also configured here, for the case
where you want the graph built somewhere other than Modal: --store ssh-ng://eu.nixbuild.net --eval-store auto rather than a builders entry, so
the whole graph stays there and only .drv files go up.
One thing this container is not representative of: /etc/localtime is a
regular file here rather than a symlink, so anything that reads the zone out
of its path sees nothing. That is a real deployment shape, not an artefact —
frq.clock handles it.
Never pipe a long task through tail
tail and head do not emit anything until their input ends, so a build, a
test run or a deploy piped through one shows nothing at all until it is over —
and if it is killed or times out first, its output is lost with it. That is the
opposite of what you want from the commands that take longest.
Let them write to the terminal, or tee them if you want a copy to grep
afterwards:
modal run containers/frq/container.py 2>&1 | tee /tmp/frq-build.log
Trim afterwards, on the file, where the whole run is still there to re-read.
The same goes for grep and awk in a live pipeline: they buffer when their
output is not a terminal, so pass --line-buffered / fflush() or watch the
file instead.
The three source trees
common/ .cljc jolt AND ClojureDart
src/ .clj jolt only
flutter/ .cljd ClojureDart only
The extension is the boundary, not a convention: ClojureDart reads .cljd and
.cljc and never .clj, jolt reads all three. So the rule for anything under
common/ is that it may not require jolt.*, glimmer* or a dart: library
— if it needs the host, it asks frq.io, and the backend that installed itself
answers. frq.io.jolt is required for its side effect by frq.app;
frq.io.dart is installed by flutter/src/frq/main.cljd, which has to await
the storage directory first.
Adding a host call means adding it to the seam in common/frq/io.cljc and to
both implementations. Name it for the result rather than the mechanism — the
seam has write-private-file! and not a chmod, because Dart has no chmod.
flutter/ builds two things, from one clojure -M:cljd compile:
just apk, out of the flake's own .#flutter shell (clojure, jdk17, flutter)
and its .#android-sdk package. Impure on purpose: Gradle fetches its own
dependencies and writes into ANDROID_HOME, so the recipe copies the store SDK
to flutter/.home and lets it finish there. It is the only APK there is — the
jolt APK, nix/android.nix, android/ and the .#apk outputs are gone,
because every backend that APK could paint with is retired.
just flutter-desktop, out of .#flutter-desktop (the same clojure and
flutter, with cmake, ninja, pkg-config and gtk3 where the JDK and the SDK are).
Impure for the network half of the same reasons and no writable-SDK dance, since
nothing writes into the store. nixGL off NixOS, like just cosmic run.
So there are two desktop GUIs and they are both first-class: just cosmic run is libcosmic under jolt, just flutter-desktop is Flutter's Linux target
over
frq.hiccup. Same screens out of common/frq/screens/, two renderers. jvui and
Vidya were experiments and are gone; libcosmic is a desktop window and does not
cross to a phone, which is what the Flutter half is for.
The consequence for common/ is that "the phone" is no longer a synonym for
"the ClojureDart side" — two targets compile it. An implementation that branches
on the platform has to ask (Platform.isAndroid) rather than assume; see
frq.io.dart/write-private-file!, where assuming cost a token its file mode.
See flutter/README.md.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
|