Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{ lib, stdenv, haskellPackages, symlinkJoin, makeWrapper 2# GHC will have LLVM available if necessary for the respective target, 3# so useLLVM only needs to be changed if -fllvm is to be used for a 4# platform that has NCG support 5, useLLVM ? false 6, withHoogle ? false 7, hoogleWithPackages 8, postBuild ? "" 9, ghcLibdir ? null # only used by ghcjs, when resolving plugins 10}: 11 12# This argument is a function which selects a list of Haskell packages from any 13# passed Haskell package set. 14# 15# Example: 16# (hpkgs: [ hpkgs.mtl hpkgs.lens ]) 17selectPackages: 18 19# It's probably a good idea to include the library "ghc-paths" in the 20# compiler environment, because we have a specially patched version of 21# that package in Nix that honors these environment variables 22# 23# NIX_GHC 24# NIX_GHCPKG 25# NIX_GHC_DOCDIR 26# NIX_GHC_LIBDIR 27# 28# instead of hard-coding the paths. The wrapper sets these variables 29# appropriately to configure ghc-paths to point back to the wrapper 30# instead of to the pristine GHC package, which doesn't know any of the 31# additional libraries. 32# 33# A good way to import the environment set by the wrapper below into 34# your shell is to add the following snippet to your ~/.bashrc: 35# 36# if [ -e ~/.nix-profile/bin/ghc ]; then 37# eval $(grep export ~/.nix-profile/bin/ghc) 38# fi 39 40let 41 inherit (haskellPackages) llvmPackages ghc; 42 43 packages = selectPackages haskellPackages 44 ++ lib.optional withHoogle (hoogleWithPackages selectPackages); 45 46 isGhcjs = ghc.isGhcjs or false; 47 isHaLVM = ghc.isHaLVM or false; 48 ghc761OrLater = isGhcjs || isHaLVM || lib.versionOlder "7.6.1" ghc.version; 49 packageDBFlag = if ghc761OrLater then "--global-package-db" else "--global-conf"; 50 ghcCommand' = if isGhcjs then "ghcjs" else "ghc"; 51 ghcCommand = "${ghc.targetPrefix}${ghcCommand'}"; 52 ghcCommandCaps= lib.toUpper ghcCommand'; 53 libDir = if isHaLVM then "$out/lib/HaLVM-${ghc.version}" 54 else "$out/lib/${ghc.targetPrefix}${ghc.haskellCompilerName}"; 55 docDir = "$out/share/doc/ghc/html"; 56 packageCfgDir = "${libDir}/package.conf.d"; 57 paths = lib.filter (x: x ? isHaskellLibrary) (lib.closePropagation packages); 58 hasLibraries = lib.any (x: x.isHaskellLibrary) paths; 59 # CLang is needed on Darwin for -fllvm to work: 60 # https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/codegens.html#llvm-code-generator-fllvm 61 llvm = lib.makeBinPath 62 ([ llvmPackages.llvm ] 63 ++ lib.optional stdenv.targetPlatform.isDarwin llvmPackages.clang); 64in 65 66assert ghcLibdir != null -> (ghc.isGhcjs or false); 67 68if paths == [] && !useLLVM then ghc else 69symlinkJoin { 70 # this makes computing paths from the name attribute impossible; 71 # if such a feature is needed, the real compiler name should be saved 72 # as a dedicated drv attribute, like `compiler-name` 73 name = ghc.name + "-with-packages"; 74 paths = paths ++ [ghc]; 75 nativeBuildInputs = [ makeWrapper ]; 76 postBuild = '' 77 # wrap compiler executables with correct env variables 78 79 for prg in ${ghcCommand} ${ghcCommand}i ${ghcCommand}-${ghc.version} ${ghcCommand}i-${ghc.version}; do 80 if [[ -x "${ghc}/bin/$prg" ]]; then 81 rm -f $out/bin/$prg 82 makeWrapper ${ghc}/bin/$prg $out/bin/$prg \ 83 --add-flags '"-B$NIX_${ghcCommandCaps}_LIBDIR"' \ 84 --set "NIX_${ghcCommandCaps}" "$out/bin/${ghcCommand}" \ 85 --set "NIX_${ghcCommandCaps}PKG" "$out/bin/${ghcCommand}-pkg" \ 86 --set "NIX_${ghcCommandCaps}_DOCDIR" "${docDir}" \ 87 --set "NIX_${ghcCommandCaps}_LIBDIR" "${libDir}" \ 88 ${lib.optionalString (ghc.isGhcjs or false) 89 ''--set NODE_PATH "${ghc.socket-io}/lib/node_modules"'' 90 } \ 91 ${lib.optionalString useLLVM ''--prefix "PATH" ":" "${llvm}"''} 92 fi 93 done 94 95 for prg in runghc runhaskell; do 96 if [[ -x "${ghc}/bin/$prg" ]]; then 97 rm -f $out/bin/$prg 98 makeWrapper ${ghc}/bin/$prg $out/bin/$prg \ 99 --add-flags "-f $out/bin/${ghcCommand}" \ 100 --set "NIX_${ghcCommandCaps}" "$out/bin/${ghcCommand}" \ 101 --set "NIX_${ghcCommandCaps}PKG" "$out/bin/${ghcCommand}-pkg" \ 102 --set "NIX_${ghcCommandCaps}_DOCDIR" "${docDir}" \ 103 --set "NIX_${ghcCommandCaps}_LIBDIR" "${libDir}" 104 fi 105 done 106 107 for prg in ${ghcCommand}-pkg ${ghcCommand}-pkg-${ghc.version}; do 108 if [[ -x "${ghc}/bin/$prg" ]]; then 109 rm -f $out/bin/$prg 110 makeWrapper ${ghc}/bin/$prg $out/bin/$prg --add-flags "${packageDBFlag}=${packageCfgDir}" 111 fi 112 done 113 114 # haddock was referring to the base ghc, https://github.com/NixOS/nixpkgs/issues/36976 115 if [[ -x "${ghc}/bin/haddock" ]]; then 116 rm -f $out/bin/haddock 117 makeWrapper ${ghc}/bin/haddock $out/bin/haddock \ 118 --add-flags '"-B$NIX_${ghcCommandCaps}_LIBDIR"' \ 119 --set "NIX_${ghcCommandCaps}_LIBDIR" "${libDir}" 120 fi 121 122 '' + (lib.optionalString (stdenv.targetPlatform.isDarwin && !isGhcjs && !stdenv.targetPlatform.isiOS) '' 123 # Work around a linker limit in macOS Sierra (see generic-builder.nix): 124 local packageConfDir="${packageCfgDir}"; 125 local dynamicLinksDir="$out/lib/links" 126 mkdir -p $dynamicLinksDir 127 # Clean up the old links that may have been (transitively) included by 128 # symlinkJoin: 129 rm -f $dynamicLinksDir/* 130 for d in $(grep -Poz "dynamic-library-dirs:\s*\K .+\n" $packageConfDir/*|awk '{print $2}'|sort -u); do 131 ln -s $d/*.dylib $dynamicLinksDir 132 done 133 for f in $packageConfDir/*.conf; do 134 # Initially, $f is a symlink to a read-only file in one of the inputs 135 # (as a result of this symlinkJoin derivation). 136 # Replace it with a copy whose dynamic-library-dirs points to 137 # $dynamicLinksDir 138 cp $f $f-tmp 139 rm $f 140 sed "N;s,dynamic-library-dirs:\s*.*,dynamic-library-dirs: $dynamicLinksDir," $f-tmp > $f 141 rm $f-tmp 142 done 143 '') + '' 144 ${lib.optionalString hasLibraries '' 145 # GHC 8.10 changes. 146 # Instead of replacing package.cache[.lock] with the new file, 147 # ghc-pkg is now trying to open the file. These file are symlink 148 # to another nix derivation, so they are not writable. Removing 149 # them allow the correct behavior of ghc-pkg recache 150 # See: https://github.com/NixOS/nixpkgs/issues/79441 151 rm ${packageCfgDir}/package.cache.lock 152 rm ${packageCfgDir}/package.cache 153 154 $out/bin/${ghcCommand}-pkg recache 155 ''} 156 ${# ghcjs will read the ghc_libdir file when resolving plugins. 157 lib.optionalString (isGhcjs && ghcLibdir != null) '' 158 mkdir -p "${libDir}" 159 rm -f "${libDir}/ghc_libdir" 160 printf '%s' '${ghcLibdir}' > "${libDir}/ghc_libdir" 161 ''} 162 $out/bin/${ghcCommand}-pkg check 163 '' + postBuild; 164 passthru = { 165 preferLocalBuild = true; 166 inherit (ghc) version meta; 167 168 # Inform users about backwards incompatibilities with <= 21.05 169 override = _: throw '' 170 The ghc.withPackages wrapper itself can now be overridden, but no longer 171 the result of calling it (as before). Consequently overrides need to be 172 adjusted: Instead of 173 174 (ghc.withPackages (p: [ p.my-package ])).override { withLLLVM = true; } 175 176 use 177 178 (ghc.withPackages.override { useLLVM = true; }) (p: [ p.my-package ]) 179 180 Also note that withLLVM has been renamed to useLLVM for consistency with 181 the GHC Nix expressions.''; 182 }; 183}