1{ pkgs, stdenv, buildPackages, ghc, lib, gobject-introspection ? null, haskellLib, makeConfigFiles, haddockBuilder, ghcForComponent, hsPkgs, compiler, runCommand, libffi, gmp, zlib, ncurses, numactl, nodejs }@defaults:
7, name # This is the package name
16, preUnpack ? component.preUnpack, postUnpack ? component.postUnpack
17, configureFlags ? component.configureFlags
18, preConfigure ? component.preConfigure, postConfigure ? component.postConfigure
19, setupBuildFlags ? component.setupBuildFlags
20, preBuild ? component.preBuild , postBuild ? component.postBuild
21, preCheck ? component.preCheck , postCheck ? component.postCheck
22, setupInstallFlags ? component.setupInstallFlags
23, preInstall ? component.preInstall , postInstall ? component.postInstall
24, preHaddock ? component.preHaddock , postHaddock ? component.postHaddock
26, configureAllComponents ? component.configureAllComponents ||
27 # When set, configure all the components in the package
28 # (not just the one we are building).
29 # Enable for tests in packages that use cabal-doctest.
30 ( haskellLib.isTest componentId &&
31 lib.any (x: x.identifier.name or "" == "cabal-doctest") package.setup-depends
33, allComponent # Used when `configureAllComponents` is set to get a suitable configuration.
35, build-tools ? component.build-tools
36, pkgconfig ? component.pkgconfig
37, platforms ? component.platforms
38, frameworks ? component.frameworks
40, dontPatchELF ? component.dontPatchELF
41, dontStrip ? component.dontStrip
42, hardeningDisable ? component.hardeningDisable
44, enableStatic ? component.enableStatic
45, enableShared ? ghc.enableShared && component.enableShared && !haskellLib.isCrossHost
46 # on x86 we'll use shared libraries, even with musl m(
47 # ghc's internal linker seems to be broken on x86.
48 && !(stdenv.hostPlatform.isMusl && !stdenv.hostPlatform.isx86)
49, enableDeadCodeElimination ? component.enableDeadCodeElimination
50, writeHieFiles ? component.writeHieFiles
52, ghcOptions ? component.ghcOptions
54# Options for Haddock generation
55, doHaddock ? component.doHaddock # Enable haddock and hoogle generation
56, doHoogle ? component.doHoogle # Also build a hoogle index
57, hyperlinkSource ? component.doHyperlinkSource # Link documentation to the source code
58, quickjump ? component.doQuickjump # Generate an index for interactive documentation navigation
59, keepSource ? component.keepSource || configureAllComponents # Build from `source` output in the store then delete `dist`
60, setupHaddockFlags ? component.setupHaddockFlags
63, enableLibraryProfiling ? component.enableLibraryProfiling
64, enableExecutableProfiling ? component.enableExecutableProfiling
65, profilingDetail ? component.profilingDetail
68, doCoverage ? component.doCoverage
71, enableSeparateDataOutput ? component.enableSeparateDataOutput
73# Prelinked ghci libraries; will make iserv faster; especially for static builds.
74, enableLibraryForGhci ? true
77, enableDebugRTS ? false
80# This will only work with a custom TSan way enabled custom compiler
81, enableTSanRTS ? false
84, useLLVM ? ghc.useLLVM
90 if configureAllComponents
94 # Ignore attempts to include DWARF info when it is not possible
95 enableDWARF = drvArgs.enableDWARF or false
96 && stdenv.hostPlatform.isLinux
97 && !haskellLib.isCrossHost
98 && !stdenv.hostPlatform.isMusl
99 && builtins.compareVersions defaults.ghc.version "8.10.2" >= 0;
101 ghc = if enableDWARF then defaults.ghc.dwarf else defaults.ghc;
102 setup = if enableDWARF then drvArgs.setup.dwarf else drvArgs.setup;
104 # TODO fix cabal wildcard support so hpack wildcards can be mapped to cabal wildcards
105 canCleanSource = !(cabal-generator == "hpack" && !(package.cleanHpack or false));
106 # In order to support relative references to other packages we need to use
107 # the `origSrc` diretory as the root `src` for the derivation.
108 # We use `rootAndSubDir` here to split the cleaned source into a `cleanSrc.root`
109 # path (that respects the filtering) and a `cleanSrc.subDir` that
110 # is the sub directory in that root path that contains the package.
111 # `cleanSrc.subDir` is used in `prePatch` and `lib/cover.nix`.
112 cleanSrc = haskellLib.rootAndSubDir (if canCleanSource
113 then haskellLib.cleanCabalComponent package componentForSetup "${componentId.ctype}-${componentId.cname}" src
115 # We can clean out the siblings though to at least avoid changes to other packages
116 # from triggering a rebuild of this one.
117 # Passing `subDir` but not `includeSiblings = true;` will exclude anything not
119 if src ? origSrc && src ? filter && src.origSubDir or "" != ""
120 then haskellLib.cleanSourceWith {
121 name = src.name or "source";
123 subDir = lib.removePrefix "/" src.origSubDir;
124 inherit (src) filter;
128 nameOnly = "${package.identifier.name}-${componentId.ctype}-${componentId.cname}";
130 fullName = "${nameOnly}-${package.identifier.version}";
132 needsProfiling = enableExecutableProfiling || enableLibraryProfiling;
134 configFiles = makeConfigFiles {
135 component = componentForSetup;
136 inherit (package) identifier;
137 inherit fullName flags needsProfiling enableDWARF;
140 enableFeature = enable: feature:
141 (if enable then "--enable-" else "--disable-") + feature;
143 disableFeature = disable: enableFeature (!disable);
145 finalConfigureFlags = lib.concatStringsSep " " (
148 # We don't specify this in 'commonConfigureFlags', as these are also
149 # used by haddock-builder.nix. If we do specify these options in
150 # commonConfigureFlags, then the haddock-builder will fail, because it
151 # sets its own outputs which *don't* include $hie
152 lib.optionals writeHieFiles [
153 "--ghc-option=-fwrite-ide-info" "--ghc-option=-hiedir$hie"
156 # If configureAllComponents is set we should not specify the component
157 # and Setup will attempt to configure them all.
158 if configureAllComponents
159 then ["--enable-tests" "--enable-benchmarks"]
160 else ["${haskellLib.componentTarget componentId}"]
161 ) ++ [ "$(cat ${configFiles}/configure-flags)"
162 ] ++ commonConfigureFlags);
164 # From nixpkgs 20.09, the pkg-config exe has a prefix matching the ghc one
165 pkgConfigHasPrefix = builtins.compareVersions lib.version "20.09pre" >= 0;
167 commonConfigureFlags = ([
169 "--with-ghc=${ghc.targetPrefix}ghc"
170 "--with-ghc-pkg=${ghc.targetPrefix}ghc-pkg"
171 "--with-hsc2hs=${ghc.targetPrefix}hsc2hs"
172 ] ++ lib.optional (pkgConfigHasPrefix && pkgconfig != [])
173 "--with-pkg-config=${ghc.targetPrefix}pkg-config"
174 ++ lib.optionals (stdenv.hasCC or (stdenv.cc != null))
176 [ "--with-gcc=${stdenv.cc.targetPrefix}cc"
179 (if stdenv.hostPlatform.isLinux
180 # use gold as the linker on linux to improve link times
182 "--with-ld=${stdenv.cc.bintools.targetPrefix}ld.gold"
183 "--ghc-option=-optl-fuse-ld=gold"
184 "--ld-option=-fuse-ld=gold"
186 "--with-ld=${stdenv.cc.bintools.targetPrefix}ld"
189 "--with-ar=${stdenv.cc.bintools.targetPrefix}ar"
190 "--with-strip=${stdenv.cc.bintools.targetPrefix}strip"
193 (disableFeature dontStrip "executable-stripping")
194 (disableFeature dontStrip "library-stripping")
195 (enableFeature enableLibraryProfiling "library-profiling")
196 (enableFeature enableExecutableProfiling "executable-profiling")
197 (enableFeature enableStatic "static")
198 (enableFeature enableShared "shared")
199 (enableFeature doCoverage "coverage")
200 (enableFeature enableLibraryForGhci "library-for-ghci")
201 ] ++ lib.optionals (stdenv.hostPlatform.isMusl && (haskellLib.isExecutableType componentId)) [
202 # These flags will make sure the resulting executable is statically linked.
203 # If it uses other libraries it may be necessary for to add more
204 # `--ghc-option=-optl=-L` options to the `configurationFlags` of the
206 "--disable-executable-dynamic"
207 "--ghc-option=-optl=-pthread"
208 "--ghc-option=-optl=-static"
209 ] ++ lib.optional enableSeparateDataOutput "--datadir=$data/share/${ghc.name}"
210 ++ lib.optional (enableLibraryProfiling || enableExecutableProfiling) "--profiling-detail=${profilingDetail}"
211 ++ lib.optional stdenv.hostPlatform.isLinux (enableFeature enableDeadCodeElimination "split-sections")
212 ++ lib.optionals haskellLib.isCrossHost (
213 map (arg: "--hsc2hs-option=" + arg) (["--cross-compile"] ++ lib.optionals (stdenv.hostPlatform.isWindows) ["--via-asm"])
214 ++ lib.optional (package.buildType == "Configure") "--configure-option=--host=${stdenv.hostPlatform.config}" )
216 ++ (ghc.extraConfigureFlags or [])
217 ++ lib.optional enableDebugRTS "--ghc-option=-debug"
218 ++ lib.optional enableTSanRTS "--ghc-option=-tsan"
219 ++ lib.optional enableDWARF "--ghc-option=-g3"
220 ++ lib.optionals useLLVM [
221 "--ghc-option=-fPIC" "--gcc-option=-fPIC"
223 ++ map (o: ''--ghc${lib.optionalString (stdenv.hostPlatform.isGhcjs) "js"}-options="${o}"'') ghcOptions
226 executableToolDepends =
227 (lib.concatMap (c: if c.isHaskell or false
228 then builtins.attrValues (c.components.exes or {})
229 else [c]) build-tools) ++
230 lib.optional (pkgconfig != []) buildPackages.pkgconfig;
232 # Unfortunately, we need to wrap ghc commands for cabal builds to
233 # work in the nix-shell. See ../doc/removing-with-package-wrapper.md.
234 shellWrappers = ghcForComponent {
235 componentName = fullName;
236 inherit configFiles enableDWARF;
239 # In order to let shell hooks make package-specific things like Hoogle databases
240 shellHookApplied = if builtins.isString shellHook then shellHook else
241 if builtins.isFunction shellHook then shellHook { inherit package shellWrappers; }
242 else abort "shellHook should be a string or a function";
244 exeExt = if stdenv.hostPlatform.isGhcjs then ".jsexe/all.js" else
245 stdenv.hostPlatform.extensions.executable;
246 exeName = componentId.cname + exeExt;
247 testExecutable = "dist/build/${componentId.cname}/${exeName}";
249 # Attributes that are common to both the build and haddock derivations
253 LANG = "en_US.UTF-8"; # GHC needs the locale configured during the Haddock phase.
254 LC_ALL = "en_US.UTF-8";
256 enableParallelBuilding = true;
258 SETUP_HS = setup + /bin/Setup;
261 # If the package is in a sub directory `cd` there first.
262 # In some cases the `cleanSrc.subDir` will be empty and the `.cabal`
263 # file will be in the root of `src` (`cleanSrc.root`). This
265 # * the .cabal file is in the projects `src.origSrc or src`
266 # * the package src was overridden with a value that does not
267 # include an `origSubDir`
268 (lib.optionalString (cleanSrc.subDir != "") ''
269 cd ${lib.removePrefix "/" cleanSrc.subDir}
272 (if cabalFile != null
273 then ''cat ${cabalFile} > ${package.identifier.name}.cabal''
275 # When building hpack package we use the internal nix-tools
276 # (compiled with a fixed GHC version)
277 lib.optionalString (cabal-generator == "hpack") ''
278 ${buildPackages.haskell-nix.internal-nix-tools}/bin/hpack
282 # patches can (if they like) depend on the version and revision of the package.
283 // lib.optionalAttrs (patches != []) {
285 if builtins.isFunction p
286 then p { inherit (package.identifier) version; inherit revision; }
290 // haskellLib.optionalHooks {
291 # These are hooks are needed to set up the source for building and running haddock
292 inherit preUnpack postUnpack preConfigure postConfigure;
294 // lib.optionalAttrs (stdenv.buildPlatform.libc == "glibc") {
295 LOCALE_ARCHIVE = "${buildPackages.glibcLocales}/lib/locale/locale-archive";
298 haddock = haddockBuilder {
299 inherit componentId component package flags commonConfigureFlags
300 commonAttrs revision doHaddock
301 doHoogle hyperlinkSource quickjump setupHaddockFlags
302 needsProfiling configFiles preHaddock postHaddock pkgconfig;
307 drv = stdenv.mkDerivation (commonAttrs // {
309 inherit (package.identifier) version;
312 doCrossCheck = false;
314 inherit dontPatchELF dontStrip;
317 inherit (package) identifier;
319 srcSubDir = cleanSrc.subDir;
320 srcSubDirPath = cleanSrc.root + cleanSrc.subDir;
321 inherit configFiles executableToolDepends exeName enableDWARF;
322 exePath = drv + "/bin/${exeName}";
324 profiled = self (drvArgs // { enableLibraryProfiling = true; });
325 dwarf = self (drvArgs // { enableDWARF = true; });
326 } // lib.optionalAttrs (haskellLib.isLibrary componentId) ({
328 inherit (haddock) haddockDir; # This is null if `doHaddock = false`
329 } // lib.optionalAttrs (haddock ? doc) {
330 # `doHaddock = false` turns the doc of haddock output off
331 inherit (haddock) doc;
336 homepage = package.homepage or "";
337 description = package.synopsis or "";
338 license = haskellLib.cabalToNixpkgsLicense package.license;
339 platforms = if platforms == null then lib.platforms.all else platforms;
342 propagatedBuildInputs =
343 frameworks # Frameworks will be needed at link time
344 # Not sure why pkgconfig needs to be propagatedBuildInputs but
345 # for gi-gtk-hs it seems to help.
346 ++ builtins.concatLists pkgconfig;
348 buildInputs = component.libs
349 ++ map haskellLib.dependToLib component.depends;
352 [shellWrappers buildPackages.removeReferencesTo]
353 ++ executableToolDepends;
356 ++ (lib.optional enableSeparateDataOutput "data")
357 ++ (lib.optional keepSource "source")
358 ++ (lib.optional writeHieFiles "hie");
361 # emcc is very slow if it cannot cache stuff in $HOME
362 (lib.optionalString (stdenv.hostPlatform.isGhcjs) ''
363 export HOME=$(mktemp -d)
365 (lib.optionalString (!canCleanSource) ''
366 echo "Cleaning component source not supported, leaving it un-cleaned"
368 (lib.optionalString keepSource ''
372 '') + commonAttrs.prePatch;
376 echo Configure flags:
377 printf "%q " ${finalConfigureFlags}
379 $SETUP_HS configure ${finalConfigureFlags}
380 runHook postConfigure
385 # https://gitlab.haskell.org/ghc/ghc/issues/9221
386 $SETUP_HS build ${haskellLib.componentTarget componentId} -j$(($NIX_BUILD_CORES > 4 ? 4 : $NIX_BUILD_CORES)) ${lib.concatStringsSep " " setupBuildFlags}
390 # Note: Cabal does *not* copy test executables during the `install` phase.
392 # Note 2: if a package contains multiple libs (lib + sublibs) SETUP register will generate a
393 # folder instead of a file for the configuration. Therefore if the result is a folder,
394 # we need to register each and every element of that folder.
396 # Note 3: if a package has no libs SETUP will not generate anything. This can
397 # happen when building the `all` component of a package.
399 target-pkg-and-db = "${ghc.targetPrefix}ghc-pkg -v0 --package-db $out/package.conf.d";
402 $SETUP_HS copy ${lib.concatStringsSep " " (
404 ++ lib.optional configureAllComponents
405 (haskellLib.componentTarget componentId)
407 ${lib.optionalString (haskellLib.isLibrary componentId) ''
408 $SETUP_HS register --gen-pkg-config=${name}.conf
409 ${ghc.targetPrefix}ghc-pkg -v0 init $out/package.conf.d
410 ${ghc.targetPrefix}ghc-pkg -v0 --package-db ${configFiles}/${configFiles.packageCfgDir} -f $out/package.conf.d register ${name}.conf
412 mkdir -p $out/exactDep
413 touch $out/exactDep/configure-flags
414 touch $out/exactDep/cabal.config
417 ${ # The main library in a package has the same name as the package
418 if package.identifier.name == componentId.cname
420 if id=$(${target-pkg-and-db} field ${package.identifier.name} id --simple-output); then
421 echo "--dependency=${package.identifier.name}=$id" >> $out/exactDep/configure-flags
422 echo "package-id $id" >> $out/envDep
424 echo 'ERROR: ${package.identifier.name} id could not be found with ${target-pkg-and-db}'
427 if ver=$(${target-pkg-and-db} field ${package.identifier.name} version --simple-output); then
428 echo "constraint: ${package.identifier.name} == $ver" >> $out/exactDep/cabal.config
429 echo "constraint: ${package.identifier.name} installed" >> $out/exactDep/cabal.config
431 echo 'ERROR: ${package.identifier.name} version could not be found with ${target-pkg-and-db}'
436 # If the component name is not the package name this must be a sublib.
437 # As we build sublibs separately, the following query should be safe.
439 if id=$(${target-pkg-and-db} field "z-${package.identifier.name}-z-*" id --simple-output); then
440 name=$(${target-pkg-and-db} field "z-${package.identifier.name}-z-*" name --simple-output)
441 echo "--dependency=''${name#z-${package.identifier.name}-z-}=$id" >> $out/exactDep/configure-flags
443 # Allow `package-name:sublib-name` to work in `build-depends`
444 # by adding the same `--dependency` again, but with the package
447 echo "--dependency=${package.identifier.name}:''${name#z-${package.identifier.name}-z-}=$id" >> $out/exactDep/configure-flags
449 echo 'ERROR: ${package.identifier.name} id could not be found with ${target-pkg-and-db}'
455 ${(lib.optionalString (haskellLib.isTest componentId || haskellLib.isBenchmark componentId) ''
457 if [ -f ${testExecutable} ]; then
458 mkdir -p $(dirname $out/bin/${exeName})
459 ${if stdenv.hostPlatform.isGhcjs then ''
460 cat <(echo \#!${lib.getBin buildPackages.nodejs}/bin/node) ${testExecutable} >| $out/bin/${exeName}
461 chmod +x $out/bin/${exeName}
463 cp -r ${testExecutable} $(dirname $out/bin/${exeName})
467 # In case `setup copy` did not create this
468 + (lib.optionalString enableSeparateDataOutput "mkdir -p $data")
469 + (lib.optionalString (stdenv.hostPlatform.isWindows && (haskellLib.mayHaveExecutable componentId)) (''
470 echo "Symlink libffi and gmp .dlls ..."
471 for p in ${lib.concatStringsSep " " [ libffi gmp ]}; do
472 find "$p" -iname '*.dll' -exec ln -s {} $out/bin \;
475 # symlink all .dlls into the local directory.
476 # we ask ghc-pkg for *all* dynamic-library-dirs and then iterate over the unique set
477 # to symlink over dlls as needed.
479 echo "Symlink library dependencies..."
480 for libdir in $(${stdenv.hostPlatform.config}-ghc-pkg field "*" dynamic-library-dirs --simple-output|xargs|sed 's/ /\n/g'|sort -u); do
481 if [ -d "$libdir" ]; then
482 find "$libdir" -iname '*.dll' -exec ln -s {} $out/bin \;
486 + (lib.optionalString doCoverage ''
488 cp -r dist/hpc $out/share
489 cp dist/setup-config $out/
494 # Keep just the autogen files and package.conf.inplace package
495 # DB (probably empty unless this is a library component).
496 # We also have to remove any refernces to $out to avoid
497 # circular references.
498 lib.optionalString (configureAllComponents || keepSource) ''
501 if [ -d dist-tmp-dir/build/${componentId.cname}/autogen ]; then
502 mv dist-tmp-dir/build/${componentId.cname}/autogen dist/build/
503 elif [ -d dist-tmp-dir/build/autogen ]; then
504 mv dist-tmp-dir/build/autogen dist/build/
506 mv dist-tmp-dir/package.conf.inplace dist/
507 if [ -d dist/build/autogen ]; then
508 remove-references-to -t $out dist/build/autogen/*
512 ) + (lib.optionalString (keepSource && haskellLib.isLibrary componentId) ''
513 remove-references-to -t $out ${name}.conf
514 '') + (lib.optionalString (haskellLib.isTest componentId) ''
515 echo The test ${package.identifier.name}.components.tests.${componentId.cname} was built. To run the test build ${package.identifier.name}.checks.${componentId.cname}.
518 doInstallCheck = true;
519 installCheckPhase = lib.optionalString (haskellLib.isLibrary componentId) ''
520 if test -n "$(shopt -s nullglob; echo $out/package.conf.d/${name}-*.conf)"; then
521 echo $out/package.conf.d/${name}-*.conf " is present"
523 echo "ERROR: $out/package.conf.d/${name}-*.conf was not created"
529 export PATH="${shellWrappers}/bin:$PATH"
533 // haskellLib.optionalHooks {
534 # These are the hooks that are not needed by haddock (see commonAttrs for the ones that
535 # are shared with the haddock derivation)
538 preInstall postInstall;
540 // lib.optionalAttrs (hardeningDisable != [] || stdenv.hostPlatform.isMusl) {
541 hardeningDisable = hardeningDisable ++ lib.optional stdenv.hostPlatform.isMusl "pie";
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list