I'm writing Bazel rules for OCaml and I've run into a problem that I think is due to a tool that wants to work outside of Bazel's control. In short, tool `ocamlfind` runs the compiler `ocamlopt`, which runs clang.
Now this works fine, except when it doesn't. I "think* the problem is traceable to the tools reaching outside of Bazel. I'm looking for confirmation and suggested remedies.
This is a little complicated, because OCaml compilation is, let's just say, a little eccentric. A module has two parts, an interface and an implementation. So a compiled module Foo would have foo.cmi (Compiled Module Interface) and foo.cmx (the implementation file). You can compile the cmi first, then the cmx, or you can pass them both to the compiler at once. The rules are a little odd: the compiler looks for an mli, and it if finds it, looks for the cmi. If it does not find it, it generates the cmi from the ml file.
In any case, I have a rule to compile mli files and a rule to compile ml files; the latter has an (optional) attribute for a cmi dependency. This works fine:
```
INFO: From ocaml_module(RefList), compiling impl :
+ clang -arch x86_64 -Wno-trigraphs -c -o 'bazel-out/darwin-fastbuild/bin/src/refList.o' '/var/folders/wz/dx0cgvqx5qn802qmc3d4hcfr0000gp/T/camlasmca0598.s'
Effective set of compiler predicates: pkg_bytes,autolink,native
+ ocamlopt.opt -verbose -g -bin-annot -c -I bazel-out/darwin-fastbuild/bin/src -I src -I bazel-out/darwin-fastbuild/bin/src/tmp -o bazel-out/darwin-fastbuild/bin/src/refList.cmx -I /Users/gar/.opam/4.07.1/lib/bytes src/refList.ml
Target //src:RefList up-to-date:
bazel-bin/src/refList.cmx
bazel-bin/src/refList.o
bazel-bin/src/refList.cmi
bazel-bin/src/refList.cmt
```
(Ignore the *.cmt file)
Note the clang output and input locations.
Now I've enhanced the rule to take an mli (source) file OR a cmi file. Passing both source files (.mli, .ml) works if I construct a compile command by hand on the CLI. The rule generates a command that looks correct. But when I run it, the .cmi file is produced but I get an error:
```
INFO: From ocaml_module(RefList), compiling impl :
+ clang -arch x86_64 -Wno-trigraphs -c -o 'src/refList.o' '/var/folders/wz/dx0cgvqx5qn802qmc3d4hcfr0000gp/T/camlasm35a097.s'
Effective set of compiler predicates: pkg_bytes,autolink,native
+ ocamlopt.opt -verbose -g -bin-annot -c -I bazel-out/darwin-fastbuild/bin/src -I src -I bazel-out/darwin-fastbuild/bin/src/tmp -o bazel-out/darwin-fastbuild/bin/src/refList.cmx -I /Users/gar/.opam/4.07.1/lib/bytes src/refList.mli src/refList.ml
ERROR: /Users/gar/mina/ocaml-extlib/src/BUILD.bazel:596:13: output 'src/refList.cmt' was not created
ERROR: /Users/gar/mina/ocaml-extlib/src/BUILD.bazel:596:13: output 'src/refList.cmx' was not created
ERROR: /Users/gar/mina/ocaml-extlib/src/BUILD.bazel:596:13: output 'src/refList.o' was not created
ERROR: /Users/gar/mina/ocaml-extlib/src/BUILD.bazel:596:13: not all outputs were created or valid
```
Note the output of the clang command - it wants to write its output to src rather than one of the bazel-* dirs. I believe that is the problem - am I right?
(Related: if that is indeed the problem, should not Bazel recognize it and issue a meaningful error message?)
I have encountered this previously in a different context, and the solution I came up with was to copy the source file to a temp dir created by the Bazel rule and run the compile action from there. Then clang writes its output there, which works.
Is there a better way to handle this?
Thanks,
Gregg