on iko/ghcjs-patch-master help sign in
builder: Add haddock and hoogle to components.library.doc
d145760Rodney Lorrimar
builder/comp-builder.nix+57−14
@@ -16,6 +16,7 @@
16, preBuild ? null, postBuild ? null
16, preBuild ? null, postBuild ? null
17, preCheck ? null, postCheck ? null
17, preCheck ? null, postCheck ? null
18, preInstall ? null, postInstall ? null
18, preInstall ? null, postInstall ? null
19+, preHaddock ? null, postHaddock ? null
19, shellHook ? null
20, shellHook ? null
20
21
21, doCheck ? component.doCheck || haskellLib.isTest componentId
22, doCheck ? component.doCheck || haskellLib.isTest componentId
@@ -25,6 +26,11 @@
25
26
26, static ? stdenv.hostPlatform.isMusl
27, static ? stdenv.hostPlatform.isMusl
27, deadCodeElimination ? true
28, deadCodeElimination ? true
29+
30+# Options for Haddock generation
31+, doHaddock ? component.doHaddock # Enable haddock and hoogle generation
32+, doHoogle ? true # Also build a hoogle index
33+, hyperlinkSource ? true # Link documentation to the source code
28}:
34}:
29
35
30let
36let
@@ -164,7 +170,8 @@ let
164 # other flags
170 # other flags
165 "--enable-executable-stripping"
171 "--enable-executable-stripping"
166 "--enable-library-stripping"
172 "--enable-library-stripping"
173+ ] ++ lib.optional doHaddock' "--docdir=${docdir "$doc"}"
167− ] ++ lib.optional (deadCodeElimination && stdenv.hostPlatform.isLinux) "--enable-split-sections"
174+ ++ lib.optional (deadCodeElimination && stdenv.hostPlatform.isLinux) "--enable-split-sections"
168 ++ lib.optional (static) "--enable-static"
175 ++ lib.optional (static) "--enable-static"
169 ++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) (
176 ++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) (
170 map (arg: "--hsc2hs-option=" + arg) ["--cross-compile" "--via-asm"]
177 map (arg: "--hsc2hs-option=" + arg) ["--cross-compile" "--via-asm"]
@@ -182,7 +189,14 @@ let
182 inherit package configFiles;
189 inherit package configFiles;
183 };
190 };
184
191
192+ # the target dir for haddock documentation
193+ docdir = docoutput: docoutput + "/share/doc/" + componentId.cname;
194+
195+ doHaddock' = doHaddock && (haskellLib.isLibrary componentId);
196+
197+in stdenv.lib.fix (drv:
198+
185−in stdenv.mkDerivation ({
199+stdenv.mkDerivation ({
186 name = fullName;
200 name = fullName;
187
201
188 inherit src doCheck doCrossCheck dontPatchELF dontStrip;
202 inherit src doCheck doCrossCheck dontPatchELF dontStrip;
@@ -192,6 +206,10 @@ in stdenv.mkDerivation ({
192 config = component;
206 config = component;
193 inherit configFiles;
207 inherit configFiles;
194 env = shellWrappers;
208 env = shellWrappers;
209+
210+ # The directory containing the haddock documentation.
211+ # `null' if no haddock documentation was built.
212+ haddockDir = if doHaddock' then "${docdir drv.doc}/html" else null;
195 };
213 };
196
214
197 meta = {
215 meta = {
@@ -216,13 +234,17 @@ in stdenv.mkDerivation ({
216 ++ component.pkgconfig;
234 ++ component.pkgconfig;
217
235
218 nativeBuildInputs =
236 nativeBuildInputs =
219− [ghc]
237+ [ghc buildPackages.removeReferencesTo]
220 ++ lib.optional (component.pkgconfig != []) pkgconfig
238 ++ lib.optional (component.pkgconfig != []) pkgconfig
221 ++ executableToolDepends;
239 ++ executableToolDepends;
222
240
223 SETUP_HS = setup + /bin/Setup;
241 SETUP_HS = setup + /bin/Setup;
224
242
243+ outputs = ["out" ] ++ (lib.optional doHaddock' "doc");
244+
225 # Phases
245 # Phases
246+ preInstallPhases = lib.optional doHaddock' "haddockPhase";
247+
226 prePatch = lib.optionalString (cabalFile != null) ''
248 prePatch = lib.optionalString (cabalFile != null) ''
227 cat ${cabalFile} > ${package.identifier.name}.cabal
249 cat ${cabalFile} > ${package.identifier.name}.cabal
228 '';
250 '';
@@ -250,6 +272,32 @@ in stdenv.mkDerivation ({
250 runHook postCheck
272 runHook postCheck
251 '';
273 '';
252
274
275+ haddockPhase = ''
276+ runHook preHaddock
277+ docdir="${docdir "$doc"}"
278+ mkdir -p "$docdir"
279+
280+ $SETUP_HS haddock \
281+ "--html" \
282+ ${lib.optionalString doHoogle "--hoogle"} \
283+ ${lib.optionalString hyperlinkSource "--hyperlink-source"} \
284+ ${lib.concatStringsSep " " component.setupHaddockFlags}
285+
286+ html="dist/doc/html/${componentId.cname}"
287+
288+ if [ -d "$html" ]; then
289+ # Ensure that libraries are not pulled into the docs closure.
290+ # As an example, the prettified source code of a
291+ # Paths_package module will contain store paths of the library package.
292+ for x in "$html/src/"*.html; do
293+ remove-references-to -t $out $x
294+ done
295+
296+ cp -R "$html" "$docdir"/html
297+ fi
298+ runHook postHaddock
299+ '';
300+
253 # Note: Cabal does *not* copy test executables during the `install` phase.
301 # Note: Cabal does *not* copy test executables during the `install` phase.
254 installPhase = ''
302 installPhase = ''
255 runHook preInstall
303 runHook preInstall
@@ -278,15 +326,10 @@ in stdenv.mkDerivation ({
278}
326}
279# patches can (if they like) depend on the version and revision of the package.
327# patches can (if they like) depend on the version and revision of the package.
280// lib.optionalAttrs (patches != []) { patches = map (p: if builtins.isFunction p then p { inherit (package.identifier) version; inherit revision; } else p) patches; }
328// lib.optionalAttrs (patches != []) { patches = map (p: if builtins.isFunction p then p { inherit (package.identifier) version; inherit revision; } else p) patches; }
281−// lib.optionalAttrs (preUnpack != "") { inherit preUnpack; }
329+// haskellLib.optionalHooks {
282−// lib.optionalAttrs (postUnpack != "") { inherit postUnpack; }
330+ inherit preUnpack postUnpack preConfigure postConfigure
283−// lib.optionalAttrs (preConfigure != "") { inherit preConfigure; }
331+ preBuild postBuild preCheck postCheck
284−// lib.optionalAttrs (postConfigure != "") { inherit postConfigure; }
332+ preInstall postInstall preHaddock postHaddock;
285−// lib.optionalAttrs (preBuild != "") { inherit preBuild; }
333+}
286−// lib.optionalAttrs (postBuild != "") { inherit postBuild; }
287−// lib.optionalAttrs (preCheck != "") { inherit preCheck; }
288−// lib.optionalAttrs (postCheck != "") { inherit postCheck; }
289−// lib.optionalAttrs (preInstall != "") { inherit preInstall; }
290−// lib.optionalAttrs (postInstall != "") { inherit postInstall; }
291// lib.optionalAttrs (stdenv.buildPlatform.libc == "glibc"){ LOCALE_ARCHIVE = "${buildPackages.glibcLocales}/lib/locale/locale-archive"; }
334// lib.optionalAttrs (stdenv.buildPlatform.libc == "glibc"){ LOCALE_ARCHIVE = "${buildPackages.glibcLocales}/lib/locale/locale-archive"; }
292−)
335+))
builder/default.nix+5−1
@@ -21,6 +21,8 @@
21, postCheck
21, postCheck
22, preInstall
22, preInstall
23, postInstall
23, postInstall
24+, preHaddock
25+, postHaddock
24
26
25, shellHook
27, shellHook
26
28
@@ -73,7 +75,9 @@ let
73
75
74 buildComp = componentId: component: comp-builder {
76 buildComp = componentId: component: comp-builder {
75 inherit componentId component package name src flags setup cabalFile patches revision
77 inherit componentId component package name src flags setup cabalFile patches revision
76− preUnpack postUnpack preConfigure postConfigure preBuild postBuild preCheck postCheck preInstall postInstall
78+ preUnpack postUnpack preConfigure postConfigure
79+ preBuild postBuild preCheck postCheck
80+ preInstall postInstall preHaddock postHaddock
77 shellHook
81 shellHook
78 ;
82 ;
79 };
83 };
lib/default.nix+3
@@ -61,6 +61,9 @@ with haskellLib;
61 if componentId.ctype == "all" then ""
61 if componentId.ctype == "all" then ""
62 else "${componentId.ctype}:${componentId.cname}";
62 else "${componentId.ctype}:${componentId.cname}";
63
63
64+ # Remove null or empty values from an attrset.
65+ optionalHooks = lib.filterAttrs (_: hook: hook != null && hook != "");
66+
64 # Avoid pkgs.callPackage for now. It does a lot of nonsense with OOP
67 # Avoid pkgs.callPackage for now. It does a lot of nonsense with OOP
65 # style programming that we should avoid until we know we want it.
68 # style programming that we should avoid until we know we want it.
66
69
modules/package.nix+26
@@ -135,6 +135,10 @@ in {
135 type = listOfFilteringNulls str;
135 type = listOfFilteringNulls str;
136 default = config.setupInstallFlags;
136 default = config.setupInstallFlags;
137 };
137 };
138+ setupHaddockFlags = mkOption {
139+ type = listOfFilteringNulls str;
140+ default = config.setupHaddockFlags;
141+ };
138 doExactConfig = mkOption {
142 doExactConfig = mkOption {
139 type = bool;
143 type = bool;
140 default = config.doExactConfig;
144 default = config.doExactConfig;
@@ -147,6 +151,11 @@ in {
147 type = bool;
151 type = bool;
148 default = config.doCrossCheck;
152 default = config.doCrossCheck;
149 };
153 };
154+ doHaddock = mkOption {
155+ description = "Enable building of the Haddock documentation from the annotated Haskell source code.";
156+ type = bool;
157+ default = config.doHaddock;
158+ };
150 };
159 };
151 };
160 };
152 in {
161 in {
@@ -225,6 +234,10 @@ in {
225 type = listOfFilteringNulls str;
234 type = listOfFilteringNulls str;
226 default = [];
235 default = [];
227 };
236 };
237+ setupHaddockFlags = mkOption {
238+ type = listOfFilteringNulls str;
239+ default = [];
240+ };
228 preUnpack = mkOption {
241 preUnpack = mkOption {
229 type = nullOr lines;
242 type = nullOr lines;
230 default = null;
243 default = null;
@@ -265,6 +278,14 @@ in {
265 type = nullOr string;
278 type = nullOr string;
266 default = null;
279 default = null;
267 };
280 };
281+ preHaddock = mkOption {
282+ type = nullOr string;
283+ default = null;
284+ };
285+ postHaddock = mkOption {
286+ type = nullOr string;
287+ default = null;
288+ };
268 shellHook = mkOption {
289 shellHook = mkOption {
269 type = nullOr string;
290 type = nullOr string;
270 default = null;
291 default = null;
@@ -282,6 +303,11 @@ in {
282 type = bool;
303 type = bool;
283 default = false;
304 default = false;
284 };
305 };
306+ doHaddock = mkOption {
307+ description = "Enable building of the Haddock documentation from the annotated Haskell source code.";
308+ type = bool;
309+ default = true;
310+ };
285 };
311 };
286
312
287 # This has one quirk. Manually setting options on the all component
313 # This has one quirk. Manually setting options on the all component
test/cabal-simple/default.nix+9−3
@@ -19,7 +19,13 @@ let
19 { cabal-simple = ./cabal-simple.nix;
19 { cabal-simple = ./cabal-simple.nix;
20 }
20 }
21 ];
21 ];
22− modules = [ ];
22+ modules = [
23+ {
24+ # Package has no exposed modules which causes
25+ # haddock: No input file(s)
26+ packages.cabal-simple.doHaddock = false;
27+ }
28+ ];
23 };
29 };
24
30
25 packages = pkgSet.config.hsPkgs;
31 packages = pkgSet.config.hsPkgs;
@@ -56,8 +62,8 @@ in
56 meta.platforms = platforms.all;
62 meta.platforms = platforms.all;
57
63
58 passthru = {
64 passthru = {
59− inherit (packages) cabal-simple;
65+ # Used for debugging with nix repl
60− inherit pkgSet;
66+ inherit pkgSet packages;
61
67
62 # Used for testing externally with nix-shell (../tests.sh).
68 # Used for testing externally with nix-shell (../tests.sh).
63 # This just adds cabal-install to the existing shells.
69 # This just adds cabal-install to the existing shells.