-- -fno-warn-deprecations for use of Map.foldWithKey
{-# OPTIONS_GHC -fno-warn-deprecations #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  Distribution.PackageDescription.Configuration
-- Copyright   :  Thomas Schilling, 2007
-- License     :  BSD3
--
-- Maintainer  :  cabal-devel@haskell.org
-- Portability :  portable
--
-- This is about the cabal configurations feature. It exports
-- 'finalizePD' and 'flattenPackageDescription' which are
-- functions for converting 'GenericPackageDescription's down to
-- 'PackageDescription's. It has code for working with the tree of conditions
-- and resolving or flattening conditions.

module Distribution.PackageDescription.Configuration (
    finalizePD,
    flattenPackageDescription,

    -- Utils
    parseCondition,
    freeVars,
    extractCondition,
    extractConditions,
    addBuildableCondition,
    mapCondTree,
    mapTreeData,
    mapTreeConds,
    mapTreeConstrs,
    transformAllBuildInfos,
    transformAllBuildDepends,
    transformAllBuildDependsN,
    simplifyWithSysParams
  ) where

import Distribution.Compat.Prelude
import Prelude ()

-- lens
import qualified Distribution.Types.BuildInfo.Lens                 as L
import qualified Distribution.Types.GenericPackageDescription.Lens as L
import qualified Distribution.Types.PackageDescription.Lens        as L
import qualified Distribution.Types.SetupBuildInfo.Lens            as L

import           Distribution.Compat.CharParsing             hiding (char)
import qualified Distribution.Compat.CharParsing             as P
import           Distribution.Compat.Lens
import           Distribution.Compiler
import           Distribution.PackageDescription
import           Distribution.PackageDescription.Utils
import           Distribution.Parsec
import           Distribution.Pretty
import           Distribution.System
import           Distribution.Types.Component
import Distribution.Utils.Path
import           Distribution.Types.ComponentRequestedSpec
import           Distribution.Types.DependencyMap
import           Distribution.Types.PackageVersionConstraint
import           Distribution.Utils.Generic
import           Distribution.Version

import qualified Data.Map.Lazy as Map
import           Data.Tree     (Tree (Node))

------------------------------------------------------------------------------

-- | Simplify a configuration condition using the OS and arch names.  Returns
--   the names of all the flags occurring in the condition.
simplifyWithSysParams :: OS -> Arch -> CompilerInfo -> Condition ConfVar
                      -> (Condition FlagName, [FlagName])
simplifyWithSysParams :: OS
-> Arch
-> CompilerInfo
-> Condition ConfVar
-> (Condition FlagName, [FlagName])
simplifyWithSysParams OS
os Arch
arch CompilerInfo
cinfo Condition ConfVar
cond = (Condition FlagName
cond', [FlagName]
flags)
  where
    (Condition FlagName
cond', [FlagName]
flags) = forall c d.
Condition c -> (c -> Either d Bool) -> (Condition d, [d])
simplifyCondition Condition ConfVar
cond ConfVar -> Either FlagName Bool
interp
    interp :: ConfVar -> Either FlagName Bool
interp (OS OS
os')    = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ OS
os' forall a. Eq a => a -> a -> Bool
== OS
os
    interp (Arch Arch
arch') = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ Arch
arch' forall a. Eq a => a -> a -> Bool
== Arch
arch
    interp (Impl CompilerFlavor
comp VersionRange
vr)
      | CompilerId -> Bool
matchImpl (CompilerInfo -> CompilerId
compilerInfoId CompilerInfo
cinfo) = forall a b. b -> Either a b
Right Bool
True
      | Bool
otherwise = case CompilerInfo -> Maybe [CompilerId]
compilerInfoCompat CompilerInfo
cinfo of
          -- fixme: treat Nothing as unknown, rather than empty list once we
          --        support partial resolution of system parameters
          Maybe [CompilerId]
Nothing     -> forall a b. b -> Either a b
Right Bool
False
          Just [CompilerId]
compat -> forall a b. b -> Either a b
Right (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any CompilerId -> Bool
matchImpl [CompilerId]
compat)
          where
            matchImpl :: CompilerId -> Bool
matchImpl (CompilerId CompilerFlavor
c Version
v) = CompilerFlavor
comp forall a. Eq a => a -> a -> Bool
== CompilerFlavor
c Bool -> Bool -> Bool
&& Version
v Version -> VersionRange -> Bool
`withinRange` VersionRange
vr
    interp (PackageFlag FlagName
f) = forall a b. a -> Either a b
Left FlagName
f

-- TODO: Add instances and check
--
-- prop_sC_idempotent cond a o = cond' == cond''
--   where
--     cond'  = simplifyCondition cond a o
--     cond'' = simplifyCondition cond' a o
--
-- prop_sC_noLits cond a o = isLit res || not (hasLits res)
--   where
--     res = simplifyCondition cond a o
--     hasLits (Lit _) = True
--     hasLits (CNot c) = hasLits c
--     hasLits (COr l r) = hasLits l || hasLits r
--     hasLits (CAnd l r) = hasLits l || hasLits r
--     hasLits _ = False
--

-- | Parse a configuration condition from a string.
parseCondition :: CabalParsing m => m (Condition ConfVar)
parseCondition :: forall (m :: * -> *). CabalParsing m => m (Condition ConfVar)
parseCondition = m (Condition ConfVar)
condOr
  where
    condOr :: m (Condition ConfVar)
condOr   = forall (m :: * -> *) a sep.
Alternative m =>
m a -> m sep -> m (NonEmpty a)
sepByNonEmpty m (Condition ConfVar)
condAnd (String -> m ()
oper String
"||") forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> a -> a) -> NonEmpty a -> a
foldl1 forall c. Condition c -> Condition c -> Condition c
COr
    condAnd :: m (Condition ConfVar)
condAnd  = forall (m :: * -> *) a sep.
Alternative m =>
m a -> m sep -> m (NonEmpty a)
sepByNonEmpty m (Condition ConfVar)
cond (String -> m ()
oper String
"&&")forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> a -> a) -> NonEmpty a -> a
foldl1 forall c. Condition c -> Condition c -> Condition c
CAnd
    -- TODO: try?
    cond :: m (Condition ConfVar)
cond     = m ()
sp forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (forall {c}. m (Condition c)
boolLiteral forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall {a}. m a -> m a
inparens m (Condition ConfVar)
condOr forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m (Condition ConfVar)
notCond forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m (Condition ConfVar)
osCond
                      forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m (Condition ConfVar)
archCond forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m (Condition ConfVar)
flagCond forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m (Condition ConfVar)
implCond )
    inparens :: m a -> m a
inparens   = forall (m :: * -> *) bra ket a.
Applicative m =>
m bra -> m ket -> m a -> m a
between (forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'(' forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m ()
sp) (m ()
sp forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
')' forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m ()
sp)
    notCond :: m (Condition ConfVar)
notCond  = forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'!' forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m ()
sp forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m (Condition ConfVar)
cond forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. Condition c -> Condition c
CNot
    osCond :: m (Condition ConfVar)
osCond   = forall (m :: * -> *). CharParsing m => String -> m String
string String
"os" forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m ()
sp forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall {a}. m a -> m a
inparens m ConfVar
osIdent forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. c -> Condition c
Var
    archCond :: m (Condition ConfVar)
archCond = forall (m :: * -> *). CharParsing m => String -> m String
string String
"arch" forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m ()
sp forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall {a}. m a -> m a
inparens m ConfVar
archIdent forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. c -> Condition c
Var
    flagCond :: m (Condition ConfVar)
flagCond = forall (m :: * -> *). CharParsing m => String -> m String
string String
"flag" forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m ()
sp forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall {a}. m a -> m a
inparens m ConfVar
flagIdent forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. c -> Condition c
Var
    implCond :: m (Condition ConfVar)
implCond = forall (m :: * -> *). CharParsing m => String -> m String
string String
"impl" forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m ()
sp forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall {a}. m a -> m a
inparens m ConfVar
implIdent forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall c. c -> Condition c
Var
    boolLiteral :: m (Condition c)
boolLiteral   = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall c. Bool -> Condition c
Lit  forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
    archIdent :: m ConfVar
archIdent     = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Arch -> ConfVar
Arch forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
    osIdent :: m ConfVar
osIdent       = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap OS -> ConfVar
OS   forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
    flagIdent :: m ConfVar
flagIdent     = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (FlagName -> ConfVar
PackageFlag forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> FlagName
mkFlagName forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
lowercase) (forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m String
munch1 Char -> Bool
isIdentChar)
    isIdentChar :: Char -> Bool
isIdentChar Char
c = Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'_' Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'-'
    oper :: String -> m ()
oper String
s        = m ()
sp forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *). CharParsing m => String -> m String
string String
s forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m ()
sp
    sp :: m ()
