Dependency hell in cabal. It is really a hell - haskell

Different programming languages use different packaging systems.
In their varied approach, Java's Maven looks like the best bet for me since it maintains different version of jar files in seperately versioned folders and hence, there is no way one will end up in conflicting versions of a library.
Next comes python. Python's pip puts its packages into /usr/local/lib/python/dist-packages/site-packages. When there is a version conflict, one can use its virtualenv and live with it.
Nodejs supports installing packages both in local folders and global folders. Till date for me, i never had a dependency conflict in the global libraries.
Then I got fascinated by the haskell's style and started using cabal. First, i was installing my libraries inside /home/user1/.cabal. Then when the package system broke, one friend suggested me to remove two folders - /home/user1/.cabal && /home/user1/.ghc. Now, my first confusion arose, why does cabal's library files sit in two folders .cabal && .ghc. I cleaned the library folders, ~/.ghc and ~/.cabal and did cabal install from a package source for cabal-db-0.1.12. Now, there was a new error and i was surprised, because i had sanitized all local repositories. The error was,
Configuring Cabal-1.22.2.0...
Building Cabal-1.22.2.0...
Installed Cabal-1.22.2.0
cabal: Error: some packages failed to install:
ansi-terminal-0.6.2.1 failed during the configure step. The exception was:
user error (The package 'ansi-terminal' requires Cabal library version -any &&
>=1.6 but no suitable version is installed.)
Then I tried the safest bet - sandbox for cabal-db. It worked. Then i repeated sandboxing for another pacakge, ghc-pkg-autofix. I did,
cd ghc-pkg-autofix-0.2.0.1
cabal sandbox init
cabal install
And for sandbox where there are absolutely no external dependencies, there are errors again,
cabal: Could not resolve dependencies:
trying: ghc-pkg-autofix-0.2.0.1 (user goal)
trying: Cabal-1.22.2.0 (dependency of ghc-pkg-autofix-0.2.0.1)
next goal: process (dependency of ghc-pkg-autofix-0.2.0.1)
rejecting: process-1.2.0.0/installed-06c..., 1.2.3.0, 1.2.2.0, 1.2.1.0,
1.2.0.0, 1.1.0.2, 1.1.0.1, 1.1.0.0 (conflict: ghc-pkg-autofix => process>=1.0
&& <1.1)
rejecting: process-1.0.1.5, 1.0.1.4, 1.0.1.3, 1.0.1.2, 1.0.1.1, 1.0.0.0
(conflict: Cabal => process>=1.1.0.1 && <1.3)
Dependency tree exhaustively searched.
Note: when using a sandbox, all packages are required to have consistent
dependencies. Try reinstalling/unregistering the offending packages or
recreating the sandbox.
Am i doing something wrong (or) this kind of dependency conflicts are quite common in cabal? I see, managing dependencies in other languages are a lot simpler.
Note: I use cabal-install version 1.22.0.0 && The Glorious Glasgow Haskell Compilation System, version 7.8.4

"And for sandbox where there are absolutely no external dependencies" this is not true. A sandbox still has dependencies on the global package database. Things like Cabal, GHC, process are typically installed in the global package database. Here you want to install ghc-pkg-autofix which requires process 1.0, but you have a more recent version of process already installed. Are you sure you need ghc-pkg-autofix, it seems to be quite old.

Related

Cabal tries to build unknown package when building with alex, happy in nix-shell

