diff options
| -rwxr-xr-x | scripts/build-emacs.sh | 302 |
1 files changed, 194 insertions, 108 deletions
diff --git a/scripts/build-emacs.sh b/scripts/build-emacs.sh index 6750adce..8561db74 100755 --- a/scripts/build-emacs.sh +++ b/scripts/build-emacs.sh @@ -8,25 +8,11 @@ IFS=$'\n\t' # ------------------------ Config (overwrite via ENV) ----------------------- -SRC_DIR="${SRC_DIR:-$HOME/code/emacs-src}" +SRC_DIR="${SRC_DIR:-$HOME/.local/src/emacs}" 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}" -# Add DEBUG_BUILD flag -DEBUG_BUILD="${DEBUG_BUILD:-1}" -if [[ "$DEBUG_BUILD" == "1" ]]; then - PREFIX="${PREFIX:-$PREFIX_BASE/${CHECKOUT_REF}-debug}" - CFLAGS="${CFLAGS:--O0 -g}" - ENABLE_CHECKING="${ENABLE_CHECKING:-yes,glyphs}" - ENABLE_NATIVE="${ENABLE_NATIVE:-0}" # Disable native comp for debug -else - PREFIX="${PREFIX:-$PREFIX_BASE/${CHECKOUT_REF}}" - CFLAGS="${CFLAGS:--O2 -g}" - ENABLE_CHECKING="${ENABLE_CHECKING:-no}" - ENABLE_NATIVE="${ENABLE_NATIVE:-1}" -fi - LOG_DIR="${LOG_DIR:-$HOME/}" WITH_PGTK="${WITH_PGTK:-0}" JOBS="${JOBS:-auto}" @@ -36,11 +22,13 @@ EXTRA_CONFIG="${EXTRA_CONFIG:-}" 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}${DEBUG_BUILD:+-debug}.log}" +: "${LOGFILE:=$LOG_DIR/emacs-build-$(date +%Y%m%d-%H%M%S)-${CHECKOUT_REF}.log}" say() { printf '>>> %s\n' "$*" | tee -a "$LOGFILE" ; } run() { say "+ $*" + # shellcheck disable=SC2294 + # eval is necessary here because run() is called with shell command strings if ! eval "$@" >>"$LOGFILE" 2>&1; then echo "ERROR: Command failed: $*" >&2 echo "Last 20 lines of output:" >&2 @@ -69,12 +57,8 @@ if [[ "${ID:-}" == "arch" || "${ID_LIKE:-}" == *arch* ]]; then say "Arch Linux detected; checking required build/runtime packages" # Base packages needed for the requested configure flags - pkgs=(jansson tree-sitter imagemagick mailutils harfbuzz cairo gnutls libxml2 texinfo gtk3) - - # Only if native-compilation is enabled - if [[ "${ENABLE_NATIVE:-1}" == "1" ]]; then - pkgs+=(libgccjit) - fi + # Always include libgccjit since we'll be building the regular version with native-comp + pkgs=(jansson tree-sitter imagemagick mailutils harfbuzz cairo gnutls libxml2 texinfo gtk3 libgccjit) # List packages that are not installed missing="$(pacman -T "${pkgs[@]}" || true)" @@ -115,117 +99,214 @@ if [[ -x "$SRC_DIR/autogen.sh" ]]; then run "cd '$SRC_DIR' && ./autogen.sh" fi -# ------------------------------ Configure Flags ------------------------------ +# ----------------------------- Build Function ------------------------------ -conf_flags=( - "--prefix=${PREFIX}" - "--with-json" - "--with-modules" -) +build_emacs() { + local build_type="$1" + local PREFIX CFLAGS ENABLE_CHECKING ENABLE_NATIVE -# Add debug-specific flags -if [[ "$DEBUG_BUILD" == "1" ]]; then - say "Building DEBUG version with symbols and checking" - conf_flags+=( - "--enable-checking=${ENABLE_CHECKING}" - "--enable-check-lisp-object-type" - # Note the quotes around the entire CFLAGS assignment: - "CFLAGS=${CFLAGS}" # This keeps it as a single argument + say "==========================================" + say "Building ${build_type} version" + say "==========================================" + + # Set build-specific variables + if [[ "$build_type" == "debug" ]]; then + PREFIX="$PREFIX_BASE/${CHECKOUT_REF}-debug" + CFLAGS="-O0 -g" + ENABLE_CHECKING="yes,glyphs" + ENABLE_NATIVE="0" # Disable native comp for debug + else + PREFIX="$PREFIX_BASE/${CHECKOUT_REF}" + CFLAGS="-O2 -g" + ENABLE_CHECKING="no" + ENABLE_NATIVE="1" + fi + +# ------------------------------ Configure Flags ------------------------------ + + local conf_flags=( + "--prefix=${PREFIX}" + "--with-json" + "--with-modules" ) -fi -# 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=gtk3") -fi + # Add debug-specific flags + if [[ "$build_type" == "debug" ]]; then + say "Building DEBUG version with symbols and checking" + conf_flags+=( + "--enable-checking=${ENABLE_CHECKING}" + "--enable-check-lisp-object-type" + "CFLAGS=${CFLAGS}" + ) + fi -# Native-compilation -if [[ "$ENABLE_NATIVE" == "1" ]]; then - conf_flags+=("--with-native-compilation=yes") -else - conf_flags+=("--with-native-compilation=no") -fi + # 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=gtk3") + fi -# Useful extras -conf_flags+=( - "--with-cairo" - "--with-harfbuzz" - "--with-tree-sitter" - "--with-imagemagick" - "--with-mailutils" -) - -# Optional extra flags from env -if [[ -n "$EXTRA_CONFIG" ]]; then - conf_flags+=($EXTRA_CONFIG) -fi + # Native-compilation + if [[ "$ENABLE_NATIVE" == "1" ]]; then + conf_flags+=("--with-native-compilation=yes") + else + conf_flags+=("--with-native-compilation=no") + fi -# ----------------------------- Build And Install ----------------------------- + # Useful extras + conf_flags+=( + "--with-cairo" + "--with-harfbuzz" + "--with-tree-sitter" + "--with-imagemagick" + "--with-mailutils" + ) -mkdir -p "$PREFIX" + # Optional extra flags from env + if [[ -n "$EXTRA_CONFIG" ]]; then + # shellcheck disable=SC2206 + # Word splitting is intentional here to allow multiple flags in EXTRA_CONFIG + conf_flags+=($EXTRA_CONFIG) + fi -# Temporarily change IFS to space for configure argument expansion -old_ifs="$IFS" -IFS=' ' -cd "$SRC_DIR" -"./configure" "${conf_flags[@]}" -IFS="$old_ifs" +# ----------------------------- Build And Install ----------------------------- -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" + mkdir -p "$PREFIX" -# Build documentation (info files) -say "...building info files" -( + # Temporarily change IFS to space for configure argument expansion + local old_ifs="$IFS" + IFS=' ' cd "$SRC_DIR" - run "make info" -) + say "Running configure with flags: ${conf_flags[*]}" + if ! "./configure" "${conf_flags[@]}" >>"$LOGFILE" 2>&1; then + echo "ERROR: Configure failed" >&2 + echo "Last 50 lines of output:" >&2 + tail -n 50 "$LOGFILE" >&2 + exit 1 + fi + IFS="$old_ifs" + + local num_jobs="$JOBS" + if [[ "$num_jobs" == "auto" ]]; then + if command -v nproc >/dev/null 2>&1; then num_jobs=$(nproc); else num_jobs=4; fi + fi + run "cd '$SRC_DIR' && make -j$num_jobs" -run "cd '$SRC_DIR' && make install" -run "cd '$SRC_DIR' && make install-info" + # 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 -------------------------------- -if [[ "$DEBUG_BUILD" == "1" ]]; then - run "ln -sfn '$PREFIX' '$PREFIX_BASE/emacs-debug'" - # Create debug-specific symlinks - for exe in emacs emacsclient; do - target="$PREFIX/bin/$exe" - link="$HOME/.local/bin/${exe}-debug" - if [[ -x "$target" ]]; then - run "rm -f '$link'" - run "ln -s '$target' '$link'" - fi - done - say "Debug build available as 'emacs-debug' and 'emacsclient-debug'" + if [[ "$build_type" == "debug" ]]; then + run "ln -sfn '$PREFIX' '$PREFIX_BASE/emacs-debug'" + # Create debug-specific symlinks + for exe in emacs emacsclient; do + target="$PREFIX/bin/$exe" + link="$HOME/.local/bin/${exe}-debug" + if [[ -x "$target" ]]; then + run "rm -f '$link'" + run "ln -s '$target' '$link'" + fi + done + say "Debug build available as 'emacs-debug' and 'emacsclient-debug'" + else + run "ln -sfn '$PREFIX' '$PREFIX_BASE/emacs-current'" + for exe in emacs emacsclient; do + target="$PREFIX/bin/$exe" + link="$HOME/.local/bin/$exe" + if [[ -x "$target" ]]; then + run "rm -f '$link'" + run "ln -s '$target' '$link'" + fi + done + fi +} # End of build_emacs function + +# ----------------------------- Build Both Versions ----------------------------- + +say "Building both regular and debug versions of Emacs..." + +# Build regular version first +build_emacs "regular" + +# Build debug version second +build_emacs "debug" + +# ---------------------------- Post-Build Validation ---------------------------- + +say "Running post-build validation checks..." + +# Check that both binaries exist and are executable +if [[ ! -x "$HOME/.local/bin/emacs" ]]; then + echo "ERROR: Regular emacs binary not found or not executable" >&2 + exit 1 +fi +say "✓ Regular emacs binary exists and is executable" + +if [[ ! -x "$HOME/.local/bin/emacs-debug" ]]; then + echo "ERROR: Debug emacs binary not found or not executable" >&2 + exit 1 +fi +say "✓ Debug emacs binary exists and is executable" + +# Check that the binaries are actually different +if cmp -s "$HOME/.local/bin/emacs" "$HOME/.local/bin/emacs-debug"; then + echo "ERROR: Regular and debug builds are identical!" >&2 + exit 1 +fi +say "✓ Regular and debug builds are different" + +# Check that debug build has debug symbols +if ! readelf -S "$HOME/.local/bin/emacs-debug" 2>/dev/null | grep -q "\.debug_"; then + echo "WARNING: Debug build may not have debug symbols" >&2 else - run "ln -sfn '$PREFIX' '$PREFIX_BASE/emacs-current'" - for exe in emacs emacsclient; do - target="$PREFIX/bin/$exe" - link="$HOME/.local/bin/$exe" - if [[ -x "$target" ]]; then - run "rm -f '$link'" - run "ln -s '$target' '$link'" - fi - done + say "✓ Debug build contains debug symbols" +fi + +# Smoke test both versions +if ! "$HOME/.local/bin/emacs" --batch --eval '(message "Regular: %s" emacs-version)' 2>&1 | grep -q "Regular:"; then + echo "ERROR: Regular emacs failed smoke test" >&2 + exit 1 fi +say "✓ Regular emacs smoke test passed" + +if ! "$HOME/.local/bin/emacs-debug" --batch --eval '(message "Debug: %s" emacs-version)' 2>&1 | grep -q "Debug:"; then + echo "ERROR: Debug emacs failed smoke test" >&2 + exit 1 +fi +say "✓ Debug emacs smoke test passed" + +say "All validation checks passed!" # ---------------------------------- Wrap Up ---------------------------------- +say "==========================================" +say "Both builds completed successfully!" +say "==========================================" + +# Show version info for both builds command -v emacs >/dev/null && emacs --version | head -n1 || true -command -v emacsclient >/dev/null && emacsclient --version | head -n1 || true +command -v emacs-debug >/dev/null && emacs-debug --version | head -n1 || true # ----------------------------- Show Build Features ---------------------------- -say "Launching Emacs to display version and build features..." -"$HOME/.local/bin/emacs" -Q --batch --eval ' +show_build_features() { + local emacs_bin="$1" + local build_name="$2" + + say "Launching $build_name to display version and build features..." + "$emacs_bin" -Q --batch --eval ' (progn (princ (format "Emacs version: %s\n" emacs-version)) (princ (format "Build configuration:\n")) @@ -242,5 +323,10 @@ say "Launching Emacs to display version and build features..." (princ (format "\nFull system configuration:\n%s\n" system-configuration)) (princ (format "\nConfigured features:\n%s\n" system-configuration-features))) ' 2>&1 | tee -a "$LOGFILE" +} + +show_build_features "$HOME/.local/bin/emacs" "Regular build" +echo "" +show_build_features "$HOME/.local/bin/emacs-debug" "Debug build" echo "Done. See $LOGFILE" |
