require asdf failed in sbcl repl - common-lisp

I meet the following error. Any clue?
CL-USER> (require "asdf")
NIL
But the page https://common-lisp.net/project/asdf/asdf.html#Loading-ASDF said
The recommended way to load ASDF is via:
(require "asdf")
All actively maintained Lisp implementations now include a copy of ASDF 3 that you can load this way using Common Lisp’s require function.1

The specification for PROVIDE, REQUIRE says that the return value of require is implementation-dependant, but that it should signal an error if a module fails to be loaded. In your case, the NIL return value is not an error, but an indication that the operation succeeded.
Try (asdf:make "optima"), for example. Your environment should recognize the ASDF:MAKE symbol, but it might fail to load the :optima system. See Quicklisp to download and install systems.
By the way, you rarely need to require asdf (you don't need to do it in SBCL nor in CCL, at least). To be sure, you might want to restart your Lisp environment and see if the ASDF package exists.

Related

asdf:load-system after closing emacs?

When I create a new project with quickprojects, and then load it with asdf:load-system, everything works fine.
But when I come back to emacs after it has been closed and a run (asdf:load-system "system-name"), I get an error:
Component "next" not found
[Condition of type ASDF/FIND-COMPONENT:MISSING-COMPONENT]
I understood the package system to be like a project management system where I can load a package from the repl when I choose.
Which mistake am I making?
In quickproject.lisp, there is the following line:
(pushnew *default-pathname-defaults* asdf:*central-registry*
:test 'equal)
Which is the reason why the system can be loaded: the path to your new project is pushed into ASDF's *central-registry*, which acts like the PATH environment variable in POSIX to indicate where to look for systems.
This change is not persisted and the next time you start Lisp, the variable is set to its default value and the path is not set. I think Quickproject should at least warn that this is happening because it is not very intuitive1
Usually you should add your projects in a path that is visible by ASDF, as explained in 4.1 Configuring ASDF to find your systems. Pushing to *central-registry* works but is old style: 4.2 Configuring ASDF to find your systems — old style.
When using Quicklisp you can also define your projects in ~/quicklisp/local-projects/ (either directly or by using symlinks), which is a place that Quicklisp makes also visible by ASDF.
You can temporarily bind *default-pathname-defaults* to one of these known locations when creating your projects, so that it can be found again when restarting your environment:
(let ((*default-pathname-defaults*
(merge-pathnames "quicklisp/local-projects/"
(user-homedir-pathname)))
(quickproject:make-project "test-project"))
1. To Quickproject's defense, this is explained in the second sentence of the documentation:
Quickproject provides a quick way to make a Common Lisp project. After creating a project, it extends the ASDF registry so the project may be immediately loaded.

Debugging Quicklisp when the backtrace lacks information

What's your general approach when quickload fails? I guess I'd like to know the line that provoked the problem, but all I'm given is a backtrace with a reference to a bytecompiled-function. How should I proceed to determine which package, file and form causes the problem?
Update
My environment is ECL in Emacs. The backtrace is provided by the SLIME debugger.
Quicklisp uses ASDF (which usually comes preinstalled), you can try to use it directly to get more detailed error. See manual.
Put (or symlink) your system in one of the standard locations, as subdirectory for example "foo" under
~/common-lisp/ or
~/.local/share/common-lisp/source/.
Try to load it
(asdf:load-system :foo)

How to get Emacs/Slime/SBCL to recognize quicklisp packages

I am trying to get Emacs, SLIME and quicklisp to work together properly. I have the following environment set up:
Installed Emacs
Installed SLIME in Emacs
Installed SBCL
Installed quicklisp
Run (quicklisp-quickstart:install) in SBCL
Run (ql:add-to-init-file) in SBCL
Run (ql:quickload "quicklisp-slime-helper") in SBCL
Installed package cl-csv using (ql:quickload "cl-csv") in SBCL
Added (setq inferior-lisp-program "sbcl") to .emacs
Added (load (expand-file-name "~/quicklisp/slime-helper.el")) to .emacs
Restarted everything
I have a test.lisp file that starts with (ql:quickload "cl-csv") to load the package and use it. When I load the file into Emacs and run SLIME, then try to compile it using slime-compile-and-load-file, I get the error in SBCL that Package CL-CSV does not exist.
What have I missed to get these pieces working together properly?
If you compile a file which contains a statement
(ql:quickload "cl-csv")
then this call will be compiled, but not executed. That's what a compiler usually does: it compiles, but does not execute. Thus if you use some Lisp package (a namespace) later in the same file - a package which would be introduced in the system cl-csv - then it might not be present, if you have not loaded it before, by loading the system.
There are two typical solutions to this:
put the loading command in a file which one compiles (optionally) and/or loads before
use EVAL-WHEN with :compile-toplevel, :load-toplevel and :execute
Note that cl-csv is a system, organizing source files. A package is a Lisp namespace for organizing Lisp symbols. A package and a system can have the same name, but they really are two different things.
Calling ql:quickload directly is good for tests and while interacting with your development environment. If you use some systems a lot, you may quickload them inside your initialization file (in your case, ~/.sbclrc).
However, your purpose when programming is generally to develop a new system (a library, or an application, but as far as Common Lisp is concerned, this is a "system"). You generally do not need to have explicit (ql:quickload ...) calls inside your source code. Instead, you define a system where you declare dependencies and your code assumes that the appropriate dependencies are loaded.
Create and enter directory "my-system"
Create and edit "my-system.asd"
(in-package :asdf-user)
(defsystem :my-system
:depends-on (:cl-csv))
Quicklisp can find your system if you link the directory inside ~/quicklisp/local-projects/.
So the next time you restart your Lisp and want to develop on my-system, you can perform (ql:quickload :my-system) which will load all the declared dependencies.
Reinstall quicklisp at the Emacs' SLIME REPL.
The problem is that Emacs Slime (REPL) doesn't know neither whether quicklisp is installed nor where it is installed. All you have to do to fix the problem is to reinstall quicklisp at the Emacs' slime repl. ("quicklisp.lisp" file should be in the SLIME REPL's current working folder.)
M-x slime
CL-USER> (load "quicklisp.lisp")
CL-USER> (quicklisp-quickstart:install)
CL-USER> (ql:add-to-init-file)
CL-USER> (ql:quickload "quicklisp-slime-helper")
e.g.) My "~/.emacs" file:
(use-package slime
:ensure t
:defer t
:init
(setq inferior-lisp-program "clisp")
:config
(slime-setup '(slime-fancy slime-company))
:hook
(slime-mode . slime-company)
(slime-mode . (lambda ()
(load (expand-file-name "D:/util/emacs27/quicklisp/slime-helper.el"))
(add-to-list 'slime-contribs 'slime-fancy)
(add-to-list 'slime-contribs 'inferior-slime))))
(use-package slime-company
:after slime
:bind-keymap
("C-n" . company-select-next)
("C-p" . company-select-previous)
("C-d" . company-show-doc-buffer)
("M-." . company-show-location)
:config (setq slime-company-completion 'fuzzy
slime-company-after-completion 'slime-company-just-one-space))
Then, quicklisp will be reinstalled in the Emacs's HOME directory ("~/"). Now, you have installed the same quicklisp in the (a) Windows 10's HOME and (a) the Emacs' HOME. If you use quicklisp only at the Emacs' Slime REPL, the copy in the Windows 10' HOME is useless, and you can delete it.

How does one avoid loading multiple asdf files for a common lisp project?

While working through Peter Seibel's book Practical Common Lisp, I've had some difficulty understanding how to handle the Common Lisp package system in conjunction with Emacs's SLIME and quicklisp. The project he supplies has the following structure:
spam.lisp in the package com.gigamonkeys.spam, which relies on two other packages, cl-ppcre and com.gigamonkeys.pathnames.
pathnames.lisp in the package com.gigamonkeys.pathnames
spam.asd, which describes the dependencies of com.gigamonkeys.spam package
pathnames.asd, which describes the dependencies of the com.gigamonkeys.pathnames package
The only way that I've currently found to build the final target, spam.lisp, is to:
Compile and load the pathnames.asd file using SLIME (C-x C-k)
Load the com.gigamonkeys.pathname package by typing (asdf:operate 'asdf:load-op 'spam) at the REPL
Load the cl-ppcre package by typing (ql:quickload "cl-ppcre") at the REPL
Compile and load the spam.asd file using SLIME
Load the com.gigamonkeys.spam package by typing (asdf:operate 'asdf:load-op 'spam) at the REPL
This seems like an insane amount of work required to use the functions defined in a single file (spam.lisp) - I've got to be doing something wrong. Is there some way to load spam.lisp and, recursively, its dependencies, with fewer commands?
Source + Full Story
Long story short, packages are bags of symbols and systems describe
relationships between files and other systems.
So, using your structure here is a simple system definition:
(asdf:defsystem #:spam-filter
:serial t
:description "Simple Spam Filter"
:author "PCL"
:depends-on (#:cl-ppcre
#:com.gigamonkeys.pathnames)
:components ((:file "package")
(:file "spam")))
Now, I'll suppose the system com.gigamonkeys.pathnames is in
~/src/lisp/com/gigamonkeys/pathnames/ and the spam filter in
~/src/lisp/spam-filter/.
M-xslimeRET
,cd~/src/lisp/com/gigamonkeys/pathnamesRET
(push (truename ".") asdf:*central-registry*)
,cd~/src/lisp/spam-filterRET
(push (truename ".") asdf:*central-registry*)
(ql:quickload :spam-filter)
Because Quicklisp relies on ASDF to load systems, you've to add the systems directories
in ASDF search-path.
You could also put your systems in Quicklisp's search path by adding
them in ~/quicklisp/local-projects/. You can either store your code
there or use symbolic links.
PS: You can find
here
a slime-shortcut that allows me to write ,addRET
instead of (push (truename ".") asdf:*central-registry*).
And just below another slime-shortcut to quickload a system.
(,qlsome-system-nameRET)
A little bit terminology:
a Package is a Common Lisp standard feature. A package is a namespace for symbols. Nothing more. It is not a file, not a module, not a library and not tied to any such thing. It's not even a namespace for functions, variables or classes. Just for symbols. There is a convention to put the definitions that setup a package into a file of its own. But that is just a convention.
a System is used to define, load and compile all files which make up a software library or application. The idea of a System is old (over thirty years). ASDF (Another System Definition Facility) is a popular and free implementation of that idea. Kent Pitman wrote in 1984 about The Description of Large Systems.
A part of such a system facility is a registry, from where all systems can be found. A system definition describes the files it consists of and all the systems it depends on. Typically such a registry is a directory in the file system and/or a registry (a variable, ...) in a running Lisp.
On loading a particular system, the system tool looks into the registry and finds it, loads the definition, loads recursively all needed systems, and then loads all the files.
See the ASDF manual: Configuring ASDF to find your systems

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