jevsnes.git / tools / mcp / install.sh
1#!/usr/bin/env bash
2# Build `native` and keep a copy of it where `launch.sh` looks. See ./README.md.
3set -euo pipefail
4
5REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
6cd "$REPO_ROOT"
7
8# The library path the copy will run with is the DEVSHELL's: read it here,
9# inside the shell, and write it down for launch.sh, which runs outside one.
10if [[ -z "${IN_NIX_SHELL:-}" ]]; then
11    exec nix develop -c "$0" "$@"
12fi
13
14BIN_DIR="run/bin"
15ROOTS="$BIN_DIR/roots"
16mkdir -p "$BIN_DIR"
17
18built="$(buck2 build //apps/native:native --show-full-simple-output)"
19[[ -x "$built" ]] || { echo "install.sh: buck2 named no executable ($built)" >&2; exit 1; }
20
21# A copy, never a symlink into buck-out: buck-out is wiped (2026-09-21) and
22# rewritten mid-build, and either would take the proxy away from the client.
23# The rename is atomic, so a launch racing this sees the old copy or the new.
24cp "$built" "$BIN_DIR/native.new"
25# The hot-patch build keeps every symbol and all debug info (285 MB, measured
26# 2026-09-21). The proxy is never patched - patch.sh reads the WINDOW's own
27# /proc/PID/exe - so its copy drops the debug info; C: is the scarce thing.
28strip --strip-debug "$BIN_DIR/native.new"
29printf 'LD_LIBRARY_PATH=%s\n' "$LD_LIBRARY_PATH" >"$BIN_DIR/native.env.new"
30mv -f "$BIN_DIR/native.env.new" "$BIN_DIR/native.env"
31mv -f "$BIN_DIR/native.new" "$BIN_DIR/native"
32
33# The copy names store paths - its ELF interpreter and every library it links
34# - that nothing else keeps alive outside the devshell. Root the ones ldd
35# resolves, so a garbage collection cannot leave a binary that will not start.
36rm -rf "$ROOTS"
37mkdir -p "$ROOTS"
38i=0
39while read -r store; do
40    nix-store --add-root "$ROOTS/$i" --realise "$store" >/dev/null
41    i=$((i + 1))
42done < <(ldd "$BIN_DIR/native" | grep -o '/nix/store/[^/]*' | sort -u)
43
44echo "install.sh: $BIN_DIR/native from $built ($i store paths rooted)" >&2