分享一下MacOS下编译Emacs 28 native-comp分支

在编译gcc的时候遇到了如下的错误,不过一直没看见到有人遇到,或许是我个例?分享一下解决的方式。

环境: macOS Catalina 10.15.3

源码下载的是 gcc-9.3.0

报错如下:

In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/sys/wait.h:110,
                 from /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/stdlib.h:66,
                 from ../.././libdecnumber/decNumber.c:175:
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/sys/resource.h: In function 'getiopolicy_np':
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/sys/resource.h:443:34: error: expected declaration specifiers before '__OSX_AVAILABLE_STARTING'
  443 | int     getiopolicy_np(int, int) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
      |                                  ^~~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/sys/resource.h:449:39: error: expected '=', ',', ';', 'asm' or '__attribute__' before '__OSX_AVAILABLE_STARTING'
  449 | int     setiopolicy_np(int, int, int) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
      |                                       ^~~~~~~~~~~~~~~~~~~~~~~~

解决的方法是这篇博文中的,修改/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/Availability.h文件,在300行左右的位置添加如下内容,

#ifndef __OSX_AVAILABLE_STARTING
    #define __OSX_AVAILABLE_STARTING(_osx, _ios)
    #define __OSX_AVAILABLE_BUT_DEPRECATED(_osxIntro, _osxDep, _iosIntro, _iosDep)
    #define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(_osxIntro, _osxDep, _iosIntro, _iosDep, _msg)
#endif
1 个赞

估计是OS X10.15的原因. 我们几个都是10.14的系统. emacs编译的部分通过了嘛

gcc的编译完了,没有报错。

尝试了编译了emacs几次,都在同一个地方挂了。感觉可能是libgccjit库编的有问题。

./temacs --batch  -l loadup --temacs=pbootstrap
dyld: Library not loaded: libgccjit.so.0
  Referenced from: /Users/chaomai/Documents/workspace/github/emacs/src/./temacs
  Reason: image not found
make[1]: *** [bootstrap-emacs.pdmp] Abort trap: 6
make: *** [src] Error 2

试试 export LDFLAGS="-L/path/to/libgccjit.so.0" ?

已经是 export LDFLAGS 后进行的 make。

改为 export DYLD_LIBRARY_PATH="/xxx/gcc_build9/lib/,并手动运行 ./temacs xxx可以成功,执行 make 还是失败。在 profile 或者相关 rc 文件中 export 也不管用。

先放弃了。

brew 安装的 gcc libgccjit.so 默认位置在 /usr/local/Cellar/gcc/9.x.x/lib/gcc/9 下,设置 LDFLAGS 的时候需要注意,否则会提示找不到。

我也碰到这种状况了

