[med-svn] [Git][med-team/pplacer][master] 3 commits: Build against libmcl-ocaml-dev (current MCL) instead of mcl14

Andreas Tille (@tille) gitlab at salsa.debian.org
Wed Sep 23 09:03:35 BST 2026



Andreas Tille pushed to branch master at Debian Med / pplacer


Commits:
745faa67 by Andreas Tille at 2026-09-22T22:03:20+02:00
Build against libmcl-ocaml-dev (current MCL) instead of mcl14

The OCaml bindings have been re-enabled in the mcl package against MCL
22-282 (caml_mcl.c is source compatible with the current MCL: the
mclv/mclx type names are kept as aliases), so pplacer can keep using the
"guppy mcl" subcommand and the "--mcl" option of "guppy compress"
while building against the maintained MCL instead of the frozen mcl14
fork, which can now be dropped from Debian.

Also replace the removed ocaml-nox build dependency by ocaml
(Closes: #1131241).

- - - - -
788a05ee by Andreas Tille at 2026-09-23T09:57:04+02:00
Replace the removed Array.create with Array.make and build mutable buffers with Bytes.create instead of String.create (OCaml 5.2+), which is needed now that the build gets past dependency resolution against the re-enabled OCaml bindings of the current mcl package.

* Replace the removed Array.create with Array.make and build mutable
  buffers with Bytes.create instead of String.create (OCaml 5.2+), which
  is needed now that the build gets past dependency resolution against
  the re-enabled OCaml bindings of the current mcl package.
* Build-Depends: add libtingea-dev.  The current mcl OCaml bindings
  record -ltingea in mcl.cmxa, so pplacer needs the tINGea development
  files to link.

- - - - -
0c18ab9d by Andreas Tille at 2026-09-23T09:57:32+02:00
Fix deadlock of pplacer -j N due to OCaml Marshal.header_size change

OCaml changed Marshal.header_size from 20 to 16 bytes.  pplacer
hardcoded the 20-byte header and used Marshal.data_size for the body,
so the 20-byte read consumed 4 bytes of the data and the parent waited
for body bytes that never arrived, deadlocking the forked placement
workers (-j N, default 2).  Read Marshal.header_size bytes and size the
body with Marshal.total_size minus Marshal.header_size instead.

- - - - -


6 changed files:

- debian/changelog
- debian/control
- debian/patches/caml_bigarray.patch
- + debian/patches/marshal_header_size.patch
- + debian/patches/ocaml5-compat.patch
- debian/patches/series


Changes:

=====================================
debian/changelog
=====================================
@@ -1,3 +1,34 @@
+pplacer (1.1~alpha19-10) UNRELEASED; urgency=medium
+
+  * Build against the OCaml bindings for the current MCL version
+    (libmcl-ocaml-dev) instead of the frozen mcl14 fork.  The OCaml
+    bindings have been re-enabled in the mcl package against MCL 22-282,
+    so the mcl14 package can be dropped from Debian.  This keeps the
+    "guppy mcl" subcommand and the "--mcl" option of "guppy compress"
+    working.
+  * Build-Depends: s/ocaml-nox/ocaml/ since ocaml-nox was removed from
+    Debian (Closes: #1131241).
+  * Replace the removed Array.create with Array.make and build mutable
+    buffers with Bytes.create instead of String.create (OCaml 5.2+), which
+    is needed now that the build gets past dependency resolution against
+    the re-enabled OCaml bindings of the current mcl package.
+  * Build-Depends: add libtingea-dev.  The current mcl OCaml bindings
+    record -ltingea in mcl.cmxa, so pplacer needs the tINGea development
+    files to link.
+  * caml_bigarray.patch: use Caml_ba_data_val (the bigarray data pointer)
+    instead of Caml_ba_array_val (the bigarray struct pointer) in the C
+    stubs, which had been operating on the bigarray header.  This was
+    causing wrong likelihood values and heap corruption that surfaced as
+    test failures and segfaults.  gemmish_c also passed the struct pointer
+    to Caml_ba_data_val, yielding the flags field as the data pointer.
+  * New patch marshal_header_size.patch: OCaml reduced Marshal.header_size
+    from 20 to 16 bytes.  pplacer hardcoded the 20-byte header, so the
+    -j N (default 2) forked placement workers deadlocked because the
+    parent read 4 bytes of the data into the "header" and then waited for
+    body bytes that never arrived.  Use Marshal.header_size/total_size.
+
+ -- Andreas Tille <tille at debian.org>  Mon, 21 Sep 2026 00:00:00 +0200
+
 pplacer (1.1~alpha19-9) UNRELEASED; urgency=medium
 
   * Fix Build issues with OCaml 5.2.0 


=====================================
debian/control
=====================================
@@ -6,16 +6,17 @@ Section: science
 Priority: optional
 Build-Depends: debhelper-compat (= 13),
                dh-ocaml,
-               ocaml-nox,
+               ocaml,
                ocamlbuild,
                libcsv-ocaml-dev,
                libxmlm-ocaml-dev,
                libbatteries-ocaml-dev,
-               libmcl14-ocaml-dev,
+               libmcl-ocaml-dev,
                libocamlgsl-ocaml-dev,
                libsqlite3-ocaml-dev,
                libzip-ocaml-dev,
-               libounit-ocaml-dev
+               libounit-ocaml-dev,
+               libtingea-dev
 Standards-Version: 4.7.1
 Vcs-Browser: https://salsa.debian.org/med-team/pplacer
 Vcs-Git: https://salsa.debian.org/med-team/pplacer.git


=====================================
debian/patches/caml_bigarray.patch
=====================================
@@ -1,18 +1,21 @@
 Description: Fix Build issues with OCaml 5.2.0: Upgrade to Ocaml 5.2.0 API of bigarray
+ Fix data pointers: Data_bigarray_val -> Caml_ba_data_val (NOT Caml_ba_array_val,
+ which is the struct pointer). Only gemmish_c got this right originally, the rest
+ pointed at the bigarray header, giving wrong results and heap corruption.
 Author: Andreas Tille <tille at debian.org>
 Bug-Debian: https://bugs.debian.org/1074546
-Last-Update: 2024-12-13
+Last-Update: 2026-09-23
 
 --- a/cdd_src/caml_cdd.c
 +++ b/cdd_src/caml_cdd.c
-@@ -25,17 +25,18 @@
+@@ -25,17 +25,18 @@ double *extreme_vertices(const double *, const size_t, const size_t, float, floa
  CAMLprim value caml_extreme_vertices(value vertices, value lower_bound, value upper_bound)
  {
    CAMLparam3(vertices, lower_bound, upper_bound);
 -  double *vert_arr = Data_bigarray_val(vertices);
 -  int nrows = (Bigarray_val(vertices)->dim[0]);
 -  int ncols = (Bigarray_val(vertices)->dim[1]);
-+  double *vert_arr = Caml_ba_array_val(vertices);
++  double *vert_arr = (double *)Caml_ba_data_val(vertices);
 +  struct caml_ba_array *ba = Caml_ba_array_val(vertices);
 +  int nrows = ba->dim[0];
 +  int ncols = ba->dim[1];
@@ -31,16 +34,16 @@ Last-Update: 2024-12-13
    }
 --- a/pam_src/caml_pam.c
 +++ b/pam_src/caml_pam.c
-@@ -16,7 +16,7 @@
+@@ -16,7 +16,7 @@ CAMLprim value caml_pam(value k_value, value keep_value, value dist_value)
  {
    CAMLparam3(k_value, keep_value, dist_value);
    char *keep = String_val(keep_value);
 -  double *dist = Data_bigarray_val(dist_value);
-+  double *dist = Caml_ba_array_val(dist_value);
++  double *dist = (double *)Caml_ba_data_val(dist_value);
    gsl_matrix_view m;
    gsl_vector_char_view v;
    double work;
-@@ -26,15 +26,16 @@
+@@ -26,15 +26,16 @@ CAMLprim value caml_pam(value k_value, value keep_value, value dist_value)
    intnat *res_ptr;
    int i, k;
  
@@ -56,8 +59,8 @@ Last-Update: 2024-12-13
  
 -  res_bigarr = alloc_bigarray_dims(BIGARRAY_CAML_INT | BIGARRAY_C_LAYOUT, 1, NULL, k);
 -  res_ptr = Data_bigarray_val(res_bigarr);
-+  res_bigarr = caml_ba_alloc_dims(CAML_BA_INT32 | CAML_BA_C_LAYOUT, 1, NULL, k);
-+  res_ptr = Caml_ba_array_val(res_bigarr);
++  res_bigarr = caml_ba_alloc_dims(CAML_BA_CAML_INT | CAML_BA_C_LAYOUT, 1, NULL, k);
++  res_ptr = (intnat *)Caml_ba_data_val(res_bigarr);
    medoids_ptr = medoids;
    for (i = 0; i < k; ++i) {
      *res_ptr++ = *medoids_ptr++;
@@ -75,9 +78,9 @@ Last-Update: 2024-12-13
 +  struct caml_ba_array *dst_ba = Caml_ba_array_val(dst_value);
 +  struct caml_ba_array *a_ba = Caml_ba_array_val(a_value);
 +  struct caml_ba_array *b_ba = Caml_ba_array_val(b_value);
-+  double *dst = (double *)Caml_ba_data_val(dst_ba);
-+  double *a = (double *)Caml_ba_data_val(a_ba);
-+  double *b = (double *)Caml_ba_data_val(b_ba);
++  double *dst = (double *)dst_ba->data;
++  double *a = (double *)a_ba->data;
++  double *b = (double *)b_ba->data;
 +
 +  int n_states = a_ba->dim[0];
 +  int n_sites = b_ba->dim[0];
@@ -100,7 +103,7 @@ Last-Update: 2024-12-13
    if(n_states == 4) {
      for(site=0; site < n_sites; site++) {
        // start back at the top of the matrix
-@@ -92,12 +100,13 @@
+@@ -92,12 +100,13 @@ CAMLprim value gemmish_c(value dst_value, value a_value, value b_value)
  CAMLprim value dediagonalize (value dst_value, value u_value, value lambda_value, value uit_value)
  {
    CAMLparam4(dst_value, u_value, lambda_value, uit_value);
@@ -108,10 +111,10 @@ Last-Update: 2024-12-13
 -  double *u = Data_bigarray_val(u_value);
 -  double *lambda = Data_bigarray_val(lambda_value);
 -  double *uit = Data_bigarray_val(uit_value);
-+  double *dst = Caml_ba_array_val(dst_value);
-+  double *u = Caml_ba_array_val(u_value);
-+  double *lambda = Caml_ba_array_val(lambda_value);
-+  double *uit = Caml_ba_array_val(uit_value);
++  double *dst = (double *)Caml_ba_data_val(dst_value);
++  double *u = (double *)Caml_ba_data_val(u_value);
++  double *lambda = (double *)Caml_ba_data_val(lambda_value);
++  double *uit = (double *)Caml_ba_data_val(uit_value);
    double *uit_p;
 -  int n = Bigarray_val(lambda_value)->dim[0];
 +  struct caml_ba_array *ba = Caml_ba_array_val(lambda_value);
@@ -119,21 +122,21 @@ Last-Update: 2024-12-13
    int i, j, k;
    /* dst.{i,j} <- dst.{i,j} +. (lambda.{k} *. u.{i,k} *. uit.{j,k}) */
    if(n == 4) {
-@@ -152,9 +161,10 @@
+@@ -152,9 +161,10 @@ CAMLprim value dediagonalize (value dst_value, value u_value, value lambda_value
  CAMLprim value mat_print_c(value x_value)
  {
    CAMLparam1(x_value);
 -  double *x = Data_bigarray_val(x_value);
 -  int n_sites = (Bigarray_val(x_value)->dim[0]);
 -  int n_states = (Bigarray_val(x_value)->dim[1]);
-+  double *x = Caml_ba_array_val(x_value);
++  double *x = (double *)Caml_ba_data_val(x_value);
 +  struct caml_ba_array *ba = Caml_ba_array_val(x_value);
 +  int n_sites = ba->dim[0];
 +  int n_states = ba->dim[1];
    double *loc = x;
    int site, state;
    for(site=0; site < n_sites; site++) {
-@@ -171,12 +181,13 @@
+@@ -171,12 +181,13 @@ CAMLprim value mat_log_like3_c(value statd_value, value x_value, value y_value,
  {
    CAMLparam4(statd_value, x_value, y_value, z_value);
    CAMLlocal1(ml_ll_tot);
@@ -143,17 +146,17 @@ Last-Update: 2024-12-13
 -  double *z = Data_bigarray_val(z_value);
 -  int n_sites = Bigarray_val(x_value)->dim[0];
 -  int n_states = Bigarray_val(x_value)->dim[1];
-+  double *statd = Caml_ba_array_val(statd_value);
-+  double *x = Caml_ba_array_val(x_value);
-+  double *y = Caml_ba_array_val(y_value);
-+  double *z = Caml_ba_array_val(z_value);
++  double *statd = (double *)Caml_ba_data_val(statd_value);
++  double *x = (double *)Caml_ba_data_val(x_value);
++  double *y = (double *)Caml_ba_data_val(y_value);
++  double *z = (double *)Caml_ba_data_val(z_value);
 +  struct caml_ba_array *ba = Caml_ba_array_val(x_value);
 +  int n_sites = ba->dim[0];
 +  int n_states = ba->dim[1];
    int site, state;
    double util, ll_tot=0;
    // here we hard code in the limits for some popular choices
-@@ -218,10 +229,11 @@
+@@ -218,10 +229,11 @@ CAMLprim value mat_log_like3_c(value statd_value, value x_value, value y_value,
  CAMLprim value mat_pairwise_prod_c(value dst_value, value x_value, value y_value)
  {
    CAMLparam3(dst_value, x_value, y_value);
@@ -161,15 +164,15 @@ Last-Update: 2024-12-13
 -  double *x = Data_bigarray_val(x_value);
 -  double *y = Data_bigarray_val(y_value);
 -  int size = (Bigarray_val(x_value)->dim[0]) * (Bigarray_val(x_value)->dim[1]);
-+  double *dst = Caml_ba_array_val(dst_value);
-+  double *x = Caml_ba_array_val(x_value);
-+  double *y = Caml_ba_array_val(y_value);
++  double *dst = (double *)Caml_ba_data_val(dst_value);
++  double *x = (double *)Caml_ba_data_val(x_value);
++  double *y = (double *)Caml_ba_data_val(y_value);
 +  struct caml_ba_array *ba = Caml_ba_array_val(x_value);
 +  int size = (ba->dim[0]) * (ba->dim[1]);
    int i;
    for(i=0; i < size; i++) {
      dst[i] = x[i] * y[i];
-@@ -232,12 +244,13 @@
+@@ -232,12 +244,13 @@ CAMLprim value mat_pairwise_prod_c(value dst_value, value x_value, value y_value
  CAMLprim value mat_statd_pairwise_prod_c(value statd_value, value dst_value, value a_value, value b_value)
  {
    CAMLparam4(statd_value, dst_value, a_value, b_value);
@@ -179,17 +182,17 @@ Last-Update: 2024-12-13
 -  double *b = Data_bigarray_val(b_value);
 -  int n_sites = Bigarray_val(a_value)->dim[0];
 -  int n_states = Bigarray_val(a_value)->dim[1];
-+  double *statd = Caml_ba_array_val(statd_value);
-+  double *dst = Caml_ba_array_val(dst_value);
-+  double *a = Caml_ba_array_val(a_value);
-+  double *b = Caml_ba_array_val(b_value);
++  double *statd = (double *)Caml_ba_data_val(statd_value);
++  double *dst = (double *)Caml_ba_data_val(dst_value);
++  double *a = (double *)Caml_ba_data_val(a_value);
++  double *b = (double *)Caml_ba_data_val(b_value);
 +  struct caml_ba_array *ba = Caml_ba_array_val(a_value);
 +  int n_sites = ba->dim[0];
 +  int n_states = ba->dim[1];
    int site, state;
    for(site=0; site < n_sites; site++) {
      for(state=0; state < n_states; state++) {
-@@ -252,12 +265,14 @@
+@@ -252,12 +265,14 @@ CAMLprim value mat_masked_logdot_c(value x_value, value y_value, value mask_valu
  {
    CAMLparam3(x_value, y_value, mask_value);
    CAMLlocal1(ml_ll_tot);
@@ -199,9 +202,9 @@ Last-Update: 2024-12-13
 -  int n_sites = (Bigarray_val(x_value)->dim[0]);
 -  int n_states = (Bigarray_val(x_value)->dim[1]);
 -  if(n_sites != Bigarray_val(mask_value)->dim[0])
-+  double *x = Caml_ba_array_val(x_value);
-+  double *y = Caml_ba_array_val(y_value);
-+  uint16_t *mask = Caml_ba_array_val(mask_value);
++  double *x = (double *)Caml_ba_data_val(x_value);
++  double *y = (double *)Caml_ba_data_val(y_value);
++  uint16_t *mask = (uint16_t *)Caml_ba_data_val(mask_value);
 +  struct caml_ba_array *bax = Caml_ba_array_val(x_value);
 +  struct caml_ba_array *bam = Caml_ba_array_val(mask_value);
 +  int n_sites = bax->dim[0];
@@ -210,14 +213,14 @@ Last-Update: 2024-12-13
      { printf("mat_masked_logdot_c: Mask length doesn't match!"); };
    int site, state;
    double util, ll_tot=0;
-@@ -299,12 +314,13 @@
+@@ -299,12 +314,13 @@ CAMLprim value mat_bounded_logdot_c(value x_value, value y_value, value first_va
  {
    CAMLparam4(x_value, y_value, first_value, last_value);
    CAMLlocal1(ml_ll_tot);
 -  double *x = Data_bigarray_val(x_value);
 -  double *y = Data_bigarray_val(y_value);
-+  double *x = Caml_ba_array_val(x_value);
-+  double *y = Caml_ba_array_val(y_value);
++  double *x = (double *)Caml_ba_data_val(x_value);
++  double *y = (double *)Caml_ba_data_val(y_value);
    int first = Int_val(first_value);
    int last = Int_val(last_value);
    int n_used = 1 + last - first;
@@ -227,7 +230,7 @@ Last-Update: 2024-12-13
    int site, state;
    double util, ll_tot=0;
    // start at the beginning
-@@ -345,10 +361,11 @@
+@@ -345,10 +361,11 @@ CAMLprim value mat_bounded_logdot_c(value x_value, value y_value, value first_va
  CAMLprim value ten_print_c(value x_value)
  {
    CAMLparam1(x_value);
@@ -235,7 +238,7 @@ Last-Update: 2024-12-13
 -  int n_rates = (Bigarray_val(x_value)->dim[0]);
 -  int n_sites = (Bigarray_val(x_value)->dim[1]);
 -  int n_states = (Bigarray_val(x_value)->dim[2]);
-+  double *x = Caml_ba_array_val(x_value);
++  double *x = (double *)Caml_ba_data_val(x_value);
 +  struct caml_ba_array *ba = Caml_ba_array_val(x_value);
 +  int n_rates = ba->dim[0];
 +  int n_sites = ba->dim[1];
@@ -243,7 +246,7 @@ Last-Update: 2024-12-13
    double *loc = x;
    int rate, site, state;
    for(rate=0; rate < n_rates; rate++) {
-@@ -368,14 +385,15 @@
+@@ -368,14 +385,15 @@ CAMLprim value ten_log_like3_c(value statd_value, value x_value, value y_value,
  {
    CAMLparam5(statd_value, x_value, y_value, z_value, util_value);
    CAMLlocal1(ml_ll_tot);
@@ -255,11 +258,11 @@ Last-Update: 2024-12-13
 -  int n_rates = Bigarray_val(x_value)->dim[0];
 -  int n_sites = Bigarray_val(x_value)->dim[1];
 -  int n_states = Bigarray_val(x_value)->dim[2];
-+  double *statd = Caml_ba_array_val(statd_value);
-+  double *x = Caml_ba_array_val(x_value);
-+  double *y = Caml_ba_array_val(y_value);
-+  double *z = Caml_ba_array_val(z_value);
-+  double *util = Caml_ba_array_val(util_value);
++  double *statd = (double *)Caml_ba_data_val(statd_value);
++  double *x = (double *)Caml_ba_data_val(x_value);
++  double *y = (double *)Caml_ba_data_val(y_value);
++  double *z = (double *)Caml_ba_data_val(z_value);
++  double *util = (double *)Caml_ba_data_val(util_value);
 +  struct caml_ba_array *ba = Caml_ba_array_val(x_value);
 +  int n_rates = ba->dim[0];
 +  int n_sites = ba->dim[1];
@@ -267,16 +270,16 @@ Last-Update: 2024-12-13
    int rate, site, state;
    double *util_v;
    for(site=0; site < n_sites; site++) { util[site] = 0.0; }
-@@ -426,13 +444,14 @@
+@@ -426,13 +444,14 @@ CAMLprim value ten_log_like3_c(value statd_value, value x_value, value y_value,
  CAMLprim value ten_pairwise_prod_c(value dst_value, value x_value, value y_value)
  {
    CAMLparam3(dst_value, x_value, y_value);
 -  double *dst = Data_bigarray_val(dst_value);
 -  double *x = Data_bigarray_val(x_value);
 -  double *y = Data_bigarray_val(y_value);
-+  double *dst = Caml_ba_array_val(dst_value);
-+  double *x = Caml_ba_array_val(x_value);
-+  double *y = Caml_ba_array_val(y_value);
++  double *dst = (double *)Caml_ba_data_val(dst_value);
++  double *x = (double *)Caml_ba_data_val(x_value);
++  double *y = (double *)Caml_ba_data_val(y_value);
 +  struct caml_ba_array *ba = Caml_ba_array_val(x_value);
    int size =
 -    (Bigarray_val(x_value)->dim[0])
@@ -288,7 +291,7 @@ Last-Update: 2024-12-13
    int i;
    for(i=0; i < size; i++) {
      dst[i] = x[i] * y[i];
-@@ -443,13 +462,14 @@
+@@ -443,13 +462,14 @@ CAMLprim value ten_pairwise_prod_c(value dst_value, value x_value, value y_value
  CAMLprim value ten_statd_pairwise_prod_c(value statd_value, value dst_value, value a_value, value b_value)
  {
    CAMLparam4(statd_value, dst_value, a_value, b_value);
@@ -299,10 +302,10 @@ Last-Update: 2024-12-13
 -  int n_rates = Bigarray_val(a_value)->dim[0];
 -  int n_sites = Bigarray_val(a_value)->dim[1];
 -  int n_states = Bigarray_val(a_value)->dim[2];
-+  double *statd = Caml_ba_array_val(statd_value);
-+  double *dst = Caml_ba_array_val(dst_value);
-+  double *a = Caml_ba_array_val(a_value);
-+  double *b = Caml_ba_array_val(b_value);
++  double *statd = (double *)Caml_ba_data_val(statd_value);
++  double *dst = (double *)Caml_ba_data_val(dst_value);
++  double *a = (double *)Caml_ba_data_val(a_value);
++  double *b = (double *)Caml_ba_data_val(b_value);
 +  struct caml_ba_array *ba = Caml_ba_array_val(a_value);
 +  int n_rates = ba->dim[0];
 +  int n_sites = ba->dim[1];
@@ -310,7 +313,7 @@ Last-Update: 2024-12-13
    int rate, site, state;
    for(rate=0; rate < n_rates; rate++) {
      for(site=0; site < n_sites; site++) {
-@@ -466,16 +486,19 @@
+@@ -466,16 +486,19 @@ CAMLprim value ten_masked_logdot_c(value x_value, value y_value, value mask_valu
  {
    CAMLparam4(x_value, y_value, mask_value, util_value);
    CAMLlocal1(ml_ll_tot);
@@ -322,10 +325,10 @@ Last-Update: 2024-12-13
 -  int n_sites = Bigarray_val(x_value)->dim[1];
 -  int n_states = Bigarray_val(x_value)->dim[2];
 -  if(n_sites != Bigarray_val(mask_value)->dim[0])
-+  double *x = Caml_ba_array_val(x_value);
-+  double *y = Caml_ba_array_val(y_value);
-+  uint16_t *mask = Caml_ba_array_val(mask_value);
-+  double *util = Caml_ba_array_val(util_value);
++  double *x = (double *)Caml_ba_data_val(x_value);
++  double *y = (double *)Caml_ba_data_val(y_value);
++  uint16_t *mask = (uint16_t *)Caml_ba_data_val(mask_value);
++  double *util = (double *)Caml_ba_data_val(util_value);
 +  struct caml_ba_array *bax = Caml_ba_array_val(x_value);
 +  struct caml_ba_array *bam = Caml_ba_array_val(mask_value);
 +  int n_rates = bax->dim[0];
@@ -339,21 +342,21 @@ Last-Update: 2024-12-13
      { printf("ten_masked_logdot_c: Util length doesn't match!"); };
    int rate, site, state;
    double *x_p, *y_p, *util_v;
-@@ -542,14 +565,15 @@
+@@ -542,14 +565,15 @@ CAMLprim value ten_bounded_logdot_c(value x_value, value y_value, value first_va
  {
    CAMLparam5(x_value, y_value, first_value, last_value, util_value);
    CAMLlocal1(ml_ll_tot);
 -  double *x = Data_bigarray_val(x_value);
 -  double *y = Data_bigarray_val(y_value);
-+  double *x = Caml_ba_array_val(x_value);
-+  double *y = Caml_ba_array_val(y_value);
++  double *x = (double *)Caml_ba_data_val(x_value);
++  double *y = (double *)Caml_ba_data_val(y_value);
    int first = Int_val(first_value);
    int last = Int_val(last_value);
 -  double *util = Data_bigarray_val(util_value);
 -  int n_rates = Bigarray_val(x_value)->dim[0];
 -  int n_sites = Bigarray_val(x_value)->dim[1];
 -  int n_states = Bigarray_val(x_value)->dim[2];
-+  double *util = Caml_ba_array_val(util_value);
++  double *util = (double *)Caml_ba_data_val(util_value);
 +  struct caml_ba_array *ba = Caml_ba_array_val(x_value);
 +  int n_rates = ba->dim[0];
 +  int n_sites = ba->dim[1];
@@ -361,16 +364,16 @@ Last-Update: 2024-12-13
    int rate, site, state;
    int n_used = 1 + last - first;
    /* we make pointers to x, y, and util so that we can do pointer arithmetic
-@@ -607,11 +631,12 @@
+@@ -607,11 +631,12 @@ CAMLprim value ten_bounded_logdot_c(value x_value, value y_value, value first_va
  CAMLprim value vec_pairwise_prod_c(value dst_value, value x_value, value y_value)
  {
    CAMLparam3(dst_value, x_value, y_value);
 -  double *dst = Data_bigarray_val(dst_value);
 -  double *x = Data_bigarray_val(x_value);
 -  double *y = Data_bigarray_val(y_value);
-+  double *dst = Caml_ba_array_val(dst_value);
-+  double *x = Caml_ba_array_val(x_value);
-+  double *y = Caml_ba_array_val(y_value);
++  double *dst = (double *)Caml_ba_data_val(dst_value);
++  double *x = (double *)Caml_ba_data_val(x_value);
++  double *y = (double *)Caml_ba_data_val(y_value);
    int i;
 -  for(i=0; i < Bigarray_val(x_value)->dim[0]; i++) {
 +  struct caml_ba_array *ba = Caml_ba_array_val(x_value);
@@ -378,12 +381,12 @@ Last-Update: 2024-12-13
      dst[i] = x[i] * y[i];
    }
    CAMLreturn(Val_unit);
-@@ -620,10 +645,11 @@
+@@ -620,10 +645,11 @@ CAMLprim value vec_pairwise_prod_c(value dst_value, value x_value, value y_value
  CAMLprim value int_vec_tot_c(value x_value)
  {
    CAMLparam1(x_value);
 -  uint16_t *x = Data_bigarray_val(x_value);
-+  uint16_t *x = Caml_ba_array_val(x_value);
++  uint16_t *x = (uint16_t *)Caml_ba_data_val(x_value);
    CAMLlocal1(ml_tot);
    int i, tot = 0;
 -  for(i=0; i < Bigarray_val(x_value)->dim[0]; i++)
@@ -392,7 +395,7 @@ Last-Update: 2024-12-13
      tot += *x++;
    ml_tot = Val_int(tot);
    CAMLreturn(ml_tot);
-@@ -632,10 +658,11 @@
+@@ -632,10 +658,11 @@ CAMLprim value int_vec_tot_c(value x_value)
  CAMLprim value int_vec_pairwise_prod_c(value dst_value, value x_value, value y_value)
  {
    CAMLparam3(dst_value, x_value, y_value);
@@ -400,24 +403,24 @@ Last-Update: 2024-12-13
 -  uint16_t *x = Data_bigarray_val(x_value);
 -  uint16_t *y = Data_bigarray_val(y_value);
 -  uint16_t *dst_end = dst + Bigarray_val(dst_value)->dim[0];
-+  uint16_t *dst = Caml_ba_array_val(dst_value);
-+  uint16_t *x = Caml_ba_array_val(x_value);
-+  uint16_t *y = Caml_ba_array_val(y_value);
++  uint16_t *dst = (uint16_t *)Caml_ba_data_val(dst_value);
++  uint16_t *x = (uint16_t *)Caml_ba_data_val(x_value);
++  uint16_t *y = (uint16_t *)Caml_ba_data_val(y_value);
 +  struct caml_ba_array *ba = Caml_ba_array_val(dst_value);
 +  uint16_t *dst_end = dst + ba->dim[0];
    while (dst < dst_end)
      *dst++ = *x++ * *y++;
    CAMLreturn(Val_unit);
-@@ -644,16 +671,19 @@
+@@ -644,16 +671,19 @@ CAMLprim value int_vec_pairwise_prod_c(value dst_value, value x_value, value y_v
  CAMLprim value float_mat_int_vec_mul_c(value dst_value, value mat_value, value vec_value)
  {
    CAMLparam3(dst_value, mat_value, vec_value);
 -  double *dst = Data_bigarray_val(dst_value);
 -  double *mat = Data_bigarray_val(mat_value);
 -  uint16_t vec_j, *vec = Data_bigarray_val(vec_value);
-+  double *dst = Caml_ba_array_val(dst_value);
-+  double *mat = Caml_ba_array_val(mat_value);
-+  uint16_t vec_j, *vec = Caml_ba_array_val(vec_value);
++  double *dst = (double *)Caml_ba_data_val(dst_value);
++  double *mat = (double *)Caml_ba_data_val(mat_value);
++  uint16_t vec_j, *vec = (uint16_t *)Caml_ba_data_val(vec_value);
    int j;
 -  int n = Bigarray_val(mat_value)->dim[0], k = Bigarray_val(mat_value)->dim[1];
 +  struct caml_ba_array *bam = Caml_ba_array_val(mat_value);


=====================================
debian/patches/marshal_header_size.patch
=====================================
@@ -0,0 +1,36 @@
+Description: Use Marshal.header_size/total_size for the multiprocessing protocol
+ OCaml changed Marshal.header_size from 20 to 16 bytes.  pplacer hardcoded
+ the 20-byte header and used Marshal.data_size for the body, so the 20-byte
+ read consumed 4 bytes of the data and the parent waited for body bytes that
+ never arrived, deadlocking the forked placement workers (-j N).  Read
+ Marshal.header_size bytes and size the body with Marshal.total_size minus
+ Marshal.header_size instead.
+Author: Andreas Tille <tille at debian.org>
+Forwarded: not-needed
+Last-Update: 2026-09-23
+
+--- a/pplacer_src/multiprocessing.ml
++++ b/pplacer_src/multiprocessing.ml
+@@ -176,7 +176,7 @@
+    *  (b) reading the marshal contents.
+    * Once a whole cycle of this has been completed, call obj_received. *)
+   method virtual obj_received: 'a message -> unit
+-  val mutable marshal_state = Needs_header (buffer 20)
++  val mutable marshal_state = Needs_header (buffer Marshal.header_size)
+   method private marshal_recv h =
+     let b = match marshal_state with
+       | Needs_header b -> b
+@@ -184,11 +184,11 @@
+     in match fill_buffer b h.ch, marshal_state with
+       | Needs_more, _ -> ()
+       | Done header, Needs_header _ ->
+-        marshal_state <- Needs_data (header, buffer (Marshal.data_size (Bytes.of_string header) 0))
++        marshal_state <- Needs_data (header, buffer (Marshal.total_size (Bytes.of_string header) 0 - Marshal.header_size))
+       | Done body, Needs_data (header, _) ->
+         let obj = Marshal.from_string (header ^ body) 0 in
+         self#obj_received obj;
+-        marshal_state <- Needs_header (buffer 20)
++        marshal_state <- Needs_header (buffer Marshal.header_size)
+ 
+   (* By setting the progress channel to work in nonblocking mode, we can use
+    * ocaml's existing line buffering implementation instead of writing our


=====================================
debian/patches/ocaml5-compat.patch
=====================================
@@ -0,0 +1,118 @@
+Description: Fix OCaml 5 compatibility issues
+ Array.create was removed in OCaml 5.2 (deprecated in 5.1) and must be
+ replaced by Array.make.  String.create now returns an immutable string in
+ OCaml 5, so mutable buffers must be built with Bytes.create.  The parser
+ no longer accepts the s.[i] <- v assignment syntax (strings are
+ immutable), so Bytes.set must be used instead.  String.uppercase was
+ removed as well, use String.uppercase_ascii.
+Author: Andreas Tille <tille at debian.org>
+Forwarded: not-needed
+Last-Update: 2026-09-22
+
+--- a/common_src/ppatteries.ml
++++ b/common_src/ppatteries.ml
+@@ -445,7 +445,7 @@
+     if l <> Array.length b then
+       invalid_arg "map2: unequal length arrays";
+     if l = 0 then [||] else begin
+-      let r = Array.create l
++      let r = Array.make l
+         (f (Array.unsafe_get a 0) (Array.unsafe_get b 0)) in
+       for i = 1 to l - 1 do
+         Array.unsafe_set r i
+
+--- a/common_src/uptri.ml
++++ b/common_src/uptri.ml
+@@ -56,7 +56,7 @@
+   if not (dims_ok u i j) then
+     invalid_arg (Printf.sprintf "uptri : dims %d %d in %d not OK" i j u.dim)
+ 
+-let create d x = {dim = d; data = Array.create (n_entries_of_dim d) x}
++let create d x = {dim = d; data = Array.make (n_entries_of_dim d) x}
+ let size u = u.dim
+ let get u i j = assert_dims_ok u i j; u.data.(pair_to_int u.dim i j)
+ let set u i j x = assert_dims_ok u i j; u.data.(pair_to_int u.dim i j) <- x
+
+--- a/common_src/alignment.ml
++++ b/common_src/alignment.ml
+@@ -57,7 +57,7 @@
+   else if same_lengths align then String.length (get_seq align 0)
+   else failwith "length: not all same length"
+ 
+-let pair_uppercase (name, seq) = (name, String.uppercase seq)
++let pair_uppercase (name, seq) = (name, String.uppercase_ascii seq)
+ let uppercase aln = Array.map pair_uppercase aln
+ 
+ let list_of_any_file fname =
+
+--- a/pam_src/pam_solver.ml
++++ b/pam_src/pam_solver.ml
+@@ -22,7 +22,7 @@
+   and total_mass = I.total_mass mass in
+   let keep_string = Bytes.make (Array.length leaf_arr) '\000' in
+   Option.may
+-    (IntSet.iter (fun leaf -> keep_string.[old_leaf_idx leaf] <- '\001'))
++    (IntSet.iter (fun leaf -> Bytes.set keep_string (old_leaf_idx leaf) '\001'))
+     keep;
+   (* Generate a work matrix. *)
+   let leaf_vec, work = IntMap.fold
+
+--- a/pplacer_src/pplacer_run.ml
++++ b/pplacer_src/pplacer_run.ml
+@@ -110,12 +110,12 @@
+     mask
+   in
+   let cut_from_mask (name, seq) =
+-    let seq' = String.create masklen
++    let seq' = Bytes.create masklen
+     and pos = ref 0 in
+     Array.iteri
+       (fun e not_masked ->
+         if not_masked then
+-          (seq'.[!pos] <- seq.[e];
++          (Bytes.set seq' !pos seq.[e];
+            incr pos))
+       mask;
+     name, (Bytes.to_string seq')
+@@ -406,7 +406,7 @@
+   in
+   let q = Queue.create () in
+   List.iter
+-    (fun (name, seq) -> Queue.push (name, (String.uppercase seq)) q)
++    (fun (name, seq) -> Queue.push (name, (String.uppercase_ascii seq)) q)
+     query_list;
+ 
+   (* functions called respectively: when a result is received from a child
+
+--- a/json_src/jsonparse.mly
++++ b/json_src/jsonparse.mly
+@@ -10,19 +10,19 @@
+     and chr i = Char.chr (Int32.to_int i)
+     in
+     if x <= 0x7f then
+-      let s = String.create 1 in
+-      s.[0] <- chr x';
++      let s = Bytes.create 1 in
++      Bytes.set s 0 (chr x');
+       s
+     else if x <= 0x7ff then
+-      let s = String.create 2 in
+-      s.[0] <- chr (x' >>- 6 &- 0b00011111l |- 0b11000000l);
+-      s.[1] <- chr (x' &- 0b00111111l |- 0b10000000l);
++      let s = Bytes.create 2 in
++      Bytes.set s 0 (chr (x' >>- 6 &- 0b00011111l |- 0b11000000l));
++      Bytes.set s 1 (chr (x' &- 0b00111111l |- 0b10000000l));
+       s
+     else if x <= 0xffff then
+-      let s = String.create 3 in
+-      s.[0] <- chr (x' >>- 12 &- 0b00001111l |- 0b11100000l);
+-      s.[1] <- chr (x' >>- 6 &- 0b00111111l |- 0b10000000l);
+-      s.[2] <- chr (x' &- 0b00111111l |- 0b10000000l);
++      let s = Bytes.create 3 in
++      Bytes.set s 0 (chr (x' >>- 12 &- 0b00001111l |- 0b11100000l));
++      Bytes.set s 1 (chr (x' >>- 6 &- 0b00111111l |- 0b10000000l));
++      Bytes.set s 2 (chr (x' &- 0b00111111l |- 0b10000000l));
+       s
+     else
+       invalid_arg "utf8_encode"
+


=====================================
debian/patches/series
=====================================
@@ -10,3 +10,5 @@ no-incompatible-pointer-types.patch
 misleading-indentation.patch
 no_redefined_definitions.patch
 caml_bigarray.patch
+ocaml5-compat.patch
+marshal_header_size.patch



View it on GitLab: https://salsa.debian.org/med-team/pplacer/-/compare/219a43e48523ff25c3b0e12c59c8ea62c128ff3d...0c18ab9df68dd126ae331ac274977d3223e945b5

-- 
View it on GitLab: https://salsa.debian.org/med-team/pplacer/-/compare/219a43e48523ff25c3b0e12c59c8ea62c128ff3d...0c18ab9df68dd126ae331ac274977d3223e945b5
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20260923/2d637971/attachment-0001.htm>


More information about the debian-med-commit mailing list