From c167aea5bcc1572eccdc6dcf6cf82c48547c1d78 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Wed, 3 Sep 2025 02:15:48 -0500 Subject: adding build-emacs script --- dotfiles/system/.local/bin/build-emacs.sh | 146 ++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100755 dotfiles/system/.local/bin/build-emacs.sh diff --git a/dotfiles/system/.local/bin/build-emacs.sh b/dotfiles/system/.local/bin/build-emacs.sh new file mode 100755 index 0000000..f3f0f9b --- /dev/null +++ b/dotfiles/system/.local/bin/build-emacs.sh @@ -0,0 +1,146 @@ +#!/usr/bin/env bash +# Craig Jennings +# Build & install Emacs from source +# safe, versioned, user-local, blunt, fast, reversible. + +set -euo pipefail + +### --------- CONFIG (edit these) --------- +# Where the git checkout lives: +SRC_DIR="${SRC_DIR:-$HOME/code/emacs-src}" + +# Which repo/branch/tag to build: +EMACS_REPO="${EMACS_REPO:-https://git.savannah.gnu.org/git/emacs.git}" +CHECKOUT_REF="${CHECKOUT_REF:-emacs-29.2}" # e.g. "emacs-30.1", "master", "emacs-29" + +# Install prefix (keeps versions side-by-side): +PREFIX_BASE="${PREFIX_BASE:-$HOME/.local/opt}" +PREFIX="${PREFIX:-$PREFIX_BASE/${CHECKOUT_REF}}" + +# Optional knobs: +ENABLE_NATIVE="${ENABLE_NATIVE:-0}" # 1 to enable native-comp if toolchain supports it +ENABLE_PGTK="${ENABLE_PGTK:-0}" # 1 to use pgtk (Wayland-only build) +ENABLE_XWIDGETS="${ENABLE_XWIDGETS:-0}" # 1 to enable xwidgets (known flaky on some 29/30 tags) +MAKE_JOBS="${MAKE_JOBS:-$(command -v nproc >/dev/null 2>&1 && nproc || sysctl -n hw.ncpu || echo 4)}" + +# CFLAGS (tune lightly; keep reproducible): +CFLAGS_OVERRIDES="${CFLAGS_OVERRIDES:--O2 -march=native}" + +LOG_DIR="${LOG_DIR:-$HOME/.cache/build-logs}" +mkdir -p "$LOG_DIR" +LOGFILE="$LOG_DIR/emacs-build-$(date +%Y%m%d-%H%M%S)-${CHECKOUT_REF}.log" +### --------------------------------------- + +say() { printf '%s\n' "$*" | tee -a "$LOGFILE" ; } +run() { say "+ $*"; eval "$@" >>"$LOGFILE" 2>&1; } + +trap 'echo "ERROR: see $LOGFILE" >&2' ERR + +say ">>> Building Emacs" +say "SRC_DIR=$SRC_DIR" +say "CHECKOUT_REF=$CHECKOUT_REF" +say "PREFIX=$PREFIX" +say "LOGFILE=$LOGFILE" + +# Fetch or update source +if [[ -d "$SRC_DIR/.git" ]]; then + say "...updating existing checkout" + (cd "$SRC_DIR" && run "git fetch --tags --prune" && run "git status --porcelain") +else + say "...cloning source" + mkdir -p "$(dirname "$SRC_DIR")" + run "git clone --depth=1 --branch ${CHECKOUT_REF} ${EMACS_REPO} ${SRC_DIR}" || { + # If ref isn’t a branch, do full clone then checkout tag + run "git clone ${EMACS_REPO} ${SRC_DIR}" + } +fi + +# Checkout desired ref/tag +( + cd "$SRC_DIR" + run "git fetch --tags --force" + run "git checkout ${CHECKOUT_REF}" +) + +# Autogen/bootstrap (needed for git checkouts) +if [[ -x "$SRC_DIR/autogen.sh" ]]; then + say "...running autogen.sh" + (cd "$SRC_DIR" && run "./autogen.sh") +fi + +# Configure flags +conf_flags=( + "--prefix=${PREFIX}" + "--with-json" + "--with-modules" + "--with-cairo" + "--with-harfbuzz" + "--with-native-compilation=$( [[ $ENABLE_NATIVE -eq 1 ]] && echo yes || echo no )" + "--with-mailutils" + "--with-imagemagick" +) + +# pgtk vs X +if [[ $ENABLE_PGTK -eq 1 ]]; then + conf_flags+=("--with-pgtk" "--without-x") +else + conf_flags+=("--with-x" "--with-x-toolkit=gtk3") +fi + +# xwidgets if requested +if [[ $ENABLE_XWIDGETS -eq 1 ]]; then + conf_flags+=("--with-xwidgets") +fi + +# Prefer system tree-sitter if present +if pkg-config --exists tree-sitter 2>/dev/null; then + conf_flags+=("--with-tree-sitter") +fi + +say "...configure flags:" +printf ' %s\n' "${conf_flags[@]}" | tee -a "$LOGFILE" + +# Configure +mkdir -p "$PREFIX" # ensure we can write there +( + cd "$SRC_DIR" + run "env CFLAGS='${CFLAGS_OVERRIDES}' ./configure ${conf_flags[*]}" +) + +# Build (and bootstrap if needed) +say "...compiling (jobs=$MAKE_JOBS)" +( + cd "$SRC_DIR" + # master sometimes needs bootstrap after significant changes; harmless otherwise: + run "make -j${MAKE_JOBS}" +) + +# Install to user-local prefix +say "...installing to ${PREFIX}" +( + cd "$SRC_DIR" + run "make install" +) + +# ymlink all installed executables (emacs, emacsclient, etags, etc.) +mkdir -p "$HOME/.local/bin" + +# Atomic swap: build symlinks in a temp dir, then move them into place. +tmpdir="$(mktemp -d)" +for exe in "$PREFIX/bin/"*; do + [ -x "$exe" ] || continue + name="$(basename "$exe")" + ln -s "$exe" "$tmpdir/$name" +done + +# Move into ~/.local/bin (overwriting existing symlinks/files with same names) +for link in "$tmpdir"/*; do + name="$(basename "$link")" + mv -f "$link" "$HOME/.local/bin/$name" +done +rmdir "$tmpdir" + +# Optional: quick sanity print +command -v emacs >/dev/null && emacs --version | head -n1 || true +command -v emacsclient >/dev/null && emacsclient --version | head -n1 || true + -- cgit v1.2.3