about summary refs log tree commit diff
path: root/pkgs/development/lisp-modules/quicklisp-to-nix
diff options
context:
space:
mode:
authorMichael Raskin <7c6f434c@mail.ru>2017-03-26 04:15:42 +0200
committerMichael Raskin <7c6f434c@mail.ru>2017-03-29 00:40:01 +0200
commit13007957e5bf8bf31f7c99a054e2f0bdb395e860 (patch)
treefe8e83ef8d0ce5e5dc44595edf7e2811f9aea05a /pkgs/development/lisp-modules/quicklisp-to-nix
parenteb70ae34b1da2894bc60ed0064efd2de068d28ad (diff)
downloadnixlib-13007957e5bf8bf31f7c99a054e2f0bdb395e860.tar
nixlib-13007957e5bf8bf31f7c99a054e2f0bdb395e860.tar.gz
nixlib-13007957e5bf8bf31f7c99a054e2f0bdb395e860.tar.bz2
nixlib-13007957e5bf8bf31f7c99a054e2f0bdb395e860.tar.lz
nixlib-13007957e5bf8bf31f7c99a054e2f0bdb395e860.tar.xz
nixlib-13007957e5bf8bf31f7c99a054e2f0bdb395e860.tar.zst
nixlib-13007957e5bf8bf31f7c99a054e2f0bdb395e860.zip
quicklispPackages: init
The idea is to have an almost-automatic conversion from QuickLisp, the
definitive Common Lisp package repository, to Nix. The benefit over just
using lispPackages.quicklisp is automatic installation of non-Lisp
dependencies from NixPkgs (and integration with Nix package management).
The benefit over lispPackages for normal Lisp packages is packaging just
a snapshot of QuickLisp which is known to be tested for version
compatibility between libraries.

There are some packages in lispPackages that are not from QuickLisp (for
example, the installable wrapper of QuickLisp itself). My hope is to
replace the rest with the expressions converted from QuickLisp.

