hamacs/README-MacOS.org
Howard Abrams 6d92980311 Migration from ~/other to ~/src
Why was it any other way?
2024-10-19 13:34:01 -07:00

350 lines
12 KiB
Org Mode
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#+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 Ive been having difficulties installing Emacs from source on a Mac, Im 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 cant 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 doesnt 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 doesnt 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 Im 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
Lets 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