来自字节编译的错误和警告信息会输出到名为 *Compile-Log* 的缓冲区中。 这些信息包含文件名和行号,用于定位问题所在。 通常用于处理编译器输出的 Emacs 命令也可用于这些信息。
当错误是由程序中非法的语法导致时,字节编译器 可能无法准确判断错误的具体位置。 一种排查方法是切换到缓冲区 *Compiler Input*。 (该缓冲区名以空格开头,因此不会出现在缓冲区菜单中。) 该缓冲区包含正在编译的程序,光标位置 表示字节编译器成功读到的位置; 错误原因通常就在附近。 See 调试无效的 Lisp 语法,了解定位语法错误的一些技巧。
字节编译器最常见的一类警告是针对 被使用但未定义的函数和变量。 这类警告报告的行号是文件末尾, 而非缺失的函数或变量实际被使用的位置; 要找到这些位置,你必须手动搜索文件。
如果你确信某条关于缺失函数或变量的警告是不合理的, 有多种方法可以抑制它:
fboundp 进行条件判断来抑制警告,例如:
(if (fboundp 'func) ...(func ...)...)
对 func 的调用必须位于 if 的 then-form 中,
并且 func 在 fboundp 中必须带引号。
(该特性对 cond 同样有效。)
boundp 进行条件判断来抑制警告:
(if (boundp 'variable) ...variable...)
对 variable 的引用必须位于 if 的 then-form 中,
并且 variable 在 boundp 中必须带引号。
declare-function 告知编译器某个函数已定义。
See 告知编译器某个函数已被定义。
defvar
告知编译器某个变量已定义。
(注意这会将该变量标记为特殊变量,
即动态绑定,但仅在当前词法作用域内有效,
如果在顶层则是整个文件。)
See 定义全局变量。
你还可以使用 with-suppressed-warnings 宏
在指定表达式内抑制编译器警告:
执行时,它等价于 (progn body...),
但编译器不会对 body 中指定的条件发出警告。
warnings 是一个关联列表,
元素为警告符号及其作用的函数/变量符号。
例如,如果你希望调用名为 foo 的废弃函数,
但又想抑制编译警告,可以这样写:
(with-suppressed-warnings ((obsolete foo)) (foo ...))
若要更粗粒度地抑制编译器警告,
可以使用 with-no-warnings 结构:
执行时,它等价于 (progn body...),
但编译器不会对 body 内部的任何内容发出警告。
我们推荐你优先使用 with-suppressed-warnings,
如果确实要使用本结构,请将它包裹在尽可能小的代码片段周围,
以免遗漏除目标警告外的其他有用警告。
通过设置变量 byte-compile-warnings,
可以更精细地控制字节编译器的警告。
详情参见其文档字符串。
有时你可能希望字节编译器将警告以 error 形式报告。
如果需要,将 byte-compile-error-on-warn 设置为非nil。