public/ghostty-build-update.sh

244 lines
6.0 KiB
Bash

#!/bin/bash
#Script to build ghostty from source. It automatically grabs required zig version binary.
#v1.0.3
set -euo pipefail
# === Config ===
PREFIX="${HOME}/.local"
OPTIMIZATION="ReleaseFast"
GHOSTTY_REPO="https://github.com/ghostty-org/ghostty.git"
GHOSTTY_PUBKEY="RWQlAjJC23149WL2sEpT/l0QKy7hMIFhYdQOFy0Z7z7PbneUgvlsnYcV"
BUILD_DIR="/tmp/ghostty_build"
CLEAN_BUILD=false
# === Parse arguments ===
for arg in "$@"; do
case $arg in
--clean)
CLEAN_BUILD=true
shift
;;
esac
done
# === Helpers ===
command_exists() { command -v "$1" >/dev/null 2>&1; }
info() { echo "==> $*"; }
error() { echo "ERROR: $*" >&2; exit 1; }
# === Create build directory ===
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
# === Version selection ===
choose_version() {
info "Fetching available Ghostty versions from GitHub..."
local tags
tags=$(curl -s https://api.github.com/repos/ghostty-org/ghostty/tags \
| grep '"name":' \
| cut -d'"' -f4)
if [ -z "$tags" ]; then
error "Could not fetch tags from GitHub."
fi
local latest
latest=$(echo "$tags" | head -n1)
echo
echo "Available Ghostty versions:"
echo " 0) $latest (latest release)"
echo " 1) tip (development)"
local i=2
local arr=()
while read -r tag; do
if [ "$tag" != "$latest" ] && [ "$tag" != "tip" ]; then
echo " $i) $tag"
arr+=("$tag")
i=$((i+1))
fi
done <<< "$tags"
echo
read -rp "Select a version [0-$((i-1))]: " choice
case "$choice" in
0) GHOSTTY_VERSION="$latest" ;;
1) GHOSTTY_VERSION="tip" ;;
*) local idx=$((choice-2)); GHOSTTY_VERSION="${arr[$idx]}" ;;
esac
info "Selected Ghostty version: $GHOSTTY_VERSION"
}
# === Zig version mapping ===
resolve_zig_version() {
case "$GHOSTTY_VERSION" in
1.0.*|1.1.*) echo "0.13.0" ;;
1.2.*) echo "0.14.1" ;;
tip) echo "0.14.1" ;;
v*)
local ver="${GHOSTTY_VERSION#v}"
case "$ver" in
1.0.*|1.1.*) echo "0.13.0" ;;
1.2.*) echo "0.14.1" ;;
*) error "Unknown mapping for Ghostty version $ver";;
esac
;;
*) error "Unknown Ghostty version format: $GHOSTTY_VERSION";;
esac
}
# === Download Zig standalone binary ===
setup_zig() {
local zig_version="$1"
local os=$(uname -s | tr '[:upper:]' '[:lower:]')
local arch=$(uname -m)
case "$os" in
linux) os="linux" ;;
darwin) os="macos" ;;
*) error "Unsupported OS: $os";;
esac
case "$arch" in
x86_64) arch="x86_64" ;;
aarch64|arm64) arch="aarch64" ;;
*) error "Unsupported arch: $arch";;
esac
local tarball
local dirname
if [[ "$zig_version" < "0.14.1" ]]; then
tarball="zig-${os}-${arch}-${zig_version}.tar.xz"
dirname="zig-${os}-${arch}-${zig_version}"
else
tarball="zig-${arch}-${os}-${zig_version}.tar.xz"
dirname="zig-${arch}-${os}-${zig_version}"
fi
if [ ! -d "$dirname" ]; then
info "Downloading Zig $zig_version from https://ziglang.org/download/$zig_version/$tarball"
curl -fLO "https://ziglang.org/download/$zig_version/$tarball"
tar -xf "$tarball"
fi
export PATH="$BUILD_DIR/$dirname:$PATH"
info "Using Zig at $(command -v zig) ($(zig version))"
}
# === Install build dependencies ===
install_deps_linux() {
if ! command_exists apt-get && ! command_exists pacman && ! command_exists dnf; then
error "No supported package manager found (apt, pacman, dnf). Install dependencies manually."
fi
local distro=""
if [ -f /etc/os-release ]; then
. /etc/os-release
distro="$ID"
fi
if command_exists apt-get; then
info "Installing dependencies via apt-get..."
sudo apt-get update
# Base packages
sudo apt-get install -y git libgtk-4-dev gettext libxml2-utils pkg-config curl tar xz-utils g++
# Harfbuzz development
sudo apt-get install -y libharfbuzz-dev libharfbuzz-gobject0
# GTK Blueprint compiler
sudo apt-get install -y blueprint-compiler
# libadwaita package
case "$distro" in
ubuntu|debian)
if ! sudo apt-get install -y libadwaita-1-dev; then
sudo apt-get install -y libadwaita-dev || true
fi
;;
*)
sudo apt-get install -y libadwaita-1-dev libadwaita-dev || true
;;
esac
# GTK layer-shell package
case "$distro" in
ubuntu)
sudo apt-get install -y libgtk-layer-shell-dev || true
;;
debian)
sudo apt-get install -y libgtk4-layer-shell-dev || true
;;
*)
sudo apt-get install -y libgtk4-layer-shell-dev libgtk-layer-shell-dev || true
;;
esac
# Verify critical pkg-config dependencies
for pkg in gtk4 libadwaita-1 gtk4-layer-shell; do
if ! pkg-config --exists "$pkg"; then
error "Missing required development package: $pkg. Did apt-get install succeed?"
fi
done
elif command_exists pacman; then
sudo pacman -Sy --noconfirm \
git gtk4 gtk4-layer-shell libadwaita gettext pkgconf curl tar xz g++ blueprint-compiler harfbuzz
elif command_exists dnf; then
sudo dnf install -y \
git gtk4-devel gtk4-layer-shell-devel libadwaita-devel \
gettext pkgconf curl tar xz g++ blueprint-compiler harfbuzz-devel
fi
}
# === Clone Ghostty repo and checkout version ===
fetch_source_git() {
if [ ! -d "ghostty" ]; then
git clone "$GHOSTTY_REPO"
fi
cd ghostty
git fetch --tags --quiet
if [ "$GHOSTTY_VERSION" = "tip" ]; then
git checkout main
else
git checkout "$GHOSTTY_VERSION"
fi
}
# === Build and install Ghostty ===
build_install() {
zig build -Doptimize="$OPTIMIZATION"
zig build install -p "$PREFIX" -Doptimize="$OPTIMIZATION"
info "Ghostty installed to $PREFIX/bin/ghostty"
}
# === Clean build directory ===
cleanup_build() {
if $CLEAN_BUILD; then
info "Cleaning up build directory $BUILD_DIR"
cd ..
rm -rf "$BUILD_DIR"
fi
}
# === Main ===
main() {
choose_version
if [[ "$(uname -s)" == "Linux" ]]; then
install_deps_linux
fi
local zig_ver
zig_ver=$(resolve_zig_version)
setup_zig "$zig_ver"
fetch_source_git
build_install
cleanup_build
}
main "$@"