Right now, I write my .ml files, open utop and use #show to see the inferred interface and copy-paste that into a .mli file, which I then edit to remove private interfaces. Is there a more automated way to show the generated interface?
I’m sure this has been asked a thousand times, but I couldn’t find it. Thanks.
I have a follow-up question: I more or less managed to do this with dune by going to the _build directory with ocamlc -i -I . file.ml. Is there a better way to generate the .mli with dune?
As @gadmm says, it’s what the -i option is intended for. However in practice, the actual command line can be very complicated due to various dependencies.
What I’ve been using is the cmi file produced by building the ml file normally, and then generate an mli file from that. It’s a simple translation from a binary format to a text format and it doesn’t need to know about dependencies. The tool for this is cmitomli, available in opam. It goes like this:
It provides a command to generate a .mli file from the currently-open .ml file. It has saved me a tremendous amount of hassle. Note that the command is called “create interface file” if you’re looking for it in the Ctrl-Shift-P popup command menu.
Yeah, I plan on giving that newer plugin a shot after work on my current project is ~complete. Nothing worse than environment upgrades in the middle of things and the potential of breakage that goes along.
This looks great, both cmitomli and ocaml-print-intf seem pretty easy to use in combination with dune. The latter also proposes the following command: dune exec -- ocaml-print-intf file.ml. Case solved. Thanks!
My main.ml does use modules: my dune file reads (executable (name main) (modules main util) (libraries)).
I’m at the same time sorry to spam this thread (and a few others recently) and desperate that nothing seems to work as intended. (Please tell me if another place is more appropriate for these basic questions.)
The feature is called ‘Switch implementation/interface’. The naming is slightly misleading, it will generate a new file containing the interface for you if it doesn’t already exist.
If your file is an executable, what do you want to use the .mli for? In fact, dune 3 started generating empty .mli for executables to trigger the OCaml compiler to emit “unused identifier” warnings.
I tried the proposed command in order to see if and how dune exec -- ocaml-print-intf ***.ml works.
Anticipating that some may question the question instead of answering it, I wrote above that my program does use modules (another file named util.ml in the same folder), but when I do dune exec -- ocaml-print-intf util.ml, I get the same error. (Actually, I was hoping that a command would generate all mli’s at once.)
Or was your remark a way to tell me that my dune file above is not correct ?
My questions may be too basic for this forum. Should I post on stackoverflow or another site instead ?
First, I’m presuming that this isn’t a common problem you want to solve all the time – just from time-to-time. Second, I’m not a dune user (I prefer Makefiles) but OTOH, I often have to reverse-engineer dune arcana when writing unit-tests that need to work the same with standard PPX rewriters, and the ones I write using Camlp5. So I have had the problem many times, of figuring out how some particular output file (cmo, cmi, whatever) got created.
Typically, I look in the “log” file and find the output filename, and it’ll appear first on the line that creates it. Then I can cut-and-paste that line and rerun it, or modify (e.g. remove the “-o blabla.cmo” and add a “-i” in order to get the .mli output.
Hope this helps. I recognize that this isn’t some fancy automated solution. OTOH, it’s pretty simple. An equivalent method works with Makefiles.