From 64e52fb36022af7186bbe21807619ec3ea7464d8 Mon Sep 17 00:00:00 2001 From: Samuel Evans-Powell Date: Mon, 3 Aug 2020 12:26:21 +0800 Subject: [PATCH] WIP --- lib/cover-files-only.nix | 100 +++++++++++++++++++++++++++++++++++++++ lib/default.nix | 4 ++ overlays/haskell.nix | 19 +++++++- 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 lib/cover-files-only.nix diff --git a/lib/cover-files-only.nix b/lib/cover-files-only.nix new file mode 100644 index 0000000000..3709e66e4c --- /dev/null +++ b/lib/cover-files-only.nix @@ -0,0 +1,100 @@ +{ pkgs, stdenv, lib, haskellLib }: + +projects: + +let + buildWithCoverage = builtins.map (d: d.covered); + runCheck = builtins.map (d: haskellLib.check d); + + # drvs' = buildWithCoverage drvs; + # drvSources = builtins.map (d: d.src.outPath) drvs; + # testsWithCoverage = buildWithCoverage tests; + # checks' = runCheck testsWithCoverage; + drvs' = null; + drvSources = null; + testsWithCoverage = null; + checks' = null; + + projects' = builtins.map (p: + rec { + name = p.name; + drv = p.drv.covered; + testsWithCoverage = buildWithCoverage p.tests; + checks = runCheck testsWithCoverage; + } + ) projects; + + doThis = p: '' + mkdir $out/share/hpc/mix/${p.name} + + for drv in ${lib.concatStringsSep " " ([ p.drv ] ++ p.testsWithCoverage)}; do + # Copy over mix files + local mixDir=$(findMixDir $drv) + echo "MixDir: $mixDir" + cp -R $mixDir/* $out/share/hpc/mix/${p.name} + done + ''; + +in stdenv.mkDerivation { + name = "coverage-report"; + + inherit checks' drvs' drvSources; + + phases = ["buildPhase"]; + + buildInputs = (with pkgs.haskellPackages; [ + ghc + ]); + + buildPhase = '' + mkdir -p $out/share/hpc/mix + mkdir -p $out/share/hpc/tix + mkdir -p $out/share/hpc/tix/all + + findMixDir() { + find $1 -iwholename "*/hpc/vanilla/mix" -exec find {} -maxdepth 1 -type d -iwholename "*/mix/*" \; -quit + } + + findCabalFile() { + find $1 -iname "*.cabal" -print -quit + } + + ${lib.concatStringsSep "\n" (builtins.map doThis projects')} + + ''; + + # for check in ${lib.concatStringsSep " " checks'}; do + # cp -R $check/share/hpc/tix/* $out/share/hpc/tix + # done + + # # For each derivation to generate coverage for + # for drv in ${lib.concatStringsSep " " (drvs' ++ testsWithCoverage)}; do + # # Copy over mix files + # local mixDir=$(findMixDir $drv) + # echo "MixDir: $mixDir" + # cp -R $mixDir/* $out/share/hpc/mix/ + # done + + # excludedModules=("Main") + # for drv in ${lib.concatStringsSep " " drvSources}; do + # # Exclude test modules + # local cabalFile=$(findCabalFile $drv) + # for module in $(${pkgs.cq}/bin/cq $cabalFile testModules | ${pkgs.jq}/bin/jq ".[]"); do + # excludedModules+=("$module") + # done + # done + # echo "''${excludedModules[@]}" + + # tixFile="$out/share/hpc/tix/all/all.tix" + # hpcSumCmd=("hpc" "sum" "--union" "--output=$tixFile") + # for check in ${lib.concatStringsSep " " checks'}; do + # for tix in $(find $check -name '*.tix' -print); do + # hpcSumCmd+=("$tix") + # done + # done + # for exclude in ''${excludedModules[@]}; do + # hpcSumCmd+=("--exclude=$exclude") + # done + # echo "''${hpcSumCmd[@]}" + # eval "''${hpcSumCmd[@]}" +} diff --git a/lib/default.nix b/lib/default.nix index 7402c9eaff..d1b9fc9fdf 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -244,6 +244,10 @@ in { inherit stdenv lib haskellLib; }; + coverageReport' = import ./cover-files-only.nix { + inherit stdenv lib haskellLib pkgs; + }; + # 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. diff --git a/overlays/haskell.nix b/overlays/haskell.nix index 7ae5eb7dfc..7c0d2b0fec 100644 --- a/overlays/haskell.nix +++ b/overlays/haskell.nix @@ -473,11 +473,13 @@ final: prev: { { compiler.nix-name = args.compiler-nix-name; }; extra-hackages = args.extra-hackages or []; }; - in addProjectAndPackageAttrs { + in addProjectAndPackageAttrs rec { inherit (pkg-set.config) hsPkgs; inherit pkg-set; plan-nix = callProjectResults.projectNix; inherit (callProjectResults) index-state; + + coverageReport = projectCoverageReport (haskellLib.selectProjectPackages hsPkgs); }; # Take `hsPkgs` from the `rawProject` and update all the packages and @@ -509,7 +511,7 @@ final: prev: { cabalProject = args: let p = cabalProject' args; in p.hsPkgs // { - inherit (p) plan-nix; + inherit (p) plan-nix coverageReport; # Provide `nix-shell -A shells.ghc` for users migrating from the reflex-platform. # But we should encourage use of `nix-shell -A shellFor` shells.ghc = p.hsPkgs.shellFor {}; @@ -582,6 +584,19 @@ final: prev: { } // final.lib.optionalAttrs (p ? stack-nix) { inherit (p) stack-nix; } // final.lib.optionalAttrs (p ? plan-nix ) { inherit (p) plan-nix; }; + projectCoverageReport = packages: + let + # TODO what if package doesn't have library and/or tests? + projectInfo = with final.lib; + mapAttrsToList (n: p: { + name = n; + drv = p.components.library; + tests = filter isDerivation (attrValues p.components.tests); + } + ) packages; + in + haskellLib.coverageReport' projectInfo; + # Like `cabalProject'`, but for building the GHCJS compiler. # This is exposed to allow GHCJS developers to work on the GHCJS # code in a nix-shell with `shellFor`.