haskellPackages.mkDerivation: New intermediates output

This adds a new `intermediates` output that can be used to
accelerate a Haskell build by importing build products
exported from a prior similar build.

The motivation for this is explained by the following post:

https://www.haskellforall.com/2022/12/nixpkgs-support-for-incremental-haskell.html
This commit is contained in:
Gabriella Gonzalez 2023-01-31 09:34:01 -08:00 committed by Rebecca Turner
parent 0d1d890799
commit 72a70bd73b
No known key found for this signature in database

View file

@ -31,6 +31,7 @@ in
, doBenchmark ? false
, doHoogle ? true
, doHaddockQuickjump ? doHoogle && lib.versionAtLeast ghc.version "8.6"
, doInstallIntermediates ? false
, editedCabalFile ? null
# aarch64 outputs otherwise exceed 2GB limit
, enableLibraryProfiling ? !(ghc.isGhcjs or stdenv.targetPlatform.isAarch64 or false)
@ -84,6 +85,7 @@ in
, enableSeparateBinOutput ? false
, enableSeparateDataOutput ? false
, enableSeparateDocOutput ? doHaddock
, enableSeparateIntermediatesOutput ? false
, # Don't fail at configure time if there are multiple versions of the
# same package in the (recursive) dependencies of the package being
# built. Will delay failures, if any, to compile time.
@ -93,6 +95,10 @@ in
# This can make it slightly faster to load this library into GHCi, but takes
# extra disk space and compile time.
enableLibraryForGhci ? false
# Set this to a previous build of this same package to reuse the intermediate
# build products from that prior build as a starting point for accelerating
# this build
, previousIntermediates ? null
} @ args:
assert editedCabalFile != null -> revision != null;
@ -240,6 +246,8 @@ let
"--ghc-options=-haddock"
];
postPhases = optional doInstallIntermediates [ "installIntermediatesPhase" ];
setupCompileFlags = [
(optionalString (!coreSetup) "-${nativePackageDbFlag}=$setupPackageConfDir")
(optionalString enableParallelBuilding (parallelBuildingFlags))
@ -316,7 +324,9 @@ stdenv.mkDerivation ({
outputs = [ "out" ]
++ (optional enableSeparateDataOutput "data")
++ (optional enableSeparateDocOutput "doc")
++ (optional enableSeparateBinOutput "bin");
++ (optional enableSeparateBinOutput "bin")
++ (optional enableSeparateIntermediatesOutput "intermediates");
setOutputFlags = false;
pos = builtins.unsafeGetAttrPos "pname" args;
@ -393,7 +403,13 @@ stdenv.mkDerivation ({
# only use the links hack if we're actually building dylibs. otherwise, the
# "dynamic-library-dirs" point to nonexistent paths, and the ln command becomes
# "ln -s $out/lib/links", which tries to recreate the links dir and fails
+ (optionalString (stdenv.isDarwin && (enableSharedLibraries || enableSharedExecutables)) ''
#
# Note: We need to disable this work-around when using intermediate build
# products from a prior build because otherwise Nix will change permissions on
# the `$out/lib/links` directory to read-only when the build is done after the
# dist directory has already been exported, which triggers an unnecessary
# rebuild of modules included in the exported dist directory.
+ (optionalString (stdenv.isDarwin && (enableSharedLibraries || enableSharedExecutables) && !enableSeparateIntermediatesOutput) ''
# Work around a limit in the macOS Sierra linker on the number of paths
# referenced by any one dynamic library:
#
@ -471,11 +487,22 @@ stdenv.mkDerivation ({
runHook postConfigure
'';
buildPhase = ''
runHook preBuild
${setupCommand} build ${buildTarget}${crossCabalFlagsString}${buildFlagsString}
runHook postBuild
'';
buildPhase =
''
runHook preBuild
''
+ lib.optionalString (previousIntermediates != null)
''
mkdir -p dist;
rm -r dist/build
cp -r ${previousIntermediates}/dist/build dist/build
find dist/build -exec chmod u+w {} +
find dist/build -exec touch -d '1970-01-01T00:00:00Z' {} +
''
+ ''
${setupCommand} build ${buildTarget}${crossCabalFlagsString}${buildFlagsString}
runHook postBuild
'';
inherit doCheck;
@ -558,6 +585,14 @@ stdenv.mkDerivation ({
runHook postInstall
'';
${if doInstallIntermediates then "installIntermediatesPhase" else null} = ''
runHook preInstallIntermediates
installIntermediatesDir=${if enableSeparateIntermediatesOutput then "$intermediates" else "$out"}
mkdir -p $installIntermediatesDir/dist
cp -r dist/build $installIntermediatesDir/dist
runHook postInstallIntermediates
'';
passthru = passthru // rec {
inherit pname version;
@ -719,6 +754,7 @@ stdenv.mkDerivation ({
// optionalAttrs (args ? preFixup) { inherit preFixup; }
// optionalAttrs (args ? postFixup) { inherit postFixup; }
// optionalAttrs (args ? dontStrip) { inherit dontStrip; }
// optionalAttrs (postPhases != []) { inherit postPhases; }
// optionalAttrs (stdenv.buildPlatform.libc == "glibc"){ LOCALE_ARCHIVE = "${glibcLocales}/lib/locale/locale-archive"; }
)
)