.cma、.cmo、.cmx 文件之间的区别以及如何在编译中正确使用它们?

Difference between .cma, .cmo, .cmx files and how to use them correctly in compilation?

我是 OCaml 的新手,我对 .cma.cmo 和 [=18= 的文件感到困惑.cmx。有时我必须在编译命令中包含一个 .cma 文件,但有时我必须包含一个 .cmo 文件。

为什么图书馆会有这样的差异? C++中的library和include path是同一个概念吗?

示例:ocamlc -o 可执行文件 str.cma extstring.cmo mycode.ml

谢谢

所以,区别就在这里(当文件扩展名中有x时,表示它是本机代码编译对象,因此运行速度更快。cmx文件是通过ocamlopt 和带有 ocamlc) 的 cmo 文件:

  • .cma / .cmxa -> 已经可供程序员使用的库(标准库和您安装的库)
  • .cmo / .cmx -> 与您的 .ml 文件对应的目标文件

TL;DR : .cm(x)a 个文件不是您创建的,.cm(o|x) 个文件是您创建的。

您可能认为 .cmo 是图书馆,但它不是。

  • .cmo 是字节码目标文件。就像 Java 中的 .class
  • .cma 是字节码库。它是通过将一些 .cmo 归档到 .cma
  • 中产生的
  • .cmxocamlopt(本机代码编译器)生成。 ocamlopt 的主要输出文件是 .oocamlopt 也会产生它。

为了创建可执行文件,我们将 .cmo.cma 排列成 ocamlc -o executable lib.cma a.cmo b.cmo ... 到 link 它们。
您可以在此处编写 .ml 而不是 .cmo,但这与使用 -c 和 link、.cmo 和其他文件编译 .ml 相同。


为了你的深刻理解,最好检查一下每个文件(与ocaml相关)是如何产生的。
让我们看看 ocamlcocamlopt.

生成了哪些文件
[/tmp/test] ls
test.ml
[/tmp/test] cat ./test.ml 
let id x = x
[/tmp/test] ocamlc -c /tmp/test/test.ml 
[/tmp/test] ls
test.cmi  test.cmo  test.ml
[/tmp/test] 

现在我编译了 test.ml 文件并用 ocamlc-c 选项编译它 (test.ml 的内容在这里无关紧要)。 你看到 ocamlc 输出两个文件:

  • test.cmi:编译接口文件。此文件包含函数的类型信息,test.ml中的变量用于单独编译。
  • test.cmo:字节码目标文件:类似于 Java.
  • 中的 .class 文件

我们使用 .cmo 个文件来创建可执行文件。

[/tmp/test] ocamlc -c test.ml 
[/tmp/test] ocamlc -o a.out test.cmo
[/tmp/test] ls
a.out  test.cmi  test.cmo  test.ml

您看到 a.out 文件是通过 .cmo 文件生成的。

.cma 是库文件。这些是通过组合多个 .cmo 个文件生成的。

[/tmp/test] ls
test.ml lib.ml
[/tmp/test] cat lib.ml 
let i = Test.id 1
let j = Test.id 2
[/tmp/test] ocamlc -c test.ml; ocamlc -c lib.ml
[/tmp/test] ls
lib.cmi  lib.cmo  lib.ml  test.cmi  test.cmo  test.ml
[/tmp/test] ocamlc -a -o testlib.cma ./test.cmo lib.cmo
[/tmp/test] ls
lib.cmi  lib.cmo  lib.ml  test.cmi  test.cmo  test.ml  testlib.cma

现在我创建 lib.ml(它在 test.ml 中使用 id 函数)并编译 test.mllib.ml,然后 link 它们创建 testlib.cma(选项 -a 表示创建库)。
您可以看到 .cma 只包含 .cmo 个文件。

要使用该库,我们只需将其与其他目标文件排列即可。

[/tmp/test] cat user.ml
let _ = print_int (Lib.i + Lib.j)
[/tmp/test] ocamlc -c user.ml
[/tmp/test] ocamlc -o a.out testlib.cma user.cmo

最后,让我们检查一下 ocamlopt.

生成的文件
[/tmp/test] ocamlopt -c ./test.ml 
[/tmp/test] ls
test.cmi  test.cmx  test.ml  test.o

ocamlopt 产生

  • test.o: 本机对象文件
  • test.cmi: 编译界面文件
  • test.cmx:也是原生目标文件,但主要用于跨文件内联函数!!!