How to make Quicklisp available to a script that runs from a Shebang? - common-lisp

I've been playing around with Quicklisp lately, and have this minor problem working with scripts with Shebangs.
Setup
I did the following:
Downloaded quicklisp with curl https://beta.quicklisp.org/quicklisp.lisp -o /tmp/quicklisp.lisp
Installed it with (quicklisp-quickstart:install) while having /tmp/quicklisp loaded in the environment.
Added Quicklisp to init file using (ql:add-to-init-file)
Problem
For a script that needs Quicklisp (specifically ASDF), I can run it with sbcl --load ~/quicklisp/setup.lisp --script start.lisp just fine. However, when I run it as a standalone script with the Shebang /usr/bin/env sbcl --script, it fails with an error saying that it isn't able to find things like UIOP, etc. unless I place the below two lines in the script itself:
(load "~/quicklisp/setup.lisp")
(ql:quickload "asdf")
You can find my stupid experiment here, and the script in question here.
PS: Any pointers would be really helpful.
PPS: I'm sure it's a stupid mistake on my end, forgive me.

In that case you need:
(require :asdf)
TBH, I don't know exactly why. --script equals to --no-sysinit --no-userinit --disable-debugger --end-toplevel-options, so it's a lot we ignore. (thus loading quicklisp's setup.lisp seems required too, because it won't be loaded by your .sbclrc, which is where Quicklisp adds this little snippet)
It's a setting I have needed in other environments, such as a CI.

I would use roswell - which makes standalone scripts available which use Common Lisp code.
I described setting up roswell here. It is super easy.
I describe there system-wide installation of roswell or also how to locally install roswell in ubuntu, mac and windows.
Or you could also directly lookup on roswell's site.
Using roswell would have the advantage that you can use any roswell-installable Common Lisp implementations, which are:
Candidates impls for installation are:
abcl-bin
allegro
ccl-bin
clasp-bin
clasp
clisp
cmu-bin
ecl
mkcl
sbcl-bin
sbcl
sbcl-source
not only sbcl alone.
And roswell allows scripts which are call-able directly from the shell while written in Common Lisp.
From inside roswell $ ros ... commands , quicklisp is available. So $ ros install xxx uses usually quicklisp to install xxx.
Using roswell, you can make any Common Lisp program callable from the bash by a single command - including your script - written in common lisp.
Look at e.g. here:
https://roswell.github.io/Roswell-as-a-Scripting-Environment.html

Related

Portacle Common Lisp connection to Swank Hangs

I have a Portacle installation on Windows 10. Sometimes it works properly, sometimes it doesn't. The problem occurs when Portacle is started and it attempts to connect to Swank. Emacs freezes, and I cannot edit anything in the editing windows (therefore, sorry, I cannot copy the messages to show you). The Emacs editor looks like this:
That's it. If I make Emacs full screen, the editor window is blank.
Thoughts, please.
I once wrote this article - and there I explain also how to install Roswell and with the help of Roswell a Common Lisp implementation and connect with emacs/slime. Roswell is definitely to be preferred over Portacle.
If you install first scoop, installing Roswell becomes trivial. (scoop install roswell).
https://towardsdatascience.com/how-to-set-up-common-lisp-ide-in-2021-5be70d88975b
Once, Roswell is installed, you install sbcl easily by ros install sbcl. You can install then several versions of sbcl - but especially all the other Common Lisp implementations, too. And switch between them by ros use command. How to install emacs and slime is explained there, too.
Portacle is bound to sbcl and cannot jump between versions and implementations. Plus Roswell is not buggy like Portacle is.

Can I run a script with LispWorks, like with SBCL's "--script" option?

I mean with SBCL I can run a script as easy as sbcl --script piece-of-code.lisp. But I can't find an obvious way to do so with LispWorks. Of course there's always a deploy and run option, but it requires a build script for every little exercise.
Is there a way to run a script with LispWorks without building an executable or running it from listener manually?
I'd recommend you create lispworks console, like in:
http://www.lispworks.com/documentation/lw60/LW/html/lw-177.htm#83244
Then, you can use lw-console -init foo.lisp without IDE.
The sbcl --script is to make sbcl aware the first line of your code might be #!/usr/bin/sbcl ... and LispWorks doesn't seem to have that.
However, if you just want to run a script and not make it executable, then you can write:
lispworks -init my-lisp-init
And it will load my-lisp-init.lisp if I understood the documentation right
The various command line option for the latest LispWorks 6.1 are described here:
http://www.lispworks.com/documentation/lw61/LW/html/lw-517.htm#pgfId-891723

Test if quicklisp has already been installed in clisp

I'm working on a project in Common Lisp which makes use of a package installed with quickload. I'm making a bash script in the root of the project which tests if the necessary programs are installed, and if it all checks out, it runs a lisp script which loads my project. I want some way of testing if quicklisp is installed, so that I can have it can ask the user for permission to download and install quicklisp automatically. Is there a way to test for this? Quicklisp is installed within clisp, not as a package on the OS, so using the bash builtins for testing if a program's installed won't work.
From inside Lisp: Quicklisp puts :quicklisp onto the cl:*features* list.
If Quicklisp is already loaded into Lisp, then this symbol is on the *features* list.
To test that:
(member :quicklisp *features*)
In Lisp code you can also use the conditional reader:
#+quicklisp (print "quicklisp installed")
or
#-quicklisp (print "quicklisp not installed")

