← Commit history

chore(tools): add install.sh, an idempotent toolchain installer for pacman, apt and dnf

lennoxrose committed on Oct 18, 2026 at 23:09 UTC

7e4705eparentce3e1ab

1 file changed+85−0

Installs the C, Fortran, Zig, nasm, debugging and cross-compile tools plus
rustup (stable and nightly with miri) and cbindgen. --check only reports what
is missing.

tools/install.shadded

+85−0
@@ -0,0 +1,85 @@
1+#!/usr/bin/env bash
2+# Mnemosyne / Ash toolchain installer. Safe to re-run; installs only what is missing.
3+#
4+# tools/install.sh install everything
5+# tools/install.sh --check only report what is missing (exit 1 if anything is)
6+#
7+# Supports pacman (Arch/CachyOS), apt (Debian/Ubuntu) and dnf (Fedora).
8+# Rust comes from rustup on every distro (stable + nightly/miri for memory checking).
9+set -euo pipefail
10+
11+CHECK=0
12+[[ "${1:-}" == "--check" ]] && CHECK=1
13+
14+# command -> package, per package manager. "-" means not packaged: handled below.
15+# cmd pacman apt dnf
16+TOOLS=(
17+ "git git git git"
18+ "curl curl curl curl"
19+ "make make make make"
20+ "gcc gcc build-essential gcc"
21+ "g++ gcc g++ gcc-c++"
22+ "clang clang clang clang"
23+ "cmake cmake cmake cmake"
24+ "pkg-config pkgconf pkg-config pkgconf-pkg-config"
25+ "ld binutils binutils binutils"
26+ "gfortran gcc-fortran gfortran gcc-gfortran"
27+ "nasm nasm nasm nasm"
28+ "zig zig - zig"
29+ "gdb gdb gdb gdb"
30+ "valgrind valgrind valgrind valgrind"
31+ "strace strace strace strace"
32+ "perf perf linux-tools-generic perf"
33+ "x86_64-w64-mingw32-gcc mingw-w64-gcc gcc-mingw-w64-x86-64 mingw64-gcc"
34+ "wine wine wine64 wine"
35+ "qemu-system-x86_64 qemu-system-x86 qemu-system-x86 qemu-system-x86"
36+)
37+
38+if command -v pacman >/dev/null; then PM=pacman; COL=2
39+elif command -v apt-get >/dev/null; then PM=apt; COL=3
40+elif command -v dnf >/dev/null; then PM=dnf; COL=4
41+else echo "unsupported distro: need pacman, apt or dnf" >&2; exit 2; fi
42+
43+missing_cmds=(); pkgs=()
44+for row in "${TOOLS[@]}"; do
45+ read -ra f <<<"$row"
46+ cmd=${f[0]}; pkg=${f[$((COL-1))]}
47+ command -v "$cmd" >/dev/null && continue
48+ missing_cmds+=("$cmd")
49+ [[ "$pkg" == "-" ]] && { echo "note: $cmd is not packaged for $PM; install it from https://ziglang.org/download" >&2; continue; }
50+ pkgs+=("$pkg")
51+done
52+
53+have_rust() { command -v rustup >/dev/null || [[ -x "$HOME/.cargo/bin/rustup" ]]; }
54+have_rust || missing_cmds+=("rustup")
55+
56+if (( CHECK )); then
57+ if (( ${#missing_cmds[@]} )); then echo "missing: ${missing_cmds[*]}"; exit 1; fi
58+ echo "all tools present"; exit 0
59+fi
60+
61+SUDO=""; [[ $EUID -ne 0 ]] && SUDO="sudo"
62+
63+if (( ${#pkgs[@]} )); then
64+ mapfile -t pkgs < <(printf '%s\n' "${pkgs[@]}" | sort -u)
65+ echo ">> installing: ${pkgs[*]}"
66+ case $PM in
67+ pacman) $SUDO pacman -S --needed --noconfirm "${pkgs[@]}" ;;
68+ apt) $SUDO apt-get update && $SUDO apt-get install -y "${pkgs[@]}" ;;
69+ dnf) $SUDO dnf install -y "${pkgs[@]}" ;;
70+ esac
71+fi
72+
73+# Rust: rustup so nightly + miri (UB / aliasing checker for unsafe code) are available.
74+export PATH="$HOME/.cargo/bin:$PATH"
75+if ! command -v rustup >/dev/null; then
76+ echo ">> installing rustup"
77+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable
78+fi
79+rustup component add rustfmt clippy
80+rustup toolchain install nightly --profile minimal --component miri --component rust-src
81+command -v cbindgen >/dev/null || cargo install cbindgen # generates the C ABI header from Rust
82+
83+echo
84+echo "done. Add to your shell if not already: export PATH=\"\$HOME/.cargo/bin:\$PATH\""
85+echo "fish: fish_add_path ~/.cargo/bin"