Update to asdf-3.3.3

parent e8c243e8
\input texinfo @c -*- texinfo -*- \input texinfo @c -*- mode: texinfo; coding: utf-8 -*-
@c %**start of header @c %**start of header
@documentencoding UTF-8
@setfilename asdf.info @setfilename asdf.info
@settitle ASDF Manual @settitle ASDF Manual
@syncodeindex tp fn
@c %**end of header @c %**end of header
@c We use @&key, etc to escape & from TeX in lambda lists -- @c We use @&key, etc to escape & from TeX in lambda lists --
...@@ -36,11 +36,11 @@ for Common Lisp programs and libraries. ...@@ -36,11 +36,11 @@ for Common Lisp programs and libraries.
You can find the latest version of this manual at You can find the latest version of this manual at
@url{https://common-lisp.net/project/asdf/asdf.html}. @url{https://common-lisp.net/project/asdf/asdf.html}.
ASDF Copyright @copyright{} 2001-2016 Daniel Barlow and contributors. ASDF Copyright @copyright{} 2001-2019 Daniel Barlow and contributors.
This manual Copyright @copyright{} 2001-2016 Daniel Barlow and contributors. This manual Copyright @copyright{} 2001-2019 Daniel Barlow and contributors.
This manual revised @copyright{} 2009-2016 Robert P. Goldman and Francois-Rene Rideau. This manual revised @copyright{} 2009-2019 Robert P. Goldman and Francois-Rene Rideau.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the
...@@ -65,7 +65,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ...@@ -65,7 +65,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@titlepage @titlepage
@title ASDF: Another System Definition Facility @title ASDF: Another System Definition Facility
@subtitle Manual for Version 3.3.2 @subtitle Manual for Version 3.3.3
@c The following two commands start the copyright page. @c The following two commands start the copyright page.
@page @page
@vskip 0pt plus 1filll @vskip 0pt plus 1filll
...@@ -82,7 +82,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ...@@ -82,7 +82,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@node Top, Introduction, (dir), (dir) @node Top, Introduction, (dir), (dir)
@top ASDF: Another System Definition Facility @top ASDF: Another System Definition Facility
@ifnottex @ifnottex
Manual for Version 3.3.2 Manual for Version 3.3.3
@end ifnottex @end ifnottex
...@@ -105,9 +105,9 @@ Manual for Version 3.3.2 ...@@ -105,9 +105,9 @@ Manual for Version 3.3.2
* Ongoing Work:: * Ongoing Work::
* Bibliography:: * Bibliography::
* Concept Index:: * Concept Index::
* Function and Class Index:: * Function and Macro Index::
* Variable Index:: @c @detailmenu * Variable Index:: @c @detailmenu
@c * Class and Type Index:: @c
@detailmenu @detailmenu
--- The Detailed Node Listing --- --- The Detailed Node Listing ---
...@@ -281,7 +281,7 @@ ASDF development FAQs ...@@ -281,7 +281,7 @@ ASDF development FAQs
@cindex :asdf2 @cindex :asdf2
@cindex :asdf3 @cindex :asdf3
ASDF is Another System Definition Facility: ASDF, or Another System Definition Facility, is a @emph{build system}:
a tool for specifying how systems of Common Lisp software a tool for specifying how systems of Common Lisp software
are made up of components (sub-systems and files), are made up of components (sub-systems and files),
and how to operate on these components in the right order and how to operate on these components in the right order
...@@ -308,8 +308,8 @@ it plays a role like @code{make} or @code{ant}, not like a package manager. ...@@ -308,8 +308,8 @@ it plays a role like @code{make} or @code{ant}, not like a package manager.
In particular, ASDF should not to be confused with Quicklisp or ASDF-Install, In particular, ASDF should not to be confused with Quicklisp or ASDF-Install,
that attempt to find and download ASDF systems for you. that attempt to find and download ASDF systems for you.
Despite what the name might suggest, Despite what the name might suggest,
ASDF-Install was never a part of ASDF, it was a separate piece of software. ASDF-Install was never a part of ASDF; it was always a separate piece of software.
ASDF-Install is also unmaintained and obsolete. ASDF-Install has also been unmaintained and obsolete for a very long time.
We recommend you use Quicklisp We recommend you use Quicklisp
(@uref{http://www.quicklisp.org/}) instead, (@uref{http://www.quicklisp.org/}) instead,
a Common Lisp package manager which works well and is being actively maintained. a Common Lisp package manager which works well and is being actively maintained.
...@@ -934,15 +934,17 @@ ASDF hooks into the @code{cl:require} facility and you can just use: ...@@ -934,15 +934,17 @@ ASDF hooks into the @code{cl:require} facility and you can just use:
(require :@var{foo}) (require :@var{foo})
@end example @end example
Note that the canonical name of a system is a string, conventionally lowercase. Note that the canonical name of a system is a string, in @emph{lowercase}.
A system name can also be specified as a symbol (including a keyword), System names can also be specified as symbols (including keyword
in which case its @code{symbol-name} is taken and lowercased. symbols).
If a symbol is given as argument, its package is ignored,
its @code{symbol-name} is taken, and converted to lowercase.
The name must be a suitable value for the @code{:name} initarg The name must be a suitable value for the @code{:name} initarg
to @code{make-pathname} in whatever filesystem the system is to be found. to @code{make-pathname} in whatever filesystem the system is to be found.
The lower-casing-symbols behaviour is unconventional, Using lowercase as canonical is unconventional,
but was selected after some consideration. but was selected after some consideration.
The type of systems we want to support The type of file systems we support
either have lowercase as customary case (Unix, Mac, Windows) either have lowercase as customary case (Unix, Mac, Windows)
or silently convert lowercase to uppercase (lpns). or silently convert lowercase to uppercase (lpns).
@c so this makes more sense than attempting to use @code{:case :common}, @c so this makes more sense than attempting to use @code{:case :common},
...@@ -1001,18 +1003,13 @@ compiling, loading and testing. ...@@ -1001,18 +1003,13 @@ compiling, loading and testing.
@c FIXME: the following is too complicated for here, especially since @c FIXME: the following is too complicated for here, especially since
@c :force hasn't been defined yet. Move it. [2014/02/27:rpg] @c :force hasn't been defined yet. Move it. [2014/02/27:rpg]
@vindex *load-system-operation*
@findex already-loaded-systems @findex already-loaded-systems
@defun load-system system @Arest{} keys @Akey{} force force-not verbose version @AallowOtherKeys{} @defun load-system system @Arest{} keys @Akey{} force force-not verbose version @AallowOtherKeys{}
Apply @code{operate} with the operation from Apply @code{operate} with the operation @code{load-op}, the
@code{*load-system-operation*} @var{system}, and any provided keyword arguments. Calling
the @var{system}, and any provided keyword arguments. @code{load-system} is the regular, recommended way to load a system
@code{*load-system-operation*} by default is @code{load-op}; into the current image.
it would be @code{load-bundle-op} by default on ECL,
if only an implementation bug were fixed.
Calling @code{load-system} is the regular, recommended way
to load a system into the current image.
@end defun @end defun
@defun compile-system system @Arest{} keys @Akey{} force force-not verbose version @AallowOtherKeys{} @defun compile-system system @Arest{} keys @Akey{} force force-not verbose version @AallowOtherKeys{}
...@@ -1039,7 +1036,7 @@ The default behaviour is to load the system as if by @code{load-system}; ...@@ -1039,7 +1036,7 @@ The default behaviour is to load the system as if by @code{load-system};
but system authors can override this default in their system definition but system authors can override this default in their system definition
they may specify an alternate operation as the intended use of their system, they may specify an alternate operation as the intended use of their system,
with a @code{:build-operation} option in the @code{defsystem} form with a @code{:build-operation} option in the @code{defsystem} form
(@pxref{The defsystem grammar, build-operation}), (@pxref{Build-operation}),
and an intended output pathname for that operation with and an intended output pathname for that operation with
@code{:build-pathname}. @code{:build-pathname}.
@c Document :build-operation in the defsystem section. @c Document :build-operation in the defsystem section.
...@@ -1192,7 +1189,7 @@ especially if you intend your software to be eventually included in Quicklisp. ...@@ -1192,7 +1189,7 @@ especially if you intend your software to be eventually included in Quicklisp.
@item @item
Make sure you know how the @code{:version} numbers will be parsed! Make sure you know how the @code{:version} numbers will be parsed!
Only period-separated non-negative integers are accepted at present. Only period-separated non-negative integers are accepted at present.
See below Version specifiers in @ref{The defsystem grammar}. @xref{Version specifiers}.
@item @item
This file contains a single form, the @code{defsystem} declaration. This file contains a single form, the @code{defsystem} declaration.
...@@ -1273,7 +1270,7 @@ see the discussion of the @code{:pathname} option in @ref{The defsystem grammar} ...@@ -1273,7 +1270,7 @@ see the discussion of the @code{:pathname} option in @ref{The defsystem grammar}
@item @item
The @code{:serial t} says that each sub-component of @code{mod} depends on the previous components, The @code{:serial t} says that each sub-component of @code{mod} depends on the previous components,
so that @file{cooker.lisp} depends-on @file{utils.lisp}, which depends-on @file{reader.lisp}. so that @file{cooker.lisp} depends-on @file{reader.lisp}, which depends-on @file{utils.lisp}.
Also @file{data.raw} depends on all of them, but that doesn't matter since it's a static file; Also @file{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 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. when the data is modified, which is probably not what is desired in this case.
...@@ -1424,11 +1421,19 @@ Presumably, the 4th form looks like @code{(defparameter *foo-version* "5.6.7")}. ...@@ -1424,11 +1421,19 @@ Presumably, the 4th form looks like @code{(defparameter *foo-version* "5.6.7")}.
@example @example
system-definition := ( defsystem system-designator @var{system-option}* ) system-definition := ( defsystem system-designator @var{system-option}*)
system-designator := simple-component-name | complex-component-name
simple-component-name := lower-case string | symbol
NOTE: Underscores are not permitted. See below.
complex-component-name := string | symbol
See below.
system-option := :defsystem-depends-on system-list system-option := :defsystem-depends-on system-list
| :weakly-depends-on @var{system-list} | :weakly-depends-on @var{system-list}
| :class class-name (see discussion below) | :class class-name # @pxref{System class names}
| :build-operation @var{operation-name} | :build-operation @var{operation-name}
| system-option | system-option
| module-option | module-option
...@@ -1441,6 +1446,7 @@ system-option := :homepage string ...@@ -1441,6 +1446,7 @@ system-option := :homepage string
| :long-name string | :long-name string
| :source-control source-control | :source-control source-control
| :version version-specifier | :version version-specifier
| :entry-point object # @pxref{Entry point}
source-control := (keyword string) source-control := (keyword string)
...@@ -1468,13 +1474,13 @@ component-def := ( component-type simple-component-name @var{option}* ) ...@@ -1468,13 +1474,13 @@ component-def := ( component-type simple-component-name @var{option}* )
component-type := :module | :file | :static-file | other-component-type component-type := :module | :file | :static-file | other-component-type
other-component-type := symbol-by-name other-component-type := symbol-by-name
(@pxref{The defsystem grammar,,Component types}) # @pxref{Component types}
# This is used in :depends-on, as opposed to ``dependency,'' # This is used in :depends-on, as opposed to ``dependency,''
# which is used in :in-order-to # which is used in :in-order-to
dependency-def := simple-component-name dependency-def := simple-component-name
| ( :feature @var{feature-expression} dependency-def ) | ( :feature @var{feature-expression} dependency-def )
# (@pxref{The defsystem grammar,,Feature dependencies}) # @pxref{Feature dependencies}
| ( :version simple-component-name version-specifier ) | ( :version simple-component-name version-specifier )
| ( :require module-name ) | ( :require module-name )
...@@ -1489,6 +1495,10 @@ simple-component-name := string ...@@ -1489,6 +1495,10 @@ simple-component-name := string
| symbol | symbol
pathname-specifier := pathname | string | symbol pathname-specifier := pathname | string | symbol
NOTE: pathnames should be all lower case, and have no
underscores, although hyphens are permitted.
version-specifier := string version-specifier := string
| (:read-file-form <pathname-specifier> <form-specifier>?) | (:read-file-form <pathname-specifier> <form-specifier>?)
...@@ -1497,7 +1507,8 @@ line-specifier := :at integer # base zero ...@@ -1497,7 +1507,8 @@ line-specifier := :at integer # base zero
form-specifier := :at [ integer | ( integer+ )] form-specifier := :at [ integer | ( integer+ )]
method-form := (operation-name qual lambda-list @Arest{} body) method-form := (operation-name qual lambda-list @Arest{} body)
qual := method qualifier? qual := method-qualifier?
method-qualifier = :before | :after | :around
feature-expression := keyword feature-expression := keyword
| (:and @var{feature-expression}*) | (:and @var{feature-expression}*)
...@@ -1505,13 +1516,53 @@ feature-expression := keyword ...@@ -1505,13 +1516,53 @@ feature-expression := keyword
| (:not @var{feature-expression}) | (:not @var{feature-expression})
@end example @end example
@subsection System designators
System designators are either simple component names, or
complex (``slashy'') component names.
@subsection Simple component names (@code{simple-component-name})
Simple component names may be written as either strings or symbols.
When using strings, use lower case exclusively.
Symbols will be interpreted as convenient shorthand for the string
that is their @code{symbol-name}, converted to lower case. Put
differently, a symbol may be a simple component name @emph{designator},
but the simple component name itself is the string.
@subsection Component names @strong{Never} use underscores in component names, whether written as
strings or symbols.
Component names (@code{simple-component-name}) @strong{Never} use slashes (``/'') in simple component names. A slash
may be either strings or symbols. indicates a @emph{complex} component name; see below. Using a slash
improperly will cause ASDF to issue a warning.
Violating these constraints by mixing case, or including underscores in
component names, may lead to systems or components being impossible to
find, because component names are interpreted as file names. These
problems will @emph{definitely} occur for users who have configured ASDF
using logical pathnames.
@subsection Complex component names
A complex component name is a master name followed by a slash, followed
by a subsidiary name. This allows programmers to put multiple system
definitions in a single @code{.asd} file, while still allowing ASDF to
find these systems.
The master name of a complex system @strong{must} be the same as the
name of the @code{.asd} file.
The file @code{foo.asd} will contain the definition of the system
@code{"foo"}. However, it may @emph{also} contain definitions of
subsidiary systems, such as @code{"foo/test"}, @code{"foo/docs"}, and so
forth. ASDF will ``know'' that if you ask it to load system
@code{"foo/test"} it should look for that system's definition in @code{foo.asd}.
@subsection Component types @subsection Component types
@anchor{Component types}
Component type names, even if expressed as keywords, will be looked up 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 by name in the current package and in the asdf package, if not found in
...@@ -1523,6 +1574,7 @@ the current package @code{my-system-asd} can be specified as ...@@ -1523,6 +1574,7 @@ the current package @code{my-system-asd} can be specified as
allowed as component types for such children components. allowed as component types for such children components.
@subsection System class names @subsection System class names
@anchor {System class names}
A system class name will be looked up A system class name will be looked up
in the same way as a Component type (see above), in the same way as a Component type (see above),
...@@ -1554,6 +1606,7 @@ system definition. ...@@ -1554,6 +1606,7 @@ system definition.
@subsection Build-operation @subsection Build-operation
@cindex :build-operation @cindex :build-operation
@anchor{Build-operation}
The @code{:build-operation} option to @code{defsystem} allows the The @code{:build-operation} option to @code{defsystem} allows the
programmer to specify an operation that will be applied, in place of programmer to specify an operation that will be applied, in place of
...@@ -1601,6 +1654,7 @@ this anomalous behaviour may be removed without warning. ...@@ -1601,6 +1654,7 @@ this anomalous behaviour may be removed without warning.
@subsection Pathname specifiers @subsection Pathname specifiers
@cindex pathname specifiers @cindex pathname specifiers
@anchor{Pathname specifiers}
A pathname specifier (@code{pathname-specifier}) A pathname specifier (@code{pathname-specifier})
may be a pathname, a string or a symbol. may be a pathname, a string or a symbol.
...@@ -1641,13 +1695,17 @@ If a symbol is given, it will be translated into a string, ...@@ -1641,13 +1695,17 @@ If a symbol is given, it will be translated into a string,
and downcased in the process. and downcased in the process.
The downcasing of symbols is unconventional, The downcasing of symbols is unconventional,
but was selected after some consideration. but was selected after some consideration.
Observations suggest that the type of systems we want to support The file systems we support
either have lowercase as customary case (Unix, Mac, windows) either have lowercase as customary case (Unix, Mac, Windows)
or silently convert lowercase to uppercase (lpns), or silently convert lowercase to uppercase (lpns),
so this makes more sense than attempting to use @code{:case :common} so this makes more sense than attempting to use @code{:case :common}
as argument to @code{make-pathname}, as argument to @code{make-pathname},
which is reported not to work on some implementations. which is reported not to work on some implementations.
Please avoid using underscores in system names, or component (module or
file) names, since underscores are not
compatible with logical pathnames (@pxref{Using logical pathnames}).
Pathname objects may be given to override the path for a component. Pathname objects may be given to override the path for a component.
Such objects are typically specified using reader macros such as @code{#p} Such objects are typically specified using reader macros such as @code{#p}
or @code{#.(make-pathname ...)}. or @code{#.(make-pathname ...)}.
...@@ -1656,7 +1714,7 @@ a shorthand for @code{#.(parse-namestring ...)} ...@@ -1656,7 +1714,7 @@ a shorthand for @code{#.(parse-namestring ...)}
and that the behaviour of @code{parse-namestring} is completely non-portable, and that the behaviour of @code{parse-namestring} is completely non-portable,
unless you are using Common Lisp @code{logical-pathname}s, unless you are using Common Lisp @code{logical-pathname}s,
which themselves involve other non-portable behaviour which themselves involve other non-portable behaviour
(@pxref{The defsystem grammar,,Using logical pathnames}, below). (@pxref{Using logical pathnames}).
Pathnames made with @code{#.(make-pathname ...)} Pathnames made with @code{#.(make-pathname ...)}
can usually be done more easily with the string syntax above. 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 only case that you really need a pathname object is to override
...@@ -1681,6 +1739,7 @@ be forced upon you if you were specifying a string. ...@@ -1681,6 +1739,7 @@ be forced upon you if you were specifying a string.
@subsection Version specifiers @subsection Version specifiers
@cindex version specifiers @cindex version specifiers
@cindex :version @cindex :version
@anchor{Version specifiers}
Version specifiers are strings to be parsed as period-separated lists of integers. Version specifiers are strings to be parsed as period-separated lists of integers.
I.e., in the example, @code{"0.2.1"} is to be interpreted, I.e., in the example, @code{"0.2.1"} is to be interpreted,
...@@ -1695,9 +1754,8 @@ Instead of a string representing the version, ...@@ -1695,9 +1754,8 @@ Instead of a string representing the version,
the @code{:version} argument can be an expression that is resolved to the @code{:version} argument can be an expression that is resolved to
such a string using the following trivial domain-specific language: such a string using the following trivial domain-specific language:
in addition to being a literal string, it can be an expression of the form in addition to being a literal string, it can be an expression of the form
@code{(:read-file-form <pathname-or-string> [:at <access-at-specifier]>)}, @code{(:read-file-form <pathname-or-string> [:at <access-at-specifier>])},
or @code{(:read-file-line <pathname-or-string> [:at or @code{(:read-file-line <pathname-or-string> [:at <access-at-specifier>])}.
<access-at-specifier]?>)}.
As the name suggests, the former will be resolved by reading a form in the specified pathname As the name suggests, the former will be resolved by reading a form in the specified pathname
(read as a subpathname of the current system if relative or a (read as a subpathname of the current system if relative or a
unix-namestring), and the latter by reading a line. unix-namestring), and the latter by reading a line.
...@@ -1722,13 +1780,14 @@ where significant API incompatibilities are signaled by an increased major numbe ...@@ -1722,13 +1780,14 @@ where significant API incompatibilities are signaled by an increased major numbe
Use the implementation's own @code{require} to load the @var{module-name}. Use the implementation's own @code{require} to load the @var{module-name}.
It is good taste to use @code{:if-feature @emph{:implementation-name}} It is good taste to use @code{(:feature @emph{:implementation-name} (:require @var{module-name}))}
rather than @code{#+@emph{implementation-name}} rather than @code{#+@emph{implementation-name} (:require @var{module-name})}
to only depend on the specified module on the specific implementation that provides it. to only depend on the specified module on the specific implementation that provides it.
@xref{if-feature-option}. @xref{Feature dependencies}.
@subsection Feature dependencies @subsection Feature dependencies
@cindex :feature dependencies @cindex :feature dependencies
@anchor{Feature dependencies}
A feature dependency is of the form A feature dependency is of the form
@code{(:feature @var{feature-expression} @var{dependency})} @code{(:feature @var{feature-expression} @var{dependency})}
...@@ -1744,11 +1803,12 @@ definition to be loaded. E.g., one cannot use @code{(:feature :sbcl)} ...@@ -1744,11 +1803,12 @@ definition to be loaded. E.g., one cannot use @code{(:feature :sbcl)}
to require that a system only be used on SBCL. to require that a system only be used on SBCL.
Feature dependencies are not to be confused with the obsolete Feature dependencies are not to be confused with the obsolete
feature requirement (@pxref{The defsystem grammar,,feature requirement}), or feature requirement (@pxref{feature requirement}), or
with @code{if-feature}. with @code{if-feature}.
@subsection Using logical pathnames @subsection Using logical pathnames
@cindex logical pathnames @cindex logical pathnames
@anchor{Using logical pathnames}
We do not generally recommend the use of logical pathnames, We do not generally recommend the use of logical pathnames,
especially not so to newcomers to Common Lisp. especially not so to newcomers to Common Lisp.
...@@ -1880,7 +1940,7 @@ from within an editor without clobbering its source location) ...@@ -1880,7 +1940,7 @@ from within an editor without clobbering its source location)
@subsection if-feature option @subsection if-feature option
@cindex :if-feature component option @cindex :if-feature component option
@anchor{if-feature-option} @c redo if this ever becomes a node in @anchor{if-feature option} @c redo if this ever becomes a node in
@c its own right... @c its own right...
This option allows you to specify a feature expression to be evaluated This option allows you to specify a feature expression to be evaluated
...@@ -1905,9 +1965,17 @@ been performed. ...@@ -1905,9 +1965,17 @@ been performed.
This option was added in ASDF 3. For more information, This option was added in ASDF 3. For more information,
@xref{required-features, Required features}. @xref{required-features, Required features}.
@subsection Entry point
@cindex :entry-point
@anchor{Entry point}
The @code{:entry-point} option allows a developer to specify the entry point of an executable program created by @code{program-op}.
When @code{program-op} is invoked, the form passed to this option is converted to a function by @code{uiop:ensure-function} and bound to @code{uiop:*image-entry-point*}. Typically one will specify a string, e.g. @code{"foo:main"}, so that the executable starts with the @code{foo:main} function. Note that using the symbol @code{foo:main} instead might not work because the @code{foo} package doesn't necessarily exist when ASDF reads the @code{defsystem} form. For more information on @code{program-op}, @pxref{Predefined operations of ASDF}.
@subsection feature requirement @subsection feature requirement
@anchor{feature requirement}
This requirement was removed in ASDF 3.1. Please do not use it. In This requirement was removed in ASDF 3.1. Please do not use it. In
most cases, @code{:if-feature} (@pxref{if-feature-option}) will provide most cases, @code{:if-feature} (@pxref{if-feature option}) will provide
an adequate substitute. an adequate substitute.
The @code{feature} requirement used to ensure that a chain of component The @code{feature} requirement used to ensure that a chain of component
...@@ -1947,14 +2015,20 @@ of output from ASDF operations. ...@@ -1947,14 +2015,20 @@ of output from ASDF operations.
@node The package-inferred-system extension, , Other code in .asd files, Defining systems with defsystem @node The package-inferred-system extension, , Other code in .asd files, Defining systems with defsystem
@section The package-inferred-system extension @section The package-inferred-system extension
@codequoteundirected on
@cindex Package inferred systems
@cindex Packages, inferring dependencies from
@findex package-inferred-system
@cindex One package per file systems
Starting with release 3.1.2, Starting with release 3.1.2,
ASDF supports a one-package-per-file style of programming, ASDF supports a one-package-per-file style of programming,
whereby each file is its own system, in which each file is its own system,
and dependencies are deduced from the @code{defpackage} form and dependencies are deduced from the @code{defpackage} form
(or its variant @code{uiop:define-package}). or its variant, @code{uiop:define-package}.
In this style, packages refer to a system with the same name (downcased); In this style of system definition, package names map to systems with
the same name (in lower case letters),
and if a system is defined with @code{:class package-inferred-system}, and if a system is defined with @code{:class package-inferred-system},
then system names that start with that name then system names that start with that name
(using the slash @code{/} separator) (using the slash @code{/} separator)
...@@ -1963,23 +2037,26 @@ For instance, if system @code{my-lib} is defined in ...@@ -1963,23 +2037,26 @@ For instance, if system @code{my-lib} is defined in
@file{/foo/bar/my-lib/my-lib.asd}, then system @code{my-lib/src/utility} @file{/foo/bar/my-lib/my-lib.asd}, then system @code{my-lib/src/utility}
will be found in file @file{/foo/bar/my-lib/src/utility.lisp}. will be found in file @file{/foo/bar/my-lib/src/utility.lisp}.
This style was made popular by @code{faslpath} and @code{quick-build} before, One package per file style was made popular by @code{faslpath} and @code{quick-build},
and at the cost of a stricter package discipline, and at the cost of stricter package discipline,
seems to make for more maintainable code. may yield more maintainable code.
It is used by ASDF itself (starting with ASDF 3), by @code{lisp-interface-library}, This style is used in ASDF itself (starting with ASDF 3), by @code{lisp-interface-library},
and a few other libraries. and a few other libraries.
To use this style, choose a toplevel system name, e.g. @code{my-lib}, To use this style, choose a toplevel system name, e.g. @code{my-lib},
and create a file @file{my-lib.asd} and create a file @file{my-lib.asd}.
with the @code{:class :package-inferred-system} option in its @code{defsystem}. Define @code{my-lib}
using the @code{:class :package-inferred-system} option in its @code{defsystem}.
For instance: For instance:
@example @example
#-asdf3.1 (error "my-lib requires ASDF 3.1") ;; This example is based on lil.asd of LISP-INTERFACE-LIBRARY.
#-asdf3.1 (error "MY-LIB requires ASDF 3.1 or later.")
(defsystem "my-lib" (defsystem "my-lib"
:class :package-inferred-system :class :package-inferred-system
:depends-on ("my-lib/interface/all" :depends-on ("my-lib/interface/all"
"my-lib/src/all" "my-lib/src/all"
"my-lib/extras/all") "my-lib/extras/all")
:in-order-to ((test-op (load-op "my-lib/test/all"))) :in-order-to ((test-op (load-op "my-lib/test/all")))
:perform (test-op (o c) (symbol-call :my-lib/test/all :test-suite))) :perform (test-op (o c) (symbol-call :my-lib/test/all :test-suite)))
...@@ -1991,43 +2068,84 @@ For instance: ...@@ -1991,43 +2068,84 @@ For instance:
(register-system-packages (register-system-packages
"closer-mop" "closer-mop"
'(:c2mop :closer-common-lisp :c2cl :closer-common-lisp-user :c2cl-user)) '(:c2mop
:closer-common-lisp
:c2cl
:closer-common-lisp-user
:c2cl-user))
@end example @end example
In the code above, the first line checks that we are using ASDF 3.1, @noindent
which provides @code{package-inferred-system}. In the code above, the first form checks that we are using ASDF 3.1 or
later, which provides @code{package-inferred-system}. This is probably
The function @code{register-system-packages} has to be called to register no longer necessary, since none of the major lisp implementations
packages used or provided by your system and its components provides an older version of ASDF.
where the name of the system that provides the package
is not the downcase of the package name. @findex register-system-packages
The function @code{register-system-packages} must be called to register
Then, file @file{interface/order.lisp} under the @code{lil} hierarchy, packages used or provided by your system
that defines abstract interfaces for order comparisons, when the name of the system/file that provides the package
starts with the following form, is not the same as the package name (converted to lower case).
dependencies being trivially computed from the @code{:use} and @code{:mix} clauses:
Each file under the @code{my-lib} hierarchy will start with a
package definition.
@findex define-package
@findex uiop:define-package
The form @code{uiop:define-package} is supported as well as
@code{defpackage}.
ASDF will compute dependencies from the
@code{:use}, @code{:mix}, and other importation clauses of this package definition. Take the file
@file{interface/order.lisp} as an example:
@example @example
(uiop:define-package :lil/interface/order (uiop:define-package :my-lib/interface/order
(:use :closer-common-lisp (:use :closer-common-lisp
:lil/interface/definition :my-lib/interface/definition
:lil/interface/base :my-lib/interface/base)
:lil/interface/eq :lil/interface/group)
(:mix :fare-utils :uiop :alexandria) (:mix :fare-utils :uiop :alexandria)
(:export ...)) (:export ...))
@end example @end example
ASDF can tell that this file depends on system @code{closer-mop} (registered above), ASDF can tell that this file/system depends on system @code{closer-mop} (registered above),
@code{lil/interface/definition}, @code{lil/interface/base}, @code{my-lib/interface/definition}, and @code{my-lib/interface/base}.
@code{lil/interface/eq}, and @code{lil/interface/group}
(package and system names match, and they will be looked up hierarchically). How can ASDF find the file @file{interface/order.lisp} from the
toplevel system @code{my-lib}, however? In the example above,
@file{interface/all.lisp} (and other @file{all.lisp}) reexport
all the symbols exported from the packages at the same or lower levels
of the hierarchy. This can be easily done with
@code{uiop:define-package}, which has many options that prove useful in this
context. For example:
@example
(uiop:define-package :my-lib/interface/all
(:nicknames :my-lib-interface)
(:use :closer-common-lisp)
(:mix :fare-utils :uiop :alexandria)
(:use-reexport
:my-lib/interface/definition
:my-lib/interface/base
:my-lib/interface/order
:my-lib/interface/monad/continuation))
@end example
Thus the top level system need only depend on the @code{my-lib/.../all} systems
because ASDF detects
@file{interface/order.lisp} and all other dependencies from @code{all}
systems' @code{:use-reexport} clauses, which effectively
allow for ``inheritance'' of symbols being exported.
ASDF also detects dependencies from @code{:import-from} clauses. ASDF also detects dependencies from @code{:import-from} clauses.
You may thus import a well-defined set of symbols from an existing package You may thus import a well-defined set of symbols from an existing