How to use install package into system directory for SBCL by QuickLisp?

I'm using quicklisp as the package management tool for SBCL.
However, sometimes I found it's not very convenient to install a package to the HOME directory of current user by ql:quickload. (For example, if I use (ql:quickload "xmls") to install xmls, other users can't use it.)
What's worse, I'd like to run the lisp code as a script. So when I use the package installed by quicklisp, I need to add the absolute path of that package uncomfortably, such as:
#!/usr/bin/sbcl --script
(require 'xmls "..../quicklisp/dists/quicklisp/software/xmls-1.4/xmls")
If I use (require 'xmls), the compiler will not work because it cannot find that package if I use the --script options.
Does anyone knows how to solve the problem so that I can use --script and require(no need to add absolute path) at the same time?
I don't know of a good solution to this problem. The solution I use is to not write scripts with Common Lisp; I usually write applications that I use interactively from CL sessions. When I do want to run things from the command-line, I use buildapp for it, and use ql:write-asdf-manifest-file to create a file to pass to --manifest-file for buildapp.
I sometimes wish there was a better solution, but it'll probably take some work by someone (hopefully not me).
I just do sudo sbcl and this way it'll be installed for every user on my PC - it's OK, because it's my home PC, so there's no danger.
One thing I could think of is maybe symlinking the directory where ql installs stuff to something that is easier to access, like $HOME/packages -> .../quicklisp/software or something?

cffi installation

I'm trying to install cffi package into sbcl.
First, I tried clbuild that is recommended on the cffi installation page.
When I tried to run :
clbuild quickload cffi
I was given an error saying :
The function ASDF::SOURCE-REGISTRY is undefined.
I then tried asdf-install, it end up complaining about
Component "cffi-examples" not found
Any help on this would be appreciated.
UPDATE
For asdf-install, I'm running sbcl with slime. It seems that whenever it complains about a component that is missing, that component is actually installed. I just have to abort the debugger and restart Emacs, start slime, and do that install again, and it will finish successfully. If I don't run it with slime, just running it inside sbcl prompt in terminal, it will keep complaining about the component missing nonstop.
So to get cffi installed with asdf-install, I had to restart Emacs for about 4-5 times.
I'm not sure if there is configuration issue with sbcl?
I suppose I should ask this question in different thread.
It's pretty easy with Quicklisp. To install Quicklisp:
Download http://beta.quicklisp.org/quicklisp.lisp
sbcl --load quicklisp.lisp
(quicklisp-quickstart:install)
(ql:add-to-init-file)
Then you can install and load CFFI like so:
(ql:quickload "cffi")
I wrote a bit about how I manage small projects and their required libraries at Making a small Lisp project with quickproject and Quicklisp.
Here are the exact steps for manual installation under Windows 7:
First, download and install SBCL from:
http://www.sbcl.org/platform-table.html
Then download and untar (tar xzf ...) babel, alexandria, trivial-features, and cffi.
Then, start SBCL, load ASDF, and add the paths to these systems to asdf:*central-registry*:
C:\Program Files\Steel Bank Common Lisp\1.0.49>sbcl.exe --core sbcl.core
This is SBCL 1.0.49, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
This is experimental prerelease support for the Windows platform: use
at your own risk. "Your Kitten of Death awaits!"
* (load "asdf/asdf")
T
* (push "C:/Users/dhl/build/asdf/babel_0.3.0/" asdf:*central-registry*)
("C:/Users/dhl/build/asdf/babel_0.3.0/")
* (push "C:/Users/dhl/build/asdf/alexandria/" asdf:*central-registry*)
("C:/Users/dhl/build/asdf/alexandria/" "C:/Users/dhl/build/asdf/babel_0.3.0/")
* (push "C:/Users/dhl/build/asdf/trivial-features_0.6/" asdf:*central-registry*)
("C:/Users/dhl/build/asdf/trivial-features_0.6/"
"C:/Users/dhl/build/asdf/alexandria/" "C:/Users/dhl/build/asdf/babel_0.3.0/")
* (push "C:/Users/dhl/build/asdf/cffi_0.10.6/" asdf:*central-registry*)
("C:/Users/dhl/build/asdf/cffi_0.10.6/"
"C:/Users/dhl/build/asdf/trivial-features_0.6/"
"C:/Users/dhl/build/asdf/alexandria/" "C:/Users/dhl/build/asdf/babel_0.3.0/")
*
(Of course, you'd have to give your paths to the libraries instead of `"C:/Users/dhl/...")
Then, you can load CFFI:
* (asdf:load-system 'cffi)
[much compilation output]
T
*
Now, that's pretty much the bare bones way to install systems for Common Lisp. Nowadays, there is Quicklisp, which is easy to use and covered by Xach's answer. Also, note that there are better ways to register your systems with asdf, like symlinking the asd-files to a single directory on platforms that support symlinking, and ASDF 2 provides a source-registry facility, so you won't have to deal with asdf:*central-registry* at all (I still like it for REPL use).
All in all, I guess Xach's answer provides the easiest way to get a working installation of CFFI, so I recommend his answer and will vote it up, but I already started writing my article before he posted it, and maybe its of some use to you to know how to do things manually.

Resources