Dune question: two executables sharing a module

I want to create two executable files that share a single module arith_inst. Here is what I tried to do in my dune file:

(executable
  (public_name arith)
  (name arith_interp)
  (modules arith arith_inst arith_interp)
  (modes byte)
  (libraries necromonads))

(executable
  (public_name arith_div)
  (name arith_div_interp)
  (modules arith_div arith_inst arith_div_interp)
  (modes byte)
  (libraries necromonads))

This fails because I am including the same module in two executable (which is exactly what I want to do). If I remove the modules stanza, I get an error about arith_interp being used in both executable (which is false, only the first one needs it).

What is the dune way to have a project with several executable files sharing some modules?

1 Like

Yes, you can use the (executables ...) stanza Stanza Reference — dune documentation. Dune automatically knows which modules to link to each executable by using ocamldep.

Cheers,
Nicolas

2 Likes

You could also make this module into a library that both executables would depend on

Thank you for the suggestion. Here is what I ended up doing:

(executables
  (public_names arith arith_div)
  (names arith_interp arith_div_interp)
  (modes byte)
  (libraries necromonads))

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

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

Yes, but it’s one more thing to learn :wink: I’ll have to tackle it, eventually.

Ya, i ran into this learning too. Jarring at first, but it’s actually fast and simple. “dune init” your lib into a new folder and that’s all there is to it. Not bad! It pays dividends for testing too. Recommend to give it a try sooner than later if the project is more than a toy

(library 
  (public_name arith.arith_inst)
  (name arith_inst)
  (modules arith_inst))

(executable
  (public_name arith)
  (name arith_interp)
  (modules arith arith_interp)
  (modes byte)
  (libraries necromonads arith_inst))

(executable
  (public_name arith_div)
  (name arith_div_interp)
  (modules arith_div arith_div_interp)
  (modes byte)
  (libraries necromonads arith_inst))

I think this should do, providing your package is named arith.

Thanks a lot, this is most useful!

1 Like

A common pattern I use for including “executable” sub-projects while building a project is using the module exclusion feature:

(library (name program_generator)
 (modules (:standard \ "main"))
 (libraries lang containers)
)

(executable (name main)
 (modules main)
 (libraries program_generator containers))

In this way, I can add more modules to my main library without having to update the module stanza each time.

1 Like