sp            = forall (m :: * -> *). CharParsing m => m ()
spaces
    implIdent :: m ConfVar
implIdent     = do CompilerFlavor
i <- forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
                       VersionRange
vr <- m ()
sp forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Alternative m => a -> m a -> m a
option VersionRange
anyVersion forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
                       forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ CompilerFlavor -> VersionRange -> ConfVar
Impl CompilerFlavor
i VersionRange
vr

------------------------------------------------------------------------------

-- | Result of dependency test. Isomorphic to @Maybe d@ but renamed for
--   clarity.
data DepTestRslt d = DepOk | MissingDeps d

instance Semigroup d => Monoid (DepTestRslt d) where
    mempty :: DepTestRslt d
mempty = forall d. DepTestRslt d
DepOk
    mappend :: DepTestRslt d -> DepTestRslt d -> DepTestRslt d
mappend = forall a. Semigroup a => a -> a -> a
(<>)

instance Semigroup d => Semigroup (DepTestRslt d) where
    DepTestRslt d
DepOk <> :: DepTestRslt d -> DepTestRslt d -> DepTestRslt d
<> DepTestRslt d
x     = DepTestRslt d
x
    DepTestRslt d
x     <> DepTestRslt d
DepOk = DepTestRslt d
x
    (MissingDeps d
d) <> (MissingDeps d
d') = forall d. d -> DepTestRslt d
MissingDeps (d
d forall a. Semigroup a => a -> a -> a
<> d
d')


-- | Try to find a flag assignment that satisfies the constraints of all trees.
--
-- Returns either the missing dependencies, or a tuple containing the
-- resulting data, the associated dependencies, and the chosen flag
-- assignments.
--
-- In case of failure, the union of the dependencies that led to backtracking
-- on all branches is returned.
-- [TODO: Could also be specified with a function argument.]
--
-- TODO: The current algorithm is rather naive.  A better approach would be to:
--
-- * Rule out possible paths, by taking a look at the associated dependencies.
--
-- * Infer the required values for the conditions of these paths, and
--   calculate the required domains for the variables used in these
--   conditions.  Then picking a flag assignment would be linear (I guess).
--
-- This would require some sort of SAT solving, though, thus it's not
-- implemented unless we really need it.
--
resolveWithFlags ::
     [(FlagName,[Bool])]
        -- ^ Domain for each flag name, will be tested in order.
  -> ComponentRequestedSpec
  -> OS      -- ^ OS where the installed artifacts will run (host OS)
  -> Arch    -- ^ Arch where the installed artifacts will run (host Arch)
  -> CompilerInfo  -- ^ Compiler information
  -> [PackageVersionConstraint]  -- ^ Additional constraints
  -> [CondTree ConfVar [Dependency] PDTagged]
  -> ([Dependency] -> DepTestRslt [Dependency])  -- ^ Dependency test function.
  -> Either [Dependency] (TargetSet PDTagged, FlagAssignment)
       -- ^ Either the missing dependencies (error case), or a pair of
       -- (set of build targets with dependencies, chosen flag assignments)
resolveWithFlags :: [(FlagName, [Bool])]
-> ComponentRequestedSpec
-> OS
-> Arch
-> CompilerInfo
-> [PackageVersionConstraint]
-> [CondTree ConfVar [Dependency] PDTagged]
-> ([Dependency] -> DepTestRslt [Dependency])
-> Either [Dependency] (TargetSet PDTagged, FlagAssignment)
resolveWithFlags [(FlagName, [Bool])]
dom ComponentRequestedSpec
enabled OS
os Arch
arch CompilerInfo
impl [PackageVersionConstraint]
constrs [CondTree ConfVar [Dependency] PDTagged]
trees [Dependency] -> DepTestRslt [Dependency]
checkDeps =
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a b. a -> Either a b
Left forall b c a. (b -> c) -> (a -> b) -> a -> c
. DepMapUnion -> [Dependency]
fromDepMapUnion) forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ Tree FlagAssignment
-> Either DepMapUnion (TargetSet PDTagged, FlagAssignment)
explore (FlagAssignment -> [(FlagName, [Bool])] -> Tree FlagAssignment
build forall a. Monoid a => a
mempty [(FlagName, [Bool])]
dom)
  where
    -- simplify trees by (partially) evaluating all conditions and converting
    -- dependencies to dependency maps.
    simplifiedTrees :: [CondTree FlagName DependencyMap PDTagged]
    simplifiedTrees :: [CondTree FlagName DependencyMap PDTagged]
simplifiedTrees = forall a b. (a -> b) -> [a] -> [b]
map ( forall c d v a. (c -> d) -> CondTree v c a -> CondTree v d a
mapTreeConstrs [Dependency] -> DependencyMap
toDepMap  -- convert to maps
                          forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall v c.
(Eq v, Monoid c) =>
CondTree v c PDTagged -> CondTree v c PDTagged
addBuildableConditionPDTagged
                          forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall v w c a.
(Condition v -> Condition w) -> CondTree v c a -> CondTree w c a
mapTreeConds (forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. OS
-> Arch
-> CompilerInfo
-> Condition ConfVar
-> (Condition FlagName, [FlagName])
simplifyWithSysParams OS
os Arch
arch CompilerInfo
impl))
                          [CondTree ConfVar [Dependency] PDTagged]
trees

    -- @explore@ searches a tree of assignments, backtracking whenever a flag
    -- introduces a dependency that cannot be satisfied.  If there is no
    -- solution, @explore@ returns the union of all dependencies that caused
    -- it to backtrack.  Since the tree is constructed lazily, we avoid some
    -- computation overhead in the successful case.
    explore :: Tree FlagAssignment
            -> Either DepMapUnion (TargetSet PDTagged, FlagAssignment)
    explore :: Tree FlagAssignment
-> Either DepMapUnion (TargetSet PDTagged, FlagAssignment)
explore (Node FlagAssignment
flags [Tree FlagAssignment]
ts) =
        let targetSet :: TargetSet PDTagged
targetSet = forall a. [(DependencyMap, a)] -> TargetSet a
TargetSet forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a b. (a -> b) -> [a] -> [b]
map [CondTree FlagName DependencyMap PDTagged]
simplifiedTrees forall a b. (a -> b) -> a -> b
$
                -- apply additional constraints to all dependencies
                forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (DependencyMap -> [PackageVersionConstraint] -> DependencyMap
`constrainBy` [PackageVersionConstraint]
constrs) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                forall a d v.
(Semigroup a, Semigroup d) =>
(v -> Either v Bool) -> CondTree v d a -> (d, a)
simplifyCondTree (FlagAssignment -> FlagName -> Either FlagName Bool
env FlagAssignment
flags)
            deps :: DependencyMap
deps = ComponentRequestedSpec -> TargetSet PDTagged -> DependencyMap
overallDependencies ComponentRequestedSpec
enabled TargetSet PDTagged
targetSet
        in case [Dependency] -> DepTestRslt [Dependency]
checkDeps (DependencyMap -> [Dependency]
fromDepMap DependencyMap
deps) of
             DepTestRslt [Dependency]
DepOk | forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Tree FlagAssignment]
ts   -> forall a b. b -> Either a b
Right (TargetSet PDTagged
targetSet, FlagAssignment
flags)
                   | Bool
