OCaml - Latest topics https://discuss.ocaml.org/latest Latest topics Thu, 23 Apr 2026 12:05:13 +0000 [ANN] UnifiedScript_{Std,Top} - literate testing Ecosystem I am pleased to introduce the UnifiedScript_Std and UnifiedScript_Top packages. Unified scripts are a way to write tests and documentation simultaneously. Cram tests and MDX scripts are both similar to unified scripts, but unified scripts aren’t tied to Markdown (MDX) or tied to POSIX shell commands (cram tests).

Examples:

  • .ml example: The following is a snippet from a regular OCaml .ml module where the (* ... *) comments are OCaml REPL toplevel responses maintained by the unified tools.

    let lyrics =
      "Everybody step to the left."
      (* val lyrics : string = "Everybody step to the left." *)[@ocamlformat "disable"]
    
    let (_ : string) =
      Printf.sprintf "Now let's sing: %s" lyrics
      (* - : string = "Now let's sing: Everybody step to the left." *)[@ocamlformat "disable"]
    

Docs are at dk/docs/UNIFIED_SCRIPTS.md (of course generated by the unified tools).

Install the tools with:

opam pin add UnifiedScript_Std https://gitlab.com/dkml/build-tools/MlFront/-/releases/permalink/latest/downloads/MlFront.tar.gz
opam pin add UnifiedScript_Top https://gitlab.com/dkml/build-tools/MlFront/-/releases/permalink/latest/downloads/MlFront.tar.gz

After feedback I’ll release them officially to opam. I would like feedback overall and also specifically on the agent skill that converts expect tests to unified tests.

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/ann-unifiedscript-std-top-literate-testing/18013 Thu, 23 Apr 2026 12:05:13 +0000 No No No discuss.ocaml.org-topic-18013 [ANN] UnifiedScript_{Std,Top} - literate testing
Issue compiling Cuite (producing a .so file from C++ stubs) Ecosystem I am trying to build cuite on Windows/MSYS2/minwg64 with OCaml 4.14.2.. I have managed to fix many issues. But the latest one is more tricky.

A have a bunch of compiled C++ file (*.o) that use some OCaml FFI functions (__imp_caml_alloc_tuple and others). The Makefile try to package all of them in a shared object (libcuite.so).

Some OCaml functions (__imp_caml_alloc_tuple, __imp_caml_modify, __imp_caml_invalid_argument) are missing and I don’t find a library (.a file) that provides them. (Even libasmrun.a suggested by an AI).

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/issue-compiling-cuite-producing-a-so-file-from-c-stubs/18012 Thu, 23 Apr 2026 11:19:08 +0000 No No No discuss.ocaml.org-topic-18012 Issue compiling Cuite (producing a .so file from C++ stubs)
[ANN] valkey: modern Valkey client for OCaml 5 + Eio, on opam Community Hi everyone,

I wanted to share that valkey 0.2.0 is now on opam:

The main thing I wanted with this project was to focus on the current Valkey stack with the newer OCaml stack.

So valkey is built around:

  • OCaml 5
  • Eio-native direct-style concurrency
  • RESP3 only
  • Modern Valkey features and real cluster behavior

A few parts I’m happy with:

  • Cluster support with a strong focus on durability and high availability:
    topology refresh, periodic background refresh, MOVED / ASK / CLUSTERDOWN handling, replica-aware reads, AZ-aware routing, and failover-aware sharded pub/sub replay

  • connection/runtime behavior:
    circuit breaker, reconnect handling, keepalive, TLS, and optional separation between socket I/O and parsing via Eio.Domain_manager, so one side of the system does not block the other

  • batch support:
    scatter-gather across slots, atomic single-slot flows with WATCH / MULTI / EXEC, multi-slot helpers, and in
    0.2.0 also WATCH guards for read-modify-write CAS plus cross-slot pfcount_cluster

  • command surface:
    typed helpers across a pretty broad set of commands, Client.custom /custom_multi for custom commands and multi-node execution, and named commands so you can register command templates once and reuse them later

  • scripting:
    local script caching and optimistic EVALSHA handling with automatic fallback/retry on NOSCRIPT, so callers don’t need to manage that flow themselves

There is also already a pretty good amount of validation around it:
integration tests, property tests, fuzzing, chaos testing, examples, and guides.

Performance-wise, it also came out pretty nicely: in several scenarios it gets to 90%+ of the C reference client.

opam update
opam install valkey eio_main

Current next steps on the roadmap are things like:

  • client-side caching
  • connection pools / blocking pools
  • IAM + mTLS
  • Valkey module support (JSON, search, bloom)

If there’s a feature people care about, I’d be very happy to reprioritize the roadmap around real interest.

I’d also really love feedback from the OCaml community on the API, ergonomics, docs, and general design.

I’m very familiar with the Valkey world, but OCaml is more of a side fun for me than my daily language, so feedback from people who really live in the OCaml ecosystem is especially valuable to me.

If you try it, I’d love to hear what you think.

5 posts - 3 participants

Read full topic

]]>
https://discuss.ocaml.org/t/ann-valkey-modern-valkey-client-for-ocaml-5-eio-on-opam/18010 Thu, 23 Apr 2026 01:01:31 +0000 No No No discuss.ocaml.org-topic-18010 [ANN] valkey: modern Valkey client for OCaml 5 + Eio, on opam
[ANN] ocaml-wire: a Binary wire format DSL with EverParse 3D output Community I’m happy to announce the release of ocaml-wire 0.9.0 to opam!

ocaml-wire is a set of combinators to describe binary protocols in OCaml. “Binary” as in fixed-layout: sizes and shapes are mostly known up front, so you’re reading fields at known offsets rather than parsing a free-form grammar (like in Menhir). There are already many good binary parser frameworks in OCaml – here’s what’s different in ocaml-wire:

  • The central data structure is EverParse’s 3D grammar. The OCaml combinators describe a 3D structure. Following Daniel’s tagged final encoding approach, you build a codec that describes a struct and how to serialise/deserialise it from an OCaml value.
  • Which means every description can compile down to a .3d file and from there to C via EverParse – and the generated C compiles cleanly with -std=c99 -Wall -Werror. So you could, in theory (I haven’t pushed on this too far for now), build and link a complex stack as an standalone, external C parser whose memory safety, single-pass behaviour, and conformance to the 3D spec are proven in F*(EverParse doesn’t give you serialisers, unfortunately).
  • If you prefer, you can still use the OCaml parsers/verifiers, which have been made reasonably fast (i.e. no extra allocations on the hot path), and as they are streaming codecs you can just read or write a single field of the structure without parsing the whole thing. They also compile trivially to JavaScript via js_of_ocaml, if you need to parse the same format in the browser.

A small example – a packet with two nibble-wide fields, a big-endian length, and a variable-size payload whose length is read from the Length field:

open Wire

type packet = { version : int; flags : int; length : int; payload : string }

let f_version = Field.v "Version" (bits ~width:4 U8)
let f_flags   = Field.v "Flags"   (bits ~width:4 U8)
let f_length  = Field.v "Length"  uint16be
let f_payload = Field.v "Payload" (byte_array ~size:(Field.ref f_length))

let codec =
  let open Codec in
  v "Packet" (fun version flags length payload -> { version; flags; length; payload })
    [ f_version $ (fun p -> p.version);
      f_flags   $ (fun p -> p.flags);
      f_length  $ (fun p -> p.length);
      f_payload $ (fun p -> p.payload) ]

Field.ref f_length is the dependent-size bit: the payload’s length comes from the f_length field read earlier in the same struct. That same codec value is what you hand to Everparse.schema to get the 3D file out, and what backs Codec.get / Codec.set for streaming field access from OCaml. ocaml-wire also ships the infrastructure for generating FFI stubs and for differential testing to make sure the verified C and hand-written OCaml parsers agree. So far they seem to :slight_smile:

