Skip to content

Commit

Permalink
Merge pull request #10122 from jasagredo/js/warn-missing-pkgconfig
Browse files Browse the repository at this point in the history
Make clear when pkg-config is not present
  • Loading branch information
mergify[bot] authored Jun 28, 2024
2 parents 7cbc45e + 345a8d2 commit a407863
Show file tree
Hide file tree
Showing 18 changed files with 54 additions and 56 deletions.
2 changes: 1 addition & 1 deletion cabal-install-solver/src/Distribution/Solver/Modular.hs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ modularResolver sc (Platform arch os) cinfo iidx sidx pkgConfigDB pprefs pcs pns
solve' :: SolverConfig
-> CompilerInfo
-> Index
-> PkgConfigDb
-> Maybe PkgConfigDb
-> (PN -> PackagePreferences)
-> Map PN [LabeledPackageConstraint]
-> Set PN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ showFR :: ConflictSet -> FailReason -> String
showFR _ (UnsupportedExtension ext) = " (conflict: requires " ++ showUnsupportedExtension ext ++ ")"
showFR _ (UnsupportedLanguage lang) = " (conflict: requires " ++ showUnsupportedLanguage lang ++ ")"
showFR _ (MissingPkgconfigPackage pn vr) = " (conflict: pkg-config package " ++ prettyShow pn ++ prettyShow vr ++ ", not found in the pkg-config database)"
showFR _ (MissingPkgconfigProgram pn vr) = " (pkg-config package " ++ prettyShow pn ++ prettyShow vr ++ " is needed but no pkg-config executable was found or querying it failed)"
showFR _ (NewPackageDoesNotMatchExistingConstraint d) = " (conflict: " ++ showConflictingDep d ++ ")"
showFR _ (ConflictingConstraints d1 d2) = " (conflict: " ++ L.intercalate ", " (L.map showConflictingDep [d1, d2]) ++ ")"
showFR _ (NewPackageIsMissingRequiredComponent comp dr) = " (does not contain " ++ showExposedComponent comp ++ ", which is required by " ++ showDependencyReason dr ++ ")"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ newtype PruneAfterFirstSuccess = PruneAfterFirstSuccess Bool
solve :: SolverConfig -- ^ solver parameters
-> CompilerInfo
-> Index -- ^ all available packages as an index
-> PkgConfigDb -- ^ available pkg-config pkgs
-> Maybe PkgConfigDb -- ^ available pkg-config pkgs
-> (PN -> PackagePreferences) -- ^ preferences
-> M.Map PN [LabeledPackageConstraint] -- ^ global constraints
-> S.Set PN -- ^ global goals
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ data POption = POption I (Maybe PackagePath)
data FailReason = UnsupportedExtension Extension
| UnsupportedLanguage Language
| MissingPkgconfigPackage PkgconfigName PkgconfigVersionRange
| MissingPkgconfigProgram PkgconfigName PkgconfigVersionRange
| NewPackageDoesNotMatchExistingConstraint ConflictingDep
| ConflictingConstraints ConflictingDep ConflictingDep
| NewPackageIsMissingRequiredComponent ExposedComponent (DependencyReason QPN)
Expand Down
14 changes: 8 additions & 6 deletions cabal-install-solver/src/Distribution/Solver/Modular/Validate.hs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ import Distribution.Types.PkgconfigVersionRange
data ValidateState = VS {
supportedExt :: Extension -> Bool,
supportedLang :: Language -> Bool,
presentPkgs :: PkgconfigName -> PkgconfigVersionRange -> Bool,
presentPkgs :: Maybe (PkgconfigName -> PkgconfigVersionRange -> Bool),
index :: Index,

-- Saved, scoped, dependencies. Every time 'validate' makes a package choice,
Expand Down Expand Up @@ -383,7 +383,7 @@ extractNewDeps v b fa sa = go
-- or the successfully extended assignment.
extend :: (Extension -> Bool) -- ^ is a given extension supported
-> (Language -> Bool) -- ^ is a given language supported
-> (PkgconfigName -> PkgconfigVersionRange -> Bool) -- ^ is a given pkg-config requirement satisfiable
-> Maybe (PkgconfigName -> PkgconfigVersionRange -> Bool) -- ^ is a given pkg-config requirement satisfiable
-> [LDep QPN]
-> PPreAssignment
-> Either Conflict PPreAssignment
Expand All @@ -398,8 +398,10 @@ extend extSupported langSupported pkgPresent newactives ppa = foldM extendSingle
if langSupported lang then Right a
else Left (dependencyReasonToConflictSet dr, UnsupportedLanguage lang)
extendSingle a (LDep dr (Pkg pn vr)) =
if pkgPresent pn vr then Right a
else Left (dependencyReasonToConflictSet dr, MissingPkgconfigPackage pn vr)
case (\f -> f pn vr) <$> pkgPresent of
Just True -> Right a
Just False -> Left (dependencyReasonToConflictSet dr, MissingPkgconfigPackage pn vr)
Nothing -> Left (dependencyReasonToConflictSet dr, MissingPkgconfigProgram pn vr)
extendSingle a (LDep dr (Dep dep@(PkgComponent qpn _) ci)) =
let mergedDep = M.findWithDefault (MergedDepConstrained []) qpn a
in case (\ x -> M.insert qpn x a) <$> merge mergedDep (PkgDep dr dep ci) of
Expand Down Expand Up @@ -561,15 +563,15 @@ extendRequiredComponents eqpn available = foldM extendSingle


-- | Interface.
validateTree :: CompilerInfo -> Index -> PkgConfigDb -> Tree d c -> Tree d c
validateTree :: CompilerInfo -> Index -> Maybe PkgConfigDb -> Tree d c -> Tree d c
validateTree cinfo idx pkgConfigDb t = runValidate (validate t) VS {
supportedExt = maybe (const True) -- if compiler has no list of extensions, we assume everything is supported
(\ es -> let s = S.fromList es in \ x -> S.member x s)
(compilerInfoExtensions cinfo)
, supportedLang = maybe (const True)
(flip L.elem) -- use list lookup because language list is small and no Ord instance
(compilerInfoLanguages cinfo)
, presentPkgs = pkgConfigPkgIsPresent pkgConfigDb
, presentPkgs = pkgConfigPkgIsPresent <$> pkgConfigDb
, index = idx
, saved = M.empty
, pa = PA M.empty M.empty M.empty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type DependencyResolver loc = Platform
-> CompilerInfo
-> InstalledPackageIndex
-> PackageIndex (SourcePackage loc)
-> PkgConfigDb
-> Maybe PkgConfigDb
-> (PackageName -> PackagePreferences)
-> [LabeledPackageConstraint]
-> Set PackageName
Expand Down
44 changes: 14 additions & 30 deletions cabal-install-solver/src/Distribution/Solver/Types/PkgConfigDb.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,12 @@ import Distribution.Types.PkgconfigVersionRange
import Distribution.Verbosity (Verbosity)

-- | The list of packages installed in the system visible to
-- @pkg-config@. This is an opaque datatype, to be constructed with
-- `readPkgConfigDb` and queried with `pkgConfigPkgPresent`.
data PkgConfigDb = PkgConfigDb (M.Map PkgconfigName (Maybe PkgconfigVersion))
-- ^ If an entry is `Nothing`, this means that the
-- package seems to be present, but we don't know the
-- exact version (because parsing of the version
-- number failed).
| NoPkgConfigDb
-- ^ For when we could not run pkg-config successfully.
-- @pkg-config@.
--
-- If an entry is `Nothing`, this means that the package seems to be present,
-- but we don't know the exact version (because parsing of the version number
-- failed).
newtype PkgConfigDb = PkgConfigDb (M.Map PkgconfigName (Maybe PkgconfigVersion))
deriving (Show, Generic, Typeable)

instance Binary PkgConfigDb
Expand All @@ -64,11 +61,11 @@ instance Structured PkgConfigDb
-- | Query pkg-config for the list of installed packages, together
-- with their versions. Return a `PkgConfigDb` encapsulating this
-- information.
readPkgConfigDb :: Verbosity -> ProgramDb -> IO PkgConfigDb
readPkgConfigDb :: Verbosity -> ProgramDb -> IO (Maybe PkgConfigDb)
readPkgConfigDb verbosity progdb = handle ioErrorHandler $ do
mpkgConfig <- needProgram verbosity pkgConfigProgram progdb
case mpkgConfig of
Nothing -> noPkgConfig "Cannot find pkg-config program"
Nothing -> noPkgConfig "cannot find pkg-config program"
Just (pkgConfig, _) -> do
-- To prevent malformed Unicode in the descriptions from crashing cabal,
-- read without interpreting any encoding first. (#9608)
Expand Down Expand Up @@ -106,7 +103,7 @@ readPkgConfigDb verbosity progdb = handle ioErrorHandler $ do
(programInvocation pkgConfig ("--modversion" : pkgNames))
let pkgVersions = lines outs
if exitCode == ExitSuccess && length pkgVersions == length pkgNames
then (return . pkgConfigDbFromList . zip pkgNames) pkgVersions
then (return . Just . pkgConfigDbFromList . zip pkgNames) pkgVersions
else
-- if there's a single broken pc file the above fails, so we fall back
-- into calling it individually
Expand All @@ -116,17 +113,17 @@ readPkgConfigDb verbosity progdb = handle ioErrorHandler $ do
-- requested one, we fall back to querying one by one.
do
info verbosity ("call to pkg-config --modversion on all packages failed. Falling back to querying pkg-config individually on each package")
pkgConfigDbFromList . catMaybes <$> mapM (getIndividualVersion pkgConfig) pkgNames
Just . pkgConfigDbFromList . catMaybes <$> mapM (getIndividualVersion pkgConfig) pkgNames
where
-- For when pkg-config invocation fails (possibly because of a
-- too long command line).
noPkgConfig extra = do
info verbosity ("Failed to query pkg-config, Cabal will continue"
++ " without solving for pkg-config constraints: "
info verbosity ("Warning: Failed to query pkg-config, Cabal will backtrack "
++ "if a package from pkg-config is requested. Error message: "
++ extra)
return NoPkgConfigDb
return Nothing

ioErrorHandler :: IOException -> IO PkgConfigDb
ioErrorHandler :: IOException -> IO (Maybe PkgConfigDb)
ioErrorHandler e = noPkgConfig (show e)

getIndividualVersion :: ConfiguredProgram -> String -> IO (Maybe (String, String))
Expand Down Expand Up @@ -162,26 +159,13 @@ pkgConfigPkgIsPresent (PkgConfigDb db) pn vr =
Nothing -> False -- Package not present in the DB.
Just Nothing -> True -- Package present, but version unknown.
Just (Just v) -> withinPkgconfigVersionRange v vr
-- If we could not read the pkg-config database successfully we fail.
-- The plan found by the solver can't be executed later, because pkg-config itself
-- is going to be called in the build phase to get the library location for linking
-- so even if there is a library, it would need to be passed manual flags anyway.
pkgConfigPkgIsPresent NoPkgConfigDb _ _ = False



-- | Query the version of a package in the @pkg-config@ database.
-- @Nothing@ indicates the package is not in the database, while
-- @Just Nothing@ indicates that the package is in the database,
-- but its version is not known.
pkgConfigDbPkgVersion :: PkgConfigDb -> PkgconfigName -> Maybe (Maybe PkgconfigVersion)
pkgConfigDbPkgVersion (PkgConfigDb db) pn = M.lookup pn db
-- NB: Since the solver allows solving to succeed if there is
-- NoPkgConfigDb, we should report that we *guess* that there
-- is a matching pkg-config configuration, but that we just
-- don't know about it.
pkgConfigDbPkgVersion NoPkgConfigDb _ = Just Nothing


-- | Query pkg-config for the locations of pkg-config's package files. Use this
-- to monitor for changes in the pkg-config DB.
Expand Down
2 changes: 1 addition & 1 deletion cabal-install/src/Distribution/Client/Configure.hs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ planLocalPackage
-> ConfigExFlags
-> InstalledPackageIndex
-> SourcePackageDb
-> PkgConfigDb
-> Maybe PkgConfigDb
-> IO (Progress String String SolverInstallPlan)
planLocalPackage
verbosity
Expand Down
2 changes: 1 addition & 1 deletion cabal-install/src/Distribution/Client/Dependency.hs
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ runSolver = modularResolver
resolveDependencies
:: Platform
-> CompilerInfo
-> PkgConfigDb
-> Maybe PkgConfigDb
-> DepResolverParams
-> Progress String String SolverInstallPlan
resolveDependencies platform comp pkgConfigDB params =
Expand Down
2 changes: 1 addition & 1 deletion cabal-install/src/Distribution/Client/Fetch.hs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ planPackages
-> FetchFlags
-> InstalledPackageIndex
-> SourcePackageDb
-> PkgConfigDb
-> Maybe PkgConfigDb
-> [PackageSpecifier UnresolvedSourcePackage]
-> IO [UnresolvedSourcePackage]
planPackages
Expand Down
2 changes: 1 addition & 1 deletion cabal-install/src/Distribution/Client/Freeze.hs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ planPackages
-> FreezeFlags
-> InstalledPackageIndex
-> SourcePackageDb
-> PkgConfigDb
-> Maybe PkgConfigDb
-> [PackageSpecifier UnresolvedSourcePackage]
-> IO [SolverPlanPackage]
planPackages
Expand Down
4 changes: 2 additions & 2 deletions cabal-install/src/Distribution/Client/Install.hs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ install
type InstallContext =
( InstalledPackageIndex
, SourcePackageDb
, PkgConfigDb
, Maybe PkgConfigDb
, [UserTarget]
, [PackageSpecifier UnresolvedSourcePackage]
, HttpTransport
Expand Down Expand Up @@ -567,7 +567,7 @@ planPackages
-> InstallFlags
-> InstalledPackageIndex
-> SourcePackageDb
-> PkgConfigDb
-> Maybe PkgConfigDb
-> [PackageSpecifier UnresolvedSourcePackage]
-> Progress String String SolverInstallPlan
planPackages
Expand Down
12 changes: 6 additions & 6 deletions cabal-install/src/Distribution/Client/ProjectPlanning.hs
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ rebuildInstallPlan
-> (Compiler, Platform, ProgramDb)
-> [PackageSpecifier UnresolvedSourcePackage]
-> InstalledPackageIndex
-> Rebuild (SolverInstallPlan, PkgConfigDb, IndexUtils.TotalIndexState, IndexUtils.ActiveRepos)
-> Rebuild (SolverInstallPlan, Maybe PkgConfigDb, IndexUtils.TotalIndexState, IndexUtils.ActiveRepos)
phaseRunSolver
projectConfig@ProjectConfig
{ projectConfigShared
Expand Down Expand Up @@ -776,7 +776,7 @@ rebuildInstallPlan
phaseElaboratePlan
:: ProjectConfig
-> (Compiler, Platform, ProgramDb)
-> PkgConfigDb
-> Maybe PkgConfigDb
-> SolverInstallPlan
-> [PackageSpecifier (SourcePackage (PackageLocation loc))]
-> Rebuild
Expand Down Expand Up @@ -1010,7 +1010,7 @@ getSourcePackages verbosity withRepoCtx idxState activeRepos = do
$ repos
return sourcePkgDbWithTIS

getPkgConfigDb :: Verbosity -> ProgramDb -> Rebuild PkgConfigDb
getPkgConfigDb :: Verbosity -> ProgramDb -> Rebuild (Maybe PkgConfigDb)
getPkgConfigDb verbosity progdb = do
dirs <- liftIO $ getPkgConfigDbDirs verbosity progdb
-- Just monitor the dirs so we'll notice new .pc files.
Expand Down Expand Up @@ -1210,7 +1210,7 @@ planPackages
-> SolverSettings
-> InstalledPackageIndex
-> SourcePackageDb
-> PkgConfigDb
-> Maybe PkgConfigDb
-> [PackageSpecifier UnresolvedSourcePackage]
-> Map PackageName (Map OptionalStanza Bool)
-> Progress String String SolverInstallPlan
Expand Down Expand Up @@ -1533,7 +1533,7 @@ elaborateInstallPlan
-> Platform
-> Compiler
-> ProgramDb
-> PkgConfigDb
-> Maybe PkgConfigDb
-> DistDirLayout
-> StoreDirLayout
-> SolverInstallPlan
Expand Down Expand Up @@ -1937,7 +1937,7 @@ elaborateInstallPlan
++ " from "
++ prettyShow (elabPkgSourceId elab0)
)
(pkgConfigDbPkgVersion pkgConfigDB pn)
(pkgConfigDB >>= \db -> pkgConfigDbPkgVersion db pn)
)
| PkgconfigDependency pn _ <-
PD.pkgconfigDepends
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ exResolve
-> Maybe [Extension]
-- List of languages supported by the compiler, or Nothing if unknown.
-> Maybe [Language]
-> PC.PkgConfigDb
-> Maybe PC.PkgConfigDb
-> [ExamplePkgName]
-> Maybe Int
-> CountConflicts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ data SolverTest = SolverTest
, testDb :: ExampleDb
, testSupportedExts :: Maybe [Extension]
, testSupportedLangs :: Maybe [Language]
, testPkgConfigDb :: PkgConfigDb
, testPkgConfigDb :: Maybe PkgConfigDb
, testEnableAllTests :: EnableAllTests
}

Expand Down Expand Up @@ -233,7 +233,7 @@ mkTestExtLangPC exts langs mPkgConfigDb db label targets result =
, testDb = db
, testSupportedExts = exts
, testSupportedLangs = langs
, testPkgConfigDb = maybe NoPkgConfigDb pkgConfigDbFromList mPkgConfigDb
, testPkgConfigDb = pkgConfigDbFromList <$> mPkgConfigDb
, testEnableAllTests = EnableAllTests False
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ solve enableBj fineGrainedConflicts reorder countConflicts indep prefOldest goal
(unTestDb (testDb test))
Nothing
Nothing
(pkgConfigDbFromList [])
(Just $ pkgConfigDbFromList [])
(map unPN (testTargets test))
-- The backjump limit prevents individual tests from using
-- too much time and memory.
Expand Down
2 changes: 1 addition & 1 deletion cabal-testsuite/PackageTests/ExtraProgPath/setup.out
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ Resolving dependencies...
Error: [Cabal-7107]
Could not resolve dependencies:
[__0] next goal: CheckExtraProgPath (user goal)
[__0] rejecting: CheckExtraProgPath-0.1 (conflict: pkg-config package zlib-any, not found in the pkg-config database)
[__0] rejecting: CheckExtraProgPath-0.1 (pkg-config package zlib-any is needed but no pkg-config executable was found or querying it failed)
[__0] fail (backjumping, conflict set: CheckExtraProgPath)
After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: CheckExtraProgPath (2)
10 changes: 10 additions & 0 deletions changelog.d/pr-10122
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
synopsis: Clarify error message when pkg-config is not found
packages: cabal-install-solver
prs: #10122

description: {

- The error message when pkg-config is not found or querying it fails will no
longer incorrectly claim that the package is missing in the database.

}

0 comments on commit a407863

Please sign in to comment.