Skip to content

3.25.0~alpha0 no longer exports OCAMLPATH to actions #16617

Closed

Description

@mtelvers

3.25.0~alpha0 no longer exports OCAMLPATH to actions, breaking opam install -t for packages whose tests find themselves through findlib.

Up to 3.24, every action dune runs gets OCAMLPATH=<root>/_build/install/<context>/lib (plus the other install roots) from make_root_env in src/dune_rules/super_context.ml. In 3.25.0~alpha0 that is gone: #14373 replaced it with a per-action layout that is only set up for actions declaring (deps (package ...)). A one-rule project shows the difference:

(rule (alias runtest) (action (system "echo OCAMLPATH=${OCAMLPATH:-unset}")))
  dune 3.24.2:         OCAMLPATH=/tmp/e/_build/install/default/lib
  dune 3.25.0~alpha0:  OCAMLPATH=unset

A number of released packages rely on the old behaviour, because their tests reach for the package by name rather than through dune: ocamlfind query, #require in an mdx block, a nested dune build of a scratch project inside a cram test, or loading a stub library through CAML_LD_LIBRARY_PATH. Under 3.24 those resolve to the package being built. Under the alpha they resolve only to an installed copy, so a fresh opam install -t fails:

docker run --rm -it ocaml/opam:debian-13-ocaml-5.5
sudo ln -sf /usr/bin/opam-dev /usr/bin/opam && opam init --reinit -ni
opam install dune.3.24.2
opam install -t hxd.0.5.0        # passes
opam install -t GT.0.5.5         # passes
opam install -t bogue.20260208   # passes

Trying the same with dune.3.25.0~alpha0

docker run --rm -it ocaml/opam:debian-13-ocaml-5.5
sudo ln -sf /usr/bin/opam-dev /usr/bin/opam && opam init --reinit -ni
opam repo add dune-alpha https://github.com/ocaml/opam-repository.git#refs/pull/30850/head
opam install dune.3.25.0~alpha0
opam install -t hxd.0.5.0        # Error: Library "hxd.string" not found   (nested dune build in a cram test)
opam install -t GT.0.5.5         # No such package: GT                      (mdx #require)
opam install -t bogue.20260208   # ocamlfind: Package `bogue' not found    (ocamlfind query at test time)

Each of these passes again under the alpha if the package was installed first and then rebuilt with opam reinstall -t, because opam builds before it removes and the test finds the old install. That is why the reverse dependency run on ocaml/opam-repository#30850 reported them green: opam-repo-ci installs each dependent without tests and then reinstalls it with tests, so the package is always present while its tests run. Building with-tests in a fresh switch finds 88 failing jobs across bogue (13 versions), hxd (9), flint, GT, ostap, embedded_ocaml_templates, ocaml-index and topup, on their current releases as well as older ones.

