{-# 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 type of install plan produced by the solver and used as the starting -- point for the 'ElaboratedInstallPlan'. -- type SolverInstallPlan = InstallPlan --TODO: [code cleanup] redefine locally or move def to solver interface -- | 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 -- | The programs that the compiler configured (e.g. for GHC, the progs -- ghc & ghc-pkg). Once constructed, only the 'configuredPrograms' are -- used. pkgConfigCompilerProgs :: ProgramDb } deriving (Show, Generic) --TODO: [code cleanup] no Eq instance 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, pkgProgramPaths :: Map String FilePath, pkgProgramArgs :: Map String [String], pkgProgramPathExtra :: [FilePath], 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 InstalledPackageInfo --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 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 --------------------------- -- 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 --------------------------- -- Setup.hs script policy -- -- | 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 -- 3. @build-type@ not Custom with @cabal-version > $our-cabal-version@ -- 4. @build-type@ not Custom with @cabal-version <= $our-cabal-version@ -- -- It's also worth noting that packages specifying @cabal-version: >= 1.23@ -- or later that have @build-type@ Custom will always have a @custom-setup@ -- section. Therefore in case 2, the specified @cabal-version@ will always be -- less than 1.23. -- -- In cases 1 and 2 we obviously have to build an external Setup.hs script, -- while in case 4 we can use the internal library API. In case 3 we also have -- 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