Skip to main content

max / alloy

3.4 KB · 92 lines History Blame Raw
1 #!/usr/bin/env bash
2 #
3 # build-nvidia.sh — build alloy-nvidia, Alloy plus the open NVIDIA module.
4 #
5 # A thin derived image over an Alloy that already exists. It does not build
6 # Alloy: the whole point of the derived shape (alloy `2a382a75`, option c) is
7 # that the module is compiled against the kernel of one specific Alloy image,
8 # so the input is a digest and this script's job is to resolve one and hold it.
9 #
10 # aarch64 only, and that is not a limitation to lift. The card this exists for
11 # is in astra; CLAUDE.md forbids cross-compiling, and an x86_64 machine with an
12 # NVIDIA card would want the proprietary module rather than the open one
13 # Blackwell requires.
14 #
15 # Rootful, for build-image.sh's reason: it shares one container store with the
16 # Alloy build, so the digest below resolves without a rootless->rootful copy.
17 #
18 # Usage:
19 # build/build-nvidia.sh # derive from localhost/alloy:local
20 # build/build-nvidia.sh --digest sha256:... # derive from a named digest
21 # build/build-nvidia.sh --tag alloy-nvidia:aarch64
22
23 set -euo pipefail
24
25 REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
26
27 # priv / privc. See build/privilege.sh.
28 # shellcheck source=build/privilege.sh
29 . "$REPO_ROOT/build/privilege.sh"
30
31 BASE="localhost/alloy:local"
32 DIGEST=""
33 TAG="localhost/alloy-nvidia:aarch64"
34
35 while [ $# -gt 0 ]; do
36 case "$1" in
37 --digest) DIGEST="${2:?--digest needs a sha256:... value}"; shift 2 ;;
38 --base) BASE="${2:?--base needs an image}"; shift 2 ;;
39 --tag) TAG="${2:?--tag needs a name}"; shift 2 ;;
40 -h|--help) sed -n '2,25p' "$0"; exit 0 ;;
41 *) echo "error: unknown argument $1" >&2; exit 2 ;;
42 esac
43 done
44
45 arch="$(uname -m)"
46 if [ "$arch" != "aarch64" ]; then
47 echo "error: alloy-nvidia is aarch64 only; this is $arch." >&2
48 echo " The card it exists for is astra's. Builds are native per" >&2
49 echo " architecture (CLAUDE.md), so build it there." >&2
50 exit 1
51 fi
52
53 # The digest is the input, so it is resolved and printed rather than assumed.
54 # Deriving from a tag would mean two runs a week apart produced modules for
55 # different kernels while claiming the same provenance, which is the drift the
56 # base pins in the Containerfile exist to stop.
57 if [ -z "$DIGEST" ]; then
58 DIGEST="$(priv podman image inspect "$BASE" --format '{{.Digest}}' 2>/dev/null || true)"
59 [ -n "$DIGEST" ] || {
60 echo "error: no image $BASE to derive from." >&2
61 echo " Build Alloy first: build/build-image.sh --skip-bib" >&2
62 exit 1
63 }
64 fi
65
66 kernel="$(priv podman run --rm "$BASE" ls /usr/lib/modules | head -1)"
67 echo "deriving from $BASE"
68 echo " digest: $DIGEST"
69 echo " kernel: $kernel"
70 echo
71
72 priv podman build \
73 --build-arg "ALLOY_DIGEST=$DIGEST" \
74 -f "$REPO_ROOT/build/Containerfile.nvidia" \
75 -t "$TAG" \
76 "$REPO_ROOT"
77
78 echo
79 echo "built $TAG"
80 # Read back out of the finished image rather than trusting the build log: the
81 # Containerfile asserts this too, and a second reading from the outside is what
82 # a person checking the machine would do.
83 priv podman run --rm "$TAG" sh -c '
84 kernel="$(ls /usr/lib/modules | head -1)"
85 module="/usr/lib/modules/$kernel/extra/nvidia/nvidia.ko.xz"
86 [ -f "$module" ] || module="/usr/lib/modules/$kernel/extra/nvidia/nvidia.ko"
87 echo " kernel: $kernel"
88 echo " vermagic: $(modinfo -F vermagic "$module")"
89 echo " licence: $(modinfo -F license "$module")"
90 echo " version: $(modinfo -F version "$module")"
91 '
92