问题描述
我正在使用 Dune 来构建 OCaml 项目,我想构建一个独立的库以便在其他项目中重用它。
库的根文件夹是 mylib
,库初始化为 dune init lib mylib src
(在 cd mylib
之后)。
项目根目录mylib
的目录树如下:
mylib
+---dune-project
│
+---src
dune
priv.ml
mymodule.ml
mymodule.mli
mylib/dune-project:
(lang dune 2.7)
mylib/src/dune:
(library
(name mylib))
mylib/src/priv.ml:
let rec loop a accu i =
let n = Array.length a in
if i = n then
accu
else
loop a (accu + Array.unsafe_get a i) (succ i)
mylib/src/mymodule.mli:
val sum : int array -> int
mylib/src/mymodule.ml:
let sum a =
Priv.loop a 0 0
在给出上下文并显示这个玩具示例的每个文件的内容后,问题如下:
- 如何构建库
mylib
并在另一个单独的项目中使用它?
Open Mylib
let () =
print_int (Mymodule.sum [1;2;3])
或
let () =
print_int (Mylib.Mymodule.sum [1;2;3])
)
对于 Dune,给定可执行文件 main
,您将编写以下 dune
文件以使用库 mylib
(如果它在 Opam 上发布)。
沙丘:
(executable
(name main)
(libraries mylib))
- 成功构建库并将其链接到另一个项目后,如何隐藏或不公开某些模块?例如,鉴于之前的玩具库
mylib
,我不想暴露模块Priv
并使模块不可访问(这样Priv
只能在 {{1} 的模块内使用}} - 就像 Java/C# 中的受保护/内部类一样)。
我尝试在 Real World OCaml、Cornell CS3110 textbook、Dune documentation、OCaml Learn 上进行搜索,但是,除非嵌套很深,否则我一无所获。
非常感谢您的帮助,如果我没有解释清楚,请追问,我会尽量解释得更好。
解决方法
- 在根目录中,这些应该是一个名为
mylib.opam
的文件,其内容类似于 this one。然后,应将(public_name mylib)
s 表达式添加到 mylib/src/dune 中的library
。最后,确保在项目的根目录中,库应使用dune build
构建并使用opam install .
安装。
要在另一个项目中实际使用该库,即使在不同的沙丘工作区中,只需将(libraries mylib)
添加到将使用该库的项目的沙丘文件中。 - 应该将
(private_modules priv)
s 表达式添加到 mylib/src/dune 中的library
。然后,需要使用以下内容创建mylib.ml
:module Mymodule = Mymodule
:这将确保只有Mymodule
会在包Mylib
下公开。