Skip to content

Commit 97a950d

Browse files
committed
feat(cabal-install-solver): all of it, second part
1 parent ca0a28d commit 97a950d

File tree

27 files changed

+365
-268
lines changed

27 files changed

+365
-268
lines changed

cabal-install-solver/src/Distribution/Solver/Modular.hs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ import Distribution.Solver.Modular.IndexConversion
3939
( convPIs )
4040
import Distribution.Solver.Modular.Log
4141
( SolverFailure(..), displayLogMessages )
42+
import Distribution.Solver.Modular.Message
43+
( renderSummarizedMessage )
4244
import Distribution.Solver.Modular.Package
4345
( PN )
4446
import Distribution.Solver.Modular.RetryLog
@@ -65,25 +67,26 @@ import Distribution.Solver.Types.Progress
6567
( Progress(..), foldProgress )
6668
import Distribution.Solver.Types.SummarizedMessage
6769
( SummarizedMessage(StringMsg) )
68-
import Distribution.Solver.Types.Variable ( Variable(..) )
69-
import Distribution.System
70-
( Platform(..) )
70+
import Distribution.Solver.Types.Variable
71+
( Variable(..) )
72+
import Distribution.Solver.Types.Toolchain
73+
7174
import Distribution.Simple.Setup
7275
( BooleanFlag(..) )
7376
import Distribution.Simple.Utils
7477
( ordNubBy )
7578
import Distribution.Verbosity ( normal, verbose )
76-
import Distribution.Solver.Modular.Message ( renderSummarizedMessage )
7779

7880
-- | Ties the two worlds together: classic cabal-install vs. the modular
7981
-- solver. Performs the necessary translations before and after.
8082
modularResolver :: SolverConfig -> DependencyResolver loc
81-
modularResolver sc (Platform arch os) cinfo iidx sidx pkgConfigDB pprefs pcs pns =
82-
uncurry postprocess <$> -- convert install plan
83-
solve' sc cinfo idx pkgConfigDB pprefs gcs pns
84-
where
83+
modularResolver sc toolchains pkgConfigDbs iidx sidx pprefs pcs pns = do
84+
uncurry postprocess <$> solve' sc cinfo pkgConfigDbs idx pprefs gcs pns
85+
where
86+
cinfo = fst <$> toolchains
87+
8588
-- Indices have to be converted into solver-specific uniform index.
86-
idx = convPIs os arch cinfo gcs (shadowPkgs sc) (strongFlags sc) (solveExecutables sc) iidx sidx
89+
idx = convPIs toolchains gcs (shadowPkgs sc) (strongFlags sc) (solveExecutables sc) iidx sidx
8790
-- Constraints have to be converted into a finite map indexed by PN.
8891
gcs = M.fromListWith (++) (map pair pcs)
8992
where
@@ -133,21 +136,21 @@ modularResolver sc (Platform arch os) cinfo iidx sidx pkgConfigDB pprefs pcs pns
133136
-- complete, i.e., it shows the whole chain of dependencies from the user
134137
-- targets to the conflicting packages.
135138
solve' :: SolverConfig
136-
-> CompilerInfo
139+
-> Staged CompilerInfo
140+
-> Staged (Maybe PkgConfigDb)
137141
-> Index
138-
-> Maybe PkgConfigDb
139142
-> (PN -> PackagePreferences)
140143
-> Map PN [LabeledPackageConstraint]
141144
-> Set PN
142145
-> Progress SummarizedMessage String (Assignment, RevDepMap)
143-
solve' sc cinfo idx pkgConfigDB pprefs gcs pns =
146+
solve' sc cinfo pkgConfigDb idx pprefs gcs pns =
144147
toProgress $ retry (runSolver printFullLog sc) createErrorMsg
145148
where
146149
runSolver :: Bool -> SolverConfig
147150
-> RetryLog SummarizedMessage SolverFailure (Assignment, RevDepMap)
148151
runSolver keepLog sc' =
149152
displayLogMessages keepLog $
150-
solve sc' cinfo idx pkgConfigDB pprefs gcs pns
153+
solve sc' cinfo pkgConfigDb idx pprefs gcs pns
151154

152155
createErrorMsg :: SolverFailure
153156
-> RetryLog SummarizedMessage String (Assignment, RevDepMap)

