2013-03-11 89 views
13

我現在正在通過MELPA和Marmalade儘可能地安裝,並使用git管理我的〜/ .emacs.d。但是,我有git忽略* .elc文件。如何自動(重新)編譯ELPA包?

這意味着當我在一個系統上安裝一個軟件包,然後開始使用另一個系統時,git pull只給我* .el文件。使用這些文件通常比使用* .elc慢。

我嘗試添加以下到〜/ .emacs.d/init.el:

;; load the packages we've installed. Note that package-install 
;; byte-compiles the packages, but .elc is ignored by git so we force recompilation here 
(byte-recompile-directory (expand-file-name "~/.emacs.d/elpa") 0) 
(package-initialize) 

不幸的是,這並不等同於package.el完成編譯。例如,如果我安裝的Emacs eclim,package.el不編譯的Emacs eclim /公司的Emacs eclim.el,我得到以下錯誤:

Leaving directory `/home/wilfred/.emacs.d/elpa' 

Compiling file /home/wilfred/.emacs.d/elpa/emacs-eclim-20130310.1237/company-emacs-eclim.el at Mon Mar 11 15:40:01 2013 
Entering directory `/home/wilfred/.emacs.d/elpa/emacs-eclim-20130310.1237/' 
company-emacs-eclim.el:35:1:Error: Cannot open load file: eclim 
Warning: reference to free variable `multiple-cursors-mode' 
Warning: reference to free variable `mc--read-char' 
Warning: assignment to free variable `mc--read-char' 
Warning: reference to free variable `multiple-cursors-mode' 
Warning: reference to free variable `mc--read-quoted-char' 
Warning: assignment to free variable `mc--read-quoted-char' 
Warning: reference to free variable `rectangular-region-mode' 
Warning: reference to free variable `rectangular-region-mode' 

如何使Emacs的字節 - 只編譯與package.el相同的文件?

回答

6

package.el實際上使用完全相同的方法,它只是在啓動時重新編譯會使錯誤更明顯。

使用的功能是package--make-autoloads-and-compile,它要求:

(byte-recompile-directory pkg-dir 0 t) 

所以在這個問題的原代碼是正確的。然而,重新編譯尚未編譯的目錄,你可以做到以下幾點:

(require 'dash) 
(require 'f) 

(defun was-compiled-p (path) 
    "Does the directory at PATH contain any .elc files?" 
    (--any-p (f-ext? it "elc") (f-files path))) 

(defun ensure-packages-compiled() 
    "If any packages installed with package.el aren't compiled yet, compile them." 
    (--each (f-directories package-user-dir) 
    (unless (was-compiled-p it) 
     (byte-recompile-directory it 0)))) 

(ensure-packages-compiled) 
2

我不知道你的關於字節編譯軟件包的具體問題的答案與package.el完全一樣。

但是,對於在通過Melpa或橘子醬安裝擴展時在git中維護emacs配置目錄的更一般問題,我建議您看看pallet,它旨在解決這個問題。

+1

謝謝,我不知道托盤。但是,我真的很喜歡我的.emacs.d自成一體 - 過去我很悲傷,很少更新的elisp文件在我最初下載的地方不再可用。 – 2013-03-12 14:42:56

8

我建議不要讓軟件包保留在版本控制中(你不會把.o文件放在版本控制下,你會嗎?)。下面是我用它來保持我的包在同步代碼:

(setq jpk-packages 
     '(
     ac-dabbrev 
     ... 
     yasnippet 
     )) 

(package-initialize) 
(add-to-list 'package-archives 
      '("melpa" . "http://melpa.milkbox.net/packages/")) 
(add-to-list 'package-archives 
      '("org" . "http://orgmode.org/elpa/")) 

(when (not package-archive-contents) 
    (package-refresh-contents)) 

(dolist (pkg jpk-packages) 
    (when (and (not (package-installed-p pkg)) 
      (assoc pkg package-archive-contents)) 
    (package-install pkg))) 

(defun package-list-unaccounted-packages() 
    "Like `package-list-packages', but shows only the packages that 
    are installed and are not in `jpk-packages'. Useful for 
    cleaning out unwanted packages." 
    (interactive) 
    (package-show-package-list 
    (remove-if-not (lambda (x) (and (not (memq x jpk-packages)) 
          (not (package-built-in-p x)) 
          (package-installed-p x))) 
        (mapcar 'car package-archive-contents)))) 

我把上面的init.el(這當然是版本控制之下),並將其安裝不存在任何軟件包然而,當emacs啓動。更新是從緩衝區package-list-packages創建完成的。 package-list-unaccounted-packages顯示了所有已安裝但未列入我的jpk-packages列表中的軟件包,並且可以輕鬆刪除我從列表中刪除的軟件包。

要回答您的具體問題,我只需刪除elpa目錄並重新安裝所有內容(使用上面的代碼)。

+0

看起來你的jpk軟件包相當於一個紙箱清單(就像@francesco用上面的Pallet描述的那樣),但是你失去了指定確切軟件包版本的能力。 – 2013-03-12 14:40:45

+0

我不使用紙箱或托盤,但根據我的理解,我使用的是它們的一個非常簡單的版本。我喜歡我的方式,因爲我需要幾乎所有的代碼來引導紙箱/托盤,到目前爲止,我還沒有指定版本的包的問題。 – jpkotta 2013-03-12 18:27:16

+2

「你不會把.o文件放在版本控制下,你會嗎?」我不覺得這是一個公平的比較。構建.o文件應始終可重現。但是,似乎沒有辦法指定特定版本的軟件包。我檢查包文件,以便能夠部署我知道一起工作的emacs配置的一致快照。 – 2015-04-04 12:20:43

1

你的問題很簡單,你字節編譯初始化你的包之前的文件。如果切換兩條線,則問題應該消失。您收到的錯誤(Cannot open load file: eclim)是因爲~/.emacs.d/elpa/emacs-eclim-20130310.1237/尚未在您的load-path中,並且package-initialize會將其添加到load-path(以及其他一些內容)。

6

我喜歡更常見的問題「我如何自動重新編譯任何過時的解決方案。elc文件「是要使用的https://github.com/tarsius/auto-compile

我曾經有一些自定義解決方案覆蓋了我遇到的大多數情況,但是這個庫涵蓋了我正在做的以及更多的一切,只是在加載其他任何東西之前初始化它,而你

至於最初編譯不是最初編譯的文件的問題,這就是byte-recompile-directory0參數的作用,所以你明確地要求那個行爲。默認行爲是隻重新編譯現有的過時的.elc文件,所以你應該簡單地刪除那0