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