doc/lisp: add links to sections and upstream websites

Also clean up complex paragraphs and fix section on building wrappers
This commit is contained in:
Kasper Gałkowski 2023-08-25 21:35:34 +02:00
parent b991ea8385
commit 9ce6e34ddf

View file

@ -1,36 +1,32 @@
# lisp-modules {#lisp} # lisp-modules {#lisp}
This document describes the Nixpkgs infrastructure for building Common Lisp This document describes the Nixpkgs infrastructure for building Common Lisp
libraries that use ASDF (Another System Definition Facility). It lives in systems that use [ASDF](https://asdf.common-lisp.dev/) (Another System
`pkgs/development/lisp-modules`. Definition Facility). It lives in `pkgs/development/lisp-modules`.
## Overview {#lisp-overview} ## Overview {#lisp-overview}
The main entry point of the API are the Common Lisp implementation packages The main entry point of the API are the Common Lisp implementation packages
themselves (e.g. `abcl`, `ccl`, `clasp-common-lisp`, `clisp` `ecl`, themselves (e.g. `abcl`, `ccl`, `clasp-common-lisp`, `clisp`, `ecl`,
`sbcl`). They have the `pkgs` and `withPackages` attributes, which can be used `sbcl`). They have the `pkgs` and `withPackages` attributes, which can be used
to discover available packages and to build wrappers, respectively. to discover available packages and to build wrappers, respectively.
The `pkgs` attribute set contains packages that were automatically imported from The `pkgs` attribute set contains packages that were automatically
Quicklisp, and any other manually defined ones. Not every package works for all [imported](#lisp-importing-packages-from-quicklisp) from Quicklisp, and any
the CL implementations (e.g. `nyxt` only makes sense for `sbcl`). other [manually defined](#lisp-defining-packages-inside) ones. Not every package
works for all the CL implementations (e.g. `nyxt` only makes sense for `sbcl`).
The `withPackages` function is of primary utility. It is used to build runnable The `withPackages` function is of primary utility. It is used to build
wrappers, with a pinned and pre-built ASDF FASL available in the `ASDF` [runnable wrappers](#lisp-building-wrappers), with a pinned and pre-built
environment variable, and `CL_SOURCE_REGISTRY`/`ASDF_OUTPUT_TRANSLATIONS` [ASDF FASL](#lisp-loading-asdf) available in the `ASDF` environment variable,
configured to find the desired systems on runtime. and `CL_SOURCE_REGISTRY`/`ASDF_OUTPUT_TRANSLATIONS` configured to
[find the desired systems on runtime](#lisp-loading-systems).
With a few exceptions, the primary thing that the infrastructure does is to run
`asdf:load-system` for each system specified in the `systems` argument to
`build-asdf-system`, and save the FASLs to the Nix store. Then, it makes these
FASLs available to wrappers. Any other use-cases, such as producing SBCL
executables with `sb-ext:save-lisp-and-die`, are achieved via overriding the
`buildPhase` etc.
In addition, Lisps have the `withOverrides` function, which can be used to In addition, Lisps have the `withOverrides` function, which can be used to
substitute any package in the scope of their `pkgs`. This will be useful [substitute](#lisp-including-external-pkg-in-scope) any package in the scope of
together with `overrideLispAttrs` when dealing with slashy ASDF systems, because their `pkgs`. This will also be useful together with `overrideLispAttrs` when
they should stay in the main package and be built by specifying the `systems` [dealing with slashy systems](#lisp-dealing-with-slashy-systems), because they
should stay in the main package and be built by specifying the `systems`
argument to `build-asdf-system`. argument to `build-asdf-system`.
## The 90% use case example {#lisp-use-case-example} ## The 90% use case example {#lisp-use-case-example}
@ -94,7 +90,7 @@ The maintainer's job is to:
1. Re-run the `ql-import.lisp` script when there is a new Quicklisp release 1. Re-run the `ql-import.lisp` script when there is a new Quicklisp release
2. [Add any missing native dependencies](#lisp-quicklisp-adding-native-dependencies) in `ql.nix` 2. [Add any missing native dependencies](#lisp-quicklisp-adding-native-dependencies) in `ql.nix`
3. For packages that still don't build, package them manually in `packages.nix` 3. For packages that still don't build, [package them manually](#lisp-defining-packages-inside) in `packages.nix`
Also, the `imported.nix` file **must not be edited manually**! It should only be Also, the `imported.nix` file **must not be edited manually**! It should only be
generated as described in this section (by running `ql-import.lisp`). generated as described in this section (by running `ql-import.lisp`).
@ -139,13 +135,14 @@ During Quicklisp import:
## Defining packages manually inside Nixpkgs {#lisp-defining-packages-inside} ## Defining packages manually inside Nixpkgs {#lisp-defining-packages-inside}
New packages, that for some reason are not in Quicklisp, and so cannot be Packages that for some reason are not in Quicklisp, and so cannot be
auto-imported, can be written in the `packages.nix` file. auto-imported, or don't work straight from the import, are defined in the
`packages.nix` file.
In that file, use the `build-asdf-system` function, which is a wrapper around In that file, use the `build-asdf-system` function, which is a wrapper around
`mkDerivation` for building ASDF systems. Various other hacks are present, such `mkDerivation` for building ASDF systems. Various other hacks are present, such
as `build-with-compile-into-pwd` for systems which create files during as `build-with-compile-into-pwd` for systems which create files during
compilation. compilation (such as cl-unicode).
The `build-asdf-system` function is documented with comments in The `build-asdf-system` function is documented with comments in
`nix-cl.nix`. Also, `packages.nix` is full of examples of how to use it. `nix-cl.nix`. Also, `packages.nix` is full of examples of how to use it.
@ -203,28 +200,6 @@ sbcl.pkgs.alexandria.overrideLispAttrs (oldAttrs: rec {
}) })
``` ```
## Overriding packages in scope {#lisp-overriding-packages-in-scope}
Packages can be woven into a new scope by using `withOverrides`:
```
let
sbcl' = sbcl.withOverrides (self: super: {
alexandria = super.alexandria.overrideLispAttrs (oldAttrs: rec {
pname = "alexandria";
version = "1.4";
src = fetchFromGitLab {
domain = "gitlab.common-lisp.net";
owner = "alexandria";
repo = "alexandria";
rev = "v${version}";
hash = "sha256-1Hzxt65dZvgOFIljjjlSGgKYkj+YBLwJCACi5DZsKmQ=";
};
});
});
in builtins.elemAt sbcl'.pkgs.bordeaux-threads.lispLibs 0
```
### Dealing with slashy systems {#lisp-dealing-with-slashy-systems} ### Dealing with slashy systems {#lisp-dealing-with-slashy-systems}
Slashy (secondary) systems should not exist in their own packages! Instead, they Slashy (secondary) systems should not exist in their own packages! Instead, they
@ -245,8 +220,8 @@ ecl.pkgs.alexandria.overrideLispAttrs (oldAttrs: {
}) })
``` ```
See the respective section on using `withOverrides` for how to weave it back See the [respective section](#lisp-including-external-pkg-in-scope) on using
into `ecl.pkgs`. `withOverrides` for how to weave it back into `ecl.pkgs`.
Note that sometimes the slashy systems might not only have more dependencies Note that sometimes the slashy systems might not only have more dependencies
than the main one, but create a circular dependency between `.asd` than the main one, but create a circular dependency between `.asd`
@ -258,13 +233,16 @@ Wrappers can be built using the `withPackages` function of Common Lisp
implementations (`abcl`, `ecl`, `sbcl` etc.): implementations (`abcl`, `ecl`, `sbcl` etc.):
``` ```
sbcl.withPackages (ps: [ ps.alexandria ps.bordeaux-threads ]) nix-shell -p 'sbcl.withPackages (ps: [ ps.alexandria ps.bordeaux-threads ])'
``` ```
Such a wrapper can then be executed like this: Such a wrapper can then be used like this:
``` ```
result/bin/sbcl $ sbcl
* (load (sb-ext:posix-getenv "ASDF"))
* (asdf:load-system 'alexandria)
* (asdf:load-system 'bordeaux-threads)
``` ```
### Loading ASDF {#lisp-loading-asdf} ### Loading ASDF {#lisp-loading-asdf}