tvl-depot/nix/buildLisp
sterni 7df7cd6257 feat(nix/buildLisp): pass implementation description instead of name
Instead of using a string to refer to an internal set defined in
buildLisp, we just expose the relevant sets (as nix.buildLisp.sbcl,
nix.buildLisp.ecl, …) and receive them as the `implementation`
argument directly. This has several advantages:

* It becomes easier to extend buildLisp, even for downstream users:
  Since you can just pass your own set, there's nothing stopping you
  from adding support for another implementation in a downstream
  derivation without having to edit the buildLisp file in any way which
  is great if you're using e. g. builtins.fetchGit to import it.

* Users can mess with the implementation set by changing out some parts
  of it for customization purposes. Note that currently the sets use a
  lot of self-references which aren't even bound by a fix-point, so to
  make this work smoothly, we'd need to add some overriding mechanism.

* The buildLisp code becomes quite a bit clearer. Since we're now always
  dealing with the implementation set, the confusing distinction between
  `impl`, `impl.name` and `implementation` no longer exists. `impl` is
  now exclusively an abbreviation of `implementation` (we could make
  this more consistent in the future even).

Change-Id: I36d68069dd1315610b2f7159941507b465469b7c
Reviewed-on: https://cl.tvl.fyi/c/depot/+/3368
Reviewed-by: tazjin <mail@tazj.in>
Reviewed-by: grfn <grfn@gws.fyi>
Tested-by: BuildkiteCI
2021-08-24 22:00:15 +00:00
..
example chore: Rename pkgs->depot in all Nix file headers 2020-02-21 13:54:53 +00:00
default.nix feat(nix/buildLisp): pass implementation description instead of name 2021-08-24 22:00:15 +00:00
README.md docs(nix/buildLisp): mention drawback of non-parallel compilation 2021-08-12 15:08:15 +00:00

buildLisp.nix

This is a build system for Common Lisp, written in Nix.

It aims to offer an alternative to ASDF for users who live in a Nix-based ecosystem. This offers several advantages over ASDF:

  • Simpler (logic-less) package definitions
  • Easy linking of native dependencies (from Nix)
  • Composability with Nix tooling for other languages
  • Effective, per-system caching strategies
  • Easy overriding of dependencies and whatnot
  • ... and more!

The project is still in its early stages and some important restrictions should be highlighted:

  • Only SBCL is supported (though the plan is to add support for at least ABCL and Clozure CL, and maybe make it extensible)
  • Parallel compilation is not possible: Since buildLisp doesn't encode dependencies between components (i. e. source files) like ASDF, it must compile source files in sequence to avoid errors due to undefined symbols.

Usage

buildLisp exposes four different functions:

  • buildLisp.library: Builds a collection of Lisp files into a library.

    parameter type use required?
    name string Name of the library yes
    srcs list<path> List of paths to source files yes
    deps list<drv> List of dependencies no
    native list<drv> List of native dependencies no
    test see "Tests" Specification for test suite no

    The output of invoking this is a directory containing a FASL file that is the concatenated result of all compiled sources.

  • buildLisp.program: Builds an executable program out of Lisp files.

    parameter type use required?
    name string Name of the program yes
    srcs list<path> List of paths to source files yes
    deps list<drv> List of dependencies no
    native list<drv> List of native dependencies no
    main string Entrypoint function no
    test see "Tests" Specification for test suite no

    The main parameter should be the name of a function and defaults to ${name}:main (i.e. the exported main function of the package named after the program).

    The output of invoking this is a directory containing a bin/${name}.

  • buildLisp.bundled: Creates a virtual dependency on a built-in library.

    Certain libraries ship with Lisp implementations, for example UIOP/ASDF are commonly included but many implementations also ship internals (such as SBCLs various sb-* libraries).

    This function takes a single string argument that is the name of a built-in library and returns a "package" that simply requires this library.

  • buildLisp.sbclWith: Creates an SBCL pre-loaded with various dependencies.

    This function takes a single argument which is a list of Lisp libraries programs or programs. It creates an SBCL that is pre-loaded with all of that Lisp code and can be used as the host for e.g. Sly or SLIME.

Tests

Both buildLisp.library and buildLisp.program take an optional argument tests, which has the following supported fields:

parameter type use required?
name string Name of the test suite no
expression string Lisp expression to run tests yes
srcs list<path> List of paths to source files no
native list<drv> List of native dependencies no

the expression parameter should be a Lisp expression and will be evaluated after loading all sources and dependencies (including library/program dependencies). It must return a non-NIL value if the test suite has passed.

Example

Using buildLisp could look like this:

{ buildLisp, lispPkgs }:

let libExample = buildLisp.library {
    name = "lib-example";
    srcs = [ ./lib.lisp ];

    deps = with lispPkgs; [
      (buildLisp.bundled "sb-posix")
      iterate
      cl-ppcre
    ];
};
in buildLisp.program {
    name = "example";
    deps = [ libExample ];
    srcs = [ ./main.lisp ];
    tests = {
      deps = [ lispPkgs.fiveam ];
      srcs = [ ./tests.lisp ];
      expression = "(fiveam:run!)";
    };
}