I have downloaded a large software project FriCAS which I have compiled from source and using SBCL. This was just a matter of using GNU .configure - I am a complete Lisp newbie.
However, in order to add some further functionality I have - by very carefully following directions - installed quicklisp and a few extra packages. So far so good.
Here's my issue: I am trying to compile an external lisp file for use in the system. I need to make quicklisp and its packages visible to the compiler. So I've copied my .sbclrc file to the top of my lisp file:
#-quicklisp
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
(user-homedir-pathname))))
(when (probe-file quicklisp-init)
(load quicklisp-init)))
I have followed this with
(eval-when (:compile-toplevel)
(ql:quickload "f2cl-lib"))
I have already installed f2cl-lib
with quicklisp. However, my compiler (within FriCAS) immediately aborts with
; caught ERROR:
; READ error during COMPILE-FILE:
;
; Package QL does not exist.
I'm a bit stumped here - there's probably something trivial and obvious which is missing, but as I say from a newbie perspective I don't know what it is.
Looks like a FAQ. See also the documentation for
eval-when
.The File Compiler
Remember, a file compiler compiles forms and does not execute them. It just generates code for later execution. Generally. Though, in Common Lisp there are some exceptions to this rule: for example a macro, used in the source code, will be run by the file compiler. But Common Lisp also allows us to tell the file compiler to execute code at compile time, that's one of the use cases of
eval-when
.Your example simplified
If you have a file:
Then the file compiler will generate code for loading the file, but it will not load the file.
Next, the file compiler sees a second form, where the file compiler is instructed to execute a statement at compile time (and only at compile time), so
(foo:bar)
will be executed at compile time. But it is worse: Since the loading code has not been executed yet, the packageFOO
is unknown, and the form(foo:bar)
will be read at compile time, the reader already complains at compile time that the packageFOO
does not exist.The use of EVAL-WHEN
What you need to do, is to tell the file compiler to actually load the stuff it needs during compilation. The file already contains an
eval-when
form, so that should give you a hint: useeval-when
. It has three situations::compile-toplevel
-> the file compiler executes the enclosed forms:load-toplevel
-> the file compiler generates code so that the code will be executed when loading the code:execute
Make sure that those situations are mentioned, when the code should be executed.
Possible solutions
So there are possible solutions:
EVAL-WHEN
to be able to execute forms by the file compiler