about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <Vincent Ambo>2020-01-08T02·00+0000
committerVincent Ambo <Vincent Ambo>2020-01-08T02·00+0000
commita954bd8d5e448b32cd8517affe2607a41c7103ad (patch)
tree94a555d01fd09e809c0274e49d75e785ce29a999
parentcd0093d46ea4cb64aab9ca31c14663c7c9271602 (diff)
feat(nix/buildLisp): Add initial sketch including buildLisp.library r/343
Adds a Nix function to build a Lisp library out of a specified set of
Nix files. All files are combined into a single FASL.

This is by design only compatible with SBCL (for now).
-rw-r--r--nix/buildLisp/README.md21
-rw-r--r--nix/buildLisp/default.nix76
2 files changed, 97 insertions, 0 deletions
diff --git a/nix/buildLisp/README.md b/nix/buildLisp/README.md
new file mode 100644
index 000000000000..513656f5706d
--- /dev/null
+++ b/nix/buildLisp/README.md
@@ -0,0 +1,21 @@
+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.
+
+This is what it currently looks like:
+
+```nix
+nix.buildLisp.library {
+  name = "test-lib";
+  srcs = [
+    ./nix/buildLisp/test-lib.lisp
+  ];
+}
+```
+
+Check back here in a few days for more information.
diff --git a/nix/buildLisp/default.nix b/nix/buildLisp/default.nix
new file mode 100644
index 000000000000..69fcb44ed920
--- /dev/null
+++ b/nix/buildLisp/default.nix
@@ -0,0 +1,76 @@
+# buildLisp provides Nix functions to build Common Lisp packages,
+# targeting SBCL.
+#
+# buildLisp is designed to enforce conventions and do away with the
+# free-for-all of existing Lisp build systems.
+
+{ pkgs ? { third_party = import <nixpkgs> {}; }
+, ... }:
+
+let
+  inherit (builtins) map elemAt match;
+  inherit (pkgs.third_party) lib runCommand writeText sbcl;
+
+  #
+  # Internal helper definitions
+  #
+
+  # 'genCompileLisp' generates a Lisp file that instructs SBCL to
+  # compile the provided list of Lisp source files to $out.
+  genCompileLisp = srcs: writeText "compile.lisp" ''
+      ;; This file compiles the specified sources into the Nix build
+      ;; directory, creating one FASL file for each source.
+      (require 'sb-posix)
+
+      (defun nix-compile-lisp (srcfile)
+        (let ((outfile (make-pathname :type "fasl"
+                                      :directory (or (sb-posix:getenv "NIX_BUILD_TOP")
+                                                     (error "not running in a Nix build"))
+                                      :defaults srcfile)))
+          (compile-file srcfile :output-file outfile)))
+
+      (let ((*compile-verbose* t)
+            ;; FASL files are compiled into the working directory of the
+            ;; build and *then* moved to the correct out location.
+            (pwd (sb-posix:getcwd)))
+
+        ;; These forms were inserted by the Nix build:
+        ${
+          lib.concatStringsSep "\n" (map (src: "(nix-compile-lisp \"${src}\")") srcs)
+        }
+      )
+    '';
+
+  #
+  # Public API functions
+  #
+
+  # Add an `overrideLisp` attribute to a function result that works
+  # similar to `overrideAttrs`, but is used specifically for the
+  # arguments passed to Lisp builders.
+  makeOverridable = f: orig: (f orig) // {
+    overrideLisp = new: makeOverridable f (orig // (new orig));
+  };
+
+  # 'library' builds a list of Common Lisp files into a single FASL
+  # which can then be loaded into SBCL.
+  library = { name, srcs, deps ? [] }: runCommand "${name}-cllib" {} ''
+    ${sbcl}/bin/sbcl --script ${genCompileLisp srcs}
+
+    # FASL files can be combined by simply concatenating them together:
+    mkdir $out
+    cat ./*.fasl > $out/${name}.fasl
+  '';
+
+  # 'program' creates an executable containing a dumped image of the
+  # specified sources and dependencies.
+  program = {};
+
+  # 'sbclWith' creates an image with the specified libraries /
+  # programs loaded.
+  sbclWith = {};
+in {
+  library = makeOverridable library;
+  program = makeOverridable program;
+  sbclWith = makeOverridable sbclWith;
+}