最近几天又在 Mac 下折腾了下 native-comp, 发现基本可用了, 速度也有一定的提升. 具体步骤如下:

  1. 编译 gcc 增加 jit 支持。

     $ cat ~/src/gcc_jit.patch
     diff --git a/Formula/gcc.rb b/Formula/gcc.rb
     index bcbc53c82..cd550bd0d 100644
     --- a/Formula/gcc.rb
     +++ b/Formula/gcc.rb
     @@ -46,7 +46,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
     @@ -58,6 +58,7 @@ class Gcc < Formula
            --disable-nls
            --enable-checking=release
            --enable-languages=#{languages.join(",")}
     +      --enable-host-shared
            --program-suffix=-#{version_suffix}
            --with-gmp=#{Formula["gmp"].opt_prefix}
            --with-mpfr=#{Formula["mpfr"].opt_prefix}
            
    
     $ cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core
     $ git checkout ./Formula/gcc.rb
     $ git apply ~/src/gcc_jit.patch
     $ brew install --build-from-source gcc
    
  2. 编译 Emacs native-comp 分支

     $ git clone -b feature/native-comp https://github.com/emacs-mirror/emacs.git
     $ cd emacs
     $ export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:${PATH}"
     $ export LDFLAGS="-L/usr/local/lib/gcc/9"
     $ git clean -fdx
     $ ./autogen.sh
     $ CC='clang' \
         ./configure \
         --disable-silent-rules \
         --enable-locallisppath=/usr/local/share/emacs/site-lisp \
         --prefix=${HOME}/gccemacs \
         --with-nativecomp \
         --with-ns \
         --disable-ns-self-contained
     $ time make -j4 NATIVE_FAST_BOOT=1
    

    使用 NATIVE_FAST_BOOT=1 可以只编译生成 pdump 需要的 elisp 文件,极大的节约编译时间。在我的 Macbook pro early 2013 上编译大约需要 50 分钟。 编译时使用这个选项的话,需要在 early-init.el 或者 init.el 里加上

     (setq comp-deferred-compilation t)
    

    来自动编译 emacs 自带的 lexical scope 的 elisp 文件。

    默认会使用 comp-speed 2 来进行编译,如果想使用 3, 可以在 make 命令里添加

     BYTE_COMPILE_EXTRA_FLAGS='--eval "(setq comp-speed 3)"'
    
  3. 安装

     $ make install
    

    目前的版本 Emacs.app 路径有问题(2020-04-30)

     $ ./nextstep/Emacs.app/Contents/MacOS/Emacs
     emacs: dlopen(/Users/sde/src/emacs/nextstep/Emacs.app/Contents/MacOS/../lisp/eln-x86_64-apple-darwin19.5.0-3e45ce4a4d47424c/custom.eln, 1): image not found
    

    但可以通过

     $ ~/gccemacs/bin/emacs
    

    来启动 Emacs.

我使用 elisp-benchmarks 进行了性能测试。结果如下:

  • Emacs master 分支加载 elc 文件

  • Emacs native-comp 分支加载 eln 文件

除去 pidigits, 速度有明显的提升。

7 个赞

按你的方法编译成功了,但是按键似乎有问题 C-k被转成 'up’了

EDIT:我的问题, karabiner 的问题。 似乎是使用 ~/gccemacs/bin/emacs. 没有被识别为emacs ,可能跟 bundleID为关

Emacs.app的问题可以在 Emacs.app/Contents/MacOS/ 加个到 ${prefix}/share/emacs/28.0.50/lisp 的软链搞定。

求助各位, 我现在按照前三楼的脚本无法build成功. 之前已经私信过两位build成功的老哥, 暂时还没有发现问题. 我想大家一起看看这个build失败的问题是咋回事.

./configure … 的输出:

make -j4 NATIVE_FAST_BOOT=1 的输出:

相关信息:

| OSX信息       | brew        |
| -------------|-------------| 
| 10.15.4      | 最新(2.2.14-54-g3247f26)| 

/usr/local/lib/gcc/9 下有编译出来的 libgccjit.so 文件

其他相关命令的输出:

