昨天我一直关注的类型声明分支总算是合并了:Merge branch ‘lisp-func-type-decls’ into ‘master’,理论上添加函数的类型声明后 native-comp 能够更有效地优化代码,不过具体的优化代码似乎还没有写。看到这个分支合并后我在 Windows 上用 MSYS2 拉下来编译了一下,没啥感觉(汗)。
这个帖子是介绍我在折腾 native-comp 的时候找到的不用在 MSYS2 的 Mingw64 SHELL 中启动 Emacs 也能用上 native-comp 的方法。使用的方法来自: MS-Windows版 Emacs 29.1への移行作業 | Misohena Blog
Emacs 官方提供的官方 Windows 编译版本
在 Emacs 的 FTP 里面提供了编译好的 Windows 版本可供下载,下载后运行 bin 目录下的 runemacs.exe 即可启动 Emacs。以 Emacs 29.2 为例,在 bin 目录下已经提供了许多 DLL 文件,但其中没有 libgccjit 相关的 DLL。
虽然我们在运行 (native-comp-available-p)
时得到的结果是 nil
,但是查看 system-configuration-options
时可以注意到它在编译时启用了 native-comp 特性:
system-configuration-options is a variable defined in ‘C source code’.
Its value is
"--with-modules --without-dbus --with-native-compilation=aot --without-compress-install --with-tree-sitter --with-sqlite3 CFLAGS=-O2"
String containing the configuration options Emacs was built with.
[back]
使 (native-comp-available-p)
返回 t
根据 Windows 的 DLL 查找规则,我们将 gccjit 相关的 DLL 放在 Emacs 的 bin 目录下即可。我们可以在 MSYS2 的 Mingw64 SHELL 中通过以下命令安装 libgccjit:
pacman -S mingw-w64-x86_64-libgccjit
安装完成后,MSYS2 的目录中的 mingw64/bin 中会出现一个名叫 libgccjit-0.dll
的文件,但光是把它拖到 emacs 的 bin 目录下还不够,它依赖这些 DLL:
其中除系统 DLL 和 libisl-23.dll
, libmpc-3.dll
和 libmpfr-6.dll
外,Windows 版 Emacs 均已提供,因此我们只需要将 mingw64/bin 下的以下 DLL 移动至 Emacs 的 bin 目录下即可:
- libgccjit-0.dll
- libisl-23.dll
- libmpc-3.dll
- libmpfr-6.dll
完成以上操作并重启 Emacs 后,调用 (native-comp-available-p)
应该会得到 t
。
添加 as.exe
和 ld.exe
虽然此时 native-comp 特性已经可用,但当你切换到 *Async-native-compile-log*
buffer 时,你会注意到编译因为找不到 as
而失败。(我在出现这个错误的时候忘记截图了,这是来自一篇文章的输出结果: Windows版Emacsを28.1に上げたのでNative Compilationフィーバーに便乗する:
Compiling c:/emacs/share/emacs/28.1/lisp/emacs-lisp/cconv.el...
x86_64-w64-mingw32-gcc-11.3.0: fatal error: cannot execute 'as': CreateProcess: No such file or directory
compilation terminated.
参考在帖子开头给出的教程,我们可以在 Emacs 的 lib 目录下创建 gcc 目录,然后从 mingw64/bin 中复制一份 as.exe
和 ld.exe
过来,记得带上它们依赖的 DLL:
- as.exe
- ld.exe
- libzstd.dll
- zlib1.dll
添加文件后,在自己的配置文件中添加以下配置来指定这些文件的路径:
(setq native-comp-driver-options (list "-B" (expand-file-name (file-name-concat invocation-directory "../lib/gcc"))))
此时再次重启 Emacs, *Async-native-compile-log*
中的错误会变成一系列的缺少库文件:(我也忘了截图了,只能偷别人的):
Compiling c:/emacs/share/emacs/28.1/lisp/language/japan-util.el...
ld: dllcrt2.o が見つかりません: No such file or directory
ld: crtbegin.o が見つかりません: No such file or directory
ld: -lmingw32 が見つかりません
ld: -lgcc_s が見つかりません
ld: -lgcc が見つかりません
ld: -lmoldname が見つかりません
ld: -lmingwex が見つかりません
ld: -lmsvcrt が見つかりません
ld: -lmingw32 が見つかりません
ld: -lgcc_s が見つかりません
ld: -lgcc が見つかりません
ld: -lmoldname が見つかりません
ld: -lmingwex が見つかりません
ld: -lmsvcrt が見つかりません
ld: crtend.o が見つかりません: No such file or directory
c:\emacs\bin\libgccjit-0.dll: error: error invoking gcc driver
c:/emacs/share/emacs/28.1/lisp/language/japan-util.el: Error: Internal native compiler error failed to compile
根据帖子开头的教程,需要从以下位置复制文件到 Emacs 目录中的 lib/gcc 目录下:
[mingw64/lib]
crtbegin.o
crtend.o
dllcrt2.o
libadvapi32.a
libgcc_s.a
libkernel32.a
libmingw32.a
libmingwex.a
libmoldname.a
libmsvcrt.a
libpthread.a
libshell32.a
libuser32.a
[mingw64/lib/gcc/x86_64-w64-mingw32/13.1.0/]
libgcc.a
再次重启 Emacs ,应该就能正常完成编译了。
Summary
以下是我现在使用的关于 native-comp
的配置:
;;@@NATIVE-COMP
;; https://misohena.jp/blog/2023-07-31-setup-emacs-29-1-for-windows.html
;;te 在 bin/ 下添加必要库
;; 注意 bin/ 中 libgccjit-0.dll 存在以下依赖项:
;; 可使用 https://github.com/lucasg/Dependencies 获取 DLL 的依赖项
;; system32/{advapi32.dll, kernel32.dll, MSVCRT.dll}
;; libgcc_s_seh-1.dll, libgmp-10.dll
;; libisl-23.dll, libmpc-3.dll, libmpfr-6.dll ; 注意这三个
;; libwinpthread-1.dll, zlib1.dll, libzstd.dll
;; 随后,在 /lib/gcc/ 下添加以下内容:(一共 18 个)
;; mingw64/bin/ 中的 as.exe 和 ld.exe,它们依赖同目录下的 libzstd.dll 和 zlib1.dll
;; mingw64/lib 下的以下文件:
;; crtbegin.o, crtend.o, dllcrt2.o
;; lib{ advapi32.a, gcc_s.a, kernel32.a, mingw32.a
;; mingwex.a, moldname.a, msvcrt.a, pthread.a
;; shell32.a, user32.a}
;; mingw64/lib/gcc 中的 libgcc.a
;; 忽略 native-comp 过程中的 warning
(setopt native-comp-async-report-warnings-errors nil)
;; 添加编译的工具和库位置
(when (and (fboundp #'native-comp-available-p)
(native-comp-available-p)
(eq system-type 'windows-nt))
(setopt native-comp-driver-options
(list "-B" (expand-file-name (file-name-concat
invocation-directory
"../lib/gcc")))))
我原本打算重现一遍我之前遇到的错误,但即使我注释掉了上面的代码,native-comp 似乎也能正常工作,很奇怪…
也许之后版本的 Windows 版 Emacs 会提供 native-comp 依赖项,也就不用我们手动添加了。