otherwise -> forall a. [Either DepMapUnion a] -> Either DepMapUnion a
tryAll forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map Tree FlagAssignment
-> Either DepMapUnion (TargetSet PDTagged, FlagAssignment)
explore [Tree FlagAssignment]
ts
             MissingDeps [Dependency]
mds   -> forall a b. a -> Either a b
Left ([Dependency] -> DepMapUnion
toDepMapUnion [Dependency]
mds)

    -- Builds a tree of all possible flag assignments.  Internal nodes
    -- have only partial assignments.
    build :: FlagAssignment -> [(FlagName, [Bool])] -> Tree FlagAssignment
    build :: FlagAssignment -> [(FlagName, [Bool])] -> Tree FlagAssignment
build FlagAssignment
assigned [] = forall a. a -> [Tree a] -> Tree a
Node FlagAssignment
assigned []
    build FlagAssignment
assigned ((FlagName
fn, [Bool]
vals) : [(FlagName, [Bool])]
unassigned) =
        forall a. a -> [Tree a] -> Tree a
Node FlagAssignment
assigned forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (\Bool
v -> FlagAssignment -> [(FlagName, [Bool])] -> Tree FlagAssignment
build (FlagName -> Bool -> FlagAssignment -> FlagAssignment
insertFlagAssignment FlagName
fn Bool
v FlagAssignment
assigned) [(FlagName, [Bool])]
unassigned) [Bool]
vals

    tryAll :: [Either DepMapUnion a] -> Either DepMapUnion a
    tryAll :: forall a. [Either DepMapUnion a] -> Either DepMapUnion a
tryAll = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr forall a.
Either DepMapUnion a
-> Either DepMapUnion a -> Either DepMapUnion a
mp forall a. Either DepMapUnion a
mz

    -- special version of `mplus' for our local purposes
    mp :: Either DepMapUnion a -> Either DepMapUnion a -> Either DepMapUnion a
    mp :: forall a.
Either DepMapUnion a
-> Either DepMapUnion a -> Either DepMapUnion a
mp m :: Either DepMapUnion a
m@(Right a
_) Either DepMapUnion a
_           = Either DepMapUnion a
m
    mp Either DepMapUnion a
_           m :: Either DepMapUnion a
m@(Right a
_) = Either DepMapUnion a
m
    mp (Left DepMapUnion
xs)   (Left DepMapUnion
ys)   = forall a b. a -> Either a b
Left (DepMapUnion
xs forall a. Semigroup a => a -> a -> a
<> DepMapUnion
ys)

    -- `mzero'
    mz :: Either DepMapUnion a
    mz :: forall a. Either DepMapUnion a
mz = forall a b. a -> Either a b
Left (Map PackageName (VersionRange, NonEmptySet LibraryName)
-> DepMapUnion
DepMapUnion forall k a. Map k a
Map.empty)

    env :: FlagAssignment -> FlagName -> Either FlagName Bool
    env :: FlagAssignment -> FlagName -> Either FlagName Bool
env FlagAssignment
flags FlagName
flag = (forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall a b. a -> Either a b
Left FlagName
flag) forall a b. b -> Either a b
Right forall b c a. (b -> c) -> (a -> b) -> a -> c
. FlagName -> FlagAssignment -> Maybe Bool
lookupFlagAssignment FlagName
flag) FlagAssignment
flags

-- | Transforms a 'CondTree' by putting the input under the "then" branch of a
-- conditional that is True when Buildable is True. If 'addBuildableCondition'
-- can determine that Buildable is always True, it returns the input unchanged.
-- If Buildable is always False, it returns the empty 'CondTree'.
addBuildableCondition :: (Eq v, Monoid a, Monoid c) => (a -> BuildInfo)
                      -> CondTree v c a
                      -> CondTree v c a
addBuildableCondition :: forall v a c.
(Eq v, Monoid a, Monoid c) =>
(a -> BuildInfo) -> CondTree v c a -> CondTree v c a
addBuildableCondition a -> BuildInfo
getInfo CondTree v c a
t =
  case forall v a c. Eq v => (a -> Bool) -> CondTree v c a -> Condition v
extractCondition (BuildInfo -> Bool
buildable forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> BuildInfo
getInfo) CondTree v c a
t of
    Lit Bool
True  -> CondTree v c a
t
    Lit Bool
False -> forall v c a. a -> c -> [CondBranch v c a] -> CondTree v c a
CondNode forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty []
    Condition v
c         -> forall v c a. a -> c -> [CondBranch v c a] -> CondTree v c a
CondNode forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty [forall v c a. Condition v -> CondTree v c a -> CondBranch v c a
condIfThen Condition v
c CondTree v c a
t]

-- | This is a special version of 'addBuildableCondition' for the 'PDTagged'
-- type.
--
-- It is not simply a specialisation. It is more complicated than it
-- ought to be because of the way the 'PDTagged' monoid instance works. The
-- @mempty = 'PDNull'@ forgets the component type, which has the effect of
-- completely deleting components that are not buildable.
--
-- See <https://github.com/haskell/cabal/pull/4094> for more details.
--
addBuildableConditionPDTagged :: (Eq v, Monoid c) =>
                                 CondTree v c PDTagged
                              -> CondTree v c PDTagged
addBuildableConditionPDTagged :: forall v c.
(Eq v, Monoid c) =>
CondTree v c PDTagged -> CondTree v c PDTagged
addBuildableConditionPDTagged CondTree v c PDTagged
t =
    case forall v a c. Eq v => (a -> Bool) -> CondTree v c a -> Condition v
extractCondition (BuildInfo -> Bool
buildable forall b c a. (b -> c) -> (a -> b) -> a -> c
. PDTagged -> BuildInfo
getInfo) CondTree v c PDTagged
t of
      Lit Bool
True  -> CondTree v c PDTagged
t
      Lit Bool
False -> forall {v} {c} {a}. CondTree v c a -> CondTree v c a
deleteConstraints CondTree v c PDTagged
t
      Condition v
c         -> forall v c a. a -> c -> [CondBranch v c a] -> CondTree v c a
CondNode forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty [forall v c a.
Condition v -> CondTree v c a -> CondTree v c a -> CondBranch v c a
condIfThenElse Condition v
c CondTree v c PDTagged
t (forall {v} {c} {a}. CondTree v c a -> CondTree v c a
deleteConstraints CondTree v c PDTagged
t)]
  where
    deleteConstraints :: CondTree v c a -> CondTree v c a
deleteConstraints = forall c d v a. (c -> d) -> CondTree v c a -> CondTree v d a
mapTreeConstrs (forall a b. a -> b -> a
const forall a. Monoid a => a
mempty)

    getInfo :: PDTagged -> BuildInfo
    getInfo :: PDTagged -> BuildInfo
getInfo (Lib Library
l) = Library -> BuildInfo
libBuildInfo Library
l
    getInfo (SubComp UnqualComponentName
_ Component
c) = Component -> BuildInfo
componentBuildInfo Component
c
    getInfo PDTagged
PDNull = forall a. Monoid a => a
mempty


-- Note: extracting buildable conditions.
-- --------------------------------------
--
-- If the conditions in a cond tree lead to Buildable being set to False, then
-- none of the dependencies for this cond tree should actually be taken into
-- account. On the other hand, some of the flags may only be decided in the
-- solver, so we cannot necessarily make the decision whether a component is
-- Buildable or not prior to solving.
--
-- What we are doing here is to partially evaluate a condition tree in order to
-- extract the condition under which Buildable is True. The predicate determines
-- whether data under a 'CondTree' is buildable.

-- | Extract conditions matched by the given predicate from all cond trees in a
-- 'GenericPackageDescription'.
extractConditions :: (BuildInfo -> Bool) -> GenericPackageDescription
                     -> [Condition ConfVar]