You can read more about it here: Thomas Gazagnaire :: Describing Binary Formats in OCaml.

To try it: opam install wire

Feedback very welcome on the issue tracker (or bellow)!

3 posts - 2 participants

Read full topic

]]>
https://discuss.ocaml.org/t/ann-ocaml-wire-a-binary-wire-format-dsl-with-everparse-3d-output/18009 Wed, 22 Apr 2026 21:13:57 +0000 No No No discuss.ocaml.org-topic-18009 [ANN] ocaml-wire: a Binary wire format DSL with EverParse 3D output
Closing Old Bugs With Tests: A Dune Contribution Story Community I recently started contributing to Dune with no prior familiarity with the code base. One thing I found rewarding was closing old issues — some filed as far back as 2018 — and I wanted to share the approach I used.

The Method: Close With a Test

Many open issues describe behaviour that has already been fixed, or behaviour that is working correctly but was never verified with a test. My approach: write a cram test that demonstrates the expected behaviour, link the PR to the issue with fixes #NNNN, and let the merge close the issue automatically.

This has several advantages over simply closing an issue with a comment like “this works now”:

  • It’s verifiable. Anyone can read the test and see exactly what behaviour is being asserted. There’s no argument about whether the issue is truly resolved.
  • It prevents regressions. If the behaviour breaks again in the future, the test fails. The issue doesn’t silently reopen — the CI catches it.
  • It grows the test suite. Every closed issue leaves behind a test that documents a real-world scenario someone cared about.
  • It respects the reporter. Someone took the time to file the issue. A test that captures their concern is a better acknowledgement than a drive-by close.

After a few weeks of contributing test PRs and bug fixes, I was given triager and then maintainer status on the project. This let me close issues directly when they were clearly resolved, and merge my own test PRs. Before that, the existing maintainers merged them on my behalf.

Honestly, I regret closing issues where I could have used this method but didn’t. The method is much superior to simply adding to a GitHub discussion about the bug and then closing the issue.

Issues I Helped Close

Here’s an accounting of what I helped close, grouped by what it took:

Confirmed resolved; closed directly

These issues described problems that no longer existed on main. In some cases I confirmed this myself, in others someone else had already verified it. As a triager/maintainer I was able to close them:

  • #1974@all target doesn’t interact well with (include_subdirs ...) (filed 2019)
  • #3173 — Can’t promote into a directory starting with underscore (filed 2020)
  • #3805 — No such file or directory when DUNE_BUILD_DIR is set during test (filed 2020)
  • #8242 — Very slow emacs compilation buffer updates (filed 2023)
  • #10360executables_implicit_empty_intf expects dune >= 2.9 but was only added in 3.0 (filed 2024)

Closed with a test PR

These issues were resolved by writing a test that demonstrates the correct behaviour. No code changes were needed — the test itself closed the issue:

  • #2370.h files copied to _build without foreign stubs (filed 2019, test: #14172)
  • #3362 — Cannot use %{lib:...} in the flags stanza (filed 2020, test: #14146)
  • #3484 — Promoting over a running binary (filed 2020, test: #14173)
  • #11110 — Libexec site install doesn’t set executable bit (filed 2024, test: #14171)

Closed with a test and a code fix

These required both a test and a code change to resolve:

  • #878dune subst adds duplicate version field in opam (filed 2018, fix: #14136)
  • #2445 — dune sends SIGKILL without prior SIGTERM (filed 2019, fixes: #14170, #14224)
  • #3916 — Duplicate bounds in autogenerated opam files (filed 2020, fix: #14175)
  • #6148root_module generates duplicate module definition (filed 2022, fix: #14135)
  • #9757dune runtest doesn’t execute byte-only inline tests (filed 2024, fix: #14174)
  • #10707 — Missing menhir lower bound in generated opam files (filed 2024, fix: #14168)
  • #11002 — opam file generation error-prone (filed 2024, fix: #14136)
  • #11106 — Redundant dune version constraint in opam files (filed 2024, fix: #14175)
  • #12007dune build @ocaml-index builds too many files (filed 2025, partially fixed with #14137)
  • #14089 — Incremental builds with (wrapped (transition ...)) broken (filed 2026, test: #14088, fix: #14090)

What I Learned

Writing tests is a good way to learn about a code base. Each test forced me to understand how a feature actually works — not the architecture in the abstract, but the concrete behaviour in specific scenarios. The understanding compounded.

Dune’s cram tests make this easy. Each test is a self-contained shell script with expected output, checked into the repo as a .t file. The barrier to writing a test is low, which is exactly what you want when your goal is to close issues by testing them. This occasionally backfired by being “too easy” - when I wrote tests to which maintainers objected because I had not done so in a Dune-idiomatic way; but this was still net positive for sure.

Consistent presence matters. I contributed nearly every day over several weeks. I think that this helped maintainers feel that I was “present” - that efforts that they made to help me were investments; so they were less prone to holding back reviews.

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/closing-old-bugs-with-tests-a-dune-contribution-story/18008 Tue, 21 Apr 2026 22:01:29 +0000 No No No discuss.ocaml.org-topic-18008 Closing Old Bugs With Tests: A Dune Contribution Story
First beta release of OCaml 5.5.0 Ecosystem With most developer tools available and the good stability of the compiler, I am happy to announce the first beta release of OCaml 5.5.0.

Compared to the last alpha, this new version improves the manpage for
ocamlopt and fixes:

  • two runtime bugs (for ephemerons and the bytecode interpreter)
  • two type system bugs (for classes and module-dependent functions)
  • three warning or error message bugs

(See the Changelog below for a full list).

Concerning the associated compiler tools, most of them are already
available (as least in a preview version), and there are patches in
progress for the remaining ones. You can track the last remaining
update efforts on the release readiness meta-issue.

Thus, it should be safe to test your libraries and programs with the
new version OCaml 5.5.0 version in preparation of the final release.
If everything goes well, we might see a release in May.

If you find any bugs, please report them to the GitHub issue tracker.

If you are interested by the full list of new features and bug fixes, the
changelog for OCaml 5.5.0 is the most up-to-date resource.

Happy hacking,
Florian Angeletti for the OCaml team.


Installation Instructions

The base compiler can be installed as an opam switch with the following commands
on opam 2.1 and later:

opam update
opam switch create 5.5.0~beta1

The source code for the beta is also available at these addresses:

Fine-Tuned Compiler Configuration

If you want to tweak the configuration of the compiler, you can switch to the option variant with:

opam update
opam switch create <switch_name> ocaml-variants.5.5.0~beta1+options <option_list>

where option_list is a space separated list of ocaml-option-* packages. For instance, for a flambda and no-flat-float-array switch:

opam switch create 5.5.0~beta1+flambda+nffa ocaml-variants.5.5.0~beta1+options ocaml-option-flambda ocaml-option-no-flat-float-array

All available options can be listed with opam search ocaml-option.


Changes compared to the last alpha

Documentation update

  • #14684: Improve ocamlopt’s manual page
    (Samuel Hym, review by Florian Angeletti)

Runtime fixes

  • #14644, #14647: Fix a bug related to unhandled effects in bytecode.
    (Vincent Laviron, report by Thibaut Mattio,
    review by Nicolás Ojeda Bär, Stephen Dolan and Olivier Nicole)

  • #14349, #14718: runtime, fix in the orphaning of ephemerons
    (Gabriel Scherer, review by Olivier Nicole and Damien Doligez,
    report by Jan Midtgaard)

Type system fixes

  • #14557, #12150, #14696: ensure that the self type of class cannot escape
    through type constraints.
    (Leo White, review by Florian Angeletti)

  • #14667: enable application related warnings for module-dependent functions
    (Florian Angeletti, review by Gabriel Scherer)

