Stubs c - shared and static libs

Hi,
I’m currently working with an ocaml library that uses c++ binding. When I build the library from the sources, in the build repository, there are both .so and .a file. However, when I install it from opam and pin-depends, only the .a files are built.

I don’t understand why, and I wonder if there is a way to force that?

1 Like

I don’t know much about opam, but the shared library is only built for use with the bytecode interpreter. So perhaps if opam is only installing the native version, then the shared library will not be built.

Cheers,
Nicolás

Thanks for your reply and for the answer!
My issue is when I try to use it, I have an error because the shared libraries are not included.
Is there a way to tell dune to not care about them?

The .so file shouldn’t be installed as native dynamic library is packaged as cmxs file. A cmxs file is a normal shared library, with several sections specific to OCaml.

Probably you’re looking in a wrong direction, what’s that the error that you’re getting? And how do you build and run your program?

That’s not true, OCaml supports native dynamic linking since 3.03, IIRC, and is capable of building and loading shared libraries.

Indeed, I forgot about .cmxs! Thanks for the correction.

Best,
Nicolás

1 Like

Is it the case even with c++ stubs? The part which is not built is the static c++ library. The issue is it’s built when I do a dune build but not with opam install (it uses dune to create the package.

As the .so file is not present, it says libmammut.so is missing.

Yes, because the opam package that is distributing bindings to the library is not responsible for distribution the actual library. In fact, there are two approaches. You can distribute only the bindings code and assume that the bound library is linked by the user code, or you can statically link the bound library and distributed in one big cmxs file.

Before dune, the build systems were able to notice in the META file that an OCaml library has an extra dependency on a foreign shared library and automatically pass the corresponding command-line options during the linking phase. In addition, cma and cmxa files (OCaml library archives) contain information about the libraries that has to be linked and about the C compiler options that has to be used during linking via the -cclib and -ccopt command-line options.

Unfortunately, the library that you’re using is doing neither so it is you task to specify the extra dependencies1. In general you can use the link_flags (or flags) stanza, e.g., (link_flags -cclib -lfoo) to link the libfoo.so library to your library (executable). But in case of ocaml_mammut I think you would need to add much more than that, e.g., this is what I think you need to add,

-cclib -lstdc++ -cclib -lraplcap-msr -cclib -lsmartgauge -cclib -lusb-1.0 -cclib -lmammut

E.g., if you’re building a binary that uses ocaml_mamut then add to the executable stanza the following line,

(flags (:standard -w -49 -cclib -lstdc++ -cclib -lraplcap-msr -cclib -lsmartgauge -cclib -lusb-1.0 -cclib -lmammut))

1) when we link with libc or lm we don’t have to specify their dependencies as well, it is the responsibility of the linked library to specify their dependencies. So mamut_ocaml shall pass those options as link_flags when they define the mammut library. If they would do this, then you we wouldn’t need to write those options in the code that use their library. I would suggest you to open an issue or suggest a PR with the fix.

1 Like

Thanks for this really detail reply, it helps me a lot! I will see with the maintainer if I can add the flags directly in the library.

I have a last question about your suggestion to embed the library directly in a cmxs file. Is it still possible to do it with dune and how should you then link the code in the executable dune?

Of course, just link statically with the mammut library. You can do it both in ocaml_mammut or in your application, if you want to make it self-contained. The only caveat is that the mammut library should distribute .a files. If they are provided, e.g., there is libmammut.a at some directory /foo/bar/mammut then passing -cclib -L -cclib /foo/bar/mammut -cclib libmammut.a to the flags (link_flags) stanza will take the libmammut code and copy it into your binary (library). For bytedcode it will create a special dll<yourlib>.so library that will be loaded by the OCaml runtime.

Ok, I see! Thanks so much for your help!

Hi,
I’m sorry to reopen this ticket, I seem to still struggle with it (lib). When I insert the cflags directly in the lib dune file it’s not able to find it whereas when I use it in the example dune file, there is no
error.

Dune from the lib directory (flags generate errors here) :

(library
  (public_name tezos_oxymeter)
  (name tezos_oxymeter)
  (flags (:standard -w -49
                    -cclib -lstdc++
                    -cclib -lraplcap-msr
                    -cclib -lsmartgauge
                    -cclib -lusb-1.0
                    -cclib -lmammut
                    -linkall))
  (libraries re
             yojson
             lwt
             lwt.unix
             mammut
             mammut.generated
             data-encoding))

Dune from the example directory :

(executable
  (name main)
  (flags (:standard -w -49
                    -cclib -lstdc++
                    -cclib -lraplcap-msr
                    -cclib -lsmartgauge
                    -cclib -lusb-1.0
                    -cclib -lmammut))
  (libraries tezos_oxymeter))

Because of it, I’m not able to build a self contain library… Would you have any suggestions ?