Commit dd2da8de authored by Duncan Coutts's avatar Duncan Coutts Committed by Edward Z. Yang
Browse files

Split the ProjectPlanning types out into another module

Not needed immediately, but we'll need it eventually to avoid import
cycles later. No other changes, just moving things around and pruning
imports and language extensions.
parent a59f269b
{-# LANGUAGE CPP, RecordWildCards, NamedFieldPuns,
DeriveGeneric, DeriveDataTypeable,
RankNTypes, ScopedTypeVariables #-}
{-# LANGUAGE CPP, RecordWildCards, NamedFieldPuns, RankNTypes #-}
-- | Planning how to build everything in a project.
--
......@@ -56,15 +54,14 @@ module Distribution.Client.ProjectPlanning (
createPackageDBIfMissing
) where
import Distribution.Client.ProjectPlanning.Types
import Distribution.Client.PackageHash
import Distribution.Client.RebuildMonad
import Distribution.Client.ProjectConfig
import Distribution.Client.Types hiding
(BuildResult,BuildSuccess(..), BuildFailure(..), DocsResult(..)
,TestsResult(..))
import Distribution.Client.InstallPlan
( GenericInstallPlan, GenericPlanPackage, SolverInstallPlan )
import Distribution.Client.Types
hiding ( BuildResult, BuildSuccess(..), BuildFailure(..)
, DocsResult(..), TestsResult(..) )
import qualified Distribution.Client.InstallPlan as InstallPlan
import Distribution.Client.Dependency
import Distribution.Client.Dependency.Types
......@@ -87,7 +84,6 @@ import Distribution.System
import qualified Distribution.PackageDescription as Cabal
import qualified Distribution.PackageDescription as PD
import qualified Distribution.PackageDescription.Configuration as PD
import Distribution.InstalledPackageInfo (InstalledPackageInfo)
import Distribution.Simple.PackageIndex (InstalledPackageIndex)
import qualified Distribution.Simple.PackageIndex as PackageIndex
import Distribution.Simple.Compiler hiding (Flag)
......@@ -100,12 +96,10 @@ import qualified Distribution.Simple.Setup as Cabal
import Distribution.Simple.Setup
(Flag, toFlag, flagToMaybe, flagToList, fromFlagOrDefault)
import qualified Distribution.Simple.Configure as Cabal
import Distribution.ModuleName (ModuleName)
import qualified Distribution.Simple.LocalBuildInfo as Cabal
import Distribution.Simple.LocalBuildInfo (ComponentName(..))
import qualified Distribution.Simple.Register as Cabal
import qualified Distribution.Simple.InstallDirs as InstallDirs
import Distribution.Simple.InstallDirs (PathTemplate)
import qualified Distribution.Simple.BuildTarget as Cabal
import Distribution.Simple.Utils hiding (matchFileGlob)
......@@ -119,8 +113,6 @@ import Data.Set (Set)
import qualified Data.Set as Set
import qualified Data.Graph as Graph
import qualified Data.Tree as Tree
import qualified Data.ByteString.Lazy as LBS
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative
#endif
......@@ -131,11 +123,6 @@ import Data.List
import Data.Maybe
import Data.Monoid
import Data.Function
import Distribution.Compat.Binary
import GHC.Generics (Generic)
import Data.Typeable (Typeable)
import System.FilePath
......@@ -180,230 +167,13 @@ import System.FilePath
-- condition on the graph structure).
--
-- | The combination of an elaborated install plan plus a
-- 'ElaboratedSharedConfig' contains all the details necessary to be able
-- to execute the plan without having to make further policy decisions.
--
-- It does not include dynamic elements such as resources (such as http
-- connections).
--
type ElaboratedInstallPlan
= GenericInstallPlan InstalledPackageInfo
ElaboratedConfiguredPackage
BuildSuccess BuildFailure
type ElaboratedPlanPackage
= GenericPlanPackage InstalledPackageInfo
ElaboratedConfiguredPackage
BuildSuccess BuildFailure
--TODO: [code cleanup] decide if we really need this, there's not much in it, and in principle
-- even platform and compiler could be different if we're building things
-- like a server + client with ghc + ghcjs
data ElaboratedSharedConfig
= ElaboratedSharedConfig {
pkgConfigPlatform :: Platform,
pkgConfigCompiler :: Compiler, --TODO: [code cleanup] replace with CompilerInfo
pkgConfigCompilerProgs :: ProgramDb --TODO: [code cleanup] no Eq instance
--TODO: [code cleanup] binary instance does not preserve the prog paths
-- perhaps should keep the configured progs separately
}
deriving (Show, Generic)
instance Binary ElaboratedSharedConfig
data ElaboratedConfiguredPackage
= ElaboratedConfiguredPackage {
pkgInstalledId :: InstalledPackageId,
pkgSourceId :: PackageId,
-- | TODO: [code cleanup] we don't need this, just a few bits from it:
-- build type, spec version
pkgDescription :: Cabal.PackageDescription,
-- | A total flag assignment for the package
pkgFlagAssignment :: Cabal.FlagAssignment,
-- | The original default flag assignment, used only for reporting.
pkgFlagDefaults :: Cabal.FlagAssignment,
-- | The exact dependencies (on other plan packages)
--
pkgDependencies :: ComponentDeps [ConfiguredId],
-- | Which optional stanzas (ie testsuites, benchmarks) can be built.
-- This means the solver produced a plan that has them available.
-- This doesn't necessary mean we build them by default.
pkgStanzasAvailable :: Set OptionalStanza,
-- | Which optional stanzas the user explicitly asked to enable or
-- to disable. This tells us which ones we build by default, and
-- helps with error messages when the user asks to build something
-- they explicitly disabled.
pkgStanzasRequested :: Map OptionalStanza Bool,
-- | Which optional stanzas (ie testsuites, benchmarks) will actually
-- be enabled during the package configure step.
pkgStanzasEnabled :: Set OptionalStanza,
-- | Where the package comes from, e.g. tarball, local dir etc. This
-- is not the same as where it may be unpacked to for the build.
pkgSourceLocation :: PackageLocation (Maybe FilePath),
-- | The hash of the source, e.g. the tarball. We don't have this for
-- local source dir packages.
pkgSourceHash :: Maybe PackageSourceHash,
--pkgSourceDir ? -- currently passed in later because they can use temp locations
--pkgBuildDir ? -- but could in principle still have it here, with optional instr to use temp loc
pkgBuildStyle :: BuildStyle,
pkgSetupPackageDBStack :: PackageDBStack,
pkgBuildPackageDBStack :: PackageDBStack,
pkgRegisterPackageDBStack :: PackageDBStack,
-- | The package contains a library and so must be registered
pkgRequiresRegistration :: Bool,
pkgDescriptionOverride :: Maybe CabalFileText,
pkgVanillaLib :: Bool,
pkgSharedLib :: Bool,
pkgDynExe :: Bool,
pkgGHCiLib :: Bool,
pkgProfLib :: Bool,
pkgProfExe :: Bool,
pkgProfLibDetail :: ProfDetailLevel,
pkgProfExeDetail :: ProfDetailLevel,
pkgCoverage :: Bool,
pkgOptimization :: OptimisationLevel,
pkgSplitObjs :: Bool,
pkgStripLibs :: Bool,
pkgStripExes :: Bool,
pkgDebugInfo :: DebugInfoLevel,
pkgConfigureScriptArgs :: [String],
pkgExtraLibDirs :: [FilePath],
pkgExtraFrameworkDirs :: [FilePath],
pkgExtraIncludeDirs :: [FilePath],
pkgProgPrefix :: Maybe PathTemplate,
pkgProgSuffix :: Maybe PathTemplate,
pkgInstallDirs :: InstallDirs.InstallDirs FilePath,
pkgHaddockHoogle :: Bool,
pkgHaddockHtml :: Bool,
pkgHaddockHtmlLocation :: Maybe String,
pkgHaddockExecutables :: Bool,
pkgHaddockTestSuites :: Bool,
pkgHaddockBenchmarks :: Bool,
pkgHaddockInternal :: Bool,
pkgHaddockCss :: Maybe FilePath,
pkgHaddockHscolour :: Bool,
pkgHaddockHscolourCss :: Maybe FilePath,
pkgHaddockContents :: Maybe PathTemplate,
-- Setup.hs related things:
-- | One of four modes for how we build and interact with the Setup.hs
-- script, based on whether it's a build-type Custom, with or without
-- explicit deps and the cabal spec version the .cabal file needs.
pkgSetupScriptStyle :: SetupScriptStyle,
-- | The version of the Cabal command line interface that we are using
-- for this package. This is typically the version of the Cabal lib
-- that the Setup.hs is built against.
pkgSetupScriptCliVersion :: Version,
-- Build time related:
pkgBuildTargets :: [ComponentTarget],
pkgReplTarget :: Maybe ComponentTarget,
pkgBuildHaddocks :: Bool
}
deriving (Eq, Show, Generic)
instance Binary ElaboratedConfiguredPackage
instance Package ElaboratedConfiguredPackage where
packageId = pkgSourceId
instance HasUnitId ElaboratedConfiguredPackage where
installedUnitId = pkgInstalledId
instance PackageFixedDeps ElaboratedConfiguredPackage where
depends = fmap (map installedPackageId) . pkgDependencies
-- | This is used in the install plan to indicate how the package will be
-- built.
--
data BuildStyle =
-- | The classic approach where the package is built, then the files
-- installed into some location and the result registered in a package db.
--
-- If the package came from a tarball then it's built in a temp dir and
-- the results discarded.
BuildAndInstall
-- | The package is built, but the files are not installed anywhere,
-- rather the build dir is kept and the package is registered inplace.
--
-- Such packages can still subsequently be installed.
--
-- Typically 'BuildAndInstall' packages will only depend on other
-- 'BuildAndInstall' style packages and not on 'BuildInplaceOnly' ones.
--
| BuildInplaceOnly
deriving (Eq, Show, Generic)
instance Binary BuildStyle
type CabalFileText = LBS.ByteString
type ElaboratedReadyPackage = GenericReadyPackage ElaboratedConfiguredPackage
--TODO: [code cleanup] this duplicates the InstalledPackageInfo quite a bit in an install plan
-- because the same ipkg is used by many packages. So the binary file will be big.
-- Could we keep just (ipkgid, deps) instead of the whole InstalledPackageInfo?
-- or transform to a shared form when serialising / deserialising
-- Refer to ProjectPlanning.Types for details of these important types:
data GenericBuildResult ipkg iresult ifailure
= BuildFailure ifailure
| BuildSuccess (Maybe ipkg) iresult
deriving (Eq, Show, Generic)
instance (Binary ipkg, Binary iresult, Binary ifailure) =>
Binary (GenericBuildResult ipkg iresult ifailure)
type BuildResult = GenericBuildResult InstalledPackageInfo
BuildSuccess BuildFailure
data BuildSuccess = BuildOk DocsResult TestsResult
deriving (Eq, Show, Generic)
data DocsResult = DocsNotTried | DocsFailed | DocsOk
deriving (Eq, Show, Generic)
data TestsResult = TestsNotTried | TestsOk
deriving (Eq, Show, Generic)
data BuildFailure = PlanningFailed --TODO: [required eventually] not yet used
| DependentFailed PackageId
| DownloadFailed String --TODO: [required eventually] not yet used
| UnpackFailed String --TODO: [required eventually] not yet used
| ConfigureFailed String
| BuildFailed String
| TestsFailed String --TODO: [required eventually] not yet used
| InstallFailed String
deriving (Eq, Show, Typeable, Generic)
instance Exception BuildFailure
instance Binary BuildFailure
instance Binary BuildSuccess
instance Binary DocsResult
instance Binary TestsResult
-- type ElaboratedInstallPlan = ...
-- type ElaboratedPlanPackage = ...
-- data ElaboratedSharedConfig = ...
-- data ElaboratedConfiguredPackage = ...
-- data BuildStyle =
sanityCheckElaboratedConfiguredPackage :: ElaboratedSharedConfig
......@@ -1302,32 +1072,11 @@ elaborateInstallPlan platform compiler compilerprogdb
-- Build targets
--
-- | The various targets within a package. This is more of a high level
-- specification than a elaborated prescription.
--
data PackageTarget =
-- | Build the default components in this package. This usually means
-- just the lib and exes, but it can also mean the testsuites and
-- benchmarks if the user explicitly requested them.
BuildDefaultComponents
-- | Build a specific component in this package.
| BuildSpecificComponent ComponentTarget
| ReplDefaultComponent
| ReplSpecificComponent ComponentTarget
| HaddockDefaultComponents
deriving (Eq, Show, Generic)
data ComponentTarget = ComponentTarget ComponentName SubComponentTarget
deriving (Eq, Show, Generic)
data SubComponentTarget = WholeComponent
| ModuleTarget ModuleName
| FileTarget FilePath
deriving (Eq, Show, Generic)
instance Binary PackageTarget
instance Binary ComponentTarget
instance Binary SubComponentTarget
-- Refer to ProjectPlanning.Types for details of these important types:
-- data PackageTarget = ...
-- data ComponentTarget = ...
-- data SubComponentTarget = ...
--TODO: this needs to report some user target/config errors
......@@ -1675,8 +1424,8 @@ dependencyGraph pkgid deps pkgs =
-- solver phase, and part in the elaboration phase. We keep the helper
-- functions for both phases together here so at least you can see all of it
-- in one place.
-- | There are four major cases for Setup.hs handling:
--
-- There are four major cases for Setup.hs handling:
--
-- 1. @build-type@ Custom with a @custom-setup@ section
-- 2. @build-type@ Custom without a @custom-setup@ section
......@@ -1693,14 +1442,7 @@ dependencyGraph pkgid deps pkgs =
-- to build an external Setup.hs script because the package needs a later
-- Cabal lib version than we can support internally.
--
data SetupScriptStyle = SetupCustomExplicitDeps
| SetupCustomImplicitDeps
| SetupNonCustomExternalLib
| SetupNonCustomInternalLib
deriving (Eq, Show, Generic)
instance Binary SetupScriptStyle
-- data SetupScriptStyle = ... -- see ProjectPlanning.Types
-- | Work out the 'SetupScriptStyle' given the package description.
--
......
{-# LANGUAGE DeriveGeneric, DeriveDataTypeable #-}
-- | Types used while planning how to build everything in a project.
--
-- Primarily this is the 'ElaboratedInstallPlan'.
--
module Distribution.Client.ProjectPlanning.Types (
SolverInstallPlan,
-- * Elaborated install plan types
ElaboratedInstallPlan,
ElaboratedConfiguredPackage(..),
ElaboratedPlanPackage,
ElaboratedSharedConfig(..),
ElaboratedReadyPackage,
BuildStyle(..),
CabalFileText,
-- * Types used in executing an install plan
--TODO: [code cleanup] these types should live with execution, not with
-- plan definition. Need to better separate InstallPlan definition.
GenericBuildResult(..),
BuildResult,
BuildSuccess(..),
BuildFailure(..),
DocsResult(..),
TestsResult(..),
-- * Build targets
PackageTarget(..),
ComponentTarget(..),
SubComponentTarget(..),
-- * Setup script
SetupScriptStyle(..),
) where
import Distribution.Client.PackageHash
import Distribution.Client.Types
hiding ( BuildResult, BuildSuccess(..), BuildFailure(..)
, DocsResult(..), TestsResult(..) )
import Distribution.Client.InstallPlan
( GenericInstallPlan, InstallPlan, GenericPlanPackage )
import Distribution.Client.ComponentDeps (ComponentDeps)
import Distribution.Package
hiding (InstalledPackageId, installedPackageId)
import Distribution.System
import qualified Distribution.PackageDescription as Cabal
import Distribution.InstalledPackageInfo (InstalledPackageInfo)
import Distribution.Simple.Compiler
import Distribution.Simple.Program.Db
import Distribution.ModuleName (ModuleName)
import Distribution.Simple.LocalBuildInfo (ComponentName(..))
import qualified Distribution.Simple.InstallDirs as InstallDirs
import Distribution.Simple.InstallDirs (PathTemplate)
import Distribution.Version
import Data.Map (Map)
import Data.Set (Set)
import qualified Data.ByteString.Lazy as LBS
import Distribution.Compat.Binary
import GHC.Generics (Generic)
import Data.Typeable (Typeable)
import Control.Exception
-- | The combination of an elaborated install plan plus a
-- 'ElaboratedSharedConfig' contains all the details necessary to be able
-- to execute the plan without having to make further policy decisions.
--
-- It does not include dynamic elements such as resources (such as http
-- connections).
--
type ElaboratedInstallPlan
= GenericInstallPlan InstalledPackageInfo
ElaboratedConfiguredPackage
BuildSuccess BuildFailure
type ElaboratedPlanPackage
= GenericPlanPackage InstalledPackageInfo
ElaboratedConfiguredPackage
BuildSuccess BuildFailure
--TODO: [code cleanup] decide if we really need this, there's not much in it, and in principle
-- even platform and compiler could be different if we're building things
-- like a server + client with ghc + ghcjs
data ElaboratedSharedConfig
= ElaboratedSharedConfig {
pkgConfigPlatform :: Platform,
pkgConfigCompiler :: Compiler, --TODO: [code cleanup] replace with CompilerInfo
pkgConfigCompilerProgs :: ProgramDb --TODO: [code cleanup] no Eq instance
--TODO: [code cleanup] binary instance does not preserve the prog paths
-- perhaps should keep the configured progs separately
}
deriving (Show, Generic)
instance Binary ElaboratedSharedConfig
data ElaboratedConfiguredPackage
= ElaboratedConfiguredPackage {
pkgInstalledId :: InstalledPackageId,
pkgSourceId :: PackageId,
-- | TODO: [code cleanup] we don't need this, just a few bits from it:
-- build type, spec version
pkgDescription :: Cabal.PackageDescription,
-- | A total flag assignment for the package
pkgFlagAssignment :: Cabal.FlagAssignment,
-- | The original default flag assignment, used only for reporting.
pkgFlagDefaults :: Cabal.FlagAssignment,
-- | The exact dependencies (on other plan packages)
--
pkgDependencies :: ComponentDeps [ConfiguredId],
-- | Which optional stanzas (ie testsuites, benchmarks) can be built.
-- This means the solver produced a plan that has them available.
-- This doesn't necessary mean we build them by default.
pkgStanzasAvailable :: Set OptionalStanza,
-- | Which optional stanzas the user explicitly asked to enable or
-- to disable. This tells us which ones we build by default, and
-- helps with error messages when the user asks to build something
-- they explicitly disabled.
pkgStanzasRequested :: Map OptionalStanza Bool,
-- | Which optional stanzas (ie testsuites, benchmarks) will actually
-- be enabled during the package configure step.
pkgStanzasEnabled :: Set OptionalStanza,
-- | Where the package comes from, e.g. tarball, local dir etc. This
-- is not the same as where it may be unpacked to for the build.
pkgSourceLocation :: PackageLocation (Maybe FilePath),
-- | The hash of the source, e.g. the tarball. We don't have this for
-- local source dir packages.
pkgSourceHash :: Maybe PackageSourceHash,
--pkgSourceDir ? -- currently passed in later because they can use temp locations
--pkgBuildDir ? -- but could in principle still have it here, with optional instr to use temp loc
pkgBuildStyle :: BuildStyle,
pkgSetupPackageDBStack :: PackageDBStack,
pkgBuildPackageDBStack :: PackageDBStack,
pkgRegisterPackageDBStack :: PackageDBStack,
-- | The package contains a library and so must be registered
pkgRequiresRegistration :: Bool,
pkgDescriptionOverride :: Maybe CabalFileText,
pkgVanillaLib :: Bool,
pkgSharedLib :: Bool,
pkgDynExe :: Bool,
pkgGHCiLib :: Bool,
pkgProfLib :: Bool,
pkgProfExe :: Bool,
pkgProfLibDetail :: ProfDetailLevel,
pkgProfExeDetail :: ProfDetailLevel,
pkgCoverage :: Bool,
pkgOptimization :: OptimisationLevel,
pkgSplitObjs :: Bool,
pkgStripLibs :: Bool,
pkgStripExes :: Bool,
pkgDebugInfo :: DebugInfoLevel,
pkgConfigureScriptArgs :: [String],
pkgExtraLibDirs :: [FilePath],
pkgExtraFrameworkDirs :: [FilePath],
pkgExtraIncludeDirs :: [FilePath],
pkgProgPrefix :: Maybe PathTemplate,
pkgProgSuffix :: Maybe PathTemplate,
pkgInstallDirs :: InstallDirs.InstallDirs FilePath,
pkgHaddockHoogle :: Bool,
pkgHaddockHtml :: Bool,
pkgHaddockHtmlLocation :: Maybe String,
pkgHaddockExecutables :: Bool,
pkgHaddockTestSuites :: Bool,
pkgHaddockBenchmarks :: Bool,
pkgHaddockInternal :: Bool,
pkgHaddockCss :: Maybe FilePath,
pkgHaddockHscolour :: Bool,
pkgHaddockHscolourCss :: Maybe FilePath,
pkgHaddockContents :: Maybe PathTemplate,
-- Setup.hs related things:
-- | One of four modes for how we build and interact with the Setup.hs
-- script, based on whether it's a build-type Custom, with or without
-- explicit deps and the cabal spec version the .cabal file needs.
pkgSetupScriptStyle :: SetupScriptStyle,
-- | The version of the Cabal command line interface that we are using
-- for this package. This is typically the version of the Cabal lib
-- that the Setup.hs is built against.
pkgSetupScriptCliVersion :: Version,
-- Build time related:
pkgBuildTargets :: [ComponentTarget],
pkgReplTarget :: Maybe ComponentTarget,
pkgBuildHaddocks :: Bool
}
deriving (Eq, Show, Generic)
instance Binary ElaboratedConfiguredPackage
instance Package ElaboratedConfiguredPackage where
packageId = pkgSourceId
instance HasUnitId ElaboratedConfiguredPackage where
installedUnitId = pkgInstalledId
instance PackageFixedDeps ElaboratedConfiguredPackage where
depends = fmap (map installedPackageId) . pkgDependencies
-- | This is used in the install plan to indicate how the package will be
-- built.
--
data BuildStyle =
-- | The classic approach where the package is built, then the files
-- installed into some location and the result registered in a package db.
--
-- If the package came from a tarball then it's built in a temp dir and
-- the results discarded.
BuildAndInstall
-- | The package is built, but the files are not installed anywhere,
-- rather the build dir is kept and the package is registered inplace.
--
-- Such packages can still subsequently be installed.
--