使用ocamlc独立编译库

时间:2017-02-07 23:08:49

标签: ocaml ocamlbuild

我有三个文件:

$ ls
lib.ml  desk.ml  test.ml

$ cat lib.ml
let myfunction () = print_endline "Hello world"

$ cat desk.ml
module Liberty = Lib

$ cat test.ml
Desk.Liberty.myfunction ()

我想编译desk.cma 公开模块Lib,但能够使用它。例如,我尝试过:

$ ocamlc -a lib.ml -o lib.cma
$ ocamlc -a lib.cma desk.ml -o desk.cma
$ ocamlc desk.cma test.ml -o test.byte

不幸的是,如果您将test.ml更改为Lib.myfunction (),则相同的编译步骤可以正常工作。我希望它Lib不会向test.ml公开,只会向desk.ml公开。有谁知道如何做到这一点?非常感谢!

2 个答案:

答案 0 :(得分:2)

看起来你正在寻找OCaml的-pack机制。这允许您从几个编译单元(如pack.cmo库)创建pack.cmx(或pack.cma进行本机编译),但具有额外的优势,即您可以拥有相应的{{1接口,您可以使用该接口隐藏pack.mli内部的部分。在您的示例中,您可以例如:

- lib.ml -

pack

- liberty.ml -

let myfunction () = print_endline "Hello world"

- desk.mli -

include Lib

然后你可以用

编译它
(* No module Lib: Lib will not be seen outside of the pack. *)

module Liberty: sig
  val myfunction: unit -> unit
end

这将为您提供一个模块ocamlc -for-pack Desk -c lib.ml ocamlc -for-pack Desk -c liberty.ml ocamlc desk.mli ocamlc -pack -o desk.cmo lib.cmo liberty.cmo ,它只包含Desk个子模块。当然,Liberty可用于获得更细粒度的限制,例如与

desk.mli

使用空签名导出module Lib: sig end module Liberty: sig val myfunction: unit -> unit end ,从而隐藏Lib中的单个(尽管是示例中唯一的一个;-P)函数。

答案 1 :(得分:0)

您要求Lib成为desk.cma Desk可以使用的模块,但没有其他模块。我非常确定cma文件的结构不能提供这种控制。

如果您在Lib内定义Desk,则可以将其设为隐藏的详细信息。

$ ls
desk.ml  desk.mli test1.ml test2.ml test3.ml

$ cat desk.ml
module Lib = struct
    let myfunction () = print_endline "Hello world"
end
module Liberty = Lib

$ cat desk.mli
module Liberty : sig
val myfunction : unit -> unit
end

$ cat test1.ml
Desk.Liberty.myfunction ()

$ cat test2.ml
Lib.myfunction ()

$ cat test3.ml
Desk.Lib.myfunction ()

Liberty模块对测试程序可见,但Lib模块不是:

$ ocamlc -c desk.mli
$ ocamlc -a desk.ml -o desk.cma
$ ocamlc desk.cma test1.ml -o test1.byte
$ ./test1.byte
Hello world
$ ocamlc desk.cma test2.ml -o test2.byte
File "test2.ml", line 1, characters 0-14:
Error: Unbound module Lib
$ ocamlc desk.cma test3.ml -o test3.byte
File "test3.ml", line 1, characters 0-19:
Error: Unbound module Desk.Lib

您可以在单独的文件中实现Lib,然后将include实现到Desk.Lib模块的定义中。

我怀疑这不是一个完全令人满意的答案,但我希望它有所帮助。