-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnix-opam-switch.nix
92 lines (80 loc) · 3.03 KB
/
nix-opam-switch.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
{ ocamlformat_version ? "" # Argument used in 'create'
, pkgs ? import <nixpkgs> { } }:
with pkgs.lib;
let
overlay = pkgs.callPackage ./overlay { };
ocaml_version_of_pkgs = ocamlPkgs: ocamlPkgs.ocaml.meta.branch;
ocamlPackages_per_version = mapAttrs' (n: ocamlPkgs:
let
name = if n == "ocamlPackages" then
"default"
else
ocaml_version_of_pkgs ocamlPkgs;
in nameValuePair name ocamlPkgs)
(filterAttrs (n: _: hasPrefix "ocamlPackages" n) pkgs.ocaml-ng);
# Returns '[ pkg ]' if the given package is available, '[]' otherwise.
# A package is available if it evaluates successfully.
if_available = name: pkg:
let e = builtins.tryEval (pkg.outPath);
in if e.success then
[ e.value ]
else
warn "Package '${name}' is not available for this OCaml version." [ ];
# Rewrite a package to be compatible with the directory hierarchy of an Opam
# switch
switch_of_paths = { name, ocaml_version, paths, postBuild ? "" }:
pkgs.symlinkJoin {
inherit name paths;
postBuild = ''
sitelib=$out/lib/ocaml/${ocaml_version}/site-lib
if [[ -d $sitelib ]]; then
mv "$sitelib"/* "$out/lib"
rm -r "$out/lib/ocaml/${ocaml_version}"
fi
mv "$out/share/man" "$out/man"
rm -rf "$out/"{nix-support,include}
${postBuild}
'';
};
# ocamlfind does this by shadowing the 'ocaml' binary, which is no longer
# possible since we copy 'ocaml' into the 'bin/' directory.
override_ocaml_toplevel = ocaml:
pkgs.writeShellScript "ocaml" ''
${ocaml}/bin/ocaml -I "$OCAML_TOPLEVEL_PATH" "$@"
'';
mk_switch = ocamlPkgs:
let
# If the specified version is not right, continue with a default version
ocamlformat = if hasAttr ocamlformat_version overlay.ocamlformat_versions then
getAttr ocamlformat_version overlay.ocamlformat_versions
else
overlay.ocamlformat_default;
paths = concatLists [
[ ocamlPkgs.ocaml ]
(if_available "merlin" ocamlPkgs.merlin)
(if_available "ocp-indent" ocamlPkgs.ocp-indent)
(if_available "ocamlformat" ocamlformat)
];
in switch_of_paths {
name = "opam-switch-${ocaml_version_of_pkgs ocamlPkgs}";
ocaml_version = ocamlPkgs.ocaml.version;
inherit paths;
postBuild = ''
ln -sf "${override_ocaml_toplevel ocamlPkgs.ocaml}" "$out/bin/ocaml"
'';
};
in {
list-available = mapAttrsToList (v: _: v) ocamlPackages_per_version;
# Opam switches mapped by OCaml versions. The version "default" maps to the
# default version exposed in nixpkgs (which is not always the lastest).
create = mapAttrs (_: mk_switch) ocamlPackages_per_version;
# OCamlformat packages mapped by versions. The version "default" points to
# the lastest, as defined in nixpkgs.
# Result matches the hierarchy of an Opam switch.
ocamlformat = mapAttrs (v: pkg:
switch_of_paths {
name = "ocamlformat-${v}";
ocaml_version = pkgs.ocaml.version;
paths = [ pkg ];
}) overlay.ocamlformat_versions;
}