使用OCaml Batteries Included作为纯净的cma文件

11

我对OCaml Batteries Included的概念和大多数教程的处理方式感到有些沮丧和困惑。在使用“生产力”工具(如GODI)或将ocamlc的调用替换为ocamlfind batteries/ocamlc之前(此时对我来说太神奇了),我希望能够像使用其他库一样简单地使用OCaml Batteries Included核心库集。为此,我从git(head hash:9f94ecb)下载了最新的源代码并执行了make all。我注意到在./_build/src/目录下得到了三个.cma库,以及同一目录中的102个.cmi文件。因此,我假设编译时使用指向该目录的-I开关,并链接其中一个找到的三个.cma库,就足够了,而不需要“安装”Batteries或使用平台工具。为了测试这一点,我开始为以下简单程序生成可执行文件:

(* file euler001.ml *)
open BatEnum      
open BatPervasives
let main () = 
 (1--999)
|> BatEnum.filter (fun i -> i mod 3 = 0 || i mod 5 == 0)
|> BatEnum.reduce (+) 
|> BatInt.print stdout

let _ = main ()

我能够使用以下命令进行编译:
ocamlc -c -I ../batteries-included/_build/src/ euler001.ml
但是当我尝试链接时,使用以下命令:
ocamlc -o euler001 unix.cma nums.cma ../batteries-included/_build/src/batteries.cma euler001.cmo
我得到了错误信息:
File "_none_", line 1, characters 0-1: Error: Error while linking ../batteries-included/_build/src/batteries.cma(BatBigarray): The external function `caml_ba_reshape' is not available 我在命令行中添加了nums.cmaunix.cma,因为链接器抱怨缺少对未定义全局变量Big_int的引用(在添加后),以及对Unix的引用。但是,在这两个模块被添加到链接器调用后,我收到了最后一个消息(关于缺少外部函数'caml_ba_reshape'),这对我来说是一个阻碍。所以我想问一下:
  1. 在这种特定情况下,应该怎么做?
  2. 在一般情况下(即当链接器抱怨缺少外部函数时),应该怎么做?
  3. 以这种方式使用Batteries Included是否可行?在依赖平台工具之前,我想确保如果遇到问题,可以使用标准的OCaml编译器和链接器来使用底层构件(cma和cmi/mli文件)。
1个回答

15

caml_ba_reshapeBigarray模块的一个原语,正如您从名称中可以猜到但我同意这不是显而易见的。在编译命令中应该先添加bigarray.cma,然后才是依赖于它的batteries.cma

使用ocamlfind有其建议的原因,即用于抽象化这些依赖关系。我认为您不应该使用ocamlfind batteries/ocamlc,而应该使用ocamlfind ocamlc -package batteries。如果您坚持使用没有此类支持的编译器,则确实需要手动编译——我理解您的挫败感,但我希望您也明白这是任何足够复杂的OCaml库固有的,并且这仅来自您自己施加的限制。

一般情况下怎么办(即当链接器抱怨缺少外部函数时)?

您必须知道或猜测原语来自何处。查看库提供的META文件可以帮助您通知ocamlfind依赖项。如果要检查您的假设,可以使用工具ocamlobjinfo来了解.cma提供哪个原语。 (或者更好的方法是使用ocamlfind来输出正确的编译命令,见下文。)

以这种方式使用Batteries Included是否可行?

如果您坚持手动编译,则是合理的。但在不安装库的情况下仅在源代码存储库中工作则不太可取。在进行安装后继续执行您正在执行的操作很容易,只需将您的-I...替换为所选的安装路径即可。

在依赖于平台工具之前,我想确保如果遇到问题,我可以使用标准的OCaml编译器和链接器使用底层构件(cma和cmi/mli文件)。

ocamlfind不仅仅是一个平台工具。它是使用第三方OCaml库的方法,无论如何都应该是标准的。它应该是任何使用ocaml的平台上的标准工具。它未随INRIA发行版一起提供只是一个历史细节。

您可以要求ocamlfind向您显示裸编译器的调用:

% ocamlfind ocamlc -linkpkg -package batteries t.ml -o test -verbose
Effective set of compiler predicates:
pkg_unix,pkg_num.core,pkg_num,pkg_bigarray,pkg_str,pkg_batteries,autolink,byte
+ ocamlc.opt -o test -verbose -I /usr/local/lib/ocaml/3.12.1/batteries /usr/lib/ocaml/unix.cma /usr/lib/ocaml/nums.cma /usr/lib/ocaml/bigarray.cma /usr/lib/ocaml/str.cma /usr/local/lib/ocaml/3.12.1/batteries/batteries.cma t.ml

我不想抨击你。除了源分发提供的最小工具集之外,OCaml工具的景象相当稀少,缺少一个连贯的入口点。随着时间的推移,我已经习惯了这些工具,使用它们变得很自然,但我知道我们应该尝试降低一些入门成本。

PS:欢迎任何有关如何改进Batteries文档的建议。添加或修复文档的补丁甚至更好。请前往batteries-devel@lists.forge.ocamlcore.org


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接