Cabal: RFC: ~~Merge~~Rename `Cabal` and `cabal-install` packages

Created on 9 Oct 2016  路  20Comments  路  Source: haskell/cabal

Thanks to nix-local-build & @ezyang's per-component feature we could now finally fix one awkward and hard to explain wart of cabal: if you want the cabal executable, you have to install a weirdly named package:

cabal install cabal-install

instead, we'd want to have

cabal install cabal

UPDATE See the new strategy described at https://github.com/haskell/cabal/issues/3965#issuecomment-255468685


the part below has been obsoleted

So instead, if we could fold the executable into the Cabal package, and then we could simply say

cabal install Cabal

Moreover, thanks to build-depends only requesting the Cabal library component, one can safely

build-depends: Cabal == 2.0.*

without having the executable build.

This would be more symmetric with the Stack package, http://hackage.haskell.org/package/stack
which also combines executable and library in one package, and provides users with a better story, since you can say

cabal install stack`

and you get the executable, while if you say build-depends: stack == 1.2.* you only get the library.

discussion

Most helpful comment

I'm fine with @mgsloan's suggestion to rename the two packages if this gets consensus; I've talked to @ezyang and we came up with a scheme for this variant:

Good thing is, that cabal has long supported case sensitive names; it's just the CLI that autocorrects the letter case if there's no ambiguity. .cabal files have to match the exact case of package names.

We already have two cabal packages in the index that only differ by case:

and that didn't cause any obvious problems.

Also, since Cabal 2.0 is going to be a disruptive/breaking release, and we have an implicit Cabal < 2 upper bound for custom build-types in place, this would be a good time to consider renaming Cabal.

So, the concrete scheme then would come down to simply

  • Rename Cabal to cabal-lib
  • Rename cabal-install to cabal (use at most 4-part version numbers)
  • (_maybe_) Keep a shim package Cabal to aid transition for some time which reexports all modules of cabal-lib

    • use a version number which matches the respective cabal-lib version but padded with trailing zero version components up to 5 version components (that way, even on case-insensitive filesystems there won't be any clash between cabal-1.2.3.4.tar.gz and cabal-lib-1.2.3.4/Cabal-1.2.3.4.0.tar.gz)

Obviously, we'd have to make sure that bootstrapping on lnx/win/osx still works in various combinations, and look for places where the package name "Cabal" is currently hardwired. But this seems all doable to me.

All 20 comments

Maybe we should take over http://hackage.haskell.org/package/cabal as well.

@hvr and I had a discussion on IRC about this; the conclusion was that I am basically OK with this as long as we don't have serious plans to _actually_ decouple cabal-install and Cabal (it doesn't seem like it.) There are some things that have to be dealt with to actually make this happen:

  1. cabal-install uses a Custom setup to build manpages; need to do something about it
  2. We need to make sure hackage-security will still build correctly (it should, but not obviously true! Probably would give Stack fits)
  3. Need to make sure that you can still bootstrap up

I wonder how this fits with the plans to separate the solver and hackage-client bits from cabal-install into separate libraries.

It's the same deal with hackage-security: the executable needs to be able to depend on an external package that depends on Cabal library

Won't this lead to a large risk of (accidentally or otherwise) increasing coupling between Cabal and cabal-install? In my experience, the _minute_ you make it easier to introduce coupling, e.g. by colocating projects, it'll start happening -- not through any malice, but because things have a natural tendency to drift towards the 'easy-now' solution vs. the 'harder-now-but-better-in-the-long-run' solution.

What are the other potential downsides here?

I also want to reiterate @23Skidoo 's question here: Won't this just put more roadblocks in the way of the "split solver"[1] plans? (@ezyang: If your comment was an answer to that, then I'm not sure I follow. Could you expand on how it would work?)

[1] I'm basically using "split solver" as a proxy for "any useful piece of functionality", the solver being the most obvious example.

While it wouldn't dramatically impact the stack project, we would really prefer to not have cabal-install as a dep. We appreciate keeping the separation of concerns.

I also agree with @BardurArantsson 's point that this will make it far easier to introduce unintended coupling.

Oh, forgot to mention: Currently the project is dogfooding new-build (albeit at small scale). I see that as quite valuable in itself and if the only upside is "users have to type 8 letters" then I don't want this.

Are there other upsides I'm missing?

Won't this lead to a large risk of (accidentally or otherwise) increasing coupling between Cabal and cabal-install?

I don't think it will increase coupling any more than the coupling today. Even today it is effectively not possible to do a cabal-install release without a Cabal release. cabal-install HEAD is only built and tested against Cabal HEAD. If we're serious about decoupling, we need to at least decolocate the two projects.

If your comment was an answer to that, then I'm not sure I follow. Could you expand on how it would work?

Today, if we have a set of packages like this:

Cabal.cabal
  library
  executable cabal
    build-depends: hackage-security

hackage-security.cabal
  library
    build-depends: Cabal

the dependency solver will fail with the following message:

Resolving dependencies...
cabal: Could not resolve dependencies:
trying: p-0.1.0.0 (user goal)
next goal: q (user goal)
rejecting: q-0.1.0.0 (cyclic dependencies; conflict set: p, q)
fail (backjumping, conflict set: p, q)
Dependency tree exhaustively searched.

However, there is no reason why it _couldn't_ find a solution in this case; if you solve for the dependencies of each component in p separately, the solution ends up being non-cyclic. It's a long-standing request, even; see #1768 for a case where someone wants deps for differing components to be solved separately.

I see that as quite valuable in itself and if the only upside is "users have to type 8 letters" then I don't want this.

Based on discussion with @hvr, he wants to smooth over the bootstrapping experience; so instead of cabal install cabal-install, it's just cabal install Cabal, which "makes more sense".

If it is about the name, then how about just rename Cabal to cabal-library, and cabal-install to cabal? This would still be an unpleasant name change, but at least the capitalization would be consistent.

I don't think making them components in one package is a good idea. Packages are our unit of distribution, and the thing other packages can depend on. cabal-install can sometimes optimise and omit components in packages it doesn't need, e.g. when it just needs the lib, but that's not something other tools can do, and it's not really part of the Cabal spec (think of distro tools).

I'd be quite happy renaming things though, e.g. Cabal -> cabal-lib(rary); cabal-install -> cabal.

@BardurArantsson it's not clear to me there's any more or less tendency to spaghetti if code is in separate components in one package vs separate packages in the same repo.

I'm fine with @mgsloan's suggestion to rename the two packages if this gets consensus; I've talked to @ezyang and we came up with a scheme for this variant:

Good thing is, that cabal has long supported case sensitive names; it's just the CLI that autocorrects the letter case if there's no ambiguity. .cabal files have to match the exact case of package names.

We already have two cabal packages in the index that only differ by case:

and that didn't cause any obvious problems.

Also, since Cabal 2.0 is going to be a disruptive/breaking release, and we have an implicit Cabal < 2 upper bound for custom build-types in place, this would be a good time to consider renaming Cabal.

So, the concrete scheme then would come down to simply

  • Rename Cabal to cabal-lib
  • Rename cabal-install to cabal (use at most 4-part version numbers)
  • (_maybe_) Keep a shim package Cabal to aid transition for some time which reexports all modules of cabal-lib

    • use a version number which matches the respective cabal-lib version but padded with trailing zero version components up to 5 version components (that way, even on case-insensitive filesystems there won't be any clash between cabal-1.2.3.4.tar.gz and cabal-lib-1.2.3.4/Cabal-1.2.3.4.0.tar.gz)

Obviously, we'd have to make sure that bootstrapping on lnx/win/osx still works in various combinations, and look for places where the package name "Cabal" is currently hardwired. But this seems all doable to me.

For extra disambiguation, what if the library got its own name?

Here's a cute idea: pyramid. Insofar as stack and cabal-install both use Cabal:

stack ... tall thing ... pyramid ... pyramid scheme ... illegal organization ... cabal.

Also the convex hull of a dependency graph laid out sensibly in R^3 with built-in packages pruned is....roughly a pyramid?

Assigned @hvr to this. I guess if we're going to do this, better be for 2.0.

Just for the record, as I mentioned in haskell/hackage-server#773, I'm planning to do this for 3.0 (which is what people originally assumed 2.0 to be)

We really need per-component solving for this, otherwise I consider merging a very bad idea.

@phadej actually, the plan is to go with a variant of https://github.com/haskell/cabal/issues/3965#issuecomment-255468685 as coupling the exe w/ the lib wouldn't necessarily be ideal anyway

@hvr could you update the title and the first message in the issue. It's very confusing otherwise.

@phadej done

This is definitely not for 3.0

I don't want to edit this issue, but everytime I run into this issue I need to follow links to comments, which refer further back.

Also since "Also, since Cabal 2.0 is going to be a disruptive/breaking release," doesn't apply anymore, that needs to be rethought.

So I use my power and close this issue, as in current state it's not clear and not actionable. Also the name if misleading.

Was this page helpful?
0 / 5 - 0 ratings