{-# LANGUAGE DataKinds #-}

-- |
-- Module      :  Distribution.Client.Configure
-- Copyright   :  (c) David Himmelstrup 2005,
--                    Duncan Coutts 2005
-- License     :  BSD-like
--
-- Maintainer  :  cabal-devel@haskell.org
-- Portability :  portable
--
-- High level interface to configuring a package.
module Distribution.Client.Configure
  ( configure
  , configureSetupScript
  , chooseCabalVersion
  , checkConfigExFlags

    -- * Saved configure flags
  , readConfigFlagsFrom
  , readConfigFlags
  , writeConfigFlagsTo
  , writeConfigFlags
  ) where

import Distribution.Client.Compat.Prelude
import Distribution.Utils.Generic (safeHead)
import Prelude ()

import Distribution.Client.Dependency
import Distribution.Client.IndexUtils as IndexUtils
  ( getInstalledPackages
  , getSourcePackages
  )
import qualified Distribution.Client.InstallPlan as InstallPlan
import Distribution.Client.JobControl (Lock)
import Distribution.Client.Setup
  ( ConfigExFlags (..)
  , RepoContext (..)
  , configureCommand
  , configureExCommand
  , filterConfigureFlags
  )
import Distribution.Client.SetupWrapper
  ( SetupScriptOptions (..)
  , defaultSetupScriptOptions
  , setupWrapper
  )
import Distribution.Client.SolverInstallPlan (SolverInstallPlan)
import Distribution.Client.Targets
  ( userConstraintPackageName
  , userToPackageConstraint
  )
import Distribution.Client.Types as Source

import qualified Distribution.Solver.Types.ComponentDeps as CD
import Distribution.Solver.Types.ConstraintSource
import Distribution.Solver.Types.LabeledPackageConstraint
import Distribution.Solver.Types.OptionalStanza
import Distribution.Solver.Types.PackageIndex
  ( PackageIndex
  , elemByPackageName
  )
import Distribution.Solver.Types.PkgConfigDb
  ( PkgConfigDb
  , readPkgConfigDb
  )
import Distribution.Solver.Types.Settings
import Distribution.Solver.Types.SourcePackage

import Distribution.Client.SavedFlags (readCommandFlags, writeCommandFlags)
import Distribution.Package
  ( Package (..)
  , PackageId
  , packageName
  )
import qualified Distribution.PackageDescription as PkgDesc
import Distribution.PackageDescription.Configuration
  ( finalizePD
  )
import Distribution.Simple.Compiler
  ( Compiler
  , CompilerInfo
  , PackageDBStackCWD
  , PackageDBX (..)
  , compilerInfo
  )
import Distribution.Simple.PackageDescription
  ( readGenericPackageDescription
  )
import Distribution.Simple.PackageIndex as PackageIndex
  ( InstalledPackageIndex
  , lookupPackageName
  )
import Distribution.Simple.Program (ProgramDb)
import Distribution.Simple.Setup
  ( CommonSetupFlags (..)
  , ConfigFlags (..)
  , flagToMaybe
  , fromFlagOrDefault
  , maybeToFlag
  , toFlag
  )
import Distribution.Simple.Utils as Utils
  ( debug
  , defaultPackageDescCwd
  , dieWithException
  , notice
  , warn
  )
import Distribution.System
  ( Platform
  )
import Distribution.Types.GivenComponent
  ( GivenComponent (..)
  )
import Distribution.Types.PackageVersionConstraint
  ( PackageVersionConstraint (..)
  , thisPackageVersionConstraint
  )
import Distribution.Utils.Path
import Distribution.Version
  ( Version
  , VersionRange
  , anyVersion
  , thisVersion
  )

import Distribution.Client.Errors

-- | Choose the Cabal version such that the setup scripts compiled against this
-- version will support the given command-line flags. Currently, it implements no
-- specific restrictions and allows any version, unless the second argument is
-- filled with a 'Version', in which case this version is picked.
chooseCabalVersion :: ConfigExFlags -> Maybe Version -> VersionRange
chooseCabalVersion :: ConfigExFlags -> Maybe Version -> VersionRange
chooseCabalVersion ConfigExFlags
_configExFlags Maybe Version
maybeVersion =
  VersionRange
-> (Version -> VersionRange) -> Maybe Version -> VersionRange
forall b a. b -> (a -> b) -> Maybe a -> b
maybe VersionRange
anyVersion Version -> VersionRange
thisVersion Maybe Version
maybeVersion

-- | Configure the package found in the local directory
configure
  :: Verbosity
  -> PackageDBStackCWD
  -> RepoContext
  -> Compiler
  -> Platform
  -> ProgramDb
  -> ConfigFlags
  -> ConfigExFlags
  -> [String]
  -> IO ()
configure :: Verbosity
-> PackageDBStackCWD
-> RepoContext
-> Compiler
-> Platform
-> ProgramDb
-> ConfigFlags
-> ConfigExFlags
-> [FilePath]
-> IO ()
configure
  Verbosity
verbosity
  PackageDBStackCWD
packageDBs
  RepoContext
repoCtxt
  Compiler
comp
  Platform
platform
  ProgramDb
progdb
  ConfigFlags
configFlags
  ConfigExFlags
configExFlags
  [FilePath]
extraArgs = do
    InstalledPackageIndex
installedPkgIndex <- Verbosity
-> Compiler
-> PackageDBStackCWD
-> ProgramDb
-> IO InstalledPackageIndex
getInstalledPackages Verbosity
verbosity Compiler
comp PackageDBStackCWD
packageDBs ProgramDb
progdb
    SourcePackageDb
sourcePkgDb <- Verbosity -> RepoContext -> IO SourcePackageDb
getSourcePackages Verbosity
verbosity RepoContext
repoCtxt
    Maybe PkgConfigDb
pkgConfigDb <- Verbosity -> ProgramDb -> IO (Maybe PkgConfigDb)
readPkgConfigDb Verbosity
verbosity ProgramDb
progdb

    Verbosity
-> InstalledPackageIndex
-> PackageIndex UnresolvedSourcePackage
-> ConfigExFlags
-> IO ()
forall pkg.
Package pkg =>
Verbosity
-> InstalledPackageIndex
-> PackageIndex pkg
-> ConfigExFlags
-> IO ()
checkConfigExFlags
      Verbosity
verbosity
      InstalledPackageIndex
installedPkgIndex
      (SourcePackageDb -> PackageIndex UnresolvedSourcePackage
packageIndex SourcePackageDb
sourcePkgDb)
      ConfigExFlags
configExFlags

    Progress FilePath FilePath SolverInstallPlan
progress <-
      Verbosity
-> Compiler
-> Platform
-> ConfigFlags
-> ConfigExFlags
-> InstalledPackageIndex
-> SourcePackageDb
-> Maybe PkgConfigDb
-> IO (Progress FilePath FilePath SolverInstallPlan)
planLocalPackage
        Verbosity
verbosity
        Compiler
comp
        Platform
platform
        ConfigFlags
configFlags
        ConfigExFlags
configExFlags
        InstalledPackageIndex
installedPkgIndex
        SourcePackageDb
sourcePkgDb
        Maybe PkgConfigDb
pkgConfigDb

    Verbosity -> FilePath -> IO ()
notice Verbosity
verbosity FilePath
"Resolving dependencies..."
    Either FilePath SolverInstallPlan
maybePlan <-
      (FilePath
 -> IO (Either FilePath SolverInstallPlan)
 -> IO (Either FilePath SolverInstallPlan))
-> (FilePath -> IO (Either FilePath SolverInstallPlan))
-> (SolverInstallPlan -> IO (Either FilePath SolverInstallPlan))
-> Progress FilePath FilePath SolverInstallPlan
-> IO (Either FilePath SolverInstallPlan)
forall step a fail done.
(step -> a -> a)
-> (fail -> a) -> (done -> a) -> Progress step fail done -> a
foldProgress
        FilePath
-> IO (Either FilePath SolverInstallPlan)
-> IO (Either FilePath SolverInstallPlan)
forall {b}. FilePath -> IO b -> IO b
logMsg
        (Either FilePath SolverInstallPlan
-> IO (Either FilePath SolverInstallPlan)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either FilePath SolverInstallPlan
 -> IO (Either FilePath SolverInstallPlan))
-> (FilePath -> Either FilePath SolverInstallPlan)
-> FilePath
-> IO (Either FilePath SolverInstallPlan)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Either FilePath SolverInstallPlan
forall a b. a -> Either a b
Left)
        (Either FilePath SolverInstallPlan
-> IO (Either FilePath SolverInstallPlan)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either FilePath SolverInstallPlan
 -> IO (Either FilePath SolverInstallPlan))
-> (SolverInstallPlan -> Either FilePath SolverInstallPlan)
-> SolverInstallPlan
-> IO (Either FilePath SolverInstallPlan)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SolverInstallPlan -> Either FilePath SolverInstallPlan
forall a b. b -> Either a b
Right)
        Progress FilePath FilePath SolverInstallPlan
progress
    case Either FilePath SolverInstallPlan
maybePlan of
      Left FilePath
message -> do
        Verbosity -> FilePath -> IO ()
warn Verbosity
verbosity (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$
          FilePath
"solver failed to find a solution:\n"
            FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
message
            FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\nTrying configure anyway."
        Verbosity
-> SetupScriptOptions
-> Maybe PackageDescription
-> CommandUI ConfigFlags
-> (ConfigFlags -> CommonSetupFlags)
-> (Version -> IO ConfigFlags)
-> (Version -> [FilePath])
-> IO ()
forall flags.
Verbosity
-> SetupScriptOptions
-> Maybe PackageDescription
-> CommandUI flags
-> (flags -> CommonSetupFlags)
-> (Version -> IO flags)
-> (Version -> [FilePath])
-> IO ()
setupWrapper
          Verbosity
verbosity
          (InstalledPackageIndex -> Maybe ReadyPackage -> SetupScriptOptions
setupScriptOptions InstalledPackageIndex
installedPkgIndex Maybe ReadyPackage
forall a. Maybe a
Nothing)
          Maybe PackageDescription
forall a. Maybe a
Nothing
          CommandUI ConfigFlags
configureCommand
          ConfigFlags -> CommonSetupFlags
configCommonFlags
          (IO ConfigFlags -> Version -> IO ConfigFlags
forall a b. a -> b -> a
const (ConfigFlags -> IO ConfigFlags
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ConfigFlags
configFlags))
          ([FilePath] -> Version -> [FilePath]
forall a b. a -> b -> a
const [FilePath]
extraArgs)
      Right SolverInstallPlan
installPlan0 ->
        let installPlan :: InstallPlan
installPlan = ConfigFlags -> SolverInstallPlan -> InstallPlan
InstallPlan.configureInstallPlan ConfigFlags
configFlags SolverInstallPlan
installPlan0
         in case ([ReadyPackage], Processing) -> [ReadyPackage]
forall a b. (a, b) -> a
fst (InstallPlan -> ([ReadyPackage], Processing)
forall ipkg srcpkg.
(IsUnit ipkg, IsUnit srcpkg) =>
GenericInstallPlan ipkg srcpkg
-> ([GenericReadyPackage srcpkg], Processing)
InstallPlan.ready InstallPlan
installPlan) of
              [ pkg :: ReadyPackage
pkg@( ReadyPackage
                        ( ConfiguredPackage
                            InstalledPackageId
_
                            (SourcePackage PackageId
_ GenericPackageDescription
_ (LocalUnpackedPackage FilePath
_) PackageDescriptionOverride
_)
                            FlagAssignment
_
                            OptionalStanzaSet
_
                            ComponentDeps [ConfiguredId]
_
                          )
                      )
                ] -> do
                  Verbosity
-> Platform
-> CompilerInfo
-> SetupScriptOptions
-> ConfigFlags
-> ReadyPackage
-> [FilePath]
-> IO ()
configurePackage
                    Verbosity
verbosity
                    Platform
platform
                    (Compiler -> CompilerInfo
compilerInfo Compiler
comp)
                    (InstalledPackageIndex -> Maybe ReadyPackage -> SetupScriptOptions
setupScriptOptions InstalledPackageIndex
installedPkgIndex (ReadyPackage -> Maybe ReadyPackage
forall a. a -> Maybe a
Just ReadyPackage
pkg))
                    ConfigFlags
configFlags
                    ReadyPackage
pkg
                    [FilePath]
extraArgs
              [ReadyPackage]
_ ->
                Verbosity -> CabalInstallException -> IO ()
forall a1 a.
(HasCallStack, Show a1, Typeable a1,
 Exception (VerboseException a1)) =>
Verbosity -> a1 -> IO a
dieWithException Verbosity
verbosity CabalInstallException
ConfigureInstallInternalError
    where
      setupScriptOptions
        :: InstalledPackageIndex
        -> Maybe ReadyPackage
        -> SetupScriptOptions
      setupScriptOptions :: InstalledPackageIndex -> Maybe ReadyPackage -> SetupScriptOptions
setupScriptOptions =
        PackageDBStackCWD
-> Compiler
-> Platform
-> ProgramDb
-> SymbolicPath Pkg ('Dir Dist)
-> VersionRange
-> Maybe Lock
-> Bool
-> InstalledPackageIndex
-> Maybe ReadyPackage
-> SetupScriptOptions
configureSetupScript
          PackageDBStackCWD
packageDBs
          Compiler
comp
          Platform
platform
          ProgramDb
progdb
          ( SymbolicPath Pkg ('Dir Dist)
-> Flag (SymbolicPath Pkg ('Dir Dist))
-> SymbolicPath Pkg ('Dir Dist)
forall a. a -> Flag a -> a
fromFlagOrDefault
              (SetupScriptOptions -> SymbolicPath Pkg ('Dir Dist)
useDistPref SetupScriptOptions
defaultSetupScriptOptions)
              (CommonSetupFlags -> Flag (SymbolicPath Pkg ('Dir Dist))
setupDistPref (CommonSetupFlags -> Flag (SymbolicPath Pkg ('Dir Dist)))
-> CommonSetupFlags -> Flag (SymbolicPath Pkg ('Dir Dist))
forall a b. (a -> b) -> a -> b
$ ConfigFlags -> CommonSetupFlags
configCommonFlags ConfigFlags
configFlags)
          )
          ( ConfigExFlags -> Maybe Version -> VersionRange
chooseCabalVersion
              ConfigExFlags
configExFlags
              (Flag Version -> Maybe Version
forall a. Flag a -> Maybe a
flagToMaybe (ConfigExFlags -> Flag Version
configCabalVersion ConfigExFlags
configExFlags))
          )
          Maybe Lock
forall a. Maybe a
Nothing
          Bool
False

      logMsg :: FilePath -> IO b -> IO b
logMsg FilePath
message IO b
rest = Verbosity -> FilePath -> IO ()
debug Verbosity
verbosity FilePath
message IO () -> IO b -> IO b
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO b
rest

configureSetupScript
  :: PackageDBStackCWD
  -> Compiler
  -> Platform
  -> ProgramDb
  -> SymbolicPath Pkg (Dir Dist)
  -> VersionRange
  -> Maybe Lock
  -> Bool
  -> InstalledPackageIndex
  -> Maybe ReadyPackage
  -> SetupScriptOptions
configureSetupScript :: PackageDBStackCWD
-> Compiler
-> Platform
-> ProgramDb
-> SymbolicPath Pkg ('Dir Dist)
-> VersionRange
-> Maybe Lock
-> Bool
-> InstalledPackageIndex
-> Maybe ReadyPackage
-> SetupScriptOptions
configureSetupScript
  PackageDBStackCWD
packageDBs
  Compiler
comp
  Platform
platform
  ProgramDb
progdb
  SymbolicPath Pkg ('Dir Dist)
distPref
  VersionRange
cabalVersion
  Maybe Lock
lock
  Bool
forceExternal
  InstalledPackageIndex
index
  Maybe ReadyPackage
mpkg =
    SetupScriptOptions
      { useCabalVersion :: VersionRange
useCabalVersion = VersionRange
cabalVersion
      , useCabalSpecVersion :: Maybe Version
useCabalSpecVersion = Maybe Version
forall a. Maybe a
Nothing
      , useCompiler :: Maybe Compiler
useCompiler = Compiler -> Maybe Compiler
forall a. a -> Maybe a
Just Compiler
comp
      , usePlatform :: Maybe Platform
usePlatform = Platform -> Maybe Platform
forall a. a -> Maybe a
Just Platform
platform
      , usePackageDB :: PackageDBStackCWD
usePackageDB = PackageDBStackCWD
packageDBs'
      , usePackageIndex :: Maybe InstalledPackageIndex
usePackageIndex = Maybe InstalledPackageIndex
index'
      , useProgramDb :: ProgramDb
useProgramDb = ProgramDb
progdb
      , useDistPref :: SymbolicPath Pkg ('Dir Dist)
useDistPref = SymbolicPath Pkg ('Dir Dist)
distPref
      , useLoggingHandle :: Maybe Handle
useLoggingHandle = Maybe Handle
forall a. Maybe a
Nothing
      , useWorkingDir :: Maybe (SymbolicPath CWD ('Dir Pkg))
useWorkingDir = Maybe (SymbolicPath CWD ('Dir Pkg))
forall a. Maybe a
Nothing
      , useExtraPathEnv :: [FilePath]
useExtraPathEnv = []
      , useExtraEnvOverrides :: [(FilePath, Maybe FilePath)]
useExtraEnvOverrides = []
      , setupCacheLock :: Maybe Lock
setupCacheLock = Maybe Lock
lock
      , useWin32CleanHack :: Bool
useWin32CleanHack = Bool
False
      , forceExternalSetupMethod :: Bool
forceExternalSetupMethod = Bool
forceExternal
      , -- If we have explicit setup dependencies, list them; otherwise, we give
        -- the empty list of dependencies; ideally, we would fix the version of
        -- Cabal here, so that we no longer need the special case for that in
        -- `compileSetupExecutable` in `externalSetupMethod`, but we don't yet
        -- know the version of Cabal at this point, but only find this there.
        -- Therefore, for now, we just leave this blank.
        useDependencies :: [(InstalledPackageId, PackageId)]
useDependencies = [(InstalledPackageId, PackageId)]
-> Maybe [(InstalledPackageId, PackageId)]
-> [(InstalledPackageId, PackageId)]
forall a. a -> Maybe a -> a
fromMaybe [] Maybe [(InstalledPackageId, PackageId)]
explicitSetupDeps
      , useDependenciesExclusive :: Bool
useDependenciesExclusive = Bool -> Bool
not Bool
defaultSetupDeps Bool -> Bool -> Bool
&& Maybe [(InstalledPackageId, PackageId)] -> Bool
forall a. Maybe a -> Bool
isJust Maybe [(InstalledPackageId, PackageId)]
explicitSetupDeps
      , useVersionMacros :: Bool
useVersionMacros = Bool -> Bool
not Bool
defaultSetupDeps Bool -> Bool -> Bool
&& Maybe [(InstalledPackageId, PackageId)] -> Bool
forall a. Maybe a -> Bool
isJust Maybe [(InstalledPackageId, PackageId)]
explicitSetupDeps
      , isInteractive :: Bool
isInteractive = Bool
False
      }
    where
      -- When we are compiling a legacy setup script without an explicit
      -- setup stanza, we typically want to allow the UserPackageDB for
      -- finding the Cabal lib when compiling any Setup.hs even if we're doing
      -- a global install. However we also allow looking in a specific package
      -- db.
      packageDBs' :: PackageDBStackCWD
      index' :: Maybe InstalledPackageIndex
      (PackageDBStackCWD
packageDBs', Maybe InstalledPackageIndex
index') =
        case PackageDBStackCWD
packageDBs of
          (PackageDBX FilePath
GlobalPackageDB : PackageDBStackCWD
dbs)
            | PackageDBX FilePath
forall fp. PackageDBX fp
UserPackageDB PackageDBX FilePath -> PackageDBStackCWD -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` PackageDBStackCWD
dbs
            , Maybe [(InstalledPackageId, PackageId)]
Nothing <- Maybe [(InstalledPackageId, PackageId)]
explicitSetupDeps ->
                (PackageDBX FilePath
forall fp. PackageDBX fp
GlobalPackageDB PackageDBX FilePath -> PackageDBStackCWD -> PackageDBStackCWD
forall a. a -> [a] -> [a]
: PackageDBX FilePath
forall fp. PackageDBX fp
UserPackageDB PackageDBX FilePath -> PackageDBStackCWD -> PackageDBStackCWD
forall a. a -> [a] -> [a]
: PackageDBStackCWD
dbs, Maybe InstalledPackageIndex
forall a. Maybe a
Nothing)
          -- but if the user is using an odd db stack, don't touch it
          PackageDBStackCWD
_otherwise -> (PackageDBStackCWD
packageDBs, InstalledPackageIndex -> Maybe InstalledPackageIndex
forall a. a -> Maybe a
Just InstalledPackageIndex
index)

      maybeSetupBuildInfo :: Maybe PkgDesc.SetupBuildInfo
      maybeSetupBuildInfo :: Maybe SetupBuildInfo
maybeSetupBuildInfo = do
        ReadyPackage ConfiguredPackage UnresolvedPkgLoc
cpkg <- Maybe ReadyPackage
mpkg
        let gpkg :: GenericPackageDescription
gpkg = UnresolvedSourcePackage -> GenericPackageDescription
forall loc. SourcePackage loc -> GenericPackageDescription
srcpkgDescription (ConfiguredPackage UnresolvedPkgLoc -> UnresolvedSourcePackage
forall loc. ConfiguredPackage loc -> SourcePackage loc
confPkgSource ConfiguredPackage UnresolvedPkgLoc
cpkg)
        PackageDescription -> Maybe SetupBuildInfo
PkgDesc.setupBuildInfo (GenericPackageDescription -> PackageDescription
PkgDesc.packageDescription GenericPackageDescription
gpkg)

      -- Was a default 'custom-setup' stanza added by 'cabal-install' itself? If
      -- so, 'setup-depends' must not be exclusive. See #3199.
      defaultSetupDeps :: Bool
      defaultSetupDeps :: Bool
defaultSetupDeps =
        Bool -> (SetupBuildInfo -> Bool) -> Maybe SetupBuildInfo -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
          Bool
False
          SetupBuildInfo -> Bool
PkgDesc.defaultSetupDepends
          Maybe SetupBuildInfo
maybeSetupBuildInfo

      explicitSetupDeps :: Maybe [(InstalledPackageId, PackageId)]
      explicitSetupDeps :: Maybe [(InstalledPackageId, PackageId)]
explicitSetupDeps = do
        -- Check if there is an explicit setup stanza.
        SetupBuildInfo
_buildInfo <- Maybe SetupBuildInfo
maybeSetupBuildInfo
        -- Return the setup dependencies computed by the solver
        ReadyPackage ConfiguredPackage UnresolvedPkgLoc
cpkg <- Maybe ReadyPackage
mpkg
        [(InstalledPackageId, PackageId)]
-> Maybe [(InstalledPackageId, PackageId)]
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return
          [ (InstalledPackageId
cid, PackageId
srcid)
          | ConfiguredId
              PackageId
srcid
              (Just (PkgDesc.CLibName LibraryName
PkgDesc.LMainLibName))
              InstalledPackageId
cid <-
              ComponentDeps [ConfiguredId] -> [ConfiguredId]
forall a. Monoid a => ComponentDeps a -> a
CD.setupDeps (ConfiguredPackage UnresolvedPkgLoc -> ComponentDeps [ConfiguredId]
forall loc. ConfiguredPackage loc -> ComponentDeps [ConfiguredId]
confPkgDeps ConfiguredPackage UnresolvedPkgLoc
cpkg)
          ]

-- | Warn if any constraints or preferences name packages that are not in the
-- source package index or installed package index.
checkConfigExFlags
  :: Package pkg
  => Verbosity
  -> InstalledPackageIndex
  -> PackageIndex pkg
  -> ConfigExFlags
  -> IO ()
checkConfigExFlags :: forall pkg.
Package pkg =>
Verbosity
-> InstalledPackageIndex
-> PackageIndex pkg
-> ConfigExFlags
-> IO ()
checkConfigExFlags Verbosity
verbosity InstalledPackageIndex
installedPkgIndex PackageIndex pkg
sourcePkgIndex ConfigExFlags
flags = do
  Maybe (UserConstraint, ConstraintSource)
-> ((UserConstraint, ConstraintSource) -> IO ()) -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ ([(UserConstraint, ConstraintSource)]
-> Maybe (UserConstraint, ConstraintSource)
forall a. [a] -> Maybe a
safeHead [(UserConstraint, ConstraintSource)]
unknownConstraints) (((UserConstraint, ConstraintSource) -> IO ()) -> IO ())
-> ((UserConstraint, ConstraintSource) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \(UserConstraint, ConstraintSource)
h ->
    Verbosity -> FilePath -> IO ()
warn Verbosity
verbosity (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$
      FilePath
"Constraint refers to an unknown package: "
        FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ (UserConstraint, ConstraintSource) -> FilePath
forall {a}. Pretty a => (a, ConstraintSource) -> FilePath
showConstraint (UserConstraint, ConstraintSource)
h
  Maybe PackageVersionConstraint
-> (PackageVersionConstraint -> IO ()) -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ ([PackageVersionConstraint] -> Maybe PackageVersionConstraint
forall a. [a] -> Maybe a
safeHead [PackageVersionConstraint]
unknownPreferences) ((PackageVersionConstraint -> IO ()) -> IO ())
-> (PackageVersionConstraint -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \PackageVersionConstraint
h ->
    Verbosity -> FilePath -> IO ()
warn Verbosity
verbosity (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$
      FilePath
"Preference refers to an unknown package: "
        FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ PackageVersionConstraint -> FilePath
forall a. Pretty a => a -> FilePath
prettyShow PackageVersionConstraint
h
  where
    unknownConstraints :: [(UserConstraint, ConstraintSource)]
unknownConstraints =
      ((UserConstraint, ConstraintSource) -> Bool)
-> [(UserConstraint, ConstraintSource)]
-> [(UserConstraint, ConstraintSource)]
forall a. (a -> Bool) -> [a] -> [a]
filter (PackageName -> Bool
unknown (PackageName -> Bool)
-> ((UserConstraint, ConstraintSource) -> PackageName)
-> (UserConstraint, ConstraintSource)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UserConstraint -> PackageName
userConstraintPackageName (UserConstraint -> PackageName)
-> ((UserConstraint, ConstraintSource) -> UserConstraint)
-> (UserConstraint, ConstraintSource)
-> PackageName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UserConstraint, ConstraintSource) -> UserConstraint
forall a b. (a, b) -> a
fst) ([(UserConstraint, ConstraintSource)]
 -> [(UserConstraint, ConstraintSource)])
-> [(UserConstraint, ConstraintSource)]
-> [(UserConstraint, ConstraintSource)]
forall a b. (a -> b) -> a -> b
$
        ConfigExFlags -> [(UserConstraint, ConstraintSource)]
configExConstraints ConfigExFlags
flags
    unknownPreferences :: [PackageVersionConstraint]
unknownPreferences =
      (PackageVersionConstraint -> Bool)
-> [PackageVersionConstraint] -> [PackageVersionConstraint]
forall a. (a -> Bool) -> [a] -> [a]
filter (PackageName -> Bool
unknown (PackageName -> Bool)
-> (PackageVersionConstraint -> PackageName)
-> PackageVersionConstraint
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \(PackageVersionConstraint PackageName
name VersionRange
_) -> PackageName
name) ([PackageVersionConstraint] -> [PackageVersionConstraint])
-> [PackageVersionConstraint] -> [PackageVersionConstraint]
forall a b. (a -> b) -> a -> b
$
        ConfigExFlags -> [PackageVersionConstraint]
configPreferences ConfigExFlags
flags
    unknown :: PackageName -> Bool
unknown PackageName
pkg =
      [(Version, [InstalledPackageInfo])] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (InstalledPackageIndex
-> PackageName -> [(Version, [InstalledPackageInfo])]
forall a. PackageIndex a -> PackageName -> [(Version, [a])]
PackageIndex.lookupPackageName InstalledPackageIndex
installedPkgIndex PackageName
pkg)
        Bool -> Bool -> Bool
&& Bool -> Bool
not (PackageIndex pkg -> PackageName -> Bool
forall pkg. Package pkg => PackageIndex pkg -> PackageName -> Bool
elemByPackageName PackageIndex pkg
sourcePkgIndex PackageName
pkg)
    showConstraint :: (a, ConstraintSource) -> FilePath
showConstraint (a
uc, ConstraintSource
src) =
      a -> FilePath
forall a. Pretty a => a -> FilePath
prettyShow a
uc FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" (" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ ConstraintSource -> FilePath
showConstraintSource ConstraintSource
src FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
")"

-- | Make an 'InstallPlan' for the unpacked package in the current directory,
-- and all its dependencies.
planLocalPackage
  :: Verbosity
  -> Compiler
  -> Platform
  -> ConfigFlags
  -> ConfigExFlags
  -> InstalledPackageIndex
  -> SourcePackageDb
  -> Maybe PkgConfigDb
  -> IO (Progress String String SolverInstallPlan)
planLocalPackage :: Verbosity
-> Compiler
-> Platform
-> ConfigFlags
-> ConfigExFlags
-> InstalledPackageIndex
-> SourcePackageDb
-> Maybe PkgConfigDb
-> IO (Progress FilePath FilePath SolverInstallPlan)
planLocalPackage
  Verbosity
verbosity
  Compiler
comp
  Platform
platform
  ConfigFlags
configFlags
  ConfigExFlags
configExFlags
  InstalledPackageIndex
installedPkgIndex
  (SourcePackageDb PackageIndex UnresolvedSourcePackage
_ Map PackageName VersionRange
packagePrefs)
  Maybe PkgConfigDb
pkgConfigDb = do
    GenericPackageDescription
pkg <-
      HasCallStack =>
Verbosity
-> Maybe (SymbolicPath CWD ('Dir Pkg))
-> SymbolicPath Pkg 'File
-> IO GenericPackageDescription
Verbosity
-> Maybe (SymbolicPath CWD ('Dir Pkg))
-> SymbolicPath Pkg 'File
-> IO GenericPackageDescription
readGenericPackageDescription Verbosity
verbosity Maybe (SymbolicPath CWD ('Dir Pkg))
forall a. Maybe a
Nothing
        (SymbolicPath Pkg 'File -> IO GenericPackageDescription)
-> IO (SymbolicPath Pkg 'File) -> IO GenericPackageDescription
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< case Flag (SymbolicPath Pkg 'File) -> Maybe (SymbolicPath Pkg 'File)
forall a. Flag a -> Maybe a
flagToMaybe (CommonSetupFlags -> Flag (SymbolicPath Pkg 'File)
setupCabalFilePath (CommonSetupFlags -> Flag (SymbolicPath Pkg 'File))
-> CommonSetupFlags -> Flag (SymbolicPath Pkg 'File)
forall a b. (a -> b) -> a -> b
$ ConfigFlags -> CommonSetupFlags
configCommonFlags ConfigFlags
configFlags) of
          Maybe (SymbolicPath Pkg 'File)
Nothing -> RelativePath Pkg 'File -> SymbolicPath Pkg 'File
forall from (to :: FileOrDir).
RelativePath from to -> SymbolicPath from to
relativeSymbolicPath (RelativePath Pkg 'File -> SymbolicPath Pkg 'File)
-> IO (RelativePath Pkg 'File) -> IO (SymbolicPath Pkg 'File)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Verbosity -> IO (RelativePath Pkg 'File)
defaultPackageDescCwd Verbosity
verbosity
          Just SymbolicPath Pkg 'File
fp -> SymbolicPath Pkg 'File -> IO (SymbolicPath Pkg 'File)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return SymbolicPath Pkg 'File
fp

    let
      -- We create a local package and ask to resolve a dependency on it
      localPkg :: SourcePackage (PackageLocation local)
localPkg =
        SourcePackage
          { srcpkgPackageId :: PackageId
srcpkgPackageId = GenericPackageDescription -> PackageId
forall pkg. Package pkg => pkg -> PackageId
packageId GenericPackageDescription
pkg
          , srcpkgDescription :: GenericPackageDescription
srcpkgDescription = GenericPackageDescription
pkg
          , srcpkgSource :: PackageLocation local
srcpkgSource = FilePath -> PackageLocation local
forall local. FilePath -> PackageLocation local
LocalUnpackedPackage FilePath
"."
          , srcpkgDescrOverride :: PackageDescriptionOverride
srcpkgDescrOverride = PackageDescriptionOverride
forall a. Maybe a
Nothing
          }

      testsEnabled :: Bool
      testsEnabled :: Bool
testsEnabled = Bool -> Flag Bool -> Bool
forall a. a -> Flag a -> a
fromFlagOrDefault Bool
False (Flag Bool -> Bool) -> Flag Bool -> Bool
forall a b. (a -> b) -> a -> b
$ ConfigFlags -> Flag Bool
configTests ConfigFlags
configFlags
      benchmarksEnabled :: Bool
      benchmarksEnabled :: Bool
benchmarksEnabled =
        Bool -> Flag Bool -> Bool
forall a. a -> Flag a -> a
fromFlagOrDefault Bool
False (Flag Bool -> Bool) -> Flag Bool -> Bool
forall a b. (a -> b) -> a -> b
$ ConfigFlags -> Flag Bool
configBenchmarks ConfigFlags
configFlags

      resolverParams :: DepResolverParams
      resolverParams :: DepResolverParams
resolverParams =
        AllowOlder -> DepResolverParams -> DepResolverParams
removeLowerBounds
          (AllowOlder -> Maybe AllowOlder -> AllowOlder
forall a. a -> Maybe a -> a
fromMaybe (RelaxDeps -> AllowOlder
AllowOlder RelaxDeps
forall a. Monoid a => a
mempty) (Maybe AllowOlder -> AllowOlder) -> Maybe AllowOlder -> AllowOlder
forall a b. (a -> b) -> a -> b
$ ConfigExFlags -> Maybe AllowOlder
configAllowOlder ConfigExFlags
configExFlags)
          (DepResolverParams -> DepResolverParams)
-> (DepResolverParams -> DepResolverParams)
-> DepResolverParams
-> DepResolverParams
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AllowNewer -> DepResolverParams -> DepResolverParams
removeUpperBounds
            (AllowNewer -> Maybe AllowNewer -> AllowNewer
forall a. a -> Maybe a -> a
fromMaybe (RelaxDeps -> AllowNewer
AllowNewer RelaxDeps
forall a. Monoid a => a
mempty) (Maybe AllowNewer -> AllowNewer) -> Maybe AllowNewer -> AllowNewer
forall a b. (a -> b) -> a -> b
$ ConfigExFlags -> Maybe AllowNewer
configAllowNewer ConfigExFlags
configExFlags)
          (DepResolverParams -> DepResolverParams)
-> (DepResolverParams -> DepResolverParams)
-> DepResolverParams
-> DepResolverParams
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [PackagePreference] -> DepResolverParams -> DepResolverParams
addPreferences
            -- preferences from the config file or command line
            [ PackageName -> VersionRange -> PackagePreference
PackageVersionPreference PackageName
name VersionRange
ver
            | PackageVersionConstraint PackageName
name VersionRange
ver <- ConfigExFlags -> [PackageVersionConstraint]
configPreferences ConfigExFlags
configExFlags
            ]
          (DepResolverParams -> DepResolverParams)
-> (DepResolverParams -> DepResolverParams)
-> DepResolverParams
-> DepResolverParams
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [LabeledPackageConstraint]
-> DepResolverParams -> DepResolverParams
addConstraints
            -- version constraints from the config file or command line
            -- TODO: should warn or error on constraints that are not on direct
            -- deps or flag constraints not on the package in question.
            [ PackageConstraint -> ConstraintSource -> LabeledPackageConstraint
LabeledPackageConstraint (UserConstraint -> PackageConstraint
userToPackageConstraint UserConstraint
uc) ConstraintSource
src
            | (UserConstraint
uc, ConstraintSource
src) <- ConfigExFlags -> [(UserConstraint, ConstraintSource)]
configExConstraints ConfigExFlags
configExFlags
            ]
          (DepResolverParams -> DepResolverParams)
-> (DepResolverParams -> DepResolverParams)
-> DepResolverParams
-> DepResolverParams
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [LabeledPackageConstraint]
-> DepResolverParams -> DepResolverParams
addConstraints
            -- package flags from the config file or command line
            [ let pc :: PackageConstraint
pc =
                    ConstraintScope -> PackageProperty -> PackageConstraint
PackageConstraint
                      (PackageName -> ConstraintScope
scopeToplevel (PackageName -> ConstraintScope) -> PackageName -> ConstraintScope
forall a b. (a -> b) -> a -> b
$ GenericPackageDescription -> PackageName
forall pkg. Package pkg => pkg -> PackageName
packageName GenericPackageDescription
pkg)
                      (FlagAssignment -> PackageProperty
PackagePropertyFlags (FlagAssignment -> PackageProperty)
-> FlagAssignment -> PackageProperty
forall a b. (a -> b) -> a -> b
$ ConfigFlags -> FlagAssignment
configConfigurationsFlags ConfigFlags
configFlags)
               in PackageConstraint -> ConstraintSource -> LabeledPackageConstraint
LabeledPackageConstraint PackageConstraint
pc ConstraintSource
ConstraintSourceConfigFlagOrTarget
            ]
          (DepResolverParams -> DepResolverParams)
-> (DepResolverParams -> DepResolverParams)
-> DepResolverParams
-> DepResolverParams
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [LabeledPackageConstraint]
-> DepResolverParams -> DepResolverParams
addConstraints
            -- '--enable-tests' and '--enable-benchmarks' constraints from
            -- the config file or command line
            [ let pc :: PackageConstraint
pc =
                    ConstraintScope -> PackageProperty -> PackageConstraint
PackageConstraint (PackageName -> ConstraintScope
scopeToplevel (PackageName -> ConstraintScope) -> PackageName -> ConstraintScope
forall a b. (a -> b) -> a -> b
$ GenericPackageDescription -> PackageName
forall pkg. Package pkg => pkg -> PackageName
packageName GenericPackageDescription
pkg)
                      (PackageProperty -> PackageConstraint)
-> ([OptionalStanza] -> PackageProperty)
-> [OptionalStanza]
-> PackageConstraint
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [OptionalStanza] -> PackageProperty
PackagePropertyStanzas
                      ([OptionalStanza] -> PackageConstraint)
-> [OptionalStanza] -> PackageConstraint
forall a b. (a -> b) -> a -> b
$ [OptionalStanza
TestStanzas | Bool
testsEnabled]
                        [OptionalStanza] -> [OptionalStanza] -> [OptionalStanza]
forall a. [a] -> [a] -> [a]
++ [OptionalStanza
BenchStanzas | Bool
benchmarksEnabled]
               in PackageConstraint -> ConstraintSource -> LabeledPackageConstraint
LabeledPackageConstraint PackageConstraint
pc ConstraintSource
ConstraintSourceConfigFlagOrTarget
            ]
          -- Don't solve for executables, since we use an empty source
          -- package database and executables never show up in the
          -- installed package index
          (DepResolverParams -> DepResolverParams)
-> (DepResolverParams -> DepResolverParams)
-> DepResolverParams
-> DepResolverParams
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SolveExecutables -> DepResolverParams -> DepResolverParams
setSolveExecutables (Bool -> SolveExecutables
SolveExecutables Bool
False)
          (DepResolverParams -> DepResolverParams)
-> (DepResolverParams -> DepResolverParams)
-> DepResolverParams
-> DepResolverParams
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Verbosity -> DepResolverParams -> DepResolverParams
setSolverVerbosity Verbosity
verbosity
          (DepResolverParams -> DepResolverParams)
-> DepResolverParams -> DepResolverParams
forall a b. (a -> b) -> a -> b
$ InstalledPackageIndex
-> SourcePackageDb
-> [PackageSpecifier UnresolvedSourcePackage]
-> DepResolverParams
standardInstallPolicy
            InstalledPackageIndex
installedPkgIndex
            -- NB: We pass in an *empty* source package database,
            -- because cabal configure assumes that all dependencies
            -- have already been installed
            (PackageIndex UnresolvedSourcePackage
-> Map PackageName VersionRange -> SourcePackageDb
SourcePackageDb PackageIndex UnresolvedSourcePackage
forall a. Monoid a => a
mempty Map PackageName VersionRange
packagePrefs)
            [UnresolvedSourcePackage -> PackageSpecifier UnresolvedSourcePackage
forall pkg. pkg -> PackageSpecifier pkg
SpecificSourcePackage UnresolvedSourcePackage
forall {local}. SourcePackage (PackageLocation local)
localPkg]

    Progress FilePath FilePath SolverInstallPlan
-> IO (Progress FilePath FilePath SolverInstallPlan)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Platform
-> CompilerInfo
-> Maybe PkgConfigDb
-> DepResolverParams
-> Progress FilePath FilePath SolverInstallPlan
resolveDependencies Platform
platform (Compiler -> CompilerInfo
compilerInfo Compiler
comp) Maybe PkgConfigDb
pkgConfigDb DepResolverParams
resolverParams)

-- | Call an installer for an 'SourcePackage' but override the configure
-- flags with the ones given by the 'ReadyPackage'. In particular the
-- 'ReadyPackage' specifies an exact 'FlagAssignment' and exactly
-- versioned package dependencies. So we ignore any previous partial flag
-- assignment or dependency constraints and use the new ones.
--
-- NB: when updating this function, don't forget to also update
-- 'installReadyPackage' in D.C.Install.
configurePackage
  :: Verbosity
  -> Platform
  -> CompilerInfo
  -> SetupScriptOptions
  -> ConfigFlags
  -> ReadyPackage
  -> [String]
  -> IO ()
configurePackage :: Verbosity
-> Platform
-> CompilerInfo
-> SetupScriptOptions
-> ConfigFlags
-> ReadyPackage
-> [FilePath]
-> IO ()
configurePackage
  Verbosity
verbosity
  Platform
platform
  CompilerInfo
comp
  SetupScriptOptions
scriptOptions
  ConfigFlags
configFlags
  (ReadyPackage (ConfiguredPackage InstalledPackageId
ipid UnresolvedSourcePackage
spkg FlagAssignment
flags OptionalStanzaSet
stanzas ComponentDeps [ConfiguredId]
deps))
  [FilePath]
extraArgs =
    Verbosity
-> SetupScriptOptions
-> Maybe PackageDescription
-> CommandUI ConfigFlags
-> (ConfigFlags -> CommonSetupFlags)
-> (Version -> IO ConfigFlags)
-> (Version -> [FilePath])
-> IO ()
forall flags.
Verbosity
-> SetupScriptOptions
-> Maybe PackageDescription
-> CommandUI flags
-> (flags -> CommonSetupFlags)
-> (Version -> IO flags)
-> (Version -> [FilePath])
-> IO ()
setupWrapper
      Verbosity
verbosity
      SetupScriptOptions
scriptOptions
      (PackageDescription -> Maybe PackageDescription
forall a. a -> Maybe a
Just PackageDescription
pkg)
      CommandUI ConfigFlags
configureCommand
      ConfigFlags -> CommonSetupFlags
configCommonFlags
      (ConfigFlags -> IO ConfigFlags
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ConfigFlags -> IO ConfigFlags)
-> (Version -> ConfigFlags) -> Version -> IO ConfigFlags
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Version -> ConfigFlags
configureFlags)
      ([FilePath] -> Version -> [FilePath]
forall a b. a -> b -> a
const [FilePath]
extraArgs)
    where
      gpkg :: PkgDesc.GenericPackageDescription
      gpkg :: GenericPackageDescription
gpkg = UnresolvedSourcePackage -> GenericPackageDescription
forall loc. SourcePackage loc -> GenericPackageDescription
srcpkgDescription UnresolvedSourcePackage
spkg
      configureFlags :: Version -> ConfigFlags
      configureFlags :: Version -> ConfigFlags
configureFlags =
        ConfigFlags -> Version -> ConfigFlags
filterConfigureFlags
          ConfigFlags
configFlags
            { configCommonFlags =
                (configCommonFlags configFlags)
                  { setupVerbosity = toFlag verbosity
                  , setupWorkingDir = maybeToFlag $ useWorkingDir scriptOptions
                  }
            , configIPID =
                if isJust (flagToMaybe (configIPID configFlags))
                  then -- Make sure cabal configure --ipid works.
                    configIPID configFlags
                  else toFlag (prettyShow ipid)
            , configConfigurationsFlags = flags
            , -- We generate the legacy constraints as well as the new style precise
              -- deps.  In the end only one set gets passed to Setup.hs configure,
              -- depending on the Cabal version we are talking to.
              configConstraints =
                [ thisPackageVersionConstraint srcid
                | ConfiguredId srcid (Just (PkgDesc.CLibName PkgDesc.LMainLibName)) _uid <-
                    CD.nonSetupDeps deps
                ]
            , configDependencies =
                [ GivenComponent (packageName srcid) cname uid
                | ConfiguredId srcid (Just (PkgDesc.CLibName cname)) uid <-
                    CD.nonSetupDeps deps
                ]
            , -- Use '--exact-configuration' if supported.
              configExactConfiguration = toFlag True
            , -- NB: if the user explicitly specified
              -- --enable-tests/--enable-benchmarks, always respect it.
              -- (But if they didn't, let solver decide.)
              configBenchmarks =
                toFlag (BenchStanzas `optStanzaSetMember` stanzas)
                  `mappend` configBenchmarks configFlags
            , configTests =
                toFlag (TestStanzas `optStanzaSetMember` stanzas)
                  `mappend` configTests configFlags
            }

      pkg :: PkgDesc.PackageDescription
      pkg :: PackageDescription
pkg = case FlagAssignment
-> ComponentRequestedSpec
-> (Dependency -> Bool)
-> Platform
-> CompilerInfo
-> [PackageVersionConstraint]
-> GenericPackageDescription
-> Either [Dependency] (PackageDescription, FlagAssignment)
finalizePD
        FlagAssignment
flags
        (OptionalStanzaSet -> ComponentRequestedSpec
enableStanzas OptionalStanzaSet
stanzas)
        (Bool -> Dependency -> Bool
forall a b. a -> b -> a
const Bool
True)
        Platform
platform
        CompilerInfo
comp
        []
        GenericPackageDescription
gpkg of
        Left [Dependency]
_ -> FilePath -> PackageDescription
forall a. HasCallStack => FilePath -> a
error FilePath
"finalizePD ReadyPackage failed"
        Right (PackageDescription
desc, FlagAssignment
_) -> PackageDescription
desc

-- -----------------------------------------------------------------------------

-- * Saved configure environments and flags

-- -----------------------------------------------------------------------------

-- | Read saved configure flags and restore the saved environment from the
-- specified files.
readConfigFlagsFrom
  :: FilePath
  -- ^ path to saved flags file
  -> IO (ConfigFlags, ConfigExFlags)
readConfigFlagsFrom :: FilePath -> IO (ConfigFlags, ConfigExFlags)
readConfigFlagsFrom FilePath
flags = do
  FilePath
-> CommandUI (ConfigFlags, ConfigExFlags)
-> IO (ConfigFlags, ConfigExFlags)
forall flags. FilePath -> CommandUI flags -> IO flags
readCommandFlags FilePath
flags CommandUI (ConfigFlags, ConfigExFlags)
configureExCommand

-- | The path (relative to the package root) where the arguments to @configure@
-- should be saved.
cabalConfigFlagsFile :: FilePath -> FilePath
cabalConfigFlagsFile :: FilePath -> FilePath
cabalConfigFlagsFile FilePath
dist = FilePath
dist FilePath -> FilePath -> FilePath
forall p q r. PathLike p q r => p -> q -> r
</> FilePath
"cabal-config-flags"

-- | Read saved configure flags and restore the saved environment from the
-- usual location.
readConfigFlags
  :: FilePath
  -- ^ @--build-dir@
  -> IO (ConfigFlags, ConfigExFlags)
readConfigFlags :: FilePath -> IO (ConfigFlags, ConfigExFlags)
readConfigFlags FilePath
dist =
  FilePath -> IO (ConfigFlags, ConfigExFlags)
readConfigFlagsFrom (FilePath -> FilePath
cabalConfigFlagsFile FilePath
dist)

-- | Save the configure flags and environment to the specified files.
writeConfigFlagsTo
  :: Verbosity
  -> FilePath
  -- ^ path to saved flags file
  -> (ConfigFlags, ConfigExFlags)
  -> IO ()
writeConfigFlagsTo :: Verbosity -> FilePath -> (ConfigFlags, ConfigExFlags) -> IO ()
writeConfigFlagsTo Verbosity
verb FilePath
file (ConfigFlags, ConfigExFlags)
flags = do
  Verbosity
-> FilePath
-> CommandUI (ConfigFlags, ConfigExFlags)
-> (ConfigFlags, ConfigExFlags)
-> IO ()
forall flags.
Verbosity -> FilePath -> CommandUI flags -> flags -> IO ()
writeCommandFlags Verbosity
verb FilePath
file CommandUI (ConfigFlags, ConfigExFlags)
configureExCommand (ConfigFlags, ConfigExFlags)
flags

-- | Save the build flags to the usual location.
writeConfigFlags
  :: Verbosity
  -> FilePath
  -- ^ @--build-dir@
  -> (ConfigFlags, ConfigExFlags)
  -> IO ()
writeConfigFlags :: Verbosity -> FilePath -> (ConfigFlags, ConfigExFlags) -> IO ()
writeConfigFlags Verbosity
verb FilePath
dist =
  Verbosity -> FilePath -> (ConfigFlags, ConfigExFlags) -> IO ()
writeConfigFlagsTo Verbosity
verb (FilePath -> FilePath
cabalConfigFlagsFile FilePath
dist)