cabal icon indicating copy to clipboard operation
cabal copied to clipboard

Make value of Cabal flags accessible through an autogenerated Haskell module

Open amigalemming opened this issue 2 months ago • 5 comments

Say, I have mypkg.cabal containing:

Flag special
  Description: Extra feature for you

It would nice if Cabal would create a file, say Flag_mypkg.hs, that I can use like so:

import qualified Flag_mypkg

main :: IO ()
main =
   if Flag_mypkg.special
   then putStrLn "special"
   else putStrLn "normal"

amigalemming avatar Oct 18 '25 08:10 amigalemming

This has been considered in the past, but I think the conventional solution has been to conditionally use ghc-options: -DSOMEMACRO and LANGUAGE CPP.

geekosaur avatar Oct 18 '25 15:10 geekosaur

I dislike CPP so, on the surface, I think it's a great feature request. @geekosaur do you have any links to pay discussions? They could change my mind...

ulysses4ever avatar Oct 18 '25 15:10 ulysses4ever

Not off the top of my head. But the rationale I recall is that flags are not supposed to change functionality, they're supposed to govern alternative solver paths (for example, back when things were removed from base to separate packages, they allowed compatibility with both arrangements; look for flag old-base on Hackage for some examples); and the reason to use CPP is that those paths may require alternative imports, which can't be done any other way.

geekosaur avatar Oct 18 '25 15:10 geekosaur

I try to avoid CPP in my projects because CPP changes syntax (e.g. interpretation of hash symbol) and may lead to mysterious syntax errors if you happen to use a token somewhere in your Haskell code that clashes with a CPP macro name. Usually I switch between different module implementations using

If flag(special)
  Hs-Source-Dirs: src/special
Else
  Hs-Source-Dirs: src/normal

In my actual case I want to enable some debug functionality. That is, yes functionality changes, but not for production code, not in a way that hurts other packages that import mypkg. For now I will use CPP workaround. I can limit the effects of CPP to one module by writing a module that translates a CPP macro to a Haskell Bool value and import that module from non-CPP modules.

amigalemming avatar Oct 18 '25 19:10 amigalemming

In practice, flags used for many things, not just imports. The fact that Cabal twists user's elbow into using CPP where a mere Bool could do is horrible. Every other year GHC Implementors workshop has a talk how to buy our way out of CPP, so it seems to me that the broad agreement is that we should strive to lower CPP involvement.

ulysses4ever avatar Oct 22 '25 00:10 ulysses4ever