.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
中产生的
.cmx
由 ocamlopt
(本机代码编译器)生成。 ocamlopt
的主要输出文件是 .o
但 ocamlopt
也会产生它。
为了创建可执行文件,我们将 .cmo
和 .cma
排列成 ocamlc -o executable lib.cma a.cmo b.cmo ...
到 link 它们。
您可以在此处编写 .ml
而不是 .cmo
,但这与使用 -c
和 link、.cmo
和其他文件编译 .ml
相同。
为了你的深刻理解,最好检查一下每个文件(与ocaml相关)是如何产生的。
让我们看看 ocamlc
和 ocamlopt
.
生成了哪些文件
[/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.ml
和 lib.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
:也是原生目标文件,但主要用于跨文件内联函数!!!
我是 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
中产生的
.cmx
由ocamlopt
(本机代码编译器)生成。ocamlopt
的主要输出文件是.o
但ocamlopt
也会产生它。
为了创建可执行文件,我们将 .cmo
和 .cma
排列成 ocamlc -o executable lib.cma a.cmo b.cmo ...
到 link 它们。
您可以在此处编写 .ml
而不是 .cmo
,但这与使用 -c
和 link、.cmo
和其他文件编译 .ml
相同。
为了你的深刻理解,最好检查一下每个文件(与ocaml相关)是如何产生的。
让我们看看 ocamlc
和 ocamlopt
.
[/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.ml
和 lib.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
:也是原生目标文件,但主要用于跨文件内联函数!!!