haskell / cabal

Official upstream development repository for Cabal and cabal-install
https://haskell.org/cabal
Other
1.61k stars 691 forks source link

The solver should distinguish errors that are cause by the absence of a system libraries from other errors #10239

Open Kleidukos opened 1 month ago

Kleidukos commented 1 month ago

Let's take a very real and reproducible solver error message:

[__0] trying: cardano-node-9.1.0 (user goal)
[__1] trying: ouroboros-consensus-0.20.0.0 (dependency of cardano-node)
[__2] trying: vector-0.13.1.0 (dependency of ouroboros-consensus)
[__3] next goal: cardano-crypto-class (dependency of cardano-node)
[__3] rejecting: cardano-crypto-class; 2.1.5.0, 2.1.4.0 (conflict: pkg-config package libblst-any, not found in the pkg-config database)
[__3] rejecting: cardano-crypto-class-2.1.3.0 (conflict: vector==0.13.1.0, cardano-crypto-class => vector<0.13)
[__3] skipping: cardano-crypto-class; 2.1.2.0, 2.1.1.0, 2.1.0.2, 2.1.0.1, 2.1.0.0 (has the same characteristics that caused the previous version to fail: excludes 'vector' version 0.13.1.0)
[__3] trying: cardano-crypto-class-2.0.0.1
[__4] next goal: base (dependency of cardano-node)
[__4] rejecting: base-4.18.2.1/installed-4.18.2.1 (conflict: cardano-crypto-class => base>=4.14 && <4.17)
[__4] skipping: base; 4.20.0.1, 4.20.0.0, 4.19.1.0, 4.19.0.0, 4.18.2.1, 4.18.2.0, 4.18.1.0, 4.18.0.0, 4.17.2.1, 4.17.2.0, 4.17.1.0, 4.17.0.0 (has the same characteristics that caused the previous version to fail: excluded by constraint '>=4.14 && <4.17' from 'cardano-crypto-class')

Two things happen here:

However these are two very different types of error, and mixing them together does not help anyone!


@PPKFS comments, quite understandably:

what I'm saying is the error should be this

[0] trying: cardano-node-9.1.0 (user goal) [1] trying: ouroboros-consensus-0.20.0.0 (dependency of cardano-node) [2] trying: vector-0.13.1.0 (dependency of ouroboros-consensus) [3] next goal: cardano-crypto-class (dependency of cardano-node) [__3] rejecting: cardano-crypto-class; 2.1.5.0, 2.1.4.0 (conflict: pkg-config package libblst-any, not found in the pkg-config database) this ain't it chief. we're done. sorry.

no trying base 3.0, no endless spam of every minor version of every transitive package and how it doesn't work with some other package

If people want to provide optional system dependency, we have a tool for it, it's called a flag. The solver is even able to switch them on and off if it thinks it will help finding a working plan.

Let's get rid of this quirk.

Kleidukos commented 1 month ago

@grayjay Do you have a first opinion on the feasibility of such a thing?

michaelpj commented 1 month ago

I'm not sure which of these you're asking for:

  1. Don't backtrack if you hit a missing system dependency, instead just fail immediately. This seems like a major change to how the solver works and doesn't obviously seem like a good idea at all. Why shouldn't we look for a plan that works without the system dependency?
  2. Report the solver problems more comprehensively, so the user can see that the "real" problem is the missing system dependency. Of course, which problem is "real" rather depends: if you in fact don't want to install the system library then perhaps it is helpful to know that you could use an old version of cardano-crypto-class if you used an older GHC. Who are we to say? And in general the solver error can be more complex.

[__3] rejecting: cardano-crypto-class; 2.1.5.0, 2.1.4.0 (conflict: pkg-config package libblst-any, not found in the pkg-config database) this ain't it chief. we're done. sorry.

no trying base 3.0, no endless spam of every minor version of every transitive package and how it doesn't work with some other package

This is what you would get... if someone had put a lower-bound on cardano-crypto-class. It looks like they haven't and so are advertising that it will work with all historical versions, which is false (and leads to bad error messages like this when we try).

If people want to provide optional system dependency, we have a tool for it, it's called a flag. The solver is even able to switch them on and off if it thinks it will help finding a working plan.

This doesn't make sense to me, can you elaborate? In the example you give it doesn't look like the dependency is optional, rather it became mandatory at some point in the version history.

Kleidukos commented 1 month ago

@michaelpj thank you for popping up,

