# Understanding how to import a dune module

**URL:** <https://discuss.ocaml.org/t/understanding-how-to-import-a-dune-module/5660>\
**Category:** Learning\
**Created:** [April 30, 2020, 7:12am UTC](https://discuss.ocaml.org/t/understanding-how-to-import-a-dune-module/5660 "2020-04-30T07:12:48Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![lucaszanella](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lucaszanella/32/2163_2.png) [@lucaszanella](https://discuss.ocaml.org/u/lucaszanella)\
**Post date:** [April 30, 2020, 7:12am UTC](https://discuss.ocaml.org/t/understanding-how-to-import-a-dune-module/5660/1 "2020-04-30T07:12:48Z")

</div>

I’m trying to understand the dune build system and how to ‘import’ modules into OCaml files.

The way I understood, initially, was that in a dune file like this:

```
(library
 (name tcpip_stack_direct)
 (public_name tcpip.stack-direct)
 (libraries logs ipaddr lwt result fmt mirage-time mirage-random
   mirage-protocols mirage-stack mirage-net ethernet))

```

Then if I need to use this I’d do

`Tcpip_stack_direct.Filename1.Make(...)`

where `filename1.ml` is a file in the same folder as that dune project file, and that contains a `Make`.

However if we go into the [dune file of the ipv4 part of the code](https://github.com/mirage/mirage-tcpip/blob/master/src/ipv4/dune):

```
(library
 (name tcpip_ipv4)
 (public_name tcpip.ipv4)
 (libraries logs mirage-protocols ipaddr cstruct rresult tcpip
   tcpip.udp mirage-random mirage-clock randomconv lru)
 (preprocess (pps ppx_cstruct))
 (wrapped false))

```

In order to use it, I should do

`Tcpip_ipv4.Wire.Make(...)`

(as example)

However, [this code](https://github.com/mirage/mirage-vnetif/blob/master/examples/connect/unikernel.ml#L32) uses it like this:

`module I = Ipv4.Make(E)(Clock)(OS.Time)`

where did `Ipv4` come from?

---

<div class="post-metadata">

**Author:** ![CraigFe](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/craigfe/32/1989_2.png) [@CraigFe](https://discuss.ocaml.org/u/CraigFe)\
**Post date:** [April 30, 2020, 7:53am UTC](https://discuss.ocaml.org/t/understanding-how-to-import-a-dune-module/5660/2 "2020-04-30T07:53:15Z")

</div>

Some of the time, your initial understanding will be correct: a file `foo.ml` inside a library with name `lib` will be accessible to your code at `Lib.Foo`. This is because Dune provides a feature called “[wrapping](https://dune.readthedocs.io/en/stable/dune-files.html#library)” which keeps all of the files in a single top-level module named after the library. There are two (?) exceptions to this:

1. If `(wrapped false)` is specified in the library `dune` file (_as is the case here_), this mechanism is disabled. The library may provide more than one top-level module, and they can be named arbitrarily. Sure enough, if we consult the [documentation for `mirage-tcpip`](https://mirage.github.io/mirage-tcpip/tcpip/index.html#library-tcpip.ipv4), we see that the library `tcpip.ipv4` is exporting a whole bunch of top-level modules. At the time when [this code](https://github.com/mirage/mirage-vnetif/blob/master/examples/connect/unikernel.ml#L32) was written, `Ipv4` was one of them (it isn’t any more).

2. If the library contains a file with the same name – i.e. library `lib` contains a file `lib.ml` – this module becomes the wrapper module. Only modules in the signature of `lib.ml` will be accessible outside. This is often used to hide `utils.ml` files and other things that you don’t want to export to users of your library.

In general: use Dune’s wrapping and (2) if you want to hide top-level files or shrink their interface. As you’ve discovered, the alternatives are confusing for end-users and can lead to namespace collisions between different libraries.
