Let's say I build an application on top of net.aserve
and bordeaux-threads
. My package declaration might look like this:
(defpackage :my-package
(:use :cl :net.aserve :bordeaux-threads)
(:export …))
I use Quicklisp, so I run (ql:quickload "aserve") (ql:quickload "bordeaux-threads")
in SLIME before compiling my package, and everything is fine.
Of course, tomorrow I start up SLIME again and I have to remember to issue the QUICKLOAD
s before I compile, otherwise I'm in for trouble.
I could put something like
(eval-when (:compile-toplevel)
(ql:quickload "aserve")
(ql:quickload "bordeaux-threads"))
at the top of my package—it's what I've done for development—but I have a feeling it's not a good idea to force a package manager on a user.
Is there a better alternative?
If you don't want to include a quicklisp call in the deployed source code at all, separate the quickproject system definition file from the rest of the source.
At the top of the source, just before the defpackage
call, add the necessary (require ...)
's for your package dependencies. This guarantees that those lisp packages are loaded (somehow) before proceeding, but does not specify 'how' those packages get loaded. They could be loaded by running the ql:quickload :my-package
call (using quickproject), which would first load the dependencies, and then run through the require calls when loading the source. Or possibly a user could load the source directly (without calling ql:quickload
), and the dependencies would be loaded during the require call, if those dependencies can be found on the *module-search-path*
. This technique, as you said, would allow the end user to use whatever build tool he/she wants to load your source.
After experimenting with this for a few minutes, it seems that quicklisp latches into the require function call, so that if quicklisp is installed, and (require :bordeaux-threads)
e.g., is called, lisp will use quicklisp to download and install that dependency. This is a very nice feature (IMO), because it allows the Common Lisp standard require
function to act as the interface layer, and abstracts the specific build tool used to satisfy the dependency. Quicklisp can latch into the require, asdf latches into it (IIRC), etc.
So to answer your question, quicklisp calls should not go anywhere in the deployed source code, and requires
should be used to ensure that dependencies are loaded before the package definition file is evaluated. If someone has quicklisp installed before loading the package definition file, those requires will be satisfied by using quicklisp to download and install the dependencies. If someone has asdf installed, those dependencies will be satisfied with that build tool. And if someone already has the dependencies installed (using some other technique), the requires will simply be passed over.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With