2017-05-14 00:10:00 +00:00
|
|
|
***************
|
|
|
|
Advanced topics
|
|
|
|
***************
|
|
|
|
|
2018-06-29 13:27:35 +00:00
|
|
|
This section describes some details of dune for advanced users.
|
2017-05-14 00:10:00 +00:00
|
|
|
|
|
|
|
META file generation
|
|
|
|
====================
|
|
|
|
|
2018-06-29 13:27:35 +00:00
|
|
|
Dune uses ``META`` files from the `findlib library
|
2017-05-14 00:10:00 +00:00
|
|
|
manager <http://projects.camlcity.org/projects/findlib.html>`__ in order
|
|
|
|
to interoperate with the rest of the world when installing libraries. It
|
|
|
|
is able to generate them automatically. However, for the rare cases
|
|
|
|
where you would need a specific ``META`` file, or to ease the transition
|
2018-06-29 13:27:35 +00:00
|
|
|
of a project to dune, it is allowed to write/generate a specific
|
2017-05-14 00:10:00 +00:00
|
|
|
one.
|
|
|
|
|
|
|
|
In order to do that, write or setup a rule to generate a
|
2018-01-19 08:50:06 +00:00
|
|
|
``META.<package>.template`` file in the same directory as the
|
2018-06-29 13:27:35 +00:00
|
|
|
``<package>.opam`` file. Dune will generate a ``META.<package>``
|
2018-01-19 08:50:06 +00:00
|
|
|
file from the ``META.<package>.template`` file by replacing lines of
|
|
|
|
the form ``# JBUILDER_GEN`` by the contents of the ``META`` it would
|
|
|
|
normally generate.
|
|
|
|
|
|
|
|
For instance if you want to extend the ``META`` file generated by
|
2018-06-29 13:27:35 +00:00
|
|
|
dune you can write the folliwing ``META.foo.template`` file:
|
2018-01-19 08:50:06 +00:00
|
|
|
|
|
|
|
.. code::
|
|
|
|
|
|
|
|
# JBUILDER_GEN
|
|
|
|
blah = "..."
|
2017-05-14 00:10:00 +00:00
|
|
|
|
2017-05-29 09:26:37 +00:00
|
|
|
Findlib integration and limitations
|
|
|
|
===================================
|
|
|
|
|
2018-06-29 13:27:35 +00:00
|
|
|
Dune uses ``META`` files to support external libraries. However, it
|
2017-05-29 09:26:37 +00:00
|
|
|
doesn't export the full power of findlib to the user, and especially
|
|
|
|
it doesn't let the user specify *predicates*.
|
|
|
|
|
|
|
|
The reason for this limitation is that so far they haven't been
|
|
|
|
needed, and adding full support for them would complicate things quite
|
|
|
|
a lot. In particular, complex ``META`` files are often hand-written and
|
|
|
|
the various features they offer are only available once the package is
|
2018-06-29 13:27:35 +00:00
|
|
|
installed, which goes against the root ideas dune is built on.
|
2017-05-29 09:26:37 +00:00
|
|
|
|
2018-06-29 13:27:35 +00:00
|
|
|
In practice, dune interprets ``META`` files assuming the following
|
2017-05-29 09:26:37 +00:00
|
|
|
set of predicates:
|
|
|
|
|
|
|
|
- ``mt``: what this means is that using a library that can be used
|
2018-06-29 13:27:35 +00:00
|
|
|
with or without threads with dune will force the threaded
|
2017-05-29 09:26:37 +00:00
|
|
|
version
|
|
|
|
|
|
|
|
- ``mt_posix``: forces the use of posix threads rather than VM
|
2018-05-21 11:29:18 +00:00
|
|
|
threads. VM threads are deprecated and are likely to go away soon
|
2017-05-29 09:26:37 +00:00
|
|
|
|
|
|
|
- ``ppx_driver``: when a library acts differently depending on whether
|
|
|
|
it is linked as part of a driver or meant to add a ``-ppx`` argument
|
|
|
|
to the compiler, choose the former behavior
|
2017-12-11 11:40:54 +00:00
|
|
|
|
2018-08-23 11:41:01 +00:00
|
|
|
Dynamic loading of packages
|
|
|
|
===========================
|
|
|
|
|
|
|
|
Dune supports the ``findlib.dynload`` package from `findlib
|
|
|
|
<http://projects.camlcity.org/projects/findlib.html>_` that allows to dynamically
|
|
|
|
load packages and their dependencies (using OCaml Dynlink module).
|
|
|
|
So adding the ability for an application to have plugins just requires
|
|
|
|
to add ``findlib.dynload`` to the set of library dependencies:
|
|
|
|
|
|
|
|
.. code:: scheme
|
|
|
|
(library
|
|
|
|
(name mytool)
|
|
|
|
(public_name mytool)
|
|
|
|
(modules ...)
|
|
|
|
)
|
|
|
|
|
|
|
|
(executable
|
|
|
|
(name main)
|
|
|
|
(public_name mytool)
|
|
|
|
(libraries mytool findlib.dynload)
|
|
|
|
(modules ...)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
Then you could use in your application ``Fl_dynload.load_packages l``
|
|
|
|
that will load the list ``l`` of packages. The packages are loaded
|
|
|
|
only once. So trying to load a package statically linked does nothing.
|
|
|
|
|
|
|
|
A plugin creator just need to link to your library:
|
|
|
|
|
|
|
|
.. code:: scheme
|
|
|
|
(library
|
|
|
|
(name mytool_plugin_a)
|
|
|
|
(public_name mytool-plugin-a)
|
|
|
|
(libraries mytool)
|
|
|
|
)
|
|
|
|
|
|
|
|
By choosing some naming convention, for example all the plugins of
|
|
|
|
``mytool`` should start with ``mytool-plugin-``. You can automatically
|
|
|
|
load all the plugins installed for your tool by listing the existing packages:
|
|
|
|
|
|
|
|
.. code:: ocaml
|
|
|
|
let () = Findlib.init ()
|
|
|
|
let () =
|
|
|
|
let pkgs = Fl_package_base.list_packages () in
|
|
|
|
let pkgs =
|
|
|
|
List.filter
|
|
|
|
(fun pkg -> 14 <= String.length pkg && String.sub pkg 0 14 = "mytool-plugin-")
|
|
|
|
pkgs
|
|
|
|
in
|
|
|
|
Fl_dynload.load_packages pkgs
|
|
|
|
|
2018-06-01 13:24:35 +00:00
|
|
|
.. _advanced-cross-compilation:
|
|
|
|
|
2017-12-21 11:59:09 +00:00
|
|
|
Cross Compilation
|
|
|
|
=================
|
|
|
|
|
2018-06-29 13:27:35 +00:00
|
|
|
Dune allows for cross compilation by defining build contexts with
|
2017-12-21 11:59:09 +00:00
|
|
|
multiple targets. Targets are specified by adding a ``targets`` field
|
|
|
|
to the definition of a build context.
|
|
|
|
|
|
|
|
``targets`` takes a list of target name. It can be either:
|
|
|
|
|
|
|
|
- ``native`` which means using the native tools that can build
|
|
|
|
binaries that run on the machine doing the build
|
|
|
|
|
|
|
|
- the name of an alternative toolchain
|
|
|
|
|
|
|
|
Note that at the moment, there is no official support for
|
2018-06-29 13:27:35 +00:00
|
|
|
cross-compilation in OCaml. Dune supports the opam-cross-x
|
2018-01-22 09:45:43 +00:00
|
|
|
repositories from the `ocaml-cross organization on github
|
2018-01-25 05:40:05 +00:00
|
|
|
<https://github.com/ocaml-cross/>`_, such as:
|
2018-01-22 09:45:43 +00:00
|
|
|
|
|
|
|
- `opam-cross-windows <https://github.com/ocaml-cross/opam-cross-windows>`_
|
|
|
|
- `opam-cross-android <https://github.com/ocaml-cross/opam-cross-android>`_
|
|
|
|
- `opam-cross-ios <https://github.com/ocaml-cross/opam-cross-ios>`_
|
|
|
|
|
|
|
|
In particular:
|
|
|
|
|
|
|
|
- to build Windows binaries using opam-cross-windows, write ``windows``
|
|
|
|
in the list of targets
|
|
|
|
- to build Android binaries using opam-cross-android, write
|
|
|
|
``android`` in the list of targets
|
2018-05-16 16:05:14 +00:00
|
|
|
- to build IOS binaries using opam-cross-ios, write ``ios`` in the
|
2018-01-22 09:45:43 +00:00
|
|
|
list of targets
|
2017-12-21 11:59:09 +00:00
|
|
|
|
|
|
|
For example, the following workspace file defines three different
|
|
|
|
targets for the ``default`` build context:
|
|
|
|
|
|
|
|
.. code:: scheme
|
|
|
|
|
|
|
|
(context (default (targets (native windows android))))
|
|
|
|
|
|
|
|
This configuration defines three build contexts:
|
|
|
|
|
|
|
|
- ``default``
|
|
|
|
- ``default.windows``
|
|
|
|
- ``default.android``
|
|
|
|
|
|
|
|
Note that the ``native`` target is always implicitly added when not
|
2018-06-29 13:27:35 +00:00
|
|
|
present. However, when implicitly added ``dune build @install``
|
2017-12-21 11:59:09 +00:00
|
|
|
will skip this context, i.e. ``default`` will only be used for
|
|
|
|
building executables needed by the other contexts.
|
|
|
|
|
2018-06-29 13:27:35 +00:00
|
|
|
With such a setup, calling ``dune build @install`` will build all
|
2017-12-21 11:59:09 +00:00
|
|
|
the packages three times.
|
|
|
|
|
2018-06-29 22:30:27 +00:00
|
|
|
Note that instead of writing a ``dune-workspace`` file, you can also
|
|
|
|
use the ``-x`` command line option. Passing ``-x foo`` to ``dune``
|
|
|
|
without having a ``dune-workspace`` file is the same as writing the
|
|
|
|
following ``dune-workspace`` file:
|
2017-12-21 11:59:09 +00:00
|
|
|
|
|
|
|
.. code:: scheme
|
|
|
|
|
|
|
|
(context (default (targets (foo))))
|
|
|
|
|
2018-06-29 22:30:27 +00:00
|
|
|
If you have a ``dune-workspace`` and pass a ``-x foo`` option,
|
2017-12-21 11:59:09 +00:00
|
|
|
``foo`` will be added as target of all context stanzas.
|
|
|
|
|
|
|
|
How does it work?
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
In such a setup, binaries that need to be built and executed in the
|
|
|
|
``default.windows`` or ``default.android`` contexts as part of the
|
|
|
|
build, will no longer be executed. Instead, all the binaries that will
|
|
|
|
be executed will come from the ``default`` context. One consequence of
|
|
|
|
this is that all preprocessing (ppx or otherwise) will be done using
|
|
|
|
binaries built in the ``default`` context.
|
|
|
|
|
2018-07-06 08:10:59 +00:00
|
|
|
To clarify this with an example, let's assume that you have the following
|
|
|
|
``src/dune`` file:
|
2017-12-21 11:59:09 +00:00
|
|
|
|
|
|
|
.. code:: scheme
|
|
|
|
|
2018-07-06 08:10:59 +00:00
|
|
|
(executable (name foo))
|
2017-12-21 11:59:09 +00:00
|
|
|
(rule (with-stdout-to blah (run ./foo.exe)))
|
|
|
|
|
2018-06-29 13:27:35 +00:00
|
|
|
When building ``_build/default/src/blah``, dune will resolve ``./foo.exe`` to
|
2017-12-21 11:59:09 +00:00
|
|
|
``_build/default/src/foo.exe`` as expected. However, for
|
2018-06-29 13:27:35 +00:00
|
|
|
``_build/default.windows/src/blah`` dune will resolve ``./foo.exe`` to
|
2017-12-21 11:59:09 +00:00
|
|
|
``_build/default/src/foo.exe``
|
|
|
|
|
|
|
|
Assuming that the right packages are installed or that your workspace
|
2018-06-29 13:27:35 +00:00
|
|
|
has no external dependencies, dune will be able to cross-compile a
|
2017-12-21 11:59:09 +00:00
|
|
|
given package without doing anything special.
|
|
|
|
|
|
|
|
Some packages might still have to be updated to support cross-compilation. For
|
|
|
|
instance if the ``foo.exe`` program in the previous example was using
|
|
|
|
``Sys.os_type``, it should instead take it as a command line argument:
|
|
|
|
|
|
|
|
.. code:: scheme
|
|
|
|
|
2018-07-06 08:10:59 +00:00
|
|
|
(rule (with-stdout-to blah (run ./foo.exe -os-type %{os_type})))
|
2017-12-21 11:59:09 +00:00
|
|
|
|
2017-12-11 11:40:54 +00:00
|
|
|
Classical ppx
|
|
|
|
=============
|
|
|
|
|
|
|
|
*classical ppx* refers to running ppx using the -ppx compiler option, which is
|
|
|
|
composed using Findlib. Even though this is useful to run some (usually old)
|
2018-06-29 13:27:35 +00:00
|
|
|
ppx's which don't support drivers, dune does not support preprocessing with
|
2017-12-11 11:40:54 +00:00
|
|
|
ppx this way. but a workaround exists using the `ppxfind
|
|
|
|
<https://github.com/diml/ppxfind>`_ tool.
|