Replace collectRunComponents with haskellLib.check (#316)

This change replaces `passthru.run` and `collectRunComponents` with
`haskellLib.check` and `$pkg.checks`.

Uses `ln -s` instead of `cp` for DLLs to avoid duplicating them.

Adds features to help debugging eval issues with haskell.nix/release.nix.
The ifdInputLevel can be set to limit the jobs included to control
how much work is done at the eval stage when looking for issues.

Reduce CI times by excluding older ghc versions from haskellNixRoots
(GHC 8.6.3 and 8.6.4)

Sets `preferLocalBuild=false` on `callCabalProjectToNix` and `callStackToNix`
to ensure they are cached on hydra for both Linux and macOS.

Fix `data-dir:` when cleaning components.
`normalizeRelativeDir` adds a slash on to the end of `dataDir`.
Adding another one here results in `//` and files are left out by
mistake.
This commit is contained in:
Hamish Mackenzie 2019-11-29 23:28:47 +13:00 committed by GitHub
parent fa9a60d77b
commit a9b01221dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 241 additions and 128 deletions

View File

@ -7,7 +7,10 @@ steps:
- label: 'Check that jobset will evaluate in Hydra'
command:
- nix-build build.nix -A maintainer-scripts.check-hydra -o check-hydra.sh
- ./check-hydra.sh
- ./check-hydra.sh 0
- ./check-hydra.sh 1
- ./check-hydra.sh 2
- ./check-hydra.sh 3
agents:
system: x86_64-linux

View File

@ -9,27 +9,19 @@
, crossSystem ? null
, config ? {}
, nixpkgsArgs ? { inherit system crossSystem; }
, ifdLevel ? 1000
}:
let
haskellNixArgs = import ./default.nix;
pkgs = import nixpkgs ({
config = haskellNixArgs.config // config;
overlays = haskellNixArgs.overlays ++
[(self: super: {
darcs = (self.haskell-nix.hackage-package {
name = "darcs";
version = "2.14.2";
index-state = "2019-10-28T00:00:00Z";
plan-sha256 = "1h8dxib0wz6mg8md6ldwa54dsr1dn7vxfij8cfhdawl4y3wr51k0";
# Apply the latest darcs.net Setup.hs patches
modules = [{packages.darcs.patches = [ ./patches/darcs-setup.patch ];}];
}).components.exes.darcs;
})]; } // nixpkgsArgs);
config = haskellNixArgs.config // config;
inherit (haskellNixArgs) overlays;
} // nixpkgsArgs);
haskell = pkgs.haskell-nix;
in rec {
tests = import ./test/default.nix { inherit nixpkgs nixpkgsArgs; };
tests = import ./test/default.nix { inherit nixpkgs nixpkgsArgs ifdLevel; };
# Scripts for keeping Hackage and Stackage up to date, and CI tasks.
# The dontRecurseIntoAttrs prevents these from building on hydra
@ -52,6 +44,11 @@ in rec {
}) {};
};
};
# Because this is going to be used to test caching on hydra, it must not
# use the darcs package from the haskell.nix we are testing. For that reason
# it uses `pkgs.buildPackages.callPackage` not `haskell.callPackage`
# (We could pull in darcs from a known good haskell.nix for hydra to
# use)
check-hydra = pkgs.buildPackages.callPackage ./scripts/check-hydra.nix {};
check-closure-size = pkgs.buildPackages.callPackage ./scripts/check-closure-size.nix {
inherit (haskell) nix-tools;
@ -60,11 +57,16 @@ in rec {
# These are pure parts of maintainer-script so they can be built by hydra
# and added to the cache to speed up buildkite.
maintainer-script-cache = pkgs.recurseIntoAttrs {
inherit (maintainer-scripts) update-docs check-hydra check-closure-size;
# Some of the dependencies of the impure scripts so that they will
# will be in the cache too for buildkite.
inherit (pkgs.buildPackages) glibc coreutils git openssh cabal-install nix-prefetch-git;
inherit (haskell) nix-tools;
};
maintainer-script-cache = pkgs.recurseIntoAttrs (
(pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isWindows {
inherit (maintainer-scripts) check-hydra;
})
// (pkgs.lib.optionalAttrs (ifdLevel > 2) {
inherit (maintainer-scripts) update-docs check-closure-size;
# Some of the dependencies of the impure scripts so that they will
# will be in the cache too for buildkite.
inherit (pkgs.buildPackages) glibc coreutils git openssh cabal-install nix-prefetch-git;
inherit (haskell) nix-tools;
})
);
}

View File

