Using ocamldebug with dune

I have a problem trying to use ocamldebug on programs compiled with dune.
Suppose I have the following dune project:

<root>/src/lib/foo.ml
              /dune
<root>/example/main.ml
              /dune 

where foo.ml defines a library and main.mluses it. For ex (silly example)

(* foo.ml *)
let bar x =
  let y =  x*2  in
  y+1

(* main.ml *)
let _ =
  let r1 = Foo.bar 1 in
  let r2 = Foo.bar 2 in
  print_int (r1+r2)

These files are, classicaly, compiled with the following dune stanzas, resp.:

(library
  (name foo)
  (modules foo ))

and

(executable
 (name main)
 (modes byte)
 (modules main)
 (libraries foo))

To use ocamldebug the resulting program (main.bc), i cd to the corresponding _build subdir:

cd _build/default/example

and run ocamldebug (either from the CL or Emacs) passing main.bc as the program name and no argument (IIUC dune uses the -g ocamlc argument for bytecode pgms).

I would have imagined that setting a breakpoint, say at line 2 of foo.ml would not work because the current directory (_build/default/example) does not contain the corresponding source file. Surprizingly enough, it does:

(ocd) break @ Foo 2
Loading program... done.
Breakpoint 1 at 0:10492: file src/lib/foo.ml, line 2, characters 3-25

It seems that dune has, somehow “under the hood” adjusted the directory variable of ocamldebug. This is confimed by inspecting this variable:

(ocd) directory
Reinitialize directory list ? (y or n) n
Directories:  . /Users/jserot/.opam/4.10.0/lib/ocaml
  /Users/jserot/.opam/4.10.0/.opam-switch/build/ocaml-base-compiler.4.10.0/stdlib
  /Users/jserot/.opam/4.10.0/lib/ocaml
  /Users/jserot/Dev/ml/dune-debug/_build/default
  /Users/jserot/Dev/ml/dune-debug/_build/default/example
  /Users/jserot/Dev/ml/dune-debug/_build/default/example/.main.eobjs/byte
  /Users/jserot/Dev/ml/dune-debug/_build/default/src/lib
  /Users/jserot/Dev/ml/dune-debug/_build/default/src/lib/.foo.objs/byte

So far so good.
The problem is that setting a breakpoint in main.ml does not work:

(ocd) list "main.ml"
1 let _ =
2   let r1 = Foo.bar 1 in
3   let r2 = Foo.bar 2 in
4   print_int (r1+r2)
Position out of range.
(ocd) break @ Main 2
Can't find any event there.

What’s going on here ? The corresponding source file

  • is in directory listed in the ocamldebug directory variable
  • has been compiled with -g

Am i missing sth ?

Hi,

I think you are in the same situation as this dune issue: Byte target can't be debugged with ocamldebug · Issue #4347 · ocaml/dune · GitHub

The solution seems to refer to the main module as @dune__exe__Main and it should be better in dune 3.0.

My quick search for similar issues was apparently too quick :wink:

Setting the breakpoint with

 break @ dune__exe__Main 2

works.

What is specially misleading is that this explicit “demangling” is not required for other modules (such as Foo here)…

Another inconvenient is that breakpoints cannot be set from Emacs this way :frowning:

Thanks for the pointer anyway

2 Likes

Try adding (wrapped_executables false) stanza to the dune-project file. This will allow you to do break @ Main 2

1 Like

Thanks for the tip, @sid !
And sorry for the delay in answering :confused:

1 Like

No problems! BTW did it work for you after using my suggestion?

Yes, like a charm :slight_smile:

1 Like

Well, things seem to be broken again in dune 3.6 :confused: :

After launching ocamldebug :

...
...
(ocd) break @ Main 2
Loading program... done.
No source file for Main.
(ocd) directory
Reinitialize directory list ? (y or n) n
Directories:  . /Users/jserot/.opam/5.0.0/lib/ocaml
  /Users/jserot/.opam/5.0.0/.opam-switch/build/ocaml-base-compiler.5.0.0/stdlib
  /Users/jserot/.opam/5.0.0/lib/ocaml /workspace_root /workspace_root/example
  /workspace_root/example/.main.eobjs/byte /workspace_root/src/lib
  /workspace_root/src/lib/.foo.objs/byte

Seems that the workspace_root variable has not been resolved correctly …
I will file an issue on the dune GH.

Meanwhile, the workaround seems to be get back to dune 2.6