Given that most of the OCaml ecosystem is now built with dune, nixpkgs includes a convenience build support function called `buildDunePackage` that will build an OCaml package using dune, OCaml and findlib and any additional dependencies provided as `buildInputs` or `propagatedBuildInputs`.
Here is a simple package example.
- It defines an (optional) attribute `minimalOCamlVersion` (see note below)
that will be used to throw a descriptive evaluation error if building with
an older OCaml is attempted.
- It uses the `fetchFromGitHub` fetcher to get its source.
- It also accepts a `duneVersion` parameter (valid values are `"1"`, `"2"`, and
`"3"`). The recommended practice is to set it only if you don't want the default
value and/or it depends on something else like package version. You might see
a not-supported argument `useDune2`. The behavior was `useDune2 = true;` =>
`duneVersion = "2";` and `useDune2 = false;` => `duneVersion = "1";`. It was
used at the time when dune3 didn't exist.
- It sets the optional `doCheck` attribute such that tests will be run with
`dune runtest -p angstrom` after the build (`dune build -p angstrom`) is
complete, but only if the Ocaml version is at at least `"4.05"`.
- It uses the package `ocaml-syntax-shims` as a build input, `alcotest` and
`ppx_let` as check inputs (because they are needed to run the tests), and
`bigstringaf` and `result` as propagated build inputs (thus they will also be
available to libraries depending on this library).
- The library will be installed using the `angstrom.install` file that dune
generates.
```nix
{
lib,
fetchFromGitHub,
buildDunePackage,
ocaml,
ocaml-syntax-shims,
alcotest,
result,
bigstringaf,
ppx_let,
}:
buildDunePackage rec {
pname = "angstrom";
version = "0.15.0";
minimalOCamlVersion = "4.04";
src = fetchFromGitHub {
owner = "inhabitedtype";
repo = "angstrom";
tag = version;
hash = "sha256-MK8o+iPGANEhrrTc1Kz9LBilx2bDPQt7Pp5P2libucI=";
};
checkInputs = [
alcotest
ppx_let
];
buildInputs = [ ocaml-syntax-shims ];
propagatedBuildInputs = [
bigstringaf
result
];
doCheck = lib.versionAtLeast ocaml.version "4.05";
meta = {
homepage = "https://github.com/inhabitedtype/angstrom";
description = "OCaml parser combinators built for speed and memory efficiency";
license = lib.licenses.bsd3;
maintainers = with lib.maintainers; [ sternenseemann ];
};
}
```
Here is a second example, this time using a source archive generated with `dune-release`. It is a good idea to use this archive when it is available as it will usually contain substituted variables such as a `%%VERSION%%` field. This library does not depend on any other OCaml library and no tests are run after building it.
```nix
{
lib,
fetchurl,
buildDunePackage,
}:
buildDunePackage rec {
pname = "wtf8";
version = "1.0.2";
minimalOCamlVersion = "4.02";
src = fetchurl {
url = "https://github.com/flowtype/ocaml-wtf8/releases/download/v${version}/wtf8-v${version}.tbz";
hash = "sha256-d5/3KUBAWRj8tntr4RkJ74KWW7wvn/B/m1nx0npnzyc=";
};
meta = {
homepage = "https://github.com/flowtype/ocaml-wtf8";
description = "WTF-8 is a superset of UTF-8 that allows unpaired surrogates";
license = lib.licenses.mit;
maintainers = [ lib.maintainers.eqyiel ];
};
}
```
The build will automatically fail if two distinct versions of the same library
are added to `buildInputs` (which usually happens transitively because of
`propagatedBuildInputs`). Set `dontDetectOcamlConflicts` to true to disable this
behavior.