我有三个文件:
$ 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
公开。有谁知道如何做到这一点?非常感谢!
答案 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
模块的定义中。
我怀疑这不是一个完全令人满意的答案,但我希望它有所帮助。