The usual way to develop programs in Common Lisp is to use
SLIME in Emacs, which starts an
implementation and provides a REPL. When a program needs to be running in
production, one can either execute it from source or compile it to an
executable core, for example with
sb-ext:save-lisp-and-die in SBCL.
While executable cores works well for conventional applications, they are less suitable for small scripts which should be easy to run without having to build anything.
Writing a basic script with SBCL is easy:
#!/bin/sh #| exec sbcl --script "$0" "$@" |# (format t "Hello world!~%")
Since UNIX shebangs cannot be used to run commands with more than one
argument, it is impossible to call SBCL directly (it requires the
#!/usr/bin/env sbcl --script contains two arguments). However
it is possible to start as a simple shell script and just execute SBCL with
the right arguments. And since we can include any shell commands, it is
possible to support multiple Common Lisp implementations depending on the
This method works. But if your script has any dependency, configuring ASDF can be tricky. ASDF can pick up system directory paths from multiple places, and you do not want your program to depend on your development environment. If you run your script in a CI environment or a production system, you will not have access to your ASDF configuration and your systems.
Fortunately, ASDF makes it possible to manually configure the source registry
at runtime using
asdf:initialize-source-registry, giving you total control
on the places which will be used to find systems.
For example, if your Common Lisp systems happen to be stored in a
directory at the same level as your script, you can use the
#!/bin/sh #| exec sbcl --script "$0" "$@" |# (require 'asdf) (asdf:initialize-source-registry `(:source-registry :ignore-inherited-configuration (:tree (:here "systems"))))
And if you store all your systems in a Git repository, you can use
submodules to include a
systems directory in every project, making it simple to manage the systems
you need and their version. Additionally, anyone with an implementation
installed, SBCL in this example, can now execute these scripts without having
to install or configure anything. This is quite useful when you work with
people who do not know Common Lisp.
Of course, you can use the same method when building executables: just create a script whose only job is to setup ASDF, load your program, and dump an executable core. This way, you can make sure you control exactly which set of systems is used. And it can easily be run in a CI environment.