【问题标题】:Compiling modules in different directories在不同目录中编译模块
【发布时间】:2019-11-07 22:29:30
【问题描述】:

我正在尝试按照这些说明编译一个依赖于我创建的另一个模块的模块:https://ocaml.org/learn/tutorials/modules.html

就我而言,我有一个模块 ~/courseFiles/chapter5/moduleA.ml 和另一个模块 ~/OCamlCommons/listMethods.ml。我使用ocamlopt -c listMethods.ml 编译了listMethods.ml,这似乎有效,它生成了一个文件listMethods.cmx

文件moduleA.ml 包含open ListMethods;;。现在我的终端位于~/courseFiles/chapter5,我运行ocamlopt -c moduleA.ml,但终端返回

错误:未绑定的模块 ListMethods

现在我可以理解它为什么会这样做,但该网站上的说明似乎表明我所做的就是你应该如何做到这一点。大概我在编译moduleA.ml时需要传入脚本或可执行文件的位置,但我不确定语法应该是什么。我尝试了一些猜测,并猜测如何使用ocamlfind 做到这一点,但我没有成功。我尝试查找有关编译位于不同目录中的模块的说明,但没有找到任何东西(或者任何我能理解的东西)。

【问题讨论】:

标签: ocaml ocamlfind


【解决方案1】:

首先,OCaml System Distribution 附带的工具包(又名编译器)非常通用,但级别很低,应该被视为构建更高级别构建系统的基础层。因此,学习它非常困难,而且通常只有在您要构建这样的系统时才有意义。学习如何使用duneoasisocamlbuild 会更容易。此外,它会使您的注意力从真正重要的事情上转移 - 学习语言。

说了这么多,让我详细回答你的问题。 OCaml 实现了一个单独的编译方案,其中每个编译单元可以独立构建,然后链接到单个二进制文件中。这种方案在 C/C++ 语言中很常见,实际上 OCaml 编译器工具链与 C 编译器工具链非常相似。

当您运行ocamlopt -c x.ml 时,您正在创建一个编译单元,因此会生成一些文件,即:

  • x.o - 实际上包含已编译的机器代码
  • x.cmx - 包含优化数据和其他编译器特定信息
  • x.cmi - 包含模块 X 的编译接口。

为了编译一个模块,编译器不需要该模块中使用的任何其他模块的代码。但它需要的是输入信息,即它需要知道List.find 函数的类型,或者由模块外部的某个模块提供的任何其他函数的类型。此信息存储在 cmi 文件中,C/C++ 中的(编译的)头文件是最接近的对应文件。与在 C/C++ 中一样,编译器在包含搜索路径中搜索它们,默认情况下包括当前目录和标准库的位置,但可以使用 -I 选项进行扩展(与 C/C++ 中相同) )。因此,如果您的模块正在使用文件夹 A 中定义的另一个模块,您需要告诉编译器在哪里搜索它,例如,

 ocamlopt -I A -c x.ml

生成的目标文件将不包含来自外部模块的任何代码。因此,一旦您到达编译的最后阶段 - 链接阶段,您必须提供实现,例如,如果您的模块 X 使用在具有相对路径 A/y.ml 的文件中实现的模块,并且您已经编译它在那个文件夹中,那么你需要再次指定编译实现的位置,例如,

 ocamlopt -I A y.cmx x.cmx -o exe

顺序很重要,一个模块使用的所有模块都应该在该模块之前指定,否则你会得到“没有提供实现”的错误。

如您所见,这是一个相当复杂的过程,花时间学习它真的不值得。因此,如果您可以选择,请使用更高级别的工具来构建您的程序。如果不确定,请选择沙丘:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多