Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am new to the OCaml and I'm confused with the file of .cma, .cmo and .cmx. Sometimes I have to include a .cma file in the compile command but sometimes I have to include a .cmo file.

Why is there a such difference for library? Is it the same concept in C++ as library and include path?

Example: ocamlc -o executable str.cma extstring.cmo mycode.ml

Thanks

like image 393
Quincy Hsieh Avatar asked Jun 10 '16 16:06

Quincy Hsieh


2 Answers

You may think that .cmo is library, but it's not.

  • .cmo is bytecode object file. It's like .class in Java.
  • .cma is bytecode library. It's produce by archiving some .cmo into .cma
  • .cmx is produced by ocamlopt (the native-code compiler). Main output files of ocamlopt is .o but ocamlopt also produce it.

To create executable files, we arrange .cmo and .cma like ocamlc -o executable lib.cma a.cmo b.cmo ... to link them.
You can write .ml here instead of .cmo but it's the same as compiling .ml with -c and link the .cmo and other files.


For your deep undestanding, it's better to check how each files (related to ocaml) are produced.
Let's see what files are produce by ocamlc and 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] 

Now I compiled test.ml file and compile it with ocamlc with -c option (the content of test.ml is not matter here). You see ocamlc outputs two files:

  • test.cmi: Compiled interface file. This file includes type information of functions, variables in test.ml for separate compilation.
  • test.cmo: Bytecode object file: It's like .class file in Java.

We use .cmo files to create executable files.

[/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

You see a.out file are produced via the .cmo file.

.cma are library files. These are produced by composing multiple .cmo files.

[/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

Now I create lib.ml (which use id function in test.ml) and compile test.ml and lib.ml, then link them to create testlib.cma (option -a means creating a library).
You can see .cma is just packed with .cmo files.

To use the library, we just arrange it with other object files.

[/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

Finally, let's check what files are produce by ocamlopt.

[/tmp/test] ocamlopt -c ./test.ml 
[/tmp/test] ls
test.cmi  test.cmx  test.ml  test.o

ocamlopt produces

  • test.o: Native object file
  • test.cmi: Compiled interaface file
  • test.cmx: Also native object file, but it is mainly used for inlining functions across files!!!
like image 173
nomaddo Avatar answered Nov 14 '22 22:11

nomaddo


So, the difference is here (when there's a x in the file extension, it means it's a native-code compiled object so that it runs faster. The cmx files are obtained with ocamlopt and the cmo files with ocamlc) :

  • .cma / .cmxa -> libraries that are already available for the programmer (standard libraries and libraries you installed)
  • .cmo / .cmx -> object files corresponding to your .ml files

TL;DR : .cm(x)a files were not created by you, .cm(o|x) files were.

like image 41
Lhooq Avatar answered Nov 14 '22 22:11

Lhooq