package opam-monorepo
opam
-provided dependencies
This section documents a feature that’s useful when some dependencies cannot be installed via opam-monorepo
. This workflow isn’t meant for regular use but only as a way to use opam-monorepo
in cases where it wouldn't be otherwise possible.
We suggest minimizing its usage and prefer to use (and contribute) dune-ports
from the opam-overlays
repository. It's usage is safest with leaf-dependencies and those that don’t have dependency intersections with vendored packages. Due to possibly of unexpected interactions, this feature is only meant for advanced users, and the solutions it produces might be in flux.
Usecases
Sometimes it is not possible to put all your dependencies into the duniverse
, be it due to your dependencies not building with dune
or some tooling that should be just installed via opam
. Such examples include:
- Packages not building with Dune
- Packages that should not be vendored for legal reasons
These users can opt-in to having some of their dependencies provided by opam
instead of opam-monorepo
pulling them into the duniverse
.
Initial setup
With the default configuration, opam-monorepo
runs in full-duniverse
mode, i.e., requiring all the dependencies of your opam
files to be able to be built as part of the duniverse
.
As such it is only recommended that packages are installed via opam
for which there is no way to build them with dune
, e.g., by using the opam-overlays repository with Dune ports.
To let opam-monorepo
know a package is to be installed via opam
, it needs to be marked as such in the Opam file. For this, it needs to be added as normal in the depends
field, as well in addition into the new x-opam-monorepo-opam-provided
field. This field takes a single package or a list of packages to be installed via opam
instead of being pulled into the duniverse
.
To configure opam-monorepo
to avoid pulling in package foo
, specify it in the list of packages provided by Opam:
depends: [
"foo"
]
x-opam-monorepo-opam-provided: ["foo"]
This can either be specified directly in the Opam file or, if you use Dune to generate Opam files, in the .template
file. In such case, make sure to regenerate the Opam file.
As a shortcut syntax, if there’s only one package, it’s possible to leave out the list and just specify the package itself:
depends: [
"foo"
]
x-opam-monorepo-opam-provided: "foo"
Usage
After you configured your Opam file, you have to lock the environment.
$ opam monorepo lock
After this succeeds, you will have an .opam.locked
file, which contains all your project’s dependencies (including transitive dependencies). The ones that opam-monorepo
will pull into the duniverse
are marked as vendor
.
$ opam install --ignore-pin-depends --deps-only ./ --locked
$ opam-monorepo pull
How it works
In addition to calculating the dependencies of the packages that will be included in the duniverse
, opam-monorepo
calculates the dependencies of the packages to be installed via opam
. opam-monorepo
then writes a lockfile that sets a variable on all the dependencies it will pull, whereas opam
-provided dependencies don't have variables set. In Opam, unset variables are false; thus Opam will ignore the packages that opam-monorepo
will pull.
The opam
-provided subset of dependencies is then excluded from the duniverse
packages.
Resolution of dependency overlaps
There are cases where a dependency package appears multiple times in the project’s dependency tree. It’s possible that a package is part of the packages to be included in the duniverse
, as well as packages installed by opam
.
In such cases there are two possibilities:
- Install the package in
opam
, exclude it from duniverse - Install the package in
opam
, include a duplicate in the duniverse
Both these approaches have advantages and disadvantages. opam-monorepo
currently chooses #2 to maximize the amount of packages that are vendored, thus increasing the size of the reproducible set. Yet this doesn’t mean that two different versions of the package can be installed. The set of packages in Opam and the duniverse
must be co-installable!