#!/bin/sh
# Build quarry on a Linux host, with the zit it is meant to run against.
#
# Why a script and not a cross-compile: the DuckDB bindings ship a static
# C++ library per platform that links against the GNU C++ runtime, and a
# cross-link from macOS with zig's libc++ fails on missing std::string
# symbols (tried 2026-09-04). Building ON Linux is the honest path, and
# the golang image proves it works in a container before a VPS exists:
#
# docker run --rm -v "$PWD":/src -w /src golang:1.26 scripts/build-linux.sh
#
# zit is pinned to a RELEASE, not whatever is on PATH: 0001 §2 makes the
# zit CLI the entire store interface, so quarry's behaviour is zit's,
# and the two must not drift. The release tarballs are qualified per
# target (see zit's release-manifest.json) and checksummed.
#
# Inputs (environment):
# ZIT_VERSION zit release to install (default below)
# GITHUB_TOKEN read access to the private zit repository, for its release assets
# ZIT_RELEASE_DIR a directory holding the tarball and SHA256SUMS instead of a token
# VERSION stamp for `quarry version` (default: 0.1.0-beta+<checkout hash or "local">)
# PREFIX where binaries land (default: ./bin)
set -eu
ZIT_VERSION="${ZIT_VERSION:-0.3.4}"
PREFIX="${PREFIX:-$PWD/bin}"
mkdir -p "$PREFIX"
arch="$(uname -m)"
case "$arch" in
x86_64|amd64) zit_arch=x86_64 ;;
aarch64|arm64) zit_arch=aarch64 ;;
*) echo "build-linux: unsupported architecture $arch" >&2; exit 1 ;;
esac
[ "$(uname -s)" = Linux ] || { echo "build-linux: this builds on Linux (see the header for why)" >&2; exit 1; }
# ---- zit, from its release ---------------------------------------------
# The zit repository is private, so its release assets need a token
# (GITHUB_TOKEN, read access to danmestas/zit) and the API's asset
# route — the browser download URL answers 404 without a session.
# ZIT_RELEASE_DIR names a directory that already holds the tarball and
# SHA256SUMS, for a host with no token: copy them there and set it.
tarball="zit-${ZIT_VERSION}-linux-${zit_arch}.tar.gz"
work="$(mktemp -d)"
trap 'rm -rf "$work"' EXIT
if [ -n "${ZIT_RELEASE_DIR:-}" ]; then
echo "build-linux: using zit ${ZIT_VERSION} from $ZIT_RELEASE_DIR"
cp "$ZIT_RELEASE_DIR/$tarball" "$ZIT_RELEASE_DIR/SHA256SUMS" "$work/"
else
[ -n "${GITHUB_TOKEN:-}" ] || { echo "build-linux: set GITHUB_TOKEN (read access to danmestas/zit) or ZIT_RELEASE_DIR" >&2; exit 1; }
api="https://api.github.com/repos/danmestas/zit/releases/tags/version-${ZIT_VERSION}"
echo "build-linux: fetching zit ${ZIT_VERSION} for linux-${zit_arch}"
curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -H "Accept: application/vnd.github+json" "$api" > "$work/release.json"
for name in "$tarball" SHA256SUMS; do
id="$(grep -o "\"id\": *[0-9]*,\|\"name\": *\"[^\"]*\"" "$work/release.json" | awk -v n="$name" '
/"id":/ {gsub(/[^0-9]/,"",$0); last=$0}
/"name":/ {gsub(/"name": *"/,"",$0); gsub(/"/,"",$0); if ($0==n) {print last; exit}}')"
[ -n "$id" ] || { echo "build-linux: no asset $name on release version-${ZIT_VERSION}" >&2; exit 1; }
curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -H "Accept: application/octet-stream" \
"https://api.github.com/repos/danmestas/zit/releases/assets/$id" -o "$work/$name"
done
fi
( cd "$work" && grep " $tarball\$" SHA256SUMS | sha256sum -c - >/dev/null ) || {
echo "build-linux: checksum mismatch for $tarball" >&2; exit 1; }
tar -xzf "$work/$tarball" -C "$work"
install -m 0755 "$work/zit-${ZIT_VERSION}/zit" "$PREFIX/zit"
echo "build-linux: $("$PREFIX/zit" version)"
# ---- quarry, from this tree -------------------------------------------
if [ -z "${VERSION:-}" ]; then
tip="$("$PREFIX/zit" status 2>/dev/null | awk '/^checkout:/ {print substr($2,1,12)}')"
VERSION="0.1.0-beta+${tip:-local}"
fi
echo "build-linux: building quarry $VERSION with $(go version)"
CGO_ENABLED=1 go build -trimpath -ldflags "-X main.version=$VERSION" -o "$PREFIX/quarry" ./cmd/quarry
echo "build-linux: quarry built: $("$PREFIX/quarry" version 2>/dev/null || echo "$VERSION")"
echo "build-linux: binaries in $PREFIX"