I'm currently trying to build a Haskell project using nix-shell and cabal, with alex and happy as build tools. Building inside nix-shell (with and without --pure), I get the following strange error message:
cabal: Could not resolve dependencies:
[__0] trying: aoc-0.1.0.0 (user goal)
[__1] unknown package: aoc:happy:exe.happy (dependency of aoc)
[__1] fail (backjumping, conflict set: aoc, aoc:happy:exe.happy)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: aoc, aoc:happy:exe.happy
It appears to be trying to satisfy some nonsense dependency aoc:happy:exe.happy, despite no reference to such a thing in the cabal file. Within the nix-shell, I am able to run alex and happy directly as executables, as they have been provided by nix.
Question: Does anyone know what I might be able to try to resolve this? I would like to try to provide dependencies completely using nix, instead of using cabal update to download packages from Hackage.
The source code can be found in the branch unhappy here, with files of interest:
package.yaml (for hpack)
aoc.cabal
default.nix
Some things I've tried so far are:
I found a similar-looking error here, but it was not fully resolved, and the nix build there was using haskell.nix.
I've tried the following other build methods while troubleshooting:
Building with cabal/ghc installed through ghcup (cabal 3.2.0.0, ghc 8.10.2): the build succeeds—alex and happy are fetched from Hackage and run successfully as build-tools.
Building with nix-build: the build runs successfully (without packages being fetched to .cabal). callCabal2nix recognizes alex and happy, and provides them successfully to cabal.
Building within nix-shell with cabal update: the same as 1. occurs and it succeeds, as nix's provided cabal fetches the packages from Hackage, but this is not what I'm trying to accomplish.
I've also tried using nix-shell to build a minimal example alex/happy project, using the same generic *.nix files from my own project, with the same errors being produced.
Cabal simply isn't convinced that alex is installed by Nixpkgs' custom Haskell environment (the .env attribute on the package that you correctly use for the shell).
If you run cabal update, cabal-install will be able to install alex and happy the way it wants and continue to build your project.
$ cabal v2-build
[... omitted ...]
[__0] trying: aoc-0.1.0.0 (user goal)
[__1] unknown package: aoc:happy:exe.happy (dependency of aoc)
[__1] fail (backjumping, conflict set: aoc, aoc:happy:exe.happy)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: aoc, aoc:happy:exe.happy
$ cabal update
Downloading the latest package list from hackage.haskell.org
$ cabal v2-build
Resolving dependencies...
Build profile: -w ghc-8.10.2 -O1
In order, the following will be built (use -v for more details):
- alex-3.2.6 (exe:alex) (requires download & build)
- happy-1.20.0 (exe:happy) (requires download & build)
- aoc-0.1.0.0 (lib) (configuration changed)
- aoc-0.1.0.0 (exe:aoc) (dependency rebuilt)
Downloading happy-1.20.0
[... omitted ...]
Configuring library for aoc-0.1.0.0..
Preprocessing library for aoc-0.1.0.0..
Building library for aoc-0.1.0.0..
[... omitted ...]
According to the Cabal build-tools documentation the field has been deprecated and removed. It seems like you'll be better off with build-tool-depends.
build-tool-depends:
alex:alex >=3.2.5 && <3.3
, happy:happy >=1.20.0 && <1.21

Cabal cannot find locally sourced (yet correctly installed) packages

