@@ -1,4 +1,4 @@
1−{ stdenv, buildPackages, ghc, lib, pkgconfig, writeText, runCommand, haskellLib, nonReinstallablePkgs }:
1+{ stdenv, buildPackages, ghc, lib, pkgconfig, writeText, runCommand, haskellLib, nonReinstallablePkgs, withPackage }:
3{ componentId
3{ componentId
@@ -16,8 +16,9 @@
16, preBuild ? null, postBuild ? null
16, preBuild ? null, postBuild ? null
17, preCheck ? null, postCheck ? null
17, preCheck ? null, postCheck ? null
18, preInstall ? null, postInstall ? null
18, preInstall ? null, postInstall ? null
20−, doCheck ? component.doCheck || componentId.ctype == "test"
21+, doCheck ? component.doCheck || haskellLib.isTest componentId
21, doCrossCheck ? component.doCrossCheck || false
22, doCrossCheck ? component.doCrossCheck || false
22, dontPatchELF ? true
23, dontPatchELF ? true
23, dontStrip ? true
24, dontStrip ? true
@@ -27,7 +28,9 @@
31+ fullName = if haskellLib.isAll componentId
30− fullName = "${name}-${componentId.ctype}-${componentId.cname}";
33+ else "${name}-${componentId.ctype}-${componentId.cname}";
32 flagsAndConfig = field: xs: lib.optionalString (xs != []) ''
35 flagsAndConfig = field: xs: lib.optionalString (xs != []) ''
33 echo ${lib.concatStringsSep " " (map (x: "--${field}=${x}") xs)} >> $out/configure-flags
36 echo ${lib.concatStringsSep " " (map (x: "--${field}=${x}") xs)} >> $out/configure-flags
@@ -44,18 +47,30 @@ let
44 in map ({val,...}: val) closure;
47 in map ({val,...}: val) closure;
46 exactDep = pdbArg: p: ''
49 exactDep = pdbArg: p: ''
47− if id=$(${ghc.targetPrefix}ghc-pkg -v0 ${pdbArg} field ${p} id --simple-output); then
50+ if id=$(target-pkg ${pdbArg} field ${p} id --simple-output); then
48 echo "--dependency=${p}=$id" >> $out/configure-flags
51 echo "--dependency=${p}=$id" >> $out/configure-flags
50− if ver=$(${ghc.targetPrefix}ghc-pkg -v0 ${pdbArg} field ${p} version --simple-output); then
53+ if ver=$(target-pkg ${pdbArg} field ${p} version --simple-output); then
51 echo "constraint: ${p} == $ver" >> $out/cabal.config
54 echo "constraint: ${p} == $ver" >> $out/cabal.config
52 echo "constraint: ${p} installed" >> $out/cabal.config
55 echo "constraint: ${p} installed" >> $out/cabal.config
59+ envDep = pdbArg: p: ''
60+ if id=$(target-pkg ${pdbArg} field ${p} id --simple-output); then
61+ echo "package-id $id" >> $out/ghc-environment
56 configFiles = runCommand "${fullName}-config" { nativeBuildInputs = [ghc]; } (''
65 configFiles = runCommand "${fullName}-config" { nativeBuildInputs = [ghc]; } (''
57 mkdir -p $out
66 mkdir -p $out
68+ # Calls ghc-pkg for the target platform
58− ${ghc.targetPrefix}ghc-pkg -v0 init $out/package.conf.d
70+ ${ghc.targetPrefix}ghc-pkg "$@"
73+ target-pkg init $out/package.conf.d
60 ${lib.concatStringsSep "\n" (lib.mapAttrsToList flagsAndConfig {
75 ${lib.concatStringsSep "\n" (lib.mapAttrsToList flagsAndConfig {
61 "extra-lib-dirs" = map (p: "${lib.getLib p}/lib") component.libs;
76 "extra-lib-dirs" = map (p: "${lib.getLib p}/lib") component.libs;
@@ -67,11 +82,11 @@ let
67 # Note: we need to use --global-package-db with ghc-pkg to prevent it
82 # Note: we need to use --global-package-db with ghc-pkg to prevent it
68 # from looking into the implicit global package db when registering the package.
83 # from looking into the implicit global package db when registering the package.
69 ${lib.concatMapStringsSep "\n" (p: ''
84 ${lib.concatMapStringsSep "\n" (p: ''
70− ${ghc.targetPrefix}ghc-pkg -v0 describe ${p} | ${ghc.targetPrefix}ghc-pkg -v0 --force --global-package-db $out/package.conf.d register - || true
85+ target-pkg describe ${p} | target-pkg --force --global-package-db $out/package.conf.d register - || true
71 '') nonReinstallablePkgs}
86 '') nonReinstallablePkgs}
73 ${lib.concatMapStringsSep "\n" (p: ''
88 ${lib.concatMapStringsSep "\n" (p: ''
74− ${ghc.targetPrefix}ghc-pkg -v0 --package-db ${p}/package.conf.d dump | ${ghc.targetPrefix}ghc-pkg -v0 --force --package-db $out/package.conf.d register -
89+ target-pkg --package-db ${p}/package.conf.d dump | target-pkg --force --package-db $out/package.conf.d register -
75 '') flatDepends}
90 '') flatDepends}
77 # Note: we pass `clear` first to ensure that we never consult the implicit global package db.
92 # Note: we pass `clear` first to ensure that we never consult the implicit global package db.
@@ -79,6 +94,14 @@ let
80 echo ${lib.concatStringsSep " " (lib.mapAttrsToList (fname: val: "--flags=${lib.optionalString (!val) "-" + fname}") flags)} >> $out/configure-flags
95 echo ${lib.concatStringsSep " " (lib.mapAttrsToList (fname: val: "--flags=${lib.optionalString (!val) "-" + fname}") flags)} >> $out/configure-flags
97+ # Provide a GHC environment file
98+ cat > $out/ghc-environment <<EOF
100+ package-db $out/package.conf.d
102+ ${lib.concatMapStringsSep "\n" (p: envDep "--package-db ${p.components.library}/package.conf.d" p.identifier.name) component.depends}
103+ ${lib.concatMapStringsSep "\n" (envDep "") (lib.remove "ghc" nonReinstallablePkgs)}
82 '' + lib.optionalString component.doExactConfig ''
105 '' + lib.optionalString component.doExactConfig ''
83 echo "--exact-configuration" >> $out/configure-flags
106 echo "--exact-configuration" >> $out/configure-flags
84 echo "allow-newer: ${package.identifier.name}:*" >> $out/cabal.config
107 echo "allow-newer: ${package.identifier.name}:*" >> $out/cabal.config
@@ -115,14 +138,14 @@ let
115 sed -i "s,dynamic-library-dirs: .*,dynamic-library-dirs: $dynamicLinksDir," $f
138 sed -i "s,dynamic-library-dirs: .*,dynamic-library-dirs: $dynamicLinksDir," $f
118− ${ghc.targetPrefix}ghc-pkg -v0 --package-db $out/package.conf.d recache
141+ target-pkg --package-db $out/package.conf.d recache
120− ${ghc.targetPrefix}ghc-pkg -v0 --package-db $out/package.conf.d check
143+ target-pkg --package-db $out/package.conf.d check
123 finalConfigureFlags = lib.concatStringsSep " " (
146 finalConfigureFlags = lib.concatStringsSep " " (
124 [ "--prefix=$out"
147 [ "--prefix=$out"
125− "${componentId.ctype}:${componentId.cname}"
148+ "${haskellLib.componentTarget componentId}"
126 "$(cat ${configFiles}/configure-flags)"
149 "$(cat ${configFiles}/configure-flags)"
128 "--with-ghc=${ghc.targetPrefix}ghc"
151 "--with-ghc=${ghc.targetPrefix}ghc"
@@ -145,6 +168,16 @@ let
145 ++ component.configureFlags
168 ++ component.configureFlags
171+ executableToolDepends = lib.concatMap (c: if c.isHaskell or false
172+ then builtins.attrValues (c.components.exes or {})
173+ else [c]) component.build-tools;
175+ # Unfortunately, we need to wrap ghc commands for cabal builds to
176+ # work in the nix-shell. See ../doc/removing-with-package-wrapper.md.
177+ shellWrappers = withPackage {
178+ inherit package configFiles;
148in stdenv.mkDerivation ({
181in stdenv.mkDerivation ({
149 name = fullName;
182 name = fullName;
@@ -154,6 +187,7 @@ in stdenv.mkDerivation ({
154 inherit (package) identifier;
187 inherit (package) identifier;
155 config = component;
188 config = component;
156 inherit configFiles;
189 inherit configFiles;
190+ env = shellWrappers;
@@ -167,6 +201,7 @@ in stdenv.mkDerivation ({
169 CABAL_CONFIG = configFiles + /cabal.config;
203 CABAL_CONFIG = configFiles + /cabal.config;
204+ GHC_ENVIRONMENT = configFiles + /ghc-environment;
170 LANG = "en_US.UTF-8"; # GHC needs the locale configured during the Haddock phase.
205 LANG = "en_US.UTF-8"; # GHC needs the locale configured during the Haddock phase.
171 LC_ALL = "en_US.UTF-8";
206 LC_ALL = "en_US.UTF-8";
@@ -179,9 +214,7 @@ in stdenv.mkDerivation ({
179 nativeBuildInputs =
214 nativeBuildInputs =
181 ++ lib.optional (component.pkgconfig != []) pkgconfig
216 ++ lib.optional (component.pkgconfig != []) pkgconfig
182− ++ lib.concatMap (c: if c.isHaskell or false
217+ ++ executableToolDepends;
183− then builtins.attrValues (c.components.exes or {})
184− else [c]) component.build-tools;
186 SETUP_HS = setup + /bin/Setup;
219 SETUP_HS = setup + /bin/Setup;
@@ -217,12 +250,12 @@ in stdenv.mkDerivation ({
217 installPhase = ''
250 installPhase = ''
218 runHook preInstall
251 runHook preInstall
219 $SETUP_HS copy ${lib.concatStringsSep " " component.setupInstallFlags}
252 $SETUP_HS copy ${lib.concatStringsSep " " component.setupInstallFlags}
220− ${lib.optionalString (haskellLib.isLibrary componentId) ''
253+ ${lib.optionalString (haskellLib.isLibrary componentId || haskellLib.isAll componentId) ''
221 $SETUP_HS register --gen-pkg-config=${name}.conf
254 $SETUP_HS register --gen-pkg-config=${name}.conf
222 ${ghc.targetPrefix}ghc-pkg -v0 init $out/package.conf.d
255 ${ghc.targetPrefix}ghc-pkg -v0 init $out/package.conf.d
223 ${ghc.targetPrefix}ghc-pkg -v0 --package-db ${configFiles}/package.conf.d -f $out/package.conf.d register ${name}.conf
256 ${ghc.targetPrefix}ghc-pkg -v0 --package-db ${configFiles}/package.conf.d -f $out/package.conf.d register ${name}.conf
225− ${lib.optionalString (componentId.ctype == "test") ''
258+ ${lib.optionalString (haskellLib.isTest componentId || haskellLib.isAll componentId) ''
226 mkdir -p $out/${name}
259 mkdir -p $out/${name}
227 if [ -f "dist/build/${componentId.cname}/${componentId.cname}" ]; then
260 if [ -f "dist/build/${componentId.cname}/${componentId.cname}" ]; then
228 cp dist/build/${componentId.cname}/${componentId.cname} $out/${name}/
261 cp dist/build/${componentId.cname}/${componentId.cname} $out/${name}/
@@ -233,6 +266,11 @@ in stdenv.mkDerivation ({
234 runHook postInstall
267 runHook postInstall
271+ export PATH="${shellWrappers}/bin:$PATH"
272+ ${toString shellHook}
237# patches can (if they like) depend on the version and revision of the package.
275# patches can (if they like) depend on the version and revision of the package.
238// lib.optionalAttrs (patches != []) { patches = map (p: if builtins.isFunction p then p { inherit (package.identifier) version; inherit revision; } else p) patches; }
276// lib.optionalAttrs (patches != []) { patches = map (p: if builtins.isFunction p then p { inherit (package.identifier) version; inherit revision; } else p) patches; }