Dune, emacs compilation error, and setting the directory in actions

Hello,

TL/DR: compiling a file using an action in dune seem to run directly in the directory where the dependency lives, breaking error reporting in emacs.

When compiling an OCaml file for a project, dune jumps to the root of the project (with a message Entering directory… and then it silently switches to the build directory to actually compile the file. So to compile bin/main.ml, the compilation command uses that path, as can be seen in the verbose log:

❯ dune exe asm --verbose
Entering directory '/Users/schmitta/work/teaching/asm/skel/cours_2024/asm'
Shared cache: enabled-except-user-rules
Shared cache location: /Users/schmitta/.cache/dune/db
Workspace root: /Users/schmitta/work/teaching/asm/skel/cours_2024/asm
Auto-detected concurrency: 8
Dune context:
 { name = "default"
 ; kind = "default"
 ; profile = Dev
 ; merlin = true
 ; fdo_target_exe = None
 ; build_dir = In_build_dir "default"
 ; instrument_with = []
 }
Running[1]: (cd _build/default && /Users/schmitta/.opam/5.2.0/bin/ocamlopt.opt -w @1..3@5..28@31..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -w -32 -w -37 -w -27 -g -I bin/.main.eobjs/byte -I bin/.main.eobjs/native -I /Users/schmitta/.opam/5.2.0/lib/necroml -intf-suffix .ml -no-alias-deps -opaque -open Dune__exe -o bin/.main.eobjs/native/dune__exe__Main.cmx -c -impl bin/main.ml)
Command [1] exited with code 2:
$ (cd _build/default && /Users/schmitta/.opam/5.2.0/bin/ocamlopt.opt -w @1..3@5..28@31..39@43@46..47@49..57@61..62@67@69-40 -strict-sequence -strict-formats -short-paths -keep-locs -w -32 -w -37 -w -27 -g -I bin/.main.eobjs/byte -I bin/.main.eobjs/native -I /Users/schmitta/.opam/5.2.0/lib/necroml -intf-suffix .ml -no-alias-deps -opaque -open Dune__exe -o bin/.main.eobjs/native/dune__exe__Main.cmx -c -impl bin/main.ml)
File "bin/main.ml", line 171, characters 7-9:
171 |   n1 + n2 foo
             ^^
Error: This expression has type int
       This is not a function; it cannot be applied.

The important part is that the error reported mentions bin/main.ml (as it is the path of the file compiled), so emacs can find it when running dune from it.

This unfortunately does not work when the file is compiled because of an action. I have the following in my dune file:

(rule
  (target arith.ml)
  (deps arith.sk)
  (action (run necroml -o %{target} %{deps})))

When I have an error in bin/arith.sk, it is reported as being in arith.sk directly as it is how the action is run:

❯ dune exe asm --verbose
Entering directory '/Users/schmitta/work/teaching/asm/skel/cours_2024/asm'
Shared cache: enabled-except-user-rules
Shared cache location: /Users/schmitta/.cache/dune/db
Workspace root: /Users/schmitta/work/teaching/asm/skel/cours_2024/asm
Auto-detected concurrency: 8
Dune context:
 { name = "default"
 ; kind = "default"
 ; profile = Dev
 ; merlin = true
 ; fdo_target_exe = None
 ; build_dir = In_build_dir "default"
 ; instrument_with = []
 }
Running[1]: (cd _build/default && /Users/schmitta/.opam/5.2.0/bin/ocamldep.opt -modules -impl bin/main.ml) > _build/default/bin/.main.eobjs/dune__exe__Main.impl.d
Running[2]: (cd _build/default/bin && /Users/schmitta/.opam/5.2.0/bin/necroml -o arith.ml arith.sk)
Command [2] exited with code 1:
$ (cd _build/default/bin && /Users/schmitta/.opam/5.2.0/bin/necroml -o arith.ml arith.sk)
File "arith.sk", line 63, characters 10-11:
Syntax error, unexpected token: a

As the path is missing, emacs cannot directly jump to the error.

Is there a way to tell dune to run the action from the build directory root (here to run necroml -o bin/arith.ml bin/arith.sk)?

Alan

Hello,

I would try writing the action as follows (sorry, cannot test it right now):

(chdir %{workspace_root} (run necroml -o %{target} %{deps}))

Cheers,
Nicolas

1 Like

It works! Thanks a lot.