2012-10-07 124 views
5

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

a.ml 
b.ml 

文件b.ml使用的定义从a.ml。据我所知,我只能使用ocamlc -c来执行编译。当我将所有.cmo文件链接到可执行文件时,我可以最后一次致电ocamlc。另外,编译使用另一个文件定义的文件时,我必须告诉编译器在哪个文件中找到外部定义。

所以我的想法是使用:

ocamlc -i -c a.ml > a.mli 
ocamlc -c a.mli b.ml 
ocamlc -o b a.cmo b.cmo 

的第一步作品,并产生文件a.mlia.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";; 

真正的例子是大,但这些文件我已经有我上面报告错误的定义。

EDIT 2

我已经编辑文件b.mlA.foo更换foo和这个工程(foo是可见b.ml即使我有另一个编译错误,这并不重要,这个问题)。我想这是明确写我自己的.mli文件,如

+1

您是否打开A中的B ?,因为否则这没有任何意义。 –

+0

不需要在A中定义一个模块并在B中打开它吗?目前,A中的所有定义都是全局的(我没有模块)。 – Giorgio

+1

每个OCaml文件都有一个隐式模块。所以你的文件'a.ml'定义了一个名为'A'的模块。 –

回答

5

建议,如果你显示的代码不工作,这将更清晰。正如Kristopher指出的那样,最可能的问题是您没有指定模块foo所在的模块。您可以明确指定模块,如A.foo。或者您可以使用open A,并使用名称foo

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

5

首先修复unbound value问题,正如Jeffrey的答案所解释的那样。 这是对您正在使用的命令的评论。

分几步分解编译是了解发生了什么的好方法。 如果你想编写你自己的a.mli,最有可能隐藏模块A的一些值,那么你的命令ocaml -i -c a.ml > a.mli是获得该文件的第一版本然后编辑它的好方法。但是,如果你不接触a.mli,那么你并不需要生成它:您也可以直接输入

ocamlc -o foo a.ml b.ml 

这将产生a.cmob.cmo和exectuable foo

(这也将产生a.cmi,这是a.mli的编译版本,您通过发行ocamlc -c a.mli得到,同样也会产生b.cmi)。

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


一些更多的评论:

  • 你就在你 “据我了解” 的段落。
  • 你真的不包括一个单独的文件,它更像进口在Python:模块A的值是可用的,但在名称A.fooa.ml的内容尚未被复制粘贴到b.ml中,而是访问了a.ml中定义的模块A的值以及编译后的版本a.cmo
  • 如果你在b.ml使用此模块A,您可以b.ml前通过任何命令行上以下内容:
    • a.mli,如果你已经将编译到a.cmi
    • a.cmi编译a.mlia.cmi
    • a.ml或它的编译版本a.cmo,如果你不需要编写自己的a.mli,也就是说,如果模块的默认界面适合你。 (这个接口只是每个值a.ml)。