Emacs: how I build from emacs.git on Debian stable
I have been following the master
branch of the emacs.git repository
for many years now. It helps me test new features and make necessary
adjustments to all the packages I develop/maintain. Below I explain
how I make this happen on my computer, which is running Debian stable
(Debian 12 “Bookworm” as of this writing). If you are a regular user,
there is no reason to build from source: just use the latest stable
release and you should be fine.
Configure the apt
development sources
To build Emacs from source on Debian, you first need to have the
deb-src
package archive enabled. In your /etc/apt/sources.list
file you must have something like this:
deb http://deb.debian.org/debian/ bookworm main
deb-src http://deb.debian.org/debian/ bookworm main
After modifying the sources, run the following on the command line to fetch the index with new package names+versions:
sudo apt update
Get the Emacs build dependencies
Now that you have enabled the deb-src
archive, you can install the
build dependencies of the Debian emacs
package with the following on
the command line:
sudo apt build-dep emacs
With this done, you are ready to build Emacs from source.
Get the Emacs source code
You need the git
program to get the source code from the emacs.git
website. So install it with this command:
sudo apt install git
Now make a copy of the Emacs source code, using this on the command line:
git clone https://git.savannah.gnu.org/git/emacs.git ~/path/to/my/copy-of-emacs.git
Replace ~/path/to/my/copy-of-emacs.git
with the actual destination
of your preference. I have a ~/Builds
directory where I store all
the projects I build from source. I thus do:
git clone https://git.savannah.gnu.org/git/emacs.git ~/Builds/emacs.git
If the cloning process is too slow on your end, perform a shallow clone instead. For example:
git clone --depth 1 https://git.savannah.gnu.org/git/emacs.git ~/Builds/emacs.git
And if the Savannah website is not responsive, then clone from the
GitHub mirror (with the --depth 1
if necessary):
git clone https://github.com/emacs-mirror/emacs.git ~/Builds/emacs.git
Switch to the Emacs directory
Assuming you have the copy of emacs.git stored at ~/Builds/emacs.git
,
you switch to that directory with the following:
cd ~/Builds/emacs.git
Keep in mind that unless you explicitly switch to another branch, you
are on master
, i.e. the latest development target.
NOTE: All subsequent commands are ran from your equivalent of
~/Builds/emacs.git
.
Run the autogen.sh
the first time
This script will generate the configuration scaffold. You only really need to do this once (and I always forget about it for this very reason). Simply do this on the command line:
./autogen.sh
It checks that you have all you need to get started and prints output like this:
Checking whether you have the necessary tools...
(Read INSTALL.REPO for more details on building Emacs)
Checking for autoconf (need at least version 2.65) ... ok
Your system has the required tools.
Building aclocal.m4 ...
Running 'autoreconf -fi -I m4' ...
Building 'aclocal.m4' in exec ...
Running 'autoreconf -fi' in exec ...
Configuring local git repository...
'.git/config' -> '.git/config.~1~'
git config transfer.fsckObjects 'true'
git config diff.cpp.xfuncname '!^[ ]*[A-Za-z_][A-Za-z_0-9]*:[[:space:]]*($|/[/*])
^((::[[:space:]]*)?[A-Za-z_][A-Za-z_0-9]*[[:space:]]*\(.*)$
^((#define[[:space:]]|DEFUN).*)$'
git config diff.elisp.xfuncname '^\([^[:space:]]*def[^[:space:]]+[[:space:]]+([^()[:space:]]+)'
git config diff.m4.xfuncname '^((m4_)?define|A._DEFUN(_ONCE)?)\([^),]*'
git config diff.make.xfuncname '^([$.[:alnum:]_].*:|[[:alnum:]_]+[[:space:]]*([*:+]?[:?]?|!?)=|define .*)'
git config diff.shell.xfuncname '^([[:space:]]*[[:alpha:]_][[:alnum:]_]*[[:space:]]*\(\)|[[:alpha:]_][[:alnum:]_]*=)'
git config diff.texinfo.xfuncname '^@node[[:space:]]+([^,[:space:]][^,]+)'
Installing git hooks...
'build-aux/git-hooks/commit-msg' -> '.git/hooks/commit-msg'
'build-aux/git-hooks/pre-commit' -> '.git/hooks/pre-commit'
'build-aux/git-hooks/prepare-commit-msg' -> '.git/hooks/prepare-commit-msg'
'build-aux/git-hooks/post-commit' -> '.git/hooks/post-commit'
'build-aux/git-hooks/pre-push' -> '.git/hooks/pre-push'
'build-aux/git-hooks/commit-msg-files.awk' -> '.git/hooks/commit-msg-files.awk'
'.git/hooks/applypatch-msg.sample' -> '.git/hooks/applypatch-msg'
'.git/hooks/pre-applypatch.sample' -> '.git/hooks/pre-applypatch'
You can now run './configure'.
Do not be intimidated by it. Focus on the final line instead, which
directs you to the configure
directive.
Explore the build flags
How exactly you build Emacs depends on your preferences and system-specific requirements. At the end of this post, I copy my current configuration, though I advise against copying it without understanding what it does.
If you have no specific preferences, just use the defaults by running this on the command line:
./configure
It will set up the build environment for you. If, however, you wish
to explore your options and customise the emacs
program you will
get, then issue the following command and carefully read its output:
./configure --help
The minimum I recommend is to specify where the build artefacts are stored. I use this, which has not caused me any issues over the years:
./configure --prefix=/usr/local
Configure the build environment with your preferred flags
Once you have understood the available options, go ahead and run
configure
. For example:
./configure --prefix=/usr/local --with-x-toolkit=gtk3
Whenever you need to rebuild Emacs with some new flags, run the
configure
command again, passing it the relevant flags. If you wish
to keep the same options for a new build, then simply do not run
configure
again.
Make the program
Once configure
finishes its work, it is time to run the make
program. For new builds, this is as simple as:
make
Sometimes you have old build artefacts that conflict with changes upstream. When that happens, the build process will fail. You may then need to use:
make bootstrap
In general, make
is enough. It will be slow the first time, but will
be faster on subsequent runs as it reuses what is already there. A
make bootstrap
will always be slow though, as it generates
everything anew.
Install the program that was made
After make
is done, you are ready to install Emacs:
sudo make install
You will not need escalated privileges (i.e. sudo
) is you specified
a --prefix
with a user directory during the configure
step. How
you go about it is up to you.
Keeping Emacs up-to-date
Whenever you wish to update from source, go to where your copy of
emacs.git is (e.g. ~/Builds/emacs.git
) and pull the latest changes
using the git
program:
git pull
Then repeat make
and make install
. Remember that you do not need
to re-run configure
unless you specifically want to modify your
build (and if you do that, you probably need to make bootstrap
).
Learn about the latest NEWS
Emacs users can at all times learn about changes introduced in their
current version of Emacs with M-x view-emacs-news
. It is bound to
the key C-h n
by default. This command opens the current NEWS
file. With a numeric prefix argument, you get the NEWS
of the given
Emacs version. For example, C-u 27 C-h n
shows you what Emacs
version 27 introduced.
Compare your NEWS
to those of emacs.git
With the help of the built-in Emacs ediff
package, you can compare
your latest NEWS
to those coming from emacs.git. I always do this
after pulling the latest changes from source (with git pull
).
From the root directory of your copye of emacs.git (e.g.
~/Builds/emacs.git
), and while using Emacs, you can do M-x
project-find-file
(C-x p f
) to search the Emacs “project” for a
file called etc/NEWS
. This is where the latest user-facing changes
are recorded.
If you are not sure where you are on the filesystem while inside
Emacs, do M-x cd
(or M-x dired
or M-x find-file
), select the
root directory of your emacs.git, hit RET
, and then do M-x
project-find-file
.
Now that you have emacs.git/etc/NEWS
in a buffer, also load your
copy of NEWS
with M-x view-emacs-news
(C-h n
).
Then do M-x ediff-buffers
, which will prompt for two buffers to
compare. First select your version of NEWS
and then that of emacs.git.
NOTE: I think the default Ediff interface is problematic. Put the following in your configuration to make it work in a single frame:
(setq ediff-split-window-function 'split-window-horizontally)
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
Also watch my video with the Ediff basics: https://protesilaos.com/codelog/2023-11-17-emacs-ediff-basics/.
This is it. You are now in the flow of building Emacs from source. Good luck with everything!
My current build options
--prefix=/usr/local --without-xinput2 --without-compress-install --without-gpm --without-selinux --with-native-compilation=yes --with-sound=no --without-gif --without-tiff --with-cairo --with-harfbuzz --with-tree-sitter=ifavailable --with-json --without-gsettings --without-gconf --with-x-toolkit=no --without-toolkit-scroll-bars --without-xft --without-xaw3d
I am not updating old publications, unless otherwise noted. The most up-to-date recode of my Emacs build is documented in my dotemacs: https://protesilaos.com/emacs/dotemacs.
Inspect the value of the Emacs variable system-configuration-options
to find out how your Emacs is built.
Have fun!