E.1 构建 Emacs

本节说明构建 Emacs 可执行文件的相关步骤。你无需了解这些内容即可构建与安装 Emacs,因为 makefile 会自动完成所有工作。这些信息主要面向 Emacs 开发者。

构建 Emacs 需要 GNU Make 3.81 或更高版本。

src 目录下的 C 源文件进行编译,会生成一个名为 temacs 的可执行文件,也称为 纯净版未转储 Emacs(bare impure Emacs)。它包含 Emacs Lisp 解释器与 I/O 例程,但不含编辑命令。

命令 temacs -l loadup 会运行 temacs 并指示其加载 loadup.elloadup 库会加载更多 Lisp 库,从而搭建起正常的 Emacs 编辑环境。完成这一步后,Emacs 可执行文件就不再是 纯净版未转储(bare) 状态。

由于加载标准 Lisp 文件需要一定时间,用户通常不会直接运行 temacs。 相反,构建 Emacs 的最后步骤之一会执行命令 ‘temacs -batch -l loadup --temacs=dump-method。专用选项 --temacs 用于告知 temacs 如何记录所有标准预加载 Lisp 函数与变量,使后续运行 Emacs 时启动速度大幅提升。 --temacs 选项需要一个参数 dump-method,可选值如下:

pdump

将预加载的 Lisp 数据记录到 转储文件(dump file) 中。该方式会生成一个附加数据文件,Emacs 启动时会加载它。生成的转储文件通常名为 emacs.pdmp,并安装到 Emacs 的 exec-directory 目录(see 帮助函数)。该方式为首选方案,因为它不需要 Emacs 使用特殊的内存分配技术,避免与现代系统用于增强安全性与隐私保护的各类内存布局机制冲突。

pbootstrap

与 ‘pdump’ 类似,但用于 引导构建(bootstrapping) Emacs 的场景,即此时尚无可用的 Emacs 二进制文件与 *.elc 字节编译 Lisp 文件。这种情况下生成的转储文件通常命名为 bootstrap-emacs.pdmp

dump

该方式使 temacs 转储出一个名为 emacs 的可执行程序,其中已预加载所有标准 Lisp 文件。(‘-batch’ 参数会阻止 temacs 尝试在终端上初始化任何数据,因此转储后的 Emacs 中终端信息表为空。)该方式也称为 unexec,因为它从运行中的进程生成程序文件,在某种意义上与执行程序启动进程的操作相反。尽管这是 Emacs 传统的状态保存方式,但现已被弃用。

bootstrap

与 ‘dump’ 类似,但用于通过 unexec 方式引导构建 Emacs 的场景。

转储后的 emacs 可执行文件(也称为 pure Emacs)即为最终安装的程序。如果使用可移植转储器构建 Emacs,则 emacs 可执行文件实际上是 temacs 的精确副本,同时会一并安装对应的 emacs.pdmp 文件。变量 preloaded-file-list 保存转储文件或转储后 Emacs 可执行文件中记录的预加载 Lisp 文件列表。若将 Emacs 移植到新操作系统且无法实现任何形式的转储,则 Emacs 每次启动时都必须加载 loadup.el

默认情况下,转储后的 emacs 可执行文件会记录构建时间、主机名等信息。使用 configure--disable-build-details 选项可禁用这些信息,使从相同源码两次构建安装的 Emacs 更有可能生成完全一致的副本。

你可以编写名为 site-load.el 的库来指定额外预加载的文件。可能需要在重新构建 Emacs 时添加定义:

#define SITELOAD_PURESIZE_EXTRA n

以增加 n 字节的纯净存储空间来存放额外文件;详见 src/puresize.h。 (可尝试每次增加 20000 字节直至空间足够。)不过,随着计算机速度提升,预加载额外文件的优势逐渐减小。在现代机器上通常不建议这样做。

loadup.el 读取 site-load.el 后,会通过调用 Snarf-documentation(see Accessing Documentation)从 etc/DOC 文件中查找原语与预加载函数(及变量)的文档字符串。

你可以将转储前需要执行的其他 Lisp 表达式放入名为 site-init.el 的库中。该文件会在查找文档字符串之后执行。

若要预加载函数或变量定义,并确保后续运行 Emacs 时能访问其文档字符串,有三种方式:

不建议在 site-load.elsite-init.el 中放入任何会修改用户期望的标准未修改 Emacs 功能的代码。若确实需要为站点覆盖默认功能,应使用 default.el,以便用户可以根据需要覆盖你的修改。See 概述:启动时的操作序列。 注意:若 site-load.elsite-init.el 修改了 load-path,这些修改在转储后会丢失。See 库搜索。要永久修改 load-path,请使用 configure--enable-locallisppath 选项。

在可预加载的包中,有时需要(或适合)将某些求值延迟到 Emacs 后续启动时执行。绝大多数此类情况与可自定义变量的取值相关。例如,tutorial-directory 是在预加载文件 startup.el 中定义的变量,其默认值基于 data-directory 设置。该变量需要在 Emacs 启动时(而非转储时)获取 data-directory 的值,因为转储后 Emacs 可执行文件通常会被安装到不同位置。

Function: custom-initialize-delay symbol value

该函数将 symbol 的初始化延迟到下一次 Emacs 启动。通常将该函数指定为可自定义变量的 :initialize 属性。(参数 value 未使用,仅为兼容 Custom 期望的格式而提供。)

在极少数需要比 custom-initialize-delay 更通用功能的场景下,可使用 before-init-hook(see 概述:启动时的操作序列)。

Function: dump-emacs-portable to-file &optional track-referrers

该函数使用 pdump 方式将 Emacs 当前状态转储到文件 to-file 中。通常转储文件名为 emacs-name.dmp,其中 emacs-name 为 Emacs 可执行文件名。可选参数 track-referrers 若非 nil,会使可移植转储器保留额外信息,用于追踪 pdump 方式暂不支持的对象类型来源。

尽管可移植转储器代码可在多种平台运行,但其生成的转储文件不可移植—只能由生成该转储文件的 Emacs 可执行文件加载。

若要在已转储的 Emacs 中使用该函数,必须以 ‘-batch’ 选项运行 Emacs。

若你在转储后的 Emacs 中包含 ‘.el’ 文件,且该 ‘.el’ 文件含有加载时正常执行的代码,则这些代码在 Emacs 转储后启动时不会运行。为解决该问题,可将函数添加到 after-pdump-load-hook 钩子中。该钩子会在 Emacs 启动时运行。

Function: dump-emacs to-file from-file

该函数使用 unexec 方式将 Emacs 当前状态转储到可执行文件 to-file 中。它从 from-file(通常为可执行文件 temacs)中获取符号。

该函数无法在已转储的 Emacs 中使用。 该函数已被弃用,且默认构建 Emacs 时不包含 unexec 支持,因此该函数不可用。

Function: pdumper-stats

若当前 Emacs 会话从转储文件恢复状态,则该函数返回转储文件及恢复状态耗时相关信息。返回值为关联表 ((dumped-with-pdumper . t) (load-time . time) (dump-file-name . file)), 其中 file 为转储文件名,time 为从转储文件恢复状态所用的秒数。 若当前会话并非从转储文件恢复,则返回值为 nil