commit id:
commit 02e3ffad6d9f757599bb441704b6cf6494183174
       * Fix async compilation non respecting `comp-always-compile' nil 
value.v

$ xcode-select -p 
/Library/Developer/CommandLineTools

$ clang --version
Apple clang version 11.0.3 (clang-1103.0.32.59)
Target: x86_64-apple-darwin19.4.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

$ gcc --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.3 (clang-1103.0.32.59)
Target: x86_64-apple-darwin19.4.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

./configure里加上--without-x --without-dbus试试看呢?

似乎你在用 brew 安装 llvm 之后设置过CPPFLAGS, 也可以试试在脚本里把它 unset.

wow, 多谢多谢! 我在脚本里加上unset CFLAGS; unset CPPFLAGS;之后, 现在编译已经过了之前出错的地方, 暂时没有报错了. 再次感谢! 我觉得你可以更新一下你的答案, 可能有人会遇到一样的问题吧.

2 个赞

我编译完成使用benchmarks 并没有发现这么大的性能提升

直接运行elisp-benchmarks-run的话加载的是 elc 文件,需要修改代码以加载 eln 文件。

嗯嗯, 看了一下这个库的源码, 是的, 加载的是el文件,而非eln文件

我加了个软链,好像也没解决问题,能否帮忙看看是不是加的有问题?

emacs/nextstep/Emacs.app/Contents/MacOS $ ls -la                                                                                                                                                                                    [9:54:24]
drwxr-xr-x user staff  160 B  Wed May  6 18:00:07 2020   .
drwxr-xr-x user staff  192 B  Wed May  6 15:56:01 2020   ..
.rwxr-xr-x user staff    7 MB Wed May  6 15:56:01 2020   Emacs
.rw-r--r-- user staff 15.9 MB Wed May  6 15:56:01 2020   Emacs.pdmp
lrwxr-xr-x user staff   50 B  Wed May  6 18:00:07 2020   lisp ⇒ /Users/user/gccemacs/share/emacs/28.0.50/lisp/

链接到上一层,Emacs.app/Contents

1 个赞

这几天尝试了一下gcc 10.1.0

编译 gcc-10.1.0

从gcc的mirror上下载的源代码 需要先安装几个包

  brew install gmp mpfr libmpc isl

进入source目录, 开始编译:

  mkdir build
  cd build
  SED=/usr/bin/sed ../configure \
     --enable-languages=jit,c,c++,objc,obj-c++ \
     --prefix=/usr/local/opt/gcc/10.1.0 \
     --disable-nls \
     --enable-checking=release \
     --enable-host-shared \
     --program-suffix=-10.1 \
     --with-system-zlib \
     --with-gmp=/usr/local/Cellar/gmp/6.2.0 \
     --with-mpfr=/usr/local/Cellar/mpfr/4.0.2 \
     --with-mpc=/usr/local/Cellar/libmpc/1.1.0 \
     --with-isl=/usr/local/Cellar/isl/0.22.1 \
     --with-native-system-header-dir=/usr/include \
     --with-sysroot=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk \
     --disable-multilib \
     --disable-bootstrap

  make BOOT_LDFLAGS=-Wl,-headerpad_max_install_names -j2

整个编译过程大概50分钟,然后安装,并且做一些链接, 让其能够被访问

  make install

  cd /usr/local/bin
  ln -s /usr/local/opt/gcc/10.1.0/bin/* .
  cd /usr/local/include
  ln -s /usr/local/opt/gcc/10.1.0/include/* .
  cd /usr/local/lib
  ln -s /usr/local/opt/gcc/10.1.0/lib/* .

编译emacs

按楼主的方式clone

  git clean -fdx
  ./autogen.sh
  CC='clang'  ./configure \
    --disable-silent-rules \
    --enable-locallisppath=/usr/local/share/emacs/28.0.50/site-lisp  \
    --prefix=/usr/local/opt/gccemacs  \
    --with-nativecomp \
    --without-dbus \
    --with-ns \
    --with-mailutils \
    --disable-ns-self-contained \
    --with-xml2 \
    --with-gnutls \
    --with-imagemagick  \
    --with-modules  \
    --with-rsvg 

  make -j2 NATIVE_FAST_BOOT=1

编译时间80分钟左右,完成后安装:

  make install
  mv nextstep/Emacs.App /Applications

  cd /usr/local/bin
  ln -s /usr/local/opt/gccemacs/bin/emacs .
  ln -s /usr/local/opt/gccemacs/bin/emacsclient .

  cd /Applications/Emacs.app/Contents
  ln -s /usr/local/opt/gccemacs/share/emacs/28.0.50/elisp .

在 ~/.emacs.d/early-init.el 中配置:

  (setq comp-deferred-compilation t)

然后就可以启动了,等待下载安装package

完成

完成后,启动的时间居然比27 elisp版本还慢了很多,一次要18s

不过ivy确实很快,尤其是使用系统路径时,之前一直很卡,现在完全不卡

问题

那个native-comp-async 我这都是报 void function ,查看elpa的目录,只有很少的一些包被编译成了eln, org,ivy,evil 什么的,哪位大佬给指点一下