From d545ef3fa11198f12e525b641aeb33887694f97f Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Sat, 23 Dec 2017 11:44:18 -0500 Subject: [PATCH] hslib: Function to extract the haskell build inputs of a package. This works by extracting out some logic from generic-builder.nix to make it possible to get at the relevant information by overriding mkDerivation for the haskell package. --- .../haskell-modules/generic-builder.nix | 45 +++-------- pkgs/development/haskell-modules/lib.nix | 80 +++++++++++++++++++ .../haskell-modules/make-package-set.nix | 2 +- 3 files changed, 94 insertions(+), 33 deletions(-) diff --git a/pkgs/development/haskell-modules/generic-builder.nix b/pkgs/development/haskell-modules/generic-builder.nix index 3182b4846c0..16d5c7ba7c5 100644 --- a/pkgs/development/haskell-modules/generic-builder.nix +++ b/pkgs/development/haskell-modules/generic-builder.nix @@ -1,31 +1,27 @@ { stdenv, fetchurl, ghc, pkgconfig, glibcLocales, coreutils, gnugrep, gnused -, jailbreak-cabal, hscolour, cpphs, nodejs, lib, removeReferencesTo +, jailbreak-cabal, hscolour, cpphs, nodejs, lib, removeReferencesTo, haskellLib }: -let isCross = (ghc.cross or null) != null; in +let inherit (haskellLib.ghcInfo ghc) isCross isGhcjs nativeGhc; in { pname -, dontStrip ? (ghc.isGhcjs or false) +, dontStrip ? isGhcjs , version, revision ? null , sha256 ? null , src ? fetchurl { url = "mirror://hackage/${pname}-${version}.tar.gz"; inherit sha256; } -, buildDepends ? [], setupHaskellDepends ? [], libraryHaskellDepends ? [], executableHaskellDepends ? [] , buildTarget ? "" -, buildTools ? [], libraryToolDepends ? [], executableToolDepends ? [], testToolDepends ? [], benchmarkToolDepends ? [] +, buildTools ? [], libraryToolDepends ? [], executableToolDepends ? [] , configureFlags ? [] , description ? "" -, doCheck ? !isCross && (stdenv.lib.versionOlder "7.4" ghc.version) -, doBenchmark ? false , doHoogle ? true , editedCabalFile ? null , enableLibraryProfiling ? false , enableExecutableProfiling ? false # TODO enable shared libs for cross-compiling -, enableSharedExecutables ? !isCross && (((ghc.isGhcjs or false) || stdenv.lib.versionOlder "7.7" ghc.version)) -, enableSharedLibraries ? !isCross && (((ghc.isGhcjs or false) || stdenv.lib.versionOlder "7.7" ghc.version)) +, enableSharedExecutables ? !isCross && ((isGhcjs || stdenv.lib.versionOlder "7.7" ghc.version)) +, enableSharedLibraries ? !isCross && ((isGhcjs || stdenv.lib.versionOlder "7.7" ghc.version)) , enableSplitObjs ? null # OBSOLETE, use enableDeadCodeElimination , enableDeadCodeElimination ? (!stdenv.isDarwin) # TODO: use -dead_strip for darwin , enableStaticLibraries ? true -, extraLibraries ? [], librarySystemDepends ? [], executableSystemDepends ? [] , homepage ? "http://hackage.haskell.org/package/${pname}" , platforms ? ghc.meta.platforms , hydraPlatforms ? platforms @@ -37,9 +33,6 @@ let isCross = (ghc.cross or null) != null; in , doCoverage ? false , doHaddock ? !(ghc.isHaLVM or false) , passthru ? {} -, pkgconfigDepends ? [], libraryPkgconfigDepends ? [], executablePkgconfigDepends ? [], testPkgconfigDepends ? [], benchmarkPkgconfigDepends ? [] -, testDepends ? [], testHaskellDepends ? [], testSystemDepends ? [] -, benchmarkDepends ? [], benchmarkHaskellDepends ? [], benchmarkSystemDepends ? [] , testTarget ? "" , broken ? false , preCompileBuildDriver ? "", postCompileBuildDriver ? "" @@ -56,6 +49,7 @@ let isCross = (ghc.cross or null) != null; in , hardeningDisable ? lib.optional (ghc.isHaLVM or false) "all" , enableSeparateDataOutput ? false , enableSeparateDocOutput ? doHaddock +, ... # For other arguments, see the 'mkDerivation helpers' section of lib.nix } @ args: assert editedCabalFile != null -> revision != null; @@ -63,18 +57,17 @@ assert editedCabalFile != null -> revision != null; assert enableSplitObjs == null; let + inherit (haskellLib.controlPhases ghc args) doCheck doBenchmark; inherit (stdenv.lib) optional optionals optionalString versionOlder versionAtLeast concatStringsSep enableFeature optionalAttrs toUpper filter makeLibraryPath; - isGhcjs = ghc.isGhcjs or false; isHaLVM = ghc.isHaLVM or false; packageDbFlag = if isGhcjs || isHaLVM || versionOlder "7.6" ghc.version then "package-db" else "package-conf"; - nativeGhc = if isCross || isGhcjs then ghc.bootPkgs.ghc else ghc; nativePackageDbFlag = if versionOlder "7.6" nativeGhc.version then "package-db" else "package-conf"; @@ -146,25 +139,11 @@ let (optionalString (versionOlder "7.10" ghc.version && !isHaLVM) "-threaded") ]; - isHaskellPkg = x: (x ? pname) && (x ? version) && (x ? env); - isSystemPkg = x: !isHaskellPkg x; - - allPkgconfigDepends = pkgconfigDepends ++ libraryPkgconfigDepends ++ executablePkgconfigDepends ++ - optionals doCheck testPkgconfigDepends ++ optionals doBenchmark benchmarkPkgconfigDepends; + inherit (haskellLib.extractBuildInputs ghc (args // { inherit doCheck doBenchmark; })) + allPkgconfigDepends propagatedBuildInputs otherBuildInputs haskellBuildInputs systemBuildInputs; nativeBuildInputs = optional (allPkgconfigDepends != []) pkgconfig ++ buildTools ++ libraryToolDepends ++ executableToolDepends ++ [ removeReferencesTo ]; - propagatedBuildInputs = buildDepends ++ libraryHaskellDepends ++ executableHaskellDepends; - otherBuildInputs = setupHaskellDepends ++ extraLibraries ++ librarySystemDepends ++ executableSystemDepends ++ - optionals (allPkgconfigDepends != []) allPkgconfigDepends ++ - optionals doCheck (testDepends ++ testHaskellDepends ++ testSystemDepends ++ testToolDepends) ++ - # ghcjs's hsc2hs calls out to the native hsc2hs - optional isGhcjs nativeGhc ++ - optionals doBenchmark (benchmarkDepends ++ benchmarkHaskellDepends ++ benchmarkSystemDepends ++ benchmarkToolDepends); - allBuildInputs = propagatedBuildInputs ++ otherBuildInputs; - - haskellBuildInputs = stdenv.lib.filter isHaskellPkg allBuildInputs; - systemBuildInputs = stdenv.lib.filter isSystemPkg allBuildInputs; ghcEnv = ghc.withPackages (p: haskellBuildInputs); @@ -348,7 +327,9 @@ stdenv.mkDerivation ({ passthru = passthru // { - inherit pname version; + inherit pname version ghc; + + isHaskellPkg = true; isHaskellLibrary = hasActiveLibrary; diff --git a/pkgs/development/haskell-modules/lib.nix b/pkgs/development/haskell-modules/lib.nix index 96520dce2b2..74ad46b6564 100644 --- a/pkgs/development/haskell-modules/lib.nix +++ b/pkgs/development/haskell-modules/lib.nix @@ -147,4 +147,84 @@ rec { overrideSrc = drv: { src, version ? drv.version }: overrideCabal drv (_: { inherit src version; editedCabalFile = null; }); + # Extract the haskell build inputs of a haskell package. + # This is useful to build environments for developing on that + # package. + getHaskellBuildInputs = p: + (p.override { mkDerivation = extractBuildInputs p.ghc; + }).haskellBuildInputs; + + ghcInfo = ghc: + rec { isCross = (ghc.cross or null) != null; + isGhcjs = ghc.isGhcjs or false; + nativeGhc = if isCross || isGhcjs + then ghc.bootPkgs.ghc + else ghc; + }; + + ### mkDerivation helpers + # These allow external users of a haskell package to extract + # information about how it is built in the same way that the + # generic haskell builder does, by reusing the same functions. + # Each function here has the same interface as mkDerivation and thus + # can be called for a given package simply by overriding the + # mkDerivation argument it used. See getHaskellBuildInputs above for + # an example of this. + + # Some information about which phases should be run. + controlPhases = ghc: let inherit (ghcInfo ghc) isCross; in + { doCheck ? !isCross && (lib.versionOlder "7.4" ghc.version) + , doBenchmark ? false + , ... + }: { inherit doCheck doBenchmark; }; + + # Divide the build inputs of the package into useful sets. + extractBuildInputs = ghc: + { setupHaskellDepends ? [], extraLibraries ? [] + , librarySystemDepends ? [], executableSystemDepends ? [] + , pkgconfigDepends ? [], libraryPkgconfigDepends ? [] + , executablePkgconfigDepends ? [], testPkgconfigDepends ? [] + , benchmarkPkgconfigDepends ? [], testDepends ? [] + , testHaskellDepends ? [], testSystemDepends ? [] + , testToolDepends ? [], benchmarkDepends ? [] + , benchmarkHaskellDepends ? [], benchmarkSystemDepends ? [] + , benchmarkToolDepends ? [], buildDepends ? [] + , libraryHaskellDepends ? [], executableHaskellDepends ? [] + , ... + }@args: + let inherit (ghcInfo ghc) isGhcjs nativeGhc; + inherit (controlPhases ghc args) doCheck doBenchmark; + isHaskellPkg = x: x.isHaskellPkg or false; + allPkgconfigDepends = + pkgconfigDepends ++ libraryPkgconfigDepends ++ + executablePkgconfigDepends ++ + lib.optionals doCheck testPkgconfigDepends ++ + lib.optionals doBenchmark benchmarkPkgconfigDepends; + otherBuildInputs = + setupHaskellDepends ++ extraLibraries ++ + librarySystemDepends ++ executableSystemDepends ++ + allPkgconfigDepends ++ + lib.optionals doCheck ( testDepends ++ testHaskellDepends ++ + testSystemDepends ++ testToolDepends + ) ++ + # ghcjs's hsc2hs calls out to the native hsc2hs + lib.optional isGhcjs nativeGhc ++ + lib.optionals doBenchmark ( benchmarkDepends ++ + benchmarkHaskellDepends ++ + benchmarkSystemDepends ++ + benchmarkToolDepends + ); + propagatedBuildInputs = + buildDepends ++ libraryHaskellDepends ++ + executableHaskellDepends; + allBuildInputs = propagatedBuildInputs ++ otherBuildInputs; + isHaskellPartition = + lib.partition isHaskellPkg allBuildInputs; + in + { haskellBuildInputs = isHaskellPartition.right; + systemBuildInputs = isHaskellPartition.wrong; + inherit propagatedBuildInputs otherBuildInputs + allPkgconfigDepends; + }; + } diff --git a/pkgs/development/haskell-modules/make-package-set.nix b/pkgs/development/haskell-modules/make-package-set.nix index 7ac0ef509f4..dda16d22c9b 100644 --- a/pkgs/development/haskell-modules/make-package-set.nix +++ b/pkgs/development/haskell-modules/make-package-set.nix @@ -33,7 +33,7 @@ let inherit (haskellLib) overrideCabal; mkDerivationImpl = pkgs.callPackage ./generic-builder.nix { - inherit stdenv; + inherit stdenv haskellLib; inherit (pkgs) fetchurl pkgconfig glibcLocales coreutils gnugrep gnused; nodejs = pkgs.nodejs-slim; jailbreak-cabal = if (self.ghc.cross or null) != null