Compiling Emacs on MacOS
PSA: Don't do this
Just use emacs-plus. That does everything these notes do, but better.
Git Clone
git clone git://git.sv.gnu.org/emacs.git cd emacs
Install Prerequisites
brew install libxml2 brew install librsvg brew install imagemagick brew install jansson
Provide path to libxml headers
Assuming you have already run brew install libxml2
from above:
prefix=$(brew --prefix) export PKG_CONFIG_PATH="$prefix/lib/pkgconfig:$prefix/opt/libxml2/lib/pkgconfig"
Autogen
./autogen.sh
Configure
The configure
script provides many options (run ./configure --help
to see
them all). You can just run ./configure
and it will choose sensible
defaults, printing out a summary of all the options it used at the end.
On MacOS, use the --with-xwidgets
in order to use the a built-in browser.
Great for live HTML previewing.
If imagemagick is installed, --with-imagemagick
allows for some extra
features for displaying images in Emacs.
./configure \ --with-xwidgets \ --with-imagemagick \ --without-dbus \ --with-json
Compile
Now run make bootstrap
. The -j
is optional; it allows make
to run
recipies in parllel, which speeds things up. This command will take 10-15
minutes.
make bootstrap -j
Question: What is the difference between make bootstrap
and make
? One
thing: when running make bootstrap
I need to have PKG_CONFIG_PATH
set, but
when just doing a make
I don't. What else?
make -j make install
After a make install
, the executable is located at
./nextstep/Emacs.app/Contents/MacOS/Emacs
.
MacOS recognizes the directory ./nextstep/Emacs.app
as an "Application", so
from the Finder, you can just double-click that directory to launch Emacs.
Add Icon to Dock
Just open Emacs.app (by double-clicking on the ./nextstep/Emacs.app/
directory in Finder), and that will put an icon in the dock. Then, pin the
icon in the dock.
Verify Features
Once Emacs is running, check whether these features were properly enabled.
(image-type-available-p 'png)
(image-type-available-p 'svg)
(image-type-available-p 'imagemagick)
Debugging
$ lldb (lldb) target create "nextstep/Emacs.app/Contents/MacOS/Emacs" Current executable set to '/Users/chris.clark/Projects/emacs/nextstep/Emacs.app/Contents/MacOS/Emacs' (x86_64). (lldb) run
To debug problems during running the init.el
file, run $EMACS --debug-init
.
Resources
Emacs for OSX https://github.com/caldwell/build-emacs
Similar to Emacs for OSX, but supports arbitrary git tags https://github.com/jimeh/build-emacs-for-macos
Homebrew emacs formula https://github.com/Homebrew/homebrew-core/blob/master/Formula/emacs.rb
Homebrew emacs-plus formula, which has a few more patches https://github.com/d12frosted/homebrew-emacs-plus
EmacsWiki Building Emacs on MacOS https://www.emacswiki.org/emacs?action=browse;oldid=EmacsOnMacOS;id=EmacsForMacOS
ARCHIVED: Native Compilation
Do things in this section if you want to compile Emacs
--with-native-compilation
.
NOTE 1: After a lot of struggle, I got this sort of working, but eventually gave up on native compilation. Some of the beauty of hacking on interpreted languages is not having to deal with compilation.
NOTE 2: Next time, probably best to use: https://github.com/jimeh/build-emacs-for-macos
Get libgccjit:
brew install libgccjit
Upgate the homebrew formula for gcc
as described here: https://gist.github.com/AllenDang/f019593e65572a8e0aefc96058a2d23e
Then, Install gcc
(I've heard clang
works as well).
brew install gcc --build-from-source --force
You will now have a program on you $PATH
called gcc-11
. For some reason
(why?) brew
does not link gcc
to gcc-11
.
Do NOT manually create that link (say, by doing something like
ln -s /usr/local/bin/gcc-11 /usr/local/bin/gcc
). When I tried, it caused the following error during the./configure
step of building Emacs:checking for AppKit/AppKit.h... no configure: error: The include files (AppKit/AppKit.h etc) that are required for a Nextstep build are missing or cannot be compiled. Either fix this, or re-configure with the option '--without-ns'.
Why does that happen?
Now, we have to tell Emacs which gcc
to use and link some extra stuff.
gccVersion=$(brew info gcc --json | jq -r '.[].installed[].version') gccMajorVersion=$(echo $gccVersion | cut -d "." -f 1) export CFLAGS="-I/usr/local/Cellar/gcc/$gccVersion/include" export CC="/usr/local/bin/gcc-$gccMajorVersion" export LDFLAGS="-I/usr/local/Cellar/gcc/$gccVersion/lib/gcc/$gccMajorVersion -I/usr/local/Cellar/gcc/$gccVersion/include" export LIBRARY_PATH="/usr/local/Cellar/gcc/$gccVersion/lib/gcc/$gccMajorVersion"
Now when running ./configure
in the next section, add the
--with-native-compilation
flag.
When opening Emacs, the LIBRARY_PATH
env var has to be set inside of
Emacs. That means, start Emacs from the same terminal window where you set
that $LIBRARY_PATH
env var, so Emacs inherits it. If, instead, you start
Emacs from a pinned Dock icon, Emacs won't have LIBRARY_PATH
set, and you'll
see an error like:
ld: library not found for -lgcc_ext.10.5 libgccjit.so: error: error invoking gcc driver
Notes/Questions
I think the LIBRARY_PATH
env var only needs to be set in Emacs the first
time it starts (?). Try pulling new packages and see if they are properly
compiled when that env var isn't set.
Does LIBRARY_PATH
need to be set when compiling Emacs, or only when
starting Emacs?
Does this stuff have to happen before running the ./autogen.sh
script?