about summary refs log tree commit diff
path: root/nix/buildLisp
diff options
context:
space:
mode:
authorVincent Ambo <Vincent Ambo>2020-01-09T02·57+0000
committerVincent Ambo <Vincent Ambo>2020-01-09T02·57+0000
commit44820827d191b9a7bec152b5a51d101661e8f4a5 (patch)
tree041acde1a09670bf6cd289737f47816605d5c596 /nix/buildLisp
parentfd9fb7730ad1f99fe24b524985bb80116a2fd31c (diff)
feat(buildLisp): Initial implementation of foreign library loading r/364
Adds a new 'native' parameter to the buildLisp functions in which
libraries can be passed in.

This does not yet work with CFFI packages.
Diffstat (limited to 'nix/buildLisp')
-rw-r--r--nix/buildLisp/default.nix55
1 files changed, 46 insertions, 9 deletions
diff --git a/nix/buildLisp/default.nix b/nix/buildLisp/default.nix
index 15dddfbbab..15dc5f73e4 100644
--- a/nix/buildLisp/default.nix
+++ b/nix/buildLisp/default.nix
@@ -70,6 +70,22 @@ let
     lib.flatten (deps ++ (map (d: d.lispDeps) deps))
   ))).result;
 
+  # 'allNative' extracts all native dependencies of a dependency list
+  # to ensure that library load paths are set correctly during all
+  # compilations and program assembly.
+  allNative = native: deps: lib.unique (
+    lib.flatten (native ++ (map (d: d.lispNativeDeps) deps))
+  );
+
+  # 'pushLibDirs' generates forms that push all native library paths
+  # onto the variable `CFFI:*FOREIGN-LIBRARY-DIRECTORIES*` which is
+  # required for any runtime loading of libraries via CFFI.
+  pushLibDirs = deps: lib.concatStringsSep "\n" (
+    map (l: "(push \"${
+      lib.getLib l
+    }/lib\" cffi:*foreign-library-directories*)") (allNative [] deps)
+  );
+
   # 'genDumpLisp' generates a Lisp file that instructs SBCL to dump
   # the currently loaded image as an executable to $out/bin/$name.
   #
@@ -80,6 +96,10 @@ let
 
     ${genLoadLisp deps}
 
+    ;; Push library directories if CFFI is in use.
+    (when (boundp 'cffi:*foreign-library-directories*)
+      ${pushLibDirs deps})
+
     (let* ((bindir (concatenate 'string (sb-posix:getenv "out") "/bin"))
            (outpath (make-pathname :name "${name}"
                                    :directory bindir)))
@@ -103,8 +123,16 @@ let
 
   # 'library' builds a list of Common Lisp files into a single FASL
   # which can then be loaded into SBCL.
-  library = { name, srcs, deps ? [] }: runCommandNoCC "${name}-cllib" {} ''
-    ${sbcl}/bin/sbcl --script ${genCompileLisp srcs deps}
+  library = { name, srcs, deps ? [], native ? [] }:
+  let
+    lispNativeDeps = (allNative native deps);
+    lispDeps = allDeps deps;
+  in runCommandNoCC "${name}-cllib" {
+    LD_LIBRARY_PATH = lib.makeLibraryPath lispNativeDeps;
+  } ''
+    ${sbcl}/bin/sbcl --script ${genCompileLisp srcs lispDeps}
+
+    echo "Compilation finished, assembling FASL files"
 
     # FASL files can be combined by simply concatenating them
     # together, but it needs to be in the compilation order.
@@ -112,25 +140,34 @@ let
 
     chmod +x cat_fasls
     ./cat_fasls > $out/${name}.fasl
-  '' // { lispName = name; lispDeps = deps; };
+  '' // {
+    inherit lispNativeDeps lispDeps;
+    lispName = name;
+  };
 
   # 'program' creates an executable containing a dumped image of the
   # specified sources and dependencies.
-  program = { name, main ? "${name}:main", srcs, deps ? [] }: runCommandNoCC "${name}" {} ''
+  program = { name, main ? "${name}:main", srcs, deps ? [], native ? [] }:
+  let
+    lispDeps = allDeps deps;
+    selfLib = library {
+      inherit name srcs native;
+      deps = lispDeps;
+    };
+  in runCommandNoCC "${name}" {} ''
     mkdir -p $out/bin
     ${sbcl}/bin/sbcl --script ${
-      genDumpLisp name main (lib.singleton (library {
-        inherit name srcs deps;
-      }))
+      genDumpLisp name main ([ selfLib ] ++ lispDeps)
     }
   '';
 
   # 'sbclWith' creates an image with the specified libraries /
   # programs loaded.
-  sbclWith = deps: writeShellScriptBin "sbcl" ''
+  sbclWith = deps: let lispDeps = 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 deps)}"
+      else "--load ${writeText "load.lisp" (genLoadLisp lispDeps)}"
     } $@
   '';
 in {