I’ve previously written about my annoyance with Hackage packages that have compulsory testing dependencies (note that I’ve since modified my position from that post, as noted by the presence of optional testing modules for graphviz). However, the situation is definitely getting better: even my old bugbear hmatrix has made the testing dependencies and modules optional by using a Cabal flag of
However, several package maintainers seem to be unaware of a minor subtlety of how Cabal parses dependencies.
Let us consider a simple example: we have a package
foo which is primarily a library but also contains a testing executable which uses QuickCheck. The relevant parts of the
.cabal file look something like this:
... Flag test Description: Build the test suite, including an executable to run it. Default: False Library Build-Depends: base == 4.*, containers == 0.3.* Exposed-Modules: Data.Foo Executable foo-tester if flag(test) Buildable: True else Buildable: False Main-Is: FooTester.hs Build-Depends: QuickCheck >= 2.1 && < 2.1.2
So, we have an optional testing executable called
foo-tester and bonus points for defaulting the testing of this executable to
However, this doesn’t quite behave as expected: if we try to build it as-is without enabling the
test flag, then Cabal will still make
foo depend upon
QuickCheck. Why? Because the dependency is not optional (I’m not saying that this behaviour is correct, just that this is how Cabal acts). This became noticeable when QuickCheck-2.2 came out, I upgraded to it and then
ghc-pkg check complained that some packages were now broken.
I’ve pointed out the correct way of doing this to individual maintainers in the past when I noticed it in their packages; now I’m doing it in this blog post in the hope that maintainers of all affected packages will remedy this. To ensure that testing dependencies are only considered when we are indeed building the testing executable, just shift it inside the if-statement:
... Executable foo-tester if flag(test) Buildable: True Build-Depends: QuickCheck >= 2.1 && < 2.1.2 else Buildable: False Main-Is: FooTester.hs
QuickCheck will only be brought in when you’re building tests.
This doesn’t also apply to testing executables, but to any conditional dependencies. See for example how I have testing modules built and exported in graphviz’s