1389 lines
49 KiB
ReStructuredText
1389 lines
49 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.
|
|
|
|
The syntax of ``jbuild`` files is described in
|
|
:ref:``metadata-format`` section.
|
|
|
|
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 :ref:`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 which should be built by default. The
|
|
most common use for this feature is to disable native compilation
|
|
when writing libraries for the OCaml toplevel. The following modes
|
|
are available: ``byte``, ``native`` and ``best``. ``best`` is
|
|
``native`` or ``byte`` when native compilation is not available
|
|
|
|
- ``(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 :ref:`jbuild-jsoo`
|
|
|
|
- ``flags``, ``ocamlc_flags`` and ``ocamlopt_flags``. See the section about
|
|
`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
|
|
|
|
- ``(modules_without_implementation <modules>)`` specifies a list of
|
|
modules that have only a ``.mli`` or ``.rei`` but no ``.ml`` or
|
|
``.re`` file. Such modules are usually referred as *mli only
|
|
modules*. They are not officially supported by the OCaml compiler,
|
|
however they are commonly used. Such modules must only define
|
|
types. Since it is not reasonably possible for Jbuilder to check
|
|
that this is the case, Jbuilder requires the user to explicitly list
|
|
such modules to avoid surprises. ``<modules>`` must be a subset of
|
|
the modules listed in the ``(modules ...)`` field.
|
|
|
|
- ``(allow_overlapping_dependencies)`` allows external dependencies to
|
|
overlap with libraries that are present in the workspace
|
|
|
|
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. Moreover, it is
|
|
usually preferable to use ``<name>.exe`` in custom rules or when
|
|
calling the executable by hand. This is because running a byte-code
|
|
executable often requires loading shared libraries that are locally
|
|
built, and so requires additional setup such as setting specific
|
|
environment variables and jbuilder doesn't do at the moment.
|
|
|
|
Native compilation is considered not available when there is no ``ocamlopt``
|
|
binary at the same place as where ``ocamlc`` was found.
|
|
|
|
Executables can also be linked as object or shared object files. See
|
|
`linking modes`_ for more information.
|
|
|
|
``<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
|
|
|
|
- ``(link_flags <flags>)`` specifies additional flags to pass to the linker.
|
|
This field supports ``(:include ...)`` forms
|
|
|
|
- ``(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 `library`_
|
|
|
|
- ``(modes (<modes>))`` sets the `linking modes`_. The default is
|
|
``(byte exe)``
|
|
|
|
- ``(preprocess <preprocess-spec>)`` is the same as the ``(preprocess ...)``
|
|
field of `library`_
|
|
|
|
- ``(preprocessor_deps (<deps-conf list>))`` is the same as the
|
|
``(preprocessor_deps ...)`` field of `library`_
|
|
|
|
- ``js_of_ocaml``. See the section about `js_of_ocaml`_
|
|
|
|
- ``flags``, ``ocamlc_flags`` and ``ocamlopt_flags``. See the section about
|
|
specifying `OCaml flags`_
|
|
|
|
- ``(modules_without_implementation <modules>)`` is the same as the
|
|
corresponding field of `library`_
|
|
|
|
- ``(allow_overlapping_dependencies)`` is the same as the
|
|
corresponding field of `library`_
|
|
|
|
Linking modes
|
|
~~~~~~~~~~~~~
|
|
|
|
The ``modes`` field allows to select what linking modes should be used
|
|
to link executables. Each mode is a pair ``(<compilation-mode>
|
|
<binary-kind>)`` where ``<compilation-mode>`` describes whether the
|
|
byte code or native code backend of the OCaml compiler should be used
|
|
and ``<binary-kind>`` describes what kind of file should be produced.
|
|
|
|
``<compilation-mode>`` must be ``byte``, ``native`` or ``best``, where
|
|
``best`` is ``native`` with a fallback to byte-code when native
|
|
compilation is not available.
|
|
|
|
``<binary-kind>`` is one of:
|
|
|
|
- ``exe`` for normal executables
|
|
- ``object`` for producing static object files that can be manually
|
|
linked into C applications
|
|
- ``shared_object`` for producing object files that can be dynamically
|
|
loaded into an application. This mode can be used to write a plugin
|
|
in OCaml for a non-OCaml application.
|
|
|
|
For instance the following ``executables`` stanza will produce byte
|
|
code executables and native shared objects:
|
|
|
|
.. code:: scheme
|
|
|
|
(executables
|
|
((names (a b c))
|
|
(modes ((byte exe) (native shared_object)))))
|
|
|
|
Additionally, you can use the following short-hands:
|
|
|
|
- ``exe`` for ``(best exe)``
|
|
- ``object`` for ``(best object)``
|
|
- ``shared_object`` for ``(best shared_object)``
|
|
- ``byte`` for ``(byte exe)``
|
|
- ``native`` for ``(native exe)``
|
|
|
|
For instance the following ``modes`` fields are all equivalent:
|
|
|
|
.. code:: scheme
|
|
|
|
(modes (exe object shared_object))
|
|
(modes ((best exe)
|
|
(best object)
|
|
(best shared_object)))
|
|
|
|
The extensions for the various linking modes are choosen as follow:
|
|
|
|
================ ============= =================
|
|
compilation mode binary kind extensions
|
|
---------------- ------------- -----------------
|
|
byte exe .bc and .bc.js
|
|
native/best exe .exe
|
|
byte object .bc${ext_obj}
|
|
native/best object .exe${ext_obj}
|
|
byte shared_object .bc${ext_dll}
|
|
native/best shared_object ${ext_dll}
|
|
================ ============= =================
|
|
|
|
Where ``${ext_obj}`` and ``${ext_dll}`` are the extensions for object
|
|
and shared object files. Their value depends on the OS, for instance
|
|
on Unix ``${ext_obj}`` is usually ``.o`` and ``${ext_dll}`` is usually
|
|
``.so`` while on Windows ``${ext_obj}`` is ``.obj`` and ``${ext_dll}``
|
|
is ``.dll``.
|
|
|
|
Note that when ``(byte exe)`` is specified but neither ``(best exe)``
|
|
nor ``(native exe)`` are specified, Jbuilkd still knows how to build
|
|
an executable with the extension ``.exe``. In such case, the ``.exe``
|
|
version is the same as the ``.bc`` one except that it is linked with
|
|
the ``-custom`` option of the compiler. You should always use the
|
|
``.exe`` rather that the ``.bc`` inside build rules.
|
|
|
|
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>))
|
|
(action <action>)
|
|
<optional-fields>))
|
|
|
|
``<filenames>`` is a list of file names. Note that currently Jbuilder only
|
|
support user rules with targets in the current directory.
|
|
|
|
``<action>`` is the action to run to produce the targets from the dependencies.
|
|
See the `User actions`_ section for more details.
|
|
|
|
``<optional-fields>`` are:
|
|
|
|
- ``(deps (<deps-conf list>))`` to specify the dependencies of the
|
|
rule. See the `Dependency specification`_ section for more details.
|
|
|
|
- ``(mode <mode>)`` to specify how to handle the targets, see `modes`_
|
|
for details
|
|
|
|
- ``(fallback)`` is deprecated and is the same as ``(mode fallback)``
|
|
|
|
- ``(locks (<lock-names>))`` specify that the action must be run while
|
|
holding the following locks. See the `Locks`_ 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.
|
|
|
|
modes
|
|
~~~~~
|
|
|
|
By default, the target of a rule must not exist in the source tree and
|
|
Jbuilder will error out when this is the case.
|
|
|
|
However, it is possible to change this behavior using the ``mode``
|
|
field. The following modes are available:
|
|
|
|
- ``standard``, this is the standard mode
|
|
|
|
- ``fallback``, in this mode, when the targets are already present in
|
|
the source tree, jbuilder will ignore the rule. It is an error if
|
|
only a subset of the targets are present in the tree. The common use
|
|
of fallback rules is to generate default configuration files that
|
|
may be generated by a configure script.
|
|
|
|
- ``promote``, in this mode, the files in the source tree will be
|
|
ignored. Once the rule has been executed, the targets will be copied
|
|
back to the source tree
|
|
|
|
- ``promote-until-clean`` is the same as ``promote`` except than
|
|
``jbuilder clean`` will remove the promoted files from the source
|
|
tree
|
|
|
|
|
|
There are two use cases for promote rules. The first one is when the
|
|
generated code is easier to review than the generator, so it's easier
|
|
to commit the generated code and review it. The second is to cut down
|
|
dependencies during releases: by passing ``--ignore-promoted-rules``
|
|
to jbuilder, rules will ``(mode promote)`` will be ignored and the
|
|
source files will be used instead. The
|
|
``-p/--for-release-of-packages`` flag implies
|
|
``--ignore-promote-rules``.
|
|
|
|
inferred rules
|
|
~~~~~~~~~~~~~~
|
|
|
|
When using the action DSL (see `User actions`_), it is most of the
|
|
time obvious what are the dependencies and targets.
|
|
|
|
For instance:
|
|
|
|
.. code:: scheme
|
|
|
|
(rule
|
|
((targets (b)
|
|
(deps (a)
|
|
(action (copy ${<} ${@}))))))
|
|
|
|
In this example it is obvious by inspecting the action what the
|
|
dependencies and targets are. When this is the case you can use the
|
|
following shorter syntax, where Jbuilder infers dependencies and
|
|
targets for you:
|
|
|
|
.. code:: scheme
|
|
|
|
(rule <action>)
|
|
|
|
For instance:
|
|
|
|
.. code:: scheme
|
|
|
|
(rule (copy a b))
|
|
|
|
Note that in Jbuilder, targets must always be known
|
|
statically. Especially, this mean that Jbuilder must be able to
|
|
statically determine all targets. For instance, this ``(rule ...)``
|
|
stanza is rejected by Jbuilder:
|
|
|
|
.. code:: scheme
|
|
|
|
(rule (copy a b.${read:file}))
|
|
|
|
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 ${<})))))
|
|
|
|
To use a different rule mode, use the long form:
|
|
|
|
.. code:: scheme
|
|
|
|
(ocamllex
|
|
((modules (<names>))
|
|
(mode <mode>)))
|
|
|
|
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} ${<})))))
|
|
|
|
To use a different rule mode, use the long form:
|
|
|
|
.. code:: scheme
|
|
|
|
(ocamlyacc
|
|
((modules (<names>))
|
|
(mode <mode>)))
|
|
|
|
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 `User
|
|
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>``
|
|
|
|
- ``(locks (<lock-names>))`` specify that the action must be run while
|
|
holding the following locks. See the `Locks`_ section for more details.
|
|
|
|
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 :ref:`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 and executables 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. Each element in the list
|
|
must be either a literal filename or a S-expression of the form:
|
|
|
|
.. code:: scheme
|
|
|
|
(<filename> as <destination>)
|
|
|
|
where ``<destination>`` describe how the file will be installed. For
|
|
instance, to install a file ``mylib.el`` as
|
|
``emacs/site-lisp/mylib.el`` in the ``share_root`` section:
|
|
|
|
(install
|
|
((section share_root)
|
|
(files ((mylib.el as emacs/site-lisp/mylib.el)))))
|
|
|
|
``<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
|
|
|
|
Handling of the .exe extension on Windows
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Under Microsoft Windows, executables must be suffixed with
|
|
``.exe``. Jbuilder tries to make sure that executables are always
|
|
installed with this extension on Windows.
|
|
|
|
More precisely, when installing a file via an ``(install ...)``
|
|
stanza, if the source file has extension ``.exe`` or ``.bc``, then
|
|
Jbuilder implicitly adds the ``.exe`` extension to the destination, if
|
|
not already present.
|
|
|
|
copy_files
|
|
----------
|
|
|
|
The ``copy_files`` and ``copy_files#`` stanzas allow to specify that
|
|
files from another directory could be copied if needed to the current
|
|
directory.
|
|
|
|
The syntax is as follows:
|
|
|
|
.. code:: scheme
|
|
|
|
(copy_files <glob>)
|
|
|
|
``<glob>`` represents the set of files to copy, see the :ref:`glob
|
|
<glob>` for details.
|
|
|
|
The difference between ``copy_files`` and ``copy_files#`` is the same
|
|
as the difference between the ``copy`` and ``copy#`` action. See the
|
|
`User actions`_ section for more details.
|
|
|
|
include
|
|
-------
|
|
|
|
The ``include`` stanza allows to include the contents of another file
|
|
into the current jbuild file. Currently, the included file cannot be
|
|
generated and must be present in the source tree. This feature is
|
|
intended to be used in conjunction with promotion, when parts of a
|
|
jbuild file are to be generated.
|
|
|
|
For instance:
|
|
|
|
.. code:: scheme
|
|
|
|
(include jbuild.inc)
|
|
|
|
(rule (with-stdout-to jbuild.inc.gen (run ./gen-jbuild.exe)))
|
|
|
|
(alias
|
|
((name runtest)
|
|
(action (diff jbuild.inc jbuild.inc.gen))))
|
|
|
|
With this jbuild file, running jbuilder as follow will replace the
|
|
``jbuild.inc`` file in the source tree by the generated one:
|
|
|
|
.. code:: shell
|
|
|
|
$ jbuilder build @runtest --auto-promote
|
|
|
|
Common items
|
|
============
|
|
|
|
.. _ordered-set-language:
|
|
|
|
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. Note that ``ROOT`` depends on the worksace
|
|
configuration. As such you shouldn't use ``ROOT`` to denote the
|
|
root of your project. Use ``SCOPE_ROOT`` instead for this purpose
|
|
- ``SCOPE_ROOT`` is the root of the current scope. It is typically
|
|
the toplevel directory of your project and as long as you have at
|
|
least one ``<package>.opam`` file there, ``SCOPE_ROOT`` is
|
|
independent of the workspace configuration
|
|
- ``CC`` is the C compiler command line (list made of the compiler
|
|
name followed by its flags) that was used to compile OCaml 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
|
|
- ``ext_obj``, ``ext_asm``, ``ext_lib``, ``ext_dll`` and ``ext_exe``
|
|
are the file extension used for various artifacts
|
|
- ``ocaml-config:v`` for every variable ``v`` in the output of
|
|
``ocamlc -config``. Note that output Jbuilder processes the output
|
|
of ``ocamlc -config`` in order to make it a bit more stable across
|
|
versions, so the exact set of variables accessible this way might
|
|
not be exactly the same as what you can see in the output of
|
|
``ocamlc -config``. In particular, variables added in new versions
|
|
of OCaml needs to be registered in Jbuilder before they can be used
|
|
|
|
In addition, ``(action ...)`` fields support the following special variables:
|
|
|
|
- ``@`` expands to the list of target
|
|
- ``<`` 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>``
|
|
- ``path-no-dep:<path>`` is the same as ``path:<path>``, except that
|
|
``<path>`` is not considered as a dependency of the action. For instance
|
|
``(chdir ${ROOT} (run foo --base ${path-no-dep:bar}))`` in ``src/blah/jbuild``
|
|
will expand to ``(chdir ../.. (run foo --base src/blah/bar))`` where
|
|
``src/blah/bar`` doesn't have to be an existing or buildable file
|
|
- ``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. Note that ``(run
|
|
${bin:program} ...)`` and ``(run program ...)`` behave in the same
|
|
way. ``${bin:...}`` is only necessary when you are using ``(bash
|
|
...)`` or ``(system ...)``
|
|
- ``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
|
|
whether 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
|
|
- ``read:<path>`` expands to the contents of the given file
|
|
- ``read-lines:<path>`` expands to the list of lines in the given
|
|
file
|
|
- ``read-strings:<path>`` expands to the list of lines in the given
|
|
file, unescaped using OCaml lexical convention
|
|
|
|
The ``${<kind>:...}`` forms are what allows you to write custom rules that work
|
|
transparently whether things are installed or not.
|
|
|
|
Note that aliases are ignored by both ``${<}`` and ``${^}``.
|
|
|
|
The intent of this last form is to reliably read a list of strings
|
|
generated by an OCaml program via:
|
|
|
|
.. code:: ocaml
|
|
|
|
List.iter (fun s -> print_string (String.escaped s)) l
|
|
|
|
#. Expansion of lists
|
|
|
|
Forms that expands to list of items, such as ``${CC}``, ``${^}``,
|
|
``${@}`` or ``${read-lines:...}``, are suitable to be used in, say,
|
|
``(run <prog> <arguments>)``. For instance in:
|
|
|
|
.. code:: scheme
|
|
|
|
(run foo ${^})
|
|
|
|
if there are two dependencies ``a`` and ``b``, the produced command
|
|
will be equivalent to the shell command:
|
|
|
|
.. code:: shell
|
|
|
|
$ foo "a" "b"
|
|
|
|
If you want the two dependencies to be passed as a single argument,
|
|
you have to quote the variable as in:
|
|
|
|
.. code:: scheme
|
|
|
|
(run foo "${^}")
|
|
|
|
which is equivalent to the following shell command:
|
|
|
|
.. code:: shell
|
|
|
|
$ foo "a b"
|
|
|
|
(the items of the list are concatenated with space).
|
|
Note that, since ``${^}`` is a list of items, the first one may be
|
|
used as a program name, for instance:
|
|
|
|
.. code:: scheme
|
|
|
|
(rule
|
|
((targets (result.txt))
|
|
(deps (foo.exe (glob_files *.txt)))
|
|
(action (run ${^}))))
|
|
|
|
Here is another example:
|
|
|
|
.. code:: scheme
|
|
|
|
(rule
|
|
((targets (foo.exe))
|
|
(deps (foo.c))
|
|
(action (run ${CC} -o ${@} ${<} -lfoolib))))
|
|
|
|
|
|
Library dependencies
|
|
--------------------
|
|
|
|
Dependencies on libraries are specified using ``(libraries ...)`` fields in
|
|
``library`` and ``executables`` stanzas.
|
|
|
|
For libraries defined in the current scope, you can use either the
|
|
real name or the public name. For libraries that are part of the
|
|
installed world, or for libraries that are part of the current
|
|
workspace but in another scope, you need to use the public name. For
|
|
instance: ``(libraries (base re))``.
|
|
|
|
When resolving libraries, libraries that are part of the workspace are always
|
|
preferred to ones that are part of the installed world.
|
|
|
|
.. _alternative-deps:
|
|
|
|
Alternative dependencies
|
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
In addition to direct dependencies you can specify alternative dependencies.
|
|
This is described in the :ref:`Alternative dependencies <alternative-deps>`
|
|
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.
|
|
Additionally, 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
|
|
:ref:`custom-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_module
|
|
(<spec1> (<module-list1>))
|
|
(<spec2> (<module-list2>))
|
|
...))
|
|
|
|
Where ``<spec1>``, ``<spec2>``, ... are preprocessing specifications
|
|
and ``<module-list1>``, ``<module-list2>``, ... are list of module
|
|
names.
|
|
|
|
For instance:
|
|
|
|
.. code:: scheme
|
|
|
|
(preprocess (per_module
|
|
(((action (run ./pp.sh X=1 ${<})) (foo bar)))
|
|
(((action (run ./pp.sh X=2 ${<})) (baz)))))
|
|
|
|
.. _deps-field:
|
|
|
|
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)``
|
|
- ``(alias_rec <alias-name>)``: depend on the construction of this
|
|
alias recursively in all children directories wherever it is
|
|
defined. For instance: ``(alias_rec src/runtest)`` might depend on
|
|
``(alias src/runtest)``, ``(alias src/foo/bar/runtest)``, ...
|
|
- ``(glob_files <glob>)``: depend on all files matched by ``<glob>``, see the
|
|
:ref:`glob <glob>` for details
|
|
- ``(files_recursively_in <dir>)``: depend on all files in the subtree with root
|
|
``<dir>``
|
|
- ``(universe)``: depend on everything in the universe. This is for
|
|
cases where dependencies are too hard to specify. Note that Jbuilder
|
|
will not be able to cache the result of actions that depend on the
|
|
universe. In any case, this is only for dependencies in the
|
|
installed world, you must still specify all dependencies that come
|
|
from the workspace.
|
|
- ``(package <pkg>)`` depend on all files installed by ``<package>``, as well
|
|
as on the transitive package dependencies of ``<package>``. This can be used
|
|
to test a command against the files that will be installed
|
|
|
|
In all these cases, the argument supports `Variables expansion`_.
|
|
|
|
.. _glob:
|
|
|
|
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`_.
|
|
These fields all support ``(:include ...)`` forms.
|
|
|
|
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>))
|
|
|
|
.. _jbuild-jsoo:
|
|
|
|
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``. This field
|
|
supports ``(:include ...)`` forms
|
|
|
|
- ``(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:
|
|
|
|
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`_ for configuration related tasks.
|
|
|
|
The following constructions are available:
|
|
|
|
- ``(run <prog> <args>)`` to execute a program. ``<prog>`` is resolved
|
|
locally if it is available in the current workspace, otherwise it is
|
|
resolved using the ``PATH``
|
|
- ``(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
|
|
- ``(write-file <file> <string>)`` writes ``<string>`` to ``<file>``
|
|
- ``(cat <file>)`` to print the contents of a file to stdout
|
|
- ``(copy <src> <dst>)`` to copy a file
|
|
- ``(copy# <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
|
|
- ``(diff <file1> <file2>)`` is similar to ``(run diff <file1>
|
|
<file2>)`` but is better and allows promotion. See `Diffing and
|
|
promotion`_ for more details
|
|
- ``(diff? <file1> <file2>)`` is the same as ``(diff <file1>
|
|
<file2>)`` except that it is ignored when ``<file1>`` or ``<file2>``
|
|
doesn't exists
|
|
|
|
As mentioned ``copy#`` inserts a line directive at the beginning of
|
|
the destination file. More precisely, it inserts the following line:
|
|
|
|
.. code:: ocaml
|
|
|
|
# 1 "<source file name>"
|
|
|
|
Most languages recognize such lines and update their current location,
|
|
in order to report errors in the original file rather than the
|
|
copy. This is important as the copy exists only under the ``_build``
|
|
directory and in order for editors to jump to errors when parsing the
|
|
output of the build system, errors must point to files that exist in
|
|
the source tree. In the beta versions of jbuilder, ``copy#`` was
|
|
called ``copy-and-add-line-directive``. However, most of time one
|
|
wants this behavior rather than a bare copy, so it was renamed to
|
|
something shorter.
|
|
|
|
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 ${@} ${<})))))
|
|
|
|
Locks
|
|
-----
|
|
|
|
Given two rules that are independent, Jbuilder will assume that there
|
|
associated action can be run concurrently. Two rules are considered
|
|
independent if none of them depend on the other, either directly or
|
|
through a chain of dependencies. This basic assumption allows to
|
|
parallelize the build.
|
|
|
|
However, it is sometimes the case that two independent rules cannot be
|
|
executed concurrently. For instance this can happen for more
|
|
complicated tests. In order to prevent jbuilder from running the
|
|
actions at the same time, you can specify that both actions take the
|
|
same lock:
|
|
|
|
.. code:: scheme
|
|
|
|
(alias
|
|
((name runtest)
|
|
(deps (foo))
|
|
(locks (m))
|
|
(action (run test.exe ${<}))))
|
|
|
|
(alias
|
|
((name runtest)
|
|
(deps (bar))
|
|
(locks (m))
|
|
(action (run test.exe ${<}))))
|
|
|
|
Jbuilder will make sure that the executions of ``test.exe foo`` and
|
|
``test.exe bar`` are serialized.
|
|
|
|
Although they don't live in the filesystem, lock names are interpreted
|
|
as file names. So for instance ``(with-lock m ...)`` in ``src/jbuild``
|
|
and ``(with-lock ../src/m)`` in ``test/jbuild`` refer to the same
|
|
lock.
|
|
|
|
Note also that locks are per build context. So if your workspace has
|
|
two build contexts setup, the same rule might still be executed
|
|
concurrently between the two build contexts. If you want a lock that
|
|
is global to all build contexts, simply use an absolute filename:
|
|
|
|
.. code:: scheme
|
|
|
|
(alias
|
|
((name runtest)
|
|
(deps (foo))
|
|
(locks (/tcp-port/1042))
|
|
(action (run test.exe ${<}))))
|
|
|
|
.. _ocaml-syntax:
|
|
|
|
Diffing and promotion
|
|
---------------------
|
|
|
|
``(diff <file1> <file2>)`` is very similar to ``(run diff <file1>
|
|
<file2>)``. In particular it behaves in the same way:
|
|
|
|
- when ``<file1>`` and ``<file2>`` are equal, it doesn't nothing
|
|
- when they are not, the differences are shown and the action fails
|
|
|
|
However, it is different for the following reason:
|
|
|
|
- the exact command used to diff files can be configured via the
|
|
``--diff-command`` command line argument. Note that it is only
|
|
called when the files are not byte equals
|
|
|
|
- by default, it will use ``patdiff`` if it is installed. ``patdiff``
|
|
is a better diffing program. You can install it via opam with:
|
|
|
|
.. code:: sh
|
|
|
|
$ opam install patdiff
|
|
|
|
- since ``(diff a b)`` is a builtin action, Jbuilder knowns that ``a``
|
|
and ``b`` are needed and so you don't need to specify them
|
|
explicitly as dependencies
|
|
|
|
- you can use ``(diff? a b)`` after a command that might or might not
|
|
produce ``b``. For cases where commands optionally produce a
|
|
*corrected* file
|
|
|
|
- it allows promotion. See below
|
|
|
|
Promotion
|
|
~~~~~~~~~
|
|
|
|
Whenever an action ``(diff <file1> <file2>)`` or ``(diff? <file1>
|
|
<file2>)`` fails because the two files are different, jbuilder allows
|
|
you to promote ``<file2>`` as ``<file1>`` if ``<file1>`` is a source
|
|
file and ``<file2>`` is a generated file.
|
|
|
|
More precisely, let's consider the following jbuild file:
|
|
|
|
.. code:: scheme
|
|
|
|
(rule
|
|
(with-stdout-to data.out (run ./test.exe)))
|
|
|
|
(alias
|
|
((name runtest)
|
|
(action (diff data.expected data.out))))
|
|
|
|
Where ``data.expected`` is a file committed in the source
|
|
repository. You can use the following workflow to update your test:
|
|
|
|
- update the code of your test
|
|
- run ``jbuilder runtest``. The diff action will fail and a diff will
|
|
be printed
|
|
- check the diff to make sure it is what you expect
|
|
- run ``jbuilder promote``. This will copy the generated ``data.out``
|
|
file to ``data.expected`` directly in the source tree
|
|
|
|
You can also use ``jbuilder runtest --auto-promote`` which will
|
|
automatically do the promotion.
|
|
|
|
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/ocaml/dune/blob/master/plugin/jbuild_plugin.mli>`__
|
|
module containing details about the build context it is executed in.
|
|
|
|
The OCaml syntax gives you an escape hatch for when the S-expression
|
|
syntax is not enough. It is not clear whether the OCaml syntax will be
|
|
supported in the long term as it doesn't work well with incremental
|
|
builds. It is possible that it will be replaced by just an ``include``
|
|
stanza where one can include a generated file.
|
|
|
|
Consequently **you must not** build complex systems based on it.
|