34

Occasionally, when I start Emacs, I get a message like.

Source file `/home/USER/.emacs.d/elpa/....el' newer than byte-compiled file

Also, I sometimes edit a package I'm developing and forget to recompile it. When I try to load the new file, it takes me a while to realise that Emacs is still using the old compiled file.

Is there a way I can tell Emacs to completely avoid byte-compiled files that are older than their respective source files?

Malabarba
  • 22,878
  • 6
  • 78
  • 163

5 Answers5

43

Emacs 24.3 or below

There's no built-in way of preventing these old files from being loaded, but there are easy ways to get rid of them.

  • You can recompile the entire elpa directory by calling:
    M-x byte-recompile-directory RET ~/.emacs.d/elpa/.
    This should get rid of outdated files.
  • You can use the auto-compile package and activate auto-compile-on-load-mode which can compile files before they are loaded.

Emacs 24.4

Yes, and it turns out to be rather simple. The load-prefer-newer variable serves precisely this purpose.

(setq load-prefer-newer t)

Unfortunately, it won't work when some code specifically targets the .elc file, such as (load "server.elc"). But it should be enough as long as you're using requires or calling load without a suffix, which you should.

From the doc:

load-prefer-newer is a variable defined in lread.c.
Its value is nil

Documentation:
Non-nil means load prefers the newest version of a file.
This applies when a filename suffix is not explicitly specified and load is trying various possible suffixes (see load-suffixes and load-file-rep-suffixes). Normally, it stops at the first file that exists unless you explicitly specify one or the other. If this option is non-nil, it checks all suffixes and uses whichever file is newest.
Note that if you customize this, obviously it will not affect files that are loaded before your customizations are read!

Malabarba
  • 22,878
  • 6
  • 78
  • 163
  • 2
    I would urge people to use the (excellent!) [`auto-compile`](https://github.com/tarsius/auto-compile) library in Emacs 24.4+, as well as below. It's a real configure-and-forget solution. `load-prefer-newer` only ensures that you'll *continue to run slow uncompiled code* after your compiled code gets out of date. – phils Dec 20 '14 at 22:40
  • 1
    @phils Nowadays byte code isn't much faster than plain source code, thanks to eager macro expansion. –  Dec 24 '14 at 22:03
  • Changes I made to org-agenda-sorting-strategy (in org-agenda.el) weren't being reflected after a restart, but recompiling the .elc files as described in the answer solved the problem. – earlio Nov 16 '17 at 07:15
16

If you only set load-prefer-newer (where available), the correct code will get loaded, but it might not have been byte-compiled, so there may be a slight performance penalty.

You can use Jonas Bernoulli's excellent auto-compile library to help make sure this problem doesn't arise. In particular, auto-compile-on-load-mode will recompile outdated .elc files before loading them.

artagnon
  • 2,237
  • 1
  • 15
  • 17
sanityinc
  • 2,871
  • 13
  • 17
3

I met this on the Internet long time ago:

;; If you're saving an elisp file, likely the .elc is no longer valid:
(add-hook 'emacs-lisp-mode-hook 'esk-remove-elc-on-save)
(defun esk-remove-elc-on-save ()
  "If you're saving an elisp file, likely the .elc is no longer valid."
  (make-local-variable 'after-save-hook)
  (add-hook 'after-save-hook
            (lambda ()
              (if (file-exists-p (concat buffer-file-name "c"))
                  (delete-file (concat buffer-file-name "c"))))))

if you work with FILE in emacs-lisp-mode and you save it -- the code above removes FILEc if it exists.

Adobe
  • 1,859
  • 13
  • 27
1

found a snippet similar to sanityinc's, works for current.

LesleyLai/recompile-on-save.el: https://gist.github.com/LesleyLai/627085e275d2cf46429c0f44c27a92d7

(defun recompile-elc-on-save ()
  "If you're saving an elisp file, likely the .elc is no longer valid."
  (make-local-variable 'after-save-hook)
  (add-hook 'after-save-hook
            (lambda ()
              (if (file-exists-p (byte-compile-dest-file buffer-file-name))
                  (byte-compile-file buffer-file-name)))))
(add-hook 'emacs-lisp-mode-hook 'recompile-elc-on-save
          )
roomworoof
  • 394
  • 2
  • 9
0

Also, I sometimes edit a package I'm developing and forget to recompile it. When I try to load the new file, it takes me a while to realise that Emacs is still using the old compiled file.

May I suggest to add a hook in your init file?

(add-hook 'after-save-hook 'byte-compile-current-buffer)

Or, if you want to apply the hook only on el files:

(add-hook 'emacs-lisp-mode-hook (lambda () (add-hook 'after-save-hook 'byte-compile-current-buffer nil t)))
sanityinc
  • 2,871
  • 13
  • 17
Nsukami _
  • 6,341
  • 2
  • 22
  • 35
  • 9
    Whoah, that would try to byte-compile even non-elisp buffers. Not ideal! The robust way to do this is with the auto-compile package. – sanityinc Sep 25 '14 at 09:59