Include OCaml binary library - ocaml

I'm trying to use the OcamlGraph library and it's not clear to me how to add it to my project. It was suggested to me that I just compile the source of the library along with the source of my project, but there has to be some way of linking the binary of a precompiled library without using OPAM. Can this be done, and if so, how?
Thanks.

compiling:
ocamlc -I /path/to/ocamlgraph -c mysource.ml
(as suggested by ocamlfind ocamlc -package ocamlgraph -c -only-show, if ocamlfind and ocamlgraph are installed)
linking:
ocamlc -I /path/to/ocamlgraph /path/to/ocamlgraph/graph.cma mysource.cmo -o test.byte
(as suggested by ocamlfind ocamlc -linkpkg -package ocamlgraph -only-show )
But normally, you should use ocamlfind and the ocamlgraph package of opam or your distribution.

Related

How to transform the Yojson Library of Ocaml into a .byte file using js_of_ocaml?

I am trying to transform the Yojson with the source code download online into a byte file using js_of_ocaml.
I try the following commands:
%: ocamlfind ocamlc -package yojson -linkpkg -g -o yojson.cmo
%: ocamlfind ocamlc -package js_of_ocaml -package js_of_ocaml-ppx -linkpkg -g -o -package yojson yojson.byte
I am trying to compile into bytecode an OCaml file but it give the following error:
%: ocamlfind ocamlc -package js_of_ocaml -package js_of_ocaml-ppx -linkpkg -o preprocessing.byte preprocessing.ml
File "preprocessing.ml", line 4, characters 5-22:
4 | open Yojson.Basic.Util
^^^^^^^^^^^^^^^^^
Error: Unbound module Yojson
The OCaml compiler will not use any compilation units that are not specified on the command line. In addition, you have to specify them in a correct order, so that a user of a unit will come after that unit, e.g.,
ocamlfind ocamlc -package js_of_ocaml -package js_of_ocaml-ppx -linkpkg -o preprocessing.byte yojson.cmo preprocessing.ml
Also, your invocation,
ocamlfind ocamlc -package yojson -linkpkg -g -o yojson.cmo
is incorrect and should issue an error. You need to specify the -c option to generate the object file.
With that said, you don't need to do what you're doing at all, like building yojson manually (you could install from opam). In fact, it is much better to use a high-level tool, like dune to build your js_of_ocaml programs. The dune documentation provides detailed instructions on how to do this

Required module 'Yojson' is unavailable without location

I am trying to build a simple program using Yojson: the main.ml file is just
let () = exit 1;
and an mod.ml file contains
open Yojson
open Yojson.Basic.Util
let rec json_to_tree json =
let _ = json |> member "key" in
()
I have a Makefile which first compiles .ml files, then links. For simplicity, let assume we run the three following commands:
ocamlfind ocamlc -package yojson -g -c mod.ml
ocamlfind ocamlc -package yojson -g -c main.ml
ocamlfind ocamlc -package yojson -g -o inter mod.cmo main.cmo
The problem is that the linking part produces the following error:
File "_none_", line 1:
Error: Required module `Yojson' is unavailable
which I have no idea to solve. Using the Unix module can lead to similar error which are resolved adding unix.cma when linking, but this doesn't help for Yojson.
For the sake of completeness, I installed yojson via opam, and ocamlfind list | grep yojson returns
yojson (version: 1.3.3)
yojson.biniou (version: 1.3.3)
This works.
ocamlfind ocamlc -package yojson -linkpkg -g -o inter mod.cmo main.cmo
While this works, https://github.com/ocaml/dune is the better option to building ocaml code.

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
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!!!
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.

Why doesn't corebuild work with absolute paths?

I was using ocamlc.opt like this:
ocamlc.opt -I /home/foo/bar/baz -c foo.ml
I thought I could do the same with corebuild:
ocamlc.opt -I /home/foo/bar/baz -c foo.ml
But that throws an error:
Failure:
Included or excluded directories must be implicit (not "/home/foo/bar/baz").
AFAIR, corebuild does some internal directory re-ordering and explicit paths break its re-ordering algorithm.

Build native executable with profile information using Ocamlbuild

How to build with enabled profile information using Ocamlbuild? It seems -p doesn't work there.
Now, I use ocamlopt for this. For example,
$ ocamlfind ocamlopt -c -p -thread -package core test.ml
$ ocamlfind ocamlopt -p -o test -thread -package core -linkpkg test.cmx
How to do the same with
ocamlbuild -user-ocamlfind test.native
You can pass the argument explicitly,
ocamlbuild -cflags -p
or in your _tags file,
true : profile
There is also a rule for the file-name,
ocamlbuild test.p.native