All the operations described in this section are in the asdf
package.
They are invoked via the operate
generic function.
(asdf:operate 'asdf:operation-name :system-name {operation-options ...})
compile-op
This operation compiles the specified component. A
cl-source-file
will becompile-file
'd. All the children and dependencies of a system or module will be recursively compiled bycompile-op
.
compile-op
depends onprepare-op
which itself depends on aload-op
of all of a component's dependencies, as well as of its parent's dependencies. Whenoperate
is called oncompile-op
, all these dependencies will be loaded as well as compiled; yet, some parts of the system main remain unloaded, because nothing depends on them. Useload-op
to load a system.
load-op
This operation loads the compiled code for a specified component. A
cl-source-file
will have its compiled faslload
ed, which fasl is the output ofcompile-op
thatload-op
depends on. All the children and dependencies of a system or module will be recursively loaded byload-op
.
load-op
depends onprepare-op
which itself depends on aload-op
of all of a component's dependencies, as well as of its parent's dependencies.
prepare-op
This operation ensures that the dependencies of a component and its recursive parents are loaded (as per
load-op
), as a prerequisite beforecompile-op
andload-op
operations may be performed on a given component.
load-source-op
, prepare-source-op
load-source-op
will load the source for the files in a module rather than they compiled fasl output. It has aprepare-source-op
analog toprepare-op
, that ensures the dependencies are themselves loaded viaload-source-op
.There is no provision in ASDF for ensuring that some components are always loaded as source, while others are always compiled. While this idea often comes up in discussions, it actually doesn't play well with either the linking model of ECL or with various bundle operations (see below), and is eventually not workable; also the dependency model of ASDF would have to be modified incompatibly to allow for such trick. If your code doesn't compile cleanly, fix it. If compilation makes it slow, use
declaim
oreval-when
to adjust your compiler settings, or eschew compilation byeval
uating a quoted source form at load-time.
test-op
This operation will perform some tests on the module. The default method will do nothing. The default dependency is to require
load-op
to be performed on the module first. The defaultoperation-done-p
is that the operation is never done — we assume that if you invoke thetest-op
, you want to test the system, even if you have already done so.The results of this operation are not defined by ASDF. It has proven difficult to define how the test operation should signal its results to the user in a way that is compatible with all of the various test libraries and test techniques in use in the community.
People typically define
test-op
methods like thus:(defmethod perform ((o asdf:test-op) (s (eql (asdf:find-system :my-system)))) (asdf:load-system :my-system-test) (funcall (read-from-string "my-system-test:test-suite")))Using
load-system
in the perform method rather than an:in-order-to
dependency, is sometimes necessary for backward compatibility with ASDF 2 and older, to avoid circular dependencies that could arise because of the way these old versions propagate dependencies.If you don't care for compatibility with ASDF 2, you could use the following options in your
defsystem
form::in-order-to ((test-op (load-op :my-system-test))) :perform (test-op (o c) (symbol-call :my-system-test :test-suite))
fasl-op
, monolithic-fasl-op
, load-fasl-op
, binary-op
, monolithic-binary-op
, lib-op
, monolithic-lib-op
, dll-op
, monolithic-dll-op
, program-op
These are “bundle” operations, that can create a single-file “bundle” for all the contents of each system in an application, or for the entire application.
fasl-op
will create a single fasl file for each of the systems needed, grouping all its many fasls in one, so you can deliver each system as a single fasl.monolithic-fasl-op
will create a single fasl file for target system and all its dependencies, so you can deliver your entire application as a single fasl.load-fasl-op
will load the output offasl-op
(though if it the output is not up-to-date, it will load the intermediate fasls indeed as part of building it); this matters a lot on ECL, where the dynamic linking involved in loading tens of individual fasls can be noticeably more expensive than loading a single one.Once you have created a fasl with
fasl-op
, you can useprecompiled-system
to deliver it in a way that is compatible with clients having dependencies on your system, whether it is distributed as source or as a single binary; the .asd file to be delivered with the fasl will look like this:(defsystem :mysystem :class :precompiled-system :fasl (some expression that will evaluate to a pathname))Or you can use
binary-op
to let ASDF create such a system for you as well as thefasl-op
output, ormonolithic-binary-op
. This allows you to deliver code for your systems or applications as a single file. Of course, if you want to test the result in the current image, before you try to use any newly created .asd files, you should not forget to(asdf:clear-configuration)
or at least(asdf:clear-source-registry)
, so it re-populates the source-registry from the filesystem.The
program-op
operation will create an executable program from the specified system and its dependencies. You can use UIOP for its pre-image-dump hooks, its post-image-restore hooks, and its access to command-line arguments. And you can specify an entry pointmy-app:main
by specifying in yourdefsystem
the option:entry-point "my-app:main"
. Depending on your implementation, running(asdf:operate 'asdf:program-op :my-app)
may quit the current Lisp image upon completion. See the example in test/hello-world-example.asd and test/hello.lisp, as built and tested by test/test-program.script and test/make-hello-world.lisp.There is also
lib-op
for building a linkable .a file (Windows: .lib) from all linkable object dependencies (FFI files, and on ECL, Lisp files too), and its monolithic equivalentmonolithic-lib-op
. And there is alsodll-op
(respectively its monolithic equivalentmonolithic-lib-op
) for building a linkable .so file (Windows: .dll, MacOS X: .dynlib) to create a single dynamic library for all the extra FFI code to be linked into each of your systems (respectively your entire application).All these “bundle” operations are available since ASDF 3 on all actively supported Lisp implementations, but may be unavailable on unmaintained legacy implementations. This functionality was previously available for select implementations, as part of a separate system
asdf-bundle
, itself descended from the ECL-onlyasdf-ecl
.The pathname of the output of bundle operations is subject to output-translation as usual, unless the operation is equal to the
:build-operation
argument todefsystem
. This behavior is not very satisfactory and may change in the future. Maybe you have suggestions on how to better configure it?
concatenate-source-op
, monolithic-concatenate-source-op
, load-concatenated-source-op
, compile-concatenated-source-op
, load-compiled-concatenated-source-op
, monolithic-load-concatenated-source-op
, monolithic-compile-concatenated-source-op
, monolithic-load-compiled-concatenated-source-op
These operation, as their respective names indicate, consist in concatenating all
cl-source-file
source files in a system (or in a system and all its dependencies, if monolithic), in the order defined by dependencies, then loading the result, or compiling then loading the result.These operations are useful to deliver a system or application as a single source file, and for testing that said file loads properly, or compiles then loads properly.
ASDF itself is notably delivered as a single source file this way using
monolithic-concatenate-source-op
, transcluding a prelude and theuiop
library before theasdf/defsystem
system itself.