diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 5a2846c460..9eaae77ad1 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -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 diff --git a/build.nix b/build.nix index 7acf14bad4..114cef40c8 100644 --- a/build.nix +++ b/build.nix @@ -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; + }) + ); } diff --git a/builder/comp-builder.nix b/builder/comp-builder.nix index 52b10865a6..564732f2b1 100644 --- a/builder/comp-builder.nix +++ b/builder/comp-builder.nix @@ -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"; } diff --git a/builder/hspkg-builder.nix b/builder/hspkg-builder.nix index d5e2656821..b244cde960 100644 --- a/builder/hspkg-builder.nix +++ b/builder/hspkg-builder.nix @@ -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; diff --git a/docs/reference/library.md b/docs/reference/library.md index b44af52b83..513fee4a6e 100644 --- a/docs/reference/library.md +++ b/docs/reference/library.md @@ -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: diff --git a/lib/call-cabal-project-to-nix.nix b/lib/call-cabal-project-to-nix.nix index b97e090d4a..7f7c937c1c 100644 --- a/lib/call-cabal-project-to-nix.nix +++ b/lib/call-cabal-project-to-nix.nix @@ -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 { diff --git a/lib/call-stack-to-nix.nix b/lib/call-stack-to-nix.nix index 7a607d0a6d..5089f3e570 100644 --- a/lib/call-stack-to-nix.nix +++ b/lib/call-stack-to-nix.nix @@ -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) '' diff --git a/lib/check.nix b/lib/check.nix new file mode 100644 index 0000000000..f1626cdc3b --- /dev/null +++ b/lib/check.nix @@ -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; +}) diff --git a/lib/default.nix b/lib/default.nix index ed95685cf7..a0230093e6 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -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; + }; } diff --git a/modules/plan.nix b/modules/plan.nix index e2755ddafc..d604b1d7cb 100644 --- a/modules/plan.nix +++ b/modules/plan.nix @@ -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."; diff --git a/overlays/bootstrap.nix b/overlays/bootstrap.nix index f9da41d99a..37bcc94eea 100644 --- a/overlays/bootstrap.nix +++ b/overlays/bootstrap.nix @@ -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; }; }; }; diff --git a/overlays/haskell.nix b/overlays/haskell.nix index 54f1b82904..ec81691d59 100644 --- a/overlays/haskell.nix +++ b/overlays/haskell.nix @@ -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); + }); }; } diff --git a/package-set.nix b/package-set.nix index b8f2ea9859..63523a8831 100644 --- a/package-set.nix +++ b/package-set.nix @@ -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 diff --git a/release.nix b/release.nix index 6b75de73e2..98cedb1827 100644 --- a/release.nix +++ b/release.nix @@ -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; }); }); diff --git a/scripts/check-hydra.nix b/scripts/check-hydra.nix index a2b10ff866..7f54b87479 100644 --- a/scripts/check-hydra.nix +++ b/scripts/check-hydra.nix @@ -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 ] diff --git a/test/buildable/default.nix b/test/buildable/default.nix index b7e703c438..c06d072fe0 100644 --- a/test/buildable/default.nix +++ b/test/buildable/default.nix @@ -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 ''; diff --git a/test/cabal-22/default.nix b/test/cabal-22/default.nix index 4e1a7d2d55..777ba0e743 100644 --- a/test/cabal-22/default.nix +++ b/test/cabal-22/default.nix @@ -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; diff --git a/test/cabal-simple-prof/default.nix b/test/cabal-simple-prof/default.nix index 39c03c84bc..d0dad6fbe2 100644 --- a/test/cabal-simple-prof/default.nix +++ b/test/cabal-simple-prof/default.nix @@ -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"; diff --git a/test/cabal-simple/default.nix b/test/cabal-simple/default.nix index deaa452e31..82eaeb142d 100644 --- a/test/cabal-simple/default.nix +++ b/test/cabal-simple/default.nix @@ -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" diff --git a/test/cabal-source-repo/default.nix b/test/cabal-source-repo/default.nix index 14d97e4c4f..22289a7eb6 100644 --- a/test/cabal-source-repo/default.nix +++ b/test/cabal-source-repo/default.nix @@ -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 ''; diff --git a/test/cabal-sublib/default.nix b/test/cabal-sublib/default.nix index 7b2fa79822..bc23264897 100644 --- a/test/cabal-sublib/default.nix +++ b/test/cabal-sublib/default.nix @@ -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 '' diff --git a/test/call-cabal-project-to-nix/default.nix b/test/call-cabal-project-to-nix/default.nix index 5d3dadbd97..73fbab1fcd 100644 --- a/test/call-cabal-project-to-nix/default.nix +++ b/test/call-cabal-project-to-nix/default.nix @@ -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 ''; diff --git a/test/call-stack-to-nix/default.nix b/test/call-stack-to-nix/default.nix index 2bacfea781..c0701da065 100644 --- a/test/call-stack-to-nix/default.nix +++ b/test/call-stack-to-nix/default.nix @@ -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 ''; diff --git a/test/default.nix b/test/default.nix index cbed52242a..3657b8d6ae 100644 --- a/test/default.nix +++ b/test/default.nix @@ -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 diff --git a/test/exe-only/default.nix b/test/exe-only/default.nix index baaf91dfca..356d7f8f9f 100644 --- a/test/exe-only/default.nix +++ b/test/exe-only/default.nix @@ -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" diff --git a/test/fully-static/default.nix b/test/fully-static/default.nix index 44ae613627..8320a45f4c 100644 --- a/test/fully-static/default.nix +++ b/test/fully-static/default.nix @@ -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"; diff --git a/test/ghc-options/cabal.nix b/test/ghc-options/cabal.nix index 6569ab2321..d5ba605f66 100644 --- a/test/ghc-options/cabal.nix +++ b/test/ghc-options/cabal.nix @@ -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 ''; diff --git a/test/ghc-options/stack.nix b/test/ghc-options/stack.nix index 9b3bdc16b5..55f0bf79c7 100644 --- a/test/ghc-options/stack.nix +++ b/test/ghc-options/stack.nix @@ -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 ''; diff --git a/test/project-flags/cabal.nix b/test/project-flags/cabal.nix index 76c7fc1cf2..ec4d54af88 100644 --- a/test/project-flags/cabal.nix +++ b/test/project-flags/cabal.nix @@ -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 ''; diff --git a/test/project-flags/stack.nix b/test/project-flags/stack.nix index de16d6e1ed..7b60bba117 100644 --- a/test/project-flags/stack.nix +++ b/test/project-flags/stack.nix @@ -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 ''; diff --git a/test/setup-deps/default.nix b/test/setup-deps/default.nix index 995c98f29b..74c526b6dc 100644 --- a/test/setup-deps/default.nix +++ b/test/setup-deps/default.nix @@ -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"; diff --git a/test/shell-for-setup-deps/default.nix b/test/shell-for-setup-deps/default.nix index d6cb710edc..1647b583f5 100644 --- a/test/shell-for-setup-deps/default.nix +++ b/test/shell-for-setup-deps/default.nix @@ -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"; diff --git a/test/stack-simple/default.nix b/test/stack-simple/default.nix index 56ab1c361f..f476347a2f 100644 --- a/test/stack-simple/default.nix +++ b/test/stack-simple/default.nix @@ -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; }