ocamlbuild stubs and dynamic libraries

The other day I wrote about my experience to set up the build system for a simple library. However, since parmap includes only two simple stubs to syscall I didn't have the chance to talk how to convince ocamlbuild to build stubs that depend on an external dynamic library.

I'm sure, facing this problem you had a look at this example : http://brion.inria.fr/gallium/index.php/Ocamlbuild_example_with_C_stubs

Despite providing all elements, the page is a bit scars of details and explanations (at least for me...).

So, suppose you want to build ocaml stubs for a C library called toto . Good practices tell us to put our stubs in a file that is called toto_stubs.c and then add the .o file in a clib file (libtoto_stubs.clib ) that ocamlbuild is going to use to build out dynamic library.

So far so good. Now we need to add a tag, say use_toto that we will use to compile our binaries and libraries. Our _tags file will look like :

 <libtoto_stubs.*>: use_toto

Here I use only one tag. In the example of the ocamlbuild they use two tags, one to compile, one to link.

At this point we need to explain to ocamlbuild how to build our library. First we add a compile rule where we say that whenever we compile a c object that use toto, then we must also add its include directory.

       flag ["c"; "use_toto"; "compile"] & S[
         A"-ccopt"; A"-I/usr/include/toto";
       ];

Second we add a link flag to add to the dynamic library all the information it needs to load other external libraries. This is important as we don't want to add any other flags anywhere else. When we use -ltoto_stubs we want all other dependencies automatically satisfied by the linker. Note the libtoto.so referred by -ltoto is the C library for which we are writing these bindings and that sits in /usr/lib/.

       flag ["c"; "use_toto"; "ocamlmklib"] & S[
         A"-ltoto";
       ];

At the end we add a flag that whenever we try to build out ocaml module ( say toto.cma ), we want to add all necessary information to load at run time its dynamic component.

       flag ["ocaml"; "use_toto"; "link"; "library"; "byte"] & S[
         A"-dllib"; A"-ltoto_stubs";
       ];

Using ocamlobjdump we can easily check if the cma contains indeed this information. The output should look something like this :

$ocamlobjinfo _build/toto.cma
File _build/toto.cma
Force custom: no
Extra C object files:
Extra C options:
Extra dynamically-loaded libraries: -ltoto_stubs
Unit name: Toto
Force link: no
...

In order to generate cmxa and a objects we need to specify few other flags and dependencies like :

       dep ["link"; "ocaml"; "link_toto"] ["libtoto_stubs.a"]
       flag ["ocaml"; "use_toto"; "link"; "library"; "native"] & S[
         A"-cclib"; A"-ltoto_stubs";
       ];

As always, if I'm missing something, please drop a note in the comment page.

Average: 1.5 (6 votes)

Comments

You can have a look at

You can have a look at //oasis.forge.ocamlcore.org oasis. There is an example with a C stub library in the example section.

All you have todo is to add, to your library

Library toto

 Modules: Toto
 CSources: toto_stubs.c
You can then use the toto library further into your files:

Executable foo

  BuildDepends: toto
And oasis will take care to generate the META file for toto and install it in the right place.

Personaly, I stopped using

Personaly, I stopped using ocamlbuild once I needed to bind to a C library. I went back to a plain Makefile and was happy ever after. Oasis looks good if it is that simple to configure.

Regards, F.

I'm pretty happy with

I'm pretty happy with ocamlbuild. The problem is that you need to configure it at-hoc for every library when I guess it won't be too difficult to add few conventions and default rules. There is a third-party plugin to solve this problem, but I'd rather have it upstream. Yes oasis is nice. I should have a look at it one of these days.