Next: , Previous: Operations, Up: Operations


7.1.1 Predefined operations of ASDF

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 ...})
— Operation: compile-op

This operation compiles the specified component. A cl-source-file will be compile-file'd. All the children and dependencies of a system or module will be recursively compiled by compile-op.

compile-op depends on prepare-op which itself depends on a load-op of all of a component's dependencies, as well as of its parent's dependencies. When operate is called on compile-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. Use load-op to load a system.

— Operation: load-op

This operation loads the compiled code for a specified component. A cl-source-file will have its compiled fasl loaded, which fasl is the output of compile-op that load-op depends on. All the children and dependencies of a system or module will be recursively loaded by load-op.

load-op depends on prepare-op which itself depends on a load-op of all of a component's dependencies, as well as of its parent's dependencies.

— Operation: prepare-op

This operation ensures that the dependencies of a component and its recursive parents are loaded (as per load-op), as a prerequisite before compile-op and load-op operations may be performed on a given component.

— Operation: 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 a prepare-source-op analog to prepare-op, that ensures the dependencies are themselves loaded via load-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 or eval-when to adjust your compiler settings, or eschew compilation by evaluating a quoted source form at load-time.

— Operation: 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 default operation-done-p is that the operation is never done — we assume that if you invoke the test-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))
— Operation: 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 of fasl-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 use precompiled-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 the fasl-op output, or monolithic-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 point my-app:main by specifying in your defsystem 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 equivalent monolithic-lib-op. And there is also dll-op (respectively its monolithic equivalent monolithic-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-only asdf-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 to defsystem. This behavior is not very satisfactory and may change in the future. Maybe you have suggestions on how to better configure it?

— Operation: 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 the uiop library before the asdf/defsystem system itself.