make LTS branch pre-releases
[cabal.git] / cabal-install-solver / src / Distribution / Solver / Modular / IndexConversion.hs
blob72d0b8193e3226fedc83046a5eae33cf795a4923
1 module Distribution.Solver.Modular.IndexConversion
2 ( convPIs
3 ) where
5 import Distribution.Solver.Compat.Prelude
6 import Prelude ()
8 import qualified Data.List as L
9 import qualified Data.Map.Strict as M
10 import qualified Distribution.Compat.NonEmptySet as NonEmptySet
11 import qualified Data.Set as S
13 import qualified Distribution.InstalledPackageInfo as IPI
14 import Distribution.Compiler
15 import Distribution.Package -- from Cabal
16 import Distribution.Simple.BuildToolDepends -- from Cabal
17 import Distribution.Types.ExeDependency -- from Cabal
18 import Distribution.Types.PkgconfigDependency -- from Cabal
19 import Distribution.Types.ComponentName -- from Cabal
20 import Distribution.Types.CondTree -- from Cabal
21 import Distribution.Types.MungedPackageId -- from Cabal
22 import Distribution.Types.MungedPackageName -- from Cabal
23 import Distribution.PackageDescription -- from Cabal
24 import Distribution.PackageDescription.Configuration
25 import qualified Distribution.Simple.PackageIndex as SI
26 import Distribution.System
28 import Distribution.Solver.Types.ComponentDeps
29 ( Component(..), componentNameToComponent )
30 import Distribution.Solver.Types.Flag
31 import Distribution.Solver.Types.LabeledPackageConstraint
32 import Distribution.Solver.Types.OptionalStanza
33 import Distribution.Solver.Types.PackageConstraint
34 import qualified Distribution.Solver.Types.PackageIndex as CI
35 import Distribution.Solver.Types.Settings
36 import Distribution.Solver.Types.SourcePackage
38 import Distribution.Solver.Modular.Dependency as D
39 import Distribution.Solver.Modular.Flag as F
40 import Distribution.Solver.Modular.Index
41 import Distribution.Solver.Modular.Package
42 import Distribution.Solver.Modular.Tree
43 import Distribution.Solver.Modular.Version
45 -- | Convert both the installed package index and the source package
46 -- index into one uniform solver index.
48 -- We use 'allPackagesBySourcePackageId' for the installed package index
49 -- because that returns us several instances of the same package and version
50 -- in order of preference. This allows us in principle to \"shadow\"
51 -- packages if there are several installed packages of the same version.
52 -- There are currently some shortcomings in both GHC and Cabal in
53 -- resolving these situations. However, the right thing to do is to
54 -- fix the problem there, so for now, shadowing is only activated if
55 -- explicitly requested.
56 convPIs :: OS -> Arch -> CompilerInfo -> Map PN [LabeledPackageConstraint]
57 -> ShadowPkgs -> StrongFlags -> SolveExecutables
58 -> SI.InstalledPackageIndex -> CI.PackageIndex (SourcePackage loc)
59 -> Index
60 convPIs os arch comp constraints sip strfl solveExes iidx sidx =
61 mkIndex $
62 convIPI' sip iidx ++ convSPI' os arch comp constraints strfl solveExes sidx
64 -- | Convert a Cabal installed package index to the simpler,
65 -- more uniform index format of the solver.
66 convIPI' :: ShadowPkgs -> SI.InstalledPackageIndex -> [(PN, I, PInfo)]
67 convIPI' (ShadowPkgs sip) idx =
68 -- apply shadowing whenever there are multiple installed packages with
69 -- the same version
70 [ maybeShadow (convIP idx pkg)
71 -- IMPORTANT to get internal libraries. See
72 -- Note [Index conversion with internal libraries]
73 | (_, pkgs) <- SI.allPackagesBySourcePackageIdAndLibName idx
74 , (maybeShadow, pkg) <- zip (id : repeat shadow) pkgs ]
75 where
77 -- shadowing is recorded in the package info
78 shadow (pn, i, PInfo fdeps comps fds _)
79 | sip = (pn, i, PInfo fdeps comps fds (Just Shadowed))
80 shadow x = x
82 -- | Extract/recover the package ID from an installed package info, and convert it to a solver's I.
83 convId :: IPI.InstalledPackageInfo -> (PN, I)
84 convId ipi = (pn, I ver $ Inst $ IPI.installedUnitId ipi)
85 where MungedPackageId mpn ver = mungedId ipi
86 -- HACK. See Note [Index conversion with internal libraries]
87 pn = encodeCompatPackageName mpn
89 -- | Convert a single installed package into the solver-specific format.
90 convIP :: SI.InstalledPackageIndex -> IPI.InstalledPackageInfo -> (PN, I, PInfo)
91 convIP idx ipi =
92 case traverse (convIPId (DependencyReason pn M.empty S.empty) comp idx) (IPI.depends ipi) of
93 Left u -> (pn, i, PInfo [] M.empty M.empty (Just (Broken u)))
94 Right fds -> (pn, i, PInfo fds components M.empty Nothing)
95 where
96 -- TODO: Handle sub-libraries and visibility.
97 components =
98 M.singleton (ExposedLib LMainLibName)
99 ComponentInfo {
100 compIsVisible = IsVisible True
101 , compIsBuildable = IsBuildable True
104 (pn, i) = convId ipi
106 -- 'sourceLibName' is unreliable, but for now we only really use this for
107 -- primary libs anyways
108 comp = componentNameToComponent $ CLibName $ IPI.sourceLibName ipi
109 -- TODO: Installed packages should also store their encapsulations!
111 -- Note [Index conversion with internal libraries]
112 -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
113 -- Something very interesting happens when we have internal libraries
114 -- in our index. In this case, we maybe have p-0.1, which itself
115 -- depends on the internal library p-internal ALSO from p-0.1.
116 -- Here's the danger:
118 -- - If we treat both of these packages as having PN "p",
119 -- then the solver will try to pick one or the other,
120 -- but never both.
122 -- - If we drop the internal packages, now p-0.1 has a
123 -- dangling dependency on an "installed" package we know
124 -- nothing about. Oops.
126 -- An expedient hack is to put p-internal into cabal-install's
127 -- index as a MUNGED package name, so that it doesn't conflict
128 -- with anyone else (except other instances of itself). But
129 -- yet, we ought NOT to say that PNs in the solver are munged
130 -- package names, because they're not; for source packages,
131 -- we really will never see munged package names.
133 -- The tension here is that the installed package index is actually
134 -- per library, but the solver is per package. We need to smooth
135 -- it over, and munging the package names is a pretty good way to
136 -- do it.
138 -- | Convert dependencies specified by an installed package id into
139 -- flagged dependencies of the solver.
141 -- May return Nothing if the package can't be found in the index. That
142 -- indicates that the original package having this dependency is broken
143 -- and should be ignored.
144 convIPId :: DependencyReason PN -> Component -> SI.InstalledPackageIndex -> UnitId -> Either UnitId (FlaggedDep PN)
145 convIPId dr comp idx ipid =
146 case SI.lookupUnitId idx ipid of
147 Nothing -> Left ipid
148 Just ipi -> let (pn, i) = convId ipi
149 name = ExposedLib LMainLibName -- TODO: Handle sub-libraries.
150 in Right (D.Simple (LDep dr (Dep (PkgComponent pn name) (Fixed i))) comp)
151 -- NB: something we pick up from the
152 -- InstalledPackageIndex is NEVER an executable
154 -- | Convert a cabal-install source package index to the simpler,
155 -- more uniform index format of the solver.
156 convSPI' :: OS -> Arch -> CompilerInfo -> Map PN [LabeledPackageConstraint]
157 -> StrongFlags -> SolveExecutables
158 -> CI.PackageIndex (SourcePackage loc) -> [(PN, I, PInfo)]
159 convSPI' os arch cinfo constraints strfl solveExes =
160 L.map (convSP os arch cinfo constraints strfl solveExes) . CI.allPackages
162 -- | Convert a single source package into the solver-specific format.
163 convSP :: OS -> Arch -> CompilerInfo -> Map PN [LabeledPackageConstraint]
164 -> StrongFlags -> SolveExecutables -> SourcePackage loc -> (PN, I, PInfo)
165 convSP os arch cinfo constraints strfl solveExes (SourcePackage (PackageIdentifier pn pv) gpd _ _pl) =
166 let i = I pv InRepo
167 pkgConstraints = fromMaybe [] $ M.lookup pn constraints
168 in (pn, i, convGPD os arch cinfo pkgConstraints strfl solveExes pn gpd)
170 -- We do not use 'flattenPackageDescription' or 'finalizePD'
171 -- from 'Distribution.PackageDescription.Configuration' here, because we
172 -- want to keep the condition tree, but simplify much of the test.
174 -- | Convert a generic package description to a solver-specific 'PInfo'.
175 convGPD :: OS -> Arch -> CompilerInfo -> [LabeledPackageConstraint]
176 -> StrongFlags -> SolveExecutables -> PN -> GenericPackageDescription
177 -> PInfo
178 convGPD os arch cinfo constraints strfl solveExes pn
179 (GenericPackageDescription pkg scannedVersion flags mlib sub_libs flibs exes tests benchs) =
181 fds = flagInfo strfl flags
184 conv :: Monoid a => Component -> (a -> BuildInfo) -> DependencyReason PN ->
185 CondTree ConfVar [Dependency] a -> FlaggedDeps PN
186 conv comp getInfo dr =
187 convCondTree M.empty dr pkg os arch cinfo pn fds comp getInfo solveExes .
188 addBuildableCondition getInfo
190 initDR = DependencyReason pn M.empty S.empty
192 flagged_deps
193 = concatMap (\ds -> conv ComponentLib libBuildInfo initDR ds) (maybeToList mlib)
194 ++ concatMap (\(nm, ds) -> conv (ComponentSubLib nm) libBuildInfo initDR ds) sub_libs
195 ++ concatMap (\(nm, ds) -> conv (ComponentFLib nm) foreignLibBuildInfo initDR ds) flibs
196 ++ concatMap (\(nm, ds) -> conv (ComponentExe nm) buildInfo initDR ds) exes
197 ++ prefix (Stanza (SN pn TestStanzas))
198 (L.map (\(nm, ds) -> conv (ComponentTest nm) testBuildInfo (addStanza TestStanzas initDR) ds)
199 tests)
200 ++ prefix (Stanza (SN pn BenchStanzas))
201 (L.map (\(nm, ds) -> conv (ComponentBench nm) benchmarkBuildInfo (addStanza BenchStanzas initDR) ds)
202 benchs)
203 ++ maybe [] (convSetupBuildInfo pn) (setupBuildInfo pkg)
205 addStanza :: Stanza -> DependencyReason pn -> DependencyReason pn
206 addStanza s (DependencyReason pn' fs ss) = DependencyReason pn' fs (S.insert s ss)
208 -- | A too-new specVersion is turned into a global 'FailReason'
209 -- which prevents the solver from selecting this release (and if
210 -- forced to, emit a meaningful solver error message).
211 fr = case scannedVersion of
212 Just ver -> Just (UnsupportedSpecVer ver)
213 Nothing -> Nothing
215 components :: Map ExposedComponent ComponentInfo
216 components = M.fromList $ libComps ++ subLibComps ++ exeComps
217 where
218 libComps = [ (ExposedLib LMainLibName, libToComponentInfo lib)
219 | lib <- maybeToList mlib ]
220 subLibComps = [ (ExposedLib (LSubLibName name), libToComponentInfo lib)
221 | (name, lib) <- sub_libs ]
222 exeComps = [ ( ExposedExe name
223 , ComponentInfo {
224 compIsVisible = IsVisible True
225 , compIsBuildable = IsBuildable $ testCondition (buildable . buildInfo) exe /= Just False
228 | (name, exe) <- exes ]
230 libToComponentInfo lib =
231 ComponentInfo {
232 compIsVisible = IsVisible $ testCondition (isPrivate . libVisibility) lib /= Just True
233 , compIsBuildable = IsBuildable $ testCondition (buildable . libBuildInfo) lib /= Just False
236 testCondition = testConditionForComponent os arch cinfo constraints
238 isPrivate LibraryVisibilityPrivate = True
239 isPrivate LibraryVisibilityPublic = False
241 in PInfo flagged_deps components fds fr
243 -- | Applies the given predicate (for example, testing buildability or
244 -- visibility) to the given component and environment. Values are combined with
245 -- AND. This function returns 'Nothing' when the result cannot be determined
246 -- before dependency solving. Additionally, this function only considers flags
247 -- that are set by unqualified flag constraints, and it doesn't check the
248 -- intra-package dependencies of a component.
249 testConditionForComponent :: OS
250 -> Arch
251 -> CompilerInfo
252 -> [LabeledPackageConstraint]
253 -> (a -> Bool)
254 -> CondTree ConfVar [Dependency] a
255 -> Maybe Bool
256 testConditionForComponent os arch cinfo constraints p tree =
257 case go $ extractCondition p tree of
258 Lit True -> Just True
259 Lit False -> Just False
260 _ -> Nothing
261 where
262 flagAssignment :: [(FlagName, Bool)]
263 flagAssignment =
264 mconcat [ unFlagAssignment fa
265 | PackageConstraint (ScopeAnyQualifier _) (PackagePropertyFlags fa)
266 <- L.map unlabelPackageConstraint constraints]
268 -- Simplify the condition, using the current environment. Most of this
269 -- function was copied from convBranch and
270 -- Distribution.Types.Condition.simplifyCondition.
271 go :: Condition ConfVar -> Condition ConfVar
272 go (Var (OS os')) = Lit (os == os')
273 go (Var (Arch arch')) = Lit (arch == arch')
274 go (Var (Impl cf cvr))
275 | matchImpl (compilerInfoId cinfo) ||
276 -- fixme: Nothing should be treated as unknown, rather than empty
277 -- list. This code should eventually be changed to either
278 -- support partial resolution of compiler flags or to
279 -- complain about incompletely configured compilers.
280 any matchImpl (fromMaybe [] $ compilerInfoCompat cinfo) = Lit True
281 | otherwise = Lit False
282 where
283 matchImpl (CompilerId cf' cv) = cf == cf' && checkVR cvr cv
284 go (Var (PackageFlag f))
285 | Just b <- L.lookup f flagAssignment = Lit b
286 go (Var v) = Var v
287 go (Lit b) = Lit b
288 go (CNot c) =
289 case go c of
290 Lit True -> Lit False
291 Lit False -> Lit True
292 c' -> CNot c'
293 go (COr c d) =
294 case (go c, go d) of
295 (Lit False, d') -> d'
296 (Lit True, _) -> Lit True
297 (c', Lit False) -> c'
298 (_, Lit True) -> Lit True
299 (c', d') -> COr c' d'
300 go (CAnd c d) =
301 case (go c, go d) of
302 (Lit False, _) -> Lit False
303 (Lit True, d') -> d'
304 (_, Lit False) -> Lit False
305 (c', Lit True) -> c'
306 (c', d') -> CAnd c' d'
308 -- | Create a flagged dependency tree from a list @fds@ of flagged
309 -- dependencies, using @f@ to form the tree node (@f@ will be
310 -- something like @Stanza sn@).
311 prefix :: (FlaggedDeps qpn -> FlaggedDep qpn)
312 -> [FlaggedDeps qpn] -> FlaggedDeps qpn
313 prefix _ [] = []
314 prefix f fds = [f (concat fds)]
316 -- | Convert flag information. Automatic flags are now considered weak
317 -- unless strong flags have been selected explicitly.
318 flagInfo :: StrongFlags -> [PackageFlag] -> FlagInfo
319 flagInfo (StrongFlags strfl) =
320 M.fromList . L.map (\ (MkPackageFlag fn _ b m) -> (fn, FInfo b (flagType m) (weak m)))
321 where
322 weak m = WeakOrTrivial $ not (strfl || m)
323 flagType m = if m then Manual else Automatic
325 -- | Convert condition trees to flagged dependencies. Mutually
326 -- recursive with 'convBranch'. See 'convBranch' for an explanation
327 -- of all arguments preceding the input 'CondTree'.
328 convCondTree :: Map FlagName Bool -> DependencyReason PN -> PackageDescription -> OS -> Arch -> CompilerInfo -> PN -> FlagInfo ->
329 Component ->
330 (a -> BuildInfo) ->
331 SolveExecutables ->
332 CondTree ConfVar [Dependency] a -> FlaggedDeps PN
333 convCondTree flags dr pkg os arch cinfo pn fds comp getInfo solveExes@(SolveExecutables solveExes') (CondNode info ds branches) =
334 -- Merge all library and build-tool dependencies at every level in
335 -- the tree of flagged dependencies. Otherwise 'extractCommon'
336 -- could create duplicate dependencies, and the number of
337 -- duplicates could grow exponentially from the leaves to the root
338 -- of the tree.
339 mergeSimpleDeps $
340 [ D.Simple singleDep comp
341 | dep <- ds
342 , singleDep <- convLibDeps dr dep ] -- unconditional package dependencies
344 ++ L.map (\e -> D.Simple (LDep dr (Ext e)) comp) (allExtensions bi) -- unconditional extension dependencies
345 ++ L.map (\l -> D.Simple (LDep dr (Lang l)) comp) (allLanguages bi) -- unconditional language dependencies
346 ++ L.map (\(PkgconfigDependency pkn vr) -> D.Simple (LDep dr (Pkg pkn vr)) comp) (pkgconfigDepends bi) -- unconditional pkg-config dependencies
347 ++ concatMap (convBranch flags dr pkg os arch cinfo pn fds comp getInfo solveExes) branches
348 -- build-tools dependencies
349 -- NB: Only include these dependencies if SolveExecutables
350 -- is True. It might be false in the legacy solver
351 -- codepath, in which case there won't be any record of
352 -- an executable we need.
353 ++ [ D.Simple (convExeDep dr exeDep) comp
354 | solveExes'
355 , exeDep <- getAllToolDependencies pkg bi
356 , not $ isInternal pkg exeDep
358 where
359 bi = getInfo info
361 data SimpleFlaggedDepKey qpn =
362 SimpleFlaggedDepKey (PkgComponent qpn) Component
363 deriving (Eq, Ord)
365 data SimpleFlaggedDepValue qpn = SimpleFlaggedDepValue (DependencyReason qpn) VR
367 -- | Merge 'Simple' dependencies that apply to the same library or build-tool.
368 -- This function should be able to merge any two dependencies that can be merged
369 -- by extractCommon, in order to prevent the exponential growth of dependencies.
371 -- Note that this function can merge dependencies that have different
372 -- DependencyReasons, which can make the DependencyReasons less precise. This
373 -- loss of precision only affects performance and log messages, not correctness.
374 -- However, when 'mergeSimpleDeps' is only called on dependencies at a single
375 -- location in the dependency tree, the only difference between
376 -- DependencyReasons should be flags that have value FlagBoth. Adding extra
377 -- flags with value FlagBoth should not affect performance, since they are not
378 -- added to the conflict set. The only downside is the possibility of the log
379 -- incorrectly saying that the flag contributed to excluding a specific version
380 -- of a dependency. For example, if +/-flagA introduces pkg >=2 and +/-flagB
381 -- introduces pkg <5, the merged dependency would mean that
382 -- +/-flagA and +/-flagB introduce pkg >=2 && <5, which would incorrectly imply
383 -- that +/-flagA excludes pkg-6.
384 mergeSimpleDeps :: Ord qpn => FlaggedDeps qpn -> FlaggedDeps qpn
385 mergeSimpleDeps deps = L.map (uncurry toFlaggedDep) (M.toList merged) ++ unmerged
386 where
387 (merged, unmerged) = L.foldl' f (M.empty, []) deps
388 where
389 f :: Ord qpn
390 => (Map (SimpleFlaggedDepKey qpn) (SimpleFlaggedDepValue qpn), FlaggedDeps qpn)
391 -> FlaggedDep qpn
392 -> (Map (SimpleFlaggedDepKey qpn) (SimpleFlaggedDepValue qpn), FlaggedDeps qpn)
393 f (merged', unmerged') (D.Simple (LDep dr (Dep dep (Constrained vr))) comp) =
394 ( M.insertWith mergeValues
395 (SimpleFlaggedDepKey dep comp)
396 (SimpleFlaggedDepValue dr vr)
397 merged'
398 , unmerged')
399 f (merged', unmerged') unmergeableDep = (merged', unmergeableDep : unmerged')
401 mergeValues :: SimpleFlaggedDepValue qpn
402 -> SimpleFlaggedDepValue qpn
403 -> SimpleFlaggedDepValue qpn
404 mergeValues (SimpleFlaggedDepValue dr1 vr1) (SimpleFlaggedDepValue dr2 vr2) =
405 SimpleFlaggedDepValue (unionDRs dr1 dr2) (vr1 .&&. vr2)
407 toFlaggedDep :: SimpleFlaggedDepKey qpn
408 -> SimpleFlaggedDepValue qpn
409 -> FlaggedDep qpn
410 toFlaggedDep (SimpleFlaggedDepKey dep comp) (SimpleFlaggedDepValue dr vr) =
411 D.Simple (LDep dr (Dep dep (Constrained vr))) comp
413 -- | Branch interpreter. Mutually recursive with 'convCondTree'.
415 -- Here, we try to simplify one of Cabal's condition tree branches into the
416 -- solver's flagged dependency format, which is weaker. Condition trees can
417 -- contain complex logical expression composed from flag choices and special
418 -- flags (such as architecture, or compiler flavour). We try to evaluate the
419 -- special flags and subsequently simplify to a tree that only depends on
420 -- simple flag choices.
422 -- This function takes a number of arguments:
424 -- 1. A map of flag values that have already been chosen. It allows
425 -- convBranch to avoid creating nested FlaggedDeps that are
426 -- controlled by the same flag and avoid creating DependencyReasons with
427 -- conflicting values for the same flag.
429 -- 2. The DependencyReason calculated at this point in the tree of
430 -- conditionals. The flag values in the DependencyReason are similar to
431 -- the values in the map above, except for the use of FlagBoth.
433 -- 3. Some pre dependency-solving known information ('OS', 'Arch',
434 -- 'CompilerInfo') for @os()@, @arch()@ and @impl()@ variables,
436 -- 4. The package name @'PN'@ which this condition tree
437 -- came from, so that we can correctly associate @flag()@
438 -- variables with the correct package name qualifier,
440 -- 5. The flag defaults 'FlagInfo' so that we can populate
441 -- 'Flagged' dependencies with 'FInfo',
443 -- 6. The name of the component 'Component' so we can record where
444 -- the fine-grained information about where the component came
445 -- from (see 'convCondTree'), and
447 -- 7. A selector to extract the 'BuildInfo' from the leaves of
448 -- the 'CondTree' (which actually contains the needed
449 -- dependency information.)
451 -- 8. The set of package names which should be considered internal
452 -- dependencies, and thus not handled as dependencies.
453 convBranch :: Map FlagName Bool
454 -> DependencyReason PN
455 -> PackageDescription
456 -> OS
457 -> Arch
458 -> CompilerInfo
459 -> PN
460 -> FlagInfo
461 -> Component
462 -> (a -> BuildInfo)
463 -> SolveExecutables
464 -> CondBranch ConfVar [Dependency] a
465 -> FlaggedDeps PN
466 convBranch flags dr pkg os arch cinfo pn fds comp getInfo solveExes (CondBranch c' t' mf') =
467 go c'
468 (\flags' dr' -> convCondTree flags' dr' pkg os arch cinfo pn fds comp getInfo solveExes t')
469 (\flags' dr' -> maybe [] (convCondTree flags' dr' pkg os arch cinfo pn fds comp getInfo solveExes) mf')
470 flags dr
471 where
472 go :: Condition ConfVar
473 -> (Map FlagName Bool -> DependencyReason PN -> FlaggedDeps PN)
474 -> (Map FlagName Bool -> DependencyReason PN -> FlaggedDeps PN)
475 -> Map FlagName Bool -> DependencyReason PN -> FlaggedDeps PN
476 go (Lit True) t _ = t
477 go (Lit False) _ f = f
478 go (CNot c) t f = go c f t
479 go (CAnd c d) t f = go c (go d t f) f
480 go (COr c d) t f = go c t (go d t f)
481 go (Var (PackageFlag fn)) t f = \flags' ->
482 case M.lookup fn flags' of
483 Just True -> t flags'
484 Just False -> f flags'
485 Nothing -> \dr' ->
486 -- Add each flag to the DependencyReason for all dependencies below,
487 -- including any extracted dependencies. Extracted dependencies are
488 -- introduced by both flag values (FlagBoth). Note that we don't
489 -- actually need to add the flag to the extracted dependencies for
490 -- correct backjumping; the information only improves log messages
491 -- by giving the user the full reason for each dependency.
492 let addFlagValue v = addFlagToDependencyReason fn v dr'
493 addFlag v = M.insert fn v flags'
494 in extractCommon (t (addFlag True) (addFlagValue FlagBoth))
495 (f (addFlag False) (addFlagValue FlagBoth))
496 ++ [ Flagged (FN pn fn) (fds M.! fn) (t (addFlag True) (addFlagValue FlagTrue))
497 (f (addFlag False) (addFlagValue FlagFalse)) ]
498 go (Var (OS os')) t f
499 | os == os' = t
500 | otherwise = f
501 go (Var (Arch arch')) t f
502 | arch == arch' = t
503 | otherwise = f
504 go (Var (Impl cf cvr)) t f
505 | matchImpl (compilerInfoId cinfo) ||
506 -- fixme: Nothing should be treated as unknown, rather than empty
507 -- list. This code should eventually be changed to either
508 -- support partial resolution of compiler flags or to
509 -- complain about incompletely configured compilers.
510 any matchImpl (fromMaybe [] $ compilerInfoCompat cinfo) = t
511 | otherwise = f
512 where
513 matchImpl (CompilerId cf' cv) = cf == cf' && checkVR cvr cv
515 addFlagToDependencyReason :: FlagName -> FlagValue -> DependencyReason pn -> DependencyReason pn
516 addFlagToDependencyReason fn v (DependencyReason pn' fs ss) =
517 DependencyReason pn' (M.insert fn v fs) ss
519 -- If both branches contain the same package as a simple dep, we lift it to
520 -- the next higher-level, but with the union of version ranges. This
521 -- heuristic together with deferring flag choices will then usually first
522 -- resolve this package, and try an already installed version before imposing
523 -- a default flag choice that might not be what we want.
525 -- Note that we make assumptions here on the form of the dependencies that
526 -- can occur at this point. In particular, no occurrences of Fixed, as all
527 -- dependencies below this point have been generated using 'convLibDep'.
529 -- WARNING: This is quadratic!
530 extractCommon :: Eq pn => FlaggedDeps pn -> FlaggedDeps pn -> FlaggedDeps pn
531 extractCommon ps ps' =
532 -- Union the DependencyReasons, because the extracted dependency can be
533 -- avoided by removing the dependency from either side of the
534 -- conditional.
535 [ D.Simple (LDep (unionDRs vs1 vs2) (Dep dep1 (Constrained $ vr1 .||. vr2))) comp
536 | D.Simple (LDep vs1 (Dep dep1 (Constrained vr1))) _ <- ps
537 , D.Simple (LDep vs2 (Dep dep2 (Constrained vr2))) _ <- ps'
538 , dep1 == dep2
541 -- | Merge DependencyReasons by unioning their variables.
542 unionDRs :: DependencyReason pn -> DependencyReason pn -> DependencyReason pn
543 unionDRs (DependencyReason pn' fs1 ss1) (DependencyReason _ fs2 ss2) =
544 DependencyReason pn' (M.union fs1 fs2) (S.union ss1 ss2)
546 -- | Convert a Cabal dependency on a set of library components (from a single
547 -- package) to solver-specific dependencies.
548 convLibDeps :: DependencyReason PN -> Dependency -> [LDep PN]
549 convLibDeps dr (Dependency pn vr libs) =
550 [ LDep dr $ Dep (PkgComponent pn (ExposedLib lib)) (Constrained vr)
551 | lib <- NonEmptySet.toList libs ]
553 -- | Convert a Cabal dependency on an executable (build-tools) to a solver-specific dependency.
554 convExeDep :: DependencyReason PN -> ExeDependency -> LDep PN
555 convExeDep dr (ExeDependency pn exe vr) = LDep dr $ Dep (PkgComponent pn (ExposedExe exe)) (Constrained vr)
557 -- | Convert setup dependencies
558 convSetupBuildInfo :: PN -> SetupBuildInfo -> FlaggedDeps PN
559 convSetupBuildInfo pn nfo =
560 [ D.Simple singleDep ComponentSetup
561 | dep <- setupDepends nfo
562 , singleDep <- convLibDeps (DependencyReason pn M.empty S.empty) dep ]