我对OCaml Batteries Included概念和我能找到的大多数教程的方式感到有点沮丧和困惑.之前,我用像GODI"生产力"工具或更换的调用ocamlc与ocamlfind电池/ ocamlc(这是,在这一点上,对我来说太不可思议),我希望能够简单地使用OCaml中有电池组核心库像任何其他图书馆.为此,我从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 ()
Run Code Online (Sandbox Code Playgroud)
我能够编译它:
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'上),这证明了我的阻塞.所以我想问一下:
gas*_*che 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
Run Code Online (Sandbox Code Playgroud)
我不想向你扔石头.OCaml工具的风景,除了源分布提供的最简单的外壳之外,非常稀疏,缺乏连贯的入口点.随着时间的推移,我已经习惯了这些工具并且使用它们很自然,但我知道我们应该尝试降低一些入门成本.
PS:热烈欢迎任何关于如何改进电池文档的建议.将内容添加到文档或修复它的补丁甚至更好.batteries-devel@lists.forge.ocamlcore.org是个好去处.