fw: fix build on darwin
[NixPkgs.git] / doc / languages-frameworks / lisp.section.md
blob8712c3412064507b5c18604afddc1b16964c6085
1 # lisp-modules {#lisp}
3 This 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`.
7 ## Overview {#lisp-overview}
9 The 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.
14 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`).
19 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).
25 In 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`
30 argument to `build-asdf-system`.
32 ## The 90% use case example {#lisp-use-case-example}
34 The most common way to use the library is to run ad-hoc wrappers like this:
36 `nix-shell -p 'sbcl.withPackages (ps: with ps; [ alexandria ])'`
38 Then, in a shell:
40 ```
41 $ sbcl
42 * (load (sb-ext:posix-getenv "ASDF"))
43 * (asdf:load-system 'alexandria)
44 ```
46 Also one can create a `pkgs.mkShell` environment in `shell.nix`/`flake.nix`:
48 ```
49 let
50   sbcl' = sbcl.withPackages (ps: [ ps.alexandria ]);
51 in mkShell {
52   packages = [ sbcl' ];
54 ```
56 Such a Lisp can be now used e.g. to compile your sources:
58 ```
59 buildPhase = ''
60   ${sbcl'}/bin/sbcl --load my-build-file.lisp
62 ```
64 ## Importing packages from Quicklisp {#lisp-importing-packages-from-quicklisp}
66 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).
71 The 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
73 execute `ql-import.lisp`:
75 ```
76 cd pkgs/development/lisp-modules
77 nix-shell --run 'sbcl --script ql-import.lisp'
78 ```
80 The script will:
82 1. Download the latest Quicklisp `systems.txt` and `releases.txt` files
83 2. Generate a temporary SQLite database of all QL systems in `packages.sqlite`
84 3. Generate an `imported.nix` file from the database
86 (The `packages.sqlite` file can be deleted at will, because it is regenerated
87 each time the script runs.)
89 The maintainer's job is to:
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`
95 Also, 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`).
98 ### Adding native dependencies {#lisp-quicklisp-adding-native-dependencies}
100 The Quicklisp files contain ASDF dependency data, but don't include native
101 library (CFFI) dependencies, and, in the case of ABCL, Java dependencies.
103 The `ql.nix` file contains a long list of overrides, where these dependencies
104 can be added.
106 Packages defined in `packages.nix` contain these dependencies naturally.
108 ### Trusting `systems.txt` and `releases.txt` {#lisp-quicklisp-trusting}
110 The previous implementation of `lisp-modules` didn't fully trust the Quicklisp
111 data, because there were times where the dependencies specified were not
112 complete and caused broken builds. It instead used a `nix-shell` environment to
113 discover real dependencies by using the ASDF APIs.
115 The current implementation has chosen to trust this data, because it's faster to
116 parse a text file than to build each system to generate its Nix file, and
117 because that way packages can be mass-imported. Because of that, there may come
118 a day where some packages will break, due to bugs in Quicklisp. In that case,
119 the fix could be a manual override in `packages.nix` and `ql.nix`.
121 A known fact is that Quicklisp doesn't include dependencies on slashy systems in
122 its data. This is an example of a situation where such fixes were used, e.g. to
123 replace the `systems` attribute of the affected packages. (See the definition of
124 `iolib`).
126 ### Quirks {#lisp-quicklisp-quirks}
128 During Quicklisp import:
130 - `+` 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
136 ## Defining packages manually inside Nixpkgs {#lisp-defining-packages-inside}
138 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.
142 In 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
144 as `build-with-compile-into-pwd` for systems which create files during
145 compilation (such as cl-unicode).
147 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.
151 ## Defining packages manually outside Nixpkgs {#lisp-defining-packages-outside}
153 Lisp 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.
157 It takes the following arguments:
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
168 It can be used to define packages outside Nixpkgs, and, for example, add them
169 into the package scope with `withOverrides`.
171 ### Including an external package in scope {#lisp-including-external-pkg-in-scope}
173 A package defined outside Nixpkgs using `buildASDFSystem` can be woven into the
174 Nixpkgs-provided scope like this:
178   alexandria = sbcl.buildASDFSystem rec {
179     pname = "alexandria";
180     version = "1.4";
181     src = fetchFromGitLab {
182       domain = "gitlab.common-lisp.net";
183       owner = "alexandria";
184       repo = "alexandria";
185       rev = "v${version}";
186       hash = "sha256-1Hzxt65dZvgOFIljjjlSGgKYkj+YBLwJCACi5DZsKmQ=";
187     };
188   };
189   sbcl' = sbcl.withOverrides (self: super: {
190     inherit alexandria;
191   });
192 in sbcl'.pkgs.alexandria
195 ## Overriding package attributes {#lisp-overriding-package-attributes}
197 Packages export the `overrideLispAttrs` function, which can be used to build a
198 new package with different parameters.
200 Example of overriding `alexandria`:
203 sbcl.pkgs.alexandria.overrideLispAttrs (oldAttrs: rec {
204   version = "1.4";
205   src = fetchFromGitLab {
206     domain = "gitlab.common-lisp.net";
207     owner = "alexandria";
208     repo = "alexandria";
209     rev = "v${version}";
210     hash = "sha256-1Hzxt65dZvgOFIljjjlSGgKYkj+YBLwJCACi5DZsKmQ=";
211   };
215 ### Dealing with slashy systems {#lisp-dealing-with-slashy-systems}
217 Slashy (secondary) systems should not exist in their own packages! Instead, they
218 should be included in the parent package as an extra entry in the `systems`
219 argument to the `build-asdf-system`/`buildASDFSystem` functions.
221 The reason is that ASDF searches for a secondary system in the `.asd` of the
222 parent package. Thus, having them separate would cause either one of them not to
223 load cleanly, because one will contains FASLs of itself but not the other, and
224 vice versa.
226 To package slashy systems, use `overrideLispAttrs`, like so:
229 ecl.pkgs.alexandria.overrideLispAttrs (oldAttrs: {
230   systems = oldAttrs.systems ++ [ "alexandria/tests" ];
231   lispLibs = oldAttrs.lispLibs ++ [ ecl.pkgs.rt ];
235 See the [respective section](#lisp-including-external-pkg-in-scope) on using
236 `withOverrides` for how to weave it back into `ecl.pkgs`.
238 Note that sometimes the slashy systems might not only have more dependencies
239 than the main one, but create a circular dependency between `.asd`
240 files. Unfortunately, in this case an adhoc solution becomes necessary.
242 ## Building Wrappers {#lisp-building-wrappers}
244 Wrappers can be built using the `withPackages` function of Common Lisp
245 implementations (`abcl`, `ecl`, `sbcl` etc.):
248 nix-shell -p 'sbcl.withPackages (ps: [ ps.alexandria ps.bordeaux-threads ])'
251 Such a wrapper can then be used like this:
254 $ sbcl
255 * (load (sb-ext:posix-getenv "ASDF"))
256 * (asdf:load-system 'alexandria)
257 * (asdf:load-system 'bordeaux-threads)
260 ### Loading ASDF {#lisp-loading-asdf}
262 For best results, avoid calling `(require 'asdf)` When using the
263 library-generated wrappers.
265 Use `(load (ext:getenv "ASDF"))` instead, supplying your implementation's way of
266 getting an environment variable for `ext:getenv`. This will load the
267 (pre-compiled to FASL) Nixpkgs-provided version of ASDF.
269 ### Loading systems {#lisp-loading-systems}
271 There, you can simply use `asdf:load-system`. This works by setting the right
272 values for the `CL_SOURCE_REGISTRY`/`ASDF_OUTPUT_TRANSLATIONS` environment
273 variables, so that systems are found in the Nix store and pre-compiled FASLs are
274 loaded.
276 ## Adding a new Lisp {#lisp-adding-a-new-lisp}
278 The function `wrapLisp` is used to wrap Common Lisp implementations. It adds the
279 `pkgs`, `withPackages`, `withOverrides` and `buildASDFSystem` attributes to the
280 derivation.
282 `wrapLisp` takes these arguments:
284 - `pkg`: the Lisp package
285 - `faslExt`: Implementation-specific extension for FASL files
286 - `program`: The name of executable file in `${pkg}/bin/` (Default: `pkg.pname`)
287 - `flags`: A list of flags to always pass to `program` (Default: `[]`)
288 - `asdf`: The ASDF version to use (Default: `pkgs.asdf_3_3`)
289 - `packageOverrides`: Package overrides config (Default: `(self: super: {})`)
291 This example wraps CLISP:
294 wrapLisp {
295   pkg = clisp;
296   faslExt = "fas";
297   flags = ["-E" "UTF8"];