Library Dependencies¶
Library dependencies are specified using (libraries ...) fields in
library and executables stanzas.
For libraries defined in the current scope, you can either use 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, ones that are part of the workspace are always preferred to ones that are part of the installed world.
Alternative Dependencies¶
Sometimes, one doesn’t want to depend on a specific library but rather on whatever is already installed, e.g., to use a different backend, depending on the target.
Dune allows this by using a (select ... from ...) form inside the list
of library dependencies.
Select forms are specified as follows:
(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, Dune 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.
Re-Exported Dependencies¶
A dependency foo may be marked as always re-exported using the
following syntax:
(re_export foo)
For instance:
(library
(name bar)
(libraries (re_export foo)))
This states that this library explicitly re-exports the interface of
foo. Concretely, when something depends on bar, it will also
be able to see foo independently of whether implicit
transitive dependencies are
allowed or not. When they are allowed, which is the default, all transitive
dependencies are visible, whether they are marked as re-exported or not.
Instantiating Parameterised Dependencies¶
This feature requires OxCaml, see library_parameter.
A parameterised dependency foo can be instantiated with the arguments
bar, qux using the syntax:
(instantiate foo bar qux)
For example:
(library
(name test)
(libraries (instantiate foo bar qux)))
The library foo must have declared the set of parameters it expects, and
the arguments given to the instantiation must implement a subset of these
parameters. The ordering of the arguments does not matter, as the instantiation
relies on the implemented parameter to uniquely identify each argument.
For executables, the parameterised dependencies must be fully instantiated.
In the OCaml code, the instantiated library will be available under the module
name Foo. To avoiding overlapping module names when instantiating the same
dependency multiple times, the syntax :as allows renaming the module. For
example:
(library
(name test)
(libraries
(instantiate foo a b :as foo_a_b)
(instantiate foo bar qux :as foo_bar_qux)))
Then the instantiations will be available under the names Foo_a_b and
Foo_bar_qux.
Dependencies automatically inherit the parameters of their parent library.
For example, assuming the parameterised library foo requires two
parameters p and q:
(library
(name test)
(parameters p q)
(libraries
(instantiate foo :as foo_implicit)
(instantiate foo an_implementation_of_q :as foo_q)
(instantiate foo bar qux :as foo_bar_qux)
other_foo))
Then foo_implicit is implicitly (instantiate foo p q), while
(instantiate foo an_implementation_of_q) will only inherit the parameter
p.
If other_foo, which is not explicitly instantiated here, is also
parameterised by the parameters p (and) or q, it will also inherit
its parent arguments. Dune will report an error if a dependency requires
parameters which have neither been given explicitly given via an instantiation
and are not listed in the parent library parameters.
For unwrapped libaries, the instantiation of parameterised libraries is not
currently generated. This is subject to change soon, but in the mean time,
you’ll need to manually declare the instantiations: If you depend on the
instantiation (instantiate foo bar qux :as new_name) with bar an
implementation of the parameter param_bar and qux an implementation of
param_qux, then you’ll need to write the following:
module New_name = Foo (Param_bar) (Bar) (Param_qux) (Qux) [@jane.non_erasable.instances]
Note
While this reuses the OCaml functor application syntax, the attribute changes
the meaning: The (Param) (Impl) must go together as a pair, but the
ordering of the arguments otherwise does not matter.