制作顶层时,不允许模块名与内部编译器库冲突。
修复此类模块名称冲突有哪些策略?
理想情况下,是否可以将一些参数传递给ocamlc
,以指示它为" mangle"要使用MyProject_
等自定义前缀的所有模块的名称? (从OCaml ABI的角度来看,不是字面上改变源文件)
以下完整示例:
Sqrt.ml
包含
let sqrt x = x ** 0.5
Sqrt.mli
包含
val sqrt : float -> float
mktop
包含
#!/bin/bash
ocamlc -c Sqrt.mli -o Sqrt.cmi
ocamlc -c Sqrt.ml -o Sqrt.cmo
ocamlmktop -o sqrt_toplevel Sqrt.cmo
我可以制作一个包含我想要的功能的顶层。
% ./sqrt_toplevel
OCaml version 4.04.0
# Sqrt.sqrt 4.5;;
- : float = 2.12132034355964239
如果我通过更改文件名将Sqrt
模块重命名为Parse
,则该名称与内部库冲突,并且顶层无法链接。
mktop
现在
#!/bin/bash
ocamlc -c Parse.mli -o Parse.cmi
ocamlc -c Parse.ml -o Parse.cmo
ocamlmktop -o parse_toplevel Parse.cmo
将其他文件重命名为Parse.ml
和Parse.mli
。
如果我这样做,我会遇到与编译器库的命名冲突。
% ./mktop |& sed -e s:"$HOME":~:
File "Parse.cmo", line 1:
Warning 31: files Parse.cmo and ~/.opam/4.04.0/lib/ocaml/compiler-libs/ocamlcommon.cma(Parse) both define a module named Parse
File "_none_", line 1:
Error: Some fatal warnings were triggered (1 occurrences)
Exit 2
答案 0 :(得分:3)
除了使用与内部模块不冲突的名称之外,我没有看到记录的方法来避免此问题。
这是用于列出所有禁用名称的Unix命令,至少是:
$ cd ~/.opam/4.04.0/lib/ocaml/compiler-libs
$ ocamlobjinfo ocamlbytecomp.cma ocamlcommon.cma ocamltoplevel.cma |
awk '/^Unit name:/ { print $3}' | sort
对我来说(现在使用OCaml 4.03.0)有96个禁用名称。我写了一个脚本来验证所有96个都是真的被禁止。
作为旁注,事实上,尽管报告了错误,但仍然生成了顶层。并且,在快速测试中,它似乎有效。函数Parse.sqrt
(例如)存在并计算正确的答案。但可能还有一些我偶然遇到的问题。
答案 1 :(得分:2)
使用ocamlbuild,实现这一目标的一种标准方法是将模块封装到mlpack中,如下所述:http://l-lang.blogspot.fr/2012/12/using-ocaml-packages-with-ocamlbuild.html
文件:repo / A.ml
let a = 3;;
文件:repo / b.ml
let b = A.a;;
文件:repo.mlpack
repo/A
repo/B
文件:main.ml
Repo.B.b
这解决了名称冲突问题,但迫使您通过"超级模块访问您的模块"
答案 2 :(得分:1)
默认情况下,Dune / jbuilder会将您的模块包装到以库命名的包含模块中。虽然这不能为您提供正确的命名空间,但您只需确保您的库名称是唯一的。
sample project可以具有以下结构:
proj ├── Makefile ├── proj.opam ├── README.md ├── sub1 │ ├── lib │ │ ├── a.ml │ │ ├── a.mli │ │ ├── b.ml │ │ └── jbuild │ └── test │ ├── a.ml │ ├── b.ml │ └── jbuild ├── sub2 │ ├── bin │ │ ├── bar_main.ml │ │ ├── foo_main.ml │ │ └── jbuild │ ├── lib │ │ ├── a.ml │ │ └── jbuild │ └── test │ ├── a.ml │ └── jbuild └── test ├── jbuild └── run_tests.ml
请注意我们有多个a.ml
和b.ml
个文件。
jbuild
中的sub1/lib
文件是:
(jbuild_version 1) ; name = name of the supermodule that will wrap all source files as submodules ; public_name = name of the library for ocamlfind and opam (library ((name proj_sub1) (public_name proj.sub1) (libraries (unix)) (synopsis "This is a short description of the sub1 library.")))
这将导致模块Proj_sub1.A
和Proj_sub1.B
分别对应sub1/lib/a.ml
和sub2/lib/b.ml
。同样,我们还会构建Test_sub1.A
,Test_sub1.B
,Proj_sub2.A
等