1 { lib, stdenv, buildPackages, buildHaskellPackages, ghc
2 , jailbreak-cabal, hscolour, cpphs, runCommandCC
3 , ghcWithHoogle, ghcWithPackages
8 isCross = stdenv.buildPlatform != stdenv.hostPlatform;
10 # Note that ghc.isGhcjs != stdenv.hostPlatform.isGhcjs.
11 # ghc.isGhcjs implies that we are using ghcjs, a project separate from GHC.
12 # (mere) stdenv.hostPlatform.isGhcjs means that we are using GHC's JavaScript
13 # backend. The latter is a normal cross compilation backend and needs little
14 # special accommodation.
15 outputsJS = ghc.isGhcjs or false || stdenv.hostPlatform.isGhcjs;
17 # Pass the "wrong" C compiler rather than none at all so packages that just
18 # use the C preproccessor still work, see
19 # https://github.com/haskell/cabal/issues/6466 for details.
21 if stdenv.hasCC then "$CC"
22 else if stdenv.hostPlatform.isGhcjs then "${emscripten}/bin/emcc"
25 inherit (buildPackages)
26 fetchurl removeReferencesTo
27 pkg-config coreutils gnugrep glibcLocales
33 , dontStrip ? outputsJS
34 , version, revision ? null
36 , src ? fetchurl { url = "mirror://hackage/${pname}-${version}.tar.gz"; inherit sha256; }
38 , setSourceRoot ? null
39 , buildDepends ? [], setupHaskellDepends ? [], libraryHaskellDepends ? [], executableHaskellDepends ? []
41 , buildTools ? [], libraryToolDepends ? [], executableToolDepends ? [], testToolDepends ? [], benchmarkToolDepends ? []
49 , doHaddockQuickjump ? doHoogle
50 , doInstallIntermediates ? false
51 , editedCabalFile ? null
52 , enableLibraryProfiling ? !outputsJS
53 , enableExecutableProfiling ? false
54 , profilingDetail ? "exported-functions"
55 # TODO enable shared libs for cross-compiling
56 , enableSharedExecutables ? false
57 , enableSharedLibraries ? !stdenv.hostPlatform.isStatic && (ghc.enableShared or false)
58 , enableDeadCodeElimination ? (!stdenv.hostPlatform.isDarwin) # TODO: use -dead_strip for darwin
59 # Disabling this for ghcjs prevents this crash: https://gitlab.haskell.org/ghc/ghc/-/issues/23235
60 , enableStaticLibraries ? !(stdenv.hostPlatform.isWindows || stdenv.hostPlatform.isWasm || stdenv.hostPlatform.isGhcjs)
61 , enableHsc2hsViaAsm ? stdenv.hostPlatform.isWindows
62 , extraLibraries ? [], librarySystemDepends ? [], executableSystemDepends ? []
63 # On macOS, statically linking against system frameworks is not supported;
64 # see https://developer.apple.com/library/content/qa/qa1118/_index.html
65 # They must be propagated to the environment of any executable linking with the library
66 , libraryFrameworkDepends ? [], executableFrameworkDepends ? []
67 , homepage ? "https://hackage.haskell.org/package/${pname}"
68 , platforms ? with lib.platforms; all # GHC can cross-compile
69 , badPlatforms ? lib.platforms.none
70 , hydraPlatforms ? null
71 , hyperlinkSource ? true
72 , isExecutable ? false, isLibrary ? !isExecutable
75 , enableParallelBuilding ? true
80 , doHaddock ? !(ghc.isHaLVM or false) && (ghc.hasHaddock or true)
81 , doHaddockInterfaces ? doHaddock && lib.versionAtLeast ghc.version "9.0.1"
83 , pkg-configDepends ? [], libraryPkgconfigDepends ? [], executablePkgconfigDepends ? [], testPkgconfigDepends ? [], benchmarkPkgconfigDepends ? []
84 , testDepends ? [], testHaskellDepends ? [], testSystemDepends ? [], testFrameworkDepends ? []
85 , benchmarkDepends ? [], benchmarkHaskellDepends ? [], benchmarkSystemDepends ? [], benchmarkFrameworkDepends ? []
86 , testTarget ? "", testFlags ? []
88 , preCompileBuildDriver ? null, postCompileBuildDriver ? null
89 , preUnpack ? null, postUnpack ? null
90 , patches ? null, patchPhase ? null, prePatch ? "", postPatch ? ""
91 , preConfigure ? null, postConfigure ? null
92 , preBuild ? null, postBuild ? null
93 , preHaddock ? null, postHaddock ? null
94 , installPhase ? null, preInstall ? null, postInstall ? null
95 , checkPhase ? null, preCheck ? null, postCheck ? null
96 , preFixup ? null, postFixup ? null
98 , coreSetup ? false # Use only core packages to build Setup.hs.
100 , hardeningDisable ? null
101 , enableSeparateBinOutput ? false
102 , enableSeparateDataOutput ? false
103 , enableSeparateDocOutput ? doHaddock
104 , enableSeparateIntermediatesOutput ? false
105 , # Don't fail at configure time if there are multiple versions of the
106 # same package in the (recursive) dependencies of the package being
107 # built. Will delay failures, if any, to compile time.
108 allowInconsistentDependencies ? false
109 , maxBuildCores ? 16 # more cores usually don't improve performance: https://ghc.haskell.org/trac/ghc/ticket/9221
110 , # If set to true, this builds a pre-linked .o file for this Haskell library.
111 # This can make it slightly faster to load this library into GHCi, but takes
112 # extra disk space and compile time.
113 enableLibraryForGhci ? false
114 # Set this to a previous build of this same package to reuse the intermediate
115 # build products from that prior build as a starting point for accelerating
117 , previousIntermediates ? null
118 # References to these store paths are forbidden in the produced output.
119 , disallowedRequisites ? []
120 # Whether to allow the produced output to refer to `ghc`.
122 # This is used by `haskell.lib.justStaticExecutables` to help prevent static
123 # Haskell binaries from having erroneous dependencies on GHC.
125 # See https://nixos.org/manual/nixpkgs/unstable/#haskell-packaging-helpers
126 # or its source doc/languages-frameworks/haskell.section.md
127 , disallowGhcReference ? false
128 , # Cabal 3.8 which is shipped by default for GHC >= 9.3 always calls
129 # `pkg-config --libs --static` as part of the configure step. This requires
130 # Requires.private dependencies of pkg-config dependencies to be present in
131 # PKG_CONFIG_PATH which is normally not the case in nixpkgs (except in pkgsStatic).
132 # Since there is no patch or upstream patch yet, we replicate the automatic
133 # propagation of dependencies in pkgsStatic for allPkgConfigDepends for
134 # GHC >= 9.3 by default. This option allows overriding this behavior manually
135 # if mismatching Cabal and GHC versions are used.
136 # See also <https://github.com/haskell/cabal/issues/8455>.
137 __propagatePkgConfigDepends ? lib.versionAtLeast ghc.version "9.3"
138 , # Propagation can easily lead to the argv limit being exceeded in linker or C
139 # compiler invocations. To work around this we can only propagate derivations
140 # that are known to provide pkg-config modules, as indicated by the presence
141 # of `meta.pkgConfigModules`. This option defaults to false for now, since
142 # this metadata is far from complete in nixpkgs.
143 __onlyPropagateKnownPkgConfigModules ? false
146 assert editedCabalFile != null -> revision != null;
148 # --enable-static does not work on windows. This is a bug in GHC.
149 # --enable-static will pass -staticlib to ghc, which only works for mach-o and elf.
150 assert stdenv.hostPlatform.isWindows -> enableStaticLibraries == false;
151 assert stdenv.hostPlatform.isWasm -> enableStaticLibraries == false;
155 inherit (lib) optional optionals optionalString versionAtLeast
156 concatStringsSep enableFeature optionalAttrs;
158 isGhcjs = ghc.isGhcjs or false;
159 isHaLVM = ghc.isHaLVM or false;
161 # GHC used for building Setup.hs
163 # Same as our GHC, unless we're cross, in which case it is native GHC with the
164 # same version, or ghcjs, in which case its the ghc used to build ghcjs.
165 nativeGhc = buildHaskellPackages.ghc;
167 # the target dir for haddock documentation
168 docdir = docoutput: docoutput + "/share/doc/" + pname + "-" + version;
170 binDir = if enableSeparateBinOutput then "$bin/bin" else "$out/bin";
172 newCabalFileUrl = "mirror://hackage/${pname}-${version}/revision/${revision}.cabal";
173 newCabalFile = fetchurl {
174 url = newCabalFileUrl;
175 sha256 = editedCabalFile;
176 name = "${pname}-${version}-r${revision}.cabal";
179 defaultSetupHs = builtins.toFile "Setup.hs" ''
180 import Distribution.Simple
184 # This awk expression transforms a package conf file like
186 # author: John Doe <john-doe@example.com>
188 # The purpose of this library is to do
189 # foo and bar among other things
191 # into a more easily processeable form:
193 # author: John Doe <john-doe@example.com>
194 # description: The purpose of this library is to do foo and bar among other things
195 unprettyConf = builtins.toFile "unpretty-cabal-conf.awk" ''
197 # When the line starts with a new field, terminate the previous one with a newline
198 if (started == 1) print ""
199 # to strip leading spaces
206 # to strip leading spaces
211 # Terminate the final field with a newline
216 "--with-ghc=${ghcCommand}"
217 "--with-ghc-pkg=${ghc.targetPrefix}ghc-pkg"
219 ] ++ optionals stdenv.hasCC [
220 "--with-ld=${stdenv.cc.bintools.targetPrefix}ld"
221 "--with-ar=${stdenv.cc.bintools.targetPrefix}ar"
222 # use the one that comes with the cross compiler.
223 "--with-hsc2hs=${ghc.targetPrefix}hsc2hs"
224 "--with-strip=${stdenv.cc.bintools.targetPrefix}strip"
225 ] ++ optionals (!isHaLVM) [
226 "--hsc2hs-option=--cross-compile"
227 (optionalString enableHsc2hsViaAsm "--hsc2hs-option=--via-asm")
228 ] ++ optional (allPkgconfigDepends != [])
229 "--with-pkg-config=${pkg-config.targetPrefix}pkg-config";
231 makeGhcOptions = opts: lib.concatStringsSep " " (map (opt: "--ghc-option=${opt}") opts);
233 buildFlagsString = optionalString (buildFlags != []) (" " + concatStringsSep " " buildFlags);
235 defaultConfigureFlags = [
238 # Note: This must be kept in sync manually with mkGhcLibdir
239 ("--libdir=\\$prefix/lib/\\$compiler" + lib.optionalString (ghc ? hadrian) "/lib")
240 "--libsubdir=\\$abi/\\$libname"
241 (optionalString enableSeparateDataOutput "--datadir=$data/share/${ghcNameWithPrefix}")
242 (optionalString enableSeparateDocOutput "--docdir=${docdir "$doc"}")
243 ] ++ optionals stdenv.hasCC [
244 "--with-gcc=$CC" # Clang won't work without that extra information.
246 "--package-db=$packageConfDir"
247 (optionalString (enableSharedExecutables && stdenv.hostPlatform.isLinux) "--ghc-option=-optl=-Wl,-rpath=$out/${ghcLibdir}/${pname}-${version}")
248 (optionalString (enableSharedExecutables && stdenv.hostPlatform.isDarwin) "--ghc-option=-optl=-Wl,-headerpad_max_install_names")
249 (optionalString enableParallelBuilding (makeGhcOptions [ "-j$NIX_BUILD_CORES" "+RTS" "-A64M" "-RTS" ]))
250 (optionalString useCpphs ("--with-cpphs=${cpphs}/bin/cpphs " + (makeGhcOptions [ "-cpp" "-pgmP${cpphs}/bin/cpphs" "-optP--cpp" ])))
251 (enableFeature enableLibraryProfiling "library-profiling")
252 (optionalString (enableExecutableProfiling || enableLibraryProfiling) "--profiling-detail=${profilingDetail}")
253 (enableFeature enableExecutableProfiling "profiling")
254 (enableFeature enableSharedLibraries "shared")
255 (enableFeature doCoverage "coverage")
256 (enableFeature enableStaticLibraries "static")
257 (enableFeature enableSharedExecutables "executable-dynamic")
258 (enableFeature doCheck "tests")
259 (enableFeature doBenchmark "benchmarks")
260 "--enable-library-vanilla" # TODO: Should this be configurable?
261 (enableFeature enableLibraryForGhci "library-for-ghci")
262 (enableFeature enableDeadCodeElimination "split-sections")
263 (enableFeature (!dontStrip) "library-stripping")
264 (enableFeature (!dontStrip) "executable-stripping")
265 ] ++ optionals isGhcjs [
267 ] ++ optionals isCross ([
268 "--configure-option=--host=${stdenv.hostPlatform.config}"
270 ) ++ optionals enableSeparateBinOutput [
272 ] ++ optionals (doHaddockInterfaces && isLibrary) [
273 "--ghc-option=-haddock"
276 postPhases = optional doInstallIntermediates "installIntermediatesPhase";
278 setupCompileFlags = [
279 (optionalString (!coreSetup) "-package-db=$setupPackageConfDir")
280 "-threaded" # https://github.com/haskell/cabal/issues/2398
283 isHaskellPkg = x: x ? isHaskellLibrary;
285 # Work around a Cabal bug requiring pkg-config --static --libs to work even
286 # when linking dynamically, affecting Cabal 3.8 and 3.9.
287 # https://github.com/haskell/cabal/issues/8455
289 # For this, we treat the runtime system/pkg-config dependencies of a Haskell
290 # derivation as if they were propagated from their dependencies which allows
291 # pkg-config --static to work in most cases.
292 allPkgconfigDepends =
294 # If __onlyPropagateKnownPkgConfigModules is set, packages without
295 # meta.pkgConfigModules will be filtered out, otherwise all packages in
296 # buildInputs and propagatePlainBuildInputs are propagated.
297 propagateValue = drv:
299 && (__onlyPropagateKnownPkgConfigModules -> drv ? meta.pkgConfigModules);
301 # Take list of derivations and return list of the transitive dependency
302 # closure, only taking into account buildInputs. Loosely based on
303 # closePropagationFast.
304 propagatePlainBuildInputs = drvs:
305 builtins.map (i: i.val) (
306 builtins.genericClosure {
307 startSet = builtins.map (drv:
308 { key = drv.outPath; val = drv; }
309 ) (builtins.filter propagateValue drvs);
310 operator = { val, ... }:
311 builtins.concatMap (drv:
312 if propagateValue drv
313 then [ { key = drv.outPath; val = drv; } ]
315 ) (val.buildInputs or [ ] ++ val.propagatedBuildInputs or [ ]);
320 if __propagatePkgConfigDepends
321 then propagatePlainBuildInputs allPkgconfigDepends'
322 else allPkgconfigDepends';
323 allPkgconfigDepends' =
324 pkg-configDepends ++ libraryPkgconfigDepends ++ executablePkgconfigDepends ++
325 optionals doCheck testPkgconfigDepends ++ optionals doBenchmark benchmarkPkgconfigDepends;
327 depsBuildBuild = [ nativeGhc ]
328 # CC_FOR_BUILD may be necessary if we have no C preprocessor for the host
329 # platform. See crossCabalFlags above for more details.
330 ++ lib.optionals (!stdenv.hasCC) [ buildPackages.stdenv.cc ];
331 collectedToolDepends =
332 buildTools ++ libraryToolDepends ++ executableToolDepends ++
333 optionals doCheck testToolDepends ++
334 optionals doBenchmark benchmarkToolDepends;
336 [ ghc removeReferencesTo ] ++ optional (allPkgconfigDepends != []) (assert pkg-config != null; pkg-config) ++
337 setupHaskellDepends ++ collectedToolDepends ++ optional stdenv.hostPlatform.isGhcjs nodejs;
338 propagatedBuildInputs = buildDepends ++ libraryHaskellDepends ++ executableHaskellDepends ++ libraryFrameworkDepends;
339 otherBuildInputsHaskell =
340 optionals doCheck (testDepends ++ testHaskellDepends) ++
341 optionals doBenchmark (benchmarkDepends ++ benchmarkHaskellDepends);
342 otherBuildInputsSystem =
343 extraLibraries ++ librarySystemDepends ++ executableSystemDepends ++ executableFrameworkDepends ++
344 allPkgconfigDepends ++
345 optionals doCheck (testSystemDepends ++ testFrameworkDepends) ++
346 optionals doBenchmark (benchmarkSystemDepends ++ benchmarkFrameworkDepends);
347 # TODO next rebuild just define as `otherBuildInputsHaskell ++ otherBuildInputsSystem`
349 extraLibraries ++ librarySystemDepends ++ executableSystemDepends ++ executableFrameworkDepends ++
350 allPkgconfigDepends ++
351 optionals doCheck (testDepends ++ testHaskellDepends ++ testSystemDepends ++ testFrameworkDepends) ++
352 optionals doBenchmark (benchmarkDepends ++ benchmarkHaskellDepends ++ benchmarkSystemDepends ++ benchmarkFrameworkDepends);
354 setupCommand = "./Setup";
356 ghcCommand' = if isGhcjs then "ghcjs" else "ghc";
357 ghcCommand = "${ghc.targetPrefix}${ghcCommand'}";
359 ghcNameWithPrefix = "${ghc.targetPrefix}${ghc.haskellCompilerName}";
360 mkGhcLibdir = ghc: "lib/${ghc.targetPrefix}${ghc.haskellCompilerName}"
361 + lib.optionalString (ghc ? hadrian) "/lib";
362 ghcLibdir = mkGhcLibdir ghc;
364 nativeGhcCommand = "${nativeGhc.targetPrefix}ghc";
366 buildPkgDb = thisGhc: packageConfDir: ''
367 # If this dependency has a package database, then copy the contents of it,
368 # unless it is one of our GHCs. These can appear in our dependencies when
369 # we are doing native builds, and they have package databases in them, but
370 # we do not want to copy them over.
372 # We don't need to, since those packages will be provided by the GHC when
373 # we compile with it, and doing so can result in having multiple copies of
374 # e.g. Cabal in the database with the same name and version, which is
376 if [ -d "$p/${mkGhcLibdir thisGhc}/package.conf.d" ] && [ "$p" != "${ghc}" ] && [ "$p" != "${nativeGhc}" ]; then
377 cp -f "$p/${mkGhcLibdir thisGhc}/package.conf.d/"*.conf ${packageConfDir}/
382 intermediatesDir = "share/haskell/${ghc.version}/${pname}-${version}/dist";
384 # This is a script suitable for --test-wrapper of Setup.hs' test command
385 # (https://cabal.readthedocs.io/en/3.12/setup-commands.html#cmdoption-runhaskell-Setup.hs-test-test-wrapper).
386 # We use it to set some environment variables that the test suite may need,
387 # e.g. GHC_PACKAGE_PATH to invoke GHC(i) at runtime with build dependencies
388 # available. See the comment accompanying checkPhase below on how to customize
389 # this behavior. We need to use a wrapper script since Cabal forbids setting
390 # certain environment variables since they can alter GHC's behavior (e.g.
391 # GHC_PACKAGE_PATH) and cause failures. While building, Cabal will set
392 # GHC_ENVIRONMENT to make the packages picked at configure time available to
393 # GHC, but unfortunately not at test time. The test wrapper script will be
394 # executed after such environment checks, so we can take some liberties which
395 # is unproblematic since we know our synthetic package db matches what Cabal
396 # will see at configure time exactly. See also
397 # <https://github.com/haskell/cabal/issues/7792>.
398 testWrapperScript = buildPackages.writeShellScript
399 "haskell-generic-builder-test-wrapper.sh"
403 # We expect this to be either empty or set by checkPhase
404 if [[ -n "''${NIX_GHC_PACKAGE_PATH_FOR_TEST}" ]]; then
405 export GHC_PACKAGE_PATH="''${NIX_GHC_PACKAGE_PATH_FOR_TEST}"
413 stdenv.mkDerivation ({
414 inherit pname version;
417 ++ (optional enableSeparateDataOutput "data")
418 ++ (optional enableSeparateDocOutput "doc")
419 ++ (optional enableSeparateBinOutput "bin")
420 ++ (optional enableSeparateIntermediatesOutput "intermediates");
422 setOutputFlags = false;
424 pos = builtins.unsafeGetAttrPos "pname" args;
426 prePhases = ["setupCompilerEnvironmentPhase"];
427 preConfigurePhases = ["compileBuildDriverPhase"];
428 preInstallPhases = ["haddockPhase"];
432 inherit depsBuildBuild nativeBuildInputs;
433 buildInputs = otherBuildInputs ++ optionals (!isLibrary) propagatedBuildInputs
434 # For patchShebangsAuto in fixupPhase
435 ++ optionals stdenv.hostPlatform.isGhcjs [ nodejs ];
436 propagatedBuildInputs = optionals isLibrary propagatedBuildInputs;
438 LANG = "en_US.UTF-8"; # GHC needs the locale configured during the Haddock phase.
440 prePatch = optionalString (editedCabalFile != null) ''
441 echo "Replace Cabal file with edited version from ${newCabalFileUrl}."
442 cp ${newCabalFile} ${pname}.cabal
445 postPatch = optionalString jailbreak ''
446 echo "Run jailbreak-cabal to lift version restrictions on build inputs."
447 ${jailbreak-cabal}/bin/jailbreak-cabal ${pname}.cabal
450 setupCompilerEnvironmentPhase = ''
451 NIX_BUILD_CORES=$(( NIX_BUILD_CORES < ${toString maxBuildCores} ? NIX_BUILD_CORES : ${toString maxBuildCores} ))
452 runHook preSetupCompilerEnvironment
454 echo "Build with ${ghc}."
455 ${optionalString (isLibrary && hyperlinkSource) "export PATH=${hscolour}/bin:$PATH"}
457 builddir="$(mktemp -d)"
458 setupPackageConfDir="$builddir/setup-package.conf.d"
459 mkdir -p $setupPackageConfDir
460 packageConfDir="$builddir/package.conf.d"
461 mkdir -p $packageConfDir
463 setupCompileFlags="${concatStringsSep " " setupCompileFlags}"
464 configureFlags="${concatStringsSep " " defaultConfigureFlags} $configureFlags"
466 # We build the Setup.hs on the *build* machine, and as such should only add
467 # dependencies for the build machine.
469 # pkgs* arrays defined in stdenv/setup.hs
471 for p in "''${pkgsBuildBuild[@]}" "''${pkgsBuildHost[@]}" "''${pkgsBuildTarget[@]}"; do
472 ${buildPkgDb nativeGhc "$setupPackageConfDir"}
474 ${nativeGhcCommand}-pkg --package-db="$setupPackageConfDir" recache
476 # For normal components
478 for p in "''${pkgsHostHost[@]}" "''${pkgsHostTarget[@]}"; do
479 ${buildPkgDb ghc "$packageConfDir"}
480 if [ -d "$p/include" ]; then
481 configureFlags+=" --extra-include-dirs=$p/include"
483 if [ -d "$p/lib" ]; then
484 configureFlags+=" --extra-lib-dirs=$p/lib"
486 if [[ -d "$p/Library/Frameworks" ]]; then
487 configureFlags+=" --extra-framework-dirs=$p/Library/Frameworks"
492 + (optionalString stdenv.hostPlatform.isGhcjs ''
493 export EM_CACHE="$(realpath "$(mktemp -d emcache.XXXXXXXXXX)")"
494 cp -Lr ${emscripten}/share/emscripten/cache/* "$EM_CACHE/"
495 chmod u+rwX -R "$EM_CACHE"
497 # only use the links hack if we're actually building dylibs. otherwise, the
498 # "dynamic-library-dirs" point to nonexistent paths, and the ln command becomes
499 # "ln -s $out/lib/links", which tries to recreate the links dir and fails
501 # Note: We need to disable this work-around when using intermediate build
502 # products from a prior build because otherwise Nix will change permissions on
503 # the `$out/lib/links` directory to read-only when the build is done after the
504 # dist directory has already been exported, which triggers an unnecessary
505 # rebuild of modules included in the exported dist directory.
506 + (optionalString (stdenv.hostPlatform.isDarwin && (enableSharedLibraries || enableSharedExecutables) && !enableSeparateIntermediatesOutput) ''
507 # Work around a limit in the macOS Sierra linker on the number of paths
508 # referenced by any one dynamic library:
510 # Create a local directory with symlinks of the *.dylib (macOS shared
511 # libraries) from all the dependencies.
512 local dynamicLinksDir="$out/lib/links"
513 mkdir -p $dynamicLinksDir
515 # Unprettify all package conf files before reading/writing them
516 for d in "$packageConfDir/"*; do
517 # gawk -i inplace seems to strip the last newline
518 gawk -f ${unprettyConf} "$d" > tmp
522 for d in $(grep '^dynamic-library-dirs:' "$packageConfDir"/* | cut -d' ' -f2- | tr ' ' '\n' | sort -u); do
523 for lib in "$d/"*.{dylib,so}; do
524 # Allow overwriting because C libs can be pulled in multiple times.
525 ln -sf "$lib" "$dynamicLinksDir"
528 # Edit the local package DB to reference the links directory.
529 for f in "$packageConfDir/"*.conf; do
530 sed -i "s,dynamic-library-dirs: .*,dynamic-library-dirs: $dynamicLinksDir," "$f"
533 ${ghcCommand}-pkg --package-db="$packageConfDir" recache
535 runHook postSetupCompilerEnvironment
538 compileBuildDriverPhase = ''
539 runHook preCompileBuildDriver
541 for i in Setup.hs Setup.lhs ${defaultSetupHs}; do
545 echo setupCompileFlags: $setupCompileFlags
546 ${nativeGhcCommand} $setupCompileFlags --make -o Setup -odir $builddir -hidir $builddir $i
548 runHook postCompileBuildDriver
551 # Cabal takes flags like `--configure-option=--host=...` instead
552 configurePlatforms = [];
553 inherit configureFlags;
555 # Note: the options here must be always added, regardless of whether the
556 # package specifies `hardeningDisable`.
557 hardeningDisable = lib.optionals (args ? hardeningDisable) hardeningDisable
558 ++ lib.optional (ghc.isHaLVM or false) "all"
559 # Static libraries (ie. all of pkgsStatic.haskellPackages) fail to build
560 # because by default Nix adds `-pie` to the linker flags: this
561 # conflicts with the `-r` and `-no-pie` flags added by GHC (see
562 # https://gitlab.haskell.org/ghc/ghc/-/issues/19580). hardeningDisable
563 # changes the default Nix behavior regarding adding "hardening" flags.
564 ++ lib.optional enableStaticLibraries "pie";
569 echo configureFlags: $configureFlags
570 ${setupCommand} configure $configureFlags 2>&1 | ${coreutils}/bin/tee "$NIX_BUILD_TOP/cabal-configure.log"
571 ${lib.optionalString (!allowInconsistentDependencies) ''
572 if ${gnugrep}/bin/egrep -q -z 'Warning:.*depends on multiple versions' "$NIX_BUILD_TOP/cabal-configure.log"; then
573 echo >&2 "*** abort because of serious configure-time warning from Cabal"
578 runHook postConfigure
585 + lib.optionalString (previousIntermediates != null)
589 cp -r ${previousIntermediates}/${intermediatesDir}/build dist/build
590 find dist/build -exec chmod u+w {} +
591 find dist/build -exec touch -d '1970-01-01T00:00:00Z' {} +
594 ${setupCommand} build ${buildTarget}${buildFlagsString}
600 # Run test suite(s) and pass `checkFlags` as well as `checkFlagsArray`.
601 # `testFlags` are added to `checkFlagsArray` each prefixed with
602 # `--test-option`, so Cabal passes it to the underlying test suite binary.
604 # We also take care of setting GHC_PACKAGE_PATH during test suite execution,
605 # so it can run GHC(i) with build dependencies available:
606 # - If NIX_GHC_PACKAGE_PATH_FOR_TEST is set, it become the value of GHC_PACKAGE_PATH
607 # while the test suite is executed.
608 # - If it is empty, it'll be unset during test suite execution.
609 # - Otherwise GHC_PACKAGE_PATH will have the package db used for configuring
610 # plus GHC's core packages.
614 "--show-details=streaming"
615 "--test-wrapper=${testWrapperScript}"
616 ${lib.escapeShellArgs (builtins.map (opt: "--test-option=${opt}") testFlags)}
618 export NIX_GHC_PACKAGE_PATH_FOR_TEST="''${NIX_GHC_PACKAGE_PATH_FOR_TEST:-$packageConfDir:}"
619 ${setupCommand} test ${testTarget} $checkFlags ''${checkFlagsArray:+"''${checkFlagsArray[@]}"}
625 ${optionalString (doHaddock && isLibrary) ''
626 ${setupCommand} haddock --html \
627 ${optionalString doHoogle "--hoogle"} \
628 ${optionalString doHaddockQuickjump "--quickjump"} \
629 ${optionalString (isLibrary && hyperlinkSource) "--hyperlink-source"} \
630 ${lib.concatStringsSep " " haddockFlags}
638 ${if !isLibrary && buildTarget == "" then "${setupCommand} install"
639 # ^^ if the project is not a library, and no build target is specified, we can just use "install".
640 else if !isLibrary then "${setupCommand} copy ${buildTarget}"
641 # ^^ if the project is not a library, and we have a build target, then use "copy" to install
642 # just the target specified; "install" will error here, since not all targets have been built.
644 ${setupCommand} copy ${buildTarget}
645 local packageConfDir="$out/${ghcLibdir}/package.conf.d"
646 local packageConfFile="$packageConfDir/${pname}-${version}.conf"
647 mkdir -p "$packageConfDir"
648 ${setupCommand} register --gen-pkg-config=$packageConfFile
649 if [ -d "$packageConfFile" ]; then
650 mv "$packageConfFile/"* "$packageConfDir"
651 rmdir "$packageConfFile"
653 for packageConfFile in "$packageConfDir/"*; do
654 local pkgId=$(gawk -f ${unprettyConf} "$packageConfFile" \
655 | grep '^id:' | cut -d' ' -f2)
656 mv "$packageConfFile" "$packageConfDir/$pkgId.conf"
659 # delete confdir if there are no libraries
660 find $packageConfDir -maxdepth 0 -empty -delete;
662 ${optionalString isGhcjs ''
663 for exeDir in "${binDir}/"*.jsexe; do
664 exe="''${exeDir%.jsexe}"
665 printWords '#!${nodejs}/bin/node' > "$exe"
667 cat "$exeDir/all.js" >> "$exe"
671 ${optionalString doCoverage "mkdir -p $out/share && cp -r dist/hpc $out/share"}
673 ${optionalString enableSeparateDocOutput ''
674 for x in ${docdir "$doc"}"/html/src/"*.html; do
675 remove-references-to -t $out $x
679 ${optionalString enableSeparateDataOutput "mkdir -p $data"}
684 ${if doInstallIntermediates then "installIntermediatesPhase" else null} = ''
685 runHook preInstallIntermediates
686 intermediatesOutput=${if enableSeparateIntermediatesOutput then "$intermediates" else "$out"}
687 installIntermediatesDir="$intermediatesOutput/${intermediatesDir}"
688 mkdir -p "$installIntermediatesDir"
689 cp -r dist/build "$installIntermediatesDir"
690 runHook postInstallIntermediates
693 passthru = passthru // rec {
695 inherit pname version disallowGhcReference;
699 # All this information is intended just for `shellFor`. It should be
700 # considered unstable and indeed we knew how to keep it private we would.
705 executableFrameworkDepends
706 executableHaskellDepends
707 executablePkgconfigDepends
708 executableSystemDepends
709 executableToolDepends
711 libraryFrameworkDepends
712 libraryHaskellDepends
713 libraryPkgconfigDepends
719 } // lib.optionalAttrs doCheck {
728 } // lib.optionalAttrs doBenchmark {
731 benchmarkFrameworkDepends
732 benchmarkHaskellDepends
733 benchmarkPkgconfigDepends
734 benchmarkSystemDepends
739 # Attributes for the old definition of `shellFor`. Should be removed but
740 # this predates the warning at the top of `getCabalDeps`.
741 getBuildInputs = rec {
742 inherit propagatedBuildInputs otherBuildInputs allPkgconfigDepends;
743 haskellBuildInputs = isHaskellPartition.right;
744 systemBuildInputs = isHaskellPartition.wrong;
745 isHaskellPartition = lib.partition
747 (propagatedBuildInputs ++ otherBuildInputs ++ depsBuildBuild ++ nativeBuildInputs);
750 isHaskellLibrary = isLibrary;
752 # TODO: ask why the split outputs are configurable at all?
753 # TODO: include tests for split if possible
754 # Given the haskell package, returns
755 # the directory containing the haddock documentation.
756 # `null' if no haddock documentation was built.
757 # TODO: fetch the self from the fixpoint instead
758 haddockDir = self: if doHaddock then "${docdir self.doc}/html" else null;
760 # Creates a derivation containing all of the necessary dependencies for building the
761 # parent derivation. The attribute set that it takes as input can be viewed as:
765 # The derivation that it builds contains no outpaths because it is meant for use
769 # # Creates a shell with all of the dependencies required to build the "hello" package,
772 # > nix-shell -E 'with (import <nixpkgs> {}); \
773 # > haskell.packages.ghc865.hello.envFunc { buildInputs = [ python ]; }'
774 envFunc = { withHoogle ? false }:
776 name = "ghc-shell-for-${drv.name}";
778 withPackages = if withHoogle then ghcWithHoogle else ghcWithPackages;
780 # We use the `ghcWithPackages` function from `buildHaskellPackages` if we
781 # want a shell for the sake of cross compiling a package. In the native case
782 # we don't use this at all, and instead put the setupDepends in the main
783 # `ghcWithPackages`. This way we don't have two wrapper scripts called `ghc`
784 # shadowing each other on the PATH.
787 buildHaskellPackages.ghcWithPackages (_: setupHaskellDepends);
789 ghcEnv = withPackages (_:
790 otherBuildInputsHaskell ++
791 propagatedBuildInputs ++
792 lib.optionals (!isCross) setupHaskellDepends);
794 ghcCommandCaps = lib.toUpper ghcCommand';
795 in runCommandCC name {
798 depsBuildBuild = lib.optional isCross ghcEnvForBuild;
800 [ ghcEnv ] ++ optional (allPkgconfigDepends != []) pkg-config ++
801 collectedToolDepends;
803 otherBuildInputsSystem;
804 LANG = "en_US.UTF-8";
805 LOCALE_ARCHIVE = lib.optionalString (stdenv.hostPlatform.libc == "glibc") "${buildPackages.glibcLocales}/lib/locale/locale-archive";
806 "NIX_${ghcCommandCaps}" = "${ghcEnv}/bin/${ghcCommand}";
807 "NIX_${ghcCommandCaps}PKG" = "${ghcEnv}/bin/${ghcCommand}-pkg";
808 # TODO: is this still valid?
809 "NIX_${ghcCommandCaps}_DOCDIR" = "${ghcEnv}/share/doc/ghc/html";
810 "NIX_${ghcCommandCaps}_LIBDIR" = if ghc.isHaLVM or false
811 then "${ghcEnv}/lib/HaLVM-${ghc.version}"
812 else "${ghcEnv}/${ghcLibdir}";
813 } "echo $nativeBuildInputs $buildInputs > $out";
819 meta = { inherit homepage license platforms; }
820 // optionalAttrs (args ? broken) { inherit broken; }
821 // optionalAttrs (args ? description) { inherit description; }
822 // optionalAttrs (args ? maintainers) { inherit maintainers; }
823 // optionalAttrs (args ? hydraPlatforms) { inherit hydraPlatforms; }
824 // optionalAttrs (args ? badPlatforms) { inherit badPlatforms; }
825 // optionalAttrs (args ? changelog) { inherit changelog; }
826 // optionalAttrs (args ? mainProgram) { inherit mainProgram; }
830 // optionalAttrs (args ? sourceRoot) { inherit sourceRoot; }
831 // optionalAttrs (args ? setSourceRoot) { inherit setSourceRoot; }
832 // optionalAttrs (args ? preCompileBuildDriver) { inherit preCompileBuildDriver; }
833 // optionalAttrs (args ? postCompileBuildDriver) { inherit postCompileBuildDriver; }
834 // optionalAttrs (args ? preUnpack) { inherit preUnpack; }
835 // optionalAttrs (args ? postUnpack) { inherit postUnpack; }
836 // optionalAttrs (args ? patches) { inherit patches; }
837 // optionalAttrs (args ? patchPhase) { inherit patchPhase; }
838 // optionalAttrs (args ? preConfigure) { inherit preConfigure; }
839 // optionalAttrs (args ? postConfigure) { inherit postConfigure; }
840 // optionalAttrs (args ? preBuild) { inherit preBuild; }
841 // optionalAttrs (args ? postBuild) { inherit postBuild; }
842 // optionalAttrs (args ? doBenchmark) { inherit doBenchmark; }
843 // optionalAttrs (args ? checkPhase) { inherit checkPhase; }
844 // optionalAttrs (args ? preCheck) { inherit preCheck; }
845 // optionalAttrs (args ? postCheck) { inherit postCheck; }
846 // optionalAttrs (args ? preHaddock) { inherit preHaddock; }
847 // optionalAttrs (args ? postHaddock) { inherit postHaddock; }
848 // optionalAttrs (args ? preInstall) { inherit preInstall; }
849 // optionalAttrs (args ? installPhase) { inherit installPhase; }
850 // optionalAttrs (args ? postInstall) { inherit postInstall; }
851 // optionalAttrs (args ? preFixup) { inherit preFixup; }
852 // optionalAttrs (args ? postFixup) { inherit postFixup; }
853 // optionalAttrs (args ? dontStrip) { inherit dontStrip; }
854 // optionalAttrs (postPhases != []) { inherit postPhases; }
855 // optionalAttrs (stdenv.buildPlatform.libc == "glibc"){ LOCALE_ARCHIVE = "${glibcLocales}/lib/locale/locale-archive"; }
856 // optionalAttrs (disallowedRequisites != [] || disallowGhcReference) {
857 disallowedRequisites =
860 if disallowGhcReference
866 # Implicit pointer to integer conversions are errors by default since clang 15.
867 # Works around https://gitlab.haskell.org/ghc/ghc/-/issues/23456.
868 // optionalAttrs (stdenv.hasCC && stdenv.cc.isClang) {
869 NIX_CFLAGS_COMPILE = "-Wno-error=int-conversion";