about summary refs log tree commit diff
path: root/nix/buildLisp
diff options
context:
space:
mode:
authorsterni <sternenseemann@systemli.org>2021-08-11T11·29+0200
committersterni <sternenseemann@systemli.org>2021-08-24T22·00+0000
commitee6b2003fc19337bcce49695a07fe477e221efe0 (patch)
tree58ebe14fbb445e1dafe48b72a96b2d9eb7b2bcf9 /nix/buildLisp
parentacb5994e87fd5aa306f63196fdef9c55cc6345f4 (diff)
feat(nix/buildLisp): implementation specific deps and srcs r/2769
Both the deps and srcs arguments may now have special “filter sets” in
the lists they receive as arguments. When building, buildLisp checks if
such sets either have a attribute named like the current implementation
or a "default" attribute. If yes, the set is replaced by the respective
attribute's value. If no, the set is removed from the list without
replacement.

This can be used to add elements for (a) specific implementation(s):

  { sbcl = buildLisp.bundled "sb-posix"; }

  { sbcl = ./sbcl/optional-sbcl.lisp; }

or to switch between files for different implementations:

  # If a implementation case is missing and no default set present,
  # no file will be added. Compilation will likely fail as a result.
  {
    ecl = ./tf-ecl.lisp;
    ccl = ./tf-ccl.lisp;
    sbcl = ./tf-sbcl.lisp;
  }

or to account for special behavior for a certain implementation:

  {
    ccl = ./ccl-quirk-impl.lisp
    default = ./ansi-impl.lisp;
  }

Change-Id: I082c3701d1f5063b92100bf336a83425471c269d
Reviewed-on: https://cl.tvl.fyi/c/depot/+/3321
Tested-by: BuildkiteCI
Reviewed-by: tazjin <mail@tazj.in>
Diffstat (limited to 'nix/buildLisp')
-rw-r--r--nix/buildLisp/default.nix80
1 files changed, 67 insertions, 13 deletions
diff --git a/nix/buildLisp/default.nix b/nix/buildLisp/default.nix
index d12c1ff1d9..84d5ef08c9 100644
--- a/nix/buildLisp/default.nix
+++ b/nix/buildLisp/default.nix
@@ -16,6 +16,51 @@ let
 
   defaultImplementation = "sbcl";
 
+  # Process a list of arbitrary values which also contains “implementation
+  # filter sets” which describe conditonal inclusion of elements depending
+  # on the CL implementation used. Elements are processed in the following
+  # manner:
+  #
+  # * Paths, strings, derivations are left as is
+  # * A non-derivation attribute set is processed like this:
+  #   1. If it has an attribute equal to impl.name, replace with its value.
+  #   2. Alternatively use the value of the "default" attribute.
+  #   3. In all other cases delete the element from the list.
+  #
+  # This can be used to express dependencies or source files which are specific
+  # to certain implementations:
+  #
+  #  srcs = [
+  #    # mixable with unconditional entries
+  #    ./package.lisp
+  #
+  #    # implementation specific source files
+  #    {
+  #      ccl = ./impl-ccl.lisp;
+  #      sbcl = ./impl-sbcl.lisp;
+  #      ecl = ./impl-ecl.lisp;
+  #    }
+  #  ];
+  #
+  #  deps = [
+  #    # this dependency is ignored if impl.name != "sbcl"
+  #    { sbcl = buildLisp.bundled "sb-posix"; }
+  #
+  #    # only special casing for a single implementation
+  #    {
+  #      sbcl = buildLisp.bundled "uiop";
+  #      default = buildLisp.bundled "asdf";
+  #    }
+  #  ];
+  implFilter = impl: xs:
+    let
+      isFilterSet = x: builtins.isAttrs x && !(lib.isDerivation x);
+    in builtins.map (
+      x: if isFilterSet x then x.${impl.name} or x.default else x
+    ) (builtins.filter (
+      x: !(isFilterSet x) || x ? ${impl.name} || x ? default
+    ) xs);
+
   # Generates lisp code which instructs the given lisp implementation to load
   # all the given dependencies.
   genLoadLispGeneric = impl: deps:
@@ -72,7 +117,8 @@ let
   testSuite = { name, expression, srcs, deps ? [], native ? [], impl }:
     let
       lispNativeDeps = allNative native deps;
-      lispDeps = allDeps impl deps;
+      lispDeps = allDeps impl (implFilter impl deps);
+      filteredSrcs = implFilter impl srcs;
     in runCommandNoCC name {
       LD_LIBRARY_PATH = lib.makeLibraryPath lispNativeDeps;
       LANG = "C.UTF-8";
@@ -81,7 +127,9 @@ let
 
       ${impl.runScript} ${
         impl.genTestLisp {
-          inherit name srcs deps expression;
+          inherit name expression;
+          srcs = filteredSrcs;
+          deps = lispDeps;
         }
       } | tee $out
 
@@ -240,13 +288,15 @@ let
     let
       impl = impls."${implementation}" or
         (builtins.throw "Unkown Common Lisp Implementation ${implementation}");
-      lispNativeDeps = (allNative native deps);
-      lispDeps = allDeps impl deps;
+      filteredDeps = implFilter impl deps;
+      filteredSrcs = implFilter impl srcs;
+      lispNativeDeps = (allNative native filteredDeps);
+      lispDeps = allDeps impl filteredDeps;
       testDrv = if ! isNull tests
         then testSuite {
           name = tests.name or "${name}-test";
-          srcs = srcs ++ (tests.srcs or []);
-          deps = deps ++ (tests.deps or []);
+          srcs = filteredSrcs ++ (tests.srcs or []);
+          deps = filteredDeps ++ (tests.deps or []);
           expression = tests.expression;
           inherit impl;
         }
@@ -270,7 +320,8 @@ let
 
       ${impl.runScript} ${
         impl.genCompileLisp {
-          inherit name srcs;
+          srcs = filteredSrcs;
+          inherit name;
           deps = lispDeps;
         }
       }
@@ -290,20 +341,23 @@ let
     let
       impl = impls."${implementation}" or
         (builtins.throw "Unkown Common Lisp Implementation ${implementation}");
-      lispDeps = allDeps impl deps;
+      filteredSrcs = implFilter impl srcs;
+      filteredDeps = implFilter impl deps;
+      lispDeps = allDeps impl filteredDeps;
       libPath = lib.makeLibraryPath (allNative native lispDeps);
       # overriding is used internally to propagate the implementation to use
       selfLib = (makeOverridable library) {
-        inherit name srcs native;
+        inherit name native;
         deps = lispDeps;
+        srcs = filteredSrcs;
       };
       testDrv = if ! isNull tests
         then testSuite {
           name = tests.name or "${name}-test";
           srcs =
-            (
-              srcs ++ (tests.srcs or []));
-          deps = deps ++ (tests.deps or []);
+            ( # testSuite does run implFilter as well
+              filteredSrcs ++ (tests.srcs or []));
+          deps = filteredDeps ++ (tests.deps or []);
           expression = tests.expression;
           inherit impl;
         }
@@ -314,7 +368,7 @@ let
       LANG = "C.UTF-8";
       passthru = {
         lispName = name;
-        lispDeps = [ selfLib ] ++ (tests.deps or []);
+        lispDeps = [ selfLib ];
         lispNativeDeps = native;
         lispBinary = true;
         tests = testDrv;