10

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

(* 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

我有:

文件“_none_”,第 1 行,字符 0-1:
错误:链接 ../batteries-included/_build/src/batteries.cma(BatBigarray) 时出错:
外部函数“caml_ba_reshape”不可用

我在命令行中添加的nums.cmaunix.cma是因为链接器抱怨缺少对 undefined global Big_int和(添加时)对Unix的引用。但是在链接器调用中添加了这两个模块之后,我收到了最后一条消息(在缺少的外部函数'caml_ba_reshape'上),这证明对我来说是阻塞的。所以我想问:

  1. 在这种特殊情况下如何进行?
  2. 在一般情况下如何进行(即当链接器抱怨缺少外部函数时)
  3. 以这种方式使用包含的电池是否可行?在我依赖平台工具之前,我想确保如果遇到问题,我可以将底层工件(cma 和 cmi/mli 文件)与标准 OCaml 编译器和链接器一起使用。
4

1 回答 1

14

caml_ba_reshape是,正如您可以从名称中猜到的那样,但我同意这并不明显,是Bigarray模块的原语。您应该添加bigarray.cma编译命令,之前batteries.cma取决于它。

建议使用 是有原因的ocamlfind,它正是用于抽象这些依赖关系。我认为您不应该使用ocamlfind batteries/ocamlc,而是应该使用ocamlfind ocamlc -package batteries. 如果你坚持在没有这种支持的情况下使用编译器,那么你确实必须手动编译——我理解你的沮丧,但我希望你也明白它对于任何足够复杂的 OCaml 库都是固有的,并且它只来自你自己- 施加的约束。

在一般情况下如何进行(即当链接器抱怨缺少外部函数时

您必须知道或猜测原语的来源。查看库提供的用于通知ocamlfind依赖关系的 META 文件可能会对您有所帮助。如果您想检查您的假设,您可以使用该工具ocamlobjinfo了解 a 提供的原语。.cma(或者更好的是,使用 ocamlfind 吐出正确的编译命令,见下文。)

以这种方式使用包含的电池是否可行?

如果您坚持,“手工”编译是合理的。仅在源存储库中工作,而不安装库,不是。安装后很容易继续做你做的事情,只需用-I ...选择的安装路径替换你的。

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

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:任何关于如何改进电池文档的建议都受到热烈欢迎。将内容添加到文档或修复它的补丁会更好。battery-devel@lists.forge.ocamlcore.org是去的地方。

于 2012-05-19T19:37:50.307 回答