Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make clear when pkg-config is not present #10122

Merged
merged 2 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)"
andreabedini marked this conversation as resolved.
Show resolved Hide resolved
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
jasagredo marked this conversation as resolved.
Show resolved Hide resolved
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).
jasagredo marked this conversation as resolved.
Show resolved Hide resolved
| 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.

}
Loading