package.elにpackage.el以外の方法でインストールした拡張を認識させる
Emacsの拡張の管理は、できるだけpackage.elで行うようにしています。
ある日Emacsを起動すると、以下の警告が表示されました。
Warning (emacs): Unable to activate package `popup'. Required package `cl-lib-0.3' is unavailable
原因はすぐわかりました。
package.elがインストールしたcl-libをアンインストールしていたためです。
なぜアンインストールしたのかと言うと
現在、私はWindowsとUbuntuを併用しており、EmacsのバージョンがWindowsでは24.2.1、Ubuntuでは24.3.1です。
~/.emacs.d を同期させて同じ環境にしています。
で、以前UbuntuでEmacsを使った時にエラーに遭遇しまして、その原因がpackage.elがインストールしたcl-libでした。
以下の事例と全く同じ現象で、package.elでcl-libをアンインストールすることにより解決しました。
https://github.com/emacs-jp/issues/issues/13
24.2.1でエラーにならないように
cl-libが自動でインストールされたのは、popup.elが要求しているバージョンが Emacs24.2.1には無いためだったので、ただアンインストールしただけだと、Emacs24.2.1でpopup.elが使えません。
そのため、WindowsのEmacsのsite-lispフォルダに、自動でインストールされたcl-libをコピーしておくことにしました。
これで、package.elでcl-libをアンインストールしても、Windowsでも正常に動作するだろうと考えました。
前置き終了
前置きが長くなりましたが、そういう経緯があった上で上記の警告が出たため、
package.elは、自身の管理下でインストールされたもの以外は認識していなそうだと感じました。
警告が出るだけでなく、popup.elを使った機能が正常に動作しなかったので、
何とかしなければいけませんでしたが、package.elでインストールすればUbuntuではまたエラー...。
しょうがないのでソース見る
package.elの処理を見ると、package-initializeされた際、package-user-dirに見つからない拡張は
package--builtinsという変数に定義されていればbuiltinな拡張、でなければ上記警告、という処理でした。
package--builtins
この変数はfinder-inf.elにハードコーディングで定義されていました。
さらに調べてみると、finder-inf.elはfinder.elのfinder-compile-keywords関数が生成したものだとわかりました。
ファイルの更新日時から考えて、Emacsのインストール時に一度だけ実行されているようでした。
finder-compile-keywordsを再実行すれば良さそうでしたが、finder-inf.elが変更されることや、
今後、別の拡張で同じ事象があった時に面倒かなと思ったので、別途実装することにしました。
結論
以下の設定をpackage-initializeの前に記述することで警告を回避できました。
(when (require 'finder nil t) (let* ((regist (lambda (file) (with-temp-buffer (insert-file-contents file) (let* ((pkgnm (lm-get-package-name)) (pkg (when (and (stringp pkgnm) (string-match "\\.el\\'" pkgnm)) (intern (replace-regexp-in-string "\\.el\\'" "" pkgnm)))) (ver (ignore-errors (version-to-list (lm-header "version")))) (doc (lm-synopsis)) (vec (vector ver nil doc))) (when (and pkg (not (assq pkg package--builtins))) (message "registed package--builtin: %s (%s) --- %s" pkg ver doc) (push `(,pkg . ,vec) package--builtins)))))) (seek (lambda (dir) (setq dir (expand-file-name dir)) (message "seek builtin from %s ..." dir) (dolist (node (directory-files dir)) (let ((fullpath (concat dir "/" node))) (cond ((string-match "\\`[._]" node) nil) ((file-directory-p fullpath) (funcall seek fullpath)) ((and (file-regular-p fullpath) (string-match "\\.el\\'" node)) (funcall regist fullpath)))))))) ;; 追加認識させたい拡張があるルートディレクトリ毎に繰り返し記述 (funcall seek (concat exec-directory "../site-lisp")) (funcall seek (concat user-emacs-directory "elisp/etc")) ... ))
Emacs起動後、*Messages*バッファに以下のようなメッセージがあれば追加できていると思います。
registed package--builtin: cl-lib ((0 4)) --- Properly prefixed CL functions and macros
※ メッセージがうざかったら、(message "... ) の処理を削除して下さい。
※ package--builtins変数を参照する拡張の動作がおかしくなる可能性がありますが、とりあえず様子見という感じで。