It's actually a bit strange to call them "nested libraries" since you want to call them with Lib.Utils.Whatever
. Utils
, here, is a sub-module of Lib
. Here's what I was able to do if it can help you:
.
├── bin
│ ├── cli.ml
│ └── dune
├── dune-project
├── lib
│ ├── dune
│ ├── lib.ml
│ ├── suba
│ │ └── suba.ml
│ └── subb
│ └── subb.ml
With
bin/cli.ml
let () =
Lib.Suba.a ();
Lib.Subb.b ()
bin/dune
(executable
(name cli)
(libraries lib)
)
lib/dune
(include_subdirs unqualified)
(library
(name lib)
(modules suba subb)
)
(If you include your modules like this, you'll have to use them with these exact names, another way of gaining control is to add the following file and remove the (modules suba subb)
line:
lib/lib.ml
(* here you can give the name you want -- say A -- and use it in bin with Lib.A *)
module Suba = Suba
module Subb = Subb
(to summarise:
- either your
dune
file is containing (modules suba subb)
- if sub-directory is containing multiple files, you need to put all the files you're using inside your
(modules ...)
stanza or the compiler won't be able to use them
- or a
lib.ml
file where each module you want to export should be included with module MyName = AModule
(and only the ones you want to export)
- with this solution, the modules you don't want to export don't need to be explicitly included in the
lib.ml
file, the compiler will use them if needed
)
sub{a|b}/{a|b}.ml
let {a|b} () = Format.eprintf "{A|B}@."
suba.ml
and subb.ml
are used as sub-modules of lib
and can be used with Lib.Suba.a()
as you can see in cli.ml
Notice that this forbids you from giving the exact same name to two files since the directories will all be flatten in the parent directory so you can't have something like:
.
├── bin
│ ├── cli.ml
│ └── dune
├── dune-project
├── lib
│ ├── dune
│ ├── lib.ml
│ ├── suba
│ │ └── lib.ml
│ └── subb
│ └── lib.ml
because (include_subdirs unqualified)
will make it look like
.
├── bin
│ ├── cli.ml
│ └── dune
├── dune-project
├── lib
│ ├── dune
│ ├── lib.ml
│ ├── lib.ml
| └── lib.ml
and dune
won't be able to know which lib.ml
file to use.
[EDIT] If you want one directory per library you just have to remove the dune
file at the root of lib
and create one for each subdirectories:
.
├── bin
│ ├── cli.ml
│ └── dune
├── dune-project
├── lib
│ ├── suba
│ │ ├── dune
│ │ └── suba.ml
│ └── subb
│ ├── dune
│ └── subb.ml
The only changes are:
bin/cli.ml
let () =
Suba.a (); (* no more Lib.(...) *)
Subb.b ()
bin/dune
(executable
(name cli)
(libraries suba subb)
)
lib/dune
has been removed
lib/sub{a|b}/dune
(library
(name sub{a|b})
)
And in that case, multiple files inside different directories can have the same name.
Lib
I have made multipleMyproject_<whatever>
libs in the root of my project dir. That way I can live with the single level of nesting and the naming is not too bad. – Taurine