Managing Dependencies with opam

Installing Dependencies

TL;DR

opam switch create . --deps-only --with-test --with-doc

It is recommended to install the dependencies of a project in a local opam switch to sandbox your development environment.

If you're using opam 2.0.X, you can do this with:

# if you need external dependencies
opam pin add -n .
opam depext -i <packages>
opam install . --deps-only --with-test --with-doc

If you use opam 2.1.X, it will install the system dependencies automatically, so you can run:

opam install . --deps-only --with-test --with-doc

Now, if for some reason you prefer to install your dependencies in a global switch, you can run:

opam switch set <switch_name>
opam install . --deps-only --with-test --with-doc

Once the dependencies have been installed successfully, and assuming the project uses dune as the build system, you can compile it with:

opam exec -- dune build

Or if you set your environment with eval $(opam env):

dune build

Updating Dependencies

TL;DR

If the project generates the *.opam file from the dune-project, add the dependency in the package stanza and run opam install . --deps-only. If the project does not generate the *.opam file, add the dependency in the *.opam file and run opam install . --deps-only. To avoid duplicating the project configuration into multiple files, Dune allows to generate the *.opam file of the project from the package definitions in dune-project when adding the (generate_opam_files true) stanza.

However, opam remains a central piece of the ecosystem and it's very likely that you will have to work with *.opam files at some point, so we don't take a stance on wether you should specify your dependencies in the *.opam file or in dune-project.

If the project generates the opam file from the dune-project (you can tell by the line # This file is generated by dune, edit dune-project instead at the top of the *.opam file), you can add your dependencies in the dune-project in the appropriate package stanza. It should look like this:

(package
 (name demo)
 (synopsis "A short, but powerful statement about your project")
 (description "An complete and exhaustive description everything your project does.")
 (depends
  (ocaml
   (>= 4.08.0))
  dune
  (alcotest :with-test)
  (odoc :with-doc)))

Once you have added your dependency, you can build your project with dune build which will re-generate the *.opam files.

If the *.opam files are not generated, you can add the dependencies in them directly, in the depends field. If should look like this:

opam-version: "2.0"
synopsis: "A short, but powerful statement about your project"
description: "An complete and exhaustive description everything your project does."
depends: [
  "ocaml" {>= "4.08.0"}
  "dune"
  "alcotest" {with-test}
  "odoc" {with-doc}
]
build: [
  ["dune" "subst"] {pinned}
  [
    "dune"
    "build"
    "-p"
    name
    "-j"
    jobs
    "@install"
    "@runtest" {with-test}
    "@doc" {with-doc}
  ]
]

Either way, once you have added your dependency in the appropriate file, you can run opam install . --deps-only to update your current switch dependencies.

Dealing with Development-Only Dependencies

Opam does not have a notion of development dependencies. Instead, each dependency can be either:

  • A normal dependency (used at runtime)
  • A build dependency (used to build the project)
  • A test dependency (used to test the project)
  • A documentation dependency (used to generate the documentation)

When adding a new dependency, as seen in the "Update dependencies" workflow, you can add a flag to your dependency.

For dune-project, it looks like this:

(alcotest :with-test)

And for the *.opam file, it looks like:

"alcotest" {with-test}

The available flags for each dependencies are:

  • Normal: no flag
  • Build: build
  • Test: with-test
  • Documentation: with-doc

See opam documentation for more details on the opam syntax.

Help Improve Our Documentation

All OCaml docs are open source. See something that's wrong or unclear? Submit a pull request.

Contribute