Emacs 29 brings built-in SQLite support that is superior to the community developed packages I’ve tried. Debian’s latest Emacs binary is version 28, which does not have this feature. I’d also like to turn on a few additional features like tree-sitter1. This article was adapted and expanded from this one - but I found it made a few mistakes and was missing a few details.

To start, take a deep breath and purge all Emacs packages from your system. autoremove will clean up any stray packages.

sudo apt remove emacs emacs-common
sudo apt autoremove

Let’s also clean up our Emacs directory while we’re at it. While the compiled .elc files should work with an updated version of Emacs, it’s nice to recompile everything from scratch.

cd ~/.emacs.d/
rm -rf elpa
rm -rf straight

Next, install build dependencies:

sudo apt update
sudo apt-get build-dep emacs
sudo apt install libmagickwand-dev libmagickcore-dev

On Ubuntu, you’ll have to do this before installing the build dependencies:

# Add the following snippet to /etc/apt/sources.list.d/ubuntu.sources
Types: deb-src
URIs: http://us.archive.ubuntu.com/ubuntu/
Suites: noble noble-updates noble-backports noble-proposed
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

To keep organized, create a source directory to keep all of this work in.

mkdir source
cd source

Tree-sitter enables a variety of benefits - clone, make, and install it.

sudo apt install libtree-sitter0

# Alternatively
cd ~/source/
git clone https://github.com/tree-sitter/tree-sitter.git
cd tree-sitter
make
sudo make install

Finally, we arrive at the interesting bit - actually cloning and installing Emacs from source. Cloning and building can take anywhere from a few minutes to fifteen, depending on the speed and age of your machine. For starters, clone the repository and run the autogen script.

cd ~ && mkdir source && cd ~/source/
git clone -b emacs-29 git://git.sv.gnu.org/emacs.git
cd emacs
git clean -f -d -x  # run if you changed branches
./autogen.sh

To configure my installation of Emacs I use the following flags. Your mileage may vary, and you may need a slightly different set for your system. Read ./configure --help first if you’d like to know more about any of the options below.

./configure --with-native-compilation=aot \
            --with-tree-sitter \
            --with-modules \
            --with-threads \
            --with-mailutils \
            --with-tree-sitter \
            --with-imagemagick \
            --with-json \
            --with-x-toolkit=lucid  # Use the older 'lucid' gui toolkit over GTK
            # --with-xwidgets       # If using GTK, include XWidgets
  • If you are on Wayland, replace the x-toolkit line with --with-pgtk
  • If you don’t know, run echo $XDG_SESSION_TYPE to find out
  • The Lucid graphics have always been much faster than GTK for me

You could run sudo make uninstall if you previously installed Emacs with make.

The final steps - compile and install Emacs 29:

make clean
LD_LIBRARY_PATH=/usr/local/lib/  make
LD_LIBRARY_PATH=/usr/local/lib/  sudo make install

Emacs should now be compiled and installed! You may need to log out and back in for your window manager to identify the launch icons.

Once you have launched Emacs and perhaps used the --debug-init flag to fix any problems in your configuration, tree-sitter can be set up by adding the following to your configs:

(setq treesit-language-source-alist
  '(
    (elixir "https://github.com/elixir-lang/tree-sitter-elixir")
    (clojure "https://github.com/sogaiu/tree-sitter-clojure")
    (bash "https://github.com/tree-sitter/tree-sitter-bash")
    (cmake "https://github.com/uyha/tree-sitter-cmake")
    (c "https://github.com/tree-sitter/tree-sitter-c")
    (elisp "https://github.com/Wilfred/tree-sitter-elisp")
    (html "https://github.com/tree-sitter/tree-sitter-html")
    (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src")
    (json "https://github.com/tree-sitter/tree-sitter-json")
    (make "https://github.com/alemuller/tree-sitter-make")
    (markdown "https://github.com/ikatyang/tree-sitter-markdown")
    (python "https://github.com/tree-sitter/tree-sitter-python")))

Now in ielm or a scratch buffer in Emacs run the following:

;; To install a few:
(mapcar #'treesit-install-language-grammar
    '(bash elisp markdown python clojure elixir))

;; To install everything:
(mapcar #'treesit-install-language-grammar
    (mapcar 'car treesit-language-source-alist))

That’s all for now. Enjoy your speedy compiled copy of Emacs!

Compiling on MacOS

On a Mac I highly recommend using jimeh/build-emacs-for-macos over any homebrew installation or DIY method. Extract and copy the resulting .app in the archive to Applications and you’ll be done. This is the fastest, smoothest, crispiest EMACS install I have used on Mac yet!

You’ll need to have asdf and homebrew installed - the makefiles in the repository will do the rest.

asdf plugin add ruby https://github.com/asdf-vm/asdf-ruby.git
asdf install ruby latest
asdf use ruby 3.4.2
make bootstrap
./build-emacs-for-macos emacs-29.4