It’s been a while since I used Ocaml and perhaps my setup is now incorrect but I can’t seem to use a standard opam-installed library without specifying the full path. I’ve done:
opam update -u; opam switch 5.0.0; eval
opam config env; opam user-setup install
ocamlfind ocamlc -only-show tells me the correct compile command is
ocamlc.opt -o testprog.exe -I /home/toby/.opam/5.0.0/lib/zarith /home/toby/.opam/5.0.0/lib/zarith/zarith.cma testprog.ml
which works, but I have to include the full library path. The following commands
ocamlc.opt -o testprog.exe zarith.cma testprog.ml
ocamlc.opt -o testprog.exe /home/toby/.opam/5.0.0/lib/zarith/zarith.cma testprog.ml
ocamlc.opt -o testprog.exe -I +zarith zarith.cma testprog.ml
all give me the dreaded “Unbound module” error.
I have these set;
OPAM_SWITCH_PREFIX=‘/home/toby/.opam/5.0.0’; export OPAM_SWITCH_PREFIX;
CAML_LD_LIBRARY_PATH=‘/home/toby/.opam/5.0.0/lib/stublibs:/home/toby/.opam/5.0.0/lib/ocaml/stublibs:/home/toby/.opam/5.0.0/lib/ocaml’; export CAML_LD_LIBRARY_PATH;
OCAML_TOPLEVEL_PATH=‘/home/toby/.opam/5.0.0/lib/toplevel’; export OCAML_TOPLEVEL_PATH;
How can I compile and link with libraries such as zarith without having to specify full paths or use ocamlfind every time?
I guess the nowadays approach consists to have a
dune-project and a
dune files and lets
dune search the library. When all is setup, a single
dune exec ./testprog.exe compile the program if needed and launch it.
OK I will look into that, but it is strange the compiler cant find the module interface or library using the environment variables when it is installed in a standard place. In particular I don’t know why ‘-I +zarith’ doesn’t work.
+ is only useful for the handful of libraries bundled with the compiler, which is not the case for
Ok, that’s not mentioned in the man page: “Add the given directory to the list of directories searched”
The OCaml compiler still operates on a model where it controls where its own libraries are installed, but not others. So
-I +unix/ means that you expect the compiler to have installed unix in a subdirectory of its standard library location, and this works because unix is shipped by the compiler.
On the other hand, external libraries like
zarith can be installed in arbitrary ways (through
opam, your system package manager, or by hand), so you cannot rely on it being located close to the standard library.
(The compiler knows where it is going to be installed itself, so I guess we could add support for syntax like
~lib/zarith to point to the library folder of the installation target, but given that
ocamlfind already does a very good job of dealing with these issues it is not a priority.)
You can use
ocamlfind to either generate whole command-line, like you did, or just find the library for a specific package (
ocamlfind query zarith). The second option would likely be useful if you want to integrate it in your own build system.
Finally, if you know your packages come from
opam and are installed in predictable ways, you can also ask
opam for the path to its installation library and use it to semi-hardcode paths:
$(opam var lib)/zarith.
I think the issue is that
zarith used to (and maybe still does) install itself in the OCaml standard library directory if
ocamlfind was not available. In that case, simply passing
-I +zarith would work.
There’s nothing wrong with using ocamlfind “every time”, i.e. for all invocations of the OCaml compilers: it’s lightweight and handles library packages very well. Or, use Dune as a build manager, it will also handle library packages correctly.
The ZArith readme should be updated to not mention
-I +zarith, which no longer works.