2020-12-02 05:09:57 +01:00
# OCaml {#sec-language-ocaml}
2021-11-16 17:49:17 +01:00
## User guide {#sec-language-ocaml-user-guide}
OCaml libraries are available in attribute sets of the form `ocaml-ng.ocamlPackages_X_XX` where X is to be replaced with the desired compiler version. For example, ocamlgraph compiled with OCaml 4.12 can be found in `ocaml-ng.ocamlPackages_4_12.ocamlgraph` . The compiler itself is also located in this set, under the name `ocaml` .
If you don't care about the exact compiler version, `ocamlPackages` is a top-level alias pointing to a recent version of OCaml.
OCaml applications are usually available top-level, and not inside `ocamlPackages` . Notable exceptions are build tools that must be built with the same compiler version as the compiler you intend to use like `dune` or `ocaml-lsp` .
To open a shell able to build a typical OCaml project, put the dependencies in `buildInputs` and add `ocamlPackages.ocaml` and `ocamlPackages.findlib` to `nativeBuildInputs` at least.
For example:
```nix
let
pkgs = import < nixpkgs > {};
# choose the ocaml version you want to use
ocamlPackages = pkgs.ocaml-ng.ocamlPackages_4_12;
in
pkgs.mkShell {
# build tools
nativeBuildInputs = with ocamlPackages; [ ocaml findlib dune_2 ocaml-lsp ];
# dependencies
buildInputs = with ocamlPackages; [ ocamlgraph ];
}
```
## Packaging guide {#sec-language-ocaml-packaging}
2020-12-02 05:09:57 +01:00
OCaml libraries should be installed in `$(out)/lib/ocaml/${ocaml.version}/site-lib/` . Such directories are automatically added to the `$OCAMLPATH` environment variable when building another package that depends on them or when opening a `nix-shell` .
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` .
2021-06-22 18:53:27 +02:00
Here is a simple package example.
2022-01-19 11:16:45 +01:00
- 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.
2021-06-22 18:53:27 +02:00
- It uses the `fetchFromGitHub` fetcher to get its source.
2022-03-27 15:07:31 +02:00
- `duneVersion = "2"` ensures that Dune version 2 is used for the
build (this is the default; valid values are `"1"` , `"2"` , and `"3"` );
note that there is also a legacy `useDune2` boolean attribute:
set to `false` it corresponds to `duneVersion = "1"` ; set to `true` it
corresponds to `duneVersion = "2"` . If both arguments (`duneVersion` and
`useDune2` ) are given, the second one (`useDune2`) is silently ignored.
2021-06-22 18:53:27 +02:00
- 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.
2020-12-02 05:09:57 +01:00
```nix
2021-06-22 18:53:27 +02:00
{ lib,
fetchFromGitHub,
buildDunePackage,
ocaml,
ocaml-syntax-shims,
alcotest,
result,
bigstringaf,
ppx_let }:
2020-12-02 05:09:57 +01:00
buildDunePackage rec {
pname = "angstrom";
2021-06-22 18:53:27 +02:00
version = "0.15.0";
2022-03-27 15:07:31 +02:00
duneVersion = "2";
2020-12-02 05:09:57 +01:00
2021-06-22 18:53:27 +02:00
minimalOCamlVersion = "4.04";
2020-12-02 05:09:57 +01:00
src = fetchFromGitHub {
owner = "inhabitedtype";
repo = pname;
rev = version;
doc: use sri hash syntax
The nixpkgs manual contains references to both sri hash and explicit
sha256 attributes. This is at best confusing to new users. Since the
final destination is exclusive use of sri hashes, see nixos/rfcs#131,
might as well push new users in that direction gently.
Notable exceptions to sri hash support are builtins.fetchTarball,
cataclysm-dda, coq, dockerTools.pullimage, elixir.override, and
fetchCrate. None, other than builtins.fetchTarball, are fundamentally
incompatible, but all currently accept explicit sha256 attributes as
input. Because adding backwards compatibility is out of scope for this
change, they have been left intact, but migration to sri format has been
made for any using old hash formats.
All hashes have been manually tested to be accurate, and updates were
only made for missing upstream artefacts or bugs.
2022-12-03 20:49:00 +01:00
hash = "sha256-MK8o+iPGANEhrrTc1Kz9LBilx2bDPQt7Pp5P2libucI=";
2020-12-02 05:09:57 +01:00
};
2021-06-22 18:53:27 +02:00
checkInputs = [ alcotest ppx_let ];
buildInputs = [ ocaml-syntax-shims ];
2020-12-02 05:09:57 +01:00
propagatedBuildInputs = [ bigstringaf result ];
2021-06-22 18:53:27 +02:00
doCheck = lib.versionAtLeast ocaml.version "4.05";
2020-12-02 05:09:57 +01:00
2021-06-22 18:53:27 +02:00
meta = {
2020-12-02 05:09:57 +01:00
homepage = "https://github.com/inhabitedtype/angstrom";
description = "OCaml parser combinators built for speed and memory efficiency";
2021-06-22 18:53:27 +02:00
license = lib.licenses.bsd3;
maintainers = with lib.maintainers; [ sternenseemann ];
2020-12-02 05:09:57 +01:00
};
```
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
2021-06-22 18:53:27 +02:00
{ lib, fetchurl, buildDunePackage }:
2020-12-02 05:09:57 +01:00
buildDunePackage rec {
pname = "wtf8";
2021-06-22 18:53:27 +02:00
version = "1.0.2";
useDune2 = true;
2020-12-02 05:09:57 +01:00
2021-06-22 18:53:27 +02:00
minimalOCamlVersion = "4.02";
2020-12-02 05:09:57 +01:00
src = fetchurl {
2021-06-22 18:53:27 +02:00
url = "https://github.com/flowtype/ocaml-${pname}/releases/download/v${version}/${pname}-v${version}.tbz";
doc: use sri hash syntax
The nixpkgs manual contains references to both sri hash and explicit
sha256 attributes. This is at best confusing to new users. Since the
final destination is exclusive use of sri hashes, see nixos/rfcs#131,
might as well push new users in that direction gently.
Notable exceptions to sri hash support are builtins.fetchTarball,
cataclysm-dda, coq, dockerTools.pullimage, elixir.override, and
fetchCrate. None, other than builtins.fetchTarball, are fundamentally
incompatible, but all currently accept explicit sha256 attributes as
input. Because adding backwards compatibility is out of scope for this
change, they have been left intact, but migration to sri format has been
made for any using old hash formats.
All hashes have been manually tested to be accurate, and updates were
only made for missing upstream artefacts or bugs.
2022-12-03 20:49:00 +01:00
hash = "sha256-d5/3KUBAWRj8tntr4RkJ74KWW7wvn/B/m1nx0npnzyc=";
2020-12-02 05:09:57 +01:00
};
2021-01-10 22:30:22 +01:00
meta = with lib; {
2020-12-02 05:09:57 +01:00
homepage = "https://github.com/flowtype/ocaml-wtf8";
description = "WTF-8 is a superset of UTF-8 that allows unpaired surrogates.";
license = licenses.mit;
maintainers = [ maintainers.eqyiel ];
};
}
```
2022-01-19 11:16:45 +01:00
Note about `minimalOCamlVersion` . A deprecated version of this argument was
spelled `minimumOCamlVersion` ; setting the old attribute wrongly modifies the
derivation hash and is therefore inappropriate. As a technical dept, currently
packaged libraries may still use the old spelling: maintainers are invited to
fix this when updating packages. Massive renaming is strongly discouraged as it
would be challenging to review, difficult to test, and will cause unnecessary
rebuild.
2022-12-11 13:00:00 +01:00
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.