Skip to content

Instantly share code, notes, and snippets.

@mikroskeem
Last active July 11, 2023 14:59
Show Gist options
  • Star 47 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save mikroskeem/0a5c909c1880408adf732ceba6d3f9ab to your computer and use it in GitHub Desktop.
Save mikroskeem/0a5c909c1880408adf732ceba6d3f9ab to your computer and use it in GitHub Desktop.
gccemacs on OSX

gccemacs on OS X

Read this first: http://akrl.sdf.org/gccemacs.html

Prerequisites

1) GCC with libgccjit enabled

For that you need to compile gcc (duh). I edited Homebrew's gcc formula:

diff --git a/Formula/gcc.rb b/Formula/gcc.rb
index 1bd636d496..03ad124218 100644
--- a/Formula/gcc.rb
+++ b/Formula/gcc.rb
@@ -53,7 +53,7 @@ class Gcc < Formula
     #  - Ada, which requires a pre-existing GCC Ada compiler to bootstrap
     #  - Go, currently not supported on macOS
     #  - BRIG
-    languages = %w[c c++ objc obj-c++ fortran]
+    languages = %w[c c++ objc obj-c++ fortran jit]

     osmajor = `uname -r`.split(".").first
     pkgversion = "Homebrew GCC #{pkg_version} #{build.used_options*" "}".strip
@@ -73,6 +73,7 @@ class Gcc < Formula
       --with-system-zlib
       --with-pkgversion=#{pkgversion}
       --with-bugurl=https://github.com/Homebrew/homebrew-core/issues
+      --enable-host-shared
     ]

     # Xcode 10 dropped 32-bit support

(easy way to apply this is to cd into /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core and run pbpaste | git apply - after copying the diff into clipboard 😄)

(or whereever is your Homebrew library set up)

2) Bunch of dependencies

  • giflib
  • jpeg
  • libtiff
  • gnutls

And XQuartz, because GCC is not able to parse Objective-C dialect changes what Apple has done for now and thus Apple Cocoa support is not available. (See: https://lists.gnu.org/archive/html/emacs-devel/2019-08/msg00056.html)

3) Source

Clone https://github.com/emacs-mirror/emacs and checkout feature/native-comp branch

2) Building

Here's the script I used (note to adjust package versions if needed):

libs=(
    /usr/local/Cellar/gcc/9.2.0_2
    /usr/local/Cellar/giflib/5.2.1
    /usr/local/Cellar/jpeg/9c
    /usr/local/Cellar/libtiff/4.1.0
    /usr/local/Cellar/gnutls/3.6.10

    # Required by gnutls
    /usr/local/Cellar/nettle/3.4.1 
    /usr/local/Cellar/libtasn1/4.15.0
    /usr/local/Cellar/p11-kit/0.23.18.1
)

export PATH="/usr/local/Cellar/gcc/9.2.0_2/bin:${PATH}"

export CC="gcc-9"
export CPP="cpp-9"
CFLAGS=""
LDFLAGS=""
PKG_CONFIG_PATH=""

for dir in "${libs[@]}"; do
    CFLAGS="${CFLAGS}-I${dir}/include "
    LDFLAGS="${LDFLAGS}-L${dir}/lib "
    PKG_CONFIG_PATH="${PKG_CONFIG_PATH}${dir}/lib/pkgconfig:"
done

export CPPFLAGS="${CFLAGS}"
export CFLAGS
export LDFLAGS
export PKG_CONFIG_PATH

./configure \
    --prefix="${HOME}"/gccemacs \
    --with-nativecomp \
    --without-ns

Save it into build.sh

Then run: sh build.sh && make bootstrap && make install

And result is in ~/gccemacs. Add ~/gccemacs/bin into PATH and start experimenting with el native building

@AndreaCorallo
Copy link

AndreaCorallo commented Jul 24, 2020

Interesting, this is the same question I was asking here https://debbugs.gnu.org/cgi/bugreport.cgi?bug=41877#8

I'd be happy to find a fix for this but I've no knowledge of MacOS and no machine to test it either so I need some help here :)

So IIUC apparently bin-dest-dir is wrong? Then I'm wondering how make install could work because both are derived from ${bindir} in the Makefile.

@mnewt
Copy link

mnewt commented Jul 24, 2020

I've been doing two things to address this:

  1. After make install, copy the contents of the lisp directory into the app bundle because that's where it ends up looking for the eln files.
