I have the following directory structure:
my-project/
├── my-project.asd
├── package.lisp # defpackage.
├── utils.lisp # Functions used by main.lisp.
└── main.lisp # Main program.
my-project.asd
:
(defsystem "my-project"
:components ((:file "package")
(:file "utils")
(:file "main")))
package.lisp
:
(defpackage :com.example
(:use :cl))
utils.lisp
:
(in-package :com.example)
(defun double (x)
(* x 2))
main.lisp
:
(in-package :com.example)
(format t "~a" (double 3))
The problem is: how do I compile and run main.lisp
using ASDF?
I was able to compile and run the program by:
$ mv my-project ~/common-lisp/.
$ sbcl
* (require :asdf)
* (asdf:load-system :my-project)
However, this is incredibly silly. I do not want to move my project into ~/common-lisp/
just to run it. I want to compile and run the program right from the project directory itself. The my-project/
directory could be anywhere, and I want it to be possible to be placed anywhere. In other words, I would like to load the system from the current directory.
Think of make
, where I can compile files right from the directory of the Makefile
itself. How do I similarly compile and run a Common Lisp program from the directory of the *.asd
file itself?
(I am using SBCL version 1.4.5 and ASDF version 3.3.1)
I found that it is possible to do the following:
$ sbcl
* (require "asdf")
* (asdf:load-asd (merge-pathnames "my-project.asd" (uiop:getcwd)))
* (asdf:load-system :my-project)
Note:
(require "asdf")
is the recommended way to load ASDF, according to the "Loading ASDF" section of the ASDF manual.
NB: all implementations except GNU CLISP also accept
(require "ASDF")
,(require 'asdf)
and(require :asdf)
. For portability’s sake, you should use(require "asdf")
.
asdf:load-asd
must be an absolute path and might not fail with any error when the path given to it is incorrect (!), so make sure that the given absolute path is correct.
Using cl:load
instead of asdf:load-asd
might also appear to work, but the ASDF manual explicitly warns against this practice:
Indeed, ASDF does not load
.asd
files simply withcl:load
, and neither should you. You should let ASDF find and load them when you operate on systems. If you somehow must load a.asd
file, use the same functionasdf:load-asd
that ASDF uses. Among other things, it already binds the*package*
toasdf-user
. Recent versions of SLIME (2013-02 and later) know to do that when youC-c C-k
when you use theslime-asdf
contrib.