# Raw ocamlopt commands to create a cmxs file

**URL:** <https://discuss.ocaml.org/t/raw-ocamlopt-commands-to-create-a-cmxs-file/10883>\
**Category:** Learning\
**Tags:** dynlink\
**Created:** [November 30, 2022, 10:20am UTC](https://discuss.ocaml.org/t/raw-ocamlopt-commands-to-create-a-cmxs-file/10883 "2022-11-30T10:20:06Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![rwmjones](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/rwmjones/32/818_2.png) [@rwmjones](https://discuss.ocaml.org/u/rwmjones)\
**Post date:** [November 30, 2022, 10:20am UTC](https://discuss.ocaml.org/t/raw-ocamlopt-commands-to-create-a-cmxs-file/10883/1 "2022-11-30T10:20:06Z")

</div>

I was trying to demonstrate cmxs and native dynamic loading to someone but I cannot come up with the raw commands needed to make a simple example, and I can’t find anyone who has written them down either. NB I do not want to know how to do this in dune or another build system, just the raw ocaml\* commands.

Here’s what I have so far:

main.ml:

```auto
open Printf

let f () =
  printf "this is Main.f ()\n%!"

let () =
  printf "this is Main toplevel\n%!";
  Dynlink.loadfile "lib.cmxs"

```

lib.ml:

```auto
open Printf

let () =
  printf "this is Lib toplevel\n%!";
  Main.f ()

```

Commands:

```auto
ocamlopt -linkall -shared dynlink.cmxa main.ml -o main
ocamlopt -shared lib.ml -o lib.cmxs

```

Running `./main` core dumps!

---

<div class="post-metadata">

**Author:** ![vlaviron](https://avatars.discourse-cdn.com/v4/letter/v/ec9cab/32.png) [@vlaviron](https://discuss.ocaml.org/u/vlaviron)\
**Post date:** [November 30, 2022, 10:39am UTC](https://discuss.ocaml.org/t/raw-ocamlopt-commands-to-create-a-cmxs-file/10883/2 "2022-11-30T10:39:49Z")

</div>

> [@rwmjones](#):
>
> Commands:
> 
> ```auto
> ocamlopt -linkall -shared dynlink.cmxa main.ml -o main
> ocamlopt -shared lib.ml -o lib.cmxs
> 
> ```
> 
> Running `./main` core dumps!

The `-shared` flag is only for generating `.cmxs` files, so your first link command should not include it. If you fix that, I believe that your commands should work.

However, there is a big issue in your code itself: it’s forbidden to refer to a module that has not been initialised completely. With normal linking this is checked by the compiler, but with Dynlink it’s more complicated, and here your `Lib` module refers to `Main`, but it’s loaded before `Main` is fully initialised.  
The usual setup for small dynlink programs is to have three files:

- a common library, which would contain `f` in your example, and is compiled normally (in your example you only need a single file, so you don’t even need to bother with a `.cmxa`, just producing the `.cmx` will work)
- a plugin file that depends on the library and is compiled with `-shared`
- a main file that does the dynlinking (and depends on the library). It’s not strictly necessary to link it with `-linkall`, but it’s safer as it ensures that modules from the linked libraries (typically the standard library) are present even if the main module doesn’t need them, in case the plugins do need them.

I hope this helps.

---

<div class="post-metadata">

**Author:** ![vlaviron](https://avatars.discourse-cdn.com/v4/letter/v/ec9cab/32.png) [@vlaviron](https://discuss.ocaml.org/u/vlaviron)\
**Post date:** [November 30, 2022, 10:43am UTC](https://discuss.ocaml.org/t/raw-ocamlopt-commands-to-create-a-cmxs-file/10883/3 "2022-11-30T10:43:13Z")

</div>

I forgot to add the typical commands for the three file setup:

```nohighlight
ocamlopt -linkall dynlink.cmxa common.ml main.ml -o main
ocamlopt -shared lib.ml -o lib.cmxs

```

Where `common.ml` contains the functions that `lib.ml` needs to call.

---

<div class="post-metadata">

**Author:** ![rwmjones](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/rwmjones/32/818_2.png) [@rwmjones](https://discuss.ocaml.org/u/rwmjones)\
**Post date:** [November 30, 2022, 10:46am UTC](https://discuss.ocaml.org/t/raw-ocamlopt-commands-to-create-a-cmxs-file/10883/4 "2022-11-30T10:46:51Z")

</div>

That would explain my next question about what `Dynlink.Uninitialized_global "Main"` means.

Is it possible at all to call functions in the main program from a library which is loaded at runtime? That’s actually what I’m trying to demonstrate here.

---

<div class="post-metadata">

**Author:** ![rwmjones](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/rwmjones/32/818_2.png) [@rwmjones](https://discuss.ocaml.org/u/rwmjones)\
**Post date:** [November 30, 2022, 10:49am UTC](https://discuss.ocaml.org/t/raw-ocamlopt-commands-to-create-a-cmxs-file/10883/5 "2022-11-30T10:49:01Z")

</div>

To answer my own question, yes it is. We just have to split up main into two parts:

main.ml:

```auto
open Printf

let f () =
  printf "this is Main.f ()\n%!"

```

loader.ml

```auto
open Printf

let () =
  printf "this is Loader toplevel\n%!";
  Dynlink.loadfile "lib.cmxs"

```

(lib.ml as above)

```auto
$ ./main 
this is Loader toplevel
this is Lib toplevel
this is Main.f ()

```
