Skip to content

Commit aa2ec04

Browse files
author
Iñaki García Etxebarria
committed
Make the solver aware of pkg-config constraints
When solving, we now discard plans that would involve packages with a pkgconfig-depends constraint which is not satisfiable with the current set of installed packages (as listed by pkg-config --list-all). This fixes #3016. It is possible (in principle, although it should be basically impossible in practice) that "pkg-config --modversion pkg1 pkg2... pkgN" fails to execute for various reasons, in particular because N is too large, so the command line becomes too long for the operating system limits. If this happens, revert to the previous behavior of accepting any install plan, regardless of any pkgconfig-depends constraints.
1 parent 50e7cf0 commit aa2ec04

File tree

19 files changed

+249
-57
lines changed

19 files changed

+249
-57
lines changed

cabal-install/Distribution/Client/Configure.hs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import Distribution.Client.InstallPlan (InstallPlan)
2727
import Distribution.Client.IndexUtils as IndexUtils
2828
( getSourcePackages, getInstalledPackages )
2929
import Distribution.Client.PackageIndex ( PackageIndex, elemByPackageName )
30+
import Distribution.Client.PkgConfigDb (PkgConfigDb, readPkgConfigDb)
3031
import Distribution.Client.Setup
3132
( ConfigExFlags(..), configureCommand, filterConfigureFlags
3233
, RepoContext(..) )
@@ -110,11 +111,13 @@ configure verbosity packageDBs repoCtxt comp platform conf
110111

111112
installedPkgIndex <- getInstalledPackages verbosity comp packageDBs conf
112113
sourcePkgDb <- getSourcePackages verbosity repoCtxt
114+
pkgConfigDb <- readPkgConfigDb verbosity conf
115+
113116
checkConfigExFlags verbosity installedPkgIndex
114117
(packageIndex sourcePkgDb) configExFlags
115118

116119
progress <- planLocalPackage verbosity comp platform configFlags configExFlags
117-
installedPkgIndex sourcePkgDb
120+
installedPkgIndex sourcePkgDb pkgConfigDb
118121

119122
notice verbosity "Resolving dependencies..."
120123
maybePlan <- foldProgress logMsg (return . Left) (return . Right)
@@ -269,10 +272,10 @@ planLocalPackage :: Verbosity -> Compiler
269272
-> ConfigFlags -> ConfigExFlags
270273
-> InstalledPackageIndex
271274
-> SourcePackageDb
275+
-> PkgConfigDb
272276
-> IO (Progress String String InstallPlan)
273277
planLocalPackage verbosity comp platform configFlags configExFlags
274-
installedPkgIndex
275-
(SourcePackageDb _ packagePrefs) = do
278+
installedPkgIndex (SourcePackageDb _ packagePrefs) pkgConfigDb = do
276279
pkg <- readPackageDescription verbosity =<< defaultPackageDesc verbosity
277280
solver <- chooseSolver verbosity (fromFlag $ configSolver configExFlags)
278281
(compilerInfo comp)
@@ -326,7 +329,7 @@ planLocalPackage verbosity comp platform configFlags configExFlags
326329
(SourcePackageDb mempty packagePrefs)
327330
[SpecificSourcePackage localPkg]
328331

329-
return (resolveDependencies platform (compilerInfo comp) solver resolverParams)
332+
return (resolveDependencies platform (compilerInfo comp) pkgConfigDb solver resolverParams)
330333

331334

332335
-- | Call an installer for an 'SourcePackage' but override the configure

