Is there any way to tell Emacs to only consider loading a
.elc file if a corresponding
.el file exists?
I am not sure whether this exact option exists, but the Emacs 24.4+ variable
load-prefer-newer comes close:
load-prefer-newer is a variable defined in ‘C source code’.
Its value is
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-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
Note that if you customize this, obviously it will not affect files
that are loaded before your customizations are read!
customize this variable.
This variable was introduced, or its default value was changed, in
version 24.4 of Emacs.
Setting this to
t will allow you to place newer
.el files alongside obsolete
.elc files and Emacs will prefer the former. As the documentation warns, this setting must be changed before any of the relevant files are loaded. So, if you want the setting to apply to your
user-init-file, you must enable it before this is loaded, i.e. in your
site-run-file or similar.
Another solution to this loading problem is provided by the package
auto-compile in the form of
auto-compile-on-load-mode. Enabling this minor mode causes outdated
.elc files to be automatically recompiled when they are loaded.
Further to OP's comment below, here is one possible approach to solving the issue by advising
(defun my--locate-file (base suffix)
"Search for BASE filename with SUFFIX in `load-path'.
Representations of SUFFIX under `load-file-rep-suffixes' are
tried successively until one succeeds."
(locate-file-internal base load-path (mapcar (lambda (rep)
(concat suffix rep))
(define-advice require (:before-while (feature &optional filename _noerror)
"Do not delegate an obsolete compiled FILENAME to `require'.
FILENAME is considered obsolete if it is byte-compiled but lacks
a source file."
(let ((base (file-name-base (or filename (symbol-name feature)))))
(or (not (my--locate-file base ".elc"))
(my--locate-file base ".el"))))
Note that this affects nearly all file loading in Emacs, so if left non-byte-compiled it may even double your startup time. You can mitigate this by byte-compiling your
user-init-file and/or further guarding the calls to
my--locate-file, e.g. with a
FILENAME whitelist or similar.
Also note that
define-advice is an Emacs 25 feature - in Emacs 24 you should adapt the code to call
advice-add directly instead.