nandi/frqpublic Fork 0
9db383cd55e49cc0c9fc80cf49e2e10c2fd034a9
Commits
Clone
git clone https://git.rickub.com/nandi/frq.git
git clone ssh://git@rickub.com/nandi/frq.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

desktop-toolchain.sh · 217 lines · 9.7 KBBash Blame HistoryRaw
A Mesa nobody needed, and the AppImage that carried it 9db383c nandi 20h ago1#!/usr/bin/env bash
2# The cosmic desktop build's toolchain: a jolt binary, the native objects, and
3# the two Jolt libraries the launcher hands to `-Sdeps`. Each pinned, fetched
4# into a directory, and that is the whole of it. No nix.
5#
6# This is `tools/toolchain.sh` for the other target. That one fetches a
7# Flutter, a JDK and a Clojure CLI because the web build is a compiler run;
8# this one fetches a runtime and its libraries because the cosmic build is not
9# a compilation at all — jolt reads source at startup, so "building" frq for
10# the desktop means putting the right files next to each other.
11#
12# What made this possible is that every piece is now published as something a
13# machine without nix can use:
14#
15# jolt one binary, chez linked in statically. Stock /lib64
16# interpreter, NEEDED libc and libm and nothing else.
17# jolt-native the `portable` tarball — the backends with their NEEDED
18# closure beside them and RUNPATH $ORIGIN. The plain
19# x86_64-linux tarball is NOT this: those objects resolve
20# through the builder's /nix/store and are for nix consumers.
21# libmoq_ffi an upstream release object, no RUNPATH, needs libgcc_s.
22# glimmer Jolt source. Read, not linked.
23#
24# What is NOT here, and has to be on the machine that RUNS the result: the GL
25# driver, and glibc. That is deliberate and it is what replaces the AppImage —
26# nix-appimage carried a Mesa, which is why the launcher needed a nixGL to put
27# the host's driver in front of it. Carrying no Mesa needs no nixGL.
28#
29# tools/desktop-toolchain.sh fetch whatever is missing
30# eval "$(tools/desktop-toolchain.sh env)" ...and set this shell up
31# tools/desktop-toolchain.sh exec -- jolt --version
32#
33# `FRQ_DESKTOP_TOOLCHAIN` says where it lives; the default is `.toolchain-
34# desktop/` at the top of the checkout, and the container points it at a
35# volume so the fetch happens once across runs rather than once across
36# containers.
37set -euo pipefail
38
39root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
40TC="${FRQ_DESKTOP_TOOLCHAIN:-$root/.toolchain-desktop}"
41
42# The pins. A URL and a hash, and nothing resolved at run time — the same rule
43# tools/toolchain.sh states and for the same reason.
44
45# The runtime. One binary out of the fork's release, and it really is one
46# binary: `patchelf --print-needed` on it says libm and libc.
47#
48# To move it: tag a release in gitlab.com/nandithebull/jolt and take the URL
49# and sha256 from its asset. The version string the binary prints is the tag,
50# so a mismatch between this pin and the flake's `jolt-src` rev is visible in
51# `jolt --version` rather than silent.
52JOLT_VERSION="v0.7.28-1-g2b80d68d"
53JOLT_URL="https://gitlab.com/-/project/85910549/uploads/c67e91d30934c404583c004710c249a6/jolt-${JOLT_VERSION}-x86_64-linux.tar.gz"
54JOLT_SHA="aabb71f809aebd9d607b7a5036229f933c733ae90785cb29df899f116be9589f"
55
56# The native backends, and the Jolt source that binds them, at ONE revision.
57#
58# One variable for both on purpose. glimmer-cosmic talks to libjoltcosmic over
59# a retained-tree ABI that is not versioned, and the flake's comment on the
60# jolt-native input says what drift costs: the Jolt half sent a reaction
61# pill's hover card to a backend with no handler for one, and the pill said
62# nothing. The source and the object are the same commit here by construction.
63JOLT_NATIVE_REV="65c27be020b52eb87d0c0718c8cfff1869e8d2f7"
64JOLT_NATIVE_URL="https://gitlab.com/api/v4/projects/85910092/packages/generic/jolt-native/${JOLT_NATIVE_REV}/x86_64-linux-portable.tar.gz"
65# Filled in from the first pipeline that publishes this revision's tarball:
66#
67# curl -fsSL "$JOLT_NATIVE_URL" | sha256sum
68#
69# Left as the placeholder deliberately rather than omitted — an unpinned
70# fetch of a URL under a package registry that serves the NEWEST upload for a
71# given name is exactly the moving target these pins exist to refuse.
72JOLT_NATIVE_SHA="${FRQ_JOLT_NATIVE_SHA:-0000000000000000000000000000000000000000000000000000000000000000}"
73
74# MoQ over QUIC behind UniFFI's C ABI, from upstream's release rather than
75# built. Same object and same version the flake fetches.
76MOQ_FFI_VERSION="0.3.17"
77# The triple is the Rust one and not the nix system name -- `x86_64-linux`
78# gets a 404 from this URL, which is how that got noticed.
79MOQ_FFI_TARGET="x86_64-unknown-linux-gnu"
80MOQ_FFI_URL="https://github.com/kixelated/moq/releases/download/moq-ffi-v${MOQ_FFI_VERSION}/moq-ffi-${MOQ_FFI_VERSION}-${MOQ_FFI_TARGET}-libmoq_ffi.so"
81MOQ_FFI_SHA="773417a55e0981db43fa0df7597e7514501075f0945e436cc75c4f6e86cf7d42"
82
83# glimmer, at the rev deps.edn pins. Source, so it is cloned rather than
84# fetched as an archive: a git rev is immutable in a way a forge's generated
85# tarball is not — those are re-compressed across forge versions, and a
86# sha256 over one is a pin that breaks without anything having changed.
87GLIMMER_REPO="https://gitlab.com/nandithebull/glimmer.git"
88GLIMMER_REV="399df371c790d690fb6e4560c3d4d7f838502857"
89
90JOLT_NATIVE_REPO="https://gitlab.com/nandithebull/jolt-native.git"
91
92# What the host still has to bring. Small and boring, but a missing one fails
93# further from here with a worse message.
94require_host_tools() {
95 local missing=()
96 for t in curl tar git sha256sum; do
97 command -v "$t" >/dev/null 2>&1 || missing+=("$t")
98 done
99 if [ ${#missing[@]} -gt 0 ]; then
100 echo "desktop-toolchain: this needs ${missing[*]} on PATH and cannot fetch them" >&2
101 exit 1
102 fi
103}
104
105# One archive, unpacked once. The stamp holds the hash rather than the
106# version, and the work happens in `.tmp` so a half-finished unpack is never
107# mistaken for a finished one — `tools/toolchain.sh` explains at length.
108install_archive() {
109 local name=$1 url=$2 sha=$3 strip=$4
110 local dest="$TC/$name" stamp="$TC/$name.sha256"
111 if [ -d "$dest" ] && [ "$(cat "$stamp" 2>/dev/null || true)" = "$sha" ]; then
112 return 0
113 fi
114 echo "desktop-toolchain: fetching $name" >&2
115 local dl="$TC/.download.$name"
116 rm -rf "$dest" "$dest.tmp" "$dl"
117 mkdir -p "$dest.tmp"
118 curl -fsSL --retry 3 -o "$dl" "$url"
119 echo "$sha $dl" | sha256sum -c - >/dev/null
120 tar -xf "$dl" -C "$dest.tmp" --strip-components="$strip"
121 rm -f "$dl"
122 mv "$dest.tmp" "$dest"
123 echo "$sha" > "$stamp"
124}
125
126# The same, for something that is one file rather than an archive.
127install_file() {
128 local name=$1 url=$2 sha=$3 into=$4
129 local dest="$TC/$name" stamp="$TC/$name.sha256"
130 if [ -d "$dest" ] && [ "$(cat "$stamp" 2>/dev/null || true)" = "$sha" ]; then
131 return 0
132 fi
133 echo "desktop-toolchain: fetching $name" >&2
134 rm -rf "$dest" "$dest.tmp"
135 mkdir -p "$dest.tmp/$(dirname "$into")"
136 curl -fsSL --retry 3 -o "$dest.tmp/$into" "$url"
137 echo "$sha $dest.tmp/$into" | sha256sum -c - >/dev/null
138 mv "$dest.tmp" "$dest"
139 echo "$sha" > "$stamp"
140}
141
142# Source, by revision. `git -c advice.detachedHead=false` because this is
143# always a detached checkout and the advice is four lines of it per fetch.
144install_source() {
145 local name=$1 repo=$2 rev=$3
146 local dest="$TC/$name" stamp="$TC/$name.rev"
147 if [ -d "$dest" ] && [ "$(cat "$stamp" 2>/dev/null || true)" = "$rev" ]; then
148 return 0
149 fi
150 echo "desktop-toolchain: cloning $name at ${rev:0:8}" >&2
151 rm -rf "$dest" "$dest.tmp"
152 # A rev is not a ref, so this is init-fetch rather than clone --branch:
153 # `git clone --depth 1` cannot take a sha unless the server allows it, and
154 # `fetch --depth 1 <sha>` is the form that works everywhere.
155 mkdir -p "$dest.tmp"
156 git -C "$dest.tmp" init -q
157 git -C "$dest.tmp" remote add origin "$repo"
158 git -C "$dest.tmp" fetch -q --depth 1 origin "$rev"
159 git -C "$dest.tmp" -c advice.detachedHead=false checkout -q FETCH_HEAD
160 mv "$dest.tmp" "$dest"
161 echo "$rev" > "$stamp"
162}
163
164check_pins() {
165 if [ "$JOLT_NATIVE_SHA" = "0000000000000000000000000000000000000000000000000000000000000000" ]; then
166 cat >&2 <<MSG
167desktop-toolchain: the jolt-native portable tarball is not pinned yet.
168
169 It is published by the first pipeline to run on jolt-native's main at
170 ${JOLT_NATIVE_REV:0:8}. Once it exists:
171
172 curl -fsSL "$JOLT_NATIVE_URL" | sha256sum
173
174 and put that in JOLT_NATIVE_SHA here, or pass it for one run as
175 FRQ_JOLT_NATIVE_SHA=<sha256>.
176MSG
177 exit 1
178 fi
179}
180
181install_all() {
182 require_host_tools
183 check_pins
184 mkdir -p "$TC"
185 # strip 1: the jolt tarball is rooted at a versioned directory.
186 install_archive jolt "$JOLT_URL" "$JOLT_SHA" 1
187 # strip 0: the portable tarball is rooted at lib/ and include/ already,
188 # which is the shape a consumer is meant to take it in.
189 install_archive jolt-native "$JOLT_NATIVE_URL" "$JOLT_NATIVE_SHA" 0
190 install_file moq-ffi "$MOQ_FFI_URL" "$MOQ_FFI_SHA" lib/libmoq_ffi.so
191 install_source glimmer "$GLIMMER_REPO" "$GLIMMER_REV"
192 install_source jolt-native-src "$JOLT_NATIVE_REPO" "$JOLT_NATIVE_REV"
193}
194
195# The environment, as shell.
196#
197# JOLT_NATIVE_LIB is how jolt resolves every `:jolt/native` name, and it wants
198# ONE directory — the objects come from two places (the portable tarball and
199# the moq-ffi release), so `tools/build-desktop.sh` stages them into one and
200# this names where that landed.
201print_env() {
202 cat <<ENV
203export FRQ_DESKTOP_TOOLCHAIN="$TC"
204export JOLT_NATIVE_LIB="$TC/native"
205export LD_LIBRARY_PATH="$TC/native\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH}"
206export FRQ_GLIMMER="$TC/glimmer"
207export FRQ_GLIMMER_COSMIC="$TC/jolt-native-src/glimmer-backends/glimmer-cosmic"
208export PATH="$TC/jolt:\$PATH"
209ENV
210}
211
212case "${1:-install}" in
213 install) install_all ;;
214 env) install_all; print_env ;;
215 exec) install_all; eval "$(print_env)"; shift; [ "${1:-}" = "--" ] && shift; exec "$@" ;;
216 *) echo "usage: desktop-toolchain.sh [install|env|exec -- cmd...]" >&2; exit 1 ;;
217esac