I am a complete newbie to OCaml. Other languages I have used (for instance Scala, Clojure, Javascript on Node.js) have package managers that allow one to start a project as a clean slate that has a declared set of dependencies of known versions.
I am trying to do something of the sort with Opam. Ideally, I would like to have a file that lists dependencies (and possibly OCaml version) so that a collaborator can start a project with
git clone myproject
<magic opam command>
ocamlbuild
and have a working version, without having installed anything globally.
I understand that the right way to do this would be to use Opam switches, but I am not sure what to do in practice. It seems that switches are tied to a compiler version, rather than per-project (altough there are aliases), and also I could not find whether there exists a sort of project Opam configuration file.
In short: say one wants to start a new project depending on Core and Yojson (for the sake of example). What would be the steps to have a clean reproducible build? Here, clean means that it won't interfere with existing installed libraries, and reproducible means that it will work on a clean machine with a freshly-cloned project.
It can't be really clean with respect to system libraries. Otherwise you need to start your own VM or some other container. But with respect to OCaml environment, you can achieve your goal with
opam
file in the root of your project. After you've described all your dependencies (including system one) in it, you canpin
your project, and this will install all your dependencies, compile your project and deploy it to the opam stack. So the workflow is the following:Now let's walk through this workflow in a step-by-step manner.
Install compiler
This command creates a new compiler installation. Here
fresh
has no special meaning it is just an arbitrary name for the installation. Usually, I usedate +"%y%m%d"
command instead offresh
that creates a name consisting of current year, month and day.Pin the project
This command will introduce your project to OPAM system. It is like creating your own small repository of packages, containing only one package, the
proj
. The nameproj
is of course just a name of your project, whatever it is.pin
usesopam
file that describes your project to the OPAM system, you can create it manually using this instructions. Or you can allowpin
command to create it for you. It will drive you gently through the process, asking some questions. You can read more about pinning in this blog post.Installing package and dependencies
In the previous command we add
-n
flag, that will stoppin
command from installing your package just after the pinning, because we want to move in small steps.This command will compute a transitive closure of your package dependencies and install them, including your system dependencies (if you're on ubuntu or fedora, and if you've specified your dependencies in
opam
file in a previous step).Working on the project
Suppose you want to develop the code. There is an OPAM friendly workflow:
This will reinstall your packages (and reinstall all dependents of your package, if they exist).
This workflow, on the other hand, has a severe drawback if your project is not tiny, as it will copy all the sources and compile them from scratch. But if you have a set of dependent packages on which you're working in parallel, then it is a way to do this.
Compiling and other stuff
But this is only about package management and inter-package dependencies. OPAM is absolutely agnostic to a particular build system, and don't give any favor to any of them (but still have tooling support for some of them). So, you can write a
Makefile
by yourself or have your own set of shell scripts invokingocamlbuild
this is absolutely up to you. But if I were in you, than I will use OASIS to manage my building process. OASIS is not a build system by itself, its purpose is to manage build systems in a cross-platform way. But by default it usesocamlbuild
and it integrates with it smoothly. Also, it has an integration with OPAM (in fact it is OPAM who has the integration with OASIS). There is aoasis2opam
package, that will create anopam
file from_oasis
file. What about creating_oasis
file, that describes building process of your project, then you can either create it by hand with your favorite text emacs, or you can allow OASIS to create it for you withoasis quickstart
.As a final note, I would suggest you to view existing projects and use them as a source of inspiration. You can start with BAP project, that I'm maintaining, but it has rather complex configuration. So, there might be a simpler examples.