nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 lib,
3 stdenv,
4 fetchurl,
5 perl,
6 gcc,
7 ncurses5,
8 ncurses6,
9 gmp,
10 libiconv,
11 numactl,
12 libffi,
13 coreutils,
14 targetPackages,
15}:
16
17# Prebuilt only does native
18assert stdenv.targetPlatform == stdenv.hostPlatform;
19
20let
21 version = "9.6.6";
22
23 # GHC upstream doesn't release bindist tarballs for some platforms.
24 # We're using Debian's binary package, and patching it into a usable-in-Nixpkgs state.
25 ghcDebs = {
26 powerpc64-linux = {
27 src = {
28 urls = [
29 "http://ftp.ports.debian.org/debian-ports/pool-ppc64/main/g/ghc/ghc_9.6.6-4_ppc64.deb"
30 "https://snapshot.debian.org/archive/debian-ports/20250917T193713Z/pool-ppc64/main/g/ghc/ghc_9.6.6-4_ppc64.deb"
31 ];
32 sha256 = "722cc301b6ba70b342e5e3d9d0671440bcd749cd2f13dcccbd23c3f6a6060171";
33 };
34 exePathForLibraryCheck = null;
35 archSpecificLibraries = [
36 {
37 nixPackage = gmp;
38 fileToCheckFor = null;
39 }
40 {
41 nixPackage = ncurses6;
42 fileToCheckFor = "libtinfo.so.6";
43 }
44 {
45 nixPackage = numactl;
46 fileToCheckFor = null;
47 }
48 {
49 nixPackage = libffi;
50 fileToCheckFor = null;
51 }
52 ];
53 };
54 };
55
56 debUsed =
57 ghcDebs.${stdenv.hostPlatform.system}
58 or (throw "cannot bootstrap GHC on this platform ('${stdenv.hostPlatform.system}') from Debian debs");
59
60 gmpUsed =
61 (builtins.head (
62 builtins.filter (drv: lib.hasPrefix "gmp" (drv.nixPackage.name or "")) debUsed.archSpecificLibraries
63 )).nixPackage;
64
65 runtimeDeps = [
66 targetPackages.stdenv.cc
67 targetPackages.stdenv.cc.bintools
68 coreutils # for cat
69 ];
70
71 extraLibraryMapping = {
72 gmp = gmpUsed;
73 numa = numactl;
74 ffi = libffi;
75 };
76
77in
78
79stdenv.mkDerivation (finalAttrs: {
80 inherit version;
81 pname = "ghc-debian-binary";
82
83 src = fetchurl debUsed.src;
84
85 nativeBuildInputs = [ perl ];
86
87 sourceRoot = "${finalAttrs.pname}-${finalAttrs.version}";
88
89 # Custom unpack phase to handle .deb files
90 unpackPhase = ''
91 runHook preUnpack
92
93 ar x $src
94 tar xf data.tar.xz
95 mkdir -p ${finalAttrs.sourceRoot}
96 mv -t ${finalAttrs.sourceRoot}/ usr var
97
98 runHook postUnpack
99 '';
100
101 postUnpack =
102 # Verify our assumptions of which `libtinfo.so` (ncurses) version is used,
103 # so that we know when ghc debs upgrade that and we need to update the
104 # version used in `archSpecificLibraries`.
105 lib.optionalString (debUsed.exePathForLibraryCheck != null) (
106 lib.concatStringsSep "\n" [
107 ''
108 shopt -u nullglob
109 echo "Checking that ghc binary exists in deb at ${debUsed.exePathForLibraryCheck}"
110 if ! test -e ${debUsed.exePathForLibraryCheck}; then
111 echo >&2 "GHC binary ${debUsed.exePathForLibraryCheck} could not be found in the deb unpack directory for arch ${stdenv.hostPlatform.system}, please check that ghcDebs correctly reflect the deb dependencies!"; exit 1;
112 fi
113 ''
114 (lib.concatMapStringsSep "\n" (
115 { fileToCheckFor, nixPackage }:
116 lib.optionalString (fileToCheckFor != null) ''
117 echo "Checking deb for ${fileToCheckFor} to ensure that is still used"
118 if ! readelf -d ${debUsed.exePathForLibraryCheck} | grep "${fileToCheckFor}"; then
119 echo >&2 "File ${fileToCheckFor} could not be found in ${debUsed.exePathForLibraryCheck} for arch ${stdenv.hostPlatform.system}, please check that ghcDebs correctly reflect the deb dependencies!"; exit 1;
120 fi
121
122 echo "Checking that the nix package ${nixPackage} contains ${fileToCheckFor}"
123 if ! test -e "${lib.getLib nixPackage}/lib/${fileToCheckFor}"; then
124 echo >&2 "Nix package ${nixPackage} did not contain ${fileToCheckFor} for arch ${stdenv.hostPlatform.system}, please check that ghcDebs correctly reflect the deb dependencies!"; exit 1;
125 fi
126 ''
127 ) debUsed.archSpecificLibraries)
128 ]
129 )
130
131 # Linking to non-compiler libraries requires GHC to know about our non-FHS paths for those libraries
132 + (lib.strings.concatMapAttrsStringSep "\n" (libName: libPackage: ''
133 for packageDbDir in $(find . -name package.conf.d); do
134 for packageDb in $(grep -l 'extra-libraries:.*${libName}' "$packageDbDir"/*.conf); do
135 echo "Patching include & library path for ${libName} into package DB: $packageDb"
136 sed -i "$packageDb" \
137 -e '/^[a-z-]*include-dirs/a \ ${lib.getDev libPackage}/include' \
138 -e '/^[a-z-]*library-dirs/a \ ${lib.getLib libPackage}/lib'
139 done
140 done
141 '') extraLibraryMapping)
142
143 +
144 # Rename needed libraries and binaries, fix interpreter
145 lib.optionalString stdenv.hostPlatform.isLinux ''
146 find . -type f -executable -exec patchelf \
147 --interpreter ${stdenv.cc.bintools.dynamicLinker} {} \;
148 '';
149
150 # Not a bindist, nothing to configure
151 dontConfigure = true;
152
153 # Not a bindist, it's already built
154 dontBuild = true;
155
156 # Install prebuilt GHC files
157 installPhase = ''
158 runHook preInstall
159
160 mkdir -p $out
161
162 cp -t $out/ -a usr/*
163 rm -f $out/lib/ghc/lib/package.conf.d
164 find var -name "package.conf.d" -type d -exec cp -a {} $out/lib/ghc/lib/ \;
165
166 runHook postInstall
167 '';
168
169 postInstall =
170 # Patch scripts to include runtime dependencies in $PATH.
171 ''
172 for i in "$out/bin/"*; do
173 test ! -h "$i" || continue
174 isScript "$i" || continue
175 sed -i -e '2i export PATH="${lib.makeBinPath runtimeDeps}:$PATH"' "$i"
176 done
177 ''
178
179 # Patch /usr paths
180 + ''
181 for i in "$out/bin/"*; do
182 test ! -h "$i" || continue
183 isScript "$i" || continue
184 substituteInPlace "$i" \
185 --replace-fail '="/usr' '="${placeholder "out"}'
186 done
187 find "$out/lib/ghc/lib/package.conf.d" -type f -name '*.conf' \
188 -exec sed -i "s|/usr/|$out/|g" {} +
189 ''
190
191 # Patch ghc settings
192 + ''
193 substituteInPlace $out/lib/ghc/lib/settings \
194 --replace-fail powerpc64-linux-gnu-gcc gcc \
195 --replace-fail powerpc64-linux-gnu-g++ g++ \
196 --replace-fail powerpc64-linux-gnu-ld ld \
197 --replace-fail powerpc64-linux-gnu-ar ar \
198 --replace-fail powerpc64-linux-gnu-ranlib ranlib \
199 --replace-fail llc-18 llc \
200 --replace-fail opt-18 opt
201 '';
202
203 # On Linux, use patchelf to modify the executables so that they can
204 # find editline/gmp.
205 postFixup =
206 lib.optionalString (stdenv.hostPlatform.isLinux && !(debUsed.isStatic or false))
207 # Keep rpath as small as possible, running autoPatchelf makes everything segfault (maybe similar to patchelf#244).
208 # All Elfs are 2 directories deep from $out/lib, so pooling symlinks there makes a short rpath.
209 ''
210 (cd $out/lib; ln -s ${ncurses6.out}/lib/libtinfo.so.6)
211 (cd $out/lib; ln -s ${lib.getLib gmpUsed}/lib/libgmp.so.10)
212 (cd $out/lib; ln -s ${numactl.out}/lib/libnuma.so.1)
213 (cd $out/lib; ln -s ${libffi.out}/lib/libffi.so.8)
214 for p in $(find "$out/lib" -type f -name "*\.so*"); do
215 (cd $out/lib; ln -s $p)
216 done
217
218 for p in $(find "$out/lib" -type f -executable); do
219 if isELF "$p"; then
220 echo "Patchelfing $p"
221 patchelf --set-rpath "\$ORIGIN:\$ORIGIN/../.." $p
222 fi
223 done
224 ''
225 # Recache package db which needs to happen because
226 # we modify the package db
227 + ''
228 "$out/bin/ghc-pkg" --package-db=$out/lib/ghc/lib/package.conf.d recache
229 '';
230
231 doInstallCheck = true;
232 installCheckPhase = ''
233 # Sanity check, can ghc create executables?
234 cd $TMP
235 mkdir test-ghc; cd test-ghc
236 cat > main.hs << EOF
237 {-# LANGUAGE TemplateHaskell #-}
238 module Main where
239 main = putStrLn \$([|"yes"|])
240 EOF
241 env -i $out/bin/ghc --make main.hs || exit 1
242 echo compilation ok
243 [ $(./main) == "yes" ]
244 '';
245
246 passthru = {
247 targetPrefix = "";
248 enableShared = true;
249
250 llvmPackages = null;
251
252 # Our Cabal compiler name
253 haskellCompilerName = "ghc-${version}";
254
255 # Normal GHC derivations expose the hadrian derivation used to build them
256 # here. In the case of debs we just make sure that the attribute exists,
257 # as it is used for checking if a GHC derivation has been built with hadrian.
258 hadrian = null;
259 };
260
261 meta = {
262 homepage = "http://haskell.org/ghc";
263 description = "Glasgow Haskell Compiler";
264 license = lib.licenses.bsd3;
265 platforms = builtins.attrNames ghcDebs;
266 maintainers = [ lib.maintainers.OPNA2608 ];
267 teams = [ lib.teams.haskell ];
268 };
269})