Error messages and warning fixes

  • #14690: Fix Name_type_mismatch error message when the expected type is an
    alias: print the expanded path on the right-hand side of the equality, not
    the alias twice.
    (Weixie Cui, review by Florian Angeletti)

  • #14719, #14721: compute arity correctly for module-dependent function
    (Florian Angeletti, report by Jeremy Yallop, review by Stefan Muenzel)

  • #14655, #14691: check for size overflow in caml_ba_reshape
    (Stephen Dolan, review by Xavier Leroy)

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/first-beta-release-of-ocaml-5-5-0/18006 Mon, 20 Apr 2026 14:47:10 +0000 No No No discuss.ocaml.org-topic-18006 First beta release of OCaml 5.5.0
Experience Report: Refining Dune’s Dependency Graph Community Refining Dune’s Dependency Graph: Per-Module Library Filtering

I’ve been working on improving Dune’s inter-library dependency tracking, and wanted to share the experience — both the technical details and what it’s like as a first-time contributor to this large open source OCaml project.

The Problem I Took On

When libA depends on libB, Dune gives every module in libA a glob dependency on all .cmi files in libB. If any .cmi in libB changes, every module in libA is recompiled — even modules that never reference libB.

For projects with many libraries, this creates a cascade of unnecessary recompilations. The issue that tracks this matter #4572 has been open since 2021.

My Approach

Dune already runs ocamldep to compute intra-library module dependencies. The key insight: that same output tells us which libraries each module references, via their entry module names. We can use this to filter both the build dependencies and the -I/-H compiler flags per-module.

The implementation (PR #14116 and PR #14186) works as follows:

  1. For each module and its transitive intra-library dependencies, read the ocamldep output (both .ml and .mli)
  2. Union all referenced module names, including -open flags
  3. Map those names to libraries via a Lib_index
  4. Transitively close the filtered library set via Lib.closure
  5. Use the result for both hidden deps and -I/-H compiler flags, partitioning into direct (visible via -I) and hidden (via -H) based on requires_compile membership

With both deps and flags filtered, a clean build will fail if a module references a library it doesn’t declare — previously, overly-broad -I flags could mask such errors.

A False Start

My first attempt (PR #14021) tried to implement the filtering in a single PR without sufficient test coverage. It was closed after review revealed that the approach was fragile in edge cases I hadn’t anticipated — particularly around transparent module aliases and virtual libraries.

Challenges

Transparent module aliases. OCaml’s module alias mechanism means ocamldep doesn’t always report all libraries a module transitively depends on. If libB has module M = LibC.Something, and a module in libA uses LibB.M, ocamldep reports LibB but not LibC. The fix: transitively close the filtered library set using Lib.closure, bounded by the compilation context.

Root modules. The (root_module) stanza creates a module that implicitly aliases all libraries in the compilation context. When ocamldep reports a reference to a root module, we can’t determine which underlying libraries are actually needed, so we fall back to the full dependency set.

Virtual libraries. When virtual library implementations are present in the compilation context, parameter libraries may not appear in requires_compile, so filtering could miss them. Another fallback case.

Menhir-generated modules. These mock modules aren’t in the ocamldep dependency graph, so we skip filtering for them.

Null build overhead. The filtering reads .d files and computes library closures per-module. On a fresh dune process (no memo cache), this is new work on every build — including null builds where nothing changed. This is a real trade-off: better incremental rebuild performance at the cost of some null-build overhead.

Prerequisite Test PRs

Before the implementation PRs, I submitted six test-only PRs to document existing behavior and establish a safety net:

  • #14017 — Baseline tests documenting current inter-library recompilation behavior
  • #14031 — Test documenting module name shadowing between stanzas and libraries
  • #14100 — Test verifying library file deps in compilation rules and sandboxed builds
  • #14101 — Test verifying transparent alias incremental build safety
  • #14129 — Test verifying incremental builds with alias re-exported libraries
  • #14178 — Test documenting ocamldep behavior with transparent alias chains

This made the implementation PRs’ diffs focused on the actual change, and gave reviewers confidence that existing behavior was preserved. It also helped me understand the edge cases that tripped up my first attempt.

The Review Process

The Dune maintainers (@rgrinberg and @art-w) provided thorough, constructive reviews. Some highlights:

  • Replacing my hand-rolled transitive closure with Lib.closure from the existing library — a cleaner approach I wouldn’t have found without familiarity with Dune’s internals
  • Identifying that both .ml and .mli ocamldep output need to be read, since the interface can reference different libraries than the implementation
  • Suggesting per-module -I/-H flag filtering, which makes clean builds more precise and improves caching
  • Questioning every fallback case and special-cased module kind, leading to simpler code

The PRs went through significant refactoring during review — the final versions are substantially tighter than the initial submissions.

What Could Be Better

Working on this was a positive experience overall, but a few things created friction:

No way to benchmark before merging. The null-build overhead question came up late in the process. I discovered through manual benchmarking that the change added ~70% to null build time — a significant regression. Dune’s benchmark CI workflow runs only on pushes to main, not on PRs. Contributor-accessible performance tooling would help catch regressions before they land.

Review momentum vs. rebasing. The test PRs merged quickly, but the implementation PR required multiple rounds of review over days. Between rounds, main moves forward, requiring rebases that risk introducing conflicts. The contributor carries the burden of keeping branches fresh. This is compounded when PRs depend on each other — every rebase of #14116 required rebasing #14186 as well. GitHub has no first-class support for PR stacks, so this is manual and error-prone. Of course, all GitHub-hosted repos suffer from this.

Flaky CI. Many CI runs had errors that were not related to my code. It was often an upstream provider of an OCaml package that was unreachable or faulty (temporarily). These problems often resolved themselves, but caused day-long delays in the PR lifetimes. The problem stems from the setup code that is run and re-run over and over in CI jobs.

Reflections

The Dune codebase is well-structured, with clear separation between the build engine, rule generation, and scheduler. It is also of good quality, making it feel like time spent on keeping the quality high is worthwhile.

I found the cram test infrastructure good for testing. Each test scenario is a self-contained shell script with expected output, making it easy to document and verify exact recompilation behavior. It inspires confidence in the code.

The maintainers have been responsive and the review process, while slowed by thoroughness, is collaborative and professional. Thank you, maintainers!

9 posts - 6 participants

Read full topic

]]>
https://discuss.ocaml.org/t/experience-report-refining-dune-s-dependency-graph/18002 Sun, 19 Apr 2026 20:23:54 +0000 No No No discuss.ocaml.org-topic-18002 Experience Report: Refining Dune’s Dependency Graph
[ANN] ppx_mixins: slightly more elegant mixin syntax Ecosystem Hello,

I’ve written a tiny ppx called ppx_mixins so that one can write:

type u [@@mixins Map.OrderedType + Printable]

which gets desugared to

type u
include Map.OrderedType with type t := u
include Printable with type t := u

Not much but increases readability in a codebase that uses the “mixin” pattern a lot

Constructing type signatures

One can also write

