mirror of
https://github.com/simplex-chat/haskell.nix.git
synced 2026-06-03 09:17:32 +00:00
e49b15fefc
* update llvm-hs llvm from 11 to 12 * allow passing version args to build-tools; fix llvm-hs build-tools, pass allRefs to builtins.fetchGit to allow fetching non-standard-refs (to mirror stack behaviour)
611 lines
26 KiB
Nix
611 lines
26 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))
|
|
(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.
|
|
lib.optionalString (!haskellLib.isTest componentId && !haskellLib.isBenchmark componentId) ''
|
|
$SETUP_HS copy ${lib.concatStringsSep " " (
|
|
setupInstallFlags
|
|
++ lib.optional configureAllComponents
|
|
(haskellLib.componentTarget componentId)
|
|
)}''}
|
|
${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})
|
|
${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)
|