Depending on a package only if another package is at a particular version

One of aeson-2.2's breaking changes was moving the Data.Aeson.Parser module out into a new attoparsec-aeson package. I have some code that uses this module, and I’m not sure how best to continue supporting versions <2.2 and start supporting versions >=2.2.

attoparsec-aeson depends on aeson >=2.2.0.0, so I can’t add a new dependency on attoparsec-aeson and then import the module with a package-qualified import from attoparsec-aeson instead of aeson.

It would seem I’d need some conditional in the cabal file that only adds attoparsec-aeson as a dep if aeson is >=2.2. Reading this section in the cabal manual (in particular the backtracking search bit) suggests that a configuration flag might work, though that feels like it’d be a somewhat indirect/ad-hoc approach.

Is a configuration flag the standard way of handling this or is there a better way?

Yes, as long as the flag is not set to manual, the cabal solver may switch flags while trying to find a build plan. It will first try the default values though.

So something like:

flag old-aeson
  description: Allow aeson versions lower than 2.2
  manual: False
  default: False

library
  [ ... ]
  if flag(old-aeson)
    build-depends:
      aeson < 2.2.0.0
  else
    build-depends:
        attoparsec-aeson ^>=2.2.0.0
      , aeson ^>=2.2.0.0

The problem with this is that flags have no convention… so every package might define them slightly different (e.g. different name or indeed set to manual) and it’s going to be a nightmare to globally make something work across the 2.2 boundaries.

3 Likes

In this case you’d actually prefer Cabal to switch this flag automatically, depending on whether external circumstances allow aeson-2.2 or not.

See also Version of `attoparsec-aeson` for older `aeson` versions · Issue #1048 · haskell/aeson · GitHub

2 Likes

Thanks all - got the flag approach working. @Bodigrim, the linked issue sounds like the way to go in the long run.