module type M = [%mixins Map.OrderedType + Printable]`
(* desugars to *)
module type M = sig 
   type t 
   include Map.OrderedType with type t := t
   include Printable with type t := t
end

In particular, if you also overcome the lack of support for e.g. pretty printing (or other features) in the standard library by extending functors:

module type Hashed_and_printable = sig
   include Stdlib.Hashtbl.HashedType
   val pp : Format.formatter -> t -> unit
end

module Make (T: Hashed_and_printable) = struct 
   include Stdlib.Hashtbl.Make(T)
   let pp = ...
end

You can instead write:

module Make(T: [%mixins Stdlib.Hashtbl.HashedType + Printable]) = struct 
   ...
end

Additional features

One can also override other types, e.g.

type u [@@mixins Mappable(key = int; value := v)]
(* desugars to *)
type u
include Mappable with type t := u and type key = int and type value := v

Limitations

  • No support for parametric types, e.g. with type 'a u = 'a v
  • No support for tuple and function types, e.g. with type t = int -> bool

This is because the preprocessor parses the payload as an expression, and these don’t parse nicely a expressions.
Deeper support (e.g. for mixins with type parameters) would probably also require language support.

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/ann-ppx-mixins-slightly-more-elegant-mixin-syntax/18001 Sun, 19 Apr 2026 13:22:52 +0000 No No No discuss.ocaml.org-topic-18001 [ANN] ppx_mixins: slightly more elegant mixin syntax
Seeking maintainers for our OCaml SIP server, gRPC, and HTTP/2 libraries Ecosystem As we’re moving off OCaml at dialo, we’d like to donate the libraries we built to people who will properly maintain them. We built a highly performant telephony system using OCaml, but as a small team we ended up maintaining too much software for our liking.

We initially built a SIP server implementation in OCaml, which was a perfect fit. We needed to connect it to the rest of our system in a language agnostic way. We chose gRPC and that’s where things got difficult.

At a smaller scale our own buggy implementation of gRPC on top of h2 was good enough. Then we started scaling and at the same time transitioned to OCaml 5.0. The combination of those factors resulted in:

  1. Performance regressions in 5.0 related to memory management, both inside of app code, SIP stack, and inside of h2.
  2. We needed a more robust implementation of gRPC to handle errors and edge cases better.

Long story short we ended up:

  1. Writing our own implementation of http2
  2. Rewriting the gRPC library exclusively for eio to limit the scope together with decent codegen

Then, in late 2025, we had to add new features to the SIP server and something inside us just broke. The SIP server had accumulated quite a bit of legacy code over 3.5 years, so we wanted to rewrite some parts. We were extremely excited to build the new architecture centered around effects — only to discover that user-space effects and concurrency libraries don’t really work well together, since callbacks lose their scope (duh). That was the final straw.

We decided to run two 1-week stints to try rewriting the service in Rust and Go. We ended up choosing Rust. We still miss OCaml, but not having to implement and maintain our own http2/grpc/sip stack is a breath of fresh air.

So here we are — we’re gradually removing OCaml from our stack, and that’s why we’d like to donate:

  • ocaml-grpc - the new code is on dialo branch, eio only at the moment, battle tested on production. It does have some bugs in it but few and it’s pretty solid.
  • haha (http2) - overall good but could be better. We cancel fibers too often, it’s a very low hanging fruit to make it much faster.
  • Our SIP stack — this is currently not open source, but we’re happy to share the source code with the right person or team.

Please write dms to me and feel free to ask me or @adamchol about specifics.

3 posts - 3 participants

Read full topic

]]>
https://discuss.ocaml.org/t/seeking-maintainers-for-our-ocaml-sip-server-grpc-and-http-2-libraries/18000 Sat, 18 Apr 2026 12:37:09 +0000 No No No discuss.ocaml.org-topic-18000 Seeking maintainers for our OCaml SIP server, gRPC, and HTTP/2 libraries
[ANN] Code navigation and search on Github Ecosystem GitHub is now using tree-sitter-ocaml for code navigation and code search.

  • Code highlighting should be more accurate (compared to the old TextMate grammar) and supports all features up to OCaml 5.4.
  • There is a symbols side panel for each file.
  • You can click on symbols to find definitions and references.
  • You can search for definitions.
  • There is limited support for nested structures.

They enabled it a few months ago already, but I forgot to post it here.

The code navigation is not always 100% accurate, but good enough to be helpful. If you encounter any issues with incorrectly highlighted code, this could be a tree-sitter-ocaml issue.

2 posts - 2 participants

Read full topic

]]>
https://discuss.ocaml.org/t/ann-code-navigation-and-search-on-github/17999 Sat, 18 Apr 2026 12:15:26 +0000 No No No discuss.ocaml.org-topic-17999 [ANN] Code navigation and search on Github
[ANN] Restarting OCaml.jp: The OCaml Japan User Group Community Dear OCaml community,

We’re excited to announce the relaunch of OCaml.jp (https://ocaml.jp/), the OCaml Japan User Group!

Our goal is to grow and energize the OCaml community in Japan by bringing together users to foster broader adoption and deeper engagement with OCaml across the country.

Current Activities

We’ve already kicked off a couple of initiatives:

  • OCaml Weekly News - Japanese Edition: We’re maintaining a Japanese translation of the OCaml Weekly News at https://ocaml.jp/cwn-ja/, making it easier for Japanese speakers to stay up to date with the latest happenings in the OCaml ecosystem.

  • OCaml Meetup in Tokyo (August 2026): We are currently preparing to host an OCaml Meetup in Tokyo this August, the first one in over ten years! More details will be shared soon; please stay tuned!

Join Us!

We’re using Discord as our primary communication platforms. Whether you’re based in Japan, are a Japanese-speaking OCaml enthusiast anywhere in the world, or simply want to connect with the Japanese OCaml community, we’d love to have you join us!

Please use the following link to join Discord: https://discord.gg/qQTbny8KF4

We look forward to building a vibrant OCaml community in Japan together. よろしくお願いします!

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/ann-restarting-ocaml-jp-the-ocaml-japan-user-group/17998 Fri, 17 Apr 2026 12:31:10 +0000 No No No discuss.ocaml.org-topic-17998 [ANN] Restarting OCaml.jp: The OCaml Japan User Group
[ANN] opam 2.5.1 Ecosystem Hi everyone,

opam 2.5.1 is now available. This release is fixing a security issue (OSEC-2026-03) and other minor things. Thanks to @andrew for reporting this issue.

We invite everyone to upgrade to 2.5.1 as soon as possible.

If you depend on the older opam package of your preferred distribution, distributions such as Debian Stable have already started backporting the relevant fix and the patched version should be available there very soon.

You can read our blog post for relevant links and details.

Try it!

The upgrade instructions are unchanged:

For Unix systems

bash -c "sh <(curl -fsSL https://opam.ocaml.org/install.sh) --version 2.5.1"

or from PowerShell for Windows systems

Invoke-Expression "& { $(Invoke-RestMethod https://opam.ocaml.org/install.ps1) } -Version 2.5.1"

Please report any issues to the bug-tracker.

Happy hacking,

<> <> The opam team <> <> :camel:

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/ann-opam-2-5-1/17997 Thu, 16 Apr 2026 21:04:25 +0000 No No No discuss.ocaml.org-topic-17997 [ANN] opam 2.5.1
Emacs warning when opening OCaml file Ecosystem After following the Configuring Your Editor instructions for Emacs on the official OCaml website, I am getting a warning in Emacs after opening an *.ml file. Any help would be appreciated. I am using Emacs version 30.2 on Linux. I can suppress defvaralias warnings, but I’d rather not if this can be fixed somehow.

Warning:

⛔ Warning (defvaralias): Overwriting value of ‘ocaml-eglot-hook’ by aliasing to ‘ocaml-eglot-mode-hook’

Warning stack trace:

Debugger entered: nil
  (progn (debug))
  (if (eq new-alias 'ocaml-eglot-hook) (progn (debug)))
  defvaralias@trace-defvarialias(ocaml-eglot-hook ocaml-eglot-mode-hook)
  apply(defvaralias@trace-defvarialias (ocaml-eglot-hook ocaml-eglot-mode-hook))
  defvaralias(ocaml-eglot-hook ocaml-eglot-mode-hook)
  byte-code("\301\302N\204\f\0\303\301\302\304#\210\303\301\305\306#\210\303\301\307\310C#\210\311\312\313\10\310\211%\210\314\315\312\"\210\316\315\312\317#\210\314\320\321\"\210\316\320\312\317#\210\322\323\301\"\210\324\323\301\317#\210\322\325\300\"\210\324\325\300\317#\210\326\315!\207" [ocaml-eglot-mode-map ocaml-eglot-mode-hook variable-documentation put "Hook run after entering or leaving `ocaml-eglot-mode'.\nNo problems result if this variable is not bound.\n`add-hook' automatically binds it.  (This is true for all hook variables.)" custom-type hook standard-value nil add-minor-mode ocaml-eglot-mode " OCaml-eglot" defalias ocaml-eglot make-obsolete "1.4.0" ocaml-eglot-setup ocaml-eglot--setup defvaralias ocaml-eglot-hook make-obsolete-variable ocaml-eglot-map provide] 6)
  ocaml-eglot()
  run-hooks(change-major-mode-after-body-hook prog-mode-hook tuareg-load-hook tuareg-mode-hook)
  apply(run-hooks change-major-mode-after-body-hook (prog-mode-hook tuareg-load-hook tuareg-mode-hook))
  run-mode-hooks(tuareg-mode-hook)
  tuareg-mode()
  set-auto-mode-0(tuareg-mode nil)
  set-auto-mode--apply-alist((("dune-project\\'" . dune-mode) ("dune\\'" . dune-mode) ("\\(?:\\`\\|/\\)dune\\(?:\\.inc\\|\\-project\\|\\-workspace\\)?\\'" . dune-mode) ("\\.ocamlinit\\'" . tuareg-mode) ("[./]opam_?\\'" . tuareg-opam-mode) ("\\.mly\\'" . tuareg-menhir-mode) ("\\.eliomi?\\'" . tuareg-mode) ("\\.ml[ip]?\\'" . tuareg-mode) ("\\.mli\\'" . tuareg-mode) ("\\.ml\\'" . tuareg-mode) ("\\.desktop\\(\\.in\\)?$" . desktop-entry-mode) ("CMakeLists\\.txt\\'" . cmake-mode) ("\\.cmake\\'" . cmake-mode) (".at'" . autotest-mode) ("\\.gpg\\(~\\|\\.~[0-9]+~\\)?\\'" nil epa-file) ("\\.elc\\'" . elisp-byte-code-mode) ("\\.zst\\'" nil jka-compr) ("\\.dz\\'" nil jka-compr) ("\\.xz\\'" nil jka-compr) ("\\.lzma\\'" nil jka-compr) ("\\.lz\\'" nil jka-compr) ("\\.g?z\\'" nil jka-compr) ("\\.bz2\\'" nil jka-compr) ("\\.Z\\'" nil jka-compr) ("\\.vr[hi]?\\'" . vera-mode) ("\\(?:\\.\\(?:rbw?\\|ru\\|rake\\|thor\\|axlsx\\|jbuilder\\|rabl\\|gemspec\\|podspec\\)\\|/\\(?:Gem\\|Rake\\|Cap\\|Thor\\|Puppet\\|Berks\\|Brew\\|Fast\\|Vagrant\\|Guard\\|Pod\\)file\\)\\'" . ruby-mode) ("\\.re?st\\'" . rst-mode) ("/\\(?:Pipfile\\|\\.?flake8\\)\\'" . conf-mode) ("\\.py[iw]?\\'" . python-mode) ("\\.m\\'" . octave-maybe-mode) ("\\.less\\'" . less-css-mode) ("\\.editorconfig\\'" . editorconfig-conf-mode) ("\\.scss\\'" . scss-mode) ("\\.cs\\'" . csharp-mode) ("\\.awk\\'" . awk-mode) ("\\.\\(u?lpc\\|pike\\|pmod\\(\\.in\\)?\\)\\'" . pike-mode) ("\\.idl\\'" . idl-mode) ("\\.java\\'" . java-mode) ("\\.m\\'" . objc-mode) ("\\.ii\\'" . c++-mode) ("\\.i\\'" . c-mode) ("\\.lex\\'" . c-mode) ("\\.y\\(acc\\)?\\'" . c-mode) ("\\.h\\'" . c-or-c++-mode) ("\\.c\\'" . c-mode) ("\\.\\(CC?\\|HH?\\)\\'" . c++-mode) ("\\.[ch]\\(pp\\|xx\\|\\+\\+\\)\\'" . c++-mode) ("\\.\\(cc\\|hh\\)\\'" . c++-mode) ("\\.\\(bat\\|cmd\\)\\'" . bat-mode) ("\\.[sx]?html?\\(\\.[a-zA-Z_]+\\)?\\'" . mhtml-mode) ...) nil nil)
  set-auto-mode()
  normal-mode(t)
  after-find-file(nil t)
  find-file-noselect-1(#<buffer test.ml> "~/projects/cs3110/unit-testing/test.ml" nil nil "~/projects/cs3110/unit-testing/test.ml" (1021339 44))
  find-file-noselect("~/projects/cs3110/unit-testing/test.ml" nil nil nil)
  find-file("~/projects/cs3110/unit-testing/test.ml")
  recentf-open-most-recent-file(2)
  recentf-open-most-recent-file-2()
  funcall-interactively(recentf-open-most-recent-file-2)
  command-execute(recentf-open-most-recent-file-2)

My config (matches official suggestion):

Note: I’m using straight.el configured such that :ensure t isn’t necessary.

(use-package tuareg
  :mode (("\\.ocamlinit\\'" . tuareg-mode)))

(use-package ocaml-eglot
  :after tuareg
  :hook
  (tuareg-mode . ocaml-eglot)
  (ocaml-eglot . eglot-ensure))

3 posts - 2 participants

Read full topic

]]>
https://discuss.ocaml.org/t/emacs-warning-when-opening-ocaml-file/17996 Thu, 16 Apr 2026 14:14:45 +0000 No No No discuss.ocaml.org-topic-17996 Emacs warning when opening OCaml file
[ANN] Stk 0.6 released Community Hello,

