***************
Advanced topics
***************

This section describes some details of Jbuilder for advanced users.

META file generation
====================

Jbuilder uses ``META`` files from the `findlib library
manager <http://projects.camlcity.org/projects/findlib.html>`__ 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:

.. code:: scheme

    (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.

.. _custom-driver:

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
<https://github.com/janestreet/ppx_driver>`__. To use it instead of
``ocaml-migrate-parsetree.driver-main``, simply write ``ppx_driver.runner`` as
the last library:

.. code:: scheme

    (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:

.. code:: bash

    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
