1

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?

Stephen Dedalus
  • 227
  • 1
  • 2
  • 9
  • You can use "ocamlobjinfo " to determine what other external libraries are required. – nlucaroni Feb 12 '14 at 17:12
  • ... but this is the entire point of these build systems, so I don't know why you're calling all these build steps by hand. Am I to understand you want to distribute the compiled libraries for others to compile against? Why not compile your project statically for distribution? (assuming licenses allow this). – nlucaroni Feb 12 '14 at 17:14
  • >Am I to understand you want to distribute the compiled libraries for others to compile against? There is no exact reason why I am doing that, I want just to be able to build my project from source files *.ml, *.mli (and maybe some additional files like these libraries above) up to executable. I'd be grateful if you could elaborate "Why not compile your project statically for distribution?". Would it work on another distribution without mentioned libraries? If so it is the proof I'm looking for. – Stephen Dedalus Feb 12 '14 at 18:53
  • Yes it would work without external libraries. What you are doing --as i understand it-- is trying to distribute all the external libraries with your source so compiling your project on a different system without those libraries installed explicitly will succeed? – nlucaroni Feb 12 '14 at 19:10
  • I don't believe you can do what I've described in byte-code. – nlucaroni Feb 12 '14 at 19:13
  • I'm not sure whether I understand you correctly. You are saying that I cannot distribute source files etc and simulate whole compile-link process on another computer but solution using statically pre-compiled files (not the source files and additional stuff like above) will work? – Stephen Dedalus Feb 12 '14 at 19:33
  • You can do that, I'm not understanding why you would want to as opposed to just compiling everything statically and directly. I've mentioned how you can look up the dependencies programatically, you can also use ocamlfind to query dependences (`ocamlfind query -r -i-format `. You may be confused because I'm also being tepid in saying you are within the license agreements of these packages do even do what you're stating. – nlucaroni Feb 12 '14 at 20:21

1 Answers1

2

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.

ygrek
  • 6,656
  • 22
  • 29