extractConditions :: (BuildInfo -> Bool)
-> GenericPackageDescription -> [Condition ConfVar]
extractConditions BuildInfo -> Bool
f GenericPackageDescription
gpkg =
  forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [
      forall v a c. Eq v => (a -> Bool) -> CondTree v c a -> Condition v
extractCondition (BuildInfo -> Bool
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. Library -> BuildInfo
libBuildInfo)             forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Maybe a -> [a]
maybeToList (GenericPackageDescription
-> Maybe (CondTree ConfVar [Dependency] Library)
condLibrary GenericPackageDescription
gpkg)
    , forall v a c. Eq v => (a -> Bool) -> CondTree v c a -> Condition v
extractCondition (BuildInfo -> Bool
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. Library -> BuildInfo
libBuildInfo)       forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenericPackageDescription
-> [(UnqualComponentName, CondTree ConfVar [Dependency] Library)]
condSubLibraries   GenericPackageDescription
gpkg
    , forall v a c. Eq v => (a -> Bool) -> CondTree v c a -> Condition v
extractCondition (BuildInfo -> Bool
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. Executable -> BuildInfo
buildInfo)          forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenericPackageDescription
-> [(UnqualComponentName,
     CondTree ConfVar [Dependency] Executable)]
condExecutables GenericPackageDescription
gpkg
    , forall v a c. Eq v => (a -> Bool) -> CondTree v c a -> Condition v
extractCondition (BuildInfo -> Bool
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. TestSuite -> BuildInfo
testBuildInfo)      forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenericPackageDescription
-> [(UnqualComponentName, CondTree ConfVar [Dependency] TestSuite)]
condTestSuites  GenericPackageDescription
gpkg
    , forall v a c. Eq v => (a -> Bool) -> CondTree v c a -> Condition v
extractCondition (BuildInfo -> Bool
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. Benchmark -> BuildInfo
benchmarkBuildInfo) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenericPackageDescription
-> [(UnqualComponentName, CondTree ConfVar [Dependency] Benchmark)]
condBenchmarks  GenericPackageDescription
gpkg
    ]


-- | A map of package constraints that combines version ranges using 'unionVersionRanges'.
newtype DepMapUnion = DepMapUnion { DepMapUnion
-> Map PackageName (VersionRange, NonEmptySet LibraryName)
unDepMapUnion :: Map PackageName (VersionRange, NonEmptySet LibraryName) }

instance Semigroup DepMapUnion where
    DepMapUnion Map PackageName (VersionRange, NonEmptySet LibraryName)
x <> :: DepMapUnion -> DepMapUnion -> DepMapUnion
<> DepMapUnion Map PackageName (VersionRange, NonEmptySet LibraryName)
y = Map PackageName (VersionRange, NonEmptySet LibraryName)
-> DepMapUnion
DepMapUnion forall a b. (a -> b) -> a -> b
$
        forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a
Map.unionWith (VersionRange, NonEmptySet LibraryName)
-> (VersionRange, NonEmptySet LibraryName)
-> (VersionRange, NonEmptySet LibraryName)
unionVersionRanges' Map PackageName (VersionRange, NonEmptySet LibraryName)
x Map PackageName (VersionRange, NonEmptySet LibraryName)
y

unionVersionRanges'
    :: (VersionRange, NonEmptySet LibraryName)
    -> (VersionRange, NonEmptySet LibraryName)
    -> (VersionRange, NonEmptySet LibraryName)
unionVersionRanges' :: (VersionRange, NonEmptySet LibraryName)
-> (VersionRange, NonEmptySet LibraryName)
-> (VersionRange, NonEmptySet LibraryName)
unionVersionRanges' (VersionRange
vr, NonEmptySet LibraryName
cs) (VersionRange
vr', NonEmptySet LibraryName
cs') = (VersionRange -> VersionRange -> VersionRange
unionVersionRanges VersionRange
vr VersionRange
vr', NonEmptySet LibraryName
cs forall a. Semigroup a => a -> a -> a
<> NonEmptySet LibraryName
cs')

toDepMapUnion :: [Dependency] -> DepMapUnion
toDepMapUnion :: [Dependency] -> DepMapUnion
toDepMapUnion [Dependency]
ds =
  Map PackageName (VersionRange, NonEmptySet LibraryName)
-> DepMapUnion
DepMapUnion forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith (VersionRange, NonEmptySet LibraryName)
-> (VersionRange, NonEmptySet LibraryName)
-> (VersionRange, NonEmptySet LibraryName)
unionVersionRanges' [ (PackageName
p,(VersionRange
vr,NonEmptySet LibraryName
cs)) | Dependency PackageName
p VersionRange
vr NonEmptySet LibraryName
cs <- [Dependency]
ds ]


fromDepMapUnion :: DepMapUnion -> [Dependency]
fromDepMapUnion :: DepMapUnion -> [Dependency]
fromDepMapUnion DepMapUnion
m = [ PackageName
-> VersionRange -> NonEmptySet LibraryName -> Dependency
Dependency PackageName
p VersionRange
vr NonEmptySet LibraryName
cs | (PackageName
p,(VersionRange
vr,NonEmptySet LibraryName
cs)) <- forall k a. Map k a -> [(k, a)]
Map.toList (DepMapUnion
-> Map PackageName (VersionRange, NonEmptySet LibraryName)
unDepMapUnion DepMapUnion
m) ]

freeVars :: CondTree ConfVar c a  -> [FlagName]
freeVars :: forall c a. CondTree ConfVar c a -> [FlagName]
freeVars CondTree ConfVar c a
t = [ FlagName
f | PackageFlag FlagName
f <- forall {b} {c} {a}. CondTree b c a -> [b]
freeVars' CondTree ConfVar c a
t ]
  where
    freeVars' :: CondTree b c a -> [b]
freeVars' (CondNode a
_ c
_ [CondBranch b c a]
ifs) = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap CondBranch b c a -> [b]
compfv [CondBranch b c a]
ifs
    compfv :: CondBranch b c a -> [b]
compfv (CondBranch Condition b
c CondTree b c a
ct Maybe (CondTree b c a)
mct) = forall {a}. Condition a -> [a]
condfv Condition b
c forall a. [a] -> [a] -> [a]
++ CondTree b c a -> [b]
freeVars' CondTree b c a
ct forall a. [a] -> [a] -> [a]
++ forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] CondTree b c a -> [b]
freeVars' Maybe (CondTree b c a)
mct
    condfv :: Condition a -> [a]
condfv Condition a
c = case Condition a
c of
      Var a
v      -> [a
v]
      Lit Bool
_      -> []
      CNot Condition a
c'    -> Condition a -> [a]
condfv Condition a
c'
      COr Condition a
c1 Condition a
c2  -> Condition a -> [a]
condfv Condition a
c1 forall a. [a] -> [a] -> [a]
++ Condition a -> [a]
condfv Condition a
c2
      CAnd Condition a
c1 Condition a
c2 -> Condition a -> [a]
condfv Condition a
c1 forall a. [a] -> [a] -> [a]
++ Condition a -> [a]
condfv Condition a
c2


------------------------------------------------------------------------------

-- | A set of targets with their package dependencies
newtype TargetSet a = TargetSet [(DependencyMap, a)]

-- | Combine the target-specific dependencies in a TargetSet to give the
-- dependencies for the package as a whole.
overallDependencies :: ComponentRequestedSpec -> TargetSet PDTagged -> DependencyMap
overallDependencies :: ComponentRequestedSpec -> TargetSet PDTagged -> DependencyMap
overallDependencies ComponentRequestedSpec
enabled (TargetSet [(DependencyMap, PDTagged)]
targets) = forall a. Monoid a => [a] -> a
mconcat [DependencyMap]
depss
  where
    ([DependencyMap]
depss, [PDTagged]
_) = forall a b. [(a, b)] -> ([a], [b])
unzip forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
filter (PDTagged -> Bool
removeDisabledSections forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd) [(DependencyMap, PDTagged)]
targets
    removeDisabledSections :: PDTagged -> Bool
    -- UGH. The embedded componentName in the 'Component's here is
    -- BLANK.  I don't know whose fault this is but I'll use the tag
    -- instead. -- ezyang
    removeDisabledSections :: PDTagged -> Bool
removeDisabledSections (Lib Library
_)     = ComponentRequestedSpec -> ComponentName -> Bool
componentNameRequested
                                           ComponentRequestedSpec
