Previous: Predefined operations of ASDF, Up: Operations [Contents][Index]
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 operation
.
ASDF’s pre-defined operations are in no way “privileged”,
but it is requested that developers never use the asdf
package
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:
perform
Unless 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.
The perform
method must call input-files
and 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 output-files
.
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-files
If 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),
then enclosing :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 :around
method.
component-depends-on
If the action of performing the operation on a component has dependencies,
you must define a method on component-depends-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 (call-next-method)
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 make-operation
).
For instance, load-op
, compile-op
and prepare-op
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
.
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 coerce-name
),
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-files
A method for this function is often not needed,
since ASDF has a pretty clever default input-files
mechanism.
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.
Return a list of pathnames that represent the input to operation performed on component.
operation-done-p
You 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 t
).
For instance, the method for test-op
always returns nil
,
so that tests are always run afresh.
Of course, the test-op
for your system could depend
on a deterministically repeatable test-report-op
,
and just read the results from the report files,
in which case you could have this method return t
.
Operations that print output should send that output to the standard
CL stream *standard-output*
, as the Lisp compiler and loader do.
Previous: Predefined operations of ASDF, Up: Operations [Contents][Index]