Visualizing dependencies between Ocaml modules

Hi,

I am trying to understand a (more or less large) Ocaml project with lot of files and modules.
I am particularly interested, as a first step, in understanding the interfaces theses modules expose and how theses interfaces are used. I believe an UML component diagram would help with this.

My question is : Is there any tool that can generate the component diagram from Ocaml code?
I have in the past worked with a tool called Moose (http://moosetechnology.org/) that not only generates visualization of OO source code but also allows one to make queries and interact with diagrams to navigate specific aspects of the code. I wonder if such a tool exists for Ocaml (or more broadly, functional) code.

1 Like

I have two answers that are likely not quite what you asked for, but I hope you find them relevant regardless.

At Robur we use opam-graph to generate visualizations for dependencies at opam package level. You can look at an example for this build (the top visualization): https://builds.robur.coop/job/opam-graph/build/f4823163-eaae-4ce1-9bd2-60261f930392

We also use modulectomy (or rather a fork) originally created by @Drup to visualize OCaml binary size as contributed by different OCaml modules. See for example the second visualization here: Job miragevpn-server 2024-09-05 15:27:23Z

2 Likes

I’ll use this opportunity to plug my own tool: GitHub - sim642/odep: Dependency graphs for OCaml modules, libraries and packages. It can do visualizations at various levels: dune modules, findlib libraries and opam packages.
At the end of odep’s README I have a list of various other tools I’ve found and how they differ.

8 Likes

This post really drives the point home that I’m a bad maintainer, all my funky weird experiments end up adopted and maintained by someone else :sweat_smile:

@sim642 Well done, that tool looks amazing !
@reynir Maybe we should do some github shenanigans to make your repository the main one. :slight_smile:

Your tool looks great @sim642 !
I could not find the explanations for the generated graphs. In particular,

  • what does it mean when a node is grey? (is a node grey if and only if it is in a “foreign” package ?)
  • what does it mean when a node has lozenge shape ? (is a node a lozenge if and only if it is an executable ?)
  • what does it mean when a node has rectangle or ellipse shape ?

Also, is it correct that the graph only shows the “transitive core” of the dependency relation (that is, if A depends on B and also explicitly on C, and B depends on C, then the arrow from A to C is not displayed) ? Is there (a project of) an option to display all explicit dependencies, even the ones deducible by transitivity ? (note that this is included, but need not be, the transitive closure of the above)

Indeed, I haven’t provided documentation about the output, but here are the answers to your questions:

  1. Gray ellipses are (findlib) libraries outside the current dune project (if using the dune mode).
  2. White diamonds are dune executables.
  3. White ellipses are dune libraries in the current dune project.
  4. White rectangles can be one of two things:
    1. (opam) packages if they include a version number (in the findlib graph, they surround libraries).
    2. (OCaml) modules otherwise (in the dune graph, they are surrounded by a rectangle that also indicates the cluster corresponding to one library).
  5. Yes, by default it computes the transitive reduction to keep the graphs easier to look at (and faster to render by Graphviz). Depending on the graph, you can use --tred-modules=false or --tred-libraries=false to disable the reduction.
1 Like