Files
haskell.nix/builder/comp-builder.nix
Jean-Baptiste G cebbb6d232 shellFor: provide build tools for all packages when exactDeps = false. Fix #1753. (#1769)
* shellFor: provide build tools for all packages when exactDeps = false

 When not using `exactDeps` cabal may try to build arbitrary dependencies
 so in this case we need to provide the build tools for all of hsPkgs.

* comp-builder: exclude hsc2hs from build-tools as it is never used,

 since it is provided by ghc env, which is first in PATH.
 This avoid possible collisions when using eg. devshells, which
 fuse all binaries into a single output directory.
2022-11-08 15:24:01 +13:00

634 lines
27 KiB
Nix

{ pkgs, stdenv, buildPackages, ghc, lib, gobject-introspection ? null, haskellLib, makeConfigFiles, haddockBuilder, ghcForComponent, hsPkgs, compiler, runCommand, libffi, gmp, zlib, ncurses, nodejs }@defaults:
lib.makeOverridable (
let self =
{ componentId
, component
, package
, name # This is the package name
, setup
, src
, flags
, revision
, cabalFile
, cabal-generator
, patches ? []
, preUnpack ? component.preUnpack, postUnpack ? component.postUnpack
, configureFlags ? component.configureFlags
, preConfigure ? component.preConfigure, postConfigure ? component.postConfigure
, setupBuildFlags ? component.setupBuildFlags
, preBuild ? component.preBuild , postBuild ? component.postBuild
, preCheck ? component.preCheck , postCheck ? component.postCheck
, setupInstallFlags ? component.setupInstallFlags
, preInstall ? component.preInstall , postInstall ? component.postInstall
, preHaddock ? component.preHaddock , postHaddock ? component.postHaddock
, shellHook ? ""
, configureAllComponents ? component.configureAllComponents ||
# When set, configure all the components in the package
# (not just the one we are building).
# Enable for tests in packages that use cabal-doctest.
( haskellLib.isTest componentId &&
lib.any (x: x.identifier.name or "" == "cabal-doctest") package.setup-depends
)
, allComponent # Used when `configureAllComponents` is set to get a suitable configuration.
, build-tools ? component.build-tools
, pkgconfig ? component.pkgconfig
, platforms ? component.platforms
, frameworks ? component.frameworks
, dontPatchELF ? component.dontPatchELF
, dontStrip ? component.dontStrip
, hardeningDisable ? component.hardeningDisable
, enableStatic ? component.enableStatic
, enableShared ? ghc.enableShared && component.enableShared && !haskellLib.isCrossHost
# on x86 we'll use shared libraries, even with musl m(
# ghc's internal linker seems to be broken on x86.
&& !(stdenv.hostPlatform.isMusl && !stdenv.hostPlatform.isx86)
, enableDeadCodeElimination ? component.enableDeadCodeElimination
, writeHieFiles ? component.writeHieFiles
, ghcOptions ? component.ghcOptions
, contentAddressed ? component.contentAddressed
# Options for Haddock generation
, doHaddock ? component.doHaddock # Enable haddock and hoogle generation
, doHoogle ? component.doHoogle # Also build a hoogle index
, hyperlinkSource ? component.doHyperlinkSource # Link documentation to the source code
, quickjump ? component.doQuickjump # Generate an index for interactive documentation navigation
, keepSource ? component.keepSource || configureAllComponents # Build from `source` output in the store then delete `dist`
, setupHaddockFlags ? component.setupHaddockFlags
# Profiling
, enableLibraryProfiling ? component.enableLibraryProfiling
, enableProfiling ? component.enableProfiling
, profilingDetail ? component.profilingDetail
# Coverage
, doCoverage ? component.doCoverage
# Data
, enableSeparateDataOutput ? component.enableSeparateDataOutput
# Prelinked ghci libraries; will make iserv faster; especially for static builds.
, enableLibraryForGhci ? true
# Debug
, enableDebugRTS ? false
, enableDWARF ? false
# This will only work with a custom TSan way enabled custom compiler
, enableTSanRTS ? false
# LLVM
, useLLVM ? ghc.useLLVM
, smallAddressSpace ? false
}@drvArgs:
let
componentForSetup =
if configureAllComponents
then allComponent
else component;
# Ignore attempts to include DWARF info when it is not possible
enableDWARF = drvArgs.enableDWARF or false
&& stdenv.hostPlatform.isLinux
&& !haskellLib.isCrossHost
&& !stdenv.hostPlatform.isMusl
&& builtins.compareVersions defaults.ghc.version "8.10.2" >= 0;
ghc = (if enableDWARF then (x: x.dwarf) else (x: x)) (
(if smallAddressSpace then (x: x.smallAddressSpace) else (x: x)) defaults.ghc);
setup = (if enableDWARF then (x: x.dwarf) else (x: x)) (
(if smallAddressSpace then (x: x.smallAddressSpace) else (x: x)) drvArgs.setup);
# TODO fix cabal wildcard support so hpack wildcards can be mapped to cabal wildcards
canCleanSource = !(cabal-generator == "hpack" && !(package.cleanHpack or false));
# In order to support relative references to other packages we need to use
# the `origSrc` diretory as the root `src` for the derivation.
# We use `rootAndSubDir` here to split the cleaned source into a `cleanSrc.root`
# path (that respects the filtering) and a `cleanSrc.subDir` that
# is the sub directory in that root path that contains the package.
# `cleanSrc.subDir` is used in `prePatch` and `lib/cover.nix`.
cleanSrc = haskellLib.rootAndSubDir (if canCleanSource
then haskellLib.cleanCabalComponent package componentForSetup "${componentId.ctype}-${componentId.cname}" src
else
# We can clean out the siblings though to at least avoid changes to other packages
# from triggering a rebuild of this one.
# Passing `subDir` but not `includeSiblings = true;` will exclude anything not
# in the `subDir`.
if src ? origSrc && src ? filter && src.origSubDir or "" != ""
then haskellLib.cleanSourceWith {
name = src.name or "source";
src = src.origSrc;
subDir = lib.removePrefix "/" src.origSubDir;
inherit (src) filter;
}
else src);
nameOnly = "${package.identifier.name}-${componentId.ctype}-${componentId.cname}";
fullName = "${nameOnly}-${package.identifier.version}";
needsProfiling = enableProfiling || enableLibraryProfiling;
configFiles = makeConfigFiles {
component = componentForSetup;
inherit (package) identifier;
inherit fullName flags needsProfiling enableDWARF;
};
enableFeature = enable: feature:
(if enable then "--enable-" else "--disable-") + feature;
disableFeature = disable: enableFeature (!disable);
finalConfigureFlags = lib.concatStringsSep " " (
[ "--prefix=$out"
] ++
# We don't specify this in 'commonConfigureFlags', as these are also
# used by haddock-builder.nix. If we do specify these options in
# commonConfigureFlags, then the haddock-builder will fail, because it
# sets its own outputs which *don't* include $hie
lib.optionals writeHieFiles [
"--ghc-option=-fwrite-ide-info" "--ghc-option=-hiedir$hie"
] ++
(
# If configureAllComponents is set we should not specify the component
# and Setup will attempt to configure them all.
if configureAllComponents
then ["--enable-tests" "--enable-benchmarks"]
else ["${haskellLib.componentTarget componentId}"]
) ++ [ "$(cat ${configFiles}/configure-flags)"
] ++ commonConfigureFlags);
# From nixpkgs 20.09, the pkg-config exe has a prefix matching the ghc one
pkgConfigHasPrefix = builtins.compareVersions lib.version "20.09pre" >= 0;
commonConfigureFlags = ([
# GHC
"--with-ghc=${ghc.targetPrefix}ghc"
"--with-ghc-pkg=${ghc.targetPrefix}ghc-pkg"
"--with-hsc2hs=${ghc.targetPrefix}hsc2hs"
] ++ lib.optional (pkgConfigHasPrefix && pkgconfig != [])
"--with-pkg-config=${ghc.targetPrefix}pkg-config"
++ lib.optionals (stdenv.hasCC or (stdenv.cc != null))
( # CC
[ "--with-gcc=${stdenv.cc.targetPrefix}cc"
] ++
# BINTOOLS
(if stdenv.hostPlatform.isLinux && !stdenv.hostPlatform.isAndroid # might be better check to see if cc is clang/llvm?
# use gold as the linker on linux to improve link times
then [
"--with-ld=${stdenv.cc.bintools.targetPrefix}ld.gold"
"--ghc-option=-optl-fuse-ld=gold"
"--ld-option=-fuse-ld=gold"
] else [
"--with-ld=${stdenv.cc.bintools.targetPrefix}ld"
]
) ++ [
"--with-ar=${stdenv.cc.bintools.targetPrefix}ar"
"--with-strip=${stdenv.cc.bintools.targetPrefix}strip"
]
) ++ [ # other flags
(disableFeature dontStrip "executable-stripping")
(disableFeature dontStrip "library-stripping")
(enableFeature enableLibraryProfiling "library-profiling")
(enableFeature enableProfiling "profiling")
(enableFeature enableStatic "static")
(enableFeature enableShared "shared")
(enableFeature doCoverage "coverage")
(enableFeature enableLibraryForGhci "library-for-ghci")
] ++ lib.optionals (stdenv.hostPlatform.isMusl && (haskellLib.isExecutableType componentId)) [
# These flags will make sure the resulting executable is statically linked.
# If it uses other libraries it may be necessary for to add more
# `--ghc-option=-optl=-L` options to the `configureFlags` of the
# component.
"--disable-executable-dynamic"
"--ghc-option=-optl=-pthread"
"--ghc-option=-optl=-static"
] ++ lib.optional enableSeparateDataOutput "--datadir=$data/share/${ghc.name}"
++ lib.optional (enableLibraryProfiling || enableProfiling) "--profiling-detail=${profilingDetail}"
++ lib.optional stdenv.hostPlatform.isLinux (enableFeature enableDeadCodeElimination "split-sections")
++ lib.optionals haskellLib.isCrossHost (
map (arg: "--hsc2hs-option=" + arg) (["--cross-compile"] ++ lib.optionals (stdenv.hostPlatform.isWindows) ["--via-asm"])
++ lib.optional (package.buildType == "Configure") "--configure-option=--host=${stdenv.hostPlatform.config}" )
++ configureFlags
++ (ghc.extraConfigureFlags or [])
++ lib.optional enableDebugRTS "--ghc-option=-debug"
++ lib.optional enableTSanRTS "--ghc-option=-tsan"
++ lib.optional enableDWARF "--ghc-option=-g3"
++ lib.optionals useLLVM [
"--ghc-option=-fPIC" "--gcc-option=-fPIC"
]
++ map (o: ''--ghc${lib.optionalString (stdenv.hostPlatform.isGhcjs) "js"}-options="${o}"'') ghcOptions
++ lib.optional (
# GHC 9.2 cross compiler built with older versions of GHC seem to have problems
# with unique conters. Perhaps because the name changed for the counters.
# TODO This work around to use `-j1` should be removed once we are able to build 9.2 with 9.2.
haskellLib.isCrossHost
&& builtins.compareVersions defaults.ghc.version "9.2.1" >= 0
&& builtins.compareVersions defaults.ghc.version "9.3" < 0)
"--ghc-options=-j1"
);
# the build-tools version might be depending on the version of the package, similarly to patches
executableToolDepends =
(lib.concatMap (c: if c.isHaskell or false
then builtins.attrValues (c.components.exes or {})
else [c])
(builtins.filter (x: !(isNull x)
# We always exclude hsc2hs from build-tools because it is unecessary as it is provided by ghc
# and hsc2hs from ghc is first in PATH so the one from build-tools is never used.
&& x.identifier.name or "" != "hsc2hs")
(map
(p: if builtins.isFunction p
then p { inherit (package.identifier) version; inherit revision; }
else p) build-tools))) ++
lib.optional (pkgconfig != []) buildPackages.cabalPkgConfigWrapper;
# Unfortunately, we need to wrap ghc commands for cabal builds to
# work in the nix-shell. See ../doc/removing-with-package-wrapper.md.
shellWrappers = ghcForComponent {
componentName = fullName;
inherit configFiles enableDWARF;
inherit (component) plugins;
};
# In order to let shell hooks make package-specific things like Hoogle databases
shellHookApplied = if builtins.isString shellHook then shellHook else
if builtins.isFunction shellHook then shellHook { inherit package shellWrappers; }
else abort "shellHook should be a string or a function";
exeExt = if stdenv.hostPlatform.isGhcjs then ".jsexe/all.js" else
stdenv.hostPlatform.extensions.executable;
exeName = componentId.cname + exeExt;
testExecutable = "dist/build/${componentId.cname}/${exeName}";
# Attributes that are common to both the build and haddock derivations
commonAttrs = {
src = cleanSrc.root;
LANG = "en_US.UTF-8"; # GHC needs the locale configured during the Haddock phase.
LC_ALL = "en_US.UTF-8";
enableParallelBuilding = true;
SETUP_HS = setup + /bin/Setup;
prePatch =
# If the package is in a sub directory `cd` there first.
# In some cases the `cleanSrc.subDir` will be empty and the `.cabal`
# file will be in the root of `src` (`cleanSrc.root`). This
# will happen when:
# * the .cabal file is in the projects `src.origSrc or src`
# * the package src was overridden with a value that does not
# include an `origSubDir`
(lib.optionalString (cleanSrc.subDir != "") ''
cd ${lib.removePrefix "/" cleanSrc.subDir}
''
) +
(if cabalFile != null
then ''cat ${cabalFile} > ${package.identifier.name}.cabal''
else
# When building hpack package we use the internal nix-tools
# (compiled with a fixed GHC version)
lib.optionalString (cabal-generator == "hpack") ''
${buildPackages.haskell-nix.internal-nix-tools}/bin/hpack
''
);
}
# patches can (if they like) depend on the version and revision of the package.
// lib.optionalAttrs (patches != []) {
patches = map (p:
if builtins.isFunction p
then p { inherit (package.identifier) version; inherit revision; }
else p
) patches;
}
// haskellLib.optionalHooks {
# These are hooks are needed to set up the source for building and running haddock
inherit preUnpack postUnpack preConfigure postConfigure;
}
// lib.optionalAttrs (stdenv.buildPlatform.libc == "glibc") {
LOCALE_ARCHIVE = "${buildPackages.glibcLocales}/lib/locale/locale-archive";
};
haddock = haddockBuilder {
inherit componentId component package flags commonConfigureFlags
commonAttrs revision doHaddock
doHoogle hyperlinkSource quickjump setupHaddockFlags
needsProfiling configFiles preHaddock postHaddock pkgconfig;
componentDrv = drv;
};
contentAddressedAttrs = lib.optionalAttrs contentAddressed {
__contentAddressed = true;
outputHashMode = "recursive";
outputHashAlgo = "sha256";
};
drv = stdenv.mkDerivation (commonAttrs // contentAddressedAttrs // {
pname = nameOnly;
inherit (package.identifier) version;
doCheck = false;
doCrossCheck = false;
inherit dontPatchELF dontStrip;
passthru = {
inherit (package) identifier;
config = component;
srcSubDir = cleanSrc.subDir;
srcSubDirPath = cleanSrc.root + cleanSrc.subDir;
inherit configFiles executableToolDepends exeName enableDWARF;
exePath = drv + "/bin/${exeName}";
env = shellWrappers;
profiled = self (drvArgs // { enableLibraryProfiling = true; });
dwarf = self (drvArgs // { enableDWARF = true; });
} // lib.optionalAttrs (haskellLib.isLibrary componentId) ({
inherit haddock;
inherit (haddock) haddockDir; # This is null if `doHaddock = false`
} // lib.optionalAttrs (haddock ? doc) {
# `doHaddock = false` turns the doc of haddock output off
inherit (haddock) doc;
}
);
meta = {
homepage = package.homepage or "";
description = package.synopsis or "";
license = haskellLib.cabalToNixpkgsLicense package.license;
platforms = if platforms == null then lib.platforms.all else platforms;
} // lib.optionalAttrs (haskellLib.isExecutableType componentId) {
# Set main executable name for executable components, so that `nix run` in
# nix flakes will work correctly. When not set, `nix run` would (typically
# erroneously) deduce the executable name from the derivation name and
# attempt to run, for example,
# `/nix/store/...-project-exe-app-0.1.0.0/bin/project-exe-app` instead of
# `/nix/store/...-project-exe-app-0.1.0.0/bin/app`.
mainProgram = exeName;
};
propagatedBuildInputs =
frameworks # Frameworks will be needed at link time
# Not sure why pkgconfig needs to be propagatedBuildInputs but
# for gi-gtk-hs it seems to help.
++ map pkgs.lib.getDev (builtins.concatLists pkgconfig)
++ lib.optionals (stdenv.hostPlatform.isWindows)
(lib.flatten component.libs
++ map haskellLib.dependToLib component.depends);
buildInputs = lib.optionals (!stdenv.hostPlatform.isWindows)
(lib.flatten component.libs
++ map haskellLib.dependToLib component.depends);
nativeBuildInputs =
[shellWrappers buildPackages.removeReferencesTo]
++ executableToolDepends;
outputs = ["out" ]
++ (lib.optional enableSeparateDataOutput "data")
++ (lib.optional keepSource "source")
++ (lib.optional writeHieFiles "hie");
prePatch =
# emcc is very slow if it cannot cache stuff in $HOME
(lib.optionalString (stdenv.hostPlatform.isGhcjs) ''
export HOME=$(mktemp -d)
'') +
(lib.optionalString (!canCleanSource) ''
echo "Cleaning component source not supported, leaving it un-cleaned"
'') +
(lib.optionalString keepSource ''
cp -r . $source
cd $source
chmod -R +w .
'') + commonAttrs.prePatch;
configurePhase = ''
runHook preConfigure
echo Configure flags:
printf "%q " ${finalConfigureFlags}
echo
$SETUP_HS configure ${finalConfigureFlags}
runHook postConfigure
'';
buildPhase =
# It seems that by the time the iserv wrapper specifiec by `--ghc-option=-pgmi` runs
# all the array environment variables are removed from the environment. To get a list
# of all the locations a DLLs might be present we need access to pkgsHostTarget.
# Adding a string version of the list array of nix store paths allows us to get that
# list when we need it.
(lib.optionalString stdenv.hostPlatform.isWindows ''
export pkgsHostTargetAsString="''${pkgsHostTarget[@]}"
'') +
# The following could be refactored but would lead to many rebuilds
# In case of content addressed components we need avoid parallel building (passing -j1)
# in order to have a deterministic output and therefore avoid potential situations
# where the binary cache becomes useless
# See also https://gitlab.haskell.org/ghc/ghc/-/issues/12935
(if contentAddressed then ''
runHook preBuild
$SETUP_HS build ${haskellLib.componentTarget componentId} -j1 ${lib.concatStringsSep " " setupBuildFlags}
runHook postBuild
'' else if stdenv.hostPlatform.isGhcjs then ''
runHook preBuild
# https://gitlab.haskell.org/ghc/ghc/issues/9221
$SETUP_HS build ${haskellLib.componentTarget componentId} ${lib.concatStringsSep " " setupBuildFlags}
runHook postBuild
'' else ''
runHook preBuild
# https://gitlab.haskell.org/ghc/ghc/issues/9221
$SETUP_HS build ${haskellLib.componentTarget componentId} -j$(($NIX_BUILD_CORES > 4 ? 4 : $NIX_BUILD_CORES)) ${lib.concatStringsSep " " setupBuildFlags}
runHook postBuild
'');
# Note: Cabal does *not* copy test executables during the `install` phase.
#
# Note 2: if a package contains multiple libs (lib + sublibs) SETUP register will generate a
# folder instead of a file for the configuration. Therefore if the result is a folder,
# we need to register each and every element of that folder.
#
# Note 3: if a package has no libs SETUP will not generate anything. This can
# happen when building the `all` component of a package.
installPhase = let
target-pkg-and-db = "${ghc.targetPrefix}ghc-pkg -v0 --package-db $out/package.conf.d";
in ''
runHook preInstall
${ # `Setup copy` does not install tests and benchmarks.
if !haskellLib.isTest componentId && !haskellLib.isBenchmark componentId
then ''
$SETUP_HS copy ${lib.concatStringsSep " " (
setupInstallFlags
++ lib.optional configureAllComponents
(haskellLib.componentTarget componentId)
)}''
else
# However if there are exes or libraries it does copy the datadir.
# So run it, but expect it might complain there was nothing to do.
''
SETUP_ERR=$(mktemp)
if $SETUP_HS copy ${lib.concatStringsSep " " (
setupInstallFlags
++ lib.optional configureAllComponents
(haskellLib.componentTarget componentId)
)} 2> >(tee $SETUP_ERR >&2); then
echo Setup copy success
else
# we assume that if the SETUP_HS command fails and the following line was found in the error
# log, that it was the only error. Hence if we do _not_ find the line, grep will fail and this derivation
# will be marked as failure.
cat $SETUP_ERR | grep 'Error: Setup: No executables and no library found\. Nothing to do\.'
fi
''}
${lib.optionalString (haskellLib.isLibrary componentId) ''
$SETUP_HS register --gen-pkg-config=${name}.conf
${ghc.targetPrefix}ghc-pkg -v0 init $out/package.conf.d
${ghc.targetPrefix}ghc-pkg -v0 --package-db ${configFiles}/${configFiles.packageCfgDir} -f $out/package.conf.d register ${name}.conf
mkdir -p $out/exactDep
touch $out/exactDep/configure-flags
touch $out/exactDep/cabal.config
touch $out/envDep
${ # The main library in a package has the same name as the package
if package.identifier.name == componentId.cname
then ''
if id=$(${target-pkg-and-db} field ${package.identifier.name} id --simple-output); then
echo "--dependency=${package.identifier.name}=$id" >> $out/exactDep/configure-flags
echo "package-id $id" >> $out/envDep
else
echo 'ERROR: ${package.identifier.name} id could not be found with ${target-pkg-and-db}'
exit 1
fi
if ver=$(${target-pkg-and-db} field ${package.identifier.name} version --simple-output); then
echo "constraint: ${package.identifier.name} == $ver" >> $out/exactDep/cabal.config
echo "constraint: ${package.identifier.name} installed" >> $out/exactDep/cabal.config
else
echo 'ERROR: ${package.identifier.name} version could not be found with ${target-pkg-and-db}'
exit 1
fi
''
else
# If the component name is not the package name this must be a sublib.
# As we build sublibs separately, the following query should be safe.
(''
if id=$(${target-pkg-and-db} field "z-${package.identifier.name}-z-*" id --simple-output); then
name=$(${target-pkg-and-db} field "z-${package.identifier.name}-z-*" name --simple-output)
echo "--dependency=''${name#z-${package.identifier.name}-z-}=$id" >> $out/exactDep/configure-flags
''
# Allow `package-name:sublib-name` to work in `build-depends`
# by adding the same `--dependency` again, but with the package
# name added.
+ ''
echo "--dependency=${package.identifier.name}:''${name#z-${package.identifier.name}-z-}=$id" >> $out/exactDep/configure-flags
else
echo 'ERROR: ${package.identifier.name} id could not be found with ${target-pkg-and-db}'
exit 1
fi
'')
}
''}
${(lib.optionalString (haskellLib.isTest componentId || haskellLib.isBenchmark componentId) ''
mkdir -p $out/bin
if [ -f ${testExecutable} ]; then
mkdir -p $(dirname $out/bin/${exeName})
${lib.optionalString stdenv.buildPlatform.isLinux "sync"}
${if stdenv.hostPlatform.isGhcjs then ''
cat <(echo \#!${lib.getBin buildPackages.nodejs-18_x}/bin/node) ${testExecutable} >| $out/bin/${exeName}
chmod +x $out/bin/${exeName}
'' else ''
cp -r ${testExecutable} $(dirname $out/bin/${exeName})
''}
fi
'')
# In case `setup copy` did not create this
+ (lib.optionalString enableSeparateDataOutput ''
mkdir -p $data
'')
+ (lib.optionalString (stdenv.hostPlatform.isWindows && (haskellLib.mayHaveExecutable componentId)) (''
echo "Symlink libffi and gmp .dlls ..."
for p in ${lib.concatStringsSep " " [ libffi gmp ]}; do
find "$p" -iname '*.dll' -exec ln -s {} $out/bin \;
done
''
# symlink all .dlls into the local directory.
+ ''
for p in $pkgsHostTargetAsString; do
find "$p" -iname '*.dll' -exec ln -s {} $out/bin \;
find "$p" -iname '*.dll.a' -exec ln -s {} $out/bin \;
done
''))
+ (lib.optionalString doCoverage ''
mkdir -p $out/share
cp -r dist/hpc $out/share
cp dist/setup-config $out/
'')
}
runHook postInstall
'' + (
# Keep just the autogen files and package.conf.inplace package
# DB (probably empty unless this is a library component).
# We also have to remove any refernces to $out to avoid
# circular references.
lib.optionalString (configureAllComponents || keepSource) ''
mv dist dist-tmp-dir
mkdir -p dist/build
if [ -d dist-tmp-dir/build/${componentId.cname}/autogen ]; then
mv dist-tmp-dir/build/${componentId.cname}/autogen dist/build/
elif [ -d dist-tmp-dir/build/autogen ]; then
mv dist-tmp-dir/build/autogen dist/build/
fi
mv dist-tmp-dir/package.conf.inplace dist/
if [ -d dist/build/autogen ]; then
remove-references-to -t $out dist/build/autogen/*
fi
rm -rf dist-tmp-dir
''
) + (
# Avoid circular refernces that crop up by removing references to $out
# from the current directory ($source).
# So far we have seen these in:
# * The `${name}.conf` of a library component.
# * The `hie` files for the Paths_ module (when building the stack exe).
lib.optionalString keepSource ''
find . -type f -exec remove-references-to -t $out '{}' +
'') + (lib.optionalString (haskellLib.isTest componentId) ''
echo The test ${package.identifier.name}.components.tests.${componentId.cname} was built. To run the test build ${package.identifier.name}.checks.${componentId.cname}.
'');
doInstallCheck = true;
installCheckPhase = lib.optionalString (haskellLib.isLibrary componentId) ''
if test -n "$(shopt -s nullglob; echo $out/package.conf.d/${name}-*.conf)"; then
echo $out/package.conf.d/${name}-*.conf " is present"
else
echo "ERROR: $out/package.conf.d/${name}-*.conf was not created"
exit 1
fi
'';
shellHook = ''
export PATH="${shellWrappers}/bin:$PATH"
${shellHookApplied}
'';
}
// haskellLib.optionalHooks {
# These are the hooks that are not needed by haddock (see commonAttrs for the ones that
# are shared with the haddock derivation)
inherit
preBuild postBuild
preInstall postInstall;
}
// lib.optionalAttrs (hardeningDisable != [] || stdenv.hostPlatform.isMusl) {
hardeningDisable = hardeningDisable ++ lib.optional stdenv.hostPlatform.isMusl "pie";
});
in drv; in self)