Stk is a SDL-based graphical user interface toolkit. Its interface is inspired by Gtk and should look familiar to developers using Lablgtk.

Stk 0.6 is available. Among changes listed here, this release introduces Tooltips and handling of user’s configuration, including user-defined themes.

The stk* packages are available from my personal opam repository.

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/ann-stk-0-6-released/17994 Thu, 16 Apr 2026 07:52:55 +0000 No No No discuss.ocaml.org-topic-17994 [ANN] Stk 0.6 released
OUPS meetup april 2026 Community The next OUPS meetup will take place on Wednesday, 29th of April 2026. It will start at 6:30pm at the 45 rue d’Ulm in Paris. It will be in the in the Rataud amphitheater.

:warning: It’s not in Jussieu as usual but in ENS Ulm! If you’re not familiar with the place, there is a map of the buildings.

Please, register on meetup as soon as possible to let us know how many pizza we should order.

For more details, you may check the OUPS’ website .

Moreover, we’d like to announce that the organizing team moved to the OCaml Zulip. Feel free to contact us there if you’d like to suggest talks.


This time we’ll have the following talks:

When Turing machines meet GADTs – Florian Angeletti

Abstract (click for more details)

Extending OCaml’s pattern matching – Yanni Lefki

Abstract (click for more details)

After the talks there will be some pizzas offered by the OCaml Software Foundation and later on we’ll move to a pub nearby as usual.

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/oups-meetup-april-2026/17989 Wed, 15 Apr 2026 15:19:50 +0000 No No No discuss.ocaml.org-topic-17989 OUPS meetup april 2026
[ANN] Mollymawk and Albatross orchestrating all virtual machines Community Dear everyone,

we just finished and deployed Albatross and Mollymawk to support virtual machines that are not MirageOS unikernels.

The reasoning is simple: we embedded so many nice features (metrics, console output, deploying via web UI, multi-tenant, startup dependencies, restart-on-failure,..) that we really wanted to deploy our non-MirageOS virtual machines as well with the same mechanism and don’t have duplicated code all over.

For the time being, it only supports FreeBSD BHyve, but let us know if you’re interested in other virtualization technologies and we will prioritize that work!

We also wrote a brief blog article with screenshots: Robur's blog - Mollymawk supporting other virtual machines

12 posts - 4 participants

