OCaml 静态检测对标准发行版中非普遍性库的依赖

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

OCaml 附带的某些模块,如 UnixBigarrayocamlopt -where 中有自己的 .cmx.cmxa 文件(即 ~/.opam/4.03.0/lib/ocaml 在我当前的 opam 开关中的系统上)。

有没有办法在不编译的情况下确定哪些源文件依赖于标准发行版中的哪些 "special" 库?我打算稍后在 Makefile 中使用此输出。

下面的程序example.ml

open Unix;;

Unix.system "echo hi";;

可以使用ocamlfind ocamlopt -package unix -linkpkg example.ml编译。我不确定如何在不通过 ocamlfind 包装器的情况下编译它。

我想知道是否有办法静态检测未绑定的文件模块 Unix 对应于标准分发中的 "something" 并报告 unix.cmxa 为一种依赖。 ocamldep 默认情况下似乎没有将其报告为依赖项。

ocamldep -all example.ml 只是报告可以使用 example.ml 生成的各种对象和接口文件取决于 example.ml。我希望收到一条错误消息,抱怨 ocamldep 不理解 Unix 模块,或者一些指示它需要构建对象。

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

我了解到您的问题是:

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

遗憾的是(目前)还没有这样的工具。

如果我们将搜索 space 限制在 OCaml 编译器本身附带的库中,我会这样做:

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

这将列出每个存档中定义的所有模块。您可能会也可能不会在结果中找到模块名称。

一般情况下是不可能的,因为你找的库可能不是标准的,也可能本地没有安装。您可以使用 API 搜索引擎,如 ocamloscope,但它们当然不会涵盖所有曾经编写过的 OCaml 库。

虽然模块可能被打包到具有任意名称的库中,但模块接口仍然保留顶级模块名称和编译模块接口文件名之间的一对一映射。所以如果你有一个错误'Unbound module Xxx',你可以做

find ~/.opam -iname Xxx.cmi

如果没有找到,说明没有安装这样的库。目前,还没有确定的方法来找出哪个包提供了这个模块,你可以使用 Google,在邮件列表或论坛上询问人们,或者尝试使用 apt-file 希望库服从标准分布。

如果搜索只返回一个文件夹,那么您很幸运,您收到了包裹。该包可能包含不同类的目标文件(.cmx - 用于本机代码,.cmo - 用于字节码)以及库(.cma - 是 .cmo 的集合,.cmxa - 是 .cmx 的集合, .cmxs 是 .cmxs 的动态版本)。 OCaml 的灵活性既是福音又是祸根,允许这些文件中的任何一个丢失。良好的库通常会提供所有这些文件,并且具有包名称与库名称匹配的命名约定。但是,如果您使用的是 ocamlfind 并且该文件夹包含 META 文件,那么该文件夹的名称就是您需要传递给 ocamlfind 以便 link 的包的名称这个包中的库。

如果您有多个结果,那么您需要使用常识来确定您需要使用这两个库中的哪一个。或者,您可以尝试使用一个和另一个,看看哪个可以编译。