cabal-install-solver/src/Distribution/Solver/Modular/Builder.hs

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{-# LANGUAGE ScopedTypeVariables #-}
2+
{-# LANGUAGE NamedFieldPuns #-}
23
module Distribution.Solver.Modular.Builder (
34
buildTree
45
, splits -- for testing
@@ -35,6 +36,7 @@ import qualified Distribution.Solver.Modular.WeightedPSQ as W
3536

3637
import Distribution.Solver.Types.ComponentDeps
3738
import Distribution.Solver.Types.PackagePath
39+
import qualified Distribution.Solver.Types.Stage as Stage
3840

3941
-- | All state needed to build and link the search tree. It has a type variable
4042
-- because the linking phase doesn't need to know about the state used to build
@@ -138,40 +140,42 @@ addChildren bs@(BS { rdeps = rdm, open = gs, next = Goals })
138140

139141
-- If we have already picked a goal, then the choice depends on the kind
140142
-- of goal.
141-
--
142-
-- For a package, we look up the instances available in the global info,
143-
-- and then handle each instance in turn.
144-
addChildren bs@(BS { rdeps = rdm, index = idx, next = OneGoal (PkgGoal qpn@(Q _ pn) gr) }) =
145-
case M.lookup pn idx of
146-
Nothing -> FailF
147-
(varToConflictSet (P qpn) `CS.union` goalReasonToConflictSetWithConflict qpn gr)
148-
UnknownPackage
149-
Just pis -> PChoiceF qpn rdm gr (W.fromList (L.map (\ (i, info) ->
150-
([], POption i Nothing, bs { next = Instance qpn info }))
151-
(M.toList pis)))
152-
-- TODO: data structure conversion is rather ugly here
153-
154-
-- For a flag, we create only two subtrees, and we create them in the order
155-
-- that is indicated by the flag default.
156-
addChildren bs@(BS { rdeps = rdm, next = OneGoal (FlagGoal qfn@(FN qpn _) (FInfo b m w) t f gr) }) =
157-
FChoiceF qfn rdm gr weak m b (W.fromList
158-
[([if b then 0 else 1], True, (extendOpen qpn t bs) { next = Goals }),
159-
([if b then 1 else 0], False, (extendOpen qpn f bs) { next = Goals })])
160-
where
161-
trivial = L.null t && L.null f
162-
weak = WeakOrTrivial $ unWeakOrTrivial w || trivial
163-
164-
-- For a stanza, we also create only two subtrees. The order is initially
165-
-- False, True. This can be changed later by constraints (force enabling
166-
-- the stanza by replacing the False branch with failure) or preferences
167-
-- (try enabling the stanza if possible by moving the True branch first).
168-
169-
addChildren bs@(BS { rdeps = rdm, next = OneGoal (StanzaGoal qsn@(SN qpn _) t gr) }) =
170-
SChoiceF qsn rdm gr trivial (W.fromList
171-
[([0], False, bs { next = Goals }),
172-
([1], True, (extendOpen qpn t bs) { next = Goals })])
173-
where
174-
trivial = WeakOrTrivial (L.null t)
143+
addChildren bs@(BS { rdeps, index, next = OneGoal goal }) =
144+
case goal of
145+
PkgGoal qpn@(Q (PackagePath s _) pn) gr ->
146+
-- For a package goal, we look up the instances available in the global
147+
-- info, and then handle each instance in turn.
148+
case M.lookup pn index of
149+
Nothing -> FailF
150+
(varToConflictSet (P qpn) `CS.union` goalReasonToConflictSetWithConflict qpn gr)
151+
UnknownPackage
152+
Just pis -> PChoiceF qpn rdeps gr $ W.fromList
153+
[ ([], POption i Nothing, bs { next = Instance qpn info })
154+
| (i@(I s' _ver _loc), info) <- M.toList pis
155+
-- Only instances belonging to the same stage are allowed.
156+
, s == s'
157+
]
158+
-- For a flag, we create only two subtrees, and we create them in the order
159+
-- that is indicated by the flag default.
160+
FlagGoal qfn@(FN qpn _) (FInfo b m w) t f gr ->
161+
FChoiceF qfn rdeps gr weak m b $ W.fromList
162+
[ ([if b then 0 else 1], True, (extendOpen qpn t bs) { next = Goals })
163+
, ([if b then 1 else 0], False, (extendOpen qpn f bs) { next = Goals })
164+
]
165+
where
166+
trivial = L.null t && L.null f
167+
weak = WeakOrTrivial $ unWeakOrTrivial w || trivial
168+
-- For a stanza, we also create only two subtrees. The order is initially
169+
-- False, True. This can be changed later by constraints (force enabling
170+
-- the stanza by replacing the False branch with failure) or preferences
171+
-- (try enabling the stanza if possible by moving the True branch first).
172+
StanzaGoal qsn@(SN qpn _) t gr ->
173+
SChoiceF qsn rdeps gr trivial $ W.fromList
174+
[ ([0], False, bs { next = Goals })
175+
, ([1], True, (extendOpen qpn t bs) { next = Goals })
176+
]
177+
where
178+
trivial = WeakOrTrivial (L.null t)
175179

176180
-- For a particular instance, we change the state: we update the scope,
177181
-- and furthermore we update the set of goals.
@@ -259,7 +263,7 @@ buildTree idx igs =
259263
where
260264
topLevelGoal qpn = PkgGoal qpn UserGoal
261265

262-
qpns = L.map (Q (PackagePath QualToplevel)) igs
266+
qpns = L.map (Q (PackagePath Stage.Host QualToplevel)) igs
263267

264268
{-------------------------------------------------------------------------------
265269
Goals

cabal-install-solver/src/Distribution/Solver/Modular/ConfiguredConversion.hs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import Data.Maybe
66
import Prelude hiding (pi)
77
import Data.Either (partitionEithers)
88

9-
import Distribution.Package (UnitId, packageId)
10-
119
import qualified Distribution.Simple.PackageIndex as SI
1210

1311
import Distribution.Solver.Modular.Configured
@@ -21,41 +19,45 @@ import Distribution.Solver.Types.SolverId
2119
import Distribution.Solver.Types.SolverPackage
2220
import Distribution.Solver.Types.InstSolverPackage
2321
import Distribution.Solver.Types.SourcePackage
22+
import Distribution.Solver.Types.Stage (Staged (..))
2423

2524
-- | Converts from the solver specific result @CP QPN@ into
2625
-- a 'ResolverPackage', which can then be converted into
2726
-- the install plan.
28-
convCP :: SI.InstalledPackageIndex ->
27+
convCP :: Staged SI.InstalledPackageIndex ->
2928
CI.PackageIndex (SourcePackage loc) ->
3029
CP QPN -> ResolverPackage loc
3130
convCP iidx sidx (CP qpi fa es ds) =
32-
case convPI qpi of
33-
Left pi -> PreExisting $
31+
case qpi of
32+
-- Installed
33+
(PI qpn (I s _ (Inst pi))) ->
34+
PreExisting $
3435
InstSolverPackage {
35-
instSolverPkgIPI = fromJust $ SI.lookupUnitId iidx pi,
36+
instSolverStage = s,
37+
instSolverQPN = qpn,
38+
instSolverPkgIPI = fromMaybe (error "convCP: lookupUnitId failed") $ SI.lookupUnitId (getStage iidx s) pi,
3639
instSolverPkgLibDeps = fmap fst ds',
3740
instSolverPkgExeDeps = fmap snd ds'
3841
}
39-
Right pi -> Configured $
42+
-- "In repo" i.e. a source package
43+
(PI qpn@(Q _path pn) (I s v (InRepo _pn))) ->
44+
let pi = PackageIdentifier pn v in
45+
Configured $
4046
SolverPackage {
41-
solverPkgSource = srcpkg,
47+
solverPkgStage = s,
48+
solverPkgQPN = qpn,
49+
solverPkgSource = fromMaybe (error "convCP: lookupPackageId failed") $ CI.lookupPackageId sidx pi,
4250
solverPkgFlags = fa,
4351
solverPkgStanzas = es,
4452
solverPkgLibDeps = fmap fst ds',
4553
solverPkgExeDeps = fmap snd ds'
4654
}
47-
where
48-
srcpkg = fromMaybe (error "convCP: lookupPackageId failed") $ CI.lookupPackageId sidx pi
4955
where
5056
ds' :: ComponentDeps ([SolverId] {- lib -}, [SolverId] {- exe -})
5157
ds' = fmap (partitionEithers . map convConfId) ds
5258

53-
convPI :: PI QPN -> Either UnitId PackageId
54-
convPI (PI _ (I _ (Inst pi))) = Left pi
55-
convPI pi = Right (packageId (either id id (convConfId pi)))
56-
5759
convConfId :: PI QPN -> Either SolverId {- is lib -} SolverId {- is exe -}
58-
convConfId (PI (Q (PackagePath q) pn) (I v loc)) =
60+
convConfId (PI (Q (PackagePath _stage q) pn) (I _stage' v loc)) =
5961
case loc of
6062
Inst pi -> Left (PreExistingId sourceId pi)
6163
_otherwise

cabal-install-solver/src/Distribution/Solver/Modular/Dependency.hs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import Distribution.Solver.Types.PackagePath
6262
import Distribution.Types.LibraryName
6363
import Distribution.Types.PkgconfigVersionRange
6464
import Distribution.Types.UnqualComponentName
65+
import Distribution.Solver.Types.Stage
6566

6667
{-------------------------------------------------------------------------------
6768
Constrained instances
@@ -97,6 +98,7 @@ data FlaggedDep qpn
9798
Stanza (SN qpn) (TrueFlaggedDeps qpn)
9899
| -- | Dependencies which are always enabled, for the component 'comp'.
99100
Simple (LDep qpn) Component
101+
deriving Show
100102

101103
-- | Conservatively flatten out flagged dependencies
102104
--
@@ -119,6 +121,7 @@ type FalseFlaggedDeps qpn = FlaggedDeps qpn
119121
-- depending; having a 'Functor' instance makes bugs where we don't distinguish
120122
-- these two far too likely. (By rights 'LDep' ought to have two type variables.)
121123
data LDep qpn = LDep (DependencyReason qpn) (Dep qpn)
124+
deriving Show
122125

123126
-- | A dependency (constraint) associates a package name with a constrained
124127
-- instance. It can also represent other types of dependencies, such as
@@ -132,7 +135,7 @@ data Dep qpn
132135
Lang Language
133136
| -- | dependency on a pkg-config package
134137
Pkg PkgconfigName PkgconfigVersionRange
135-
deriving (Functor)
138+
deriving (Functor, Show)
136139

137140
-- | An exposed component within a package. This type is used to represent
138141
-- build-depends and build-tool-depends dependencies.
@@ -166,7 +169,7 @@ showDependencyReason (DependencyReason qpn flags stanzas) =
166169
-- NOTE: It's the _dependencies_ of a package that may or may not be independent
167170
-- from the package itself. Package flag choices must of course be consistent.
168171
qualifyDeps :: QPN -> FlaggedDeps PN -> FlaggedDeps QPN
169-
qualifyDeps (Q pp@(PackagePath q) pn) = go
172+
qualifyDeps (Q pp@(PackagePath s q) pn) = go
170173
where
171174
go :: FlaggedDeps PN -> FlaggedDeps QPN
172175
go = map go1
@@ -191,24 +194,17 @@ qualifyDeps (Q pp@(PackagePath q) pn) = go
191194
goD (Ext ext) _ = Ext ext
192195
goD (Lang lang) _ = Lang lang
193196
goD (Pkg pkn vr) _ = Pkg pkn vr
194-
goD (Dep dep@(PkgComponent qpn (ExposedExe _)) ci) _ =
195-
Dep (Q (PackagePath (QualExe pn qpn)) <$> dep) ci
196-
goD (Dep dep@(PkgComponent _qpn (ExposedLib _)) ci) comp
197-
| comp == ComponentSetup = Dep (Q (PackagePath (QualSetup pn)) <$> dep) ci
198-
| otherwise = Dep (Q (PackagePath inheritedQ) <$> dep) ci
199-
200-
-- If P has a setup dependency on Q, and Q has a regular dependency on R, then
201-
-- we say that the 'Setup' qualifier is inherited: P has an (indirect) setup
202-
-- dependency on R. We do not do this for the base qualifier however.
203-
--
204-
-- The inherited qualifier is only used for regular dependencies; for setup
205-
-- and base dependencies we override the existing qualifier. See #3160 for
206-
-- a detailed discussion.
207-
inheritedQ :: Qualifier
208-
inheritedQ = case q of
209-
QualSetup _ -> q
210-
QualExe _ _ -> q
211-
QualToplevel -> q
197+
198+
-- In case of executable and setup dependencies, we need to qualify the dependency
199+
-- with the previsous stage (e.g. Host -> Build).
200+
goD (Dep dep@(PkgComponent qpn (ExposedExe _)) ci) _component =
201+
Dep (Q (PackagePath (prevStage s) (QualExe pn qpn)) <$> dep) ci
202+
203+
goD (Dep dep@(PkgComponent _qpn (ExposedLib _)) ci) ComponentSetup =
204+
Dep (Q (PackagePath (prevStage s) (QualSetup pn)) <$> dep) ci
205+
206+
goD (Dep dep@(PkgComponent _qpn _) ci) _component =
207+
Dep (Q (PackagePath s q) <$> dep) ci
212208

213209
-- | Remove qualifiers from set of dependencies
214210
--

cabal-install-solver/src/Distribution/Solver/Modular/Explore.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ exploreLog mbj enableBj fineGrainedConflicts (CountConflicts countConflicts) idx
268268
-- Skipping it is an optimization. If false, it returns a new conflict set
269269
-- to be merged with the previous one.
270270
couldResolveConflicts :: QPN -> POption -> S.Set CS.Conflict -> Maybe ConflictSet
271-
couldResolveConflicts currentQPN@(Q _ pn) (POption i@(I v _) _) conflicts =
271+
couldResolveConflicts currentQPN@(Q _ pn) (POption i@(I _stage v _) _) conflicts =
272272
let (PInfo deps _ _ _) = idx M.! pn M.! i
273273
qdeps = qualifyDeps currentQPN deps
274274

0 commit comments

Comments
 (0)