ASDF and Quicklisp - Confession 10

2014.07.15 11:34:34

Continuing on in my endeavour to wrap up some loose ends and missing chapters of PCL I'll take a look at ASDF and Quicklisp. Neither of these are required to use CL —even for large projects— but they can help tremendously to get things done quick. So, let's see what they do and how they may be of use to you.

First we'll look at ASDF. The acronym stands for Another System Definition Facility and alludes to a command on the lisp implementations way back when: defsystem. This command, which ASDF provides too, allows you to define build systems. It is CL's equivalent of Make, Ant or similar tools that are used in other languages to compile a multitude of files and perhaps manage dependencies and produce a binary or whatever your target might be.

ASDF does just this; it primarily allows you to define the way your project's files should be compiled and loaded, allowing for easy distribution and setup on other systems. If your project is defined with ASDF, anyone else that receives it doesn't have to worry about load order or anything, but can simply call ASDF to load your project. It will also handle dependency management as to ensure that all projects you require are loaded first. ASDF allows you to do more than that though (as is customary to Lisp solutions). Furthermore it makes it possible to annotate your system definition with information about the project, such as the name, author, version, site and so on. Not to mention that you can define custom operations to for instance generate a binary, compile C libraries as a dependency and so on.

So, if you want to distribute your project or if it is bigger than one file it is probably a good idea to define an ASDF system for it so you can easily load it again once you want to resume work in a new lisp session. ASDF works by detecting .asd files automatically. In order to make your system recognised, create a .asd file (Slime should automatically detect it as a common-lisp file) with the name that you want to use to load your project. In this file you'll need a defsystem statement to define what you need. Here's a basic template for such a file.

The first thing done in the file is to create a package specifically for the system definition so we don't need to litter the cl-user (or whatever other package is active) or our own main project package with other symbols. Also note the use of #:asdf so we don't need to use the package prefixes. Next comes the big system definition. The symbol name of your system should be the same as the file name (my-project in this case). The :name parameter itself can be a more ‘presentable’ name for the project, but won't have any bearing on how you load it. The :version, :license, and so on parameters should be self-explanatory.

Now the :serial parameter tells ASDF that it should simply load the files in the sequence that they are defined in your system definition. Without it, you'll have to manually add :depends-on clauses to each :file definition to ensure that it will compile and load the files in the order you require. The :components parameter itself tells which files belong to the system. A :file component is a lisp source file with the given name string and the file extension .lisp . If you split your source into multiple directories, you'll have to refer to these using a :module component and defining sub-components within it as is illustrated in the example. The last parameter is :depends-on which is a list of ASDF system names that need to be loaded before your system can be compiled, which means any library you use in your sources should be put in there.

While this only touches the bare surface of what ASDF can do and offers to you, it should suffice for most of what you'll do with it. ASDF itself is not part of ANSI CL, but it is an extension that should be included with most implementations of CL today. One thing that ASDF does not do is the fetching of dependencies. If you want to rely purely on ASDF you will have to manually download all required dependencies and put them into ASDF's load path.

This is where Quicklisp steps in. Quicklisp will manage dependencies for you and automatically download and load whatever systems your projects depend on. It will also allow you to distribute your own projects to other people and make it easy to access. Because of how incredibly convenient Quicklisp is (chapeau to Zach Beane for creating it), it is probably almost a requirement to work with CL efficiently today.

Even managing your own projects with QL is simple. Either symlink or directly put them into Quicklisp's local-projects folder. QL automatically registers systems in this path with ASDF. Aside from dependency management and project loading, Quicklisp also allows you to keep track of the different versions of the libraries. Every time a new QL release occurs (usually once a month), you can directly update all your libraries to the latest versions and if anything breaks, roll back to a previous state.

While ASDF is integrated with most CL implementations, Quicklisp is not. However, installing it and getting started is not a difficult procedure, as the beta page explains the setup process well enough. As the page also illustrates, loading a project with QL is just a ql:quickload call away.

Hopefully this short summary of ASDF and Quicklisp is enough to get you started on writing projects in CL.

Written by shinmera