使用作为香草cma附带的OCaml电池

使用作为香草cma附带的OCaml电池,ocaml,Ocaml,我对OCaml电池的概念和我能找到的大多数教程的处理方式感到有点沮丧和困惑。在我开始使用像GODI这样的“生产力”工具或者用ocamlfind batters/ocamlc替换对ocamlc的调用之前(这对我来说太神奇了),我希望能够像其他库一样简单地使用OCaml batters包含的核心库集。为此,我从(headhash:9f94ecb)下载了最新的源代码,并做了一个makeall。我注意到我在/\u build/src/上得到了三个.cma库,以及同一目录下的102个.cmi文件。因此,我

我对OCaml电池的概念和我能找到的大多数教程的处理方式感到有点沮丧和困惑。在我开始使用像GODI这样的“生产力”工具或者用ocamlfind batters/ocamlc替换对ocamlc的调用之前(这对我来说太神奇了),我希望能够像其他库一样简单地使用OCaml batters包含的核心库集。为此,我从(headhash:9f94ecb)下载了最新的源代码,并做了一个makeall。我注意到我在/\u 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-c-I../batters include/_build/src/euler001.ml 但当我试图联系:

ocamlc -o euler001 unix.cma nums.cma ../batteries-included/_build/src/batteries.cma euler001.cmo ocamlc-o euler001 unix.cma nums.cma../batters include/_build/src/batters.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 文件“\u none\u”,第1行,字符0-1: 错误:链接../batters include/_build/src/batters.cma(BatBigarray)时出错: 外部功能“caml_ba_Reforme”不可用 我在命令行中添加了nums.cmaunix.cma,因为链接器抱怨缺少对未定义全局Big_intunix的引用。但是在链接器调用中添加了这两个模块之后,我收到了最后一条消息(关于丢失的外部函数“caml_ba_reforme”),这对我来说是阻塞的。因此,我想问:

  • 在这种特殊情况下,我们如何处理?
  • 在一般情况下(即当链接器抱怨缺少外部功能时),如何处理
  • 使用这种方式的电池是否可行?在依赖平台工具之前,我希望能够保证,如果遇到问题,我可以使用标准OCaml编译器和链接器的底层构件(cma和cmi/mli文件)。
    caml_ba_reforme
    Bigarray
    模块的一个原语,你可以从名称猜出来,但我同意这并不明显。您应该在编译命令中,在依赖于它的
    batters.cma
    之前添加
    bigarray.cma

    建议使用
    ocamlfind
    是有原因的,它正好用于对这些依赖项进行抽象。我认为您不应该使用
    ocamlfind-batters/ocamlc
    ,而是应该使用
    ocamlfind-ocamlc-package-batters
    。如果您坚持在没有此类支持的情况下使用编译器,那么实际上您必须手动编译——我理解您的沮丧,但我希望您也理解它对任何足够复杂的OCaml库都是至关重要的,并且它只来自您自己强加的约束

    在一般情况下(即当链接器抱怨缺少外部功能时),如何处理

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

    使用这种方式的电池是否可行

    如果您坚持,“手动”编译是合理的。仅在源代码存储库中工作而不安装库是不合理的。安装后继续执行您的操作很容易,只需将
    -I…
    替换为所选的安装路径即可

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

    ocamlfind
    不仅仅是一个平台工具。它是使用第三方ocaml库的方式,period。它应该是任何使用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工具的前景,除了源代码发行版提供的最简单的内容之外,是相当稀疏的,并且缺乏一个连贯的入口点。随着时间的推移,我已经习惯了这些工具,使用它们是很自然的,但我理解我们应该降低一些入口成本

    附言:任何关于如何改进电池文档的建议都是非常受欢迎的。在文档中添加东西或修复它的补丁甚至更好。这是一个值得去的地方