I am trying to compile a single file, minimized below, with ocamlfind ocamlopt. It succeeds as expected with -I +threads threads.cmxa, but fails when I add -package threads or a package which depends on threads (in my case -package coq-core.kernel). What am I doing wrong?
I think you need to remove unix.cmxa and threads.cmxa from the command-line; -linkpkg will take care of linking those archives into your final artifact.
If you are using ocamlfind then you don’t normally need to pass -I flags nor .cmxa archives by hand in the command-line, all of these is taken care of by the -package and -linkpkg flags. The OCaml manual does not use ocamlfind which is why they pass -I flags and .cmxa archives on the command-line.
The first failure is expected because you are not passing -package flags. The second failure is less clear. Maybe your installation is not correctly configured? What is the output of ocamlfind printconf?
I see. Then it’s extra strange because it’s fine linking with other packages.
$ ocamlfind printconf
Effective configuration:
Configuration file:
/home/sam/.opam/myswitch/lib/findlib.conf
Search path:
/home/sam/.opam/myswitch/lib64
/home/sam/.opam/myswitch/lib
Packages will be installed in/removed from:
/home/sam/.opam/myswitch/lib
META files will be installed in/removed from:
the corresponding package directories
The standard library is assumed to reside in:
/home/sam/.opam/myswitch/lib64
The ld.conf file can be found here:
/home/sam/.opam/myswitch/lib64/ld.conf
The ocamlfind option -thread seems to fix this. It’s confusing because when I first saw it, with ocamlfind ocamlopt --help, it only showed ocamlopt’s -thread which says it’s deprecated:
-thread (deprecated) same as -I +threads
and I then found ocamlfind’s actual -thread flag documented on man ocamlfind. Or am I still misunderstanding it?
-thread
This standard option causes that the predicate “mt” is added to the set of actual predicates. If POSIX threads are available, the predicate “mt_posix” is selected, too. If only VM threads are available, the predicate “mt_vm” is included into the set, and the compiler switch is changed into -vmthread.
Your ocamlfind printconf looks a bit strange normally these lib64 should be the directory ocaml.
The -thread option should also no longer be needed in ocamlfind in OCaml >= 5.0.0 since the libraries are no longer predicated by mt and mt_posix.
Could you output the result of cat $(ocamlfind query -format "%m" threads). If all is well (but this lib64 is suspicious) you should see something like:
# otherlibs/systhreads/META. Generated from META.in by configure.
version = "5.1.0"
description = "Multi-threading"
requires = "unix"
archive(byte) = "threads.cma"
archive(native) = "threads.cmxa"
type_of_threads = "posix"
package "posix" (
requires = "threads"
version = "[internal]"
)
Well in fact I can perfectly reproduce your problem.
Eco-system tools always needs special casing around upstream provided libraries because they can’t be bothered.
What you see here is likely the result of some form of special casing in ocamlfind hitting back (a git grep on threads in ocamlfind’s sources will show the many potential offending locations).
The following command should actually compile the source you provided but it does not.
It’s missing the -I to the ocaml/threads directory
It locates the library in the ocaml libdir instead of ocaml/threads.
All this despite the META file being well aligned on ocamlfind’s convention (i.e. present in ocaml/threads and as provided above).
Just to nail that down a bit further, it must be somewhere in the tool wrapping logic as ocamlfind query (which I use in my builds) reports the right bits, e.g.: