Question

I've to prepare my OCaml project to compile/link/run on system where some libraries are not availible (yojson, curl, cryptokit but it's probably not so important) how may I do it?

So far I was using:

$ ocamlbuild -use-ocamlfind -pkgs curl,yojson,netstring,cryptokit,netclient,lablgtk2.auto-init,pgocaml tweetomat.native

it obviously won't work if some packages are missing. My attempt was to look for libraries path typing

$ ocamlfind printconf path

and manually copy missing libraries' folders to project's folder, here is listining of them

$ tree -r libs

libs/
├── yojson
│   ├── yojson.o
│   ├── yojson.mli
│   ├── yojson.cmx
│   ├── yojson.cmo
│   ├── yojson.cmi
│   ├── yojson_biniou.o
│   ├── yojson_biniou.mli
│   ├── yojson_biniou.cmx
│   ├── yojson_biniou.cmo
│   ├── yojson_biniou.cmi
│   └── META
├── curl
│   ├── META
│   ├── libcurl-helper.a
│   ├── curl.mli
│   ├── curl.cmxa
│   ├── curl.cmi
│   ├── curl.cma
│   └── curl.a
└── cryptokit
    ├── META
    ├── libcryptokit_stubs.a
    ├── cryptokit.mli
    ├── cryptokit.cmxs
    ├── cryptokit.cmxa
    ├── cryptokit.cmx
    ├── cryptokit.cmi
    ├── cryptokit.cma
    └── cryptokit.a

Ok so I tried to compile step-by-step every single file from project and then compile everything to executable using:

$ ocamlc -c twitter_oauth.mli
$ ocamlfind ocamlc -package netstring,netclient -I ./libs/cryptokit/ \
    -c twitter_oauth.ml
$ ocamlc -c connection.mli
$ ocamlfind ocamlc -I ./libs/curl/ -c connection.ml
$ ocamlfind ocamlc -I ./libs/yojson/ -c parser.ml
$ ocamlfind ocamlc -package pgocaml -c sql.ml
$ ocamlfind ocamlc -package lablgtk2.auto-init,pgocaml -c gui.ml
$ ocamlfind ocamlc -package lablgtk2.auto-init,pgocaml,netstring,netclient \
    -I ./libs/cryptokit/ -I ./libs/curl/ -I ./libs/yojson/ -o tweetomat \
    yojson.cmo curl.cma cryptokit.cma \
    twitter_oauth.cmo connection.cmo parser.cmo sql.cmo gui.cmo

but I'm getting:

File "_none_", line 1:
Error: Error while linking ./libs/yojson/yojson.cmo:
Reference to undefined global `Bi_outbuf'

I googled a little and it looks like yojson is not built statically and needs 'biniou' library to fullfill dependencies (I'm not sure about statically build but it looks like that). And in fact after changing last command to (changes are marked by asterisks):

$ ocamlfind ocamlc -package lablgtk2.auto-init,**biniou**,pgocaml,netstring,netclient \
    -I ./libs/cryptokit/ -I ./libs/curl/ -I ./libs/yojson/ -o tweetomat \
    **biniou.cma** yojson.cmo curl.cma cryptokit.cma \
    twitter_oauth.cmo connection.cmo parser.cmo sql.cmo gui.cmo

previous error does not occur but I've new one:

File "_none_", line 1:
Error: Error while linking ./libs/yojson/yojson.cmo:
Reference to undefined global `Easy_format'

oh god I won't include every single library on which yojson/curl/cryptokit depends >:(. Can you help me guys? Moreover does there exist some simpler way to do that using ocamlbuild?

Was it helpful?

Solution

Don't specify include paths for dependencies manually - let ocamlfind handle it. So the question remains on how to make that libraries available via ocamlfind.

Either:

  • Use opam to download and install missing dependencies
  • If opam dependency is not an option - distribute other libraries as tarballs together with your project and make the build script unpack and build them when needed (build steps may be different for each library) - and install as usual (via ocamlfind).

    There may be a problem of ocamlfind installing into system directory writable by root only. This can be handled by setting environment variable telling another directory for ocamlfind to install to and lookup from.

    That would be manual bundling until we have it automatic from opam one day.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top