Activity

  1. added theissue type on Oct 16, 2026
  2. added
    regressionA defect in previously working behavior, generally breaks existing user workflows
    and removed
    regressionA defect in previously working behavior, generally breaks existing user workflows
    on Oct 16, 2026
  3. self-assigned this
    on Oct 17, 2026
  4. shonfeder commented on Oct 17, 2026

    @shonfeder
    Member

    Thanks to initial triage and analysis by @Alizter, our current inclination is to
    understand this as a result of improved build hygiene, resulting from the elimination of
    dependency ambiguity as part of #14432

    We believe all these cases of build failures detected by day10 are actually misconfigurations of the build, but I'll present a catalogue here of the failure cases to confirm.

    (Thanks to a quick chat with @Alizter, today, I removed some nonsense I asked
    here due to having my wires crossed.)

  5. shonfeder commented on Oct 20, 2026

    @shonfeder
    Member

    hxd:

    Fails on running tests

    % dune test
    File "test/lib.t", line 1, characters 0-0:
    diff --git a/_build/default/test/lib.t b/_build/default/test/lib.t.corrected
    index 4667c5e..78958ab 100644
    --- a/_build/default/test/lib.t
    +++ b/_build/default/test/lib.t.corrected
    @@ -14,11 +14,21 @@ Tests with caml
       > (lang dune 2.0)
       > EOF
       $ dune build --display=short ./main.exe
    -        ocamlc .main.eobjs/byte/dune__exe__Main.{cmi,cmo,cmt}
    -      ocamlopt .main.eobjs/native/dune__exe__Main.{cmx,o}
    -      ocamlopt main.exe
    +  File "dune", line 3, characters 12-22:
    +  3 |  (libraries hxd.string))
    +                  ^^^^^^^^^^
    +  Error: Library "hxd.string" not found.
    +  -> required by _build/default/.main.eobjs/native/dune__exe__Main.cmx
    +  -> required by _build/default/main.exe
    +  [1]
       $ dune exec ./main.exe
    -  00000000: 4865 6c6c 6f20 576f 726c 6421            Hello World!
    +  File "dune", line 3, characters 12-22:
    +  3 |  (libraries hxd.string))
    +                  ^^^^^^^^^^
    +  Error: Library "hxd.string" not found.
    +  -> required by _build/default/.main.eobjs/native/dune__exe__Main.cmx
    +  -> required by _build/default/main.exe
    +  [1]
       $ cat >main.ml <<EOF
       > let default = Hxd.default
       >
    @@ -27,9 +37,18 @@ Tests with caml
       >     (Hxd_string.pp default) (String.make 32 'x')
       > EOF
       $ dune build --display=short ./main.exe
    -        ocamlc .main.eobjs/byte/dune__exe__Main.{cmi,cmo,cmt}
    -      ocamlopt .main.eobjs/native/dune__exe__Main.{cmx,o}
    -      ocamlopt main.exe
    +  File "dune", line 3, characters 12-22:
    +  3 |  (libraries hxd.string))
    +                  ^^^^^^^^^^
    +  Error: Library "hxd.string" not found.
    +  -> required by _build/default/.main.eobjs/native/dune__exe__Main.cmx
    +  -> required by _build/default/main.exe
    +  [1]
       $ dune exec ./main.exe
    -  raw: 00000000: 7878 7878 7878 7878 7878 7878 7878 7878  xxxxxxxxxxxxxxxx
    -       00000010: 7878 7878 7878 7878 7878 7878 7878 7878  xxxxxxxxxxxxxxxx
    +  File "dune", line 3, characters 12-22:
    +  3 |  (libraries hxd.string))
    +                  ^^^^^^^^^^
    +  Error: Library "hxd.string" not found.
    +  -> required by _build/default/.main.eobjs/native/dune__exe__Main.cmx
    +  -> required by _build/default/main.exe
    +  [1]

    Fixed with

    diff --git a/test/dune b/test/dune
    index a178ddc..7f82027 100644
    --- a/test/dune
    +++ b/test/dune
    @@ -1,5 +1,15 @@
     (cram
    + (applies_to * \ lib)
      (enabled_if
       (= %{ocaml-config:word_size} 64))
      ; the only way to avoid tests on x86_32/arm32 which uses the bytecode compiler
      (deps zh.txt %{bin:hxd.xxd} %{bin:hxd.caml}))
    +
    +(cram
    + ; the lib.t test requires access to the hxd package libraries, but not the executables
    + (applies_to lib)
    + (enabled_if
    +  (= %{ocaml-config:word_size} 64))
    + ; the only way to avoid tests on x86_32/arm32 which uses the bytecode compiler
    + (deps
    +  (package hxd)))

    The cram test in lib.t includes the generation of a libraries that has a library dependency on hxd.string, and this assumes that the package is installed in the context of the test.

  6. shonfeder commented on Oct 20, 2026

    @shonfeder
    Member

    GT:

    Errors
    sfubu@counteragent:~/Repos/GT$ dune build
    File "camlp5/dune", lines 122-136, characters 0-316:    
    122 | (rule
    123 |  (targets pp5+gt+o.byte)
    124 |  (deps pa_gt.cma)
    .....
    134 |    %{deps}
    135 |    -o
    136 |    %{targets})))
    ocamlfind: Package `GT.common' not found
    Maybe an error? Command exited with code 2
    File "camlp5/dune", lines 108-120, characters 0-270:    
    108 | (rule
    109 |  (targets pp5+gt+o.exe)
    110 |  (deps pa_gt.cmxa)
    .....
    118 |    %{deps}
    119 |    -o
    120 |    %{targets})))
    ocamlfind: Package `GT.common' not found
    Maybe an error? Command exited with code 2
    sfubu@counteragent:~/Repos/GT$ dune test
    File "dune", lines 6-9, characters 0-64:                
    6 | (mdx
    7 |  (files index.mld README.md)
    8 |  (package GT)
    9 |  (libraries GT))
    Got an error while evaluating:
    ---
    #require "GT";;
    ---
    No such package: GT
    File "index.mld", line 1, characters 0-0:                        
    diff --git a/_build/default/index.mld b/_build/default/.mdx/index.mld.corrected
    index 0bf157c13..cd54eff33 100644
    --- a/_build/default/index.mld
    +++ b/_build/default/.mdx/index.mld.corrected
    @@ -20,8 +20,11 @@ Findlib has been successfully loaded. Additional directives:
     
     - : unit = ()
     # #require "GT";;
    +No such package: GT
     # #require "GT.syntax.all";;
    +No such package: GT.syntax.all
     # #require "GT.ppx_all";;
    +No such package: GT.ppx_all
     ]}
     
     The `deriving` specification will generate
    @@ -32,49 +35,13 @@ The `deriving` specification will generate
     {@ocaml[
     # type 'a list = Nil | Cons of 'a * 'a list [@@deriving gt ~options:{fmt; show}];;
     type 'a list = Nil | Cons of 'a * 'a list
    -class virtual ['ia, 'a, 'sa, 'inh, 'extra, 'syn] list_t :
    -  object
    -    method virtual c_Cons : 'inh -> 'extra -> 'a -> 'a list -> 'syn
    -    method virtual c_Nil : 'inh -> 'extra -> 'syn
    -  end
    -val gcata_list :
    -  ('a, 'typ0__003_, 'b, 'c, 'typ0__003_ list, 'd) #list_t ->
    -  'c -> 'typ0__003_ list -> 'd = <fun>
    -class ['a, 'b] show_list_t :
    -  (unit -> 'a -> string) ->
    -  (unit -> 'a list -> string) ->
    -  object
    -    constraint 'b = 'a list
    -    method c_Cons : unit -> 'a list -> 'a -> 'a list -> string
    -    method c_Nil : unit -> 'a list -> string
    -  end
    -class ['a, 'b] fmt_list_t :
    -  (Format.formatter -> 'a -> unit) ->
    -  (Format.formatter -> 'a list -> unit) ->
    -  object
    -    constraint 'b = 'a list
    -    method c_Cons : Format.formatter -> 'a list -> 'a -> 'a list -> unit
    -    method c_Nil : Format.formatter -> 'a list -> unit
    -  end
    -val fmt_list :
    -  (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a list -> unit =
    -  <fun>
    -val list :
    -  (('a, 'b, 'c, 'd, 'b list, 'e) #list_t -> 'd -> 'b list -> 'e,
    -   < fmt : (Format.formatter -> 'f -> unit) ->
    -           Format.formatter -> 'f list -> unit;
    -     show : ('g -> string) -> 'g list -> string >,
    -   (('h -> 'i list -> 'j) -> ('k, 'i, 'l, 'h, 'i list, 'j) #list_t) ->
    -   'h -> 'i list -> 'j)
    -  GT.t = {GT.gcata = <fun>; plugins = <obj>; fix = <fun>}
    -val show_list : ('a -> string) -> 'a list -> string = <fun>
     ]}
     
     
     {@ocaml[
     # Format.printf "%a\n%!" (fmt_list Format.pp_print_int) (Cons(1, Nil));;
    -Cons (1, Nil)
    -- : unit = ()
    +Line 1, characters 25-33:
    +Error: Unbound value fmt_list
     ]}
     
     
    @@ -105,28 +72,6 @@ type expr =
       | Mul of expr * expr
       | Int of int
       | Var of string
    -class virtual ['inh, 'extra, 'syn] expr_t :
    -  object
    -    method virtual c_Add : 'inh -> 'extra -> expr -> expr -> 'syn
    -    method virtual c_Int : 'inh -> 'extra -> int -> 'syn
    -    method virtual c_Mul : 'inh -> 'extra -> expr -> expr -> 'syn
    -    method virtual c_Var : 'inh -> 'extra -> string -> 'syn
    -  end
    -val gcata_expr : ('a, expr, 'b) #expr_t -> 'a -> expr -> 'b = <fun>
    -class ['a] show_expr_t :
    -  (unit -> expr -> string) ->
    -  object
    -    constraint 'a = expr
    -    method c_Add : unit -> expr -> expr -> expr -> string
    -    method c_Int : unit -> expr -> int -> string
    -    method c_Mul : unit -> expr -> expr -> expr -> string
    -    method c_Var : unit -> expr -> string -> string
    -  end
    -val expr :
    -  (('a, expr, 'b) #expr_t -> 'a -> expr -> 'b, < show : expr -> string >,
    -   (('c -> expr -> 'd) -> ('c, expr, 'd) #expr_t) -> 'c -> expr -> 'd)
    -  GT.t = {GT.gcata = <fun>; plugins = <obj>; fix = <fun>}
    -val show_expr : expr -> string = <fun>
     ]}
     
     For mutually recursive type declarations add decoration only to the last type
    @@ -140,7 +85,11 @@ In our framework (at least by now) all transformations are expressed by the foll
     
     {@ocaml[
       fun tr_obj init value -> GT.transform(t) tr_obj init value
    -]}
    +][
    +{err@mdx-error[
    +Line 1, characters 41-42:
    +Error: Unbound value t
    +]err}]}
     
     or more precisely
     
    @@ -174,20 +123,16 @@ For example, if we are not satisfied by the "default" behavior of "show", we can
        inherit [_] show_expr_t fself
        method c_Var _ _ s = s
       end;;
    -class show' :
    -  (unit -> expr -> string) ->
    -  object
    -    method c_Add : unit -> expr -> expr -> expr -> string
    -    method c_Int : unit -> expr -> int -> string
    -    method c_Mul : unit -> expr -> expr -> expr -> string
    -    method c_Var : unit -> expr -> string -> string
    -  end
    +Line 2, characters 12-27:
    +Error: Unbound class show_expr_t
     ]}
     
     {@ocaml[
     # GT.transform expr (new show') ()
         (Mul (Var "a", Add (Int 1, Var "b")))
    -- : string = "Mul (a, Add (Int (1), b))"
    +Line 1, characters 14-18:
    +Error: Unbound value expr
    +Hint:   Did you mean exp?
     ]}
     
     Now the result is
    @@ -207,17 +152,14 @@ If we still not satisfied with the result, we can further proceed with fixing th
         inherit show' fself
         method c_Int _ _ i = string_of_int i
       end;;
    -class show'' :
    -  (unit -> expr -> string) ->
    -  object
    -    method c_Add : unit -> expr -> expr -> expr -> string
    -    method c_Int : unit -> expr -> int -> string
    -    method c_Mul : unit -> expr -> expr -> expr -> string
    -    method c_Var : unit -> expr -> string -> string
    -  end
    +Line 2, characters 13-18:
    +Error: Unbound class show'
    +Hint:   Did you mean show''?
     
     # GT.transform(expr) (new show'') () (Mul (Var "a", Add (Int 1, Var "b")))
    -- : string = "Mul (a, Add (1, b))"
    +Line 1, characters 14-18:
    +Error: Unbound value expr
    +Hint:   Did you mean exp?
     ]}
     
     In the next step we're going to switch to infix representation of operators;
    @@ -231,17 +173,14 @@ Fortunately, this is easy:
         method c_Add () _ x y = fself () x ^ " + " ^ fself () y
         method c_Mul () _ x y = fself () x ^ " * " ^ fself () y
       end
    -class show''' :
    -  (unit -> expr -> string) ->
    -  object
    -    method c_Add : unit -> expr -> expr -> expr -> string
    -    method c_Int : unit -> expr -> int -> string
    -    method c_Mul : unit -> expr -> expr -> expr -> string
    -    method c_Var : unit -> expr -> string -> string
    -  end
    +Line 2, characters 13-19:
    +Error: Unbound class show''
    +Hint:   Did you mean show'''?
     
     # GT.transform(expr) (new show''') () (Mul (Var "a", Add (Int 1, Var "b")))
    -- : string = "a * 1 + b"
    +Line 1, characters 14-18:
    +Error: Unbound value expr
    +Hint:   Did you mean exp?
     ]}
     
     Method "`c_Add`" takes four arguments:
    @@ -270,14 +209,9 @@ Finally, we may want to provide a complete infix representation (including a min
           method c_Mul _ _ x y = enclose "*" 2 x y
           method c_Add _ _ x y = enclose "+" 1 x y
         end;;
    -class show4 :
    -  (unit -> expr -> string) ->
    -  object
    -    method c_Add : unit -> expr -> expr -> expr -> string
    -    method c_Int : unit -> expr -> int -> string
    -    method c_Mul : unit -> expr -> expr -> expr -> string
    -    method c_Var : unit -> expr -> string -> string
    -  end
    +Line 13, characters 15-22:
    +Error: Unbound class show'''
    +Hint:   Did you mean show4?
     ]}
     
     On the final note for this example we point out that all these flavors of "show" transformation coexist simultaneously; any of them can be used as a starting point for further adjustments.
    @@ -295,39 +229,6 @@ type expr =
       | Mul of expr * expr
       | Int of int
       | Var of string
    -class virtual ['inh, 'extra, 'syn] expr_t :
    -  object
    -    method virtual c_Add : 'inh -> 'extra -> expr -> expr -> 'syn
    -    method virtual c_Int : 'inh -> 'extra -> int -> 'syn
    -    method virtual c_Mul : 'inh -> 'extra -> expr -> expr -> 'syn
    -    method virtual c_Var : 'inh -> 'extra -> string -> 'syn
    -  end
    -val gcata_expr : ('a, expr, 'b) #expr_t -> 'a -> expr -> 'b = <fun>
    -class ['syn, 'a] foldl_expr_t :
    -  ('syn -> expr -> 'syn) ->
    -  object
    -    constraint 'a = expr
    -    method c_Add : 'syn -> expr -> expr -> expr -> 'syn
    -    method c_Int : 'syn -> expr -> int -> 'syn
    -    method c_Mul : 'syn -> expr -> expr -> expr -> 'syn
    -    method c_Var : 'syn -> expr -> string -> 'syn
    -  end
    -val foldl_expr : 'a -> expr -> 'a = <fun>
    -class ['a] show_expr_t :
    -  (unit -> expr -> string) ->
    -  object
    -    constraint 'a = expr
    -    method c_Add : unit -> expr -> expr -> expr -> string
    -    method c_Int : unit -> expr -> int -> string
    -    method c_Mul : unit -> expr -> expr -> expr -> string
    -    method c_Var : unit -> expr -> string -> string
    -  end
    -val expr :
    -  (('a, expr, 'b) #expr_t -> 'a -> expr -> 'b,
    -   < foldl : 'c -> expr -> 'c; show : expr -> string >,
    -   (('d -> expr -> 'e) -> ('d, expr, 'e) #expr_t) -> 'd -> expr -> 'e)
    -  GT.t = {GT.gcata = <fun>; plugins = <obj>; fix = <fun>}
    -val show_expr : expr -> string = <fun>
     ]}
     
     With this plugin enabled we can easily express what we want:
    @@ -341,17 +242,13 @@ With this plugin enabled we can easily express what we want:
         inherit [S.t,_] foldl_expr_t fself
         method c_Var s _ x = S.add x s
       end
    -class vars :
    -  (S.t -> expr -> S.t) ->
    -  object
    -    method c_Add : S.t -> expr -> expr -> expr -> S.t
    -    method c_Int : S.t -> expr -> int -> S.t
    -    method c_Mul : S.t -> expr -> expr -> expr -> S.t
    -    method c_Var : S.t -> expr -> string -> S.t
    -  end
    +Line 2, characters 13-33:
    +Error: Unbound class foldl_expr_t
     
     # let vars e = S.elements (GT.transform(expr) (new vars) S.empty e)
    -val vars : expr -> string list/2 = <fun>
    +Line 1, characters 39-43:
    +Error: Unbound value expr
    +Hint:   Did you mean exp?
     ]}
     
     In the default version, [ foldl_expr_t ] is generated in such a way that inherited attribute value (in out case of type [S.t]) is simply threaded through all nodes of the data structure. This behavior as such gives us nothing; however we can redefine the "interesting case" (variable occurrence) to take this occurrence into account.
    @@ -366,14 +263,8 @@ The next example - expression evaluator - demonstrates the case when we implemen
         method c_Add s _ x y = fself s x + fself s y
         method c_Mul s _ x y = fself s x * fself s y
       end;;
    -class eval :
    -  ((string -> int) -> expr -> int) ->
    -  object
    -    method c_Add : (string -> int) -> int -> expr -> expr -> int
    -    method c_Int : (string -> int) -> int -> int -> int
    -    method c_Mul : (string -> int) -> int -> expr -> expr -> int
    -    method c_Var : (string -> int) -> int -> string -> int
    -  end
    +Line 2, characters 13-43:
    +Error: Unbound class expr_t
     ]}
     
     Since we develop a new transformation, we have to take care of types for inherited and synthesized attributes (when we're extending the existing classes these types are already taken care of). Since our evaluator needs a state to bind variables, the type of inherited attribute is "`string -> int`" and the type of synthesized attribute is just "`int`". The implementations of methods are straightforward.
    @@ -391,50 +282,6 @@ type expr =
       | Mul of expr * expr
       | Int of int
       | Var of string
    -class virtual ['inh, 'extra, 'syn] expr_t :
    -  object
    -    method virtual c_Add : 'inh -> 'extra -> expr -> expr -> 'syn
    -    method virtual c_Int : 'inh -> 'extra -> int -> 'syn
    -    method virtual c_Mul : 'inh -> 'extra -> expr -> expr -> 'syn
    -    method virtual c_Var : 'inh -> 'extra -> string -> 'syn
    -  end
    -val gcata_expr : ('a, expr, 'b) #expr_t -> 'a -> expr -> 'b = <fun>
    -class ['a, 'b] gmap_expr_t :
    -  (unit -> expr -> expr) ->
    -  object
    -    constraint 'a = expr
    -    constraint 'b = expr
    -    method c_Add : unit -> expr -> expr -> expr -> expr
    -    method c_Int : unit -> expr -> int -> expr
    -    method c_Mul : unit -> expr -> expr -> expr -> expr
    -    method c_Var : unit -> expr -> string -> expr
    -  end
    -class ['syn, 'a] foldl_expr_t :
    -  ('syn -> expr -> 'syn) ->
    -  object
    -    constraint 'a = expr
    -    method c_Add : 'syn -> expr -> expr -> expr -> 'syn
    -    method c_Int : 'syn -> expr -> int -> 'syn
    -    method c_Mul : 'syn -> expr -> expr -> expr -> 'syn
    -    method c_Var : 'syn -> expr -> string -> 'syn
    -  end
    -val foldl_expr : 'a -> expr -> 'a = <fun>
    -class ['a] show_expr_t :
    -  (unit -> expr -> string) ->
    -  object
    -    constraint 'a = expr
    -    method c_Add : unit -> expr -> expr -> expr -> string
    -    method c_Int : unit -> expr -> int -> string
    -    method c_Mul : unit -> expr -> expr -> expr -> string
    -    method c_Var : unit -> expr -> string -> string
    -  end
    -val expr :
    -  (('a, expr, 'b) #expr_t -> 'a -> expr -> 'b,
    -   < foldl : 'c -> expr -> 'c; gmap : expr -> expr; show : expr -> string >,
    -   (('d -> expr -> 'e) -> ('d, expr, 'e) #expr_t) -> 'd -> expr -> 'e)
    -  GT.t = {GT.gcata = <fun>; plugins = <obj>; fix = <fun>}
    -val gmap_expr : expr -> expr = <fun>
    -val show_expr : expr -> string = <fun>
     ]}
     
     In the first iteration we simplify additions by performing constant calculations; we also "normalize" additions in such a way, that if it has one constant operand, then this operand occupies "left" position. The normalization makes it possible to take into account the associativity of addition:
    @@ -454,14 +301,8 @@ In the first iteration we simplify additions by performing constant calculations
           inherit [_,_] gmap_expr_t fself
           method c_Add _ _ x y = fself () x + fself () y
         end
    -class simplify_add :
    -  (unit -> expr -> expr) ->
    -  object
    -    method c_Add : unit -> expr -> expr -> expr -> expr
    -    method c_Int : unit -> expr -> int -> expr
    -    method c_Mul : unit -> expr -> expr -> expr -> expr
    -    method c_Var : unit -> expr -> string -> expr
    -  end
    +Line 12, characters 15-32:
    +Error: Unbound class gmap_expr_t
     ]}
     
     As we can see, we again concentrated only on the "interesting case"; the implementation of infix "`+`" may look cumbersome, but this is an essential part of the transformation.
    @@ -483,7 +324,12 @@ Equally, we can handle the simplification of multiplication:
          inherit simplify_add fself
          method c_Mul _ _ x y = fself () x * fself () y
        end
    -]}
    +][
    +{err@mdx-error[
    +Line 12, characters 16-28:
    +Error: Unbound class simplify_add
    +Hint:   Did you mean simplify_mul?
    +]err}]}
     
     The class "`simplify_mul`" implements a decent simplifier; however, it overlooks the following equalities: "0*x=0", "0+x=x", and "1*x=x". These cases can be easily integrated into existing implementation:
     
    @@ -500,14 +346,9 @@ The class "`simplify_mul`" implements a decent simplifier; however, it overlooks
            | Mul (Int 0, _) -> Int 0
            | x -> x
       end;;
    -class simplify_all :
    -  (unit -> expr -> expr) ->
    -  object
    -    method c_Add : unit -> expr -> expr -> expr -> expr
    -    method c_Int : unit -> expr -> int -> expr
    -    method c_Mul : unit -> expr -> expr -> expr -> expr
    -    method c_Var : unit -> expr -> string -> expr
    -  end
    +Line 2, characters 13-25:
    +Error: Unbound class simplify_mul
    +Hint:   Did you mean simplify_all?
     ]}
     
     The interesting part of this implementation is an explicit utilization of a superclass' methods.

    Fix

    diff --git a/camlp5/dune b/camlp5/dune
    index 85d7ab2b73c..f0d10645121 100644
    --- a/camlp5/dune
    +++ b/camlp5/dune
    @@ -107,7 +107,9 @@
    
     (rule
      (targets pp5+gt+o.exe)
    - (deps pa_gt.cmxa)
    + (deps
    +  pa_gt.cmxa
    +  (package GT))
      (action
       (run
        mkcamlp5.opt
    @@ -121,7 +123,9 @@
    
     (rule
      (targets pp5+gt+o.byte)
    - (deps pa_gt.cma)
    + (deps
    ↳[0]
    
    [11:19:15 ~/Scratch/GT]
    $ git diff main |cat
    diff --git a/camlp5/dune b/camlp5/dune
    index 85d7ab2b73c..f0d10645121 100644
    --- a/camlp5/dune
    +++ b/camlp5/dune
    @@ -107,7 +107,9 @@
    
     (rule
      (targets pp5+gt+o.exe)
    - (deps pa_gt.cmxa)
    + (deps
    +  pa_gt.cmxa
    +  (package GT))
      (action
       (run
        mkcamlp5.opt
    @@ -121,7 +123,9 @@
    
     (rule
      (targets pp5+gt+o.byte)
    - (deps pa_gt.cma)
    + (deps
    +  pa_gt.cma
    +  (package GT))
      (action
       (run
        mkcamlp5
    diff --git a/dune b/dune
    index eb4e0d45a3a..629740c7dc7 100644
    --- a/dune
    +++ b/dune
    @@ -6,4 +6,6 @@
     (mdx
      (files index.mld README.md)
      (package GT)
    - (libraries GT))
    + (libraries GT)
    + (deps
    +  (package GT)))
  7. shonfeder commented on Oct 20, 2026

    @shonfeder
    Member

    bogue

    The claude-reported error is a bit misleading here. Running a local build, we get the following (with output trimmed to what is strictly relevant):

    File "examples/dune", lines 10-25, characters 0-232:  
    10 | (rule
    11 |  (alias runtest)
    12 |  (deps
    ....
    23 |      DIR
    24 |      share
    25 |      (run ./examples.exe 00))))))
    Command [1] exited with code 2:
    $ (cd _build/default/examples && ./examples.exe 00)
    ...
    [11][0] :	 Warning: User variable 'DIR' not found in config.
    [11][0] :	 Warning: Using DIR=
    [11][0] :	 Warning: Using [<masked:HOME>/.config/bogue/themes] as bogue themes directory
    [11][0] :	 Warning: User variable 'THEME' not found in config.
    [11][0] :	 Warning: Using THEME=default
    [11][0] :	 I/O: No theme specified, using default=default.
    [11][0] :	 I/O: Reading config file [<masked:HOME>/.config/bogue/themes/default/bogue.conf]. BOGUE Version [MinimalConfig]
    ...
    Loading Bogue 20260208 with config dir <masked:HOME>/.config/bogue/themes/default
    ...
    [21][0] :	 Memory: Create surface_load (/home/sf/.config/bogue/assets/images/chl.png)
    INFO: Using SDL 2.32.72
    Fatal error: exception Bogue__B_utils.Sdl_error("SDL ERROR: Couldn't open /home/sf/.config/bogue/assets/images/chl.png: No such file or directory")

    When running the opam install command in a docker container, as reported, it is true that the line ocamlfind: Package bogue' not found` occurs, but this is downstream of the relevant fatal error:

    #=== ERROR while compiling bogue.20260208 =====================================#
    # context     2.6.1 | linux/x86_64 | ocaml-base-compiler.5.5.1 | git+https://github.com/ocaml/opam-repository.git#refs/pull/30850/head
    # path        ~/.opam/5.5/.opam-switch/build/bogue.20260208
    # command     ~/.opam/5.5/bin/dune build -p bogue -j 27 @install @runtest
    # exit-code   1
    # env-file    ~/.opam/log/bogue-4136-fc61ea.env
    # output-file ~/.opam/log/bogue-4136-fc61ea.out
    ### output ###
    # File "examples/dune", lines 10-20, characters 0-178:
    # 10 | (rule
    # 11 |  (alias runtest)
    # 12 |  (deps (source_tree "../share/themes/"))
    # 13 |  (action
    # 14 |   (setenv
    # 15 |    SDL_VIDEODRIVER
    # 16 |    dummy
    # 17 |    (setenv
    # 18 |     BOGUE_DEBUG
    # 19 |     true
    # 20 |     (run ./examples.exe 00)))))
    # (cd _build/default/examples && ./examples.exe 00)
    # [0][0] :	 Warning: User variable 'DEBUG_CODE' not found in config.
    # [0][0] :	 Warning: Using DEBUG_CODE=1023
    # [0][0] :	 Warning: User variable 'LOG_TO_FILE' not found in config.
    # [0][0] :	 Warning: Using LOG_TO_FILE=false
    # [0][0] :	 I/O: Executable=examples.exe
    # [0][0] :	 I/O: Invoking opam
    # [12][0] :	 ERROR: Cannot find share directory for examples.exe/.! bin_dir=/home/opam/.opam/5.5/.opam-switch/build/bogue.20260208/_build/default/examples, prefix_dir=/home/opam/.opam/5.5/.opam-switch/build/bogue.20260208/_build/default
    # [12][0] :	 Warning: User variable 'DIR' not found in config.
    # [12][0] :	 Warning: Using DIR=
    # [14][0] :	 ERROR: (FATAL) Bogue configuration directory [] does not exist, and system-wide config cannot be found.
    # Cannot find bogue lib directory
    # Trying to download a minimal Bogue config...
    # ocamlfind: Package `bogue' not found

    Which is also due to the invalid DIR configuration.

    "A diff shows the one-rule fix":

    diff --git a/bogue.opam b/bogue.opam
    index c5c0c4ca0ff..0fe2b8ad902 100644
    --- a/bogue.opam
    +++ b/bogue.opam
    @@ -50,3 +50,4 @@ build: [
       ]
     ]
     dev-repo: "git+https://github.com/sanette/bogue.git"
    +available: [ (os-distribution != "opensuse-leap" | os-version >= 16) ]
    diff --git a/examples/dune b/examples/dune
    index 6f7d9424c63..065bbbe8b97 100644
    --- a/examples/dune
    +++ b/examples/dune
    @@ -9,7 +9,8 @@
     
     (rule
      (alias runtest)
    - (deps (source_tree "../share/themes/"))
    + (deps
    +  (source_tree "../share/"))
      (action
       (setenv
        SDL_VIDEODRIVER
    @@ -17,4 +18,7 @@
        (setenv
         BOGUE_DEBUG
         true
    -    (run ./examples.exe 00)))))
    +    (setenv
    +     BOGUE_DIR
    +     "../share/themes"
    +     (run ./examples.exe 00))))))
  8. shonfeder commented on Oct 20, 2026

    @shonfeder
    Member

    The following packages will need upper bounds added on test running in the opam repo:

  9. shonfeder commented on Oct 20, 2026

    @shonfeder
    Member

    Submitted all upstream fixes and added needed bounds on the opam repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions