Configurations specify paths where to find system files.
CL_SOURCE_REGISTRY
if it exists.
:directory
entries for $XDG_DATA_DIRS/common-lisp/systems/ and
:tree
entries for $XDG_DATA_DIRS/common-lisp/source/.
For instance, SBCL will include directories for its contribs
when it can find them; it will look for them where SBCL was installed,
or at the location specified by the SBCL_HOME
environment variable.
Each of these configurations is specified as an s-expression in a trivial domain-specific language (defined below). Additionally, a more shell-friendly syntax is available for the environment variable (defined yet below).
Each of these configurations is only used if the previous configuration explicitly or implicitly specifies that it includes its inherited configuration.
Additionally, some implementation-specific directories may be automatically prepended to whatever directories are specified in configuration files, no matter if the last one inherits or not.
Note that we purport to respect the XDG base directory specification as to where configuration files are located, where data files are located, where output file caches are located. Mentions of XDG variables refer to that document.
http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
This specification allows the user to specify some environment variables to customize how applications behave to his preferences.
On Windows platforms, when not using Cygwin,
instead of the XDG base directory specification,
we try to use folder configuration from the registry regarding
Common AppData
and similar directories.
However, support for querying the Windows registry is limited as of ASDF 2,
and on many implementations, we may fall back to always using the defaults
without consulting the registry.
Patches welcome.
For backward compatibility as well as to provide a practical backdoor for hackers,
ASDF will first search for .asd
files in the directories specified in
asdf:*central-registry*
before it searches in the source registry above.
See Configuring ASDF to find your systems — old style.
By default, asdf:*central-registry*
will be empty.
This old mechanism will therefore not affect you if you don't use it, but will take precedence over the new mechanism if you do use it.
Here is the grammar of the s-expression (SEXP) DSL for source-registry configuration:
;; A configuration is a single SEXP starting with keyword :source-registry
;; followed by a list of directives.
CONFIGURATION := (:source-registry DIRECTIVE ...)
;; A directive is one of the following:
DIRECTIVE :=
;; INHERITANCE DIRECTIVE:
;; Your configuration expression MUST contain
;; exactly one of either of these:
:inherit-configuration | ; splices inherited configuration (often specified last)
:ignore-inherited-configuration | ; drop inherited configuration (specified anywhere)
;; forward compatibility directive (since ASDF 2.011.4), useful when
;; you want to use new configuration features but have to bootstrap a
;; the newer required ASDF from an older release that doesn't sport said features:
:ignore-invalid-entries | ; drops subsequent invalid entries instead of erroring out
;; add a single directory to be scanned (no recursion)
(:directory DIRECTORY-PATHNAME-DESIGNATOR) |
;; add a directory hierarchy, recursing but excluding specified patterns
(:tree DIRECTORY-PATHNAME-DESIGNATOR) |
;; override the defaults for exclusion patterns
(:exclude EXCLUSION-PATTERN ...) |
;; augment the defaults for exclusion patterns
(:also-exclude EXCLUSION-PATTERN ...) |
;; Note that the scope of a an exclude pattern specification is
;; the rest of the current configuration expression or file.
;; splice the parsed contents of another config file
(:include REGULAR-FILE-PATHNAME-DESIGNATOR) |
;; This directive specifies that some default must be spliced.
:default-registry
REGULAR-FILE-PATHNAME-DESIGNATOR := PATHNAME-DESIGNATOR ;; interpreted as a file
DIRECTORY-PATHNAME-DESIGNATOR := PATHNAME-DESIGNATOR ;; interpreted as a directory name
PATHNAME-DESIGNATOR :=
NIL | ;; Special: skip this entry.
ABSOLUTE-COMPONENT-DESIGNATOR ;; see pathname DSL
EXCLUSION-PATTERN := a string without wildcards, that will be matched exactly
against the name of a any subdirectory in the directory component
of a path. e.g. "_darcs"
will match #p"/foo/bar/_darcs/src/bar.asd"
Pathnames are designated using another DSL,
shared with the output-translations configuration DSL below.
The DSL is resolved by the function asdf::resolve-location
,
to be documented and exported at some point in the future.
ABSOLUTE-COMPONENT-DESIGNATOR := (ABSOLUTE-COMPONENT-DESIGNATOR RELATIVE-COMPONENT-DESIGNATOR ...) | STRING | ;; namestring (better be absolute or bust, directory assumed where applicable). ;; In output-translations, directory is assumed and **/*.*.* added if it's last. ;; On MCL, a MacOSX-style POSIX namestring (for MacOS9 style, use #p"..."); ;; Note that none of the above applies to strings used in *central-registry*, ;; which doesn't use this DSL: they are processed as normal namestrings. ;; however, you can compute what you put in the *central-registry* ;; based on the results of say (asdf::resolve-location "/Users/fare/cl/cl-foo/") PATHNAME | ;; pathname (better be an absolute path, or bust) ;; In output-translations, unless followed by relative components, ;; it better have appropriate wildcards, as in **/*.*.* :HOME | ;; designates the user-homedir-pathname ~/ :USER-CACHE | ;; designates the default location for the user cache :HERE | ;; designates the location of the configuration file ;; (or *default-pathname-defaults*, if invoked interactively) :ROOT ;; magic, for output-translations source only: paths that are relative ;; to the root of the source host and device ;; Not valid anymore: :SYSTEM-CACHE (was a security hazard) RELATIVE-COMPONENT-DESIGNATOR := (RELATIVE-COMPONENT-DESIGNATOR RELATIVE-COMPONENT-DESIGNATOR ...) | STRING | ;; relative directory pathname as interpreted by coerce-pathname. ;; In output translations, if last component, **/*.*.* is added PATHNAME | ;; pathname; unless last component, directory is assumed. :IMPLEMENTATION | ;; directory based on implementation, e.g. sbcl-1.0.45-linux-x64 :IMPLEMENTATION-TYPE | ;; a directory based on lisp-implementation-type only, e.g. sbcl :DEFAULT-DIRECTORY | ;; a relativized version of the default directory :*/ | ;; any direct subdirectory (since ASDF 2.011.4) :**/ | ;; any recursively inferior subdirectory (since ASDF 2.011.4) :*.*.* | ;; any file (since ASDF 2.011.4) ;; Not supported (anymore): :UID and :USERNAME
For instance, as a simple case, my ~/.config/common-lisp/source-registry.conf, which is the default place ASDF looks for this configuration, once contained:
(:source-registry (:tree (:home "cl")) ;; will expand to e.g. "/home/joeluser/cl/" :inherit-configuration)
Configuration directories consist in files each containing
a list of directives without any enclosing (:source-registry ...)
form.
The files will be sorted by namestring as if by string<
and
the lists of directives of these files with be concatenated in order.
An implicit :inherit-configuration
will be included
at the end of the list.
This allows for packaging software that has file granularity
(e.g. Debian's dpkg
or some future version of clbuild
)
to easily include configuration information about distributed software.
The convention is that, for sorting purposes,
the names of files in such a directory begin with two digits
that determine the order in which these entries will be read.
Also, the type of these files is conventionally "conf"
and as a limitation to some implementations (e.g. GNU clisp),
the type cannot be NIL
.
Directories may be included by specifying a directory pathname
or namestring in an :include
directive, e.g.:
(:include "/foo/bar/")
Hence, to achieve the same effect as my example ~/.config/common-lisp/source-registry.conf above, I could simply create a file ~/.config/common-lisp/source-registry.conf.d/33-home-fare-cl.conf alone in its directory with the following contents:
(:tree "/home/fare/cl/")
The :here
directive is an absolute pathname designator that
refers to the directory containing the configuration file currently
being processed.
The :here
directive is intended to simplify the delivery of
complex CL systems, and for easy configuration of projects shared through
revision control systems, in accordance with our design principle that
each participant should be able to provide all and only the information
available to him or her.
Consider a person X who has set up the source code repository for a complex project with a master directory dir/. Ordinarily, one might simply have the user add a directive that would look something like this:
(:tree "path/to/dir")
But what if X knows that there are very large subtrees under dir that are filled with, e.g., Java source code, image files for icons, etc.? All of the asdf system definitions are contained in the subdirectories dir/src/lisp/ and dir/extlib/lisp/, and these are the only directories that should be searched.
In this case, X can put into dir/ a file asdf.conf that contains the following:
(:source-registry (:tree (:here "src/lisp/")) (:tree (:here "extlib/lisp")) (:directory (:here "outlier/")))
Then when someone else (call her Y) checks out a copy of this repository, she need only add
(:include "/path/to/my/checkout/directory/asdf.conf")
to one of her previously-existing asdf source location configuration
files, or invoke initialize-source-registry
with a configuration
form containing that s-expression. ASDF will find the .conf file that X
has provided, and then set up source locations within the working
directory according to X's (relative) instructions.
When considering environment variable CL_SOURCE_REGISTRY
ASDF will skip to next configuration if it's an empty string.
It will READ
the string as a SEXP in the DSL
if it begins with a paren (
and it will be interpreted much like TEXINPUTS
list of paths, where
* paths are separated
by a :
(colon) on Unix platforms (including cygwin),
by a ;
(semicolon) on other platforms (mainly, Windows).
* each entry is a directory to add to the search path.
* if the entry ends with a double slash //
then it instead indicates a tree in the subdirectories
of which to recurse.
* if the entry is the empty string (which may only appear once), then it indicates that the inherited configuration should be spliced there.
In case that isn't clear, the semantics of the configuration is that when searching for a system of a given name, directives are processed in order.
When looking in a directory, if the system is found, the search succeeds, otherwise it continues.
When looking in a tree, if one system is found, the search succeeds. If multiple systems are found, the consequences are unspecified: the search may succeed with any of the found systems, or an error may be raised. ASDF currently returns the first system found, XCVB currently raised an error. If none is found, the search continues.
Exclude statements specify patterns of subdirectories
the systems from which to ignore.
Typically you don't want to use copies of files kept by such
version control systems as Darcs.
Exclude statements are not propagated to further included or inherited
configuration files or expressions;
instead the defaults are reset around every configuration statement
to the default defaults from asdf::*default-source-registry-exclusions*
.
Include statements cause the search to recurse with the path specifications from the file specified.
An inherit-configuration statement cause the search to recurse with the path specifications from the next configuration (see Configurations above).
The implementation is allowed to either eagerly compute the information from the configurations and file system, or to lazily re-compute it every time, or to cache any part of it as it goes. To explicitly flush any information cached by the system, use the API below.
The specified functions are exported from your build system's package. Thus for ASDF the corresponding functions are in package ASDF, and for XCVB the corresponding functions are in package XCVB.
will read the configuration and initialize all internal variables. You may extend or override configuration from the environment and configuration files with the given PARAMETER, which can be
NIL
(no configuration override), or a SEXP (in the SEXP DSL), a string (as in the string DSL), a pathname (of a file or directory with configuration), or a symbol (fbound to function that when called returns one of the above).
undoes any source registry configuration and clears any cache for the search algorithm. You might want to call this function (or better,
clear-configuration
) before you dump an image that would be resumed with a different configuration, and return an empty configuration. Note that this does not include clearing information about systems defined in the current image, only about where to look for systems not yet defined.
checks whether a source registry has been initialized. If not, initialize it with the given PARAMETER.
Every time you use ASDF's find-system
, or
anything that uses it (such as operate
, load-system
, etc.),
ensure-source-registry
is called with parameter NIL,
which the first time around causes your configuration to be read.
If you change a configuration file,
you need to explicitly initialize-source-registry
again,
or maybe simply to clear-source-registry
(or clear-configuration
)
which will cause the initialization to happen next time around.
If this mechanism is successful, in the future, we may declare
asdf:*central-registry*
obsolete and eventually remove it.
Any hook into implementation-specific search mechanisms will by then
have been integrated in the :default-configuration
which everyone
should either explicitly use or implicit inherit. Some shell syntax
for it should probably be added somehow.
But we're not there yet. For now, let's see how practical this new source-registry is.
Alternatives I considered and rejected included:
asdf:*central-registry*
as the master with its current semantics,
and somehow the configuration parser expands the new configuration
language into a expanded series of directories of subdirectories to
lookup, pre-recursing through specified hierarchies. This is kludgy,
and leaves little space of future cleanups and extensions.
asdf:*central-registry*
remains the master but extend its semantics
in completely new ways, so that new kinds of entries may be implemented
as a recursive search, etc. This seems somewhat backwards.
asdf:*central-registry*
and break backwards compatibility.
Hopefully this will happen in a few years after everyone migrate to
a better ASDF and/or to XCVB, but it would be very bad to do it now.
asdf:*central-registry*
by a symbol-macro with appropriate magic
when you dereference it or setf it. Only the new variable with new
semantics is handled by the new search procedure.
Complex and still introduces subtle semantic issues.
I've been suggested the below features, but have rejected them, for the sake of keeping ASDF no more complex than strictly necessary.
(:add-directory X)
for (:directory X)
, or (:add-directory-hierarchy X)
or (:add-directory X :recurse t)
for (:tree X)
.
USER-HOMEDIR-PATHNAME
and $SBCL_HOME
Hopefully, these are already superseded by the :default-registry
/**
instead of //
to specify recursion
down a filesystem tree in the environment variable.
It isn't that Lisp friendly either.
Thanks a lot to Stelian Ionescu for the initial idea.
Thanks to Rommel Martinez for the initial implementation attempt.
All bad design ideas and implementation bugs are to mine, not theirs. But so are good design ideas and elegant implementation tricks.
— Francois-Rene Rideau fare@tunes.org, Mon, 22 Feb 2010 00:07:33 -0500