18 Lisp 本地代码编译

除了上一章字节编译介绍的字节编译外, Emacs 还可选择性地将 Lisp 函数定义编译为真正的编译代码, 称为本地代码(native code)。该特性依赖 libgccjit 库(属于 GCC 套件), 且要求构建 Emacs 时启用该库支持。 要对 Lisp 代码进行本地编译,系统还必须安装 GCC 和 Binutils(汇编器与链接器)。

要判断当前 Emacs 进程能否生成并加载本地编译的 Lisp 代码, 可调用 native-comp-available-p(see 本地编译函数)。

与字节编译代码不同,本地编译的 Lisp 代码由机器硬件直接执行, 因此能以宿主 CPU 的全速运行。 加速效果通常取决于 Lisp 代码的具体功能, 一般比对应字节编译代码快 **2.5~5 倍**。

由于本地代码在不同系统间通常不兼容, 本地编译代码**无法**在不同机器之间移植, 只能在生成它的同一台机器或高度相似的机器(相同 CPU 与运行时库)上使用。 本地编译代码的可移植性与共享库(.so.dll 文件)一致。

本地编译代码库对 Emacs Lisp 原语(see 什么是函数?) 及其调用约定存在关键依赖, 因此 Emacs 通常无法加载由其他版本 Emacs 生成的本地编译代码。 同一 Lisp 代码经不同版本 Emacs 本地编译后, 通常会生成文件名唯一的本地编译库,仅对应版本 Emacs 可加载。 不过,唯一文件名机制允许同一 Lisp 库经多个 Emacs 版本编译后的库文件共存于同一目录。

文件局部变量 no-byte-compile(see 字节编译)设为非nil 时, 也会同时禁用该文件的本地编译。 此外,类似变量 no-native-compile 可仅禁用本地编译。 若同时指定 no-byte-compileno-native-compile,以前者为准。

有时需要阻止本地编译将结果(*.eln 文件)写入 user-emacs-directory 的子目录(see The Init File)。 可通过修改 native-comp-eln-load-path(see 本地编译变量) 或临时将 HOME 环境变量指向不存在的目录实现。 注意:若 Emacs 需要生成跳板函数(trampolines),后一种方法仍可能产生少量 *.eln 文件—— 跳板函数用于本地编译代码中对 Lisp 原语进行 advising 或重定义的场景。 see trampolines。 或者,可使用 startup-redirect-eln-cache 函数 将 *.eln 文件写入非默认目录;see 本地编译函数


emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© 2025 Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike