# Dynlink with static binary

**URL:** <https://discuss.ocaml.org/t/dynlink-with-static-binary/8249>\
**Category:** Learning\
**Tags:** dynlink, static-link, build, dune\
**Created:** [August 4, 2021, 10:57am UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249 "2021-08-04T10:57:12Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![abate](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/abate/32/3126_2.png) [@abate](https://discuss.ocaml.org/u/abate)\
**Post date:** [August 4, 2021, 10:57am UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/1 "2021-08-04T10:57:12Z")

</div>

hi all. I want to use dynlink with a statically linked binary.

my dune file looks like

```auto
(env (static (flags (:standard -ccopt -static )))) 

(executable (name main)  
(libraries dynlink)  
;(link_flags -linkall) I can add this, but the problem is the same
 (modules main) ) 

(executable (name dyn)   
(modules dyn)  
 (link_flags -linkall) 
  (modes (native plugin)) 
  (embed_in_plugin_libraries stdlib) )

```

and this is the error I get :

```auto
dune build main.exe --profile static ; \
	dune build dyn.cmxs ; \
	cd _build/default ; \
	./main.exe ; \
	ldd main.exe || true ; \
	ocamlobjinfo dyn.cmxs ; \
	cd -
    ocamlopt main.exe
/usr/bin/ld: /home/abate/Projects/repos/tezos/tezos_master/_opam/lib/ocaml/libasmrun.a(unix.n.o): in function `caml_dlopen':
/home/abate/Projects/repos/tezos/tezos_master/_opam/.opam-switch/build/ocaml-base-compiler.4.12.0/runtime/unix.c:271: warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"/home/abate/Projects/repos/tezos/test-dynlink/_build/default/dyn.cmxs: undefined symbol: camlStdlib __format__ printf_1230\")")
	not a dynamic executable
File dyn.cmxs
Name: Dune __exe__ Dyn
CRC of implementation: 3f141250177d7b60b987e7f5d99446f3
Globals defined:
	Dune __exe__ Dyn
Interfaces imported:
	82dadcd908dde621b8842c96ba644dc6	Stdlib__uchar
	185075aa99b059ad4cae15cb411fcc0c	Stdlib__seq
	e8696010fc66d4ce9a3bc3f311f6ea20	Stdlib__format
	9eaf2b1cd70e33601c152d1ce1bb8be9	Stdlib__buffer
	4b04b4eda19aa722df365141895fb347	Stdlib
	9fc7c355dbbc8f9dae052e4c2ee0e13d	Dune __exe__ Dyn
	b6c6694955e10001aed267571104a961	CamlinternalFormatBasics
Implementations imported:
	41296ac99a85560c95c2f9d56ed27a7d	Stdlib__format

```

there are two problems.

- first the warning. Does this mean if I compile the statically linked library on alpine (musl ) i cannot use any dyn linked modules compiled on glibc : this is just a confirmation, then answer seems clear.

- second: how do I solve this linking problem with `format` ?

this is a small repo to explain the problem : [Files · master · pietro / test-dynlink · GitLab](https://gitlab.com/abate/test-dynlink/-/tree/master)

`make dyn` compiles the dyn linked library ( no errors )  
`make` compiles the statically linked library (errors above)

What Am I doing wrong ?

many thanks,  
pietro

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [August 4, 2021, 12:16pm UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/2 "2021-08-04T12:16:38Z")

</div>

I’m not sure I follow, but off the bat it seems strange to try to embed the `stdlib` into the plugin. I would try removing `(embed_in_plugin_libraries ...)` and `(link_flags -linkall)` in the rule for the plugin and add back `(link_flags -linkall)` to the rule for `main.exe`.

Cheers,  
Nicolas

---

<div class="post-metadata">

**Author:** ![abate](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/abate/32/3126_2.png) [@abate](https://discuss.ocaml.org/u/abate)\
**Post date:** [August 4, 2021, 1:15pm UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/3 "2021-08-04T13:15:01Z")

</div>

I tried with this dune file as suggested ( that was also my first try ):

```auto
(env
 (static (flags (:standard -ccopt -static ))))

(executable
 (name main)
 (libraries dynlink)
 (link_flags -linkall)
 (modules main)
 )

(executable
  (name dyn)
  (modules dyn)
  ;(link_flags -linkall)
  (modes (native plugin))
  ;(embed_in_plugin_libraries stdlib)
)

```

but get exactly the same problem.

---

<div class="post-metadata">

**Author:** ![emillon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emillon/32/1206_2.png) [@emillon](https://discuss.ocaml.org/u/emillon)\
**Post date:** [August 4, 2021, 2:32pm UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/4 "2021-08-04T14:32:17Z")

</div>

I think the env stanza will also apply to `dyn`, so it might create an unusable `cmxs` file (not sure about the details).

- do you see `-static` on the command line of the command that builds `dyn.cmxs`? (in `_build/log`)
- What happens if you set `(flags)` on just `main`?

---

<div class="post-metadata">

**Author:** ![abate](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/abate/32/3126_2.png) [@abate](https://discuss.ocaml.org/u/abate)\
**Post date:** [August 4, 2021, 2:39pm UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/5 "2021-08-04T14:39:34Z")

</div>

I don’t think the static profile is used in the `dyn`modules  
I get the same problem if I specify explicitely two different profiles  
`dune build main.exe --profile static` and `dune build dyn.cmxs --profile dev" .

Here in `dev` is the default profile.

this is the log:

