Take every jolt-native half from the release, and only from there
A sibling checkout used to win over the pinned release, so what an APK carried depended on which directories happened to sit beside this one. It is gone: the manifests in scripts/ are the only answer, `just lib` fetches both desktop objects out of the linux-x86_64 archive instead of cloning and cargo-building them, and android/BUCK has one branch where it had two — defs.bzl existed only to hold that fork and is deleted. scripts/bump-jolt-native.bb moves every pin at once: the tag, URL, size and digest of each archive, the release's commit in deps.edn, and the table buck reads. `just bump` for the latest release, `just bump v0.1.2` for a named one. Doing it by hand meant copying between a browser and a sha256sum, and the failure mode was a manifest still naming one release while carrying another's digest. Two things the checkout had been covering for: build-jolt-boot.bb computed glimmer-vidya's cache path itself, and had it wrong — a dependency with :deps/root lands somewhere else entirely. It asks `jolt path` now, which is the only thing that knows. build-apk.bb compiled FrqActivity.java alone, so CameraCapture never reached the dex; libjoltmoq looks that class up by name over JNI the moment a call starts the camera. It globs android/java the way the BUCK file does, and the two dexes are identical again. The one wart is in lib.bb: v0.1.3's desktop libjoltmoq.so does not name libasound, so a copy is patched to. jolt-native has the real fix now, and the test for it — `patchelf --print-needed` — is what makes this go away on its own with the release that carries it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
a008d3b parent: 03d5a6b modified
.buckconfig +1 -1 | @@ -29,4 +29,4 @@ | ||
| 29 | 29 | execution_platforms = root//platforms:cache |
| 30 | 30 | |
| 31 | 31 | [project] |
| 32 | - ignore = .git,android/build,.jolt-native,buck-out | |
| 32 | + ignore = .git,android/build,build,buck-out | |
| @@ -29,4 +29,4 @@ | |||
| 29 | execution_platforms = root//platforms:cache | 29 | execution_platforms = root//platforms:cache |
| 30 | 30 | ||
| 31 | [project] | 31 | [project] |
| 32 | - ignore = .git,android/build,.jolt-native,buck-out | 32 | + ignore = .git,android/build,build,buck-out |
modified
.gitignore +3 -6 | @@ -1,17 +1,14 @@ | ||
| 1 | -# Build outputs: the boot image, the staged libraries, the APK. | |
| 1 | +# Build outputs: the boot image and the APK. | |
| 2 | 2 | /android/build/ |
| 3 | 3 | |
| 4 | -# libvidya, staged out of jolt-native by the `buck` recipe. | |
| 5 | -/android/prebuilt/ | |
| 4 | +# The native libraries `just lib` links out of the DotSlash cache. | |
| 5 | +/build/ | |
| 6 | 6 | |
| 7 | 7 | # buck2 output tree. |
| 8 | 8 | /buck-out |
| 9 | 9 | # Written by the `buck` recipe: this machine's paths, not a shared setting. |
| 10 | 10 | /.buckconfig.local |
| 11 | 11 | |
| 12 | -# jolt-native, cloned by `just lib` when there is no sibling checkout. | |
| 13 | -/.jolt-native/ | |
| 14 | - | |
| 15 | 12 | # Tool caches. |
| 16 | 13 | /.cpcache/ |
| 17 | 14 | /.jolt/ |
| @@ -1,17 +1,14 @@ | |||
| 1 | -# Build outputs: the boot image, the staged libraries, the APK. | 1 | +# Build outputs: the boot image and the APK. |
| 2 | /android/build/ | 2 | /android/build/ |
| 3 | 3 | ||
| 4 | -# libvidya, staged out of jolt-native by the `buck` recipe. | 4 | +# The native libraries `just lib` links out of the DotSlash cache. |
| 5 | -/android/prebuilt/ | 5 | +/build/ |
| 6 | 6 | ||
| 7 | # buck2 output tree. | 7 | # buck2 output tree. |
| 8 | /buck-out | 8 | /buck-out |
| 9 | # Written by the `buck` recipe: this machine's paths, not a shared setting. | 9 | # Written by the `buck` recipe: this machine's paths, not a shared setting. |
| 10 | /.buckconfig.local | 10 | /.buckconfig.local |
| 11 | 11 | ||
| 12 | -# jolt-native, cloned by `just lib` when there is no sibling checkout. | ||
| 13 | -/.jolt-native/ | ||
| 14 | - | ||
| 15 | # Tool caches. | 12 | # Tool caches. |
| 16 | /.cpcache/ | 13 | /.cpcache/ |
| 17 | /.jolt/ | 14 | /.jolt/ |
modified
README.md +20 -16 | @@ -41,16 +41,19 @@ just lib | ||
| 41 | 41 | just run |
| 42 | 42 | ``` |
| 43 | 43 | |
| 44 | -`just lib` builds [jolt-native](https://gitlab.com/nandithebull/jolt-native), | |
| 45 | -cloning it into `.jolt-native` at the pinned commit unless you already have a | |
| 46 | -sibling checkout, which wins. That repo is where every shared object this | |
| 47 | -client loads comes from: `libvidya`, the retained-tree ABI glimmer paints | |
| 48 | -through, and `libjoltmoq`, the AV media plane. They come out of one directory, | |
| 49 | -and `just run` puts that one directory on the loader path. | |
| 50 | - | |
| 51 | -`just run` is `jolt -M:frq` with `LD_LIBRARY_PATH` pointed at the built | |
| 52 | -library. It connects to `irc.freeq.at:6697` over TLS and joins `#test`. Untick | |
| 53 | -TLS on the connect screen (or point it at `127.0.0.1`) for a local server's | |
| 44 | +`just lib` fetches both shared objects this client loads — | |
| 45 | +[jolt-native](https://gitlab.com/nandithebull/jolt-native)'s `libvidya`, the | |
| 46 | +retained-tree ABI glimmer paints through, and `libjoltmoq`, the AV media plane | |
| 47 | +— out of that project's release, by the digests in `scripts/*.dotslash`, and | |
| 48 | +links them into `build/lib`. Nothing is compiled: no Rust toolchain, and no | |
| 49 | +jolt-native checkout beside this one. It needs `patchelf`, and only to name | |
| 50 | +libasound in `libjoltmoq.so`, which v0.1.3 does not — see the comment in | |
| 51 | +`scripts/lib.bb`; that goes away with the release that links it. `just bump` moves every pin to the | |
| 52 | +latest release at once, and `just bump v0.1.2` to a named one. | |
| 53 | + | |
| 54 | +`just run` is `jolt -M:frq` with `LD_LIBRARY_PATH` pointed at `build/lib`. It | |
| 55 | +connects to `irc.freeq.at:6697` over TLS and joins `#test`. Untick TLS on the | |
| 56 | +connect screen (or point it at `127.0.0.1`) for a local server's | |
| 54 | 57 | plain listener: |
| 55 | 58 | |
| 56 | 59 | ```bash |
| @@ -91,18 +94,19 @@ A refused sign-in is reported and the connection carries on as a guest. | ||
| 91 | 94 | |
| 92 | 95 | ## Android |
| 93 | 96 | |
| 94 | -An APK with two shared libraries and no Java: `libvidya.so` (vidya's Rust/egui | |
| 95 | -C ABI, which owns the event loop as the NativeActivity's own library) and | |
| 96 | -`libjoltapp.so` (frq compiled to a Chez boot image). Both native halves come | |
| 97 | -from the vidya checkout; only the boot image is frq's. | |
| 97 | +An APK whose native halves come from jolt-native's release and whose Jolt half | |
| 98 | +is frq's: `libvidya.so` (the Rust/egui C ABI, which owns the event loop as the | |
| 99 | +NativeActivity's own library), `libjoltmoq.so` (the media plane) and | |
| 100 | +`libjoltapp.so` (frq compiled to a Chez boot image, linked against both). | |
| 98 | 101 | |
| 99 | 102 | ```bash |
| 100 | 103 | ./android/build-apk.bb run # build, install, launch on a connected device |
| 101 | 104 | ./android/build-apk.bb log # logcat, filtered |
| 102 | 105 | ``` |
| 103 | 106 | |
| 104 | -Needs what vidya's Android build needs — SDK, NDK r29, and a cross-built Chez | |
| 105 | -in `~/.cache/vidya-chez-android`. | |
| 107 | +Needs an SDK and a cross-built Chez in `~/.cache/vidya-chez-android`; the NDK | |
| 108 | +comes down through `scripts/android-ndk.dotslash`. `just apk` builds the same | |
| 109 | +APK as a buck2 graph, which is the incremental way in. | |
| 106 | 110 | |
| 107 | 111 | TLS does not work there: jolt reaches OpenSSL through the dynamic loader, and |
| 108 | 112 | Android has no public `libssl` to load. The connect screen falls back to the |
| @@ -41,16 +41,19 @@ just lib | |||
| 41 | just run | 41 | just run |
| 42 | ``` | 42 | ``` |
| 43 | 43 | ||
| 44 | -`just lib` builds [jolt-native](https://gitlab.com/nandithebull/jolt-native), | 44 | +`just lib` fetches both shared objects this client loads — |
| 45 | -cloning it into `.jolt-native` at the pinned commit unless you already have a | 45 | +[jolt-native](https://gitlab.com/nandithebull/jolt-native)'s `libvidya`, the |
| 46 | -sibling checkout, which wins. That repo is where every shared object this | 46 | +retained-tree ABI glimmer paints through, and `libjoltmoq`, the AV media plane |
| 47 | -client loads comes from: `libvidya`, the retained-tree ABI glimmer paints | 47 | +— out of that project's release, by the digests in `scripts/*.dotslash`, and |
| 48 | -through, and `libjoltmoq`, the AV media plane. They come out of one directory, | 48 | +links them into `build/lib`. Nothing is compiled: no Rust toolchain, and no |
| 49 | -and `just run` puts that one directory on the loader path. | 49 | +jolt-native checkout beside this one. It needs `patchelf`, and only to name |
| 50 | - | 50 | +libasound in `libjoltmoq.so`, which v0.1.3 does not — see the comment in |
| 51 | -`just run` is `jolt -M:frq` with `LD_LIBRARY_PATH` pointed at the built | 51 | +`scripts/lib.bb`; that goes away with the release that links it. `just bump` moves every pin to the |
| 52 | -library. It connects to `irc.freeq.at:6697` over TLS and joins `#test`. Untick | 52 | +latest release at once, and `just bump v0.1.2` to a named one. |
| 53 | -TLS on the connect screen (or point it at `127.0.0.1`) for a local server's | 53 | + |
| 54 | +`just run` is `jolt -M:frq` with `LD_LIBRARY_PATH` pointed at `build/lib`. It | ||
| 55 | +connects to `irc.freeq.at:6697` over TLS and joins `#test`. Untick TLS on the | ||
| 56 | +connect screen (or point it at `127.0.0.1`) for a local server's | ||
| 54 | plain listener: | 57 | plain listener: |
| 55 | 58 | ||
| 56 | ```bash | 59 | ```bash |
| @@ -91,18 +94,19 @@ A refused sign-in is reported and the connection carries on as a guest. | |||
| 91 | 94 | ||
| 92 | ## Android | 95 | ## Android |
| 93 | 96 | ||
| 94 | -An APK with two shared libraries and no Java: `libvidya.so` (vidya's Rust/egui | 97 | +An APK whose native halves come from jolt-native's release and whose Jolt half |
| 95 | -C ABI, which owns the event loop as the NativeActivity's own library) and | 98 | +is frq's: `libvidya.so` (the Rust/egui C ABI, which owns the event loop as the |
| 96 | -`libjoltapp.so` (frq compiled to a Chez boot image). Both native halves come | 99 | +NativeActivity's own library), `libjoltmoq.so` (the media plane) and |
| 97 | -from the vidya checkout; only the boot image is frq's. | 100 | +`libjoltapp.so` (frq compiled to a Chez boot image, linked against both). |
| 98 | 101 | ||
| 99 | ```bash | 102 | ```bash |
| 100 | ./android/build-apk.bb run # build, install, launch on a connected device | 103 | ./android/build-apk.bb run # build, install, launch on a connected device |
| 101 | ./android/build-apk.bb log # logcat, filtered | 104 | ./android/build-apk.bb log # logcat, filtered |
| 102 | ``` | 105 | ``` |
| 103 | 106 | ||
| 104 | -Needs what vidya's Android build needs — SDK, NDK r29, and a cross-built Chez | 107 | +Needs an SDK and a cross-built Chez in `~/.cache/vidya-chez-android`; the NDK |
| 105 | -in `~/.cache/vidya-chez-android`. | 108 | +comes down through `scripts/android-ndk.dotslash`. `just apk` builds the same |
| 109 | +APK as a buck2 graph, which is the incremental way in. | ||
| 106 | 110 | ||
| 107 | TLS does not work there: jolt reaches OpenSSL through the dynamic loader, and | 111 | TLS does not work there: jolt reaches OpenSSL through the dynamic loader, and |
| 108 | Android has no public `libssl` to load. The connect screen falls back to the | 112 | Android has no public `libssl` to load. The connect screen falls back to the |
modified
android/BUCK +49 -34 | @@ -2,16 +2,13 @@ | ||
| 2 | 2 | # |
| 3 | 3 | # Every step the old build-apk script ran in sequence is a target here, so a change |
| 4 | 4 | # to one screen rebuilds the boot image and repackages, and touches neither the |
| 5 | -# Rust nor the Java. The two native halves come from jolt-native — libvidya out | |
| 6 | -# of its buck2 graph, the glue compiled by the NDK its scripts/ pin — and the | |
| 7 | -# rest is this repo's. | |
| 5 | +# Rust nor the Java. The two native halves and the glue come out of jolt-native's | |
| 6 | +# release, fetched by digest through scripts/*.dotslash; the rest is this repo's. | |
| 7 | +# Nothing here is built out of a jolt-native checkout, and none is needed. | |
| 8 | 8 | # |
| 9 | 9 | # The machine-specific paths are read from .buckconfig.local, which the `buck` |
| 10 | 10 | # recipe in the justfile writes. Nothing here is found by looking around the |
| 11 | 11 | # machine; if a path is missing the recipe says which. |
| 12 | -load(":defs.bzl", "glue", "libjoltmoq", "libvidya") | |
| 13 | - | |
| 14 | -_JOLT_NATIVE = read_root_config("frq", "jolt_native", "") | |
| 15 | 12 | _ANDROID_HOME = read_root_config("frq", "android_home", "") |
| 16 | 13 | _CHEZ = read_root_config("frq", "chez_android", "") |
| 17 | 14 | _OPENSSL = read_root_config("frq", "openssl_android", "") |
| @@ -21,24 +18,22 @@ _TOOLS = _ANDROID_HOME + "/build-tools/36.0.0" | ||
| 21 | 18 | _ANDROID_JAR = _ANDROID_HOME + "/platforms/android-36/android.jar" |
| 22 | 19 | # `$(...)` in a genrule cmd is a buck macro, not the shell's substitution, so |
| 23 | 20 | # everything this file runs at command time uses backticks. |
| 24 | -# This repo's own, not the other checkout's: an APK build needs a clang and an | |
| 25 | -# llvm-objcopy whether or not jolt-native is on the machine. Both resolve the | |
| 26 | -# NDK through scripts/android-ndk.dotslash, downloading it once. | |
| 21 | +# This repo's own: an APK build needs a clang and an llvm-objcopy, and neither | |
| 22 | +# is jolt-native's to supply. Both resolve the NDK through | |
| 23 | +# scripts/android-ndk.dotslash, downloading it once. | |
| 27 | 24 | _NDK_BIN = "ndk=`$(location //scripts:android-ndk-bin)`" |
| 28 | 25 | _CC = "$(location //scripts:android-cc)" |
| 29 | 26 | |
| 30 | 27 | # An absolute path for $OUT, so a command may cd without losing it. buck has |
| 31 | 28 | # already made the parent directory. Spelled out step by step because backticks |
| 32 | 29 | # do not nest. |
| 33 | -# Empty when a checkout answers for it, so the script's own lookup wins. | |
| 34 | 30 | # The archive's top directory is what strip_prefix took off, so `src` is |
| 35 | 31 | # directly inside it. Absolute, because the script is handed this and does its |
| 36 | 32 | # own directory changing. |
| 37 | -_GLIMMER_VIDYA = "" if read_root_config("frq", "libvidya", "pinned") == "checkout" else \ | |
| 38 | - "GLIMMER_VIDYA=`realpath $(location toolchains//dist:glimmer-vidya)/src` " | |
| 33 | +_GLIMMER_VIDYA = "GLIMMER_VIDYA=`realpath $(location toolchains//dist:glimmer-vidya)/src` " | |
| 39 | 34 | |
| 40 | -# jolt_main.c and the ABI's headers, as targets — see defs.bzl for which of | |
| 41 | -# the two sources answers, and why neither may be a bare path. | |
| 35 | +# jolt_main.c and the ABI's headers, as targets rather than bare paths — see | |
| 36 | +# the rules below. | |
| 42 | 37 | _GLUE_C = "`realpath $(location :glue-c)`" |
| 43 | 38 | _GLUE_INCLUDE = "`realpath $(location :glue-include)`" |
| 44 | 39 | |
| @@ -57,23 +52,43 @@ export_file( | ||
| 57 | 52 | ) |
| 58 | 53 | |
| 59 | 54 | # --- the UI half ------------------------------------------------------------ |
| 60 | -# Two ways in, and both make the library's bytes an input rather than a | |
| 61 | -# command buck would cache forever: | |
| 62 | -# | |
| 63 | -# pinned the .so out of jolt-native's release, fetched by digest. What a | |
| 64 | -# build gets by default, and what makes an APK buildable with no | |
| 65 | -# jolt-native checkout and no NDK anywhere on the machine. | |
| 66 | -# checkout the .so a sibling jolt-native just built, staged into this cell | |
| 67 | -# by the `buck` recipe. Anyone working on both repos at once | |
| 68 | -# builds what they are editing. | |
| 69 | -# | |
| 70 | -# The recipe decides which, by whether that checkout exists, and says so here. | |
| 71 | -libvidya(name = "libvidya") | |
| 55 | +# The .so out of jolt-native's release, fetched by digest — which is what makes | |
| 56 | +# an APK buildable with no jolt-native checkout and no NDK anywhere on the | |
| 57 | +# machine. A genrule rather than a path, so the library's bytes are an input to | |
| 58 | +# what reads them: an action that shelled out to build it would have nothing to | |
| 59 | +# invalidate on and would serve the same stale object forever. | |
| 60 | +genrule( | |
| 61 | + name = "libvidya", | |
| 62 | + out = "libvidya.so", | |
| 63 | + cmd = "cp $(location toolchains//dist:libvidya-android)/libvidya.so \"$OUT\"", | |
| 64 | +) | |
| 65 | + | |
| 66 | +# The media plane, out of the same archive. Necessarily the same release: | |
| 67 | +# libjoltapp links both, and pairing one release's media plane with another's | |
| 68 | +# UI is a combination nothing has tested. | |
| 69 | +genrule( | |
| 70 | + name = "libjoltmoq", | |
| 71 | + out = "libjoltmoq.so", | |
| 72 | + cmd = "cp $(location toolchains//dist:libjoltmoq-android)/libjoltmoq.so \"$OUT\"", | |
| 73 | +) | |
| 72 | 74 | |
| 73 | -# The media plane, on the same terms and from the same release. | |
| 74 | -libjoltmoq(name = "libjoltmoq") | |
| 75 | +# jolt_main.c and the ABI's headers, from the glue archive of the same release. | |
| 76 | +# Targets rather than paths for the reason above — an input is the only thing | |
| 77 | +# buck can notice a change in. | |
| 78 | +genrule( | |
| 79 | + name = "glue-c", | |
| 80 | + out = "jolt_main.c", | |
| 81 | + cmd = "cp $(location toolchains//dist:android-glue)/android/jolt_main.c \"$OUT\"", | |
| 82 | +) | |
| 75 | 83 | |
| 76 | -glue(c_name = "glue-c", include_name = "glue-include") | |
| 84 | +# A directory of headers rather than a filegroup: a filegroup keeps each file | |
| 85 | +# at its own path inside the output, so `-I` would have to name the staging | |
| 86 | +# directory again. | |
| 87 | +genrule( | |
| 88 | + name = "glue-include", | |
| 89 | + out = "include", | |
| 90 | + cmd = "cp -r $(location toolchains//dist:android-glue)/include \"$OUT\"", | |
| 91 | +) | |
| 77 | 92 | |
| 78 | 93 | # The C++ runtime, out of the same NDK the glue is compiled with. |
| 79 | 94 | # |
| @@ -96,8 +111,8 @@ genrule( | ||
| 96 | 111 | # are an input so that editing one rebuilds this; the compile itself reads them |
| 97 | 112 | # through the deps.edn the script writes. |
| 98 | 113 | # The sources here are frq's own. The other two roots the image is compiled |
| 99 | -# from — glimmer, out of the jolt cache, and glimmer-vidya, out of jolt-native | |
| 100 | -# — are outside this cell, and so are Chez's cross boot files and the pinned | |
| 114 | +# from — glimmer and glimmer-vidya, both out of the jolt cache — are outside | |
| 115 | +# this cell, and so are Chez's cross boot files and the pinned | |
| 101 | 116 | # jolt itself. None of them can be an input, so the `buck` recipe hashes them |
| 102 | 117 | # and writes the digest below; naming it in the command is what puts them in |
| 103 | 118 | # this action's identity. |
| @@ -112,9 +127,9 @@ genrule( | ||
| 112 | 127 | cmd = "# sources outside this cell: " + read_root_config("frq", "boot_stamp", "unknown") + "\n" + |
| 113 | 128 | "DOTSLASH=$(location toolchains//dist:dotslash)/dotslash " + |
| 114 | 129 | "JOLT_MANIFEST=$(location //scripts:jolt) " + |
| 115 | - # The one source root the script cannot find for itself when there | |
| 116 | - # is no jolt-native checkout. An input, so a new release recompiles | |
| 117 | - # the image. | |
| 130 | + # The one source root the script cannot find for itself: the jolt | |
| 131 | + # cache is not an action input, and this is. A new release recompiles | |
| 132 | + # the image because of it. | |
| 118 | 133 | _GLIMMER_VIDYA + |
| 119 | 134 | "$(location :build-jolt-boot.bb) \"$OUT\" >&2", |
| 120 | 135 | ) |
| @@ -2,16 +2,13 @@ | |||
| 2 | # | 2 | # |
| 3 | # Every step the old build-apk script ran in sequence is a target here, so a change | 3 | # Every step the old build-apk script ran in sequence is a target here, so a change |
| 4 | # to one screen rebuilds the boot image and repackages, and touches neither the | 4 | # to one screen rebuilds the boot image and repackages, and touches neither the |
| 5 | -# Rust nor the Java. The two native halves come from jolt-native — libvidya out | 5 | +# Rust nor the Java. The two native halves and the glue come out of jolt-native's |
| 6 | -# of its buck2 graph, the glue compiled by the NDK its scripts/ pin — and the | 6 | +# release, fetched by digest through scripts/*.dotslash; the rest is this repo's. |
| 7 | -# rest is this repo's. | 7 | +# Nothing here is built out of a jolt-native checkout, and none is needed. |
| 8 | # | 8 | # |
| 9 | # The machine-specific paths are read from .buckconfig.local, which the `buck` | 9 | # The machine-specific paths are read from .buckconfig.local, which the `buck` |
| 10 | # recipe in the justfile writes. Nothing here is found by looking around the | 10 | # recipe in the justfile writes. Nothing here is found by looking around the |
| 11 | # machine; if a path is missing the recipe says which. | 11 | # machine; if a path is missing the recipe says which. |
| 12 | -load(":defs.bzl", "glue", "libjoltmoq", "libvidya") | ||
| 13 | - | ||
| 14 | -_JOLT_NATIVE = read_root_config("frq", "jolt_native", "") | ||
| 15 | _ANDROID_HOME = read_root_config("frq", "android_home", "") | 12 | _ANDROID_HOME = read_root_config("frq", "android_home", "") |
| 16 | _CHEZ = read_root_config("frq", "chez_android", "") | 13 | _CHEZ = read_root_config("frq", "chez_android", "") |
| 17 | _OPENSSL = read_root_config("frq", "openssl_android", "") | 14 | _OPENSSL = read_root_config("frq", "openssl_android", "") |
| @@ -21,24 +18,22 @@ _TOOLS = _ANDROID_HOME + "/build-tools/36.0.0" | |||
| 21 | _ANDROID_JAR = _ANDROID_HOME + "/platforms/android-36/android.jar" | 18 | _ANDROID_JAR = _ANDROID_HOME + "/platforms/android-36/android.jar" |
| 22 | # `$(...)` in a genrule cmd is a buck macro, not the shell's substitution, so | 19 | # `$(...)` in a genrule cmd is a buck macro, not the shell's substitution, so |
| 23 | # everything this file runs at command time uses backticks. | 20 | # everything this file runs at command time uses backticks. |
| 24 | -# This repo's own, not the other checkout's: an APK build needs a clang and an | 21 | +# This repo's own: an APK build needs a clang and an llvm-objcopy, and neither |
| 25 | -# llvm-objcopy whether or not jolt-native is on the machine. Both resolve the | 22 | +# is jolt-native's to supply. Both resolve the NDK through |
| 26 | -# NDK through scripts/android-ndk.dotslash, downloading it once. | 23 | +# scripts/android-ndk.dotslash, downloading it once. |
| 27 | _NDK_BIN = "ndk=`$(location //scripts:android-ndk-bin)`" | 24 | _NDK_BIN = "ndk=`$(location //scripts:android-ndk-bin)`" |
| 28 | _CC = "$(location //scripts:android-cc)" | 25 | _CC = "$(location //scripts:android-cc)" |
| 29 | 26 | ||
| 30 | # An absolute path for $OUT, so a command may cd without losing it. buck has | 27 | # An absolute path for $OUT, so a command may cd without losing it. buck has |
| 31 | # already made the parent directory. Spelled out step by step because backticks | 28 | # already made the parent directory. Spelled out step by step because backticks |
| 32 | # do not nest. | 29 | # do not nest. |
| 33 | -# Empty when a checkout answers for it, so the script's own lookup wins. | ||
| 34 | # The archive's top directory is what strip_prefix took off, so `src` is | 30 | # The archive's top directory is what strip_prefix took off, so `src` is |
| 35 | # directly inside it. Absolute, because the script is handed this and does its | 31 | # directly inside it. Absolute, because the script is handed this and does its |
| 36 | # own directory changing. | 32 | # own directory changing. |
| 37 | -_GLIMMER_VIDYA = "" if read_root_config("frq", "libvidya", "pinned") == "checkout" else \ | 33 | +_GLIMMER_VIDYA = "GLIMMER_VIDYA=`realpath $(location toolchains//dist:glimmer-vidya)/src` " |
| 38 | - "GLIMMER_VIDYA=`realpath $(location toolchains//dist:glimmer-vidya)/src` " | ||
| 39 | 34 | ||
| 40 | -# jolt_main.c and the ABI's headers, as targets — see defs.bzl for which of | 35 | +# jolt_main.c and the ABI's headers, as targets rather than bare paths — see |
| 41 | -# the two sources answers, and why neither may be a bare path. | 36 | +# the rules below. |
| 42 | _GLUE_C = "`realpath $(location :glue-c)`" | 37 | _GLUE_C = "`realpath $(location :glue-c)`" |
| 43 | _GLUE_INCLUDE = "`realpath $(location :glue-include)`" | 38 | _GLUE_INCLUDE = "`realpath $(location :glue-include)`" |
| 44 | 39 | ||
| @@ -57,23 +52,43 @@ export_file( | |||
| 57 | ) | 52 | ) |
| 58 | 53 | ||
| 59 | # --- the UI half ------------------------------------------------------------ | 54 | # --- the UI half ------------------------------------------------------------ |
| 60 | -# Two ways in, and both make the library's bytes an input rather than a | 55 | +# The .so out of jolt-native's release, fetched by digest — which is what makes |
| 61 | -# command buck would cache forever: | 56 | +# an APK buildable with no jolt-native checkout and no NDK anywhere on the |
| 62 | -# | 57 | +# machine. A genrule rather than a path, so the library's bytes are an input to |
| 63 | -# pinned the .so out of jolt-native's release, fetched by digest. What a | 58 | +# what reads them: an action that shelled out to build it would have nothing to |
| 64 | -# build gets by default, and what makes an APK buildable with no | 59 | +# invalidate on and would serve the same stale object forever. |
| 65 | -# jolt-native checkout and no NDK anywhere on the machine. | 60 | +genrule( |
| 66 | -# checkout the .so a sibling jolt-native just built, staged into this cell | 61 | + name = "libvidya", |
| 67 | -# by the `buck` recipe. Anyone working on both repos at once | 62 | + out = "libvidya.so", |
| 68 | -# builds what they are editing. | 63 | + cmd = "cp $(location toolchains//dist:libvidya-android)/libvidya.so \"$OUT\"", |
| 69 | -# | 64 | +) |
| 70 | -# The recipe decides which, by whether that checkout exists, and says so here. | 65 | + |
| 71 | -libvidya(name = "libvidya") | 66 | +# The media plane, out of the same archive. Necessarily the same release: |
| 67 | +# libjoltapp links both, and pairing one release's media plane with another's | ||
| 68 | +# UI is a combination nothing has tested. | ||
| 69 | +genrule( | ||
| 70 | + name = "libjoltmoq", | ||
| 71 | + out = "libjoltmoq.so", | ||
| 72 | + cmd = "cp $(location toolchains//dist:libjoltmoq-android)/libjoltmoq.so \"$OUT\"", | ||
| 73 | +) | ||
| 72 | 74 | ||
| 73 | -# The media plane, on the same terms and from the same release. | 75 | +# jolt_main.c and the ABI's headers, from the glue archive of the same release. |
| 74 | -libjoltmoq(name = "libjoltmoq") | 76 | +# Targets rather than paths for the reason above — an input is the only thing |
| 77 | +# buck can notice a change in. | ||
| 78 | +genrule( | ||
| 79 | + name = "glue-c", | ||
| 80 | + out = "jolt_main.c", | ||
| 81 | + cmd = "cp $(location toolchains//dist:android-glue)/android/jolt_main.c \"$OUT\"", | ||
| 82 | +) | ||
| 75 | 83 | ||
| 76 | -glue(c_name = "glue-c", include_name = "glue-include") | 84 | +# A directory of headers rather than a filegroup: a filegroup keeps each file |
| 85 | +# at its own path inside the output, so `-I` would have to name the staging | ||
| 86 | +# directory again. | ||
| 87 | +genrule( | ||
| 88 | + name = "glue-include", | ||
| 89 | + out = "include", | ||
| 90 | + cmd = "cp -r $(location toolchains//dist:android-glue)/include \"$OUT\"", | ||
| 91 | +) | ||
| 77 | 92 | ||
| 78 | # The C++ runtime, out of the same NDK the glue is compiled with. | 93 | # The C++ runtime, out of the same NDK the glue is compiled with. |
| 79 | # | 94 | # |
| @@ -96,8 +111,8 @@ genrule( | |||
| 96 | # are an input so that editing one rebuilds this; the compile itself reads them | 111 | # are an input so that editing one rebuilds this; the compile itself reads them |
| 97 | # through the deps.edn the script writes. | 112 | # through the deps.edn the script writes. |
| 98 | # The sources here are frq's own. The other two roots the image is compiled | 113 | # The sources here are frq's own. The other two roots the image is compiled |
| 99 | -# from — glimmer, out of the jolt cache, and glimmer-vidya, out of jolt-native | 114 | +# from — glimmer and glimmer-vidya, both out of the jolt cache — are outside |
| 100 | -# — are outside this cell, and so are Chez's cross boot files and the pinned | 115 | +# this cell, and so are Chez's cross boot files and the pinned |
| 101 | # jolt itself. None of them can be an input, so the `buck` recipe hashes them | 116 | # jolt itself. None of them can be an input, so the `buck` recipe hashes them |
| 102 | # and writes the digest below; naming it in the command is what puts them in | 117 | # and writes the digest below; naming it in the command is what puts them in |
| 103 | # this action's identity. | 118 | # this action's identity. |
| @@ -112,9 +127,9 @@ genrule( | |||
| 112 | cmd = "# sources outside this cell: " + read_root_config("frq", "boot_stamp", "unknown") + "\n" + | 127 | cmd = "# sources outside this cell: " + read_root_config("frq", "boot_stamp", "unknown") + "\n" + |
| 113 | "DOTSLASH=$(location toolchains//dist:dotslash)/dotslash " + | 128 | "DOTSLASH=$(location toolchains//dist:dotslash)/dotslash " + |
| 114 | "JOLT_MANIFEST=$(location //scripts:jolt) " + | 129 | "JOLT_MANIFEST=$(location //scripts:jolt) " + |
| 115 | - # The one source root the script cannot find for itself when there | 130 | + # The one source root the script cannot find for itself: the jolt |
| 116 | - # is no jolt-native checkout. An input, so a new release recompiles | 131 | + # cache is not an action input, and this is. A new release recompiles |
| 117 | - # the image. | 132 | + # the image because of it. |
| 118 | _GLIMMER_VIDYA + | 133 | _GLIMMER_VIDYA + |
| 119 | "$(location :build-jolt-boot.bb) \"$OUT\" >&2", | 134 | "$(location :build-jolt-boot.bb) \"$OUT\" >&2", |
| 120 | ) | 135 | ) |
modified
android/build-apk.bb +45 -31 | @@ -5,21 +5,24 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | ||
| 5 | 5 | |
| 6 | 6 | ;; Glue the two halves of the frq Android app into an APK. |
| 7 | 7 | ;; |
| 8 | -;; libvidya.so the C ABI on Rust/egui, cross-compiled by buck2, and the | |
| 8 | +;; libvidya.so the C ABI on Rust/egui, out of the pinned release, and the | |
| 9 | 9 | ;; NativeActivity's own library (it holds android-activity's |
| 10 | 10 | ;; glue, so it owns the event loop) |
| 11 | +;; libjoltmoq.so the AV media plane — MoQ over QUIC, Opus, H.264, Camera2 | |
| 11 | 12 | ;; libjoltapp.so jolt-native's android/jolt_main.c plus frq's Jolt boot |
| 12 | 13 | ;; image, dlopened by the above |
| 13 | -;; classes.dex one Java class, and only because a picture chooser answers | |
| 14 | -;; through onActivityResult and a NativeActivity has nowhere | |
| 15 | -;; to deliver that | |
| 14 | +;; libc++_shared.so the NDK's C++ runtime, which libjoltmoq names | |
| 15 | +;; classes.dex two Java classes: a picture chooser answers through | |
| 16 | +;; onActivityResult and a NativeActivity has nowhere to | |
| 17 | +;; deliver that, and Camera2 has no C API worth the name | |
| 16 | 18 | ;; libssl.so OpenSSL, because the platform's own is not ours to load: an |
| 17 | 19 | ;; libcrypto.so app's linker namespace refuses /system/lib64/libssl.so, and |
| 18 | 20 | ;; without one there is no TLS at all on the phone |
| 19 | 21 | ;; |
| 20 | -;; Neither half is built here beyond that last link: the UI library comes from | |
| 21 | -;; jolt-native's `just ffi-android` and the boot image from build-jolt-boot.bb. | |
| 22 | -;; Both native pieces are jolt-native's — only the boot image is frq's. | |
| 22 | +;; Neither half is built here beyond that last link: the UI library and the glue | |
| 23 | +;; come out of jolt-native's release, fetched by digest through the DotSlash | |
| 24 | +;; pins in scripts/, and the boot image from build-jolt-boot.bb. Both native | |
| 25 | +;; pieces are jolt-native's — only the boot image is frq's. | |
| 23 | 26 | ;; |
| 24 | 27 | ;; build-apk.bb [build|install|run|log] |
| 25 | 28 | (require '[babashka.classpath :as cp]) |
| @@ -31,13 +34,6 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | ||
| 31 | 34 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) |
| 32 | 35 | (def action (or (first *command-line-args*) "build")) |
| 33 | 36 | |
| 34 | -;; Where jolt-native is, answered the way the justfile answers it: a sibling | |
| 35 | -;; checkout wins, and otherwise it is the clone `just lib` leaves under | |
| 36 | -;; .jolt-native. | |
| 37 | -(def jolt-native (paths/jolt-native root)) | |
| 38 | -(when-not (fs/directory? jolt-native) | |
| 39 | - (paths/die (str "no jolt-native at " jolt-native " — run `just lib` to clone it"))) | |
| 40 | - | |
| 41 | 37 | (def android-home (paths/env "ANDROID_HOME" (str (fs/path (fs/home) ".local" "share" "android-sdk")))) |
| 42 | 38 | (def ndk-home (paths/env "ANDROID_NDK_HOME" (str (fs/path (fs/home) ".local" "share" "android-ndk-r29")))) |
| 43 | 39 | (def chez (paths/env "CHEZ_ANDROID" (str (fs/path (fs/home) ".cache" "vidya-chez-android")))) |
| @@ -62,12 +58,17 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | ||
| 62 | 58 | (fs/path openssl "libssl.so") (fs/path openssl "libcrypto.so")]) |
| 63 | 59 | |
| 64 | 60 | ;; --- the UI half ----------------------------------------------------------- |
| 65 | -;; buck2 fetches its own NDK for this, from the pin in jolt-native's | |
| 66 | -;; scripts/android-ndk.dotslash, so the toolchain above is the only one that | |
| 67 | -;; has to be installed by hand. | |
| 68 | -(p/shell {:dir jolt-native :out *err*} "just" "ffi-android") | |
| 69 | -(def vidya-so (fs/path jolt-native "build" "android" "arm64-v8a" "libvidya.so")) | |
| 70 | -(paths/require-paths! "library" [vidya-so]) | |
| 61 | +;; The release's own object, and the glue beside it, both by digest: this build | |
| 62 | +;; compiles no Rust and needs no jolt-native checkout, exactly as the graph in | |
| 63 | +;; android/BUCK needs none. | |
| 64 | +(def vidya-so (paths/dist root "libvidya-android")) | |
| 65 | +;; The media plane, out of the same archive. The glue registers its symbols and | |
| 66 | +;; includes its header, so this is not optional beside that jolt_main.c: link | |
| 67 | +;; without it and --no-undefined says so. | |
| 68 | +(def joltmoq-so (paths/dist root "libjoltmoq-android")) | |
| 69 | +(def glue-c (paths/dist root "android-glue")) | |
| 70 | +(def glue-include (fs/path (fs/parent (fs/parent glue-c)) "include")) | |
| 71 | +(paths/require-paths! "library" [vidya-so joltmoq-so glue-c glue-include]) | |
| 71 | 72 | |
| 72 | 73 | ;; --- the Jolt half --------------------------------------------------------- |
| 73 | 74 | (p/shell (str (fs/path root "android" "build-jolt-boot.bb")) (str jolt-build)) |
| @@ -81,19 +82,24 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | ||
| 81 | 82 | "jolt.boot" "jolt_boot.o") |
| 82 | 83 | |
| 83 | 84 | ;; --- the Java half --------------------------------------------------------- |
| 84 | -;; One class: the photo chooser's result has to land somewhere, and native code | |
| 85 | -;; is not somewhere. d8 turns it into the classes.dex the runtime loads. | |
| 85 | +;; Two classes: the photo chooser's result has to land somewhere and native | |
| 86 | +;; code is not somewhere, and Camera2 has no C API worth the name. d8 turns | |
| 87 | +;; them into the classes.dex the runtime loads. | |
| 86 | 88 | (def java-build (fs/path build "java")) |
| 87 | 89 | (fs/delete-tree java-build) |
| 88 | 90 | (fs/create-dirs (fs/path java-build "classes")) |
| 89 | 91 | ;; android.jar on the class path is where every android.* type comes from; the |
| 90 | -;; JDK's own java.* is what is left, and this class uses nothing of it that | |
| 92 | +;; JDK's own java.* is what is left, and neither class uses anything of it that | |
| 91 | 93 | ;; Android does not have. (`-bootclasspath` would be the stricter way to say |
| 92 | 94 | ;; that, and javac refuses it for a release this recent.) |
| 93 | -(p/shell "javac" "--release" "17" | |
| 94 | - "--class-path" (str android-jar) | |
| 95 | - "-d" (str (fs/path java-build "classes")) | |
| 96 | - (str (fs/path root "android" "java" "uk" "nandi" "frq" "FrqActivity.java"))) | |
| 95 | +;; | |
| 96 | +;; Every class under android/java, the way android/BUCK globs them: naming one | |
| 97 | +;; here left CameraCapture out of the dex, and libjoltmoq looks that class up | |
| 98 | +;; by name over JNI the moment a call starts the camera. | |
| 99 | +(apply p/shell "javac" "--release" "17" | |
| 100 | + "--class-path" (str android-jar) | |
| 101 | + "-d" (str (fs/path java-build "classes")) | |
| 102 | + (map str (fs/glob (fs/path root "android" "java") "**.java"))) | |
| 97 | 103 | (apply p/shell (str (fs/path tools "d8")) "--min-api" api "--output" (str java-build) |
| 98 | 104 | (map str (fs/glob (fs/path java-build "classes") "**.class"))) |
| 99 | 105 | |
| @@ -101,6 +107,13 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | ||
| 101 | 107 | (fs/create-dirs arm-lib) |
| 102 | 108 | (fs/copy (fs/path java-build "classes.dex") (fs/path stage "classes.dex")) |
| 103 | 109 | (fs/copy vidya-so (fs/path arm-lib "libvidya.so")) |
| 110 | +(fs/copy joltmoq-so (fs/path arm-lib "libjoltmoq.so")) | |
| 111 | +;; openh264 is C++ and asks to be linked against libc++_shared.so by name, so | |
| 112 | +;; libjoltmoq carries it as a DT_NEEDED and the APK has to carry the object — | |
| 113 | +;; an app's linker namespace will not hand out the platform's own. | |
| 114 | +(fs/copy (fs/path ndk-bin ".." "sysroot" "usr" "lib" "aarch64-linux-android" | |
| 115 | + "libc++_shared.so") | |
| 116 | + (fs/path arm-lib "libc++_shared.so")) | |
| 104 | 117 | ;; jolt.mvn-http dlopens these by name at first use; beside the app's own |
| 105 | 118 | ;; libraries is where an app's namespace will answer for that name. |
| 106 | 119 | (doseq [lib ["libssl.so" "libcrypto.so"]] |
| @@ -108,14 +121,14 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | ||
| 108 | 121 | |
| 109 | 122 | (p/shell clang "-shared" "-fPIC" "-O2" |
| 110 | 123 | "-o" (str (fs/path arm-lib "libjoltapp.so")) |
| 111 | - (str (fs/path jolt-native "android" "jolt_main.c")) | |
| 124 | + (str glue-c) | |
| 112 | 125 | (str (fs/path jolt-build "jolt_boot.o")) |
| 113 | 126 | (str "-I" jolt-build) |
| 114 | - (str "-I" (fs/path jolt-native "crates" "jolt-vidya" "include")) | |
| 127 | + (str "-I" glue-include) | |
| 115 | 128 | (str "-L" arm-lib) |
| 116 | 129 | (str (fs/path chez "tarm64le" "boot" "tarm64le" "libkernel.a")) |
| 117 | 130 | (str (fs/path chez "lz4" "lib" "liblz4.a")) |
| 118 | - "-lvidya" "-landroid" "-llog" "-lz" "-ldl" "-lm" | |
| 131 | + "-lvidya" "-ljoltmoq" "-landroid" "-llog" "-lz" "-ldl" "-lm" | |
| 119 | 132 | "-Wl,--no-undefined") |
| 120 | 133 | |
| 121 | 134 | ;; --- the APK --------------------------------------------------------------- |
| @@ -133,7 +146,8 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | ||
| 133 | 146 | "--version-name" "0.1.0") |
| 134 | 147 | ;; Stored, not deflated: the loader maps these straight out of the APK. |
| 135 | 148 | (p/shell {:dir (str stage)} "zip" "-q" "-0" (str unaligned) |
| 136 | - "lib/arm64-v8a/libvidya.so" "lib/arm64-v8a/libjoltapp.so" | |
| 149 | + "lib/arm64-v8a/libvidya.so" "lib/arm64-v8a/libjoltmoq.so" | |
| 150 | + "lib/arm64-v8a/libc++_shared.so" "lib/arm64-v8a/libjoltapp.so" | |
| 137 | 151 | "lib/arm64-v8a/libssl.so" "lib/arm64-v8a/libcrypto.so") |
| 138 | 152 | ;; The dex is read by the runtime rather than mapped, so it may as well deflate. |
| 139 | 153 | (p/shell {:dir (str stage)} "zip" "-q" (str unaligned) "classes.dex") |
| @@ -5,21 +5,24 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | |||
| 5 | 5 | ||
| 6 | ;; Glue the two halves of the frq Android app into an APK. | 6 | ;; Glue the two halves of the frq Android app into an APK. |
| 7 | ;; | 7 | ;; |
| 8 | -;; libvidya.so the C ABI on Rust/egui, cross-compiled by buck2, and the | 8 | +;; libvidya.so the C ABI on Rust/egui, out of the pinned release, and the |
| 9 | ;; NativeActivity's own library (it holds android-activity's | 9 | ;; NativeActivity's own library (it holds android-activity's |
| 10 | ;; glue, so it owns the event loop) | 10 | ;; glue, so it owns the event loop) |
| 11 | +;; libjoltmoq.so the AV media plane — MoQ over QUIC, Opus, H.264, Camera2 | ||
| 11 | ;; libjoltapp.so jolt-native's android/jolt_main.c plus frq's Jolt boot | 12 | ;; libjoltapp.so jolt-native's android/jolt_main.c plus frq's Jolt boot |
| 12 | ;; image, dlopened by the above | 13 | ;; image, dlopened by the above |
| 13 | -;; classes.dex one Java class, and only because a picture chooser answers | 14 | +;; libc++_shared.so the NDK's C++ runtime, which libjoltmoq names |
| 14 | -;; through onActivityResult and a NativeActivity has nowhere | 15 | +;; classes.dex two Java classes: a picture chooser answers through |
| 15 | -;; to deliver that | 16 | +;; onActivityResult and a NativeActivity has nowhere to |
| 17 | +;; deliver that, and Camera2 has no C API worth the name | ||
| 16 | ;; libssl.so OpenSSL, because the platform's own is not ours to load: an | 18 | ;; libssl.so OpenSSL, because the platform's own is not ours to load: an |
| 17 | ;; libcrypto.so app's linker namespace refuses /system/lib64/libssl.so, and | 19 | ;; libcrypto.so app's linker namespace refuses /system/lib64/libssl.so, and |
| 18 | ;; without one there is no TLS at all on the phone | 20 | ;; without one there is no TLS at all on the phone |
| 19 | ;; | 21 | ;; |
| 20 | -;; Neither half is built here beyond that last link: the UI library comes from | 22 | +;; Neither half is built here beyond that last link: the UI library and the glue |
| 21 | -;; jolt-native's `just ffi-android` and the boot image from build-jolt-boot.bb. | 23 | +;; come out of jolt-native's release, fetched by digest through the DotSlash |
| 22 | -;; Both native pieces are jolt-native's — only the boot image is frq's. | 24 | +;; pins in scripts/, and the boot image from build-jolt-boot.bb. Both native |
| 25 | +;; pieces are jolt-native's — only the boot image is frq's. | ||
| 23 | ;; | 26 | ;; |
| 24 | ;; build-apk.bb [build|install|run|log] | 27 | ;; build-apk.bb [build|install|run|log] |
| 25 | (require '[babashka.classpath :as cp]) | 28 | (require '[babashka.classpath :as cp]) |
| @@ -31,13 +34,6 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | |||
| 31 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) | 34 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) |
| 32 | (def action (or (first *command-line-args*) "build")) | 35 | (def action (or (first *command-line-args*) "build")) |
| 33 | 36 | ||
| 34 | -;; Where jolt-native is, answered the way the justfile answers it: a sibling | ||
| 35 | -;; checkout wins, and otherwise it is the clone `just lib` leaves under | ||
| 36 | -;; .jolt-native. | ||
| 37 | -(def jolt-native (paths/jolt-native root)) | ||
| 38 | -(when-not (fs/directory? jolt-native) | ||
| 39 | - (paths/die (str "no jolt-native at " jolt-native " — run `just lib` to clone it"))) | ||
| 40 | - | ||
| 41 | (def android-home (paths/env "ANDROID_HOME" (str (fs/path (fs/home) ".local" "share" "android-sdk")))) | 37 | (def android-home (paths/env "ANDROID_HOME" (str (fs/path (fs/home) ".local" "share" "android-sdk")))) |
| 42 | (def ndk-home (paths/env "ANDROID_NDK_HOME" (str (fs/path (fs/home) ".local" "share" "android-ndk-r29")))) | 38 | (def ndk-home (paths/env "ANDROID_NDK_HOME" (str (fs/path (fs/home) ".local" "share" "android-ndk-r29")))) |
| 43 | (def chez (paths/env "CHEZ_ANDROID" (str (fs/path (fs/home) ".cache" "vidya-chez-android")))) | 39 | (def chez (paths/env "CHEZ_ANDROID" (str (fs/path (fs/home) ".cache" "vidya-chez-android")))) |
| @@ -62,12 +58,17 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | |||
| 62 | (fs/path openssl "libssl.so") (fs/path openssl "libcrypto.so")]) | 58 | (fs/path openssl "libssl.so") (fs/path openssl "libcrypto.so")]) |
| 63 | 59 | ||
| 64 | ;; --- the UI half ----------------------------------------------------------- | 60 | ;; --- the UI half ----------------------------------------------------------- |
| 65 | -;; buck2 fetches its own NDK for this, from the pin in jolt-native's | 61 | +;; The release's own object, and the glue beside it, both by digest: this build |
| 66 | -;; scripts/android-ndk.dotslash, so the toolchain above is the only one that | 62 | +;; compiles no Rust and needs no jolt-native checkout, exactly as the graph in |
| 67 | -;; has to be installed by hand. | 63 | +;; android/BUCK needs none. |
| 68 | -(p/shell {:dir jolt-native :out *err*} "just" "ffi-android") | 64 | +(def vidya-so (paths/dist root "libvidya-android")) |
| 69 | -(def vidya-so (fs/path jolt-native "build" "android" "arm64-v8a" "libvidya.so")) | 65 | +;; The media plane, out of the same archive. The glue registers its symbols and |
| 70 | -(paths/require-paths! "library" [vidya-so]) | 66 | +;; includes its header, so this is not optional beside that jolt_main.c: link |
| 67 | +;; without it and --no-undefined says so. | ||
| 68 | +(def joltmoq-so (paths/dist root "libjoltmoq-android")) | ||
| 69 | +(def glue-c (paths/dist root "android-glue")) | ||
| 70 | +(def glue-include (fs/path (fs/parent (fs/parent glue-c)) "include")) | ||
| 71 | +(paths/require-paths! "library" [vidya-so joltmoq-so glue-c glue-include]) | ||
| 71 | 72 | ||
| 72 | ;; --- the Jolt half --------------------------------------------------------- | 73 | ;; --- the Jolt half --------------------------------------------------------- |
| 73 | (p/shell (str (fs/path root "android" "build-jolt-boot.bb")) (str jolt-build)) | 74 | (p/shell (str (fs/path root "android" "build-jolt-boot.bb")) (str jolt-build)) |
| @@ -81,19 +82,24 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | |||
| 81 | "jolt.boot" "jolt_boot.o") | 82 | "jolt.boot" "jolt_boot.o") |
| 82 | 83 | ||
| 83 | ;; --- the Java half --------------------------------------------------------- | 84 | ;; --- the Java half --------------------------------------------------------- |
| 84 | -;; One class: the photo chooser's result has to land somewhere, and native code | 85 | +;; Two classes: the photo chooser's result has to land somewhere and native |
| 85 | -;; is not somewhere. d8 turns it into the classes.dex the runtime loads. | 86 | +;; code is not somewhere, and Camera2 has no C API worth the name. d8 turns |
| 87 | +;; them into the classes.dex the runtime loads. | ||
| 86 | (def java-build (fs/path build "java")) | 88 | (def java-build (fs/path build "java")) |
| 87 | (fs/delete-tree java-build) | 89 | (fs/delete-tree java-build) |
| 88 | (fs/create-dirs (fs/path java-build "classes")) | 90 | (fs/create-dirs (fs/path java-build "classes")) |
| 89 | ;; android.jar on the class path is where every android.* type comes from; the | 91 | ;; android.jar on the class path is where every android.* type comes from; the |
| 90 | -;; JDK's own java.* is what is left, and this class uses nothing of it that | 92 | +;; JDK's own java.* is what is left, and neither class uses anything of it that |
| 91 | ;; Android does not have. (`-bootclasspath` would be the stricter way to say | 93 | ;; Android does not have. (`-bootclasspath` would be the stricter way to say |
| 92 | ;; that, and javac refuses it for a release this recent.) | 94 | ;; that, and javac refuses it for a release this recent.) |
| 93 | -(p/shell "javac" "--release" "17" | 95 | +;; |
| 94 | - "--class-path" (str android-jar) | 96 | +;; Every class under android/java, the way android/BUCK globs them: naming one |
| 95 | - "-d" (str (fs/path java-build "classes")) | 97 | +;; here left CameraCapture out of the dex, and libjoltmoq looks that class up |
| 96 | - (str (fs/path root "android" "java" "uk" "nandi" "frq" "FrqActivity.java"))) | 98 | +;; by name over JNI the moment a call starts the camera. |
| 99 | +(apply p/shell "javac" "--release" "17" | ||
| 100 | + "--class-path" (str android-jar) | ||
| 101 | + "-d" (str (fs/path java-build "classes")) | ||
| 102 | + (map str (fs/glob (fs/path root "android" "java") "**.java"))) | ||
| 97 | (apply p/shell (str (fs/path tools "d8")) "--min-api" api "--output" (str java-build) | 103 | (apply p/shell (str (fs/path tools "d8")) "--min-api" api "--output" (str java-build) |
| 98 | (map str (fs/glob (fs/path java-build "classes") "**.class"))) | 104 | (map str (fs/glob (fs/path java-build "classes") "**.class"))) |
| 99 | 105 | ||
| @@ -101,6 +107,13 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | |||
| 101 | (fs/create-dirs arm-lib) | 107 | (fs/create-dirs arm-lib) |
| 102 | (fs/copy (fs/path java-build "classes.dex") (fs/path stage "classes.dex")) | 108 | (fs/copy (fs/path java-build "classes.dex") (fs/path stage "classes.dex")) |
| 103 | (fs/copy vidya-so (fs/path arm-lib "libvidya.so")) | 109 | (fs/copy vidya-so (fs/path arm-lib "libvidya.so")) |
| 110 | +(fs/copy joltmoq-so (fs/path arm-lib "libjoltmoq.so")) | ||
| 111 | +;; openh264 is C++ and asks to be linked against libc++_shared.so by name, so | ||
| 112 | +;; libjoltmoq carries it as a DT_NEEDED and the APK has to carry the object — | ||
| 113 | +;; an app's linker namespace will not hand out the platform's own. | ||
| 114 | +(fs/copy (fs/path ndk-bin ".." "sysroot" "usr" "lib" "aarch64-linux-android" | ||
| 115 | + "libc++_shared.so") | ||
| 116 | + (fs/path arm-lib "libc++_shared.so")) | ||
| 104 | ;; jolt.mvn-http dlopens these by name at first use; beside the app's own | 117 | ;; jolt.mvn-http dlopens these by name at first use; beside the app's own |
| 105 | ;; libraries is where an app's namespace will answer for that name. | 118 | ;; libraries is where an app's namespace will answer for that name. |
| 106 | (doseq [lib ["libssl.so" "libcrypto.so"]] | 119 | (doseq [lib ["libssl.so" "libcrypto.so"]] |
| @@ -108,14 +121,14 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | |||
| 108 | 121 | ||
| 109 | (p/shell clang "-shared" "-fPIC" "-O2" | 122 | (p/shell clang "-shared" "-fPIC" "-O2" |
| 110 | "-o" (str (fs/path arm-lib "libjoltapp.so")) | 123 | "-o" (str (fs/path arm-lib "libjoltapp.so")) |
| 111 | - (str (fs/path jolt-native "android" "jolt_main.c")) | 124 | + (str glue-c) |
| 112 | (str (fs/path jolt-build "jolt_boot.o")) | 125 | (str (fs/path jolt-build "jolt_boot.o")) |
| 113 | (str "-I" jolt-build) | 126 | (str "-I" jolt-build) |
| 114 | - (str "-I" (fs/path jolt-native "crates" "jolt-vidya" "include")) | 127 | + (str "-I" glue-include) |
| 115 | (str "-L" arm-lib) | 128 | (str "-L" arm-lib) |
| 116 | (str (fs/path chez "tarm64le" "boot" "tarm64le" "libkernel.a")) | 129 | (str (fs/path chez "tarm64le" "boot" "tarm64le" "libkernel.a")) |
| 117 | (str (fs/path chez "lz4" "lib" "liblz4.a")) | 130 | (str (fs/path chez "lz4" "lib" "liblz4.a")) |
| 118 | - "-lvidya" "-landroid" "-llog" "-lz" "-ldl" "-lm" | 131 | + "-lvidya" "-ljoltmoq" "-landroid" "-llog" "-lz" "-ldl" "-lm" |
| 119 | "-Wl,--no-undefined") | 132 | "-Wl,--no-undefined") |
| 120 | 133 | ||
| 121 | ;; --- the APK --------------------------------------------------------------- | 134 | ;; --- the APK --------------------------------------------------------------- |
| @@ -133,7 +146,8 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | |||
| 133 | "--version-name" "0.1.0") | 146 | "--version-name" "0.1.0") |
| 134 | ;; Stored, not deflated: the loader maps these straight out of the APK. | 147 | ;; Stored, not deflated: the loader maps these straight out of the APK. |
| 135 | (p/shell {:dir (str stage)} "zip" "-q" "-0" (str unaligned) | 148 | (p/shell {:dir (str stage)} "zip" "-q" "-0" (str unaligned) |
| 136 | - "lib/arm64-v8a/libvidya.so" "lib/arm64-v8a/libjoltapp.so" | 149 | + "lib/arm64-v8a/libvidya.so" "lib/arm64-v8a/libjoltmoq.so" |
| 150 | + "lib/arm64-v8a/libc++_shared.so" "lib/arm64-v8a/libjoltapp.so" | ||
| 137 | "lib/arm64-v8a/libssl.so" "lib/arm64-v8a/libcrypto.so") | 151 | "lib/arm64-v8a/libssl.so" "lib/arm64-v8a/libcrypto.so") |
| 138 | ;; The dex is read by the runtime rather than mapped, so it may as well deflate. | 152 | ;; The dex is read by the runtime rather than mapped, so it may as well deflate. |
| 139 | (p/shell {:dir (str stage)} "zip" "-q" (str unaligned) "classes.dex") | 153 | (p/shell {:dir (str stage)} "zip" "-q" (str unaligned) "classes.dex") |
modified
android/build-jolt-boot.bb +35 -24 | @@ -21,33 +21,9 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | ||
| 21 | 21 | '[clojure.string :as str]) |
| 22 | 22 | |
| 23 | 23 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) |
| 24 | -(def jolt-native (paths/jolt-native root)) | |
| 25 | 24 | (def args *command-line-args*) |
| 26 | 25 | (def stamp-only? (= "--stamp" (first args))) |
| 27 | 26 | |
| 28 | -(def glimmer | |
| 29 | - (paths/env "GLIMMER" | |
| 30 | - (str (fs/path (fs/home) ".jolt" "gitlibs" | |
| 31 | - "https___gitlab.com_nandithebull_glimmer" | |
| 32 | - (paths/dep-sha root "https://gitlab.com/nandithebull/glimmer") | |
| 33 | - "src")))) | |
| 34 | - | |
| 35 | -;; glimmer-vidya lives inside jolt-native, so a sibling checkout answers for it | |
| 36 | -;; the way it answers for libvidya; the cache is the fallback, at the sha | |
| 37 | -;; deps.edn pins. | |
| 38 | -(def glimmer-vidya | |
| 39 | - (or (paths/env "GLIMMER_VIDYA" nil) | |
| 40 | - (let [in-checkout (fs/path jolt-native "jolt" "glimmer-vidya" "src")] | |
| 41 | - (if (fs/directory? in-checkout) | |
| 42 | - (str in-checkout) | |
| 43 | - (str (fs/path (fs/home) ".jolt" "gitlibs" | |
| 44 | - "https___gitlab.com_nandithebull_jolt-native" | |
| 45 | - (paths/dep-sha root "https://gitlab.com/nandithebull/jolt-native") | |
| 46 | - "jolt" "glimmer-vidya" "src")))))) | |
| 47 | - | |
| 48 | -(paths/require-paths! "Jolt source root" [glimmer glimmer-vidya] | |
| 49 | - "run `jolt -M:frq --help` once to populate the git cache") | |
| 50 | - | |
| 51 | 27 | ;; The DotSlash-pinned jolt, not whatever is on PATH: an upstream jolt cannot |
| 52 | 28 | ;; open a TLS connection on Android — it reads the socket address out of |
| 53 | 29 | ;; `struct addrinfo` at glibc's offset, which is Bionic's `ai_canonname` — so a |
| @@ -67,6 +43,41 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | ||
| 67 | 43 | (paths/out dotslash "--" "fetch" manifest) |
| 68 | 44 | (str (fs/path root "scripts" "jolt")))))) |
| 69 | 45 | |
| 46 | +;; The two source roots that are not this repo's, asked of jolt rather than | |
| 47 | +;; guessed at. `jolt path` prints what it resolved deps.edn to, which is the | |
| 48 | +;; only thing that knows where a git dependency landed: a plain :git/sha goes | |
| 49 | +;; to one cache layout and one with :deps/root to another, and glimmer and | |
| 50 | +;; glimmer-vidya are one of each. | |
| 51 | +;; | |
| 52 | +;; GLIMMER and GLIMMER_VIDYA name them instead when a caller already knows. | |
| 53 | +;; buck sets the second: the jolt cache cannot be an action input, so that | |
| 54 | +;; build hands over the release archive it fetched by digest, and with both set | |
| 55 | +;; nothing here shells out at all. | |
| 56 | +(def roots | |
| 57 | + (delay | |
| 58 | + ;; From this tree, whatever directory the caller was in: deps.edn is what | |
| 59 | + ;; `path` reads. | |
| 60 | + (str/split (str/trim (:out (p/shell {:out :string :dir root} jolt "path"))) #":"))) | |
| 61 | + | |
| 62 | +(defn root-of [k env pred] | |
| 63 | + (or (paths/env env nil) | |
| 64 | + (first (filter pred @roots)) | |
| 65 | + (paths/die (str "jolt resolved no " (name k) " source root") | |
| 66 | + "check the :deps in deps.edn"))) | |
| 67 | + | |
| 68 | +;; Matched by name rather than by shape: a cache path carries the repo, the sha | |
| 69 | +;; and — for a dependency with a :deps/root — the root inside it, and which of | |
| 70 | +;; those it ends with is jolt's business, not this script's. | |
| 71 | +(defn names? [root s] (str/includes? root s)) | |
| 72 | + | |
| 73 | +(def glimmer-vidya | |
| 74 | + (root-of :glimmer-vidya "GLIMMER_VIDYA" #(names? % "glimmer-vidya"))) | |
| 75 | +(def glimmer | |
| 76 | + (root-of :glimmer "GLIMMER" #(and (names? % "glimmer") | |
| 77 | + (not (names? % "glimmer-vidya"))))) | |
| 78 | + | |
| 79 | +(paths/require-paths! "Jolt source root" [glimmer glimmer-vidya]) | |
| 80 | + | |
| 70 | 81 | (def module (paths/env "MODULE" "frq.app")) |
| 71 | 82 | (def chez (paths/env "CHEZ_ANDROID" (str (fs/path (fs/home) ".cache" "vidya-chez-android")))) |
| 72 | 83 | (def host-scheme (str (fs/path chez "ta6le" "bin" "ta6le" "scheme"))) |
| @@ -21,33 +21,9 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | |||
| 21 | '[clojure.string :as str]) | 21 | '[clojure.string :as str]) |
| 22 | 22 | ||
| 23 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) | 23 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) |
| 24 | -(def jolt-native (paths/jolt-native root)) | ||
| 25 | (def args *command-line-args*) | 24 | (def args *command-line-args*) |
| 26 | (def stamp-only? (= "--stamp" (first args))) | 25 | (def stamp-only? (= "--stamp" (first args))) |
| 27 | 26 | ||
| 28 | -(def glimmer | ||
| 29 | - (paths/env "GLIMMER" | ||
| 30 | - (str (fs/path (fs/home) ".jolt" "gitlibs" | ||
| 31 | - "https___gitlab.com_nandithebull_glimmer" | ||
| 32 | - (paths/dep-sha root "https://gitlab.com/nandithebull/glimmer") | ||
| 33 | - "src")))) | ||
| 34 | - | ||
| 35 | -;; glimmer-vidya lives inside jolt-native, so a sibling checkout answers for it | ||
| 36 | -;; the way it answers for libvidya; the cache is the fallback, at the sha | ||
| 37 | -;; deps.edn pins. | ||
| 38 | -(def glimmer-vidya | ||
| 39 | - (or (paths/env "GLIMMER_VIDYA" nil) | ||
| 40 | - (let [in-checkout (fs/path jolt-native "jolt" "glimmer-vidya" "src")] | ||
| 41 | - (if (fs/directory? in-checkout) | ||
| 42 | - (str in-checkout) | ||
| 43 | - (str (fs/path (fs/home) ".jolt" "gitlibs" | ||
| 44 | - "https___gitlab.com_nandithebull_jolt-native" | ||
| 45 | - (paths/dep-sha root "https://gitlab.com/nandithebull/jolt-native") | ||
| 46 | - "jolt" "glimmer-vidya" "src")))))) | ||
| 47 | - | ||
| 48 | -(paths/require-paths! "Jolt source root" [glimmer glimmer-vidya] | ||
| 49 | - "run `jolt -M:frq --help` once to populate the git cache") | ||
| 50 | - | ||
| 51 | ;; The DotSlash-pinned jolt, not whatever is on PATH: an upstream jolt cannot | 27 | ;; The DotSlash-pinned jolt, not whatever is on PATH: an upstream jolt cannot |
| 52 | ;; open a TLS connection on Android — it reads the socket address out of | 28 | ;; open a TLS connection on Android — it reads the socket address out of |
| 53 | ;; `struct addrinfo` at glibc's offset, which is Bionic's `ai_canonname` — so a | 29 | ;; `struct addrinfo` at glibc's offset, which is Bionic's `ai_canonname` — so a |
| @@ -67,6 +43,41 @@ exec "$(dirname "$0")/../scripts/bb" "$0" "$@" | |||
| 67 | (paths/out dotslash "--" "fetch" manifest) | 43 | (paths/out dotslash "--" "fetch" manifest) |
| 68 | (str (fs/path root "scripts" "jolt")))))) | 44 | (str (fs/path root "scripts" "jolt")))))) |
| 69 | 45 | ||
| 46 | +;; The two source roots that are not this repo's, asked of jolt rather than | ||
| 47 | +;; guessed at. `jolt path` prints what it resolved deps.edn to, which is the | ||
| 48 | +;; only thing that knows where a git dependency landed: a plain :git/sha goes | ||
| 49 | +;; to one cache layout and one with :deps/root to another, and glimmer and | ||
| 50 | +;; glimmer-vidya are one of each. | ||
| 51 | +;; | ||
| 52 | +;; GLIMMER and GLIMMER_VIDYA name them instead when a caller already knows. | ||
| 53 | +;; buck sets the second: the jolt cache cannot be an action input, so that | ||
| 54 | +;; build hands over the release archive it fetched by digest, and with both set | ||
| 55 | +;; nothing here shells out at all. | ||
| 56 | +(def roots | ||
| 57 | + (delay | ||
| 58 | + ;; From this tree, whatever directory the caller was in: deps.edn is what | ||
| 59 | + ;; `path` reads. | ||
| 60 | + (str/split (str/trim (:out (p/shell {:out :string :dir root} jolt "path"))) #":"))) | ||
| 61 | + | ||
| 62 | +(defn root-of [k env pred] | ||
| 63 | + (or (paths/env env nil) | ||
| 64 | + (first (filter pred @roots)) | ||
| 65 | + (paths/die (str "jolt resolved no " (name k) " source root") | ||
| 66 | + "check the :deps in deps.edn"))) | ||
| 67 | + | ||
| 68 | +;; Matched by name rather than by shape: a cache path carries the repo, the sha | ||
| 69 | +;; and — for a dependency with a :deps/root — the root inside it, and which of | ||
| 70 | +;; those it ends with is jolt's business, not this script's. | ||
| 71 | +(defn names? [root s] (str/includes? root s)) | ||
| 72 | + | ||
| 73 | +(def glimmer-vidya | ||
| 74 | + (root-of :glimmer-vidya "GLIMMER_VIDYA" #(names? % "glimmer-vidya"))) | ||
| 75 | +(def glimmer | ||
| 76 | + (root-of :glimmer "GLIMMER" #(and (names? % "glimmer") | ||
| 77 | + (not (names? % "glimmer-vidya"))))) | ||
| 78 | + | ||
| 79 | +(paths/require-paths! "Jolt source root" [glimmer glimmer-vidya]) | ||
| 80 | + | ||
| 70 | (def module (paths/env "MODULE" "frq.app")) | 81 | (def module (paths/env "MODULE" "frq.app")) |
| 71 | (def chez (paths/env "CHEZ_ANDROID" (str (fs/path (fs/home) ".cache" "vidya-chez-android")))) | 82 | (def chez (paths/env "CHEZ_ANDROID" (str (fs/path (fs/home) ".cache" "vidya-chez-android")))) |
| 72 | (def host-scheme (str (fs/path chez "ta6le" "bin" "ta6le" "scheme"))) | 83 | (def host-scheme (str (fs/path chez "ta6le" "bin" "ta6le" "scheme"))) |
deleted
android/defs.bzl +0 -86 | deleted file mode 100644 | ||
| @@ -1,86 +0,0 @@ | ||
| 1 | -# Where libvidya comes from, which is a question with two answers. | |
| 2 | -# | |
| 3 | -# A BUCK file cannot branch — `if` outside a `def` is not this dialect — and | |
| 4 | -# this is not a `select` either: it does not vary by configuration but by | |
| 5 | -# whether a checkout is sitting next to this one. So it lives in a macro. | |
| 6 | -def libvidya(name): | |
| 7 | - """The Android libvidya: a sibling checkout's, or the pinned release's. | |
| 8 | - | |
| 9 | - Either way the library's bytes are an input to what reads them, which is | |
| 10 | - the part that matters — an action that shelled out to build it would have | |
| 11 | - nothing to invalidate on and would serve the same stale object forever. | |
| 12 | - """ | |
| 13 | - if native.read_root_config("frq", "libvidya", "pinned") == "checkout": | |
| 14 | - # Staged by the `buck` recipe out of the sibling jolt-native, so that | |
| 15 | - # anyone working on both repos at once builds what they are editing. | |
| 16 | - native.export_file( | |
| 17 | - name = name, | |
| 18 | - src = "prebuilt/arm64-v8a/libvidya.so", | |
| 19 | - mode = "reference", | |
| 20 | - ) | |
| 21 | - else: | |
| 22 | - # The release, fetched by digest. This is what makes an APK buildable | |
| 23 | - # with no jolt-native checkout and no NDK anywhere on the machine. | |
| 24 | - native.genrule( | |
| 25 | - name = name, | |
| 26 | - out = "libvidya.so", | |
| 27 | - cmd = "cp $(location toolchains//dist:libvidya-android)/libvidya.so \"$OUT\"", | |
| 28 | - ) | |
| 29 | - | |
| 30 | -def libjoltmoq(name): | |
| 31 | - """The Android libjoltmoq: a sibling checkout's, or the pinned release's. | |
| 32 | - | |
| 33 | - The same two answers as libvidya, and necessarily the same one — the two | |
| 34 | - objects are built together, libjoltapp links both, and pairing one release's | |
| 35 | - media plane with another's UI is a combination nothing has tested. Both | |
| 36 | - macros read the same config key, so they cannot disagree. | |
| 37 | - """ | |
| 38 | - if native.read_root_config("frq", "libvidya", "pinned") == "checkout": | |
| 39 | - native.export_file( | |
| 40 | - name = name, | |
| 41 | - src = "prebuilt/arm64-v8a/libjoltmoq.so", | |
| 42 | - mode = "reference", | |
| 43 | - ) | |
| 44 | - else: | |
| 45 | - native.genrule( | |
| 46 | - name = name, | |
| 47 | - out = "libjoltmoq.so", | |
| 48 | - cmd = "cp $(location toolchains//dist:libjoltmoq-android)/libjoltmoq.so \"$OUT\"", | |
| 49 | - ) | |
| 50 | - | |
| 51 | -def glue(c_name, include_name): | |
| 52 | - """jolt_main.c and the ABI's headers, from wherever libvidya came from. | |
| 53 | - | |
| 54 | - Targets rather than paths, and that is the point: naming a checkout's file | |
| 55 | - by absolute path leaves buck with nothing to notice when it changes, so | |
| 56 | - editing the glue rebuilt nothing and the APK kept the old object. It has to | |
| 57 | - be an input. | |
| 58 | - """ | |
| 59 | - if native.read_root_config("frq", "libvidya", "pinned") == "checkout": | |
| 60 | - # Staged by the `buck` recipe, because a cell cannot reach outside its | |
| 61 | - # own root. | |
| 62 | - native.export_file( | |
| 63 | - name = c_name, | |
| 64 | - src = "prebuilt/glue/android/jolt_main.c", | |
| 65 | - mode = "reference", | |
| 66 | - ) | |
| 67 | - # A genrule rather than a filegroup: a filegroup keeps each file at | |
| 68 | - # its own path inside the output, so `-I` would have to name the | |
| 69 | - # staging directory again. This hands back a directory of headers. | |
| 70 | - native.genrule( | |
| 71 | - name = include_name, | |
| 72 | - out = "include", | |
| 73 | - srcs = native.glob(["prebuilt/glue/include/*.h"]), | |
| 74 | - cmd = "mkdir -p \"$OUT\" && cp $SRCS \"$OUT\"/", | |
| 75 | - ) | |
| 76 | - else: | |
| 77 | - native.genrule( | |
| 78 | - name = c_name, | |
| 79 | - out = "jolt_main.c", | |
| 80 | - cmd = "cp $(location toolchains//dist:android-glue)/android/jolt_main.c \"$OUT\"", | |
| 81 | - ) | |
| 82 | - native.genrule( | |
| 83 | - name = include_name, | |
| 84 | - out = "include", | |
| 85 | - cmd = "cp -r $(location toolchains//dist:android-glue)/include \"$OUT\"", | |
| 86 | - ) | |
| deleted file mode 100644 | |||
| @@ -1,86 +0,0 @@ | |||
| 1 | -# Where libvidya comes from, which is a question with two answers. | ||
| 2 | -# | ||
| 3 | -# A BUCK file cannot branch — `if` outside a `def` is not this dialect — and | ||
| 4 | -# this is not a `select` either: it does not vary by configuration but by | ||
| 5 | -# whether a checkout is sitting next to this one. So it lives in a macro. | ||
| 6 | -def libvidya(name): | ||
| 7 | - """The Android libvidya: a sibling checkout's, or the pinned release's. | ||
| 8 | - | ||
| 9 | - Either way the library's bytes are an input to what reads them, which is | ||
| 10 | - the part that matters — an action that shelled out to build it would have | ||
| 11 | - nothing to invalidate on and would serve the same stale object forever. | ||
| 12 | - """ | ||
| 13 | - if native.read_root_config("frq", "libvidya", "pinned") == "checkout": | ||
| 14 | - # Staged by the `buck` recipe out of the sibling jolt-native, so that | ||
| 15 | - # anyone working on both repos at once builds what they are editing. | ||
| 16 | - native.export_file( | ||
| 17 | - name = name, | ||
| 18 | - src = "prebuilt/arm64-v8a/libvidya.so", | ||
| 19 | - mode = "reference", | ||
| 20 | - ) | ||
| 21 | - else: | ||
| 22 | - # The release, fetched by digest. This is what makes an APK buildable | ||
| 23 | - # with no jolt-native checkout and no NDK anywhere on the machine. | ||
| 24 | - native.genrule( | ||
| 25 | - name = name, | ||
| 26 | - out = "libvidya.so", | ||
| 27 | - cmd = "cp $(location toolchains//dist:libvidya-android)/libvidya.so \"$OUT\"", | ||
| 28 | - ) | ||
| 29 | - | ||
| 30 | -def libjoltmoq(name): | ||
| 31 | - """The Android libjoltmoq: a sibling checkout's, or the pinned release's. | ||
| 32 | - | ||
| 33 | - The same two answers as libvidya, and necessarily the same one — the two | ||
| 34 | - objects are built together, libjoltapp links both, and pairing one release's | ||
| 35 | - media plane with another's UI is a combination nothing has tested. Both | ||
| 36 | - macros read the same config key, so they cannot disagree. | ||
| 37 | - """ | ||
| 38 | - if native.read_root_config("frq", "libvidya", "pinned") == "checkout": | ||
| 39 | - native.export_file( | ||
| 40 | - name = name, | ||
| 41 | - src = "prebuilt/arm64-v8a/libjoltmoq.so", | ||
| 42 | - mode = "reference", | ||
| 43 | - ) | ||
| 44 | - else: | ||
| 45 | - native.genrule( | ||
| 46 | - name = name, | ||
| 47 | - out = "libjoltmoq.so", | ||
| 48 | - cmd = "cp $(location toolchains//dist:libjoltmoq-android)/libjoltmoq.so \"$OUT\"", | ||
| 49 | - ) | ||
| 50 | - | ||
| 51 | -def glue(c_name, include_name): | ||
| 52 | - """jolt_main.c and the ABI's headers, from wherever libvidya came from. | ||
| 53 | - | ||
| 54 | - Targets rather than paths, and that is the point: naming a checkout's file | ||
| 55 | - by absolute path leaves buck with nothing to notice when it changes, so | ||
| 56 | - editing the glue rebuilt nothing and the APK kept the old object. It has to | ||
| 57 | - be an input. | ||
| 58 | - """ | ||
| 59 | - if native.read_root_config("frq", "libvidya", "pinned") == "checkout": | ||
| 60 | - # Staged by the `buck` recipe, because a cell cannot reach outside its | ||
| 61 | - # own root. | ||
| 62 | - native.export_file( | ||
| 63 | - name = c_name, | ||
| 64 | - src = "prebuilt/glue/android/jolt_main.c", | ||
| 65 | - mode = "reference", | ||
| 66 | - ) | ||
| 67 | - # A genrule rather than a filegroup: a filegroup keeps each file at | ||
| 68 | - # its own path inside the output, so `-I` would have to name the | ||
| 69 | - # staging directory again. This hands back a directory of headers. | ||
| 70 | - native.genrule( | ||
| 71 | - name = include_name, | ||
| 72 | - out = "include", | ||
| 73 | - srcs = native.glob(["prebuilt/glue/include/*.h"]), | ||
| 74 | - cmd = "mkdir -p \"$OUT\" && cp $SRCS \"$OUT\"/", | ||
| 75 | - ) | ||
| 76 | - else: | ||
| 77 | - native.genrule( | ||
| 78 | - name = c_name, | ||
| 79 | - out = "jolt_main.c", | ||
| 80 | - cmd = "cp $(location toolchains//dist:android-glue)/android/jolt_main.c \"$OUT\"", | ||
| 81 | - ) | ||
| 82 | - native.genrule( | ||
| 83 | - name = include_name, | ||
| 84 | - out = "include", | ||
| 85 | - cmd = "cp -r $(location toolchains//dist:android-glue)/include \"$OUT\"", | ||
| 86 | - ) | ||
modified
deps.edn +1 -1 | @@ -13,7 +13,7 @@ | ||
| 13 | 13 | :deps {jolt-lang/glimmer {:git/url "https://gitlab.com/nandithebull/glimmer" |
| 14 | 14 | :git/sha "399df371c790d690fb6e4560c3d4d7f838502857"} |
| 15 | 15 | nandi/glimmer-vidya {:git/url "https://gitlab.com/nandithebull/jolt-native" |
| 16 | - :git/sha "c71fc595f031aaa5cb461735af1865146f7b42ec" | |
| 16 | + :git/sha "fd0e21a6c5d745ff9d134f92f909665454a7a1c9" | |
| 17 | 17 | :deps/root "jolt/glimmer-vidya"}} |
| 18 | 18 | |
| 19 | 19 | ;; Both objects come from gitlab.com/nandithebull/jolt-native, one crate each, |
| @@ -13,7 +13,7 @@ | |||
| 13 | :deps {jolt-lang/glimmer {:git/url "https://gitlab.com/nandithebull/glimmer" | 13 | :deps {jolt-lang/glimmer {:git/url "https://gitlab.com/nandithebull/glimmer" |
| 14 | :git/sha "399df371c790d690fb6e4560c3d4d7f838502857"} | 14 | :git/sha "399df371c790d690fb6e4560c3d4d7f838502857"} |
| 15 | nandi/glimmer-vidya {:git/url "https://gitlab.com/nandithebull/jolt-native" | 15 | nandi/glimmer-vidya {:git/url "https://gitlab.com/nandithebull/jolt-native" |
| 16 | - :git/sha "c71fc595f031aaa5cb461735af1865146f7b42ec" | 16 | + :git/sha "fd0e21a6c5d745ff9d134f92f909665454a7a1c9" |
| 17 | :deps/root "jolt/glimmer-vidya"}} | 17 | :deps/root "jolt/glimmer-vidya"}} |
| 18 | 18 | ||
| 19 | ;; Both objects come from gitlab.com/nandithebull/jolt-native, one crate each, | 19 | ;; Both objects come from gitlab.com/nandithebull/jolt-native, one crate each, |
modified
justfile +4 -0 | @@ -20,6 +20,10 @@ buck *args: | ||
| 20 | 20 | apk action="build": |
| 21 | 21 | scripts/apk.bb {{action}} |
| 22 | 22 | |
| 23 | +# Every jolt-native pin — manifests, deps.edn, the buck table — at a release. | |
| 24 | +bump tag="": | |
| 25 | + scripts/bump-jolt-native.bb {{tag}} | |
| 26 | + | |
| 23 | 27 | # The archives scripts/*.dotslash pins, as the table buck reads. |
| 24 | 28 | sync-dist: |
| 25 | 29 | scripts/dotslash-to-buck |
| @@ -20,6 +20,10 @@ buck *args: | |||
| 20 | apk action="build": | 20 | apk action="build": |
| 21 | scripts/apk.bb {{action}} | 21 | scripts/apk.bb {{action}} |
| 22 | 22 | ||
| 23 | +# Every jolt-native pin — manifests, deps.edn, the buck table — at a release. | ||
| 24 | +bump tag="": | ||
| 25 | + scripts/bump-jolt-native.bb {{tag}} | ||
| 26 | + | ||
| 23 | # The archives scripts/*.dotslash pins, as the table buck reads. | 27 | # The archives scripts/*.dotslash pins, as the table buck reads. |
| 24 | sync-dist: | 28 | sync-dist: |
| 25 | scripts/dotslash-to-buck | 29 | scripts/dotslash-to-buck |
modified
nix/android.nix +3 -3 | @@ -1,9 +1,9 @@ | ||
| 1 | 1 | # The APK, as derivations rather than as a buck2 graph. |
| 2 | 2 | # |
| 3 | 3 | # android/BUCK builds the same five things, and does it better for a person at |
| 4 | -# a terminal: it is incremental, and it lets a sibling jolt-native checkout win | |
| 5 | -# over the pinned release so that editing the Rust rebuilds the APK. Nothing | |
| 6 | -# here replaces that. What this adds is the other build — from nothing, on a | |
| 4 | +# a terminal: it is incremental, and it fetches jolt-native's release by digest | |
| 5 | +# rather than rebuilding the world. Nothing here replaces that. What this adds | |
| 6 | +# is the other build — from nothing, on a | |
| 7 | 7 | # machine with no Android SDK, no NDK, no hand-built Chez cross target and no |
| 8 | 8 | # ~/.cache at all: |
| 9 | 9 | # |
| @@ -1,9 +1,9 @@ | |||
| 1 | # The APK, as derivations rather than as a buck2 graph. | 1 | # The APK, as derivations rather than as a buck2 graph. |
| 2 | # | 2 | # |
| 3 | # android/BUCK builds the same five things, and does it better for a person at | 3 | # android/BUCK builds the same five things, and does it better for a person at |
| 4 | -# a terminal: it is incremental, and it lets a sibling jolt-native checkout win | 4 | +# a terminal: it is incremental, and it fetches jolt-native's release by digest |
| 5 | -# over the pinned release so that editing the Rust rebuilds the APK. Nothing | 5 | +# rather than rebuilding the world. Nothing here replaces that. What this adds |
| 6 | -# here replaces that. What this adds is the other build — from nothing, on a | 6 | +# is the other build — from nothing, on a |
| 7 | # machine with no Android SDK, no NDK, no hand-built Chez cross target and no | 7 | # machine with no Android SDK, no NDK, no hand-built Chez cross target and no |
| 8 | # ~/.cache at all: | 8 | # ~/.cache at all: |
| 9 | # | 9 | # |
modified
scripts/buck.bb +3 -39 | @@ -15,7 +15,6 @@ exec "$(dirname "$0")/bb" "$0" "$@" | ||
| 15 | 15 | '[babashka.process :as p]) |
| 16 | 16 | |
| 17 | 17 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) |
| 18 | -(def jolt-native (paths/jolt-native root)) | |
| 19 | 18 | (def android-home (paths/env "ANDROID_HOME" (str (fs/path (fs/home) ".local" "share" "android-sdk")))) |
| 20 | 19 | (def chez (paths/env "CHEZ_ANDROID" (str (fs/path (fs/home) ".cache" "vidya-chez-android")))) |
| 21 | 20 | (def openssl (paths/env "OPENSSL_ANDROID" (str (fs/path (fs/home) ".cache" "frq-openssl-android" "lib")))) |
| @@ -26,52 +25,17 @@ exec "$(dirname "$0")/bb" "$0" "$@" | ||
| 26 | 25 | (fs/path chez "boot" "tarm64le" "scheme.boot") |
| 27 | 26 | (fs/path openssl "libssl.so")]) |
| 28 | 27 | |
| 29 | -;; A jolt-native checkout wins over the pinned release, so that anyone working | |
| 30 | -;; on both repos at once builds what they are editing. It is staged into this | |
| 31 | -;; tree because a buck2 cell cannot reach outside its own root, and an action | |
| 32 | -;; that shelled out to the other project would have nothing to invalidate on. | |
| 33 | -;; With no checkout the release answers instead, fetched by digest — see | |
| 34 | -;; toolchains/dist and scripts/libvidya-android.dotslash. | |
| 35 | -(def libvidya | |
| 36 | - (if (fs/directory? (fs/path jolt-native "crates")) | |
| 37 | - (let [prebuilt (fs/path root "android" "prebuilt")] | |
| 38 | - (p/shell {:dir jolt-native :out :string} "just" "ffi-android") | |
| 39 | - (fs/create-dirs (fs/path prebuilt "arm64-v8a")) | |
| 40 | - (fs/copy (fs/path jolt-native "build" "android" "arm64-v8a" "libvidya.so") | |
| 41 | - (fs/path prebuilt "arm64-v8a" "libvidya.so") | |
| 42 | - {:replace-existing true}) | |
| 43 | - ;; The media plane, staged the same way. `just ffi-android` builds both. | |
| 44 | - (fs/copy (fs/path jolt-native "build" "android" "arm64-v8a" "libjoltmoq.so") | |
| 45 | - (fs/path prebuilt "arm64-v8a" "libjoltmoq.so") | |
| 46 | - {:replace-existing true}) | |
| 47 | - ;; The glue travels with it, for the same reason: editing jolt_main.c | |
| 48 | - ;; should relink libjoltapp, and it cannot if buck only knows a path. | |
| 49 | - (fs/create-dirs (fs/path prebuilt "glue" "android")) | |
| 50 | - (fs/create-dirs (fs/path prebuilt "glue" "include")) | |
| 51 | - (fs/copy (fs/path jolt-native "android" "jolt_main.c") | |
| 52 | - (fs/path prebuilt "glue" "android" "jolt_main.c") | |
| 53 | - {:replace-existing true}) | |
| 54 | - ;; Both ABIs' headers: jolt_main.c includes joltmoq.h now, for the | |
| 55 | - ;; symbols it registers and for joltmoq_android_init. | |
| 56 | - (doseq [dir ["jolt-vidya" "jolt-moq"] | |
| 57 | - h (fs/glob (fs/path jolt-native "crates" dir "include") "*.h")] | |
| 58 | - (fs/copy h (fs/path prebuilt "glue" "include" (fs/file-name h)) | |
| 59 | - {:replace-existing true})) | |
| 60 | - "checkout") | |
| 61 | - "pinned")) | |
| 62 | - | |
| 63 | -;; The boot image's other source roots are outside this cell too; hash them | |
| 64 | -;; here so the digest reaches the action. See android/BUCK. | |
| 28 | +;; The boot image is compiled from source roots outside this cell — glimmer and | |
| 29 | +;; glimmer-vidya, out of the jolt cache — which cannot be action inputs. Hash | |
| 30 | +;; them here so the digest reaches the action instead. See android/BUCK. | |
| 65 | 31 | (def boot-stamp |
| 66 | 32 | (paths/out (str (fs/path root "android" "build-jolt-boot.bb")) "--stamp")) |
| 67 | 33 | |
| 68 | 34 | (spit (str (fs/path root ".buckconfig.local")) |
| 69 | 35 | (str "[frq]\n" |
| 70 | - " jolt_native = " jolt-native "\n" | |
| 71 | 36 | " android_home = " android-home "\n" |
| 72 | 37 | " chez_android = " chez "\n" |
| 73 | 38 | " openssl_android = " openssl "\n" |
| 74 | - " libvidya = " libvidya "\n" | |
| 75 | 39 | " boot_stamp = " boot-stamp "\n")) |
| 76 | 40 | |
| 77 | 41 | (System/exit |
| @@ -15,7 +15,6 @@ exec "$(dirname "$0")/bb" "$0" "$@" | |||
| 15 | '[babashka.process :as p]) | 15 | '[babashka.process :as p]) |
| 16 | 16 | ||
| 17 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) | 17 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) |
| 18 | -(def jolt-native (paths/jolt-native root)) | ||
| 19 | (def android-home (paths/env "ANDROID_HOME" (str (fs/path (fs/home) ".local" "share" "android-sdk")))) | 18 | (def android-home (paths/env "ANDROID_HOME" (str (fs/path (fs/home) ".local" "share" "android-sdk")))) |
| 20 | (def chez (paths/env "CHEZ_ANDROID" (str (fs/path (fs/home) ".cache" "vidya-chez-android")))) | 19 | (def chez (paths/env "CHEZ_ANDROID" (str (fs/path (fs/home) ".cache" "vidya-chez-android")))) |
| 21 | (def openssl (paths/env "OPENSSL_ANDROID" (str (fs/path (fs/home) ".cache" "frq-openssl-android" "lib")))) | 20 | (def openssl (paths/env "OPENSSL_ANDROID" (str (fs/path (fs/home) ".cache" "frq-openssl-android" "lib")))) |
| @@ -26,52 +25,17 @@ exec "$(dirname "$0")/bb" "$0" "$@" | |||
| 26 | (fs/path chez "boot" "tarm64le" "scheme.boot") | 25 | (fs/path chez "boot" "tarm64le" "scheme.boot") |
| 27 | (fs/path openssl "libssl.so")]) | 26 | (fs/path openssl "libssl.so")]) |
| 28 | 27 | ||
| 29 | -;; A jolt-native checkout wins over the pinned release, so that anyone working | 28 | +;; The boot image is compiled from source roots outside this cell — glimmer and |
| 30 | -;; on both repos at once builds what they are editing. It is staged into this | 29 | +;; glimmer-vidya, out of the jolt cache — which cannot be action inputs. Hash |
| 31 | -;; tree because a buck2 cell cannot reach outside its own root, and an action | 30 | +;; them here so the digest reaches the action instead. See android/BUCK. |
| 32 | -;; that shelled out to the other project would have nothing to invalidate on. | ||
| 33 | -;; With no checkout the release answers instead, fetched by digest — see | ||
| 34 | -;; toolchains/dist and scripts/libvidya-android.dotslash. | ||
| 35 | -(def libvidya | ||
| 36 | - (if (fs/directory? (fs/path jolt-native "crates")) | ||
| 37 | - (let [prebuilt (fs/path root "android" "prebuilt")] | ||
| 38 | - (p/shell {:dir jolt-native :out :string} "just" "ffi-android") | ||
| 39 | - (fs/create-dirs (fs/path prebuilt "arm64-v8a")) | ||
| 40 | - (fs/copy (fs/path jolt-native "build" "android" "arm64-v8a" "libvidya.so") | ||
| 41 | - (fs/path prebuilt "arm64-v8a" "libvidya.so") | ||
| 42 | - {:replace-existing true}) | ||
| 43 | - ;; The media plane, staged the same way. `just ffi-android` builds both. | ||
| 44 | - (fs/copy (fs/path jolt-native "build" "android" "arm64-v8a" "libjoltmoq.so") | ||
| 45 | - (fs/path prebuilt "arm64-v8a" "libjoltmoq.so") | ||
| 46 | - {:replace-existing true}) | ||
| 47 | - ;; The glue travels with it, for the same reason: editing jolt_main.c | ||
| 48 | - ;; should relink libjoltapp, and it cannot if buck only knows a path. | ||
| 49 | - (fs/create-dirs (fs/path prebuilt "glue" "android")) | ||
| 50 | - (fs/create-dirs (fs/path prebuilt "glue" "include")) | ||
| 51 | - (fs/copy (fs/path jolt-native "android" "jolt_main.c") | ||
| 52 | - (fs/path prebuilt "glue" "android" "jolt_main.c") | ||
| 53 | - {:replace-existing true}) | ||
| 54 | - ;; Both ABIs' headers: jolt_main.c includes joltmoq.h now, for the | ||
| 55 | - ;; symbols it registers and for joltmoq_android_init. | ||
| 56 | - (doseq [dir ["jolt-vidya" "jolt-moq"] | ||
| 57 | - h (fs/glob (fs/path jolt-native "crates" dir "include") "*.h")] | ||
| 58 | - (fs/copy h (fs/path prebuilt "glue" "include" (fs/file-name h)) | ||
| 59 | - {:replace-existing true})) | ||
| 60 | - "checkout") | ||
| 61 | - "pinned")) | ||
| 62 | - | ||
| 63 | -;; The boot image's other source roots are outside this cell too; hash them | ||
| 64 | -;; here so the digest reaches the action. See android/BUCK. | ||
| 65 | (def boot-stamp | 31 | (def boot-stamp |
| 66 | (paths/out (str (fs/path root "android" "build-jolt-boot.bb")) "--stamp")) | 32 | (paths/out (str (fs/path root "android" "build-jolt-boot.bb")) "--stamp")) |
| 67 | 33 | ||
| 68 | (spit (str (fs/path root ".buckconfig.local")) | 34 | (spit (str (fs/path root ".buckconfig.local")) |
| 69 | (str "[frq]\n" | 35 | (str "[frq]\n" |
| 70 | - " jolt_native = " jolt-native "\n" | ||
| 71 | " android_home = " android-home "\n" | 36 | " android_home = " android-home "\n" |
| 72 | " chez_android = " chez "\n" | 37 | " chez_android = " chez "\n" |
| 73 | " openssl_android = " openssl "\n" | 38 | " openssl_android = " openssl "\n" |
| 74 | - " libvidya = " libvidya "\n" | ||
| 75 | " boot_stamp = " boot-stamp "\n")) | 39 | " boot_stamp = " boot-stamp "\n")) |
| 76 | 40 | ||
| 77 | (System/exit | 41 | (System/exit |
added
scripts/bump-jolt-native.bb +158 -0 | new file mode 100755 | ||
| @@ -0,0 +1,158 @@ | ||
| 1 | +#!/bin/sh | |
| 2 | +#_( | |
| 3 | +exec "$(dirname "$0")/bb" "$0" "$@" | |
| 4 | +) | |
| 5 | + | |
| 6 | +;; Move every jolt-native pin in this tree to a release of it. | |
| 7 | +;; | |
| 8 | +;; scripts/bump-jolt-native.bb # the latest release | |
| 9 | +;; scripts/bump-jolt-native.bb v0.1.3 # a named one | |
| 10 | +;; | |
| 11 | +;; A jolt-native bump is four facts in three places: the tag, the URL, the size | |
| 12 | +;; and the digest of each archive in scripts/*.dotslash, the release's commit in | |
| 13 | +;; deps.edn, and the table buck reads, which is generated from the first. Done | |
| 14 | +;; by hand it is a lot of copying between a browser and a sha256sum, and the | |
| 15 | +;; failure mode is a manifest that still says v0.1.2 while its digest is v0.1.3's | |
| 16 | +;; — which DotSlash catches, but only on the machine that next fetches it. | |
| 17 | +;; | |
| 18 | +;; So: ask GitLab what the release holds, fetch each archive once, weigh it, | |
| 19 | +;; write the manifests back, put the release's commit in deps.edn — which is | |
| 20 | +;; what jolt resolves glimmer-vidya from, and so what the boot image compiles | |
| 21 | +;; against — and re-run dotslash-to-buck. | |
| 22 | +;; | |
| 23 | +;; Nothing here decides whether the new release is a good idea. It only makes | |
| 24 | +;; the tree say one version instead of two. | |
| 25 | +(require '[babashka.classpath :as cp]) | |
| 26 | +(cp/add-classpath (str (babashka.fs/parent *file*))) | |
| 27 | +(require '[frq.paths :as paths] | |
| 28 | + '[babashka.fs :as fs] | |
| 29 | + '[babashka.process :as p] | |
| 30 | + '[cheshire.core :as json] | |
| 31 | + '[clojure.string :as str]) | |
| 32 | + | |
| 33 | +(def here (fs/parent (fs/canonicalize *file*))) | |
| 34 | +(def root (str (fs/parent here))) | |
| 35 | +(def project "nandithebull%2Fjolt-native") | |
| 36 | +(def repo "https://gitlab.com/nandithebull/jolt-native") | |
| 37 | + | |
| 38 | +;; The release, as GitLab has it. `?per_page=1` when no tag is asked for: the | |
| 39 | +;; list is newest first, and the newest is what "latest" means here — the | |
| 40 | +;; /releases/permalink/latest endpoint sorts by release date, which is not the | |
| 41 | +;; same thing once a release is edited. | |
| 42 | +(defn release [tag] | |
| 43 | + (let [url (if tag | |
| 44 | + (str "https://gitlab.com/api/v4/projects/" project "/releases/" tag) | |
| 45 | + (str "https://gitlab.com/api/v4/projects/" project "/releases?per_page=1")) | |
| 46 | + body (json/parse-string (paths/out "curl" "-fsSL" url))] | |
| 47 | + (if tag | |
| 48 | + body | |
| 49 | + (or (first body) (paths/die (str "no releases at all under " repo)))))) | |
| 50 | + | |
| 51 | +;; The manifests this tree pins out of jolt-native. Every DotSlash file beside | |
| 52 | +;; this script whose providers point at the repo — rather than a list written | |
| 53 | +;; here, which would be a sixth place to forget. | |
| 54 | +(defn manifests [] | |
| 55 | + (->> (fs/glob here "*.dotslash") | |
| 56 | + sort | |
| 57 | + (keep (fn [file] | |
| 58 | + (let [text (slurp (str file)) | |
| 59 | + json (json/parse-string (subs text (str/index-of text "{")))] | |
| 60 | + (when (->> (get json "platforms") | |
| 61 | + vals | |
| 62 | + (some #(str/starts-with? (get-in % ["providers" 0 "url"]) repo))) | |
| 63 | + {:file file :text text :json json})))))) | |
| 64 | + | |
| 65 | +;; The archive an entry names, at the new tag. The URL a manifest carries is the | |
| 66 | +;; release permalink — /-/releases/<tag>/downloads/<asset> — so the asset's name | |
| 67 | +;; is its last segment, and the name carries the version too. Both move. | |
| 68 | +(defn retag [url old new] | |
| 69 | + (-> url | |
| 70 | + (str/replace (str "/releases/" old "/") (str "/releases/" new "/")) | |
| 71 | + (str/replace (str "-" old ".") (str "-" new ".")))) | |
| 72 | + | |
| 73 | +(defn tag-of [url] | |
| 74 | + (second (re-find #"/-/releases/([^/]+)/downloads/" url))) | |
| 75 | + | |
| 76 | +;; Fetch once per distinct URL, then weigh it: DotSlash wants the size and the | |
| 77 | +;; sha256 of the archive as downloaded, not of anything inside it. | |
| 78 | +(def weigh | |
| 79 | + (memoize | |
| 80 | + (fn [dir url] | |
| 81 | + (let [file (fs/path dir (last (str/split url #"/")))] | |
| 82 | + (println (str " fetching " (fs/file-name file))) | |
| 83 | + (p/shell "curl" "-fsSL" "-o" (str file) url) | |
| 84 | + {:size (fs/size file) | |
| 85 | + :digest (first (str/split (paths/out "sha256sum" (str file)) #"\s+")) | |
| 86 | + :file file})))) | |
| 87 | + | |
| 88 | +;; What the shim will reach for inside the archive. A release that moved a file | |
| 89 | +;; leaves a manifest that fetches and verifies and then cannot resolve, which is | |
| 90 | +;; a worse thing to find out from than this. | |
| 91 | +(defn check-path! [{:keys [file]} path] | |
| 92 | + (let [names (set (str/split-lines (paths/out "tar" "-tzf" (str file))))] | |
| 93 | + (when-not (some #(= path (str/replace % #"^\./" "")) names) | |
| 94 | + (paths/die (str "no " path " in " (fs/file-name file)) | |
| 95 | + "The release moved it; the manifest's `path` needs a hand.")))) | |
| 96 | + | |
| 97 | +;; The JSON back out, in the shape it went in: two-space indentation, a value | |
| 98 | +;; after each key, and the `//` comment block above it kept — that block is why | |
| 99 | +;; anyone reading the manifest knows what the object is for. | |
| 100 | +(def pretty | |
| 101 | + (json/create-pretty-printer | |
| 102 | + (assoc json/default-pretty-print-options | |
| 103 | + :indentation " " | |
| 104 | + :indent-arrays? true | |
| 105 | + :object-field-value-separator ": "))) | |
| 106 | + | |
| 107 | +(defn rewrite [{:keys [file text json]} tmp tag] | |
| 108 | + (let [platforms (get json "platforms") | |
| 109 | + updated | |
| 110 | + (into (array-map) | |
| 111 | + (for [[platform entry] platforms | |
| 112 | + :let [url (retag (get-in entry ["providers" 0 "url"]) (tag-of (get-in entry ["providers" 0 "url"])) tag) | |
| 113 | + {:keys [size digest] :as got} (weigh tmp url)]] | |
| 114 | + (do | |
| 115 | + (check-path! got (get entry "path")) | |
| 116 | + [platform (-> entry | |
| 117 | + (assoc "size" size "digest" digest) | |
| 118 | + (assoc-in ["providers" 0 "url"] url))]))) | |
| 119 | + head (subs text 0 (str/index-of text "{")) | |
| 120 | + ;; The prose above the JSON names the release too — "from jolt-native's | |
| 121 | + ;; v0.1.3 release". Left saying the old one it would be a lie the moment | |
| 122 | + ;; this script succeeds. | |
| 123 | + head (reduce (fn [h old] (str/replace h old tag)) | |
| 124 | + head | |
| 125 | + (distinct (keep #(tag-of (get-in % ["providers" 0 "url"])) (vals platforms))))] | |
| 126 | + (spit (str file) (str head (json/generate-string (assoc json "platforms" updated) {:pretty pretty}) "\n")) | |
| 127 | + (println (str " " (fs/file-name file))))) | |
| 128 | + | |
| 129 | +;; deps.edn takes glimmer-vidya as a git dependency, and the boot image is | |
| 130 | +;; compiled from the source root jolt resolves that to. Replaced as text rather | |
| 131 | +;; than round-tripped as EDN: the file is mostly comments explaining why each | |
| 132 | +;; pin is where it is, and rewriting it as data would throw all of them away. | |
| 133 | +(defn bump-deps! [commit] | |
| 134 | + (let [file (fs/path root "deps.edn") | |
| 135 | + text (slurp (str file)) | |
| 136 | + old (paths/dep-sha root repo)] | |
| 137 | + (cond | |
| 138 | + (nil? old) (paths/die (str "no dependency on " repo " in deps.edn")) | |
| 139 | + (= old commit) (println " deps.edn already at this commit") | |
| 140 | + :else (do (spit (str file) (str/replace text old commit)) | |
| 141 | + (println (str " deps.edn " (subs old 0 8) " -> " (subs commit 0 8))))))) | |
| 142 | + | |
| 143 | +(let [tag (first *command-line-args*) | |
| 144 | + rel (release tag) | |
| 145 | + tag (get rel "tag_name") | |
| 146 | + commit (get-in rel ["commit" "id"]) | |
| 147 | + files (manifests) | |
| 148 | + tmp (fs/create-temp-dir {:prefix "jolt-native-"})] | |
| 149 | + (when (empty? files) | |
| 150 | + (paths/die (str "no DotSlash manifest in " here " points at " repo))) | |
| 151 | + (println (str "jolt-native " tag " (" (subs commit 0 8) ")")) | |
| 152 | + (try | |
| 153 | + (doseq [m files] (rewrite m tmp tag)) | |
| 154 | + (finally (fs/delete-tree tmp))) | |
| 155 | + (bump-deps! commit) | |
| 156 | + (p/shell (str (fs/path here "dotslash-to-buck"))) | |
| 157 | + (println (str "\nNow: git diff, then `just lib` and `just apk` — the pins are " | |
| 158 | + "written, nothing is built."))) | |
| new file mode 100755 | |||
| @@ -0,0 +1,158 @@ | |||
| 1 | +#!/bin/sh | ||
| 2 | +#_( | ||
| 3 | +exec "$(dirname "$0")/bb" "$0" "$@" | ||
| 4 | +) | ||
| 5 | + | ||
| 6 | +;; Move every jolt-native pin in this tree to a release of it. | ||
| 7 | +;; | ||
| 8 | +;; scripts/bump-jolt-native.bb # the latest release | ||
| 9 | +;; scripts/bump-jolt-native.bb v0.1.3 # a named one | ||
| 10 | +;; | ||
| 11 | +;; A jolt-native bump is four facts in three places: the tag, the URL, the size | ||
| 12 | +;; and the digest of each archive in scripts/*.dotslash, the release's commit in | ||
| 13 | +;; deps.edn, and the table buck reads, which is generated from the first. Done | ||
| 14 | +;; by hand it is a lot of copying between a browser and a sha256sum, and the | ||
| 15 | +;; failure mode is a manifest that still says v0.1.2 while its digest is v0.1.3's | ||
| 16 | +;; — which DotSlash catches, but only on the machine that next fetches it. | ||
| 17 | +;; | ||
| 18 | +;; So: ask GitLab what the release holds, fetch each archive once, weigh it, | ||
| 19 | +;; write the manifests back, put the release's commit in deps.edn — which is | ||
| 20 | +;; what jolt resolves glimmer-vidya from, and so what the boot image compiles | ||
| 21 | +;; against — and re-run dotslash-to-buck. | ||
| 22 | +;; | ||
| 23 | +;; Nothing here decides whether the new release is a good idea. It only makes | ||
| 24 | +;; the tree say one version instead of two. | ||
| 25 | +(require '[babashka.classpath :as cp]) | ||
| 26 | +(cp/add-classpath (str (babashka.fs/parent *file*))) | ||
| 27 | +(require '[frq.paths :as paths] | ||
| 28 | + '[babashka.fs :as fs] | ||
| 29 | + '[babashka.process :as p] | ||
| 30 | + '[cheshire.core :as json] | ||
| 31 | + '[clojure.string :as str]) | ||
| 32 | + | ||
| 33 | +(def here (fs/parent (fs/canonicalize *file*))) | ||
| 34 | +(def root (str (fs/parent here))) | ||
| 35 | +(def project "nandithebull%2Fjolt-native") | ||
| 36 | +(def repo "https://gitlab.com/nandithebull/jolt-native") | ||
| 37 | + | ||
| 38 | +;; The release, as GitLab has it. `?per_page=1` when no tag is asked for: the | ||
| 39 | +;; list is newest first, and the newest is what "latest" means here — the | ||
| 40 | +;; /releases/permalink/latest endpoint sorts by release date, which is not the | ||
| 41 | +;; same thing once a release is edited. | ||
| 42 | +(defn release [tag] | ||
| 43 | + (let [url (if tag | ||
| 44 | + (str "https://gitlab.com/api/v4/projects/" project "/releases/" tag) | ||
| 45 | + (str "https://gitlab.com/api/v4/projects/" project "/releases?per_page=1")) | ||
| 46 | + body (json/parse-string (paths/out "curl" "-fsSL" url))] | ||
| 47 | + (if tag | ||
| 48 | + body | ||
| 49 | + (or (first body) (paths/die (str "no releases at all under " repo)))))) | ||
| 50 | + | ||
| 51 | +;; The manifests this tree pins out of jolt-native. Every DotSlash file beside | ||
| 52 | +;; this script whose providers point at the repo — rather than a list written | ||
| 53 | +;; here, which would be a sixth place to forget. | ||
| 54 | +(defn manifests [] | ||
| 55 | + (->> (fs/glob here "*.dotslash") | ||
| 56 | + sort | ||
| 57 | + (keep (fn [file] | ||
| 58 | + (let [text (slurp (str file)) | ||
| 59 | + json (json/parse-string (subs text (str/index-of text "{")))] | ||
| 60 | + (when (->> (get json "platforms") | ||
| 61 | + vals | ||
| 62 | + (some #(str/starts-with? (get-in % ["providers" 0 "url"]) repo))) | ||
| 63 | + {:file file :text text :json json})))))) | ||
| 64 | + | ||
| 65 | +;; The archive an entry names, at the new tag. The URL a manifest carries is the | ||
| 66 | +;; release permalink — /-/releases/<tag>/downloads/<asset> — so the asset's name | ||
| 67 | +;; is its last segment, and the name carries the version too. Both move. | ||
| 68 | +(defn retag [url old new] | ||
| 69 | + (-> url | ||
| 70 | + (str/replace (str "/releases/" old "/") (str "/releases/" new "/")) | ||
| 71 | + (str/replace (str "-" old ".") (str "-" new ".")))) | ||
| 72 | + | ||
| 73 | +(defn tag-of [url] | ||
| 74 | + (second (re-find #"/-/releases/([^/]+)/downloads/" url))) | ||
| 75 | + | ||
| 76 | +;; Fetch once per distinct URL, then weigh it: DotSlash wants the size and the | ||
| 77 | +;; sha256 of the archive as downloaded, not of anything inside it. | ||
| 78 | +(def weigh | ||
| 79 | + (memoize | ||
| 80 | + (fn [dir url] | ||
| 81 | + (let [file (fs/path dir (last (str/split url #"/")))] | ||
| 82 | + (println (str " fetching " (fs/file-name file))) | ||
| 83 | + (p/shell "curl" "-fsSL" "-o" (str file) url) | ||
| 84 | + {:size (fs/size file) | ||
| 85 | + :digest (first (str/split (paths/out "sha256sum" (str file)) #"\s+")) | ||
| 86 | + :file file})))) | ||
| 87 | + | ||
| 88 | +;; What the shim will reach for inside the archive. A release that moved a file | ||
| 89 | +;; leaves a manifest that fetches and verifies and then cannot resolve, which is | ||
| 90 | +;; a worse thing to find out from than this. | ||
| 91 | +(defn check-path! [{:keys [file]} path] | ||
| 92 | + (let [names (set (str/split-lines (paths/out "tar" "-tzf" (str file))))] | ||
| 93 | + (when-not (some #(= path (str/replace % #"^\./" "")) names) | ||
| 94 | + (paths/die (str "no " path " in " (fs/file-name file)) | ||
| 95 | + "The release moved it; the manifest's `path` needs a hand.")))) | ||
| 96 | + | ||
| 97 | +;; The JSON back out, in the shape it went in: two-space indentation, a value | ||
| 98 | +;; after each key, and the `//` comment block above it kept — that block is why | ||
| 99 | +;; anyone reading the manifest knows what the object is for. | ||
| 100 | +(def pretty | ||
| 101 | + (json/create-pretty-printer | ||
| 102 | + (assoc json/default-pretty-print-options | ||
| 103 | + :indentation " " | ||
| 104 | + :indent-arrays? true | ||
| 105 | + :object-field-value-separator ": "))) | ||
| 106 | + | ||
| 107 | +(defn rewrite [{:keys [file text json]} tmp tag] | ||
| 108 | + (let [platforms (get json "platforms") | ||
| 109 | + updated | ||
| 110 | + (into (array-map) | ||
| 111 | + (for [[platform entry] platforms | ||
| 112 | + :let [url (retag (get-in entry ["providers" 0 "url"]) (tag-of (get-in entry ["providers" 0 "url"])) tag) | ||
| 113 | + {:keys [size digest] :as got} (weigh tmp url)]] | ||
| 114 | + (do | ||
| 115 | + (check-path! got (get entry "path")) | ||
| 116 | + [platform (-> entry | ||
| 117 | + (assoc "size" size "digest" digest) | ||
| 118 | + (assoc-in ["providers" 0 "url"] url))]))) | ||
| 119 | + head (subs text 0 (str/index-of text "{")) | ||
| 120 | + ;; The prose above the JSON names the release too — "from jolt-native's | ||
| 121 | + ;; v0.1.3 release". Left saying the old one it would be a lie the moment | ||
| 122 | + ;; this script succeeds. | ||
| 123 | + head (reduce (fn [h old] (str/replace h old tag)) | ||
| 124 | + head | ||
| 125 | + (distinct (keep #(tag-of (get-in % ["providers" 0 "url"])) (vals platforms))))] | ||
| 126 | + (spit (str file) (str head (json/generate-string (assoc json "platforms" updated) {:pretty pretty}) "\n")) | ||
| 127 | + (println (str " " (fs/file-name file))))) | ||
| 128 | + | ||
| 129 | +;; deps.edn takes glimmer-vidya as a git dependency, and the boot image is | ||
| 130 | +;; compiled from the source root jolt resolves that to. Replaced as text rather | ||
| 131 | +;; than round-tripped as EDN: the file is mostly comments explaining why each | ||
| 132 | +;; pin is where it is, and rewriting it as data would throw all of them away. | ||
| 133 | +(defn bump-deps! [commit] | ||
| 134 | + (let [file (fs/path root "deps.edn") | ||
| 135 | + text (slurp (str file)) | ||
| 136 | + old (paths/dep-sha root repo)] | ||
| 137 | + (cond | ||
| 138 | + (nil? old) (paths/die (str "no dependency on " repo " in deps.edn")) | ||
| 139 | + (= old commit) (println " deps.edn already at this commit") | ||
| 140 | + :else (do (spit (str file) (str/replace text old commit)) | ||
| 141 | + (println (str " deps.edn " (subs old 0 8) " -> " (subs commit 0 8))))))) | ||
| 142 | + | ||
| 143 | +(let [tag (first *command-line-args*) | ||
| 144 | + rel (release tag) | ||
| 145 | + tag (get rel "tag_name") | ||
| 146 | + commit (get-in rel ["commit" "id"]) | ||
| 147 | + files (manifests) | ||
| 148 | + tmp (fs/create-temp-dir {:prefix "jolt-native-"})] | ||
| 149 | + (when (empty? files) | ||
| 150 | + (paths/die (str "no DotSlash manifest in " here " points at " repo))) | ||
| 151 | + (println (str "jolt-native " tag " (" (subs commit 0 8) ")")) | ||
| 152 | + (try | ||
| 153 | + (doseq [m files] (rewrite m tmp tag)) | ||
| 154 | + (finally (fs/delete-tree tmp))) | ||
| 155 | + (bump-deps! commit) | ||
| 156 | + (p/shell (str (fs/path here "dotslash-to-buck"))) | ||
| 157 | + (println (str "\nNow: git diff, then `just lib` and `just apk` — the pins are " | ||
| 158 | + "written, nothing is built."))) | ||
modified
scripts/frq/paths.clj +12 -18 | @@ -21,24 +21,18 @@ | ||
| 21 | 21 | |
| 22 | 22 | (defn env [k default] (or (not-empty (System/getenv k)) default)) |
| 23 | 23 | |
| 24 | -;; The checkout this tree belongs to, which in a git worktree is not this tree: | |
| 25 | -;; the scripts sit under .claude/worktrees/<name>, so "../jolt-native" from | |
| 26 | -;; here is nothing at all. --git-common-dir is the one thing that answers the | |
| 27 | -;; same in a worktree as in the checkout it came from. | |
| 28 | -(defn checkout [root] | |
| 29 | - (str (fs/parent (out "git" "-C" (str root) | |
| 30 | - "rev-parse" "--path-format=absolute" "--git-common-dir")))) | |
| 31 | - | |
| 32 | -;; jolt-native holds both native halves. A sibling checkout wins, so anyone | |
| 33 | -;; working on the two repos together builds what they are editing; everyone | |
| 34 | -;; else gets the clone `just lib` leaves under .jolt-native. | |
| 35 | -(defn jolt-native [root] | |
| 36 | - (or (env "JOLT_NATIVE" nil) | |
| 37 | - (let [c (checkout root) | |
| 38 | - sibling (fs/path (fs/parent c) "jolt-native")] | |
| 39 | - (if (fs/directory? sibling) | |
| 40 | - (str (fs/canonicalize sibling)) | |
| 41 | - (str (fs/path c ".jolt-native")))))) | |
| 24 | +;; An archive pinned in scripts/*.dotslash, resolved to the file its manifest | |
| 25 | +;; names. DotSlash downloads it once, verifies the digest and caches it, so | |
| 26 | +;; every script here asks the same question of the same pin and a second | |
| 27 | +;; jolt-native checkout is never part of the answer. | |
| 28 | +;; | |
| 29 | +;; DOTSLASH names the fetcher for a caller that has one but has not got it on | |
| 30 | +;; PATH — buck sets it, because the fetcher is an input to those actions. | |
| 31 | +(defn dist [root name] | |
| 32 | + (let [manifest (fs/path root "scripts" (str name ".dotslash"))] | |
| 33 | + (when-not (fs/exists? manifest) | |
| 34 | + (die (str "no DotSlash manifest: " manifest))) | |
| 35 | + (out (env "DOTSLASH" "dotslash") "--" "fetch" manifest))) | |
| 42 | 36 | |
| 43 | 37 | ;; The sha deps.edn pins for a git url, so a bump there reaches the boot image. |
| 44 | 38 | ;; Read as data rather than grepped: it is Clojure, and so is this. |
| @@ -21,24 +21,18 @@ | |||
| 21 | 21 | ||
| 22 | (defn env [k default] (or (not-empty (System/getenv k)) default)) | 22 | (defn env [k default] (or (not-empty (System/getenv k)) default)) |
| 23 | 23 | ||
| 24 | -;; The checkout this tree belongs to, which in a git worktree is not this tree: | 24 | +;; An archive pinned in scripts/*.dotslash, resolved to the file its manifest |
| 25 | -;; the scripts sit under .claude/worktrees/<name>, so "../jolt-native" from | 25 | +;; names. DotSlash downloads it once, verifies the digest and caches it, so |
| 26 | -;; here is nothing at all. --git-common-dir is the one thing that answers the | 26 | +;; every script here asks the same question of the same pin and a second |
| 27 | -;; same in a worktree as in the checkout it came from. | 27 | +;; jolt-native checkout is never part of the answer. |
| 28 | -(defn checkout [root] | 28 | +;; |
| 29 | - (str (fs/parent (out "git" "-C" (str root) | 29 | +;; DOTSLASH names the fetcher for a caller that has one but has not got it on |
| 30 | - "rev-parse" "--path-format=absolute" "--git-common-dir")))) | 30 | +;; PATH — buck sets it, because the fetcher is an input to those actions. |
| 31 | - | 31 | +(defn dist [root name] |
| 32 | -;; jolt-native holds both native halves. A sibling checkout wins, so anyone | 32 | + (let [manifest (fs/path root "scripts" (str name ".dotslash"))] |
| 33 | -;; working on the two repos together builds what they are editing; everyone | 33 | + (when-not (fs/exists? manifest) |
| 34 | -;; else gets the clone `just lib` leaves under .jolt-native. | 34 | + (die (str "no DotSlash manifest: " manifest))) |
| 35 | -(defn jolt-native [root] | 35 | + (out (env "DOTSLASH" "dotslash") "--" "fetch" manifest))) |
| 36 | - (or (env "JOLT_NATIVE" nil) | ||
| 37 | - (let [c (checkout root) | ||
| 38 | - sibling (fs/path (fs/parent c) "jolt-native")] | ||
| 39 | - (if (fs/directory? sibling) | ||
| 40 | - (str (fs/canonicalize sibling)) | ||
| 41 | - (str (fs/path c ".jolt-native")))))) | ||
| 42 | 36 | ||
| 43 | ;; The sha deps.edn pins for a git url, so a bump there reaches the boot image. | 37 | ;; The sha deps.edn pins for a git url, so a bump there reaches the boot image. |
| 44 | ;; Read as data rather than grepped: it is Clojure, and so is this. | 38 | ;; Read as data rather than grepped: it is Clojure, and so is this. |
modified
scripts/glimmer-vidya.dotslash +13 -13 | @@ -1,6 +1,6 @@ | ||
| 1 | 1 | #!/usr/bin/env dotslash |
| 2 | 2 | |
| 3 | -// The Jolt side that binds the tree ABI, from jolt-native's v0.1.2 release. | |
| 3 | +// The Jolt side that binds the tree ABI, from jolt-native's v0.1.3 release. | |
| 4 | 4 | // |
| 5 | 5 | // deps.edn takes this as a git dependency, and jolt resolves it into its own |
| 6 | 6 | // cache. The boot image cannot: a cross compile has no dependency resolution, |
| @@ -11,50 +11,50 @@ | ||
| 11 | 11 | "name": "glimmer-vidya", |
| 12 | 12 | "platforms": { |
| 13 | 13 | "linux-x86_64": { |
| 14 | - "size": 18069, | |
| 14 | + "size": 17988, | |
| 15 | 15 | "hash": "sha256", |
| 16 | - "digest": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | |
| 16 | + "digest": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", | |
| 17 | 17 | "format": "tar.gz", |
| 18 | 18 | "path": "glimmer-vidya/deps.edn", |
| 19 | 19 | "providers": [ |
| 20 | 20 | { |
| 21 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz" | |
| 21 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz" | |
| 22 | 22 | } |
| 23 | 23 | ] |
| 24 | 24 | }, |
| 25 | 25 | "linux-aarch64": { |
| 26 | - "size": 18069, | |
| 26 | + "size": 17988, | |
| 27 | 27 | "hash": "sha256", |
| 28 | - "digest": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | |
| 28 | + "digest": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", | |
| 29 | 29 | "format": "tar.gz", |
| 30 | 30 | "path": "glimmer-vidya/deps.edn", |
| 31 | 31 | "providers": [ |
| 32 | 32 | { |
| 33 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz" | |
| 33 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz" | |
| 34 | 34 | } |
| 35 | 35 | ] |
| 36 | 36 | }, |
| 37 | 37 | "macos-x86_64": { |
| 38 | - "size": 18069, | |
| 38 | + "size": 17988, | |
| 39 | 39 | "hash": "sha256", |
| 40 | - "digest": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | |
| 40 | + "digest": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", | |
| 41 | 41 | "format": "tar.gz", |
| 42 | 42 | "path": "glimmer-vidya/deps.edn", |
| 43 | 43 | "providers": [ |
| 44 | 44 | { |
| 45 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz" | |
| 45 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz" | |
| 46 | 46 | } |
| 47 | 47 | ] |
| 48 | 48 | }, |
| 49 | 49 | "macos-aarch64": { |
| 50 | - "size": 18069, | |
| 50 | + "size": 17988, | |
| 51 | 51 | "hash": "sha256", |
| 52 | - "digest": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | |
| 52 | + "digest": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", | |
| 53 | 53 | "format": "tar.gz", |
| 54 | 54 | "path": "glimmer-vidya/deps.edn", |
| 55 | 55 | "providers": [ |
| 56 | 56 | { |
| 57 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz" | |
| 57 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz" | |
| 58 | 58 | } |
| 59 | 59 | ] |
| 60 | 60 | } |
| @@ -1,6 +1,6 @@ | |||
| 1 | #!/usr/bin/env dotslash | 1 | #!/usr/bin/env dotslash |
| 2 | 2 | ||
| 3 | -// The Jolt side that binds the tree ABI, from jolt-native's v0.1.2 release. | 3 | +// The Jolt side that binds the tree ABI, from jolt-native's v0.1.3 release. |
| 4 | // | 4 | // |
| 5 | // deps.edn takes this as a git dependency, and jolt resolves it into its own | 5 | // deps.edn takes this as a git dependency, and jolt resolves it into its own |
| 6 | // cache. The boot image cannot: a cross compile has no dependency resolution, | 6 | // cache. The boot image cannot: a cross compile has no dependency resolution, |
| @@ -11,50 +11,50 @@ | |||
| 11 | "name": "glimmer-vidya", | 11 | "name": "glimmer-vidya", |
| 12 | "platforms": { | 12 | "platforms": { |
| 13 | "linux-x86_64": { | 13 | "linux-x86_64": { |
| 14 | - "size": 18069, | 14 | + "size": 17988, |
| 15 | "hash": "sha256", | 15 | "hash": "sha256", |
| 16 | - "digest": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | 16 | + "digest": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", |
| 17 | "format": "tar.gz", | 17 | "format": "tar.gz", |
| 18 | "path": "glimmer-vidya/deps.edn", | 18 | "path": "glimmer-vidya/deps.edn", |
| 19 | "providers": [ | 19 | "providers": [ |
| 20 | { | 20 | { |
| 21 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz" | 21 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz" |
| 22 | } | 22 | } |
| 23 | ] | 23 | ] |
| 24 | }, | 24 | }, |
| 25 | "linux-aarch64": { | 25 | "linux-aarch64": { |
| 26 | - "size": 18069, | 26 | + "size": 17988, |
| 27 | "hash": "sha256", | 27 | "hash": "sha256", |
| 28 | - "digest": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | 28 | + "digest": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", |
| 29 | "format": "tar.gz", | 29 | "format": "tar.gz", |
| 30 | "path": "glimmer-vidya/deps.edn", | 30 | "path": "glimmer-vidya/deps.edn", |
| 31 | "providers": [ | 31 | "providers": [ |
| 32 | { | 32 | { |
| 33 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz" | 33 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz" |
| 34 | } | 34 | } |
| 35 | ] | 35 | ] |
| 36 | }, | 36 | }, |
| 37 | "macos-x86_64": { | 37 | "macos-x86_64": { |
| 38 | - "size": 18069, | 38 | + "size": 17988, |
| 39 | "hash": "sha256", | 39 | "hash": "sha256", |
| 40 | - "digest": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | 40 | + "digest": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", |
| 41 | "format": "tar.gz", | 41 | "format": "tar.gz", |
| 42 | "path": "glimmer-vidya/deps.edn", | 42 | "path": "glimmer-vidya/deps.edn", |
| 43 | "providers": [ | 43 | "providers": [ |
| 44 | { | 44 | { |
| 45 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz" | 45 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz" |
| 46 | } | 46 | } |
| 47 | ] | 47 | ] |
| 48 | }, | 48 | }, |
| 49 | "macos-aarch64": { | 49 | "macos-aarch64": { |
| 50 | - "size": 18069, | 50 | + "size": 17988, |
| 51 | "hash": "sha256", | 51 | "hash": "sha256", |
| 52 | - "digest": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | 52 | + "digest": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", |
| 53 | "format": "tar.gz", | 53 | "format": "tar.gz", |
| 54 | "path": "glimmer-vidya/deps.edn", | 54 | "path": "glimmer-vidya/deps.edn", |
| 55 | "providers": [ | 55 | "providers": [ |
| 56 | { | 56 | { |
| 57 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz" | 57 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz" |
| 58 | } | 58 | } |
| 59 | ] | 59 | ] |
| 60 | } | 60 | } |
modified
scripts/lib.bb +50 -16 | @@ -3,28 +3,62 @@ | ||
| 3 | 3 | exec "$(dirname "$0")/bb" "$0" "$@" |
| 4 | 4 | ) |
| 5 | 5 | |
| 6 | -;; Both native libraries: libvidya (the tree ABI glimmer-vidya binds) and | |
| 7 | -;; libjoltmoq (the AV media plane). One workspace, one target directory. | |
| 6 | +;; Both native libraries, out of jolt-native's release rather than a checkout. | |
| 8 | 7 | ;; |
| 9 | -;; A sibling jolt-native checkout wins, so anyone working on the two repos | |
| 10 | -;; together builds what they are editing; everyone else gets a clone of the | |
| 11 | -;; gitlab repo under .jolt-native, pinned to the commit deps.edn takes | |
| 12 | -;; glimmer-vidya from — one place to bump, rather than a second sha here. | |
| 8 | +;; libvidya is the tree ABI glimmer-vidya binds; libjoltmoq is the AV media | |
| 9 | +;; plane. They come out of one archive because they are built together, and | |
| 10 | +;; they land in build/lib because a loader wants one directory, which is where | |
| 11 | +;; run.bb points LD_LIBRARY_PATH. | |
| 12 | +;; | |
| 13 | +;; Nothing is compiled here. The pinned bytes are the bytes: this repo used to | |
| 14 | +;; clone jolt-native and cargo-build it, which meant a Rust toolchain, a build | |
| 15 | +;; whose output depended on the machine, and two places — the clone's sha and | |
| 16 | +;; the release digest — that could disagree about which jolt-native frq was | |
| 17 | +;; running against. Bump scripts/*.dotslash instead: see bump-jolt-native.bb. | |
| 18 | +;; | |
| 19 | +;; Linked rather than copied, so a bump reaches a running tree by relinking and | |
| 20 | +;; nothing goes stale in build/ — except for the one object that has to be | |
| 21 | +;; repaired on the way through. See below. | |
| 13 | 22 | (require '[babashka.classpath :as cp]) |
| 14 | 23 | (cp/add-classpath (str (babashka.fs/parent *file*))) |
| 15 | 24 | (require '[frq.paths :as paths] |
| 16 | 25 | '[babashka.fs :as fs] |
| 17 | - '[babashka.process :as p]) | |
| 26 | + '[clojure.string :as str]) | |
| 18 | 27 | |
| 19 | 28 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) |
| 20 | -(def url "https://gitlab.com/nandithebull/jolt-native.git") | |
| 21 | -(def sha (paths/dep-sha root "https://gitlab.com/nandithebull/jolt-native")) | |
| 22 | -(def jolt-native (paths/jolt-native root)) | |
| 29 | +(def lib (fs/path root "build" "lib")) | |
| 30 | + | |
| 31 | +;; v0.1.3's desktop libjoltmoq.so has 68 undefined `snd_*` symbols and no | |
| 32 | +;; DT_NEEDED on libasound: cpal's ALSA host is compiled in, and the library it | |
| 33 | +;; calls is not named. It is the defect that release fixed for Android, in the | |
| 34 | +;; place the fix did not reach — buck2 keeps a build script's cfgs and drops | |
| 35 | +;; its link directives, so `cargo:rustc-link-lib=asound` never became a link | |
| 36 | +;; argument. Undefined symbols are legal in a cdylib, so nothing said so until | |
| 37 | +;; something tried to load it. | |
| 38 | +;; | |
| 39 | +;; So the library is named here instead, on a copy: the DotSlash cache holds | |
| 40 | +;; what the release published, and rewriting that in place would make a | |
| 41 | +;; verified digest a lie about the bytes on disk. | |
| 42 | +;; | |
| 43 | +;; This goes away with the release that links it. `patchelf --print-needed` | |
| 44 | +;; below is the test for that — a fixed object is linked, not copied. | |
| 45 | +(def repairs {"libjoltmoq.so" "libasound.so.2"}) | |
| 23 | 46 | |
| 24 | -;; Already here whenever the sibling checkout exists, since that is what | |
| 25 | -;; jolt-native then points at. | |
| 26 | -(when-not (fs/directory? jolt-native) | |
| 27 | - (p/shell "git" "clone" url jolt-native) | |
| 28 | - (p/shell {:dir jolt-native} "git" "checkout" "--detach" sha)) | |
| 47 | +(defn needed [file] | |
| 48 | + (set (str/split-lines (paths/out "patchelf" "--print-needed" file)))) | |
| 29 | 49 | |
| 30 | -(p/shell {:dir jolt-native} "just" "build") | |
| 50 | +(fs/create-dirs lib) | |
| 51 | +(doseq [name ["libvidya-linux" "libjoltmoq-linux"]] | |
| 52 | + (let [file (paths/dist root name) | |
| 53 | + base (fs/file-name file) | |
| 54 | + dest (fs/path lib base) | |
| 55 | + missing (get repairs base)] | |
| 56 | + (fs/delete-if-exists dest) | |
| 57 | + (if (and missing (not (contains? (needed file) missing))) | |
| 58 | + (do (fs/copy file dest) | |
| 59 | + ;; Out of the cache read-only, and patchelf writes. | |
| 60 | + (fs/set-posix-file-permissions dest "rw-r--r--") | |
| 61 | + (paths/out "patchelf" "--add-needed" missing (str dest)) | |
| 62 | + (println (str (fs/relativize root dest) " <- " file " (+" missing ")"))) | |
| 63 | + (do (fs/create-sym-link dest file) | |
| 64 | + (println (str (fs/relativize root dest) " -> " file)))))) | |
| @@ -3,28 +3,62 @@ | |||
| 3 | exec "$(dirname "$0")/bb" "$0" "$@" | 3 | exec "$(dirname "$0")/bb" "$0" "$@" |
| 4 | ) | 4 | ) |
| 5 | 5 | ||
| 6 | -;; Both native libraries: libvidya (the tree ABI glimmer-vidya binds) and | 6 | +;; Both native libraries, out of jolt-native's release rather than a checkout. |
| 7 | -;; libjoltmoq (the AV media plane). One workspace, one target directory. | ||
| 8 | ;; | 7 | ;; |
| 9 | -;; A sibling jolt-native checkout wins, so anyone working on the two repos | 8 | +;; libvidya is the tree ABI glimmer-vidya binds; libjoltmoq is the AV media |
| 10 | -;; together builds what they are editing; everyone else gets a clone of the | 9 | +;; plane. They come out of one archive because they are built together, and |
| 11 | -;; gitlab repo under .jolt-native, pinned to the commit deps.edn takes | 10 | +;; they land in build/lib because a loader wants one directory, which is where |
| 12 | -;; glimmer-vidya from — one place to bump, rather than a second sha here. | 11 | +;; run.bb points LD_LIBRARY_PATH. |
| 12 | +;; | ||
| 13 | +;; Nothing is compiled here. The pinned bytes are the bytes: this repo used to | ||
| 14 | +;; clone jolt-native and cargo-build it, which meant a Rust toolchain, a build | ||
| 15 | +;; whose output depended on the machine, and two places — the clone's sha and | ||
| 16 | +;; the release digest — that could disagree about which jolt-native frq was | ||
| 17 | +;; running against. Bump scripts/*.dotslash instead: see bump-jolt-native.bb. | ||
| 18 | +;; | ||
| 19 | +;; Linked rather than copied, so a bump reaches a running tree by relinking and | ||
| 20 | +;; nothing goes stale in build/ — except for the one object that has to be | ||
| 21 | +;; repaired on the way through. See below. | ||
| 13 | (require '[babashka.classpath :as cp]) | 22 | (require '[babashka.classpath :as cp]) |
| 14 | (cp/add-classpath (str (babashka.fs/parent *file*))) | 23 | (cp/add-classpath (str (babashka.fs/parent *file*))) |
| 15 | (require '[frq.paths :as paths] | 24 | (require '[frq.paths :as paths] |
| 16 | '[babashka.fs :as fs] | 25 | '[babashka.fs :as fs] |
| 17 | - '[babashka.process :as p]) | 26 | + '[clojure.string :as str]) |
| 18 | 27 | ||
| 19 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) | 28 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) |
| 20 | -(def url "https://gitlab.com/nandithebull/jolt-native.git") | 29 | +(def lib (fs/path root "build" "lib")) |
| 21 | -(def sha (paths/dep-sha root "https://gitlab.com/nandithebull/jolt-native")) | 30 | + |
| 22 | -(def jolt-native (paths/jolt-native root)) | 31 | +;; v0.1.3's desktop libjoltmoq.so has 68 undefined `snd_*` symbols and no |
| 32 | +;; DT_NEEDED on libasound: cpal's ALSA host is compiled in, and the library it | ||
| 33 | +;; calls is not named. It is the defect that release fixed for Android, in the | ||
| 34 | +;; place the fix did not reach — buck2 keeps a build script's cfgs and drops | ||
| 35 | +;; its link directives, so `cargo:rustc-link-lib=asound` never became a link | ||
| 36 | +;; argument. Undefined symbols are legal in a cdylib, so nothing said so until | ||
| 37 | +;; something tried to load it. | ||
| 38 | +;; | ||
| 39 | +;; So the library is named here instead, on a copy: the DotSlash cache holds | ||
| 40 | +;; what the release published, and rewriting that in place would make a | ||
| 41 | +;; verified digest a lie about the bytes on disk. | ||
| 42 | +;; | ||
| 43 | +;; This goes away with the release that links it. `patchelf --print-needed` | ||
| 44 | +;; below is the test for that — a fixed object is linked, not copied. | ||
| 45 | +(def repairs {"libjoltmoq.so" "libasound.so.2"}) | ||
| 23 | 46 | ||
| 24 | -;; Already here whenever the sibling checkout exists, since that is what | 47 | +(defn needed [file] |
| 25 | -;; jolt-native then points at. | 48 | + (set (str/split-lines (paths/out "patchelf" "--print-needed" file)))) |
| 26 | -(when-not (fs/directory? jolt-native) | ||
| 27 | - (p/shell "git" "clone" url jolt-native) | ||
| 28 | - (p/shell {:dir jolt-native} "git" "checkout" "--detach" sha)) | ||
| 29 | 49 | ||
| 30 | -(p/shell {:dir jolt-native} "just" "build") | 50 | +(fs/create-dirs lib) |
| 51 | +(doseq [name ["libvidya-linux" "libjoltmoq-linux"]] | ||
| 52 | + (let [file (paths/dist root name) | ||
| 53 | + base (fs/file-name file) | ||
| 54 | + dest (fs/path lib base) | ||
| 55 | + missing (get repairs base)] | ||
| 56 | + (fs/delete-if-exists dest) | ||
| 57 | + (if (and missing (not (contains? (needed file) missing))) | ||
| 58 | + (do (fs/copy file dest) | ||
| 59 | + ;; Out of the cache read-only, and patchelf writes. | ||
| 60 | + (fs/set-posix-file-permissions dest "rw-r--r--") | ||
| 61 | + (paths/out "patchelf" "--add-needed" missing (str dest)) | ||
| 62 | + (println (str (fs/relativize root dest) " <- " file " (+" missing ")"))) | ||
| 63 | + (do (fs/create-sym-link dest file) | ||
| 64 | + (println (str (fs/relativize root dest) " -> " file)))))) | ||
modified
scripts/libjoltmoq-android.dotslash +1 -1 | @@ -11,7 +11,7 @@ | ||
| 11 | 11 | // PipeWire, which a phone has neither of. The camera is Camera2 over JNI now |
| 12 | 12 | // and the microphone is cpal's AAudio host. |
| 13 | 13 | // |
| 14 | -// A sibling jolt-native checkout still wins over this, the same as libvidya. | |
| 14 | +// The only answer for it, the same as libvidya. | |
| 15 | 15 | { |
| 16 | 16 | "name": "libjoltmoq-android", |
| 17 | 17 | "platforms": { |
| @@ -11,7 +11,7 @@ | |||
| 11 | // PipeWire, which a phone has neither of. The camera is Camera2 over JNI now | 11 | // PipeWire, which a phone has neither of. The camera is Camera2 over JNI now |
| 12 | // and the microphone is cpal's AAudio host. | 12 | // and the microphone is cpal's AAudio host. |
| 13 | // | 13 | // |
| 14 | -// A sibling jolt-native checkout still wins over this, the same as libvidya. | 14 | +// The only answer for it, the same as libvidya. |
| 15 | { | 15 | { |
| 16 | "name": "libjoltmoq-android", | 16 | "name": "libjoltmoq-android", |
| 17 | "platforms": { | 17 | "platforms": { |
added
scripts/libjoltmoq-linux.dotslash +27 -0 | new file mode 100755 | ||
| @@ -0,0 +1,27 @@ | ||
| 1 | +#!/usr/bin/env dotslash | |
| 2 | + | |
| 3 | +// The AV media plane for the desktop, from jolt-native's v0.1.3 release. | |
| 4 | +// | |
| 5 | +// MoQ over QUIC, Opus and H.264, with V4L2 and PipeWire at the capture end. | |
| 6 | +// Out of the same archive as libvidya-linux and pinned with it, for the reason | |
| 7 | +// the Android pair gives: the two objects are built together, frq loads both, | |
| 8 | +// and one release's media plane beside another's UI is untested. | |
| 9 | +// | |
| 10 | +// x86_64 only; see libvidya-linux. | |
| 11 | +{ | |
| 12 | + "name": "libjoltmoq-linux", | |
| 13 | + "platforms": { | |
| 14 | + "linux-x86_64": { | |
| 15 | + "size": 14870823, | |
| 16 | + "hash": "sha256", | |
| 17 | + "digest": "b49ca39793c0ee3809ba747d0040ac370ee4e6c92e433c53ca5459eaa90def18", | |
| 18 | + "format": "tar.gz", | |
| 19 | + "path": "libjoltmoq.so", | |
| 20 | + "providers": [ | |
| 21 | + { | |
| 22 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-linux-x86_64-v0.1.3.tar.gz" | |
| 23 | + } | |
| 24 | + ] | |
| 25 | + } | |
| 26 | + } | |
| 27 | +} | |
| new file mode 100755 | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | +#!/usr/bin/env dotslash | ||
| 2 | + | ||
| 3 | +// The AV media plane for the desktop, from jolt-native's v0.1.3 release. | ||
| 4 | +// | ||
| 5 | +// MoQ over QUIC, Opus and H.264, with V4L2 and PipeWire at the capture end. | ||
| 6 | +// Out of the same archive as libvidya-linux and pinned with it, for the reason | ||
| 7 | +// the Android pair gives: the two objects are built together, frq loads both, | ||
| 8 | +// and one release's media plane beside another's UI is untested. | ||
| 9 | +// | ||
| 10 | +// x86_64 only; see libvidya-linux. | ||
| 11 | +{ | ||
| 12 | + "name": "libjoltmoq-linux", | ||
| 13 | + "platforms": { | ||
| 14 | + "linux-x86_64": { | ||
| 15 | + "size": 14870823, | ||
| 16 | + "hash": "sha256", | ||
| 17 | + "digest": "b49ca39793c0ee3809ba747d0040ac370ee4e6c92e433c53ca5459eaa90def18", | ||
| 18 | + "format": "tar.gz", | ||
| 19 | + "path": "libjoltmoq.so", | ||
| 20 | + "providers": [ | ||
| 21 | + { | ||
| 22 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-linux-x86_64-v0.1.3.tar.gz" | ||
| 23 | + } | ||
| 24 | + ] | ||
| 25 | + } | ||
| 26 | + } | ||
| 27 | +} | ||
modified
scripts/libvidya-android.dotslash +4 -3 | @@ -6,9 +6,10 @@ | ||
| 6 | 6 | // same object `just ffi-android` produces there, pinned so that building the |
| 7 | 7 | // APK needs neither that checkout nor an NDK. |
| 8 | 8 | // |
| 9 | -// A sibling jolt-native checkout still wins over this: see the `buck` recipe | |
| 10 | -// in the justfile. Anyone working on both repos at once builds what they are | |
| 11 | -// editing; everyone else gets these bytes. | |
| 9 | +// This is the only answer, and deliberately: a checkout used to win over it, | |
| 10 | +// which meant the APK on a phone depended on which directories happened to sit | |
| 11 | +// beside this one. To build against a jolt-native you are editing, cut a | |
| 12 | +// release of it and point these manifests at it — `just bump <tag>`. | |
| 12 | 13 | { |
| 13 | 14 | "name": "libvidya-android", |
| 14 | 15 | "platforms": { |
| @@ -6,9 +6,10 @@ | |||
| 6 | // same object `just ffi-android` produces there, pinned so that building the | 6 | // same object `just ffi-android` produces there, pinned so that building the |
| 7 | // APK needs neither that checkout nor an NDK. | 7 | // APK needs neither that checkout nor an NDK. |
| 8 | // | 8 | // |
| 9 | -// A sibling jolt-native checkout still wins over this: see the `buck` recipe | 9 | +// This is the only answer, and deliberately: a checkout used to win over it, |
| 10 | -// in the justfile. Anyone working on both repos at once builds what they are | 10 | +// which meant the APK on a phone depended on which directories happened to sit |
| 11 | -// editing; everyone else gets these bytes. | 11 | +// beside this one. To build against a jolt-native you are editing, cut a |
| 12 | +// release of it and point these manifests at it — `just bump <tag>`. | ||
| 12 | { | 13 | { |
| 13 | "name": "libvidya-android", | 14 | "name": "libvidya-android", |
| 14 | "platforms": { | 15 | "platforms": { |
added
scripts/libvidya-linux.dotslash +27 -0 | new file mode 100755 | ||
| @@ -0,0 +1,27 @@ | ||
| 1 | +#!/usr/bin/env dotslash | |
| 2 | + | |
| 3 | +// libvidya for the desktop, from jolt-native's v0.1.3 release. | |
| 4 | +// | |
| 5 | +// The retained-tree ABI glimmer-vidya binds, on egui. `just lib` fetches this | |
| 6 | +// and libjoltmoq-linux — one archive holds both — and links them where `just | |
| 7 | +// run` points the loader. | |
| 8 | +// | |
| 9 | +// x86_64 only, because that is the only desktop asset the release cuts: a | |
| 10 | +// linux-aarch64 or a macOS frq needs jolt-native built by hand for now. | |
| 11 | +{ | |
| 12 | + "name": "libvidya-linux", | |
| 13 | + "platforms": { | |
| 14 | + "linux-x86_64": { | |
| 15 | + "size": 14870823, | |
| 16 | + "hash": "sha256", | |
| 17 | + "digest": "b49ca39793c0ee3809ba747d0040ac370ee4e6c92e433c53ca5459eaa90def18", | |
| 18 | + "format": "tar.gz", | |
| 19 | + "path": "libvidya.so", | |
| 20 | + "providers": [ | |
| 21 | + { | |
| 22 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-linux-x86_64-v0.1.3.tar.gz" | |
| 23 | + } | |
| 24 | + ] | |
| 25 | + } | |
| 26 | + } | |
| 27 | +} | |
| new file mode 100755 | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | +#!/usr/bin/env dotslash | ||
| 2 | + | ||
| 3 | +// libvidya for the desktop, from jolt-native's v0.1.3 release. | ||
| 4 | +// | ||
| 5 | +// The retained-tree ABI glimmer-vidya binds, on egui. `just lib` fetches this | ||
| 6 | +// and libjoltmoq-linux — one archive holds both — and links them where `just | ||
| 7 | +// run` points the loader. | ||
| 8 | +// | ||
| 9 | +// x86_64 only, because that is the only desktop asset the release cuts: a | ||
| 10 | +// linux-aarch64 or a macOS frq needs jolt-native built by hand for now. | ||
| 11 | +{ | ||
| 12 | + "name": "libvidya-linux", | ||
| 13 | + "platforms": { | ||
| 14 | + "linux-x86_64": { | ||
| 15 | + "size": 14870823, | ||
| 16 | + "hash": "sha256", | ||
| 17 | + "digest": "b49ca39793c0ee3809ba747d0040ac370ee4e6c92e433c53ca5459eaa90def18", | ||
| 18 | + "format": "tar.gz", | ||
| 19 | + "path": "libvidya.so", | ||
| 20 | + "providers": [ | ||
| 21 | + { | ||
| 22 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-linux-x86_64-v0.1.3.tar.gz" | ||
| 23 | + } | ||
| 24 | + ] | ||
| 25 | + } | ||
| 26 | + } | ||
| 27 | +} | ||
modified
scripts/run.bb +5 -7 | @@ -3,12 +3,10 @@ | ||
| 3 | 3 | exec "$(dirname "$0")/bb" "$0" "$@" |
| 4 | 4 | ) |
| 5 | 5 | |
| 6 | -;; The app. The native libraries are wherever jolt-native is — a sibling | |
| 7 | -;; checkout, or the clone `just lib` leaves under .jolt-native. | |
| 8 | -(require '[babashka.classpath :as cp]) | |
| 9 | -(cp/add-classpath (str (babashka.fs/parent *file*))) | |
| 10 | -(require '[frq.paths :as paths] | |
| 11 | - '[babashka.fs :as fs] | |
| 6 | +;; The app, with the native libraries `just lib` linked into build/lib on the | |
| 7 | +;; loader path. Those are jolt-native's release, fetched by digest; nothing | |
| 8 | +;; here looks for a checkout of it. | |
| 9 | +(require '[babashka.fs :as fs] | |
| 12 | 10 | '[babashka.process :as p]) |
| 13 | 11 | |
| 14 | 12 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) |
| @@ -17,5 +15,5 @@ exec "$(dirname "$0")/bb" "$0" "$@" | ||
| 17 | 15 | (:exit @(apply p/process |
| 18 | 16 | {:inherit true |
| 19 | 17 | :extra-env {"LD_LIBRARY_PATH" |
| 20 | - (str (fs/path (paths/jolt-native root) "target" "release"))}} | |
| 18 | + (str (fs/path root "build" "lib"))}} | |
| 21 | 19 | "jolt" "-M:frq" *command-line-args*))) |
| @@ -3,12 +3,10 @@ | |||
| 3 | exec "$(dirname "$0")/bb" "$0" "$@" | 3 | exec "$(dirname "$0")/bb" "$0" "$@" |
| 4 | ) | 4 | ) |
| 5 | 5 | ||
| 6 | -;; The app. The native libraries are wherever jolt-native is — a sibling | 6 | +;; The app, with the native libraries `just lib` linked into build/lib on the |
| 7 | -;; checkout, or the clone `just lib` leaves under .jolt-native. | 7 | +;; loader path. Those are jolt-native's release, fetched by digest; nothing |
| 8 | -(require '[babashka.classpath :as cp]) | 8 | +;; here looks for a checkout of it. |
| 9 | -(cp/add-classpath (str (babashka.fs/parent *file*))) | 9 | +(require '[babashka.fs :as fs] |
| 10 | -(require '[frq.paths :as paths] | ||
| 11 | - '[babashka.fs :as fs] | ||
| 12 | '[babashka.process :as p]) | 10 | '[babashka.process :as p]) |
| 13 | 11 | ||
| 14 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) | 12 | (def root (str (fs/canonicalize (fs/path (fs/parent *file*) "..")))) |
| @@ -17,5 +15,5 @@ exec "$(dirname "$0")/bb" "$0" "$@" | |||
| 17 | (:exit @(apply p/process | 15 | (:exit @(apply p/process |
| 18 | {:inherit true | 16 | {:inherit true |
| 19 | :extra-env {"LD_LIBRARY_PATH" | 17 | :extra-env {"LD_LIBRARY_PATH" |
| 20 | - (str (fs/path (paths/jolt-native root) "target" "release"))}} | 18 | + (str (fs/path root "build" "lib"))}} |
| 21 | "jolt" "-M:frq" *command-line-args*))) | 19 | "jolt" "-M:frq" *command-line-args*))) |
modified
toolchains/dist/generated.bzl +8 -8 | @@ -58,26 +58,26 @@ DIST = { | ||
| 58 | 58 | }, |
| 59 | 59 | "glimmer-vidya": { |
| 60 | 60 | "linux-aarch64": { |
| 61 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz", | |
| 62 | - "sha256": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | |
| 61 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz", | |
| 62 | + "sha256": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", | |
| 63 | 63 | "strip_prefix": "glimmer-vidya", |
| 64 | 64 | "type": "tar.gz" |
| 65 | 65 | }, |
| 66 | 66 | "linux-x86_64": { |
| 67 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz", | |
| 68 | - "sha256": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | |
| 67 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz", | |
| 68 | + "sha256": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", | |
| 69 | 69 | "strip_prefix": "glimmer-vidya", |
| 70 | 70 | "type": "tar.gz" |
| 71 | 71 | }, |
| 72 | 72 | "macos-aarch64": { |
| 73 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz", | |
| 74 | - "sha256": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | |
| 73 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz", | |
| 74 | + "sha256": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", | |
| 75 | 75 | "strip_prefix": "glimmer-vidya", |
| 76 | 76 | "type": "tar.gz" |
| 77 | 77 | }, |
| 78 | 78 | "macos-x86_64": { |
| 79 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz", | |
| 80 | - "sha256": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | |
| 79 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz", | |
| 80 | + "sha256": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", | |
| 81 | 81 | "strip_prefix": "glimmer-vidya", |
| 82 | 82 | "type": "tar.gz" |
| 83 | 83 | } |
| @@ -58,26 +58,26 @@ DIST = { | |||
| 58 | }, | 58 | }, |
| 59 | "glimmer-vidya": { | 59 | "glimmer-vidya": { |
| 60 | "linux-aarch64": { | 60 | "linux-aarch64": { |
| 61 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz", | 61 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz", |
| 62 | - "sha256": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | 62 | + "sha256": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", |
| 63 | "strip_prefix": "glimmer-vidya", | 63 | "strip_prefix": "glimmer-vidya", |
| 64 | "type": "tar.gz" | 64 | "type": "tar.gz" |
| 65 | }, | 65 | }, |
| 66 | "linux-x86_64": { | 66 | "linux-x86_64": { |
| 67 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz", | 67 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz", |
| 68 | - "sha256": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | 68 | + "sha256": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", |
| 69 | "strip_prefix": "glimmer-vidya", | 69 | "strip_prefix": "glimmer-vidya", |
| 70 | "type": "tar.gz" | 70 | "type": "tar.gz" |
| 71 | }, | 71 | }, |
| 72 | "macos-aarch64": { | 72 | "macos-aarch64": { |
| 73 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz", | 73 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz", |
| 74 | - "sha256": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | 74 | + "sha256": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", |
| 75 | "strip_prefix": "glimmer-vidya", | 75 | "strip_prefix": "glimmer-vidya", |
| 76 | "type": "tar.gz" | 76 | "type": "tar.gz" |
| 77 | }, | 77 | }, |
| 78 | "macos-x86_64": { | 78 | "macos-x86_64": { |
| 79 | - "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.2/downloads/jolt-native-glimmer-vidya-v0.1.2.tar.gz", | 79 | + "url": "https://gitlab.com/nandithebull/jolt-native/-/releases/v0.1.3/downloads/jolt-native-glimmer-vidya-v0.1.3.tar.gz", |
| 80 | - "sha256": "1e544ef9c354e56bbfe280fee72e79e4a8bd6c746fe51a779e0afebb4465917d", | 80 | + "sha256": "5ea0f7d2c3d3ff56daa3983c7222bd724a6dd4d6977c6b3bb2311d7d708ea9fe", |
| 81 | "strip_prefix": "glimmer-vidya", | 81 | "strip_prefix": "glimmer-vidya", |
| 82 | "type": "tar.gz" | 82 | "type": "tar.gz" |
| 83 | } | 83 | } |