Emacs 加载 Lisp 库时,会在变量 load-path 指定的目录列表中搜索该库。
该变量的值是一个目录列表,使用 load 加载文件时会搜索这些目录。
列表中的每个元素要么是字符串(必须为目录路径),要么是 nil(代表当前工作目录)。
Emacs 启动时,会通过多个步骤初始化 load-path 的值:
首先,它会根据编译时设置的默认路径,查找自身 Lisp 文件所在的目录,
并将该目录保存到 lisp-directory 中。
通常,该目录是安装 *.elc 文件的路径,格式类似:
"/usr/local/share/emacs/version/lisp"
其中 version 为 Emacs 的版本号。 (在本节及后续示例中,请将 /usr/local 替换为你系统中 Emacs 的实际安装前缀。) 该目录及其子目录包含 Emacs 自带的标准 Lisp 文件; 若 Emacs 无法找到自身的 Lisp 文件,将无法正常启动。
若你从编译目录运行 Emacs(即未安装的可执行文件),
则 Emacs 会改用编译源码所在目录的 lisp 子目录来初始化 lisp-directory。
随后,Emacs 会以该 lisp-directory 初始化 load-path。
若你在源码目录外的独立目录编译 Emacs,
它还会将编译目录的 lisp 子目录添加到 load-path。
上述所有目录均以绝对文件名形式存储在上述两个变量中。
除非你使用 --no-site-lisp 选项启动 Emacs,
否则它会在 load-path 的前端额外添加两个 site-lisp 目录。
这些目录用于存放本地安装的 Lisp 文件,格式通常为:
"/usr/local/share/emacs/version/site-lisp"
和
"/usr/local/share/emacs/site-lisp"
第一个目录用于当前 Emacs version 版本的本地安装文件; 第二个目录用于所有已安装 Emacs 版本共享的本地文件。 (若 Emacs 以未安装状态运行,还会添加源码目录和编译目录下的 site-lisp 子目录(若存在); 但通常源码目录和编译目录不含 site-lisp 子目录。)
若设置了环境变量 EMACSLOADPATH,它会修改上述初始化流程,
Emacs 会基于该环境变量的值初始化 load-path。
EMACSLOADPATH 的语法与 PATH 相同:
目录之间用 ‘:’ 分隔(部分操作系统为 ‘;’)。
以下是设置 EMACSLOADPATH 变量的示例(基于 sh 风格的 shell):
export EMACSLOADPATH=/home/foo/.emacs.d/lisp:
该环境变量值中的空元素(无论是末尾空元素(如上述示例中末尾的 ‘:’)、
开头空元素还是中间嵌入的空元素),都会被标准初始化流程生成的 load-path 默认值替换。
若不存在此类空元素,则 EMACSLOADPATH 会完全指定 load-path 的内容。
你必须要么包含空元素,要么显式指定标准 Lisp 文件所在目录的路径,
否则 Emacs 将无法正常运行。
(修改 load-path 的另一种方式是启动 Emacs 时使用 -L 命令行选项,详见下文。)
对于 load-path 中的每个目录,Emacs 会检查是否存在 subdirs.el 文件,
若存在则加载该文件。subdirs.el 文件在 Emacs 编译/安装时生成,
其中包含的代码会让 Emacs 将这些目录的所有子目录添加到 load-path 中——
包括直接子目录和多级嵌套子目录。
但会排除以下子目录:名称非以字母/数字开头的、名为 RCS 或 CVS 的、
以及包含 .nosearch 文件的子目录。
接下来,Emacs 会添加你通过 -L 命令行选项指定的额外加载目录 (see Action Arguments in The GNU Emacs Manual); 若存在已安装的可选软件包,还会添加这些软件包的安装目录(see Packaging Basics)。
常见做法是在初始化文件中添加代码(see The Init File),
将一个或多个目录添加到 load-path。例如:
(push "~/.emacs.d/lisp" load-path)
See push,查看 push 的说明。
转储 Emacs 时会使用 load-path 的一个特殊值。
如果你使用 site-load.el 或 site-init.el 文件来定制转储后的 Emacs(see Building Emacs),
这些文件对 load-path 所做的任何修改在转储后都会丢失。
该变量保存一个字符串,指明存放 Emacs 自身 *.el 和 *.elc 文件的目录。 通常这是 Emacs 安装目录结构中这些文件所在的位置; 如果是从编译目录直接运行 Emacs,则指向编译所用源码目录中的 lisp 子目录。
该命令查找库 library 对应的精确文件名。
它搜索库的方式与 load 相同,参数 nosuffix 的含义也与 load 中一致:
不向指定的 library 名称添加 ‘.elc’ 或 ‘.el’ 后缀。
若 path 非 nil,则使用该目录列表而非 load-path。
当 locate-library 被程序调用时,以字符串形式返回文件名。
当用户交互式运行 locate-library 时,参数 interactive-call 为 t,
指示 locate-library 在回显区显示文件名。
该命令显示被 遮蔽(shadowed) 的 Emacs Lisp 文件列表。
被遮蔽的文件是指:虽然位于 load-path 的某个目录中,
但由于 load-path 中靠前的目录里存在同名文件,
导致其通常不会被加载的文件。
例如,假设 load-path 设置为:
("/opt/emacs/site-lisp" "/usr/share/emacs/29.1/lisp")
且两个目录中都有名为 foo.el 的文件。
那么 (require 'foo) 永远不会加载第二个目录中的文件。
这种情况可能表明 Emacs 的安装存在问题。
当从 Lisp 中调用此函数时,会打印被遮蔽文件的信息,而非在缓冲区中显示。
若可选参数 stringp 非 nil,则以字符串形式返回这些被遮蔽文件。
如果 Emacs 编译时启用了原生编译支持(see Lisp 本地代码编译),
当通过 load-path 搜索到 ‘.elc’ 字节编译文件时,
Emacs 会尝试查找对应的存放原生编译代码的 ‘.eln’ 文件。
原生编译文件的搜索目录由 native-comp-eln-load-path 指定。
该变量保存一个目录列表,Emacs 会在其中搜索原生编译的 ‘.eln’ 文件。
列表中非绝对路径的文件名会被解释为相对于 invocation-directory 的路径(see Operating System Environment)。
列表中的最后一个目录为系统目录,即 Emacs 编译安装过程中安装 ‘.eln’ 文件的目录。
在列表中的每个目录下,Emacs 会在一个子目录中查找 ‘.eln’ 文件,
该子目录名由 Emacs 版本和一个依赖当前原生编译 ABI 的 8 位哈希值构成;
此子目录名保存在变量 comp-native-version-dir 中。