Tl;dr

Create a local package from the current directory

$ opam pin add <name> .

Get a local copy of an existing package and install from there

$ opam source <package> --pin

Get it back to normal

$ opam pin remove <package>

Publish to the OPAM repository:

Creating OPAM packages

An OPAM package is basically just a bunch of data on a software project:

This document will go through a simple way to get it in the right format, whether you are packaging your own project or someone else's. It's not a complete guide to the opam file format.

Creating a local package

We'll be assuming that you have a working OPAM installation. If not, please first read the quick install guide.

Get the source

Let's start from the root directory of your project source, typically obtained from a version-controlled repository or from a tarball.

$ wget https://.../project.tar.gz && tar xvzf project.tar.gz
# Or
$ git clone git://.../project.git
...
$ cd project

Opam pin

OPAM 1.2 provides a feature that allows you to register packages locally, without the need for them to exist in a repository. We call this pinning, because it is an extension of the very common feature that allows to pin a package to a specific version number in other package managers.

So let's create a package pinned to the current directory. We just need to choose a name and issue the command:

$ opam pin add <project> . -n

(-n tells OPAM to not try and install just yet, we'll get to it later)

The "opam" file

At this stage, OPAM will be looking for metadata for the package <project>, on its repository and in the source directory. Not finding any, it will open an editor with a pre-filled template for your package's opam file. It's best to keep the project's README file open at this stage, as it should contain the information we're interested in, only in a less normalised format.

opam-version: "1.2"
maintainer: "Name <email>"
author: "Name <email>"
name: "project"
version: "0.1"
homepage: ""
bug-reports: ""
license: ""
build: [
  ["./configure" "--prefix=%{prefix}%"]
  [make]
]
install: [make "install"]
remove: ["ocamlfind" "remove" "project"]
depends: "ocamlfind"

The opam-version, maintainer and version fields are mandatory ; you should remove the others rather than leave them empty.

A few other fields are available, but that should be enough to get started. Like install and remove, most fields may contain lists in square brackets rather than a single element: maintainer, author, homepage, bug-reports, license and depends.

One you save and quit, OPAM will syntax-check and let you edit again in case of errors.

Installing

The best test is to let OPAM attempt to install your just created package. As for any package, you do it by hand with:

$ opam install <project> --verbose

At this point, OPAM will get a snapshot of the project, resolve its dependencies and propose a course of actions for the install. Let it go and see if your project installs successfully ; it's a good idea to use --verbose as it will make OPAM print the output of the externals commands, in particular the ones in the build instructions.

You can now check that everything is installed as expected. Do also check that opam remove <project> works properly.

If you need to change anything, simply do

opam pin edit <project>

to get back to editing the opam file. Manually editing the opam file in your source tree also works.

So far, so good ! You may have missed dependencies in case they were already installed on your system, but that will be checked automatically by the continuous integration system when you attempt to publish your package to the OPAM repository, so don't worry.

Getting a full OPAM package

There are still two things missing for a complete package.

Publishing

Publishing is currently handled through Github, using the pull-request mechanism. If you're not familiar with it, it is a fancy way to:

Here is how to do it from scratch:

  1. Go to https://github.com/ocaml/opam-repository and hit the Fork button on the top right corner (you may be asked to login or register)

  2. Get the clone URL on the right, and, from the shell, run git clone <url> to get your local copy

  3. Now we'll add the new package description (opam, descr and url files) into opam-repository/packages/<project>/<project>.<version>/ and make that a git commit:

    $ cd opam-repository/packages
    $ mkdir -p <project>/<project>.<version>
    $ cp <project-src>/opam <project>/<project>.<version>
    $ cp <path-to>/url <path-to>/descr <project>/<project>.<version>
    $ git add <project>
    $ git commit -m "Added new fancy <project>.<version>"
  4. Sending that back to github is just a matter of running git push

  5. Back to the web interface, refresh, hit the Pull request button, check your changes and confirm;

  6. Wait for feedback !

Don't forget to opam pin remove <project> once your project is on the repository, if you don't want to continue using your local version. Remember that as long as the package is pinned, OPAM will use the metadata found in its source if any, but otherwise only what is in the OPAM repository matters. Use git pin list to list all currently pinned packages.

Some tricks

More on opam files

The opam files can express much more than what was shown above. Without getting into too much details, here are some of the most useful features:

For more, see the OPAM Developer's Manual