diff --git a/pkgs/development/compilers/ghc/9.6.6-debian-binary.nix b/pkgs/development/compilers/ghc/9.6.6-debian-binary.nix new file mode 100644 index 0000000000000..81af893586d70 --- /dev/null +++ b/pkgs/development/compilers/ghc/9.6.6-debian-binary.nix @@ -0,0 +1,267 @@ +{ + lib, + stdenv, + fetchurl, + perl, + gcc, + ncurses5, + ncurses6, + gmp, + libiconv, + numactl, + libffi, + coreutils, + targetPackages, +}: + +# Prebuilt only does native +assert stdenv.targetPlatform == stdenv.hostPlatform; + +let + version = "9.6.6"; + + # GHC upstream doesn't release bindist tarballs for some platforms. + # We're using Debian's binary package, and patching it into a usable-in-Nixpkgs state. + ghcDebs = { + powerpc64-linux = { + variantSuffix = ""; + src = { + url = "http://ftp.ports.debian.org/debian-ports/pool-ppc64/main/g/ghc/ghc_9.6.6-4_ppc64.deb"; + sha256 = "722cc301b6ba70b342e5e3d9d0671440bcd749cd2f13dcccbd23c3f6a6060171"; + }; + exePathForLibraryCheck = null; + archSpecificLibraries = [ + { + nixPackage = gmp; + fileToCheckFor = null; + } + { + nixPackage = ncurses6; + fileToCheckFor = "libtinfo.so.6"; + } + { + nixPackage = numactl; + fileToCheckFor = null; + } + { + nixPackage = libffi; + fileToCheckFor = null; + } + ]; + }; + }; + + debUsed = + ghcDebs.${stdenv.hostPlatform.system} + or (throw "cannot bootstrap GHC on this platform ('${stdenv.hostPlatform.system}') from Debian debs"); + + gmpUsed = + (builtins.head ( + builtins.filter (drv: lib.hasPrefix "gmp" (drv.nixPackage.name or "")) debUsed.archSpecificLibraries + )).nixPackage; + + runtimeDeps = [ + targetPackages.stdenv.cc + targetPackages.stdenv.cc.bintools + coreutils # for cat + ]; + + extraLibraryMapping = { + gmp = gmpUsed; + numa = numactl; + ffi = libffi; + }; + +in + +stdenv.mkDerivation (finalAttrs: { + inherit version; + pname = "ghc-debian-binary${debUsed.variantSuffix}"; + + src = fetchurl debUsed.src; + + nativeBuildInputs = [ perl ]; + + sourceRoot = "${finalAttrs.pname}-${finalAttrs.version}"; + + # Custom unpack phase to handle .deb files + unpackPhase = '' + runHook preUnpack + + ar x $src + tar xf data.tar.xz + mkdir -p ${finalAttrs.sourceRoot} + mv -t ${finalAttrs.sourceRoot}/ usr var + + runHook postUnpack + ''; + + postUnpack = + # Verify our assumptions of which `libtinfo.so` (ncurses) version is used, + # so that we know when ghc debs upgrade that and we need to update the + # version used in `archSpecificLibraries`. + lib.optionalString (debUsed.exePathForLibraryCheck != null) ( + lib.concatStringsSep "\n" [ + '' + shopt -u nullglob + echo "Checking that ghc binary exists in deb at ${debUsed.exePathForLibraryCheck}" + if ! test -e ${debUsed.exePathForLibraryCheck}; then + 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; + fi + '' + (lib.concatMapStringsSep "\n" ( + { fileToCheckFor, nixPackage }: + lib.optionalString (fileToCheckFor != null) '' + echo "Checking deb for ${fileToCheckFor} to ensure that is still used" + if ! readelf -d ${debUsed.exePathForLibraryCheck} | grep "${fileToCheckFor}"; then + 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; + fi + + echo "Checking that the nix package ${nixPackage} contains ${fileToCheckFor}" + if ! test -e "${lib.getLib nixPackage}/lib/${fileToCheckFor}"; then + 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; + fi + '' + ) debUsed.archSpecificLibraries) + ] + ) + + # Linking to non-compiler libraries requires GHC to know about our non-FHS paths for those libraries + + (lib.strings.concatMapAttrsStringSep "\n" (libName: libPackage: '' + for packageDbDir in $(find . -name package.conf.d); do + for packageDb in $(grep -l 'extra-libraries:.*${libName}' "$packageDbDir"/*.conf); do + echo "Patching include & library path for ${libName} into package DB: $packageDb" + sed -i "$packageDb" \ + -e '/^[a-z-]*include-dirs/a \ ${lib.getDev libPackage}/include' \ + -e '/^[a-z-]*library-dirs/a \ ${lib.getLib libPackage}/lib' + done + done + '') extraLibraryMapping) + + + + # Rename needed libraries and binaries, fix interpreter + lib.optionalString stdenv.hostPlatform.isLinux '' + find . -type f -executable -exec patchelf \ + --interpreter ${stdenv.cc.bintools.dynamicLinker} {} \; + ''; + + # Not a bindist, nothing to configure + dontConfigure = true; + + # Not a bindist, it's already built + dontBuild = true; + + # Install prebuilt GHC files + installPhase = '' + runHook preInstall + + mkdir -p $out + + cp -t $out/ -a usr/* + rm -f $out/lib/ghc/lib/package.conf.d + find var -name "package.conf.d" -type d -exec cp -a {} $out/lib/ghc/lib/ \; + + runHook postInstall + ''; + + postInstall = + # Patch scripts to include runtime dependencies in $PATH. + '' + for i in "$out/bin/"*; do + test ! -h "$i" || continue + isScript "$i" || continue + sed -i -e '2i export PATH="${lib.makeBinPath runtimeDeps}:$PATH"' "$i" + done + '' + + # Patch /usr paths + + '' + for i in "$out/bin/"*; do + test ! -h "$i" || continue + isScript "$i" || continue + substituteInPlace "$i" \ + --replace-fail '="/usr' '="${placeholder "out"}' + done + find "$out/lib/ghc/lib/package.conf.d" -type f -name '*.conf' \ + -exec sed -i "s|/usr/|$out/|g" {} + + '' + + # Patch ghc settings + + '' + substituteInPlace $out/lib/ghc/lib/settings \ + --replace-fail powerpc64-linux-gnu-gcc gcc \ + --replace-fail powerpc64-linux-gnu-g++ g++ \ + --replace-fail powerpc64-linux-gnu-ld ld \ + --replace-fail powerpc64-linux-gnu-ar ar \ + --replace-fail powerpc64-linux-gnu-ranlib ranlib \ + --replace-fail llc-18 llc \ + --replace-fail opt-18 opt + ''; + + # On Linux, use patchelf to modify the executables so that they can + # find editline/gmp. + postFixup = + lib.optionalString (stdenv.hostPlatform.isLinux && !(debUsed.isStatic or false)) + # Keep rpath as small as possible, running autoPatchelf makes everything segfault (maybe similar to patchelf#244). + # All Elfs are 2 directories deep from $out/lib, so pooling symlinks there makes a short rpath. + '' + (cd $out/lib; ln -s ${ncurses6.out}/lib/libtinfo.so.6) + (cd $out/lib; ln -s ${lib.getLib gmpUsed}/lib/libgmp.so.10) + (cd $out/lib; ln -s ${numactl.out}/lib/libnuma.so.1) + (cd $out/lib; ln -s ${libffi.out}/lib/libffi.so.8) + for p in $(find "$out/lib" -type f -name "*\.so*"); do + (cd $out/lib; ln -s $p) + done + + for p in $(find "$out/lib" -type f -executable); do + if isELF "$p"; then + echo "Patchelfing $p" + patchelf --set-rpath "\$ORIGIN:\$ORIGIN/../.." $p + fi + done + '' + # Recache package db which needs to happen because + # we modify the package db + + '' + "$out/bin/ghc-pkg" --package-db=$out/lib/ghc/lib/package.conf.d recache + ''; + + doInstallCheck = true; + installCheckPhase = '' + # Sanity check, can ghc create executables? + cd $TMP + mkdir test-ghc; cd test-ghc + cat > main.hs << EOF + {-# LANGUAGE TemplateHaskell #-} + module Main where + main = putStrLn \$([|"yes"|]) + EOF + env -i $out/bin/ghc --make main.hs || exit 1 + echo compilation ok + [ $(./main) == "yes" ] + ''; + + passthru = { + targetPrefix = ""; + enableShared = true; + + llvmPackages = null; + + # Our Cabal compiler name + haskellCompilerName = "ghc-${version}"; + + # Normal GHC derivations expose the hadrian derivation used to build them + # here. In the case of debs we just make sure that the attribute exists, + # as it is used for checking if a GHC derivation has been built with hadrian. + hadrian = null; + }; + + meta = { + homepage = "http://haskell.org/ghc"; + description = "Glasgow Haskell Compiler"; + license = lib.licenses.bsd3; + platforms = builtins.attrNames ghcDebs; + maintainers = [ lib.maintainers.OPNA2608 ]; + teams = [ lib.teams.haskell ]; + }; +}) diff --git a/pkgs/development/haskell-modules/configuration-common.nix b/pkgs/development/haskell-modules/configuration-common.nix index c08915cbc734b..c1a20e721b0dd 100644 --- a/pkgs/development/haskell-modules/configuration-common.nix +++ b/pkgs/development/haskell-modules/configuration-common.nix @@ -276,6 +276,8 @@ with haskellLib; # Ironically, we still need to build the doctest suite. # vector-0.13.2.0 has a doctest < 0.24 constraint jailbreak = true; + # inspection-testing doesn't work on all archs & ABIs + doCheck = !self.inspection-testing.meta.broken; }) super.vector; # https://github.com/lspitzner/data-tree-print/issues/4 @@ -694,6 +696,12 @@ with haskellLib; hash = "sha256-feGEuALVJ0Zl8zJPIfgEFry9eH/MxA0Aw7zlDq0PC/s="; }) super.algebraic-graphs; + # Relies on DWARF <-> register mappings in GHC, not available for every arch & ABI + # (check dwarfReturnRegNo in compiler/GHC/CmmToAsm/Dwarf/Constants.hs, that's where ppc64 elfv1 gives up) + inspection-testing = overrideCabal (drv: { + broken = with pkgs.stdenv.hostPlatform; !(isx86 || (isPower64 && isAbiElfv2) || isAarch64); + }) super.inspection-testing; + # Too strict bounds on filepath, hpsec, tasty, tasty-quickcheck, transformers # https://github.com/illia-shkroba/pfile/issues/3 pfile = doJailbreak super.pfile; @@ -2432,6 +2440,26 @@ with haskellLib; )) ]; + # Test failures on various archs + # https://github.com/kazu-yamamoto/crypton/issues/49 + crypton = dontCheckIf ( + pkgs.stdenv.hostPlatform.isPower64 && pkgs.stdenv.hostPlatform.isBigEndian + ) super.crypton; + + # Test failures on at least ppc64 + # https://github.com/kazu-yamamoto/crypton-certificate/issues/25 + # Likely related to the issues in crypton + # https://github.com/kazu-yamamoto/crypton/issues/49 + crypton-x509-validation = dontCheckIf ( + pkgs.stdenv.hostPlatform.isPower64 && pkgs.stdenv.hostPlatform.isBigEndian + ) super.crypton-x509-validation; + + # Likely fallout from the crypton issues + # exception: HandshakeFailed (Error_Protocol "bad PubKeyALG_Ed448 signature for ecdhparams" DecryptError) + tls = dontCheckIf ( + pkgs.stdenv.hostPlatform.isPower64 && pkgs.stdenv.hostPlatform.isBigEndian + ) super.tls; + # Too strict bounds on text and tls # https://github.com/barrucadu/irc-conduit/issues/54 # Use crypton-connection instead of connection @@ -2663,8 +2691,23 @@ with haskellLib; # hashable <1.4, mmorph <1.2 composite-aeson = doJailbreak super.composite-aeson; - # Overly strict bounds on tasty-quickcheck (test suite) (< 0.11) - hashable = doJailbreak super.hashable; + hashable = lib.pipe super.hashable [ + # Overly strict bounds on tasty-quickcheck (test suite) (< 0.11) + doJailbreak + + # Big-endian POWER: + # Test suite xxhash-tests: RUNNING... + # xxhash + # oneshot + # w64-ref: OK (0.03s) + # +++ OK, passed 100 tests. + # w64-examples: FAIL + # tests/xxhash-tests.hs:21: + # expected: 2768807632077661767 + # but got: 13521078365639231154 + # https://github.com/haskell-unordered-containers/hashable/issues/323 + (dontCheckIf pkgs.stdenv.hostPlatform.isBigEndian) + ]; cborg = appendPatches [ # This patch changes CPP macros form gating on the version of ghc-prim to base diff --git a/pkgs/top-level/haskell-packages.nix b/pkgs/top-level/haskell-packages.nix index 6cf6be084b438..cba689d91e98e 100644 --- a/pkgs/top-level/haskell-packages.nix +++ b/pkgs/top-level/haskell-packages.nix @@ -14,6 +14,7 @@ let "native-bignum" # Binary GHCs "ghc902Binary" + "ghc966DebianBinary" "ghc984Binary" ]; @@ -86,6 +87,8 @@ in inherit llvmPackages; }; + ghc966DebianBinary = callPackage ../development/compilers/ghc/9.6.6-debian-binary.nix { }; + ghc984Binary = callPackage ../development/compilers/ghc/9.8.4-binary.nix { }; ghc948 = callPackage ../development/compilers/ghc/9.4.8.nix { @@ -99,27 +102,69 @@ in }; ghc94 = compiler.ghc948; ghc967 = callPackage ../development/compilers/ghc/9.6.7.nix { - bootPkgs = bb.packages.ghc948; + bootPkgs = + if + stdenv.buildPlatform.isPower64 + && stdenv.buildPlatform.isBigEndian + && pkgs.stdenv.hostPlatform.isAbiElfv1 + then + # No bindist, "borrowing" the GHC from Debian + bb.packages.ghc966DebianBinary + else + bb.packages.ghc948; inherit (buildPackages.python3Packages) sphinx; inherit (buildPackages.darwin) xattr autoSignDarwinBinariesHook; inherit buildTargetLlvmPackages llvmPackages; }; ghc96 = compiler.ghc967; ghc984 = callPackage ../development/compilers/ghc/9.8.4.nix { - bootPkgs = if stdenv.buildPlatform.isi686 then bb.packages.ghc948 else bb.packages.ghc984Binary; + bootPkgs = + if + stdenv.buildPlatform.isPower64 + && stdenv.buildPlatform.isBigEndian + && pkgs.stdenv.hostPlatform.isAbiElfv1 + then + # No bindist, "borrowing" the GHC from Debian + bb.packages.ghc966DebianBinary + else if stdenv.buildPlatform.isi686 then + bb.packages.ghc948 + else + bb.packages.ghc984Binary; inherit (buildPackages.python3Packages) sphinx; inherit (buildPackages.darwin) xattr autoSignDarwinBinariesHook; inherit buildTargetLlvmPackages llvmPackages; }; ghc98 = compiler.ghc984; ghc9102 = callPackage ../development/compilers/ghc/9.10.2.nix { - bootPkgs = if stdenv.buildPlatform.isi686 then bb.packages.ghc967 else bb.packages.ghc984Binary; + bootPkgs = + if + stdenv.buildPlatform.isPower64 + && stdenv.buildPlatform.isBigEndian + && pkgs.stdenv.hostPlatform.isAbiElfv1 + then + # No bindist, "borrowing" the GHC from Debian + bb.packages.ghc966DebianBinary + else if stdenv.buildPlatform.isi686 then + bb.packages.ghc967 + else + bb.packages.ghc984Binary; inherit (buildPackages.python3Packages) sphinx; inherit (buildPackages.darwin) xattr autoSignDarwinBinariesHook; inherit buildTargetLlvmPackages llvmPackages; }; ghc9103 = callPackage ../development/compilers/ghc/9.10.3.nix { - bootPkgs = if stdenv.buildPlatform.isi686 then bb.packages.ghc967 else bb.packages.ghc984Binary; + bootPkgs = + if + stdenv.buildPlatform.isPower64 + && stdenv.buildPlatform.isBigEndian + && pkgs.stdenv.hostPlatform.isAbiElfv1 + then + # No bindist, "borrowing" the GHC from Debian + bb.packages.ghc966DebianBinary + else if stdenv.buildPlatform.isi686 then + bb.packages.ghc967 + else + bb.packages.ghc984Binary; inherit (buildPackages.python3Packages) sphinx; inherit (buildPackages.darwin) xattr autoSignDarwinBinariesHook; inherit buildTargetLlvmPackages llvmPackages; @@ -135,7 +180,16 @@ in }; ghc912 = compiler.ghc9122; ghcHEAD = callPackage ../development/compilers/ghc/head.nix { - bootPkgs = bb.packages.ghc984Binary; + bootPkgs = + if + stdenv.buildPlatform.isPower64 + && stdenv.buildPlatform.isBigEndian + && pkgs.stdenv.hostPlatform.isAbiElfv1 + then + # No bindist, using older source-built GHC + bb.packages.ghc910 + else + bb.packages.ghc984Binary; inherit (buildPackages.python3Packages) sphinx; inherit (buildPackages.darwin) xattr autoSignDarwinBinariesHook; inherit buildTargetLlvmPackages llvmPackages; @@ -180,6 +234,12 @@ in compilerConfig = callPackage ../development/haskell-modules/configuration-ghc-9.0.x.nix { }; packageSetConfig = bootstrapPackageSet; }; + ghc966DebianBinary = callPackage ../development/haskell-modules { + buildHaskellPackages = bh.packages.ghc966DebianBinary; + ghc = bh.compiler.ghc966DebianBinary; + compilerConfig = callPackage ../development/haskell-modules/configuration-ghc-9.6.x.nix { }; + packageSetConfig = bootstrapPackageSet; + }; ghc984Binary = callPackage ../development/haskell-modules { buildHaskellPackages = bh.packages.ghc984Binary; ghc = bh.compiler.ghc984Binary;