Most EmacsLisp libraries run faster when byte-compiled, so you’ll usually want to ensure that the libraries you use are byte-compiled. The EmacsLispIntro has this to say on ByteCompilation:
- “As a practical matter, for most things you might do to customize or extend Emacs, you do not need to byte compile. See 'Byte Compilation' in the GNU Emacs Lisp Reference Manual, for a full description.”
The ElispManual says little on being earnest about byte compilation. If you are an EmacsNewbie, then these are good rules of thumb:
- Use byte-compiled versions of third-party libraries, that is, libraries that were not part of an Emacs distribution. A library that should not be byte-compiled will use a local-variable declaration to preveent byte-compilation:
;; -*-no-byte-compile: t; -*-
- Use byte-compiled versions of Emacs-distribution libraries – this will be the case, by default. Most of the libraries distributed with Emacs and XEmacs are byte-compiled.
- Don’t bother to byte-compile code that you write yourself, unless it is complex (in which case you are probably not an EmacsNewbie). It usually won’t hurt to byte-compile your code, but it usually won’t speed things up much either.
You can byte-compile any EmacsLisp source file using the command ‘byte-compile-file’
. For example with Emacs-Lisp you do:
(byte-compile-file "foo.el")
EmacsLisp source files have extension `.el
’. Byte-compiled files have extension `.elc
’. If both source and byte-compiled files are present for the same library at the same place in your ‘load-path’
, Emacs will load the byte-compiled file, not the source file.
This can be a source of confusion. If you change a source file, but don’t remember to byte-compile it again, then Emacs might load the out-of-date byte-compiled file instead of the newer source file. Emacs warns you about this, but you might miss the warning message.
A good way to prevent this is to get in the habit of using command ‘byte-recompile-directory’
to byte-compile all source files that are newer than their byte-compiled versions. This command will only byte-compile files that already have a byte-compiled version unless you provide it with the flag 0
.
Here it is an example of Emacs-Lisp code using such a function:
(byte-recompile-directory ".")
(byte-recompile-directory "." 0)
AutoAsyncByteCompile compiles modified *.el with batch-byte-compile automatically.
If you want to know whether a function call will be replaced by something different in byte-compiled files, you can use ‘M-x apropos’
– for example, ‘M-x apropos mapcar’
. One of the results returned will be ‘mapcar’
itself. You’ll see that it has a ‘Plist’
(property list) with an entry ‘byte-compile’
. The information stored in that entry is used by the byte-compiler.
For a way to make Emacs byte-compile and load updated `.el
’ files automatically , see AutoRecompile.
Emacs and XEmacs
Emacs and XEmacs (GnuEmacs, XEmacs) may barf on byte-compiled files that they didn’t byte-compile themselves. You need to store the compiled files in two different directories, and then you need to add to appropriate directory to your load-path (LoadPath) depending on which emacsen you are running.
Example: Compile files with Emacs and put the .elc files in ~/elisp/compiled-emacs, compile with XEmacs and put the .elc files in ~/elisp/compiled-xemacs, then add to your init file (if you share it):
(if (featurep 'xemacs)
(add-to-list 'load-path "~/elisp/compiled-xemacs")
(add-to-list 'load-path "~/elisp/compiled-emacs"))
You might be wondering how to “put the .elc files in …”. Try redefining byte-compile-dest-file in bytecomp.el.
Discussion
Debian has a pretty elaborate infrastructure for this. Essentially, you have a site_start.el which modifies the load-path depending on what flavor of Emacs you are starting up. – EraEriksson
Hmm… if you do it with load-path, then when you save a . el from emacs, compile it, then run xemacs, you will load an older, incompatible xemacs .elc. 😟
IMHO load, load-library, and require need to be modified to check for .el newer than .elc, even if they are in different directories. (The best solution is to do optional compilation during loading, not after saving.) Unless I am mistaken, this does not happen even in debian. --wayestuncool@yahoo
Discussion on WishList
This was discussion originally on WishList.
- Why not make compiled file naming let people use both editors without having to recompile their personal libraries in between?
- See CompiledFile for the manual solution.
- Well, I changed that to say what function to redefine, but we still don’t have a solution. I think that load-path will cause emacs to blithely load a .elc even if the .el is newer (such as might happen if you happened to have edited it and compiled in xemacs) and vice-versa. So I think that load-path processing needs changing to check modtimes. Am I right? A preliminary experiment suggests so. --wayestuncool
- CompiledFile explains how to set your load-path depending on Emacs or XEmacs. It should work without any further problem. If you want automatic recompilation for both editors when you change the source, then you can always do that for your local files – but often enough local files need no compilation in the first place. And for files distributed with Emacs and XEmacs, distributions such as Debian solve this problem for you. So why fix it in the editors? – AlexSchroeder
- Because when you edit myfile.el, then compile it in emacs, then edit it, then compile it in xemacs, then load it in emacs, you will get the out of date myfile.elc. The CompiledFile solutions do not address this. (My note there does but I have no code. The best solution is to do optional compilation during loading, not after saving.)
- The CompiledFile page has no solution for it. I am not sure wether the best solution is optional compilation during loading. Have you tested it? Accessing files might be even slower than compiling always – ie. just load the source files. Anyway, I do not think that this is a problem Emacs developpers should worry about, there are more important features that need work. -- AlexSchroeder
- I disagree that it’s unimportant. By optional I should have said configurable with one option to compile if the source file is newer for that version of emacs. Or you can compile always (if that makes sense) or never (presumably the default). That is what I meant, but I can see how it looked like I was saying something else. I meant to emphasize loading not saving. --wayestuncool
- I’ve written and tested several automatic compiling and/or dumping mechanisms for both emacsen and CL, including compiling on loading. I just don’t have any code suitable for this case. All my code is many years old as I have not used emacsen in many years and am just starting to use them again. Thus I cannot contribute; also since I am just getting speech recognition set up and cannot do any coding until it is, and because I am out of touch with the last n years of changes. BTW, the elephant in the room that I see after my absence is the continued incompatibility between xemacs and emacs. YMMV of course. --wayestuncool
- The background to this is that emacs and xemacs are very similar but speciating inexorably. In general, when two things in software are very similar, they should normally be made the same, even if only by abstracting away the differences, unless the goal is to split completely. By making it easy for people to experiment with code that works with both, we can delay the user’s need to choose which packages to do without. To me, this is the highest priority after fixing major bugs in each version. --wayestuncool
- In my case, I need vr-mode.el (speech recognition) to work with both emacs and xemacs but it does not. By providing a seamless compilation system, which would be easy to write, we can help prevent this type of situation, even if only a little by encouraging people who develop slow libraries to keep supporting both because it is easier. This helps even packages that do not need compilation because a developer will be more likely to keep them portable also. --wayestuncool
- Of course, portability between the two versions (or for one version to "win" undisputably so that portability is not necessary) is the real issue, for the sake of such issues as keeping vr-mode usable. --wayestuncool
- This is a pretty odd point of view…
- Why not replace the current default extension for compiled files (.elc) with .ele for emacs and .elx for xemacs so that people can use both editors without having to recompile their personal libraries in between? (wayestuncool.)
Stack traces and compiled files
If you are running code from .elc files and you get an error, the backtrace will show byte-compiled code. You might see strange control codes like:
Debugger entered--Lisp error: (scan-error "Unbalanced parentheses" 1 2)
scan-lists(1 1 -1)
down-list(1)
byte-code("\300\301\302!\210\207" [t down-list 1] 3)
pp-buffer()
pp-to-string(t)
pp(t)
...
In order to get better stack traces and provide useful information to developers, try to reproduce the same error using only the .el file. Then you will see more function calls in place of the strange codes.
TODO: how can you tell Emacs to always prefer loading .el files over loading .elc? I expected a command line flag to do that. – DanielClemente
Bug #2061 (EmacsBugs) was filed about that; thanks.
CategoryCode ComparativeEmacsology