



























这一步在编译 Emacs 之前 做,因为 Native Compiler 的配置写在 early-init.el 里,编译完第一次启动 Emacs 时它会用这些参数来编译所有 .el 文件。
先查你的 CPU 架构代号:
gcc -march=native -Q --help=target | grep march
输出类似:
-march= skylake
ARM 设备输出类似:
-march= armv8-a+crypto+crc
armv8-a 是 ARM 64 位基础指令集, +crypto 是加密扩展(硬件加速 AES、SHA 等), +crc 是 CRC32 校验扩展。 + 号是 GCC 的语法,表示在基础架构上启用可选扩展。
记住你查到的架构代号。
然后在 ~/.emacs.d/early-init.el 里加上(Emacs 27+ 才有这个文件,没有就新建一个):
(setq my-cpu-architecture "skylake") (setq native-comp-compiler-options `( "-O2" ,(format "-mtune=%s" my-cpu-architecture) ,(format "-march=%s" my-cpu-architecture) "-g0" "-fno-omit-frame-pointer" "-fno-finite-math-only"))
*ARM 用户注意*:ARM 上 -march 和 -mtune 接受的值不同。 -march 接受架构字符串(如 armv8-a+crypto+crc ),但 -mtune 要传具体 CPU 名称(如 cortex-a72 ),不能用同一个值。查 -mtune 值的命令:
gcc -mtune=native -Q --help=target | grep mtune
ARM 用户的配置要分开设置:
(setq my-cpu-architecture "armv8-a+crypto+crc") (setq my-cpu-tune "cortex-a72") (setq native-comp-compiler-options `("-O2" ,(format "-march=%s" my-cpu-architecture) ,(format "-mtune=%s" my-cpu-tune) "-g0" "-fno-omit-frame-pointer" "-fno-finite-math-only")) (setq native-comp-driver-options '( "-Wl,-z,pack-relative-relocs" "-Wl,-O2" "-Wl,--as-needed"))
几个要点:
native 做 march 的值 。libgccjit(负责 native compilation 的库)不能像独立 GCC 那样自动探测主机 CPU,传 native 可能导致编译失败。必须手动查到架构代号再填。-O2 而不是 -O3 。Emacs 开发者明确建议不要用 -O3 ,因为它在 Emacs 这种大型老旧 C 代码库上可能触发未定义行为,导致随机崩溃或界面卡死。-g0 去掉调试符号。 .eln 文件不需要调试,去掉后文件更小、编译更快。-fno-omit-frame-pointer 保留栈帧指针。虽然省掉栈帧指针能腾出一个通用寄存器,但在现代 CPU 上性能提升微乎其微,反而会让崩溃时的栈回溯变得难以阅读(Emacs 开发者 Eli Zaretskii 在 bug#76180 中也指出了这个问题)。
改完配置后,需要清掉旧的 .eln 缓存让 Emacs 用新参数重新编译:
find ~/.emacs.d/ -name '*.eln' -delete
下次启动 Emacs 时,Native Compiler 会在后台自动用新参数重新编译所有 .el 文件。不用手动触发,Emacs 加载包时发现缺 .eln ,自己就会起后台线程编译。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。