Read full topic

]]>
https://discuss.ocaml.org/t/ann-mollymawk-and-albatross-orchestrating-all-virtual-machines/17988 Wed, 15 Apr 2026 14:18:54 +0000 No No No discuss.ocaml.org-topic-17988 [ANN] Mollymawk and Albatross orchestrating all virtual machines
[ANN] ptt, a mailing list system as unikernel Community Hey! We just launched a new mailing list powered entirely by OCaml unikernels. The website (itself a unikernel) is at https://mailingl.st. You can subscribe to [email protected] by sending an email to [email protected] if you’re interested in the development and deployment of SMTP-related unikernels.

Fair warning: this is still a public test mailing list for now. In the long run, it will focus on our ptt project.

The SMTP protocol: a long and winding road!

In the beginning, email

It all started with Mr.MIME, our library for decoding and encoding emails. It’s a synthesis of the relevant RFCs, but more importantly it’s been battle-tested against real-world emails from the IEEE, Enron, KVM and, most recently, the caml-list.

This work also let us build Hamlet, a database of valid random emails generated using a fuzzer.

Under the hood, Mr.MIME relies on unstrctrd for decoding the most general form of values found in an email (with internationalisation support via rosetta) and prettym for encoding emails while respecting SMTP constraints and (Comment) Folding Whitespace handling.

Next, the protocol

Then came colombe, our OCaml implementation of the SMTP protocol. It uses ocaml-tls for STARTTLS support.

The protocol is supposedly “simple” (though the Internet always has surprises in store), but from day one we designed colombe to be independent of any scheduler and network layer. That way it slots right into unikernels without friction.

Finally, legitimacy

On top of these core components, we built several email security layers:

  • ocaml-dkim handles signing and verifying email integrity in a streaming fashion (both for verification and signature generation)
  • uspf verifies sender identity and, like most of our libraries, stays independent of any scheduler or DNS implementation
  • ocaml-dmarc automates DKIM and SPF verification, stamps emails with the result, and checks alignment across a domain name
  • ocaml-arc lets you verify and sign emails to complete a chain of trust when an email passes through multiple SMTP servers (which is exactly what happens with a mailing list)

We wrote a short article about all of this here.

All in the form of unikernels

Our first experiments already showed that we could handle emails with MirageOS unikernels. But we also hit real limitations: memory leaks, security vulnerabilities, and build issues.

So we decided to start fresh, and take the opportunity to fully embrace OCaml 5 and effects. We rebuilt the key pieces from scratch:

  • a new effect-based scheduler: Miou/Mkernel
  • a much more complete TCP/IP stack: Mnet
  • a new FAT32 file system: Mfat

ptt is built on this new stack, and so far we haven’t observed any memory leaks (thanks to mkernel-memtrace for tracing memory usage, viewable via memtrace-viewer). The CVEs related to mirage-tcpip were taken into account during mnet’s development, and the build story is much simpler now. A GitHub action can build and actually run the unikernel to test it, as you can see with mnet.

Other unikernels using this approach are available too. If you’re curious, check out this tutorial on creating a unikernel in OCaml.

Deployment

ptt also tackles the deployment question. We have an article presenting the “stateless” aspect of ptt. We’d also like to (re)introduce Albatross, our secure unikernel orchestrator, and Mollymawk, a web interface for deploying unikernels (which is itself a unikernel).

More broadly, this is what our cooperative is working towards: we really want to improve the user experience, whether you’re a developer or a deployer. We believe that actually developing, deploying, and using our unikernels is the only way to get them adopted more widely. So make sure to follow us on these projects too!

Usage

Along the way, we found it really helpful to have a tool that lets you track every stage of an email’s lifecycle. That’s how blaze came about: a Swiss Army knife for handling emails.

It’s still experimental, but it already lets you:

  • use our archive system (generate, read, index, etc.)
  • handle other archives such as mbox or maildir
  • communicate via the POP3 protocol
  • sign and verify emails (DKIM and ARC)
  • build emails from the command line
  • send emails
  • run a small local SMTP server

blaze is how we iterate on our library APIs and validate implementations. It’s experimental, but it’s gradually turning into a full email client.

Archiving & Indexing

We’d also like to present the stem project, which extracts word roots from a document (such as an email) and tokenises them to get something analysable without the complexity of natural language. This tokenisation is what powers our small bm25 search engine. You can see results here.

This is also what drives our caml-list search engine, available as a unikernel: blame, which you can try at https://caml-list.robur.coop (powered by vif).

Beyond search, there’s also email indexing via Message-IDs. For that we built bancos: a persistent radix tree in OCaml that supports parallel access! More details here.

Finally, our indexing system uses the PACKv2 format (the same one Git uses to store objects), implemented by the carton library. It has proven its stability through the ocaml-git project, so we decided to reuse it for archiving emails (much like public-inbox did, though in a different form).

Conclusion

Thanks to all this work, OCaml now has a solid set of email-related projects. This journey started back in 2016 and there’s still a long way to go, as we always aim to offer robu(r)st, battle-tested solutions. Unlike some implementations in other languages (though we are in discussion with folks in the Rust community), ours actually adhere to the standards!

It may not seem like a big deal, and you won’t see any major difference when just exchanging emails, but we believe this approach paves the way for a better internet. In the form of unikernels, it represents a genuine reclaiming of the means of communication!

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/ann-ptt-a-mailing-list-system-as-unikernel/17987 Wed, 15 Apr 2026 11:05:03 +0000 No No No discuss.ocaml.org-topic-17987 [ANN] ptt, a mailing list system as unikernel
[ANN] layoutz 0.1.0 🪶 - Zero-dep Elm-style TUIs & terminal plots for your OCaml apps Community Hello all! Thanks for your feedback last time - layoutz now has an Elm-style TUI runtime (quite different in spirit than (the excellent) Minttea) … a smoothed API .. and terminal plot built-ins.

Looking for feedback! Many thanks

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/ann-layoutz-0-1-0-zero-dep-elm-style-tuis-terminal-plots-for-your-ocaml-apps/17986 Tue, 14 Apr 2026 15:10:07 +0000 No No No discuss.ocaml.org-topic-17986 [ANN] layoutz 0.1.0 🪶 - Zero-dep Elm-style TUIs & terminal plots for your OCaml apps
[ANN] Caqti 2.3.0 Community I would like to announce the release of Caqti 2.3.0.

TL;DR: Consider adding the caqti.classic to your link line (available since this version). It currently only re-exports the caqti library, but will be replaced by a compatibility layer for the Caqti 2 API in Caqti 3 to allow incremental migration.

Release Notes

