假设我有一组模块,每个模块都与子模块相当"浓密".
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
现在,很容易构建项目目录为每个M1
,M2
以及M3
使用绿洲Pack:
选项.特别是,我喜欢和想要解决的是(a)能够以标准.ml
/ .mli
格式布置我的文件和(b)ocamldoc
生成正确链接的文档.
但因为我想分配每个M1
,M2
以及M3
在一个共同的模块层次结构下的同一个库,我不能用Pack:
和我,而不是被迫扔掉整个该死的东西到一个文件中,以(一)不小心揍全球命名空间,(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可能无法做到这一点.在这种情况下,关于如何使用其他构建工具的建议是可接受的并且是受欢迎的.假设我对其他工具的理解很少......因为它可能是真的!
在pack
在oasis
是有点坏了,因为它通过包括所有的路径到搜索路径则会覆盖的命名空间.有一个长期存在的错误请求,但事情仍然存在.但是,如果它正常工作,它可以帮助您,因为它将创建一个库命名空间,允许您在不同的文件夹中具有相同名称的模块.但是,它不起作用,所以我们应该忘记它.
我们在BAP项目中采用的方法是使用丑陋的bap_subproject_
前缀来破坏所有模块名称,以保护我们免受与我们自己的模块的冲突,以及来自外部库的冲突.对于每个bap_subproject
我们都有一个文件夹,其中包含所有具有错位名称的实现模块和一个伞形模块来统治它们.此模块存储在文件bap_subproject.ml
中,用于定义要导出的所有模块和类型的别名.通常它包含以下条目:
module X = Bap_subproject_x
还有一个大Bap
项目,它将所有子库联合在一个名称空间下Bap.Std
,并重新导出它所需的一切,以便在open Bap.Std
您拥有并访问Insn
所定义的模块之后bap_disasm/bap_disasm_insn.ml[i]
免责声明:如果您使用插件扩展它,此解决方案仍可以使用oasis.
我们在一个项目中使用过这种方法,遗憾的是闭源,所以我无法提供链接.每个子项目都在自己的子文件夹中,在它自己的命名空间内(我们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.mlpack
作为具有独立的模块Lexer
,Parser
等在它定义子模块(以及访问,例如,Expr.Lexer
).并且与兄弟项目没有冲突,也Lexer
没有冲突ocaml-libs
或与任何其他外部冲突Lexer
,因为expr
文件夹实际上从未包含在搜索路径中.
如果您需要在系统中添加另一个图层,例如包装包,那么您有三个选择:
以递归方式使用相同的方法,即创建另一个超级文件夹,其中包含指向子文件夹的文件mlpack
或mllib
文件.
只需添加big.mlpack
引用所有toplevel'ed mlpack
模块
创建big.ml
,重新引入所有模块.
最后两种方法要求顶级打包模块当然具有不同的名称.但通常这是公平的.