Next: The defsystem grammar, Previous: The defsystem form, Up: Defining systems with defsystem [Contents][Index]
Let’s illustrate some more involved uses of defsystem
via a
slightly convoluted example:
(in-package :asdf-user) (defsystem "foo" :version (:read-file-form "variables" :at (3 2)) :components ((:file "package") (:file "variables" :depends-on ("package")) (:module "mod" :depends-on ("package") :serial t :components ((:file "utils") (:file "reader") (:file "cooker") (:static-file "data.raw")) :output-files (compile-op (o c) (list "data.cooked")) :perform (compile-op :after (o c) (cook-data :in (component-pathname (find-component c "data.raw")) :out (first (output-files o c))))) (:file "foo" :depends-on ("mod")))) (defmethod action-description ((o compile-op) (c (eql (find-component "foo" "mod")))) "cooking data")
Here are some notes about this example:
foo
.
It also contains other Lisp forms, which we’ll examine below.
:module
component
named "mod"
, which is a collection of three Lisp source files
utils.lisp, reader.lisp, cooker.lisp and data.raw
:static-file
does not have an implicit file type,
unlike the Lisp source files.
:pathname
option in The defsystem grammar).
:serial t
says that each sub-component of mod
depends on the previous components,
so that cooker.lisp depends-on reader.lisp, which depends-on utils.lisp.
Also data.raw depends on all of them, but that doesn’t matter since it’s a static file;
on the other hand, if it appeared first, then all the Lisp files would be recompiled
when the data is modified, which is probably not what is desired in this case.
:output-files (compile-op (o c) (list "data.cooked")) :perform (compile-op :after (o c) (cook-data :in (component-pathname (find-component c "data.raw")) :out (first (output-files o c))))
has the effect of
(defmethod output-files ((o compile-op) (c (eql ...))) (list "data.cooked")) (defmethod perform :after ((o compile-op) (c (eql ...))) (cook-data :in (component-pathname (find-component c "data.raw")) :out (first (output-files o c))))
where ...
is the component in question.
In this case ...
would expand to something like
(find-component "foo" "mod")
For more details on the syntax of such forms, see The defsystem grammar. For more details on what these methods do, see Operations in The Object model of ASDF.
defmethod
with a similar effect,
because ASDF (as of ASDF 3.1.5)
fails to accept inline-methods as above for action-description
,
instead only supporting the deprecated explain
interface.
(in-package :asdf-user)
,
but it is actually redundant, not necessary and not recommended.
But yet more complex cases (also not recommended) may usefully use an in-package
form.
cl:load
,
and neither should you.
You should let ASDF find and load them when you operate on systems.
If you somehow must load a .asd file,
use the same function asdf:load-asd
that ASDF uses.
Among other things, it already binds the *package*
to asdf-user
.
Recent versions of SLIME (2013-02 and later) know to do that when you C-c C-k
when you use the slime-asdf
contrib.
in-package
form
if you’re keeping things simple.
You should only use in-package
(and before it, a defpackage
)
when you’re going to define new classes, functions, variables, macros, etc.,
in the .asd
file, and want to thereby avoid name clashes.
Manuals for old versions of ASDF recommended use of such an idiom in .asd files,
but as of ASDF 3, we recommend that you don’t do that anymore,
and instead define any ASDF extensions in their own system,
on which you can then declare a dependency using :defsystem-depends-on
.
See The defsystem grammar.
asdf
, common-lisp
and uiop
being available in .asd
files —
most importantly including defsystem
.
It is therefore redundant and in bad taste to use a package-prefixed asdf:defsystem
symbol
in a .asd file.
Just use (defsystem ...)
.
Only package-prefix it when somehow dynamically generating system definitions
from a package that doesn’t already use the ASDF package.
asdf-user
is actually only available starting since ASDF 3, but then again,
ASDF 1 and 2 did crazy things with packages that ASDF 3 has stopped doing9,
and since all implementations provide ASDF 3, you shouldn’t care about compatibility with ASDF 2.
We do not support ASDF 2 anymore, and we recommend that neither should you.
asdf-user
uses uiop
,
whereas in earlier variants of ASDF 3 it only used uiop/package
.
We recommend you either prefix use of UIOP functions with the package prefix uiop:
,
or make sure your system :depends-on ((:version "asdf" "3.1.2"))
or has a #-asdf3.1 (error "MY-SYSTEM requires ASDF 3.1.2")
.
(defparameter *foo-version* "5.6.7")
.
ASDF 1 and 2 (up until 2.26)
used to dynamically create and delete temporary packages asdfN
,
one for each .asd file, in a misguided attempt to thereby reduce name clashes;
but it failed at that goal and only made things more complex.
ASDF 3 just uses a shared package asdf-user
instead,
and relies on the usual Common Lisp conventions to avoid clashes.
As far as package oddities go, you may just notice that
the asdf-user
package also uses uiop/common-lisp
,
a variant of the common-lisp
package that papers over
deficiencies in more obscure Common Lisp implementations;
but unless you care about Corman Lisp, GCL, Genera or MCL, you shouldn’t be concerned.
Next: The defsystem grammar, Previous: The defsystem form, Up: Defining systems with defsystem [Contents][Index]