This library aims to provide a starting point from which one can create ASDF system classes similar to package-inferred-system, i.e. systems that are implicitly inferred based on naming conventions, file layout or certain forms.
Currently a few systems are provided for demonstration purposes. They are described below.
The system requires-system
(a subclass of asdf:system
) works a bit like package-inferred-system, except that instead of determining dependencies from defpackage
or define-package
forms like package-inferred-system, it looks for forms like (requires :alexandria "package" "util")
. Symbols indicate “normal” dependencies, while strings indicate “relative” dependencies whose names are computed based on the location of the current file. In addition, if a dependency signifies a directory, then it is assumed that the directory contains a lisp file with the same name as the directory (i.e. foo/foo.lisp
). It’s worth noting that this system does not care about packages like package-inferred-system does, it only cares about files. In other words, it does not require that the source files follow one-package-per-file style.
A requires-system
(file or directory) may be loaded normally with ASDF. For example, if we have a lisp file called start-server.lisp
or a directory called start-server
in the same directory as the system definition file my-app.asd
, then it can be loaded (along with its dependencies) by calling:
(asdf:load-system "my-app/start-server")
To better illustrate how it works, suppose we have a project with the following files:
- my-lib.asd
- package.lisp
- utils.lisp
- my-lib.lisp
- module/
- module.lisp
- module-utils.lisp
Then the contents of each file could look like this:
- my-lib.asd
(asdf:defsystem #:my-lib
:defsystem-depends-on ("extensible-inferred-system")
:class "extensible-inferred-system:requires-system")
- package.lisp
(defpackage :my-lib ...)
- utils.lisp
(extensible-inferred-system:requires :alexandria "package")
(in-package :my-lib)
...
- my-lib.lisp
(extensible-inferred-system:requires :hunchentoot
:cl-who
"package"
"utils"
"module")
(in-package :my-lib)
...
- module/module.lisp
(extensible-inferred-system:requires :my-lib/package "module-utils")
(in-package :my-lib)
...
- module/module-utils.lisp
(extensible-inferred-system:requires :cl-ppcre)
(defpackage :my-lib-module-utils (:use :cl))
(in-package :my-lib-module-utils)
...
This system is a subclass of requires-system
and behaves in a similar way, except that dependencies are specified in a comment at the beginning of a file. The format of the comment is requires dep1 dep2 ...
and it may be a single line, or it may span multiple lines. A non-comment line ends the dependency specification. A different initial symbol (instead of requires
) may be specified with the initarg :initial-symbol-name
. It should be a string, and will be read-from-string
into a temporary package. Lines containing certain strings can be ignored with the :ignore-lines
initarg. The argument should be a string or a list of strings. Its main use is to skip lines with Emacs file local variables (-*-
).
Example:
;;;; Requires
;;;;
;;;; alexandria
;;;; cl-ppcre
;;;; my-app/some/module
;;;; "package"
;;;; "util/logging"
;;;; "util/strings"
(in-package :my-app)
...
In order to use this system class, create an asd file like this in your source directory:
(asdf:defsystem #:my-app
:defsystem-depends-on ("extensible-inferred-system")
:class "extensible-inferred-system:comment-system"
:ignore-lines "-*-" ; Optional
:initial-symbol-name "dependencies") ; Optional, default is "requires".
This system is also a subclass of requires-system
and behaves in a similar way, except that dependencies are specified with a quote
form at the beginning of a file.
Example:
(quote (:alexandria
:cl-ppcre
:my-app/some/module
"package"
"util/logging"
"util/strings"))
(in-package :my-app)
...
In order to use this system class, create an asd file like this in your source directory:
(asdf:defsystem #:my-app
:defsystem-depends-on ("extensible-inferred-system")
:class "extensible-inferred-system:quote-system")
This system is also a subclass of requires-system
and behaves in a similar way, except that dependencies are specified with the reader conditional expression #+requires (...)
at the beginning of a file. It is assumed that no such feature is normally present. In order to recognize whether no dependencies have been specified, the system will look for the reader conditional “#+requires” at the beginning of the file before attempting to extract dependencies. A different feature expression may be specified with the initarg :feature-expression
. The argument should be a string, and will be read-from-string
with *package*
bound to the keyword package (so ~”FOO”~ becomes :FOO
).
Initial comment lines will be skipped by default. If comments should not be skipped, the initarg :skip-comments nil
can be used.
Example:
#+requires (:alexandria
:cl-ppcre
:my-app/some/module
"package"
"util/logging"
"util/strings")
(in-package :my-app)
...
In order to use this system class, create an asd file like this in your source directory:
(asdf:defsystem #:my-app
:defsystem-depends-on ("extensible-inferred-system")
:class "extensible-inferred-system:feature-system"
:feature-expression "dependencies") ; optional