cabal-install/Distribution/Client/Dependency.hs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import Distribution.Simple.PackageIndex (InstalledPackageIndex)
6969
import qualified Distribution.Simple.PackageIndex as InstalledPackageIndex
7070
import qualified Distribution.Client.InstallPlan as InstallPlan
7171
import Distribution.Client.InstallPlan (InstallPlan)
72+
import Distribution.Client.PkgConfigDb (PkgConfigDb)
7273
import Distribution.Client.Types
7374
( SourcePackageDb(SourcePackageDb), SourcePackage(..)
7475
, ConfiguredPackage(..), ConfiguredId(..)
@@ -523,25 +524,26 @@ runSolver Modular = modularResolver
523524
--
524525
resolveDependencies :: Platform
525526
-> CompilerInfo
527+
-> PkgConfigDb
526528
-> Solver
527529
-> DepResolverParams
528530
-> Progress String String InstallPlan
529531

530532
--TODO: is this needed here? see dontUpgradeNonUpgradeablePackages
531-
resolveDependencies platform comp _solver params
533+
resolveDependencies platform comp _pkgConfigDB _solver params
532534
| null (depResolverTargets params)
533535
= return (validateSolverResult platform comp indGoals [])
534536
where
535537
indGoals = depResolverIndependentGoals params
536538

537-
resolveDependencies platform comp solver params =
539+
resolveDependencies platform comp pkgConfigDB solver params =
538540

539541
Step (showDepResolverParams finalparams)
540542
$ fmap (validateSolverResult platform comp indGoals)
541543
$ runSolver solver (SolverConfig reorderGoals indGoals noReinstalls
542544
shadowing strFlags maxBkjumps)
543545
platform comp installedPkgIndex sourcePkgIndex
544-
preferences constraints targets
546+
pkgConfigDB preferences constraints targets
545547
where
546548

547549
finalparams @ (DepResolverParams

cabal-install/Distribution/Client/Dependency/Modular.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ import Distribution.System
3434
-- | Ties the two worlds together: classic cabal-install vs. the modular
3535
-- solver. Performs the necessary translations before and after.
3636
modularResolver :: SolverConfig -> DependencyResolver
37-
modularResolver sc (Platform arch os) cinfo iidx sidx pprefs pcs pns =
37+
modularResolver sc (Platform arch os) cinfo iidx sidx pkgConfigDB pprefs pcs pns =
3838
fmap (uncurry postprocess) $ -- convert install plan
3939
logToProgress (maxBackjumps sc) $ -- convert log format into progress format
40-
solve sc cinfo idx pprefs gcs pns
40+
solve sc cinfo idx pkgConfigDB pprefs gcs pns
4141
where
4242
-- Indices have to be converted into solver-specific uniform index.
4343
idx = convPIs os arch cinfo (shadowPkgs sc) (strongFlags sc) iidx sidx

cabal-install/Distribution/Client/Dependency/Modular/Assignment.hs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import Distribution.Client.Dependency.Modular.Configured
2727
import Distribution.Client.Dependency.Modular.Dependency
2828
import Distribution.Client.Dependency.Modular.Flag
2929
import Distribution.Client.Dependency.Modular.Package
30+
import Distribution.Client.Dependency.Modular.Version
3031

3132
-- | A (partial) package assignment. Qualified package names
3233
-- are associated with instances.
@@ -62,9 +63,10 @@ data PreAssignment = PA PPreAssignment FAssignment SAssignment
6263
-- or the successfully extended assignment.
6364
extend :: (Extension -> Bool) -- ^ is a given extension supported
6465
-> (Language -> Bool) -- ^ is a given language supported
66+
-> (PN -> VR -> Bool) -- ^ is a given pkg-config requirement satisfiable
6567
-> Goal QPN
6668
-> PPreAssignment -> [Dep QPN] -> Either (ConflictSet QPN, [Dep QPN]) PPreAssignment
67-
extend extSupported langSupported goal@(Goal var _) = foldM extendSingle
69+
extend extSupported langSupported pkgPresent goal@(Goal var _) = foldM extendSingle
6870
where
6971

7072
extendSingle :: PPreAssignment -> Dep QPN
@@ -75,6 +77,9 @@ extend extSupported langSupported goal@(Goal var _) = foldM extendSingle
7577
extendSingle a (Lang lang) =
7678
if langSupported lang then Right a
7779
else Left (toConflictSet goal, [Lang lang])
80+
extendSingle a (Pkg pn vr) =
81+
if pkgPresent pn vr then Right a
82+
else Left (toConflictSet goal, [Pkg pn vr])
7883
extendSingle a (Dep qpn ci) =
7984
let ci' = M.findWithDefault (Constrained []) qpn a
8085
in case (\ x -> M.insert qpn x a) <$> merge ci' ci of

cabal-install/Distribution/Client/Dependency/Modular/Builder.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ extendOpen qpn' gs s@(BS { rdeps = gs', open = o' }) = go gs' o' gs
6161
-- code above is correct; insert/adjust have different arg order
6262
go g o ( (OpenGoal (Simple (Ext _ext ) _) _gr) : ngs) = go g o ngs
6363
go g o ( (OpenGoal (Simple (Lang _lang)_) _gr) : ngs) = go g o ngs
64+
go g o ( (OpenGoal (Simple (Pkg _pn _vr)_) _gr) : ngs)= go g o ngs
6465

6566
cons' = P.cons . forgetCompOpenGoal
6667

@@ -121,6 +122,8 @@ build = ana go
121122
error "Distribution.Client.Dependency.Modular.Builder: build.go called with Ext goal"
122123
go (BS { index = _ , next = OneGoal (OpenGoal (Simple (Lang _ ) _) _ ) }) =
123124
error "Distribution.Client.Dependency.Modular.Builder: build.go called with Lang goal"
125+
go (BS { index = _ , next = OneGoal (OpenGoal (Simple (Pkg _ _ ) _) _ ) }) =
126+
error "Distribution.Client.Dependency.Modular.Builder: build.go called with Pkg goal"
124127
go bs@(BS { index = idx, next = OneGoal (OpenGoal (Simple (Dep qpn@(Q _ pn) _) _) gr) }) =
125128
case M.lookup pn idx of
126129
Nothing -> FailF (toConflictSet (Goal (P qpn) gr)) (BuildFailureNotInIndex pn)

cabal-install/Distribution/Client/Dependency/Modular/Dependency.hs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ type FalseFlaggedDeps qpn = FlaggedDeps Component qpn
198198
data Dep qpn = Dep qpn (CI qpn) -- dependency on a package
199199
| Ext Extension -- dependency on a language extension
200200
| Lang Language -- dependency on a language version
201+
| Pkg PN VR -- dependency on a pkg-config package
201202
deriving (Eq, Show)
202203

203204
showDep :: Dep QPN -> String
@@ -210,6 +211,9 @@ showDep (Dep qpn ci ) =
210211
showQPN qpn ++ showCI ci
211212
showDep (Ext ext) = "requires " ++ display ext
212213
showDep (Lang lang) = "requires " ++ display lang
214+
showDep (Pkg pn vr) = "requires pkg-config package "
215+
++ display pn ++ display vr
216+
++ ", not found in the pkg-config database"
213217

214218
-- | Options for goal qualification (used in 'qualifyDeps')
215219
--
@@ -253,6 +257,7 @@ qualifyDeps QO{..} (Q pp' pn) = go
253257
goD :: Dep PN -> Component -> Dep QPN
254258
goD (Ext ext) _ = Ext ext
255259
goD (Lang lang) _ = Lang lang
260+
goD (Pkg pkn vr) _ = Pkg pkn vr
256261
goD (Dep dep ci) comp
257262
| qBase dep = Dep (Q (Base pn pp) dep) (fmap (Q pp) ci)
258263
| qSetup comp = Dep (Q (Setup pn pp) dep) (fmap (Q pp) ci)
@@ -337,6 +342,7 @@ instance ResetGoal Dep where
337342
resetGoal g (Dep qpn ci) = Dep qpn (resetGoal g ci)
338343
resetGoal _ (Ext ext) = Ext ext
339344
resetGoal _ (Lang lang) = Lang lang
345+
resetGoal _ (Pkg pn vr) = Pkg pn vr
340346

341347
instance ResetGoal Goal where
342348
resetGoal = const
@@ -376,6 +382,8 @@ close (OpenGoal (Simple (Ext _) _) _ ) =
376382
error "Distribution.Client.Dependency.Modular.Dependency.close: called on Ext goal"
377383
close (OpenGoal (Simple (Lang _) _) _ ) =
378384
error "Distribution.Client.Dependency.Modular.Dependency.close: called on Lang goal"
385+
close (OpenGoal (Simple (Pkg _ _) _) _ ) =
386+
error "Distribution.Client.Dependency.Modular.Dependency.close: called on Pkg goal"
379387
close (OpenGoal (Flagged qfn _ _ _ ) gr) = Goal (F qfn) gr
380388
close (OpenGoal (Stanza qsn _) gr) = Goal (S qsn) gr
381389

cabal-install/Distribution/Client/Dependency/Modular/IndexConversion.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ convCondTree os arch cinfo pi@(PI pn _) fds comp getInfo (CondNode info ds branc
143143
L.map (\d -> D.Simple (convDep pn d) comp) ds -- unconditional package dependencies
144144
++ L.map (\e -> D.Simple (Ext e) comp) (PD.allExtensions bi) -- unconditional extension dependencies
145145
++ L.map (\l -> D.Simple (Lang l) comp) (PD.allLanguages bi) -- unconditional language dependencies
146+
++ L.map (\(Dependency pkn vr) -> D.Simple (Pkg pkn vr) comp) (PD.pkgconfigDepends bi) -- unconditional pkg-config dependencies
146147
++ concatMap (convBranch os arch cinfo pi fds comp getInfo) branches
147148
where
148149
bi = getInfo info

cabal-install/Distribution/Client/Dependency/Modular/Linking.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ linkDeps parents pp' = mapM_ go
278278
-- No choice is involved, just checking, so there is nothing to link.
279279
go (Simple (Ext _) _) = return ()
280280
go (Simple (Lang _) _) = return ()
281+
-- Similarly for pkg-config constraints
282+
go (Simple (Pkg _ _) _) = return ()
281283
go (Flagged fn _ t f) = do
282284
vs <- get
283285
case M.lookup fn (vsFlags vs) of

cabal-install/Distribution/Client/Dependency/Modular/Solver.hs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import Data.Map as M
77

88
import Distribution.Compiler (CompilerInfo)
99

10+
import Distribution.Client.PkgConfigDb (PkgConfigDb)
11+
1012
import Distribution.Client.Dependency.Types
1113

1214
import Distribution.Client.Dependency.Modular.Assignment
@@ -60,11 +62,12 @@ data SolverConfig = SolverConfig {
6062
solve :: SolverConfig -> -- ^ solver parameters
6163
CompilerInfo ->
6264
Index -> -- ^ all available packages as an index
65+
PkgConfigDb -> -- ^ available pkg-config pkgs
6366
(PN -> PackagePreferences) -> -- ^ preferences
6467
Map PN [LabeledPackageConstraint] -> -- ^ global constraints
6568
[PN] -> -- ^ global goals
6669
Log Message (Assignment, RevDepMap)
67-
solve sc cinfo idx userPrefs userConstraints userGoals =
70+
solve sc cinfo idx pkgConfigDB userPrefs userConstraints userGoals =
6871
explorePhase $
6972
detectCyclesPhase$
7073
heuristicsPhase $
@@ -86,7 +89,7 @@ solve sc cinfo idx userPrefs userConstraints userGoals =
8689
P.enforcePackageConstraints userConstraints .
8790
P.enforceSingleInstanceRestriction .
8891
validateLinking idx .
89-
validateTree cinfo idx
92+
validateTree cinfo idx pkgConfigDB
9093
prunePhase = (if avoidReinstalls sc then P.avoidReinstalls (const True) else id) .
9194
-- packages that can never be "upgraded":
9295
P.requireInstalled (`elem` [ PackageName "base"

cabal-install/Distribution/Client/Dependency/Modular/Validate.hs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ import Distribution.Client.Dependency.Modular.Index
2525
import Distribution.Client.Dependency.Modular.Package
2626
import qualified Distribution.Client.Dependency.Modular.PSQ as P
2727
import Distribution.Client.Dependency.Modular.Tree
28+
import Distribution.Client.Dependency.Modular.Version (VR)
2829

2930
import Distribution.Client.ComponentDeps (Component)
31+
import Distribution.Client.PkgConfigDb (PkgConfigDb, pkgConfigPkgIsPresent)
3032

3133
-- In practice, most constraints are implication constraints (IF we have made
3234
-- a number of choices, THEN we also have to ensure that). We call constraints
@@ -82,6 +84,7 @@ import Distribution.Client.ComponentDeps (Component)
8284
data ValidateState = VS {
8385
supportedExt :: Extension -> Bool,
8486
supportedLang :: Language -> Bool,
87+
presentPkgs :: PN -> VR -> Bool,
8588
index :: Index,
8689
saved :: Map QPN (FlaggedDeps Component QPN), -- saved, scoped, dependencies
8790
pa :: PreAssignment,
@@ -132,6 +135,7 @@ validate = cata go
132135
PA ppa pfa psa <- asks pa -- obtain current preassignment
133136
extSupported <- asks supportedExt -- obtain the supported extensions
134137
langSupported <- asks supportedLang -- obtain the supported languages
138+
pkgPresent <- asks presentPkgs -- obtain the present pkg-config pkgs
135139
idx <- asks index -- obtain the index
136140
svd <- asks saved -- obtain saved dependencies
137141
qo <- asks qualifyOptions
@@ -144,7 +148,7 @@ validate = cata go
144148
let goal = Goal (P qpn) gr
145149
let newactives = Dep qpn (Fixed i goal) : L.map (resetGoal goal) (extractDeps pfa psa qdeps)
146150
-- We now try to extend the partial assignment with the new active constraints.
147-
let mnppa = extend extSupported langSupported goal ppa newactives
151+
let mnppa = extend extSupported langSupported pkgPresent goal ppa newactives
148152
-- In case we continue, we save the scoped dependencies
149153
let nsvd = M.insert qpn qdeps svd
150154
case mfr of
@@ -162,6 +166,7 @@ validate = cata go
162166
PA ppa pfa psa <- asks pa -- obtain current preassignment
163167
extSupported <- asks supportedExt -- obtain the supported extensions
164168
langSupported <- asks supportedLang -- obtain the supported languages
169+
pkgPresent <- asks presentPkgs -- obtain the present pkg-config pkgs
165170
svd <- asks saved -- obtain saved dependencies
166171
-- Note that there should be saved dependencies for the package in question,
167172
-- because while building, we do not choose flags before we see the packages
@@ -176,7 +181,7 @@ validate = cata go
176181
-- we have chosen a new flag.
177182
let newactives = extractNewDeps (F qfn) gr b npfa psa qdeps
178183
-- As in the package case, we try to extend the partial assignment.
179-
case extend extSupported langSupported (Goal (F qfn) gr) ppa newactives of
184+
case extend extSupported langSupported pkgPresent (Goal (F qfn) gr) ppa newactives of
180185
Left (c, d) -> return (Fail c (Conflicting d)) -- inconsistency found
181186
Right nppa -> local (\ s -> s { pa = PA nppa npfa psa }) r
182187

@@ -186,6 +191,7 @@ validate = cata go
186191
PA ppa pfa psa <- asks pa -- obtain current preassignment
187192
extSupported <- asks supportedExt -- obtain the supported extensions
188193
langSupported <- asks supportedLang -- obtain the supported languages
194+
pkgPresent <- asks presentPkgs -- obtain the present pkg-config pkgs
189195
svd <- asks saved -- obtain saved dependencies
190196
-- Note that there should be saved dependencies for the package in question,
191197
-- because while building, we do not choose flags before we see the packages
@@ -200,7 +206,7 @@ validate = cata go
200206
-- we have chosen a new flag.
201207
let newactives = extractNewDeps (S qsn) gr b pfa npsa qdeps
202208
-- As in the package case, we try to extend the partial assignment.
203-
case extend extSupported langSupported (Goal (S qsn) gr) ppa newactives of
209+
case extend extSupported langSupported pkgPresent (Goal (S qsn) gr) ppa newactives of
204210
Left (c, d) -> return (Fail c (Conflicting d)) -- inconsistency found
205211
Right nppa -> local (\ s -> s { pa = PA nppa pfa npsa }) r
206212

@@ -248,14 +254,15 @@ extractNewDeps v gr b fa sa = go
248254
Just False -> []
249255

250256
-- | Interface.
251-
validateTree :: CompilerInfo -> Index -> Tree QGoalReasonChain -> Tree QGoalReasonChain
252-
validateTree cinfo idx t = runReader (validate t) VS {
257+
validateTree :: CompilerInfo -> Index -> PkgConfigDb -> Tree QGoalReasonChain -> Tree QGoalReasonChain
258+
validateTree cinfo idx pkgConfigDb t = runReader (validate t) VS {
253259
supportedExt = maybe (const True) -- if compiler has no list of extensions, we assume everything is supported
254260
(\ es -> let s = S.fromList es in \ x -> S.member x s)
255261
(compilerInfoExtensions cinfo)
256262
, supportedLang = maybe (const True)
257263
(flip L.elem) -- use list lookup because language list is small and no Ord instance
258264
(compilerInfoLanguages cinfo)
265+
, presentPkgs = pkgConfigPkgIsPresent pkgConfigDb
259266
, index = idx
260267
, saved = M.empty
261268
, pa = PA M.empty M.empty M.empty

cabal-install/Distribution/Client/Dependency/TopDown.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ search configure pref constraints =
251251
-- the standard 'DependencyResolver' interface.
252252
--
253253
topDownResolver :: DependencyResolver
254-
topDownResolver platform cinfo installedPkgIndex sourcePkgIndex
254+
topDownResolver platform cinfo installedPkgIndex sourcePkgIndex _pkgConfigDB
255255
preferences constraints targets =
256256
mapMessages $ topDownResolver'
257257
platform cinfo

cabal-install/Distribution/Client/Dependency/Types.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ import Data.Monoid
4949
( Monoid(..) )
5050
#endif
5151

52+
import Distribution.Client.PkgConfigDb
53+
( PkgConfigDb )
5254
import Distribution.Client.Types
5355
( OptionalStanza(..), SourcePackage(..), ConfiguredPackage )
5456

@@ -115,6 +117,7 @@ type DependencyResolver = Platform
115117
-> CompilerInfo
116118
-> InstalledPackageIndex
117119
-> PackageIndex.PackageIndex SourcePackage
120+
-> PkgConfigDb
118121
-> (PackageName -> PackagePreferences)
119122
-> [LabeledPackageConstraint]
120123
-> [PackageName]

0 commit comments

Comments
 (0)