139 lines
4.9 KiB
ReStructuredText
139 lines
4.9 KiB
ReStructuredText
*****************
|
|
Virtual Libraries
|
|
*****************
|
|
|
|
.. TODO(diataxis) This is a guide, with reference info in it.
|
|
|
|
Virtual libraries correspond to Dune's ability to compile parameterised
|
|
libraries and delay the selection of concrete implementations until linking an
|
|
executable.
|
|
|
|
The feature introduces two kinds of libraries: virtual and implementations. A
|
|
*virtual library* corresponds to an interface (although it may contain partial
|
|
implementation). An *implementation* of a virtual library fills in all
|
|
unimplemented modules in the virtual library.
|
|
|
|
The benefit of this partition is that other libraries may depend on and compile
|
|
against the virtual library, and they might only select concrete
|
|
implementations for these virtual libraries when linking executables. An
|
|
example where this might be useful would be a virtual, cross-platform,
|
|
``clock`` library. This library would have ``clock.unix`` and ``clock.win``
|
|
implementations. Executable using ``clock`` or libraries that use ``clock``
|
|
would conditionally select one of the implementations, depending on the target
|
|
platform.
|
|
|
|
.. note::
|
|
|
|
This feature is sometimes informally called "variants". However, this term
|
|
refers to a related feature that has been removed in Dune 2.6 in favor of
|
|
default implementation, and the correct term for the mechanism as a whole is
|
|
"virtual libraries".
|
|
|
|
Virtual Library
|
|
===============
|
|
|
|
To define a virtual library, a ``virtual_modules`` field must be added to an
|
|
ordinary library stanza, and the version of the Dune language must be at least
|
|
1.5. This field defines modules for which only an interface would be present
|
|
(mli only):
|
|
|
|
.. code:: dune
|
|
|
|
(library
|
|
(name clock)
|
|
;; clock.mli must be present, but clock.ml must not be
|
|
(virtual_modules clock))
|
|
|
|
Apart from this field, the virtual library is defined just like a normal
|
|
library and may use all the other fields. A virtual library may include other
|
|
modules (with or without implementations), which is why it's not a pure
|
|
"interface" library.
|
|
|
|
.. note::
|
|
|
|
The ``virtual_modules`` field is not merged in ``modules``, which represents
|
|
the total set of modules in a library. If a directory has more than one
|
|
stanza and thus a ``modules`` field must be specified, virtual modules still
|
|
need to be added in ``modules``.
|
|
|
|
Implementation
|
|
===============
|
|
|
|
An implementation for a library is defined as:
|
|
|
|
.. code:: dune
|
|
|
|
(library
|
|
(name clock_unix)
|
|
;; clock.ml must be present, but clock.mli must not be
|
|
(implements clock))
|
|
|
|
The ``name`` field is slightly different for an implementation than it is for a
|
|
normal library. The ``name`` is just an internal name to refer to the
|
|
implementation, it doesn't correspond to any particular module like it does in
|
|
the virtual library.
|
|
|
|
Other libraries may then depend on the virtual library as if it was a regular
|
|
library:
|
|
|
|
.. code:: dune
|
|
|
|
(library
|
|
(name calendar)
|
|
(libraries clock))
|
|
|
|
But when it comes to creating an executable, we must now select a valid
|
|
implementation for every virtual library that we've used:
|
|
|
|
.. code:: dune
|
|
|
|
(executable
|
|
(name birthday-reminder)
|
|
(libraries
|
|
clock_unix ;; leaving this dependency will make dune loudly complain
|
|
calendar))
|
|
|
|
Default Implementation
|
|
======================
|
|
|
|
A virtual library may select a default implementation, which is enabled after
|
|
variant resolution if no suitable implementation has been found.
|
|
|
|
.. code:: dune
|
|
|
|
(library
|
|
(name time)
|
|
(virtual_modules time)
|
|
(default_implementation time-js))
|
|
|
|
The default implementation must live in the same package as the virtual
|
|
library. In the example above, that would mean that the ``time-js`` and
|
|
``time`` libraries must be in the same package
|
|
|
|
Limitations
|
|
===========
|
|
|
|
The current implementation of virtual libraries suffers from a few limitations.
|
|
Some of these are temporary.
|
|
|
|
* It's impossible to link more than one implementation for the same virtual
|
|
library in one executable.
|
|
|
|
* It's not possible for implementations to introduce new public modules. That
|
|
is, modules that aren't a part of the virtual library's CMI. Consequently, a
|
|
module in an implementation either implements a virtual module or is private.
|
|
|
|
* It isn't possible to load virtual libraries into ``utop``. As a result, any
|
|
directory that contains a virtual library will not work with ``$ dune utop``.
|
|
This is an essential limitation, but it would be best to somehow skip these
|
|
libraries or provide an implementation for them when loading a toplevel.
|
|
|
|
* Virtual libraries must be defined using Dune. It's not possible for Dune to
|
|
implement virtual libraries created outside of Dune. On the other hand,
|
|
virtual libraries and implementations defined using Dune should be usable
|
|
with findlib-based build systems.
|
|
|
|
* It's impossible for a library to be both virtual and implement another
|
|
library. This isn't very useful, but it could technically be used to create
|
|
partial implementations. It is possible to lift this restriction if there's
|
|
enough demand.
|