Emacs Lisp offers an autoloading mechanism to load libraries on demand. Typically this is used to make interactive commands available to the user without entirely loading the corresponding library upfront. This article explores how autoloads work and how Emacs Lisp packages use autoloads to improve load speed.
The autoload function creates autoloads, for instance for the function
magit-status from Magit:
(autoload 'magit-status "magit" "Open a Magit status buffer […]" t nil)
Evaluating this expression tells Emacs to automatically load the library
magit-status is called for the first
time—either from Lisp, or interactively with
M-x magit-status. You can
manually add autoloads to your
init.el yourself to autoload 3rd party
libraries. In the old days before package.el, this was a common pattern.
Note the emphasis on evaluation. Merely writing this expression somewhere doesn’t create any autoloads. Emacs must evaluate it, which comes down to Emacs loading a file with this expression.
It doesn’t make any sense to put autoloads into the same file that has the actual definition of the autoloaded function. Emacs would load the rest of the file as well and thus make the definition available right away, leading the purpose of autoloads ad absurdum.
Autoloads should be in a separate file containing only autoloads and nothing else to make it load fast. Emacs calls such files “autoload files”.
Maintaining autoload files manually to keep them in sync with the actual definitions in the library file is tiresome and error-prone so Emacs allows to automate this process with update-file-autoloads and update-directory-autoloads.
update-file-autoloads inspects the source files for special comments called
“autoload cookies”. These cookies let you declare autoloads right at the
corresponding definition. An autoload cookie for
magit-status looks like
;;;###autoload (defun magit-status () "Open a Magit status buffer […]" (interactive) ;; … )
For each such cookie
update-file-autoloads generates a corresponding
autoload like the one shown above, and writes it to the autoload file.
update-directory-autoloads performs this process for all files in a directory.
These commands only generate autoload files. You still need to load the generated files explicitly to make their autoloads available.
If an autoload cookie occurs on an expression with no special support for
update-file-autoloads copies the expression verbatim. This is
used to register libraries in specific Emacs extension points, like
Emacs’ package manager
package.el goes a step further and automatically
generates autoloads files during package installation—internally it simply calls
update-directory-autoloads. This relieves package maintainers from the
tedious work of manually updating autoload files and including them in their
packages, and enables autoloads even for single-file packages1.
package-initialize automatically loads autoloads files of all
installed packages to make all autoloads available.
What to autoload?
The general rule is to autoload interactive “entry points” of a package. Examples of interactive entry points include:
- definitions of major and minor modes,
- interactive commands by which a user would start to use a specific package
- and interactive commands which offer generic utilities, e.g.
If your package just provides a library for use in Emacs Lisp code (e.g. like
dash.el or s.el) you should not add any autoloads at all. Libraries are
requiredd by dependent libraries so autoloads would be redundant.
If your package should automatically register itself in specific Emacs extension
points you should add autoloads for these as well to make sure that they are
evaluated during package initialization. A typical example is adding a mode to
;;;###autoload (add-to-list 'auto-mode-alist '("\\.pp\\'" . puppet-mode))
auto-mode-alist when Emacs starts, so that Puppet
Mode is automatically used for all files ending in
Likewise, colour themes use autoload cookies to add themselves to the color theme search path:
;;;###autoload (when (and (boundp 'custom-theme-load-path) load-file-name) (add-to-list 'custom-theme-load-path (file-name-as-directory (file-name-directory load-file-name))))
Emacs Lisp API for autoloads
Emacs Lisp has some functions to work with autoloads. In addition to autoload to create autoloads, there are autoloadp and autoload-do-load. The first lets you check whether an object is an autoload object, and the latter loads the underlying library of an autoload.
Both functions work on autoload objects, and not on symbols with attached
(autoloadp 'foo) checks whether the symbol
autoloaded, which it isn’t. Symbols are not loaded at all, they are either
directly created by the reader, or explicitly with intern.
To check whether
foo refers to an autoloaded function you need to check the
function definition of
(autoloadp (function-definition 'foo))
Single file packages are standalone Emacs Lisp files with special file headers. ↩︎