Issue using shebang to run SBCL Common LISP script as executable - common-lisp

I've been trying to learn Common Lisp with SBCL and I've ran into issues executing my code. Everything works fine using sbcl --script exec.lisp (regardless of if I have specified a shebang line) but I can't seem to execute the same file with a shebang line directly as ./exec.lisp. While I've most likely misunderstood something the manual does from my understanding imply that this should be possible. My exec.lisp script looks identical to the one in the example (and it has been given executable privileges chmod a+x exec.lisp)
#!/usr/local/bin/sbcl --script
(write-line "Hello, World!")
but instead of the desired output I receive :
$ ./exec.lisp
./exec.lisp: line 2: write-line: command not found
I've made sure that the path to sbcl is correct)
EDIT: I'm using mac OS.

had same problem on MacOS, changed to:
#!/usr/bin/env sbcl --script
worked.

Using GNU Core Utilities on Arch Linux here:
#!/usr/bin/env -S sbcl --script
(write-line "😻")

I would check the path supplied for sbcl (does it match the output of which sbcl ?)
I tried the following (running MacOS Mojave 10.14.4, SBCL version 1.4.16, obtained using nix instead of brew, but I doubt that makes a difference):
> $ which sbcl
/Users/abrahma/.nix-profile/bin/sbcl
> $ bat test.lisp
───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
β”‚ File: test.lisp
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 β”‚ #!/Users/abrahma/.nix-profile/bin/sbcl --script
2 β”‚ (write-line "Hello world from Lisp !")
3 β”‚
───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
> $ l
.rwxr-xr-x 88 abrahma 21 May 15:54 test.lisp
> $ ./test.lisp
Hello world from Lisp !

Related

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

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

How to use additional flags when creating lisp script file to start from console

I want to create a .lisp file which I can start as script, i.e., with a leading #!/bin/usr/sbcl --script. This works just fine.
File:
#!/usr/bin/sbcl --script
(format t "test~%")
Output:
$> ./test.lisp
test
However, I also need to adjust the dynamic space size for that particular script to work. But this somehow prevents the --script flag from working
File:
#!/usr/bin/sbcl --dynamic-space-size 12000 --script
(format t "test~%")
Output:
$> ./test.lisp
This is SBCL 1.4.5.debian, 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.
*
How can I increase the dynamic space size while keeping the convenience of starting the lisp program/script from the command prompt?
This is a general limitation of shebang lines and not SBCL specific.
Newer env versions (in GNU β€” FreeBSD has had this a bit longer) understand a -S option to split the argument:
https://www.gnu.org/software/coreutils/manual/html_node/env-invocation.html#g_t_002dS_002f_002d_002dsplit_002dstring-usage-in-scripts
#!/usr/bin/env -S sbcl --dynamic-space-size 9000 --script
Apparently the #! considers everything following the command as a single string and thus --dynamic-space-size 12000 --script is treated as one and not as a parameter and a flag.
My current solution is to create an additional .sh file:
#!/bin/bash
sbcl --dynamic-space-size 12000 --script ./test.lisp $#
However, this has the obvious downside that the script needs to be started from the same directory as the .lips file. Consequently, I am still looking for the 'perfect' solution and this is rather a stop-gap.

How to fix asdf error when using buildapp on a quicklisp project

