14

我现在通过 MELPA 和 Marmalade 尽可能多地安装,并且使用 git 管理我的 ~/.emacs.d。但是,我有 git ignore *.elc 文件。

这意味着当我在一个系统上安装一个软件包然后开始使用另一个系统时,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/company-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 相同的文件进行字节编译?

4

6 回答 6

10

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)
于 2013-03-12T14:53:06.503 回答
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 目录并重新安装所有内容(使用上面的代码)。

于 2013-03-12T14:04:34.977 回答
6

对于“如何自动重新编译任何过时的 .elc 文件”这个更一般的问题,我喜欢的解决方案是使用https://github.com/tarsius/auto-compile

我曾经有一些自定义解决方案涵盖了我遇到的大多数情况,但是这个库涵盖了我正在做的所有事情以及更多。只需在加载其他任何内容之前对其进行初始化,然后您就可以排序了。

至于不编译最初未编译的文件的原始问题,这就是0参数的byte-recompile-directory作用,因此您明确要求这种行为。默认行为是仅重新编译现有过时的 .elc 文件,因此您应该简单地删除该 .elc 文件0

于 2014-02-24T20:07:12.630 回答
2

我不知道您关于字节编译包的具体问题的答案与完全相同的方式package.el

但是,对于您在通过 Melpa 或 marmalade 安装扩展时在 git 中维护 emacs 配置目录的更普遍的问题,我建议您看一下 palm 它旨在解决这个问题。

于 2013-03-11T19:33:44.057 回答
2

当我需要手动重新编译以前使用 elpa 安装的软件包时,(字节编译文件)对我有用。

特别是对于这种情况:https ://github.com/yjwen/org-reveal/issues/76t

于 2014-10-28T14:13:03.427 回答
1

您遇到的问题只是在初始化包之前对文件进行字节编译。如果您切换两条线,您的问题应该会消失。您得到的错误 ( Cannot open load file: eclim) 是因为~/.emacs.d/elpa/emacs-eclim-20130310.1237/还没有在您的 中load-path,并且package-initialize会将其添加到您的load-path(以及其他一些东西)中。

于 2014-02-24T19:34:41.857 回答