我正在使用这些文件测试单独的编译:
testmoda.ml
module Testmoda = struct
let greeter () = print_endline "greetings from module a"
end
Run Code Online (Sandbox Code Playgroud)
testmodb.ml
module Testmodb = struct
let dogreet () = print_endline "Modul B:"; Testmoda.greeter ()
end
Run Code Online (Sandbox Code Playgroud)
testmod.ml
let main () =
print_endline "Calling modules now...";
Testmoda.greeter ();
Testmodb.dogreet ();
print_endline "End."
;;
let _ = main ()
Run Code Online (Sandbox Code Playgroud)
现在我生成.mli文件
ocamlc -c -i testmoda.ml >testmoda.mli
Run Code Online (Sandbox Code Playgroud)
和testmoda.cmi在那里.
接下来,我创建.cmo文件没有错误:
ocamlc -c testmoda.ml
Run Code Online (Sandbox Code Playgroud)
很好,所以使用testmodb.ml也一样:
strobel@s131-amd:~/Ocaml/ml/testmod> ocamlc -c -i testmodb.ml >testmodb.mli
File "testmodb.ml", line 3, characters 45-61:
Error: Unbound value Testmoda.greeter
Run Code Online (Sandbox Code Playgroud)
另一个尝试:
strobel@s131-amd:~/Ocaml/ml/testmod> ocamlc -c testmoda.cmo testmodb.ml
File "testmodb.ml", line 3, characters 45-61:
Error: Unbound value Testmoda.greeter
Run Code Online (Sandbox Code Playgroud)
其他组合也失败了.
我如何编译testmodb.ml和testmod.ml?这应该很容易 - 没有ocamlbuild/omake/oasis,我想.
排除文件中的语法错误,如果我将它们一起捕获到一个文件(中间需要的空间),它就会编译并完美地执行.
OCaml在每个源文件的顶层为您提供免费模块.因此,您的第一个模块实际上已命名Testmoda.Testmoda,该函数已命名Testmoda.Testmoda.greeter,依此类推.如果您的文件只包含函数定义,那么事情会更好.
作为ocamlc -i旁注,如果你打算使用生成的界面,你真的不需要mli文件.缺少mli文件时的接口与生成的接口相同ocamlc -i.如果您不想使用默认界面,则使用ocamlc -i为mli文件提供了一个很好的起点.但是对于这样一个简单的例子,它只是使事情看起来比实际上复杂得多(恕我直言).
如果您按照我的描述修改文件(删除额外的模块声明),您可以从头开始编译和运行,如下所示:
$ ls
testmod.ml testmoda.ml testmodb.ml
$ cat testmoda.ml
let greeter () = print_endline "greetings from module a"
$ cat testmodb.ml
let dogreet () = print_endline "Modul B:"; Testmoda.greeter ()
$ ocamlc -o testmod testmoda.ml testmodb.ml testmod.ml
$ ./testmod
Calling modules now...
greetings from module a
Modul B:
greetings from module a
End.
Run Code Online (Sandbox Code Playgroud)
如果您已经编制了一份文件(ocamlc -c file.ml)可以代替.ml用.cmo在上面的命令.即使所有文件名都是.cmo文件,这也可以工作; 在那种情况下,ocamlc只是将它们链接在一起.