@ -20,8 +20,6 @@
, preHaddock ? component.preHaddock , postHaddock ? component.postHaddock
, shellHook ? ""
, doCheck ? component.doCheck || haskellLib.isTest componentId
, doCrossCheck ? component.doCrossCheck || false
, dontPatchELF ? true
, dontStrip ? true
@ -128,13 +126,7 @@ let
exeExt = lib.optionalString stdenv.hostPlatform.isWindows ".exe";
testExecutable = "dist/build/${componentId.cname}/${componentId.cname}${exeExt}";
# exe components are in /bin, but test and benchmarks are not. Perhaps to avoid
# them being from being added to the PATH when the all component added to an env.
# TODO revist this to find out why and document or maybe change this.
installedExeDir = if haskellLib.isTest componentId || haskellLib.isBenchmark componentId
then name
else "bin";
installedExe = "${installedExeDir}/${componentId.cname}${exeExt}";
installedExe = "bin/${componentId.cname}${exeExt}";
in stdenv.lib.fix (drv:
@ -143,20 +135,20 @@ stdenv.mkDerivation ({
src = cleanSrc;
inherit doCheck doCrossCheck dontPatchELF dontStrip;
doCheck = false;
doCrossCheck = false;
inherit dontPatchELF dontStrip;
passthru = {
inherit (package) identifier;
config = component;
inherit configFiles executableToolDepends cleanSrc;
inherit configFiles executableToolDepends cleanSrc installedExe;
env = shellWrappers;
# The directory containing the haddock documentation.
# `null' if no haddock documentation was built.
haddockDir = if doHaddock' then "${docdir drv.doc}/html" else null;
run = runCommand (fullName + "-run") {} ''
${toString component.testWrapper} ${drv}/${installedExe} | tee $out
'';
};
meta = {
@ -217,13 +209,7 @@ stdenv.mkDerivation ({
runHook postBuild
'';
checkPhase = ''
runHook preCheck
${toString component.testWrapper} ${testExecutable} ${lib.concatStringsSep " " component.testFlags}
runHook postCheck
'';
checkPhase = "notice: Tests are only executed by building the .run sub-derivation of this component.";
haddockPhase = ''
runHook preHaddock
@ -281,25 +267,25 @@ stdenv.mkDerivation ({
fi
''}
${(lib.optionalString (haskellLib.isTest componentId || haskellLib.isBenchmark componentId || haskellLib.isAll componentId) ''
mkdir -p $out/${name}
mkdir -p $out/bin
if [ -f ${testExecutable} ]; then
cp ${testExecutable} $out/${name}/
cp ${testExecutable} $out/bin/
fi
'')
# In case `setup copy` did not creat this
+ (lib.optionalString enableSeparateDataOutput "mkdir -p $data")
+ (lib.optionalString (stdenv.hostPlatform.isWindows && (haskellLib.mayHaveExecutable componentId)) ''
echo "Copying libffi and gmp .dlls ..."
echo "Symlink libffi and gmp .dlls ..."
for p in ${lib.concatStringsSep " " [ libffi gmp ]}; do
find "$p" -iname '*.dll' -exec cp {} $out/${installedExeDir} \;
find "$p" -iname '*.dll' -exec ln -s {} $out/bin \;
done
# copy all .dlls into the local directory.
# symlink all .dlls into the local directory.
# we ask ghc-pkg for *all* dynamic-library-dirs and then iterate over the unique set
# to copy over dlls as needed.
echo "Copying library dependencies..."
# to symlink over dlls as needed.
echo "Symlink library dependencies..."
for libdir in $(x86_64-pc-mingw32-ghc-pkg --package-db=$packageConfDir field "*" dynamic-library-dirs --simple-output|xargs|sed 's/ /\n/g'|sort -u); do
if [ -d "$libdir" ]; then
find "$libdir" -iname '*.dll' -exec cp {} $out/${installedExeDir} \;
find "$libdir" -iname '*.dll' -exec ln -s {} $out/bin \;
fi
done
'')
@ -316,7 +302,7 @@ stdenv.mkDerivation ({
// lib.optionalAttrs (patches != []) { patches = map (p: if builtins.isFunction p then p { inherit (package.identifier) version; inherit revision; } else p) patches; }
// haskellLib.optionalHooks {
inherit preUnpack postUnpack preConfigure postConfigure
preBuild postBuild preCheck postCheck
preBuild postBuild
preInstall postInstall preHaddock postHaddock;
}
// lib.optionalAttrs (stdenv.buildPlatform.libc == "glibc"){ LOCALE_ARCHIVE = "${buildPackages.glibcLocales}/lib/locale/locale-archive"; }

View File

@ -57,8 +57,11 @@ let
;
};
in {
in rec {
components = haskellLib.applyComponents buildComp config;
checks = pkgs.recurseIntoAttrs (builtins.mapAttrs
(_: d: haskellLib.check d)
(lib.filterAttrs (_: d: d.config.doCheck) components.tests));
inherit (package) identifier detailLevel isLocal;
inherit setup cabalFile;
isHaskell = true;

View File

@ -286,7 +286,8 @@ Infrastructure.
Extracts a selection of components from a Haskell [package set](#package-set).
This can be used to filter out all test suites or benchmarks of
your project, so that they can be built in Hydra.
your project, so that they can be built in Hydra (see check if you
waht to run the tests as well as build them).
```
collectComponents =
@ -311,6 +312,21 @@ tests = collectComponents "tests" (package: package.identifier.name == "mypackag
Will result in moving derivations from `hsPkgs.mypackage.components.tests.unit-tests`
to `tests.mypackage.unit-tests`.
#### check
This function turns a derivation that builds a test into one to run it.
| Argument | Type | Description |
|-------------------|--------|---------------------|
| `drv` | Derivation | One of `$pkg.components.tests.$test`. |
For convenience `$pkg.components.tests` are mapped with this function
to `$pkg.components.checks`.
This function is intended for use with `tests` but it should also work
for `exes` and `benchmarks` if you just want to run them to make sure
they execute.
#### subComponentTypes
Sub-component types identify [components](#component) and are one of:

View File

@ -156,10 +156,11 @@ let
}
else replaceSoureRepos rawCabalProject;
plan-nix = runCommand "plan-to-nix-pkgs" ({
plan-nix = runCommand (if name == null then "plan-to-nix-pkgs" else name + "-plan-to-nix-pkgs") ({
nativeBuildInputs = [ nix-tools ghc hpack cabal-install pkgs.rsync pkgs.git ];
# Needed or stack-to-nix will die on unicode inputs
LANG = "en_US.UTF-8";
preferLocalBuild = false;
} // (if plan-sha256 == null
then {}
else {

View File

@ -20,6 +20,7 @@ let
LOCALE_ARCHIVE = pkgs.lib.optionalString (pkgs.stdenv.hostPlatform.libc == "glibc") "${pkgs.glibcLocales}/lib/locale/locale-archive";
LANG = "en_US.UTF-8";
LC_ALL = "en_US.UTF-8";
preferLocalBuild = false;
} (''
mkdir -p $out
'' + pkgs.lib.optionalString (cache != null) ''

42
lib/check.nix Normal file
View File

@ -0,0 +1,42 @@
{ stdenv, lib, haskellLib, srcOnly }:
drv:
let
component = drv.config;
# This derivation can be used to execute test component.
# The $out of the derivation is a file containing the resulting
# stdout output.
in stdenv.mkDerivation ({
name = (drv.name + "-check");
# Useing `srcOnly` (rather than getting the `src` via a `drv.passthru`)
# should correctly apply the patches from `drv` (if any).
src = srcOnly drv;
passthru = {
inherit (drv) identifier config configFiles executableToolDepends cleanSrc env;
};
inherit (drv) meta LANG LC_ALL;
inherit (component) doCheck doCrossCheck;
phases = ["buildPhase" "checkPhase"];
# If doCheck or doCrossCheck are false we may still build this
# component and we want it to quietly succeed.
buildPhase = ''
touch $out
'';
checkPhase = ''
runHook preCheck
${toString component.testWrapper} ${drv}/${drv.installedExe} ${lib.concatStringsSep " " component.testFlags} | tee $out
runHook postCheck
'';
} // haskellLib.optionalHooks {
inherit (component) preCheck postCheck;
})

View File

@ -1,4 +1,4 @@
{ lib, haskellLib, runCommand, git }:
{ stdenv, lib, haskellLib, runCommand, git, srcOnly }:
with haskellLib;
@ -149,4 +149,9 @@ with haskellLib;
cleanGit = import ./clean-git.nix {
inherit lib runCommand git cleanSourceWith;
};
# Check a test component
check = import ./check.nix {
inherit stdenv lib haskellLib srcOnly;
};
}

View File

@ -81,7 +81,7 @@ let
};
doCheck = mkOption {
type = bool;
default = (def.doCheck or false);
default = (def.doCheck or true);
};
doCrossCheck = mkOption {
description = "Run doCheck also in cross compilation settings. This can be tricky as the test logic must know how to run the tests on the target.";

View File

@ -267,7 +267,7 @@ self: super: {
index-state = "2019-10-20T00:00:00Z";
plan-sha256 = "086kd6aa5bir3y4aqb1wl5zkj6agz5q4wp4snvdnf6cidz5wra06";
};
alex = bootstrap.packages.alex-project.alex.components.exes.alex;
alex = bootstrap.packages.alex-project.hsPkgs.alex.components.exes.alex;
happy-project = hackage-project {
# Only a boot compiler is suitable here
ghc = ghc // { isHaskellNixCompiler = ghc.isHaskellNixBootCompiler; };
@ -276,7 +276,7 @@ self: super: {
index-state = "2019-10-20T00:00:00Z";
plan-sha256 = "011bxlxdv239psgi80j00km2wcgb68j16sz3fng67d03sqf5i37w";
};
happy = bootstrap.packages.happy-project.happy.components.exes.happy;
happy = bootstrap.packages.happy-project.hsPkgs.happy.components.exes.happy;
hscolour-project = hackage-project {
# Only a boot compiler is suitable here
ghc = ghc // { isHaskellNixCompiler = ghc.isHaskellNixBootCompiler; };
@ -285,7 +285,7 @@ self: super: {
index-state = "2019-10-20T00:00:00Z";
plan-sha256 = "021rwcmkshibc3mfr833ay5hfr19kq6k32lxyrrb6vp9vmihgw4b";
};
hscolour = bootstrap.packages.hscolour-project.hscolour.components.exes.HsColour;
hscolour = bootstrap.packages.hscolour-project.hsPkgs.hscolour.components.exes.HsColour;
};
};
};

View File

@ -59,7 +59,7 @@ self: super: {
# Utility functions for working with the component builder.
haskellLib = let hl = import ../lib {
inherit (self) lib runCommand;
inherit (self) stdenv lib runCommand srcOnly;
inherit (self.buildPackages) git;
haskellLib = hl;
}; in hl;
@ -309,7 +309,7 @@ self: super: {
tar xzf ${tarball}
mv "${name}-${version}" $out
'';
in cabalProject (builtins.removeAttrs args [ "version" ] // { inherit src; });
in cabalProject' (builtins.removeAttrs args [ "version" ] // { inherit src; });
# This function is like `cabalProject` but it makes the plan-nix available
# separately from the hsPkgs. The advantage is that the you can get the
@ -361,27 +361,36 @@ self: super: {
# project = cabalProject' {...};
# In your tests module add something that is effectively
# testProjectPlan = withInputs project.plan-nix;
withInputs = derivation: builtins.mapAttrs (_: self.recurseIntoAttrs) {
inherit derivation;
inputs = builtins.listToAttrs (
builtins.concatMap (i: if i == null then [] else [
{ name = builtins.replaceStrings ["." (self.stdenv.hostPlatform.config + "-")] ["_" ""] i.name; value = i; }
]) derivation.nativeBuildInputs);
};
withInputs = self.recurseIntoAttrs;
# Add this to your tests to make all the dependencies of haskell.nix
# are tested and cached.
haskellNixRoots = self.recurseIntoAttrs (builtins.mapAttrs (_: self.recurseIntoAttrs) {
inherit (self.buildPackages.haskell-nix) nix-tools source-pins;
bootstap-nix-tools = self.buildPackages.haskell-nix.bootstrap.packages.nix-tools;
alex-plan-nix = withInputs self.buildPackages.haskell-nix.bootstrap.packages.alex-project.plan-nix;
happy-plan-nix = withInputs self.buildPackages.haskell-nix.bootstrap.packages.happy-project.plan-nix;
hscolour-plan-nix = withInputs self.buildPackages.haskell-nix.bootstrap.packages.hscolour-project.plan-nix;
ghc-extra-projects = builtins.mapAttrs (_: proj: self.recurseIntoAttrs (withInputs proj.plan-nix))
(self.lib.filterAttrs (n: _: n != "ghc844" && n != "ghc861" && n != "ghc862"
# There is an issue with GHC 8.6.4 and nixpkgs 19.09, so only build it for 19.03 for now
&& (n != "ghc864" || super.lib.versions.majorMinor super.lib.version == "19.03")
) self.ghc-extra-projects);
});
haskellNixRoots = self.recurseIntoAttrs {
Level0 = haskellNixRoots' 0;
Level1 = haskellNixRoots' 1;
};
haskellNixRoots' = ifdLevel:
let filterSupportedGhc = self.lib.filterAttrs (n: _: n == "ghc865");
in self.recurseIntoAttrs ({
# Things that require no IFD to build
inherit (self.buildPackages.haskell-nix) nix-tools source-pins;
bootstap-nix-tools = self.buildPackages.haskell-nix.bootstrap.packages.nix-tools;
alex-plan-nix = withInputs self.buildPackages.haskell-nix.bootstrap.packages.alex-project.plan-nix;
happy-plan-nix = withInputs self.buildPackages.haskell-nix.bootstrap.packages.happy-project.plan-nix;
hscolour-plan-nix = withInputs self.buildPackages.haskell-nix.bootstrap.packages.hscolour-project.plan-nix;
} // self.lib.optionalAttrs (ifdLevel > 0) {
# Things that require one IFD to build (the inputs should be in level 0)
alex = self.buildPackages.haskell-nix.bootstrap.packages.alex;
happy = self.buildPackages.haskell-nix.bootstrap.packages.happy;
hscolour = self.buildPackages.haskell-nix.bootstrap.packages.hscolour;
ghc865 = self.buildPackages.haskell-nix.compiler.ghc865;
ghc-extra-projects = self.recurseIntoAttrs (builtins.mapAttrs (_: proj: withInputs proj.plan-nix)
(filterSupportedGhc self.ghc-extra-projects));
} // self.lib.optionalAttrs (ifdLevel > 1) {
# Things that require two levels of IFD to build (inputs should be in level 1)
ghc-extra-packages = self.recurseIntoAttrs
(filterSupportedGhc self.ghc-extra-packages);
});
};
}

View File

@ -7,7 +7,7 @@ in pkgs.lib.evalModules {
_module.args = {
# this is *not* the hasekllLib from nixpkgs; it is rather our own
# library from haskell.nix
haskellLib = let hl = import ./lib { inherit lib; inherit (pkgs) runCommand git; haskellLib = hl; }; in hl;
haskellLib = let hl = import ./lib { inherit lib; inherit (pkgs) stdenv runCommand git srcOnly; haskellLib = hl; }; in hl;
# The package descriptions depend on pkgs, which are used to resolve system package dependencies
# as well as pkgconfPkgs, which are used to resolve pkgconfig name to nixpkgs names. We simply

View File

@ -2,6 +2,7 @@
, scrubJobs ? true
, haskell-nix ? { outPath = ./.; rev = "abcdef"; }
, nixpkgsArgs ? {}
, ifdLevel ? 3
}:
let defaultNixpkgs = import ./nixpkgs {}; in
@ -31,6 +32,7 @@ let
, ...}@args:
import (haskell-nix + /build.nix) (args // {
nixpkgsArgs = nixpkgsArgs // { inherit nixpkgs-pin; };
inherit ifdLevel;
});
});

View File

@ -9,11 +9,12 @@ writeScript "check-hydra.sh" ''
export PATH="${makeBinPath [ coreutils time gnutar gzip hydra jq ]}"
echo '~~~ Evaluating release.nix'
echo '~~~ Evaluating release.nix with --arg ifdLevel '$1
command time --format '%e' -o eval-time.txt \
hydra-eval-jobs \
--option allowed-uris "https://github.com/NixOS https://github.com/input-output-hk" \
--arg supportedSystems '[ builtins.currentSystem ]' \
--arg ifdLevel $1 \
-I . release.nix > eval.json
EVAL_EXIT_CODE="$?"
if [ "$EVAL_EXIT_CODE" != 0 ]

View File

@ -12,14 +12,16 @@ let
packages = project.hsPkgs;
in recurseIntoAttrs {
inherit (project) plan-nix;
ifdInputs = {
inherit (project) plan-nix;
};
run = stdenv.mkDerivation {
name = "buildable-test";
buildCommand =
(concatStrings (mapAttrsToList (name: value: ''
printf "checking whether executable runs... " >& 2
cat ${value.run}
cat ${haskellLib.check value}
'') packages.buildable-test.components.exes)) + ''
touch $out
'';

View File

@ -11,7 +11,9 @@ let
packages = project.hsPkgs;
in recurseIntoAttrs {
inherit (project) plan-nix;
ifdInputs = {
inherit (project) plan-nix;
};
shell = util.addCabalInstall packages.project.components.all;
run = stdenv.mkDerivation {
name = "cabal-22-test";
@ -24,7 +26,7 @@ in recurseIntoAttrs {
# fixme: run on target platform when cross-compiled
printf "checking whether executable rans... " >& 2
cat ${packages.project.components.exes.project.run}
cat ${haskellLib.check packages.project.components.exes.project}
printf "checking that executable is dynamically linked to system libraries... " >& 2
'' + optionalString stdenv.isLinux ''
@ -50,10 +52,10 @@ in recurseIntoAttrs {
touch $out
printf "checking whether benchmark ran... " >& 2
cat ${packages.project.components.benchmarks.project-bench.run}
cat ${haskellLib.check packages.project.components.benchmarks.project-bench}
printf "checking whether tests ran... " >& 2
cat ${packages.project.components.tests.unit.run}
cat ${haskellLib.check packages.project.components.tests.unit}
'';
meta.platforms = platforms.all;

View File

@ -24,7 +24,9 @@ let
packages = project.hsPkgs;
in recurseIntoAttrs {
inherit (project) plan-nix;
ifdInputs = {
inherit (project) plan-nix;
};
run = stdenv.mkDerivation {
name = "cabal-simple-prof-test";

View File

@ -34,7 +34,9 @@ let
packages = project.hsPkgs;
in recurseIntoAttrs {
inherit (project) plan-nix;
ifdInputs = {
inherit (project) plan-nix;
};
# Used for testing externally with nix-shell (../tests.sh).
# This just adds cabal-install to the existing shells.
@ -51,7 +53,7 @@ in recurseIntoAttrs {
# fixme: run on target platform when cross-compiled
printf "checking whether executable runs... " >& 2
cat ${packages.cabal-simple.components.exes.cabal-simple.run}
cat ${haskellLib.check packages.cabal-simple.components.exes.cabal-simple}
'' + (if stdenv.hostPlatform.isMusl then ''
printf "checking that executable is statically linked... " >& 2
(ldd $exe 2>&1 || true) | grep -i "not a"

View File

@ -1,4 +1,4 @@
{ stdenv, cabalProject', recurseIntoAttrs }:
{ stdenv, cabalProject', recurseIntoAttrs, haskellLib }:
with stdenv.lib;
@ -10,7 +10,9 @@ let
};
packages = project.hsPkgs;
in recurseIntoAttrs {
inherit (project) plan-nix;
ifdInputs = {
inherit (project) plan-nix;
};
run = stdenv.mkDerivation {
name = "call-cabal-project-to-nix-test";
@ -18,7 +20,7 @@ in recurseIntoAttrs {
exe="${packages.use-cabal-simple.components.exes.use-cabal-simple}/bin/use-cabal-simple${stdenv.hostPlatform.extensions.executable}"
printf "checking whether executable runs... " >& 2
cat ${packages.use-cabal-simple.components.exes.use-cabal-simple.run}
cat ${haskellLib.check packages.use-cabal-simple.components.exes.use-cabal-simple}
touch $out
'';

View File

@ -22,7 +22,9 @@ let
packages = project.hsPkgs;
in recurseIntoAttrs {
inherit (project) plan-nix;
ifdInputs = {
inherit (project) plan-nix;
};
run = stdenv.mkDerivation {
name = "cabal-sublib-test";
@ -34,7 +36,7 @@ in recurseIntoAttrs {
# fixme: run on target platform when cross-compiled
printf "checking whether executable runs... " >& 2
cat ${packages.cabal-sublib.components.exes.cabal-sublib.run}
cat ${haskellLib.check packages.cabal-sublib.components.exes.cabal-sublib}
printf "checking that executable is dynamically linked to system libraries... " >& 2
'' + optionalString stdenv.isLinux ''

View File

@ -1,4 +1,4 @@
{ stdenv, mkCabalProjectPkgSet, callCabalProjectToNix, importAndFilterProject, recurseIntoAttrs }:
{ stdenv, mkCabalProjectPkgSet, callCabalProjectToNix, importAndFilterProject, recurseIntoAttrs, haskellLib }:
with stdenv.lib;
@ -17,7 +17,9 @@ let
packages = pkgSet.config.hsPkgs;
in recurseIntoAttrs {
plan-nix = plan.nix;
ifdInputs = {
plan-nix = plan.nix;
};
run = stdenv.mkDerivation {
name = "call-cabal-project-to-nix-test";
@ -25,7 +27,7 @@ in recurseIntoAttrs {
exe="${packages.cabal-simple.components.exes.cabal-simple}/bin/cabal-simple${stdenv.hostPlatform.extensions.executable}"
printf "checking whether executable runs... " >& 2
cat ${packages.cabal-simple.components.exes.cabal-simple.run}
cat ${haskellLib.check packages.cabal-simple.components.exes.cabal-simple}
touch $out
'';

View File

@ -1,4 +1,4 @@
{ stdenv, mkStackPkgSet, callStackToNix, importAndFilterProject, recurseIntoAttrs }:
{ stdenv, mkStackPkgSet, callStackToNix, importAndFilterProject, recurseIntoAttrs, haskellLib }:
with stdenv.lib;
@ -14,7 +14,9 @@ let
packages = pkgSet.config.hsPkgs;
in recurseIntoAttrs {
stack-nix = stack.nix;
ifdInputs = {
stack-nix = stack.nix;
};
run = stdenv.mkDerivation {
name = "callStackToNix-test";
@ -22,7 +24,7 @@ in recurseIntoAttrs {
exe="${packages.stack-simple.components.exes.stack-simple-exe}/bin/stack-simple-exe${stdenv.hostPlatform.extensions.executable}"
printf "checking whether executable runs... " >& 2
cat ${packages.stack-simple.components.exes.stack-simple-exe.run}
cat ${haskellLib.check packages.stack-simple.components.exes.stack-simple-exe}
touch $out
'';

View File

@ -1,14 +1,23 @@
{ pkgs ? import nixpkgs ((import ../.) // nixpkgsArgs)
, nixpkgs ? ../nixpkgs
, nixpkgsArgs ? { }
, ifdLevel ? 1000
}:
with pkgs;
let
withIfdInputs = builtins.mapAttrs (n: x:
if n == "ifdInputs"
then pkgs.recurseIntoAttrs (builtins.mapAttrs (_: pkgs.haskell-nix.withInputs) x)
else x);
util = import ./util.nix { inherit (pkgs.haskell-nix) cabal-install; };
in pkgs.recurseIntoAttrs {
inherit (haskell-nix) haskellNixRoots;
haskellNixRoots = haskell-nix.haskellNixRoots' ifdLevel;
} // pkgs.lib.optionalAttrs (ifdLevel > 1) (
builtins.mapAttrs (_: y: withIfdInputs y) ((if ifdLevel < 3
then builtins.mapAttrs (_: d: pkgs.recurseIntoAttrs (pkgs.lib.filterAttrs (n: _: n == "ifdInputs") d))
else x: x) {
cabal-simple = haskell-nix.callPackage ./cabal-simple { inherit util; };
cabal-simple-prof = haskell-nix.callPackage ./cabal-simple-prof { inherit util; };
cabal-sublib = haskell-nix.callPackage ./cabal-sublib { inherit util; };
@ -38,7 +47,7 @@ in pkgs.recurseIntoAttrs {
in runCommand "unit-tests" { passthru = { inherit tests; }; }
(lib.concatMapStringsSep "\n" (t: "echo ${t.name} failed") tests +
(if builtins.length tests == 0 then "\ntouch $out" else "\nexit 1"));
}
}))
## more possible test cases
# 1. fully static linking

View File

@ -1,5 +1,5 @@
# Test a package set
{ stdenv, util, haskell-nix, recurseIntoAttrs }:
{ stdenv, util, haskell-nix, recurseIntoAttrs, haskellLib }:
with stdenv.lib;
@ -12,7 +12,9 @@ let
packages = project.hsPkgs;
in recurseIntoAttrs {
inherit (project) plan-nix;
ifdInputs = {
inherit (project) plan-nix;
};
run = stdenv.mkDerivation {
name = "exe-only-test";
@ -24,7 +26,7 @@ in recurseIntoAttrs {
# fixme: run on target platform when cross-compiled
printf "checking whether executable ran... " >& 2
cat ${packages.exe-only.components.exes.exe-only.run}
cat ${haskellLib.check packages.exe-only.components.exes.exe-only}
'' + (if stdenv.hostPlatform.isMusl then ''
printf "checking that executable is statically linked... " >& 2
(ldd $exe 2>&1 || true) | grep -i "not a"

View File

@ -53,8 +53,10 @@ let
packagesIntegerSimple = (project { gpl = false; }).hsPkgs;
in recurseIntoAttrs {
stack-nix-gmp = (project { gpl = true; }).stack-nix;
stack-nix-simple = (project { gpl = false; }).stack-nix;
ifdInputs = {
stack-nix-gmp = (project { gpl = true; }).stack-nix;
stack-nix-simple = (project { gpl = false; }).stack-nix;
};
run = stdenv.mkDerivation {
name = "fully-static-test";

View File

@ -1,4 +1,4 @@
{ stdenv, cabalProject', recurseIntoAttrs }:
{ stdenv, cabalProject', recurseIntoAttrs, haskellLib }:
with stdenv.lib;
@ -13,13 +13,15 @@ let
packages = project.hsPkgs;
in recurseIntoAttrs {
inherit (project) plan-nix;
ifdInputs = {
inherit (project) plan-nix;
};
run = stdenv.mkDerivation {
name = "call-cabal-project-to-nix-test";
buildCommand = ''
printf "checking whether executable runs... " >& 2
cat ${packages.test-ghc-options.components.exes.test-ghc-options-exe.run}
cat ${haskellLib.check packages.test-ghc-options.components.exes.test-ghc-options-exe}
touch $out
'';

View File

@ -1,4 +1,4 @@
{ stdenv, stackProject', recurseIntoAttrs }:
{ stdenv, stackProject', recurseIntoAttrs, haskellLib }:
with stdenv.lib;
@ -9,13 +9,15 @@ let
packages = project.hsPkgs;
in recurseIntoAttrs {
inherit (project) stack-nix;
ifdInputs = {
inherit (project) stack-nix;
};
run = stdenv.mkDerivation {
name = "callStackToNix-test";
buildCommand = ''
printf "checking whether executable runs... " >& 2
cat ${packages.test-ghc-options.components.exes.test-ghc-options-exe.run}
cat ${haskellLib.check packages.test-ghc-options.components.exes.test-ghc-options-exe}
touch $out
'';

View File

@ -1,4 +1,4 @@
{ stdenv, cabalProject', recurseIntoAttrs }:
{ stdenv, cabalProject', recurseIntoAttrs, haskellLib }:
with stdenv.lib;
@ -11,7 +11,9 @@ let
packages = project.hsPkgs;
in recurseIntoAttrs {
inherit (project) plan-nix;
ifdInputs = {
inherit (project) plan-nix;
};
run = stdenv.mkDerivation {
name = "call-cabal-project-to-nix-test";
@ -19,7 +21,7 @@ in recurseIntoAttrs {
exe="${packages.test-project-flags.components.exes.test-project-flags-exe}/bin/test-project-flags-exe${stdenv.hostPlatform.extensions.executable}"
printf "checking whether executable runs... " >& 2
cat ${packages.test-project-flags.components.exes.test-project-flags-exe.run}
cat ${haskellLib.check packages.test-project-flags.components.exes.test-project-flags-exe}
touch $out
'';

View File

@ -1,4 +1,4 @@
{ stdenv, stackProject', recurseIntoAttrs }:
{ stdenv, stackProject', recurseIntoAttrs, haskellLib }:
with stdenv.lib;
@ -9,7 +9,9 @@ let
packages = project.hsPkgs;
in recurseIntoAttrs {
inherit (project) stack-nix;
ifdInputs = {
inherit (project) stack-nix;
};
run = stdenv.mkDerivation {
name = "callStackToNix-test";
@ -17,7 +19,7 @@ in recurseIntoAttrs {
exe="${packages.test-project-flags.components.exes.test-project-flags-exe}/bin/test-project-flags-exe${stdenv.hostPlatform.extensions.executable}"
printf "checking whether executable runs... " >& 2
cat ${packages.test-project-flags.components.exes.test-project-flags-exe.run}
cat ${haskellLib.check packages.test-project-flags.components.exes.test-project-flags-exe}
touch $out
'';

View File

@ -23,11 +23,13 @@ in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
touch $out
'';
in {
plan-nix = skip;
ifdInputs = { plan-nix = skip; };
run = skip;
}
else {
inherit (project) plan-nix;
ifdInputs = {
inherit (project) plan-nix;
};
run = pkgs.stdenv.mkDerivation {
name = "setup-deps-test";

View File

@ -22,12 +22,14 @@ in recurseIntoAttrs (if stdenv.hostPlatform.isWindows
touch $out
'';
in {
plan-nix = skip;
ifdInputs = { plan-nix = skip; };
env = skip;
run = skip;
}
else {
inherit (project) plan-nix;
ifdInputs = {
inherit (project) plan-nix;
};
inherit env;
run = stdenv.mkDerivation {
name = "shell-for-test";

View File

@ -1,4 +1,4 @@
{ stdenv, pkgs, mkStackPkgSet }:
{ stdenv, pkgs, mkStackPkgSet, haskellLib }:
with stdenv.lib;
@ -14,9 +14,10 @@ let
packages = pkgSet.config.hsPkgs;
in pkgs.recurseIntoAttrs {
stack-simple-exe = packages.stack-simple.components.exes.stack-simple-exe.run // {
stack-simple-exe = (haskellLib.check packages.stack-simple.components.exes.stack-simple-exe) // {
# Attributes used for debugging with nix repl
inherit pkgSet packages;
};
stack-simple-test = packages.stack-simple.components.tests.stack-simple-test.run;
stack-simple-test = packages.stack-simple.checks.stack-simple-test;
stack-simple-checks = packages.stack-simple.checks;
}