cabal-lenses-0.1: lib/CabalLenses/CondVars.hs
{-# Language TemplateHaskell, PatternGuards #-}
module CabalLenses.CondVars
( CondVars(..)
, fromDefaults
, enableFlag
, disableFlag
, eval
) where
import qualified Distribution.PackageDescription as PD
import Distribution.PackageDescription (Condition(..))
import qualified Distribution.System as S
import Distribution.System (OS(..), Arch(..))
import Distribution.Compiler (CompilerFlavor(..), buildCompilerFlavor)
import Distribution.Version (Version(..), withinRange)
import qualified Data.HashMap.Strict as HM
import Control.Lens
type FlagName = String
type FlagMap = HM.HashMap FlagName Bool
-- | The variables that are used to resolve the conditionals inside of the cabal file.
-- Holds the enable state of the cabal flags, the used OS, ARCH, CompilerFlavor and
-- compiler version.
data CondVars = CondVars
{ flags :: FlagMap -- ^ the enable state of the flags, initialized with the default flag values in the cabal file
, os :: OS -- ^ the used OS, by default the one cabal was build on
, arch :: Arch -- ^ the used ARCH, by default the one cabal was build on
, compilerFlavor :: CompilerFlavor -- ^ the used CompilerFlavor, by default the one cabal was build on
, compilerVersion :: Maybe Version -- ^ the user specified compiler version
} deriving (Show)
makeLensesFor [ ("flags", "flagsL")
] ''CondVars
-- | Create a 'CondVars' from the default flags of the cabal package description.
-- The 'os', 'arch' and 'compilerFlavor' fields are initialized by the ones the cabal library was build on.
fromDefaults :: PD.GenericPackageDescription -> CondVars
fromDefaults pkgDescrp = CondVars { flags = flags
, os = S.buildOS
, arch = S.buildArch
, compilerFlavor = buildCompilerFlavor
, compilerVersion = Nothing
}
where
flags = HM.fromList $ map nameWithDflt (PD.genPackageFlags pkgDescrp)
nameWithDflt PD.MkFlag { PD.flagName = PD.FlagName name, PD.flagDefault = dflt } =
(name, dflt)
-- | Enable the given flag in 'CondVars'.
enableFlag :: FlagName -> CondVars -> CondVars
enableFlag flag condVars =
condVars & flagsL %~ HM.insert flag True
-- | Disable the given flag in 'CondVars'.
disableFlag :: FlagName -> CondVars -> CondVars
disableFlag flag condVars =
condVars & flagsL %~ HM.insert flag False
-- | Evaluate the 'Condition' using the 'CondVars'.
eval :: CondVars -> Condition PD.ConfVar -> Bool
eval condVars = eval'
where
eval' (Var var) = hasVar var
eval' (Lit val) = val
eval' (CNot c) = not $ eval' c
eval' (COr c1 c2) = eval' c1 || eval' c2
eval' (CAnd c1 c2) = eval' c1 && eval' c2
hasVar (PD.OS osVar) = osVar == os condVars
hasVar (PD.Arch archVar) = archVar == arch condVars
hasVar (PD.Impl cflavor vrange)
| Just version <- compilerVersion condVars
= cflavor == compilerFlavor condVars && version `withinRange` vrange
| otherwise
= cflavor == compilerFlavor condVars
hasVar (PD.Flag (PD.FlagName name))
| Just v <- HM.lookup name (flags condVars)
= v
| otherwise
= False