about summary refs log tree commit diff
path: root/nix/buildLisp
diff options
context:
space:
mode:
Diffstat (limited to 'nix/buildLisp')
-rw-r--r--nix/buildLisp/README.md97
-rw-r--r--nix/buildLisp/default.nix28
2 files changed, 107 insertions, 18 deletions
diff --git a/nix/buildLisp/README.md b/nix/buildLisp/README.md
index 513656f5706d..8e45f3479c06 100644
--- a/nix/buildLisp/README.md
+++ b/nix/buildLisp/README.md
@@ -3,19 +3,94 @@ buildLisp.nix
 
 This is a build system for Common Lisp, written in Nix.
 
-The project is in its early stages and currently supports nothing
-other than compiling a bunch of Lisp sources into a combined FASL
-file.
+It aims to offer an alternative to ASDF for users who live in a
+Nix-based ecosystem. This offers several advantages over ASDF:
 
-This is what it currently looks like:
+* 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:
+
+* There is no separate abstraction for tests at the moment (i.e. they
+  are built and run as programs)
+* Only SBCL is supported (though the plan is to add support for at
+  least ABCL and Clozure CL, and maybe make it extensible)
+
+## 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        |
+
+  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        |
+
+  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.
+
+## Example
+
+Using buildLisp could look like this:
 
 ```nix
-nix.buildLisp.library {
-  name = "test-lib";
-  srcs = [
-    ./nix/buildLisp/test-lib.lisp
-  ];
+{ 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 ];
 }
 ```
-
-Check back here in a few days for more information.
diff --git a/nix/buildLisp/default.nix b/nix/buildLisp/default.nix
index 66de38663108..3203206fbe7e 100644
--- a/nix/buildLisp/default.nix
+++ b/nix/buildLisp/default.nix
@@ -8,7 +8,7 @@
 , ... }:
 
 let
-  inherit (builtins) map elemAt match;
+  inherit (builtins) map elemAt match filter;
   inherit (pkgs.third_party) lib runCommandNoCC makeWrapper writeText writeShellScriptBin sbcl;
 
   #
@@ -116,6 +116,7 @@ let
     lispDeps = allDeps deps;
   in runCommandNoCC "${name}-cllib" {
     LD_LIBRARY_PATH = lib.makeLibraryPath lispNativeDeps;
+    LANG = "C.UTF-8";
   } ''
     ${sbcl}/bin/sbcl --script ${genCompileLisp srcs lispDeps}
 
@@ -130,6 +131,7 @@ let
   '' // {
     inherit lispNativeDeps lispDeps;
     lispName = name;
+    lispBinary = false;
   };
 
   # 'program' creates an executable containing a dumped image of the
@@ -153,19 +155,31 @@ let
     }
 
     wrapProgram $out/bin/${name} --prefix LD_LIBRARY_PATH : "${libPath}"
-  '';
+  '' // {
+    lispName = name;
+    lispDeps = [ selfLib ];
+    lispNativeDeps = native;
+    lispBinary = true;
+  };
+
+  # 'bundled' creates a "library" that calls 'require' on a built-in
+  # package, such as any of SBCL's sb-* packages.
+  bundled = name: (makeOverridable library) {
+    inherit name;
+    srcs = lib.singleton (builtins.toFile "${name}.lisp" "(require '${name})");
+  };
 
   # 'sbclWith' creates an image with the specified libraries /
   # programs loaded.
-  sbclWith = deps: let lispDeps = allDeps deps; in writeShellScriptBin "sbcl" ''
+  sbclWith = deps:
+  let lispDeps = filter (d: !d.lispBinary) (allDeps deps);
+  in writeShellScriptBin "sbcl" ''
     export LD_LIBRARY_PATH=${lib.makeLibraryPath (allNative [] lispDeps)};
-    exec ${sbcl}/bin/sbcl ${
-      if deps == [] then ""
-      else "--load ${writeText "load.lisp" (genLoadLisp lispDeps)}"
-    } $@
+    exec ${sbcl}/bin/sbcl ${lib.optionalString (deps != []) "--load ${writeText "load.lisp" (genLoadLisp lispDeps)}"} $@
   '';
 in {
   library = makeOverridable library;
   program = makeOverridable program;
   sbclWith = makeOverridable sbclWith;
+  bundled = makeOverridable bundled;
 }