Subject: bug#26150: closed (Re: bug#26150: [PATCH 0/15]: Add pplacer and OCaml dependencies.)

From: [email-masked] (GNU bug Tracking System)
Date: Wed, 10 May 2017 20:29:03 +0000

Your bug report

#26150: [PATCH 0/15]: Add pplacer and OCaml dependencies.

which was filed against the guix-patches package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
26150: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=26150
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#26150: [PATCH 0/15]: Add pplacer and OCaml dependencies.
From: Ben Woodcroft <[email-masked]>
To: Ludovic Courtès <[email-masked]>
Cc: [email-masked], [email-masked]
Date: Wed, 10 May 2017 22:28:02 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

Hi Ludo,

On 05/04/17 23:18, Ludovic Courtès wrote:
> Ben Woodcroft <[email-masked]> skribis:
> [...]
>
>> +(define package-with-ocaml4.01
>> +  (package-with-explicit-ocaml (delay (default-ocaml4.01))
>> +                               (delay (default-ocaml4.01-findlib))
>> +                                "ocaml-" "ocaml4.01-"
>> +                                #:variant-property 'ocaml4.01-variant))
> I choked for a few hours on this one, my main problem being that I
> didn’t want us to duplicate the logic from build-system/python.scm.
> This led to commits f37f2b83fa95c1fe2bf01c4b8072cfc23d4c67ec and
> 1618006d0bc9bfdc63f4d199fd980f29ecc78ec4.
>
> Is the “variant” property really needed?  In Python it’s needed because
> the 2.x variants sometimes need a different set of dependencies that
> ‘package-with-python2’ cannot automatically guess.  Conversely,
> ‘package-with-guile-2.0’ has no need for that.
>
> If the variant is not needed, then I recommend using
> ‘package-with-input-rewriting’.
>
> If the variant is needed, then could you use ‘package-mapping’ as in
> 1618006d0bc9bfdc63f4d199fd980f29ecc78ec4?
I ended up pushing this series, ending in 
c033f5d6b5b565c43588d25b7b47d177f0c0933c.

There was one package where a different set of inputs was required 
(ocaml4.01-bisect), so I used 'package-mapping' as suggested. Your 
solution seemed very clean to me, thank you for spending those few hours.

> [...]
>> +      (home-page "http://matsen.fhcrc.org/pplacer")
>> +      (license license:gpl3))))
> Version 3 only?
Afraid so.

>> +;; This package is installed alongside 'pplacer'.  It is a separate package so
>> +;; that it can use the python-build-system for the scripts that are
>> +;; distributed alongside the main OCaml binaries.
>> +(define pplacer-scripts
>> +  (package
>> +    (inherit pplacer)
>> +    (name "pplacer-scripts")
> Maybe add a different synopsis?
OK, good.

> Apologies for taking so long!
Not at all, thank your for help. Very happy to see this package in Guix 
at last.
ben

Subject: Re: [PATCH 0/15]: Add pplacer and OCaml dependencies.
From: Ben Woodcroft <[email-masked]>
To: Ludovic Courtès <[email-masked]>
Cc: [email-masked]
Date: Sat, 18 Mar 2017 10:36:31 +1000
List-Id: <debbugs-submit.debbugs.gnu.org>

Hi Ludo, thanks for the feedback.

On 06/03/17 19:16, Ludovic Courtès wrote:
> Hi Ben,
>
> Sorry for the delay.
>
> Ben Woodcroft <[email-masked]> skribis:
>
>> On 10/02/17 08:32, Ludovic Courtès wrote:
>>> Hi Ben,
>>>
>>> Ben Woodcroft <[email-masked]> skribis:
>>>
>>>> I'm quite happy to send these patches in, pplacer has been near the
>>>> top of my most wanted list since I started contributing. There's two
>>>> parts that are a little out of the ordinary:
>>>>
>>>> 1) Unfortunately pplacer requires the outdated OCaml 4.01, so I
>>>> adapted the package-with-python2 approach.
>>> Is there really no way upstream could update the package to current
>>> OCaml?  That would save us a lot of packages and associated work.
>> I'm afraid I don't think so. I asked about this, but haven't received
>> a response for 3 weeks.
>> https://github.com/matsen/pplacer/issues/354
>>
>> The recommended way of installing this software is to download
>> binaries, so updating the OCaml dependency may not be at the top of
>> the priority list. This is maintained software and there's a number of
>> pieces of software which rely on pplacer (including a few of my own),
>> so I think it is worth packaging. So, IMO we should wear the costs on
>> this one.
> OK, that makes sense.
>
> To make progress, how about applying the non-4.01-specific parts of the
> patch series first (I think you didn’t get any feedback on these, so
> it’s safe to assume they’re OK if ‘guix lint’ has nothing to say)?
>
> Second, could you submit the bits about supporting 4.01 to guix-patches?
> I’ll take a look if nobody beats me at it.
OK. I've pushed the non-4.01-specific parts to master, and attached here 
a modified patch series which contains the rest. There's 15 steps but 
most are quite trivial.

Thanks, ben.
>From 1e39824159fe0a43276c810fb514f56761fb8dcd Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Mon, 2 Jan 2017 17:18:59 +1000
Subject: [PATCH 01/15] gnu: Add ocaml-4.01.

* gnu/packages/ocaml.scm (ocaml-4.01): New variable.
---
 gnu/packages/ocaml.scm | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/gnu/packages/ocaml.scm b/gnu/packages/ocaml.scm
index 2f22226b7..2a4410ab1 100644
--- a/gnu/packages/ocaml.scm
+++ b/gnu/packages/ocaml.scm
@@ -7,6 +7,7 @@
 ;;; Copyright © 2016 Jan Nieuwenhuizen <[email-masked]>
 ;;; Copyright © 2016 Efraim Flashner <[email-masked]>
 ;;; Copyright © 2016, 2017 Julien Lepiller <[email-masked]>
+;;; Copyright © 2017 Ben Woodcroft <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -212,6 +213,36 @@ functional, imperative and object-oriented styles of programming.")
     ;; distributed under lgpl2.0.
     (license (list license:qpl license:lgpl2.0))))
 
