emacs升级或直接把.emacs.d复制到其它电脑上时如何把所有的elc文件全部重新编译一遍

@redguardtoo 的elpa-mirror 建一个本地镜像 可以解决问题。但建elpa本地镜像感觉可能是个大工程。

翻我的配置文件,发现这个问题我以前解决过。但估计没有人会用这种解决办法,也还是分享出来,顺便了解下其它人是怎么解决的

我是写了一段php脚本中调用fd .elc列出.emacs.d目录下所有的的elc文件,在找到对应的el文件(找不到不编译),对每一个el文件都加上(byte-compile-file),最后生成一个compile-all.el文件,emacs在load-file这个文件,这样所有包的elc文件全都编译了

$path=str_replace("\\","/","d:/home/.emacs.d");
$arr=explode("\n",str_replace("\\","/",shell_exec("fd .elc ".$path)));
$con=";此文件由compile-all.php生成 用于在emacs升级时把配置文件中的所有包全部重编译\n";
foreach($arr as $f=>$v){
  $el_file=substr($v,0,-1);
  if(is_file($el_file)){#确定el文件存在
    $con.='(byte-compile-file "'.$el_file.'")'."\n";       
  }else{
    $con.=';err! '.$el_file." 不存在\n";
  }
}
file_put_contents($path."/init/exec/compile-all.el",$con);
echo $con;

在另一贴中看到 C-u 0 M-x byte-recompile-directory,在elpa目录下执行,编译完成后,我把所有elc文件都列出来,发现并没有把所有能找到el文件的elc文件都编译一遍,很多elc文件都不是现在的日期。

;; ** 设置 emacs 包管理器
(require 'package)
(setq package-user-dir
      (locate-user-emacs-file
       (format "%s-%s" "elpa" emacs-major-version)))
(setq package-gnupghome-dir
      (expand-file-name "gnupg" package-user-dir))
(unless package--initialized
  (package-initialize))

(defun eh-elpa-directory ()
  "返回 emacs-helper 内置 elpa 镜像的目录。"
  (file-name-as-directory
   (concat (file-name-directory
            (locate-library "eh-basic.el"))
           "elpa/")))

;; ** 设置 elpa-mirror
(require 'elpa-mirror)

(defun eh-elpa-mirror ()
  (interactive)
  (let* ((directory (file-name-as-directory (eh-elpa-directory)))
         (recreate-directory
          (yes-or-no-p (format "重新创建目录:%S ? " directory))))
    (elpamr-create-mirror-for-installed directory recreate-directory)))

(require 'package)

(defun eh-current-directory ()
  (file-name-directory
   (buffer-file-name)))

(setq package-archives
      `(("eh-elpa" . ,(concat (eh-current-directory) "elpa/"))))

(package-initialize)

(defun eh-packages-install (packages)
  (let ((refreshed nil))
    (when (not package-archive-contents)
      (package-refresh-contents)
      (setq refreshed t))
    (dolist (pkg packages)
      (when (and (not (package-installed-p pkg))
                 (assoc pkg package-archive-contents))
        (unless refreshed
          (package-refresh-contents)
          (setq refreshed t))
        (ignore-errors
          (package-install pkg))))))

(defun eh-get-mirror-packages (mirror-directory)
  "Return all package's name in a mirror directory: MIRROR-DIRECTROY."
  (when (and mirror-directory (stringp mirror-directory))
    (let ((file (concat (file-name-as-directory mirror-directory)
                        "archive-contents")))
      (when (file-exists-p file)
        (mapcar #'car (cdr (read (with-temp-buffer
                                   (insert-file-contents file)
                                   (buffer-string)))))))))

(defvar eh-config-template
  "
%% ------------------------------------
%% Add by emacs-helper installer

(add-to-list 'load-path %S)
(require 'emacs-helper)

%% ------------------------------------
")

(defun eh-installer ()
  (interactive)
  ;; 安装 elpa 目录下的所有包
  (eh-packages-install
   (eh-get-mirror-packages
    (concat (eh-current-directory) "elpa/")))
  ;; 在 "~/.emacs" 文件中插入配置片断
  (unless (with-temp-buffer
            (insert-file-contents "~/.emacs")
            (goto-char (point-min))
            (search-forward "(require 'emacs-helper)" nil t))
    (append-to-file
     (format (replace-regexp-in-string "%%" ";;" eh-config-template)
             (eh-current-directory)) nil "~/.emacs"))
  (message "Emacs-helper 安装完成,请重新启动 Emacs"))

(eh-installer)

我是将当前使用的包拷贝到一个目录,然后用 eh-installer 在其他机器上安装

为什么是大工程?只是把我家里的电脑上的正在使用的插件打包成一个repository。几秒钟就搞定了。你看一下elpa-mirror的README。这个插件是我开发的所有插件里长星最快的。就是因为使用是简易的。

嗯,我使用的elpa插件数量不是很多,应该对elpa-mirror的理解有问题,以为这个的目的是提供一个完整的elpa镜像服务,如//elpa.emacs-china.org 这样的