I recently upgraded to Cabal 3.2 (and GHC 8.10) and I am running into some major issues that make some of my project non-buildable anymore...
Thorough description of the problem
Here is a minimal (not) working configuration that fails every time:
I start off with a clean Cabal configuration (by deleting ~/.cabal); the reason for that will appear later in the post. I run cabal update to recreate the .cabal directory and to ensure Cabal is working.
I create a project (let's call it test1) using cabal init. This is a library project with one exposed module (conveniently named Test1) that exports some dummy function foo. I run cabal build, then cabal install --lib; everything is running smooth, so far so good.
Just to be sure, I leave the project directory and fire up GHCi. I type in :m Test1 to load the module I created earlier, and it works! I can type in foo ... and see my function executed. Also, I list the content of ~/.cabal/store/ghc-8.10.xxx and see that the test1-xxx directory is there.
I then create a new project, test2, still using cabal init. This time, I configure it to be an executable, and I add test1 as a dependency (using the build-depends field). But this time when I run cabal build, I run into some issue:
~/projects/haskell/test2> cabal build
Resolving dependencies...
cabal: Could not resolve dependencies:
[__0] trying: test2-0.1.0.0 (user goal)
[__1] unknown package: test1 (dependency of test2)
[__1] fail (backjumping, conflict set: test1, test2)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: test2, test1
It seems to me like package test1 cannot be found, however I can access it from GHCi (and GHC for that matters) and it is present in ~/.cabal/store...
But unfortunately there is more.
I create a third project, test3. This is a library, and it depends on nothing else than base (so in particular it does not depend on test1). The lib exposes one module, Test3, with one function exported, bar. I run cabal build, no problem here. But when I want to install test3 with cabal install --lib I run into some errors:
~/projects/haskell/test3> cabal install --lib
Wrote tarball sdist to
/home/<user>/projects/haskell/test3/dist-newstyle/sdist/test3-0.1.0.0.tar.gz
Resolving dependencies...
cabal: Could not resolve dependencies:
[__0] unknown package: test1 (user goal)
[__0] fail (backjumping, conflict set: test1)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: test1
It seems that it cannot find test1, although it has been installed correctly; may be this is a remnant of the failed build of test2 though...
Just to be sure, I fire up GHCi and type in :m Test3, but GHCi tells me that it cannot find module Test3 (and even suggests this is a typo and I was meaning Test1), showing that test3 indeed did not get installed, although it got successfully built...
Okay there is one more quirk to this whole situation: I create once again a new project with cabal init, called test4, which is an executable that (again) depends on nothing else than base. I keep the default Main.hs (that just prints "Hello, Haskell!"). I run cabal build: no problem. Then I run cabal install and... No problem either? I run test4 in a random location and it fires up the executable, printing "Hello, Haskell!" in the terminal...
And there is one last thing: I go to some random location and I run cabal install xxx --lib where xxx is a library package available on Hackage (for example xml) and:
~> cabal install xml --lib
Resolving dependencies...
cabal: Could not resolve dependencies:
[__0] unknown package: test1 (user goal)
[__0] fail (backjumping, conflict set: test1)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: test1
This is the reason why I need to nuke .cabal regularly... Right now I seem to be in some kind of stale state where I cannot install any library anymore.
Technical configuration and notes
I am running Cabal 3.2.0.0 and GHC 8.10.0.20200123. I installed them from the hvr/ghc PPA, and I made sure there are no other versions of those tools anywhere on my computer.
Just as a note, I am running Ubuntu 18.04.4 LTS (with XFCE so XUbuntu to be exact). Everything else (seem to be like it) is up to date.
Last thing, regarding the *.cabal files I use for building, they are pretty much the ones generated by cabal init, except I switch executable xxx for library in the case of libraries, and I simply add a exposed-modules field for exposing modules for the libraries (so Test1 for test1 and Test3 for test3 respectively). I also use build-depends in test2 to make the project depend on test1. Apart from that, they are pretty much left untouched.
Notes and thoughts
I must confess that I am new to Cabal 3; until last week I was using Cabal 1 (because I never bothered to update it; yes I know this is bad). With Cabal 1 I did not have any problem whatsoever, and I was perfectly able to install a package from local sources and depend on it in other projects...
I feel like I am doing something wrong; maybe am I not using the correct Cabal commands? I saw somewhere something about cabal new-build and cabal new-install but it does not seem to do anything more than cabal build and cabal install, at least in my case. I also wanted to investigate sandboxes but it seems that has disappeared since version 2 of Cabal.
There is also a slight possibility this is a Cabal bug, but I don't find any relevant issue on the bug tracker that may be related to my problem...
What do you think about this? What am I doing wrong? Do you see any alternative or possible fix?
Thanks a lot!
GHC environment files
A GHC installation comes with a certain number of packages out-of-the box. base is one of them but there are others, for example text. If you install GHC alone (no cabal or stack) and open ghci, it should let you import Data.Text without problems.
What if you want GHC or ghci to be aware of other compiled packages present in your filesystem? You can point GHC to additional package databases using command-line flags, but there's also the concept of package environment files.
Environments are plain text files that contain a list of package-related GHC flags. There might be a global environment at ~/.ghc/$ARCH-$OS-$GHCVER/environments/default, and there might also exist local environments which only affect GHC and ghci commands invoked inside the same folder. The exact rules for search are described in the GHC User Guide.
What does cabal install --lib actually do?
By default, it modifies the global environment file, so that GHC and ghci can now find that library. That's why point 3) worked. The actual compiled binaries of the library still reside in the cabal store though.
We can also create local environment files. For example cabal install sop-core --lib --package-env . will create the environment file .ghc.environment.xxx in the current folder, and the library will be available to ghc and ghci when they are invoked there.
Why isn't test1 available for test2?
Modern cabal makes a distinction between local packages and external packages.
local packages is the set of packages you are developing together in a project, being edited, recompiled and changed repeatedly. They are built "inplace" and not seen outside the project. They can depend on each other.
external packages are dependencies from build-depends: whose source code is downloaded from a package repository and which, when compiled, are put in the cabal store so that other Cabal projects might make use of them without re-compiling.
The list of local packages and other project-level configuration details are specified in a cabal.project file. But you don't need one if you work on a single isolated package; the default list of packages is simply ./*.cabal.
cabal wants to completely control the build environment of local packages, and will ignore the global environment file. In your case, you'll have to make test1 and test2 local packages in the same project (likely the best option) or publish test1 and treat it as an external package.
Note that "cabal project" is a concept relevant only during development. Packages are published independently, there are no "projects" in Hackage or other repositories, just packages.
What if I want to treat test1 as external without publishing it to Hackage?
You will have to set up a local package repository, basically a non-public Hackage.
You can tell Cabal about additional package repositories in the Cabal configuration file, that is, the file that configures cabal itself. Its location is given in the last line of cabal --help.
But how to set up the repository? The hackage-repo-tool can help with that.
Why did test3 fail? Why did further library installs fail?
That's weird, I have no idea why that happens. Did you by perchance delete the ~/.cabal folder between steps 3) and 5) ? What happens if you delete the global GHC environment file and try again?

cabal sandbox hell: can not resolve depdencies

I'm trying to build my package using a sandbox. Without it, it compiles and works like a charm. Once I introduce a sandbox though cabal says it can't resolve dependencies. To my eyes these conflicts do not look like conflicts though.
The project structure is as follows:
application (depends on library-base, library-impl1 and library-impl2)
library
├ library-base
├ library-impl1 (depends on library-base)
└ library-impl2 (depends on library-base)
These are the commands I ran in that order
rm -rf ~/.cabal
rm -rf ~/.ghc
cabal update
rm -f cabal.sandbox.config
rm -rf .cabal-sandbox
cabal sandbox init
cabal sandbox add-source $LIB_HOME/library-base
cabal sandbox add-source $LIB_HOME/library-impl1
cabal sandbox add-source $LIB_HOME/library-impl2
cabal install --only-dependencies --force-reinstalls && cabal build
cabal install --only-dependencies --force-reinstalls produces the following output:
Resolving dependencies...
cabal: Could not resolve dependencies:
next goal: lens (dependency of library-base-0.1.0.0)
rejecting: lens-4.15.4/installed-I5C... (conflict: bifunctors==5.4.2, lens =>
bifunctors==5.4.2/installed-Hs7...)
trying: lens-4.15.4
trying: unordered-containers-0.2.8.0/installed-1tq... (dependency of
lens-4.15.4)
next goal: text (dependency of lens-4.15.4)
rejecting: text-1.2.2.2/installed-3EN... (conflict: binary==0.8.5.1, text =>
binary==0.8.3.0/installed-0.8...)
trying: text-1.2.2.2
next goal: hashable (dependency of lens-4.15.4)
rejecting: hashable-1.2.6.1/installed-2nP... (conflict: text==1.2.2.2,
hashable => text==1.2.2.2/installed-3EN...)
rejecting: hashable-1.2.6.1, hashable-1.2.6.0, hashable-1.2.5.0,
hashable-1.2.4.0, hashable-1.2.3.3, hashable-1.2.3.2, hashable-1.2.3.1,
hashable-1.2.3.0, hashable-1.2.2.0, hashable-1.2.1.0, hashable-1.2.0.10,
hashable-1.2.0.9, hashable-1.2.0.8, hashable-1.2.0.7, hashable-1.2.0.6,
hashable-1.2.0.5, hashable-1.2.0.4, hashable-1.2.0.3, hashable-1.2.0.2,
hashable-1.2.0.1, hashable-1.2.0.0, hashable-1.1.2.5, hashable-1.1.2.4,
hashable-1.1.2.3, hashable-1.1.2.2, hashable-1.1.2.1, hashable-1.1.2.0,
hashable-1.1.1.0, hashable-1.1.0.0, hashable-1.0.1.1, hashable-1.0.1.0,
hashable-1.0.0 (conflict: unordered-containers =>
hashable==1.2.6.1/installed-2nP...)
Dependency tree exhaustively searched.
Does anyone have an idea what is going on here?
First I will give an explanation of what the error message says. Then I will attempt to make some guesses about why you have the error. Then I will propose some next steps.
The error says:
Maybe version 4.15.4 of lens will work.
Maybe the installed version 0.2.8.0 of unordered-containers will satisfy lens' dependency on unordered-containers.
Maybe the installed version 1.2.2.2 of text will satisfy lens' dependency on text.
Crap. You asked for version 0.8.5.1 of binary, but the installed version of text was built against version 0.8.3.0. I have to rebuild text.
Maybe the installed version 1.2.6.1 version of hashable will satisfy lens' dependency on hashable.
Crap. We're rebuilding text, a dependency of hashable. I have to rebuild hashable.
Double crap. We already committed to using the installed version of unordered-containers, which depends on the installed version of hashable, which prevents us from rebuilding hashable.
(...and I tried a bunch of other stuff that didn't work, too, but I'm not telling you what, nya nya nya)
Normally sandboxes ignore local package databases, so this suggests to me that where it is talking about "installed versions" above it is either picking these up from your global package database or from your existing sandbox. You claim that you have just created this sandbox and run this cabal install command immediately. If this is true (is it? or is this a second run of the tool? why do you have --force-reinstalls?), it cannot be picking the installed versions from your sandbox, and therefore must be picking them up from your global package database. Installing things to the global package database is generally considered a Bad Idea, because it's much more difficult to correctly clear out a cluttered/broken global package database. Take it under future advisement.
Now, to make progress, I would try one of these two things:
The only part of the above error explanation that you have control over is the "You asked for version 0.8.5.1 of binary" part. Consider relaxing your version constraints on binary to accept the already-installed version 0.8.3.0.
You can often get significantly better error messages out of cabal by cutting down on its search space; because it only prints a part of the search space in its error, you sometimes need to guide it to the problematic part of the space so that it will show you the real problem in its error. If you're pretty sure the installed versions of unordered-containers et al are a good match for your library, consider
cabal install --only-dependencies --constraint 'unordered-containers installed' --constraint 'binary installed'
and so on for any other packages it mentions trying to rebuild that you don't want it to rebuild. Alternately you can put exact version constraints in the --constraint if you don't want one of the installed versions. Don't include --force-reinstalls, basically ever.

Hackage name collision while using stack solver with extra-deps

Well it turns out that my app name is the same as one of the packages that is uploaded to hackage, so when I try to resolver extra dependencies using stack solver --resolver lts 7.12, I get the following error:
$ stack solver --resolver lts-7.12
Using configuration file: stack.yaml
Using cabal packages:
- html-parse.cabal
Using resolver: lts-7.12
Using compiler: ghc-8.0.1
Asking cabal to calculate a build plan...
Trying with packages from lts-7.12 as hard constraints...
Attempt failed.
>>>> Cabal errors begin
cabal.exe: Could not resolve dependencies:
next goal: html-parse (user goal)
rejecting: html-parse-0.2.0.0, 0.1.0.0 (global constraint requires ==0.0.0.3)
trying: html-parse-0.0.0.3
next goal: hunit (dependency of html-parse-0.0.0.3)
Dependency tree exhaustively searched.
<<<< Cabal errors end
Could not parse cabal-install errors:
>>>> Cabal errors begin
cabal.exe: Could not resolve dependencies:
next goal: html-parse (user goal)
rejecting: html-parse-0.2.0.0, 0.1.0.0 (global constraint requires ==0.0.0.3)
trying: html-parse-0.0.0.3
next goal: hunit (dependency of html-parse-0.0.0.3)
Dependency tree exhaustively searched.
<<<< Cabal errors end
My app/package name in .cabal file is html-parse and the current version is 0.0.0.3. It looks like my own package is listed as a dependency with a constraint of ==0.0.0.3, but there is another pacakge on hackage that has the same name but different versions.
Can I somehow solve this issue without renaming my own app?
Quoting the Cabal user guide (emphasis mine):
Package names and versions
All packages have a name, e.g. “HUnit”. Package names are assumed to be unique. Cabal package names can use letters, numbers and hyphens, but not spaces. The namespace for Cabal packages is flat, not hierarchical.
Accordingly, the Cabal library doesn't have a feature for handling package name conflicts, and neither do cabal-install nor stack. That being so, you will have to rename your package.
P.S.: I am deliberately not considering seriously the possibility of setting up your project to use a private Hackage that excludes the homonymous package, both because I don't know how it would play out in practice and because it is vastly more trouble than it is worth.

Polyparse library cannot be installed

I'm having a trouble on installing Polyparse library (Haskell library)
And i do not know how to solve it ....
May someone helps me,please ?
This is the error output :
D-MacBook-Pro:polyparse-1.9 d$ cabal install polyparse.cabal
Resolving dependencies...
Configuring polyparse-1.9...
Failed to install polyparse-1.9
Last 10 lines of the build log ( /Users/d/.cabal/logs/polyparse-1.9.log ):
cabal: /Users/d/.cabal/logs/polyparse-1.9.log: does not exist
The problem now ...
Resolving dependencies...
cabal: Could not resolve dependencies:
trying: bpsat-0.1.0 (user goal)
trying: smt-lib-0.0.3/installed-d94... (dependency of bpsat-0.1.0)
next goal: polyparse (dependency of smt-lib-0.0.3/installed-d94...)
rejecting: polyparse-1.9/installed-42c... (conflict: polyparse =>
text==1.1.1.2/installed-cb1..., bpsat => text==0.11.*)
rejecting: polyparse-1.9, 1.8, 1.7, 1.6, 1.5, 1.4.1, 1.4, 1.3, 1.2, 1.1, 1.0
(conflict: smt-lib => polyparse==1.9/installed-42c...)
Dependency tree exhaustively searched.
I just tried to install polyparse on my Ubuntu machine, and it worked....
Here is how I usually fix installation problems.
$ cabal update
$ cabal unpack polyparse
$ cd polyparse-*
$ cabal configure
Now look for errors.... Dependency errors usually appear at this point. They come in two forms- Either 1). for some reason another cabal package is missing, and you can usually install it by doing the appropriate cabal install <packageName> (yes, cabal was supposed to do this for you, but I find it sometimes doesn't), or 2). A system c-library is missing, and you will have install that. Either way, the message should make it clear. If it doesn't, append the message to your question and we can help.
$ cabal build
Again, look for errors. Build errors often appear here, and usually indicate a bug in the package. Since the install just worked for me, this is less likely, but I've seen stuff that installs on one OS and breaks on another. Again, you can put the message here and we can help.
$ cabal install
If this works, the package should be installed.
update
It looks like the dependency smt-lib isn't installing.... Try to repeat the steps above on that lib, and repost the results.
Update 2-
The new error message looks to be telling me there is a conflict in the Text lib, bpsat needs one version and polyparse needs another. I am not sure why this is happening, as I mentioned, for me things worked. Sometimes things in ~/.cabal get messed up, and you might want to try to delete (well, actually, move it in case you decide you need it) everything in .cabal except ~/.cabal/bin/. Then try again. You will probably have to reinstall other libs, but this might solve the problem.

Resources