···1# lisp-modules {#lisp}
23This document describes the Nixpkgs infrastructure for building Common Lisp
4-libraries that use ASDF (Another System Definition Facility). It lives in
5-`pkgs/development/lisp-modules`.
67## Overview {#lisp-overview}
89The main entry point of the API are the Common Lisp implementation packages
10-(e.g. `abcl`, `ccl`, `clasp-common-lisp`, `clisp` `ecl`, `sbcl`)
11-themselves. They have the `pkgs` and `withPackages` attributes, which can be
12-used to discover available packages and to build wrappers, respectively.
1314-The `pkgs` attribute set contains packages that were automatically imported from
15-Quicklisp, and any other manually defined ones. Not every package works for all
16-the CL implementations (e.g. `nyxt` only makes sense for `sbcl`).
01718-The `withPackages` function is of primary utility. It is used to build runnable
19-wrappers, with a pinned and pre-built ASDF FASL available in the `ASDF`
20-environment variable, and `CL_SOURCE_REGISTRY`/`ASDF_OUTPUT_TRANSLATIONS`
21-configured to find the desired systems on runtime.
22-23-With a few exceptions, the primary thing that the infrastructure does is to run
24-`asdf:load-system` for each system specified in the `systems` argument to
25-`build-asdf-system`, and save the FASLs to the Nix store. Then, it makes these
26-FASLs available to wrappers. Any other use-cases, such as producing SBCL
27-executables with `sb-ext:save-lisp-and-die`, are achieved via overriding the
28-`buildPhase` etc.
2930In addition, Lisps have the `withOverrides` function, which can be used to
31-substitute any package in the scope of their `pkgs`. This will be useful
32-together with `overrideLispAttrs` when dealing with slashy ASDF systems, because
33-they should stay in the main package and be build by specifying the `systems`
034argument to `build-asdf-system`.
3536## The 90% use case example {#lisp-use-case-example}
···42Then, in a shell:
4344```
45-$ result/bin/sbcl
46* (load (sb-ext:posix-getenv "ASDF"))
47* (asdf:load-system 'alexandria)
48```
···53let
54 sbcl' = sbcl.withPackages (ps: [ ps.alexandria ]);
55in mkShell {
56- buildInputs = [ sbcl' ];
57}
58```
59···6768## Importing packages from Quicklisp {#lisp-importing-packages-from-quicklisp}
6970-The library is able to very quickly import all the packages distributed by
71-Quicklisp by parsing its `releases.txt` and `systems.txt` files. These files are
72-available from [http://beta.quicklisp.org/dist/quicklisp.txt].
07374The import process is implemented in the `import` directory as Common Lisp
75-functions in the `org.lispbuilds.nix` ASDF system. To run the script, one can
76execute `ql-import.lisp`:
7778```
079nix-shell --run 'sbcl --script ql-import.lisp'
80```
8182The script will:
83841. Download the latest Quicklisp `systems.txt` and `releases.txt` files
85-2. Generate an SQLite database of all QL systems in `packages.sqlite`
863. Generate an `imported.nix` file from the database
8788-The maintainer's job there is to:
08990-1. Re-run the `ql-import.lisp` script
91-2. Add missing native dependencies in `ql.nix`
92-3. For packages that still don't build, package them manually in `packages.nix`
009394Also, the `imported.nix` file **must not be edited manually**! It should only be
95-generated as described in this section.
9697### Adding native dependencies {#lisp-quicklisp-adding-native-dependencies}
98···108109The previous implementation of `lisp-modules` didn't fully trust the Quicklisp
110data, because there were times where the dependencies specified were not
111-complete, and caused broken builds. It instead used a `nix-shell` environment to
112discover real dependencies by using the ASDF APIs.
113114The current implementation has chosen to trust this data, because it's faster to
···126127During Quicklisp import:
128129-- `+` in names are converted to `_plus{_,}`: `cl+ssl`->`cl_plus_ssl`, `alexandria+`->`alexandria_plus`
130-- `.` to `_dot_`: `iolib.base`->`iolib_dot_base`
131- names starting with a number have a `_` prepended (`3d-vectors`->`_3d-vectors`)
132- `_` in names is converted to `__` for reversibility
133134135## Defining packages manually inside Nixpkgs {#lisp-defining-packages-inside}
136137-New packages, that for some reason are not in Quicklisp, and so cannot be
138-auto-imported, can be written in the `packages.nix` file.
0139140In that file, use the `build-asdf-system` function, which is a wrapper around
141`mkDerivation` for building ASDF systems. Various other hacks are present, such
142as `build-with-compile-into-pwd` for systems which create files during
143-compilation.
144145-The `build-asdf-system` function is documented with comments in
146-`nix-cl.nix`. Also, `packages.nix` is full of examples of how to use it.
0147148## Defining packages manually outside Nixpkgs {#lisp-defining-packages-outside}
149150Lisp derivations (`abcl`, `sbcl` etc.) also export the `buildASDFSystem`
151-function, which is the same as `build-asdf-system`, except for the `lisp`
152-argument which is set to the given CL implementation.
00000000000153154It can be used to define packages outside Nixpkgs, and, for example, add them
155-into the package scope with `withOverrides` which will be discussed later on.
156157### Including an external package in scope {#lisp-including-external-pkg-in-scope}
158···198})
199```
200201-## Overriding packages in scope {#lisp-overriding-packages-in-scope}
202-203-Packages can be woven into a new scope by using `withOverrides`:
204-205-```
206-let
207- sbcl' = sbcl.withOverrides (self: super: {
208- alexandria = super.alexandria.overrideLispAttrs (oldAttrs: rec {
209- pname = "alexandria";
210- version = "1.4";
211- src = fetchFromGitLab {
212- domain = "gitlab.common-lisp.net";
213- owner = "alexandria";
214- repo = "alexandria";
215- rev = "v${version}";
216- hash = "sha256-1Hzxt65dZvgOFIljjjlSGgKYkj+YBLwJCACi5DZsKmQ=";
217- };
218- });
219- });
220-in builtins.elemAt sbcl'.pkgs.bordeaux-threads.lispLibs 0
221-```
222-223### Dealing with slashy systems {#lisp-dealing-with-slashy-systems}
224225Slashy (secondary) systems should not exist in their own packages! Instead, they
···240})
241```
242243-See the respective section on using `withOverrides` for how to weave it back
244-into `ecl.pkgs`.
245246Note that sometimes the slashy systems might not only have more dependencies
247than the main one, but create a circular dependency between `.asd`
···253implementations (`abcl`, `ecl`, `sbcl` etc.):
254255```
256-sbcl.withPackages (ps: [ ps.alexandria ps.bordeaux-threads ])
257```
258259-Such a wrapper can then be executed like this:
260261```
262-result/bin/sbcl
000263```
264265### Loading ASDF {#lisp-loading-asdf}
···1# lisp-modules {#lisp}
23This document describes the Nixpkgs infrastructure for building Common Lisp
4+systems that use [ASDF](https://asdf.common-lisp.dev/) (Another System
5+Definition Facility). It lives in `pkgs/development/lisp-modules`.
67## Overview {#lisp-overview}
89The main entry point of the API are the Common Lisp implementation packages
10+themselves (e.g. `abcl`, `ccl`, `clasp-common-lisp`, `clisp`, `ecl`,
11+`sbcl`). They have the `pkgs` and `withPackages` attributes, which can be used
12+to discover available packages and to build wrappers, respectively.
1314+The `pkgs` attribute set contains packages that were automatically
15+[imported](#lisp-importing-packages-from-quicklisp) from Quicklisp, and any
16+other [manually defined](#lisp-defining-packages-inside) ones. Not every package
17+works for all the CL implementations (e.g. `nyxt` only makes sense for `sbcl`).
1819+The `withPackages` function is of primary utility. It is used to build
20+[runnable wrappers](#lisp-building-wrappers), with a pinned and pre-built
21+[ASDF FASL](#lisp-loading-asdf) available in the `ASDF` environment variable,
22+and `CL_SOURCE_REGISTRY`/`ASDF_OUTPUT_TRANSLATIONS` configured to
23+[find the desired systems on runtime](#lisp-loading-systems).
0000002425In addition, Lisps have the `withOverrides` function, which can be used to
26+[substitute](#lisp-including-external-pkg-in-scope) any package in the scope of
27+their `pkgs`. This will also be useful together with `overrideLispAttrs` when
28+[dealing with slashy systems](#lisp-dealing-with-slashy-systems), because they
29+should stay in the main package and be built by specifying the `systems`
30argument to `build-asdf-system`.
3132## The 90% use case example {#lisp-use-case-example}
···38Then, in a shell:
3940```
41+$ sbcl
42* (load (sb-ext:posix-getenv "ASDF"))
43* (asdf:load-system 'alexandria)
44```
···49let
50 sbcl' = sbcl.withPackages (ps: [ ps.alexandria ]);
51in mkShell {
52+ packages = [ sbcl' ];
53}
54```
55···6364## Importing packages from Quicklisp {#lisp-importing-packages-from-quicklisp}
6566+To save some work of writing Nix expressions, there is a script that imports all
67+the packages distributed by Quicklisp into `imported.nix`. This works by parsing
68+its `releases.txt` and `systems.txt` files, which are published every couple of
69+months on [quicklisp.org](http://beta.quicklisp.org/dist/quicklisp.txt).
7071The import process is implemented in the `import` directory as Common Lisp
72+code in the `org.lispbuilds.nix` ASDF system. To run the script, one can
73execute `ql-import.lisp`:
7475```
76+cd pkgs/development/lisp-modules
77nix-shell --run 'sbcl --script ql-import.lisp'
78```
7980The script will:
81821. Download the latest Quicklisp `systems.txt` and `releases.txt` files
83+2. Generate a temporary SQLite database of all QL systems in `packages.sqlite`
843. Generate an `imported.nix` file from the database
8586+(The `packages.sqlite` file can be deleted at will, because it is regenerated
87+each time the script runs.)
8889+The maintainer's job is to:
90+91+1. Re-run the `ql-import.lisp` script when there is a new Quicklisp release
92+2. [Add any missing native dependencies](#lisp-quicklisp-adding-native-dependencies) in `ql.nix`
93+3. For packages that still don't build, [package them manually](#lisp-defining-packages-inside) in `packages.nix`
9495Also, the `imported.nix` file **must not be edited manually**! It should only be
96+generated as described in this section (by running `ql-import.lisp`).
9798### Adding native dependencies {#lisp-quicklisp-adding-native-dependencies}
99···109110The previous implementation of `lisp-modules` didn't fully trust the Quicklisp
111data, because there were times where the dependencies specified were not
112+complete and caused broken builds. It instead used a `nix-shell` environment to
113discover real dependencies by using the ASDF APIs.
114115The current implementation has chosen to trust this data, because it's faster to
···127128During Quicklisp import:
129130+- `+` in names is converted to `_plus{_,}`: `cl+ssl`->`cl_plus_ssl`, `alexandria+`->`alexandria_plus`
131+- `.` in names is converted to `_dot_`: `iolib.base`->`iolib_dot_base`
132- names starting with a number have a `_` prepended (`3d-vectors`->`_3d-vectors`)
133- `_` in names is converted to `__` for reversibility
134135136## Defining packages manually inside Nixpkgs {#lisp-defining-packages-inside}
137138+Packages that for some reason are not in Quicklisp, and so cannot be
139+auto-imported, or don't work straight from the import, are defined in the
140+`packages.nix` file.
141142In that file, use the `build-asdf-system` function, which is a wrapper around
143`mkDerivation` for building ASDF systems. Various other hacks are present, such
144as `build-with-compile-into-pwd` for systems which create files during
145+compilation (such as cl-unicode).
146147+The `build-asdf-system` function is documented
148+[here](#lisp-defining-packages-outside). Also, `packages.nix` is full of
149+examples of how to use it.
150151## Defining packages manually outside Nixpkgs {#lisp-defining-packages-outside}
152153Lisp derivations (`abcl`, `sbcl` etc.) also export the `buildASDFSystem`
154+function, which is similar to `build-asdf-system` from `packages.nix`, but is
155+part of the public API.
156+157+It takes the following arguments:
158+159+- `pname`: the package name
160+- `version`: the package version
161+- `src`: the package source
162+- `patches`: patches to apply to the source before build
163+- `nativeLibs`: native libraries used by CFFI and grovelling
164+- `javaLibs`: Java libraries for ABCL
165+- `lispLibs`: dependencies on other packages build with `buildASDFSystem`
166+- `systems`: list of systems to build
167168It can be used to define packages outside Nixpkgs, and, for example, add them
169+into the package scope with `withOverrides`.
170171### Including an external package in scope {#lisp-including-external-pkg-in-scope}
172···212})
213```
2140000000000000000000000215### Dealing with slashy systems {#lisp-dealing-with-slashy-systems}
216217Slashy (secondary) systems should not exist in their own packages! Instead, they
···232})
233```
234235+See the [respective section](#lisp-including-external-pkg-in-scope) on using
236+`withOverrides` for how to weave it back into `ecl.pkgs`.
237238Note that sometimes the slashy systems might not only have more dependencies
239than the main one, but create a circular dependency between `.asd`
···245implementations (`abcl`, `ecl`, `sbcl` etc.):
246247```
248+nix-shell -p 'sbcl.withPackages (ps: [ ps.alexandria ps.bordeaux-threads ])'
249```
250251+Such a wrapper can then be used like this:
252253```
254+$ sbcl
255+* (load (sb-ext:posix-getenv "ASDF"))
256+* (asdf:load-system 'alexandria)
257+* (asdf:load-system 'bordeaux-threads)
258```
259260### Loading ASDF {#lisp-loading-asdf}