cp -R lisp "nextstep/Emacs.app/Contents/"
  1. In init.el, put the libgccjit and dependencies on the library path so comp can find them while Emacs is running.
(setenv "LIBRARY_PATH" "/usr/local/opt/gcc/lib/gcc/10")

#1 seems undesirable because make install puts the lisp directory in /usr/local/share/emacs/28.0.50/lisp/. Would changing bin-dest-dir cause Emacs to look there for eln files on startup instead of in the app bundle?

For #2, clearly those libraries need to be located at runtime. Can the linker be configured to hard code those dependency paths so the environment doesn't need configuring?

And would either of those strategies affect emacsclient or emacs -nw?

@CarlQLange
Copy link

@mnewt Your instructions here were really very handy, thank you. However, the compilation only seems to work if I run emacs from a shell and not from the .app. I think it's to do with the LIBRARY_PATH being reset or something, but it's driving me nuts!

@mnewt
Copy link

mnewt commented Jul 27, 2020

@CarlQLange I'm glad! It did take me a while to iron out the kinks even with all the help in this thread.

Double checking: are you sure LIBRARY_PATH is being set in init.el, like in my comment above? It definitely won't be set when Emacs.app is launched initially, regardless of what's in your shell init files.

@CarlQLange
Copy link

@mnewt Yeah, it was. Still not clear on how it didn't work, but I'm sure it's my fault and not the fault of your instructions or native-comp! In the end I just couldn't make deferred compiling work nicely. Even when the compilation worked, packages would fail to load because of undefined variables and I burned a whole day on whackamole before giving up. I'm sure this would work really well if I used my own config, but it seems like doom-emacs doesn't play that nicely. It's still great to actually have nativecomp compiled though!

@jlhg
Copy link

jlhg commented Aug 13, 2020

I met an error cairo-xlib.h: No such file or directory when make. Add -I/opt/X11/include/cairo to CFLAGS can resolve this.

@schellj
Copy link

schellj commented Sep 10, 2020

FYI for anyone following this thread, I was able to successfully build the native-comp branch fairly easily using https://github.com/jimeh/build-emacs-for-macos. Only ran into a couple of minor issues for a few minutes after starting Emacs, I believe due to the async lisp package compilation not being completed yet.

@CarlQLange
Copy link

@schellj That was a great recommendation. I don't know exactly why, but building with that script has solved the problems I've had for years with scrolling. And it was extremely painless!

@daviderestivo
Copy link

I was able to compile Emacs with native-comp support but when launching emacs I get this error:

$ emacs -Q
emacs: can't find function "F656c646f632d646f63756d656e746174696f6e2d64656661756c74_eldoc_documentation_default_0" in compilation unit /usr/local/Cellar/emacs-head@28/HEAD-21021e5_1/Emacs.app/Contents/MacOS/../native-lisp/28.0.50-x86_64-apple-darwin19.6.0-7e5198856538e2d0888d324e804f0442/eldoc-47e1f01cc0121af2b62caf268f92fd16-368e1766935b99b5a29346a902b44c9b.eln

any ideas?

@AndreaCorallo
Copy link

Could you check the size of this eln file?

@schellj
Copy link

schellj commented Sep 14, 2020

I've also run into an issue where Emacs seems to create a problematic (non-zero size) eln file for cl-lib sometimes. After exiting Emacs and attempting to restart, I get the following error:

[~]$ open /Applications/Emacs.app
LSOpenURLsWithRole() failed with error -10810 for the file /Applications/Emacs.app.

If I delete ~/.emacs.d/eln-cache/28.0.50-x86_64-apple-darwin19.6.0-24f1b3501916c3935f73bd09c228268f/cl-lib-388247404020ff233a151179ccaf7d0e-fa297bdec2c84d1f0a3a03da76744f30.eln, Emacs starts successfully.

I've pushed the eln file and the original cl-lib.el file here:
https://github.com/schellj/emacs-native-comp-debug/blob/problematic-cl-lib/eln-cache/28.0.50-x86_64-apple-darwin19.6.0-24f1b3501916c3935f73bd09c228268f/cl-lib-388247404020ff233a151179ccaf7d0e-fa297bdec2c84d1f0a3a03da76744f30.eln
https://github.com/schellj/emacs-native-comp-debug/blob/problematic-cl-lib/cl-lib.el

PS - Is there a better place to report issues like this @AndreaCorallo ?

