OPAM for npm/yarn users
Author: Louis Khady (@khady)
Getting Started
OPAM is the main package manager for OCaml. This is the OCaml equivalent of npm or yarn. OPAM is a command line tool to manipulate packages that are defined in opam files. Most OPAM packages are published on the main OPAM repository, which is the equivalent of the npm registry.
This document presents the corresponding opam commands, files and configurations for the most common npm idioms.
OPAM 2.0 is available. If you’re using an earlier version, you should upgrade.
There is a summary at the end of the page, containing all the most common commands to know, and the the official OPAM introduction contains a lot of information.
Initial configuration
Installation
The first thing to do is to install OPAM, as one would install npm. There is an official documentation page on installation. Most of the time, we can simply get it from your package manager. Otherwise, binaries are provided for every platform.
Initialization
npm and yarn don’t need any initialization after they are installed, even if it is possible to customize a few settings. For opam, however, there is a necessary first step:
opam init -a
Let’s try to explain more in details what it does.
I am quoting the documentation of opam init
itself here:
The init command initialises a local “opam root” (by default,
~/.opam/
) that holds opam’s data and packages. This is a necessary step for normal operation of opam. The initial software repositories are fetched, and an initial ‘switch’ can also be installed, according to the configuration and options. These can be afterwards configured using opam switch and opam repository.
Additionally, this command allows to customise some aspects of opam’s shell integration, when run initially (avoiding the interactive dialog), but also at any later time.
The interesting parts are:
- The opam root is at
~/.opam
- opam uses shell integration to make our life easier
- opam uses the concept of a switch
A switch is the equivalent of the node_modules
folder in npm’s
world. It contains all the packages that are installed. One difference
from npm is that we can have multiple global switches, as if we could
have different yarn global
projects. It can be handy sometimes, but
to avoid confusion I recommend avoiding global switches.
The default settings can be changed if the -a
option is omitted while
calling opam init
.
Minimal package.json equivalent
The equivalent to package.json
is an app.opam
file, where app
is the name of the package.
So, for example, app.opam
could be webpack.opam
.
It is possible to have multiple opam files in the same directory.
There is no opam command to manipulate the opam file.
Things like npm init
or yarn add
will have to be done by hand.
A minimal opam file looks like this:
opam-version: "2.0"
name: "my-app"
authors: "Louis"
homepage: "https://github.com/khady/example"
maintainer: "ex@ample.com"
dev-repo: "git+ssh://git@github.com:khady/example.git"
bug-reports: "https://github.com/khady/example/issues"
version: "0.1"
build: [
[ "dune" "subst" ] {pinned}
[ "dune" "build" "-p" name "-j" jobs ]
]
depends: [
"dune" {build}
"opam-lock" {dev}
]
build:
tells opam that dune
is needed only to build the project.
dev:
is to mark dev dependencies.
npm/yarn-equivalent commands
npm install / yarn
npm install
or yarn
commands cover multiple opam commands,
depending on the context.
The first case is in the absence of a local switch in the current project.
This can be verified by looking for a _opam
directory at the root of the
project, and it corresponds to an npm project without a node_modules
directory. In this first case, we need to initialize a local switch.
opam switch create . 4.07.0 --deps-only
The second case is in the presence of a local switch.
opam install . --deps-only
npm install / yarn add
To install a package with opam is easy:
opam install PACKAGE
But opam does not modify the app.opam
file during the
installation – it has to be done by hand.
This is as simple as adding
the name of the package in the depends
field.
npm link / yarn link
npm link
in the opam world is opam pin
.
Its usage is well described in
the official documentation.
npm upgrade / yarn upgrade
In this case, there is a direct equivalent for the command in opam, and it is easy to remember.
opam upgrade PACKAGE
opam upgrade
is also able to upgrade all the packages of the local
switch if no package name is given.
There is one big difference compared to npm though: opam stores a local copy
of the opam repository, like apt-get
does in Debian.
So we often
want to update this copy before to request an upgrade:
opam update && opam upgrade PACKAGE
Extra package.json concepts
dev dependencies
There is no strict equivalent of the dev-dependencies
field of
package.json
, but it is possible to achieve the same thing in two
ways:
- By marking the package with
dev
independs
- By using a
dev.opam
file.
lock files
Lock files are also not common yet in the opam world, but it may be summarized as:
- Using
opam lock
to generate the lock file when needed (basically after eachopam install
oropam upgrade
). - Adding
--locked
to all theopam install
,--deps-only
andopam switch create .
commands.
Scripts
This aspect doesn’t exist in the opam world. The closest we get is the
equivalent of yarn exec
, which is opam exec
.
Instead of writing a package.json
with a script field like this:
"scripts": {
"release": "make release"
}
We run opam exec
like this:
opam exec -- make release