at master 27 kB view raw
1# This expression takes a file like `hackage-packages.nix` and constructs 2# a full package set out of that. 3 4{ 5 # package-set used for build tools (all of nixpkgs) 6 buildPackages, 7 8 # A haskell package set for Setup.hs, compiler plugins, and similar 9 # build-time uses. 10 buildHaskellPackages, 11 12 # package-set used for non-haskell dependencies (all of nixpkgs) 13 pkgs, 14 15 # stdenv provides our build and host platforms 16 stdenv, 17 18 # this module provides the list of known licenses and maintainers 19 lib, 20 21 # needed for overrideCabal & packageSourceOverrides 22 haskellLib, 23 24 # hashes for downloading Hackage packages 25 # This is either a directory or a .tar.gz containing the cabal files and 26 # hashes of Hackage as exemplified by this repository: 27 # https://github.com/commercialhaskell/all-cabal-hashes/tree/hackage 28 all-cabal-hashes, 29 30 # compiler to use 31 ghc, 32 33 # A function that takes `{ pkgs, lib, callPackage }` as the first arg and 34 # `self` as second, and returns a set of haskell packages 35 package-set, 36 37 # The final, fully overridden package set usable with the nixpkgs fixpoint 38 # overriding functionality 39 extensible-self, 40}: 41 42# return value: a function from self to the package set 43self: 44 45let 46 inherit (stdenv) buildPlatform hostPlatform; 47 48 inherit (lib) fix' extends makeOverridable; 49 inherit (haskellLib) overrideCabal; 50 51 mkDerivationImpl = pkgs.callPackage ./generic-builder.nix { 52 inherit stdenv; 53 nodejs = buildPackages.nodejs-slim; 54 inherit (self) 55 buildHaskellPackages 56 ghc 57 ghcWithHoogle 58 ghcWithPackages 59 ; 60 inherit (self.buildHaskellPackages) jailbreak-cabal; 61 hscolour = overrideCabal (drv: { 62 isLibrary = false; 63 doHaddock = false; 64 hyperlinkSource = false; # Avoid depending on hscolour for this build. 65 postFixup = "rm -rf $out/lib $out/share $out/nix-support"; 66 }) self.buildHaskellPackages.hscolour; 67 cpphs = 68 overrideCabal 69 (drv: { 70 isLibrary = false; 71 postFixup = "rm -rf $out/lib $out/share $out/nix-support"; 72 }) 73 ( 74 self.cpphs.overrideScope ( 75 self: super: { 76 mkDerivation = 77 drv: 78 super.mkDerivation ( 79 drv 80 // { 81 enableSharedExecutables = false; 82 enableSharedLibraries = false; 83 doHaddock = false; 84 useCpphs = false; 85 } 86 ); 87 } 88 ) 89 ); 90 }; 91 92 mkDerivation = makeOverridable mkDerivationImpl; 93 94 # manualArgs are the arguments that were explicitly passed to `callPackage`, like: 95 # 96 # callPackage foo { bar = null; }; 97 # 98 # here `bar` is a manual argument. 99 callPackageWithScope = 100 scope: fn: manualArgs: 101 let 102 # this code is copied from callPackage in lib/customisation.nix 103 # 104 # we cannot use `callPackage` here because we want to call `makeOverridable` 105 # on `drvScope` (we cannot add `overrideScope` after calling `callPackage` because then it is 106 # lost on `.override`) but determine the auto-args based on `drv` (the problem here 107 # is that nix has no way to "passthrough" args while preserving the reflection 108 # info that callPackage uses to determine the arguments). 109 drv = if lib.isFunction fn then fn else import fn; 110 drvFunctionArgs = lib.functionArgs drv; 111 auto = builtins.intersectAttrs drvFunctionArgs scope; 112 113 # Converts a returned function to a functor attribute set if necessary 114 ensureAttrs = v: if builtins.isFunction v then { __functor = _: v; } else v; 115 116 # this wraps the `drv` function to add `scope` and `overrideScope` to the result. 117 # it's a functor, so that we can pass through `functionArgs` 118 drvScope = { 119 __functor = 120 _: allArgs: 121 ensureAttrs (drv allArgs) 122 // { 123 inherit scope; 124 overrideScope = 125 f: 126 let 127 newScope = mkScope (fix' (extends f scope.__unfix__)); 128 in 129 # note that we have to be careful here: `allArgs` includes the auto-arguments that 130 # weren't manually specified. If we would just pass `allArgs` to the recursive call here, 131 # then we wouldn't look up any packages in the scope in the next interation, because it 132 # appears as if all arguments were already manually passed, so the scope change would do 133 # nothing. 134 callPackageWithScope newScope drv manualArgs; 135 }; 136 # `drvScope` accepts the same arguments as `drv` 137 __functionArgs = drvFunctionArgs; 138 }; 139 in 140 lib.makeOverridable drvScope (auto // manualArgs); 141 142 mkScope = 143 scope: 144 let 145 ps = pkgs.__splicedPackages; 146 scopeSpliced = 147 pkgs.splicePackages { 148 pkgsBuildBuild = scope.buildHaskellPackages.buildHaskellPackages; 149 pkgsBuildHost = scope.buildHaskellPackages; 150 pkgsBuildTarget = { }; 151 pkgsHostHost = { }; 152 pkgsHostTarget = scope; 153 pkgsTargetTarget = { }; 154 } 155 // { 156 # Don't splice these 157 inherit (scope) ghc buildHaskellPackages; 158 }; 159 in 160 ps // ps.xorg // ps.gnome2 // { inherit stdenv; } // scopeSpliced; 161 defaultScope = mkScope self; 162 callPackage = drv: args: callPackageWithScope defaultScope drv args; 163 164 # Use cabal2nix to create a default.nix for the package sources found at 'src'. 165 haskellSrc2nix = 166 { 167 name, 168 src, 169 sha256 ? null, 170 extraCabal2nixOptions ? "", 171 }: 172 let 173 sha256Arg = if sha256 == null then "--sha256=" else ''--sha256="${sha256}"''; 174 in 175 buildPackages.runCommand "cabal2nix-${name}" 176 { 177 nativeBuildInputs = [ buildPackages.cabal2nix-unwrapped ]; 178 preferLocalBuild = true; 179 allowSubstitutes = false; 180 LANG = "en_US.UTF-8"; 181 LOCALE_ARCHIVE = pkgs.lib.optionalString ( 182 buildPlatform.libc == "glibc" 183 ) "${buildPackages.glibcLocales}/lib/locale/locale-archive"; 184 } 185 '' 186 export HOME="$TMP" 187 mkdir -p "$out" 188 cabal2nix --compiler=${self.ghc.haskellCompilerName} --system=${hostPlatform.config} ${sha256Arg} "${src}" ${extraCabal2nixOptions} > "$out/default.nix" 189 ''; 190 191 # Given a package name and version, e.g. name = "async", version = "2.2.4", 192 # gives its cabal file and hashes (JSON file) as discovered from the 193 # all-cabal-hashes value. If that's a directory, it will copy the relevant 194 # files to $out; if it's a tarball, it will extract and move them to $out. 195 all-cabal-hashes-component = 196 name: version: 197 buildPackages.runCommand "all-cabal-hashes-component-${name}-${version}" { } '' 198 mkdir -p $out 199 if [ -d ${all-cabal-hashes} ] 200 then 201 cp ${all-cabal-hashes}/${name}/${version}/${name}.json $out 202 cp ${all-cabal-hashes}/${name}/${version}/${name}.cabal $out 203 else 204 tar --wildcards -xzvf ${all-cabal-hashes} \*/${name}/${version}/${name}.{json,cabal} 205 mv */${name}/${version}/${name}.{json,cabal} $out 206 fi 207 ''; 208 209 hackage2nix = 210 name: version: 211 let 212 component = all-cabal-hashes-component name version; 213 in 214 self.haskellSrc2nix { 215 name = "${name}-${version}"; 216 sha256 = ''$(sed -e 's/.*"SHA256":"//' -e 's/".*$//' "${component}/${name}.json")''; 217 src = "${component}/${name}.cabal"; 218 }; 219 220 # Adds a nix file derived from cabal2nix in the passthru of the derivation it 221 # produces. This is useful to debug callHackage / callCabal2nix by looking at 222 # the content of the nix file pointed by `cabal2nixDeriver`. 223 # However, it does not keep a reference to that file, which may be garbage 224 # collected, which may be an annoyance. 225 callPackageKeepDeriver = 226 src: args: 227 overrideCabal (orig: { 228 passthru = orig.passthru or { } // { 229 # When using callCabal2nix or callHackage, it is often useful 230 # to debug a failure by inspecting the Nix expression 231 # generated by cabal2nix. This can be accessed via this 232 # cabal2nixDeriver field. 233 cabal2nixDeriver = src; 234 }; 235 }) (self.callPackage src args); 236 237in 238package-set { inherit pkgs lib callPackage; } self 239// { 240 241 inherit 242 mkDerivation 243 callPackage 244 haskellSrc2nix 245 hackage2nix 246 buildHaskellPackages 247 ; 248 249 inherit (haskellLib) packageSourceOverrides; 250 251 # callHackage :: Text -> Text -> AttrSet -> HaskellPackage 252 # 253 # e.g., while overriding a package set: 254 # '... foo = self.callHackage "foo" "1.5.3" {}; ...' 255 callHackage = name: version: callPackageKeepDeriver (self.hackage2nix name version); 256 257 # callHackageDirect 258 # :: { pkg :: Text, ver :: Text, sha256 :: Text } 259 # -> AttrSet 260 # -> HaskellPackage 261 # 262 # This function does not depend on all-cabal-hashes and therefore will work 263 # for any version that has been released on hackage as opposed to only 264 # versions released before whatever version of all-cabal-hashes you happen 265 # to be currently using. 266 callHackageDirect = 267 { 268 pkg, 269 ver, 270 sha256, 271 candidate ? false, 272 rev ? { 273 revision = null; 274 sha256 = null; 275 }, 276 }: 277 args: 278 let 279 pkgver = "${pkg}-${ver}"; 280 firstRevision = self.callCabal2nix pkg (pkgs.fetchzip { 281 url = 282 if candidate then 283 "mirror://hackage/${pkgver}/candidate/${pkgver}.tar.gz" 284 else 285 "mirror://hackage/${pkgver}/${pkgver}.tar.gz"; 286 inherit sha256; 287 }) args; 288 in 289 overrideCabal (orig: { 290 revision = rev.revision; 291 editedCabalFile = rev.sha256; 292 }) firstRevision; 293 294 # Creates a Haskell package from a source package by calling cabal2nix on the source. 295 callCabal2nixWithOptions = 296 name: src: opts: args: 297 let 298 extraCabal2nixOptions = if builtins.isString opts then opts else opts.extraCabal2nixOptions or ""; 299 srcModifier = opts.srcModifier or null; 300 defaultFilter = path: type: pkgs.lib.hasSuffix ".cabal" path || baseNameOf path == "package.yaml"; 301 expr = self.haskellSrc2nix { 302 inherit name extraCabal2nixOptions; 303 src = 304 if srcModifier != null then 305 srcModifier src 306 else if pkgs.lib.canCleanSource src then 307 pkgs.lib.cleanSourceWith { 308 inherit src; 309 filter = defaultFilter; 310 } 311 else 312 src; 313 }; 314 in 315 overrideCabal (orig: { 316 inherit src; 317 }) (callPackageKeepDeriver expr args); 318 319 callCabal2nix = 320 name: src: args: 321 self.callCabal2nixWithOptions name src "" args; 322 323 # : { root : Path 324 # , name : Defaulted String 325 # , source-overrides : Defaulted (Either Path VersionNumber) 326 # , overrides : Defaulted (HaskellPackageOverrideSet) 327 # , modifier : Defaulted 328 # , returnShellEnv : Defaulted 329 # , withHoogle : Defaulted 330 # , cabal2nixOptions : Defaulted 331 # } -> NixShellAwareDerivation 332 # 333 # Given a path to a haskell package directory, an optional package name 334 # which defaults to the base name of the path, an optional set of source 335 # overrides as appropriate for the 'packageSourceOverrides' function, an 336 # optional set of arbitrary overrides, and an optional haskell package 337 # modifier, return a derivation appropriate for nix-build or nix-shell to 338 # build that package. 339 # 340 # If 'returnShellEnv' is true this returns a derivation which will give you 341 # an environment suitable for developing the listed packages with an 342 # incremental tool like cabal-install. 343 # 344 # If 'withHoogle' is true (the default if a shell environment is requested) 345 # then 'ghcWithHoogle' is used to generate the derivation (instead of 346 # 'ghcWithPackages'), see the documentation there for more information. 347 # 348 # 'cabal2nixOptions' can contain extra command line arguments to pass to 349 # 'cabal2nix' when generating the package derivation, for example setting 350 # a cabal flag with '--flag=myflag'. 351 developPackage = 352 { 353 root, 354 name ? lib.optionalString (builtins.typeOf root == "path") (builtins.baseNameOf root), 355 source-overrides ? { }, 356 overrides ? self: super: { }, 357 modifier ? drv: drv, 358 returnShellEnv ? pkgs.lib.inNixShell, 359 withHoogle ? returnShellEnv, 360 cabal2nixOptions ? "", 361 }: 362 let 363 drv = 364 (extensible-self.extend ( 365 pkgs.lib.composeExtensions (self.packageSourceOverrides source-overrides) overrides 366 )).callCabal2nixWithOptions 367 name 368 root 369 cabal2nixOptions 370 { }; 371 in 372 if returnShellEnv then (modifier drv).envFunc { inherit withHoogle; } else modifier drv; 373 374 # This can be used to easily create a derivation containing GHC and the specified set of Haskell packages. 375 # 376 # Example: 377 # $ nix-shell -p 'haskellPackages.ghcWithPackages (hpkgs: [ hpkgs.mtl hpkgs.lens ])' 378 # $ ghci # in the nix-shell 379 # Prelude > import Control.Lens 380 # 381 # GHC is setup with a package database with all the specified Haskell packages. 382 # 383 # ghcWithPackages :: (HaskellPkgSet -> [ HaskellPkg ]) -> Derivation 384 ghcWithPackages = buildHaskellPackages.callPackage ./with-packages-wrapper.nix { 385 haskellPackages = self; 386 inherit (self) hoogleWithPackages; 387 }; 388 389 # Put 'hoogle' into the derivation's PATH with a database containing all 390 # the package's dependencies; run 'hoogle server --local' in a shell to 391 # host a search engine for the dependencies. 392 # 393 # Example usage: 394 # $ nix-shell -p 'haskellPackages.hoogleWithPackages (p: [ p.mtl p.lens ])' 395 # [nix-shell] $ hoogle server 396 # 397 # hoogleWithPackages :: (HaskellPkgSet -> [ HaskellPkg ]) -> Derivation 398 # 399 # To reload the Hoogle server automatically on .cabal file changes try 400 # this: 401 # echo *.cabal | entr -r -- nix-shell --run 'hoogle server --local' 402 hoogleWithPackages = self.callPackage ./hoogle.nix { 403 haskellPackages = self; 404 }; 405 hoogleLocal = 406 { 407 packages ? [ ], 408 }: 409 lib.warn "hoogleLocal is deprecated, use hoogleWithPackages instead" ( 410 self.hoogleWithPackages (_: packages) 411 ); 412 # This is like a combination of ghcWithPackages and hoogleWithPackages. 413 # It provides a derivation containing both GHC and Hoogle with an index of 414 # the given Haskell package database. 415 # 416 # Example: 417 # $ nix-shell -p 'haskellPackages.ghcWithHoogle (hpkgs: [ hpkgs.conduit hpkgs.lens ])' 418 # 419 # ghcWithHoogle :: (HaskellPkgSet -> [ HaskellPkg ]) -> Derivation 420 ghcWithHoogle = self.ghcWithPackages.override { 421 withHoogle = true; 422 }; 423 424 # Returns a derivation whose environment contains a GHC with only 425 # the dependencies of packages listed in `packages`, not the 426 # packages themselves. Using nix-shell on this derivation will 427 # give you an environment suitable for developing the listed 428 # packages with an incremental tool like cabal-install. 429 # 430 # In addition to the "packages" arg and "withHoogle" arg, anything that 431 # can be passed into stdenv.mkDerivation can be included in the input attrset 432 # 433 # # default.nix 434 # with import <nixpkgs> {}; 435 # haskellPackages.extend (haskell.lib.compose.packageSourceOverrides { 436 # frontend = ./frontend; 437 # backend = ./backend; 438 # common = ./common; 439 # }) 440 # 441 # # shell.nix 442 # let pkgs = import <nixpkgs> {} in 443 # (import ./.).shellFor { 444 # packages = p: [p.frontend p.backend p.common]; 445 # withHoogle = true; 446 # buildInputs = [ pkgs.python pkgs.cabal-install ]; 447 # } 448 # 449 # -- cabal.project 450 # packages: 451 # frontend/ 452 # backend/ 453 # common/ 454 # 455 # bash$ nix-shell --run "cabal new-build all" 456 # bash$ nix-shell --run "python" 457 shellFor = 458 { 459 # Packages to create this development shell for. These are usually 460 # your local packages. 461 packages, 462 # Whether or not to generate a Hoogle database for all the 463 # dependencies. 464 withHoogle ? false, 465 # Whether or not to include benchmark dependencies of your local 466 # packages. You should set this to true if you have benchmarks defined 467 # in your local packages that you want to be able to run with cabal benchmark 468 doBenchmark ? false, 469 # An optional function that can modify the generic builder arguments 470 # for the fake package that shellFor uses to construct its environment. 471 # 472 # Example: 473 # let 474 # # elided... 475 # haskellPkgs = pkgs.haskell.packages.ghc884.override (hpArgs: { 476 # overrides = pkgs.lib.composeExtensions (hpArgs.overrides or (_: _: { })) ( 477 # _hfinal: hprev: { 478 # mkDerivation = args: hprev.mkDerivation ({ 479 # doCheck = false; 480 # doBenchmark = false; 481 # doHoogle = true; 482 # doHaddock = true; 483 # enableLibraryProfiling = false; 484 # enableExecutableProfiling = false; 485 # } // args); 486 # } 487 # ); 488 # }); 489 # in 490 # haskellPkgs.shellFor { 491 # packages = p: [ p.foo ]; 492 # genericBuilderArgsModifier = args: args // { doCheck = true; doBenchmark = true }; 493 # } 494 # 495 # This will disable tests and benchmarks for everything in "haskellPkgs" 496 # (which will invalidate the binary cache), and then re-enable them 497 # for the "shellFor" environment (ensuring that any test/benchmark 498 # dependencies for "foo" will be available within the nix-shell). 499 genericBuilderArgsModifier ? (args: args), 500 501 # Extra dependencies, in the form of cabal2nix build attributes. 502 # 503 # An example use case is when you have Haskell scripts that use 504 # libraries that don't occur in your packages' dependencies. 505 # 506 # Example: 507 # 508 # extraDependencies = p: { 509 # libraryHaskellDepends = [ p.releaser ]; 510 # }; 511 extraDependencies ? p: { }, 512 ... 513 }@args: 514 let 515 # A list of the packages we want to build a development shell for. 516 # This is a list of Haskell package derivations. 517 selected = packages self; 518 519 # This is a list of attribute sets, where each attribute set 520 # corresponds to the build inputs of one of the packages input to shellFor. 521 # 522 # Each attribute has keys like buildDepends, executableHaskellDepends, 523 # testPkgconfigDepends, etc. The values for the keys of the attribute 524 # set are lists of dependencies. 525 # 526 # Example: 527 # cabalDepsForSelected 528 # => [ 529 # # This may be the attribute set corresponding to the `backend` 530 # # package in the example above. 531 # { buildDepends = [ gcc ... ]; 532 # libraryHaskellDepends = [ lens conduit ... ]; 533 # ... 534 # } 535 # # This may be the attribute set corresponding to the `common` 536 # # package in the example above. 537 # { testHaskellDepends = [ tasty hspec ... ]; 538 # libraryHaskellDepends = [ lens aeson ]; 539 # benchmarkHaskellDepends = [ criterion ... ]; 540 # ... 541 # } 542 # ... 543 # ] 544 cabalDepsForSelected = map (p: p.getCabalDeps) selected; 545 546 # A predicate that takes a derivation as input, and tests whether it is 547 # the same as any of the `selected` packages. 548 # 549 # Returns true if the input derivation is not in the list of `selected` 550 # packages. 551 # 552 # isNotSelected :: Derivation -> Bool 553 # 554 # Example: 555 # 556 # isNotSelected common [ frontend backend common ] 557 # => false 558 # 559 # isNotSelected lens [ frontend backend common ] 560 # => true 561 isNotSelected = input: pkgs.lib.all (p: input.outPath or null != p.outPath) selected; 562 563 # A function that takes a list of list of derivations, filters out all 564 # the `selected` packages from each list, and concats the results. 565 # 566 # zipperCombinedPkgs :: [[Derivation]] -> [Derivation] 567 # 568 # Example: 569 # zipperCombinedPkgs [ [ lens conduit ] [ aeson frontend ] ] 570 # => [ lens conduit aeson ] 571 # 572 # Note: The reason this isn't just the function `pkgs.lib.concat` is 573 # that we need to be careful to remove dependencies that are in the 574 # `selected` packages. 575 # 576 # For instance, in the above example, if `common` is a dependency of 577 # `backend`, then zipperCombinedPkgs needs to be careful to filter out 578 # `common`, because cabal will end up ignoring that built version, 579 # assuming new-style commands. 580 zipperCombinedPkgs = vals: pkgs.lib.concatMap (drvList: pkgs.lib.filter isNotSelected drvList) vals; 581 582 # Zip `cabalDepsForSelected` into a single attribute list, combining 583 # the derivations in all the individual attributes. 584 # 585 # Example: 586 # packageInputs 587 # => # Assuming the value of cabalDepsForSelected is the same as 588 # # the example in cabalDepsForSelected: 589 # { buildDepends = [ gcc ... ]; 590 # libraryHaskellDepends = [ lens conduit aeson ... ]; 591 # testHaskellDepends = [ tasty hspec ... ]; 592 # benchmarkHaskellDepends = [ criterion ... ]; 593 # ... 594 # } 595 # 596 # See the Note in `zipperCombinedPkgs` for what gets filtered out from 597 # each of these dependency lists. 598 packageInputs = pkgs.lib.zipAttrsWith (_name: zipperCombinedPkgs) ( 599 cabalDepsForSelected ++ [ (extraDependencies self) ] 600 ); 601 602 # A attribute set to pass to `haskellPackages.mkDerivation`. 603 # 604 # The important thing to note here is that all the fields from 605 # packageInputs are set correctly. 606 genericBuilderArgs = { 607 pname = if pkgs.lib.length selected == 1 then (pkgs.lib.head selected).name else "packages"; 608 version = "0"; 609 license = null; 610 } 611 // packageInputs 612 // pkgs.lib.optionalAttrs doBenchmark { 613 # `doBenchmark` needs to explicitly be set here because haskellPackages.mkDerivation defaults it to `false`. If the user wants benchmark dependencies included in their development shell, it has to be explicitly enabled here. 614 doBenchmark = true; 615 }; 616 617 # This is a pseudo Haskell package derivation that contains all the 618 # dependencies for the packages in `selected`. 619 # 620 # This is a derivation created with `haskellPackages.mkDerivation`. 621 # 622 # pkgWithCombinedDeps :: HaskellDerivation 623 pkgWithCombinedDeps = self.mkDerivation (genericBuilderArgsModifier genericBuilderArgs); 624 625 # The derivation returned from `envFunc` for `pkgWithCombinedDeps`. 626 # 627 # This is a derivation that can be run with `nix-shell`. It provides a 628 # GHC with a package database with all the dependencies of our 629 # `selected` packages. 630 # 631 # This is a derivation created with `stdenv.mkDerivation` (not 632 # `haskellPackages.mkDerivation`). 633 # 634 # pkgWithCombinedDepsDevDrv :: Derivation 635 pkgWithCombinedDepsDevDrv = pkgWithCombinedDeps.envFunc { inherit withHoogle; }; 636 637 mkDerivationArgs = builtins.removeAttrs args [ 638 "genericBuilderArgsModifier" 639 "packages" 640 "withHoogle" 641 "doBenchmark" 642 "extraDependencies" 643 ]; 644 645 in 646 pkgWithCombinedDepsDevDrv.overrideAttrs ( 647 old: 648 mkDerivationArgs 649 // { 650 nativeBuildInputs = old.nativeBuildInputs ++ mkDerivationArgs.nativeBuildInputs or [ ]; 651 buildInputs = old.buildInputs ++ mkDerivationArgs.buildInputs or [ ]; 652 } 653 ); 654 655 ghc = ghc // { 656 withPackages = self.ghcWithPackages; 657 withHoogle = self.ghcWithHoogle; 658 }; 659 660 /* 661 Run `cabal sdist` on a source. 662 663 Unlike `haskell.lib.sdistTarball`, this does not require any dependencies 664 to be present, as it uses `cabal-install` instead of building `Setup.hs`. 665 This makes `cabalSdist` faster than `sdistTarball`. 666 */ 667 cabalSdist = 668 { 669 src, 670 name ? if src ? name then "${src.name}-sdist.tar.gz" else "source.tar.gz", 671 }: 672 pkgs.runCommandLocal name 673 { 674 inherit src; 675 nativeBuildInputs = [ 676 buildHaskellPackages.cabal-install 677 678 # TODO after https://github.com/haskell/cabal/issues/8352 679 # remove ghc 680 self.ghc 681 ]; 682 dontUnpack = false; 683 } 684 '' 685 unpackPhase 686 cd "''${sourceRoot:-.}" 687 patchPhase 688 mkdir out 689 HOME=$PWD cabal sdist --output-directory out 690 mv out/*.tar.gz $out 691 ''; 692 693 /* 694 Like `haskell.lib.buildFromSdist`, but using `cabal sdist` instead of 695 building `./Setup`. 696 697 Unlike `haskell.lib.buildFromSdist`, this does not require any dependencies 698 to be present. This makes `buildFromCabalSdist` faster than `haskell.lib.buildFromSdist`. 699 */ 700 buildFromCabalSdist = 701 pkg: 702 haskellLib.overrideSrc { 703 src = self.cabalSdist { inherit (pkg) src; }; 704 version = pkg.version; 705 } pkg; 706 707 /* 708 Modify a Haskell package to add shell completion scripts for the 709 given executables produced by it. These completion scripts will be 710 picked up automatically if the resulting derivation is installed, 711 e.g. by `nix-env -i`. 712 713 This depends on the `--*-completion` flag `optparse-applicative` provides 714 automatically. Since we need to invoke installed executables, completions 715 are not generated if we are cross-compiling. 716 717 commands: names of the executables built by the derivation 718 pkg: Haskell package that builds the executables 719 720 Example: 721 generateOptparseApplicativeCompletions [ "exec1" "exec2" ] pkg 722 723 Type: [str] -> drv -> drv 724 */ 725 generateOptparseApplicativeCompletions = self.callPackage ( 726 { stdenv }: 727 728 commands: pkg: 729 730 if stdenv.buildPlatform.canExecute stdenv.hostPlatform then 731 lib.foldr haskellLib.__generateOptparseApplicativeCompletion pkg commands 732 else 733 pkg 734 ) { }; 735 736 /* 737 Modify given Haskell package to force GHC to employ the LLVM 738 codegen backend when compiling. Useful when working around bugs 739 in a native codegen backend GHC defaults to. 740 741 Example: 742 forceLlvmCodegenBackend tls 743 744 Type: drv -> drv 745 */ 746 forceLlvmCodegenBackend = overrideCabal (drv: { 747 configureFlags = drv.configureFlags or [ ] ++ [ "--ghc-option=-fllvm" ]; 748 buildTools = 749 drv.buildTools or [ ] 750 ++ [ self.ghc.llvmPackages.llvm ] 751 # GHC >= 9.10 needs LLVM specific assembler, i.e. clang 752 # On Darwin clang is always required 753 ++ lib.optionals (lib.versionAtLeast self.ghc.version "9.10" || stdenv.hostPlatform.isDarwin) [ 754 self.ghc.llvmPackages.clang 755 ]; 756 }); 757}