1 module Distribution
.Solver
.Modular
.IndexConversion
5 import Distribution
.Solver
.Compat
.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
)
60 convPIs os arch comp constraints sip strfl solveExes iidx sidx
=
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
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
]
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
))
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
)
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
)
96 -- TODO: Handle sub-libraries and visibility.
98 M
.singleton
(ExposedLib LMainLibName
)
100 compIsVisible
= IsVisible
True
101 , compIsBuildable
= IsBuildable
True
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,
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
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
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
) =
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
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
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
)
200 ++ prefix
(Stanza
(SN pn BenchStanzas
))
201 (L
.map (\(nm
, ds
) -> conv
(ComponentBench nm
) benchmarkBuildInfo
(addStanza BenchStanzas initDR
) ds
)
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
)
215 components
:: Map ExposedComponent ComponentInfo
216 components
= M
.fromList
$ libComps
++ subLibComps
++ exeComps
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
224 compIsVisible
= IsVisible
True
225 , compIsBuildable
= IsBuildable
$ testCondition
(buildable
. buildInfo
) exe
/= Just
False
228 |
(name
, exe
) <- exes
]
230 libToComponentInfo lib
=
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
252 -> [LabeledPackageConstraint
]
254 -> CondTree ConfVar
[Dependency
] a
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
262 flagAssignment
:: [(FlagName
, Bool)]
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
283 matchImpl
(CompilerId cf
' cv
) = cf
== cf
' && checkVR cvr cv
284 go
(Var
(PackageFlag f
))
285 | Just b
<- L
.lookup f flagAssignment
= Lit b
290 Lit
True -> Lit
False
291 Lit
False -> Lit
True
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
'
302 (Lit
False, _
) -> Lit
False
304 (_
, Lit
False) -> Lit
False
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
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
)))
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
->
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
340 [ D
.Simple singleDep comp
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
355 , exeDep
<- getAllToolDependencies pkg bi
356 , not $ isInternal pkg exeDep
361 data SimpleFlaggedDepKey qpn
=
362 SimpleFlaggedDepKey
(PkgComponent qpn
) Component
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
387 (merged
, unmerged
) = L
.foldl' f
(M
.empty, []) deps
390 => (Map
(SimpleFlaggedDepKey qpn
) (SimpleFlaggedDepValue qpn
), FlaggedDeps 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
)
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
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
464 -> CondBranch ConfVar
[Dependency
] a
466 convBranch flags dr pkg os arch cinfo pn fds comp getInfo solveExes
(CondBranch c
' t
' mf
') =
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
')
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
'
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
501 go
(Var
(Arch arch
')) t 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
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
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
'
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
]