enabled
                                           (LibraryName -> ComponentName
CLibName LibraryName
LMainLibName)
    removeDisabledSections (SubComp UnqualComponentName
t Component
c)
        -- Do NOT use componentName
        = ComponentRequestedSpec -> ComponentName -> Bool
componentNameRequested ComponentRequestedSpec
enabled
        forall a b. (a -> b) -> a -> b
$ case Component
c of
            CLib  Library
_ -> LibraryName -> ComponentName
CLibName (UnqualComponentName -> LibraryName
LSubLibName UnqualComponentName
t)
            CFLib ForeignLib
_ -> UnqualComponentName -> ComponentName
CFLibName   UnqualComponentName
t
            CExe  Executable
_ -> UnqualComponentName -> ComponentName
CExeName    UnqualComponentName
t
            CTest TestSuite
_ -> UnqualComponentName -> ComponentName
CTestName   UnqualComponentName
t
            CBench Benchmark
_ -> UnqualComponentName -> ComponentName
CBenchName UnqualComponentName
t
    removeDisabledSections PDTagged
PDNull      = Bool
True

-- | Collect up the targets in a TargetSet of tagged targets, storing the
-- dependencies as we go.
flattenTaggedTargets :: TargetSet PDTagged -> (Maybe Library, [(UnqualComponentName, Component)])
flattenTaggedTargets :: TargetSet PDTagged
-> (Maybe Library, [(UnqualComponentName, Component)])
flattenTaggedTargets (TargetSet [(DependencyMap, PDTagged)]
targets) = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (DependencyMap, PDTagged)
-> (Maybe Library, [(UnqualComponentName, Component)])
-> (Maybe Library, [(UnqualComponentName, Component)])
untag (forall a. Maybe a
Nothing, []) [(DependencyMap, PDTagged)]
targets where
  untag :: (DependencyMap, PDTagged)
-> (Maybe Library, [(UnqualComponentName, Component)])
-> (Maybe Library, [(UnqualComponentName, Component)])
untag (DependencyMap
depMap, PDTagged
pdTagged) (Maybe Library, [(UnqualComponentName, Component)])
accum = case (PDTagged
pdTagged, (Maybe Library, [(UnqualComponentName, Component)])
accum) of
    (Lib Library
_, (Just Library
_, [(UnqualComponentName, Component)]
_)) -> forall a. String -> a
userBug String
"Only one library expected"
    (Lib Library
l, (Maybe Library
Nothing, [(UnqualComponentName, Component)]
comps)) -> (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. HasBuildInfo a => a -> a
redoBD Library
l, [(UnqualComponentName, Component)]
comps)
    (SubComp UnqualComponentName
n Component
c, (Maybe Library
mb_lib, [(UnqualComponentName, Component)]
comps))
      | forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ((forall a. Eq a => a -> a -> Bool
== UnqualComponentName
n) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) [(UnqualComponentName, Component)]
comps ->
        forall a. String -> a
userBug forall a b. (a -> b) -> a -> b
$ String
"There exist several components with the same name: '" forall a. [a] -> [a] -> [a]
++ forall a. Pretty a => a -> String
prettyShow UnqualComponentName
n forall a. [a] -> [a] -> [a]
++ String
"'"
      | Bool
otherwise -> (Maybe Library
mb_lib, (UnqualComponentName
n, forall a. HasBuildInfo a => a -> a
redoBD Component
c) forall a. a -> [a] -> [a]
: [(UnqualComponentName, Component)]
comps)
    (PDTagged
PDNull, (Maybe Library, [(UnqualComponentName, Component)])
x) -> (Maybe Library, [(UnqualComponentName, Component)])
x  -- actually this should not happen, but let's be liberal
    where
      redoBD :: L.HasBuildInfo a => a -> a
      redoBD :: forall a. HasBuildInfo a => a -> a
redoBD = forall s t a b. ASetter s t a b -> b -> s -> t
set forall a. HasBuildInfo a => Lens' a [Dependency]
L.targetBuildDepends forall a b. (a -> b) -> a -> b
$ DependencyMap -> [Dependency]
fromDepMap DependencyMap
depMap

------------------------------------------------------------------------------
-- Convert GenericPackageDescription to PackageDescription
--

data PDTagged = Lib Library
              | SubComp UnqualComponentName Component
              | PDNull
              deriving Int -> PDTagged -> String -> String
[PDTagged] -> String -> String
PDTagged -> String
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [PDTagged] -> String -> String
$cshowList :: [PDTagged] -> String -> String
show :: PDTagged -> String
$cshow :: PDTagged -> String
showsPrec :: Int -> PDTagged -> String -> String
$cshowsPrec :: Int -> PDTagged -> String -> String
Show

instance Monoid PDTagged where
    mempty :: PDTagged
mempty = PDTagged
PDNull
    mappend :: PDTagged -> PDTagged -> PDTagged
mappend = forall a. Semigroup a => a -> a -> a
(<>)

instance Semigroup PDTagged where
    PDTagged
PDNull    <> :: PDTagged -> PDTagged -> PDTagged
<> PDTagged
x      = PDTagged
x
    PDTagged
x         <> PDTagged
PDNull = PDTagged
x
    Lib Library
