@@ -1,4 +1,4 @@
1−{ stdenv, buildPackages, ghc, lib, gobject-introspection ? null, haskellLib, makeConfigFiles, ghcForComponent, hsPkgs, runCommand, libffi, gmp, zlib, ncurses, numactl, nodejs }:
1+{ stdenv, buildPackages, ghc, lib, gobject-introspection ? null, haskellLib, makeConfigFiles, haddockBuilder, ghcForComponent, hsPkgs, runCommand, libffi, gmp, zlib, ncurses, numactl, nodejs }:
22lib.makeOverridable (
33let self =
44{ componentId
@@ -43,6 +43,7 @@ let self =
4343, doHaddock ? component.doHaddock # Enable haddock and hoogle generation
4444, doHoogle ? component.doHoogle # Also build a hoogle index
4545, hyperlinkSource ? component.doHyperlinkSource # Link documentation to the source code
46+, quickjump ? component.doQuickjump # Generate an index for interactive documentation navigation
4647, keepSource ? component.keepSource # Build from `source` output in the store then delete `dist`
4748, setupHaddockFlags ? component.setupHaddockFlags
4849
@@ -70,10 +71,11 @@ let
7071
7172 fullName = "${nameOnly}-${package.identifier.version}";
7273
74+ needsProfiling = enableExecutableProfiling || enableLibraryProfiling;
75+
7376 configFiles = makeConfigFiles {
7477 inherit (package) identifier;
75− inherit component fullName flags;
76− needsProfiling = enableExecutableProfiling || enableLibraryProfiling;
78+ inherit component fullName flags needsProfiling;
7779 };
7880
7981 enableFeature = enable: feature:
@@ -85,6 +87,9 @@ let
8587 [ "--prefix=$out"
8688 "${haskellLib.componentTarget componentId}"
8789 "$(cat ${configFiles}/configure-flags)"
90+ ] ++ commonConfigureFlags);
91+
92+ commonConfigureFlags = ([
8893 # GHC
8994 "--with-ghc=${ghc.targetPrefix}ghc"
9095 "--with-ghc-pkg=${ghc.targetPrefix}ghc-pkg"
@@ -123,7 +128,6 @@ let
123128 "--ghc-option=-optl=-pthread"
124129 "--ghc-option=-optl=-static"
125130 ] ++ lib.optional enableSeparateDataOutput "--datadir=$data/share/${ghc.name}"
126− ++ lib.optional doHaddock' "--docdir=${docdir "$doc"}"
127131 ++ lib.optional (enableLibraryProfiling || enableExecutableProfiling) "--profiling-detail=${profilingDetail}"
128132 ++ lib.optional stdenv.hostPlatform.isLinux (enableFeature enableDeadCodeElimination "split-sections")
129133 ++ lib.optionals haskellLib.isCrossHost (
@@ -154,26 +158,63 @@ let
154158 if builtins.isFunction shellHook then shellHook { inherit package shellWrappers; }
155159 else abort "shellHook should be a string or a function";
156160
157− # the target dir for haddock documentation
158− docdir = docoutput: docoutput + "/share/doc/" + componentId.cname;
159−
160− doHaddock' = doHaddock
161− && (haskellLib.isLibrary componentId)
162− && !haskellLib.isCrossHost;
163−
164161 exeExt = if stdenv.hostPlatform.isGhcjs then ".jsexe/all.js" else
165162 if stdenv.hostPlatform.isWindows then ".exe" else "";
166163 exeName = componentId.cname + exeExt;
167164 testExecutable = "dist/build/${componentId.cname}/${exeName}";
168165
169−in stdenv.lib.fix (drv:
166+ # Attributes that are common to both the build and haddock derivations
167+ commonAttrs = {
168+ src = cleanSrc;
169+
170+ LANG = "en_US.UTF-8"; # GHC needs the locale configured during the Haddock phase.
171+ LC_ALL = "en_US.UTF-8";
172+
173+ enableParallelBuilding = true;
174+
175+ SETUP_HS = setup + /bin/Setup;
176+
177+ prePatch = if (cabalFile != null)
178+ then ''cat ${cabalFile} > ${package.identifier.name}.cabal''
179+ else lib.optionalString (cabal-generator == "hpack") ''
180+ ${buildPackages.haskell-nix.haskellPackages.hpack.components.exes.hpack}/bin/hpack
181+ '';
182+ }
183+ # patches can (if they like) depend on the version and revision of the package.
184+ // lib.optionalAttrs (patches != []) {
185+ patches = map (p:
186+ if builtins.isFunction p
187+ then p { inherit (package.identifier) version; inherit revision; }
188+ else p
189+ ) patches;
190+ }
191+ // haskellLib.optionalHooks {
192+ # These are hooks are needed to set up the source for building and running haddock
193+ inherit preUnpack postUnpack preConfigure postConfigure;
194+ }
195+ // lib.optionalAttrs (stdenv.buildPlatform.libc == "glibc") {
196+ LOCALE_ARCHIVE = "${buildPackages.glibcLocales}/lib/locale/locale-archive";
197+ };
198+
199+in
200+
201+stdenv.lib.fix (drv:
202+
203+let
204+ haddock = haddockBuilder {
205+ inherit componentId component package flags commonConfigureFlags
206+ commonAttrs revision setupGhcOptions doHaddock
207+ doHoogle hyperlinkSource quickjump setupHaddockFlags
208+ needsProfiling configFiles preHaddock postHaddock;
170209
171−stdenv.mkDerivation ({
210+ componentDrv = drv;
211+ };
212+in
213+
214+stdenv.mkDerivation (commonAttrs // {
172215 pname = nameOnly;
173216 inherit (package.identifier) version;
174217
175− src = cleanSrc;
176−
177218 doCheck = false;
178219 doCrossCheck = false;
179220
@@ -184,12 +225,15 @@ stdenv.mkDerivation ({
184225 config = component;
185226 inherit configFiles executableToolDepends cleanSrc exeName;
186227 env = shellWrappers;
187−
188− # The directory containing the haddock documentation.
189− # `null' if no haddock documentation was built.
190− haddockDir = if doHaddock' then "${docdir drv.doc}/html" else null;
191228 profiled = self (drvArgs // { enableLibraryProfiling = true; });
192− };
229+ } // lib.optionalAttrs (haskellLib.isLibrary componentId) ({
230+ inherit haddock;
231+ inherit (haddock) haddockDir; # This is null if `doHaddock = false`
232+ } // lib.optionalAttrs (haddock ? doc) {
233+ # `doHaddock = false` turns the doc of haddock output off
234+ inherit (haddock) doc;
235+ }
236+ );
193237
194238 meta = {
195239 homepage = package.homepage;
@@ -202,11 +246,6 @@ stdenv.mkDerivation ({
202246 platforms = if platforms == null then stdenv.lib.platforms.all else platforms;
203247 };
204248
205− LANG = "en_US.UTF-8"; # GHC needs the locale configured during the Haddock phase.
206− LC_ALL = "en_US.UTF-8";
207−
208− enableParallelBuilding = true;
209−
210249 propagatedBuildInputs =
211250 frameworks # Frameworks will be needed at link time
212251 # Not sure why pkgconfig needs to be propagatedBuildInputs but
@@ -220,22 +259,10 @@ stdenv.mkDerivation ({
220259 [shellWrappers buildPackages.removeReferencesTo]
221260 ++ executableToolDepends;
222261
223− SETUP_HS = setup + /bin/Setup;
224−
225262 outputs = ["out" ]
226263 ++ (lib.optional enableSeparateDataOutput "data")
227− ++ (lib.optional doHaddock' "doc")
228264 ++ (lib.optional keepSource "source");
229265
230− # Phases
231− preInstallPhases = lib.optional doHaddock' "haddockPhase";
232−
233− prePatch = if (cabalFile != null)
234− then ''cat ${cabalFile} > ${package.identifier.name}.cabal''
235− else lib.optionalString (cabal-generator == "hpack") ''
236− ${buildPackages.haskell-nix.haskellPackages.hpack.components.exes.hpack}/bin/hpack
237− '';
238−
239266 configurePhase =
240267 (lib.optionalString keepSource ''
241268 cp -r . $source
@@ -259,35 +286,6 @@ stdenv.mkDerivation ({
259286
260287 checkPhase = "notice: Tests are only executed by building the .run sub-derivation of this component.";
261288
262− haddockPhase = ''
263− runHook preHaddock
264− # If we don't have any source files, no need to run haddock
265− [[ -n $(find . -name "*.hs" -o -name "*.lhs") ]] && {
266− docdir="${docdir "$doc"}"
267− mkdir -p "$docdir"
268−
269− $SETUP_HS haddock \
270− "--html" \
271− ${lib.optionalString doHoogle "--hoogle"} \
272− ${lib.optionalString hyperlinkSource "--hyperlink-source"} \
273− ${lib.concatStringsSep " " (setupHaddockFlags ++ setupGhcOptions)}
274−
275− html="dist/doc/html/${componentId.cname}"
276−
277− if [ -d "$html" ]; then
278− # Ensure that libraries are not pulled into the docs closure.
279− # As an example, the prettified source code of a
280− # Paths_package module will contain store paths of the library package.
281− for x in "$html/src/"*.html; do
282− remove-references-to -t $out $x
283− done
284−
285− cp -R "$html" "$docdir"/html
286− fi
287− }
288− runHook postHaddock
289− '';
290−
291289 # Note: Cabal does *not* copy test executables during the `install` phase.
292290 #
293291 # Note 2: if a package contains multiple libs (lib + sublibs) SETUP register will generate a
@@ -374,12 +372,11 @@ stdenv.mkDerivation ({
374372 ${shellHookApplied}
375373 '';
376374}
377−# patches can (if they like) depend on the version and revision of the package.
378−// lib.optionalAttrs (patches != []) { patches = map (p: if builtins.isFunction p then p { inherit (package.identifier) version; inherit revision; } else p) patches; }
379375// haskellLib.optionalHooks {
380− inherit preUnpack postUnpack preConfigure postConfigure
376+ # These are the hooks that are not needed by haddock (see commonAttrs for the ones that
377+ # are shared with the haddock derivation)
378+ inherit
381379 preBuild postBuild
382− preInstall postInstall preHaddock postHaddock;
380+ preInstall postInstall;
383381}
384−// lib.optionalAttrs (stdenv.buildPlatform.libc == "glibc"){ LOCALE_ARCHIVE = "${buildPackages.glibcLocales}/lib/locale/locale-archive"; }
385382)); in self)