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?
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:
opam
to download and install missing dependenciesIf 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.