Setting up a Common Lisp environment
See the relevant section of my dotfiles for the configuration files.
1. SBCL
2. Quicklisp
Quicklisp is a library manager for Common Lisp.
Download the install script.
wget https://beta.quicklisp.org/quicklisp.lisp
Load it.
sbcl --load quicklisp.lisp
Install Quicklisp. I prefer to install it in
~/.quicklisp
.(quicklisp-quickstart:install :path ".quicklisp/")
Notify SBCL about Quicklisp. Add this to your
.sbclrc
file:#-quicklisp (let ((quicklisp-init (merge-pathnames ".quicklisp/setup.lisp" (user-homedir-pathname)))) (when (probe-file quicklisp-init) (load quicklisp-init)))
2.1. Optional
Run sbcl
again to check everything is right by trying to download a
package.
(ql:quickload "vecto")
Output:
To load "vecto": Load 1 ASDF system: asdf Install 5 Quicklisp releases: cl-vectors salza2 vecto zpb-ttf zpng ; Fetching #<URL "http://beta.quicklisp.org/archive/salza2/2013-07-20/salza2-2.0.9.tgz"> ; 15.16KB ================================================== 15,525 bytes in 0.02 seconds (631.71KB/sec) ; Fetching #<URL "http://beta.quicklisp.org/archive/zpng/2015-04-07/zpng-1.2.2.tgz"> ; 39.20KB ================================================== 40,141 bytes in 0.08 seconds (490.00KB/sec) ; Fetching #<URL "http://beta.quicklisp.org/archive/zpb-ttf/2013-07-20/zpb-ttf-1.0.3.tgz"> ; 43.82KB ================================================== 44,869 bytes in 0.08 seconds (554.65KB/sec) ; Fetching #<URL "http://beta.quicklisp.org/archive/cl-vectors/2018-02-28/cl-vectors-20180228-git.tgz"> ; 30.68KB ================================================== 31,415 bytes in 0.04 seconds (697.24KB/sec) ; Fetching #<URL "http://beta.quicklisp.org/archive/vecto/2017-12-27/vecto-1.5.tgz"> ; 69.10KB ================================================== 70,758 bytes in 0.11 seconds (628.18KB/sec) ; Loading "vecto" [package net.tuxee.aa]............................ [package net.tuxee.aa-bin]........................ [package net.tuxee.paths]......................... [package net.tuxee.vectors]....................... [package salza2].................................. [package zpng].................................... [package zpb-ttf]................................. [package vecto]........ ("vecto")
3. ASDF
Another System Definition Facility. The following instructions are documented here, as of .
Create the following directory:
~/.config/common-lisp/source-registry.conf.d/
Create a
.conf
file - I usemy-asdf.conf
. In this file, add a line like this one:(:tree "/home/alc/src/")
You should find this file here.
Since I keep my programming projects in
/home/alc/src/
, this will tell ASDF to recursively scan this directory looking for.asd
files. Of course choose your own dir :)I wouldn't keep the
.quicklisp
directory in there. I didn't test it, but that might have a few funky effects.
3.1. Optional
Let's test things out by cloning a Lisp project managed with ASDF. I will use one of my projects for this test:
git clone https://github.com/alecigne/freecomm src/freecomm sbcl
Then:
(ql:quickload :freecomm)
At this step the project dependencies should be downloaded:
* (ql:quickload "freecomm") To load "freecomm": Load 1 ASDF system: freecomm ; Loading "freecomm" .................................................. [package iterate]................................. [package cl-unicode].............................. [package cl-unicode-names]........................ [package editor-hints.named-readtables]........... [package editor-hints.named-readtables]........... [package cl-interpol]............................. [package cl-csv].................................. [package freecomm]. ("freecomm")
(in-package :freecomm)
You should enter the freecomm
package:
* (in-package :freecomm) #<PACKAGE "FREECOMM">
4. SLIME
SLIME is the Superior Lisp Interaction Mode for Emacs.
- Install it.
Using
use-package
(use-package slime :config (when (eq system-type 'gnu/linux) (setq slime-contribs '(slime-fancy) slime-protocol-version 'ignore) (setq inferior-lisp-program "sbcl")))
Using the package manager directly
Run
M-x package-install RET slime RET
. Don't forget to set your default Lisp by evaluating this expression:(setq inferior-lisp-program "sbcl")
- Launch it with
M-x slime
and start exploring.
5. Creating a Lisp project
Quickproject is pretty neat for creating a Common Lisp project from scratch.
Create a project.
(ql:quickload :quickproject) (quickproject:make-project #p"~/src/my-quickproject-test/")
Load the project:
(ql:quickload :my-quickproject-test)
We will now create a small Common Lisp project that will be useful in the next section.
In
my-quickproject-test.lisp
, add thismain
function:(defun main (argv) (declare (ignore argv)) (write-line "Hello, world"))
That's it!
6. Compilation
Buildapp is pretty cool.
Install it.
(ql:quickload :buildapp)
Build
buildapp
itself.(buildapp:build-buildapp)
The binary will be created in the current directory.
We'll now build
my-quickproject-test
:) Change thebuildapp
directory to match yours; I use~/bin/buildapp
.~/bin/buildapp --output my-quickproject-test \ --load-system my-quickproject-test \ --entry my-quickproject-test:main
Run the program:
./my-quickproject-test
. You should see:❯ ./my-quickproject-test Hello, world
7. StumpWM
Clone the StumpWM repository:
git clone https://github.com/stumpwm/stumpwm
Install the dependencies:
(ql:quickload '("clx" "cl-ppcre" "alexandria" "swank"))
Compile it:
./autogen.sh ./configure make
I prefer to link to the executable:
ln -s ~/src/stumpwm/stumpwm ~/bin/stumpwm
Create
~/.xinitrc
and add this line (point to your own executable or link):exec /home/alc/bin/stumpwm
- Run
startx
: it should work!
7.1. Optional
You can connect to the Lisp process that StumpWM uses from SLIME.
Add this to your StumpWM
init.lisp
:(in-package :stumpwm) (require :swank) (swank-loader:init) (defcommand swank () () (setf *top-level-error-action* :break) (swank:create-server :port 4005 :style swank:*communication-style* :dont-close t)) (swank)
If you encounter an error when running StumpWM with
startx
, try settingSBCL_HOME
. See this comment.Add this config to Emacs:
(defun yourname-swank-listening-p () (ignore-errors (let ((p (open-network-stream "SLIME Lisp Connection Test" nil "localhost" 4005))) (when p (delete-process p) t)))) (defun yourname-swank-autoconnect (&rest args) (if (and (not (slime-connected-p)) (yourname-swank-listening-p)) (ignore-errors (slime-connect "localhost" 4005)))) (yourname-swank-autoconnect))
When you launch Emacs, if SLIME isn't already running and if a Swank connection is available, SLIME will connect to it. Then in the REPL, you can do this:
(in-package :stumpwm) (message "hello world")
The message should appear on the screen.