Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking a library via ocamlbuild/ocamlfind

I have a locally pinned OPAM project called ojasmine which I want to compile as a library to be used by another project called test_tournabox (ultimately compiling to javascript). However, the compilation of test_tournabox is failing with a link error.

I compile ojasmine as follows, giving the target ojasmine.cma:

ocamlbuild -cflag -annot -use-ocamlfind -pkgs js_of_ocaml.log,js_of_ocaml,js_of_ocaml.syntax -syntax camlp4o ojasmine.cma
Finished, 5 targets (5 cached) in 00:00:00.

Then I install it like so:

ocamlfind install ojasmine META _build/ojasmine.cma

I found it strange that ojasmine.cma was not in my project directory, but instead is in the _build directory.

The output is:

Installed /home/laheadle/.opam/4.02.0/lib/ojasmine/ojasmine.cma
Installed /home/laheadle/.opam/4.02.0/lib/ojasmine/META

Next, I cd to my tournabox project and try to build the test suite:

ocamlbuild -cflag -annot -use-ocamlfind -pkgs js_of_ocaml.log,js_of_ocaml,js_of_ocaml.syntax,ojasmine -syntax camlp4o test_tournabox.byte
+ ocamlfind ocamlc -linkpkg -syntax camlp4o -package ojasmine -package js_of_ocaml.syntax -package js_of_ocaml -package js_of_ocaml.log choice.cmo util.cmo entry.cmo ttypes.cmo columns.cmo countries.cmo country_group.cmo jsutil.cmo performance_group.cmo round_group.cmo seed_group.cmo tlog.cmo tourney.cmo tournabox_lib.cmo test_tournabox.cmo -o test_tournabox.byte

This fails with the error:

Error: Error while linking test_tournabox.cmo:
Reference to undefined global `Ojasmine'

It seems that ojasmine.cma is not linked into the executable test_tournabox.byte. But I would expect the -linkpkg argument to ocamlfind to arrange for this. What am I missing?

Edit: Here is the META File:

description = "Unit Tests for javascript"
requires = "js_of_ocaml,js_of_ocaml.syntax"
version = "0.1"

Here is ocamlobjinfo:

trusty)laheadle@localhost:~/ocaml/ojasmine$ ocamlobjinfo _build/ojasmine.cma 
File _build/ojasmine.cma
Force custom: no
Extra C object files:
Extra C options:
Extra dynamically-loaded libraries:
Unit name: Ojasmine
Interfaces imported:
        ef5bf1a1d49ad28ddd8176a4f17055e1        Ojasmine
        c1a8a443b33589e4865a918c21fbbeb4        Js
        5de66fdff01f2735974be770893841e1        Pervasives
        a88f91d0f04fd66bc0bbaaf347081e95        CamlinternalFormatBasics
Uses unsafe features: no
Force link: no

ocamlfind sees it:

(trusty)laheadle@localhost:~/ocaml/ojasmine$ ocamlfind query ojasmine
/home/laheadle/.opam/4.02.0/lib/ojasmine

here it is:

(trusty)laheadle@localhost:~/ocaml/ojasmine$ ls `ocamlfind query ojasmine`
META  ojasmine.cma

Here is ojasmine.ml:

open Js

let describe (s : js_string t) (f: unit -> unit) : unit =
  Js.Unsafe.fun_call (Js.Unsafe.variable "describe")
    [| Js.Unsafe.inject s;
       Js.Unsafe.inject (Js.wrap_callback f) |]

let it (s : js_string t) (f: unit -> unit) : unit =
  Js.Unsafe.fun_call (Js.Unsafe.variable "it")
    [| Js.Unsafe.inject s;
       Js.Unsafe.inject (Js.wrap_callback f) |]

class type matcher = object
  method toBe: bool t -> unit meth
  method _not: matcher t readonly_prop
end

let expect_bool (b: bool t) : matcher t =
  Js.Unsafe.fun_call (Js.Unsafe.variable "expect") [|Js.Unsafe.inject b; |]

And ojasmine.mli:

open Js
val describe: js_string t -> (unit -> unit) -> unit

val it: js_string t -> (unit -> unit) -> unit

class type matcher = object
  method toBe: bool t -> unit meth
  method _not: matcher t readonly_prop
end

val expect_bool: bool t -> matcher t
like image 677
Lyn Headley Avatar asked Oct 20 '22 19:10

Lyn Headley


1 Answers

Your META file should contain an archive variable, so that ocamlfind can properly link your program with the archive, not object files. Also you need to install your cmi files. (And, although it is not needed for compilation, but it is a good manner to install mli files). So, add the following to your META

archive(byte) = "ojasmine.cma"

And do not forget to install cmi.

like image 117
ivg Avatar answered Nov 15 '22 10:11

ivg