Advanced topics

This section describes some details of Jbuilder for advanced users.

META file generation

Jbuilder uses META files from the findlib library manager in order to interoperate with the rest of the world when installing libraries. It is able to generate them automatically. However, for the rare cases where you would need a specific META file, or to ease the transition of a project to Jbuilder, it is allowed to write/generate a specific one.

In order to do that, write or setup a rule to generate a META.<package> file in the same directory as the <package>.opam file. If you do that, Jbuilder will still generate a META file but it will be called META.<package>.from-jbuilder. So for instance if you want to extend the META file generated by Jbuilder you can write:

(rule
 ((targets (META.foo))
  (deps    (META.foo.from-jbuilder))
  (action  (with-stdout-to ${@}
            (progn
             (cat ${<})
             (echo blah))))))

Additionally, Jbuilder provides a simpler mechanism for this scheme: just write or generate a META.<package>.template file containing a line of the form # JBUILDER_GEN. Jbuilder will automatically insert its generated META contents in place of this line.

Using a custom ppx driver

You can use a custom ppx driver by putting it as the last library in (pps ...) forms. An example of alternative driver is ppx_driver. To use it instead of ocaml-migrate-parsetree.driver-main, simply write ppx_driver.runner as the last library:

(preprocess (pps (ppx_sexp_conv ppx_bin_prot ppx_driver.runner)))

Driver expectation

Jbuilder will invoke the executable resulting from linking the libraries given in the (pps ...) form as follows:

ppx.exe <flags-written-by-user> --dump-ast -o <output-file> \
  [--cookie library-name="<name>"] [--impl|--intf] <source-file>

Where <source-file> is either an implementation (.ml) or interface (.mli) OCaml source file. The command is expected to write a binary OCaml AST in <output-file>.

Additionally, it is expected that if the executable is invoked with --as-ppx as its first argument, then it will behave as a standard ppx rewirter as passed to -ppx option of OCaml. This is for two reasons:

  • to improve interoperability with build systems other than Jbuilder
  • so that it can be used with merlin

Findlib integration and limitations

Jbuilder uses META files to support external libraries. However, it doesn’t export the full power of findlib to the user, and especially it doesn’t let the user specify predicates.

The reason for this limitation is that so far they haven’t been needed, and adding full support for them would complicate things quite a lot. In particular, complex META files are often hand-written and the various features they offer are only available once the package is installed, which goes against the root ideas jbuilder is built on.

In practice, jbuilder interpret META files assuming the following set of predicates:

  • mt: what this means is that using a library that can be used with or without threads with jbuilder will force the threaded version
  • mt_posix: forces the use of posix threads rather than VM threads. VM threadws are deprecated and are likely to go away soon
  • ppx_driver: when a library acts differently depending on whether it is linked as part of a driver or meant to add a -ppx argument to the compiler, choose the former behavior