Don't backtrack if you hit a missing system dependency, instead just fail immediately. This seems like a major change to how the solver works and doesn't obviously seem like a good idea at all. Why shouldn't we look for a plan that works without the system dependency?

That's indeed a major change. Why shouldn't we indeed, because then if the cabal file misses lower bounds as you say, it leads to such messages.

If you in fact don't want to install the system library then perhaps it is helpful to know that you could use an old version of cardano-crypto-class if you used an older GHC.

Can you and other maintainers of this library can tell me if this how cardano-crypto-class is supposed to be depended on? Because your message above makes me understand that it was involuntary. Maybe @erikd and @angerman can chime in too?

In general, the direction of this flow is a bad heuristic because it cannot differ between people who make a conscious choice of not having the library installed and those who haven't installed the library yes. It assumes that people are all-knowing, whereas the majority of people are just waiting to be told "you haven't installed this system library for the build to proceed".

Who are we to say?

We are the people doing tech support on Discord for beginners, who notice the same UX problems coming up again and again and again.

Staying on a library version that doesn't require the system dependency is as easy as putting a bound in your own cabal file.

This doesn't make sense to me, can you elaborate?

If a package provides an optional system dependency, they can do it with a cabal flag like in text. Indeed that's not the case of cardano-crypto-class although the end-user nor the solver can't know that, they are just confronted to the ugly error message.

Bodigrim commented 1 month ago

If people want to provide optional system dependency, we have a tool for it, it's called a flag. The solver is even able to switch them on and off if it thinks it will help finding a working plan.

The solver is able to switch automatic flags to avoid system dependencies precisely because it backtracks if any dependency (be it native or system or setup or build tool) is not satisfied. Changing this behavior is likely to be pretty damaging and counterintuitive.

Kleidukos commented 1 month ago

Okay so how do we make it so that the base experience of cabal beginners is improved?

michaelpj commented 1 month ago

Okay so how do we make it so that the base experience of cabal beginners is improved?

Well, I think there's a lot of low-hanging fruit in simply reporting the current state in a less obscure fashion:

Can you and other maintainers of this library can tell me if this how cardano-crypto-class is supposed to be depended on? Because your message above makes me understand that it was involuntary.

I tried to encourage Cardano folks to use more dependency bounds but it wasn't popular. I guess this is just a consequence :shrug: Perhaps we need to publicize more that poor lower bounds leads to worse errors for your users?

Staying on a library version that doesn't require the system dependency is as easy as putting a bound in your own cabal file.

How are you supposed to know to do that? The solver output, while verbose, does give you the hints you need to see which versions are problematic.

If a package provides an optional system dependency, they can do it with a cabal flag like in text.

There has been some discussion about this recently, but cabal flags as they currently exist are not very good for this purpose and I wouldn't recommend that people do that unless they really have to.

erikd commented 1 month ago

Can you and other maintainers of this library can tell me if this how cardano-crypto-class is supposed to be depended on? Because your message above makes me understand that it was involuntary. Maybe @erikd and @angerman can chime in too?

That is maybe libsodium, but more likely to be libblst (https://github.com/supranational/blst/) whose authors have decided to make it particularly difficult to package.

erikd commented 1 month ago

I tried to encourage Cardano folks to use more dependency bounds but it wasn't popular. I guess this is just a consequence 🤷 Perhaps we need to publicize more that poor lower bounds leads to worse errors for your users?

Lower bounds everywhere is probably not necessary. However, specific, targeted lower bounds are a good idea. cardano-crypto-class does already have a few lower bounds. Adding another would probably make sense.

The lowest recommended compiler for the Cardano code base is ghc-8.10.7 so a lower bound like base >= 4.14 would make sense.

grayjay commented 1 month ago

Are there more lines in the error message? I would have expected cabal to try more versions of base and print the final conflict set. What was the command? I'm especially interested in whether this run used --minimize-conflict-set.

I don't think that it is easy to determine which conflicts are more important to users in general, but in this case I would have expected the solver to de-emphasize the conflict with base. The solver already has a heuristic for choosing base as early as possible: https://github.com/haskell/cabal/blob/72e54398ab40d0b97d9f342d35c4d6d3128d1736/cabal-install-solver/src/Distribution/Solver/Modular/Preference.hs#L400-L404

I'm wondering if the issue is that the solver applies the heuristic when trying to find a solution (visible with -v3) but not when generating the summarized log.