id | title | description | category |
---|---|---|---|
managing-dependencies |
Managing Dependencies With opam |
How to manage dependencies with opam
|
Best Practices |
We recommend installing a project's dependencies 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 system 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
To avoid duplicating the project configuration into multiple files, Dune allows you to generate the project's *.opam
file 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 whether 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 regenerate the *.opam
files.
If the *.opam
files are not generated, you can add the dependencies in them directly in the depends
field. It 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.
Installing a package from the opam repository to your active switch, you can run
opam install <package-name>
to get the latest version of the package.
If you want to install a specific version of the package, use
opam install <package-name>.<package-version>
instead.
Sometimes, you may want to install a package directly from a Git repository, e.g., when it is not available on the opam repository or when you want to use an unreleased version.
In OCaml projects that use Dune for building and opam for package management, you can specify Git dependencies using a combination of dune-project
and .opam.template
files.
This approach is particularly useful when you want to keep the Dune and opam configurations in sync, especially when dealing with external dependencies from Git repositories.
If your project does not have a file matching the name of your project's .opam
file, but with the file extension .opam.template
, you have to create it.
For example, if your project's opam file is my_project.opam
, create my_project.opam.template
and use pin-depends
to tell opam
to install a package from a Git repository.
pin-depends: [
["<package-name>.dev" "git+https://<repository-url>#<branch-or-commit>"]
]
Next, regenerate the .opam
file of your project by running
opam exec -- dune build
Then, run
opam install . --deps-only
to install the new dependency you added.
To open your opam file, locate the opam
file for your OCaml project. This file defines the package's dependencies and other metadata.
Add the pin-depends
field in the opam
file if it doesn't exist. Inside this field, you specify the package and the URL from which it should be fetched. For example:
pin-depends: [
["<package-name>.dev" "git+https://<repository-url>#<branch-or-commit>"]
]
Finally, use opam install to install the dependencies, including the one specified in the pin-depends
field.
opam install . --deps-only
You can install a package in your active switch directly from a Git URL:
opam pin add <package-name> <git-url>#<branch-or-commit>
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.