I want to include a module in an OCaml program where the module is not
directly called by the main (or any other) module, but rather does something during
initialization. How do I do that with dune
? It seems that dune
only includes modules that are explicitly invoked, even when I list
other modules in a modules
stanza.
Example of dune
not doing what I want:
Mod1.ml
:
let mod1 () : unit =
Printf.printf "in mod1\n"
let () =
mod1 ()
Mod2.ml
:
let mod2 () : unit =
Printf.printf "in mod2\n"
let () =
mod2 ()
dune
:
(executable
(name Mod1)
(modules
Mod1
Mod2
)
)
dune-project
(lang dune 3.3)
Compiling and running:
$ dune exec ./Mod1.exe
in mod1
My goal is to also see in mod2
above output.
Example that works with direct ocamlc
invocation:
This is what I would do if not using dune
:
$ ocamlc -o both.exe Mod1.ml Mod2.ml
$ ./both.exe
in mod1
in mod2
Adding an explicit call
If I change Mod1.ml
to:
let mod1 () : unit =
Printf.printf "in mod1\n"
let () =
mod1 ();
Mod2.mod2 () (* added *)
Then both modules get included:
$ dune exec ./Mod1.exe
in mod2
in mod1
in mod2
But my goal is include Mod2
in the executable without explicitly
invoking it from Mod1
.
empty_module_interface_if_absent
does not help
In the documentation for the
executable
stanza, it says:
(empty_module_interface_if_absent)
causes the generation of empty interfaces for every module that does not have an interface file already. Useful when modules are used solely for their side-effects. This field is available since the 3.0 version of the Dune language.
However, this does not help. With dune
file:
(executable
(name Mod1)
(empty_module_interface_if_absent) ; added
(modules
Mod1
Mod2
)
)
and reverting to the original Mod1.ml
, the behavior is the same:
$ dune exec ./Mod1.exe
in mod1
Versions, etc.
$ ocamlc --version
4.14.0
$ dune --version
3.3.1
$ opam --version
2.1.2
$ uname -a
Linux mint201vm 5.4.0-58-generic #64-Ubuntu SMP Wed Dec 9 08:16:25 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux