Archiving Last updated Feb 11, 2025

Table of Contents

OCaml archives that contain modules that depend on foreign (CC) libraries may embed information about those dependencies in the archive metadata (.cma/.cmxa files). The protocol is that when such archives are used to build an executable, the OCaml linker will extract that dependency metadata and add it to the link command line, as -lfoo for example. This entails that the locations of such libraries be known to the linker. In most cases involving opam libraries, this location will already be known to the linker. This is because opam itself follows a kind of protocol; for example, shared object files intended for use in bytecode executables must be named dllfoo.so rather than the more common libfoo.so, and opam installs them in the stublibs subdirectory of the switch in which they are installed.

But this is not a requirement; an OCaml archive may depend on foreign libraries that are not installed in the stublibs directory. In that case, the location of the share library may also be recorded in the archive metadata. Or not.

So the protocol is roughly this: build the shared object file; build the OCaml archive, passing the share object file on the command line using -dllib -lfoo; then build an executable depending on the archive, and the linker will automatically discover the share library dependencies and construct the appropriate command line.

Now the problem with this, from a Bazelian perspective, is that the metadata involved - the information in the archive file recording foreign library dependencies, etc. - is hidden from the build system. In order to guarantee replicable builds, Bazel needs to know all inputs and outputs of every build action - that’s part of the “Bazel protocol”. So using the “standard” build protocol for archives with foreign library dependencies undermines the Bazel protocol. It means that Bazel will not know that the executable directly depends on the foreign libraries. (More exactly, it means that in order for such builds to succeed under Bazel, all stublibs must be listed as inputs to every “build an executable” action, whether they are needed or not.)

More precisely: the only way that Bazel can discover the (hidden) foreign library dependencies of an OCaml archive is to actually read the archive file, possibly by using ocamlobjinfo. (That’s a possible future enhancement.)

Native

Bytecode