From 2197e3219af15e57936005ea94c012b8b3f4d151 Mon Sep 17 00:00:00 2001 From: Vincent Balat Date: Fri, 29 May 2026 15:24:45 +0200 Subject: [PATCH 1/2] demo_ref: pass a Deriving_Json codec to the persistent eref Eliom 13 requires every Reference.eref ~persistent to carry a Deriving_Json codec. Use [%json: Os.Date.local_calendar option], which resolves to the codec exposed by Os.Date. --- demo_ref.eliom | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/demo_ref.eliom b/demo_ref.eliom index c7eb5b1..78b559f 100644 --- a/demo_ref.eliom +++ b/demo_ref.eliom @@ -10,7 +10,8 @@ open%shared Eliom.Content.Html.F Ocsigen Start is creating a session group for each user. *) let%server last_visit = - Eliom.Reference.eref ~persistent:"demo_last_visit" + Eliom.Reference.eref + ~persistent:("demo_last_visit", [%json: Os.Date.local_calendar option]) ~scope:Eliom.Common.default_group_scope None (* Read & reset last_visit *) From 48a1295a5b1d96b92db1c94c85977d94cb1c6554 Mon Sep 17 00:00:00 2001 From: Vincent Balat Date: Fri, 17 Jul 2026 16:24:32 +0200 Subject: [PATCH 2/2] Skip generated files in the client-module generator The generator reads the build directory (".."), which mirrors the sources but also contains generated files: the .pp.eliom/.pp.eliomi preprocessing artifacts and the .eliom modules produced from assets/*.tsv (i18n) and *.eliom.in (static config). Enumerating those emitted a client rule twice for the same target, so `make all` failed with "Multiple rules generated for ...". Filter them out and keep only real sources. Completes the sandbox fix: the previous commit corrected the paths but exposed these duplicates once the generator started reading the build tree. --- tools/gen_dune.ml | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tools/gen_dune.ml b/tools/gen_dune.ml index 9a2d8f1..c1fb399 100644 --- a/tools/gen_dune.ml +++ b/tools/gen_dune.ml @@ -23,7 +23,33 @@ let handle_file_client nm = nm nm let () = - Array.concat (List.map Sys.readdir [".."; "../assets"]) + let root = Sys.readdir ".." in + let assets = Sys.readdir "../assets" in + (* The build directory mirrors the sources but also holds generated files, + which must not be enumerated or their client rule would be emitted twice: + - .pp.eliom/.pp.eliomi: preprocessing artifacts; + - the i18n modules produced from assets/*.tsv (the .tsv already emits the + rule) and the static config produced from *.eliom.in. *) + let generated_eliom = Hashtbl.create 16 in + Array.iter + (fun nm -> + if Filename.check_suffix nm ".tsv" + then Hashtbl.replace generated_eliom (Filename.chop_suffix nm ".tsv") ()) + assets; + Array.iter + (fun nm -> + if Filename.check_suffix nm ".eliom.in" + then + Hashtbl.replace generated_eliom (Filename.chop_suffix nm ".eliom.in") ()) + root; + let is_generated nm = + Filename.check_suffix nm ".pp.eliom" + || Filename.check_suffix nm ".pp.eliomi" + || (Filename.check_suffix nm ".eliom" + && Hashtbl.mem generated_eliom (Filename.chop_suffix nm ".eliom")) + in + Array.concat [root; assets] |> Array.to_list |> List.sort compare |> List.filter (fun nm -> nm.[0] <> '.') + |> List.filter (fun nm -> not (is_generated nm)) |> List.iter handle_file_client