Note that the current commit is a mere addition.
Diffstat (limited to 'pkgs/development/lisp-modules/quicklisp-to-nix')
-rw-r--r--pkgs/development/lisp-modules/quicklisp-to-nix/invocation.emb8
-rw-r--r--pkgs/development/lisp-modules/quicklisp-to-nix/nix-package.emb14
-rw-r--r--pkgs/development/lisp-modules/quicklisp-to-nix/ql-to-nix.lisp124
-rw-r--r--pkgs/development/lisp-modules/quicklisp-to-nix/top-package.emb11
4 files changed, 157 insertions, 0 deletions
diff --git a/pkgs/development/lisp-modules/quicklisp-to-nix/invocation.emb b/pkgs/development/lisp-modules/quicklisp-to-nix/invocation.emb
new file mode 100644
index 000000000000..78e88d4b9fa9
--- /dev/null
+++ b/pkgs/development/lisp-modules/quicklisp-to-nix/invocation.emb
@@ -0,0 +1,8 @@
+  "<% @var name %>" = buildLispPackage
+    ((f: x: (x // (f x)))
+       (qlOverrides."<% @var name %>" or (x: {}))
+       (import ./quicklisp-to-nix-output/<% @var name %>.nix {
+         inherit fetchurl;
+         <% @loop deps %>"<% @var name %>" = quicklisp-to-nix-packages."<% @var name %>";
+         <% @endloop %>
+       }));
diff --git a/pkgs/development/lisp-modules/quicklisp-to-nix/nix-package.emb b/pkgs/development/lisp-modules/quicklisp-to-nix/nix-package.emb
new file mode 100644
index 000000000000..b54f555180d6
--- /dev/null
+++ b/pkgs/development/lisp-modules/quicklisp-to-nix/nix-package.emb
@@ -0,0 +1,14 @@
+args @ { fetchurl, ... }:
+rec {
+  baseName = ''<% @var name %>'';
+  version = ''<% @var version %>'';
+
+  description = ''<% @var description %>'';
+
+  deps = [ <% @loop deps %>args."<% @var name %>" <% @endloop %>];
+
+  src = fetchurl {
+    url = ''<% @var url %>'';
+    sha256 = ''<% @var sha256 %>'';
+  };
+}
diff --git a/pkgs/development/lisp-modules/quicklisp-to-nix/ql-to-nix.lisp b/pkgs/development/lisp-modules/quicklisp-to-nix/ql-to-nix.lisp
new file mode 100644
index 000000000000..ded802ca693a
--- /dev/null
+++ b/pkgs/development/lisp-modules/quicklisp-to-nix/ql-to-nix.lisp
@@ -0,0 +1,124 @@
+; QuickLisp-to-Nix export
+; Requires QuickLisp to be loaded
+; Installs the QuickLisp version of all the packages processed (in the
+; QuickLisp instance it uses)
+
+(ql:quickload :cl-emb)
+(ql:quickload :external-program)
+(ql:quickload :cl-ppcre)
+(ql:quickload :md5)
+(ql:quickload :alexandria)
+
+(defun nix-prefetch-url (url)
+  (let*
+    ((stdout nil)
+     (stderr nil))
+    (setf
+      stdout
+      (with-output-to-string (so)
+        (setf
+          stderr
+          (with-output-to-string (se)
+            (external-program:run
+              "nix-prefetch-url"
+              (list url)
+              :search t :output so :error se)))))
+    (let*
+      ((path-line (first (last (cl-ppcre:split (format nil "~%") stderr))))
+       (path (cl-ppcre:regex-replace-all "path is .(.*)." path-line "\\1")))
+      (list
+        :sha256 (first (cl-ppcre:split (format nil "~%") stdout))
+        :path path
+        :md5 (string-downcase
+               (format nil "~{~16,2,'0r~}"
+                       (map 'list 'identity (md5:md5sum-file path))))))))
+
+(defun system-data (system)
+  (ql:quickload system)
+  (let*
+    ((asdf-system (asdf:find-system system))
+     (ql-system (ql-dist:find-system system))
+     (ql-release (ql-dist:release ql-system))
+     (url (ql-dist:archive-url ql-release))
+     (local-archive (ql-dist:local-archive-file ql-release))
+     (local-url (format nil "file://~a" (pathname local-archive)))
+     (archive-data
+       (progn
+         (ql-dist:ensure-local-archive-file ql-release)
+         (nix-prefetch-url local-url)))
+     (ideal-md5 (ql-dist:archive-md5 ql-release))
+     (file-md5 (getf archive-data :md5))
+     (raw-dependencies (asdf:system-depends-on asdf-system))
+     (dependencies (remove-if-not 'ql-dist:find-system raw-dependencies))
+     (deps (mapcar (lambda (x) (list :name x)) dependencies))
+     (name (string-downcase (format nil "~a" system)))
+     (description (asdf:system-description asdf-system))
+     (release-name (ql-dist:short-description ql-release))
+     (version (cl-ppcre:regex-replace-all
+                (format nil "~a-" name) release-name "")))
+    (assert (equal ideal-md5 file-md5))
+  (list
+    :system system
+    :description description
+    :sha256 (getf archive-data :sha256)
+    :url url
+    :md5 file-md5
+    :name name
+    :deps deps
+    :dependencies dependencies
+    :version version)))
+
+(defmacro this-file ()
+  (or *compile-file-truename*
+      *load-truename*))
+
+(defun nix-expression (system)
+  (cl-emb:execute-emb
+    (merge-pathnames #p"nix-package.emb" (this-file))
+    :env (system-data system)))
+(defun nix-invocation (system)
+  (cl-emb:execute-emb
+    (merge-pathnames #p"invocation.emb" (this-file))
+    :env (system-data system)))
+
+(defun systems-closure (systems)
+  (let*
+    ((seen (make-hash-table :test 'equal)))
+    (loop
+      with queue := systems
+      with res := nil
+      while queue
+      for next := (pop queue)
+      for deps := (getf (system-data next) :dependencies)
+      unless (gethash next seen) do
+      (progn
+        (push next res)
+        (setf queue (append queue deps)))
+      do (setf (gethash next seen) t)
+      finally (return res))))
+
+(defun ql-to-nix (target-directory)
+  (let*
+    ((systems
+       (cl-ppcre:split
+         (format nil "~%")
+         (alexandria:read-file-into-string
+           (format nil "~a/quicklisp-to-nix-systems.txt" target-directory))))
+     (closure (systems-closure systems))
+     (invocations
+       (loop for s in closure
+             collect (list :code (nix-invocation s)))))
+    (loop
+      for s in closure
+      do (alexandria:write-string-into-file
+           (nix-expression s)
+           (format nil "~a/quicklisp-to-nix-output/~a.nix" target-directory s)
+           :if-exists :supersede))
+    (alexandria:write-string-into-file
+      (cl-emb:execute-emb
+        (merge-pathnames
+          #p"top-package.emb"
+          (this-file))
+        :env (list :invocations invocations))
+      (format nil "~a/quicklisp-to-nix.nix" target-directory)
+      :if-exists :supersede)))
diff --git a/pkgs/development/lisp-modules/quicklisp-to-nix/top-package.emb b/pkgs/development/lisp-modules/quicklisp-to-nix/top-package.emb
new file mode 100644
index 000000000000..2cbe73c89ca3
--- /dev/null
+++ b/pkgs/development/lisp-modules/quicklisp-to-nix/top-package.emb
@@ -0,0 +1,11 @@
+{stdenv, fetchurl, pkgs, clwrapper}:
+let quicklisp-to-nix-packages = rec {
+  inherit stdenv fetchurl clwrapper pkgs quicklisp-to-nix-packages;
+
+  callPackage = pkgs.lib.callPackageWith quicklisp-to-nix-packages;
+  buildLispPackage = callPackage ./define-package.nix;
+  qlOverrides = callPackage ./quicklisp-to-nix-overrides.nix {};
+<% @loop invocations %>
+<% @var code %>
+<% @endloop %>
+}; in quicklisp-to-nix-packages