如何拥有嵌套库?对沙丘等感到困惑
How to have nested libraries? Confused about dune etc
我有一个 OCaml 项目使用 dune
遵循基础教程中的建议,我的目录结构如下:
bin/
cli.ml
dune
lib/
dune
...
<various>.ml
我的 lib
目录中的文件数量在增加,我想要另一个级别的命名空间。
我想要像这样的子目录:
lib/
utils/
dune
...
<various>.ml
some_other_domain/
dune
...
<various>.ml
dune
...
<various>.ml
而且我希望能够像 Lib.Utils.Whatever
一样打开它们
我想这一定是可能的吧?
我尝试在 lib/utils
下创建一个 dune
文件,例如:
(library
(name utils)
(libraries ...))
...但是 open Lib.Utils.Whatever
似乎不起作用。
我找到了 subdir
stanza ...但是如果我将它添加到 lib/dune
并将 utils
定义为子目录 library
那么我就不会得到命名空间...我必须 open Utils
而不是 open Lib.Utils
将它们称为“嵌套库”实际上有点奇怪,因为您想用 Lib.Utils.Whatever
来调用它们。 Utils
,这里是Lib
的子模块。如果对您有所帮助,以下是我能够做到的:
.
├── bin
│ ├── cli.ml
│ └── dune
├── dune-project
├── lib
│ ├── dune
│ ├── lib.ml
│ ├── suba
│ │ └── suba.ml
│ └── subb
│ └── subb.ml
有
bin/cli.ml
let () =
Lib.Suba.a ();
Lib.Subb.b ()
bin/dune
(executable
(name cli)
(libraries lib)
)
lib/dune
(include_subdirs unqualified)
(library
(name lib)
(modules suba subb)
)
(如果你像这样包含你的模块,你必须使用这些确切的名称,另一种获得控制权的方法是添加以下文件并删除 (modules suba subb)
行:
lib/lib.ml
(* here you can give the name you want -- say A -- and use it in bin with Lib.A *)
module Suba = Suba
module Subb = Subb
(总结一下:
- 您的
dune
文件是否包含 (modules suba subb)
- 如果子目录包含多个文件,您需要将所有正在使用的文件放入
(modules ...)
节中,否则编译器将无法使用它们
- 或
lib.ml
文件,其中您要导出的每个模块都应包含在 module MyName = AModule
中(并且仅包含您要导出的模块)
- 使用此解决方案,您不想导出的模块无需显式包含在
lib.ml
文件中,编译器将在需要时使用它们
)
sub{a|b}/{a|b}.ml
let {a|b} () = Format.eprintf "{A|B}@."
suba.ml
和 subb.ml
用作 lib
的子模块,可以与 Lib.Suba.a()
一起使用,如您在 cli.ml
[= 中所见51=]
请注意,这会禁止您为两个文件指定完全相同的名称,因为目录将在父目录中全部展平,因此您不能使用类似的名称:
.
├── bin
│ ├── cli.ml
│ └── dune
├── dune-project
├── lib
│ ├── dune
│ ├── lib.ml
│ ├── suba
│ │ └── lib.ml
│ └── subb
│ └── lib.ml
因为(include_subdirs unqualified)
会让它看起来像
.
├── bin
│ ├── cli.ml
│ └── dune
├── dune-project
├── lib
│ ├── dune
│ ├── lib.ml
│ ├── lib.ml
| └── lib.ml
和 dune
将无法知道要使用哪个 lib.ml
文件。
[编辑] 如果你想要每个库一个目录,你只需删除 lib
根目录下的 dune
文件并为每个子目录创建一个:
.
├── bin
│ ├── cli.ml
│ └── dune
├── dune-project
├── lib
│ ├── suba
│ │ ├── dune
│ │ └── suba.ml
│ └── subb
│ ├── dune
│ └── subb.ml
唯一的变化是:
bin/cli.ml
let () =
Suba.a (); (* no more Lib.(...) *)
Subb.b ()
bin/dune
(executable
(name cli)
(libraries suba subb)
)
lib/dune
已删除
lib/sub{a|b}/dune
(library
(name sub{a|b})
)
在这种情况下,不同目录中的多个文件可以具有相同的名称。
我有一个 OCaml 项目使用 dune
遵循基础教程中的建议,我的目录结构如下:
bin/
cli.ml
dune
lib/
dune
...
<various>.ml
我的 lib
目录中的文件数量在增加,我想要另一个级别的命名空间。
我想要像这样的子目录:
lib/
utils/
dune
...
<various>.ml
some_other_domain/
dune
...
<various>.ml
dune
...
<various>.ml
而且我希望能够像 Lib.Utils.Whatever
我想这一定是可能的吧?
我尝试在 lib/utils
下创建一个 dune
文件,例如:
(library
(name utils)
(libraries ...))
...但是 open Lib.Utils.Whatever
似乎不起作用。
我找到了 subdir
stanza ...但是如果我将它添加到 lib/dune
并将 utils
定义为子目录 library
那么我就不会得到命名空间...我必须 open Utils
而不是 open Lib.Utils
将它们称为“嵌套库”实际上有点奇怪,因为您想用 Lib.Utils.Whatever
来调用它们。 Utils
,这里是Lib
的子模块。如果对您有所帮助,以下是我能够做到的:
.
├── bin
│ ├── cli.ml
│ └── dune
├── dune-project
├── lib
│ ├── dune
│ ├── lib.ml
│ ├── suba
│ │ └── suba.ml
│ └── subb
│ └── subb.ml
有
bin/cli.ml
let () =
Lib.Suba.a ();
Lib.Subb.b ()
bin/dune
(executable
(name cli)
(libraries lib)
)
lib/dune
(include_subdirs unqualified)
(library
(name lib)
(modules suba subb)
)
(如果你像这样包含你的模块,你必须使用这些确切的名称,另一种获得控制权的方法是添加以下文件并删除 (modules suba subb)
行:
lib/lib.ml
(* here you can give the name you want -- say A -- and use it in bin with Lib.A *)
module Suba = Suba
module Subb = Subb
(总结一下:
- 您的
dune
文件是否包含(modules suba subb)
- 如果子目录包含多个文件,您需要将所有正在使用的文件放入
(modules ...)
节中,否则编译器将无法使用它们
- 如果子目录包含多个文件,您需要将所有正在使用的文件放入
- 或
lib.ml
文件,其中您要导出的每个模块都应包含在module MyName = AModule
中(并且仅包含您要导出的模块)- 使用此解决方案,您不想导出的模块无需显式包含在
lib.ml
文件中,编译器将在需要时使用它们 )
- 使用此解决方案,您不想导出的模块无需显式包含在
sub{a|b}/{a|b}.ml
let {a|b} () = Format.eprintf "{A|B}@."
suba.ml
和 subb.ml
用作 lib
的子模块,可以与 Lib.Suba.a()
一起使用,如您在 cli.ml
[= 中所见51=]
请注意,这会禁止您为两个文件指定完全相同的名称,因为目录将在父目录中全部展平,因此您不能使用类似的名称:
.
├── bin
│ ├── cli.ml
│ └── dune
├── dune-project
├── lib
│ ├── dune
│ ├── lib.ml
│ ├── suba
│ │ └── lib.ml
│ └── subb
│ └── lib.ml
因为(include_subdirs unqualified)
会让它看起来像
.
├── bin
│ ├── cli.ml
│ └── dune
├── dune-project
├── lib
│ ├── dune
│ ├── lib.ml
│ ├── lib.ml
| └── lib.ml
和 dune
将无法知道要使用哪个 lib.ml
文件。
[编辑] 如果你想要每个库一个目录,你只需删除 lib
根目录下的 dune
文件并为每个子目录创建一个:
.
├── bin
│ ├── cli.ml
│ └── dune
├── dune-project
├── lib
│ ├── suba
│ │ ├── dune
│ │ └── suba.ml
│ └── subb
│ ├── dune
│ └── subb.ml
唯一的变化是:
bin/cli.ml
let () =
Suba.a (); (* no more Lib.(...) *)
Subb.b ()
bin/dune
(executable
(name cli)
(libraries suba subb)
)
lib/dune
已删除
lib/sub{a|b}/dune
(library
(name sub{a|b})
)
在这种情况下,不同目录中的多个文件可以具有相同的名称。