@AndreaCorallo
Copy link

PS - Is there a better place to report issues like this @AndreaCorallo ?

Yes the best is to use the Emacs bug tracker https://debbugs.gnu.org/Emacs.html M-x report-emacs-bug.

We usually add into the subject [feature/native-comp] (some examples https://debbugs.gnu.org/cgi/pkgreport.cgi?package=emacs;include=subject%3Anative-comp)

@schellj
Copy link

schellj commented Sep 14, 2020

Thanks, I'll work on reporting via report-emacs-bug. Though I do have the eln-cache directory saved from when that issue last occurred, I'm not sure how to reproduce it now.

@daviderestivo
Copy link

daviderestivo commented Sep 15, 2020

Could you check the size of this eln file?

gutter@nemesis ~ $ ls -al /usr/local/Cellar/emacs-head@28/HEAD-21021e5_1/Emacs.app/Contents/MacOS/../native-lisp/28.0.50-x86_64-apple-darwin19.6.0-7e5198856538e2d0888d324e804f0442/eldoc-47e1f01cc0121af2b62caf268f92fd16-368e1766935b99b5a29346a902b44c9b.eln
-r--r--r--  1 gutter  admin  82628 Sep 14 07:10 /usr/local/Cellar/emacs-head@28/HEAD-21021e5_1/Emacs.app/Contents/MacOS/../native-lisp/28.0.50-x86_64-apple-darwin19.6.0-7e5198856538e2d0888d324e804f0442/eldoc-47e1f01cc0121af2b62caf268f92fd16-368e1766935b99b5a29346a902b44c9b.eln

@AndreaCorallo Please lemme know if you need other infos ...

@Grekkor
Copy link

Grekkor commented Oct 4, 2020

I am getting this pesky error and I have the correct symlink for the lisp folder inside /Applications/Emacs.app/Contents but now it starts looking for .eln files inside a native-lisp folder:

emacs: dlopen(/Applications/Emacs.app/Contents/MacOS/../native-lisp/28.0.50-x86_64-apple-darwin19.6.0-919382e94fb290efe3ee4a93fd4035d3/lisp-mode-0189ba85598c041b7504f0a916c04219-1738806322de892570d69dfc55b437c2.eln, 1): image not found

@mattsawyer77
Copy link

@Grekkor I had the same problem. I had to do this:

sudo ln -sf /Applications/Emacs.app/Contents/native-lisp /usr/local/native-lisp

@bryanmobrien
Copy link

Late to this game, but very thankful for this gist (and all the tips/tricks within).
With the following pieces,

Big Sur 11.2 (Intel) 
HOMEBREW_VERSION: 2.7.5-237-gf7a718c
gcc: stable 10.2.0 (bottled), HEAD
libgccjit: stable 10.2.0 (bottled), HEAD
git branch: feature/native-comp b8d3ae78c5 [origin/feature/native-comp] 
src-dir:  /Users/bobrien/src/gnu-emacs/gccemacs

I was failing time and time again with this error

emacs: dlopen(/Users/bobrien/src/gnu-emacs/gccemacs/nextstep/Emacs.app/Contents/MacOS/  
../native-lisp/28.0.50-x86_64-apple-darwin20.3.0-97a65566abd4d693149e0aa232898a68/mouse-  
15f283fa50e83fc2aec8714353ada84c-de78d65d134dc032624554b36cd56584.eln, 1): image not found

I was finally able to successfully build (and run) with the following build.sh:

export CC=clang
export LDFLAGS=-L/usr/local/Cellar/libgccjit/10.2.0_1/lib/gcc/10
export CXXFLAGS=-I/usr/local/Cellar/libgccjit/10.2.0_1/include
./configure --with-nativecomp
make bindir=$(pwd)/nextstep/Emacs.app/Contents/MacOS bootstrap && make install

The piece that got me past the error was passing bindir to make (thank you @shshkn)
I didn't have to symlink any directories in the src-dir ;-)
I symlinked the built gccemacs as:

ln -sf ~/src/gnu-emacs/gccemacs/nextstep/Emacs.app ~/Applications/GCCEmacs.app

I was able to run Emacs via command line and finder (mouse-click).
Emacsclient was aliased as

em="~/src/gnu-emacs/gccemacs/nextstep/Emacs.app/bin/emacsclient -c -n -a ''

and emacsclient is working as well.

Again, thank all of you for this gist and especially the bindir= tip.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment