如何使用(或不使用)Oasis创建多级模块层次结构

时间:2015-02-25 15:19:38

标签: module ocaml oasis

假设我有一组模块,每个模块都是#34;浓密的"与子模块。

M1.X        M2.X        M3.X
M1.Y        M2.Y        M3.Y
M1.Z        M2.Z        M3.Z
M1.W        M2.W        M3.W
M1.Q        M2.Q        M3.Q
M1.P        M2.P        M3.P

此外,我希望每个灌木丛都位于一个主模块下。

Home.M1
Home.M2
Home.M3

现在,使用Oasis'为M1M2M3中的每一个构建项目目录都很容易。 Pack:选项。特别是,我喜欢和想要解决的问题是:(a)能够以标准.ml / .mli格式布置我的文件和(b)正确生成ocamldoc链接文档。

但是,由于我希望将M1M2M3中的每一个分布在公共模块层次结构下的同一个库中,因此我无法使用Pack:而且我被迫将整个该死的东西扔进一个文件中,以便(a)不小心破坏全局命名空间,(b)不会意外地扩散Home.命名空间中不打算使用的模块直接地,(c)不破坏ocamldoc连接。

所以我的问题是,根据上面建议的目标,我如何使用Oasis创建一个包含此表单层次模块的包?

一些额外的限制包括:

  • M1.M2.M3.名称空间下的模块发生冲突并非偶然 - 这也是在真实情况下发生的!
  • M2.M3.命名空间中的模块取决于M1.命名空间中的模块。

我的偏好能够达到一个解决方案,它也允许合理的文件布局,例如

src -+
     +-- m1 -+
     |       +-- x.ml
     |       +-- x.mli
     |       +-- y.ml
     |       +-- y.mli
     |       +-- z.ml
     |       +-- z.mli
     |       |
     |       ...
     |
     |
     +-- m2 -+
     |       +-- x.ml
     |       +-- x.mli
     |       +-- y.ml
     |       +-- y.mli
     |       +-- z.ml
     |       +-- z.mli
     |       |
     |       ...
     |
     |
     +-- m3 -+
             +-- x.ml
             +-- x.mli
             +-- y.ml
             +-- y.mli
             +-- z.ml
             +-- z.mli
             |
             ...

Oasis也可能无法做到这一点。在这种情况下,关于如何使用其他构建工具的建议是可接受的并且是受欢迎的。假设我对其他工具的理解很少......因为它可能是真的!

1 个答案:

答案 0 :(得分:7)

带绿洲

pack中的oasis有点破碎,因为它通过将所有路径包含在搜索路径中来破坏命名空间。有一个长期存在的错误请求,但事情仍然存在。但是,如果它正常工作,它可以帮助您,因为它将创建一个库命名空间,允许您在不同的文件夹中具有相同名称的模块。但是,它不起作用,所以我们应该忘记它。

我们在BAP项目中采用的方法是使用丑陋的bap_subproject_前缀来破坏所有模块名称,以保护我们免受与我们自己的模块的冲突,以及来自外部库的冲突。对于每个bap_subproject,我们有一个文件夹,其中包含所有具有错位名称的实现模块和一个伞形模块来统治它们。此模块存储在文件bap_subproject.ml中,它定义了要导出的所有模块和类型的别名。通常它包含如下条目:

module X = Bap_subproject_x

还有一个很大的Bap项目,它将所有子库联合在一个名称空间Bap.Std下,然后重新导出它需要的所有内容,以便在一个open Bap.Std之后拥有并访问{{ 1}} Insn

中定义的模块

没有绿洲

免责声明:如果您使用插件扩展,此解决方案仍可以使用oasis。

我们在一个项目中使用过这种方法,遗憾的是闭源,所以我无法提供链接。每个子项目都存在于自己的子文件夹中,在它自己的命名空间内(我们在每个子文件夹中都有bap_disasm/bap_disasm_insn.ml[i]模块,没有任何破坏程序)。对于每个子项目,parser文件夹中都有一个mlpack文件:

top

root + | +-- expr.mlpack +-- expr -+ | +- lexer.* +- parser.* +- ast.* +- ... +-- cameo.mlpack +-- cameo-+ | +- lexer.* +- parser.* +- ast.* +- ... 的内容是:

expr.mlpack

expr/Lexer expr/Parser expr/Ast ... 将此ocamlbuild视为一个独立模块,其中定义了expr.mlpackLexer等子模块(并可作为Parser访问) )。并且与同时具有Expr.Lexer的兄弟项目没有冲突,也没有与Lexer或任何其他外部ocaml-libs冲突,因为Lexer文件夹实际上从不包含在搜索路径中。

如果您需要在系统中添加另一个图层,例如包装包,那么您有三种选择:

  1. 以递归方式使用相同的方法,即创建另一个超级文件夹,其中包含指向子文件夹的exprmlpack个文件。
  2. 只需添加引用所有toplevel mllib'ed modules
  3. big.mlpack
  4. 创建重新引入所有模块的mlpack
  5. 最后两种方法要求顶级打包模块当然具有不同的名称。但通常这是公平的。