我对OCaml Batteries Included概念以及我能找到的大多数教程的方式感到有点沮丧和困惑。在我使用像GODI这样的“生产力”工具或用 ocamlfind电池/ ocamlc 取代 ocamlc 的调用之前(这对我来说太神奇了)我是希望能够简单地使用OCaml Batteries包括任何其他库的核心库集。为此,我从git(头部哈希: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
我得到了:
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.cma 和 unix.cma ,因为链接器抱怨缺少对未定义的全局 Big_int 的引用(当添加时)到 Unix 。但是在链接器调用上添加了这两个模块后,我收到了最后一条消息(在缺少的外部函数'caml_ba_reshape'上),这证明了我的阻塞。所以我想问一下:
答案 0 :(得分:13)
caml_ba_reshape
是,因为你可以猜测名称,但我同意它并不明显,是Bigarray
模块的原语。您应该在编译命令中添加bigarray.cma
,batteries.cma
依赖于它。
有一个原因建议使用ocamlfind
,它正是用于抽象这些依赖项的。我认为你不应该使用ocamlfind batteries/ocamlc
,而是使用ocamlfind ocamlc -package batteries
。如果你坚持在没有这种支持的情况下使用编译器,那么你确实必须手动编译 - 我理解你的挫败感,但我希望你也明白它对于任何足够复杂的OCaml库来说都是内在的,它只来自你自己 - 约束。
如何在一般情况下继续(即当链接器抱怨缺少外部功能时
)
你必须知道或猜测原语的来源。查看库提供的META文件(用于通知ocamlfind
依赖项)可能对您有所帮助。如果要检查您的假设,可以使用工具ocamlobjinfo
来了解.cma
提供的基元。 (或者更好的是,使用ocamlfind吐出正确的编译命令,见下文。)
以这种方式使用电池是否可行?
如果你坚持,“手工编制”是合理的。不在安装库的情况下仅在源存储库中工作。在安装后继续执行您的操作很容易,只需用所选的安装路径替换-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-devel@lists.forge.ocamlcore.org是值得去的地方。