+(define-public ocaml-4.01
+  (package
+    (inherit ocaml)
+    (version "4.01.0")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "http://caml.inria.fr/pub/distrib/ocaml-"
+                    (version-major+minor version)
+                    "/ocaml-" version ".tar.xz"))
+              (sha256
+               (base32
+                "03d7ida94s1gpr3gadf4jyhmh5rrszd5s4m4z59daaib25rvfyv7"))))
+    (arguments
+     (substitute-keyword-arguments (package-arguments ocaml)
+       ((#:phases phases)
+        `(modify-phases ,phases
+           (replace 'build
+             (lambda _
+               ;; Specifying '-j' at all causes the build to fail.
+               (zero? (system* "make" "world.opt"))))
+           (replace 'check
+             (lambda _
+               (with-directory-excursion "testsuite"
+                 (zero? (system*
+                         "make"
+                         "all"
+                         (string-append
+                          "TOPDIR=" (getcwd) "/.."))))))))))))
+
 (define-public opam
   (package
     (name "opam")
-- 
2.12.0

>From 6acdb4749edfeeb8a8fac3b6df75eeebad9c42cd Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Mon, 2 Jan 2017 22:29:28 +1000
Subject: [PATCH 02/15] gnu: Add ocaml4.01-findlib.

* gnu/packages/ocaml.scm (ocaml4.01-findlib): New variable.
---
 gnu/packages/ocaml.scm | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/gnu/packages/ocaml.scm b/gnu/packages/ocaml.scm
index 2a4410ab1..bff0f9986 100644
--- a/gnu/packages/ocaml.scm
+++ b/gnu/packages/ocaml.scm
@@ -838,6 +838,14 @@ compilation and linkage, there are new frontends of the various OCaml
 compilers that can directly deal with packages.")
     (license license:x11)))
 
+(define-public ocaml4.01-findlib
+  (package
+    (inherit ocaml-findlib)
+    (name "ocaml4.01-findlib")
+    (native-inputs
+     `(("m4" ,m4)
+       ("ocaml" ,ocaml-4.01)))))
+
 ;; note that some tests may hang for no obvious reason.
 (define-public ocaml-ounit
   (package
-- 
2.12.0

>From ec75318098c99f57bb7f769c7989e929cc3fa380 Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Mon, 2 Jan 2017 22:23:34 +1000
Subject: [PATCH 03/15] build-system: Add package-with-ocaml4.01.

* guix/build-system/ocaml.scm (default-ocaml4.01, default-ocaml4.01-findlib,
package-with-explicit-ocaml, package-with-ocaml4.01,
strip-ocaml4.01-variant): New variables.
---
 guix/build-system/ocaml.scm | 92 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 91 insertions(+), 1 deletion(-)

diff --git a/guix/build-system/ocaml.scm b/guix/build-system/ocaml.scm
index f4f57b5ad..7fba1c261 100644
--- a/guix/build-system/ocaml.scm
+++ b/guix/build-system/ocaml.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2016, 2017 Julien Lepiller <[email-masked]>
+;;; Copyright © 2017 Ben Woodcroft <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -15,7 +16,6 @@
 ;;;
 ;;; You should have received a copy of the GNU General Public License
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
-
 (define-module (guix build-system ocaml)
   #:use-module (guix store)
   #:use-module (guix utils)
@@ -25,7 +25,10 @@
   #:use-module (guix build-system gnu)
   #:use-module (guix packages)
   #:use-module (ice-9 match)
+  #:use-module (srfi srfi-1)
   #:export (%ocaml-build-system-modules
+            package-with-ocaml4.01
+            strip-ocaml4.01-variant
             ocaml-build
             ocaml-build-system))
 
@@ -71,6 +74,93 @@
   (let ((module (resolve-interface '(gnu packages ocaml))))
     (module-ref module 'ocaml-findlib)))
 
+(define (default-ocaml4.01)
+  (let ((ocaml (resolve-interface '(gnu packages ocaml))))
+    (module-ref ocaml 'ocaml-4.01)))
+
+(define (default-ocaml4.01-findlib)
+  (let ((module (resolve-interface '(gnu packages ocaml))))
+    (module-ref module 'ocaml4.01-findlib)))
+
+(define* (package-with-explicit-ocaml ocaml findlib old-prefix new-prefix
+                                       #:key variant-property)
+  "Return a procedure of one argument, P.  The procedure creates a package
+with the same fields as P, which is assumed to use OCAML-BUILD-SYSTEM, such
+that it is compiled with OCAML and FINDLIB instead.  The inputs are changed
+recursively accordingly.  If the name of P starts with OLD-PREFIX, this is
+replaced by NEW-PREFIX; otherwise, NEW-PREFIX is prepended to the name.
+
+When VARIANT-PROPERTY is present, it is used as a key to search for
+pre-defined variants of this transformation recorded in the 'properties' field
+of packages.  The property value must be the promise of a package.  This is a
+convenient way for package writers to force the transformation to use
+pre-defined variants."
+  (define transform
+    ;; Memoize the transformations.  Failing to do that, we would build a huge
+    ;; object graph with lots of duplicates, which in turns prevents us from
+    ;; benefiting from memoization in 'package-derivation'.
+    (memoize                                      ;FIXME: use 'eq?'
+     (lambda (p)
+       (let* ((rewrite-if-package
+               (lambda (content)
+                 ;; CONTENT may be a file name, in which case it is returned,
+                 ;; or a package, which is rewritten with the new OCAML and
+                 ;; NEW-PREFIX.
+                 (if (package? content)
+                     (transform content)
+                     content)))
+              (rewrite
+               (match-lambda
+                 ((name content . rest)
+                  (append (list name (rewrite-if-package content)) rest)))))
+
+         (cond
+          ;; If VARIANT-PROPERTY is present, use that.
+          ((and variant-property
+                (assoc-ref (package-properties p) variant-property))
+           => force)
+
+          ;; Otherwise build the new package object graph.
+          ((eq? (package-build-system p) ocaml-build-system)
+           (package
+             (inherit p)
+             (location (package-location p))
+             (name (let ((name (package-name p)))
+                     (string-append new-prefix
+                                    (if (string-prefix? old-prefix name)
+                                        (substring name
+                                                   (string-length old-prefix))
+                                        name))))
+             (arguments
+              (let ((ocaml (if (promise? ocaml)
+                               (force ocaml)
+                               ocaml))
+                    (findlib (if (promise? findlib)
+                                 (force findlib)
+                                 findlib)))
+                (ensure-keyword-arguments (package-arguments p)
+                                          `(#:ocaml ,ocaml
+                                            #:findlib ,findlib))))
+             (inputs (map rewrite (package-inputs p)))
+             (propagated-inputs (map rewrite (package-propagated-inputs p)))
+             (native-inputs (map rewrite (package-native-inputs p)))))
+          (else
+           p))))))
+
+  transform)
+
+(define package-with-ocaml4.01
+  (package-with-explicit-ocaml (delay (default-ocaml4.01))
+                               (delay (default-ocaml4.01-findlib))
+                                "ocaml-" "ocaml4.01-"
+                                #:variant-property 'ocaml4.01-variant))
+
+(define (strip-ocaml4.01-variant p)
+  "Remove the 'ocaml4.01-variant' property from P."
+  (package
+    (inherit p)
+    (properties (alist-delete 'ocaml4.01-variant (package-properties p)))))
+
 (define* (lower name
                 #:key source inputs native-inputs outputs system target
                 (ocaml (default-ocaml))
-- 
2.12.0

>From 6b98a10a41179654788f49f9eb837fff0f94de65 Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Sat, 18 Mar 2017 08:59:01 +1000
Subject: [PATCH 04/15] gnu: Add ocaml4.01-bisect.

* gnu/packages/ocaml.scm (ocaml4.01-bisect): New variable.
(ocaml-bisect)[properties]: New field.
---
 gnu/packages/ocaml.scm | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/gnu/packages/ocaml.scm b/gnu/packages/ocaml.scm
index bff0f9986..7b68b3768 100644
--- a/gnu/packages/ocaml.scm
+++ b/gnu/packages/ocaml.scm
@@ -59,7 +59,8 @@
   #:use-module ((guix licenses) #:prefix license:)
   #:use-module (guix packages)
   #:use-module (guix svn-download)
-  #:use-module (guix utils))
+  #:use-module (guix utils)
+  #:use-module (srfi srfi-1))
 
 ;; A shortcut for files from ocaml forge. Downloaded files are computed from
 ;; their number, not their name.
@@ -1102,8 +1103,20 @@ a camlp4-based tool that allows to instrument your application before running
 tests.  After application execution, it is possible to generate a report in HTML
 format that is the replica of the application source code annotated with code
 coverage information.")
+    (properties `((ocaml4.01-variant . ,(delay ocaml4.01-bisect))))
     (license license:gpl3+)))
 
+(define-public ocaml4.01-bisect
+  (let ((base (package-with-ocaml4.01 (strip-ocaml4.01-variant ocaml-bisect))))
+    (package
+      (inherit base)
+      (arguments
+       `(#:ocaml ,ocaml-4.01
+         ,@(strip-keyword-arguments '(#:make-flags) (package-arguments base))))
+      (native-inputs `(,@(alist-delete "camlp4" (package-native-inputs base))))
+      (propagated-inputs
+       `(,@(alist-delete "camlp4" (package-propagated-inputs base)))))))
+
 (define-public ocaml-bitstring
   (package
     (name "ocaml-bitstring")
-- 
2.12.0

>From e9deb37a918beba30fb3ce3c1f39f14dba28f6d4 Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Sat, 18 Mar 2017 07:10:55 +1000
Subject: [PATCH 05/15] gnu: Add ocaml4.01-sqlite3.

* gnu/packages/ocaml.scm: (ocaml4.01-sqlite3): New variable.
(ocaml-sqlite3)[properties]: New field.
---
 gnu/packages/ocaml.scm | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gnu/packages/ocaml.scm b/gnu/packages/ocaml.scm
index 7b68b3768..268a8ef4c 100644
--- a/gnu/packages/ocaml.scm
+++ b/gnu/packages/ocaml.scm
@@ -1293,8 +1293,12 @@ transactional SQL database engine with outstanding performance for many use
 cases.  These bindings are written in a way that enables a friendly
 coexistence with the old (version 2) SQLite and its OCaml wrapper
 @code{ocaml-sqlite}.")
+    (properties `((ocaml4.01-variant . ,(delay ocaml4.01-sqlite3))))
     (license license:expat)))
 
+(define-public ocaml4.01-sqlite3
+  (package-with-ocaml4.01 (strip-ocaml4.01-variant ocaml-sqlite3)))
+
 (define-public ocaml-csv
   (package
     (name "ocaml-csv")
-- 
2.12.0

>From 6861038410dee1ea663a5129d84f10a6f1cd6227 Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Sat, 18 Mar 2017 07:14:17 +1000
Subject: [PATCH 06/15] gnu: Add ocaml4.01-csv.

* gnu/packages/ocaml.scm (ocaml4.01-csv): New variable.
(ocaml-csv)[properties]: New field.
---
 gnu/packages/ocaml.scm | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gnu/packages/ocaml.scm b/gnu/packages/ocaml.scm
index 268a8ef4c..e44e2ab90 100644
--- a/gnu/packages/ocaml.scm
+++ b/gnu/packages/ocaml.scm
@@ -1321,8 +1321,12 @@ coexistence with the old (version 2) SQLite and its OCaml wrapper
 by all major spreadsheets.  This library implements pure OCaml functions to
 read and write files in this format as well as some convenience functions to
 manipulate such data.")
+    (properties `((ocaml4.01-variant . ,(delay ocaml4.01-csv))))
     (license (package-license camlp4))))
 
+(define-public ocaml4.01-csv
+  (package-with-ocaml4.01 (strip-ocaml4.01-variant ocaml-csv)))
+
 (define-public ocaml-mtime
   (package
     (name "ocaml-mtime")
-- 
2.12.0

>From a64bee2e8d248cb227801a0b915df06530d657e0 Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Sat, 18 Mar 2017 07:15:58 +1000
Subject: [PATCH 07/15] gnu: Add ocaml4.01-gsl.

* gnu/packages/maths.scm (ocaml4.01-gsl): New variable.
(ocaml-gsl)[properties]: New field.
---
 gnu/packages/maths.scm | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gnu/packages/maths.scm b/gnu/packages/maths.scm
index adc81561c..aac0de274 100644
--- a/gnu/packages/maths.scm
+++ b/gnu/packages/maths.scm
@@ -302,8 +302,12 @@ numbers.")
     (description
      "GSL-OCaml is an interface to the @dfn{GNU scientific library} (GSL) for
 the OCaml language.")
+    (properties `((ocaml4.01-variant . ,(delay ocaml4.01-gsl))))
     (license license:gpl3+)))
 
+(define-public ocaml4.01-gsl
+  (package-with-ocaml4.01 (strip-ocaml4.01-variant ocaml-gsl)))
+
 (define-public glpk
   (package
     (name "glpk")
-- 
2.12.0

>From 7c0aaffa5e556e46a9a61319714e43f93cc808d4 Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Sat, 18 Mar 2017 07:17:07 +1000
Subject: [PATCH 08/15] gnu: Add ocaml4.01-mcl.

* gnu/packages/machine-learning.scm (ocaml4.01-mcl): New variable.
(ocaml-mcl)[properties]: New field.
---
 gnu/packages/machine-learning.scm | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gnu/packages/machine-learning.scm b/gnu/packages/machine-learning.scm
index 30f005a33..463fb163f 100644
--- a/gnu/packages/machine-learning.scm
+++ b/gnu/packages/machine-learning.scm
@@ -272,8 +272,12 @@ networks) based on simulation of (stochastic) flow in graphs.")
     (description
      "This package provides OCaml bindings for the MCL graph clustering
 algorithm.")
+    (properties `((ocaml4.01-variant . ,(delay ocaml4.01-mcl))))
     (license license:gpl3)))
 
+(define-public ocaml4.01-mcl
+  (package-with-ocaml4.01 (strip-ocaml4.01-variant ocaml-mcl)))
+
 (define-public randomjungle
   (package
     (name "randomjungle")
-- 
2.12.0

>From 2d132b3c0d0604992dc5176cb5304978c06ed007 Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Fri, 6 Jan 2017 22:15:12 +1000
Subject: [PATCH 09/15] gnu: Add ocaml4.01-camlzip.

* gnu/packages/ocaml.scm (ocaml4.01-camlzip): New variable.
---
 gnu/packages/ocaml.scm | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/gnu/packages/ocaml.scm b/gnu/packages/ocaml.scm
index e44e2ab90..e22952466 100644
--- a/gnu/packages/ocaml.scm
+++ b/gnu/packages/ocaml.scm
@@ -912,8 +912,27 @@ other XUnit testing frameworks.")
     (description "Provides easy access to compressed files in ZIP, GZIP and
 JAR format.  It provides functions for reading from and writing to compressed
 files in these formats.")
+    (properties `((ocaml4.01-variant . ,(delay ocaml4.01-camlzip))))
     (license license:lgpl2.1+)))
 
+(define-public ocaml4.01-camlzip
+  (let ((base (package-with-ocaml4.01 (strip-ocaml4.01-variant camlzip))))
+    (package
+      (inherit base)
+      (name "ocaml4.01-camlzip")
+      ;; Version 1.05 is the last version to support OCaml 4.01.0.
+      (version "1.05")
+      (source
+       (origin
+         (method url-fetch)
+         (uri
+          (string-append
+           "http://forge.ocamlcore.org/frs/download.php/1037/camlzip-"
+           version ".tar.gz"))
+         (sha256
+          (base32
+           "0syh72jk9s0qwjmmfrkqchaj98m020ii082jn38pwnmb6v3p02wk")))))))
+
 (define-public ocamlmod
   (package
     (name "ocamlmod")
-- 
2.12.0

>From 9902aa5db83ee2b0879f4f350f7e827607b21cfd Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Fri, 6 Jan 2017 22:17:34 +1000
Subject: [PATCH 10/15] gnu: Add ocaml4.01-qtest.

* gnu/packages/ocaml.scm (ocaml4.01-qtest): New variable.
(ocaml-qtest)[properties]: New field.
---
 gnu/packages/ocaml.scm | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gnu/packages/ocaml.scm b/gnu/packages/ocaml.scm
index e22952466..a3e464cb9 100644
--- a/gnu/packages/ocaml.scm
+++ b/gnu/packages/ocaml.scm
@@ -1057,8 +1057,12 @@ GNU CC attributes.  It provides also a C pretty printer as an example of use.")
 syntax in comments.  Those tests are then run using the oUnit framework and the
 qcheck library.  The possibilities range from trivial tests -- extremely simple
 to use -- to sophisticated random generation of test cases.")
+    (properties `((ocaml4.01-variant . ,(delay ocaml4.01-qtest))))
     (license license:lgpl3+)))
 
+(define-public ocaml4.01-qtest
+  (package-with-ocaml4.01 (strip-ocaml4.01-variant ocaml-qtest)))
+
 (define-public ocaml-stringext
   (package
     (name "ocaml-stringext")
-- 
2.12.0

>From 6d3b0543c22323944f13d5ca7c7233b94828a144 Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Fri, 6 Jan 2017 22:34:01 +1000
Subject: [PATCH 11/15] gnu: Add ocaml4.01-ounit.

* gnu/packages/ocaml.scm (ocaml4.01-ounit): New variable.
(ocaml-ounit)[properties]: New field.
---
 gnu/packages/ocaml.scm | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gnu/packages/ocaml.scm b/gnu/packages/ocaml.scm
index a3e464cb9..89877a3f5 100644
--- a/gnu/packages/ocaml.scm
+++ b/gnu/packages/ocaml.scm
@@ -870,8 +870,12 @@ compilers that can directly deal with packages.")
     (synopsis "Unit testing framework for OCaml")
     (description "Unit testing framework for OCaml.  It is similar to JUnit and
 other XUnit testing frameworks.")
+    (properties `((ocaml4.01-variant . ,(delay ocaml4.01-ounit))))
     (license license:expat)))
 
+(define-public ocaml4.01-ounit
+  (package-with-ocaml4.01 (strip-ocaml4.01-variant ocaml-ounit)))
+
 (define-public camlzip
   (package
     (name "camlzip")
-- 
2.12.0

>From f907957a0243c43dfe9c0c29400545b115ec92f8 Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Sat, 4 Feb 2017 12:15:39 +1000
Subject: [PATCH 12/15] gnu: Add ocaml4.01-xmlm.

* gnu/packages/ocaml.scm (ocaml4.01-xmlm): New variable.
(ocaml-xmlm)[properties]: New field.
---
 gnu/packages/ocaml.scm | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gnu/packages/ocaml.scm b/gnu/packages/ocaml.scm
index 89877a3f5..20a13cdea 100644
--- a/gnu/packages/ocaml.scm
+++ b/gnu/packages/ocaml.scm
@@ -1741,8 +1741,12 @@ run command line programs.")
     (description "Xmlm is a streaming codec to decode and encode the XML data
 format.  It can process XML documents without a complete in-memory
 representation of the data.")
+    (properties `((ocaml4.01-variant . ,(delay ocaml4.01-xmlm))))
     (license license:isc)))
 
+(define-public ocaml4.01-xmlm
+  (package-with-ocaml4.01 (strip-ocaml4.01-variant ocaml-xmlm)))
+
 (define-public ocaml-ulex
   (package
     (name "ocaml-ulex")
-- 
2.12.0

>From 38c70285408cf1fd3c0d571df6b8e35abcc63236 Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Sat, 4 Feb 2017 12:16:50 +1000
Subject: [PATCH 13/15] gnu: Add ocaml4.01-batteries.

* gnu/packages/ocaml.scm (ocaml4.01-batteries): New variable.
(ocaml-batteries)[properties]: New field.
---
 gnu/packages/ocaml.scm | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gnu/packages/ocaml.scm b/gnu/packages/ocaml.scm
index 20a13cdea..94608aca6 100644
--- a/gnu/packages/ocaml.scm
+++ b/gnu/packages/ocaml.scm
@@ -2010,8 +2010,12 @@ many additional enhancements, including:
     (description "Define a standard set of libraries which may be expected on
 every compliant installation of OCaml and organize these libraries into a
 hierarchy of modules.")
+    (properties `((ocaml4.01-variant . ,(delay ocaml4.01-batteries))))
     (license license:lgpl2.1+)))
 
+(define-public ocaml4.01-batteries
+  (package-with-ocaml4.01 (strip-ocaml4.01-variant ocaml-batteries)))
+
 (define-public ocaml-pcre
   (package
     (name "ocaml-pcre")
-- 
2.12.0

>From 0253fdf1f723a8029f6e2511bfcad6543394b00a Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Sat, 4 Feb 2017 15:23:45 +1000
Subject: [PATCH 14/15] gnu: Add taxtastic.

* gnu/packages/bioinformatics.scm (taxtastic): New variable.
---
 gnu/packages/bioinformatics.scm | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/gnu/packages/bioinformatics.scm b/gnu/packages/bioinformatics.scm
index ccde01b11..25f3ea0a6 100644
--- a/gnu/packages/bioinformatics.scm
+++ b/gnu/packages/bioinformatics.scm
@@ -5228,6 +5228,42 @@ between experiments, StringTie's output can be processed either by the
 Cuffdiff or Ballgown programs.")
     (license license:artistic2.0)))
 
+(define-public taxtastic
+  (package
+    (name "taxtastic")
+    (version "0.5.7")
+    ;; Versions after 0.5.4 do not appear to be distributed on PyPI so we
+    ;; download the package from GitHub.
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "https://github.com/fhcrc/taxtastic/archive/v"
+                    version ".tar.gz"))
+              (file-name (string-append name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "1s0h5y1lds1c40jhir5585ffm6yjyn8h5aqimpgv64rhqhfv56xx"))))
+    (build-system python-build-system)
+    (arguments
+     `(#:python ,python-2
+       #:phases
+       (modify-phases %standard-phases
+         (replace 'check
+           (lambda _
+             (zero? (system* "python" "-m" "unittest" "discover" "-v")))))))
+    (propagated-inputs
+     `(("python-sqlalchemy" ,python2-sqlalchemy)
+       ("python-decorator" ,python2-decorator)
+       ("python-biopython" ,python2-biopython)
+       ("python-pandas" ,python2-pandas)))
+    (home-page "https://github.com/fhcrc/taxtastic")
+    (synopsis "Tools for taxonomic naming and annotation")
+    (description
+     "Taxtastic is software written in python used to build and maintain
+reference packages i.e. collections of reference trees, reference alignments,
+profiles, and associated taxonomic information.")
+    (license license:gpl3+)))
+
 (define-public vcftools
   (package
     (name "vcftools")
-- 
2.12.0

>From 3d4e5e2e73067c5968e38abd1fe0e88204d6d9f8 Mon Sep 17 00:00:00 2001
From: Ben Woodcroft <[email-masked]>
Date: Sat, 4 Feb 2017 15:25:29 +1000
Subject: [PATCH 15/15] gnu: Add pplacer.

* gnu/packages/bioinformatics.scm (pplacer, pplacer-scripts): New
variables.
---
 gnu/packages/bioinformatics.scm | 124 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/gnu/packages/bioinformatics.scm b/gnu/packages/bioinformatics.scm
index 25f3ea0a6..87deeebef 100644
--- a/gnu/packages/bioinformatics.scm
+++ b/gnu/packages/bioinformatics.scm
@@ -33,6 +33,7 @@
   #:use-module (guix build-system ant)
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system cmake)
+  #:use-module (guix build-system ocaml)
   #:use-module (guix build-system perl)
   #:use-module (guix build-system python)
   #:use-module (guix build-system r)
@@ -71,6 +72,7 @@
   #:use-module (gnu packages maths)
   #:use-module (gnu packages mpi)
   #:use-module (gnu packages ncurses)
+  #:use-module (gnu packages ocaml)
   #:use-module (gnu packages pcre)
   #:use-module (gnu packages parallel)
   #:use-module (gnu packages pdf)
@@ -3605,6 +3607,128 @@ interrupted by stop codons.  OrfM finds and prints these ORFs.")
     (home-page "https://github.com/wwood/OrfM")
     (license license:lgpl3+)))
 
+(define-public pplacer
+  (let ((commit "g807f6f3"))
+    (package
+      (name "pplacer")
+      ;; The commit should be updated with each version change.
+      (version "1.1.alpha19")
+      (source
+       (origin
+         (method url-fetch)
+         (uri (string-append "https://github.com/matsen/pplacer/archive/v"
+                             version ".tar.gz"))
+         (file-name (string-append name "-" version ".tar.gz"))
+         (sha256
+          (base32 "0z1lnd2s8sh6kpzg106wzbh2szw7h0hvq8syd5a6wv4rmyyz6x0f"))))
+      (build-system ocaml-build-system)
+      (arguments
+       `(#:ocaml ,ocaml-4.01
+         #:findlib ,ocaml4.01-findlib
+         #:modules ((guix build ocaml-build-system)
+                    (guix build utils)
+                    (ice-9 ftw))
+         #:phases
+         (modify-phases %standard-phases
+           (delete 'configure)
+           (add-after 'unpack 'replace-bundled-cddlib
+             (lambda* (#:key inputs #:allow-other-keys)
+               (let* ((cddlib-src (assoc-ref inputs "cddlib-src"))
+                      (local-dir "cddlib_guix"))
+                 (mkdir local-dir)
+                 (with-directory-excursion local-dir
+                   (system* "tar" "xvf" cddlib-src))
+                 (let ((cddlib-src-folder
+                        (string-append local-dir "/"
+                                       (list-ref (scandir local-dir) 2)
+                                       "/lib-src")))
+                   (for-each
+                    (lambda (file)
+                      (copy-file file
+                                 (string-append "cdd_src/" (basename file))))
+                    (find-files cddlib-src-folder ".*[ch]$")))
+                 #t)))
+           (add-after 'unpack 'fix-makefile
+             (lambda _
+               ;; Remove system calls to 'git'.
+               (substitute* "Makefile"
+                 (("^DESCRIPT:=pplacer-.*")
+                  (string-append
+                   "DESCRIPT:=pplacer-$(shell uname)-v" ,version "\n")))
+               (substitute* "myocamlbuild.ml"
+                 (("git describe --tags --long .*\\\" with")
+                  (string-append
+                   "echo -n v" ,version "-" ,commit "\" with")))
+               #t))
+           (replace 'install
+             (lambda* (#:key outputs #:allow-other-keys)
+               (let* ((out (assoc-ref outputs "out"))
+                      (bin (string-append out "/bin")))
+                 (copy-recursively "bin" bin))
+               #t)))))
+      (native-inputs
+       `(("zlib" ,zlib)
+         ("gsl" ,gsl)
+         ("ocaml-ounit" ,ocaml4.01-ounit)
+         ("ocaml-batteries" ,ocaml4.01-batteries)
+         ("ocaml-camlzip" ,ocaml4.01-camlzip)
+         ("ocaml-csv" ,ocaml4.01-csv)
+         ("ocaml-sqlite3" ,ocaml4.01-sqlite3)
+         ("ocaml-xmlm" ,ocaml4.01-xmlm)
+         ("ocaml-mcl" ,ocaml4.01-mcl)
+         ("ocaml-gsl" ,ocaml4.01-gsl)
+         ("cddlib-src" ,(package-source cddlib))))
+      (propagated-inputs
+       `(("pplacer-scripts" ,pplacer-scripts)))
+      (synopsis "Phylogenetic placement of biological sequences")
+      (description
+       "Pplacer places query sequences on a fixed reference phylogenetic tree
+to maximize phylogenetic likelihood or posterior probability according to a
+reference alignment.  Pplacer is designed to be fast, to give useful
+information about uncertainty, and to offer advanced visualization and
+downstream analysis.")
+      (home-page "http://matsen.fhcrc.org/pplacer")
+      (license license:gpl3))))
+
+;; This package is installed alongside 'pplacer'.  It is a separate package so
+;; that it can use the python-build-system for the scripts that are
+;; distributed alongside the main OCaml binaries.
+(define pplacer-scripts
+  (package
+    (inherit pplacer)
+    (name "pplacer-scripts")
+    (build-system python-build-system)
+    (arguments
+     `(#:python ,python-2
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'enter-scripts-dir
+           (lambda _ (chdir "scripts")))
+         (replace 'check
+           (lambda _
+             (zero? (system* "python" "-m" "unittest" "discover" "-v"))))
+         (add-after 'install 'wrap-executables
+           (lambda* (#:key inputs outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (bin (string-append out "/bin")))
+               (let ((path (string-append
+                            (assoc-ref inputs "hmmer") "/bin:"
+                            (assoc-ref inputs "infernal") "/bin")))
+                 (display path)
+                 (wrap-program (string-append bin "/refpkg_align.py")
+                   `("PATH" ":" prefix (,path))))
+               (let ((path (string-append
+                            (assoc-ref inputs "hmmer") "/bin")))
+                 (wrap-program (string-append bin "/hrefpkg_query.py")
+                   `("PATH" ":" prefix (,path)))))
+             #t)))))
+    (inputs
+     `(("infernal" ,infernal)
+       ("hmmer" ,hmmer)))
+    (propagated-inputs
+     `(("python-biopython" ,python2-biopython)
+       ("taxtastic" ,taxtastic)))))
+
 (define-public python2-pbcore
   (package
     (name "python2-pbcore")
-- 
2.12.0