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
This commit is contained in:
Hamish Mackenzie 2020-03-04 16:07:01 +13:00 committed by GitHub
parent 7c5c8e7691
commit 775c8cf756
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 208 additions and 105 deletions

View File

@ -24,7 +24,7 @@
, dontStrip ? component.dontStrip
, enableStatic ? component.enableStatic
, enableShared ? component.enableShared && !stdenv.hostPlatform.isWindows && !stdenv.hostPlatform.useiOSPrebuilt
, enableShared ? component.enableShared && !haskellLib.isCrossHost
, enableDeadCodeElimination ? component.enableDeadCodeElimination
# Options for Haddock generation
@ -95,11 +95,20 @@ let
(enableFeature enableExecutableProfiling "executable-profiling")
(enableFeature enableStatic "static")
(enableFeature enableShared "shared")
] ++ lib.optionals (stdenv.hostPlatform.isMusl && (haskellLib.isExecutableType componentId)) [
# These flags will make sure the resulting executable is statically linked.
# If it uses other libraries it may be necessary for to add more
# `--ghc-option=-optl=-L` options to the `configurationFlags` of the
# component.
"--disable-executable-dynamic"
"--ghc-option=-optl=-pthread"
"--ghc-option=-optl=-static"
"--ghc-option=-optl=-L${gmp.override { withStatic = true; }}/lib"
] ++ lib.optional enableSeparateDataOutput "--datadir=$data/share/${ghc.name}"
++ lib.optional doHaddock' "--docdir=${docdir "$doc"}"
++ lib.optional (enableLibraryProfiling || enableExecutableProfiling) "--profiling-detail=${profilingDetail}"
++ lib.optional stdenv.hostPlatform.isLinux (enableFeature enableDeadCodeElimination "split-sections")
++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) (
++ lib.optionals haskellLib.isCrossHost (
map (arg: "--hsc2hs-option=" + arg) (["--cross-compile"] ++ lib.optionals (stdenv.hostPlatform.isWindows) ["--via-asm"])
++ lib.optional (package.buildType == "Configure") "--configure-option=--host=${stdenv.hostPlatform.config}" )
++ component.configureFlags
@ -131,7 +140,7 @@ let
doHaddock' = doHaddock
&& (haskellLib.isLibrary componentId)
&& stdenv.hostPlatform == stdenv.buildPlatform;
&& !haskellLib.isCrossHost;
exeExt = lib.optionalString stdenv.hostPlatform.isWindows ".exe";
exeName = componentId.cname + exeExt;

View File

@ -39,10 +39,14 @@ let
hoogleLocal = let
nixpkgsHoogleLocal = import (pkgs.path + /pkgs/development/haskell-modules/hoogle.nix);
in { packages ? [], hoogle ? pkgs.haskell-nix.haskellPackages.hoogle.components.exes.hoogle }:
# Use the latest default nixpkgs hoogle.nix, as the 19.03 one does not work with cross compilers
nixpkgsHoogleLocal = import ((import ../nixpkgs {}).path + /pkgs/development/haskell-modules/hoogle.nix);
in { packages ? [], hoogle ? pkgs.buildPackages.haskell-nix.haskellPackages.hoogle.components.exes.hoogle }:
haskellLib.weakCallPackage pkgs nixpkgsHoogleLocal {
ghc = pkgs.haskell-nix.ghc;
# For musl we can use haddock from the buildGHC
ghc = if stdenv.hostPlatform.isLinux && stdenv.targetPlatform.isMusl
then ghc.buildGHC
else ghc;
inherit packages hoogle;
};

View File

@ -15,14 +15,19 @@
}:
let
inherit (configFiles) ghcCommand ghcCommandCaps packageCfgDir;
inherit (configFiles) targetPrefix ghcCommand ghcCommandCaps packageCfgDir;
libDir = "$out/${configFiles.libDir}";
docDir = "$out/share/doc/ghc/html";
# For musl we can use haddock from the buildGHC
haddock = if stdenv.hostPlatform.isLinux && stdenv.targetPlatform.isMusl
then ghc.buildGHC
else ghc;
in runCommand "${componentName}-${ghc.name}-env" {
preferLocalBuild = true;
passthru = {
inherit (ghc) version meta;
inherit targetPrefix;
baseGhc = ghc;
};
} (
@ -62,7 +67,7 @@ in runCommand "${componentName}-${ghc.name}-env" {
fi
done
for prg in runghc runhaskell; do
for prg in "${targetPrefix}runghc" "${targetPrefix}runhaskell"; do
if [[ -x "${ghc}/bin/$prg" ]]; then
rm -f $out/bin/$prg
makeWrapper ${ghc}/bin/$prg $out/bin/$prg \
@ -75,9 +80,9 @@ in runCommand "${componentName}-${ghc.name}-env" {
done
# Wrap haddock, if the base GHC provides it.
if [[ -x "${ghc}/bin/haddock" ]]; then
if [[ -x "${haddock}/bin/haddock" ]]; then
rm -f $out/bin/haddock
makeWrapper ${ghc}/bin/haddock $out/bin/haddock \
makeWrapper ${haddock}/bin/haddock $out/bin/haddock \
--add-flags '"-B$NIX_${ghcCommandCaps}_LIBDIR"' \
--set "NIX_${ghcCommandCaps}_LIBDIR" "${libDir}"
fi

View File

@ -66,7 +66,8 @@ let
in { identifier, component, fullName, flags ? {} }:
# Filters out only library packages that for this GHC target
# TODO investigate why this is needed
let libDeps = lib.filter (p: p.configFiles.targetPrefix == ghc.targetPrefix)
# TODO find out why p ? configFiles helps (for instance for `R1909.aarch64-unknown-linux-gnu.tests.cabal-22.run.x86_64-linux`)
let libDeps = lib.filter (p: (p ? configFiles) && p.configFiles.targetPrefix == ghc.targetPrefix)
(map getLibComponent component.depends);
cfgFiles =
let xs = map

View File

@ -12,6 +12,8 @@
, ... } @ args:
let
# TODO find out why hoogle index creation can be made to work for cross compilers
withHoogle' = withHoogle && !haskellLib.isCrossHost;
selected = packages hsPkgs;
additionalSelected = additional hsPkgs;
selectedConfigs = map (p: p.components.all.config) selected;
@ -53,7 +55,7 @@ let
ghcEnv = ghcForComponent {
inherit configFiles;
componentName = name;
postInstall = lib.optionalString withHoogle ''
postInstall = lib.optionalString withHoogle' ''
ln -s ${hoogleIndex}/bin/hoogle $out/bin
'';
};
@ -79,7 +81,7 @@ in
buildInputs = systemInputs
++ mkDrvArgs.buildInputs or []
++ lib.optional withHoogle hoogleIndex;
++ lib.optional withHoogle' hoogleIndex;
nativeBuildInputs = [ ghcEnv ]
++ nativeBuildInputs
++ mkDrvArgs.nativeBuildInputs or [];

View File

@ -3,7 +3,7 @@
# haskell.nix ships its own version of the ghc expression as it needs more
# control over the expression to isolate it against varying <nixpkgs> and
# allow us to customize it to the way haskell.nix works.
{ stdenv, targetPackages
{ stdenv, haskell-nix, targetPackages
# build-tools
, bootPkgs
@ -33,15 +33,24 @@
, # Whether to build dynamic libs for the standard library (on the target
# platform). Static libs are always built.
enableShared ? !stdenv.targetPlatform.isWindows && !stdenv.targetPlatform.useiOSPrebuilt
enableShared ? !haskell-nix.haskellLib.isCrossTarget
, # Whetherto build terminfo.
enableTerminfo ? !stdenv.targetPlatform.isWindows
, # Whetherto build terminfo. Musl fails to build terminfo as ncurses seems to be linked to glibc
enableTerminfo ? !stdenv.targetPlatform.isWindows && !stdenv.targetPlatform.isMusl
, # What flavour to build. An empty string indicates no
# specific flavour and falls back to ghc default values.
ghcFlavour ? stdenv.lib.optionalString (stdenv.targetPlatform != stdenv.hostPlatform)
(if useLLVM then "quick-cross" else "perf-cross-ncg")
ghcFlavour ? stdenv.lib.optionalString haskell-nix.haskellLib.isCrossTarget (
if useLLVM
then (
# TODO check if the issues with qemu and Aarch32 persist. See
# https://github.com/input-output-hk/haskell.nix/pull/411/commits/1986264683067198e7fdc1d665351622b664712e
if stdenv.targetPlatform.isAarch32
then "quick-cross"
else "perf-cross"
)
else "perf-cross-ncg"
)
, # Whether to disable the large address space allocator
# 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;
let
inherit (stdenv) buildPlatform hostPlatform targetPlatform;
inherit (haskell-nix.haskellLib) isCrossTarget;
inherit (bootPkgs) ghc;
# TODO check if this posible fix for segfaults works or not.
libffiStaticEnabled = if libffi == null || !stdenv.targetPlatform.isMusl
then libffi
else targetPackages.libffi.overrideAttrs (old: { dontDisableStatic = true; });
# TODO(@Ericson2314) Make unconditional
targetPrefix = stdenv.lib.optionalString
(targetPlatform != hostPlatform)
@ -75,8 +90,9 @@ let
DYNAMIC_GHC_PROGRAMS = ${if enableShared then "YES" else "NO"}
INTEGER_LIBRARY = ${if enableIntegerSimple then "integer-simple" else "integer-gmp"}
'' + stdenv.lib.optionalString (targetPlatform != hostPlatform) ''
Stage1Only = ${if targetPlatform.system == hostPlatform.system then "NO" else "YES"}
CrossCompilePrefix = ${targetPrefix}
'' + stdenv.lib.optionalString isCrossTarget ''
Stage1Only = ${if targetPlatform.system == hostPlatform.system then "NO" else "YES"}
HADDOCK_DOCS = NO
BUILD_SPHINX_HTML = NO
BUILD_SPHINX_PDF = NO
@ -88,11 +104,19 @@ let
'' + stdenv.lib.optionalString useLLVM ''
GhcStage2HcOpts += -fast-llvm
GhcLibHcOpts += -fast-llvm
'' + stdenv.lib.optionalString (!enableTerminfo) ''
WITH_TERMINFO=NO
''
# While split sections are now enabled by default in ghc 8.8 for windows,
# the seem to lead to `too many sections` errors when building base for
# profiling.
+ stdenv.lib.optionalString targetPlatform.isWindows ''
SplitSections = NO
'';
# Splicer will pull out correct variations
libDeps = platform: stdenv.lib.optional enableTerminfo [ ncurses ]
++ [libffi]
++ [libffiStaticEnabled]
++ stdenv.lib.optional (!enableIntegerSimple) gmp
++ stdenv.lib.optional (platform.libc != "glibc" && !targetPlatform.isWindows) libiconv;
@ -184,7 +208,7 @@ in let configured-src = stdenv.mkDerivation (rec {
configureFlags = [
"--datadir=$doc/share/doc/ghc"
"--with-curses-includes=${ncurses.dev}/include" "--with-curses-libraries=${ncurses.out}/lib"
] ++ stdenv.lib.optionals (libffi != null) ["--with-system-libffi" "--with-ffi-includes=${targetPackages.libffi.dev}/include" "--with-ffi-libraries=${targetPackages.libffi.out}/lib"
] ++ stdenv.lib.optionals (libffiStaticEnabled != null) ["--with-system-libffi" "--with-ffi-includes=${libffiStaticEnabled.dev}/include" "--with-ffi-libraries=${libffiStaticEnabled.out}/lib"
] ++ stdenv.lib.optional (!enableIntegerSimple) [
"--with-gmp-includes=${targetPackages.gmp.dev}/include" "--with-gmp-libraries=${targetPackages.gmp.out}/lib"
] ++ stdenv.lib.optional (targetPlatform == hostPlatform && hostPlatform.libc != "glibc" && !targetPlatform.isWindows) [
@ -298,7 +322,12 @@ in let configured-src = stdenv.mkDerivation (rec {
for i in "$out/bin/"*; do
test ! -h $i || continue
egrep --quiet '^#!' <(head -n 1 $i) || continue
sed -i -e '2i export PATH="$PATH:${stdenv.lib.makeBinPath [ targetPackages.stdenv.cc.bintools coreutils ]}"' $i
# The ghcprog fixup is for musl (where runhaskell script just needs to point to the correct
# ghc program to work).
sed -i \
-e '2i export PATH="$PATH:${stdenv.lib.makeBinPath [ targetPackages.stdenv.cc.bintools coreutils ]}"' \
-e 's/ghcprog="ghc-/ghcprog="${targetPrefix}ghc-/' \
$i
done
'' + installDeps targetPrefix;

View File

@ -177,4 +177,15 @@ with haskellLib;
check = import ./check.nix {
inherit stdenv lib haskellLib srcOnly;
};
# Use `isCrossHost` to identify when we are cross compiling and
# the code we are producing will not run on the build system
# without an emulator.
# In most cases we do not want to treat musl as a cross compiler.
# For instance when building ghc we want to include ghci.
isCrossHost = stdenv.hostPlatform != stdenv.buildPlatform
&& !(stdenv.buildPlatform.isLinux && stdenv.hostPlatform.isMusl);
# This is the same as isCrossHost but for use when building ghc itself
isCrossTarget = stdenv.targetPlatform != stdenv.hostPlatform
&& !(stdenv.hostPlatform.isLinux && stdenv.targetPlatform.isMusl);
}

View File

@ -1,7 +1,7 @@
{
"url": "https://github.com/input-output-hk/nixpkgs",
"rev": "31aa5316ca232a53667790a99e8b1e76252e065c",
"date": "2019-11-16T23:51:02+13:00",
"sha256": "0g0r473rdrh5vsdvr45nmfs6ibp0pqyzbw9f0iv6r0jkg6jjiykr",
"rev": "8215f2ee01c56a764416f703c66767404a321d92",
"date": "2020-01-25T20:38:55+13:00",
"sha256": "0cdmpwpi19354hqvph7mnxrdbphina1vg61fk487i9559bsv545m",
"fetchSubmodules": false
}

View File

@ -15,10 +15,10 @@ self: super:
inherit (pkgs) gmp;
# iserv-proxy needs to come from the buildPackages, as it needs to run on the
# build host.
inherit (config.hsPkgs.buildPackages.iserv-proxy.components.exes) iserv-proxy;
inherit (self.buildPackages.ghc-extra-packages."${config.compiler.nix-name}".iserv-proxy.components.exes) iserv-proxy;
# remote-iserv however needs to come from the regular packages as it has to
# run on the target host.
inherit (config.hsPkgs.remote-iserv.components.exes) remote-iserv;
inherit (self.ghc-extra-packages."${config.compiler.nix-name}".remote-iserv.components.exes) remote-iserv;
# we need to use openssl.bin here, because the .dll's are in the .bin expression.
extra-test-libs = [
# pkgs.rocksdb

View File

@ -247,6 +247,22 @@ in {
ghc-patches = ghc-patches "8.8.2";
};
ghc883 = self.callPackage ../compiler/ghc {
extra-passthru = { buildGHC = self.buildPackages.haskell-nix.compiler.ghc883; };
inherit bootPkgs sphinx installDeps;
buildLlvmPackages = self.buildPackages.llvmPackages_7;
llvmPackages = self.llvmPackages_7;
src-spec = rec {
version = "8.8.3";
url = "https://downloads.haskell.org/~ghc/${version}/ghc-${version}-src.tar.xz";
sha256 = "128g932i3wix6ic03v04nh5755vyjiidzri9iybwad72yfmc1p70";
};
ghc-patches = ghc-patches "8.8.3";
};
} // self.lib.optionalAttrs (self.targetPlatform.isGhcjs or false)
# This will inject `exactDeps` and `envDeps` into the ghcjs
# compiler defined below. This is crucial to build packages

View File

@ -2,10 +2,6 @@ self: super: with super;
# sadly we need to patch GHC a bit.
let
ghcPkgOverrides = {
# Required for cross-compilation, otherwise it throws
# Failed to load interface for GHC.Integer.Type
# Perhaps you haven't installed the "dyn" libraries for package integer-gmp-1.0.2.0?
enableShared = super.stdenv.buildPlatform == super.stdenv.hostPlatform;
enableIntegerSimple = false;
} // lib.optionalAttrs self.stdenv.hostPlatform.isAarch32 {
enableRelocatableStaticLibs = false;

View File

@ -477,7 +477,7 @@ self: super: {
};
haskellNixRoots' = ifdLevel:
let filterSupportedGhc = self.lib.filterAttrs (n: _: n == "ghc865" || n == "ghc882");
let filterSupportedGhc = self.lib.filterAttrs (n: _: n == "ghc865" || n == "ghc882" || n == "ghc883");
in self.recurseIntoAttrs ({
# Things that require no IFD to build
inherit (self.buildPackages.haskell-nix) nix-tools source-pins;
@ -492,6 +492,7 @@ self: super: {
hscolour = self.buildPackages.haskell-nix.bootstrap.packages.hscolour;
ghc865 = self.buildPackages.haskell-nix.compiler.ghc865;
ghc882 = self.buildPackages.haskell-nix.compiler.ghc882;
ghc883 = self.buildPackages.haskell-nix.compiler.ghc883;
ghc-extra-projects = self.recurseIntoAttrs (builtins.mapAttrs (_: proj: withInputs proj.plan-nix)
(filterSupportedGhc self.ghc-extra-projects));
} // self.lib.optionalAttrs (ifdLevel > 1) {

View File

@ -53,7 +53,8 @@ let
set -euo pipefail
${qemu}/bin/qemu-${qemuSuffix} $@*
'';
testFlags = lib.optionals isLinuxCross [ "--test-wrapper ${qemuTestWrapper}/bin/test-wrapper" ];
testWrapper = lib.optional isLinuxCross "${qemuTestWrapper}/bin/test-wrapper";
preCheck = lib.optionalString isLinuxCross ''
echo "================================================================="
echo "RUNNING TESTS for $name via qemu-${qemuSuffix}"
@ -71,4 +72,4 @@ let
enableShared = lib.mkDefault (!isLinuxCross);
in { inherit preCheck postCheck configureFlags setupBuildFlags testFlags enableShared; }
in { inherit preCheck postCheck configureFlags setupBuildFlags testWrapper enableShared; }

View File

@ -36,10 +36,10 @@ self: super:
inherit (pkgs) gmp;
# iserv-proxy needs to come from the buildPackages, as it needs to run on the
# build host.
inherit (self.buildPackages.ghc-extra-packages.ghc865.iserv-proxy.components.exes) iserv-proxy;
inherit (self.buildPackages.ghc-extra-packages."${config.compiler.nix-name}".iserv-proxy.components.exes) iserv-proxy;
# remote-iserv however needs to come from the regular packages as it has to
# run on the target host.
inherit (self.ghc-extra-packages.ghc865.remote-iserv.components.exes) remote-iserv;
inherit (self.ghc-extra-packages."${config.compiler.nix-name}".remote-iserv.components.exes) remote-iserv;
# we need to use openssl.bin here, because the .dll's are in the .bin expression.
# extra-test-libs = [ pkgs.rocksdb pkgs.openssl.bin pkgs.libffi pkgs.gmp ];
} // {

View File

@ -22,25 +22,39 @@ let
# to `x86_64-w64-mingw32` in 19.09.
let pinnedNixpkgs = import ./nixpkgs { inherit nixpkgs-pin; }; in
with pinnedNixpkgs.lib;
let inherit (systems.examples) musl64 mingwW64; in
with (import (pinnedNixpkgs.path + "/pkgs/top-level/release-lib.nix") {
inherit supportedSystems scrubJobs nixpkgsArgs;
packageSet = {
system ? builtins.currentSystem
, crossSystem ? null
, nixpkgsArgs ? { inherit system crossSystem; }
, ...}@args:
import (haskell-nix + /build.nix) (args // {
nixpkgsArgs = nixpkgsArgs // { inherit nixpkgs-pin; };
inherit ifdLevel;
});
});
let
inherit (systems.examples) musl64 mingwW64 aarch64-multiplatform raspberryPi;
packages = supportedSystems:
with (import (pinnedNixpkgs.path + "/pkgs/top-level/release-lib.nix") {
inherit supportedSystems scrubJobs nixpkgsArgs;
packageSet = {
system ? builtins.currentSystem
, crossSystem ? null
, nixpkgsArgs ? { inherit system crossSystem; }
, ...}@args:
import (haskell-nix + /build.nix) (args // {
nixpkgsArgs = nixpkgsArgs // {
inherit nixpkgs-pin;
};
inherit ifdLevel;
});
});
{
mapTestOn = mapTestOn (packagePlatforms pkgs);
mapTestOnCross = p: mapTestOnCross p (packagePlatforms pkgs);
};
in
{
native = filterTests (mapTestOn (packagePlatforms pkgs));
# Disabled for now. Something is wrong and this would require `allowBroken`
# "${musl64.config}" = filterTests (mapTestOnCross musl64 (packagePlatforms pkgs));
"${mingwW64.config}" = filterTests (mapTestOnCross mingwW64 (packagePlatforms pkgs));
native = filterTests ((packages supportedSystems).mapTestOn);
# Musl cross compile does not work on macOS
"${musl64.config}" = filterTests ((packages (filter (x: x == "x86_64-linux") supportedSystems)).mapTestOnCross musl64);
# Windows cross compilation is currently broken on macOS for nixpkgs 19.09 (works on 19.03)
"${mingwW64.config}" = filterTests ((packages (filter
(x: x == "x86_64-linux" || nixpkgs-pin == "release-19.03") supportedSystems)).mapTestOnCross mingwW64);
"${aarch64-multiplatform.config}" = filterTests ((packages (filter (x: x == "x86_64-linux") supportedSystems))
.mapTestOnCross aarch64-multiplatform);
# "${raspberryPi.config}" = filterTests ((packages (filter (x: x == "x86_64-linux") supportedSystems))
# .mapTestOnCross raspberryPi);
};
allJobs =
@ -57,7 +71,12 @@ in allJobs // {
meta.description = "All jobs required to pass CI";
constituents =
collect isDerivation allJobs.R1903.native
++ collect isDerivation allJobs.R1909.native;
++ collect isDerivation allJobs.R1909.native
# Windows cross compiling with GHC 8.8.2 is broken
# ++ collect isDerivation allJobs.R1903.x86_64-pc-mingw32
# ++ collect isDerivation allJobs.R1909.x86_64-w64-mingw32
++ collect isDerivation allJobs.R1903.x86_64-unknown-linux-musl
++ collect isDerivation allJobs.R1909.x86_64-unknown-linux-musl;
};
}

View File

@ -24,11 +24,15 @@ in recurseIntoAttrs {
printf "size of executable $exe is $size. \n" >& 2
# fixme: run on target platform when cross-compiled
printf "checking whether executable rans... " >& 2
printf "checking whether executable runs... " >& 2
cat ${haskellLib.check packages.project.components.exes.project}
'' +
# Aarch is statically linked and does not produce a .so file.
# Musl is also statically linked, but it does make a .so file so we should check that still.
optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64) (''
printf "checking that executable is dynamically linked to system libraries... " >& 2
'' + optionalString stdenv.isLinux ''
'' + optionalString (stdenv.isLinux && !stdenv.hostPlatform.isMusl) ''
ldd $exe | grep libgmp
'' + optionalString stdenv.isDarwin ''
otool -L $exe | grep "libSystem.B"
@ -47,7 +51,7 @@ in recurseIntoAttrs {
ldd $sofile | grep libHSghc-prim
'' + optionalString stdenv.isDarwin ''
otool -L $sofile | grep libHSghc-prim
'') + ''
'')) + ''
touch $out
printf "checking whether benchmark ran... " >& 2

View File

@ -37,7 +37,10 @@ in recurseIntoAttrs {
# fixme: run on target platform when cross-compiled
printf "checking whether executable runs with profiling... " >& 2
${toString packages.cabal-simple.components.exes.cabal-simple.config.testWrapper} $exe +RTS -p -h
# Curiosity: cross compilers prodcing profiling with `+RTS -p -h` lead to the following cryptic message:
# cabal-simple: invalid heap profile option: -h*
# Hence we pass `-hc`.
${toString packages.cabal-simple.components.exes.cabal-simple.config.testWrapper} $exe +RTS -p -hc
touch $out
'';

View File

@ -1,5 +1,5 @@
# Test a package set
{ stdenv, util, mkCabalProjectPkgSet, cabalProject', haskellLib, gmp6, zlib, recurseIntoAttrs }:
{ stdenv, util, mkCabalProjectPkgSet, cabalProject', haskellLib, recurseIntoAttrs }:
with stdenv.lib;
@ -9,19 +9,6 @@ let
# Package has no exposed modules which causes
# haddock: No input file(s)
packages.cabal-simple.doHaddock = false;
# When compiling with musl ghc, build a statically linked
# executable against static libraries.
# Ref: https://vaibhavsagar.com/blog/2018/01/03/static-haskell-nix/
packages.cabal-simple.components.exes.cabal-simple.configureFlags =
optionals stdenv.hostPlatform.isMusl [
"--disable-executable-dynamic"
"--disable-shared"
"--ghc-option=-optl=-pthread"
"--ghc-option=-optl=-static"
"--ghc-option=-optl=-L${gmp6.override { withStatic = true; }}/lib"
# "--ghc-option=-optl=-L${zlib.static}/lib"
];
}
];
@ -53,16 +40,20 @@ in recurseIntoAttrs {
# fixme: run on target platform when cross-compiled
printf "checking whether executable runs... " >& 2
cat ${haskellLib.check packages.cabal-simple.components.exes.cabal-simple}
'' + (if stdenv.hostPlatform.isMusl then ''
'' + (if stdenv.hostPlatform.isMusl
then ''
printf "checking that executable is statically linked... " >& 2
(ldd $exe 2>&1 || true) | grep -i "not a"
'' else ''
printf "checking that executable is dynamically linked to system libraries... " >& 2
'' + optionalString stdenv.isLinux ''
ldd $exe | grep libpthread
'' + optionalString stdenv.isDarwin ''
otool -L $exe |grep .dylib
'') + ''
''
else
# Skip this on aarch as we do not have an `ldd` tool
optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64) (''
printf "checking that executable is dynamically linked to system libraries... " >& 2
'' + optionalString stdenv.isLinux ''
ldd $exe | grep libpthread
'' + optionalString stdenv.isDarwin ''
otool -L $exe |grep .dylib
'')) + ''
printf "Checking that \"all\" component has the programs... " >& 2
all_exe="${packages.cabal-simple.components.all}/bin/cabal-simple${stdenv.hostPlatform.extensions.executable}"

View File

@ -37,12 +37,15 @@ in recurseIntoAttrs {
printf "checking whether executable runs... " >& 2
cat ${haskellLib.check packages.cabal-sublib.components.exes.cabal-sublib}
'' +
# Musl and Aarch are statically linked..
optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64 && !stdenv.hostPlatform.isMusl) (''
printf "checking that executable is dynamically linked to system libraries... " >& 2
'' + optionalString stdenv.isLinux ''
'' + optionalString (stdenv.isLinux && !stdenv.hostPlatform.isMusl) ''
ldd $exe | grep libgmp
'' + optionalString stdenv.isDarwin ''
otool -L $exe |grep .dylib
'' + ''
'') + ''
printf "Checking that \"all\" component has the programs... " >& 2
all_exe="${packages.cabal-sublib.components.all}/bin/cabal-sublib${stdenv.hostPlatform.extensions.executable}"

View File

@ -26,7 +26,10 @@ in recurseIntoAttrs {
# fixme: run on target platform when cross-compiled
printf "checking whether executable ran... " >& 2
cat ${haskellLib.check packages.exe-only.components.exes.exe-only}
'' + (if stdenv.hostPlatform.isMusl then ''
'' +
# Aarch are statically linked and does not have ldd for these tests.
optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64) (
if stdenv.hostPlatform.isMusl then ''
printf "checking that executable is statically linked... " >& 2
(ldd $exe 2>&1 || true) | grep -i "not a"
'' else ''

View File

@ -32,12 +32,7 @@ let
withFullyStatic = {
configureFlags =
optionals stdenv.hostPlatform.isMusl ([
"--disable-executable-dynamic"
"--disable-shared"
"--ghc-option=-optl=-pthread"
"--ghc-option=-optl=-static"
] ++ map (drv: "--ghc-option=-optl=-L${drv}/lib") staticLibs);
optionals stdenv.hostPlatform.isMusl (map (drv: "--ghc-option=-optl=-L${drv}/lib") staticLibs);
};
in {
# Select a non-GMP compiler, usually for software licensing reasons.

View File

@ -15,10 +15,10 @@ let
};
packages = project.hsPkgs;
in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
in recurseIntoAttrs (if stdenv.buildPlatform != stdenv.hostPlatform
then
let skip = pkgs.runCommand "skip-test-setup-deps" {} ''
echo "Skipping setup-deps test on windows as it needs the ghc lib" >& 2
echo "Skipping setup-deps test when cross compiling as it needs the ghc lib" >& 2
touch $out
'';
in {

View File

@ -14,10 +14,15 @@ let
env = project.hsPkgs.shellFor {};
in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
# Making this work for cross compilers will be dificult as setup-deps are
# built for the build platform and the shell will be for the host platform.
# We probably need a shell that provides both build and host ghc
# and corrisponding package DBs and a way to use them.
# This problem affects musl as well as the build libraries are linked to glibc.
in recurseIntoAttrs (if stdenv.buildPlatform != stdenv.hostPlatform
then
let skip = runCommand "skipping-test-shell-for-setup-deps" {} ''
echo "Skipping shell-for-setup-deps test on windows as does not work yet" >& 2
echo "Skipping shell-for-setup-deps test on cross compilers (does not work yet)" >& 2
touch $out
'';
in {
@ -31,7 +36,7 @@ in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
};
inherit env;
run = stdenv.mkDerivation {
name = "shell-for-test";
name = "shell-for-setup-deps-test";
buildCommand = ''
########################################################################
@ -40,13 +45,14 @@ in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
cp ${./pkg/src}/*.hs .
printf "checking that the shell env has the dependencies...\n" >& 2
${env.ghc}/bin/runghc conduit-test.hs
${env.ghc}/bin/${env.ghc.targetPrefix}ghc-pkg list
${env.ghc}/bin/${env.ghc.targetPrefix}runghc conduit-test.hs
touch $out
'';
meta.platforms = platforms.all;
meta.disabled = stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWindows;
meta.disabled = stdenv.buildPlatform != stdenv.hostPlatform;
passthru = {
# Used for debugging with nix repl

View File

@ -68,10 +68,10 @@ in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
cp ${./pkgb/src}/*.hs .
printf "checking that the shell env has the dependencies...\n" >& 2
${env.ghc}/bin/runghc conduit-test.hs
${env.ghc}/bin/${env.ghc.targetPrefix}runghc conduit-test.hs
printf "checking that the shell envDefault has the dependencies...\n" >& 2
${envDefault.ghc}/bin/runghc conduit-test.hs
${envDefault.ghc}/bin/${env.ghc.targetPrefix}runghc conduit-test.hs
touch $out
'';

View File

@ -37,10 +37,14 @@ in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
# test snapshot ghcWithHoogle
printf "checking that the ghcWithPackages env has the package...\n" >& 2
${env}/bin/ghc-pkg list | grep conduit
${env}/bin/${env.targetPrefix}ghc-pkg list | grep conduit
printf "checking that the ghcWithPackages env has a hoogle index...\n" >& 2
${env}/bin/hoogle search Conduit --count=100 | grep ConduitT
''
# Hoogle support is currently disabled in cross compiler shells
+ (optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64) ''
printf "checking that the ghcWithPackages env has a hoogle index...\n" >& 2
${env}/bin/hoogle search Conduit --count=100 | grep ConduitT
'') +''
touch $out
'';

View File

@ -73,11 +73,11 @@ in recurseIntoAttrs {
''
else ''
printf "checking that the package env has the dependencies... " >& 2
${package.components.all.env}/bin/runghc ${./Point.hs}
${package.components.all.env}/bin/${package.components.all.env.targetPrefix}runghc ${./Point.hs}
echo >& 2
printf "checking that components.library.env has the dependencies... " >& 2
${library.env}/bin/runghc ${./Point.hs}
${library.env}/bin/${library.env.targetPrefix}runghc ${./Point.hs}
echo >& 2
'') + ''
touch $out