@@ -24,14 +24,16 @@ import Distribution.Solver.Compat.Prelude
24
24
import Prelude ()
25
25
26
26
import Control.Exception (handle )
27
+ import Control.Monad (mapM )
27
28
import qualified Data.Map as M
28
29
import System.FilePath (splitSearchPath )
29
30
30
31
import Distribution.Compat.Environment (lookupEnv )
31
32
import Distribution.Package (PkgconfigName , mkPkgconfigName )
32
33
import Distribution.Parsec
33
34
import Distribution.Simple.Program
34
- (ProgramDb , getProgramOutput , pkgConfigProgram , needProgram )
35
+ (ProgramDb , getProgramOutput , pkgConfigProgram , needProgram , ConfiguredProgram )
36
+ import Distribution.Simple.Program.Run (getProgramInvocationOutputAndErrors , programInvocation )
35
37
import Distribution.Simple.Utils (info )
36
38
import Distribution.Types.PkgconfigVersion
37
39
import Distribution.Types.PkgconfigVersionRange
@@ -65,9 +67,15 @@ readPkgConfigDb verbosity progdb = handle ioErrorHandler $ do
65
67
-- The output of @pkg-config --list-all@ also includes a description
66
68
-- for each package, which we do not need.
67
69
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
71
79
where
72
80
-- For when pkg-config invocation fails (possibly because of a
73
81
-- too long command line).
@@ -80,6 +88,15 @@ readPkgConfigDb verbosity progdb = handle ioErrorHandler $ do
80
88
ioErrorHandler :: IOException -> IO PkgConfigDb
81
89
ioErrorHandler e = noPkgConfig (show e)
82
90
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
+
83
100
-- | Create a `PkgConfigDb` from a list of @(packageName, version)@ pairs.
84
101
pkgConfigDbFromList :: [(String , String )] -> PkgConfigDb
85
102
pkgConfigDbFromList pairs = (PkgConfigDb . M. fromList . map convert) pairs
0 commit comments