input-output-hk / haskell.nix

Alternative Haskell Infrastructure for Nixpkgs
https://input-output-hk.github.io/haskell.nix
Apache License 2.0
540 stars 235 forks source link

Top-level `coverage: True` inappropriately applied to dependencies #2141

Open shlevy opened 6 months ago

shlevy commented 6 months ago

When I put coverage: True as a top-level field in my cabal.project, I get a failure from haskell.nix that I don't see using cabal directly:

Resolving dependencies...
make-install-plan: dieVerbatim: user error (Error:
    Internal libraries only supported with per-component builds.
    Per-component builds were disabled because program coverage is enabled
    In the package 'attoparsec-0.14.4'
)

This is unexpected, as the top-level declaration should only apply to local packages. Indeed, if I move the coverage: True underneath a package stanza for my one package, h.nix is happy.

hamishmack commented 6 months ago

Does cabal configure work?

shlevy commented 6 months ago

Yes

andreabedini commented 6 months ago

What derivation are you building with haskell.nix? $pkg.coverageReport?

I tried but I couldn't reproduce this. It seems that cabal fails the planning step with the same message.

~/Scratchpad/haskell-nix-coverage
❯ cabal init --non-interactive --minimal --exe --dependency base --dependency attoparsec
[Log] Using cabal specification: 3.0
[Warning] unknown license type, you must put a copy in LICENSE yourself.
[Log] Creating fresh file CHANGELOG.md...
[Log] Creating fresh directory ./app...
[Log] Creating fresh file app/Main.hs...
[Log] Creating fresh file haskell-nix-coverage.cabal...
[Warning] No synopsis given. You should edit the .cabal file and add one.
[Info] You may want to edit the .cabal file and add a Description field.

~/Scratchpad/haskell-nix-coverage
❯ echo 'coverage: True' > cabal.project.local

~/Scratchpad/haskell-nix-coverage
❯ cabal build
Resolving dependencies...
Error:
    Internal libraries only supported with per-component builds.
    Per-component builds were disabled because program coverage is enabled
    In the package 'attoparsec-0.14.4'

~/Scratchpad/haskell-nix-coverage
❯ cabal --version
cabal-install version 3.10.2.1
compiled using version 3.10.2.1 of the Cabal library

while scoping coverage: True to the local package works:

~/Scratchpad/haskell-nix-coverage
❯ echo -e 'package haskell-nix-coverage\n  coverage: True' > cabal.project.local

~/Scratchpad/haskell-nix-coverage
❯ cabal build
Resolving dependencies...
Build profile: -w ghc-9.6.3 -O1
In order, the following will be built (use -v for more details):
 - haskell-nix-coverage-0.1.0.0 (exe:haskell-nix-coverage) (first run)
Configuring executable 'haskell-nix-coverage' for haskell-nix-coverage-0.1.0.0..
Preprocessing executable 'haskell-nix-coverage' for haskell-nix-coverage-0.1.0.0..
Building executable 'haskell-nix-coverage' for haskell-nix-coverage-0.1.0.0..
[1 of 1] Compiling Main             ( app/Main.hs, /home/andrea/Scratchpad/haskell-nix-coverage/dist-newstyle/build/x86_64-linux/ghc-9.6.3/haskell-nix-coverage-0.1.0.0/x/haskell-nix-coverage/build/haskell-nix-coverage/haskell-nix-coverage-tmp/Main.o )
[2 of 2] Linking /home/andrea/Scratchpad/haskell-nix-coverage/dist-newstyle/build/x86_64-linux/ghc-9.6.3/haskell-nix-coverage-0.1.0.0/x/haskell-nix-coverage/build/haskell-nix-coverage/haskell-nix-coverage

Does cabal configure work?

Since v2 commands cabal configure does nothing other than writing the configuration options from the command line into cabal.project.local. One way to trigger the planning step is cabal build --dry-run.

PS1:

this seems to work

