35

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?

5 Answers 5

44

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!

3
  • 2
    I would urge people to use the (excellent!) 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
    Commented Dec 20, 2014 at 22:40
  • 1
    @phils Nowadays byte code isn't much faster than plain source code, thanks to eager macro expansion.
    – user227
    Commented Dec 24, 2014 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
    Commented Nov 16, 2017 at 7:15
17

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.

0
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.

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
          )
3
  • 1
    Please summarize what the snippet does. Otherwise, the is a link-only answer. Maybe just include the snippet (and keep the link, for attribution), if it is really just a "snippet".
    – Drew
    Commented Aug 13, 2022 at 14:48
  • Thanks. I tried as you taught me.
    – roomworoof
    Commented Aug 14, 2022 at 16:46
  • Thx! Much better.
    – Drew
    Commented Aug 14, 2022 at 19:23
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)))
1
  • 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
    Commented Sep 25, 2014 at 9:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.