l     <> Lib Library
l' = Library -> PDTagged
Lib (Library
l forall a. Semigroup a => a -> a -> a
<> Library
l')
    SubComp UnqualComponentName
n Component
x <> SubComp UnqualComponentName
n' Component
x' | UnqualComponentName
n forall a. Eq a => a -> a -> Bool
== UnqualComponentName
n' = UnqualComponentName -> Component -> PDTagged
SubComp UnqualComponentName
n (Component
x forall a. Semigroup a => a -> a -> a
<> Component
x')
    PDTagged
_         <> PDTagged
_  = forall a. String -> a
cabalBug String
"Cannot combine incompatible tags"

-- | Create a package description with all configurations resolved.
--
-- This function takes a `GenericPackageDescription` and several environment
-- parameters and tries to generate `PackageDescription` by finding a flag
-- assignment that result in satisfiable dependencies.
--
-- It takes as inputs a not necessarily complete specifications of flags
-- assignments, an optional package index as well as platform parameters.  If
-- some flags are not assigned explicitly, this function will try to pick an
-- assignment that causes this function to succeed.  The package index is
-- optional since on some platforms we cannot determine which packages have
-- been installed before.  When no package index is supplied, every dependency
-- is assumed to be satisfiable, therefore all not explicitly assigned flags
-- will get their default values.
--
-- This function will fail if it cannot find a flag assignment that leads to
-- satisfiable dependencies.  (It will not try alternative assignments for
-- explicitly specified flags.)  In case of failure it will return the missing
-- dependencies that it encountered when trying different flag assignments.
-- On success, it will return the package description and the full flag
-- assignment chosen.
--
-- Note that this drops any stanzas which have @buildable: False@.  While
-- this is arguably the right thing to do, it means we give bad error
-- messages in some situations, see #3858.
--
finalizePD ::
     FlagAssignment  -- ^ Explicitly specified flag assignments
  -> ComponentRequestedSpec
  -> (Dependency -> Bool) -- ^ Is a given dependency satisfiable from the set of
                          -- available packages?  If this is unknown then use
                          -- True.
  -> Platform      -- ^ The 'Arch' and 'OS'
  -> CompilerInfo  -- ^ Compiler information
  -> [PackageVersionConstraint]  -- ^ Additional constraints
  -> GenericPackageDescription
  -> Either [Dependency]
            (PackageDescription, FlagAssignment)
             -- ^ Either missing dependencies or the resolved package
             -- description along with the flag assignments chosen.
finalizePD :: FlagAssignment
-> ComponentRequestedSpec
-> (Dependency -> Bool)
-> Platform
-> CompilerInfo
-> [PackageVersionConstraint]
-> GenericPackageDescription
-> Either [Dependency] (PackageDescription, FlagAssignment)
finalizePD FlagAssignment
userflags ComponentRequestedSpec
enabled Dependency -> Bool
satisfyDep
        (Platform Arch
arch OS
os) CompilerInfo
impl [PackageVersionConstraint]
constraints
        (GenericPackageDescription PackageDescription
pkg Maybe Version
_ver [PackageFlag]
flags Maybe (CondTree ConfVar [Dependency] Library)
mb_lib0 [(UnqualComponentName, CondTree ConfVar [Dependency] Library)]
sub_libs0 [(UnqualComponentName, CondTree ConfVar [Dependency] ForeignLib)]
flibs0 [(UnqualComponentName, CondTree ConfVar [Dependency] Executable)]
exes0 [(UnqualComponentName, CondTree ConfVar [Dependency] TestSuite)]
tests0 [(UnqualComponentName, CondTree ConfVar [Dependency] Benchmark)]
bms0) = do
  (TargetSet PDTagged
targetSet, FlagAssignment
flagVals) <-
    [(FlagName, [Bool])]
-> ComponentRequestedSpec
-> OS
-> Arch
-> CompilerInfo
-> [PackageVersionConstraint]
-> [CondTree ConfVar [Dependency] PDTagged]
-> ([Dependency] -> DepTestRslt [Dependency])
-> Either [Dependency] (TargetSet PDTagged, FlagAssignment)
resolveWithFlags [(FlagName, [Bool])]
flagChoices ComponentRequestedSpec
enabled OS
os Arch
arch CompilerInfo
impl [PackageVersionConstraint]
constraints [CondTree ConfVar [Dependency] PDTagged]
condTrees [Dependency] -> DepTestRslt [Dependency]
check
  let
    (Maybe Library
mb_lib, [(UnqualComponentName, Component)]
comps) = TargetSet PDTagged
-> (Maybe Library, [(UnqualComponentName, Component)])
flattenTaggedTargets TargetSet PDTagged
targetSet
    mb_lib' :: Maybe Library
mb_lib' = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Library -> Library
libFillInDefaults Maybe Library
mb_lib
    comps' :: [Component]
comps' = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a b. (a -> b) -> [a] -> [b]
map [(UnqualComponentName, Component)]
comps forall a b. (a -> b) -> a -> b
$ \(UnqualComponentName
n,Component
c) -> forall a.
(Library -> a)
-> (ForeignLib -> a)
-> (Executable -> a)
-> (TestSuite -> a)
-> (Benchmark -> a)
-> Component
-> a
foldComponent
      (\Library
l -> Library -> Component
CLib   (Library -> Library
libFillInDefaults Library
l)   { libName :: LibraryName
libName = UnqualComponentName -> LibraryName
LSubLibName UnqualComponentName
n
                                            , libExposed :: Bool
libExposed = Bool
False })
      (\ForeignLib
l -> ForeignLib -> Component
CFLib  (ForeignLib -> ForeignLib
flibFillInDefaults ForeignLib
l)  { foreignLibName :: UnqualComponentName
foreignLibName = UnqualComponentName
n })
      (\Executable
e -> Executable -> Component
CExe   (Executable -> Executable
exeFillInDefaults Executable
e)   { exeName :: UnqualComponentName
exeName = UnqualComponentName
n })
      (\TestSuite
t -> TestSuite -> Component
CTest  (TestSuite -> TestSuite
testFillInDefaults TestSuite
t)  { testName :: UnqualComponentName
testName = UnqualComponentName
n })
      (\Benchmark
b -> Benchmark -> Component
CBench (Benchmark -> Benchmark
benchFillInDefaults Benchmark
b) { benchmarkName :: UnqualComponentName
benchmarkName = UnqualComponentName
n })
      Component
c
    ([Library]
sub_libs', [ForeignLib]
flibs', [Executable]
exes', [TestSuite]
tests', [Benchmark]
bms') = [Component]
-> ([Library], [ForeignLib], [Executable], [TestSuite],
    [Benchmark])
partitionComponents [Component]
comps'
  forall (m :: * -> *) a. Monad m => a -> m a
return ( PackageDescription
pkg { library :: Maybe Library
library = Maybe Library
mb_lib'
               , subLibraries :: [Library]
subLibraries = [Library]
sub_libs'
               , foreignLibs :: [ForeignLib]
foreignLibs = [ForeignLib]
flibs'
               , executables :: [Executable]
executables = [Executable]
exes'
               , testSuites :: [TestSuite]
testSuites = [TestSuite]
tests'
               , benchmarks :: [Benchmark]
benchmarks = [Benchmark]
bms'
               }
         , FlagAssignment
flagVals )
  where
    -- Combine lib, exes, and tests into one list of @CondTree@s with tagged data
    condTrees :: [CondTree ConfVar [Dependency] PDTagged]
condTrees =    forall a. Maybe a -> [a]
maybeToList (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b v c. (a -> b) -> CondTree v c a -> CondTree v c b
mapTreeData Library -> PDTagged
Lib) Maybe (CondTree ConfVar [Dependency] Library)
mb_lib0)
                forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map (\(UnqualComponentName
name,CondTree ConfVar [Dependency] Library
tree) -> forall a b v c. (a -> b) -> CondTree v c a -> CondTree v c b
mapTreeData (UnqualComponentName -> Component -> PDTagged
SubComp UnqualComponentName
name forall b c a. (b -> c) -> (a -> b) -> a -> c
. Library -> Component
CLib) CondTree ConfVar [Dependency] Library
tree) [(UnqualComponentName, CondTree ConfVar [Dependency] Library)]
sub_libs0
                forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map (\(UnqualComponentName
name,CondTree ConfVar [Dependency] ForeignLib
tree) -> forall a b v c. (a -> b) -> CondTree v c a -> CondTree v c b
mapTreeData (UnqualComponentName -> Component -> PDTagged
SubComp UnqualComponentName
name forall b c a. (b -> c) -> (a -> b) -> a -> c
. ForeignLib -> Component
CFLib) CondTree ConfVar [Dependency] ForeignLib
tree) [(UnqualComponentName, CondTree ConfVar [Dependency] ForeignLib)]
flibs0
                forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map (\(UnqualComponentName
name,CondTree ConfVar [Dependency] Executable
tree) -> forall a b v c. (a -> b) -> CondTree v c a -> CondTree v c b
mapTreeData (UnqualComponentName -> Component -> PDTagged
SubComp UnqualComponentName
name forall b c a. (b -> c) -> (a -> b) -> a -> c
. Executable -> Component
CExe) CondTree ConfVar [Dependency] Executable
tree) [(UnqualComponentName, CondTree ConfVar [Dependency] Executable)]
exes0
                forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map (\(UnqualComponentName
name,CondTree ConfVar [Dependency] TestSuite
tree) -> forall a b v c. (a -> b) -> CondTree v c a -> CondTree v c b
mapTreeData (UnqualComponentName -> Component -> PDTagged
SubComp UnqualComponentName
name forall b c a. (b -> c) -> (a -> b) -> a -> c
. TestSuite -> Component
CTest) CondTree ConfVar [Dependency] TestSuite
tree) [(UnqualComponentName, CondTree ConfVar [Dependency] TestSuite)]
tests0
                forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map (\(UnqualComponentName
name,CondTree ConfVar [Dependency] Benchmark
tree) -> forall a b v c. (a -> b) -> CondTree v c a -> CondTree v c b
mapTreeData (UnqualComponentName -> Component -> PDTagged
SubComp UnqualComponentName
name forall b c a. (b -> c) -> (a -> b) -> a -> c
. Benchmark -> Component
CBench) CondTree ConfVar [Dependency] Benchmark
tree) [(UnqualComponentName, CondTree ConfVar [Dependency] Benchmark)]
bms0

    flagChoices :: [(FlagName, [Bool])]
flagChoices    = forall a b. (a -> b) -> [a] -> [b]
map (\(MkPackageFlag FlagName
n String
_ Bool
d Bool
manual) -> (FlagName
n, Bool -> FlagName -> Bool -> [Bool]
d2c Bool
manual FlagName
n Bool
d)) [PackageFlag]
flags
    d2c :: Bool -> FlagName -> Bool -> [Bool]
d2c Bool
manual FlagName
n Bool
b = case FlagName -> FlagAssignment -> Maybe Bool
lookupFlagAssignment FlagName
n FlagAssignment
userflags of
                     Just Bool
val -> [Bool
val]
                     Maybe Bool
Nothing
                      | Bool
manual -> [Bool
b]
                      | Bool
otherwise -> [Bool
b, Bool -> Bool
not Bool
b]
    --flagDefaults = map (\(n,x:_) -> (n,x)) flagChoices
    check :: [Dependency] -> DepTestRslt [Dependency]
check [Dependency]
ds     = let missingDeps :: [Dependency]
missingDeps = forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dependency -> Bool
satisfyDep) [Dependency]
ds
                   in if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Dependency]
