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