Cabal Package Installation Woes

tl;dr: Nuke ~/.ghc and then run cabal install --lib (every lib you need)

Edit: Since writing this post, there’s been some movement on the cabal bug, and it seems like there’s soon going to be a fix!

I’m trying to write a simple webserver based on Warp, but I ran into an issue with a hidden package. Here’s my imports in Server.hs:

{-# LANGUAGE OverloadedStrings #-}
import Network.Wai (Application, Response, rawPathInfo, responseFile, responseLBS)
import Network.HTTP.Types (status200, status404)
import Network.Wai.Handler.Warp (run)

And here’s the relevant part of my .cabal file:

executable server
  main-is: Server.hs
  build-depends:
    base >=4.12 && <4.13
    , wai
    , warp
  default-language:    Haskell2010

Note that http-types is missing, but we’ll come back to that at the end.

I’ll start by saying that I don’t fully understand the difference between cabal and stack, and at the beginning I decided to just use cabal and not worry about stack.

I ran cabal install wai warp and got the following error:

Resolving dependencies...
cabal: Cannot build the executables in the package wai because it does not
contain any executables. Check the .cabal file for the package and make sure
that it properly declares the components that you expect.
Cannot build the executables in the package warp because it does not contain
any executables. Check the .cabal file for the package and make sure that it
properly declares the components that you expect.

It turns out the solution to this is to append --lib and run cabal install --lib wai warp. (I wish it would say that in the warning though.)

I ran cabal install wai warp --lib and tried running Server.hs by pressing command+b in Sublime Text 3, but I ran into this error:

Could not load module ‘Network.HTTP.Types’
    It is a member of the hidden package ‘http-types-0.12.3’.
    You can run ‘:set -package http-types’ to expose it.
    (Note: this unloads all the modules in the current scope.)
    Use -v to see a list of the files searched for.

I think what’s happening here is that http-types is installed, but not explicitly. Haskell wants me to definitely say that I want it, so I try running cabal install --lib http-types.

This, however, runs into a very frustrating error. Apparently the process library is required at two different versions in two different packages – despite already being happily installed as an indirect dependency:

cabal: Could not resolve dependencies:
[__0] trying: base-4.12.0.0/installed-4.1... (user goal)
[__1] trying: ghc-8.6.5/installed-8.6... (user goal)
[__2] next goal: process (user goal)
[__2] rejecting: process-1.6.8.2, process-1.6.8.1, process-1.6.8.0 (constraint
from user target requires ==1.6.7.0)
[__2] rejecting: process-1.6.7.0 (conflict: ghc =>
process==1.6.5.0/installed-1.6...)
[__2] rejecting: process-1.6.6.0, process-1.6.5.1,
process-1.6.5.0/installed-1.6..., process-1.6.5.0, process-1.6.4.0,
process-1.6.3.0, process-1.6.2.0, process-1.6.1.0, process-1.6.0.0,
process-1.5.0.0, process-1.4.3.0, process-1.4.2.0, process-1.4.1.0,
process-1.4.0.0, process-1.3.0.0, process-1.2.3.0, process-1.2.2.0,
process-1.2.1.0, process-1.2.0.0, process-1.1.0.2, process-1.1.0.1,
process-1.1.0.0, process-1.0.1.5, process-1.0.1.4, process-1.0.1.3,
process-1.0.1.2, process-1.0.1.1, process-1.0.0.0 (constraint from user target
requires ==1.6.7.0)
[__2] fail (backjumping, conflict set: ghc, process)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: process, base, ghc

The solution to this is very frustrating, because even rolling back my git repo to the last known good commit didn’t fix it – it’s a global system problem (ironic, for Haskell, which is so demanding of “pureness” in the language). I deleted ~/.ghc and ran the install again:

rm -rf ~/.ghc && cabal install --lib wai warp http-types

And it worked! My server runs 🙂

The problem is now, I want to build some tests, so I run cabal install --lib hspec and I run into the same “could not resolve dependencies” as above!

Hm, let’s see if just a rm -rf ~/.ghc && cabal install will fix it, if I declare hspec in build-depends in my .cabal file? I get the following error:

cabal: Path '/Users/erty/.cabal/bin/server' already exists. Use
--overwrite-policy=always to overwrite.

So let’s try the suggestion and run --overwrite-policy=always. Infuriatingly, this build succeeds but when I try to actually run Server.hs (by pressing cmd+b in Sublime Text, perhaps that’s missing a flag or something? I wonder if cabal install builds a binary but fails to install the libraries) it fails to find any of my modules:

Could not find module ‘Network.Wai’
Could not find module ‘Network.HTTP.Types’
Could not find module ‘Network.Wai.Handler.Warp’

Let’s try rm -rf ~/.ghc && cabal install --lib, since adding --lib worked before. First, I also added http-types to my build-depends in the .cabal file. Nope:

Resolving dependencies...
cabal: Cannot build the libraries in the package crossword-hs because it does
not contain any libraries. Check the .cabal file for the package and make sure
that it properly declares the components that you expect.

But! We were able to get it working by listing all of the dependencies explicitly during the install phase. So let’s try that and run rm -rf ~/.ghc && cabal install --lib wai warp http-types hspec:

Works! The problem is that I have to remove ~/.ghc manually list out all of my deps every time I want to install something, but at least I can move forward for now.

I also added http-types to my cabal file, but it didn’t seem to really matter for running in sublime text, as long as I’d installed it via cabal install --lib.

I would love to hear from any more experienced haskellers out there if I’m not understanding something about cabal. Specifically, coming from node, I feel like cabal install (or even with --lib should “just work” and install all of the deps I’ve listed in the .cabal file.

Hopefully this writeup saves someone else time 🙂

Leave a Reply

Your email address will not be published.

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.