```auto
- _build/default/dyn.cmxs
Running[2]: (cd _build/default && /home/abate/_opam/bin/ocamlc.opt -w @1..3@5..28@30..39@43@46..47@49..57@61..62-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -bin-annot -I .dyn.eobjs/byte -no-alias-deps -opaque -o .dyn.eobjs/byte/dune __exe__ Dyn.cmo -c -impl dyn.ml)
Running[3]: (cd _build/default && /home/abate/_opam/bin/ocamlopt.opt -w @1..3@5..28@30..39@43@46..47@49..57@61..62-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -I .dyn.eobjs/byte -I .dyn.eobjs/native -intf-suffix .ml -no-alias-deps -opaque -o .dyn.eobjs/native/dune __exe__ Dyn.cmx -c -impl dyn.ml)
Running[4]: (cd _build/default && /home/abate/_opam/bin/ocamlopt.opt -w @1..3@5..28@30..39@43@46..47@49..57@61..62-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -o dyn.cmxs -shared .dyn.eobjs/native/dune __exe__ Dyn.cmx)
error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"/home/test-dynlink/_build/default/dyn.cmxs: undefined symbol: camlStdlib __format__ printf_1230\")")

```

For `main.exe` I get the `--ccopt -static` as expected :

```auto
Running[3]: (cd _build/default && /home/abate/_opam/bin/ocamlopt.opt -w -40 -ccopt -static -g -I .main.eobjs/byte -I .main.eobjs/native -intf-suffix .ml -no-alias-deps -o .main.eobjs/native/dune __exe__ Main.cmx -c -impl main.ml)

```

and it looks ok to me

I’ve added `(flags :standard)` and same error …

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [August 4, 2021, 3:00pm UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/6 "2021-08-04T15:00:23Z")

</div>

Building static binaries is very system-specific and I wouldn’t be surprised if by doing so the final executable `main.exe` ended up stripped (no symbol table) which would make using `Dynlink` impossible.

You can check this by running `nm -g main.exe` (NB this is from memory) and check if the symbol `camlStdlib __format__ printf_1230` is listed.

Cheers,  
Nicolas

---

<div class="post-metadata">

**Author:** ![abate](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/abate/32/3126_2.png) [@abate](https://discuss.ocaml.org/u/abate)\
**Post date:** [August 4, 2021, 3:09pm UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/7 "2021-08-04T15:09:44Z")

</div>

```auto
$ nm -g _build/default/main.exe | grep camlStdlib __format__ printf_1230
00000000004b1f00 T camlStdlib __format__ printf_1230

```

so it’s seems the symbol is there …

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [August 4, 2021, 3:17pm UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/8 "2021-08-04T15:17:57Z")

</div>

> [@nojb](#):
>
> I’m not sure I follow, but off the bat it seems strange to try to embed the `stdlib` into the plugin. I would try removing `(embed_in_plugin_libraries ...)` and `(link_flags -linkall)` in the rule for the plugin and add back `(link_flags -linkall)` to the rule for `main.exe` .

I just tried this in a standard Ubuntu install and it works. The issue you are having must be related to your use of musl. Linking objects built with different libc’s sure sounds like a long shot.

Cheers,  
Nicolas

---

<div class="post-metadata">

**Author:** ![abate](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/abate/32/3126_2.png) [@abate](https://discuss.ocaml.org/u/abate)\
**Post date:** [August 4, 2021, 3:20pm UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/9 "2021-08-04T15:20:51Z")

</div>

you mean you tried my example and it worked (thank you for trying !) ?

I’m doing most of my experiments on debian. On my box I expect everything to work fine… the musl problem should not be related.

I’ll be baffled if this is a setup problem 😳

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [August 4, 2021, 3:48pm UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/10 "2021-08-04T15:48:02Z")

</div>

> [@abate](#):
>
> you mean you tried my example and it worked (thank you for trying !) ?

Sorry, I had tried the wrong thing. I think that the problem is what I mentioned earlier, namely that by building a static executable the binary no longer has a “dynamic symbol table” (this is the table of symbols visible to shared objects which want to link against the binary). To check this, try `readelf --dyn-syms main.exe`. I _think_ you will find it empty.

Cheers,  
Nicolas

---

<div class="post-metadata">

**Author:** ![emillon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emillon/32/1206_2.png) [@emillon](https://discuss.ocaml.org/u/emillon)\
**Post date:** [August 4, 2021, 4:07pm UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/11 "2021-08-04T16:07:33Z")

</div>

> [@abate](#):
>
> ```auto
> (link_flags -linkall)
> 
> ```

This resets the flags because `:standard` is not there - does `(link_flags :standard -linkall)` change what’s happening?

---

<div class="post-metadata">

**Author:** ![abate](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/abate/32/3126_2.png) [@abate](https://discuss.ocaml.org/u/abate)\
**Post date:** [August 5, 2021, 6:38am UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/12 "2021-08-05T06:38:20Z")

</div>

@emilion : no changes …

---

<div class="post-metadata">

**Author:** ![abate](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/abate/32/3126_2.png) [@abate](https://discuss.ocaml.org/u/abate)\
**Post date:** [August 5, 2021, 6:40am UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/13 "2021-08-05T06:40:51Z")

</div>

> [@nojb](#):
>
> To check this, try `readelf --dyn-syms main.exe` . I _think_ you will find it empty.

it’s indeed empty. So if I manage to populate this table, then symbol problem should disappear ? At the same time I’m not sure if `-ccopt -static` is compatible with the idea of having dynamic symbols…

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [August 5, 2021, 7:47am UTC](https://discuss.ocaml.org/t/dynlink-with-static-binary/8249/14 "2021-08-05T07:47:28Z")

</div>

> [@abate](#):
>
> At the same time I’m not sure if `-ccopt -static` is compatible with the idea of having dynamic symbols…

That’s my uneducated guess as well.

Cheers,  
Nicolas
