Statically Link

Does OCaml provide a seamless way for building statically linked binaries (like Go)?


Yes. If your platform allows (e.g. you can’t on macOS), it should only be a matter of passing -ccopt -static in your final link step in ocamlopt.

> echo 'let () = print_endline "hello warld"' > 
> ocamlopt -ccopt -static

Great! And the built-in HTTP server and concurrency stuff would be there (inside the statically linked binary) too?

There’s an article by @rgrinberg that utilizes Docker to achieve it:

It mentions how to workaround glibc’s limitation by using musl (from Alpine) as alternative C libraries.


All paths lead to docker! :slight_smile:

I wish that was not the case.


I think the glibc issue also appears on Go, though (cf. this article, the author also gave a nod to Docker).

One thing I want OCaml to have from Go is the cross-compilation story :smiley: hopefully dune can solve that.

1 Like

Note that docker is in no way essential here. If you can spit up an alpine image with opam on it any other way, that should work just as well. I just used docker because it was the most convenient way to do it.

Docker is not available in this area (Iran).

I’m keeping an eye on native languages. Saw ReasonML and I thought maybe OCaml is finally going to put on a convenient show.

Other languages in this family are not ready for the show (Crystal, Pony) and Rust tries to solve other problems (mostly system programming or replacing C++ for desktop apps/games). Haskell is a programming language for hosting academic ideas (one might say otherwise but that’s my opinion).

OCaml itself seem to be stable. And if proper tooling is provided (things like automatic code formatting like gofmt - Elixir has this now - and ease of deployment like Go - I do not mean docker) OCaml can take off.

Especially if something as pragmatic and as well maintained as Phoenix pops up.

1 Like

Yes, the MirageOS project uses this to an extreme and compile down to statically linked ELF binaries, which are virtual machine images (Xen, KVM, …) including the entire stack (the Unix backend atm links against libc and libm, though). :slight_smile:

1 Like

No one seem to have mentioned it before, so just to make it extra clear: OCaml code is always statically linked by default. If you want to link OCaml code dynamically, you need to be explicit about it. All the techniques presented here are used to link the C stuff in.

So the HTTP server and the concurrency stuff will always be in there. :slight_smile:


For formatting, there’s ocamlformat in development, and refmt (from Reason) to some degree can output OCaml (although last time I checked the output is not good enough yet). In other, less-opinionated cases, ocp-indent works great.

For deployment, I think compilations is not a problem (as said in the article, static linking problems boil down to finding statically linkable C libraries). Cross-compilation is also a thing, I think we can even compile down to iOS and Android?

Also, I think there are some works on OCaml Platform (codenamed Bob) that brings the tools together, essentially producing a cli for all task (install deps, test, doc generation, etc.–think mix/cargo). Anil had a talk about it here.

I’d like to think we’re approaching the desired stability here :slightly_smiling_face:


Were there any updates on this? Or maybe some kind of roadmap for a future OCaml versions/dune versions?


So I’ve installed the 4.08.0+musl+static+flambda variant along with some other dependencies. I wanted to play with static linking on a small program.

However, I’m pretty much confused by my own expectations.

  • The musl+static variants still generate ocamlc.opt (et al.) as dynamically linked executables. This is under Ubuntu with musl-tools installed
  • If I build (using Dune) without -ccopt -static, the generated binaries are also dynamically linked
  • If I add the -ccopt -static flags to my dune file, then I get a link error against the math system library
/usr/bin/ld: dynamic STT_GNU_IFUNC symbol `sin' with pointer equality in `/usr/lib/x86_64-linux-gnu/libm-2.27.a(s_sin.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status
File "caml_startup", line 1:
Error: Error during linking

I’m obviously doing something wrong. Could anyone provide a hint so I can dive a bit deeper? Also, what about the OCaml compiler? Is it supposed to be dynamically linked even in the musl+static variants?


Seems there are some problems in some cases still -