# Dynamically link native code into utop?

**URL:** <https://discuss.ocaml.org/t/dynamically-link-native-code-into-utop/793>\
**Category:** Ecosystem\
**Tags:** utop, build\
**Created:** [September 1, 2017, 4:45am UTC](https://discuss.ocaml.org/t/dynamically-link-native-code-into-utop/793 "2017-09-01T04:45:29Z")\
**Posts on this page:** 1\
**Showing post:** 13

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [September 2, 2017, 4:12pm UTC](https://discuss.ocaml.org/t/dynamically-link-native-code-into-utop/793/13 "2017-09-02T16:12:34Z")

</div>

I spent sometime today to see where `ocamlnat` stands. I managed to get it work both on linux (via docker) and on macos.

You can try it by using [this](https://github.com/dbuenzli/opam-repo-ocamlnat) opam v2 repo (see the `README` for instructions).

With pure ocaml code it seems to work fine here’s a sample interaction using `gg`:

```ocaml
bash-4.3$ rlwrap ocamlnat -noinit 
        OCaml version 4.05.0 - native toplevel

# #directory "/home/opam/.opam/4.05.0+ocamlnat/lib/gg";;
# #load "bigarray.cmxs";;
# #load "gg.cmxs";;
# #install_printer Gg.V2.pp;;
# open Gg;;
# V2.(ox + oy);;
- : Gg.v2 = (1 1)

```

A few notes:

1. `ocamlnat` is invoked with `-noinit` this is to prevent to read your `.ocamlinit` which likely `#use 'topfind'` which fails (more on that below).
2. As a result include directories and dependencies are loaded manually. Note: it’s the `cmxs` you need to load. You’ll need to make sure the libraries you use properly builds them.
3. Toplevel support libraries that install printers like `gg_top.cmxs` fail because they try to [use](https://github.com/dbuenzli/gg/blob/a1cd31593c744c6a2473e81a4fbc2b4b1956273f/src/gg_top.ml#L7) the `Toploop` module rather than `Opttoploop`.
4. I tried with a library with simple C bindings (`mtime`), it works out of the box on linux but on macos it needs a few adjustements on the cli to find both the static C library (?) and the dynamic one. See the interaction at the end of the message.

1 and 3 are due to the infortunate API design of the byte and native toploop API that splits the module names into `Toploop` and `Opttoploop` rather than expose the same names and treat the problem as a library variant. This implies that any consumer of the API has to conditionalize itself which doesn’t scale, this problem is documented in [MPR 7589](https://caml.inria.fr/mantis/view.php?id=7589).

For a library with C bindings on macos the following env var had to be adjusted (and there are weird warnings I didn’t investigate exactly where they come from, I suspect a configuration thing that is no longer relevant in `ocaml` itself):

```ocaml
> DYLD_LIBRARY_PATH=$(opam var stublibs) LIBRARY_PATH=$(opam var mtime:lib)/os rlwrap ocamlnat -noinit
        OCaml version 4.05.0 - native toplevel

# #directory "/Users/dbuenzli/.opam/4.05.0+ocamlnat/lib/mtime";;
# #directory "/Users/dbuenzli/.opam/4.05.0+ocamlnat/lib/mtime/os";;
# #load "mtime.cmxs";;
# #use "mtime_top_init.ml";;
ld: warning: directory not found for option '-L/Users/dbuenzli/.opam/4.05.0+ocamlnat/lib/ocaml/camlp4'
ld: warning: directory not found for option '-L/Users/dbuenzli/.opam/4.05.0+ocamlnat/lib/ocaml/camlp4'
ld: warning: directory not found for option '-L/Users/dbuenzli/.opam/4.05.0+ocamlnat/lib/ocaml/camlp4'
ld: warning: directory not found for option '-L/Users/dbuenzli/.opam/4.05.0+ocamlnat/lib/ocaml/camlp4'
# #load "mtime_clock.cmxs";;
# Mtime_clock.now ();;
ld: warning: directory not found for option '-L/Users/dbuenzli/.opam/4.05.0+ocamlnat/lib/ocaml/camlp4'
- : Mtime.t = 92862271359034ns

```

---

_[View the full topic](https://discuss.ocaml.org/t/dynamically-link-native-code-into-utop/793)._
