Next: Other code in .asd files, Previous: A more involved example, Up: Defining systems with defsystem
system-definition := ( defsystem system-designator option* ) option := :components component-list | :pathname pathname-specifier | :default-component-class | :perform method-form | :explain method-form | :output-files method-form | :operation-done-p method-form | :depends-on ( dependency-def* ) | :serial [ t | nil ] | :in-order-to ( dependency+ ) component-list := ( component-def* ) component-def := ( component-type simple-component-name option* ) component-type := :system | :module | :file | :static-file | other-component-type other-component-type := symbol-by-name (see Component types) dependency-def := simple-component-name | ( :feature name ) | ( :version simple-component-name version-specifier) dependency := (dependent-op requirement+) requirement := (required-op required-component+) | (feature feature-name) dependent-op := operation-name required-op := operation-name | feature simple-component-name := string | symbol pathname-specifier := pathname | string | symbol method-form := (operation-name qual lambda-list &rest body) qual := method qualifier
Component names (simple-component-name
)
may be either strings or symbols.
Component type names, even if expressed as keywords, will be looked up
by name in the current package and in the asdf package, if not found in
the current package. So a component type my-component-type
, in
the current package my-system-asd
can be specified as
:my-component-type
, or my-component-type
.
A pathname specifier (pathname-specifier
)
may be a pathname, a string or a symbol.
When no pathname specifier is given for a component,
which is the usual case, the component name itself is used.
If a string is given, which is the usual case,
the string will be interpreted as a Unix-style pathname
where /
characters will be interpreted as directory separators.
Usually, Unix-style relative pathnames are used
(i.e. not starting with /
, as opposed to absolute pathnames);
they are relative to the path of the parent component.
Finally, depending on the component-type
,
the pathname may be interpreted as either a file or a directory,
and if it's a file,
a file type may be added corresponding to the component-type
,
or else it will be extracted from the string itself (if applicable).
For instance, the component-type
:module
wants a directory pathname, and so a string "foo/bar"
will be interpreted as the pathname #p"foo/bar/".
On the other hand, the component-type
:file
wants a file of type lisp
, and so a string "foo/bar"
will be interpreted as the pathname #p"foo/bar.lisp",
and a string "foo/bar.quux"
will be interpreted as the pathname #p"foo/bar.quux.lisp".
Finally, the component-type
:static-file
wants a file without specifying a type, and so a string "foo/bar"
will be interpreted as the pathname #p"foo/bar",
and a string "foo/bar.quux"
will be interpreted as the pathname #p"foo/bar.quux".
If a symbol is given, it will be translated into a string,
and downcased in the process.
The downcasing of symbols is unconventional,
but was selected after some consideration.
Observations suggest that the type of systems we want to support
either have lowercase as customary case (Unix, Mac, windows)
or silently convert lowercase to uppercase (lpns),
so this makes more sense than attempting to use :case :common
as argument to make-pathname
,
which is reported not to work on some implementations.
Pathnames objects may be given to override the path for a component.
Such objects are typically specified using reader macros such as #p
or #.(make-pathname ...)
.
Note however, that #p...
is a short for #.(parse-namestring ...)
and that the behavior parse-namestring
is completely non-portable,
unless you are using Common Lisp logical-pathname
s.
(See Warning about logical pathnames, below.)
Pathnames made with #.(make-pathname ...)
can usually be done more easily with the string syntax above.
The only case that you really need a pathname object is to override
the component-type default file type for a given component.
Therefore, it is a rare case that pathname objects should be used at all.
Unhappily, ASDF 1 didn't properly support
parsing component names as strings specifying paths with directories,
and the cumbersome #.(make-pathname ...)
syntax had to be used.
Note that when specifying pathname objects, no magic interpretation of the pathname
is made depending on the component type.
On the one hand, you have to be careful to provide a pathname that correctly
fulfills whatever constraints are required from that component type
(e.g. naming a directory or a file with appropriate type);
on the other hand, you can circumvent the file type that would otherwise
be forced upon you if you were specifying a string.
To use logical pathnames,
you will have to provide a pathname object as a :pathname
specifier
to components that use it, using such syntax as
#p"LOGICAL-HOST:absolute;path;to;component.lisp"
.
You only have to specify such logical pathname for your system or some top-level component, as sub-components using the usual string syntax for names will be properly merged with the pathname of their parent. The specification of a logical pathname host however is not otherwise directly supported in the ASDF syntax for pathname specifiers as strings.
Logical pathnames are not specifically recommended to newcomers,
but are otherwise supported.
Moreover, the asdf-output-translation
layer will
avoid trying to resolve and translate logical-pathnames,
so you can define yourself what translations you want to use
with the logical pathname facility.
The user of logical pathnames will have to configure logical pathnames himself, before they may be used, and ASDF provides no specific support for that.
If the :serial t
option is specified for a module,
ASDF will add dependencies for each each child component,
on all the children textually preceding it.
This is done as if by :depends-on
.
:components ((:file "a") (:file "b") (:file "c")) :serial t
is equivalent to
:components ((:file "a") (:file "b" :depends-on ("a")) (:file "c" :depends-on ("a" "b")))
The :pathname
option is optional in all cases for systems
defined via defsystem
,
and in the usual case the user is recommended not to supply it.
Instead, ASDF follows a hairy set of rules that are designed so that
find-system
will load a system from disk
and have its pathname default to the right place.
*default-pathname-defaults*
(which could be somewhere else altogether)
if the user loads up the .asd file into his editor
and interactively re-evaluates that form.
If a system is being loaded for the first time, its top-level pathname will be set to:
*load-truename*
,
if it is bound.
*default-pathname-defaults*
, otherwise.
If a system is being redefined, the top-level pathname will be
*load-truename*
(so that an updated source location is reflected in the system definition)
*default-pathname-defaults*
*load-truename*
and *load-truename*
is currently unbound
(so that a developer can evaluate a defsystem
form
from within an editor without clobbering its source location)