nixpkgs/pkgs/development/haskell-modules/generic-builder.nix
Peter Simons afca6145d4 haskell-generic-builder: simplify "package.conf.d" management
The builder creates a temporary package.conf.d database in $TMP that
contains everything required to build the current package (i.e. the
transitive closure of the package's propagated build inputs). These
files are no longer installed, however, we just install the package.conf
file for the package we're actually building. This means that
package.conf.d directory in $out won't have collisions anymore, which
simplifies the with-packages-wrapper.nix a bit.
2015-01-10 15:55:47 +01:00

224 lines
8.1 KiB
Nix

{ stdenv, fetchurl, ghc, pkgconfig, glibcLocales, coreutils, gnugrep, gnused
, jailbreak-cabal, hscolour
}:
{ pname
, version
, sha256 ? null
, src ? fetchurl { url = "mirror://hackage/${pname}-${version}.tar.gz"; inherit sha256; }
, buildDepends ? []
, buildTools ? []
, configureFlags ? []
, description ? ""
, doCheck ? stdenv.lib.versionOlder "7.4" ghc.version
, doHoogle ? true
, editedCabalFile ? null
, enableLibraryProfiling ? false
, enableSharedExecutables ? stdenv.lib.versionOlder "7.7" ghc.version
, enableSharedLibraries ? stdenv.lib.versionOlder "7.7" ghc.version
, enableSplitObjs ? !stdenv.isDarwin # http://hackage.haskell.org/trac/ghc/ticket/4013
, enableStaticLibraries ? true
, extraLibraries ? []
, homepage ? "http://hackage.haskell.org/package/${pname}"
, hydraPlatforms ? ghc.meta.hydraPlatforms or ghc.meta.platforms
, hyperlinkSource ? true
, isExecutable ? false, isLibrary ? !isExecutable
, jailbreak ? false
, license
, maintainers ? []
, noHaddock ? false
, passthru ? {}
, pkgconfigDepends ? []
, platforms ? ghc.meta.platforms
, testDepends ? []
, testTarget ? ""
, broken ? false
, patches ? [], patchPhase ? "", prePatch ? "", postPatch ? ""
, preConfigure ? "", postConfigure ? ""
, preBuild ? "", postBuild ? ""
, preInstall ? "", postInstall ? ""
, checkPhase ? "", preCheck ? "", postCheck ? ""
, preFixup ? "", postFixup ? ""
}:
assert pkgconfigDepends != [] -> pkgconfig != null;
let
inherit (stdenv.lib) optional optionals optionalString versionOlder
concatStringsSep enableFeature optionalAttrs;
defaultSetupHs = builtins.toFile "Setup.hs" ''
import Distribution.Simple
main = defaultMain
'';
defaultConfigureFlags = [
(enableFeature enableSplitObjs "split-objs")
(enableFeature enableLibraryProfiling "library-profiling")
(enableFeature enableSharedLibraries "shared")
(optionalString (versionOlder "7" ghc.version) (enableFeature enableStaticLibraries "library-vanilla"))
(optionalString (versionOlder "7.4" ghc.version) (enableFeature enableSharedExecutables "executable-dynamic"))
(optionalString (versionOlder "7" ghc.version) (enableFeature doCheck "tests"))
];
hasActiveLibrary = isLibrary && (enableStaticLibraries || enableSharedLibraries);
newCabalFile = fetchurl {
url = "http://hackage.haskell.org/package/${pname}-${version}/${pname}.cabal";
sha256 = editedCabalFile;
};
in
stdenv.mkDerivation ({
name = "${optionalString hasActiveLibrary "haskell-"}${pname}-${version}";
inherit src;
nativeBuildInputs = extraLibraries ++ buildTools ++
optionals (pkgconfigDepends != []) ([pkgconfig] ++ pkgconfigDepends) ++
optionals doCheck testDepends;
propagatedNativeBuildInputs = buildDepends;
# GHC needs the locale configured during the Haddock phase.
LANG = "en_US.UTF-8";
LOCALE_ARCHIVE = optionalString stdenv.isLinux "${glibcLocales}/lib/locale/locale-archive";
configurePhase = ''
runHook preConfigure
echo "Building with ${ghc}."
export PATH="${ghc}/bin:$PATH"
${optionalString (hasActiveLibrary && hyperlinkSource) "export PATH=${hscolour}/bin:$PATH"}
configureFlags="--verbose --prefix=$out --libdir=\$prefix/lib/\$compiler --libsubdir=\$pkgid $configureFlags"
configureFlags+=' ${concatStringsSep " " defaultConfigureFlags}'
${optionalString (enableSharedExecutables && stdenv.isLinux) ''
configureFlags+=" --ghc-option=-optl=-Wl,-rpath=$out/lib/${ghc.name}/${pname}-${version}"
''}
${optionalString (enableSharedExecutables && stdenv.isDarwin) ''
configureFlags+=" --ghc-option=-optl=-Wl,-headerpad_max_install_names"
''}
${optionalString (versionOlder "7.8" ghc.version && !isLibrary) ''
configureFlags+=" --ghc-option=-j$NIX_BUILD_CORES"
setupCompileFlags="-j$NIX_BUILD_CORES"
''}
packageConfDir="$TMP/package.conf.d"
mkdir -p $packageConfDir
local inputClosure=""
for i in $propagatedNativeBuildInputs $nativeBuildInputs; do
findInputs $i inputClosure propagated-native-build-inputs
done
for p in $inputClosure; do
if [ -d "$p/lib/${ghc.name}/package.conf.d" ]; then
cp -f "$p/lib/${ghc.name}/package.conf.d/"*.conf $packageConfDir/
continue
fi
if [ -d "$p/include" ]; then
configureFlags+=" --extra-include-dirs=$p/include"
fi
for d in lib{,64}; do
if [ -d "$p/$d" ]; then
configureFlags+=" --extra-lib-dirs=$p/$d"
fi
done
done
ghc-pkg --package-db="$packageConfDir" recache
configureFlags+=" --package-db=$packageConfDir"
${optionalString (editedCabalFile != null) ''
echo "Replacing Cabal file with edited version ${newCabalFile}."
cp ${newCabalFile} ${pname}.cabal
''}
${optionalString jailbreak ''
echo "Running jailbreak-cabal to lift version restrictions on build inputs."
${jailbreak-cabal}/bin/jailbreak-cabal ${pname}.cabal
''}
for i in Setup.hs Setup.lhs ${defaultSetupHs}; do
test -f $i && break
done
ghc -package-db=$packageConfDir $setupCompileFlags --make -o Setup -odir $TMPDIR -hidir $TMPDIR $i
echo configureFlags: $configureFlags
unset GHC_PACKAGE_PATH # Cabal complains if this variable is set during configure.
./Setup configure $configureFlags 2>&1 | ${coreutils}/bin/tee "$NIX_BUILD_TOP/cabal-configure.log"
if ${gnugrep}/bin/egrep -q '^Warning:.*depends on multiple versions' "$NIX_BUILD_TOP/cabal-configure.log"; then
echo >&2 "*** abort because of serious configure-time warning from Cabal"
exit 1
fi
export GHC_PACKAGE_PATH="$packageConfDir:"
runHook postConfigure
'';
buildPhase = ''
runHook preBuild
./Setup build
${optionalString (!noHaddock && hasActiveLibrary) ''
./Setup haddock --html \
${optionalString doHoogle "--hoogle"} \
${optionalString (hasActiveLibrary && hyperlinkSource) "--hyperlink-source"}
''}
runHook postBuild
'';
checkPhase = ''
runHook preCheck
./Setup test ${testTarget}
runHook postCheck
'';
installPhase = ''
runHook preInstall
${if !hasActiveLibrary then "./Setup install" else ''
./Setup copy
local packageConfDir="$out/lib/${ghc.name}/package.conf.d"
local packageConfFile="$packageConfDir/${pname}-${version}.conf"
mkdir -p "$packageConfDir"
./Setup register --gen-pkg-config=$packageConfFile
local pkgId=$( ${gnused}/bin/sed -n -e 's|^id: ||p' $packageConfFile )
mv $packageConfFile $packageConfDir/$pkgId.conf
''}
${optionalString (enableSharedExecutables && isExecutable && stdenv.isDarwin) ''
for exe in "$out/bin/"* ; do
install_name_tool -add_rpath "$out/lib/ghc-${ghc.version}/${pname}-${version}" "$exe"
done
''}
runHook postInstall
'';
passthru = passthru // { inherit pname version; };
meta = { inherit homepage license platforms hydraPlatforms; }
// optionalAttrs broken { inherit broken; }
// optionalAttrs (description != "") { inherit description; }
// optionalAttrs (maintainers != []) { inherit maintainers; }
;
}
// optionalAttrs (configureFlags != []) { inherit configureFlags; }
// optionalAttrs (patches != []) { inherit patches; }
// optionalAttrs (patchPhase != "") { inherit patchPhase; }
// optionalAttrs (prePatch != "") { inherit prePatch; }
// optionalAttrs (postPatch != "") { inherit postPatch; }
// optionalAttrs (preConfigure != "") { inherit preConfigure; }
// optionalAttrs (postConfigure != "") { inherit postConfigure; }
// optionalAttrs (preBuild != "") { inherit preBuild; }
// optionalAttrs (postBuild != "") { inherit postBuild; }
// optionalAttrs (preInstall != "") { inherit preInstall; }
// optionalAttrs (postInstall != "") { inherit postInstall; }
// optionalAttrs (checkPhase != "") { inherit checkPhase; }
// optionalAttrs (preCheck != "") { inherit preCheck; }
// optionalAttrs (postCheck != "") { inherit postCheck; }
// optionalAttrs (preFixup != "") { inherit preFixup; }
// optionalAttrs (postFixup != "") { inherit postFixup; }
)