Ocamlbuild and module packs
The -pack option of ocamlc and ocamlopt allows you to build a module which contains several other modules built separately. Ocamlbuild can handle such modules.
Basics
Let's pack the modules Bli, Blo and Blu together in a module Bla.
Write a file called bla.mlpack: Bli Blo Blu. Now ocamlbuild can compile
bla.cmo: ocamlbuild bla.cmo If you have a main file such as main.ml
which uses the module Bla (or Bla.Bli, Bla.Blo or Bla.Blu), you can
compile it normally, using: ocamlbuild main.byte.
Native code
This time we want to compile using ocamlopt. This requires the files
bli.cmx, blo.cmx and blu.cmx to be compiled using the -for-pack Bla
option. This option is not added automatically by Ocamlbuild, so we
have to add a tag rule in the _tags file:
<bl{i,o,u}.cmx>: for-pack(Bla) Now you can compile normally, using:
ocamlbuild main.native.
Packing from other directories
No dependencies between the directories
If the files bli.ml, blo.ml and blu.ml are in some other directories,
just modify your bla.mlpack file: otherdir1/Bli otherdir2/Blo
otherdir3/Blu. The bla.mlpack file should stay where you want the Bla
module to be created; you don't have to put it in the otherdir
directory.
Then, you can compile using: ocamlbuild bla.cmo. Notice that you don't
have to include the otherdir directories using -I. This allows you to
compile your main file using: ocamlbuild main.byte without polluting the
namespace with modules Bli, Blo and Blu (which will be reached using
Bla.Bli, Bla.Blo and Bla.Blu).
Solving dependencies
The previous approach doesn't work if the files bli.ml, blo.ml and
blu.ml depend on each other and are in different directories. Let's
assume that blo.ml depends on bli.ml. If they are in the same directory,
there is no problem because Blo sees the whole content of its directory.
But if otherdir1 and otherdir2 are different, then you get an error
because Bli is unbound in Blo.
One solution would be to use the -I option: ocamlbuild -Is
otherdir1,otherdir2,otherdir3 main.byte. But this solution pollutes
the namespace of main.ml with Bli, Blo and Blu. If for some
reason you have another module Bli in your main directory, this
approach will lead to a name clash.
Another solution is to write a plugin for Ocamlbuild. In our example,
it is sufficient to say that the files in the directory otherdir2 should
see the content of both otherdir1 and otherdir2. To do this we use the
API function Pathname.define_context. Write the following
myocamlbuild.ml in your main directory:
open Ocamlbuild_plugin
let () =
dispatch begin function
| After_rules ->
Pathname.define_context "otherdir2" ["otherdir1"; "otherdir2"]
| _ -> ()
end
Now you should be able to compile, using:
ocamlbuild main.byte