@@ -24,14 +24,16 @@ import Distribution.Solver.Compat.Prelude
2424import Prelude ()
2525
2626import Control.Exception (handle )
27+ import Control.Monad (mapM )
2728import qualified Data.Map as M
2829import System.FilePath (splitSearchPath )
2930
3031import Distribution.Compat.Environment (lookupEnv )
3132import Distribution.Package (PkgconfigName , mkPkgconfigName )
3233import Distribution.Parsec
3334import Distribution.Simple.Program
34- (ProgramDb , getProgramOutput , pkgConfigProgram , needProgram )
35+ (ProgramDb , getProgramOutput , pkgConfigProgram , needProgram , ConfiguredProgram )
36+ import Distribution.Simple.Program.Run (getProgramInvocationOutputAndErrors , programInvocation )
3537import Distribution.Simple.Utils (info )
3638import Distribution.Types.PkgconfigVersion
3739import Distribution.Types.PkgconfigVersionRange
@@ -65,9 +67,15 @@ readPkgConfigDb verbosity progdb = handle ioErrorHandler $ do
6567 -- The output of @pkg-config --list-all@ also includes a description
6668 -- for each package, which we do not need.
6769 let pkgNames = map (takeWhile (not . isSpace)) pkgList
68- pkgVersions <- lines <$> getProgramOutput verbosity pkgConfig
69- (" --modversion" : pkgNames)
70- (return . pkgConfigDbFromList . zip pkgNames) pkgVersions
70+ (pkgVersions, _errs, exitCode) <-
71+ getProgramInvocationOutputAndErrors verbosity
72+ (programInvocation pkgConfig (" --modversion" : pkgNames))
73+ case exitCode of
74+ ExitSuccess -> (return . pkgConfigDbFromList . zip pkgNames) (lines pkgVersions)
75+ -- if there's a single broken pc file the above fails, so we fall back into calling it individually
76+ _ -> do
77+ info verbosity (" call to pkg-config --modversion on all packages failed. Falling back to querying pkg-config individually on each package" )
78+ pkgConfigDbFromList . catMaybes <$> mapM (getIndividualVersion pkgConfig) pkgNames
7179 where
7280 -- For when pkg-config invocation fails (possibly because of a
7381 -- too long command line).
@@ -80,6 +88,15 @@ readPkgConfigDb verbosity progdb = handle ioErrorHandler $ do
8088 ioErrorHandler :: IOException -> IO PkgConfigDb
8189 ioErrorHandler e = noPkgConfig (show e)
8290
91+ getIndividualVersion :: ConfiguredProgram -> String -> IO (Maybe (String , String ))
92+ getIndividualVersion pkgConfig pkg = do
93+ (pkgVersion, _errs, exitCode) <-
94+ getProgramInvocationOutputAndErrors verbosity
95+ (programInvocation pkgConfig [" --modversion" ,pkg])
96+ return $ case exitCode of
97+ ExitSuccess -> Just (pkg, pkgVersion)
98+ _ -> Nothing
99+
83100-- | Create a `PkgConfigDb` from a list of @(packageName, version)@ pairs.
84101pkgConfigDbFromList :: [(String , String )] -> PkgConfigDb
85102pkgConfigDbFromList pairs = (PkgConfigDb . M. fromList . map convert) pairs
0 commit comments