2013-03-11 86 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