988c0dac2e
Oh, and let's fix the FILETAGS. Thank goodness for woccurrrrrr.
350 lines
12 KiB
Org Mode
350 lines
12 KiB
Org Mode
#+title: Installing Emacs on MacOS
|
||
#+author: Howard X. Abrams
|
||
#+date: 2022-09-02 September
|
||
#+tags: emacs macos readme
|
||
|
||
These instructions originally came from [[https://jherrlin.github.io/posts/emacs-on-macos-monterey/][this essay]], as it runs Emacs as dæmon with LaunchAgent. Also fetch mails periodically with =mbsync= via LaunchAgent.
|
||
* Install
|
||
Since I’ve been having difficulties installing Emacs from source on a Mac, I’m now taking advantage of[[https://github.com/jimeh/emacs-builds][Jim 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:
|
||
#+begin_src sh
|
||
brew tap jimeh/emacs-builds
|
||
#+end_src
|
||
And then, install Emacs:
|
||
#+begin_src sh
|
||
brew install --cask emacs-app
|
||
#+end_src
|
||
* Install from Source
|
||
If we can’t install a binary, we build from source.
|
||
** Emacs Plus
|
||
No longer need to install [[https://apps.apple.com/us/app/xcode/id497799835?mt=12][Apple XCode]], as these instructions require [[https://brew.sh][Homebrew]].
|
||
|
||
If I want to build from source (and not build from Homebrew), install all the dependencies first, by running:
|
||
#+begin_src sh
|
||
brew install pkg-config automake texinfo jpeg giflib\
|
||
libtiff jansson libpng librsvg gnutls cmake
|
||
#+end_src
|
||
|
||
To get the native compilation for Emacs working, install:
|
||
#+begin_src sh
|
||
brew install libgccjit
|
||
#+end_src
|
||
|
||
Oh, and if we are still building with [[https://imagemagick.org/][ImageMagick]], install that first:
|
||
#+begin_src sh
|
||
brew install imagemagick
|
||
#+end_src
|
||
|
||
Best success comes from using the [[https://github.com/d12frosted/homebrew-emacs-plus][emacs-plus]] installation. To begin, add the /cask/:
|
||
#+begin_src sh
|
||
brew tap d12frosted/emacs-plus
|
||
#+end_src
|
||
|
||
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 [[file:ha-feed-reader.org][elfeed]]. To that end, I run the following command to install Emacs:
|
||
#+begin_src sh
|
||
brew install emacs-plus@29 --with-native-comp --with-mailutils --with-savchenkovaleriy-big-sur-icon --with-no-frame-refocus --debug
|
||
#+end_src
|
||
And if it fails, choose =shell= and type:
|
||
#+begin_src sh
|
||
make bootstrap
|
||
#+end_src
|
||
** Build from Scratch
|
||
The failures that I often get from installing the Emacs Plus with Libgccjit, means that we might want to build from soure:
|
||
#+begin_src sh
|
||
mkdir -p ~/src
|
||
git clone https://git.savannah.gnu.org/git/emacs.git ~/src/emacs
|
||
cd ~/src/emacs
|
||
./autogen.sh
|
||
#+end_src
|
||
And we can issue the same sort of configure we used for
|
||
#+begin_src sh
|
||
./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
|
||
#+end_src
|
||
Or to install/build into =/usr/local=:
|
||
#+begin_src sh
|
||
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
|
||
#+end_src
|
||
Assuming that either works, then build it with:
|
||
#+begin_src sh
|
||
make -j4
|
||
#+end_src
|
||
** Ouchie
|
||
Sometimes get the following error:
|
||
#+begin_example
|
||
ld: symbol(s) not found for architecture x86_64
|
||
#+end_example
|
||
|
||
And [[https://duckduckgo.com/?q=brew+ld%3A+symbol(s)+not+found+for+architecture+x86_64&t=ffab&ia=web][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):
|
||
#+begin_src sh
|
||
brew update
|
||
brew upgrade
|
||
#+end_src
|
||
|
||
Next make sure that all the dependencies are /reinstalled/ with the current operating system:
|
||
#+begin_src sh
|
||
brew reinstall $(brew deps emacs-plus@29)
|
||
#+end_src
|
||
|
||
Then reinstall the =libgccjit= (as it doesn’t seem to get picked up with the /deps/ listing):
|
||
#+begin_src sh
|
||
brew uninstall libgccjit gcc
|
||
brew uninstall emacs-plus@29
|
||
brew install libgccjit gcc
|
||
#+end_src
|
||
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.
|
||
#+begin_src sh
|
||
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."
|
||
#+end_src
|
||
* Afterwards
|
||
After Emacs is /kinda/ working, make sure you install *all* the fonts, that is:
|
||
#+begin_example
|
||
M-x all-the-icons-install-fonts
|
||
#+end_example
|
||
And to get the Doom Modeline working:
|
||
#+begin_example
|
||
M-x nerd-icons-install-fonts
|
||
#+end_example
|
||
|
||
Everything golden?
|
||
#+begin_example
|
||
M-x straight-freeze-versions
|
||
#+end_example
|
||
|
||
Before we can build a Telegram server for [[file:ha-aux-apps.org::*Telega][Telega]], we need to install the /latest/ version:
|
||
#+begin_src sh
|
||
brew unlink tdlib # optional
|
||
brew install tdlib --HEAD
|
||
#+end_src
|
||
* Supporting Packages
|
||
Now install all the extras:
|
||
#+begin_src sh
|
||
brew install git-delta
|
||
brew install libvterm
|
||
brew install mu
|
||
brew install isync
|
||
brew install gpg
|
||
#+end_src
|
||
** Mu4a
|
||
See [[file:ha-email.org][ha-email]] for better instructions.
|
||
#+begin_src sh
|
||
mkdir -p ~/.mail/work ~/.mail/gmail
|
||
mu init --maildir=~/.mail mu index
|
||
mbsync -Va
|
||
mu index
|
||
#+end_src
|
||
** Mbsync config
|
||
See [[file:ha-email.org][ha-email]] for better instructions.
|
||
#+begin_src sh
|
||
cat ~/.mbsyncrc
|
||
#+end_src
|
||
Basic configuration, that I actually supersede.
|
||
#+begin_src conf
|
||
# ========== Gmail ==========
|
||
IMAPAccount gmail
|
||
Host imap.gmail.com
|
||
User username@gmail.com
|
||
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 ==========
|
||
#+end_src
|
||
* Dæmon Processes
|
||
On the Mac, =cron= has been removed and replaced with =LaunchAgent=. I find my [[file:ha-capturing-notes.org::*Push MacOS-Specific Content][ICanHazShortcut]] process pretty simple to start Emacs, so I’m not sure about this dæmon, but …
|
||
** Emacs dæmon via LaunchAgent
|
||
Notice that =UserName= section should be your =$USER= value.
|
||
#+begin_src xml :tangle ~/Library/LaunchAgents/gnu.emacs.plist
|
||
<?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>
|
||
#+end_src
|
||
|
||
Verify that the plist file is correct.
|
||
#+begin_src sh
|
||
plutil -lint ~/Library/LaunchAgents/gnu.emacs.plist
|
||
#+end_src
|
||
|
||
Start, stop and list service.
|
||
#+begin_src sh
|
||
launchctl load -w /Users/USERNAME/Library/LaunchAgents/gnu.emacs.plist
|
||
launchctl unload /Users/USERNAME/Library/LaunchAgents/gnu.emacs.plist
|
||
launchctl list
|
||
#+end_src
|
||
** Fetch mails periodically
|
||
Let’s make another dæmon for fetching mail. Again, replace =UserName= with your user account name.
|
||
#+begin_src xml :tangle ~/Library/LaunchAgents/periodic.mbsync.plist
|
||
<?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>
|
||
#+end_src
|
||
|
||
Verify that the plist file is correct.
|
||
#+begin_src sh
|
||
plutil -lint ~/Library/LaunchAgents/periodic.mbsync.plist
|
||
#+end_src
|
||
|
||
Start, stop and list service.
|
||
#+begin_src sh
|
||
launchctl load -w /Users/USERNAME/Library/LaunchAgents/periodic.mbsync.plist
|
||
launchctl unload /Users/USERNAME/Library/LaunchAgents/periodic.mbsync.plist
|
||
launchctl list
|
||
#+end_src
|
||
|
||
Script that fetches mails and updates the mail index.
|
||
#+begin_src sh :tangle ~/.bin/mbsync-task :shebang #!/bin/bash
|
||
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 $?
|
||
#+end_src
|
||
* 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:
|
||
#+begin_src sh
|
||
/opt/homebrew/bin/emacsclient -nc --socket-name work $*
|
||
#+end_src
|
||
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…
|
||
#+begin_src sh
|
||
plutil -convert json -r ~/Library/LaunchAgents/gnu.emacs.plist
|
||
#+end_src
|
||
Which should look a bit like:
|
||
#+begin_src js
|
||
{
|
||
"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"
|
||
}
|
||
#+end_src
|
||
|
||
Convert it back to XML
|
||
#+begin_src sh
|
||
plutil -convert xml1 ~/Library/LaunchAgents/gnu.emacs.plist
|
||
#+end_src
|
||
** Resources
|
||
#+begin_src sh
|
||
man launchd
|
||
man launchctl
|
||
man launchd.plist
|
||
man plutil
|
||
man plist
|
||
#+end_src
|
||
|
||
#+description: A literate programming file for installing a dæmon version of Emacs on MacOS.
|
||
|
||
#+property: header-args:sh :tangle no
|
||
#+property: header-args:emacs-lisp :tangle no
|
||
#+property: header-args :results none :eval no-export :comments no
|
||
|
||
#+options: num:nil toc:t todo:nil tasks:nil tags:nil date:nil
|
||
#+options: skip:nil author:nil email:nil creator:nil timestamp:nil
|
||
#+infojs_opt: view:nil toc:t ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
|