"No implementations provided" strange error with ocamlopt

I am currently encountering a “No implementations provided for the following modules” error. Google showed me dozens of pages about this issue, but it seems none of them deals with the particular issue I’m having. They’re all in the context of high-level tools such as ocamlfind or jbuilder , while I found this issue using only ocamlopt.
I have a file named a.ml whose one-line content is let v=7;;.
I also have another file named b.ml whose one-line content is let w=1+A.v;;.

The following output leaves me perplexed :

disk

Here are my questions :

  1. Why is ocamlopt complaining that it was not provided the implementation of A when I provided both the .cmx and .o file ?
    (and shouldn’t ocamlopt find those files on its own anyway, as ocamlc does for cmo files ?)

  2. Despite the error message, the b.ml file is actually compiled it seems. So is it a fake error message, or should I worry ?

  1. Why is ocamlopt complaining that it was not provided the implementation of A when I provided both the .cmx and .o file ?

The order in which the files are provided is significant. Since B makes use of A, a.cmx should appear before b.ml on the command line:

$ ocamlopt -o b.exe a.cmx b.ml

Despite the error message, the b.ml file is actually compiled it seems. So is it a fake error message, or should I worry ?

The error message is from the linker, not the compiler. So b.ml is compiled successfully into b.cmx, but linking a.cmx and b.cmx together fails, because the order of filenames on the command-line doesn’t match the dependency order between modules.

Breaking things down into separate steps is likely to make things easier to understand. The first step is to compile (but not link) both a.ml and b.ml by passing -c to the compiler:

$ ls
a.ml  b.ml
$ ocamlopt -c a.ml
$ ocamlopt -c b.ml
$ ls
a.cmi  a.cmx  a.ml  a.o  b.cmi  b.cmx  b.ml  b.o

The second step is to link together the object files (.cmx, not .ml) from the first step:

$ ocamlopt -o b.exe a.cmx b.cmx
$ ls
a.cmi  a.cmx  a.ml  a.o  b.cmi  b.cmx  b.exe  b.ml  b.o