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 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!
You can 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.
Update
Further to OP's comment below, here is one possible approach to solving the issue by advising require
/load
:
(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))
load-file-rep-suffixes)))
(define-advice require (:before-while (feature &optional filename _noerror)
my-ignore-obsolete-compiled)
"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 FEATURE
/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.
M-x list-directory
gives you an editable list, which you can easily change torequire
orload-library
calls. (Anyway, this doesn't answer your question - I was just wondering.)*.elc
files and get Emacs to re-byte-compile them all. I suppose I asked this question more out of curiousity as to if it was possible rather than needing a solution..elc
files seems excessive. You can list all the.elc
files which do not have a corresponding.el
file with something likefind . -regex ".*.elc?" | sed 's/\.elc\?//' | sort | uniq -u | sed 's/$/.elc/' | xargs find 2>/dev/null