Emacs設定ファイルの Byte Compileを自動化する

Debian Linux 上で GNU Emacs 27.2.50を使っています。 現状の emacs-init-time は、0.5秒前後で何ら不満はないのですが、さらなる起動時間の短縮にこだわって日々試行錯誤している Emacs馬鹿です。

設定ファイルを leaf に移行し、且つafter-init-hook を多用することでかなり短縮できました。で、最後にたどり着いたのが設定ファイルの全てを自動バイトコンパイルさせるという課題です。

auto-async-byte-compile.el を試す

Web検索でよく見つかる Tipsは、下記のパッケージを使ったものが多かったので私も試してみました。

(require 'auto-async-byte-compile)
(setq auto-async-byte-compile-exclude-files-regexp "/junk/")
(add-hook 'emacs-lisp-mode-hook 'enable-auto-async-byte-compile-mode)

確かに便利なのですがいくつかの問題に遭遇しました。

一つは、設定ファイルの実行には特に支障のない警告レベルのコンパイルエラーでも Warningバッファーが表示されてコンパイルの実行が中止されてしまうことです。もちろん致命的な syntaxエラーは修正が必要ですが、警告レベルのバグを全て潰すのはきりがないので無視してほしいです。

もう一つは、再コンパイルの必要がないファイルまで監視対象となることです。もちろん auto-async-byte-compile-exclude-files-regexp に設定したり 当該ファイルに ;; -*-no-byte-compile: t; -*- を記述することで対策はできますが結構面倒です。

標準コマンドで対応できた

思考錯誤の結果、標準コマンドの byte-recompile-directory が思い通りの仕事をしてくれることが確認できたました。最終的に下記を init.el に書くことで静かに快適に対応してくれるようになりました。

;; Byte-compile
(leaf *byte-compile
  :config
  (add-hook 'kill-emacs-hook 'my:recompile-directory)
  (defun my:recompile-directory ()
	"Byte-compile Lisp files modified in the directory."
	(interactive)
	(byte-recompile-directory (expand-file-name "~/.emacs.d/elisp") 0)
	(byte-recompile-directory (expand-file-name "~/.emacs.d/inits") 0)))

Package インストールデレクトリである ~/.emacs.d/elpa/~/.emacs/el-get/ などは対象外として、自作関数を置いてある .emacs.d/elisp/init-loader で読み込むために分割した設定ファイル群 ~/.emacs.d/inits/ のみを対象としました。 また、early-init.elinit.el 内の記述は極めて短く これらを byte-compile しても効果が薄いので無視した。

実行コマンドとしては、kill-emacs-hookafter-save-hook が選べる。両方試したが後者だと emacs-lisp 以外のファイルを編集しても実行されるので super-save.el で1秒ごとに自動保存している自分の環境ではかなりうるさい。

どうしても after-save-hook で使いたいなら以下のようになる。

(leaf *byte-compile
  :config
  (add-hook 'after-save-hook 'my:recompile-directory)
  (defun my:recompile-directory ()
	"Byte-compile Lisp files modified in the directory."
	(interactive)
	(if (string-match "\\.el$" (buffer-file-name))
		(progn
		  (byte-recompile-directory (expand-file-name "~/.emacs.d/elisp") 0)
		  (byte-recompile-directory (expand-file-name "~/.emacs.d/inits") 0)
		  (kill-buffer "*Compile-Log*")))))

起動時間短縮を追求することの意義

たかだかコンマ何秒というごくわずかの起動時間短縮を図るためにあくせく時間を費やして追求するのに何の意義があるのか?と問われたら苦笑するしかありません。 たんなる自己満足です。

Emacs28/29の native-compile も試してみましたが、少なくとも起動時間の短縮にはつながらないようなので、もうしばらく Emacs27を使い続けます。