Skip to content

Commit af03ecc

Browse files
committed
Use setup-depends from nix-tools output
1 parent b82a06c commit af03ecc

File tree

2 files changed

+115
-21
lines changed

2 files changed

+115
-21
lines changed

builder/hspkg-builder.nix

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, buildGHC, fetchurl, runCommand, pkgconfig, comp-builder }:
1+
{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, buildGHC, fetchurl, runCommand, pkgconfig, comp-builder, nonReinstallablePkgs, hsPkgs }:
22

33

44
{ flags
@@ -51,26 +51,13 @@ let
5151

5252
setup = if package.buildType == "Simple"
5353
then defaultSetup
54-
else stdenv.mkDerivation {
55-
name = "${name}-setup";
56-
nativeBuildInputs = [buildGHC];
57-
inherit src;
58-
phases = ["unpackPhase" "buildPhase" "installPhase"];
59-
buildPhase = ''
60-
for f in Setup.hs Setup.lhs; do
61-
if [ -f $f ]; then
62-
echo Compiling package $f
63-
ghc $f --make -o ./Setup
64-
setup=$(pwd)/Setup
65-
fi
66-
done
67-
[ -f ./Setup ] || (echo Failed to build Setup && exit 1)
68-
'';
69-
70-
installPhase = ''
71-
mkdir -p $out/bin
72-
install ./Setup $out/bin/Setup
73-
'';
54+
else haskellLib.weakCallPackage pkgs ./setup-builder.nix {
55+
ghc = buildGHC;
56+
setup-depends = package.setup-depends;
57+
hsPkgs = hsPkgs.buildPackages;
58+
inherit haskellLib nonReinstallablePkgs
59+
package name src flags pkgconfig
60+
;
7461
};
7562

7663
buildComp = componentId: component: comp-builder {

builder/setup-builder.nix

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
{ stdenv, buildPackages, ghc, lib, pkgconfig, writeText, runCommand
2+
, haskellLib, nonReinstallablePkgs, hsPkgs, setup-depends
3+
, package, name, src, flags }:
4+
5+
let
6+
fullName = "${name}-setup";
7+
8+
flagsAndConfig = field: xs: lib.optionalString (xs != []) ''
9+
echo ${lib.concatStringsSep " " (map (x: "--${field}=${x}") xs)} >> $out/configure-flags
10+
echo "${field}: ${lib.concatStringsSep " " xs}" >> $out/cabal.config
11+
'';
12+
13+
flatDepends =
14+
let
15+
makePairs = map (p: rec { key="${val}"; val=(p.components.library or p); });
16+
closure = builtins.genericClosure {
17+
startSet = makePairs setup-depends;
18+
operator = {val,...}: makePairs val.config.depends;
19+
};
20+
in map ({val,...}: val) closure;
21+
22+
configFiles = runCommand "${fullName}-config" { nativeBuildInputs = [ghc]; } (''
23+
mkdir -p $out
24+
25+
# Calls ghc-pkg for the target platform
26+
target-pkg() {
27+
${ghc.targetPrefix}ghc-pkg "$@"
28+
}
29+
30+
target-pkg init $out/package.conf.d
31+
32+
# Copy over the nonReinstallablePkgs from the global package db.
33+
# Note: we need to use --global-package-db with ghc-pkg to prevent it
34+
# from looking into the implicit global package db when registering the package.
35+
${lib.concatMapStringsSep "\n" (p: ''
36+
target-pkg describe ${p} | target-pkg --force --global-package-db $out/package.conf.d register - || true
37+
'') nonReinstallablePkgs}
38+
39+
${lib.concatMapStringsSep "\n" (p: ''
40+
target-pkg --package-db ${p}/package.conf.d dump | target-pkg --force --package-db $out/package.conf.d register -
41+
'') flatDepends}
42+
43+
# Note: we pass `clear` first to ensure that we never consult the implicit global package db.
44+
${flagsAndConfig "package-db" ["clear" "$out/package.conf.d"]}
45+
46+
echo ${lib.concatStringsSep " " (lib.mapAttrsToList (fname: val: "--flags=${lib.optionalString (!val) "-" + fname}") flags)} >> $out/configure-flags
47+
48+
''
49+
# This code originates in the `generic-builder.nix` from nixpkgs. However GHC has been fixed
50+
# to drop unused libraries referneced from libraries; and this patch is usually included in the
51+
# nixpkgs's GHC builds. This doesn't sadly make this stupid hack unnecessary. It resurfes in
52+
# the form of Cabal trying to be smart. Cabal when linking a library figures out that you likely
53+
# need those `rpath` entries, and passes `-optl-Wl,-rpath,...` for each dynamic library path to
54+
# GHC, thus subverting the linker and forcing it to insert all those RPATHs weather or not they
55+
# are needed. We therfore reuse the linker hack here to move all al dynamic lirbaries into a
56+
# common folder (as links) and thus prevent Cabal from going nuts.
57+
#
58+
# TODO: Fix Cabal.
59+
# TODO: this is only needed if we do dynamic libraries.
60+
+ lib.optionalString stdenv.isDarwin ''
61+
# Work around a limit in the macOS Sierra linker on the number of paths
62+
# referenced by any one dynamic library:
63+
#
64+
# Create a local directory with symlinks of the *.dylib (macOS shared
65+
# libraries) from all the dependencies.
66+
local dynamicLinksDir="$out/lib/links"
67+
mkdir -p $dynamicLinksDir
68+
for d in $(grep dynamic-library-dirs "$out/package.conf.d/"*|awk '{print $2}'|sort -u); do
69+
ln -s "$d/"*.dylib $dynamicLinksDir
70+
done
71+
# Edit the local package DB to reference the links directory.
72+
for f in "$out/package.conf.d/"*.conf; do
73+
sed -i "s,dynamic-library-dirs: .*,dynamic-library-dirs: $dynamicLinksDir," $f
74+
done
75+
'' + ''
76+
target-pkg --package-db $out/package.conf.d recache
77+
'' + ''
78+
target-pkg --package-db $out/package.conf.d check
79+
'');
80+
81+
in stdenv.lib.fix (drv:
82+
83+
stdenv.mkDerivation {
84+
name = "${fullName}";
85+
inherit src;
86+
nativeBuildInputs = [ghc];
87+
88+
CABAL_CONFIG = configFiles + /cabal.config;
89+
phases = ["unpackPhase" "buildPhase" "installPhase"];
90+
buildPhase = ''
91+
for f in Setup.hs Setup.lhs; do
92+
if [ -f $f ]; then
93+
echo Compiling package $f
94+
ghc $f --make -o ./Setup
95+
setup=$(pwd)/Setup
96+
fi
97+
done
98+
[ -f ./Setup ] || (echo Failed to build Setup && exit 1)
99+
'';
100+
101+
installPhase = ''
102+
mkdir -p $out/bin
103+
install ./Setup $out/bin/Setup
104+
'';
105+
})
106+
107+

0 commit comments

Comments
 (0)