I am currently have a small program in Common Lisp, which I want to run as a shell script. I am using the SBCL and perfectly fine with this so will prefer to stay on this platform. :)
I am aware about the --script
option and it works flawlessly except for (ql:quickload)
form.
My program uses the CL-FAD, which loads through ql:quickload
(I think I should mention that it is package-loading function from quicklisp). When script runs up to evaluating the
(ql:quickload :cl-fad)
form, it breaks with the next error:
package "QL" not found
Program is packed in the single source file, which has following header:
(defpackage :my-package
(:use :common-lisp)
(:export :my-main-method))
It is simple automation executable, so I decided (maybe erroneously) not to write any ASDF system. It exports single function which should be run without any arguments.
For this program I am currently trying to write the launcher script, and this is what I am staring at:
#!/usr/bin/sbcl --script
(load "my-program.lisp")
(in-package :my-package)
(my-main-method)
This three lines (not counting the shebang) is what I am want to automate. As I read in documentation, script with this shebang can be called as simple ./script.lisp
, and it really does this... with the error described before.
What I need to add in the launcher for :cl-fad
to load properly? Documentation states that with --script
option SBCL doesn't load any init file, so do I really need to copypaste the lines
#-quicklisp
(let ((quicklisp-init (merge-pathnames "systems/quicklisp/setup.lisp"
(user-homedir-pathname))))
(when (probe-file quicklisp-init)
(load quicklisp-init)))
(which ql:add-to-init-file
adds to .sbclrc), to my launcher script?
Maybe I have some deep architectural flaw in my program setup?
And yes, when I enter the lines which I try to automate in REPL in the sbcl itself, program runs as expected.
You are doing everything right.
Basically, before you can use quicklisp
, you need to load it (currently, it's not bundled with SBCL, although it may change in the future). There are various ways to do it. For example, you can load your .sbclrc
with the quicklisp init:
#!/usr/bin/sbcl --script
(load ".sbclrc")
(load "my-program.lisp")
(in-package :my-package)
(my-main-method)
or just paste those lines in your script, like you have suggested.
Creating a dedicated version of core image is a good option. You may:
load quicklisp
and sb-ext:save-lisp-and-die
in a new image. You write a shell/bat script named, say qlsbcl
, like this:
sbcl --core <my-new-image-full-path-location> "$@"
grab clbuild2
at http://gitorious.org/clbuild2 and run clbuild lisp
. You'll have to symlink clbuild to a binary directory in your path and tweak some scripts a bit if your quicklisp
is not in the common place ~/quicklisp (https://gist.github.com/1485836) or if you use ASDF2
(https://gist.github.com/1621825). By doing so, clbuild
create a new core with quicklisp
, ASDF
and anything you may add in conf.lisp. Now the shebang may look like this:
#!/usr/bin/env sbcl --noinform --core <my-clbuild-install-directory>/sbcl-base.core --script
The advantage of clbuild
is that you may easily create and manage core and quicklisp installation from shell for sbcl
(by default) or any other modern CL like ccl64
implementation. Mixing the two techniques (script and clbuild
) will solve your problem.
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