UPDATE: I'm no longer using these steps. See Emacs plus –with-native-comp for an easier alternative.
Below are the instructions I use to build Andrea Corallo's gccemacs on macOS. It is based on Allen Dang's handy instructions plus some changes of my own.
brew install gcc libgccjit
Create configure-gccemacs.sh
#!/bin/bash
set -o nounset
set -o errexit
# Configures Emacs for building native comp support
# http://akrl.sdf.org/gccemacs.html
readonly GCC_DIR="$(realpath $(brew --prefix libgccjit))"
[[ -d $GCC_DIR ]] || { echo "${GCC_DIR} not found"; exit 1; }
readonly SED_DIR="$(realpath $(brew --prefix gnu-sed))"
[[ -d $SED_DIR ]] || { echo "${SED_DIR} not found"; exit 1; }
readonly GCC_INCLUDE_DIR=${GCC_DIR}/include
[[ -d $GCC_INCLUDE_DIR ]] || { echo "${GCC_INCLUDE_DIR} not found"; exit 1; }
readonly GCC_LIB_DIR=${GCC_DIR}/lib/gcc/10
[[ -d $GCC_LIB_DIR ]] || { echo "${GCC_LIB_DIR} not found"; exit 1; }
export PATH="${SED_DIR}/libexec/gnubin:${PATH}"
export CFLAGS="-O2 -I${GCC_INCLUDE_DIR}"
export LDFLAGS="-L${GCC_LIB_DIR} -I${GCC_INCLUDE_DIR}"
export LD_LIBRARY_PATH="${GCC_LIB_DIR}"
export DYLD_FALLBACK_LIBRARY_PATH="${GCC_LIB_DIR}"
echo "Environment"
echo "-----------"
echo PATH: $PATH
echo CFLAGS: $CFLAGS
echo LDFLAGS: $LDFLAGS
echo DYLD_FALLBACK_LIBRARY_PATH: $DYLD_FALLBACK_LIBRARY_PATH
echo "-----------"
./autogen.sh
./configure \
--prefix="$PWD/nextstep/Emacs.app/Contents/MacOS" \
--enable-locallisppath="${PWD}/nextstep/Emacs.app/Contents/MacOS" \
--with-mailutils \
--with-ns \
--with-imagemagick \
--with-cairo \
--with-modules \
--with-xml2 \
--with-gnutls \
--with-json \
--with-rsvg \
--with-native-compilation \
--disable-silent-rules \
--disable-ns-self-contained \
--without-dbus
Make it executable
chmod +x configure-gccemacs.sh
git clone --branch master https://github.com/emacs-mirror/emacs gccemacs
cd gccemacs
../configure-gccemacs.sh
Verify native lisp compiler is found:
Does Emacs have native lisp compiler? yes
Put those cores to use. Find out how many you got with:
sysctl hw.logicalcpu
Ok so build with:
make -j4 NATIVE_FAST_BOOT=1
cp -r lisp nextstep/Emacs.app/Contents/Resources/
cp -r native-lisp nextstep/Emacs.app/Contents
make install
Note: Using NATIVE_FAST_BOOT=1 significantly improves build time (totalling between 20-30 mins, depending on your specs). Without it, the build can take hours.
The macOS app build (under nextstep/Emacs.app) is ready, but read on before launching.
You likely want to start with a clean install, byte-compiling all packages with the latest Emacs version. In any case, rename ~/emacs.d (for backup?) or remove ~/emacs.d.
Ensure exec-path includes the script's "–prefix=" value, LIBRARY_PATH points to gcc's lib dir, and finally set comp-deferred-compilation. I wrapped the snippet in my exec-path-from-shell config, but setting early in init.el should be enough.
(use-package exec-path-from-shell
:ensure t
:config
(exec-path-from-shell-initialize)
(if (and (fboundp 'native-comp-available-p)
(native-comp-available-p))
(progn
(message "Native comp is available")
;; Using Emacs.app/Contents/MacOS/bin since it was compiled with
;; ./configure --prefix="$PWD/nextstep/Emacs.app/Contents/MacOS"
(add-to-list 'exec-path (concat invocation-directory "bin") t)
(setenv "LIBRARY_PATH" (concat (getenv "LIBRARY_PATH")
(when (getenv "LIBRARY_PATH")
":")
;; This is where Homebrew puts gcc libraries.
(car (file-expand-wildcards
(expand-file-name "~/homebrew/opt/gcc/lib/gcc/*")))))
;; Only set after LIBRARY_PATH can find gcc libraries.
(setq comp-deferred-compilation t))
(message "Native comp is *not* available")))
You're good to go. Open Emacs.app via finder or shell:
open nextstep/Emacs.app
After setting comp-deferred-compilation (in init.el config section), .elc files should be asyncronously compiled. Function definition should be updated to native compiled equivalent.
Look out for an Async-native-compile-log buffer. Should have content like:
Compiling .emacs.d/elpa/moody-20200514.1946/moody.el...
Compiling .emacs.d/elpa/minions-20200522.1052/minions.el...
Compiling .emacs.d/elpa/persistent-scratch-20190922.1046/persistent-scratch.el...
Compiling .emacs.d/elpa/which-key-20200721.1927/which-key.el...
...
Can also check for .eln files:
find ~/.emacs.d -iname *.eln | wc -l
UPDATE1: Added Symlink Emacs.app/Contents/eln-cache section for update 11.
UPDATE2: Noted using NATIVE_FAST_BOOT makes the build much faster.
UPDATE3: Removed symlinks and copied content instead. This simplifies things. Inspired by Ian Wahbe's build-emacs.sh.
UPDATE4: Removed homebrew recipe patching. Thanks to Dmitry Shishkin's instructions.
UPDATE5: Use new flag –with-native-compilation and master branch.