Note that some of the new features of this release are only accessible
through the still unstable caqti.template library, which will soon be
stabilized as part of an upcoming Caqti 3 API. Due to adjustments to module
names, switching to caqti.template will not ensure future compatibility.
Instead, users are encouraged to add the new caqti.classic to their
dependencies to ease migration to Caqti 3.

  • Added an alias caqti.classic for the caqti library. This will be
    turned into a library providing compatibility with the current Caqti 2
    API when Caqti 3 is released. The two APIs can be used side-by-side to
    allow incremental migration.

  • The dialect descriptor for MariaDB in caqti.template now provides the
    server version.

  • Added Query.parens, Query.litf, Query.vars, Row_type.fields to
    the caqti.template library.

  • Revised the interface for creating row types to allow instantiating
    parametric types applicatively. Before this change, each application of
    a function representing a parametric type would generate a new type ID
    even when applied to the same type parameter argument. The key part of
    this interface is the Caqti_template.Constructor_type module.

  • The query functions provided to request templates are now memoized, so
    that they are only called once per dialect. This is meant as an
    optimization; it’s still good practise to avoid side-effects here.

  • The new function Query.with_pos_of allows query generators to add
    source locations to the syntax tree, which will be emitted as SQL
    comments in the query string if the enable_query_annotations is set.
    This should simplify debugging when the query is assembled from
    different parts of the application code.

  • The still unstable caqti.template library now supports multiple
    statements in a single request template, sent opportunistically as a
    single query where allowed. This is still experimental.

  • Fixed package scoping of shim rules for sqlite3 (#133 by mefyl).

  • Fixed the error classification for the SQLite3 driver (#132).

  • Fixed reconnect after connection loss for PostgreSQL.

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/ann-caqti-2-3-0/17985 Tue, 14 Apr 2026 14:28:59 +0000 No No No discuss.ocaml.org-topic-17985 [ANN] Caqti 2.3.0
[ANN] http-date v0.2 — Zero-dependency HTTP date parsing for OCaml Community I just released v0.2 of http-date, an RFC 9110 compliant HTTP datetime decoder/encoder for OCaml.

This is a major rewrite from v0.1. Here’s what changed:

Zero dependencies — Replaced the ocamllex/menhir parser with a hand-written implementation and removed the ptime dependency entirely. The library now only requires ocaml and dune.

New type-safe API — The parsed result is now a polymorphic variant tagged by format (IMF, RFC850, ASCTIME), so you always know which HTTP date format was parsed. The dayname, date, time, and datetime types are all exposed in the public API.

Serious testing — Added property-based tests with alcobar and AFL fuzz testing infrastructure to build confidence in the hand-written parser.

If you’re working with HTTP headers in OCaml, give it a try:

opam install http-date

https://github.com/bikallem/http-date

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/ann-http-date-v0-2-zero-dependency-http-date-parsing-for-ocaml/17984 Tue, 14 Apr 2026 09:51:54 +0000 No No No discuss.ocaml.org-topic-17984 [ANN] http-date v0.2 — Zero-dependency HTTP date parsing for OCaml
Profiling with Landmarks - setup question Ecosystem I’m trying to set up a dune project for profiling with Landmarks. Ideally I can compile the project with and without profiling. Landmarks documents a lot of ways to set it up and I struggle to make it work. So far I have:

==> dune-workspace <==
(lang dune 3.21)
(context default)
(context (default (name profiling) (instrument_with landmarks)))

==> bin/dune <==
(executable
 (name main)
 (public_name vmax)
 (instrumentation (backend landmarks))
 (libraries vmax server cmdliner))


==> lib/dune <==
(library
 (name vmax)
 (instrumentation (backend landmarks))
 (libraries ptime mustache fit utils expr yojson))


A dune build now builds

./_build/default/bin/main.exe
./_build/profiling/bin/main.exe

Observations so far:

  • Running the profiling binary does not create a profiling log, no matter if OCAML_LANDMARKS=output=landmarks.txt,time,allocation is set or not. This suggests the setup above is missing something or the build step requires something that I am missing.
  • ./_build/installcontains both binaries - but which one gets installed when doing a dune install?

I had Landmarks working when I used

(preprocess
   (pps landmarks-ppx --auto))

but this makes it difficult to switch between profiling and no profiling.

2 posts - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/profiling-with-landmarks-setup-question/17983 Tue, 14 Apr 2026 08:40:17 +0000 No No No discuss.ocaml.org-topic-17983 Profiling with Landmarks - setup question
[ANN] ATD 4.1.0 - now with YAML support Community ATD now has OCaml support for conveniently reading data from YAML files as well as from other formats with minimal effort. It means:

  1. You define a type for your config data.
  2. atdml --mode jsonlike app_config.atd generates the OCaml code that converts a JSON-like AST containing source locations into your config data structure.
  3. Your program loads a YAML file, converts it to a JSON-like tree, and then calls the generated function to translate it into an OCaml data structure.
  4. Your application prints useful error messages if the config is malformed or incomplete.

An example is included in the distribution. It uses the recently released YAMLx library.

Note that YAMLx needs generous sponsors to fund the work that was done and unlock a permissive ISC license for everyone. Or you can accept the terms of the AGPL license if you’re happy to share your application’s source code with the users.

Other input file formats or other YAML libraries can be used similarly with minimum effort as long as source locations are available. For this, you’ll need a bridge that converts your AST into the JSON-like AST.

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/ann-atd-4-1-0-now-with-yaml-support/17982 Mon, 13 Apr 2026 23:22:41 +0000 No No No discuss.ocaml.org-topic-17982 [ANN] ATD 4.1.0 - now with YAML support
[ANN] I18n 5.0 — Internationalisation made easy for any OCaml app Ecosystem The Ocsigen team is happy to announce the release of ocsigen-i18n 5.0, a small but practical internationalisation library for OCaml.

The big change in this release: ocsigen-i18n is no longer tied to Eliom. It can now be used in any OCaml project, with optional extensions for Tyxml and Eliom when you need them.

Ocsigen-i18n was initially written by @sagotch from Be Sport. This release has been made possible thanks to the work of Habib, funded by IRILL.

opam install ocsigen-i18n

How it works

Translations are written in a plain TSV file (one key per line, one column per language):

foo                 This is a simple key.        Ceci est une clé toute simple.
a_human             a human                      un humain
bar                 I am {{x}}.                  Je suis {{x}}.
baz                 There {{{c?are||is an}}} apple{{{c?s||}}} here!  Il y a {{{c?des||une}}} pomme{{{c?s||}}} ici !
bu                  I am {{x %s}} ({{n %d}}).    Je suis {{x %s}} ({{n %d}}).

The mini-templating language supports:

  • {{x}} a string variable ~x
  • {{x %d}} a typed variable using the given format specifier
  • {{{c?yes||no}}} an optional boolean ?c switching between two strings

Then in your code, a PPX extension turns [%i18n key] into the right call:

print_endline [%i18n foo];
print_endline [%i18n bar ~x:[%i18n a_human]];
print_endline [%i18n baz ~c:(nb > 1)];
print_endline [%i18n bu ~x:"Jean-Michel" ~n:42];

(* Switching language explicitly *)
print_endline [%i18n foo ~lang:My_i18n.Fr];

The current language is held in a mutable reference you can swap (or replace with an Eliom scoped reference if you need per-session/tab languages).

Dune integration

The tool plugs into Dune very naturally. Generate the OCaml module from your TSV file with a rule:

(rule
 (target example_i18n.ml)
 (deps example_i18n.tsv)
 (action
  (run %{bin:ocsigen-i18n} --languages en,fr --input-file %{deps}
                           --output-file %{target})))

And wire the PPX in your library/executable:

(preprocess (pps ocsigen-i18n -- --default-module Example_i18n))

That’s all you need for a plain OCaml project.

Tyxml support

Pass --tyxml to the generator and the same [%i18n key] expression now produces a list of Tyxml HTML elements instead of a string:

(* Builds an HTML fragment, ready to drop into a Tyxml tree *)
let greeting = [%i18n bar ~x:[%i18n a_human]]

Variables can themselves be lists of HTML nodes, so you can mix translated text with markup naturally:

[%i18n bar ~x:[ txt "Jean-Michel ("
              ; txt (string_of_int id)
              ; txt ")" ]]

If you need a plain string in Tyxml mode (for an attribute, for instance), just prefix with S.:

[%i18n S.bar ~x:[%i18n S.a_human]]   (* string output *)

Eliom support

For client–server Eliom apps, pass --eliom. The generator emits an .eliom file (so the same translations are available on both sides), implies --tyxml, and adds [@@deriving json] on the language type so you can serialise it across the wire:

(rule
 (target example_i18n.eliom)
 (deps example_i18n.tsv)
 (action
  (run %{bin:ocsigen-i18n} --eliom --languages en,fr --input-file %{deps}
                           --output-file %{target})))

Multiple TSV files

You can split translations across several files. The PPX uses your module path to find the right one:

[%i18n foo]                          (* default module *)
[%i18n MyI18n.foo]                   (* MyI18n.foo *)
[%i18n MyI18n.S.bar ~x:[%i18n S.foo]]

Optional --prefix / --suffix flags let you keep call-sites concise ([%i18n Feature.foo]Pr_Feature_i18n.foo ()).


Happy translating!

2 posts - 2 participants

Read full topic

]]>
https://discuss.ocaml.org/t/ann-i18n-5-0-internationalisation-made-easy-for-any-ocaml-app/17981 Mon, 13 Apr 2026 15:22:09 +0000 No No No discuss.ocaml.org-topic-17981 [ANN] I18n 5.0 — Internationalisation made easy for any OCaml app
How can my code know my program's version? Learning In an example in the Cmdliner tutorial tutorial (cmdliner.tutorial) I see the promising line

  Cmd.make (Cmd.info "TODO" ~version:"%%VERSION%%") @@
  ...