missingDeps
                      then forall d. DepTestRslt d
DepOk
                      else forall d. d -> DepTestRslt d
MissingDeps [Dependency]
missingDeps

{-
let tst_p = (CondNode [1::Int] [Distribution.Package.Dependency "a" AnyVersion] [])
let tst_p2 = (CondNode [1::Int] [Distribution.Package.Dependency "a" (EarlierVersion (Version [1,0] [])), Distribution.Package.Dependency "a" (LaterVersion (Version [2,0] []))] [])

let p_index = Distribution.Simple.PackageIndex.fromList [Distribution.Package.PackageIdentifier "a" (Version [0,5] []), Distribution.Package.PackageIdentifier "a" (Version [2,5] [])]
let look = not . null . Distribution.Simple.PackageIndex.lookupDependency p_index
let looks ds = mconcat $ map (\d -> if look d then DepOk else MissingDeps [d]) ds
resolveWithFlags [] Distribution.System.Linux Distribution.System.I386 (Distribution.Compiler.GHC,Version [6,8,2] []) [tst_p] looks   ===>  Right ...
resolveWithFlags [] Distribution.System.Linux Distribution.System.I386 (Distribution.Compiler.GHC,Version [6,8,2] []) [tst_p2] looks  ===>  Left ...
-}

-- | Flatten a generic package description by ignoring all conditions and just
-- join the field descriptors into on package description.  Note, however,
-- that this may lead to inconsistent field values, since all values are
-- joined into one field, which may not be possible in the original package
-- description, due to the use of exclusive choices (if ... else ...).
--
-- TODO: One particularly tricky case is defaulting.  In the original package
-- description, e.g., the source directory might either be the default or a
-- certain, explicitly set path.  Since defaults are filled in only after the
-- package has been resolved and when no explicit value has been set, the
-- default path will be missing from the package description returned by this
-- function.
flattenPackageDescription :: GenericPackageDescription -> PackageDescription
flattenPackageDescription :: GenericPackageDescription -> PackageDescription
flattenPackageDescription
  (GenericPackageDescription PackageDescription
pkg Maybe Version
_ [PackageFlag]
_ Maybe (CondTree ConfVar [Dependency] Library)
mlib0 [(UnqualComponentName, CondTree ConfVar [Dependency] Library)]
sub_libs0 [(UnqualComponentName, CondTree ConfVar [Dependency] ForeignLib)]
flibs0 [(UnqualComponentName, CondTree ConfVar [Dependency] Executable)]
exes0 [(UnqualComponentName, CondTree ConfVar [Dependency] TestSuite)]
tests0 [(UnqualComponentName, CondTree ConfVar [Dependency] Benchmark)]
bms0) =
    PackageDescription
pkg { library :: Maybe Library
library      = Maybe Library
mlib
        , subLibraries :: [Library]
subLibraries = forall a. [a] -> [a]
reverse [Library]
sub_libs
        , foreignLibs :: [ForeignLib]
foreignLibs  = forall a. [a] -> [a]
reverse [ForeignLib]
flibs
        , executables :: [Executable]
executables  = forall a. [a] -> [a]
reverse [Executable]
exes
        , testSuites :: [TestSuite]
testSuites   = forall a. [a] -> [a]
reverse [TestSuite]
tests
        , benchmarks :: [Benchmark]
benchmarks   = forall a. [a] -> [a]
reverse [Benchmark]
bms
        }
  where
    mlib :: Maybe Library
mlib = forall {b} {v}. Semigroup b => CondTree v b Library -> Library
f forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (CondTree ConfVar [Dependency] Library)
mlib0
      where f :: CondTree v b Library -> Library
f CondTree v b Library
lib = (Library -> Library
libFillInDefaults forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a c v.
(Semigroup a, Semigroup c) =>
CondTree v c a -> (a, c)
ignoreConditions forall a b. (a -> b) -> a -> b
$ CondTree v b Library
lib) { libName :: LibraryName
libName = LibraryName
LMainLibName }
    sub_libs :: [Library]
sub_libs = forall {b} {v}.
Semigroup b =>
(UnqualComponentName, CondTree v b Library) -> Library
flattenLib  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(UnqualComponentName, CondTree ConfVar [Dependency] Library)]
sub_libs0
    flibs :: [ForeignLib]
flibs    = forall {b} {v}.
Semigroup b =>
(UnqualComponentName, CondTree v b ForeignLib) -> ForeignLib
flattenFLib forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(UnqualComponentName, CondTree ConfVar [Dependency] ForeignLib)]
flibs0
    exes :: [Executable]
exes     = forall {b} {v}.
Semigroup b =>
(UnqualComponentName, CondTree v b Executable) -> Executable
flattenExe  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(UnqualComponentName, CondTree ConfVar [Dependency] Executable)]
exes0
    tests :: [TestSuite]
tests    = forall {b} {v}.
Semigroup b =>
(UnqualComponentName, CondTree v b TestSuite) -> TestSuite
flattenTst  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(UnqualComponentName, CondTree ConfVar [Dependency] TestSuite)]
tests0
    bms :: [Benchmark]
bms      = forall {b} {v}.
Semigroup b =>
(UnqualComponentName, CondTree v b Benchmark) -> Benchmark
flattenBm   forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(UnqualComponentName, CondTree ConfVar [Dependency] Benchmark)]
bms0
    flattenLib :: (UnqualComponentName, CondTree v b Library) -> Library
flattenLib (UnqualComponentName
n, CondTree v b Library
t) = Library -> Library
libFillInDefaults forall a b. (a -> b) -> a -> b
$ (forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall a c v.
(Semigroup a, Semigroup c) =>
CondTree v c a -> (a, c)
ignoreConditions CondTree v b Library
t)
      { libName :: LibraryName
libName = UnqualComponentName -> LibraryName
LSubLibName UnqualComponentName
n, libExposed :: Bool
libExposed = Bool
False }
    flattenFLib :: (UnqualComponentName, CondTree v b ForeignLib) -> ForeignLib
flattenFLib (UnqualComponentName
n, CondTree v b ForeignLib
t) = ForeignLib -> ForeignLib
flibFillInDefaults forall a b. (a -> b) -> a -> b
$ (forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall a c v.
(Semigroup a, Semigroup c) =>
CondTree v c a -> (a, c)
ignoreConditions CondTree v b ForeignLib
t)
      { foreignLibName :: UnqualComponentName
foreignLibName = UnqualComponentName
n }
    flattenExe :: (UnqualComponentName, CondTree v b Executable) -> Executable
flattenExe (UnqualComponentName
n, CondTree v b Executable
t) = Executable -> Executable
exeFillInDefaults forall a b. (a -> b) -> a -> b
$ (forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall a c v.
(Semigroup a, Semigroup c) =>
CondTree v c a -> (a, c)
ignoreConditions CondTree v b Executable
t)
      { exeName :: UnqualComponentName
exeName = UnqualComponentName
n }
    flattenTst :: (UnqualComponentName, CondTree v b TestSuite) -> TestSuite
flattenTst (UnqualComponentName
n, CondTree v b TestSuite
t) = TestSuite -> TestSuite
testFillInDefaults forall a b. (a -> b) -> a -> b
$ (forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall a c v.
(Semigroup a, Semigroup c) =>
CondTree v c a -> (a, c)
ignoreConditions CondTree v b TestSuite
t)
      { testName :: UnqualComponentName
testName = UnqualComponentName
n }
    flattenBm :: (UnqualComponentName, CondTree v b Benchmark) -> Benchmark
