-
Notifications
You must be signed in to change notification settings - Fork 701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] Move dependency solver to library #2768
Conversation
33a5311
to
2ddd877
Compare
This involves doing some surgery to factor out the sandbox bits.
Up to merge conflicts this should now pass the testsuite. However, I'm going to hold off on addressing the conflicts until there is some positive feedback on the idea and approach. |
I personally very like the idea! 👍 Other thing worth splitting is a code reading package database from tar file (I guess it's duplicated in a way or another in cabal-db and various other tools). |
I like the idea. I would like to understand how this PR would bring Cabal closer to OPAM, with the ability to use CUDF-compatible solvers: /cc @mboes @tomjaguarpaw |
👍 @mietek this is a first step. The major difference with CUDF framework is that there package managers (such as OPAM) have a textual interface with the solvers, rather than interacting via a library API. So CUDF decouples components more strongly. But it could well be pretty easy to slap a CUDF frontend in front of the existing solvers, now that they are standalone packages. |
One thing I couldn't figure out from the CUDF primer and skimming through the CUDF paper: Can |
I'm very much 👍 in this. |
Alright, so it sounds as though there is fairly wide support for this idea. It would be great if I could get a more thorough code review. This will be a very difficult patch to keep up-to-date and will be rather annoying for anyone with outstanding patches, so I'd like to ensure that we plan this carefully. @dcoutts, do you have any objections here? |
Isn't the correct solution to this to just turn the whole package into a library? One could literally make everything a library apart from the |
@tomjaguarpaw personally I would rather see it split up a bit. Currently |
Seems like turning |
@mietek and @tomjaguarpaw see #1597 for reasons why that would not be a good idea. (But certainly general-enough and disconnected parts could perhaps.) @bgamari I'll have a go at reviewing the code; I'm a noob round these parts (even more so in the solver), so I'm not sure what it's worth -- perhaps I can spot style issues and such. |
I would prefer if we separated the network-aware components of the solver from the agnostic components and move the latter into the Cabal library itself. I think separating the solver from the transport is an important step toward enabling different package distribution schemes. Also, from a purely intellectual standpoint, I think the solver should care about the contents of the package index, not where it came from. Having the transport-agnostic parts of the solver in Cabal itself would help solve #2777. I still think it's a good idea to separate the transport-sensitive parts of the solver from cabal-install, too. |
Sorry for being late to join this discussion. Could we please make it explicit what exactly it is we hope to achieve by doing this? I'm not opposed to it, but I'm not sure what the goals are. If the goals are clearly stated, it would make it easier for me to evaluate if the currently proposed split is a good way to achieve them. Note that if the goal is mostly to be able to plug in external solvers (such as SMT solvers or CUDF solvers), this can in principle be done already, without separating out the solvers into extra packages. But I think there's more involved here, such as having library interfaces for cabal-install itself and/or the solvers so that functions can be called easily from other tools/libraries. It's here where I'm not quite sure what exactly it is we want or are hoping for. |
So, I think I think I'd like to take a stab at this -- if not thing else then for my own edification. However, I want to try do it in a somewhat more... "disciplined" way than this PR. (That is, to not just create a 3rd "commons"-type library which both Cabal and cabal-install depend on.) At the very least I can hopefully see what some of the difficulties with the "disciplined" approach are and provide a summary here. There seems to be some disagreement on whether the solver should be moved to its own entirely-separate-from-Cabal library or "just" moved into Cabal-the-library. Would moving it into Cabal be an acceptable first step for the "solver" portion of your use case @bgamari? @ttuegel If it turns out that it's feasible to separate the solver entirely from Cabal (and to provide an API which would remain long-term stable), would you object to that? I'm thinking of moving only the solver, no transports, file access, or anything like that. |
Bardur Arantsson [email protected] writes:
|
Somewhat leading question for everyone in here: Is anybody actually still using the TopDown solver? Given that it's not part of any stable API, does it make sense to keep it around? After having fiddled about with the code a bit, here's my tentative plan:
Does this plan make sense to everyone? Objections? Comments? |
See #2531. |
So that would be... no? ;) |
@BardurArantsson The old solver is deprecated, but the plan is to keep it for a while (1-2 releases, I think). |
Tbh, I'm not sure this belongs into the PS: another problem I see is that tying this into |
Yes, I agree with @hvr. I said a while ago I'd think about whether to include the solvers in the library, and after doing so, I don't think it's a good idea. The Cabal lib is not tied up to the solver, and won't need to be, and putting the solver(s) in there is only going to make changes to the solvers unnecessarily harder. So I'd also go for a new package. |
@BardurArantsson Regarding topdown: I don't think it's needed anymore, as also @23Skidoo says. I would very much like to keep it though. Even though it's mostly inferior to the modular solver, it's always good to have two implementations of an interface, and it's also worthwhile to have two independent solvers in the first place. I sometimes still use it for testing purposes. |
@hvr : Right, for some reason it didn't cross my mind that I could just create a separate package which depends on Cabal and which cabal-install then depends on in turn. That's what I'll do. (Btw, the only added dependency I stumbled upon is "mtl".) @kosmikus I definitely agree that it's better to have two implementations of the same interface in principle, but given how the code looks, I'm not really sure that that's actually what we have at the moment. There's also a non-trivial cost to having the two implementations. In particular the top-down implementation looks as though is quite tied in to internal cabal-install data structures. (Though, keep in mind I haven't spent that much time analyzing the code yet, so I may be mistaken.) I'll see what can be done about preserving the top-down solver as an option in cabal-install, but I am pretty sure that it won't be possible to split it from cabal-install in any sensible way -- it looks like quite a lot of (ultimately pointless since it's already deprecated) work to do so. |
(Not sure how much the following summary will make for people not intimately familiar with the solver code, but here it is anyway: :) ) OK, so I've got a basic split-up implemented, but it needs a little bit of cleanup. Basically, it turned out that it wasn't that hard to move the two solvers to a new I'll probably open an RFC Pull Request sometime during the coming week. |
@BardurArantsson sounds great! 👍 |
See #2928. |
The discussion here seems to have glossed over a point @ttuegel, which is that currently the Cabal library has a very dumb solver for dependencies and flags which occasionally can use up a lot of memory (#2777). It seems to me that if cabal-installs is having its solver factored out, then so should Cabal. Specifically, whatever interface the separated modular solver ends up having, Cabal's solver should also be factored to follow the same interface. Though as a type this, I'm not sure how possible this is, since Cabal's solver is really dumb (it does not even attempt to make sure that the dependencies are globally consistent; it just checks it afterwards.) It is too bad we cannot just retire the solver! |
How does this follow? cabal-install is (naturally) higher up in the software stack.
I'm guessing you're thinking of the relatively hard requirement that "./Setup configure" should work? I could imagine splitting Cabal further such that the really core bits (reading the cabal files, etc.) were split up, but it's more work than I'm will to go through, at least. (Given the compatibility requirements it'd probably be a multi-year undertaking, I'm guessing. Perhaps the hassle could be alleviated by making Cabal into an "umbrella" project for compatibility, but still...) Would be nice, though... |
@BardurArantsson Taking a step back and considering this from a meta-perspective: Sadly there's also an associated cost with splitting up Cabal into smaller pieces. Even though I'd like myself to be able to tap directly into the solver as a library conveniently, there needs to be a significant benefit for the Cabal project to justify the incurred cost of management overhead of managing and coordinating multiple interdependent packages, including diligent PVP conformance. Then there's the decision to make whether to keep all sub-packages in a single Git repo (Git branching and tagging becomes confusing and unnatural, At this point I'd argue that we desperately need all resources to move forward Cabal+cabal-install development, and consequently postpone such a package refactoring to a time when the big features that are in the pipeline right now are closer to completeness, and we also have a better picture how the various moving parts of the finished thing depend on each other. |
@hvr What I'm trying to do is actually the much simpler version (which I think you actually suggested?) where we have Cabal -> cabal-solver -> cabal-install as a simple dependency chain and all in the same repo. That will at least allow others to depend on just Cabal + cabal-solver. It is the 80% solution that I personally can live with and which I think adds a lot of value -- enough to overcome the downsides. Besides, it's just good software development practice to separate modules as strictly as possible. (See #2928 for a little more detail on what I've done to this end. It needs a refresh, but I'm waiting until the solver fixes/updates from @grayjay hopefully make it in at some point.) (What I wrote in the previous comment is merely "wishlist", it's not something I'm actively pursuing.) EDIT: The higher-level "end game" here is to get to a place where we can experiment with completely new front ends which aren't
Unless you're going to just actively turn away contributors then this is what's called "herding cats". Welcome to project management! :). I don't know if anybody around here is getting paid to do Cabal/cabal-install development, but I'm certainly not... which means I'm going to work primarily work on things that interest me... or which impede my progress on things that interest me (see e.g. the new test framework for If the conclusion of "the management" is that no separation of the solver will be accepted, then I'll just find a more productive (and, frankly, fun) use of my time. (I'm not suggesting that this is about to actually happen right now, but if the decision on my approach is "no", then that's what's probably going to happen.) |
(btw, I'm not the project lead and I'm just yet another of those unpaid contributors voicing his opinion) Don't get me wrong, I still think that separating out the solver is a good thing long-term, I'm just arguing that maybe now is not the best time to do that just yet until cabal has stabilized again, unless it's apparent that factoring out the solver is orthogonal and won't hinder progress in the big new features. Btw, do you have a ticket/wiki-page for the new test framework you're working on? I wasn't aware of that |
Sure, no problem with having opinions :). I'm also just providing counterpoints. EDIT: This problem with not doing long-term work (even when said long-term work may impede short-term work temporarily) is that it leaves completely stuck in a local minimum with no way to get out. Progress on big new features is already slow enough (because the cabal-install code base is so crufty) that a little bit of extra slowness won't matter. That said, I believe that my proposal is basically orthogonal to everything other than the solver. The first step at least is a pretty simple refactor that basically just adds a type parameter here and there. Re: test framework: Already merged a few months ago. It was most of my work was in #2864 and @phadej took it from there: #2868 |
@BardurArantsson I don't want to hold up this change, so I'll just resolve any conflicts with my branch. |
(The conversation has moved on, but I mentioned Cabal the library because there is a solver, it's kind of a delicate and not very performant piece of code (#2777), and it is fully subsumed by a better solver, like the one cabal-install has. I just think it's something to keep in mind, let's do small refactors when we can!) |
@grayjay Thank you, but I don't think there's necessarily the necessary consensus that my approach is actually a good (enough) idea yet... though, given your offer I may try to actually redo my RFC PR just so people have something concrete to look at. We'll see. Thanks regardless. ... All: Maybe this is all getting too messy at this point what with two RFC pull requests and descriptions scattered over tens of comments, etc. I'll try to make a new GH Issue for this where I try to lay out my suggestion as clearly as I possibly can in the issue description and we can try to take it from here. I'll try to get to that over the next few days. Once that's done, I'll also close the two pending RFC PRs for this (mine and this one) and possibly related issues. @bgamari From what you've said so far, I take it you have no objection to this, right? |
(Assigned to self just so that I remember once I get a breather from work duties.) |
One of the major challenges when working within
cabal-install
is the monolithic nature of the codebase. Moreover, since the package provides only an executable component, features like sandbox support and the solver are inaccessible to third-party tooling (a problem which I am current feeling with cabal-ghc-dynflags). This takes the first step towards breaking upcabal-install
into a set of reusable libraries by taking the largest largely-independent chunk of code, the constraint solvers, and moving them into a separate library,cabal-install-solver
.Of course, the solvers do have some dependencies on the rest of
cabal-install
. I place these in a third package,cabal-install-lib
.This consists of two commits,
Distribution.Client.Dependency.*
) intocabal-install-solver
, moving the bare minimum modules necessary tocabal-install-lib
. This exclusively involves file renames and cabal file mangling.Distribution.Client.Dependency
itself out tocabal-install-solver
. This involves bringing over a few more modules tocabal-install-solver
and a bit of surgery to remove the policiesLooking forward, I would like to continue to move functionality into more fine-grained libraries. The package index (e.g.
PackageIndex
currently incabal-install-lib
and perhaps a few others still incabal-install
) is probably the next logical step here (moving it tocabal-install-index
). I would especially like to expose some of the sandbox interfaces as sandboxes are currently entirely opaque to third-party tools. This, however, may require substantial effort as much ofcabal-install
is written specifically as the backend to a command-line application.More on this later.