909 lines
32 KiB
ReStructuredText
909 lines
32 KiB
ReStructuredText
|
********************
|
||
|
jbuild specification
|
||
|
********************
|
||
|
|
||
|
``jbuild`` files are the main part of Jbuilder, and are the origin of
|
||
|
its name. They are used to describe libraries, executables, tests, and
|
||
|
everything Jbuilder needs to know about.
|
||
|
|
||
|
Stanzas
|
||
|
=======
|
||
|
|
||
|
``jbuild`` files are composed of stanzas. For instance a typical
|
||
|
``jbuild`` looks like:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(library
|
||
|
((name mylib)
|
||
|
(libraries (base lwt))))
|
||
|
|
||
|
(rule
|
||
|
((targets (foo.ml))
|
||
|
(deps (generator/gen.exe))
|
||
|
(action (run ${<} -o ${@}))))
|
||
|
|
||
|
The following sections describe the available stanzas and their meaning.
|
||
|
|
||
|
jbuild_version
|
||
|
--------------
|
||
|
|
||
|
``(jbuild_version 1)`` specifies that we are using the version 1 of
|
||
|
the Jbuilder metadata format in this ``jbuild`` file.
|
||
|
|
||
|
library
|
||
|
-------
|
||
|
|
||
|
The ``library`` stanza must be used to describe OCaml libraries. The
|
||
|
format of library stanzas is as follows:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(library
|
||
|
((name <library-name>)
|
||
|
<optional-fields>
|
||
|
))
|
||
|
|
||
|
``<library-name>`` is the real name of the library. It determines the
|
||
|
names of the archive files generated for the library as well as the
|
||
|
module name under which the library will be available, unless
|
||
|
``(wrapped false)`` is used (see below). It must be a valid OCaml
|
||
|
module name but doesn't need to start with a uppercase letter.
|
||
|
|
||
|
For instance, the modules of a library named ``foo`` will be
|
||
|
available as ``Foo.XXX`` outside of ``foo`` itself. It is however
|
||
|
allowed to write an explicit ``Foo`` module, in which case this will
|
||
|
be the interface of the library and you are free to expose only the
|
||
|
modules you want.
|
||
|
|
||
|
``<optional-fields>`` are:
|
||
|
|
||
|
- ``(public_name <name>)`` this is the name under which the library can be
|
||
|
referred to as a dependency when it is not part of the current workspace,
|
||
|
i.e. when it is installed. Without a ``(public_name ...)`` field, the library
|
||
|
will not be installed by Jbuilder. The public name must start by the package
|
||
|
name it is part of and optionally followed by a dot and anything else you
|
||
|
want. The package name must be one of the packages that Jbuilder knows about,
|
||
|
as determined by the *<package>.opam files*
|
||
|
|
||
|
- ``(synopsis <string>)`` should give a one-line description of the library.
|
||
|
This is used by tools that list installed libraries
|
||
|
|
||
|
- ``(modules <modules>)`` specifies what modules are part of the library. By
|
||
|
default Jbuilder will use all the .ml/.re files in the same directory as the
|
||
|
``jbuild`` file. This include ones that are present in the file system as
|
||
|
well as ones generated by user rules. You can restrict this list by using a
|
||
|
``(modules <modules>)`` field. ``<modules>`` uses the *ordered set language*
|
||
|
where elements are module names and don't need to start with a uppercase
|
||
|
letter. For instance to exclude module ``Foo``: ``(modules (:standard \
|
||
|
foo))``
|
||
|
|
||
|
- ``(libraries (<library-dependencies>))`` is used to specify the dependencies
|
||
|
of the library. See the *section about library dependencies* for more details
|
||
|
|
||
|
- ``(wrapped <boolean>)`` specifies whether the modules of the library should be
|
||
|
available only through the top-level library module, or should all be exposed
|
||
|
at the top level. The default is ``true`` and it is highly recommended to
|
||
|
keep it this way. Because OCaml top-level modules must all be unique when
|
||
|
linking an executables, polluting the top-level namespace will make your
|
||
|
library unusable with other libraries if there is a module name clash. This
|
||
|
option is only intended for libraries that manually prefix all their modules
|
||
|
by the library name and to ease porting of existing projects to Jbuilder
|
||
|
|
||
|
- ``(preprocess <preprocess-spec>)`` specifies how to preprocess files if
|
||
|
needed. The default is ``no_processing``. Other options are described in the
|
||
|
*preprocessing specification section*
|
||
|
|
||
|
- ``(preprocessor_deps (<deps-conf list>))`` specifies extra dependencies of the
|
||
|
preprocessor, for instance if the preprocessor reads a generated file. The
|
||
|
specification of dependencies is described in the *dependency specification
|
||
|
section*
|
||
|
|
||
|
- ``(optional)``, if present it indicates that the library should only be built
|
||
|
and installed if all the dependencies are available, either in the workspace
|
||
|
or in the installed world. You can use this to provide extra features without
|
||
|
adding hard dependencies to your project
|
||
|
|
||
|
- ``(c_names (<names>))``, if your library has stubs, you must list the C files
|
||
|
in this field, without the ``.c`` extension
|
||
|
|
||
|
- ``(cxx_names (<names>))`` is the same as ``c_names`` but for C++ stubs
|
||
|
|
||
|
- ``(install_c_headers (<names>))``, if your library has public C header files
|
||
|
that must be installed, you must list them in this field, with the ``.h``
|
||
|
extension
|
||
|
|
||
|
- ``(modes (<modes>))`` modes (``byte`` and ``native``) which should be built by
|
||
|
default. This is only useful when writing libraries for the OCaml toplevel
|
||
|
|
||
|
- ``(no_dynlink)`` is to disable dynamic linking of the library. This is for
|
||
|
advanced use only, by default you shouldn't set this option
|
||
|
|
||
|
- ``(kind <kind>)`` is the kind of the library. The default is ``normal``, other
|
||
|
available choices are ``ppx_rewriter`` and ``ppx_deriver`` and must be set
|
||
|
when the library is intended to be used as a ppx rewriter or a ``[@@deriving
|
||
|
...]`` plugin. The reason why ``ppx_rewriter`` and ``ppx_deriver`` are split
|
||
|
is historical and hopefully we won't need two options soon
|
||
|
|
||
|
- ``(ppx_runtime_libraries (<library-names>))`` is for when the library is a ppx
|
||
|
rewriter or a ``[@@deriving ...]`` plugin and has runtime dependencies. You
|
||
|
need to specify these runtime dependencies here
|
||
|
|
||
|
- ``(virtual_deps (<opam-packages>)``. Sometimes opam packages enable a specific
|
||
|
feature only if another package is installed. This is for instance the case
|
||
|
of ``ctypes`` which will only install ``ctypes.foreign`` if the dummy
|
||
|
``ctypes-foreign`` package is installed. You can specify such virtual
|
||
|
dependencies here. You don't need to do so unless you use Jbuilder to
|
||
|
synthesize the ``depends`` and ``depopts`` sections of your opam file
|
||
|
|
||
|
- ``js_of_ocaml``. See the *section about js_of_ocaml*
|
||
|
|
||
|
- ``flags``, ``ocamlc_flags`` and ``ocamlopt_flags``. See the
|
||
|
*section about specifying OCaml flags*
|
||
|
|
||
|
- ``(library_flags (<flags>))`` is a list of flags that are passed as it to
|
||
|
``ocamlc`` and ``ocamlopt`` when building the library archive files. You can
|
||
|
use this to specify ``-linkall`` for instance. ``<flags>`` is a list of
|
||
|
strings supporting *variables expansion*
|
||
|
|
||
|
- ``(c_flags <flags>)`` specifies the compilation flags for C stubs,
|
||
|
using the *ordered set language*. This field supports
|
||
|
``(:include ...)`` forms
|
||
|
|
||
|
- ``(cxx_flags <flags>)`` is the same as ``c_flags`` but for C++
|
||
|
stubs
|
||
|
|
||
|
- ``(c_library_flags <flags>)`` specifies the flags to pass to the C compiler
|
||
|
when constructing the library archive file for the C stubs. ``<flags>`` uses
|
||
|
the *ordered set language* and supports ``(:include ...)`` forms. When you
|
||
|
are writing bindings for a C library named ``bar``, you should typically
|
||
|
write ``-lbar`` here, or whatever flags are necessary to to link against this
|
||
|
library
|
||
|
|
||
|
- ``(self_build_stubs_archive <c-libname>)`` indicates to Jbuilder that the
|
||
|
library has stubs, but that the stubs are built manually. The aim of the
|
||
|
field is to embed a library written in foreign language and/or building with
|
||
|
another build system. It is not for casual uses, see the `re2 library
|
||
|
<https://github.com/janestreet/re2>`__ for an example of use
|
||
|
|
||
|
Note that when binding C libraries, Jbuilder doesn't provide special
|
||
|
support for tools such as ``pkg-config``, however it integrates
|
||
|
easily with
|
||
|
`configurator <https://github.com/janestreet/configurator>`__ by
|
||
|
using ``(c_flags (:include ...))`` and
|
||
|
``(c_library_flags (:include ...))``.
|
||
|
|
||
|
executable
|
||
|
----------
|
||
|
|
||
|
The ``executable`` stanza must be used to describe an executable. The
|
||
|
format of executable stanzas is as follows:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(executable
|
||
|
((name <name>)
|
||
|
<optional-fields>
|
||
|
))
|
||
|
|
||
|
``<name>`` is a module name that contains the main entry point of the
|
||
|
executable. There can be additional modules in the current directory, you only
|
||
|
need to specify the entry point. Given an ``executable`` stanza with ``(name
|
||
|
<name>)``, Jbuilder will know how to build ``<name>.exe``, ``<name>.bc`` and
|
||
|
``<name>.bc.js``. ``<name>.exe`` is a native code executable, ``<name>.bc`` is a
|
||
|
bytecode executable which requires ``ocamlrun`` to run and ``<name>.bc.js`` is a
|
||
|
JavaScript generated using js_of_ocaml.
|
||
|
|
||
|
Note that in case native compilation is not available, ``<name>.exe``
|
||
|
will in fact be a custom byte-code executable. Custom in the sense of
|
||
|
``ocamlc -custom``, meaning that it is a native executable that
|
||
|
embeds the ``ocamlrun`` virtual machine as well as the byte code. As
|
||
|
such you can always rely on ``<name>.exe`` being available.
|
||
|
|
||
|
``<optional-fields>`` are:
|
||
|
|
||
|
- ``(public_name <public-name>)`` specifies that the executable
|
||
|
should be installed under that name. It is the same as adding the
|
||
|
following stanza to your ``jbuild`` file:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(install
|
||
|
((section bin)
|
||
|
(files ((<name>.exe as <public-name>)))))
|
||
|
|
||
|
- ``(package <package>)`` if there is a ``(public_name ...)`` field,
|
||
|
this specifies the package the executables are part of
|
||
|
|
||
|
- ``(libraries (<library-dependencies>))`` specifies the library
|
||
|
dependencies. See the *section about library dependencies* for
|
||
|
more details
|
||
|
|
||
|
- ``(modules <modules>)`` specifies which modules in the current
|
||
|
directory Jbuilder should consider when building this executable.
|
||
|
Modules not listed here will be ignored and cannot be used inside
|
||
|
the executable described by the current stanza. It is interpreted
|
||
|
in the same way as the ``(modules ...)`` field of *libraries*
|
||
|
|
||
|
- ``(preprocess <preprocess-spec>)`` is the same as the
|
||
|
``(preprocess ...)`` field of *libraries*
|
||
|
|
||
|
- ``(preprocessor_deps (<deps-conf list>))`` is the same as the
|
||
|
``(preprocessor_deps ...)`` field of *libraries*
|
||
|
|
||
|
- ``js_of_ocaml``. See the *section about js_of_ocaml*
|
||
|
|
||
|
- ``flags``, ``ocamlc_flags`` and ``ocamlopt_flags``. See the
|
||
|
*section about specifying OCaml flags*
|
||
|
|
||
|
executables
|
||
|
-----------
|
||
|
|
||
|
The ``executables`` stanza is the same as the ``executable`` stanza,
|
||
|
except that it is used to describe several executables sharing the
|
||
|
same configuration.
|
||
|
|
||
|
It shares the same fields as the ``executable`` stanza, except that
|
||
|
instead of ``(name ...)`` and ``(public_name ...)`` you must use:
|
||
|
|
||
|
- ``(names (<names>))`` where ``<names>`` is a list of entry point
|
||
|
names. As for ``executable`` you only need to specify the modules
|
||
|
containing the entry point of each executable
|
||
|
|
||
|
- ``(public_names (<names>))`` describes under what name each
|
||
|
executable should be installed. The list of names must be of the
|
||
|
same length as the list in the ``(names ...)`` field. Moreover you
|
||
|
can use ``-`` for executables that shouldn't be installed
|
||
|
|
||
|
rule
|
||
|
----
|
||
|
|
||
|
The ``rule`` stanza is used to create custom user rules. It tells
|
||
|
Jbuilder how to generate a specific set of files from a specific set
|
||
|
of dependencies.
|
||
|
|
||
|
The syntax is as follows:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(rule
|
||
|
((targets (<filenames>))
|
||
|
(deps (<deps-conf list>))
|
||
|
(action <action>)))
|
||
|
|
||
|
``<filenames>`` is a list of file names. Note that currently Jbuilder
|
||
|
only support user rules with targets in the current directory.
|
||
|
|
||
|
``<deps-conf list>`` specifies the dependencies of the rule. See the
|
||
|
*dependency specification section* for more details.
|
||
|
|
||
|
``<action>`` is the action to run to produce the targets from the
|
||
|
dependencies. See the *actions section* for more details.
|
||
|
|
||
|
Note that contrary to makefiles or other build systems, user rules
|
||
|
currently don't support patterns, such as a rule to produce ``%.y``
|
||
|
from ``%.x`` for any given ``%``. This might be supported in the
|
||
|
future.
|
||
|
|
||
|
ocamllex
|
||
|
--------
|
||
|
|
||
|
``(ocamllex (<names>))`` is essentially a shorthand for:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(rule
|
||
|
((targets (<name>.ml))
|
||
|
(deps (<name>.mll))
|
||
|
(action (chdir ${ROOT} (run ${bin:ocamllex} -q -o ${<})))))
|
||
|
|
||
|
ocamlyacc
|
||
|
---------
|
||
|
|
||
|
``(ocamlyacc (<names>))`` is essentially a shorthand for:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(rule
|
||
|
((targets (<name>.ml <name>.mli))
|
||
|
(deps (<name>.mly))
|
||
|
(action (chdir ${ROOT} (run ${bin:ocamlyacc} ${<})))))
|
||
|
|
||
|
menhir
|
||
|
------
|
||
|
|
||
|
The basic form for defining menhir parsers (analogous to ocamlyacc) is:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(menhir
|
||
|
((modules (<parser1> <parser2> ...))))
|
||
|
|
||
|
Modular parsers can be defined by adding a ``merge_into`` field. This correspond
|
||
|
to the ``--base`` command line option of ``menhir``. With this option, a single
|
||
|
parser named ``base_name`` is generated.
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(menhir
|
||
|
((merge_into <base_name>)
|
||
|
(modules (<parser1> <parser2> ...))))
|
||
|
|
||
|
Extra flags can be passed to menhir using the ``flags`` flag:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(menhir
|
||
|
((flags (<option1> <option2> ...))
|
||
|
(modules (<parser1> <parser2> ...))))
|
||
|
|
||
|
alias
|
||
|
-----
|
||
|
|
||
|
The ``alias`` stanza lets you add dependencies to an alias, or specify an action
|
||
|
to run to construct the alias.
|
||
|
|
||
|
The syntax is as follows:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(alias
|
||
|
((name <alias-name>)
|
||
|
(deps (<deps-conf list>))
|
||
|
<optional-fields>
|
||
|
))
|
||
|
|
||
|
``<name>`` is an alias name such as ``runtest``.
|
||
|
|
||
|
``<deps-conf list>`` specifies the dependencies of the alias. See the
|
||
|
*dependency specification section* for more details.
|
||
|
|
||
|
``<optional-fields>`` are:
|
||
|
|
||
|
- ``<action>``, an action to run when constructing the alias. See
|
||
|
the *actions section* for more details.
|
||
|
|
||
|
- ``(package <name>)`` indicates that this alias stanza is part of
|
||
|
package ``<name>`` and should be filtered out if ``<name>`` is
|
||
|
filtered out from the command line, either with
|
||
|
``--only-packages <pkgs>`` or ``-p <pkgs>``
|
||
|
|
||
|
The typical use of the ``alias`` stanza is to define tests:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(alias
|
||
|
((name runtest)
|
||
|
(action (run ${exe:my-test-program.exe} blah))))
|
||
|
|
||
|
See the *section about running tests* for details.
|
||
|
|
||
|
Note that if your project contains several packages and you run test the tests
|
||
|
from the opam file using a ``build-test`` field, then all your ``runtest`` alias
|
||
|
stanzas should have a ``(package ...)`` field in order to partition the set of
|
||
|
tests.
|
||
|
|
||
|
install
|
||
|
-------
|
||
|
|
||
|
The ``install`` stanza is what lets you describe what Jbuilder should install,
|
||
|
either when running ``jbuilder install`` or through opam.
|
||
|
|
||
|
Libraries don't need an ``install`` stanza to be installed, just a
|
||
|
``public_name`` field. Everything else needs an ``install`` stanza.
|
||
|
|
||
|
The syntax is as follows:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(install
|
||
|
((section <section>)
|
||
|
(files (<filenames>))
|
||
|
<optional-fields>
|
||
|
))
|
||
|
|
||
|
``<section>`` is the installation section, as described in the opam
|
||
|
manual. The following sections are available:
|
||
|
|
||
|
- ``lib``
|
||
|
- ``libexec``
|
||
|
- ``bin``
|
||
|
- ``sbin``
|
||
|
- ``toplevel``
|
||
|
- ``share``
|
||
|
- ``share_root``
|
||
|
- ``etc``
|
||
|
- ``doc``
|
||
|
- ``stublibs``
|
||
|
- ``man``
|
||
|
- ``misc``
|
||
|
|
||
|
=<files>= is the list of files to install.
|
||
|
|
||
|
``<optional-fields>`` are:
|
||
|
|
||
|
- ``(package <name>)``. If there are no ambiguities, you can omit
|
||
|
this field. Otherwise you need it to specify which package these
|
||
|
files are part of. The package is not ambiguous when the first
|
||
|
parent directory to contain a ``<package>.opam`` file contains
|
||
|
exactly one ``<package>.opam`` file
|
||
|
|
||
|
Common items
|
||
|
============
|
||
|
|
||
|
Ordered set language
|
||
|
--------------------
|
||
|
|
||
|
A few fields takes as argument an ordered set and can be specified using a small
|
||
|
DSL.
|
||
|
|
||
|
This DSL is interpreted by jbuilder into an ordered set of strings using the
|
||
|
following rules:
|
||
|
|
||
|
- ``:standard`` denotes the standard value of the field when it is absent
|
||
|
- an atom not starting with a ``:`` is a singleton containing only this atom
|
||
|
- a list of sets is the concatenation of its inner sets
|
||
|
- ``(<sets1> \ <sets2>)`` is the set composed of elements of ``<sets1>`` that do
|
||
|
not appear in ``<sets2>``
|
||
|
|
||
|
In addition, some fields support the inclusion of an external file using the
|
||
|
syntax ``(:include <filename>)``. This is useful for instance when you need to
|
||
|
run a script to figure out some compilation flags. ``<filename>`` is expected to
|
||
|
contain a single S-expression and cannot contain ``(:include ...)`` forms.
|
||
|
|
||
|
Most fields using the ordered set language also support *variables expansion*.
|
||
|
Variables are expanded after the set language is interpreted.
|
||
|
|
||
|
Variables expansion
|
||
|
-------------------
|
||
|
|
||
|
Some fields can contains variables of the form ``$(var)`` or ``${var}`` that are
|
||
|
expanded by Jbuilder.
|
||
|
|
||
|
Jbuilder supports the following variables:
|
||
|
|
||
|
- ``ROOT`` is the relative path to the root of the build context
|
||
|
- ``CC`` is the C compiler command line being used in the current
|
||
|
build context
|
||
|
- ``CXX`` is the C++ compiler command line being used in the
|
||
|
current build context
|
||
|
- ``ocaml_bin`` is the path where ``ocamlc`` lives
|
||
|
- ``OCAML`` is the ``ocaml`` binary
|
||
|
- ``OCAMLC`` is the ``ocamlc`` binary
|
||
|
- ``OCAMLOPT`` is the ``ocamlopt`` binary
|
||
|
- ``ocaml_version`` is the version of the compiler used in the
|
||
|
current build context
|
||
|
- ``ocaml_where`` is the output of ``ocamlc -where``
|
||
|
- ``ARCH_SIXTYFOUR`` is ``true`` if using a compiler targeting a
|
||
|
64 bit architecture and ``false`` otherwise
|
||
|
- ``null`` is ``/dev/null`` on Unix or ``nul`` on Windows
|
||
|
|
||
|
In addition, ``(action ...)`` fields support the following special variables:
|
||
|
|
||
|
- ``@`` expands to the list of target, separated by spaces
|
||
|
- ``<`` expands to the first dependency, or the empty string if
|
||
|
there are no dependencies
|
||
|
- ``^`` expands to the list of dependencies, separated by spaces
|
||
|
- ``path:<path>`` expands to ``<path>``
|
||
|
- ``exe:<path>`` is the same as ``<path>``, except when
|
||
|
cross-compiling, in which case it will expand to ``<path>``
|
||
|
from the host build context
|
||
|
- ``bin:<program>`` expands to a path to ``program``. If
|
||
|
``program`` is installed by a package in the workspace (see
|
||
|
*install stanzas*), the locally built binary will be used,
|
||
|
otherwise it will be searched in the ``PATH`` of the current
|
||
|
build context
|
||
|
- ``lib:<public-library-name>:<file>`` expands to a path to file
|
||
|
``<file>`` of library ``<public-library-name>``. If
|
||
|
``<public-library-name>`` is available in the current
|
||
|
workspace, the local file will be used, otherwise the one from
|
||
|
the installed world will be used
|
||
|
- ``libexec:<public-library-name>:<file>`` is the same as
|
||
|
``lib:...`` except when cross-compiling, in which case it will
|
||
|
expand to the file from the host build context
|
||
|
- ``lib-available:<library-name>`` expands to ``true`` or
|
||
|
``false`` depending on wether the library is available or not.
|
||
|
A library is available iff at least one of the following
|
||
|
condition holds:
|
||
|
|
||
|
- it is part the installed worlds
|
||
|
- it is available locally and is not optional
|
||
|
- it is available locally and all its library dependencies are
|
||
|
available
|
||
|
|
||
|
- ``version:<package>`` expands to the version of the given
|
||
|
package. Note that this is only supported for packages that are
|
||
|
being defined in the current scope
|
||
|
|
||
|
The ``${<kind>:...}`` forms are what allows you to write custom rules that work
|
||
|
transparently whether things are installed or not.
|
||
|
|
||
|
Library dependencies
|
||
|
--------------------
|
||
|
|
||
|
Dependencies on libraries are specified using ``(libraries ...)``
|
||
|
fields in ``library`` and ``executables`` stanzas.
|
||
|
|
||
|
For libraries that are present in the workspace, you can use
|
||
|
either the real name (with some restrictions, see below) or the
|
||
|
public name. For libraries that are part of the installed world,
|
||
|
you need to use the public name. For instance:
|
||
|
``(libraries (base re))``.
|
||
|
|
||
|
When resolving libraries, libraries that are part of the workspace
|
||
|
are always prefered to ones that are part of the installed world.
|
||
|
|
||
|
#. Scope of internal library names
|
||
|
|
||
|
The scope of internal library names is not the whole workspace.
|
||
|
It is restricted to the subtree starting from the closest
|
||
|
parent containing a ``<package>.opam`` file, or the whole
|
||
|
workspace if no such directory exist. Moreover, a subtree
|
||
|
containing ``<package>.opam`` doesn' t inherit the internal
|
||
|
names available in its parent scope.
|
||
|
|
||
|
The idea behing this rule is that public library names must be
|
||
|
universally unique, but internal ones don't need to. In
|
||
|
particular you might have private libraries that are only used
|
||
|
for tests or building an executable.
|
||
|
|
||
|
As a result, when you create a workspace including several
|
||
|
projects there might be a name clash between internal library
|
||
|
names.
|
||
|
|
||
|
This scoping rule ensure that this won't be a problem.
|
||
|
|
||
|
#. Alternative dependencies
|
||
|
|
||
|
In addition to direct dependencies you can specify alternative
|
||
|
dependencies. This is described in the *alternative
|
||
|
dependencies section*
|
||
|
|
||
|
It is sometimes the case that one wants to not depend on a
|
||
|
specific library, but instead on whatever is already installed.
|
||
|
For instance to use a different backend depending on the
|
||
|
target.
|
||
|
|
||
|
Jbuilder allows this by using a ``(select ... from ...)`` form
|
||
|
inside the list of library dependencies.
|
||
|
|
||
|
Select forms are specified as follows:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(select <target-filename> from
|
||
|
((<literals> -> <filename>)
|
||
|
(<literals> -> <filename>)
|
||
|
...))
|
||
|
|
||
|
``<literals>`` are lists of literals, where each literal is one
|
||
|
of:
|
||
|
|
||
|
- ``<library-name>``, which will evaluate to true if
|
||
|
``<library-name>`` is available, either in the workspace or
|
||
|
in the installed world
|
||
|
- ``!<library-name>``, which will evaluate to true if
|
||
|
``<library-name>`` is not available in the workspace or in
|
||
|
the installed world
|
||
|
|
||
|
When evaluating a select form, Jbuilder will create
|
||
|
``<target-filename>`` by copying the file given by the first
|
||
|
``(<literals> -> <filename>)`` case where all the literals
|
||
|
evaluate to true. It is an error if none of the clauses are
|
||
|
selectable. You can add a fallback by adding a clause of the
|
||
|
form ``(-> <file>)`` at the end of the list.
|
||
|
|
||
|
Preprocessing specification
|
||
|
---------------------------
|
||
|
|
||
|
Jbuilder accepts three kinds of preprocessing:
|
||
|
|
||
|
- ``no_preprocessing``, meaning that files are given as it to the
|
||
|
compiler, this is the default
|
||
|
- ``(action <action>)`` to preprocess files using the given
|
||
|
action
|
||
|
- ``(pps (<ppx-rewriters-and-flags>))`` to preprocess files using
|
||
|
the given list of ppx rewriters
|
||
|
|
||
|
Note that in any cases, files are preprocessed only once. Jbuilder
|
||
|
doesn't use the ``-pp`` or ``-ppx`` of the various OCaml tools.
|
||
|
|
||
|
#. Preprocessing with actions
|
||
|
|
||
|
``<action>`` uses the same DSL as described in the *user
|
||
|
actions section*, and for the same reason given in that
|
||
|
section, it will be executed from the root of the current build
|
||
|
context. It is expected to be an action that reads the file
|
||
|
given as only dependency and outputs the preprocessed file on
|
||
|
its standard output.
|
||
|
|
||
|
More precisely, ``(preprocess (action <action>))`` acts as if
|
||
|
you had setup a rule for every file of the form:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(rule
|
||
|
((targets (file.pp.ml))
|
||
|
(deps (file.ml))
|
||
|
(action (with-stdout-to ${@} (chdir ${ROOT} <action>)))))
|
||
|
|
||
|
The equivalent of a ``-pp <command>`` option passed to the
|
||
|
OCaml compiler is ``(system "<command> ${<}")``.
|
||
|
|
||
|
#. Preprocessing with ppx rewriters
|
||
|
|
||
|
``<ppx-rewriters-and-flags>`` is expected to be a list where
|
||
|
each element is either a command line flag if starting with a
|
||
|
``-`` or the name of a library. Additionnally, any sub-list
|
||
|
will be treated as a list of command line arguments. So for
|
||
|
instance from the following ``preprocess`` field:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(preprocess (pps (ppx1 -foo ppx2 (-bar 42))))
|
||
|
|
||
|
The list of libraries will be ``ppx1`` and ``ppx2`` and the
|
||
|
command line arguments will be: ``-foo -bar 42``.
|
||
|
|
||
|
Libraries listed here should be libraries implementing an OCaml
|
||
|
AST rewriter and registering themselves using the
|
||
|
`ocaml-migrate-parsetree.driver
|
||
|
API <https://github.com/let-def/ocaml-migrate-parsetree>`__.
|
||
|
|
||
|
Jbuilder will build a single executable by linking all these
|
||
|
libraries and their dependencies. Note that it is important
|
||
|
that all these libraries are linked with ``-linkall``. Jbuilder
|
||
|
automatically uses ``-linkall`` when the ``(kind ...)`` field
|
||
|
is set to ``ppx_rewriter`` or ``ppx_deriver``.
|
||
|
|
||
|
It is guaranteed that the last library in the list will be
|
||
|
linked last. You can use this feature to use a custom ppx
|
||
|
driver. By default Jbuilder will use
|
||
|
``ocaml-migrate-parsetree.driver-main``. See the *section about
|
||
|
using a custom ppx driver* for more details.
|
||
|
|
||
|
#. Per module preprocessing specification
|
||
|
|
||
|
By default a preprocessing specification will apply to all
|
||
|
modules in the library/set of executables. It is possible to
|
||
|
select the preprocessing on a module-by-module basis by using
|
||
|
the following syntax:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(preprocess (per_file
|
||
|
(<spec1> (<module-list1>))
|
||
|
(<spec2> (<module-list2>))
|
||
|
...))
|
||
|
|
||
|
Where ``<spec1>``, ``<spec2>``, ... are preprocessing
|
||
|
specifications and ``<module-list1>``, ``<module-list2>``, ...
|
||
|
are list of module names. It is currently not possible to
|
||
|
distinguish between .ml/.mli files, however it wouldn't be hard
|
||
|
to support if needed.
|
||
|
|
||
|
For instance:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(preprocess (per_file
|
||
|
((command "./pp.sh X=1" (foo bar)))
|
||
|
((command "./pp.sh X=2" (baz)))))
|
||
|
|
||
|
Dependency specification
|
||
|
------------------------
|
||
|
|
||
|
Dependencies in ``jbuild`` files can be specified using one of the
|
||
|
following syntax:
|
||
|
|
||
|
- ``(file <filename>)`` or simply ``<filename>``: depend on this
|
||
|
file
|
||
|
- ``(alias <alias-name>)``: depend on the construction of this
|
||
|
alias, for instance: ``(alias src/runtest)``
|
||
|
- ``(glob_files <glob>)``: depend on all files matched by
|
||
|
``<glob>``, see the *glob section* for details
|
||
|
- ``(files_recursively_in <dir>)``: depend on all files in the
|
||
|
subtree with root ``<dir>``
|
||
|
|
||
|
In all these cases, the argument supports *variables expansion*.
|
||
|
|
||
|
#. Glob
|
||
|
|
||
|
You can use globs to declare dependencies on a set of files.
|
||
|
Note that globs will match files that exist in the source tree
|
||
|
as well as buildable targets, so for instance you can depend on
|
||
|
``*.cmi``.
|
||
|
|
||
|
Currently jbuilder only support globbing files in a single
|
||
|
directory. And in particular the glob is interpreted as
|
||
|
follows:
|
||
|
|
||
|
- anything before the last ``/`` is taken as a literal path
|
||
|
- anything after the last ``/``, or everything if the glob
|
||
|
contains no ``/``, is interpreted using the glob syntax
|
||
|
|
||
|
The glob syntax is interpreted as follows:
|
||
|
|
||
|
- ``\<char>`` matches exactly ``<char>``, even if it is a
|
||
|
special character (``*``, ``?``, ...)
|
||
|
- ``*`` matches any sequence of characters, except if it comes
|
||
|
first in which case it matches any character that is not
|
||
|
``.`` followed by anything
|
||
|
- ``**`` matches any character that is not ``.`` followed by
|
||
|
anything, except if it comes first in which case it matches
|
||
|
anything
|
||
|
- ``?`` matches any single character
|
||
|
- ``[<set>]`` matches any character that is part of ``<set>``
|
||
|
- ``[!<set>]`` matches any character that is not part of
|
||
|
``<set>``
|
||
|
- ``{<glob1>,<glob2>,...,<globn>}`` matches any string that is
|
||
|
matched by one of ``<glob1>``, ``<glob2>``, ...
|
||
|
|
||
|
OCaml flags
|
||
|
-----------
|
||
|
|
||
|
In ``library`` and ``executables`` stanzas, you can specify OCaml
|
||
|
compilation flags using the following fields:
|
||
|
|
||
|
- ``(flags <flags>)`` to specify flags passed to both ``ocamlc``
|
||
|
and ``ocamlopt``
|
||
|
- ``(ocamlc_flags <flags>)`` to specify flags passed to
|
||
|
``ocamlc`` only
|
||
|
- ``(ocamlopt_flags <flags>)`` to specify flags passed to
|
||
|
``ocamlopt`` only
|
||
|
|
||
|
For all these fields, ``<flags>`` is specified in the *ordered set
|
||
|
language*.
|
||
|
|
||
|
The default value for ``(flags ...)`` includes some ``-w`` options
|
||
|
to set warnings. The exact set depends on whether ``--dev`` is
|
||
|
passed to Jbuilder. As a result it is recommended to write
|
||
|
``(flags ...)`` fields as follows:
|
||
|
|
||
|
::
|
||
|
|
||
|
(flags (:standard <my options>))
|
||
|
|
||
|
js_of_ocaml
|
||
|
-----------
|
||
|
|
||
|
In ``library`` and ``executables`` stanzas, you can specify js_of_ocaml options
|
||
|
using ``(js_of_ocaml (<js_of_ocaml-options>))``.
|
||
|
|
||
|
``<js_of_ocaml-options>`` are all optional:
|
||
|
|
||
|
- ``(flags <flags>)`` to specify flags passed to ``js_of_ocaml``
|
||
|
|
||
|
- ``(javascript_files (<files-list>))`` to specify ``js_of_ocaml`` JavaScript
|
||
|
runtime files.
|
||
|
|
||
|
=<flags>= is specified in the *ordered set language*.
|
||
|
|
||
|
The default value for ``(flags ...)`` depends on whether ``--dev`` is passed to
|
||
|
Jbuilder. ``--dev`` will enable sourcemap and the pretty JavaScript output.
|
||
|
|
||
|
User actions
|
||
|
------------
|
||
|
|
||
|
``(action ...)`` fields describe user actions.
|
||
|
|
||
|
User actions are always run from the same subdirectory of the current build
|
||
|
context as the jbuild they are defined in. So for instance an action defined in
|
||
|
``src/foo/jbuild`` will be run from ``_build/<context>/src/foo``.
|
||
|
|
||
|
The argument of ``(action ...)`` fields is a small DSL that is interpreted by
|
||
|
jbuilder directly and doesn't require an external shell. All atoms in the DSL
|
||
|
support *variables expansion*. Moreover, you don't need to specify dependencies
|
||
|
explicitly for the special ``${<kind>:...}`` forms, these are recognized and
|
||
|
automatically handled by Jbuilder.
|
||
|
|
||
|
The DSL is currently quite limited, so if you want to do something complicated
|
||
|
it is recommended to write a small OCaml program and use the DSL to invoke it.
|
||
|
You can use `shexp <https://github.com/janestreet/shexp>`__ to write portable
|
||
|
scripts or `configurator <https://github.com/janestreet/configurator>`__ for
|
||
|
configuration related tasks.
|
||
|
|
||
|
The following constructions are available:
|
||
|
|
||
|
- ``(run <prog> <args>)`` to execute a program
|
||
|
- ``(chdir <dir> <DSL>)`` to change the current directory
|
||
|
- ``(setenv <var> <value> <DSL>)`` to set an environment variable
|
||
|
- ``(with-<outputs>-to <file> <DSL>)`` to redirect the output to a file, where
|
||
|
``<outputs>`` is one of: ``stdout``, ``stderr`` or ``outputs`` (for both
|
||
|
``stdout`` and ``stderr``)
|
||
|
- ``(ignore-<outputs> <DSL)`` to ignore the output, where
|
||
|
``<outputs>`` is one of: ``stdout``, ``stderr`` or ``outputs``
|
||
|
- ``(progn <DSL>...)`` to execute several commands in sequence
|
||
|
- ``(echo <string>)`` to output a string on stdout
|
||
|
- ``(cat <file>)`` to print the contents of a file to stdout
|
||
|
- ``(copy <src> <dst>)`` to copy a file
|
||
|
- ``(copy-and-add-line-directive <src> <dst>)`` to copy a file and add a line
|
||
|
directive at the beginning
|
||
|
- ``(system <cmd>)`` to execute a command using the system shell: ``sh`` on Unix
|
||
|
and ``cmd`` on Windows
|
||
|
- ``(bash <cmd>)`` to execute a command using ``/bin/bash``. This is obviously
|
||
|
not very portable
|
||
|
|
||
|
Note: expansion of the special ``${<kind>:...}`` is done relative to the current
|
||
|
working directory of the part of the DSL being executed. So for instance if you
|
||
|
have this action in a ``src/foo/jbuild``:
|
||
|
|
||
|
.. code:: scheme
|
||
|
|
||
|
(action (chdir ../../.. (echo ${path:jbuild})))
|
||
|
|
||
|
Then ``${path:jbuild}`` will expand to ``src/foo/jbuild``. When you run various
|
||
|
tools, they often use the filename given on the command line in error messages.
|
||
|
As a result, if you execute the command from the original directory, it will
|
||
|
only see the basename.
|
||
|
|
||
|
To understand why this is important, let's consider this jbuild living in
|
||
|
``src/foo``:
|
||
|
|
||
|
::
|
||
|
|
||
|
(rule
|
||
|
((targets (blah.ml))
|
||
|
(deps (blah.mll))
|
||
|
(action (run ocamllex -o ${@} ${<}))))
|
||
|
|
||
|
Here the command that will be executed is:
|
||
|
|
||
|
.. code:: bash
|
||
|
|
||
|
ocamllex -o blah.ml blah.mll
|
||
|
|
||
|
And it will be executed in ``_build/<context>/src/foo``. As a result, if there
|
||
|
is an error in the generated ``blah.ml`` file it will be reported as:
|
||
|
|
||
|
::
|
||
|
|
||
|
File "blah.ml", line 42, characters 5-10:
|
||
|
Error: ...
|
||
|
|
||
|
Which can be a problem as you editor might think that ``blah.ml`` is at the root
|
||
|
of your project. What you should write instead is:
|
||
|
|
||
|
::
|
||
|
|
||
|
(rule
|
||
|
((targets (blah.ml))
|
||
|
(deps (blah.mll))
|
||
|
(action (chdir ${ROOT} (run ocamllex -o ${@} ${<})))))
|
||
|
|
||
|
OCaml syntax
|
||
|
============
|
||
|
|
||
|
If a ``jbuild`` file starts with ``(* -*- tuareg -*- *)``, then it is
|
||
|
interpreted as an OCaml script that generates the ``jbuild`` file as described
|
||
|
in the rest of this section. The code in the script will have access to a
|
||
|
`Jbuild_plugin
|
||
|
<https://github.com/janestreet/jbuilder/blob/master/plugin/jbuild_plugin.mli>`__
|
||
|
module containing details about the build context it is executed in.
|
||
|
|
||
|
The script can use the directive ``#require`` to access libraries:
|
||
|
|
||
|
.. code:: ocaml
|
||
|
|
||
|
#require "base,re";;
|
||
|
|
||
|
Note that any library required by a ``jbuild`` file must be part of the
|
||
|
installed world.
|
||
|
|
||
|
If you don't like the S-expression syntax, then this method gives you a way to
|
||
|
use whatever else you want. For instance you could have an API to describe your
|
||
|
project in OCaml directly:
|
||
|
|
||
|
.. code:: ocaml
|
||
|
|
||
|
(* -*- tuareg -*- *)
|
||
|
#require "my_jbuild_api"
|
||
|
open My_jbuild_api
|
||
|
|
||
|
let () =
|
||
|
library "foo" ~modules:["plop"; "bidule"]
|
||
|
|
||
|
Currently the ``Jbuild_plugin`` module is only available inside plugins. It is
|
||
|
however planned to make it a proper library, see `the roadmap
|
||
|
<../ROADMAP.org>`__ for details.
|