[ANN] Cstruct 3.0.0, with packaging changes

The Cstruct is a library to make handling “C-like” binary structures easier from within OCaml code. We use it fairly heavily within the MirageOS unikernel framework.

We have just released Cstruct 3.0 which significantly changes the ocamlfind packaging format, to make it easier to only depend on the specific library functionality that is needed. In older versions, there were multiple optional dependencies in the OPAM package that activated functionality such as Lwt, Async and PPX syntax extensions if the relevant support libraries were also installed. Since the advent of tools such as Jbuilder and Topkg, it is now easier for users to eliminate such implicit optional dependencies and turn them into explicit, separate OPAM packages instead.

OPAM repository PR#9154 did this for Cstruct and so we now have separate ocamlfind package for:

  • cstruct - basic library
  • cstruct-async - Core/Async cooperatively threaded library interface
  • cstruct-lwt - cooperatively threaded Lwt library interface
  • cstruct-unix - synchronous Unix library interface
  • ppx_cstruct - the PPX syntax extension

Transitional findlib packages with the old scheme are available, but now packages should migrate to using cstruct-async instead of cstruct.async for example. This has the added benefit of the OPAM package names now matching the findlib names.

If you spot any breakage related to this in OPAM, please drop me a note. It’s a large PR, but we’ve been doing extensive testing of reverse dependencies using DataKit-CI to hopefully avoid breakage in the stable package repository.

PS: This release also ports the build to use Jbuilder as well.


Excellent to see you guys eliminating optional dependencies in opam. As others have pointed out, optional dependencies are problematic, and make the meaning of a given package hard to understand.

It might be worth mentioning that there is a version of cstruct-lwt compatible with all cstruct versions (even very old ones), so it’s safe to add cstruct-lwt as a dependency without it forcing the use of cstruct.3.0.0.

Yes my apologies for not making this clearer in the original announcement. There are packages for cstruct-lwt, cstruct-async, ppx_cstruct and cstruct-unix that are version .0 for the old (pre-3.0.0) versions, and act as dummy packages that pull in the dependencies. This should make it safe to just add them as dependencies without any fancy constraints.

However there is one failure mode that I just fixed in (for example) tar-format: https://github.com/ocaml/opam-repository/pull/9432. If a package assumed that including cstruct and lwt in its ocamlfind requires list was sufficient, this used to work since Cstruct_lwt was in the same subdirectory as Cstruct. With Cstruct-3.0 (and newer releases that use Jbuilder like Ipaddr and Uri), there is more hygiene in the installation and the separate packages are now in subdirectories, so this will no longer link. The solution is to explicitly link to cstruct.lwt in the ocamlfind requires list. This is also backwards compatible with older releases, but requires a new release of the offending package to work with newer Cstruct.

There was a small bug in Cstruct 3.0.0 that initialised the ppx driver too early, which made it fail with some jbuilder-based builds.

I’ve just released Cstruct 3.0.1 that addresses this, and also pulls in ppx_deriving to improve compatibility with the older cstruct.ppx dependency. When enough libraries have moved over to the ppx_cstruct dependency, I will release a new version of Cstruct that removes the older cstruct.ppx entirely.

If you are having any problems with Cstruct 3.0.1 builds, please do get in touch on the issue tracker.

so who is providing the findlib cstruct.lwt library? I thought now
there would be a cstruct (both opam and findlib name, as earlier) and
cstruct-lwt (opam package, does this provide a cstruct.lwt ocamlfind
package? or a cstruct-lwt ocamlfind package)?

There is a cstruct.lwt provided in the cstruct package, but it is just a transitionary one that depends on cstruct-lwt.

So this means that things should “just work” if you add a opam dependency on cstruct-lwt in your package, but you are encouraged to add a constraint on "cstruct" {>="3.0.0"} and use the cstruct-lwt findlib package name in your code as well.

This way we are moving towards removing any differences between the findlib and opam package names for a given module set.

1 Like