For Common Lisp applications and libraries it is preferred to use a system management tool. Like ASDF or whatever your implementation may provide. A system is a collection of files with dependencies and various actions (load, compile, ...).
You can always check the state of the runtime and do something.
Example:
(unless (fboundp 'foobar)
(require "foo")
(load "bar"))
(unless (find-package 'foobar)
(require "foo")
(load "bar"))
PROVIDE
and REQUIRE
are built-in functions for exactly that. If you require a module it will be loaded, unless already provided
. Unfortunately this functionality is underspecified in the standard, but implementations may provide useful functionality.
Common Lisp runtimes have a list of features on the list *features*
. You can use that to advertise and check functionality.
Example:
In your library:
(push :cool-new-graphics-library cl:*features*)
In your application code:
(when (member :cool-new-graphics-library cl:*features*)
(funcall (find-symbol "DRAW-SPACE-SHIP" "CNGL")
:death-star))
Common Lisp provides a way to conditionalize that a read time. The following code will only be read when the :cool-new-graphics-library
feature is present, and thus it only then will be executed later:
#+cool-new-graphics-library(cngl:draw-space-ship :death-star)
Common Lisp also allows you to express some logic:
#+(and lispworks cool-new-graphics-library)
(cngl:draw-space-ship :enterprise)
#-cool-new-graphics-library(warn "no cool graphics library available")
Note that you can force Lisp to execute code at compile-time:
(eval-when (:load-toplevel :compile-toplevel :execute)
#+(and lispworks cool-new-graphics-library)
(cngl:draw-space-ship :enterprise)
#-cool-new-graphics-library(warn "no cool graphics library available")
)
For this to work the EVAL-WHEN
has to be at the toplevel in a file. That means it will not work deep in nested forms. It does work inside a toplevel PROGN
,LOCALLY
, MACROLET
and SYMBOL-MACROLET
, though.
Thus EVAL-WHEN
allows you to run code which is part of the file which is currently compiled. This code than can look for loaded systems, provided modules, available functions, and more.