These instructions originally came from this essay, as it runs Emacs as dæmon with LaunchAgent. Also fetch mails periodically with mbsync
via LaunchAgent.
Since I’ve been having difficulties installing Emacs from source on a Mac, I’m now taking advantage ofJim Myhrberg’s Emacs Build project, and it is must nicer to simply, download a pre-built binary with all the bells and whistles.
First, install the Homebrew cask:
brew tap jimeh/emacs-builds
And then, install Emacs:
brew install --cask emacs-app
If we can’t install a binary, we build from source.
No longer need to install Apple XCode, as these instructions require Homebrew.
If I want to build from source (and not build from Homebrew), install all the dependencies first, by running:
brew install pkg-config automake texinfo jpeg giflib\
libtiff jansson libpng librsvg gnutls cmake
To get the native compilation for Emacs working, install:
brew install libgccjit
Oh, and if we are still building with ImageMagick, install that first:
brew install imagemagick
Best success comes from using the emacs-plus installation. To begin, add the cask:
brew tap d12frosted/emacs-plus
I find that I need to … at least, on my work computer, install two different versions of Emacs that I use to distinguish one for “work” and the other for other activities, like IRC and elfeed. To that end, I run the following command to install Emacs:
brew install emacs-plus@29 --with-native-comp --with-mailutils --with-savchenkovaleriy-big-sur-icon --with-no-frame-refocus --debug
And if it fails, choose shell
and type:
make bootstrap
The failures that I often get from installing the Emacs Plus with Libgccjit, means that we might want to build from soure:
mkdir -p ~/src
git clone https://git.savannah.gnu.org/git/emacs.git ~/src/emacs
cd ~/src/emacs
./autogen.sh
And we can issue the same sort of configure we used for
./configure --disable-dependency-tracking --disable-silent-rules \
--enable-locallisppath=/opt/homebrew/share/emacs/site-lisp \
--infodir=/opt/homebrew/Cellar/emacs-plus@29/29.2/share/info/emacs \
--prefix=/opt/homebrew/Cellar/emacs-plus@29/29.2 \
--with-xml2 --with-gnutls --with-native-compilation --without-compress-install \
--without-dbus --without-imagemagick --with-modules --with-rsvg --without-pop \
--with-ns --disable-ns-self-contained
Or to install/build into /usr/local
:
LDFLAGS=-L/opt/homebrew/opt/libgccjit/lib -L/opt/homebrew/opt/xz/lib
CPPFLAGS=-I/opt/homebrew/opt/libgccjit/include -I/opt/homebrew/opt/xz/include
export LDFLAGS CPPFLAGS
./configure --disable-dependency-tracking --disable-silent-rules \
--prefix=/usr/local \
--with-xml2 --with-gnutls --with-native-compilation --without-compress-install \
--without-dbus --without-imagemagick --with-modules --with-rsvg --without-pop \
--with-ns --disable-ns-self-contained
Assuming that either works, then build it with:
make -j4
Sometimes get the following error:
ld: symbol(s) not found for architecture x86_64
And web searches yield mixed results. To solve, first re-touch the environment (as it appears the problem is that some dependent library is now out-of-date compared to operating system installation):
brew update
brew upgrade
Next make sure that all the dependencies are reinstalled with the current operating system:
brew reinstall $(brew deps emacs-plus@29)
Then reinstall the libgccjit
(as it doesn’t seem to get picked up with the deps listing):
brew uninstall libgccjit gcc
brew uninstall emacs-plus@29
brew install libgccjit gcc
And then reinstall Emacs above.
And if that doesn’t work, then we need to delete all packages installed by brew, and essentially start all over to see what sub-sub-sub-package got rebuilt without libgccjit
. Painful and time-consuming, but I basically let it run all night.
PKG_FILE=$(mktemp --suffix=.txt)
brew list --formula > ${PKG_FILE}
while read PACKAGE
do
brew uninstall ${PACKAGE}
done < ${PKG_FILE}
brew install libgccjit gcc
# No, it doesn't seem that reinstall actuall works.
while read PACKAGE
do
brew install ${PACKAGE}
done < ${PKG_FILE}
echo "Good luck rebuilding Emacs."
After Emacs is kinda working, make sure you install all the fonts, that is:
M-x all-the-icons-install-fonts
And to get the Doom Modeline working:
M-x nerd-icons-install-fonts
Everything golden?
M-x straight-freeze-versions
Before we can build a Telegram server for Telega, we need to install the latest version:
brew unlink tdlib # optional
brew install tdlib --HEAD
Now install all the extras:
brew install git-delta
brew install libvterm
brew install mu
brew install isync
brew install gpg
See ha-email for better instructions.
mkdir -p ~/.mail/work ~/.mail/gmail
mu init --maildir=~/.mail mu index
mbsync -Va
mu index
See ha-email for better instructions.
cat ~/.mbsyncrc
Basic configuration, that I actually supersede.
# ========== Gmail ==========
IMAPAccount gmail
Host imap.gmail.com
User [email protected]
PassCmd "/opt/homebrew/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 ==========
On the Mac, cron
has been removed and replaced with LaunchAgent
. I find my ICanHazShortcut process pretty simple to start Emacs, so I’m not sure about this dæmon, but …
Notice that UserName
section should be your $USER
value.
<?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>gnu.emacs</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/bin/emacs</string>
<string>--fg-dæmon</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/tmp/gnu-emacs-dæmon.log</string>
<key>StandardOutPath</key>
<string>/tmp/gnu-emacs-dæmon.log</string>
<key>UserName</key>
<string>howard</string>
</dict>
</plist>
Verify that the plist file is correct.
plutil -lint ~/Library/LaunchAgents/gnu.emacs.plist
Start, stop and list service.
launchctl load -w /Users/USERNAME/Library/LaunchAgents/gnu.emacs.plist
launchctl unload /Users/USERNAME/Library/LaunchAgents/gnu.emacs.plist
launchctl list
Let’s make another dæmon for fetching mail. Again, replace UserName
with your user account name.
<?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")"
/opt/homebrew/bin/mbsync -Va
echo "Exit code:"
echo $?
/opt/homebrew/bin/emacsclient -e '(mu4e-update-index)'
echo "Exit code:"
echo $?
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:
/opt/homebrew/bin/emacsclient -nc --socket-name work $*
Change the Pass Input to as arguments
.
Select to Save as Emacsclient
into the Applications folder.
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
man launchd
man launchctl
man launchd.plist
man plutil
man plist