blob: 5ac2d705994aa12fefd9b75125433f9eaf1dbcfa (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#!/usr/bin/env bash
# Craig Jennings <c@cjennings.net>
# Build & install Emacs from source
# safe, user-local, fast, versioned.
set -Eeuo pipefail
IFS=$'\n\t'
# ---------- Config (override via env) ----------
SRC_DIR="${SRC_DIR:-$HOME/code/emacs-src}"
EMACS_REPO="${EMACS_REPO:-https://git.savannah.gnu.org/git/emacs.git}"
CHECKOUT_REF="${CHECKOUT_REF:-emacs-30.2}"
PREFIX_BASE="${PREFIX_BASE:-$HOME/.local/src/emacs}"
PREFIX="${PREFIX:-$PREFIX_BASE/${CHECKOUT_REF}}"
LOG_DIR="${LOG_DIR:-$HOME/.cache/emacs-build-logs}"
ENABLE_NATIVE="${ENABLE_NATIVE:-1}"
WITH_PGTK="${WITH_PGTK:-auto}"
JOBS="${JOBS:-auto}"
EXTRA_CONFIG="${EXTRA_CONFIG:-}"
# ---------- Preflight ----------
umask 022
mkdir -p "$LOG_DIR" "$PREFIX_BASE" "$HOME/.local/bin"
: "${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; }
on_err(){ ec=$?; echo "ERROR [$ec] - see $LOGFILE" >&2; tail -n 80 "$LOGFILE" >&2 || true; exit "$ec"; }
trap on_err ERR
# ---------- Clone/update ----------
if [[ -d "$SRC_DIR/.git" ]]; then
run "git -C '$SRC_DIR' fetch --tags --prune"
else
mkdir -p "$(dirname "$SRC_DIR")"
run "git clone --origin origin '$EMACS_REPO' '$SRC_DIR'"
fi
run "git -C '$SRC_DIR' reset --hard HEAD"
run "git -C '$SRC_DIR' clean -fdx"
run "git -C '$SRC_DIR' checkout -f '$CHECKOUT_REF'"
run "git -C '$SRC_DIR' submodule update --init --recursive || true"
# ---------- Autogen ----------
if [[ -x "$SRC_DIR/autogen.sh" ]]; then
run "cd '$SRC_DIR' && ./autogen.sh"
fi
# ---------- Configure flags (ARRAY!) ----------
conf_flags=(
"--prefix=${PREFIX}"
"--with-json"
"--with-modules"
)
# Wayland/X choice
if [[ "$WITH_PGTK" == "auto" ]]; then
if [[ -n "${WAYLAND_DISPLAY:-}" ]]; then WITH_PGTK="yes"; else WITH_PGTK="no"; fi
fi
if [[ "$WITH_PGTK" == "yes" ]]; then
conf_flags+=("--with-pgtk")
else
conf_flags+=("--with-x-toolkit=lucid")
fi
# Native-compilation
if [[ "$ENABLE_NATIVE" == "1" ]]; then
conf_flags+=("--with-native-compilation=yes")
else
conf_flags+=("--with-native-compilation=no")
fi
# Useful extras (disable later via EXTRA_CONFIG if missing deps)
conf_flags+=(
"--with-cairo"
"--with-harfbuzz"
"--with-tree-sitter"
"--with-imagemagick"
"--with-mailutils"
)
# Optional extra flags from env
if [[ -n "$EXTRA_CONFIG" ]]; then
# shellcheck disable=SC2206
conf_flags+=($EXTRA_CONFIG)
fi
# ---------- Build & install ----------
mkdir -p "$PREFIX"
# Temporarily change IFS to space for configure argument expansion
old_ifs="$IFS"
IFS=' '
run "cd '$SRC_DIR' && ./configure ${conf_flags[*]}"
IFS="$old_ifs"
if [[ "$JOBS" == "auto" ]]; then
if command -v nproc >/dev/null 2>&1; then JOBS=$(nproc); else JOBS=4; fi
fi
run "cd '$SRC_DIR' && make -j$JOBS"
# Build documentation (info files)
say "...building info files"
(
cd "$SRC_DIR"
run "make info"
)
run "cd '$SRC_DIR' && make install"
run "cd '$SRC_DIR' && make install-info"
# ---------- Symlinks ----------
run "ln -sfn '$PREFIX' '$PREFIX_BASE/emacs-current'"
tmpdir="$(mktemp -d)"
for exe in "$PREFIX/bin/emacs" "$PREFIX/bin/emacsclient"; do
[[ -x "$exe" ]] || continue
ln -s "$exe" "$tmpdir/$(basename "$exe")"
done
mv -f "$tmpdir"/* "$HOME/.local/bin/" || { echo "Failed to install shims to ~/.local/bin" >&2; exit 72; }
rmdir "$tmpdir"
command -v emacs >/dev/null && emacs --version | head -n1 || true
command -v emacsclient >/dev/null && emacsclient --version | head -n1 || true
echo "Done. See $LOGFILE"
|