我是OCaml的新手,我对 .cma , .cmo 和 .cmx 的文件感到困惑。有时我必须在编译命令中包含.cma文件,但有时我必须包含.cmo文件。
为什么图书馆会有这样的差异?它是C ++中与库相同的概念并包含路径吗?
示例:ocamlc -o executable str.cma extstring.cmo mycode.ml
由于
答案 0 :(得分:6)
您可能认为.cmo
是图书馆,但事实并非如此。
.cmo
是字节码对象文件。它就像Java中的.class
。.cma
是字节码库。通过将.cmo
归档到.cma
.cmx
由ocamlopt
(本机代码编译器)生成。 ocamlopt
的主要输出文件为.o
,但ocamlopt
也会生成它。要创建可执行文件,我们会安排.cmo
和.cma
ocamlc -o executable lib.cma a.cmo b.cmo ...
来链接它们。
您可以在此处写.ml
而不是.cmo
,但它与使用.ml
编译-c
并将.cmo
和其他文件相关联。
对于你的深层未定,最好检查每个文件(与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
(使用id
中的test.ml
功能)并编译test.ml
和lib.ml
,然后将它们链接到创建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
:也是原生对象文件,但它主要用于跨文件内联函数!!! 答案 1 :(得分:1)
所以,区别在于(当文件扩展名中有x
时,这意味着它是本机代码编译对象,因此它运行得更快。cmx
文件是使用ocamlopt
和cmo
文件ocamlc
获得的:
.cma
/ .cmxa
- >已经可供程序员使用的库(您安装的标准库和库).cmo
/ .cmx
- >与.ml文件对应的目标文件 TL; DR :.cm(x)a
文件不是由您创建的,.cm(o|x)
文件是。