| Three tarballs where a devShell was 5ce66d5 nandi yesterday | 1 | #!/usr/bin/env bash |
| 2 | # The toolchain the web build needs, fetched by hand. |
| 3 | # |
| The last of the Clojure 284b59c nandi 20h ago | 4 | # Archives — Flutter (which carries Dart) and Nim — |
| Three tarballs where a devShell was 5ce66d5 nandi yesterday | 5 | # pinned by version and by sha256, unpacked into `.toolchain/`, and put on a |
| 6 | # PATH. That is the whole of it. No nix, no image, no devShell: a checkout |
| Six verbs, and the last of the nix 2e24e64 nandi yesterday | 7 | # plus this script is a machine that can build any target here, and the same |
| 8 | # script is what the Modal containers run. |
| 9 | # |
| 10 | # The Android SDK is the one thing not fetched by default, because only |
| Three tarballs where a devShell was 5ce66d5 nandi yesterday | 11 | set -euo pipefail |
| 12 | |
| 13 | root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" |
| 14 | TC="${FRQ_TOOLCHAIN:-$root/.toolchain}" |
| 15 | |
| 16 | # The pins. A version and its hash, and nothing derived at run time: a |
| 17 | # toolchain that resolves "latest" is a toolchain that changes under you |
| 18 | # between two builds of the same commit. |
| 19 | # |
| 20 | # Flutter 3.47.0 is the version this tree was building with under nix, and |
| 21 | # its Dart 3.13.0 is what `flutter/pubspec.yaml` asks for with `sdk: ^3.13.0`. |
| 22 | # To move it: take `version`, `archive` and `sha256` from |
| 23 | # https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json |
| 24 | FLUTTER_VERSION="3.47.0" |
| 25 | FLUTTER_URL="https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${FLUTTER_VERSION}-stable.tar.xz" |
| 26 | FLUTTER_SHA="26cd99d3d94b1367e6b50535a18aeef0282c10a535bbe3ec493534dcdab75296" |
| 27 | |
| 28 | |
| Six verbs, and the last of the nix 2e24e64 nandi yesterday | 29 | # Nim, for `nim/` — the portable core. Upstream's prebuilt linux_x64 tarball, |
| 30 | # so there is no bootstrap compile here. The core deliberately has no |
| 31 | # dependencies outside Nim's standard library, so the compiler is all of it. |
| 32 | # |
| 33 | # Two things Nim wants from the host rather than from here: a C compiler, |
| 34 | # because `nim c` shells out to one, and OpenSSL, because `-d:ssl` in |
| 35 | # nim/nim.cfg makes std/net resolve -lssl and -lcrypto through dynlib at run |
| 36 | # time. A missing libssl is a SIGSEGV in `newContext` that says nothing about |
| 37 | # SSL, which is why require_host_tools checks for cc up front. |
| 38 | NIM_VERSION="2.2.4" |
| 39 | NIM_URL="https://nim-lang.org/download/nim-${NIM_VERSION}-linux_x64.tar.xz" |
| 40 | NIM_SHA="791802138aaf19c8579232c50b4998ce2ae2928b791127ce5b4ef3c7af53fb46" |
| 41 | |
| 42 | |
| Three tarballs where a devShell was 5ce66d5 nandi yesterday | 43 | # What the host still has to bring. Small, boring, and on every machine and |
| 44 | # in every base image that is not deliberately empty — but Flutter shells out |
| 45 | # to `git` on its own SDK and to `unzip` on its downloads, so a missing one |
| 46 | # fails somewhere far from here with a much worse message than this. |
| 47 | require_host_tools() { |
| 48 | local missing=() |
| Six verbs, and the last of the nix 2e24e64 nandi yesterday | 49 | for t in curl tar git unzip cc; do |
| Three tarballs where a devShell was 5ce66d5 nandi yesterday | 50 | command -v "$t" >/dev/null 2>&1 || missing+=("$t") |
| 51 | done |
| 52 | if [ ${#missing[@]} -gt 0 ]; then |
| 53 | echo "toolchain: this needs ${missing[*]} on PATH and cannot fetch them" >&2 |
| 54 | exit 1 |
| 55 | fi |
| 56 | } |
| 57 | |
| 58 | # One archive, unpacked once. The stamp holds the hash rather than the |
| 59 | # version, so re-pointing a pin at the same version with different bytes also |
| 60 | # refetches, and a half-finished unpack is never mistaken for a finished one: |
| 61 | # the work happens in `.tmp` and the `mv` at the end is what publishes it. |
| 62 | install_archive() { |
| 63 | local name=$1 url=$2 sha=$3 strip=$4 |
| 64 | local dest="$TC/$name" stamp="$TC/$name.sha256" |
| 65 | if [ -d "$dest" ] && [ "$(cat "$stamp" 2>/dev/null || true)" = "$sha" ]; then |
| 66 | return 0 |
| 67 | fi |
| 68 | echo "toolchain: fetching $name" >&2 |
| 69 | local dl="$TC/.download.$name" |
| 70 | rm -rf "$dest" "$dest.tmp" "$dl" |
| 71 | mkdir -p "$dest.tmp" |
| 72 | curl -fsSL --retry 3 -o "$dl" "$url" |
| 73 | echo "$sha $dl" | sha256sum -c - >/dev/null |
| 74 | tar -xf "$dl" -C "$dest.tmp" --strip-components="$strip" |
| 75 | rm -f "$dl" |
| 76 | mv "$dest.tmp" "$dest" |
| 77 | echo "$sha" > "$stamp" |
| 78 | } |
| 79 | |
| 80 | # Upstream's install.sh, minus the ruby. The scripts ship with `PREFIX` and |
| 81 | # `BINDIR` written into them literally and an installer that substitutes the |
| 82 | # directory it is installing to; this is that, done where the tarball landed. |
| 83 | |
| Six verbs, and the last of the nix 2e24e64 nandi yesterday | 84 | # The Android SDK, which is a zip rather than a tarball and has to land in a |
| 85 | # layout sdkmanager recognises: cmdline-tools/latest/, with the tools' own |
| 86 | # top-level directory renamed. Everything after that — platform-tools, the |
| 87 | # platform, the build-tools — Gradle asks sdkmanager for as it goes, which is |
| 88 | # why this directory is ours and writable rather than a read-only artifact. |
| 89 | # |
| 90 | |
| Three tarballs where a devShell was 5ce66d5 nandi yesterday | 91 | install_all() { |
| 92 | require_host_tools |
| 93 | mkdir -p "$TC" |
| 94 | install_archive flutter "$FLUTTER_URL" "$FLUTTER_SHA" 1 |
| Six verbs, and the last of the nix 2e24e64 nandi yesterday | 95 | install_archive nim "$NIM_URL" "$NIM_SHA" 1 |
| Three tarballs where a devShell was 5ce66d5 nandi yesterday | 96 | } |
| 97 | |
| The last of the Clojure 284b59c nandi 20h ago | 98 | # The environment, as shell. What would otherwise land in a home directory is |
| 99 | # named here and kept inside the toolchain instead — one directory to keep on |
| 100 | # a volume, one directory to delete when it goes wrong. |
| Three tarballs where a devShell was 5ce66d5 nandi yesterday | 101 | # |
| The last of the Clojure 284b59c nandi 20h ago | 102 | # It used to carry a JDK, the Clojure CLI, a maven repo, a gitlibs cache and |
| 103 | # an Android SDK. All of those were ClojureDart's or the APK's, and both are |
| 104 | # gone: the toolchain is a Flutter and a Nim now. |
| Three tarballs where a devShell was 5ce66d5 nandi yesterday | 105 | print_env() { |
| 106 | cat <<ENV |
| 107 | export FRQ_TOOLCHAIN="$TC" |
| 108 | # Flutter's SDK tarball is a git checkout, and the tool shells out to git |
| 109 | # against it for its version -- which fails with "detected dubious ownership" |
| 110 | # whenever the files' owner is not the user running the build. That is the |
| 111 | # normal case on a Modal volume, and the failure is not a warning: the dart |
| 112 | # process ClojureDart's live analyzer talks to dies with it, and the compile |
| 113 | # ends at 'EOF while reading' with nothing about git in the message. |
| 114 | # |
| 115 | # Said through the environment rather than 'git config --global', so it |
| 116 | # travels with this shell and writes nothing into anyone's ~/.gitconfig. |
| 117 | export GIT_CONFIG_COUNT=1 |
| 118 | export GIT_CONFIG_KEY_0=safe.directory |
| 119 | export GIT_CONFIG_VALUE_0="$TC/flutter" |
| 120 | export PUB_CACHE="$TC/pub-cache" |
| The last of the Clojure 284b59c nandi 20h ago | 121 | export PATH="$TC/flutter/bin:$TC/nim/bin:\$PATH" |
| Three tarballs where a devShell was 5ce66d5 nandi yesterday | 122 | ENV |
| 123 | } |
| 124 | |
| 125 | case "${1:-install}" in |
| 126 | install) install_all ;; |
| 127 | env) install_all; print_env ;; |
| 128 | exec) |
| 129 | install_all |
| 130 | shift |
| 131 | [ "${1:-}" = "--" ] && shift |
| 132 | eval "$(print_env)" |
| 133 | exec "$@" |
| 134 | ;; |
| 135 | versions) |
| 136 | echo "flutter $FLUTTER_VERSION" |
| Six verbs, and the last of the nix 2e24e64 nandi yesterday | 137 | echo "nim $NIM_VERSION" |
| Three tarballs where a devShell was 5ce66d5 nandi yesterday | 138 | ;; |
| The last of the Clojure 284b59c nandi 20h ago | 139 | *) echo "usage: toolchain.sh [install|env|exec -- cmd...|versions]" >&2; exit 1 ;; |
| Three tarballs where a devShell was 5ce66d5 nandi yesterday | 140 | esac |