|
| 1 | +{ stdenv, targetPackages |
| 2 | + |
| 3 | +# build-tools |
| 4 | +, bootPkgs |
| 5 | +, autoconf, automake, coreutils, fetchurl, fetchpatch, perl, python3, m4, sphinx |
| 6 | + |
| 7 | +, libiconv ? null, ncurses |
| 8 | + |
| 9 | +, # GHC can be built with system libffi or a bundled one. |
| 10 | + libffi ? null |
| 11 | + |
| 12 | +, useLLVM ? !stdenv.targetPlatform.isx86 || (stdenv.targetPlatform.isMusl && stdenv.hostPlatform != stdenv.targetPlatform) |
| 13 | +, # LLVM is conceptually a run-time-only depedendency, but for |
| 14 | + # non-x86, we need LLVM to bootstrap later stages, so it becomes a |
| 15 | + # build-time dependency too. |
| 16 | + buildLlvmPackages, llvmPackages |
| 17 | + |
| 18 | +, # If enabled, GHC will be built with the GPL-free but slower integer-simple |
| 19 | + # library instead of the faster but GPLed integer-gmp library. |
| 20 | + enableIntegerSimple ? !(stdenv.lib.any (stdenv.lib.meta.platformMatch stdenv.hostPlatform) gmp.meta.platforms), gmp |
| 21 | + |
| 22 | +, # If enabled, use -fPIC when compiling static libs. |
| 23 | + enableRelocatedStaticLibs ? stdenv.targetPlatform != stdenv.hostPlatform |
| 24 | + |
| 25 | +, # Whether to build dynamic libs for the standard library (on the target |
| 26 | + # platform). Static libs are always built. |
| 27 | + enableShared ? !stdenv.targetPlatform.isWindows && !stdenv.targetPlatform.useiOSPrebuilt |
| 28 | + |
| 29 | +, # Whetherto build terminfo. |
| 30 | + enableTerminfo ? !stdenv.targetPlatform.isWindows |
| 31 | + |
| 32 | +, # What flavour to build. An empty string indicates no |
| 33 | + # specific flavour and falls back to ghc default values. |
| 34 | + ghcFlavour ? stdenv.lib.optionalString (stdenv.targetPlatform != stdenv.hostPlatform) "perf-cross" |
| 35 | +}: |
| 36 | + |
| 37 | +assert !enableIntegerSimple -> gmp != null; |
| 38 | + |
| 39 | +let |
| 40 | + inherit (stdenv) buildPlatform hostPlatform targetPlatform; |
| 41 | + |
| 42 | + inherit (bootPkgs) ghc; |
| 43 | + |
| 44 | + # TODO(@Ericson2314) Make unconditional |
| 45 | + targetPrefix = stdenv.lib.optionalString |
| 46 | + (targetPlatform != hostPlatform) |
| 47 | + "${targetPlatform.config}-"; |
| 48 | + |
| 49 | + buildMK = '' |
| 50 | + BuildFlavour = ${ghcFlavour} |
| 51 | + ifneq \"\$(BuildFlavour)\" \"\" |
| 52 | + include mk/flavours/\$(BuildFlavour).mk |
| 53 | + endif |
| 54 | + DYNAMIC_GHC_PROGRAMS = ${if enableShared then "YES" else "NO"} |
| 55 | + INTEGER_LIBRARY = ${if enableIntegerSimple then "integer-simple" else "integer-gmp"} |
| 56 | + '' + stdenv.lib.optionalString (targetPlatform != hostPlatform) '' |
| 57 | + Stage1Only = ${if targetPlatform.system == hostPlatform.system then "NO" else "YES"} |
| 58 | + CrossCompilePrefix = ${targetPrefix} |
| 59 | + HADDOCK_DOCS = NO |
| 60 | + BUILD_SPHINX_HTML = NO |
| 61 | + BUILD_SPHINX_PDF = NO |
| 62 | + '' + stdenv.lib.optionalString enableRelocatedStaticLibs '' |
| 63 | + GhcLibHcOpts += -fPIC |
| 64 | + GhcRtsHcOpts += -fPIC |
| 65 | + '' + stdenv.lib.optionalString targetPlatform.useAndroidPrebuilt '' |
| 66 | + EXTRA_CC_OPTS += -std=gnu99 |
| 67 | + ''; |
| 68 | + |
| 69 | + # Splicer will pull out correct variations |
| 70 | + libDeps = platform: stdenv.lib.optional enableTerminfo [ ncurses ] |
| 71 | + ++ [libffi] |
| 72 | + ++ stdenv.lib.optional (!enableIntegerSimple) gmp |
| 73 | + ++ stdenv.lib.optional (platform.libc != "glibc" && !targetPlatform.isWindows) libiconv; |
| 74 | + |
| 75 | + toolsForTarget = |
| 76 | + if hostPlatform == buildPlatform then |
| 77 | + [ targetPackages.stdenv.cc ] ++ stdenv.lib.optional useLLVM llvmPackages.llvm |
| 78 | + else assert targetPlatform == hostPlatform; # build != host == target |
| 79 | + [ stdenv.cc ] ++ stdenv.lib.optional useLLVM buildLlvmPackages.llvm; |
| 80 | + |
| 81 | + targetCC = builtins.head toolsForTarget; |
| 82 | + |
| 83 | +in |
| 84 | +stdenv.mkDerivation (rec { |
| 85 | + version = "8.6.4"; |
| 86 | + name = "${targetPrefix}ghc-${version}"; |
| 87 | + |
| 88 | + src = fetchurl { |
| 89 | + url = "https://downloads.haskell.org/~ghc/${version}/ghc-${version}-src.tar.xz"; |
| 90 | + sha256 = "0fihs1sr0hpk67dn9cmrsav13kkcp9hz8ggdqcrs80rj8vj0fpav"; |
| 91 | + }; |
| 92 | + |
| 93 | + enableParallelBuilding = true; |
| 94 | + |
| 95 | + outputs = [ "out" "doc" ]; |
| 96 | + |
| 97 | + patches = [(fetchpatch rec { # https://phabricator.haskell.org/D5123 |
| 98 | + url = "http://tarballs.nixos.org/sha256/${sha256}"; |
| 99 | + name = "D5123.diff"; |
| 100 | + sha256 = "0nhqwdamf2y4gbwqxcgjxs0kqx23w9gv5kj0zv6450dq19rji82n"; |
| 101 | + })]; |
| 102 | + |
| 103 | + postPatch = "patchShebangs ."; |
| 104 | + |
| 105 | + # GHC is a bit confused on its cross terminology. |
| 106 | + preConfigure = '' |
| 107 | + for env in $(env | grep '^TARGET_' | sed -E 's|\+?=.*||'); do |
| 108 | + export "''${env#TARGET_}=''${!env}" |
| 109 | + done |
| 110 | + # GHC is a bit confused on its cross terminology, as these would normally be |
| 111 | + # the *host* tools. |
| 112 | + export CC="${targetCC}/bin/${targetCC.targetPrefix}cc" |
| 113 | + export CXX="${targetCC}/bin/${targetCC.targetPrefix}cxx" |
| 114 | + # Use gold to work around https://sourceware.org/bugzilla/show_bug.cgi?id=16177 |
| 115 | + export LD="${targetCC.bintools}/bin/${targetCC.bintools.targetPrefix}ld${stdenv.lib.optionalString targetPlatform.isAarch32 ".gold"}" |
| 116 | + export AS="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}as" |
| 117 | + export AR="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}ar" |
| 118 | + export NM="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}nm" |
| 119 | + export RANLIB="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}ranlib" |
| 120 | + export READELF="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}readelf" |
| 121 | + export STRIP="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}strip" |
| 122 | +
|
| 123 | + echo -n "${buildMK}" > mk/build.mk |
| 124 | + sed -i -e 's|-isysroot /Developer/SDKs/MacOSX10.5.sdk||' configure |
| 125 | + '' + stdenv.lib.optionalString (!stdenv.isDarwin) '' |
| 126 | + export NIX_LDFLAGS+=" -rpath $out/lib/ghc-${version}" |
| 127 | + '' + stdenv.lib.optionalString stdenv.isDarwin '' |
| 128 | + export NIX_LDFLAGS+=" -no_dtrace_dof" |
| 129 | + '' + stdenv.lib.optionalString targetPlatform.useAndroidPrebuilt '' |
| 130 | + sed -i -e '5i ,("armv7a-unknown-linux-androideabi", ("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", "cortex-a8", ""))' llvm-targets |
| 131 | + '' + stdenv.lib.optionalString targetPlatform.isMusl '' |
| 132 | + echo "patching llvm-targets for musl targets..." |
| 133 | + echo "Cloning these existing '*-linux-gnu*' targets:" |
| 134 | + grep linux-gnu llvm-targets | sed 's/^/ /' |
| 135 | + echo "(go go gadget sed)" |
| 136 | + sed -i 's,\(^.*linux-\)gnu\(.*\)$,\0\n\1musl\2,' llvm-targets |
| 137 | + echo "llvm-targets now contains these '*-linux-musl*' targets:" |
| 138 | + grep linux-musl llvm-targets | sed 's/^/ /' |
| 139 | +
|
| 140 | + echo "And now patching to preserve '-musleabi' as done with '-gnueabi'" |
| 141 | + # (aclocal.m4 is actual source, but patch configure as well since we don't re-gen) |
| 142 | + for x in configure aclocal.m4; do |
| 143 | + substituteInPlace $x \ |
| 144 | + --replace '*-android*|*-gnueabi*)' \ |
| 145 | + '*-android*|*-gnueabi*|*-musleabi*)' |
| 146 | + done |
| 147 | + ''; |
| 148 | + |
| 149 | + # TODO(@Ericson2314): Always pass "--target" and always prefix. |
| 150 | + configurePlatforms = [ "build" "host" ] |
| 151 | + ++ stdenv.lib.optional (targetPlatform != hostPlatform) "target"; |
| 152 | + # `--with` flags for libraries needed for RTS linker |
| 153 | + configureFlags = [ |
| 154 | + "--datadir=$doc/share/doc/ghc" |
| 155 | + "--with-curses-includes=${ncurses.dev}/include" "--with-curses-libraries=${ncurses.out}/lib" |
| 156 | + ] ++ stdenv.lib.optionals (libffi != null) ["--with-system-libffi" "--with-ffi-includes=${libffi.dev}/include" "--with-ffi-libraries=${libffi.out}/lib" |
| 157 | + ] ++ stdenv.lib.optional (targetPlatform == hostPlatform && !enableIntegerSimple) [ |
| 158 | + "--with-gmp-includes=${targetPackages.gmp.dev}/include" "--with-gmp-libraries=${targetPackages.gmp.out}/lib" |
| 159 | + ] ++ stdenv.lib.optional (targetPlatform == hostPlatform && hostPlatform.libc != "glibc" && !targetPlatform.isWindows) [ |
| 160 | + "--with-iconv-includes=${libiconv}/include" "--with-iconv-libraries=${libiconv}/lib" |
| 161 | + ] ++ stdenv.lib.optionals (targetPlatform != hostPlatform) [ |
| 162 | + "--enable-bootstrap-with-devel-snapshot" |
| 163 | + ] ++ stdenv.lib.optionals (targetPlatform.isAarch32) [ |
| 164 | + "CFLAGS=-fuse-ld=gold" |
| 165 | + "CONF_GCC_LINKER_OPTS_STAGE1=-fuse-ld=gold" |
| 166 | + "CONF_GCC_LINKER_OPTS_STAGE2=-fuse-ld=gold" |
| 167 | + ] ++ stdenv.lib.optionals (targetPlatform.isDarwin && targetPlatform.isAarch64) [ |
| 168 | + # fix for iOS: https://www.reddit.com/r/haskell/comments/4ttdz1/building_an_osxi386_to_iosarm64_cross_compiler/d5qvd67/ |
| 169 | + "--disable-large-address-space" |
| 170 | + ]; |
| 171 | + |
| 172 | + # Make sure we never relax`$PATH` and hooks support for compatability. |
| 173 | + strictDeps = true; |
| 174 | + |
| 175 | + # Don’t add -liconv to LDFLAGS automatically so that GHC will add it itself. |
| 176 | + dontAddExtraLibs = true; |
| 177 | + |
| 178 | + nativeBuildInputs = [ |
| 179 | + perl autoconf automake m4 python3 sphinx |
| 180 | + ghc bootPkgs.alex bootPkgs.happy bootPkgs.hscolour |
| 181 | + ]; |
| 182 | + |
| 183 | + # For building runtime libs |
| 184 | + depsBuildTarget = toolsForTarget; |
| 185 | + |
| 186 | + buildInputs = [ perl ] ++ (libDeps hostPlatform); |
| 187 | + |
| 188 | + propagatedBuildInputs = [ targetPackages.stdenv.cc ] |
| 189 | + ++ stdenv.lib.optional useLLVM llvmPackages.llvm; |
| 190 | + |
| 191 | + depsTargetTarget = map stdenv.lib.getDev (libDeps targetPlatform); |
| 192 | + depsTargetTargetPropagated = map (stdenv.lib.getOutput "out") (libDeps targetPlatform); |
| 193 | + |
| 194 | + # required, because otherwise all symbols from HSffi.o are stripped, and |
| 195 | + # that in turn causes GHCi to abort |
| 196 | + stripDebugFlags = [ "-S" ] ++ stdenv.lib.optional (!targetPlatform.isDarwin) "--keep-file-symbols"; |
| 197 | + |
| 198 | + checkTarget = "test"; |
| 199 | + |
| 200 | + hardeningDisable = [ "format" ] ++ stdenv.lib.optional stdenv.targetPlatform.isMusl "pie"; |
| 201 | + |
| 202 | + postInstall = '' |
| 203 | + # Install the bash completion file. |
| 204 | + install -D -m 444 utils/completion/ghc.bash $out/share/bash-completion/completions/${targetPrefix}ghc |
| 205 | +
|
| 206 | + # Patch scripts to include "readelf" and "cat" in $PATH. |
| 207 | + for i in "$out/bin/"*; do |
| 208 | + test ! -h $i || continue |
| 209 | + egrep --quiet '^#!' <(head -n 1 $i) || continue |
| 210 | + sed -i -e '2i export PATH="$PATH:${stdenv.lib.makeBinPath [ targetPackages.stdenv.cc.bintools coreutils ]}"' $i |
| 211 | + done |
| 212 | + ''; |
| 213 | + |
| 214 | + passthru = { |
| 215 | + inherit bootPkgs targetPrefix; |
| 216 | + |
| 217 | + inherit llvmPackages; |
| 218 | + inherit enableShared; |
| 219 | + |
| 220 | + # Our Cabal compiler name |
| 221 | + haskellCompilerName = "ghc-8.6.4"; |
| 222 | + }; |
| 223 | + |
| 224 | + meta = { |
| 225 | + homepage = http://haskell.org/ghc; |
| 226 | + description = "The Glasgow Haskell Compiler"; |
| 227 | + maintainers = with stdenv.lib.maintainers; [ marcweber andres peti ]; |
| 228 | + inherit (ghc.meta) license platforms; |
| 229 | + }; |
| 230 | + |
| 231 | +} // stdenv.lib.optionalAttrs targetPlatform.useAndroidPrebuilt { |
| 232 | + dontStrip = true; |
| 233 | + dontPatchELF = true; |
| 234 | + noAuditTmpdir = true; |
| 235 | +}) |
0 commit comments