1# Install not only the Hoogle library and executable, but also a local Hoogle
2# database which provides "Source" links to all specified 'packages' -- or the
3# current Haskell Platform if no custom package set is provided.
4
5{ lib, stdenv, buildPackages, haskellPackages
6, writeText
7}:
8
9# This argument is a function which selects a list of Haskell packages from any
10# passed Haskell package set.
11#
12# Example:
13# (hpkgs: [ hpkgs.mtl hpkgs.lens ])
14selectPackages:
15
16let
17 inherit (haskellPackages) ghc hoogle;
18 packages = selectPackages haskellPackages;
19
20 wrapper = ./hoogle-local-wrapper.sh;
21 isGhcjs = ghc.isGhcjs or false;
22 opts = lib.optionalString;
23 haddockExe =
24 if !isGhcjs
25 then "haddock"
26 else "haddock-ghcjs";
27 ghcDocLibDir =
28 if !isGhcjs
29 then ghc.doc + "/share/doc/ghc*/html/libraries"
30 else ghc + "/doc/lib";
31 # On GHCJS, use a stripped down version of GHC's prologue.txt
32 prologue =
33 if !isGhcjs
34 then "${ghcDocLibDir}/prologue.txt"
35 else writeText "ghcjs-prologue.txt" ''
36 This index includes documentation for many Haskell modules.
37 '';
38
39 # TODO: closePropagation is deprecated; replace
40 docPackages = lib.closePropagation
41 # we grab the doc outputs
42 (map (lib.getOutput "doc") packages);
43
44in
45buildPackages.stdenv.mkDerivation {
46 name = "hoogle-with-packages";
47 buildInputs = [ghc hoogle];
48
49 # compiling databases takes less time than copying the results
50 # between machines.
51 preferLocalBuild = true;
52
53 # we still allow substitutes because a database is relatively small and if it
54 # is already built downloading is probably faster. The substitution will only
55 # trigger for users who have already cached the database on a substituter and
56 # thus probably intend to substitute it.
57 allowSubstitutes = true;
58
59 inherit docPackages;
60
61 passAsFile = ["buildCommand"];
62
63 buildCommand = ''
64 ${let # Filter out nulls here to work around https://github.com/NixOS/nixpkgs/issues/82245
65 # If we don't then grabbing `p.name` here will fail.
66 packages' = lib.filter (p: p != null) packages;
67 in lib.optionalString (packages' != [] -> docPackages == [])
68 ("echo WARNING: localHoogle package list empty, even though"
69 + " the following were specified: "
70 + lib.concatMapStringsSep ", " (p: p.name) packages')}
71 mkdir -p $out/share/doc/hoogle
72
73 echo importing builtin packages
74 for docdir in ${ghcDocLibDir}"/"*; do
75 name="$(basename $docdir)"
76 ${opts isGhcjs ''docdir="$docdir/html"''}
77 if [[ -d $docdir ]]; then
78 ln -sfn $docdir $out/share/doc/hoogle/$name
79 fi
80 done
81
82 echo importing other packages
83 ${lib.concatMapStringsSep "\n" (el: ''
84 ln -sfn ${el.haddockDir} "$out/share/doc/hoogle/${el.name}"
85 '')
86 (lib.filter (el: el.haddockDir != null)
87 (builtins.map (p: { haddockDir = if p ? haddockDir then p.haddockDir p else null;
88 name = p.pname; })
89 docPackages))}
90
91 echo building hoogle database
92 hoogle generate --database $out/share/doc/hoogle/default.hoo --local=$out/share/doc/hoogle
93
94 echo building haddock index
95 # adapted from GHC's gen_contents_index
96 cd $out/share/doc/hoogle
97
98 args=
99 for hdfile in $(ls -1 *"/"*.haddock | grep -v '/ghc\.haddock' | sort); do
100 name_version=`echo "$hdfile" | sed 's#/.*##'`
101 args="$args --read-interface=$name_version,$hdfile"
102 done
103
104 ${ghc}/bin/${haddockExe} --gen-index --gen-contents -o . \
105 -t "Haskell Hierarchical Libraries" \
106 -p ${prologue} \
107 $args
108
109 echo finishing up
110 mkdir -p $out/bin
111 substitute ${wrapper} $out/bin/hoogle \
112 --subst-var out --subst-var-by shell ${stdenv.shell} \
113 --subst-var-by hoogle ${hoogle}
114 chmod +x $out/bin/hoogle
115 '';
116
117 passthru = {
118 isHaskellLibrary = false; # for the filter in ./with-packages-wrapper.nix
119 };
120
121 meta = {
122 description = "A local Hoogle database";
123 platforms = ghc.meta.platforms;
124 hydraPlatforms = with lib.platforms; none;
125 maintainers = with lib.maintainers; [ ttuegel ];
126 };
127}