Skip to main content

Emacs 31 is out and it's not yet in Sid, so let's build it from source! First, fetch, configure and build it; fortunately Emacs 31 is fairly close to Emacs 30 in terms of build deps so there's not much to do:

❯ cd ~/src/thirdparty
❯ git clone https://github.com/emacs-mirror/emacs.git && cd emacs
...
❯ git checkout emacs-31.1
...
❯ run0 apt build-dep emacs
...
❯ run0 apt install libgccjit-16-dev  # need to get this manually, since emacs=30 depends on the version of gcc that was in trixie
...
❯ run0 apt install libwebkit2gtk-4.1-dev  # needed for --with-xwidgets
...
❯ ./autogen.sh
...
❯ CFLAGS="-O2 -march=native" ./configure --with-native-compilation --with-tree-sitter --with-xwidgets --with-pgtk --with-file-notification=inotify --with-libsystemd --with-sound=alsa
...
❯ make -j $(nproc)
...

A couple of things:

To install it, I'm going to use this package, which copies the files and installs a little emacs-snapshot package to satisfy Debian dependencies:

❯ cd ~/src/thirdparty
❯ git clone https://github.com/ktetzlaff/src-emacs-on-debian.git
...
❯ cd emacs  # the script is run from the *Emacs* source dir since it's installing it
❯ run0 ../src-emacs-on-debian/restore-emacs  # install it and set some symlinks
...
❯ emacs -nw --debug-init  # I like to run it from the command line once to let my config download and build things

and here it is:

❯ apt-cache showpkg emacs-snapshot
Package: emacs-snapshot
...
Provides:
2:1.0 - news-reader (= ) mail-reader (= ) info-browser (= ) emacsen (= ) editor (= )

To load the provided debian-init.el, ~/.emacs.d/init.el needs a small snippet near the top:

(when (and (eq system-type 'gnu/linux)
           (file-readable-p "/etc/os-release")
           (with-temp-buffer
             (insert-file-contents "/etc/os-release")
             (goto-char (point-min))
             (re-search-forward "^ID=[\"']?debian[\"']?$" nil t))
           invocation-directory
           (file-equal-p
            (expand-file-name invocation-name invocation-directory)
            "/usr/local/bin/emacs"))
  (let ((debian-init (expand-file-name
                      "~/src/thirdparty/src-emacs-on-debian/debian-init.el")))
    (when (file-exists-p debian-init)
      (load debian-init nil 'nomessage 'nosuffix))))

My first attempt used (string=) instead of (file-equal-p), which was buggy - the script also creates /usr/bin/emacs-snapshot that points to /usr/local/bin/emacs, and that won't match if it's invoked via the symlink.