简体   繁体   English

在不同目录中编译模块

[英]Compiling modules in different directories

I'm trying to follow these instructions to compile a module that depends on another module which I've created: https://ocaml.org/learn/tutorials/modules.html 我正在尝试按照以下说明来编译依赖于我创建的另一个模块的模块: https : //ocaml.org/learn/tutorials/modules.html

In my case, I have a module ~/courseFiles/chapter5/moduleA.ml and another module in ~/OCamlCommons/listMethods.ml . 就我而言,我有一个模块~/courseFiles/chapter5/moduleA.ml和另一个模块~/OCamlCommons/listMethods.ml I have compiled listMethods.ml using ocamlopt -c listMethods.ml and this seemed to work, it produced a file listMethods.cmx . 我已经使用ocamlopt -c listMethods.ml编译了listMethods.ml ,这似乎可行,它生成了一个listMethods.cmx文件。

The file moduleA.ml contains open ListMethods;; 文件moduleA.ml包含open ListMethods;; . Now with my terminal located at ~/courseFiles/chapter5 I ran ocamlopt -c moduleA.ml but the terminal returns 现在,我的终端位于~/courseFiles/chapter5我运行ocamlopt -c moduleA.ml但是终端返回

Error: Unbound module ListMethods 错误:未绑定的模块ListMethods

Now I can understand why it would do this, but the instructions at that site seem to indicate that what I've done is how you're supposed to do this. 现在我可以理解为什么会这样做了,但是该站点上的说明似乎表明我所做的就是您应该如何做。 Presumably I need to pass in the location of either the script or executable files when compiling moduleA.ml , but I'm not sure what the syntax should be. 大概在编译moduleA.ml时需要传递脚本或可执行文件的位置,但是我不确定语法应该是什么。 I've tried a few guesses, and guessed about how I could do this with ocamlfind but I haven't succeeded. 我尝试了一些猜测,并猜测了如何用ocamlfind可以做到这一点,但我没有成功。 I tried looking for instructions on compiling modules located in different directories but didn't find anything (or anything I can make sense of anyway). 我试图寻找有关编译位于不同目录中的模块的说明,但未找到任何内容(或任何我可以理解的内容)。

First of all, the toolkit that is shipped with the OCaml System Distribution (aka the compiler) is very versatile but quite low-level and should be seen as a foundation layer for building more high-level build systems. 首先,OCaml System Distribution(又名编译器)附带的工具包功能非常丰富,但级别很低,应被视为构建更多高级构建系统的基础层。 Therefore, learning it is quite hard and usually makes sense only if you're going to build such systems. 因此,学习它非常困难,并且通常只有在要构建这样的系统时才有意义。 It is much easier to learn how to use dune or oasis or ocamlbuild instead. 学习如何使用沙丘绿洲ocamlbuild 容易得多 Moreover, it will diverge your attention from what actually matters - learning the language. 此外,它将使您的注意力从真正重要的部分上分散下来-学习语言。

With all that said, let me answer your question in full details. 综上所述,让我详细回答您的问题。 OCaml implements a separate compilation scheme, where each compilation unit could be built independently and then linked into a single binary. OCaml实现了一个单独的编译方案,其中每个编译单元可以独立构建,然后链接到单个二进制文件中。 This scheme is common in C/C++ languages, and in fact, OCaml compiler toolchain is very similar to the C compiler toolchain. 这种方案在C / C ++语言中很常见,实际上,OCaml编译器工具链与C编译器工具链非常相似。

When you run ocamlopt -c x.ml you're creating a compilation unit, and as a result a few files are produced, namely: 当您运行ocamlopt -c x.ml您正在创建一个编译单元,因此产生了一些文件,即:

  • xo - contains actually the compiled machine code xo实际上包含已编译的机器代码
  • x.cmx - contains optimization data and other compiler-specific information x.cmx包含优化数据和其他特定于编译器的信息
  • x.cmi - contains compiled interface to the module X . x.cmi包含模块X编译接口。

In order to compile a module, the compiler doesn't need the code of any other modules used in that module. 为了编译模块,编译器不需要该模块中使用的任何其他模块的代码。 But what it needs is the typing information, ie, it needs to know what is the type of List.find function, or a type of any other function that is provided by some module which is external to your module. 但是它需要的是类型信息,即它需要知道List.find函数的类型是什么,或者模块外部某个模块提供的任何其他函数的类型。 This information is stored in cmi files, for which (compiled) header files from C/C++ is the closest counterpart. 此信息存储在cmi文件中,对于这些文件,来自C / C ++的(已编译)头文件是最接近的对应文件。 As in C/C++ the compiler is searching for them in the include search path, which by default includes the current directory and the location of the standard library, but could be extended using the -I option (the same as in C/C++). 与在C / C ++中一样,编译器将在include搜索路径中搜索它们,默认情况下,该路径包括当前目录和标准库的位置,但是可以使用-I选项进行扩展(与C / C ++中的相同) 。 Therefore, if your module is using another module defined in a folder A you need to tell the compiler where to search for it, eg, 因此,如果您的模块正在使用文件夹A定义的另一个模块,则需要告诉编译器在哪里搜索它,例如,

 ocamlopt -I A -c x.ml

The produced objective file will not contain any code from external modules. 产生的目标文件将不包含来自外部模块的任何代码。 Therefore, once you will reach the final stage of compilation - the linking phase, you have to provide the implementation, eg, if your module X was using a module implemented in a file with relative path A/y.ml , and you have compiled it in that folder, then you need to specify again the location of the compiled implementation, eg, 因此,一旦到达编译的最后阶段(链接阶段),就必须提供实现,例如,如果模块X使用的是在相对路径为A/y.ml的文件中实现的模块,并且已经编译了它在该文件夹中,那么您需要再次指定已编译实现的位置,例如,

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

The order is important, all modules used by a module should be specified before that module, otherwise, you will get the "No implementations provided" error. 顺序很重要,一个模块使用的所有模块应在该模块之前指定,否则,将出现“未提供实现”错误。

As you can see, it is a pretty convoluted process, and it is really not worthwhile to invest your time in learning it. 如您所见,这是一个非常复杂的过程,花时间去学习它确实不值得。 So, if you have an option, then use a higher-level tool to build your programs. 因此,如果有选择,请使用更高级别的工具来构建程序。 If not sure, then choose Dune :) 如果不确定,请选择“沙丘” :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM