diff --git a/Cabal/Distribution/Simple/Program.hs b/Cabal/Distribution/Simple/Program.hs index f1428831cde7cd520c7518a79dbf4e1bc76b0ead..00168e407baa887edad1d26056614506f5a8cfff 100644 --- a/Cabal/Distribution/Simple/Program.hs +++ b/Cabal/Distribution/Simple/Program.hs @@ -90,6 +90,7 @@ module Distribution.Simple.Program ( , reconfigurePrograms , requireProgram , requireProgramVersion + , needProgram , runDbProgram , getDbProgramOutput diff --git a/Cabal/Distribution/Simple/Program/Db.hs b/Cabal/Distribution/Simple/Program/Db.hs index 520601bf7bf1cf5322a509b68cf25234ed185f92..b8fc8287210077d2b793787ceb41e2430ab4e4d0 100644 --- a/Cabal/Distribution/Simple/Program/Db.hs +++ b/Cabal/Distribution/Simple/Program/Db.hs @@ -57,6 +57,7 @@ module Distribution.Simple.Program.Db ( reconfigurePrograms, requireProgram, requireProgramVersion, + needProgram, ) where @@ -413,6 +414,22 @@ reconfigurePrograms verbosity paths argss progdb = do requireProgram :: Verbosity -> Program -> ProgramDb -> IO (ConfiguredProgram, ProgramDb) requireProgram verbosity prog progdb = do + mres <- needProgram verbosity prog progdb + case mres of + Nothing -> die' verbosity notFound + Just res -> return res + where + notFound = "The program '" ++ programName prog ++ "' is required but it could not be found." + +-- | Check that a program is configured and available to be run. +-- +-- It returns 'Nothing' if the program couldn't be configured, +-- or is not found. +-- +-- @since 3.2.0.0 +needProgram :: Verbosity -> Program -> ProgramDb + -> IO (Maybe (ConfiguredProgram, ProgramDb)) +needProgram verbosity prog progdb = do -- If it's not already been configured, try to configure it now progdb' <- case lookupProgram prog progdb of @@ -420,12 +437,8 @@ requireProgram verbosity prog progdb = do Just _ -> return progdb case lookupProgram prog progdb' of - Nothing -> die' verbosity notFound - Just configuredProg -> return (configuredProg, progdb') - - where notFound = "The program '" ++ programName prog - ++ "' is required but it could not be found." - + Nothing -> return Nothing + Just configuredProg -> return (Just (configuredProg, progdb')) -- | Check that a program is configured and available to be run. -- diff --git a/cabal-install/Distribution/Solver/Types/PkgConfigDb.hs b/cabal-install/Distribution/Solver/Types/PkgConfigDb.hs index 3d2ed076db37ff56c38cdb8c15fc1b7b5970fa2e..e63d3b0c7c22d3950cc50f7bd0f2ed487ec062d1 100644 --- a/cabal-install/Distribution/Solver/Types/PkgConfigDb.hs +++ b/cabal-install/Distribution/Solver/Types/PkgConfigDb.hs @@ -31,7 +31,7 @@ import Distribution.Compat.Environment (lookupEnv) import Distribution.Package (PkgconfigName, mkPkgconfigName) import Distribution.Parsec import Distribution.Simple.Program - (ProgramDb, getProgramOutput, pkgConfigProgram, requireProgram) + (ProgramDb, getProgramOutput, pkgConfigProgram, needProgram) import Distribution.Simple.Utils (info) import Distribution.Types.PkgconfigVersion import Distribution.Types.PkgconfigVersionRange @@ -56,23 +56,28 @@ instance Binary PkgConfigDb -- information. readPkgConfigDb :: Verbosity -> ProgramDb -> IO PkgConfigDb readPkgConfigDb verbosity progdb = handle ioErrorHandler $ do - (pkgConfig, _) <- requireProgram verbosity pkgConfigProgram progdb - pkgList <- lines <$> getProgramOutput verbosity pkgConfig ["--list-all"] - -- The output of @pkg-config --list-all@ also includes a description - -- for each package, which we do not need. - let pkgNames = map (takeWhile (not . isSpace)) pkgList - pkgVersions <- lines <$> getProgramOutput verbosity pkgConfig - ("--modversion" : pkgNames) - (return . pkgConfigDbFromList . zip pkgNames) pkgVersions - where - -- For when pkg-config invocation fails (possibly because of a - -- too long command line). - ioErrorHandler :: IOException -> IO PkgConfigDb - ioErrorHandler e = do - info verbosity ("Failed to query pkg-config, Cabal will continue" - ++ " without solving for pkg-config constraints: " - ++ show e) - return NoPkgConfigDb + mpkgConfig <- needProgram verbosity pkgConfigProgram progdb + case mpkgConfig of + Nothing -> noPkgConfig "Cannot find pkg-config program" + Just (pkgConfig, _) -> do + pkgList <- lines <$> getProgramOutput verbosity pkgConfig ["--list-all"] + -- The output of @pkg-config --list-all@ also includes a description + -- for each package, which we do not need. + let pkgNames = map (takeWhile (not . isSpace)) pkgList + pkgVersions <- lines <$> getProgramOutput verbosity pkgConfig + ("--modversion" : pkgNames) + (return . pkgConfigDbFromList . zip pkgNames) pkgVersions + 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: " + ++ extra) + return NoPkgConfigDb + + ioErrorHandler :: IOException -> IO PkgConfigDb + ioErrorHandler e = noPkgConfig (show e) -- | Create a `PkgConfigDb` from a list of @(packageName, version)@ pairs. pkgConfigDbFromList :: [(String, String)] -> PkgConfigDb @@ -134,10 +139,11 @@ getPkgConfigDbDirs verbosity progdb = -- > pkg-config --variable pc_path pkg-config -- getDefPath = handle ioErrorHandler $ do - (pkgConfig, _) <- requireProgram verbosity pkgConfigProgram progdb - parseSearchPath <$> - getProgramOutput verbosity pkgConfig - ["--variable", "pc_path", "pkg-config"] + mpkgConfig <- needProgram verbosity pkgConfigProgram progdb + case mpkgConfig of + Nothing -> return [] + Just (pkgConfig, _) -> parseSearchPath <$> + getProgramOutput verbosity pkgConfig ["--variable", "pc_path", "pkg-config"] parseSearchPath str = case lines str of