Actions¶
(action ...)
fields describe user actions.
User actions are always run from the same subdirectory of the current build
context as the dune
file they are defined in, so for instance, an action defined
in src/foo/dune
will be run from $build/<context>/src/foo
.
The argument of (action ...)
fields is a small DSL that’s interpreted by
Dune directly and doesn’t require an external shell. All atoms in the DSL
support Variables. Moreover, you don’t need to specify
dependencies explicitly for the special %{<kind>:...}
forms; these are
recognized and automatically handled by Dune.
The DSL is currently quite limited, so if you want to do something complicated, it’s recommended to write a small OCaml program and use the DSL to invoke it. You can use shexp to write portable scripts or Configurator for configuration related tasks. You can also use (Experimental) Dune Action Plugin to express program dependencies directly in the source code.
The following constructions are available:
Note: expansion of the special %{<kind>:...}
is done relative to the current
working directory of the DSL being executed. So for instance, if you
have this action in a src/foo/dune
:
(action (chdir ../../.. (echo %{dep:dune})))
Then %{dep:dune}
will expand to src/foo/dune
. When you run various
tools, they often use the filename given on the command line in error messages.
As a result, if you execute the command from the original directory, it will
only see the basename.
To understand why this is important, let’s consider this dune
file living in
src/foo
:
(rule
(target blah.ml)
(deps blah.mll)
(action
(run ocamllex -o %{target} %{deps})))
Here the command that will be executed is:
$ ocamllex -o blah.ml blah.mll
And it will be executed in _build/<context>/src/foo
. As a result, if there
is an error in the generated blah.ml
file, it will be reported as:
File "blah.ml", line 42, characters 5-10:
Error: ...
Which can be a problem, as your editor might think that blah.ml
is at the root
of your project. Instead, this is a better way to write it:
(rule
(target blah.ml)
(deps blah.mll)
(action
(chdir %{workspace_root}
(run ocamllex -o %{target} %{deps}))))