ASDF and Quicklisp: Two Layers of One System
ASDF (Another System Definition Facility) is the build tool that knows how to compile and load a collection of Lisp source files in dependency order, described by a .asd file; Quicklisp is the layer on top that knows how to find, download, and install a library and its transitive dependencies from a curated distribution called quicklisp-dists. When you run (ql:quickload :alexandria), Quicklisp resolves the dependency graph, fetches any missing archives from its mirror, and then hands off to ASDF to actually compile and load the .lisp files in the right order — the two tools solve genuinely different problems and neither replaces the other.
Cricket analogy: ASDF is like the ground staff who know the exact sequence to prepare a pitch — rolling, watering, mowing — while Quicklisp is like the tour logistics team that first has to get the equipment and personnel to the venue before ground staff can even start.
Defining a System with defsystem
A library declares its own structure in a .asd file using asdf:defsystem, listing :depends-on for other systems it needs and :components for its own source files, often nested into modules with :file entries that specify load order explicitly. This declarative dependency graph is what lets ASDF avoid loading a file before its dependencies are ready — a utils.lisp defining a package must load before a main.lisp that uses symbols from that package, and defsystem's :serial t or explicit :depends-on component lists encode exactly that ordering constraint.
Cricket analogy: It's like a team sheet that specifies not just who's playing but the batting order and which player must be padded up before another can walk in, so the innings can't proceed out of sequence.
Managing Local Projects and Version Pinning
Quicklisp looks for systems in two places: its own downloaded dists under ~/quicklisp/dists, and a local-projects directory (~/quicklisp/local-projects/) that you can symlink your own in-development systems into, so (ql:quickload :my-app) picks up your working copy instead of a published release. For reproducibility across machines or CI, Quicklisp supports pinning to a specific dist version via ql-dist:install-dist with a dated release URL, or increasingly teams use Ultralisp (a rolling, more frequently updated distribution) or vendor dependencies directly rather than relying on quicklisp-dists' slower release cadence.
Cricket analogy: It's like a domestic player being fast-tracked into the national squad's training nets directly, bypassing the usual selection pipeline that others go through to get picked.
;; my-app.asd
(asdf:defsystem "my-app"
:description "Example application"
:author "Jane Coder"
:depends-on ("alexandria" "cl-ppcre" "my-app/utils")
:serial t
:components ((:file "package")
(:file "main")))
(asdf:defsystem "my-app/utils"
:depends-on ("alexandria")
:components ((:file "utils")))
;; In the REPL:
(ql:quickload :alexandria) ; installs from quicklisp-dists if missing
(push #p"~/projects/my-app/" asdf:*central-registry*)
(ql:quickload :my-app) ; loads local system + its dependenciesQuicklisp caches every downloaded archive locally, so once a system has been loaded once, subsequent (ql:quickload :system) calls in new REPL sessions are fast local loads with no network access required.
Because quicklisp-dists releases only periodically (often monthly), a critical bug fix pushed to a library's GitHub repo today may not reach Quicklisp for weeks; for time-sensitive fixes, symlink the patched checkout into local-projects rather than waiting for the next dist release.
- ASDF is the build system that compiles and loads files in dependency order via .asd system definitions.
- Quicklisp is the package manager layer that resolves, downloads, and installs libraries and their dependencies, then delegates to ASDF.
- asdf:defsystem declares :depends-on and :components, encoding explicit load-order constraints.
- local-projects/ lets Quicklisp load your own in-development systems ahead of published releases.
- quicklisp-dists releases periodically, so bug fixes can lag; local-projects or Ultralisp bypass that lag.
- ql:quickload both fetches missing dependencies and hands off to ASDF to actually compile and load them.
- Downloaded systems are cached locally, so repeated quickloads across sessions require no network access.
Practice what you learned
1. What is the fundamental difference between ASDF and Quicklisp?
2. In a .asd defsystem form, what does :depends-on specify?
3. How can you make Quicklisp load your own in-development system instead of a published release?
4. Why might a bug fix pushed to a library's GitHub repo not be usable via (ql:quickload ...) immediately?
Was this page helpful?
You May Also Like
File I/O in LISP
How Common Lisp reads and writes files using streams, with-open-file, and reader/printer control for both text and binary data.
Error Handling and Conditions
How Common Lisp's condition system goes beyond try/catch, letting programs signal, inspect, and interactively recover from errors using restarts.
Scheme vs Common Lisp
The core philosophical and technical differences between Scheme's minimalist design and Common Lisp's large, industrial standard.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics