mirror of
https://github.com/ilyakooo0/haskell.nix.git
synced 2024-10-26 09:37:17 +03:00
Add support for coverage (#762)
- Added the ability to generate coverage reports for packages and projects. - Outputs mix and tix information, as well as a HTML report. - Added the "doCoverage" module option that allows users to choose packages to enable coverage for. - Added a "doCoverage" flag to the component builder that outputs HPC information when coverage is enabled. - Added the "overrideModules" library function to make it more ergonomic fo users to enable coverage on existing projects. - Modified the "check" builder to also output ".tix" files (if they exist). This information is required to generate the coverage report. - Added a test for coverage.
This commit is contained in:
parent
742932a968
commit
48b8674f5f
@ -53,6 +53,9 @@ let self =
|
|||||||
, enableExecutableProfiling ? component.enableExecutableProfiling
|
, enableExecutableProfiling ? component.enableExecutableProfiling
|
||||||
, profilingDetail ? component.profilingDetail
|
, profilingDetail ? component.profilingDetail
|
||||||
|
|
||||||
|
# Coverage
|
||||||
|
, doCoverage ? component.doCoverage
|
||||||
|
|
||||||
# Data
|
# Data
|
||||||
, enableSeparateDataOutput ? component.enableSeparateDataOutput
|
, enableSeparateDataOutput ? component.enableSeparateDataOutput
|
||||||
|
|
||||||
@ -118,6 +121,7 @@ let
|
|||||||
(enableFeature enableExecutableProfiling "executable-profiling")
|
(enableFeature enableExecutableProfiling "executable-profiling")
|
||||||
(enableFeature enableStatic "static")
|
(enableFeature enableStatic "static")
|
||||||
(enableFeature enableShared "shared")
|
(enableFeature enableShared "shared")
|
||||||
|
(enableFeature doCoverage "coverage")
|
||||||
] ++ lib.optionals (stdenv.hostPlatform.isMusl && (haskellLib.isExecutableType componentId)) [
|
] ++ lib.optionals (stdenv.hostPlatform.isMusl && (haskellLib.isExecutableType componentId)) [
|
||||||
# These flags will make sure the resulting executable is statically linked.
|
# These flags will make sure the resulting executable is statically linked.
|
||||||
# If it uses other libraries it may be necessary for to add more
|
# If it uses other libraries it may be necessary for to add more
|
||||||
@ -358,6 +362,11 @@ let
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
'')
|
'')
|
||||||
|
+ (lib.optionalString doCoverage ''
|
||||||
|
mkdir -p $out/share
|
||||||
|
cp -r dist/hpc $out/share
|
||||||
|
cp dist/setup-config $out/
|
||||||
|
'')
|
||||||
}
|
}
|
||||||
runHook postInstall
|
runHook postInstall
|
||||||
'' + (lib.optionalString keepSource ''
|
'' + (lib.optionalString keepSource ''
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
This file contains a summary of changes to Haskell.nix and `nix-tools`
|
This file contains a summary of changes to Haskell.nix and `nix-tools`
|
||||||
that will impact users.
|
that will impact users.
|
||||||
|
|
||||||
|
## Sep 8, 2020
|
||||||
|
* Added the ability to generate coverage reports for packages and
|
||||||
|
projects.
|
||||||
|
* Added the `doCoverage` module option that allows users to choose
|
||||||
|
packages to enable coverage for.
|
||||||
|
* Added a `doCoverage` flag to the component builder that outputs HPC
|
||||||
|
information when coverage is enabled.
|
||||||
|
* Added test for coverage.
|
||||||
|
|
||||||
## July 21, 2020
|
## July 21, 2020
|
||||||
* Removed `components.all`, use `symlinkJoin` on components.exes or
|
* Removed `components.all`, use `symlinkJoin` on components.exes or
|
||||||
`shellFor` if you need a shell.
|
`shellFor` if you need a shell.
|
||||||
|
180
docs/dev/coverage.md
Normal file
180
docs/dev/coverage.md
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
# Developer Coverage Overview
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
The implementation of coverage starts with the "doCoverage" flag on
|
||||||
|
the builder in `comp-builder.nix`. The doCoverage flag enables and
|
||||||
|
disables the Cabal coverage flag and copies any generated coverage
|
||||||
|
data to "$out/share/hpc".
|
||||||
|
|
||||||
|
### Mix and tix files
|
||||||
|
|
||||||
|
The coverage information for any derivation consists of "mix" and
|
||||||
|
"tix" files.
|
||||||
|
|
||||||
|
Mix files record static information about a source file and are
|
||||||
|
generated at build time. They primarily contain a path to the source
|
||||||
|
file and information about expressions and regions of the source file,
|
||||||
|
which are later referenced by tix files.
|
||||||
|
|
||||||
|
Tix files contain dynamic information about a test run, recording when
|
||||||
|
a portion of a source file is touched by a test. These are generated
|
||||||
|
when the test is run.
|
||||||
|
|
||||||
|
### Multiple local packages
|
||||||
|
|
||||||
|
In the context of multiple local packages, there are a few types of
|
||||||
|
coverage we might be interested in:
|
||||||
|
- How well does the tests for this package cover the package library?
|
||||||
|
- How well does the tests for this package cover the libraries of
|
||||||
|
other packages in this project?
|
||||||
|
- Both of the above.
|
||||||
|
|
||||||
|
To facilitate expressing any of these classifications of coverage, the
|
||||||
|
`lib/cover.nix` function provides the `mixLibraries` argument. If
|
||||||
|
you're just interested in how the tests cover the package library, you
|
||||||
|
provide that library as an argument to `mixLibraries`. If you're
|
||||||
|
interested in how the tests also cover other local packages in the
|
||||||
|
project, you can also provide those libraries as arguments to
|
||||||
|
mixLibraries.
|
||||||
|
|
||||||
|
The `projectCoverageReport` and `coverageReport` attributes that are
|
||||||
|
provided by default on projects and packages respectively provide
|
||||||
|
coverage information for *all* local packages in the project. This is
|
||||||
|
to mimic the behaviour of Stack, which seems to be the expectation of
|
||||||
|
most people. Of course, you can use the `projectCoverageReport` and
|
||||||
|
`coverageReport` functions to construct your own custom coverage
|
||||||
|
reports (as detailed in the [coverage tutorial](../tutorials/coverage.md#custom)).
|
||||||
|
|
||||||
|
## Coverage reports
|
||||||
|
|
||||||
|
### Package reports
|
||||||
|
|
||||||
|
The coverage information generated will look something like this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/nix/store/...-my-project-0.1.0.0-coverage-report/
|
||||||
|
└── share
|
||||||
|
└── hpc
|
||||||
|
└── vanilla
|
||||||
|
├── html
|
||||||
|
│ └── my-library-0.1.0.0
|
||||||
|
│ ├── my-library-0.1.0.0-48EVZBwW9Kj29VTaRMhBDf
|
||||||
|
│ │ ├── My.Lib.Config.hs.html
|
||||||
|
│ │ ├── My.Lib.Types.hs.html
|
||||||
|
│ │ └── My.Lib.Util.hs.html
|
||||||
|
│ ├── hpc_index_alt.html
|
||||||
|
│ ├── hpc_index_exp.html
|
||||||
|
│ ├── hpc_index_fun.html
|
||||||
|
│ └── hpc_index.html
|
||||||
|
├── mix
|
||||||
|
│ └── my-library-0.1.0.0
|
||||||
|
│ └── my-library-0.1.0.0-48EVZBwW9Kj29VTaRMhBDf
|
||||||
|
│ ├── My.Lib.Config.mix
|
||||||
|
│ ├── My.Lib.Types.mix
|
||||||
|
│ └── My.Lib.Util.mix
|
||||||
|
└── tix
|
||||||
|
└── my-library-0.1.0.0
|
||||||
|
├── my-library-0.1.0.0.tix
|
||||||
|
├── my-test-1
|
||||||
|
│ └── my-test-1.tix
|
||||||
|
└── unit-test
|
||||||
|
└── unit-test.tix
|
||||||
|
```
|
||||||
|
|
||||||
|
- The mix files are copied verbatim from the library built with
|
||||||
|
coverage.
|
||||||
|
- The tix files for each test are copied from the check run verbatim
|
||||||
|
and are output to ".../tix/<libraryname>/<testname>/<testname>.tix".
|
||||||
|
- The tix files for each library are generated by summing the tix
|
||||||
|
files for each test, but excluding any test modules. This tix file
|
||||||
|
is output to ".../tix/<libraryname>/<libraryname>.tix".
|
||||||
|
- Test modules are determined by inspecting the plan for the project
|
||||||
|
(i.e. for the project "my-project" and test-suite "my-test-1", the
|
||||||
|
test modules are read from:
|
||||||
|
`my-project.checks.my-test-1.config.modules`)
|
||||||
|
- The hpc HTML reports for each library are generated from their
|
||||||
|
respective tix files (i.e. the
|
||||||
|
`share/hpc/vanilla/html/my-library-0.1.0.0` report is generated from
|
||||||
|
the
|
||||||
|
`share/hpc/vanilla/tix/my-library-0.1.0.0/my-library-0.1.0.0.tix`
|
||||||
|
file)
|
||||||
|
|
||||||
|
### Project-wide reports
|
||||||
|
|
||||||
|
The coverage information for an entire project will look something
|
||||||
|
like this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/nix/store/...-coverage-report
|
||||||
|
└── share
|
||||||
|
└── hpc
|
||||||
|
└── vanilla
|
||||||
|
├── html
|
||||||
|
│ ├── index.html
|
||||||
|
│ ├── all
|
||||||
|
│ │ ├── my-library-0.1.0.0-ERSaOroBZhe9awsoBkhmcV
|
||||||
|
│ │ │ ├── My.Lib.Config.hs.html
|
||||||
|
│ │ │ ├── My.Lib.Types.hs.html
|
||||||
|
│ │ │ └── My.Lib.Util.hs.html
|
||||||
|
│ │ ├── other-library-0.1.0.0-48EVZBwW9Kj29VTaRMhBDf
|
||||||
|
│ │ │ ├── Other.Lib.A.hs.html
|
||||||
|
│ │ │ └── Other.Lib.B.hs.html
|
||||||
|
│ │ ├── hpc_index_alt.html
|
||||||
|
│ │ ├── hpc_index_exp.html
|
||||||
|
│ │ ├── hpc_index_fun.html
|
||||||
|
│ │ └── hpc_index.html
|
||||||
|
│ ├── my-library-0.1.0.0
|
||||||
|
│ │ ├── my-library-0.1.0.0-ERSaOroBZhe9awsoBkhmcV
|
||||||
|
│ │ │ ├── My.Lib.Config.hs.html
|
||||||
|
│ │ │ ├── My.Lib.Types.hs.html
|
||||||
|
│ │ │ └── My.Lib.Util.hs.html
|
||||||
|
│ │ ├── hpc_index_alt.html
|
||||||
|
│ │ ├── hpc_index_exp.html
|
||||||
|
│ │ ├── hpc_index_fun.html
|
||||||
|
│ │ └── hpc_index.html
|
||||||
|
│ └── other-libray-0.1.0.0
|
||||||
|
│ ├── other-library-0.1.0.0-48EVZBwW9Kj29VTaRMhBDf
|
||||||
|
│ │ ├── Other.Lib.A.hs.html
|
||||||
|
│ │ └── Other.Lib.B.hs.html
|
||||||
|
│ ├── hpc_index_alt.html
|
||||||
|
│ ├── hpc_index_exp.html
|
||||||
|
│ ├── hpc_index_fun.html
|
||||||
|
│ └── hpc_index.html
|
||||||
|
├── mix
|
||||||
|
│ ├── my-library-0.1.0.0-ERSaOroBZhe9awsoBkhmcV
|
||||||
|
│ │ ├── My.Lib.Config.mix
|
||||||
|
│ │ ├── My.Lib.Types.mix
|
||||||
|
│ │ └── My.Lib.Util.mix
|
||||||
|
│ └── other-library-0.1.0.0-48EVZBwW9Kj29VTaRMhBDf
|
||||||
|
│ ├── Other.Lib.A.mix
|
||||||
|
│ └── Other.Lib.B.mix
|
||||||
|
└── tix
|
||||||
|
├── all
|
||||||
|
│ └── all.tix
|
||||||
|
├── my-library-0.1.0.0
|
||||||
|
│ ├── my-library-0.1.0.0.tix
|
||||||
|
│ ├── my-test-1
|
||||||
|
│ │ └── my-test-1.tix
|
||||||
|
│ └── unit-test
|
||||||
|
│ └── unit-test.tix
|
||||||
|
└── another-library-0.1.0.0
|
||||||
|
├── another-library-0.1.0.0.tix
|
||||||
|
├── my-test-2
|
||||||
|
│ └── my-test-2.tix
|
||||||
|
└── unit-test
|
||||||
|
└── unit-test.tix
|
||||||
|
```
|
||||||
|
|
||||||
|
All of the coverage information is copied verbatim from the coverage
|
||||||
|
reports for each of the constituent packages. A few additions are
|
||||||
|
made:
|
||||||
|
- `tix/all/all.tix` is generated from the union of all the library
|
||||||
|
tix files.
|
||||||
|
- We use this file when generating coverage reports for
|
||||||
|
"coveralls.io".
|
||||||
|
- An index page (`html/index.html`) is generated which links to the
|
||||||
|
HTML coverage reports of the constituent packages.
|
||||||
|
- A synthetic HTML report is generated from the `tix/all/all.tix`
|
||||||
|
file. This shows the union of all the coverage information
|
||||||
|
generated by each constituent coverage report.
|
123
docs/tutorials/coverage.md
Normal file
123
docs/tutorials/coverage.md
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# Coverage
|
||||||
|
|
||||||
|
haskell.nix can generate coverage information for your package or
|
||||||
|
project using Cabal's inbuilt hpc support.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
To get a sensible coverage report, you need to enable coverage on each
|
||||||
|
of the packages of your project:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
pkgs.haskell-nix.project {
|
||||||
|
src = pkgs.haskell-nix.haskellLib.cleanGit {
|
||||||
|
name = "haskell-nix-project";
|
||||||
|
src = ./.;
|
||||||
|
};
|
||||||
|
compiler-nix-name = "ghc884";
|
||||||
|
|
||||||
|
modules = [{
|
||||||
|
packages.$pkg.components.library.doCoverage = true;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you would like to make coverage optional, add an argument to your nix expression:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ withCoverage ? false }:
|
||||||
|
|
||||||
|
pkgs.haskell-nix.project {
|
||||||
|
src = pkgs.haskell-nix.haskellLib.cleanGit {
|
||||||
|
name = "haskell-nix-project";
|
||||||
|
src = ./.;
|
||||||
|
};
|
||||||
|
compiler-nix-name = "ghc884";
|
||||||
|
|
||||||
|
modules = pkgs.lib.optional withCoverage [{
|
||||||
|
packages.$pkg.components.library.doCoverage = true;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Per-package
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix-build default.nix -A "projectWithCoverage.$pkg.coverageReport"
|
||||||
|
```
|
||||||
|
|
||||||
|
This will generate a coverage report for the package you requested.
|
||||||
|
All tests that are enabled (configured with `doCheck == true`) are
|
||||||
|
included in the coverage report.
|
||||||
|
|
||||||
|
See the [developer coverage docs](../dev/coverage.md#package-reports) for more information.
|
||||||
|
|
||||||
|
## Project-wide
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix-build default.nix -A "projectWithCoverage.projectCoverageReport"
|
||||||
|
```
|
||||||
|
|
||||||
|
This will generate a coverage report for all the local packages in
|
||||||
|
your project.
|
||||||
|
|
||||||
|
See the [developer coverage docs](../dev/coverage.md#project-wide-reports) for more information.
|
||||||
|
|
||||||
|
## Custom
|
||||||
|
|
||||||
|
By default, the behaviour of the `coverageReport` attribute is to
|
||||||
|
generate a coverage report that describes how that package affects the
|
||||||
|
coverage of all local packages (including itself) in the project.
|
||||||
|
|
||||||
|
The default behaviour of `projectCoverageReport` is to sum the
|
||||||
|
default coverage reports (produced by the above process) of all local
|
||||||
|
packages in the project.
|
||||||
|
|
||||||
|
You can modify this behaviour by using the `coverageReport` and
|
||||||
|
`projectCoverageReport` functions found in the haskell.nix library:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let
|
||||||
|
inherit (pkgs.haskell-nix) haskellLib;
|
||||||
|
|
||||||
|
project = haskellLib.project {
|
||||||
|
src = pkgs.haskell-nix.haskellLib.cleanGit {
|
||||||
|
name = "haskell-nix-project";
|
||||||
|
src = ./.;
|
||||||
|
};
|
||||||
|
compiler-nix-name = "ghc884";
|
||||||
|
|
||||||
|
modules = [{
|
||||||
|
packages.$pkgA.components.library.doCoverage = true;
|
||||||
|
packages.$pkgB.components.library.doCoverage = true;
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Generate a coverage report for $pkgA that only includes the
|
||||||
|
# unit-test check and only shows coverage information for $pkgA, not
|
||||||
|
# $pkgB.
|
||||||
|
custom$pkgACoverageReport = haskellLib.coverageReport rec {
|
||||||
|
name = "$pkgA-unit-tests-only"
|
||||||
|
inherit (project.$pkgA.components) library;
|
||||||
|
checks = [project.$pkgA.components.checks.unit-test];
|
||||||
|
# Note that this is the default value of the "mixLibraries"
|
||||||
|
# argument and so this line isn't really necessary.
|
||||||
|
mixLibraries = [project.$pkgA.components.library];
|
||||||
|
};
|
||||||
|
|
||||||
|
custom$pkgBCoverageReport = haskellLib.coverageReport rec {
|
||||||
|
name = "$pkgB-unit-tests-only"
|
||||||
|
inherit (project.$pkgB.components) library;
|
||||||
|
checks = [project.$pkgB.components.checks.unit-test];
|
||||||
|
mixLibraries = [project.$pkgB.components.library];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Generate a project coverage report that only includes the unit
|
||||||
|
# tests of the project, and only shows how each unit test effects
|
||||||
|
# the coverage of it's package, and not other packages in the
|
||||||
|
# project.
|
||||||
|
allUnitTestsProjectReport = haskellLib.projectCoverageReport [custom$pkgACoverageReport custom$pkgBCoverageReport];
|
||||||
|
in {
|
||||||
|
inherit project custom$pkgACoverageReport custom$pkgBCoverageReport allUnitTestsProjectCoverageReport;
|
||||||
|
}
|
||||||
|
```
|
@ -15,7 +15,7 @@ in stdenv.mkDerivation ({
|
|||||||
src = drv.source or (srcOnly drv);
|
src = drv.source or (srcOnly drv);
|
||||||
|
|
||||||
passthru = {
|
passthru = {
|
||||||
inherit (drv) identifier config configFiles executableToolDepends cleanSrc env;
|
inherit (drv) identifier config configFiles executableToolDepends cleanSrc env exeName;
|
||||||
};
|
};
|
||||||
|
|
||||||
inherit (drv) meta LANG LC_ALL buildInputs nativeBuildInputs;
|
inherit (drv) meta LANG LC_ALL buildInputs nativeBuildInputs;
|
||||||
@ -27,11 +27,14 @@ in stdenv.mkDerivation ({
|
|||||||
# If doCheck or doCrossCheck are false we may still build this
|
# If doCheck or doCrossCheck are false we may still build this
|
||||||
# component and we want it to quietly succeed.
|
# component and we want it to quietly succeed.
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
touch $out
|
mkdir $out
|
||||||
|
|
||||||
runHook preCheck
|
runHook preCheck
|
||||||
|
|
||||||
${toString component.testWrapper} ${drv}/bin/${drv.exeName} ${lib.concatStringsSep " " component.testFlags} | tee $out
|
${toString component.testWrapper} ${drv}/bin/${drv.exeName} ${lib.concatStringsSep " " component.testFlags} | tee $out/test-stdout
|
||||||
|
|
||||||
|
# Copy over tix files, if they exist
|
||||||
|
find . -iname '${drv.exeName}.tix' -exec mkdir -p $out/share/hpc/vanilla/tix/${drv.exeName} \; -exec cp {} $out/share/hpc/vanilla/tix/${drv.exeName}/ \;
|
||||||
|
|
||||||
runHook postCheck
|
runHook postCheck
|
||||||
'';
|
'';
|
||||||
|
150
lib/cover-project.nix
Normal file
150
lib/cover-project.nix
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
# A project coverage report is a composition of package coverage
|
||||||
|
# reports
|
||||||
|
{ stdenv, pkgs, lib, haskellLib }:
|
||||||
|
|
||||||
|
# List of coverage reports to accumulate
|
||||||
|
coverageReports:
|
||||||
|
|
||||||
|
let
|
||||||
|
toBashArray = arr: "(" + (lib.concatStringsSep " " arr) + ")";
|
||||||
|
|
||||||
|
# Create table rows for a project coverage index page that look something like:
|
||||||
|
#
|
||||||
|
# | Package |
|
||||||
|
# |------------------|
|
||||||
|
# | cardano-shell |
|
||||||
|
# | cardano-launcher |
|
||||||
|
coverageTableRows = coverageReport:
|
||||||
|
''
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="${coverageReport.passthru.name}/hpc_index.html">${coverageReport.passthru.name}</href>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
'';
|
||||||
|
|
||||||
|
projectIndexHtml = pkgs.writeText "index.html" ''
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table border="1" width="100%">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Report</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
${with lib; concatStringsSep "\n" (map coverageTableRows coverageReports)}
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
'';
|
||||||
|
|
||||||
|
ghc =
|
||||||
|
if (builtins.length coverageReports) > 0
|
||||||
|
then (builtins.head coverageReports).library.project.pkg-set.config.ghc.package or pkgs.ghc
|
||||||
|
else pkgs.ghc;
|
||||||
|
|
||||||
|
libs = map (r: r.library) coverageReports;
|
||||||
|
|
||||||
|
projectLibs = map (pkg: pkg.components.library) (lib.attrValues (haskellLib.selectProjectPackages ((lib.head libs).project.hsPkgs)));
|
||||||
|
|
||||||
|
mixDirs =
|
||||||
|
map
|
||||||
|
(l: "${l}/share/hpc/vanilla/mix/${l.identifier.name}-${l.identifier.version}")
|
||||||
|
(projectLibs);
|
||||||
|
|
||||||
|
srcDirs = map (l: l.src.outPath) (projectLibs);
|
||||||
|
|
||||||
|
in pkgs.runCommand "project-coverage-report"
|
||||||
|
({ buildInputs = [ghc];
|
||||||
|
LANG = "en_US.UTF-8";
|
||||||
|
LC_ALL = "en_US.UTF-8";
|
||||||
|
} // lib.optionalAttrs (stdenv.buildPlatform.libc == "glibc") {
|
||||||
|
LOCALE_ARCHIVE = "${pkgs.buildPackages.glibcLocales}/lib/locale/locale-archive";
|
||||||
|
})
|
||||||
|
''
|
||||||
|
function markup() {
|
||||||
|
local -n srcDs=$1
|
||||||
|
local -n mixDs=$2
|
||||||
|
local -n includedModules=$3
|
||||||
|
local destDir=$4
|
||||||
|
local tixFile=$5
|
||||||
|
|
||||||
|
local hpcMarkupCmd=("hpc" "markup" "--destdir=$destDir")
|
||||||
|
for srcDir in "''${srcDs[@]}"; do
|
||||||
|
hpcMarkupCmd+=("--srcdir=$srcDir")
|
||||||
|
done
|
||||||
|
|
||||||
|
for mixDir in "''${mixDs[@]}"; do
|
||||||
|
hpcMarkupCmd+=("--hpcdir=$mixDir")
|
||||||
|
done
|
||||||
|
|
||||||
|
for module in "''${includedModules[@]}"; do
|
||||||
|
hpcMarkupCmd+=("--include=$module")
|
||||||
|
done
|
||||||
|
|
||||||
|
hpcMarkupCmd+=("$tixFile")
|
||||||
|
|
||||||
|
echo "''${hpcMarkupCmd[@]}"
|
||||||
|
eval "''${hpcMarkupCmd[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function findModules() {
|
||||||
|
local searchDir=$2
|
||||||
|
local pattern=$3
|
||||||
|
|
||||||
|
pushd $searchDir
|
||||||
|
mapfile -d $'\0' $1 < <(find ./ -type f \
|
||||||
|
-wholename "$pattern" -not -name "Paths*" \
|
||||||
|
-exec basename {} \; \
|
||||||
|
| sed "s/\.mix$//" \
|
||||||
|
| tr "\n" "\0")
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir -p $out/share/hpc/vanilla/tix/all
|
||||||
|
mkdir -p $out/share/hpc/vanilla/mix/
|
||||||
|
mkdir -p $out/share/hpc/vanilla/html/
|
||||||
|
|
||||||
|
# Find all tix files in each package
|
||||||
|
tixFiles=()
|
||||||
|
${with lib; concatStringsSep "\n" (map (coverageReport: ''
|
||||||
|
identifier="${coverageReport.name}"
|
||||||
|
report=${coverageReport}
|
||||||
|
tix="$report/share/hpc/vanilla/tix/$identifier/$identifier.tix"
|
||||||
|
if test -f "$tix"; then
|
||||||
|
tixFiles+=("$tix")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy mix, tix, and html information over from each report
|
||||||
|
cp -Rn $report/share/hpc/vanilla/mix/$identifier/* $out/share/hpc/vanilla/mix/
|
||||||
|
cp -R $report/share/hpc/vanilla/tix/* $out/share/hpc/vanilla/tix/
|
||||||
|
cp -R $report/share/hpc/vanilla/html/* $out/share/hpc/vanilla/html/
|
||||||
|
'') coverageReports)}
|
||||||
|
|
||||||
|
if [ ''${#tixFiles[@]} -ne 0 ]; then
|
||||||
|
# Create tix file with test run information for all packages
|
||||||
|
tixFile="$out/share/hpc/vanilla/tix/all/all.tix"
|
||||||
|
hpcSumCmd=("hpc" "sum" "--union" "--output=$tixFile")
|
||||||
|
hpcSumCmd+=("''${tixFiles[@]}")
|
||||||
|
echo "''${hpcSumCmd[@]}"
|
||||||
|
eval "''${hpcSumCmd[@]}"
|
||||||
|
|
||||||
|
# Markup a HTML coverage report for the entire project
|
||||||
|
cp ${projectIndexHtml} $out/share/hpc/vanilla/html/index.html
|
||||||
|
|
||||||
|
local markupOutDir="$out/share/hpc/vanilla/html/all"
|
||||||
|
local srcDirs=${toBashArray srcDirs}
|
||||||
|
local mixDirs=${toBashArray mixDirs}
|
||||||
|
local allMixModules=()
|
||||||
|
|
||||||
|
mkdir $markupOutDir
|
||||||
|
findModules allMixModules "$out/share/hpc/vanilla/mix/" "*.mix"
|
||||||
|
|
||||||
|
markup srcDirs mixDirs allMixModules "$markupOutDir" "$tixFile"
|
||||||
|
fi
|
||||||
|
''
|
165
lib/cover.nix
Normal file
165
lib/cover.nix
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
{ stdenv, lib, haskellLib, pkgs }:
|
||||||
|
|
||||||
|
# Name of the coverage report, which should be unique
|
||||||
|
{ name
|
||||||
|
# Library to check coverage of
|
||||||
|
, library
|
||||||
|
# List of check derivations that generate coverage
|
||||||
|
, checks
|
||||||
|
# List of other libraries to include in the coverage report. The
|
||||||
|
# default value if just the derivation provided as the `library`
|
||||||
|
# argument. Use a larger list of libraries if you would like the tests
|
||||||
|
# of one local package to generate coverage for another.
|
||||||
|
, mixLibraries ? [library]
|
||||||
|
# hack for project-less projects
|
||||||
|
, ghc ? library.project.pkg-set.config.ghc.package
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
toBashArray = arr: "(" + (lib.concatStringsSep " " arr) + ")";
|
||||||
|
|
||||||
|
mixDir = l: "${l}/share/hpc/vanilla/mix/${l.identifier.name}-${l.identifier.version}";
|
||||||
|
mixDirs = map mixDir mixLibraries;
|
||||||
|
|
||||||
|
srcDirs = map (l: l.src.outPath) mixLibraries;
|
||||||
|
|
||||||
|
in pkgs.runCommand (name + "-coverage-report")
|
||||||
|
({ buildInputs = [ ghc ];
|
||||||
|
passthru = {
|
||||||
|
inherit name library checks;
|
||||||
|
};
|
||||||
|
# HPC will fail if the Haskell file contains non-ASCII characters,
|
||||||
|
# unless our locale is set correctly. This has been fixed, but we
|
||||||
|
# don't know what version of HPC we will be using, hence we should
|
||||||
|
# always use the workaround.
|
||||||
|
# https://gitlab.haskell.org/ghc/ghc/-/issues/17073
|
||||||
|
LANG = "en_US.UTF-8";
|
||||||
|
LC_ALL = "en_US.UTF-8";
|
||||||
|
} // lib.optionalAttrs (stdenv.buildPlatform.libc == "glibc") {
|
||||||
|
LOCALE_ARCHIVE = "${pkgs.buildPackages.glibcLocales}/lib/locale/locale-archive";
|
||||||
|
})
|
||||||
|
''
|
||||||
|
function markup() {
|
||||||
|
local -n srcDs=$1
|
||||||
|
local -n mixDs=$2
|
||||||
|
local -n includedModules=$3
|
||||||
|
local destDir=$4
|
||||||
|
local tixFile=$5
|
||||||
|
|
||||||
|
local hpcMarkupCmd=("hpc" "markup" "--destdir=$destDir")
|
||||||
|
for srcDir in "''${srcDs[@]}"; do
|
||||||
|
hpcMarkupCmd+=("--srcdir=$srcDir")
|
||||||
|
done
|
||||||
|
|
||||||
|
for mixDir in "''${mixDs[@]}"; do
|
||||||
|
hpcMarkupCmd+=("--hpcdir=$mixDir")
|
||||||
|
done
|
||||||
|
|
||||||
|
for module in "''${includedModules[@]}"; do
|
||||||
|
hpcMarkupCmd+=("--include=$module")
|
||||||
|
done
|
||||||
|
|
||||||
|
hpcMarkupCmd+=("$tixFile")
|
||||||
|
|
||||||
|
echo "''${hpcMarkupCmd[@]}"
|
||||||
|
eval "''${hpcMarkupCmd[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function sumTix() {
|
||||||
|
local -n includedModules=$1
|
||||||
|
local -n tixFs=$2
|
||||||
|
local outFile="$3"
|
||||||
|
|
||||||
|
local hpcSumCmd=("hpc" "sum" "--union" "--output=$outFile")
|
||||||
|
|
||||||
|
for module in "''${includedModules[@]}"; do
|
||||||
|
hpcSumCmd+=("--include=$module")
|
||||||
|
done
|
||||||
|
|
||||||
|
for tixFile in "''${tixFs[@]}"; do
|
||||||
|
hpcSumCmd+=("$tixFile")
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "''${hpcSumCmd[@]}"
|
||||||
|
eval "''${hpcSumCmd[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function findModules() {
|
||||||
|
local searchDir=$2
|
||||||
|
local pattern=$3
|
||||||
|
|
||||||
|
pushd $searchDir
|
||||||
|
mapfile -d $'\0' $1 < <(find ./ -type f \
|
||||||
|
-wholename "$pattern" -not -name "Paths*" \
|
||||||
|
-exec basename {} \; \
|
||||||
|
| sed "s/\.mix$//" \
|
||||||
|
| tr "\n" "\0")
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
local mixDirs=${toBashArray mixDirs}
|
||||||
|
|
||||||
|
mkdir -p $out/share/hpc/vanilla/mix/${name}
|
||||||
|
mkdir -p $out/share/hpc/vanilla/tix/${name}
|
||||||
|
mkdir -p $out/share/hpc/vanilla/html/${name}
|
||||||
|
|
||||||
|
# Copy over mix files verbatim
|
||||||
|
for dir in "''${mixDirs[@]}"; do
|
||||||
|
if [ -d "$dir" ]; then
|
||||||
|
cp -R "$dir"/* $out/share/hpc/vanilla/mix/${name}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
local srcDirs=${toBashArray srcDirs}
|
||||||
|
local allMixModules=()
|
||||||
|
local pkgMixModules=()
|
||||||
|
|
||||||
|
# The behaviour of stack coverage reports is to provide tix files
|
||||||
|
# that include coverage information for every local package, but
|
||||||
|
# to provide HTML reports that only include coverage info for the
|
||||||
|
# current package. We emulate the same behaviour here. If the user
|
||||||
|
# includes all local packages in the mix libraries argument, they
|
||||||
|
# will get a coverage report very similar to stack.
|
||||||
|
|
||||||
|
# All mix modules
|
||||||
|
findModules allMixModules "$out/share/hpc/vanilla/mix/${name}" "*.mix"
|
||||||
|
# Only mix modules corresponding to this package
|
||||||
|
findModules pkgMixModules "$out/share/hpc/vanilla/mix/${name}" "*${name}*/*.mix"
|
||||||
|
|
||||||
|
# For each test
|
||||||
|
local tixFiles=()
|
||||||
|
${lib.concatStringsSep "\n" (builtins.map (check: ''
|
||||||
|
if [ -d "${check}/share/hpc/vanilla/tix" ]; then
|
||||||
|
pushd ${check}/share/hpc/vanilla/tix
|
||||||
|
|
||||||
|
tixFile="$(find . -iwholename "*.tix" -type f -print -quit)"
|
||||||
|
local newTixFile=$out/share/hpc/vanilla/tix/${name}/"$tixFile"
|
||||||
|
|
||||||
|
mkdir -p "$(dirname $newTixFile)"
|
||||||
|
# Copy over the tix file verbatim
|
||||||
|
cp "$tixFile" "$newTixFile"
|
||||||
|
|
||||||
|
# Add the tix file to our list
|
||||||
|
tixFiles+=("$newTixFile")
|
||||||
|
|
||||||
|
# Create a coverage report for *just that test*
|
||||||
|
markup srcDirs mixDirs pkgMixModules "$out/share/hpc/vanilla/html/${name}/${check.exeName}/" "$newTixFile"
|
||||||
|
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
'') checks)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Sum tix files to create a tix file with all relevant tix
|
||||||
|
# information and markup a HTML report from this info.
|
||||||
|
if (( "''${#tixFiles[@]}" > 0 )); then
|
||||||
|
local sumTixFile="$out/share/hpc/vanilla/tix/${name}/${name}.tix"
|
||||||
|
local markupOutDir="$out/share/hpc/vanilla/html/${name}"
|
||||||
|
|
||||||
|
# Sum all of our tix file, including modules from any local package
|
||||||
|
sumTix allMixModules tixFiles "$sumTixFile"
|
||||||
|
|
||||||
|
# Markup a HTML report, included modules from only this package
|
||||||
|
markup srcDirs mixDirs pkgMixModules "$markupOutDir" "$sumTixFile"
|
||||||
|
fi
|
||||||
|
''
|
@ -232,6 +232,16 @@ in {
|
|||||||
inherit stdenv lib haskellLib srcOnly;
|
inherit stdenv lib haskellLib srcOnly;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Do coverage of a package
|
||||||
|
coverageReport = import ./cover.nix {
|
||||||
|
inherit stdenv lib haskellLib pkgs;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Do coverage of a project
|
||||||
|
projectCoverageReport = import ./cover-project.nix {
|
||||||
|
inherit stdenv lib haskellLib pkgs;
|
||||||
|
};
|
||||||
|
|
||||||
# Use `isCrossHost` to identify when we are cross compiling and
|
# Use `isCrossHost` to identify when we are cross compiling and
|
||||||
# the code we are producing will not run on the build system
|
# the code we are producing will not run on the build system
|
||||||
# without an emulator.
|
# without an emulator.
|
||||||
|
@ -35,6 +35,7 @@ pages:
|
|||||||
- 'Bumping Hackage and Stackage snapshots': tutorials/hackage-stackage.md
|
- 'Bumping Hackage and Stackage snapshots': tutorials/hackage-stackage.md
|
||||||
- 'Materialization: Speeding up Nix evaluation': tutorials/materialization.md
|
- 'Materialization: Speeding up Nix evaluation': tutorials/materialization.md
|
||||||
- 'Cross-compiling your project': tutorials/cross-compilation.md
|
- 'Cross-compiling your project': tutorials/cross-compilation.md
|
||||||
|
- 'Generating coverage information': tutorials/coverage.md
|
||||||
- 'Reference':
|
- 'Reference':
|
||||||
- 'Suported GHC versions': reference/supported-ghc-versions.md
|
- 'Suported GHC versions': reference/supported-ghc-versions.md
|
||||||
- 'Command-line tools': reference/commands.md
|
- 'Command-line tools': reference/commands.md
|
||||||
@ -52,4 +53,5 @@ pages:
|
|||||||
- 'Removing withPackage wrapper': dev/removing-with-package-wrapper.md
|
- 'Removing withPackage wrapper': dev/removing-with-package-wrapper.md
|
||||||
- 'Test Suite': dev/tests.md
|
- 'Test Suite': dev/tests.md
|
||||||
- 'Adding a new GHC version': dev/adding-new-ghc.md
|
- 'Adding a new GHC version': dev/adding-new-ghc.md
|
||||||
|
- 'Coverage': dev/coverage.md
|
||||||
- 'ChangeLog': changelog.md
|
- 'ChangeLog': changelog.md
|
||||||
|
@ -108,6 +108,11 @@ let
|
|||||||
type = bool;
|
type = bool;
|
||||||
default = (def.doQuickjump or true);
|
default = (def.doQuickjump or true);
|
||||||
};
|
};
|
||||||
|
doCoverage = mkOption {
|
||||||
|
description = "Enable production of test coverage reports.";
|
||||||
|
type = bool;
|
||||||
|
default = (def.doCoverage or false);
|
||||||
|
};
|
||||||
dontPatchELF = mkOption {
|
dontPatchELF = mkOption {
|
||||||
description = "If set, the patchelf command is not used to remove unnecessary RPATH entries. Only applies to Linux.";
|
description = "If set, the patchelf command is not used to remove unnecessary RPATH entries. Only applies to Linux.";
|
||||||
type = bool;
|
type = bool;
|
||||||
|
@ -482,7 +482,8 @@ final: prev: {
|
|||||||
{ compiler.nix-name = args.compiler-nix-name; };
|
{ compiler.nix-name = args.compiler-nix-name; };
|
||||||
extra-hackages = args.extra-hackages or [];
|
extra-hackages = args.extra-hackages or [];
|
||||||
};
|
};
|
||||||
in addProjectAndPackageAttrs {
|
|
||||||
|
project = addProjectAndPackageAttrs rec {
|
||||||
inherit (pkg-set.config) hsPkgs;
|
inherit (pkg-set.config) hsPkgs;
|
||||||
inherit pkg-set;
|
inherit pkg-set;
|
||||||
plan-nix = callProjectResults.projectNix;
|
plan-nix = callProjectResults.projectNix;
|
||||||
@ -491,6 +492,8 @@ final: prev: {
|
|||||||
tools = final.buildPackages.haskell-nix.tools pkg-set.config.compiler.nix-name;
|
tools = final.buildPackages.haskell-nix.tools pkg-set.config.compiler.nix-name;
|
||||||
roots = final.haskell-nix.roots pkg-set.config.compiler.nix-name;
|
roots = final.haskell-nix.roots pkg-set.config.compiler.nix-name;
|
||||||
};
|
};
|
||||||
|
in project;
|
||||||
|
|
||||||
|
|
||||||
# Take `hsPkgs` from the `rawProject` and update all the packages and
|
# Take `hsPkgs` from the `rawProject` and update all the packages and
|
||||||
# components so they have a `.project` attribute and as well as
|
# components so they have a `.project` attribute and as well as
|
||||||
@ -498,25 +501,34 @@ final: prev: {
|
|||||||
addProjectAndPackageAttrs = rawProject:
|
addProjectAndPackageAttrs = rawProject:
|
||||||
final.lib.fix (project':
|
final.lib.fix (project':
|
||||||
let project = project' // { recurseForDerivations = false; };
|
let project = project' // { recurseForDerivations = false; };
|
||||||
in rawProject // {
|
in rawProject // rec {
|
||||||
hsPkgs = (final.lib.mapAttrs (n: package':
|
hsPkgs = (final.lib.mapAttrs (n: package':
|
||||||
if package' == null
|
if package' == null
|
||||||
then null
|
then null
|
||||||
else
|
else
|
||||||
let package = package' // { recurseForDerivations = false; };
|
let package = package' // { recurseForDerivations = false; };
|
||||||
in package' // {
|
in package' // rec {
|
||||||
components = final.lib.mapAttrs (n: v:
|
components = final.lib.mapAttrs (n: v:
|
||||||
if n == "library" || n == "all"
|
if n == "library" || n == "all"
|
||||||
then v // { inherit project package; }
|
then v // { inherit project package; }
|
||||||
else final.lib.mapAttrs (_: c: c // { inherit project package; }) v
|
else final.lib.mapAttrs (_: c: c // { inherit project package; }) v
|
||||||
) package'.components;
|
) package'.components;
|
||||||
inherit project;
|
inherit project;
|
||||||
|
|
||||||
|
coverageReport = haskellLib.coverageReport (rec {
|
||||||
|
name = package.identifier.name + "-" + package.identifier.version;
|
||||||
|
inherit (components) library;
|
||||||
|
checks = final.lib.filter (final.lib.isDerivation) (final.lib.attrValues package'.checks);
|
||||||
|
mixLibraries = map (pkg: pkg.components.library) (final.lib.attrValues (haskellLib.selectProjectPackages project.hsPkgs));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
) rawProject.hsPkgs
|
) rawProject.hsPkgs
|
||||||
// {
|
// {
|
||||||
# These are functions not packages
|
# These are functions not packages
|
||||||
inherit (rawProject.hsPkgs) shellFor ghcWithHoogle ghcWithPackages;
|
inherit (rawProject.hsPkgs) shellFor ghcWithHoogle ghcWithPackages;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
projectCoverageReport = haskellLib.projectCoverageReport (map (pkg: pkg.coverageReport) (final.lib.attrValues (haskellLib.selectProjectPackages hsPkgs)));
|
||||||
});
|
});
|
||||||
|
|
||||||
cabalProject =
|
cabalProject =
|
||||||
@ -525,7 +537,7 @@ final: prev: {
|
|||||||
args = { caller = "hackage-package"; } // args';
|
args = { caller = "hackage-package"; } // args';
|
||||||
p = cabalProject' args;
|
p = cabalProject' args;
|
||||||
in p.hsPkgs // {
|
in p.hsPkgs // {
|
||||||
inherit (p) plan-nix index-state tool tools roots;
|
inherit (p) plan-nix index-state tool tools roots projectCoverageReport;
|
||||||
# Provide `nix-shell -A shells.ghc` for users migrating from the reflex-platform.
|
# Provide `nix-shell -A shells.ghc` for users migrating from the reflex-platform.
|
||||||
# But we should encourage use of `nix-shell -A shellFor`
|
# But we should encourage use of `nix-shell -A shellFor`
|
||||||
shells.ghc = p.hsPkgs.shellFor {};
|
shells.ghc = p.hsPkgs.shellFor {};
|
||||||
@ -543,7 +555,8 @@ final: prev: {
|
|||||||
++ (args.modules or [])
|
++ (args.modules or [])
|
||||||
++ final.lib.optional (args ? ghc) { ghc.package = args.ghc; };
|
++ final.lib.optional (args ? ghc) { ghc.package = args.ghc; };
|
||||||
};
|
};
|
||||||
in addProjectAndPackageAttrs {
|
|
||||||
|
project = addProjectAndPackageAttrs {
|
||||||
inherit (pkg-set.config) hsPkgs;
|
inherit (pkg-set.config) hsPkgs;
|
||||||
inherit pkg-set;
|
inherit pkg-set;
|
||||||
stack-nix = callProjectResults.projectNix;
|
stack-nix = callProjectResults.projectNix;
|
||||||
@ -551,10 +564,11 @@ final: prev: {
|
|||||||
tools = final.buildPackages.haskell-nix.tools pkg-set.config.compiler.nix-name;
|
tools = final.buildPackages.haskell-nix.tools pkg-set.config.compiler.nix-name;
|
||||||
roots = final.haskell-nix.roots pkg-set.config.compiler.nix-name;
|
roots = final.haskell-nix.roots pkg-set.config.compiler.nix-name;
|
||||||
};
|
};
|
||||||
|
in project;
|
||||||
|
|
||||||
stackProject = args: let p = stackProject' args;
|
stackProject = args: let p = stackProject' args;
|
||||||
in p.hsPkgs // {
|
in p.hsPkgs // {
|
||||||
inherit (p) stack-nix tool tools roots;
|
inherit (p) stack-nix tool tools roots projectCoverageReport;
|
||||||
# Provide `nix-shell -A shells.ghc` for users migrating from the reflex-platform.
|
# Provide `nix-shell -A shells.ghc` for users migrating from the reflex-platform.
|
||||||
# But we should encourage use of `nix-shell -A shellFor`
|
# But we should encourage use of `nix-shell -A shellFor`
|
||||||
shells.ghc = p.hsPkgs.shellFor {};
|
shells.ghc = p.hsPkgs.shellFor {};
|
||||||
|
@ -21,7 +21,7 @@ in recurseIntoAttrs {
|
|||||||
buildCommand =
|
buildCommand =
|
||||||
(concatStrings (mapAttrsToList (name: value: ''
|
(concatStrings (mapAttrsToList (name: value: ''
|
||||||
printf "checking whether executable runs... " >& 2
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check value}
|
cat ${haskellLib.check value}/test-stdout
|
||||||
'') packages.buildable-test.components.exes)) + ''
|
'') packages.buildable-test.components.exes)) + ''
|
||||||
touch $out
|
touch $out
|
||||||
'';
|
'';
|
||||||
|
@ -26,7 +26,7 @@ in recurseIntoAttrs {
|
|||||||
|
|
||||||
# fixme: run on target platform when cross-compiled
|
# fixme: run on target platform when cross-compiled
|
||||||
printf "checking whether executable runs... " >& 2
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.project.components.exes.project}
|
cat ${haskellLib.check packages.project.components.exes.project}/test-stdout
|
||||||
|
|
||||||
'' +
|
'' +
|
||||||
# Aarch is statically linked and does not produce a .so file.
|
# Aarch is statically linked and does not produce a .so file.
|
||||||
@ -56,10 +56,10 @@ in recurseIntoAttrs {
|
|||||||
touch $out
|
touch $out
|
||||||
|
|
||||||
printf "checking whether benchmark ran... " >& 2
|
printf "checking whether benchmark ran... " >& 2
|
||||||
cat ${haskellLib.check packages.project.components.benchmarks.project-bench}
|
cat ${haskellLib.check packages.project.components.benchmarks.project-bench}/test-stdout
|
||||||
|
|
||||||
printf "checking whether tests ran... " >& 2
|
printf "checking whether tests ran... " >& 2
|
||||||
cat ${haskellLib.check packages.project.components.tests.unit}
|
cat ${haskellLib.check packages.project.components.tests.unit}/test-stdout
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta.platforms = platforms.all;
|
meta.platforms = platforms.all;
|
||||||
|
@ -36,7 +36,7 @@ in recurseIntoAttrs {
|
|||||||
|
|
||||||
# fixme: run on target platform when cross-compiled
|
# fixme: run on target platform when cross-compiled
|
||||||
printf "checking whether executable runs... " >& 2
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.cabal-hpack.components.exes.cabal-hpack}
|
cat ${haskellLib.check packages.cabal-hpack.components.exes.cabal-hpack}/test-stdout
|
||||||
'' + (if stdenv.hostPlatform.isMusl
|
'' + (if stdenv.hostPlatform.isMusl
|
||||||
then ''
|
then ''
|
||||||
printf "checking that executable is statically linked... " >& 2
|
printf "checking that executable is statically linked... " >& 2
|
||||||
|
@ -39,7 +39,7 @@ in recurseIntoAttrs {
|
|||||||
|
|
||||||
# fixme: run on target platform when cross-compiled
|
# fixme: run on target platform when cross-compiled
|
||||||
printf "checking whether executable runs... " >& 2
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.cabal-simple.components.exes.cabal-simple}
|
cat ${haskellLib.check packages.cabal-simple.components.exes.cabal-simple}/test-stdout
|
||||||
'' + (if stdenv.hostPlatform.isMusl
|
'' + (if stdenv.hostPlatform.isMusl
|
||||||
then ''
|
then ''
|
||||||
printf "checking that executable is statically linked... " >& 2
|
printf "checking that executable is statically linked... " >& 2
|
||||||
|
@ -20,7 +20,7 @@ in recurseIntoAttrs {
|
|||||||
exe="${packages.use-cabal-simple.components.exes.use-cabal-simple}/bin/use-cabal-simple${stdenv.hostPlatform.extensions.executable}"
|
exe="${packages.use-cabal-simple.components.exes.use-cabal-simple}/bin/use-cabal-simple${stdenv.hostPlatform.extensions.executable}"
|
||||||
|
|
||||||
printf "checking whether executable runs... " >& 2
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.use-cabal-simple.components.exes.use-cabal-simple}
|
cat ${haskellLib.check packages.use-cabal-simple.components.exes.use-cabal-simple}/test-stdout
|
||||||
|
|
||||||
touch $out
|
touch $out
|
||||||
'';
|
'';
|
||||||
|
@ -20,7 +20,7 @@ in recurseIntoAttrs {
|
|||||||
exe="${packages.use-cabal-simple.components.exes.use-cabal-simple}/bin/use-cabal-simple${stdenv.hostPlatform.extensions.executable}"
|
exe="${packages.use-cabal-simple.components.exes.use-cabal-simple}/bin/use-cabal-simple${stdenv.hostPlatform.extensions.executable}"
|
||||||
|
|
||||||
printf "checking whether executable runs... " >& 2
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.use-cabal-simple.components.exes.use-cabal-simple}
|
cat ${haskellLib.check packages.use-cabal-simple.components.exes.use-cabal-simple}/test-stdout
|
||||||
|
|
||||||
touch $out
|
touch $out
|
||||||
'';
|
'';
|
||||||
|
@ -36,7 +36,7 @@ in recurseIntoAttrs {
|
|||||||
|
|
||||||
# fixme: run on target platform when cross-compiled
|
# fixme: run on target platform when cross-compiled
|
||||||
printf "checking whether executable runs... " >& 2
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.cabal-sublib.components.exes.cabal-sublib}
|
cat ${haskellLib.check packages.cabal-sublib.components.exes.cabal-sublib}/test-stdout
|
||||||
|
|
||||||
'' +
|
'' +
|
||||||
# Musl and Aarch are statically linked..
|
# Musl and Aarch are statically linked..
|
||||||
|
@ -29,7 +29,7 @@ in recurseIntoAttrs {
|
|||||||
exe="${packages.cabal-simple.components.exes.cabal-simple}/bin/cabal-simple${stdenv.hostPlatform.extensions.executable}"
|
exe="${packages.cabal-simple.components.exes.cabal-simple}/bin/cabal-simple${stdenv.hostPlatform.extensions.executable}"
|
||||||
|
|
||||||
printf "checking whether executable runs... " >& 2
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.cabal-simple.components.exes.cabal-simple}
|
cat ${haskellLib.check packages.cabal-simple.components.exes.cabal-simple}/test-stdout
|
||||||
|
|
||||||
touch $out
|
touch $out
|
||||||
'';
|
'';
|
||||||
|
@ -24,7 +24,7 @@ in recurseIntoAttrs {
|
|||||||
exe="${packages.stack-simple.components.exes.stack-simple-exe}/bin/stack-simple-exe${stdenv.hostPlatform.extensions.executable}"
|
exe="${packages.stack-simple.components.exes.stack-simple-exe}/bin/stack-simple-exe${stdenv.hostPlatform.extensions.executable}"
|
||||||
|
|
||||||
printf "checking whether executable runs... " >& 2
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.stack-simple.components.exes.stack-simple-exe}
|
cat ${haskellLib.check packages.stack-simple.components.exes.stack-simple-exe}/test-stdout
|
||||||
|
|
||||||
touch $out
|
touch $out
|
||||||
'';
|
'';
|
||||||
|
2
test/coverage/cabal.project
Normal file
2
test/coverage/cabal.project
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
packages: pkga
|
||||||
|
pkgb
|
19
test/coverage/conduit.hs
Normal file
19
test/coverage/conduit.hs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-- https://github.com/snoyberg/conduit#readme
|
||||||
|
|
||||||
|
import Conduit
|
||||||
|
import System.Directory (removeFile)
|
||||||
|
|
||||||
|
main = do
|
||||||
|
-- Pure operations: summing numbers.
|
||||||
|
print $ runConduitPure $ yieldMany [1..10] .| sumC
|
||||||
|
|
||||||
|
-- Exception safe file access: copy a file.
|
||||||
|
writeFile "input.txt" "This is a test." -- create the source file
|
||||||
|
runConduitRes $ sourceFileBS "input.txt" .| sinkFile "output.txt" -- actual copying
|
||||||
|
readFile "output.txt" >>= putStrLn -- prove that it worked
|
||||||
|
|
||||||
|
-- Perform transformations.
|
||||||
|
print $ runConduitPure $ yieldMany [1..10] .| mapC (+ 1) .| sinkList
|
||||||
|
|
||||||
|
removeFile "input.txt"
|
||||||
|
removeFile "output.txt"
|
127
test/coverage/default.nix
Normal file
127
test/coverage/default.nix
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
{ stdenv, cabal-install, cabalProject', stackProject', recurseIntoAttrs, runCommand, testSrc, compiler-nix-name }:
|
||||||
|
|
||||||
|
with stdenv.lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
projectArgs = {
|
||||||
|
src = testSrc "coverage";
|
||||||
|
inherit compiler-nix-name;
|
||||||
|
modules = [{
|
||||||
|
# Package has no exposed modules which causes
|
||||||
|
# haddock: No input file(s)
|
||||||
|
packages.bytestring-builder.doHaddock = false;
|
||||||
|
|
||||||
|
# Coverage
|
||||||
|
packages.pkga.components.library.doCoverage = true;
|
||||||
|
packages.pkgb.components.library.doCoverage = true;
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
|
||||||
|
cabalProj = (cabalProject' projectArgs);
|
||||||
|
stackProj = (stackProject' projectArgs);
|
||||||
|
|
||||||
|
in recurseIntoAttrs ({
|
||||||
|
run = stdenv.mkDerivation {
|
||||||
|
name = "coverage-test";
|
||||||
|
|
||||||
|
buildCommand = ''
|
||||||
|
########################################################################
|
||||||
|
# test coverage reports with an example project
|
||||||
|
|
||||||
|
fileExistsNonEmpty() {
|
||||||
|
local file=$1
|
||||||
|
if [ ! -f "$file" ]; then
|
||||||
|
echo "Missing: $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
local filesize=$(command stat --format '%s' "$file")
|
||||||
|
if [ $filesize -eq 0 ]; then
|
||||||
|
echo "File must not be empty: $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
findFileExistsNonEmpty() {
|
||||||
|
local searchDir=$1
|
||||||
|
local filePattern=$2
|
||||||
|
|
||||||
|
local file="$(find $searchDir -name $filePattern -print -quit)"
|
||||||
|
|
||||||
|
if [ -z $file ]; then
|
||||||
|
echo "Couldn't find file \"$filePattern\" in directory \"$searchDir\"."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local filesize=$(command stat --format '%s' "$file")
|
||||||
|
if [ $filesize -eq 0 ]; then
|
||||||
|
echo "File must not be empty: $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
dirExistsEmpty() {
|
||||||
|
local dir=$1
|
||||||
|
if [ ! -d "$dir" ]; then
|
||||||
|
echo "Missing: $dir"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ "$(ls -A $dir)" ]; then
|
||||||
|
echo "Dir should be empty: $dir"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
dirExists() {
|
||||||
|
local dir=$1
|
||||||
|
if [ ! -d "$dir" ]; then
|
||||||
|
echo "Missing: $dir"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
${concatStringsSep "\n" (map (project: ''
|
||||||
|
pkga_basedir="${project.hsPkgs.pkga.coverageReport}/share/hpc/vanilla"
|
||||||
|
findFileExistsNonEmpty "$pkga_basedir/mix/pkga-0.1.0.0/" "PkgA.mix"
|
||||||
|
dirExistsEmpty "$pkga_basedir/tix/pkga-0.1.0.0"
|
||||||
|
dirExistsEmpty "$pkga_basedir/html/pkga-0.1.0.0"
|
||||||
|
|
||||||
|
pkgb_basedir="${project.hsPkgs.pkgb.coverageReport}/share/hpc/vanilla"
|
||||||
|
testTix="$pkgb_basedir/tix/pkgb-0.1.0.0/tests/tests.tix"
|
||||||
|
libTix="$pkgb_basedir/tix/pkgb-0.1.0.0/pkgb-0.1.0.0.tix"
|
||||||
|
fileExistsNonEmpty "$testTix"
|
||||||
|
fileExistsNonEmpty "$libTix"
|
||||||
|
findFileExistsNonEmpty "$pkgb_basedir/mix/pkgb-0.1.0.0/" "ConduitExample.mix"
|
||||||
|
findFileExistsNonEmpty "$pkgb_basedir/mix/pkgb-0.1.0.0/" "PkgB.mix"
|
||||||
|
fileExistsNonEmpty "$pkgb_basedir/html/pkgb-0.1.0.0/hpc_index.html"
|
||||||
|
|
||||||
|
filesizeTestsTix=$(command stat --format '%s' "$testTix")
|
||||||
|
filesizeLibTix=$(command stat --format '%s' "$libTix")
|
||||||
|
if (( filesizeTestsTix <= filesizeLibTix )); then
|
||||||
|
echo "Filesize of \"$testTix\" ($filesizeTestsTix) should be greather than that of \"$libTix\" ($filesizeLibTix). Did you forget to exclude test modules when creating \"$libTix\"?"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
project_basedir="${project.projectCoverageReport}/share/hpc/vanilla"
|
||||||
|
fileExistsNonEmpty "$project_basedir/html/index.html"
|
||||||
|
dirExists "$project_basedir/html/pkga-0.1.0.0"
|
||||||
|
dirExists "$project_basedir/html/pkgb-0.1.0.0"
|
||||||
|
findFileExistsNonEmpty "$project_basedir/mix/" "PkgA.mix"
|
||||||
|
findFileExistsNonEmpty "$project_basedir/mix/" "PkgB.mix"
|
||||||
|
findFileExistsNonEmpty "$project_basedir/mix/" "ConduitExample.mix"
|
||||||
|
dirExists "$project_basedir/tix/all"
|
||||||
|
fileExistsNonEmpty "$project_basedir/tix/all/all.tix"
|
||||||
|
dirExists "$project_basedir/tix/pkga-0.1.0.0"
|
||||||
|
dirExists "$project_basedir/tix/pkgb-0.1.0.0"
|
||||||
|
fileExistsNonEmpty "$project_basedir/tix/pkgb-0.1.0.0/pkgb-0.1.0.0.tix"
|
||||||
|
dirExists "$project_basedir/tix/pkgb-0.1.0.0/tests"
|
||||||
|
fileExistsNonEmpty "$project_basedir/tix/pkgb-0.1.0.0/tests/tests.tix"
|
||||||
|
'') [ cabalProj stackProj ])}
|
||||||
|
|
||||||
|
touch $out
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta.platforms = platforms.all;
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
# Used for debugging with nix repl
|
||||||
|
inherit cabalProj stackProj;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
4
test/coverage/pkga/MainA.hs
Normal file
4
test/coverage/pkga/MainA.hs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = putStrLn "This is MainA"
|
16
test/coverage/pkga/PkgA.hs
Normal file
16
test/coverage/pkga/PkgA.hs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
module PkgA (decode) where
|
||||||
|
|
||||||
|
import Control.Lens
|
||||||
|
import Data.Text.Lens
|
||||||
|
import Data.Char
|
||||||
|
import Data.Text (Text)
|
||||||
|
|
||||||
|
decode :: Text -> Text
|
||||||
|
decode = unpacked . mapped %~ rot 13
|
||||||
|
|
||||||
|
rot :: Int -> Char -> Char
|
||||||
|
rot n c | c >= 'a' && c <= 'z' = r 'a' 'z'
|
||||||
|
| c >= 'A' && c <= 'Z' = r 'A' 'Z'
|
||||||
|
| otherwise = c
|
||||||
|
where
|
||||||
|
r a b = chr $ ord a + ((ord c - ord a + n) `mod` (ord b - ord a + 1))
|
2
test/coverage/pkga/Setup.hs
Normal file
2
test/coverage/pkga/Setup.hs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import Distribution.Simple
|
||||||
|
main = defaultMain
|
26
test/coverage/pkga/pkga.cabal
Normal file
26
test/coverage/pkga/pkga.cabal
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
cabal-version: 2.2
|
||||||
|
-- Initial package description 'pkga.cabal' generated by 'cabal init'. For
|
||||||
|
-- further documentation, see http://haskell.org/cabal/users-guide/
|
||||||
|
|
||||||
|
name: pkga
|
||||||
|
version: 0.1.0.0
|
||||||
|
-- synopsis:
|
||||||
|
-- description:
|
||||||
|
-- bug-reports:
|
||||||
|
license: LicenseRef-PublicDomain
|
||||||
|
author: Rodney Lorrimar
|
||||||
|
maintainer: rodney.lorrimar@iohk.io
|
||||||
|
category: Testing
|
||||||
|
|
||||||
|
library
|
||||||
|
exposed-modules: PkgA
|
||||||
|
build-depends: base
|
||||||
|
, lens
|
||||||
|
, text
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable pkga-exe
|
||||||
|
main-is: MainA.hs
|
||||||
|
build-depends: base
|
||||||
|
hs-source-dirs: .
|
||||||
|
default-language: Haskell2010
|
2
test/coverage/pkgb/Setup.hs
Normal file
2
test/coverage/pkgb/Setup.hs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import Distribution.Simple
|
||||||
|
main = defaultMain
|
10
test/coverage/pkgb/app/Main.hs
Normal file
10
test/coverage/pkgb/app/Main.hs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import ConduitExample (example)
|
||||||
|
import PkgB (message)
|
||||||
|
import qualified Data.Text.IO as T
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
T.putStrLn message
|
||||||
|
example
|
7
test/coverage/pkgb/app/tests.hs
Normal file
7
test/coverage/pkgb/app/tests.hs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import System.Process
|
||||||
|
import ConduitExample
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = example
|
43
test/coverage/pkgb/pkgb.cabal
Normal file
43
test/coverage/pkgb/pkgb.cabal
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
cabal-version: 2.2
|
||||||
|
-- Initial package description 'pkgb.cabal' generated by 'cabal init'. For
|
||||||
|
-- further documentation, see http://haskell.org/cabal/users-guide/
|
||||||
|
|
||||||
|
name: pkgb
|
||||||
|
version: 0.1.0.0
|
||||||
|
-- synopsis:
|
||||||
|
-- description:
|
||||||
|
-- bug-reports:
|
||||||
|
license: LicenseRef-PublicDomain
|
||||||
|
author: Rodney Lorrimar
|
||||||
|
maintainer: rodney.lorrimar@iohk.io
|
||||||
|
category: Testing
|
||||||
|
|
||||||
|
library
|
||||||
|
exposed-modules: ConduitExample
|
||||||
|
, PkgB
|
||||||
|
build-depends: base
|
||||||
|
, pkga
|
||||||
|
, conduit
|
||||||
|
, conduit-extra
|
||||||
|
, directory
|
||||||
|
, resourcet
|
||||||
|
hs-source-dirs: src
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable pkgb
|
||||||
|
main-is: Main.hs
|
||||||
|
build-depends: base
|
||||||
|
, pkgb
|
||||||
|
, optparse-applicative
|
||||||
|
, text
|
||||||
|
hs-source-dirs: app
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
test-suite tests
|
||||||
|
type: exitcode-stdio-1.0
|
||||||
|
main-is: tests.hs
|
||||||
|
hs-source-dirs: app
|
||||||
|
build-depends: base
|
||||||
|
, pkgb
|
||||||
|
, process
|
||||||
|
build-tools: pkga
|
21
test/coverage/pkgb/src/ConduitExample.hs
Normal file
21
test/coverage/pkgb/src/ConduitExample.hs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
-- https://github.com/snoyberg/conduit#readme
|
||||||
|
|
||||||
|
module ConduitExample (example) where
|
||||||
|
|
||||||
|
import Conduit
|
||||||
|
import System.Directory (removeFile)
|
||||||
|
|
||||||
|
example = do
|
||||||
|
-- Pure operations: summing numbers.
|
||||||
|
print $ runConduitPure $ yieldMany [1..10] .| sumC
|
||||||
|
|
||||||
|
-- Exception safe file access: copy a file.
|
||||||
|
writeFile "input.txt" "This is a test." -- create the source file
|
||||||
|
runConduitRes $ sourceFileBS "input.txt" .| sinkFile "output.txt" -- actual copying
|
||||||
|
readFile "output.txt" >>= putStrLn -- prove that it worked
|
||||||
|
|
||||||
|
-- Perform transformations.
|
||||||
|
print $ runConduitPure $ yieldMany [1..10] .| mapC (+ 1) .| sinkList
|
||||||
|
|
||||||
|
removeFile "input.txt"
|
||||||
|
removeFile "output.txt"
|
7
test/coverage/pkgb/src/PkgB.hs
Normal file
7
test/coverage/pkgb/src/PkgB.hs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
|
module PkgB (message) where
|
||||||
|
|
||||||
|
import PkgA (decode)
|
||||||
|
|
||||||
|
message = decode "Guvf vf n pnony cebwrpg!"
|
5
test/coverage/pkgb/src/conduit-test.hs
Normal file
5
test/coverage/pkgb/src/conduit-test.hs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import ConduitExample
|
||||||
|
|
||||||
|
main = example
|
5
test/coverage/stack.yaml
Normal file
5
test/coverage/stack.yaml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
resolver: lts-14.13
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- pkga/
|
||||||
|
- pkgb/
|
@ -181,6 +181,7 @@ let
|
|||||||
hls-stack = callTest ./haskell-language-server/stack.nix { inherit compiler-nix-name; };
|
hls-stack = callTest ./haskell-language-server/stack.nix { inherit compiler-nix-name; };
|
||||||
cabal-hpack = callTest ./cabal-hpack { inherit util compiler-nix-name; };
|
cabal-hpack = callTest ./cabal-hpack { inherit util compiler-nix-name; };
|
||||||
index-state = callTest ./index-state { inherit compiler-nix-name; };
|
index-state = callTest ./index-state { inherit compiler-nix-name; };
|
||||||
|
coverage = callTest ./coverage { inherit compiler-nix-name; };
|
||||||
|
|
||||||
unit = unitTests;
|
unit = unitTests;
|
||||||
} // lib.optionalAttrs (!stdenv.hostPlatform.isGhcjs && compiler-nix-name != "ghc8101" && compiler-nix-name != "ghc8102" ) {
|
} // lib.optionalAttrs (!stdenv.hostPlatform.isGhcjs && compiler-nix-name != "ghc8101" && compiler-nix-name != "ghc8102" ) {
|
||||||
|
@ -26,7 +26,7 @@ in recurseIntoAttrs {
|
|||||||
|
|
||||||
# fixme: run on target platform when cross-compiled
|
# fixme: run on target platform when cross-compiled
|
||||||
printf "checking whether executable ran... " >& 2
|
printf "checking whether executable ran... " >& 2
|
||||||
cat ${haskellLib.check packages.exe-only.components.exes.exe-only}
|
cat ${haskellLib.check packages.exe-only.components.exes.exe-only}/test-stdout
|
||||||
'' +
|
'' +
|
||||||
# Aarch are statically linked and does not have ldd for these tests.
|
# Aarch are statically linked and does not have ldd for these tests.
|
||||||
optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64) (
|
optionalString (!stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64) (
|
||||||
|
@ -41,7 +41,7 @@ in recurseIntoAttrs {
|
|||||||
printf "size of executable $exe is $size. \n" >& 2
|
printf "size of executable $exe is $size. \n" >& 2
|
||||||
# fixme: run on target platform when cross-compiled
|
# fixme: run on target platform when cross-compiled
|
||||||
printf "checking whether executable runs... " >& 2
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.external-package-user.components.exes.external-package-user}
|
cat ${haskellLib.check packages.external-package-user.components.exes.external-package-user}/test-stdout
|
||||||
'' + (if stdenv.hostPlatform.isMusl
|
'' + (if stdenv.hostPlatform.isMusl
|
||||||
then ''
|
then ''
|
||||||
printf "checking that executable is statically linked... " >& 2
|
printf "checking that executable is statically linked... " >& 2
|
||||||
|
@ -21,7 +21,7 @@ in recurseIntoAttrs {
|
|||||||
|
|
||||||
buildCommand = ''
|
buildCommand = ''
|
||||||
printf "checking whether executable runs... " >& 2
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.test-ghc-options.components.exes.test-ghc-options-exe}
|
cat ${haskellLib.check packages.test-ghc-options.components.exes.test-ghc-options-exe}/test-stdout
|
||||||
|
|
||||||
touch $out
|
touch $out
|
||||||
'';
|
'';
|
||||||
|
@ -22,7 +22,7 @@ in recurseIntoAttrs {
|
|||||||
|
|
||||||
buildCommand = ''
|
buildCommand = ''
|
||||||
printf "checking whether executable runs... " >& 2
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.test-ghc-options.components.exes.test-ghc-options-exe}
|
cat ${haskellLib.check packages.test-ghc-options.components.exes.test-ghc-options-exe}/test-stdout
|
||||||
|
|
||||||
echo '${concatStringsSep " " packageNames}' > $out
|
echo '${concatStringsSep " " packageNames}' > $out
|
||||||
'';
|
'';
|
||||||
|
@ -21,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}"
|
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
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.test-project-flags.components.exes.test-project-flags-exe}
|
cat ${haskellLib.check packages.test-project-flags.components.exes.test-project-flags-exe}/test-stdout
|
||||||
|
|
||||||
touch $out
|
touch $out
|
||||||
'';
|
'';
|
||||||
|
@ -19,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}"
|
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
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.test-project-flags.components.exes.test-project-flags-exe}
|
cat ${haskellLib.check packages.test-project-flags.components.exes.test-project-flags-exe}/test-stdout
|
||||||
|
|
||||||
touch $out
|
touch $out
|
||||||
'';
|
'';
|
||||||
|
@ -26,7 +26,7 @@ in recurseIntoAttrs {
|
|||||||
|
|
||||||
# fixme: run on target platform when cross-compiled
|
# fixme: run on target platform when cross-compiled
|
||||||
printf "checking whether executable runs... " >& 2
|
printf "checking whether executable runs... " >& 2
|
||||||
cat ${haskellLib.check packages.sublib-docs.components.exes.sublib-docs}
|
cat ${haskellLib.check packages.sublib-docs.components.exes.sublib-docs}/test-stdout
|
||||||
|
|
||||||
'' +
|
'' +
|
||||||
# Musl and Aarch are statically linked..
|
# Musl and Aarch are statically linked..
|
||||||
|
Loading…
Reference in New Issue
Block a user