1717
1818 # exactDep will pass --exact-configuration to the `SETUP_HS confiugre` command.
1919 # This requires us to pass --dependency={dep name}={pkg id}. The dependency
20- # name will usually be the name of the package `p`, that will have been located
21- # in the suitable package db when the dependency (along with `exactDep` and `envDep`)
22- # was built. Sublibs need a bit of special handling:
20+ # name will usually be the name of the package `p`, which we can locate in the
21+ # package-db, passed in via `pdbArg`. Thus querying the package-db for the
22+ # id field for package `p`, will unsually provide is with the right value. Sublibs
23+ # need a bit of special handling:
2324 #
2425 # - Sublibs: if the dependency is a sublibrary of a package, we need to use
2526 # the sublibrary's name for the dep name, and lookup the sublibraries
3031
3132 getLibComponent = dep :
3233 dep . components . library # Regular package dependency
33- or dep ; # or a sublib
34-
34+ or dep ; # or a sublib
35+
3536 catPkgExactDep = p : ''
36- cat ${ getLibComponent p } /exactDep/configure-flags >> $out/configure-flags
37- cat ${ getLibComponent p } /exactDep/cabal.config >> $out/cabal.config
37+ cat ${ p } /exactDep/configure-flags >> $out/configure-flags
38+ cat ${ p } /exactDep/cabal.config >> $out/cabal.config
3839 '' ;
3940
4041 catGhcPkgExactDep = p : ''
4546 '' ;
4647
4748 catPkgEnvDep = p : ''
48- cat ${ getLibComponent p } /envDep >> $out/ghc-environment
49+ cat ${ p } /envDep >> $out/ghc-environment
4950 '' ;
5051
5152 catGhcPkgEnvDep = p : ''
5455 fi
5556 '' ;
5657
58+ # Work our suitable packageCfgDir subdirectory
59+ isGhcjs = ghc . isGhcjs or false ;
60+ ghcCommand' = if isGhcjs then "ghcjs" else "ghc" ;
61+ ghcCommand = "${ ghc . targetPrefix } ${ ghcCommand' } " ;
62+ ghcCommandCaps = lib . toUpper ghcCommand' ;
63+ libDir = "lib/${ ghcCommand } -${ ghc . version } " ;
64+ packageCfgDir = "${ libDir } /package.conf.d" ;
65+
5766in { identifier , component , fullName , flags ? { } } :
58- runCommand "${ fullName } -config" { nativeBuildInputs = [ ghc ] ; } ( ''
67+ # Filters out only library packages that for this GHC target
68+ # TODO investigate why this is needed
69+ let libDeps = lib . filter ( p : p . configFiles . targetPrefix == ghc . targetPrefix )
70+ ( map getLibComponent component . depends ) ;
71+ cfgFiles =
72+ let xs = map
73+ ( p : "${ p . configFiles } " )
74+ libDeps ;
75+ in lib . concatStringsSep "\" \" " xs ;
76+ libs = lib . concatMapStringsSep "\" \" " ( p : "${ p } " ) libDeps ;
77+ in
78+ runCommand "${ ghc . targetPrefix } ${ fullName } -config" {
79+ nativeBuildInputs = [ ghc ] ;
80+ passthru = {
81+ inherit ( ghc ) targetPrefix ;
82+ inherit ghcCommand ghcCommandCaps libDir packageCfgDir ;
83+ } ;
84+ } ( ''
5985 mkdir -p $out
6086
61- ${ target-pkg } init $out/package.conf.d
87+ ${ target-pkg } init $out/${ packageCfgDir }
6288
6389 ${ lib . concatStringsSep "\n " ( lib . mapAttrsToList flagsAndConfig {
6490 "extra-lib-dirs" = map ( p : "${ lib . getLib p } /lib" ) component . libs ;
@@ -68,16 +94,22 @@ in { identifier, component, fullName, flags ? {} }:
6894
6995 # Copy over the nonReinstallablePkgs from the global package db.
7096 ${ lib . concatMapStringsSep "\n " ( p : ''
71- find ${ ghc } /lib/${ ghc . name } /package.conf.d -name '${ p } *.conf' -exec cp -f {} $out/package.conf.d \;
97+ find ${ ghc } /lib/${ ghc . name } /package.conf.d -name '${ p } *.conf' -exec cp -f {} $out/${ packageCfgDir } \;
7298 '' ) nonReinstallablePkgs }
7399
74- ${ lib . concatMapStringsSep "\n " ( p : ''
75- cp -f "${ ( getLibComponent p ) . configFiles } /package.conf.d/"*.conf $out/package.conf.d
76- cp -f "${ getLibComponent p } /package.conf.d/"*.conf $out/package.conf.d
77- '' ) component . depends }
100+ for l in "${ cfgFiles } "; do
101+ if [ -n "$l" ]; then
102+ cp -f "$l/${ packageCfgDir } /"*.conf $out/${ packageCfgDir }
103+ fi
104+ done
105+ for l in "${ libs } "; do
106+ if [ -n "$l" ]; then
107+ cp -f "$l/package.conf.d/"*.conf $out/${ packageCfgDir }
108+ fi
109+ done
78110
79111 # Note: we pass `clear` first to ensure that we never consult the implicit global package db.
80- ${ flagsAndConfig "package-db" [ "clear" "$out/package.conf.d " ] }
112+ ${ flagsAndConfig "package-db" [ "clear" "$out/${ packageCfgDir } " ] }
81113
82114 echo ${ lib . concatStringsSep " " ( lib . mapAttrsToList ( fname : val : "--flags=${ lib . optionalString ( ! val ) "-" + fname } " ) flags ) } >> $out/configure-flags
83115
@@ -86,17 +118,17 @@ in { identifier, component, fullName, flags ? {} }:
86118
87119 # Provide a GHC environment file
88120 cat > $out/ghc-environment <<EOF
89- package-db $out/package.conf.d
121+ package-db $out/${ packageCfgDir }
90122 EOF
91123
92- ${ lib . concatMapStringsSep "\n " catPkgEnvDep component . depends }
124+ ${ lib . concatMapStringsSep "\n " catPkgEnvDep libDeps }
93125 ${ lib . concatMapStringsSep "\n " catGhcPkgEnvDep ( lib . remove "ghc" nonReinstallablePkgs ) }
94126 '' + lib . optionalString component . doExactConfig ''
95127 echo "--exact-configuration" >> $out/configure-flags
96128 echo "allow-newer: ${ identifier . name } :*" >> $out/cabal.config
97129 echo "allow-older: ${ identifier . name } :*" >> $out/cabal.config
98130
99- ${ lib . concatMapStringsSep "\n " catPkgExactDep component . depends }
131+ ${ lib . concatMapStringsSep "\n " catPkgExactDep libDeps }
100132 ${ lib . concatMapStringsSep "\n " catGhcPkgExactDep nonReinstallablePkgs }
101133
102134 ''
@@ -116,10 +148,12 @@ in { identifier, component, fullName, flags ? {} }:
116148 # (e.g. libiconv), and thus we don't want to fail, but just link it again.
117149 #
118150 # Confusing sed stuff:
119- # '/^ ./{H;$!d} ; x' Groups lines that start with a space with the initial
120- # line of a block. Needs a blank line added to the file
121- # to terminate the last block.
122- # 's/ /\n/g ; s/\n\n*/\n/g; s/^\n//;' Puts each field on its own line.
151+ # '/^ ./{H;$!d} ; x' Groups lines that start with a space with the initial
152+ # line of a block. Needs a blank line added to the file
153+ # to terminate the last block.
154+ # 's/ /\n/g ; s/\n\n*/\n/g; s/^\n//;' Puts each field on its own line.
155+ # 's|/nix/store/|''${pkgroot}/../../../|' Convert store path to pkgroot relative path
156+ # 's|''${pkgroot}/../../../|/nix/store/|' Convert pkgroot relative path to store path
123157 + lib . optionalString stdenv . isDarwin ''
124158 # Work around a limit in the macOS Sierra linker on the number of paths
125159 # referenced by any one dynamic library:
@@ -128,20 +162,25 @@ in { identifier, component, fullName, flags ? {} }:
128162 # libraries) from all the dependencies.
129163 local dynamicLinksDir="$out/lib/links"
130164 mkdir -p $dynamicLinksDir
165+ # Enumerate dynamic-library-dirs with '' ${pkgroot} expanded.
131166 local dirsToLink=$(
132- for f in "$out/package.conf.d /"*.conf; do
167+ for f in "$out/${ packageCfgDir } /"*.conf; do
133168 (cat $f; echo) | sed -En '/^ ./{H;$!d} ; x ; /^dynamic-library-dirs:/ {s/^dynamic-library-dirs:// ; s/ /\n/g ; s/\n\n*/\n/g; s/^\n//; p}'
134- done | sort -u
169+ done | sed 's| '' ${pkgroot}/../../../|/nix/store/|' | sort -u
135170 )
136171 for d in $dirsToLink; do
137172 ln -f -s "$d/"*.dylib $dynamicLinksDir
138173 done
139174 # Edit the local package DB to reference the links directory.
140- for f in "$out/package.conf.d /"*.conf; do
175+ for f in "$out/${ packageCfgDir } /"*.conf; do
141176 chmod +w $f
142177 echo >> $f
143178 sed -i -E "/^ ./{H;$!d} ; x ; s,^dynamic-library-dirs:.*,dynamic-library-dirs: $dynamicLinksDir," $f
144179 done
145180 '' + ''
146- ${ target-pkg } -v0 --package-db $out/package.conf.d recache
181+ # Use '' ${pkgroot} relative paths so that we can relocate the package database
182+ # along with referenced packages and still have it work on systems with
183+ # or without nix installed.
184+ sed -i 's|/nix/store/|'' ${pkgroot}/../../../|' $out/${ packageCfgDir } /*.conf
185+ ${ target-pkg } -v0 --package-db $out/${ packageCfgDir } recache
147186 '' )
0 commit comments