diff options
author | Michael Raskin <7c6f434c@mail.ru> | 2017-03-26 04:15:42 +0200 |
---|---|---|
committer | Michael Raskin <7c6f434c@mail.ru> | 2017-03-29 00:40:01 +0200 |
commit | 13007957e5bf8bf31f7c99a054e2f0bdb395e860 (patch) | |
tree | fe8e83ef8d0ce5e5dc44595edf7e2811f9aea05a /pkgs/development/lisp-modules/quicklisp-to-nix | |
parent | eb70ae34b1da2894bc60ed0064efd2de068d28ad (diff) | |
download | nixlib-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')
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 |