I've been making my first quicklisp project lately and I wanted to share it. I've put it on github, but not everyone has emacs + slime + quicklisp installed so I wanted to make an executable I could put with the code.
To do this I'm using buildapp and following the steps laid out in this stackoverflow answer.
$ sbcl --no-userinit --no-sysinit --non-interactive \
--load ~/quicklisp/setup.lisp \
--eval '(ql:quickload "ltk-colorpicker")' \
--eval '(ql:write-asdf-manifest-file "quicklisp-manifest.txt")'
$ buildapp --output out \
--manifest-file quicklisp-manifest.txt \
--load-system ltk-colorpicker \
--entry colorpicker
After running those commands I get the following error:
Fatal INPUT-ERROR-IN-LOAD:
READ error during LOAD:
The symbol "*SYSTEM-DEFINITION-SEARCH-FUNCTIONS*" is not external in the ASDF/FIND-SYSTEM package.
Line: 16, Column: 90, File-Position: 15267
Stream: #<SB-INT:FORM-TRACKING-STREAM for "file /home/nathan/quicklisp/local-projects/ltk-colorpicker/dumper-2SKVI5f7.lisp" {1001B70F83}>
The main problem here is that I don't even have a clue at how to begin to fix it. I've seen this gibhub issue, but that had to do with problems with Homebrew and it never even mentions buildapp. It's all very confusing. And I hope I could get some help.
Thanks in advance for any answers.
I can reproduce the error. As suggested in the comments, you can build an up-to-date version of buildapp as follows:
$ sbcl
* (ql:quickload :buildapp)
...
* (buildapp:build-buildapp
(merge-pathnames "bin/buildapp" (user-homedir-pathname)))
This build $HOME/bin/buildapp. When I use the new binary, there is no error anymore.
You can also avoid generating an executable (that can end up being outdated) by systematically calling the buildapp::main function from Common Lisp; you will then always have the version that corresponds to the current release of quicklisp:
* (buildapp::main
'("BUILDAPP" ;; argv[0] must exist but the value is not important
"--manifest-file" "/tmp/quicklisp-manifest.txt"
"--load-system" "drakma" "--output" "/tmp/test"))
Some extra info from my point:
The solution was to use the newest version of buildapp as #coredump mentioned. I updated by going to the github page, downloading the zip and doing the following commands at the point where buildapp is stored.
$ make
$ cp buildapp /usr/bin
(This of course only works on linux.)
This is not an elegant solution but buildapp hasn't updated in 4 years, I think it's a safe enough bet. I also made a mistake with the command. The --entry part is wrong. It should have been: `--entry ltk-colorpicker::main`` where main is a function that takes one variable since that's required by the spec.
Main is just this: (main (i) (declare (ignore i)) (colorpicker))

How to execute a common lisp text file (clozure cl)?

I am a beginner at Lisp, having only used DrRacket for some dabbling in Racket/Scheme. I have had much trouble figuring out how to run a .lisp file with Clozure CL for Windows. I tried running a .lisp file in SBCL on Ubuntu (running on virtualbox) without success as well.
I should mention that I've looked into the related questions about running files but I wasn't able to see any direct solution. Some are using .bat files, some are "creating applications" with Clozure CL's image (or something along those lines).
For SBCL in Ubuntu, I've tried:
sbcl lisptest.lisp \ The python/forth way.
(load "lisptest.lisp")
(load lisptest.lisp)
(--load lisptest.lisp)
:cd C:\Temp
(:cd C:\Temp)
and more.
I also tried to run it from notepad++:
cmd /k C:\Temp\ccl-1.11-windows\ccl\wx86cl64.exe "$(FULL_CURRENT_PATH)"
which is how I usually execute python files, but this method hasn't been successful.
**I will definitely start learning to use Emacs and Slime (Emacs is the obvious choice for lisp). But for the sake of knowledge, I would appreciate some tips on the alternative, basic-text-editor way of getting something trivial like "hello world" to print without my typing it explicity into the REPL and instead interpreting (or compiling) a text file with the instruction.
Thanks for your help.
Typically programs have help - did you look at that?
SBCL, Ubuntu, from the shell:
A Common Lisp file:
$ cat test.lisp
(format t "Hello World~%~%")
SBCL shows help:
$ sbcl --help
Usage: sbcl [runtime-options] [toplevel-options] [user-options]
Common runtime options:
--help Print this message and exit.
--version Print version information and exit.
--core <filename> Use the specified core file instead of the default.
--dynamic-space-size <MiB> Size of reserved dynamic space in megabytes.
--control-stack-size <MiB> Size of reserved control stack in megabytes.
Common toplevel options:
--sysinit <filename> System-wide init-file to use instead of default.
--userinit <filename> Per-user init-file to use instead of default.
--no-sysinit Inhibit processing of any system-wide init-file.
--no-userinit Inhibit processing of any per-user init-file.
--disable-debugger Invoke sb-ext:disable-debugger.
--noprint Run a Read-Eval Loop without printing results.
--script [<filename>] Skip #! line, disable debugger, avoid verbosity.
--quit Exit with code 0 after option processing.
--non-interactive Sets both --quit and --disable-debugger.
Common toplevel options that are processed in order:
--eval <form> Form to eval when processing this option.
--load <filename> File to load when processing this option.
User options are not processed by SBCL. All runtime options must
appear before toplevel options, and all toplevel options must
appear before user options.
For more information please refer to the SBCL User Manual, which
should be installed along with SBCL, and is also available from the
website <http://www.sbcl.org/>.
Using the script option from above:
$ sbcl --script test.lisp
Hello World
The same for Clozure CL
$ ccl --help
usage: ccl <options>
where <options> are one or more of:
-h, --help : this text
-V, --version : print (LISP-IMPLEMENTATION-VERSION) and exit
-K, --terminal-encoding : specify character encoding to use for *TERMINAL-IO*
-n, --no-init : suppress loading of init file
-e, --eval : evaluate <form> (may need to quote <form> in shell)
-l, --load : load <file>
-T, --set-lisp-heap-gc-threshold : set lisp-heap-gc-threshold to <n>
-Q, --quiet : if --batch, also suppress printing of heralds, prompts
-R, --heap-reserve <n>: reserve <n> (default: 1610612736)
bytes for heap expansion
-S, --stack-size <n>: set size of initial thread's control stack to <n>
-Z, --thread-stack-size <n>: set default size of first (listener) thread's stacks based on <n>
-b, --batch: exit when EOF on *STANDARD-INPUT*
--no-sigtrap : obscure option for running under GDB
--debug : try to ensure that kernel debugger uses a TTY for I/O
-I, --image-name <image-name>
and <image-name> defaults to ccl.image
Any arguments following the pseudoargument "--" are
not processed and are available to the application as
the value of CCL:*UNPROCESSED-COMMAND-LINE-ARGUMENTS* .
Using the load option from above
$ ccl --load test.lisp --eval '(quit)'
Hello World
οΏΌ οΏΌ
Try
C:/path/to/ccl -l lisptest.lisp
This should work the same as
(load "lisptest.lisp")
If you can let us know specifically how that fails, we can be of more help.

Cannot source autojump script with zsh on archlinux

autojump on ArchLinux for some reason is not working in zsh.
Although If I switch to bash it works fine.
$ sudo pacman -S autojump
autojump: does not work on zsh
$ source /usr/etc/profile.d/autojump.sh
$ j
zsh: command not found: j
$ source /usr/etc/profile.d/autojump.bash
$ j
zsh: command not found: j
autojump: works on bash
$ bash
(bash) $ source /usr/etc/profile.d/autojump.bash
(bash) $ j
autojump: ...
My environment:
$ echo $SHELL
/bin/zsh
$ zsh --version
zsh 5.0.2 (x86_64-unknown-linux-gnu)
I use autojump on OS X with zsh, so it also doesn't look like a zsh specific issue to me.
Aren’t you supposed to use autojump.zsh instead?
Though from what I see the only thing autojump.sh is doing is sourcing autojump.zsh or autojump.bash from some place so it should work with .sh. Work if maintainers of arch have patched autojump.sh: it does not expect to find autojump in /usr/etc.
If it does not work with autojump.zsh, post the output of doing (set -x ; source /usr/etc/profile.d/autojump.zsh).
There is no /usr/etc/profile.d/autojump.zsh pushed when autojump is installed via pacman. I don't know why this is the case.
However, I performed, manual user installation and added autojump plugin in my zsh configuration that takes care of sourcing the file.
I have tried above the ways,but I solved this problem by add the
source ~/.autojump/etc/profile.d/autojump.zsh
because the I have not find the /usr/etc/profile.d/autojump.zsh
I had repeated trouble with Autojump in ZSH regardless of sourcing the .zsh version. I never found a decent fix and eventually chose to stick with ZSH and stop using Autojump.
My personal solution was to switch from Autojump to FASD. It has the same functionality of Autojump via the 'z' alias. It also allows for specifically jumping to either a file or directory.
FASD has been a reliable part of my ZSH setup and surpasses the functionality of Autojump. I wrote up my experiences with FASD at greater length on my blog at Civet.ws

Resources