Compilation 编译多个Ocaml文件

Compilation 编译多个Ocaml文件,compilation,ocaml,Compilation,Ocaml,我是Ocaml新手,正在尝试编写一些小示例应用程序。我正在使用Linux Ubuntu 10.04下的ocamlc3.11.2版。我想编译两个文件: a.ml b.ml 文件b.ml使用a.ml中的定义。据我所知,我只能使用ocamlc-c执行编译。当我拥有所有.cmo文件时,我可以最后一次调用ocamlc,将它们链接到可执行文件。此外,在编译使用其他文件定义的文件时,我必须告诉编译器在哪个.cmi文件中查找外部定义 所以我的想法是使用: ocamlc -i -c a.ml > a.ml

我是Ocaml新手,正在尝试编写一些小示例应用程序。我正在使用Linux Ubuntu 10.04下的
ocamlc
3.11.2版。我想编译两个文件:

a.ml
b.ml
文件
b.ml
使用
a.ml
中的定义。据我所知,我只能使用
ocamlc-c
执行编译。当我拥有所有
.cmo
文件时,我可以最后一次调用
ocamlc
,将它们链接到可执行文件。此外,在编译使用其他文件定义的文件时,我必须告诉编译器在哪个
.cmi
文件中查找外部定义

所以我的想法是使用:

ocamlc -i -c a.ml > a.mli
ocamlc -c a.mli b.ml
ocamlc -o b a.cmo b.cmo
第一步工作并生成文件
a.mli
a.cmo
,但运行第二步时,我得到

File "b.ml", line 1, characters 28-31:
Error: Unbound value foo
其中
foo
是在
a.ml
中定义并在
b.ml
中调用的函数

所以我的问题是:如何分别编译每个源文件并指定要在命令行上导入的接口?我一直在查看文档,据我所知,我必须指定要包含的
.mli
文件,但我不知道如何操作

编辑

这里有更多的细节。文件
a.ml
包含定义

let foo = 5;;
文件
b.ml
包含表达式

print_string (string_of_int foo) ^ "\n";;
真实的例子更大,但有了这些文件,我已经有了我上面报告的错误

编辑2


我已经编辑了文件
b.ml
,并用
A.foo
替换了
foo
,这很有效(foo在
b.ml
中可见,即使我有另一个编译错误,这对这个问题并不重要)。我想明确地编写自己的
.mli
文件会更清晰,正如

所建议的那样,如果您显示了不起作用的代码,则会更清晰。不过,正如克里斯托弗指出的,最可能的问题是您没有指定哪个模块
foo
。您可以显式指定模块,如
A.foo
。或者您可以
打开一个
,只需使用名称
foo


对于一个小例子来说,这并不重要,但是对于一个大项目,你应该小心不要太随意地使用
open
。您希望在模块中自由使用好的名称,如果您打开的名称太多,好的名称可能会相互冲突。

首先解决
未绑定值的问题,正如Jeffrey的回答所解释的那样。
这是关于您正在使用的命令的注释

将编译分解为几个步骤是了解发生了什么的好方法。 若您想编写自己的
a.mli
,很可能会隐藏模块
a
的一些值,那个么您的命令
ocaml-i-ca.ml>a.mli
是获取此文件的第一个版本并对其进行编辑的好方法。但是如果您没有触摸a.mli,那么您不需要生成它:您也可以直接输入

ocamlc -o foo a.ml b.ml
这将产生
a.cmo
b.cmo
和可执行的
foo

(它还将生成
a.cmi
,这是通过发布
ocamlc-c a.mli
获得的
a.mli
的编译版本。同样,它还将生成
b.cmi

请注意,顺序很重要:您需要在命令行上的
b.ml
之前提供
a.ml
。这样,在编译
b.ml
时,编译器已经看到了
a.ml
,并且知道在哪里可以找到模块
a


还有一些评论:

  • 你的“据我所知”一段是对的
  • 您实际上不包括单独的文件,它更像Python中的导入:模块
    a
    的值可用,但名称为
    a.foo
    a.ml
    的内容尚未复制粘贴到
    b.ml
    中,而是访问了
    a.ml
    中定义的模块
    a
    的值及其编译版本
    a.cmo
  • 如果您在
    b.ml
    中使用此模块
    A
    ,则可以在
    b.ml
    之前在命令行上传递以下任意命令:
    • a.mli
      ,它将被编译成
      a.cmi
    • a.cmi
      如果您已经将
      a.mli
      编译成
      a.cmi
    • a.ml
      或其编译版本
      a.cmo
      ,如果您不需要编写自己的
      a.mli
      ,即如果模块
      a
      的默认界面适合您。(此接口只是
      a.ml
      的每个值)

您是否在B中打开了A?因为否则这没有意义。否。我必须在a中定义一个模块并在B中打开它吗?目前,A中的所有定义都是全局的(我没有模块),每个OCaml文件都有一个隐式模块。因此,您的文件
a.ml
定义了一个名为
a
的模块。