ASDF was designed to be extensible in an object-oriented fashion.
To teach ASDF new tricks, a programmer can implement the behaviour he wants
by creating a subclass of
ASDF’s pre-defined operations are in no way “privileged”,
but it is requested that developers never use the
for operations they develop themselves.
The rationale for this rule is that we don’t want to establish a
“global asdf operation name registry”,
but also want to avoid name clashes.
Your operation must usually provide methods for one or more of the following generic functions:
performUnless your operation, like
prepare-op, is for dependency propagation only, the most important function for which to define a method is usually
perform, which will be called to perform the operation on a specified component, after all dependencies have been performed.
perform method must call
output-files (see below)
to locate its inputs and outputs,
because the user is allowed to override the method
or tweak the output-translation mechanism.
Perform should only use the primary value returned by
If one and only one output file is expected,
it can call
output-file that checks that this is the case
and returns the first and only list element.
output-filesIf your perform method has any output, you must define a method for this function. for ASDF to determine where the outputs of performing operation lie.
Your method may return two values, a list of pathnames, and a boolean.
If the boolean is
nil (or you fail to return multiple values),
:around methods may translate these pathnames,
e.g. to ensure object files are somehow stored
in some implementation-dependent cache.
If the boolean is
t then the pathnames are marked
not be translated by the enclosing
component-depends-onIf the action of performing the operation on a component has dependencies, you must define a method on
Your method will take as specialized arguments an operation and a component which together identify an action, and return a list of entries describing actions that this action depends on. The format of entries is described below.
It is strongly advised that
you should always append the results of
to the results of your method,
or “interesting” failures will likely occur,
unless you’re a true specialist of ASDF internals.
It is unhappily too late to compatibly use the
append method combination,
but conceptually that’s the protocol that is being manually implemented.
Each entry returned by
component-depends-on is itself a list.
The first element of an entry is an operation designator:
either an operation object designating itself, or
a symbol that names an operation class
(that ASDF will instantiate using
are common such names, denoting the respective operations.
The rest of each entry is a list of component designators:
either a component object designating itself,
or an identifier to be used with
find-component will be called with the current component’s parent as parent,
and the identifier as second argument.
The identifier is typically a string,
a symbol (to be downcased as per
or a list of strings or symbols.
In particular, the empty list
nil denotes the parent itself.
An operation may provide methods for the following generic functions:
input-filesA method for this function is often not needed, since ASDF has a pretty clever default
input-filesmechanism. You only need create a method if there are multiple ultimate input files. Most operations inherit from
selfward-operation, which appropriately sets the input-files to include the source file itself.
operation-done-pYou only need to define a method on that function if you can detect conditions that invalidate previous runs of the operation, even though no filesystem timestamp has changed, in which case you return
nil(the default is
For instance, the method for
test-op always returns
so that tests are always run afresh.
Of course, the
test-op for your system could depend
on a deterministically repeatable
and just read the results from the report files,
in which case you could have this method return
Operations that print output should send that output to the standard
*standard-output*, as the Lisp compiler and loader do.