2017-05-14 00:10:00 +00:00
|
|
|
********************
|
|
|
|
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,
|
2017-05-18 20:15:49 +00:00
|
|
|
as determined by the :ref:`opam-files`
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
- ``(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
|
2017-05-18 20:15:49 +00:00
|
|
|
``(modules <modules>)`` field. ``<modules>`` uses the `Ordered set language`_
|
2017-05-14 00:10:00 +00:00
|
|
|
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
|
2017-05-18 20:15:49 +00:00
|
|
|
of the library. See the section about `Library dependencies`_ for more
|
|
|
|
details
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
- ``(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
|
2017-05-18 20:15:49 +00:00
|
|
|
`Preprocessing specification`_ section
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
- ``(preprocessor_deps (<deps-conf list>))`` specifies extra dependencies of the
|
|
|
|
preprocessor, for instance if the preprocessor reads a generated file. The
|
2017-05-18 20:15:49 +00:00
|
|
|
specification of dependencies is described in the `Dependency specification`_
|
|
|
|
section
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
- ``(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
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
- ``js_of_ocaml``. See the section about :ref:`jbuild-jsoo`
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
- ``flags``, ``ocamlc_flags`` and ``ocamlopt_flags``. See the section about
|
|
|
|
`OCaml flags`_
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
- ``(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
|
2017-05-18 20:15:49 +00:00
|
|
|
strings supporting `Variables expansion`_
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
- ``(c_flags <flags>)`` specifies the compilation flags for C stubs,
|
2017-05-18 20:15:49 +00:00
|
|
|
using the `Ordered set language`_. This field supports
|
2017-05-14 00:10:00 +00:00
|
|
|
``(: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
|
2017-05-18 20:15:49 +00:00
|
|
|
the `Ordered set language`_ and supports ``(:include ...)`` forms. When you
|
2017-05-14 00:10:00 +00:00
|
|
|
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
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
- ``(libraries (<library-dependencies>))`` specifies the library dependencies.
|
|
|
|
See the section about `Library dependencies`_ for more details
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
- ``(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`_
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
- ``(preprocess <preprocess-spec>)`` is the same as the ``(preprocess ...)``
|
|
|
|
field of `library`_
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
- ``(preprocessor_deps (<deps-conf list>))`` is the same as the
|
|
|
|
``(preprocessor_deps ...)`` field of `library`_
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
- ``js_of_ocaml``. See the section about `js_of_ocaml`_
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
- ``flags``, ``ocamlc_flags`` and ``ocamlopt_flags``. See the section about
|
|
|
|
specifying `OCaml flags`_
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
``<deps-conf list>`` specifies the dependencies of the rule. See the `Dependency
|
|
|
|
specification`_ section for more details.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
``<action>`` is the action to run to produce the targets from the dependencies.
|
|
|
|
See the `User actions`_ section for more details.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
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
|
2017-05-18 20:15:49 +00:00
|
|
|
`Dependency specification`_ section for more details.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
``<optional-fields>`` are:
|
|
|
|
|
|
|
|
- ``<action>``, an action to run when constructing the alias. See
|
2017-05-18 20:15:49 +00:00
|
|
|
the `User actions`_ section for more details.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
- ``(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))))
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
See the section about :ref:`running-tests` for details.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
Most fields using the ordered set language also support `Variables expansion`_.
|
2017-05-14 00:10:00 +00:00
|
|
|
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:
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
- ``@`` expands to the list of target, separated by spaces
|
|
|
|
- ``<`` expands to the first dependency, or the empty string if there are no
|
|
|
|
dependencies
|
2017-05-14 00:10:00 +00:00
|
|
|
- ``^`` expands to the list of dependencies, separated by spaces
|
|
|
|
- ``path:<path>`` expands to ``<path>``
|
2017-05-18 20:15:49 +00:00
|
|
|
- ``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
|
2017-05-14 00:10:00 +00:00
|
|
|
the installed world will be used
|
2017-05-18 20:15:49 +00:00
|
|
|
- ``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:
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
- 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
|
|
|
|
--------------------
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
Dependencies on libraries are specified using ``(libraries ...)`` fields in
|
|
|
|
``library`` and ``executables`` stanzas.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
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:
|
2017-05-14 00:10:00 +00:00
|
|
|
``(libraries (base re))``.
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
When resolving libraries, libraries that are part of the workspace are always
|
|
|
|
prefered to ones that are part of the installed world.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
#. Scope of internal library names
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
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.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
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.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
As a result, when you create a workspace including several projects there
|
|
|
|
might be a name clash between internal library names.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
This scoping rule ensure that this won't be a problem.
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
.. _alternative-deps:
|
|
|
|
|
2017-05-14 00:10:00 +00:00
|
|
|
#. Alternative dependencies
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
In addition to direct dependencies you can specify alternative dependencies.
|
|
|
|
This is described in the :ref:`Alternative dependencies <alternative-deps>`
|
|
|
|
section
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
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.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
Jbuilder allows this by using a ``(select ... from ...)`` form inside the
|
|
|
|
list of library dependencies.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
``<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.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
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``.
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
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>`__.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
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``.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
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.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
#. 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:
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
- ``(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
|
|
|
|
:ref:`glob <glob>` for details
|
|
|
|
- ``(files_recursively_in <dir>)``: depend on all files in the subtree with root
|
|
|
|
``<dir>``
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
In all these cases, the argument supports `Variables expansion`_.
|
|
|
|
|
|
|
|
.. _glob:
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
#. 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
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
For all these fields, ``<flags>`` is specified in the `Ordered set language`_.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
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>))
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
.. _jbuild-jsoo:
|
|
|
|
|
2017-05-14 00:10:00 +00:00
|
|
|
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.
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
=<flags>= is specified in the `Ordered set language`_.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
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
|
2017-05-18 20:15:49 +00:00
|
|
|
support `Variables expansion`_. Moreover, you don't need to specify dependencies
|
2017-05-14 00:10:00 +00:00
|
|
|
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 ${@} ${<})))))
|
|
|
|
|
2017-05-18 20:15:49 +00:00
|
|
|
.. _ocaml-syntax:
|
|
|
|
|
2017-05-14 00:10:00 +00:00
|
|
|
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.
|