Reputation: 7078
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'
Upvotes: 4
Views: 2829
Reputation: 4098
TL;DR: Make sure you don't have any top-level side-effects in the
I was running into this same kind of trouble. My project would build fine, most modules were available, but there was one module that kept triggering Reference to undefined global
. But it was clear that the module was visible to the system: it was showing up in utop
's autocomplete list, along with all of it's values, and I could reference it and import it into other modules.
The problem turned out to be an uncaught exception that was being thrown when that module was loaded. The exception was due to an attempt to load a non-existing file. It wouldn't cause problems during complication, but when the module was actually loaded it was breaking and the exception was being swallowed somewhere before I ever saw it.
Upvotes: 0
Reputation: 2540
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"
Upvotes: 8