cabal2nix icon indicating copy to clipboard operation
cabal2nix copied to clipboard

Support cabal.project files

Open ElvishJerricco opened this issue 6 years ago • 13 comments

cabal2nix should support something similar to haskell.lib.buildStackProject for projects with a cabal.project file. I suspect this will essentially amount to a derivation with { configurePhase = "cabal new-configure"; buildPhase = "cabal new-build"; }. The work that cabal2nix needs to do is find all the cabal files in the project and put together the list of dependencies that need to be present in the build.

My main motivation for this is the "common package" problem often encountered in web development. You have a backend package and a frontend, and you also have a common package for code shared between them. The most common workflow that I've seen is to have an extension of haskellPackages like this:

haskellPackages.extend (self: super: {
  common = self.callCabal2nix "common" ./common {};
  backend = self.callCabal2nix "backend" ./backend {};
  frontend = self.callCabal2nix "frontend" ./frontend {};
})

Each of the three source directories then has a shell.nix file that just does haskellPackages.<package>.env. Finally, you can use nix-shell --run "cabal configure" so that you can do incremental compilation with just cabal build. The problem with this approach is that any change to common will necessitate:

  1. A full rebuild of the common Nix derivation
  2. backend and frontend must both redo their cabal configure command, since common is now changed.
  3. The reconfigure will require backend and frontend to be rebuilt from scratch.

You want incremental development so that a change to common merely requires incremental recompilation. This is something the cabal.project layout does spectacularly well. So it'd be nice to have a Nix expression that lets us use cabal new-build for local incremental development with the cabal.project file, and nix-build for a deterministic Nix build. I suppose the nix-build, like buildStackProject, would merely output executables, and would not be suited to building a lib for other Haskell derivations to depend on.

ElvishJerricco avatar Jul 26 '17 19:07 ElvishJerricco

Please ignore the fact that my example is flawed since frontend would be built with a different compiler =P Besides that being solved by new-build putting the compiler name in the output paths, this is also a general problem for any project with several packages.

ElvishJerricco avatar Jul 26 '17 19:07 ElvishJerricco

This would be incredibly helpful.

At the moment what I'm doing for a web project is using 3 separate cabal packages: common, backend, and frontend. I have a cabal.project file in each of backend and frontend, both of which specify ../common/ as an additional local package.

To work on the backend project what I really want a nix-shell including a ghc with both the dependencies of common and backend (but without common installed into the nix store). But a nix-expression for such a ghc doesn't seem very easy to produce from the cabal2nix outputs for backend and common individually. Getting an env from the cabal2nix output for backend works, but requires me to inject common into the haskell package set, which requires it to be built into the nix store. If it doesn't currently build I can't even do that; I'll need to drop into a separate shell just for common and fix it independently.

If cabal2nix was able to produce this from the cabal.project file (perhaps with a new --project-shell flag?), then I could easily combine the backend and frontend environments into a composite shell that would work for both simultaneously (since I can use a separate compiler for each, I don't need to be able to "merge" the ghcWithPackages results). So I don't think cabal2nix needs to worry about supporting making environments with multiple compilers.

cumber avatar Sep 04 '17 03:09 cumber

For what it's worth, I started working on a patch along these lines here. Unfortunately time has been lacking to carry it on.

Essentially, it rips the install plan out of dist-newstyle/cache/plan.json and hackily constructs some expressions. I don't recall precisely where I left off on it.

bgamari avatar Jan 21 '18 22:01 bgamari

Until this ticket gets an implementation the solution is to use stack2nix?

freeman42x avatar Aug 18 '19 16:08 freeman42x

Pretty sure this can be closed because of the existence of shellFor.

L-as avatar Oct 16 '21 08:10 L-as

I think documenting shellFor at the very least is in order which I've started here. Some automation improvements could be nice, but I'm not certain how that could look. With multi package development environments there's no longer a clear sense of the right way to generate an expression as with cabal2nix --shell

sternenseemann avatar Oct 16 '21 11:10 sternenseemann

I don't think there's a good solution to automating this. Making a shell.nix manually isn't hard and you rarely need to update the file.

L-as avatar Oct 16 '21 14:10 L-as

Generating a shellFor expression seems trivial and better than nothing. Why not exactly?

Elvecent avatar May 21 '22 18:05 Elvecent

@Elvecent Do you mean cabal2nix should offer generating a shellFor expression from the cabal.project file? I think we should rather provide good examples and documentation.

maralorn avatar May 21 '22 18:05 maralorn

Do you mean cabal2nix should offer generating a shellFor expression from the cabal.project file?

Yes, exactly.

I think we should rather provide good examples and documentation.

I don't understand which place do you have in mind for keeping these examples and docs. Do you mean cabal2nix should print related instructions as opposed to readily usable Nix expression, or do you mean it's simply out of scope for cabal2nix?

Elvecent avatar May 21 '22 18:05 Elvecent

It was my impression that cabal2nix has a long history of feature creep. So my intuition is, that a lot of things are out of scope for cabal2nix, yes. But I would probably need a discussion with the other maintainers to make up my mind as to what exactly should be included and what not.

I think docs and examples for how to setup a dev environment, including for how setup a dev environment for multiple packages at the same time, belong in the nixpkgs manual.

maralorn avatar May 21 '22 19:05 maralorn

I think support for cabal.project files can probably be implemented as a feature for shellFor in nixpkgs given someone looks into implementing the required globbing (which can probably be adapted from gitignore code that‘s already in nixpkgs).

sternenseemann avatar May 22 '22 16:05 sternenseemann

I think support for cabal.project files can probably be implemented as a feature for shellFor given someone looks into implementing the required globbing (which can probably be adapted from gitignore code that‘s already in nixpkgs).

On 21. May 2022, at 21:32, maralorn @.***> wrote:

 It was my impression that cabal2nix has a long history of feature creep. So my intuition is, that a lot of things are out of scope for cabal2nix, yes. But I would probably need a discussion with the other maintainers to make up my mind as to what exactly should be included and what not.

I think docs and examples for how to setup a dev environment, including for how setup a dev environment for multiple packages at the same time, belong in the nixpkgs manual.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.

sternenseemann avatar Oct 11 '22 08:10 sternenseemann