Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{ 2 lib, 3 stdenv, 4 fetchurl, 5 perl, 6 gcc, 7 ncurses5, 8 ncurses6, 9 gmp, 10 libiconv, 11 numactl, 12 libffi, 13 llvmPackages, 14 coreutils, 15 targetPackages, 16 17 # minimal = true; will remove files that aren't strictly necessary for 18 # regular builds and GHC bootstrapping. 19 # This is "useful" for staying within hydra's output limits for at least the 20 # aarch64-linux architecture. 21 minimal ? false, 22}: 23 24# Prebuilt only does native 25assert stdenv.targetPlatform == stdenv.hostPlatform; 26 27let 28 downloadsUrl = "https://downloads.haskell.org/ghc"; 29 30 # Copy sha256 from https://downloads.haskell.org/~ghc/9.2.4/SHA256SUMS 31 version = "9.2.4"; 32 33 # Information about available bindists that we use in the build. 34 # 35 # # Bindist library checking 36 # 37 # The field `archSpecificLibraries` also provides a way for us get notified 38 # early when the upstream bindist changes its dependencies (e.g. because a 39 # newer Debian version is used that uses a new `ncurses` version). 40 # 41 # Usage: 42 # 43 # * You can find the `fileToCheckFor` of libraries by running `readelf -d` 44 # on the compiler binary (`exePathForLibraryCheck`). 45 # * To skip library checking for an architecture, 46 # set `exePathForLibraryCheck = null`. 47 # * To skip file checking for a specific arch specific library, 48 # set `fileToCheckFor = null`. 49 ghcBinDists = { 50 # Binary distributions for the default libc (e.g. glibc, or libSystem on Darwin) 51 # nixpkgs uses for the respective system. 52 defaultLibc = { 53 i686-linux = { 54 variantSuffix = ""; 55 src = { 56 url = "${downloadsUrl}/${version}/ghc-${version}-i386-deb9-linux.tar.xz"; 57 sha256 = "5dc1eb9c65f01b1e5c5693af72af07a4e9e75c6920e620fd598daeefa804487a"; 58 }; 59 exePathForLibraryCheck = "ghc/stage2/build/tmp/ghc-stage2"; 60 archSpecificLibraries = [ 61 { 62 nixPackage = gmp; 63 fileToCheckFor = null; 64 } 65 # The i686-linux bindist provided by GHC HQ is currently built on Debian 9, 66 # which link it against `libtinfo.so.5` (ncurses 5). 67 # Other bindists are linked `libtinfo.so.6` (ncurses 6). 68 { 69 nixPackage = ncurses5; 70 fileToCheckFor = "libtinfo.so.5"; 71 } 72 ]; 73 }; 74 x86_64-linux = { 75 variantSuffix = ""; 76 src = { 77 url = "${downloadsUrl}/${version}/ghc-${version}-x86_64-deb10-linux.tar.xz"; 78 sha256 = "a77a91a39d9b0167124b7e97648b2b52973ae0978cb259e0d44f0752a75037cb"; 79 }; 80 exePathForLibraryCheck = "ghc/stage2/build/tmp/ghc-stage2"; 81 archSpecificLibraries = [ 82 { 83 nixPackage = gmp; 84 fileToCheckFor = null; 85 } 86 { 87 nixPackage = ncurses6; 88 fileToCheckFor = "libtinfo.so.6"; 89 } 90 ]; 91 }; 92 aarch64-linux = { 93 variantSuffix = ""; 94 src = { 95 url = "${downloadsUrl}/${version}/ghc-${version}-aarch64-deb10-linux.tar.xz"; 96 sha256 = "fc7dbc6bae36ea5ac30b7e9a263b7e5be3b45b0eb3e893ad0bc2c950a61f14ec"; 97 }; 98 exePathForLibraryCheck = "ghc/stage2/build/tmp/ghc-stage2"; 99 archSpecificLibraries = [ 100 { 101 nixPackage = gmp; 102 fileToCheckFor = null; 103 } 104 { 105 nixPackage = ncurses6; 106 fileToCheckFor = "libtinfo.so.6"; 107 } 108 { 109 nixPackage = numactl; 110 fileToCheckFor = null; 111 } 112 ]; 113 }; 114 x86_64-darwin = { 115 variantSuffix = ""; 116 src = { 117 url = "${downloadsUrl}/${version}/ghc-${version}-x86_64-apple-darwin.tar.xz"; 118 sha256 = "f2e8366fd3754dd9388510792aba2d2abecb1c2f7f1e5555f6065c3c5e2ffec4"; 119 }; 120 exePathForLibraryCheck = null; # we don't have a library check for darwin yet 121 archSpecificLibraries = [ 122 { 123 nixPackage = gmp; 124 fileToCheckFor = null; 125 } 126 { 127 nixPackage = ncurses6; 128 fileToCheckFor = null; 129 } 130 { 131 nixPackage = libiconv; 132 fileToCheckFor = null; 133 } 134 ]; 135 isHadrian = true; 136 }; 137 aarch64-darwin = { 138 variantSuffix = ""; 139 src = { 140 url = "${downloadsUrl}/${version}/ghc-${version}-aarch64-apple-darwin.tar.xz"; 141 sha256 = "8cf8408544a1a43adf1bbbb0dd6b074efadffc68bfa1a792947c52e825171224"; 142 }; 143 exePathForLibraryCheck = null; # we don't have a library check for darwin yet 144 archSpecificLibraries = [ 145 { 146 nixPackage = gmp; 147 fileToCheckFor = null; 148 } 149 { 150 nixPackage = ncurses6; 151 fileToCheckFor = null; 152 } 153 { 154 nixPackage = libiconv; 155 fileToCheckFor = null; 156 } 157 ]; 158 isHadrian = true; 159 }; 160 }; 161 # Binary distributions for the musl libc for the respective system. 162 musl = { 163 x86_64-linux = { 164 variantSuffix = "-musl"; 165 src = { 166 url = "${downloadsUrl}/${version}/ghc-${version}-x86_64-alpine3.12-linux-gmp.tar.xz"; 167 sha256 = "026348947d30a156b84de5d6afeaa48fdcb2795b47954cd8341db00d3263a481"; 168 }; 169 isStatic = true; 170 isHadrian = true; 171 # We can't check the RPATH for statically linked executable 172 exePathForLibraryCheck = null; 173 archSpecificLibraries = [ 174 { 175 nixPackage = gmp.override { withStatic = true; }; 176 fileToCheckFor = null; 177 } 178 ]; 179 }; 180 }; 181 }; 182 183 distSetName = if stdenv.hostPlatform.isMusl then "musl" else "defaultLibc"; 184 185 binDistUsed = 186 ghcBinDists.${distSetName}.${stdenv.hostPlatform.system} 187 or (throw "cannot bootstrap GHC on this platform ('${stdenv.hostPlatform.system}' with libc '${distSetName}')"); 188 189 gmpUsed = 190 (builtins.head ( 191 builtins.filter ( 192 drv: lib.hasPrefix "gmp" (drv.nixPackage.name or "") 193 ) binDistUsed.archSpecificLibraries 194 )).nixPackage; 195 196 useLLVM = !(import ./common-have-ncg.nix { inherit lib stdenv version; }); 197 198 libPath = lib.makeLibraryPath ( 199 # Add arch-specific libraries. 200 map ({ nixPackage, ... }: nixPackage) binDistUsed.archSpecificLibraries 201 ); 202 203 libEnvVar = lib.optionalString stdenv.hostPlatform.isDarwin "DY" + "LD_LIBRARY_PATH"; 204 205 runtimeDeps = [ 206 targetPackages.stdenv.cc 207 targetPackages.stdenv.cc.bintools 208 coreutils # for cat 209 ] 210 ++ lib.optionals useLLVM [ 211 (lib.getBin llvmPackages.llvm) 212 ] 213 # On darwin, we need unwrapped bintools as well (for otool) 214 ++ lib.optionals (stdenv.targetPlatform.linker == "cctools") [ 215 targetPackages.stdenv.cc.bintools.bintools 216 ]; 217 218in 219 220stdenv.mkDerivation { 221 inherit version; 222 pname = "ghc-binary${binDistUsed.variantSuffix}"; 223 224 src = fetchurl binDistUsed.src; 225 226 nativeBuildInputs = [ perl ]; 227 228 # Set LD_LIBRARY_PATH or equivalent so that the programs running as part 229 # of the bindist installer can find the libraries they expect. 230 # Cannot patchelf beforehand due to relative RPATHs that anticipate 231 # the final install location. 232 ${libEnvVar} = libPath; 233 234 postUnpack = 235 # Verify our assumptions of which `libtinfo.so` (ncurses) version is used, 236 # so that we know when ghc bindists upgrade that and we need to update the 237 # version used in `libPath`. 238 lib.optionalString (binDistUsed.exePathForLibraryCheck != null) 239 # Note the `*` glob because some GHCs have a suffix when unpacked, e.g. 240 # the musl bindist has dir `ghc-VERSION-x86_64-unknown-linux/`. 241 # As a result, don't shell-quote this glob when splicing the string. 242 ( 243 let 244 buildExeGlob = ''ghc-${version}*/"${binDistUsed.exePathForLibraryCheck}"''; 245 in 246 lib.concatStringsSep "\n" [ 247 ('' 248 shopt -u nullglob 249 echo "Checking that ghc binary exists in bindist at ${buildExeGlob}" 250 if ! test -e ${buildExeGlob}; then 251 echo >&2 "GHC binary ${binDistUsed.exePathForLibraryCheck} could not be found in the bindist build directory (at ${buildExeGlob}) for arch ${stdenv.hostPlatform.system}, please check that ghcBinDists correctly reflect the bindist dependencies!"; exit 1; 252 fi 253 '') 254 (lib.concatMapStringsSep "\n" ( 255 { fileToCheckFor, nixPackage }: 256 lib.optionalString (fileToCheckFor != null) '' 257 echo "Checking bindist for ${fileToCheckFor} to ensure that is still used" 258 if ! readelf -d ${buildExeGlob} | grep "${fileToCheckFor}"; then 259 echo >&2 "File ${fileToCheckFor} could not be found in ${binDistUsed.exePathForLibraryCheck} for arch ${stdenv.hostPlatform.system}, please check that ghcBinDists correctly reflect the bindist dependencies!"; exit 1; 260 fi 261 262 echo "Checking that the nix package ${nixPackage} contains ${fileToCheckFor}" 263 if ! test -e "${lib.getLib nixPackage}/lib/${fileToCheckFor}"; then 264 echo >&2 "Nix package ${nixPackage} did not contain ${fileToCheckFor} for arch ${stdenv.hostPlatform.system}, please check that ghcBinDists correctly reflect the bindist dependencies!"; exit 1; 265 fi 266 '' 267 ) binDistUsed.archSpecificLibraries) 268 ] 269 ) 270 # GHC has dtrace probes, which causes ld to try to open /usr/lib/libdtrace.dylib 271 # during linking 272 + lib.optionalString stdenv.hostPlatform.isDarwin '' 273 export NIX_LDFLAGS+=" -no_dtrace_dof" 274 # not enough room in the object files for the full path to libiconv :( 275 for exe in $(find . -type f -executable); do 276 isScript $exe && continue 277 ln -fs ${libiconv}/lib/libiconv.dylib $(dirname $exe)/libiconv.dylib 278 install_name_tool -change /usr/lib/libiconv.2.dylib @executable_path/libiconv.dylib -change /usr/local/lib/gcc/6/libgcc_s.1.dylib ${gcc.cc.lib}/lib/libgcc_s.1.dylib $exe 279 done 280 '' 281 + 282 283 # Some scripts used during the build need to have their shebangs patched 284 '' 285 patchShebangs ghc-${version}/utils/ 286 patchShebangs ghc-${version}/configure 287 test -d ghc-${version}/inplace/bin && \ 288 patchShebangs ghc-${version}/inplace/bin 289 '' 290 + 291 # We have to patch the GMP paths for the integer-gmp package. 292 '' 293 find . -name ghc-bignum.buildinfo \ 294 -exec sed -i "s@extra-lib-dirs: @extra-lib-dirs: ${lib.getLib gmpUsed}/lib@" {} \; 295 296 # we need to modify the package db directly for hadrian bindists 297 find . -name 'ghc-bignum*.conf' \ 298 -exec sed -e '/^[a-z-]*library-dirs/a \ ${lib.getLib gmpUsed}/lib' -i {} \; 299 '' 300 + lib.optionalString stdenv.hostPlatform.isDarwin '' 301 # we need to modify the package db directly for hadrian bindists 302 # (all darwin bindists are hadrian-based for 9.2.2) 303 find . -name 'base*.conf' \ 304 -exec sed -e '/^[a-z-]*library-dirs/a \ ${lib.getLib libiconv}/lib' -i {} \; 305 306 # To link RTS in the end we also need libffi now 307 find . -name 'rts*.conf' \ 308 -exec sed -e '/^[a-z-]*library-dirs/a \ ${lib.getLib libffi}/lib' \ 309 -e 's@/Library/Developer/.*/usr/include/ffi@${lib.getDev libffi}/include@' \ 310 -i {} \; 311 '' 312 + 313 # Some platforms do HAVE_NUMA so -lnuma requires it in library-dirs in rts/package.conf.in 314 # FFI_LIB_DIR is a good indication of places it must be needed. 315 lib.optionalString 316 ( 317 lib.meta.availableOn stdenv.hostPlatform numactl 318 && builtins.any ({ nixPackage, ... }: nixPackage == numactl) binDistUsed.archSpecificLibraries 319 ) 320 '' 321 find . -name package.conf.in \ 322 -exec sed -i "s@FFI_LIB_DIR@FFI_LIB_DIR ${numactl.out}/lib@g" {} \; 323 '' 324 + 325 # Rename needed libraries and binaries, fix interpreter 326 lib.optionalString stdenv.hostPlatform.isLinux '' 327 find . -type f -executable -exec patchelf \ 328 --interpreter ${stdenv.cc.bintools.dynamicLinker} {} \; 329 ''; 330 331 # fix for `configure: error: Your linker is affected by binutils #16177` 332 preConfigure = lib.optionalString stdenv.targetPlatform.isAarch32 "LD=ld.gold"; 333 334 configurePlatforms = [ ]; 335 configureFlags = [ 336 "--with-gmp-includes=${lib.getDev gmpUsed}/include" 337 # Note `--with-gmp-libraries` does nothing for GHC bindists: 338 # https://gitlab.haskell.org/ghc/ghc/-/merge_requests/6124 339 ] 340 ++ lib.optional stdenv.hostPlatform.isDarwin "--with-gcc=${./gcc-clang-wrapper.sh}" 341 # From: https://github.com/NixOS/nixpkgs/pull/43369/commits 342 ++ lib.optional stdenv.hostPlatform.isMusl "--disable-ld-override"; 343 344 # No building is necessary, but calling make without flags ironically 345 # calls install-strip ... 346 dontBuild = true; 347 348 # GHC tries to remove xattrs when installing to work around Gatekeeper 349 # (see https://gitlab.haskell.org/ghc/ghc/-/issues/17418). This step normally 350 # succeeds in nixpkgs because xattrs are not allowed in the store, but it 351 # can fail when a file has the `com.apple.provenance` xattr, and it can’t be 352 # modified (such as target of the symlink to `libiconv.dylib`). 353 # The `com.apple.provenance` xattr is a new feature of macOS as of macOS 13. 354 # See: https://eclecticlight.co/2023/03/13/ventura-has-changed-app-quarantine-with-a-new-xattr/ 355 makeFlags = lib.optionals stdenv.buildPlatform.isDarwin [ "XATTR=/does-not-exist" ]; 356 357 # Patch scripts to include runtime dependencies in $PATH. 358 postInstall = '' 359 for i in "$out/bin/"*; do 360 test ! -h "$i" || continue 361 isScript "$i" || continue 362 sed -i -e '2i export PATH="${lib.makeBinPath runtimeDeps}:$PATH"' "$i" 363 done 364 ''; 365 366 # Apparently necessary for the ghc Alpine (musl) bindist: 367 # When we strip, and then run the 368 # patchelf --set-rpath "${libPath}:$(patchelf --print-rpath $p)" $p 369 # below, running ghc (e.g. during `installCheckPhase)` gives some apparently 370 # corrupted rpath or whatever makes the loader work on nonsensical strings: 371 # running install tests 372 # Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: : symbol not found 373 # Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: ir6zf6c9f86pfx8sr30n2vjy-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/../lib/x86_64-linux-ghc-8.10.5/libHSexceptions-0.10.4-ghc8.10.5.so: symbol not found 374 # Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: y/lib/ghc-8.10.5/bin/../lib/x86_64-linux-ghc-8.10.5/libHStemplate-haskell-2.16.0.0-ghc8.10.5.so: symbol not found 375 # Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: 8.10.5/libHStemplate-haskell-2.16.0.0-ghc8.10.5.so: symbol not found 376 # Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: �: symbol not found 377 # Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: �?: symbol not found 378 # Error relocating /nix/store/...-ghc-8.10.2-binary/lib/ghc-8.10.5/bin/ghc: 64-linux-ghc-8.10.5/libHSexceptions-0.10.4-ghc8.10.5.so: symbol not found 379 # This is extremely bogus and should be investigated. 380 dontStrip = if stdenv.hostPlatform.isMusl then true else false; # `if` for explicitness 381 382 # On Linux, use patchelf to modify the executables so that they can 383 # find editline/gmp. 384 postFixup = 385 lib.optionalString (stdenv.hostPlatform.isLinux && !(binDistUsed.isStatic or false)) ( 386 if stdenv.hostPlatform.isAarch64 then 387 # Keep rpath as small as possible on aarch64 for patchelf#244. All Elfs 388 # are 2 directories deep from $out/lib, so pooling symlinks there makes 389 # a short rpath. 390 '' 391 (cd $out/lib; ln -s ${ncurses6.out}/lib/libtinfo.so.6) 392 (cd $out/lib; ln -s ${lib.getLib gmpUsed}/lib/libgmp.so.10) 393 (cd $out/lib; ln -s ${numactl.out}/lib/libnuma.so.1) 394 for p in $(find "$out/lib" -type f -name "*\.so*"); do 395 (cd $out/lib; ln -s $p) 396 done 397 398 for p in $(find "$out/lib" -type f -executable); do 399 if isELF "$p"; then 400 echo "Patchelfing $p" 401 patchelf --set-rpath "\$ORIGIN:\$ORIGIN/../.." $p 402 fi 403 done 404 '' 405 else 406 '' 407 for p in $(find "$out" -type f -executable); do 408 if isELF "$p"; then 409 echo "Patchelfing $p" 410 patchelf --set-rpath "${libPath}:$(patchelf --print-rpath $p)" $p 411 fi 412 done 413 '' 414 ) 415 + lib.optionalString stdenv.hostPlatform.isDarwin '' 416 # not enough room in the object files for the full path to libiconv :( 417 for exe in $(find "$out" -type f -executable); do 418 isScript $exe && continue 419 ln -fs ${libiconv}/lib/libiconv.dylib $(dirname $exe)/libiconv.dylib 420 install_name_tool -change /usr/lib/libiconv.2.dylib @executable_path/libiconv.dylib -change /usr/local/lib/gcc/6/libgcc_s.1.dylib ${gcc.cc.lib}/lib/libgcc_s.1.dylib $exe 421 done 422 423 for file in $(find "$out" -name setup-config); do 424 substituteInPlace $file --replace /usr/bin/ranlib "$(type -P ranlib)" 425 done 426 '' 427 + lib.optionalString minimal '' 428 # Remove profiling files 429 find $out -type f -name '*.p_o' -delete 430 find $out -type f -name '*.p_hi' -delete 431 find $out -type f -name '*_p.a' -delete 432 # `-f` because e.g. musl bindist does not have this file. 433 rm -f $out/lib/ghc-*/bin/ghc-iserv-prof 434 # Hydra will redistribute this derivation, so we have to keep the docs for 435 # legal reasons (retaining the legal notices etc) 436 # As a last resort we could unpack the docs separately and symlink them in. 437 # They're in $out/share/{doc,man}. 438 '' 439 # Recache package db which needs to happen for Hadrian bindists 440 # where we modify the package db before installing 441 + '' 442 shopt -s nullglob 443 package_db=("$out"/lib/ghc-*/lib/package.conf.d "$out"/lib/ghc-*/package.conf.d) 444 "$out/bin/ghc-pkg" --package-db="$package_db" recache 445 ''; 446 447 # GHC cannot currently produce outputs that are ready for `-pie` linking. 448 # Thus, disable `pie` hardening, otherwise `recompile with -fPIE` errors appear. 449 # See: 450 # * https://github.com/NixOS/nixpkgs/issues/129247 451 # * https://gitlab.haskell.org/ghc/ghc/-/issues/19580 452 hardeningDisable = [ "pie" ]; 453 454 doInstallCheck = true; 455 installCheckPhase = '' 456 # Sanity check, can ghc create executables? 457 cd $TMP 458 mkdir test-ghc; cd test-ghc 459 cat > main.hs << EOF 460 {-# LANGUAGE TemplateHaskell #-} 461 module Main where 462 main = putStrLn \$([|"yes"|]) 463 EOF 464 env -i $out/bin/ghc --make main.hs || exit 1 465 echo compilation ok 466 [ $(./main) == "yes" ] 467 ''; 468 469 passthru = { 470 targetPrefix = ""; 471 enableShared = true; 472 473 inherit llvmPackages; 474 475 # Our Cabal compiler name 476 haskellCompilerName = "ghc-${version}"; 477 } 478 # We duplicate binDistUsed here since we have a sensible default even if no bindist is available, 479 # this makes sure that getting the `meta` attribute doesn't throw even on unsupported platforms. 480 // lib.optionalAttrs (ghcBinDists.${distSetName}.${stdenv.hostPlatform.system}.isHadrian or false) { 481 # Normal GHC derivations expose the hadrian derivation used to build them 482 # here. In the case of bindists we just make sure that the attribute exists, 483 # as it is used for checking if a GHC derivation has been built with hadrian. 484 # The isHadrian mechanism will become obsolete with GHCs that use hadrian 485 # exclusively, i.e. 9.6 (and 9.4?). 486 hadrian = null; 487 }; 488 489 meta = rec { 490 homepage = "http://haskell.org/ghc"; 491 description = "Glasgow Haskell Compiler"; 492 license = lib.licenses.bsd3; 493 # HACK: since we can't encode the libc / abi in platforms, we need 494 # to make the platform list dependent on the evaluation platform 495 # in order to avoid eval errors with musl which supports less 496 # platforms than the default libcs (i. e. glibc / libSystem). 497 # This is done for the benefit of Hydra, so `packagePlatforms` 498 # won't return any platforms that would cause an evaluation 499 # failure for `pkgsMusl.haskell.compiler.ghc922Binary`, as 500 # long as the evaluator runs on a platform that supports 501 # `pkgsMusl`. 502 platforms = builtins.attrNames ghcBinDists.${distSetName}; 503 teams = [ lib.teams.haskell ]; 504 }; 505}