λ

Autoload Manual

Table of Contents

[in package AUTOLOAD]

λ

1 Links and Systems

Here is the official repository and the HTML documentation for the latest version.

λ

2 Introduction

Libraries often choose to limit dependencies, even if it means sacrificing features or duplicating code, to minimize

This library mitigates the first two issues by loading heavy dependencies on demand. The core idea is

(defmacro autoload (name asdf-system)
  `(defun ,name (&rest args)
     (asdf:load-system ,asdf-system)
     (apply ',name args)))

Suppose we have a library called my-lib that autoloads my-lib/full. In my-lib, we could use autoload as

(autoload foo "my-lib/full")

and have

(defun foo (x)
  "doc"
  (1+ x))

in my-lib/full.

However, manually keeping the loaddefs (e.g. the autoload form above) in sync with the definitions is fragile, so we introduce the defun/auto autodef to mark autoloaded functions in the my-lib/full system:

(defun/auto foo (x)
  "doc"
  (1+ x))


ASDF Integration

To generate loaddefs, we add a few lines to the system definitions:

(asdf:defsystem "my-lib"
  :defsystem-depends-on ("autoload")
  :class "autoload:autoload-system"
  :auto-depends-on ("my-lib/full")
  :auto-loaddefs "loaddefs.lisp"
  :components ((:file "loaddefs")
               ...))
(asdf:defsystem "my-lib/full"
  :defsystem-depends-on ("autoload")
  :class "autoload:autoload-system"
  :components (...))

Then, the loaddefs can be extracted:

(extract-loaddefs "my-lib")
=> ((autoload foo "my-lib/full" :arglist "(x)" :docstring "doc"))

This is implemented by loading the :auto-depends-on of my-lib and recording defun/autos. extract-loaddefs is a low-level utility used by record-loaddefs, which writes its results to the system's :auto-loaddefs, "loaddefs.lisp" in the above example. So, all we need to do is call record-loaddefs to regenerate the loaddefs file:

(record-loaddefs "my-lib")

To prevent the loaddefs file from getting out of sync with the definitions, asdf:test-system calls check-loaddefs by default.

ASDF, and by extension Quicklisp, doesn't know about the declared :auto-depends-on, so (ql:quickload "my-lib") does not install the autoloaded dependencies. They can be installed manually with

(autodeps "my-lib" :installer #'ql:quickload)

If all the autoloaded dependencies are installed, one can eagerly load them to ensure that autoloading is not triggered later (e.g. in deployment):

(map nil #'asdf:load-system (autodeps "my-lib"))


Other Features

Autoloading is not only for Functions:

λ

3 Basics

λ

3.1 Loading Systems

Function and class loaddefs trigger the loading of asdf:systems. Unlike normal ASDF dependencies (declared in :depends-on), autoload dependencies (which may be declared in :auto-depends-on) are allowed to be circular. The rules for loading are as follows.

  1. It is an autoload-error if loading is triggered during compile time or during a load of either a source file or a compiled file. This is to prevent infinite autoload recursion.

  2. It is an autoload-error if the system does not exist.

  3. The system is loaded under with-compilation-unit :override t and with-standard-io-syntax but with *print-readably* nil. Other non-portable measures may be taken to standardize the dynamic environment. Errors signalled during the load are not handled or resignalled by the Autoload library.

  4. It is an autoload-error if the loaddef is not replaced by a normal definition or deleted by the loaded system, that is, when it remains a loaddef (e.g. in terms of loaddef-function-p).

λ

3.2 Conditions

λ

3.3 Functions

λ

3.4 Classes

λ

3.5 Variables

λ

3.6 Packages

λ

4 ASDF Integration

λ

4.1 Automatically Generating Loaddefs