OCaml statically detect dependency on non-pervasives library in standard distribution

169 Views Asked by At

Certain modules that ship with OCaml like Unix and Bigarray have their own .cmx and .cmxa files in ocamlopt -where (which is ~/.opam/4.03.0/lib/ocaml on my system in my current opam switch).

Is there a way to determine without compiling which source files depend on which of these "special" libraries in the standard distribution? I'm intending to consume this output later in a Makefile.

The following program example.ml

open Unix;;

Unix.system "echo hi";;

Can be compiled using ocamlfind ocamlopt -package unix -linkpkg example.ml. I'm not sure how to compile it without going through the ocamlfind wrapper.

I'm wondering if there's a way to statically detect that the unbound-in-this-file module Unix corresponds to "something" in the standard distribution and report unix.cmxa as a dependency. ocamldep does not seem to report it as a dependency by default.

ocamldep -all example.ml just reports that the various object and interfaces files that can be produced using example.ml depend on example.ml. I was hoping for either an error message complaining that ocamldep doesn't understand the Unix module or some indication that it's required to build the objects.

$ ocamldep -all example.ml
example.cmo example.cmi : example.ml
example.cmx example.o example.cmi : example.ml
2

There are 2 best solutions below

0
On BEST ANSWER

I understand that your question is:

For a given module name, say Unix, how can we find the library which provides it?

Unfortunately there is no such a tool (yet).

If we limit the search space to the libraries come with the OCaml compiler itself, I would do:

$ ocamlobjinfo $HOME/.opam/4.03.0/lib/ocaml/*.cma | grep '^\(File\|Unit name\)'

This will list all the modules defined in each archive. You may or may not find the module name in the result.

It is impossible in general, since the library you seek may not be standard or may not be installed locally. You can use API search engines like ocamloscope but they never cover all the OCaml libraries ever written of course.

1
On

Though modules might be packed into libraries with arbitrary names, the module interfaces still preserve a one to one mapping between top-level module names and compiled module interface file names. So if you have an error 'Unbound module Xxx`, the you can do

find ~/.opam -iname Xxx.cmi

If you didn't find any, then it means, that such library is not installed. And currently, there is no well-established way to find out which package provides this module, you can use Google, ask people on mailing lists or discussion forums, or try to use apt-file hoping that the library is in a standard distribution.

If the search returned exactly one folder, then you're lucky, you got the package. The package may contain object files of different genera (.cmx - for native code, .cmo - for the bytecode), as well as libraries (.cma - is a collection of .cmo, .cmxa - is a collection of .cmx, and .cmxs is a dynamic version of .cmxs). The flexibility of OCaml, that is both a boon and a bane, allows any of these files to be missing. Well-mannered libraries usually provide all these files, as well as have a naming convention that package name matches with the library name. But if you're using ocamlfind and the folder has the META file, then the name of the folder is the name of the package that you need to pass to ocamlfind in order to link the libraries from this package.

If you have more than one results, then you need to use common sense to determine which of the two libraries you need to use. Alternatively, you may try to use one and another and see which one compiles.