on iko/ghcjs-patch-master help sign in
Fix cross compilation issues for musl and aarch64 (#322)

* Enables tests for Musl and AArch64 (also rasbery pi, but leaves them disabled for now) and includes many fixes for the tests that were broken. * Makes Musl cross compiler more like native (including making `ghci` and `runghc` work) * Updates selection of enableShared * Works around missing configFiles attribute issue * Use ghc-extra-packages and compiler.nix-name to pick the right extra packages * Leaves out --cross-compile on hsc2hs for musl * Fixes haddock and hoogle for musl and disables them for other cross compilers * Adds ghc 8.8.3 * Static link components (except libraries and `all`) on musl * Use qemu for the arm cross compile `testWrapper` * Add isCrossHost and isCrossTarget functions * Fixes profiling on AArch64 * Disable split sections when compiling for windows (fixes GHC 8.8 cross compile to windows) * Disable hoogle in cross compiler shells for now

commit775c8cf756c08a779bbc587013c27f4f4b3df71a authorHamish Mackenzie <Hamish.Mackenzie@iohk.io> dateWed 4 Mar 2020, 16:07 (7 years ago) parent7c5c8e7
26 files changed+209−106
builder/comp-builder.nix+12−3 builder/default.nix+7−3 builder/ghc-for-component-wrapper.nix+9−4 builder/make-config-files.nix+2−1 builder/shell-for.nix+4−2 compiler/ghc/default.nix+39−10 lib/default.nix+11 nixpkgs/github.json+3−3 overlays/armv6l-linux.nix+2−2 overlays/bootstrap.nix+16 overlays/ghc.nix−4 overlays/haskell.nix+2−1 overlays/linux-cross.nix+3−2 overlays/windows.nix+2−2 release.nix+38−19 test/cabal-22/default.nix+7−3 test/cabal-simple-prof/default.nix+4−1 test/cabal-simple/default.nix+13−22 test/cabal-sublib/default.nix+5−2 test/exe-only/default.nix+4−1 test/fully-static/default.nix+1−6 test/setup-deps/default.nix+2−2 test/shell-for-setup-deps/default.nix+11−5 test/shell-for/default.nix+2−2 test/snapshots/default.nix+8−4 test/with-packages/default.nix+2−2
builder/comp-builder.nix+12−3
@@ -24,7 +24,7 @@
2424, dontStrip ? component.dontStrip
2525
2626, enableStatic ? component.enableStatic
27−, enableShared ? component.enableShared && !stdenv.hostPlatform.isWindows && !stdenv.hostPlatform.useiOSPrebuilt
27+, enableShared ? component.enableShared && !haskellLib.isCrossHost
2828, enableDeadCodeElimination ? component.enableDeadCodeElimination
2929
3030# Options for Haddock generation
@@ -95,11 +95,20 @@ let
9595 (enableFeature enableExecutableProfiling "executable-profiling")
9696 (enableFeature enableStatic "static")
9797 (enableFeature enableShared "shared")
98+ ] ++ lib.optionals (stdenv.hostPlatform.isMusl && (haskellLib.isExecutableType componentId)) [
99+ # These flags will make sure the resulting executable is statically linked.
100+ # If it uses other libraries it may be necessary for to add more
101+ # `--ghc-option=-optl=-L` options to the `configurationFlags` of the
102+ # component.
103+ "--disable-executable-dynamic"
104+ "--ghc-option=-optl=-pthread"
105+ "--ghc-option=-optl=-static"
106+ "--ghc-option=-optl=-L${gmp.override { withStatic = true; }}/lib"
98107 ] ++ lib.optional enableSeparateDataOutput "--datadir=$data/share/${ghc.name}"
99108 ++ lib.optional doHaddock' "--docdir=${docdir "$doc"}"
100109 ++ lib.optional (enableLibraryProfiling || enableExecutableProfiling) "--profiling-detail=${profilingDetail}"
101110 ++ lib.optional stdenv.hostPlatform.isLinux (enableFeature enableDeadCodeElimination "split-sections")
102− ++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) (
111+ ++ lib.optionals haskellLib.isCrossHost (
103112 map (arg: "--hsc2hs-option=" + arg) (["--cross-compile"] ++ lib.optionals (stdenv.hostPlatform.isWindows) ["--via-asm"])
104113 ++ lib.optional (package.buildType == "Configure") "--configure-option=--host=${stdenv.hostPlatform.config}" )
105114 ++ component.configureFlags
@@ -131,7 +140,7 @@ let
131140
132141 doHaddock' = doHaddock
133142 && (haskellLib.isLibrary componentId)
134− && stdenv.hostPlatform == stdenv.buildPlatform;
143+ && !haskellLib.isCrossHost;
135144
136145 exeExt = lib.optionalString stdenv.hostPlatform.isWindows ".exe";
137146 exeName = componentId.cname + exeExt;
builder/default.nix+7−3
@@ -39,10 +39,14 @@ let
3939
4040
4141 hoogleLocal = let
42− nixpkgsHoogleLocal = import (pkgs.path + /pkgs/development/haskell-modules/hoogle.nix);
43− in { packages ? [], hoogle ? pkgs.haskell-nix.haskellPackages.hoogle.components.exes.hoogle }:
42+ # Use the latest default nixpkgs hoogle.nix, as the 19.03 one does not work with cross compilers
43+ nixpkgsHoogleLocal = import ((import ../nixpkgs {}).path + /pkgs/development/haskell-modules/hoogle.nix);
44+ in { packages ? [], hoogle ? pkgs.buildPackages.haskell-nix.haskellPackages.hoogle.components.exes.hoogle }:
4445 haskellLib.weakCallPackage pkgs nixpkgsHoogleLocal {
45− ghc = pkgs.haskell-nix.ghc;
46+ # For musl we can use haddock from the buildGHC
47+ ghc = if stdenv.hostPlatform.isLinux && stdenv.targetPlatform.isMusl
48+ then ghc.buildGHC
49+ else ghc;
4650 inherit packages hoogle;
4751 };
4852
builder/ghc-for-component-wrapper.nix+9−4
@@ -15,14 +15,19 @@
1515}:
1616
1717let
18− inherit (configFiles) ghcCommand ghcCommandCaps packageCfgDir;
18+ inherit (configFiles) targetPrefix ghcCommand ghcCommandCaps packageCfgDir;
1919 libDir = "$out/${configFiles.libDir}";
2020 docDir = "$out/share/doc/ghc/html";
21+ # For musl we can use haddock from the buildGHC
22+ haddock = if stdenv.hostPlatform.isLinux && stdenv.targetPlatform.isMusl
23+ then ghc.buildGHC
24+ else ghc;
2125
2226in runCommand "${componentName}-${ghc.name}-env" {
2327 preferLocalBuild = true;
2428 passthru = {
2529 inherit (ghc) version meta;
30+ inherit targetPrefix;
2631 baseGhc = ghc;
2732 };
2833} (
@@ -62,7 +67,7 @@ in runCommand "${componentName}-${ghc.name}-env" {
6267 fi
6368 done
6469
65− for prg in runghc runhaskell; do
70+ for prg in "${targetPrefix}runghc" "${targetPrefix}runhaskell"; do
6671 if [[ -x "${ghc}/bin/$prg" ]]; then
6772 rm -f $out/bin/$prg
6873 makeWrapper ${ghc}/bin/$prg $out/bin/$prg \
@@ -75,9 +80,9 @@ in runCommand "${componentName}-${ghc.name}-env" {
7580 done
7681
7782 # Wrap haddock, if the base GHC provides it.
78− if [[ -x "${ghc}/bin/haddock" ]]; then
83+ if [[ -x "${haddock}/bin/haddock" ]]; then
7984 rm -f $out/bin/haddock
80− makeWrapper ${ghc}/bin/haddock $out/bin/haddock \
85+ makeWrapper ${haddock}/bin/haddock $out/bin/haddock \
8186 --add-flags '"-B$NIX_${ghcCommandCaps}_LIBDIR"' \
8287 --set "NIX_${ghcCommandCaps}_LIBDIR" "${libDir}"
8388 fi
builder/make-config-files.nix+2−1
@@ -66,7 +66,8 @@ let
6666in { identifier, component, fullName, flags ? {} }:
6767 # Filters out only library packages that for this GHC target
6868 # TODO investigate why this is needed
69− let libDeps = lib.filter (p: p.configFiles.targetPrefix == ghc.targetPrefix)
69+ # TODO find out why p ? configFiles helps (for instance for `R1909.aarch64-unknown-linux-gnu.tests.cabal-22.run.x86_64-linux`)
70+ let libDeps = lib.filter (p: (p ? configFiles) && p.configFiles.targetPrefix == ghc.targetPrefix)
7071 (map getLibComponent component.depends);
7172 cfgFiles =
7273 let xs = map
builder/shell-for.nix+4−2
@@ -12,6 +12,8 @@
1212, ... } @ args:
1313
1414let
15+ # TODO find out why hoogle index creation can be made to work for cross compilers
16+ withHoogle' = withHoogle && !haskellLib.isCrossHost;
1517 selected = packages hsPkgs;
1618 additionalSelected = additional hsPkgs;
1719 selectedConfigs = map (p: p.components.all.config) selected;
@@ -53,7 +55,7 @@ let
5355 ghcEnv = ghcForComponent {
5456 inherit configFiles;
5557 componentName = name;
56− postInstall = lib.optionalString withHoogle ''
58+ postInstall = lib.optionalString withHoogle' ''
5759 ln -s ${hoogleIndex}/bin/hoogle $out/bin
5860 '';
5961 };
@@ -79,7 +81,7 @@ in
7981
8082 buildInputs = systemInputs
8183 ++ mkDrvArgs.buildInputs or []
82− ++ lib.optional withHoogle hoogleIndex;
84+ ++ lib.optional withHoogle' hoogleIndex;
8385 nativeBuildInputs = [ ghcEnv ]
8486 ++ nativeBuildInputs
8587 ++ mkDrvArgs.nativeBuildInputs or [];
compiler/ghc/default.nix+39−10
@@ -3,7 +3,7 @@
33# haskell.nix ships its own version of the ghc expression as it needs more
44# control over the expression to isolate it against varying <nixpkgs> and
55# allow us to customize it to the way haskell.nix works.
6−{ stdenv, targetPackages
6+{ stdenv, haskell-nix, targetPackages
77
88# build-tools
99, bootPkgs
@@ -33,15 +33,24 @@
3333
3434, # Whether to build dynamic libs for the standard library (on the target
3535 # platform). Static libs are always built.
36− enableShared ? !stdenv.targetPlatform.isWindows && !stdenv.targetPlatform.useiOSPrebuilt
36+ enableShared ? !haskell-nix.haskellLib.isCrossTarget
3737
38−, # Whetherto build terminfo.
39− enableTerminfo ? !stdenv.targetPlatform.isWindows
38+, # Whetherto build terminfo. Musl fails to build terminfo as ncurses seems to be linked to glibc
39+ enableTerminfo ? !stdenv.targetPlatform.isWindows && !stdenv.targetPlatform.isMusl
4040
4141, # What flavour to build. An empty string indicates no
4242 # specific flavour and falls back to ghc default values.
43− ghcFlavour ? stdenv.lib.optionalString (stdenv.targetPlatform != stdenv.hostPlatform)
44− (if useLLVM then "quick-cross" else "perf-cross-ncg")
43+ ghcFlavour ? stdenv.lib.optionalString haskell-nix.haskellLib.isCrossTarget (
44+ if useLLVM
45+ then (
46+ # TODO check if the issues with qemu and Aarch32 persist. See
47+ # https://github.com/input-output-hk/haskell.nix/pull/411/commits/1986264683067198e7fdc1d665351622b664712e
48+ if stdenv.targetPlatform.isAarch32
49+ then "quick-cross"
50+ else "perf-cross"
51+ )
52+ else "perf-cross-ncg"
53+ )
4554
4655, # Whether to disable the large address space allocator
4756 # necessary fix for iOS: https://www.reddit.com/r/haskell/comments/4ttdz1/building_an_osxi386_to_iosarm64_cross_compiler/d5qvd67/
@@ -59,9 +68,15 @@ assert !enableIntegerSimple -> gmp != null;
5968
6069let
6170 inherit (stdenv) buildPlatform hostPlatform targetPlatform;
71+ inherit (haskell-nix.haskellLib) isCrossTarget;
6272
6373 inherit (bootPkgs) ghc;
6474
75+ # TODO check if this posible fix for segfaults works or not.
76+ libffiStaticEnabled = if libffi == null || !stdenv.targetPlatform.isMusl
77+ then libffi
78+ else targetPackages.libffi.overrideAttrs (old: { dontDisableStatic = true; });
79+
6580 # TODO(@Ericson2314) Make unconditional
6681 targetPrefix = stdenv.lib.optionalString
6782 (targetPlatform != hostPlatform)
@@ -75,8 +90,9 @@ let
7590 DYNAMIC_GHC_PROGRAMS = ${if enableShared then "YES" else "NO"}
7691 INTEGER_LIBRARY = ${if enableIntegerSimple then "integer-simple" else "integer-gmp"}
7792 '' + stdenv.lib.optionalString (targetPlatform != hostPlatform) ''
78− Stage1Only = ${if targetPlatform.system == hostPlatform.system then "NO" else "YES"}
7993 CrossCompilePrefix = ${targetPrefix}
94+ '' + stdenv.lib.optionalString isCrossTarget ''
95+ Stage1Only = ${if targetPlatform.system == hostPlatform.system then "NO" else "YES"}
8096 HADDOCK_DOCS = NO
8197 BUILD_SPHINX_HTML = NO
8298 BUILD_SPHINX_PDF = NO
@@ -88,11 +104,19 @@ let
88104 '' + stdenv.lib.optionalString useLLVM ''
89105 GhcStage2HcOpts += -fast-llvm
90106 GhcLibHcOpts += -fast-llvm
107+ '' + stdenv.lib.optionalString (!enableTerminfo) ''
108+ WITH_TERMINFO=NO
109+ ''
110+ # While split sections are now enabled by default in ghc 8.8 for windows,
111+ # the seem to lead to `too many sections` errors when building base for
112+ # profiling.
113+ + stdenv.lib.optionalString targetPlatform.isWindows ''
114+ SplitSections = NO
91115 '';
92116
93117 # Splicer will pull out correct variations
94118 libDeps = platform: stdenv.lib.optional enableTerminfo [ ncurses ]
95− ++ [libffi]
119+ ++ [libffiStaticEnabled]
96120 ++ stdenv.lib.optional (!enableIntegerSimple) gmp
97121 ++ stdenv.lib.optional (platform.libc != "glibc" && !targetPlatform.isWindows) libiconv;
98122
@@ -184,7 +208,7 @@ in let configured-src = stdenv.mkDerivation (rec {
184208 configureFlags = [
185209 "--datadir=$doc/share/doc/ghc"
186210 "--with-curses-includes=${ncurses.dev}/include" "--with-curses-libraries=${ncurses.out}/lib"
187− ] ++ stdenv.lib.optionals (libffi != null) ["--with-system-libffi" "--with-ffi-includes=${targetPackages.libffi.dev}/include" "--with-ffi-libraries=${targetPackages.libffi.out}/lib"
211+ ] ++ stdenv.lib.optionals (libffiStaticEnabled != null) ["--with-system-libffi" "--with-ffi-includes=${libffiStaticEnabled.dev}/include" "--with-ffi-libraries=${libffiStaticEnabled.out}/lib"
188212 ] ++ stdenv.lib.optional (!enableIntegerSimple) [
189213 "--with-gmp-includes=${targetPackages.gmp.dev}/include" "--with-gmp-libraries=${targetPackages.gmp.out}/lib"
190214 ] ++ stdenv.lib.optional (targetPlatform == hostPlatform && hostPlatform.libc != "glibc" && !targetPlatform.isWindows) [
@@ -298,7 +322,12 @@ in let configured-src = stdenv.mkDerivation (rec {
298322 for i in "$out/bin/"*; do
299323 test ! -h $i || continue
300324 egrep --quiet '^#!' <(head -n 1 $i) || continue
301− sed -i -e '2i export PATH="$PATH:${stdenv.lib.makeBinPath [ targetPackages.stdenv.cc.bintools coreutils ]}"' $i
325+ # The ghcprog fixup is for musl (where runhaskell script just needs to point to the correct
326+ # ghc program to work).
327+ sed -i \
328+ -e '2i export PATH="$PATH:${stdenv.lib.makeBinPath [ targetPackages.stdenv.cc.bintools coreutils ]}"' \
329+ -e 's/ghcprog="ghc-/ghcprog="${targetPrefix}ghc-/' \
330+ $i
302331 done
303332 '' + installDeps targetPrefix;
304333
lib/default.nix+11
@@ -177,4 +177,15 @@ with haskellLib;
177177 check = import ./check.nix {
178178 inherit stdenv lib haskellLib srcOnly;
179179 };
180+
181+ # Use `isCrossHost` to identify when we are cross compiling and
182+ # the code we are producing will not run on the build system
183+ # without an emulator.
184+ # In most cases we do not want to treat musl as a cross compiler.
185+ # For instance when building ghc we want to include ghci.
186+ isCrossHost = stdenv.hostPlatform != stdenv.buildPlatform
187+ && !(stdenv.buildPlatform.isLinux && stdenv.hostPlatform.isMusl);
188+ # This is the same as isCrossHost but for use when building ghc itself
189+ isCrossTarget = stdenv.targetPlatform != stdenv.hostPlatform
190+ && !(stdenv.hostPlatform.isLinux && stdenv.targetPlatform.isMusl);
180191}
nixpkgs/github.json+3−3
@@ -1,7 +1,7 @@
11{
22 "url": "https://github.com/input-output-hk/nixpkgs",
3− "rev": "31aa5316ca232a53667790a99e8b1e76252e065c",
4− "date": "2019-11-16T23:51:02+13:00",
5− "sha256": "0g0r473rdrh5vsdvr45nmfs6ibp0pqyzbw9f0iv6r0jkg6jjiykr",
3+ "rev": "8215f2ee01c56a764416f703c66767404a321d92",
4+ "date": "2020-01-25T20:38:55+13:00",
5+ "sha256": "0cdmpwpi19354hqvph7mnxrdbphina1vg61fk487i9559bsv545m",
66 "fetchSubmodules": false
77}
overlays/armv6l-linux.nix+2−2
@@ -15,10 +15,10 @@ self: super:
1515 inherit (pkgs) gmp;
1616 # iserv-proxy needs to come from the buildPackages, as it needs to run on the
1717 # build host.
18− inherit (config.hsPkgs.buildPackages.iserv-proxy.components.exes) iserv-proxy;
18+ inherit (self.buildPackages.ghc-extra-packages."${config.compiler.nix-name}".iserv-proxy.components.exes) iserv-proxy;
1919 # remote-iserv however needs to come from the regular packages as it has to
2020 # run on the target host.
21− inherit (config.hsPkgs.remote-iserv.components.exes) remote-iserv;
21+ inherit (self.ghc-extra-packages."${config.compiler.nix-name}".remote-iserv.components.exes) remote-iserv;
2222 # we need to use openssl.bin here, because the .dll's are in the .bin expression.
2323 extra-test-libs = [
2424 # pkgs.rocksdb
overlays/bootstrap.nix+16
@@ -247,6 +247,22 @@ in {
247247
248248 ghc-patches = ghc-patches "8.8.2";
249249 };
250+ ghc883 = self.callPackage ../compiler/ghc {
251+ extra-passthru = { buildGHC = self.buildPackages.haskell-nix.compiler.ghc883; };
252+
253+ inherit bootPkgs sphinx installDeps;
254+
255+ buildLlvmPackages = self.buildPackages.llvmPackages_7;
256+ llvmPackages = self.llvmPackages_7;
257+
258+ src-spec = rec {
259+ version = "8.8.3";
260+ url = "https://downloads.haskell.org/~ghc/${version}/ghc-${version}-src.tar.xz";
261+ sha256 = "128g932i3wix6ic03v04nh5755vyjiidzri9iybwad72yfmc1p70";
262+ };
263+
264+ ghc-patches = ghc-patches "8.8.3";
265+ };
250266 } // self.lib.optionalAttrs (self.targetPlatform.isGhcjs or false)
251267 # This will inject `exactDeps` and `envDeps` into the ghcjs
252268 # compiler defined below. This is crucial to build packages
overlays/ghc.nix−4
@@ -2,10 +2,6 @@ self: super: with super;
22 # sadly we need to patch GHC a bit.
33 let
44 ghcPkgOverrides = {
5− # Required for cross-compilation, otherwise it throws
6− # Failed to load interface for ‘GHC.Integer.Type’
7− # Perhaps you haven't installed the "dyn" libraries for package ‘integer-gmp-1.0.2.0’?
8− enableShared = super.stdenv.buildPlatform == super.stdenv.hostPlatform;
95 enableIntegerSimple = false;
106 } // lib.optionalAttrs self.stdenv.hostPlatform.isAarch32 {
117 enableRelocatableStaticLibs = false;
overlays/haskell.nix+2−1
@@ -477,7 +477,7 @@ self: super: {
477477 };
478478
479479 haskellNixRoots' = ifdLevel:
480− let filterSupportedGhc = self.lib.filterAttrs (n: _: n == "ghc865" || n == "ghc882");
480+ let filterSupportedGhc = self.lib.filterAttrs (n: _: n == "ghc865" || n == "ghc882" || n == "ghc883");
481481 in self.recurseIntoAttrs ({
482482 # Things that require no IFD to build
483483 inherit (self.buildPackages.haskell-nix) nix-tools source-pins;
@@ -492,6 +492,7 @@ self: super: {
492492 hscolour = self.buildPackages.haskell-nix.bootstrap.packages.hscolour;
493493 ghc865 = self.buildPackages.haskell-nix.compiler.ghc865;
494494 ghc882 = self.buildPackages.haskell-nix.compiler.ghc882;
495+ ghc883 = self.buildPackages.haskell-nix.compiler.ghc883;
495496 ghc-extra-projects = self.recurseIntoAttrs (builtins.mapAttrs (_: proj: withInputs proj.plan-nix)
496497 (filterSupportedGhc self.ghc-extra-projects));
497498 } // self.lib.optionalAttrs (ifdLevel > 1) {
overlays/linux-cross.nix+3−2
@@ -53,7 +53,8 @@ let
5353 set -euo pipefail
5454 ${qemu}/bin/qemu-${qemuSuffix} $@*
5555 '';
56− testFlags = lib.optionals isLinuxCross [ "--test-wrapper ${qemuTestWrapper}/bin/test-wrapper" ];
56+ testWrapper = lib.optional isLinuxCross "${qemuTestWrapper}/bin/test-wrapper";
57+
5758 preCheck = lib.optionalString isLinuxCross ''
5859 echo "================================================================="
5960 echo "RUNNING TESTS for $name via qemu-${qemuSuffix}"
@@ -71,4 +72,4 @@ let
7172
7273 enableShared = lib.mkDefault (!isLinuxCross);
7374
74−in { inherit preCheck postCheck configureFlags setupBuildFlags testFlags enableShared; }
75+in { inherit preCheck postCheck configureFlags setupBuildFlags testWrapper enableShared; }
overlays/windows.nix+2−2
@@ -36,10 +36,10 @@ self: super:
3636 inherit (pkgs) gmp;
3737 # iserv-proxy needs to come from the buildPackages, as it needs to run on the
3838 # build host.
39− inherit (self.buildPackages.ghc-extra-packages.ghc865.iserv-proxy.components.exes) iserv-proxy;
39+ inherit (self.buildPackages.ghc-extra-packages."${config.compiler.nix-name}".iserv-proxy.components.exes) iserv-proxy;
4040 # remote-iserv however needs to come from the regular packages as it has to
4141 # run on the target host.
42− inherit (self.ghc-extra-packages.ghc865.remote-iserv.components.exes) remote-iserv;
42+ inherit (self.ghc-extra-packages."${config.compiler.nix-name}".remote-iserv.components.exes) remote-iserv;
4343 # we need to use openssl.bin here, because the .dll's are in the .bin expression.
4444 # extra-test-libs = [ pkgs.rocksdb pkgs.openssl.bin pkgs.libffi pkgs.gmp ];
4545 } // {
release.nix+38−19
@@ -22,25 +22,39 @@ let
2222 # to `x86_64-w64-mingw32` in 19.09.
2323 let pinnedNixpkgs = import ./nixpkgs { inherit nixpkgs-pin; }; in
2424 with pinnedNixpkgs.lib;
25− let inherit (systems.examples) musl64 mingwW64; in
26− with (import (pinnedNixpkgs.path + "/pkgs/top-level/release-lib.nix") {
27− inherit supportedSystems scrubJobs nixpkgsArgs;
28− packageSet = {
29− system ? builtins.currentSystem
30− , crossSystem ? null
31− , nixpkgsArgs ? { inherit system crossSystem; }
32− , ...}@args:
33− import (haskell-nix + /build.nix) (args // {
34− nixpkgsArgs = nixpkgsArgs // { inherit nixpkgs-pin; };
35− inherit ifdLevel;
36− });
37− });
38−
25+ let
26+ inherit (systems.examples) musl64 mingwW64 aarch64-multiplatform raspberryPi;
27+ packages = supportedSystems:
28+ with (import (pinnedNixpkgs.path + "/pkgs/top-level/release-lib.nix") {
29+ inherit supportedSystems scrubJobs nixpkgsArgs;
30+ packageSet = {
31+ system ? builtins.currentSystem
32+ , crossSystem ? null
33+ , nixpkgsArgs ? { inherit system crossSystem; }
34+ , ...}@args:
35+ import (haskell-nix + /build.nix) (args // {
36+ nixpkgsArgs = nixpkgsArgs // {
37+ inherit nixpkgs-pin;
38+ };
39+ inherit ifdLevel;
40+ });
41+ });
42+ {
43+ mapTestOn = mapTestOn (packagePlatforms pkgs);
44+ mapTestOnCross = p: mapTestOnCross p (packagePlatforms pkgs);
45+ };
46+ in
3947 {
40− native = filterTests (mapTestOn (packagePlatforms pkgs));
41− # Disabled for now. Something is wrong and this would require `allowBroken`
42− # "${musl64.config}" = filterTests (mapTestOnCross musl64 (packagePlatforms pkgs));
43− "${mingwW64.config}" = filterTests (mapTestOnCross mingwW64 (packagePlatforms pkgs));
48+ native = filterTests ((packages supportedSystems).mapTestOn);
49+ # Musl cross compile does not work on macOS
50+ "${musl64.config}" = filterTests ((packages (filter (x: x == "x86_64-linux") supportedSystems)).mapTestOnCross musl64);
51+ # Windows cross compilation is currently broken on macOS for nixpkgs 19.09 (works on 19.03)
52+ "${mingwW64.config}" = filterTests ((packages (filter
53+ (x: x == "x86_64-linux" || nixpkgs-pin == "release-19.03") supportedSystems)).mapTestOnCross mingwW64);
54+ "${aarch64-multiplatform.config}" = filterTests ((packages (filter (x: x == "x86_64-linux") supportedSystems))
55+ .mapTestOnCross aarch64-multiplatform);
56+ # "${raspberryPi.config}" = filterTests ((packages (filter (x: x == "x86_64-linux") supportedSystems))
57+ # .mapTestOnCross raspberryPi);
4458 };
4559
4660 allJobs =
@@ -57,7 +71,12 @@ in allJobs // {
5771 meta.description = "All jobs required to pass CI";
5872 constituents =
5973 collect isDerivation allJobs.R1903.native
60− ++ collect isDerivation allJobs.R1909.native;
74+ ++ collect isDerivation allJobs.R1909.native
75+ # Windows cross compiling with GHC 8.8.2 is broken
76+ # ++ collect isDerivation allJobs.R1903.x86_64-pc-mingw32
77+ # ++ collect isDerivation allJobs.R1909.x86_64-w64-mingw32
78+ ++ collect isDerivation allJobs.R1903.x86_64-unknown-linux-musl
79+ ++ collect isDerivation allJobs.R1909.x86_64-unknown-linux-musl;
6180 };
6281 }
6382
test/cabal-22/default.nix+7−3
@@ -24,11 +24,15 @@ in recurseIntoAttrs {
2424 printf "size of executable $exe is $size. \n" >& 2
2525
2626 # fixme: run on target platform when cross-compiled
27− printf "checking whether executable rans... " >& 2
27+ printf "checking whether executable runs... " >& 2
2828 cat ${haskellLib.check packages.project.components.exes.project}
2929
30+ '' +
31+ # Aarch is statically linked and does not produce a .so file.
32+ # Musl is also statically linked, but it does make a .so file so we should check that still.
33+ optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64) (''
3034 printf "checking that executable is dynamically linked to system libraries... " >& 2
31− '' + optionalString stdenv.isLinux ''
35+ '' + optionalString (stdenv.isLinux && !stdenv.hostPlatform.isMusl) ''
3236 ldd $exe | grep libgmp
3337 '' + optionalString stdenv.isDarwin ''
3438 otool -L $exe | grep "libSystem.B"
@@ -47,7 +51,7 @@ in recurseIntoAttrs {
4751 ldd $sofile | grep libHSghc-prim
4852 '' + optionalString stdenv.isDarwin ''
4953 otool -L $sofile | grep libHSghc-prim
50− '') + ''
54+ '')) + ''
5155 touch $out
5256
5357 printf "checking whether benchmark ran... " >& 2
test/cabal-simple-prof/default.nix+4−1
@@ -37,7 +37,10 @@ in recurseIntoAttrs {
3737
3838 # fixme: run on target platform when cross-compiled
3939 printf "checking whether executable runs with profiling... " >& 2
40− ${toString packages.cabal-simple.components.exes.cabal-simple.config.testWrapper} $exe +RTS -p -h
40+ # Curiosity: cross compilers prodcing profiling with `+RTS -p -h` lead to the following cryptic message:
41+ # cabal-simple: invalid heap profile option: -h*
42+ # Hence we pass `-hc`.
43+ ${toString packages.cabal-simple.components.exes.cabal-simple.config.testWrapper} $exe +RTS -p -hc
4144
4245 touch $out
4346 '';
test/cabal-simple/default.nix+13−22
@@ -1,5 +1,5 @@
11# Test a package set
2−{ stdenv, util, mkCabalProjectPkgSet, cabalProject', haskellLib, gmp6, zlib, recurseIntoAttrs }:
2+{ stdenv, util, mkCabalProjectPkgSet, cabalProject', haskellLib, recurseIntoAttrs }:
33
44with stdenv.lib;
55
@@ -9,19 +9,6 @@ let
99 # Package has no exposed modules which causes
1010 # haddock: No input file(s)
1111 packages.cabal-simple.doHaddock = false;
12−
13− # When compiling with musl ghc, build a statically linked
14− # executable against static libraries.
15− # Ref: https://vaibhavsagar.com/blog/2018/01/03/static-haskell-nix/
16− packages.cabal-simple.components.exes.cabal-simple.configureFlags =
17− optionals stdenv.hostPlatform.isMusl [
18− "--disable-executable-dynamic"
19− "--disable-shared"
20− "--ghc-option=-optl=-pthread"
21− "--ghc-option=-optl=-static"
22− "--ghc-option=-optl=-L${gmp6.override { withStatic = true; }}/lib"
23− # "--ghc-option=-optl=-L${zlib.static}/lib"
24− ];
2512 }
2613 ];
2714
@@ -53,16 +40,20 @@ in recurseIntoAttrs {
5340 # fixme: run on target platform when cross-compiled
5441 printf "checking whether executable runs... " >& 2
5542 cat ${haskellLib.check packages.cabal-simple.components.exes.cabal-simple}
56− '' + (if stdenv.hostPlatform.isMusl then ''
43+ '' + (if stdenv.hostPlatform.isMusl
44+ then ''
5745 printf "checking that executable is statically linked... " >& 2
5846 (ldd $exe 2>&1 || true) | grep -i "not a"
59− '' else ''
60− printf "checking that executable is dynamically linked to system libraries... " >& 2
61− '' + optionalString stdenv.isLinux ''
62− ldd $exe | grep libpthread
63− '' + optionalString stdenv.isDarwin ''
64− otool -L $exe |grep .dylib
65− '') + ''
47+ ''
48+ else
49+ # Skip this on aarch as we do not have an `ldd` tool
50+ optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64) (''
51+ printf "checking that executable is dynamically linked to system libraries... " >& 2
52+ '' + optionalString stdenv.isLinux ''
53+ ldd $exe | grep libpthread
54+ '' + optionalString stdenv.isDarwin ''
55+ otool -L $exe |grep .dylib
56+ '')) + ''
6657
6758 printf "Checking that \"all\" component has the programs... " >& 2
6859 all_exe="${packages.cabal-simple.components.all}/bin/cabal-simple${stdenv.hostPlatform.extensions.executable}"
test/cabal-sublib/default.nix+5−2
@@ -37,12 +37,15 @@ in recurseIntoAttrs {
3737 printf "checking whether executable runs... " >& 2
3838 cat ${haskellLib.check packages.cabal-sublib.components.exes.cabal-sublib}
3939
40+ '' +
41+ # Musl and Aarch are statically linked..
42+ optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64 && !stdenv.hostPlatform.isMusl) (''
4043 printf "checking that executable is dynamically linked to system libraries... " >& 2
41− '' + optionalString stdenv.isLinux ''
44+ '' + optionalString (stdenv.isLinux && !stdenv.hostPlatform.isMusl) ''
4245 ldd $exe | grep libgmp
4346 '' + optionalString stdenv.isDarwin ''
4447 otool -L $exe |grep .dylib
45− '' + ''
48+ '') + ''
4649
4750 printf "Checking that \"all\" component has the programs... " >& 2
4851 all_exe="${packages.cabal-sublib.components.all}/bin/cabal-sublib${stdenv.hostPlatform.extensions.executable}"
test/exe-only/default.nix+4−1
@@ -26,7 +26,10 @@ in recurseIntoAttrs {
2626 # fixme: run on target platform when cross-compiled
2727 printf "checking whether executable ran... " >& 2
2828 cat ${haskellLib.check packages.exe-only.components.exes.exe-only}
29− '' + (if stdenv.hostPlatform.isMusl then ''
29+ '' +
30+ # Aarch are statically linked and does not have ldd for these tests.
31+ optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64) (
32+ if stdenv.hostPlatform.isMusl then ''
3033 printf "checking that executable is statically linked... " >& 2
3134 (ldd $exe 2>&1 || true) | grep -i "not a"
3235 '' else ''
test/fully-static/default.nix+1−6
@@ -32,12 +32,7 @@ let
3232
3333 withFullyStatic = {
3434 configureFlags =
35− optionals stdenv.hostPlatform.isMusl ([
36− "--disable-executable-dynamic"
37− "--disable-shared"
38− "--ghc-option=-optl=-pthread"
39− "--ghc-option=-optl=-static"
40− ] ++ map (drv: "--ghc-option=-optl=-L${drv}/lib") staticLibs);
35+ optionals stdenv.hostPlatform.isMusl (map (drv: "--ghc-option=-optl=-L${drv}/lib") staticLibs);
4136 };
4237 in {
4338 # Select a non-GMP compiler, usually for software licensing reasons.
test/setup-deps/default.nix+2−2
@@ -15,10 +15,10 @@ let
1515 };
1616
1717 packages = project.hsPkgs;
18−in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
18+in recurseIntoAttrs (if stdenv.buildPlatform != stdenv.hostPlatform
1919 then
2020 let skip = pkgs.runCommand "skip-test-setup-deps" {} ''
21− echo "Skipping setup-deps test on windows as it needs the ghc lib" >& 2
21+ echo "Skipping setup-deps test when cross compiling as it needs the ghc lib" >& 2
2222 touch $out
2323 '';
2424 in {
test/shell-for-setup-deps/default.nix+11−5
@@ -14,10 +14,15 @@ let
1414
1515 env = project.hsPkgs.shellFor {};
1616
17−in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
17+# Making this work for cross compilers will be dificult as setup-deps are
18+# built for the build platform and the shell will be for the host platform.
19+# We probably need a shell that provides both build and host ghc
20+# and corrisponding package DBs and a way to use them.
21+# This problem affects musl as well as the build libraries are linked to glibc.
22+in recurseIntoAttrs (if stdenv.buildPlatform != stdenv.hostPlatform
1823 then
1924 let skip = runCommand "skipping-test-shell-for-setup-deps" {} ''
20− echo "Skipping shell-for-setup-deps test on windows as does not work yet" >& 2
25+ echo "Skipping shell-for-setup-deps test on cross compilers (does not work yet)" >& 2
2126 touch $out
2227 '';
2328 in {
@@ -31,7 +36,7 @@ in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
3136 };
3237 inherit env;
3338 run = stdenv.mkDerivation {
34− name = "shell-for-test";
39+ name = "shell-for-setup-deps-test";
3540
3641 buildCommand = ''
3742 ########################################################################
@@ -40,13 +45,14 @@ in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
4045 cp ${./pkg/src}/*.hs .
4146
4247 printf "checking that the shell env has the dependencies...\n" >& 2
43− ${env.ghc}/bin/runghc conduit-test.hs
48+ ${env.ghc}/bin/${env.ghc.targetPrefix}ghc-pkg list
49+ ${env.ghc}/bin/${env.ghc.targetPrefix}runghc conduit-test.hs
4450
4551 touch $out
4652 '';
4753
4854 meta.platforms = platforms.all;
49− meta.disabled = stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWindows;
55+ meta.disabled = stdenv.buildPlatform != stdenv.hostPlatform;
5056
5157 passthru = {
5258 # Used for debugging with nix repl
test/shell-for/default.nix+2−2
@@ -68,10 +68,10 @@ in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
6868 cp ${./pkgb/src}/*.hs .
6969
7070 printf "checking that the shell env has the dependencies...\n" >& 2
71− ${env.ghc}/bin/runghc conduit-test.hs
71+ ${env.ghc}/bin/${env.ghc.targetPrefix}runghc conduit-test.hs
7272
7373 printf "checking that the shell envDefault has the dependencies...\n" >& 2
74− ${envDefault.ghc}/bin/runghc conduit-test.hs
74+ ${envDefault.ghc}/bin/${env.ghc.targetPrefix}runghc conduit-test.hs
7575
7676 touch $out
7777 '';
test/snapshots/default.nix+8−4
@@ -37,10 +37,14 @@ in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
3737 # test snapshot ghcWithHoogle
3838
3939 printf "checking that the ghcWithPackages env has the package...\n" >& 2
40− ${env}/bin/ghc-pkg list | grep conduit
41−
42− printf "checking that the ghcWithPackages env has a hoogle index...\n" >& 2
43− ${env}/bin/hoogle search Conduit --count=100 | grep ConduitT
40+ ${env}/bin/${env.targetPrefix}ghc-pkg list | grep conduit
41+
42+ ''
43+ # Hoogle support is currently disabled in cross compiler shells
44+ + (optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64) ''
45+ printf "checking that the ghcWithPackages env has a hoogle index...\n" >& 2
46+ ${env}/bin/hoogle search Conduit --count=100 | grep ConduitT
47+ '') +''
4448
4549 touch $out
4650 '';
test/with-packages/default.nix+2−2
@@ -73,11 +73,11 @@ in recurseIntoAttrs {
7373 ''
7474 else ''
7575 printf "checking that the package env has the dependencies... " >& 2
76− ${package.components.all.env}/bin/runghc ${./Point.hs}
76+ ${package.components.all.env}/bin/${package.components.all.env.targetPrefix}runghc ${./Point.hs}
7777 echo >& 2
7878
7979 printf "checking that components.library.env has the dependencies... " >& 2
80− ${library.env}/bin/runghc ${./Point.hs}
80+ ${library.env}/bin/${library.env.targetPrefix}runghc ${./Point.hs}
8181 echo >& 2
8282 '') + ''
8383 touch $out