Dune build -w; dune utop; edit - recompile - reload

I have a simple OCaml project.

dune build -w works
dune utop works

I can’t use both at the same time.

I’m wondering if there is a way to have the following work flow:

  1. I’m editing in VIM

  2. I have a dune build -w running, which recompiles on source change.

  3. (I don’t have this part yet). I have dune utop running, then every time that dune build -w succeeds, it causes the dune utop to reload the latest modules. (If I end up losing some state, that’s fine ,I’ll develop techniques to work around it.)

So the overall work flow is:

  1. I write some code in vim, hit :w

  2. dune build -w tries to recompile; on error, it displays error

  3. if step 2 succeeds, dune utop reloads the new module into the repl

I wanted to do this a few days ago, you may find a few useful ideas here: Can I "reset" my REPL? - #3 by benjamin-thomas

Since then, I found another neat option which is good for little examples.

It’s document here: Toplevel Integration — Dune documentation

And not very obvious from an outsider’s perspective. In short:

  1. you write an .ocamlinit file in one of your project’s sub-directories.
  2. You add only this line. #use_output "dune ocaml top";;
  3. Now you can execute utop from this sub-directory (just utop, no dune prefix)

On entering utop, your module will be compiled “automagically”, no need for dune build.

Just ctrl+d out of utop then re-enter and you’ll have you’re latest module available, newly compiled (the recompilation is very fast).

I haven’t played with this technique extensively yet but it feels great for little examples and code exploration.

Sorry to be pedantic, I’m new to the OCaml toolchain and want to make sure I understand this correctly.

Previously, I was running with “dune build -w”, which has the benefit that on every Vim save, it auto recompiles.

Does the approach you are suggesting eliminate this? I.e. I need to manually trigger recompile by killing utop and rerunning it ?

One situation where this is inconvenient is that if I am doing a refactoring and there are many errors, with the “dune build-w” approach, I fix an error, I get next error; whereas with this approach, I have to constantly re-trigger the compile myself.

Sure. I’m new to OCaml myself so take what I’m saying with a grain of salt :slight_smile:

What you can do:

  • clone this repo
  • cd lib/chapter16/rev/
    • notice the hidden .ocamlinit file
    • rm ./lib/rev_lib.mli # remove the interface to make the whole module “open” to utop.
    • editor ./lib/rev_lib.ml
      • add this line: let hello = 1 [@@warning "-32"]
  • launch utop
    • you can now access this new function: Rev_lib.hello;;

You will see that entering utop will actually generate a _build folder at the project’s root.

Each time you re-enter utop, the files in lib/chapter16/rev/ get rebuilt.

So you can continuously exit and re-enter your REPL that way: while true;do utop;sleep 1;done (press ctrl+d to exit and recompile)

Don’t ask me how this works though :smiley: , it’s…

Shia Labeouf Magic GIF