so I guess there should be some kind of preprocessing to replace that %%VERSION%% string with the correct value, taken from a “single source of truth”, but I cannot find either. What/where should be that single source of truth, and what should be that expansion mechanism?

One candidate for the source of truth is probably the version stanza in dune-project?

As for the mechanism, I saw something a bit different in some online projects, with dune files with

(rule
 (targets version.ml)
 (action
  (with-stdout-to %{targets}
   (echo "let version = \"%{version:my_project}%\""))))

which would allow for instance to write in my code

  Cmd.make (Cmd.info "TODO" ~version:Version.version) @@
  ...

But unfortunately, that does not display the version in the version stanza, but another string that I cannot make sense of, like 2b8df27-dirty%.

Is there a “canonical” or at least a preferred way to obtain a version number in an OCaml project?

Thank you.

10 posts - 5 participants

Read full topic

]]>
https://discuss.ocaml.org/t/how-can-my-code-know-my-programs-version/17980 Sun, 12 Apr 2026 17:09:02 +0000 No No No discuss.ocaml.org-topic-17980 How can my code know my program's version?
Is it possible to allocate immediately in major heap? Community I want to parse JSON file (>1GB) from C code (because of speed), and it looks like many invocations of caml_alloc_tuple lead me to “Fatal error: allocation failure during minor GC”.
There is a function caml_alloc_shr in the manual but it looks like it is not the one: it allocated large blocks in another place, not everything. (Also, it crashes my program, but I hope it is not relevant.)

7 posts - 4 participants

Read full topic

]]>
https://discuss.ocaml.org/t/is-it-possible-to-allocate-immediately-in-major-heap/17979 Fri, 10 Apr 2026 20:02:41 +0000 No No No discuss.ocaml.org-topic-17979 Is it possible to allocate immediately in major heap?
[ANN] New release of OCaml LSP 1.26.0 & Merlin 5.7.0-504 Community Hi everyone,

We are happy to announce the double release of merlin 5.7.0-504 and ocaml-lsp 1.26.0.

The new releases contains exciting changes such as improvements to type enclosing behaviour on various class and object related items, signature help improvements and several several bug fixes.

Please do not hesitate open issues on our bug trackers if you encounter any problems:

2 posts - 2 participants

Read full topic

]]>
https://discuss.ocaml.org/t/ann-new-release-of-ocaml-lsp-1-26-0-merlin-5-7-0-504/17978 Fri, 10 Apr 2026 15:39:48 +0000 No No No discuss.ocaml.org-topic-17978 [ANN] New release of OCaml LSP 1.26.0 & Merlin 5.7.0-504
Missing ocaml.org package documentation Site Feedback The generated documentation for (all?) OPAM packages (and for all versions?) seem to be missing from ocaml.org for some days now (maybe a week?). The package overview pages are still there, and I see an older thread in Site Feedback saying the documentation resides on a separate set of servers. Are those servers having problems?

5 posts - 4 participants

Read full topic

]]>
https://discuss.ocaml.org/t/missing-ocaml-org-package-documentation/17977 Fri, 10 Apr 2026 12:57:58 +0000 No No No discuss.ocaml.org-topic-17977 Missing ocaml.org package documentation
Teachers and type-system specialists: what is your stance regarding the typing of definitions? Community Hi fellow teachers and/or OCaml-type-system experts,

Until now, when teaching at ENSEEIHT, we haven’t been insisting on typing (global) let definitions, leaving typing annotations to val declarations.

However, we are pondering adding type annotations on let definitions. Specifically explicitly polymorphic annotations (probably using the ‘a . ... syntax). There are several reasons:

  • It stresses the fact that in let definitions, a non-quantified 'a does not stand for polymorphism, contrarily to declarations (we don’t cover type systems in this course and students tend to think that 'a is necessarily polymorphic).
  • This notation is also covered in val since v4.14.0 so we now have a homogeneous notation for definitions and declarations.
  • Such annotations also provide with better error messages, in particular in cases when a unification variable would have been specialized without students noticing.
  • This syntax is also useful when introducing “non-uniform” algebraic types, in which case polymorphic recursion is needed to type some functions.
  • Finally our students already know more mainstream programming languages such as Java, where a similar notation is used for genericity, so it’s already familiar for them.

Another possibility would be to only use the type a . ... annotation which combines polymorphic recursion with locally-abstract types. Since, later in the course, we also introduce GADTs, this would allow us to teach only one notation, and since this isn’t a theory course, this would avoid difficulties trying to explain differences between syntaxes for polymorphic recursion, locally abstract types and their combination. We would lose the homogeneity with the notation in val though. (Also, as is discussed in this Github issue, the locally-abstract-type notation is probably the most user-friendly among the three possibilities.)

I’d like to know the stance of OCaml teachers or type-system experts on this topic. What would you avoid, what would you advise, how do you address this topic?

1 post - 1 participant

Read full topic

]]>
https://discuss.ocaml.org/t/teachers-and-type-system-specialists-what-is-your-stance-regarding-the-typing-of-definitions/17976 Fri, 10 Apr 2026 11:11:50 +0000 No No No discuss.ocaml.org-topic-17976 Teachers and type-system specialists: what is your stance regarding the typing of definitions?
[ANN] ocaml-letsencrypt, an OCaml way to get TLS certificates Ecosystem I am delighted to announce the release of ocaml-letsencrypt (version 2.1.0). This version introduces a new API that allows it to operate independently of a scheduler and an HTTP client. It is also a rewrite using our brand-new jws library, which now utilises the jsont library (rather than yojson).

ocaml-letsencrypt implements challenges needed to obtain a certificate via the three ways: DNS, HTTP and ACME-TLS. It therefore enables a website deployment strategy (implemented with Vif, for example) to be provided entirely in OCaml.

We use it within our cooperative for projects such as:

  • dns-letsencrypt-secondary, a unikernel that acts as a secondary DNS server capable of performing the DNS challenge for a specific domain and uploading the certificate as a TLSA record. It generally works in tandem with our primary-git, our primary DNS server.
  • contruno, a unikernel that acts as a TLS reverse proxy and is capable of performing HTTP challenges. The latter is currently being completely rewritten using mnet.

Good luck with deploying your websites, and happy hacking! Here’s hoping that jws also finds its place as a library within the OCaml ecosystem.

2 posts - 2 participants

Read full topic

]]>
https://discuss.ocaml.org/t/ann-ocaml-letsencrypt-an-ocaml-way-to-get-tls-certificates/17975 Fri, 10 Apr 2026 07:57:41 +0000 No No No discuss.ocaml.org-topic-17975 [ANN] ocaml-letsencrypt, an OCaml way to get TLS certificates
Publishing two packages at once on opam? Ecosystem I’m working on two related packages: bin_there and ppx_bin_there. They should be kept synchronized, but the latter depends on the former.

What’s the best way to push to opam? First bin_there, then wait until it’s merged, then ppx_bin_there?

Ideally, I’d like to publish automatically from my CD, is this a possible flow?

5 posts - 5 participants

Read full topic

]]>
https://discuss.ocaml.org/t/publishing-two-packages-at-once-on-opam/17972 Fri, 10 Apr 2026 07:07:47 +0000 No No No discuss.ocaml.org-topic-17972 Publishing two packages at once on opam?