Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OCaml - compiling a program as a library

Tags:

ocaml

I have an OCaml program(with a main method - it generates an executable) and I want to use it as a library.

I was compiling my program like this: ocamlc -I someDir -g -unsafe lotsOfCmoFiles -o outputFile and the program works fine.

Now I'm removing the line that makes it an executable(something like let _ = ...) and adding -a parameter to compile command: ocamlc -a -I someDir -g -unsafe lotsOfCmoFiles -o outputFile.cma

But somehow I can't load generated .cma file with ocamltop and ocamlbrowser shows an empty list. When I try to load from ocamltop:

# #load "outputFile.cma";;
Error: Reference to undefined global `Xyz'

And I'm 100% sure that xyz.cmo is included in lotsOfCmoFiles.

Am I giving some parameter wrong while compiling? Or else, what should I do to load my program in ocamltop ? (I'll use this library in another program, I'm giving ocamltop outputs as an example)

Any helps will be appreciated.

EDIT: So I can finally managed to compile and load it thanks to @cago, now I can load my library, and when I don't remove the main let _ = ... line it's automatically run when I load the .cma.

But I still can't open any modules. Strangely, this doesn't raise an exception

open Main

but then when I call a function from module Main:

# someFun;;
Error: Reference to undefined global `Main'

and ocamlbrowse still shows an empty list. now why is that?

EDIT2: I realized open Main doesn't fail because I have a Main module in the same folder(even though I didn't explicitly load it). If I move my .cma file somewhere else and load it, it works(ie. main function runs automatically), but now I can't open any modules even though ocamlobjinfo shows the modules.

EDIT3: -I doesn't help:

$ ocaml
        OCaml version 4.00.1

# #load "lib.cma";;
ok
# open Lib;;
Error: Unbound module Lib
# 
$ ocaml -I libFolder    
        OCaml version 4.00.1

# #load "toylib.cma";;
ok
# open Lib;;
# fun;;
Error: Reference to undefined global `Lib'
like image 460
sinan Avatar asked Feb 18 '23 07:02

sinan


1 Answers

Some of the cmo in your lotsOfCmoFiles need to know the module Xyz. You need to take care of the dependency between your cmo files.

For example:

toto.ml:

let x = "toto"

titi.ml:

let y = Toto.x ^ " titi"

ocamlc -c toto.ml
ocamlc -c titi.ml
ocamlc -a  titi.cmo toto.cmo -o lib.cma (* here is  the probleme *)

# #load "lib.cma"
Error: Reference to undefined global `Toto'

Because titi depends on toto so you need to change the order of cmos:

ocamlc -a toto.cmo titi.cmo -o lib.cma 

# #load "lib.cma"
# Titi.y;;
 - : string = "toto titi"

EDIT:

If your cma is in a subdirectory for example, when you call ocaml you need to specify the path:

ocaml -I subdir/ (* subdir which contains lib.cma *)

# #load "lib.cma"
# Toto.x;;
- : string = "toto"
like image 129
Çağdaş Bozman Avatar answered Feb 19 '23 22:02

Çağdaş Bozman