How to Statically Link OCaml Programs

Static linking is preferred for some cases although it has its own various problems. Static building/linking is not always possible for some languages on some platform. For OCaml, the answer to this question is yes. In this post, we will introduce 2 methods to statically linking OCaml: static linking with runtime glibc required and static linking with musl (as libc alternative which does not require runtime library).

OCaml static linking with glibc (requires runtime glibc available)

If the program is fine to have glic not "really" (see later parts for why) statically linked it, it is simple enough just to pass the -static option to the C linker by giving the OCaml compiler -ccopt -static option.

To test, let’s write a small hello.ml program as follows

let () = print_endline "hello world"

Now let’s build the program.

$ ocamlopt -ccopt -static -o hello hello.ml

It may print a warning message like

/usr/lib/ocaml/libasmrun.a(unix.o): In function `caml_dlopen':
(.text+0x37f): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

The warning message explains itself the problem of static linking against glibc: when dlopen (and more similar ones) is used during run time, the glibc version’s shared libraries will be needed for linking.

We can verify the linked binary executable is "static".

$ ldd ./hello
    not a dynamic executable

OCaml static linking with musl libc (without runtime libraries required)

Linking against glibc is not 100% fully static linking as shown above. However, there are some libc alternatives available and supported by the OCaml compiler. One is the musl libc. Let’s see how to build OCaml program with musl statically.

On Debian/Ubuntu Linux distros, you can install musl libc and tools by

$ sudo apt-get install musl-tools

You may use other ways to install it if you are using other distros.

Now, let’s switch the OCaml tool chain to the musl+static one as follows.

$ opam switch install 4.07.1+musl+static+flambda

(here, we use version 4.07.1 as an example)

Install ocamlfind if the system does not have it yet.

$ opam install ocamlfind

Then, let’s build it.

$ ocamlfind ocamlopt -ccopt -static -o hello hello.ml

Now, let’s verify the built binary is not a dynamic one any more.

$ ldd ./hello
    not a dynamic executable

Eric Ma

Eric is a systems guy. Eric is interested in building high-performance and scalable distributed systems and related technologies. The views or opinions expressed here are solely Eric's own and do not necessarily represent those of any third parties.

Leave a Reply

Your email address will not be published. Required fields are marked *