❯ nix run github:input-output-hk/haskell.nix#hix build .#haskell-nix-coverage:exe:haskell-nix-coverage.project.hsPkgs.haskell-nix-coverage.coverageReport
...
❯ tree result
result
├── nix-support
│   └── hydra-build-products
└── share
    └── hpc
        └── vanilla
            ├── haskell-nix-coverage-0.1.0.0-html.zip
            ├── html
            │   └── haskell-nix-coverage-0.1.0.0
            │       ├── hpc_index_alt.html
            │       ├── hpc_index_exp.html
            │       ├── hpc_index_fun.html
            │       └── hpc_index.html
            ├── mix
            └── tix
                └── haskell-nix-coverage-0.1.0.0
                    └── haskell-nix-coverage-0.1.0.0.tix

PS2: IIRC the incompatibility between per-component builds and hpc was recently addressed by @alt-romes.

shlevy commented 6 months ago

If I'm already in my nix develop shell and then switch to https://github.com/shlevy/e11y/tree/ca492d8309a987a20ef317b432730cd1276dc915, cabal build all then cabal test all works fine. However, on that revision, nix develop fails with:

Warning: Unknown/unsupported 'ghc' version detected (Cabal 3.10.1.0 supports
'ghc' version < 9.8):
/nix/store/zv4sldzcs922dhk2nqpga2lxz6sfzkxw-dummy-ghc-9.8.1/bin/ghc is version
9.8.1
Warning: The package list for 'hackage.haskell.org' is 19739 days old.
Run 'cabal update' to get the latest list of available packages.
Warning: Requested index-state 2024-01-16T00:00:00Z is newer than
'hackage.haskell.org'! Falling back to older state (2024-01-15T23:59:45Z).
Resolving dependencies...
make-install-plan: dieVerbatim: user error (Error:
    Internal libraries only supported with per-component builds.
    Per-component builds were disabled because program coverage is enabled
    In the package 'attoparsec-0.14.4'
)
alt-romes commented 6 months ago

This should have been fixed by https://github.com/haskell/cabal/commit/073ccc84338fb51d68d5002bdd48c4b9ad7ce363, although I don't think it is going to be backported to 3.10

shlevy commented 6 months ago

Hmm, is it possible it made it into Cabal 3.10.2.0 ? Because I see that inside the shell my cabal-install was built against that but it looks like haskell.nix is using 3.10.1.0 to generate its plan.

andreabedini commented 6 months ago

Haskell.nix backports some patches for cabal but this does not seem one of those.

andreabedini commented 6 months ago

If I'm already in my nix develop shell and then switch to https://github.com/shlevy/e11y/tree/ca492d8309a987a20ef317b432730cd1276dc915, cabal build all then cabal test all works fine. However, on that revision, nix develop fails with: :bulb: Now I see what is going on!

If you do nix develop github:shlevy/e11y/50069849193a3199c1f78d6687d76fe1521f8e02 (master at the time of writing), you are making a plan without converage reporting. Haskell.nix pre-compiles and pre-installs all dependencies.

Under that conditions, cabal's solver will prefer the pre-existing compiled packages (irrespectively of the coverage: setting, due to the solver's limitations). Therefore, troublesome packages like attoparsec are compiled without coverage reporting and cabal build works ok.

If, instead, you start with nix develop github:shlevy/e11y/ca492d8309a987a20ef317b432730cd1276dc915 the cabal's solver fails to build an install plan, with the error you show above.

tl;dr: It's a mixture of two problems:

1) cabal solver picks pre-existing packages even when they have been compiled with different options. 2) The existing problem with coverage reporting and per-component builds (which is going to be solved soon).

shlevy commented 6 months ago

Hmm... If this is right, this still seems like a cabal bug. From https://cabal.readthedocs.io/en/3.4/cabal-project.html#package-configuration-options:

Package options affect the building of specific packages. There are three ways a package option can be specified:

They can be specified at the top-level, in which case they apply only to local package, or

They can be specified inside a package stanza, in which case they apply to the build of the package, whether or not it is local or external.

They can be specified inside an package * stanza, in which case they apply to all packages, local ones from the project and also external dependencies.

So why would a top-level coverage: True impact dependencies at all? It's not like coverage for local packages depends at all on coverage info from dependencies, right?

stale[bot] commented 2 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.