Next: , Previous: , Up: Operations   [Contents][Index]

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.

load-op will recursively load all the children of a system or module.

load-op also 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
Operation: prepare-source-op

load-source-op will load the source for the files in a module rather than the compiled fasl output. It has a prepare-source-op analog to prepare-op, that ensures the dependencies are themselves loaded via load-source-op.

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. Its default operation-done-p method returns nil, which means 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, and given the fact that ASDF operations do not return a value indicating success or failure. For those willing to go to the effort, we suggest defining conditions to signal when a test-op fails, and storing in those conditions information that describes which tests fail.

People typically define a separate test system to hold the tests. Doing this avoids unnecessarily adding a test framework as a dependency on a library. For example, one might have

(defsystem "foo"
  :in-order-to ((test-op (test-op "foo/test")))

(defsystem "foo/test"
  :depends-on ("foo" "fiveam") ; fiveam is a test framework library

Then one defines perform methods on test-op such as the following:

(defsystem "foo/test"
  :depends-on ("foo" "fiveam") ; fiveam is a test framework library
  :perform (test-op (o s)
                    (uiop:symbol-call :fiveam '#:run!
                       (uiop:find-symbol* '#:foo-test-suite
Operation: compile-bundle-op
Operation: monolithic-compile-bundle-op
Operation: load-bundle-op
Operation: monolithic-load-bundle-op
Operation: deliver-asd-op
Operation: monolithic-deliver-asd-op
Operation: lib-op
Operation: monolithic-lib-op
Operation: dll-op
Operation: monolithic-dll-op
Operation: image-op
Operation: 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.

compile-bundle-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-compile-bundle-op will create a single fasl file for the target system and all its dependencies, so you can deliver your entire application as a single fasl. load-bundle-op will load the output of compile-bundle-op. Note that if the output is not up-to-date, compile-bundle-op may load the intermediate fasls as a side-effect. Bundling fasls together 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.

NB: compile-bundle-op, monolithic-compile-bundle-op, load-bundle-op, monolithic-load-bundle-op, deliver-asd-op, monolithic-deliver-asd-op were respectively called fasl-op, monolithic-fasl-op, load-fasl-op, monolithic-load-fasl-op, binary-op, monolithic-binary-op before ASDF 3.1. The old names still exist for backward compatibility, though they poorly label what is going on.

Once you have created a fasl with compile-bundle-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 deliver-asd-op to let ASDF create such a system for you as well as the compile-bundle-op output, or monolithic-deliver-asd-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. image-op will dump an image that may not be standalone and does not start its own function, but follows the usual execution convention of the underlying Lisp, just with more code pre-loaded, for use as an intermediate build result or with a wrapper invocation script.

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-dll-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 behaviour is not very satisfactory and may change in the future. Maybe you have suggestions on how to better configure it?

Operation: concatenate-source-op
Operation: monolithic-concatenate-source-op
Operation: load-concatenated-source-op
Operation: compile-concatenated-source-op
Operation: load-compiled-concatenated-source-op
Operation: monolithic-load-concatenated-source-op
Operation: monolithic-compile-concatenated-source-op
Operation: monolithic-load-compiled-concatenated-source-op

These operations, as their respective names indicate, will concatenate all the 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 load the result, or compile and then load 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 and then loads properly.

ASDF itself is delivered as a single source file this way, using monolithic-concatenate-source-op, prepending a prelude and the uiop library before the asdf/defsystem system itself.

See also FAQ entries see What happened to the bundle operations? and see How can I produce a binary at a specific path from sources at a specific path?.

Next: Creating new operations, Previous: Operations, Up: Operations   [Contents][Index]