Lapinot
Lapinot

Reputation: 1395

How to compile a jocaml file with ocamlbuild and include a package?

How can I compile a jocaml source file which needs the cryptokit package (successfully compiled with the companion ocaml) with the ocamlbuild tool?

When I execute the command ocamlbuild -pkg cryptokit -use-jocaml a.native I get this error:

Warning: tag "package" does not expect a parameter, but is used with parameter "cryptokit"¬
+ jocamlopt -I /prefix/lib/ocaml -I /prefix/lib/ocaml/site-lib/cryptokit -I /prefix/lib/ocaml/site-lib/num /prefix/lib/ocaml/unix.cmxa /prefix/lib/ocaml/nums.cmxa /prefix/lib/ocaml/site-lib/cryptokit/cryptokit.cmxa a.cmx -o a.native¬
File "_none_", line 1:¬ 
Error: Files /prefix/lib/ocaml/unix.cmxa¬
       and /prefix/lib/ocaml/unix.cmxa¬
              both define a module named Unix¬
              Command exited with code 2.¬ 
              Compilation unsuccessful after building 4 targets (3 cached) in 00:00:00.

Essentially, the ocaml Unix module clashes with himself. This error only pops when I include Cryptokit (with -pkg cryptokit) probably because Cryptokit requires Unix. a.ml can in fact be empty and still reproduce the error.

I tried to add the -use-ocamlfind flag but as it also uses ocamlfind to get the compiler, it selects the ocaml compiler instead of the jocaml one.

By executing sequentially the same commands as ocamlbuild (displayed by -verbose 1), I got that when I execute the last one without /.../unix.cmxa then there is no more clash, but the wrong Unix module is loaded: it's the one from ocaml and not from jocaml, so it it completely crashes when I use any jocaml feature in a.ml:

jocamlopt -I /prefix/lib/ocaml -I /prefix/lib/ocaml/site-lib/cryptokit -I /prefix/lib/ocaml/site-lib/num /prefix/lib/ocaml/nums.cmxa /prefix/lib/ocaml/site-lib/cryptokit/cryptokit.cmxa a.cmx -o a.native

However, when I also remove the -I /prefix/lib/ocaml part, then it compiles successfully:

jocamlopt -I /prefix/lib/ocaml/site-lib/cryptokit -I /prefix/lib/ocaml/site-lib/num /prefix/lib/ocaml/nums.cmxa /prefix/lib/ocaml/site-lib/cryptokit/cryptokit.cmxa a.cmx -o a.native

To summarize, I got it to work by executing manually a modification of the last command, but I would like to get ocamlbuild working.

I think this error has to do with the fact that Cryptokit requires the Unix module: as I compiled it with ocaml and not jocaml, at the linking stage it tries to link with the ocaml stdlib one (which needs to be included) and not the jocaml stdlib one (which is implicitly included as part of the stdlib).

Upvotes: 0

Views: 307

Answers (2)

Lapinot
Lapinot

Reputation: 1395

Elaborating on the -use-ocamlfind option as suggested by gasche, I got it to work with the addition of a small nasty hack: removing "unix" from the requires field of the META file of the cryptokit package. It works because jocaml links everything with threads and unix by default (a real solution would have been to disable this behavior, but it seems a lot harder). So the working compilation command is:

ocamlbuild -use-ocamlfind -use-jocaml -pkg cryptokit a.ml

I think it is possible to generalize this to any package that uses either unix or threads when compiling with jocaml. A subsidiary question is whether it is possible to do this dynamically with a _tags or myocamlbuild.ml file (note: comment if this remark needs to be moved).

Upvotes: 0

gasche
gasche

Reputation: 31469

I had no idea there were active users of the ocamlbuild+JOcaml combination! By curiosity, would you say a bit more about what you are using JOCaml+cryptokit for?

I don't know much about Cryptokit or JOCaml, but it looks like your main problem is not related to ocamlbuild. If I understand correctly, (1) Cryptokit needs Unix and (2) JOCaml needs to use its own variant of Unix. If this is correct, compiling Cryptokit against ocaml's Unix and expecting it to work when linked with a JOCaml program that itself requires JOCaml's Unix is bound to create a lot of trouble. If this work in your case, it must be because either the part of Cryptokit you use doesn't actually require Unix, or the JOCaml program you are testing with does not actually require JOCaml's Unix. In the long run, it would probably be best to compile Cryptokit with JOCaml directly (I don't know how comfortable you are with the OCaml ecosystem in general, but I would personally try to build an OPAM switch where ocaml{c,opt} are aliases for jocaml{c,opt} and build programs from that).

Regarding the ocamlbuild specific part, it's hard to give any accurate advice without a tarball to be able to reproduce your setup and experiment with it. But I would try one of the two following options:

  • You can use -use-ocamlfind and teach ocamlfind to use jocaml instead of ocaml by using the OCAMLFIND_COMMANDS environment variable (see man ocamlfind)
  • You can avoid -use-ocamlfind entirely and instead call ocamlfind as a command-line tool to get the location of the cryptokit library (ocamlfind query cryptokit). You would then not use -pkg cryptokit but pass the path yourself (with -lflags and -cflags or by modifying your myocamlbuild.ml configuration file).

Upvotes: 1

Related Questions