flattenBm (UnqualComponentName
n, CondTree v b Benchmark
t) = Benchmark -> Benchmark
benchFillInDefaults forall a b. (a -> b) -> a -> b
$ (forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall a c v.
(Semigroup a, Semigroup c) =>
CondTree v c a -> (a, c)
ignoreConditions CondTree v b Benchmark
t)
      { benchmarkName :: UnqualComponentName
benchmarkName = UnqualComponentName
n }

-- This is in fact rather a hack.  The original version just overrode the
-- default values, however, when adding conditions we had to switch to a
-- modifier-based approach.  There, nothing is ever overwritten, but only
-- joined together.
--
-- This is the cleanest way i could think of, that doesn't require
-- changing all field parsing functions to return modifiers instead.
libFillInDefaults :: Library -> Library
libFillInDefaults :: Library -> Library
libFillInDefaults lib :: Library
lib@(Library { libBuildInfo :: Library -> BuildInfo
libBuildInfo = BuildInfo
bi }) =
    Library
lib { libBuildInfo :: BuildInfo
libBuildInfo = BuildInfo -> BuildInfo
biFillInDefaults BuildInfo
bi }

flibFillInDefaults :: ForeignLib -> ForeignLib
flibFillInDefaults :: ForeignLib -> ForeignLib
flibFillInDefaults flib :: ForeignLib
flib@(ForeignLib { foreignLibBuildInfo :: ForeignLib -> BuildInfo
foreignLibBuildInfo = BuildInfo
bi }) =
    ForeignLib
flib { foreignLibBuildInfo :: BuildInfo
foreignLibBuildInfo = BuildInfo -> BuildInfo
biFillInDefaults BuildInfo
bi }

exeFillInDefaults :: Executable -> Executable
exeFillInDefaults :: Executable -> Executable
exeFillInDefaults exe :: Executable
exe@(Executable { buildInfo :: Executable -> BuildInfo
buildInfo = BuildInfo
bi }) =
    Executable
exe { buildInfo :: BuildInfo
buildInfo = BuildInfo -> BuildInfo
biFillInDefaults BuildInfo
bi }

testFillInDefaults :: TestSuite -> TestSuite
testFillInDefaults :: TestSuite -> TestSuite
testFillInDefaults tst :: TestSuite
tst@(TestSuite { testBuildInfo :: TestSuite -> BuildInfo
testBuildInfo = BuildInfo
bi }) =
    TestSuite
tst { testBuildInfo :: BuildInfo
testBuildInfo = BuildInfo -> BuildInfo
biFillInDefaults BuildInfo
bi }

benchFillInDefaults :: Benchmark -> Benchmark
benchFillInDefaults :: Benchmark -> Benchmark
benchFillInDefaults bm :: Benchmark
bm@(Benchmark { benchmarkBuildInfo :: Benchmark -> BuildInfo
benchmarkBuildInfo = BuildInfo
bi }) =
    Benchmark
bm { benchmarkBuildInfo :: BuildInfo
benchmarkBuildInfo = BuildInfo -> BuildInfo
biFillInDefaults BuildInfo
bi }

biFillInDefaults :: BuildInfo -> BuildInfo
biFillInDefaults :: BuildInfo -> BuildInfo
biFillInDefaults BuildInfo
bi =
    if forall (t :: * -> *) a. Foldable t => t a -> Bool
null (BuildInfo -> [SymbolicPath PackageDir SourceDir]
hsSourceDirs BuildInfo
bi)
    then BuildInfo
bi { hsSourceDirs :: [SymbolicPath PackageDir SourceDir]
hsSourceDirs = [forall from to. (IsDir from, IsDir to) => SymbolicPath from to
sameDirectory] }
    else BuildInfo
bi

-- Walk a 'GenericPackageDescription' and apply @onBuildInfo@/@onSetupBuildInfo@
-- to all nested 'BuildInfo'/'SetupBuildInfo' values.
transformAllBuildInfos :: (BuildInfo -> BuildInfo)
                       -> (SetupBuildInfo -> SetupBuildInfo)
                       -> GenericPackageDescription
                       -> GenericPackageDescription
transformAllBuildInfos :: (BuildInfo -> BuildInfo)
-> (SetupBuildInfo -> SetupBuildInfo)
-> GenericPackageDescription
-> GenericPackageDescription
transformAllBuildInfos BuildInfo -> BuildInfo
onBuildInfo SetupBuildInfo -> SetupBuildInfo
onSetupBuildInfo =
  forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over forall a. HasBuildInfos a => Traversal' a BuildInfo
L.traverseBuildInfos BuildInfo -> BuildInfo
onBuildInfo
  forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over (Lens' GenericPackageDescription PackageDescription
L.packageDescription forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' PackageDescription (Maybe SetupBuildInfo)
L.setupBuildInfo forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse) SetupBuildInfo -> SetupBuildInfo
onSetupBuildInfo

-- | Walk a 'GenericPackageDescription' and apply @f@ to all nested
-- @build-depends@ fields.
transformAllBuildDepends :: (Dependency -> Dependency)
                         -> GenericPackageDescription
                         -> GenericPackageDescription
transformAllBuildDepends :: (Dependency -> Dependency)
-> GenericPackageDescription -> GenericPackageDescription
transformAllBuildDepends Dependency -> Dependency
f =
  forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over (forall a. HasBuildInfos a => Traversal' a BuildInfo
L.traverseBuildInfos forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. HasBuildInfo a => Lens' a [Dependency]
L.targetBuildDepends forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse) Dependency -> Dependency
f
  forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over (Lens' GenericPackageDescription PackageDescription
L.packageDescription forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' PackageDescription (Maybe SetupBuildInfo)
L.setupBuildInfo forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' SetupBuildInfo [Dependency]
L.setupDepends forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse) Dependency -> Dependency
f
  -- cannot be point-free as normal because of higher rank
  forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over (\[Dependency] -> Identity [Dependency]
f' -> forall (f :: * -> *).
Applicative f =>
(forall a.
 CondTree ConfVar [Dependency] a
 -> f (CondTree ConfVar [Dependency] a))
-> GenericPackageDescription -> f GenericPackageDescription
L.allCondTrees forall a b. (a -> b) -> a -> b
$ forall v c a d. Traversal (CondTree v c a) (CondTree v d a) c d
traverseCondTreeC [Dependency] -> Identity [Dependency]
f') (forall a b. (a -> b) -> [a] -> [b]
map Dependency -> Dependency
f)

-- | Walk a 'GenericPackageDescription' and apply @f@ to all nested
-- @build-depends@ fields.
transformAllBuildDependsN :: ([Dependency] -> [Dependency])
                          -> GenericPackageDescription
                          -> GenericPackageDescription
transformAllBuildDependsN :: ([Dependency] -> [Dependency])
-> GenericPackageDescription -> GenericPackageDescription
transformAllBuildDependsN [Dependency] -> [Dependency]
f =
  forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over (forall a. HasBuildInfos a => Traversal' a BuildInfo
L.traverseBuildInfos forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. HasBuildInfo a => Lens' a [Dependency]
L.targetBuildDepends) [Dependency] -> [Dependency]
f
  forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over (Lens' GenericPackageDescription PackageDescription
L.packageDescription forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' PackageDescription (Maybe SetupBuildInfo)
L.setupBuildInfo forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' SetupBuildInfo [Dependency]
L.setupDepends) [Dependency] -> [Dependency]
f
  -- cannot be point-free as normal because of higher rank
  forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over (\[Dependency] -> Identity [Dependency]
f' -> forall (f :: * -> *).
Applicative f =>
(forall a.
 CondTree ConfVar [Dependency] a
 -> f (CondTree ConfVar [Dependency] a))
-> GenericPackageDescription -> f GenericPackageDescription
L.allCondTrees forall a b. (a -> b) -> a -> b
$ forall v c a d. Traversal (CondTree v c a) (CondTree v d a) c d
traverseCondTreeC [Dependency] -> Identity [Dependency]
f') [Dependency] -> [Dependency]
f