Installing Emacs on Ubuntu
Table of Contents
These instructions originally came from this essay.
To get the native compilation for Emacs working, first install all the pre-reqs, and we seem to need a lot of them:
sudo apt update sudo apt upgrade # Instead of this: sudo apt install -y build-essential autoconf # We can not just call this: sudo apt build-dep -y emacs # We will build using the GTK and related libraries, # instead of good ol' X11: sudo apt install -y libc6-dev libgtk-3-dev xaw3dg-dev \ zlib1g-dev libice-dev libsm-dev libx11-dev libxext-dev # Nifty new stuff supported in Emacs needs libraries: sudo apt install -y libjansson4 libjansson-dev \ gnutls-bin libtree-sitter-dev # I am not sure if/why we need these guys, but ... sudo apt install -y libxi-dev libxmu-dev libxmuu-dev \ libxrandr-dev libxt-dev libxtst-dev libxv-dev \ libattr1-dev # And install all the image libraries (otherwise, we need # the venerable imagemagick library): sudo apt install -y libtiff5-dev libgif-dev \ libpng-dev libxpm-dev libncurses-dev libtiff-dev \ libwebkit2gtk-4.0-dev libjpeg-dev # Or do we want the specific: libjpeg62-dev
Oh, and if we are still building with ImageMagick, install that too:
sudo apt-get install texinfo imagemagick
We need libgccjit that matches the GCC installed, e.g. 12
:
GCC_VERSION=$(gcc --version | head -1 | cut -d' ' -f4 | cut -d. -f1) sudo apt install libgccjit-${GCC_VERSION}-dev
Clone the Emacs repo, and jump on the latest, almost-released branch:
mkdir -p ~/other ; cd ~/other git clone git://git.sv.gnu.org/emacs emacs cd emacs git checkout -b emacs29
Then let’s build it:
./autogen.sh ./configure --with-native-compilation --with-cairo --with-json \ --with-xml2 --with-mailutils --with-tree-sitter --with-pgtk \ --with-gnutls=ifavailable --with-tiff=ifavailable \ --program-suffix=30 \ CFLAGS="-O3 -mtune=native -march=native -fomit-frame-pointer" make -j$(nproc) && sudo make install
Supporting Packages
Now install all the extras:
sudo apt install -y libvterm-dev sudo apt install -y git-delta sudo apt install -y mu4e isync sudo apt install -y gpg
Mu4a
See ha-email for better instructions.
mkdir -p ~/.mail/work ~/.mail/gmail mu init --maildir=~/.mail mu index mbsync -Va mu index
Mbsync config
See ha-email for better instructions.
cat ~/.mbsyncrc
Basic configuration, that I actually supersede.
# ========== Gmail ========== IMAPAccount gmail Host imap.gmail.com User username@gmail.com PassCmd "/usr/bin/gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.password-store/mbsync/gmail.gpg" AuthMechs LOGIN SSLType IMAPS IMAPStore gmail-remote Account gmail MaildirStore gmail-local Subfolders Verbatim Path ~/.mail/gmail/ Inbox ~/.mail/gmail/Inbox Channel gmail Far :gmail-remote: Near :gmail-local: Patterns * ![Gmail]* "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail" Expunge None CopyArrivalDate yes Sync All Create Near SyncState * # ========== Gmail ==========
Dæmon Processes
According to this essay, we have several ways to launch Emacs as a daemon during startup. Since systemd
is the init
daemon in v20+, we register Emacs as a service under systemd
to be launched during startup. Systemd will monitor this service and restart if the service crashes for any reason. To configure the service, we first create the file ~/.config/systemd/user/emacs.service
and copy the below:
[Unit] Description=Emacs text editor Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/ [Service] Type=forking ExecStart=/usr/local/bin/emacs --daemon ExecStop=/usr/local/bin/emacsclient --eval "(kill-emacs)" Environment=SSH_AUTH_SOCK=%t/keyring/ssh Restart=on-failure [Install] WantedBy=default.target
Then run the following in the terminal:
systemctl enable --user emacs systemctl start --user emacs
Verify that the emacs service is running by using:
systemctl status --user emacs
Now, we only use emacsclient
. We have these terminal alias:
e
: Open a terminal versionee
: Open an Emacs frame
Fetch mails periodically
Let’s make another dæmon for fetching mail. Perhaps we should use gnubiff instead.
[Unit] Description=Mbsync Mail Fetcher Documentation=https://www.systutorials.com/docs/linux/man/1-mbsync/ [Service] Type=forking ExecStart=/usr/bin/mbsync --daemon ExecStop=/usr/bin/mbsync --eval "(kill-mbsync)" Environment=SSH_AUTH_SOCK=%t/keyring/ssh Restart=on-failure [Install] WantedBy=default.target
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>KeepAlive</key> <true/> <key>Label</key> <string>periodic.mbsync</string> <key>ProgramArguments</key> <array> <string>/Users/USERNAME/.bin/mbsync-task</string> </array> <key>StandardOutPath</key> <string>/tmp/mbsync-task.log</string> <key>StandardErrorPath</key> <string>/tmp/mbsync-task.log</string> <key>ThrottleInterval</key> <integer>180</integer> <key>RunAtLoad</key> <true/> <key>UserName</key> <string>howard</string> </dict> </plist>
Verify that the plist file is correct.
plutil -lint ~/Library/LaunchAgents/periodic.mbsync.plist
Start, stop and list service.
launchctl load -w /Users/USERNAME/Library/LaunchAgents/periodic.mbsync.plist launchctl unload /Users/USERNAME/Library/LaunchAgents/periodic.mbsync.plist launchctl list
Script that fetches mails and updates the mail index.
echo "" echo "Running $(date +"%Y-%m-%d %H:%M")" /usr/bin/mbsync -Va echo "Exit code:" echo $? /usr/local/bin/emacsclient -e '(mu4e-update-index)' echo "Exit code:" echo $?
Emacsclient
Simple Automator script that’s wrapped into an application and placed in the Applications
folder. Select New Document, then select Application. Open the Library, and drag the Run Shell Script to the workflow. In the box, add this:
/usr/local/bin/emacsclient -nc --socket-name work $*
Change the Pass Input to as arguments
.
Select to Save as Emacsclient
into the Applications folder.
Utils
Convert a plist XML file into a JSON file. Not sure why this is important to know…
plutil -convert json -r ~/Library/LaunchAgents/gnu.emacs.plist
Which should look a bit like:
{ "KeepAlive" : true, "Label" : "gnu.emacs", "ProgramArguments" : [ "\/opt\/homebrew\/bin\/emacs", "--fg-dæmon" ], "RunAtLoad" : true, "StandardErrorPath" : "\/tmp\/gnu-emacs-dæmon.log", "StandardOutPath" : "\/tmp\/gnu-emacs-dæmon.log", "UserName" : "USERNAME" }
Convert it back to XML
plutil -convert xml1 ~/Library/LaunchAgents/gnu.emacs.plist
Resources
man launchd man launchctl man launchd.plist man plutil man plist