OCaml: Difference between revisions
overrideScope |
Clarified interaction with Opam. |
||
| (3 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
[[File:OCaml Logo.svg|alt=The OCaml logo: an orange background with a white foreground of a camel.|thumb|OCaml logo]] | |||
According to the official [ocaml.org Ocaml website]:<blockquote> | |||
[Ocaml is]... an industrial-strength functional programming language with an emphasis on expressiveness and safety </blockquote> | |||
OCaml | == Developping in OCaml with Nix == | ||
Most packages related to OCaml, in particular the OCaml compiler and many libraries, belong to the <code>ocamlPackages</code> attribute set of nixpkgs. Tools for OCaml development are, in particular, available: | |||
* the [https://dune.build/ dune] builder; | |||
* the [https://github.com/ocaml/ocaml-lsp OCaml language server]; | |||
* the [https://github.com/ocaml-ppx/ocamlformat ocamlformat formatter]. | |||
=== Build tooling === | |||
Modern development in OCaml tend to use <code>dune</code>, a build system dedicated for OCaml projects. Nixpkgs provide a dedicated helper [https://nixos.org/manual/nixpkgs/stable/#sec-language-ocaml-packaging buildDuneProject] to facilitate integration with <code>dune</code>. | |||
An example minimal flake for OCaml development is available below: | |||
{{Code|1=// flake.nix | |||
{ | |||
description = "Minimal flake for OCaml projects."; | |||
inputs = { | |||
flake-utils.url = "github:numtide/flake-utils"; | |||
nixpkgs.url = "nixpkgs"; | |||
}; | |||
outputs = | |||
{ | |||
self, | |||
flake-utils, | |||
nixpkgs, | |||
... | |||
}: | |||
flake-utils.lib.eachDefaultSystem ( | |||
system: | |||
let | |||
pkgs = nixpkgs.legacyPackages.${system}; | |||
in | |||
{ | |||
packages = { | |||
default = | |||
buildDunePackage { | |||
pname = "My Ocaml Package"; | |||
duneVersion = "3"; | |||
version = "0.1"; | |||
minimalOCamlVersion = "4.14"; | |||
installTargets = "all doc"; | |||
src = ./.; | |||
nativeBuildInputs = with p; [ | |||
dune_3 | |||
]; | |||
}; | |||
}; | |||
devShells = { | |||
default = pkgs.mkShell { | |||
name = "Ocaml development shell environment."; | |||
inputsFrom = [ self.packages.${system}.default ]; | |||
packages = with pkgs.ocaml-ng.ocamlPackages; [ | |||
ocamlformat | |||
ocaml-lsp | |||
utop | |||
pkgs.gnumake | |||
]; | |||
shellHook = '' | |||
echo "Welcome in the devshell." | |||
''; | |||
}; | |||
}; | |||
} | |||
); | |||
}|lang=nix}} | |||
<code>nix develop</code> followed by <code>dune init project myproject</code> will drop you in a development shell. | |||
==== Opam ==== | |||
OCaml has its own package manager, [https://opam.ocaml.org/ opam]. Trying to use it imperatively with Nix will result in errors. However, <code>opam</code> can generate a <code>.opam</code> file, which can be ingested by tools like [https://github.com/tweag/opam-nix opam-nix] to automatically generate a Nix derivation. | |||
==== Manual build with ocamlc, findlib, ocamlfind ==== | |||
OCaml libraries are usually located using [http://projects.camlcity.org/projects/findlib.html findlib] and the associated <code>ocamlfind</code> tool. These tools are found under the <code>ocamlPackages.findlib</code> attribute and rely on the <code>OCAMLPATH</code> environment variable. | |||
A hook in the <code>findlib</code> package will automatically populate this variable with the paths to the other libraries. For instance, when starting a shell with | |||
<code>nix-shell --packages ocamlPackages.findlib ocamlPackages.batteries</code> | <code>nix-shell --packages ocamlPackages.findlib ocamlPackages.batteries</code> | ||
will set the | will set the <code>OCAMLPATH</code> variable so that <code>ocamlfind</code> can locate the <code>batteries</code> library. | ||
This hook also sets the | This hook also sets the <code>CAML_LD_LIBRARY_PATH</code> environment variable that is used for locating the dynamically loaded shared libraries (aka stublibs). | ||
== Scripting with OCaml == | === Scripting with OCaml === | ||
OCaml can be used in nix-shell scripts as follows: | OCaml can be used in nix-shell scripts as follows: | ||
<syntaxHighlight lang=ocaml> | <syntaxHighlight lang=ocaml> | ||
| Line 22: | Line 96: | ||
</syntaxHighlight> | </syntaxHighlight> | ||
== Using Emacs == | === Using Emacs === | ||
[https://github.com/ocaml/tuareg Tuareg] is an Emacs OCaml mode. It can be installed with | [https://github.com/ocaml/tuareg Tuareg] is an Emacs OCaml mode. It can be installed with | ||
<code>nix-env -iA nixpkgs.emacsPackagesNg.tuareg</code>. | <code>nix-env -iA nixpkgs.emacsPackagesNg.tuareg</code>. | ||
Emacs must be configured to be able to find this package: you may need to add a line like this to your | Emacs must be configured to be able to find this package: you may need to add a line like this to your <code>.emacs</code> file, somewhere between <code>(require 'package)</code> and <code>(package-initialize)</code>: | ||
<syntaxHighlight lang=emacs> | <syntaxHighlight lang=emacs> | ||
| Line 39: | Line 112: | ||
Beware that merlin is specific to one particular version of OCaml (it won’t work correctly with a compiler of a different version). | Beware that merlin is specific to one particular version of OCaml (it won’t work correctly with a compiler of a different version). | ||
To configure Emacs and enable the merlin mode, add the following to your | To configure Emacs and enable the merlin mode, add the following to your <code>.emacs</code>: | ||
<syntaxHighlight lang=emacs> | <syntaxHighlight lang=emacs> | ||
| Line 47: | Line 120: | ||
</syntaxHighlight> | </syntaxHighlight> | ||
Also, a specific variable ( | Also, a specific variable (<code>merlin-command</code>) of the merlin mode must be overridden (its default is <code>opam</code>): | ||
<syntaxHighlight lang=emacs> | <syntaxHighlight lang=emacs> | ||
| Line 55: | Line 128: | ||
</syntaxHighlight> | </syntaxHighlight> | ||
A useful complement to merlin is [https://www.typerex.org/ocp-indent.html '''ocp-indent'''], a customizable tool to indent OCaml code. It can be installed using <code>nix-env -iA nixpkgs.ocamlPackages.ocpIndent</code>. To enable it in Emacs, don’t forget to add the following line to your | A useful complement to merlin is [https://www.typerex.org/ocp-indent.html '''ocp-indent'''], a customizable tool to indent OCaml code. It can be installed using <code>nix-env -iA nixpkgs.ocamlPackages.ocpIndent</code>. To enable it in Emacs, don’t forget to add the following line to your <code>.emacs</code>: | ||
<syntaxHighlight lang=emacs> | <syntaxHighlight lang=emacs> | ||
| Line 61: | Line 134: | ||
</syntaxHighlight> | </syntaxHighlight> | ||
== Specific version of the OCaml compiler == | === Specific version of the OCaml compiler === | ||
Various versions of the <code>ocamlPackage</code> attribute set are available, corresponding to various versions of OCaml. For instance, the attribute set <code>ocaml-ng.ocamlPackages_4_04</code> contains the OCaml compiler at version 4.04 and OCaml libraries compiled with that particular compiler. | |||
Various versions of the | |||
=== Custom version === | ==== Custom version ==== | ||
So as to get the set of OCaml libraries built with/for a custom version of the OCaml compiler, e.g., to enable <code>flambda</code> support, you may use the <code>ocamlPackages.overrideScope</code> function: | |||
So as to get the set of OCaml libraries built with/for a custom version of the OCaml compiler, e.g., to enable | |||
<syntaxHighlight lang=nix> | <syntaxHighlight lang=nix> | ||
| Line 76: | Line 147: | ||
More details: https://github.com/NixOS/nixpkgs/pull/53357#issuecomment-451727433 | More details: https://github.com/NixOS/nixpkgs/pull/53357#issuecomment-451727433 | ||
[[Category:Languages]] | |||