{-# LANGUAGE DeriveDataTypeable #-} -- | Types for the "Distribution.Client.ProjectBuilding" -- -- Moved out to avoid module cycles. -- module Distribution.Client.ProjectBuilding.Types ( -- * Pre-build status BuildStatusMap, BuildStatus(..), buildStatusRequiresBuild, buildStatusToString, BuildStatusRebuild(..), BuildReason(..), MonitorChangedReason(..), -- * Build outcomes BuildOutcomes, BuildOutcome, BuildResult(..), BuildFailure(..), BuildFailureReason(..), ) where import Distribution.Client.Compat.Prelude import Prelude () import Distribution.Client.Types (DocsResult, TestsResult) import Distribution.Client.FileMonitor (MonitorChangedReason(..)) import Distribution.Package (UnitId, PackageId) import Distribution.InstalledPackageInfo (InstalledPackageInfo) import Distribution.Simple.LocalBuildInfo (ComponentName) ------------------------------------------------------------------------------ -- Pre-build status: result of the dry run -- -- | The 'BuildStatus' of every package in the 'ElaboratedInstallPlan'. -- -- This is used as the result of the dry-run of building an install plan. -- type BuildStatusMap = Map UnitId BuildStatus -- | The build status for an individual package is the state that the -- package is in /prior/ to initiating a (re)build. -- -- This should not be confused with a 'BuildResult' which is the result -- /after/ successfully building a package. -- -- It serves two purposes: -- -- * For dry-run output, it lets us explain to the user if and why a package -- is going to be (re)built. -- -- * It tell us what step to start or resume building from, and carries -- enough information for us to be able to do so. -- data BuildStatus = -- | The package is in the 'InstallPlan.PreExisting' state, so does not -- need building. BuildStatusPreExisting -- | The package is in the 'InstallPlan.Installed' state, so does not -- need building. | BuildStatusInstalled -- | The package has not been downloaded yet, so it will have to be -- downloaded, unpacked and built. | BuildStatusDownload -- | The package has not been unpacked yet, so it will have to be -- unpacked and built. | BuildStatusUnpack FilePath -- | The package exists in a local dir already, and just needs building -- or rebuilding. So this can only happen for 'BuildInplaceOnly' style -- packages. | BuildStatusRebuild FilePath BuildStatusRebuild -- | The package exists in a local dir already, and is fully up to date. -- So this package can be put into the 'InstallPlan.Installed' state -- and it does not need to be built. | BuildStatusUpToDate BuildResult -- | Which 'BuildStatus' values indicate we'll have to do some build work of -- some sort. In particular we use this as part of checking if any of a -- package's deps have changed. -- buildStatusRequiresBuild :: BuildStatus -> Bool buildStatusRequiresBuild BuildStatusPreExisting = False buildStatusRequiresBuild BuildStatusInstalled = False buildStatusRequiresBuild BuildStatusUpToDate {} = False buildStatusRequiresBuild _ = True -- | This is primarily here for debugging. It's not actually used anywhere. -- buildStatusToString :: BuildStatus -> String buildStatusToString BuildStatusPreExisting = "BuildStatusPreExisting" buildStatusToString BuildStatusInstalled = "BuildStatusInstalled" buildStatusToString BuildStatusDownload = "BuildStatusDownload" buildStatusToString (BuildStatusUnpack fp) = "BuildStatusUnpack " ++ show fp buildStatusToString (BuildStatusRebuild fp _) = "BuildStatusRebuild " ++ show fp buildStatusToString (BuildStatusUpToDate _) = "BuildStatusUpToDate" -- | For a package that is going to be built or rebuilt, the state it's in now. -- -- So again, this tells us why a package needs to be rebuilt and what build -- phases need to be run. The 'MonitorChangedReason' gives us details like -- which file changed, which is mainly for high verbosity debug output. -- data BuildStatusRebuild = -- | The package configuration changed, so the configure and build phases -- needs to be (re)run. BuildStatusConfigure (MonitorChangedReason ()) -- | The configuration has not changed but the build phase needs to be -- rerun. We record the reason the (re)build is needed. -- -- The optional registration info here tells us if we've registered the -- package already, or if we still need to do that after building. -- @Just Nothing@ indicates that we know that no registration is -- necessary (e.g., executable.) -- | BuildStatusBuild (Maybe (Maybe InstalledPackageInfo)) BuildReason data BuildReason = -- | The dependencies of this package have been (re)built so the build -- phase needs to be rerun. -- BuildReasonDepsRebuilt -- | Changes in files within the package (or first run or corrupt cache) | BuildReasonFilesChanged (MonitorChangedReason ()) -- | An important special case is that no files have changed but the -- set of components the /user asked to build/ has changed. We track the -- set of components /we have built/, which of course only grows (until -- some other change resets it). -- -- The @Set 'ComponentName'@ is the set of components we have built -- previously. When we update the monitor we take the union of the ones -- we have built previously with the ones the user has asked for this -- time and save those. See 'updatePackageBuildFileMonitor'. -- | BuildReasonExtraTargets (Set ComponentName) -- | Although we're not going to build any additional targets as a whole, -- we're going to build some part of a component or run a repl or any -- other action that does not result in additional persistent artifacts. -- | BuildReasonEphemeralTargets ------------------------------------------------------------------------------ -- Build outcomes: result of the build -- -- | A summary of the outcome for building a whole set of packages. -- type BuildOutcomes = Map UnitId BuildOutcome -- | A summary of the outcome for building a single package: either success -- or failure. -- type BuildOutcome = Either BuildFailure BuildResult -- | Information arising from successfully building a single package. -- data BuildResult = BuildResult { buildResultDocs :: DocsResult, buildResultTests :: TestsResult, buildResultLogFile :: Maybe FilePath } deriving Show -- | Information arising from the failure to build a single package. -- data BuildFailure = BuildFailure { buildFailureLogFile :: Maybe FilePath, buildFailureReason :: BuildFailureReason } deriving (Show, Typeable) instance Exception BuildFailure -- | Detail on the reason that a package failed to build. -- data BuildFailureReason = DependentFailed PackageId | DownloadFailed SomeException | UnpackFailed SomeException | ConfigureFailed SomeException | BuildFailed SomeException | ReplFailed SomeException | HaddocksFailed SomeException | TestsFailed SomeException | BenchFailed SomeException | InstallFailed SomeException deriving Show