:focal(smart))
Common Lisp with Pixi
The following is a guest blog post by Shubhamkar Ayare who has done some amazing work simplifying Common Lisp packaging on prefix.dev using pixi and rattler-build.
Common Lisp is an amazing multiparadigm programming language with multiple implementations! ANSI standardized in 1994, it was developed as an amalgamation of the different lisp dialects at that time. In recent years, it has also enjoyed multiple library managers. Some of these also support project local dependencies and environment management. And there's a tool for implementation management too. Unfortunately, all of these tools solve a different aspect of the same problem: that of simplifying the installation of all the software needed to run your library, tool, or application, in a reproducible manner.
I had been using conda for python for several years. I liked it at that time because it was solving several problems at once:
Install python
Install libraries
Install any foreign libraries that the python libraries might require
Provide environment isolation to avoid conflicts with other projects
I wished something similar for Common Lisp too. Unfortunately, if you have ever used conda, you'd know that installing or updating dependencies can take forever! About a year or two ago, I moved to micromamba. I was pleased it was much faster than conda! This year, I also stumbled upon pixi. Now, this is blazing fast! And they also provide prefix.dev to create and host one's own channel for packages too!
So, I created a channel for Common Lisp: @common-lisp/common-lisp
This is still far from complete, but it is very useable. It currently contains a bit over 100 libraries. For comparison, the Common Lisp library managers quicklisp, ultralisp, and ocicl contain 1400+, 2200+ and 2500+ libraries respectively. (Technically, quicklisp and ultralisp are different dists with the same library manager quicklisp.) But for any of these, you had to manually install a Common Lisp implementation (like SBCL). Now, once pixi is installed, the steps are simple.
1: In your project directory:
pixi init
2: Add the common lisp channel:
pixi workspace channel add --prepend https://prefix.dev/conda-forge https://prefix.dev/common-lisp/common-lisp
3: Install sbcl and libraries:
pixi add sbcl alexandria pixi run sbcl
4: (Optional) Install a featureful REPL built over isocline:
pixi add cl-isocline-repl pixi run cl-isocline-repl
In an existing project, such as cl-isocline itself, if you download from GitHub, the steps to run it are even simpler:
git clone https://github.com/digikar99/cl-isocline && cd cl-isocline pixi -q run cl-isocline
This single step (i) installs sbcl and all dependencies (ii) compiles isocline repl (iii) runs the REPL.
Best of all, apart from minor differences in installing pixi, all the steps are identical across Windows, MacOS and Linux. This is because differences across the operating systems are abstracted as part of the recipes of respective libraries. To give an example, consider cl-isocline itself. The current recipe and the accompanying build.sh is given below. It is the part on requirements and build.sh that provides the abstraction across different operating systems and platforms.
recipe.yaml for cl-isocline:
package: name: cl-isocline version: "0.0.0.2026.10.17" source: git: https://github.com/digikar99/cl-isocline rev: 8441af41a145a192aa3bfa945698fd18397dc364 submodules: false build: number: 0 script: build.sh requirements: build: - if: win then: - m2-base - gcc_win-64 else: - ${{ compiler('c') }} run: - cl-asdf - alexandria - cl-cffi ignore_run_exports: by_name: - libgcc tests: - script: - sbcl --no-userinit --non-interactive --eval "(require :asdf)" --eval "(asdf:load-system \"isocline\")" requirements: run: - sbcl # about: omitted for brevity
build.sh for cl-isocline
#!/bin/bash set -euo pipefail DEST="$PREFIX/common-lisp/cl-isocline" mkdir -p "$DEST" cp -r . "$DEST/" rm -rf "$DEST/.git" case "$target_platform" in linux-*) CC_BIN="$CC" FLAGS="-shared -fPIC" LIB="libisocline.so" ;; osx-*) CC_BIN="$CC" FLAGS="-dynamiclib -fPIC" LIB="libisocline.dylib" ;; win-*) CC_BIN="x86_64-w64-mingw32-gcc" FLAGS="-shared" LIB="libisocline.dll" ;; esac "$CC_BIN" $FLAGS -O2 -DNDEBUG -Iisocline/include isocline/src/isocline.c -o "$DEST/$LIB" rm -rf "$DEST/isocline"
This step of providing the abstraction is relevant for those who develop cl-isocline. But to the user of cl-isocline, this is invisible. The above recipe builds the dynamic library libisocline and packages it with the conda package. This means the end user does not need to worry about compiling libisocline on their system. This difference becomes more prominent for more commonly used libraries like zeromq and zstd that are already present in conda-forge channel. For these libraries, recipes of foreign function interfaces (such as cl-remizmq) can directly include the prebuilt library as a dependency.
For the moment, I build the recipes in the Common Lisp channel manually, although I already have simple scripts to manage them. The hardest part, however, is adding information about documentation and license. This can be a fair bit scattered. The good news is this is a one-time task. And because Common Lisp ecosystem is very long lived (decades), it's probable the information for most of the old and most used packages won't be outdated for a while. Additionally, this also overcomes one more complaint people raise about Common Lisp that libraries often have hard-to-find documentation (whether it's true or not). I plan to set up CI or some automation once the recipes reach a critical mass, and especially once it contains libraries that are more unstable and require frequent updates.
Until I (or other pixi and lisp enthusiasts) add more libraries to the channel, you can use quicklisp alongside pixi too!
pixi add ql-https
After this, starting SBCL will load quicklisp.
pixi run sbcl --no-userinit
And you can use that to install other libraries, or ultralisp itself.
(ql:quickload "serapeum") (ql-dist:install-dist "http://dist.ultralisp.org/" :prompt nil) ;; By default, ql-https automatically upgrades the http urls to https
Enjoy 🙂
Common Lisp is just one example. If there’s a language or ecosystem you care about that lacks good packaging, Pixi and conda-forge can give it reproducible, cross-platform environments without building a package manager from scratch. Tell us what you’d like to see on Discord, or start packaging it yourself with rattler-build.