1# OCaml {#sec-language-ocaml} 2 3## User guide {#sec-language-ocaml-user-guide} 4 5OCaml 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`. 6 7If you don't care about the exact compiler version, `ocamlPackages` is a top-level alias pointing to a recent version of OCaml. 8 9OCaml 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`. 10 11To 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. 12For example: 13```nix 14let 15 pkgs = import <nixpkgs> {}; 16 # choose the ocaml version you want to use 17 ocamlPackages = pkgs.ocaml-ng.ocamlPackages_4_12; 18in 19pkgs.mkShell { 20 # build tools 21 nativeBuildInputs = with ocamlPackages; [ ocaml findlib dune_2 ocaml-lsp ]; 22 # dependencies 23 buildInputs = with ocamlPackages; [ ocamlgraph ]; 24} 25``` 26 27## Packaging guide {#sec-language-ocaml-packaging} 28 29OCaml 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`. 30 31Given 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`. 32 33Here is a simple package example. 34 35- It defines an (optional) attribute `minimalOCamlVersion` (see note below) 36 that will be used to throw a descriptive evaluation error if building with 37 an older OCaml is attempted. 38 39- It uses the `fetchFromGitHub` fetcher to get its source. 40 41- It also accept `duneVersion` parameter (valid value are `"1"`, `"2"`, and 42 `"3"`). The recommended practice it to set only if you don't want the default 43 value and/or it depends on something else like package version. You might see 44 a not-supported argument `useDune2`. The behavior was `useDune2 = true;` => 45 `duneVersion = "2";` and `useDune2 = false;` => `duneVersion = "1";`. It was 46 used at the time when dune3 didn't existed. 47 48- It sets the optional `doCheck` attribute such that tests will be run with 49 `dune runtest -p angstrom` after the build (`dune build -p angstrom`) is 50 complete, but only if the Ocaml version is at at least `"4.05"`. 51 52- It uses the package `ocaml-syntax-shims` as a build input, `alcotest` and 53 `ppx_let` as check inputs (because they are needed to run the tests), and 54 `bigstringaf` and `result` as propagated build inputs (thus they will also be 55 available to libraries depending on this library). 56 57- The library will be installed using the `angstrom.install` file that dune 58 generates. 59 60```nix 61{ lib, 62 fetchFromGitHub, 63 buildDunePackage, 64 ocaml, 65 ocaml-syntax-shims, 66 alcotest, 67 result, 68 bigstringaf, 69 ppx_let }: 70 71buildDunePackage rec { 72 pname = "angstrom"; 73 version = "0.15.0"; 74 75 minimalOCamlVersion = "4.04"; 76 77 src = fetchFromGitHub { 78 owner = "inhabitedtype"; 79 repo = pname; 80 rev = version; 81 hash = "sha256-MK8o+iPGANEhrrTc1Kz9LBilx2bDPQt7Pp5P2libucI="; 82 }; 83 84 checkInputs = [ alcotest ppx_let ]; 85 buildInputs = [ ocaml-syntax-shims ]; 86 propagatedBuildInputs = [ bigstringaf result ]; 87 doCheck = lib.versionAtLeast ocaml.version "4.05"; 88 89 meta = { 90 homepage = "https://github.com/inhabitedtype/angstrom"; 91 description = "OCaml parser combinators built for speed and memory efficiency"; 92 license = lib.licenses.bsd3; 93 maintainers = with lib.maintainers; [ sternenseemann ]; 94 }; 95``` 96 97Here 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. 98 99```nix 100{ lib, fetchurl, buildDunePackage }: 101 102buildDunePackage rec { 103 pname = "wtf8"; 104 version = "1.0.2"; 105 106 minimalOCamlVersion = "4.02"; 107 108 src = fetchurl { 109 url = "https://github.com/flowtype/ocaml-${pname}/releases/download/v${version}/${pname}-v${version}.tbz"; 110 hash = "sha256-d5/3KUBAWRj8tntr4RkJ74KWW7wvn/B/m1nx0npnzyc="; 111 }; 112 113 meta = with lib; { 114 homepage = "https://github.com/flowtype/ocaml-wtf8"; 115 description = "WTF-8 is a superset of UTF-8 that allows unpaired surrogates."; 116 license = licenses.mit; 117 maintainers = [ maintainers.eqyiel ]; 118 }; 119} 120``` 121 122Note about `minimalOCamlVersion`. A deprecated version of this argument was 123spelled `minimumOCamlVersion`; setting the old attribute wrongly modifies the 124derivation hash and is therefore inappropriate. As a technical dept, currently 125packaged libraries may still use the old spelling: maintainers are invited to 126fix this when updating packages. Massive renaming is strongly discouraged as it 127would be challenging to review, difficult to test, and will cause unnecessary 128rebuild. 129 130The build will automatically fail if two distinct versions of the same library 131are added to `buildInputs` (which usually happens transitively because of 132`propagatedBuildInputs`). Set `dontDetectOcamlConflicts` to true to disable this 133behavior.