2 {-# LANGUAGE NamedFieldPuns #-}
3 {-# LANGUAGE RankNTypes #-}
4 {-# LANGUAGE RecordWildCards #-}
5 {-# LANGUAGE ScopedTypeVariables #-}
6 {-# LANGUAGE ViewPatterns #-}
8 -- | This module deals with building and incrementally rebuilding a collection
9 -- of packages. It is what backs the @cabal build@ and @configure@ commands,
10 -- as well as being a core part of @run@, @test@, @bench@ and others.
12 -- The primary thing is in fact rebuilding (and trying to make that quick by
13 -- not redoing unnecessary work), so building from scratch is just a special
16 -- The build process and the code can be understood by breaking it down into
19 -- * The 'ElaboratedInstallPlan' type
21 -- * The \"what to do\" phase, where we look at the all input configuration
22 -- (project files, .cabal files, command line etc) and produce a detailed
23 -- plan of what to do -- the 'ElaboratedInstallPlan'.
25 -- * The \"do it\" phase, where we take the 'ElaboratedInstallPlan' and we
28 -- As far as possible, the \"what to do\" phase embodies all the policy, leaving
29 -- the \"do it\" phase policy free. The first phase contains more of the
30 -- complicated logic, but it is contained in code that is either pure or just
31 -- has read effects (except cache updates). Then the second phase does all the
32 -- actions to build packages, but as far as possible it just follows the
33 -- instructions and avoids any logic for deciding what to do (apart from
34 -- recompilation avoidance in executing the plan).
36 -- This division helps us keep the code under control, making it easier to
37 -- understand, test and debug. So when you are extending these modules, please
38 -- think about which parts of your change belong in which part. It is
39 -- perfectly ok to extend the description of what to do (i.e. the
40 -- 'ElaboratedInstallPlan') if that helps keep the policy decisions in the
41 -- first phase. Also, the second phase does not have direct access to any of
42 -- the input configuration anyway; all the information has to flow via the
43 -- 'ElaboratedInstallPlan'.
44 module Distribution
.Client
.ProjectOrchestration
45 ( -- * Discovery phase: what is in the project?
47 , establishProjectBaseContext
48 , establishProjectBaseContextWithRoot
49 , ProjectBaseContext
(..)
50 , BuildTimeSettings
(..)
51 , commandLineFlagsToProjectConfig
53 -- * Pre-build phase: decide what to do.
55 , runProjectPreBuildPhase
56 , ProjectBuildContext
(..)
58 -- ** Selecting what targets we mean
60 , reportTargetSelectorProblems
64 , uniqueTargetSelectors
66 , TargetImplicitCwd
(..)
68 , AvailableTarget
(..)
69 , AvailableTargetStatus
(..)
70 , TargetRequested
(..)
73 , ComponentTarget
(..)
74 , SubComponentTarget
(..)
75 , selectComponentTargetBasic
76 , distinctTargetComponents
78 -- ** Utils for selecting targets
80 , filterTargetsKindWith
81 , selectBuildableTargets
82 , selectBuildableTargetsWith
83 , selectBuildableTargets
'
84 , selectBuildableTargetsWith
'
87 -- ** Adjusting the plan
88 , pruneInstallPlanToTargets
90 , pruneInstallPlanToDependencies
91 , CannotPruneDependencies
(..)
94 -- * Build phase: now do it.
95 , runProjectBuildPhase
97 -- * Post build actions
98 , runProjectPostBuildPhase
102 , establishDummyProjectBaseContext
103 , establishDummyDistDirLayout
106 import Distribution
.Client
.Compat
.Prelude
107 import Distribution
.Compat
.Directory
112 import Distribution
.Client
.ProjectBuilding
113 import Distribution
.Client
.ProjectConfig
114 import Distribution
.Client
.ProjectPlanOutput
115 import Distribution
.Client
.ProjectPlanning
hiding
116 ( pruneInstallPlanToTargets
118 import qualified Distribution
.Client
.ProjectPlanning
as ProjectPlanning
119 ( pruneInstallPlanToTargets
121 import Distribution
.Client
.ProjectPlanning
.Types
123 import Distribution
.Client
.DistDirLayout
124 import qualified Distribution
.Client
.InstallPlan
as InstallPlan
125 import Distribution
.Client
.TargetProblem
128 import Distribution
.Client
.TargetSelector
130 , TargetImplicitCwd
(..)
131 , TargetSelector
(..)
133 , readTargetSelectors
134 , reportTargetSelectorProblems
136 import Distribution
.Client
.Types
138 , GenericReadyPackage
(..)
139 , PackageLocation
(..)
140 , PackageSpecifier
(..)
141 , SourcePackageDb
(..)
143 , UnresolvedSourcePackage
144 , WriteGhcEnvironmentFilesPolicy
(..)
146 import Distribution
.Solver
.Types
.PackageIndex
150 import Distribution
.Client
.BuildReports
.Anonymous
(cabalInstallID
)
151 import qualified Distribution
.Client
.BuildReports
.Anonymous
as BuildReports
152 import qualified Distribution
.Client
.BuildReports
.Storage
as BuildReports
156 import Distribution
.Client
.HttpUtils
157 import Distribution
.Client
.Setup
hiding (packageName
)
158 import Distribution
.Compiler
159 ( CompilerFlavor
(GHC
)
161 import Distribution
.Types
.ComponentName
162 ( componentNameString
164 import Distribution
.Types
.InstalledPackageInfo
165 ( InstalledPackageInfo
167 import Distribution
.Types
.UnqualComponentName
168 ( UnqualComponentName
169 , packageNameToUnqualComponentName
172 import Distribution
.Solver
.Types
.OptionalStanza
174 import Control
.Exception
(assert
)
175 import qualified Data
.List
.NonEmpty
as NE
176 import qualified Data
.Map
as Map
177 import qualified Data
.Set
as Set
178 import Distribution
.Client
.Errors
179 import Distribution
.Package
180 import Distribution
.Simple
.Command
(commandShowOptions
)
181 import Distribution
.Simple
.Compiler
182 ( OptimisationLevel
(..)
183 , compilerCompatVersion
188 import Distribution
.Simple
.Configure
(computeEffectiveProfiling
)
189 import Distribution
.Simple
.Flag
193 import Distribution
.Simple
.LocalBuildInfo
197 import Distribution
.Simple
.PackageIndex
(InstalledPackageIndex
)
198 import qualified Distribution
.Simple
.Setup
as Setup
199 import Distribution
.Simple
.Utils
200 ( createDirectoryIfMissingVerbose
208 import Distribution
.System
209 ( Platform
(Platform
)
211 import Distribution
.Types
.Flag
216 import Distribution
.Utils
.NubList
219 import Distribution
.Verbosity
220 import Distribution
.Version
223 #ifdef MIN_VERSION_unix
224 import System
.Posix
.Signals
(sigKILL
, sigSEGV
)
228 -- | Tracks what command is being executed, because we need to hide this somewhere
229 -- for cases that need special handling (usually for error reporting).
230 data CurrentCommand
= InstallCommand | HaddockCommand | BuildCommand | ReplCommand | OtherCommand
233 -- | This holds the context of a project prior to solving: the content of the
234 -- @cabal.project@ and all the local package @.cabal@ files.
235 data ProjectBaseContext
= ProjectBaseContext
236 { distDirLayout
:: DistDirLayout
237 , cabalDirLayout
:: CabalDirLayout
238 , projectConfig
:: ProjectConfig
239 , localPackages
:: [PackageSpecifier UnresolvedSourcePackage
]
240 , buildSettings
:: BuildTimeSettings
241 , currentCommand
:: CurrentCommand
242 , installedPackages
:: Maybe InstalledPackageIndex
245 establishProjectBaseContext
249 -> IO ProjectBaseContext
250 establishProjectBaseContext verbosity cliConfig currentCommand
= do
251 projectRoot
<- either throwIO
return =<< findProjectRoot verbosity mprojectDir mprojectFile
252 establishProjectBaseContextWithRoot verbosity cliConfig projectRoot currentCommand
254 mprojectDir
= Setup
.flagToMaybe projectConfigProjectDir
255 mprojectFile
= Setup
.flagToMaybe projectConfigProjectFile
256 ProjectConfigShared
{projectConfigProjectDir
, projectConfigProjectFile
} = projectConfigShared cliConfig
258 -- | Like 'establishProjectBaseContext' but doesn't search for project root.
259 establishProjectBaseContextWithRoot
264 -> IO ProjectBaseContext
265 establishProjectBaseContextWithRoot verbosity cliConfig projectRoot currentCommand
= do
266 let haddockOutputDir
= flagToMaybe
(packageConfigHaddockOutputDir
(projectConfigLocalPackages cliConfig
))
267 let distDirLayout
= defaultDistDirLayout projectRoot mdistDirectory haddockOutputDir
272 (fromNubList
. projectConfigProgPathExtra
$ projectConfigShared cliConfig
)
273 (flagToMaybe
. projectConfigHttpTransport
$ projectConfigBuildOnly cliConfig
)
275 (projectConfig
, localPackages
) <-
282 let ProjectConfigBuildOnly
283 { projectConfigLogsDir
284 } = projectConfigBuildOnly projectConfig
287 { projectConfigStoreDir
288 } = projectConfigShared projectConfig
290 mlogsDir
= Setup
.flagToMaybe projectConfigLogsDir
294 <$> Setup
.flagToMaybe projectConfigStoreDir
295 cabalDirLayout
<- mkCabalDirLayout mstoreDir mlogsDir
298 resolveBuildTimeSettings
303 -- https://github.com/haskell/cabal/issues/6013
304 when (null (projectPackages projectConfig
) && null (projectPackagesOptional projectConfig
)) $
305 warn verbosity
"There are no packages or optional-packages in the project"
318 mdistDirectory
= Setup
.flagToMaybe projectConfigDistDir
319 ProjectConfigShared
{projectConfigDistDir
} = projectConfigShared cliConfig
320 installedPackages
= Nothing
322 -- | This holds the context between the pre-build, build and post-build phases.
323 data ProjectBuildContext
= ProjectBuildContext
324 { elaboratedPlanOriginal
:: ElaboratedInstallPlan
325 -- ^ This is the improved plan, before we select a plan subset based on
326 -- the build targets, and before we do the dry-run. So this contains
327 -- all packages in the project.
328 , elaboratedPlanToExecute
:: ElaboratedInstallPlan
329 -- ^ This is the 'elaboratedPlanOriginal' after we select a plan subset
330 -- and do the dry-run phase to find out what is up-to or out-of date.
331 -- This is the plan that will be executed during the build phase. So
332 -- this contains only a subset of packages in the project.
333 , elaboratedShared
:: ElaboratedSharedConfig
334 -- ^ The part of the install plan that's shared between all packages in
335 -- the plan. This does not change between the two plan variants above,
336 -- so there is just the one copy.
337 , pkgsBuildStatus
:: BuildStatusMap
338 -- ^ The result of the dry-run phase. This tells us about each member of
339 -- the 'elaboratedPlanToExecute'.
340 , targetsMap
:: TargetsMap
341 -- ^ The targets selected by @selectPlanSubset@. This is useful eg. in
342 -- CmdRun, where we need a valid target to execute.
345 -- | Pre-build phase: decide what to do.
348 -> ProjectBaseContext
349 -> (ElaboratedInstallPlan
-> ElaboratedSharedConfig
-> IO a
)
361 -- Take the project configuration and make a plan for how to build
362 -- everything in the project. This is independent of any specific targets
363 -- the user has asked for.
365 (elaboratedPlan
, _
, elaboratedShared
, _
, _
) <-
373 action elaboratedPlan elaboratedShared
375 runProjectPreBuildPhase
377 -> ProjectBaseContext
378 -> (ElaboratedInstallPlan
-> IO (ElaboratedInstallPlan
, TargetsMap
))
379 -> IO ProjectBuildContext
380 runProjectPreBuildPhase
389 selectPlanSubset
= do
390 -- Take the project configuration and make a plan for how to build
391 -- everything in the project. This is independent of any specific targets
392 -- the user has asked for.
394 (elaboratedPlan
, _
, elaboratedShared
, _
, _
) <-
403 -- The plan for what to do is represented by an 'ElaboratedInstallPlan'
405 -- Now given the specific targets the user has asked for, decide
406 -- which bits of the plan we will want to execute.
408 (elaboratedPlan
', targets
) <- selectPlanSubset elaboratedPlan
410 -- Check which packages need rebuilding.
411 -- This also gives us more accurate reasons for the --dry-run output.
419 -- Improve the plan by marking up-to-date packages as installed.
421 let elaboratedPlan
'' =
422 improveInstallPlanWithUpToDatePackages
425 debugNoWrap verbosity
(InstallPlan
.showInstallPlan elaboratedPlan
'')
429 { elaboratedPlanOriginal
= elaboratedPlan
430 , elaboratedPlanToExecute
= elaboratedPlan
''
433 , targetsMap
= targets
436 -- | Build phase: now do it.
438 -- Execute all or parts of the description of what to do to build or
439 -- rebuild the various packages needed.
442 -> ProjectBaseContext
443 -> ProjectBuildContext
445 runProjectBuildPhase _ ProjectBaseContext
{buildSettings
} _
446 | buildSettingDryRun buildSettings
=
450 ProjectBaseContext
{..}
451 ProjectBuildContext
{..} =
452 fmap (Map
.union (previousBuildOutcomes pkgsBuildStatus
)) $
457 (cabalStoreDirLayout cabalDirLayout
)
458 elaboratedPlanToExecute
463 previousBuildOutcomes
:: BuildStatusMap
-> BuildOutcomes
464 previousBuildOutcomes
=
465 Map
.mapMaybe $ \status
-> case status
of
466 BuildStatusUpToDate buildSuccess
-> Just
(Right buildSuccess
)
467 -- TODO: [nice to have] record build failures persistently
470 -- | Post-build phase: various administrative tasks
472 -- Update bits of state based on the build outcomes and report any failures.
473 runProjectPostBuildPhase
475 -> ProjectBaseContext
476 -> ProjectBuildContext
479 runProjectPostBuildPhase _ ProjectBaseContext
{buildSettings
} _ _
480 | buildSettingDryRun buildSettings
=
482 runProjectPostBuildPhase
484 ProjectBaseContext
{..}
485 bc
@ProjectBuildContext
{..}
487 -- Update other build artefacts
488 -- TODO: currently none, but could include:
489 -- - bin symlinks/wrappers
490 -- - haddock/hoogle/ctags indexes
491 -- - delete stale lib registrations
492 -- - delete stale package dirs
495 updatePostBuildProjectStatus
498 elaboratedPlanOriginal
502 -- Write the .ghc.environment file (if allowed by the env file write policy).
503 let writeGhcEnvFilesPolicy
=
504 projectConfigWriteGhcEnvironmentFilesPolicy
. projectConfigShared
$
507 shouldWriteGhcEnvironment
:: Bool
508 shouldWriteGhcEnvironment
=
509 case fromFlagOrDefault
510 NeverWriteGhcEnvironmentFiles
511 writeGhcEnvFilesPolicy
of
512 AlwaysWriteGhcEnvironmentFiles
-> True
513 NeverWriteGhcEnvironmentFiles
-> False
514 WriteGhcEnvironmentFilesOnlyForGhc844AndNewer
->
515 let compiler
= pkgConfigCompiler elaboratedShared
516 ghcCompatVersion
= compilerCompatVersion GHC compiler
517 in maybe False (>= mkVersion
[8, 4, 4]) ghcCompatVersion
519 when shouldWriteGhcEnvironment
$
521 writePlanGhcEnvironment
522 (distProjectRootDirectory distDirLayout
)
523 elaboratedPlanOriginal
527 -- Write the build reports
528 writeBuildReports buildSettings bc elaboratedPlanToExecute buildOutcomes
530 -- Finally if there were any build failures then report them and throw
531 -- an exception to terminate the program
532 dieOnBuildFailures verbosity currentCommand elaboratedPlanToExecute buildOutcomes
534 -- Note that it is a deliberate design choice that the 'buildTargets' is
535 -- not passed to phase 1, and the various bits of input config is not
536 -- passed to phase 2.
538 -- We make the install plan without looking at the particular targets the
539 -- user asks us to build. The set of available things we can build is
540 -- discovered from the env and config and is used to make the install plan.
541 -- The targets just tell us which parts of the install plan to execute.
543 -- Conversely, executing the plan does not directly depend on any of the
544 -- input config. The bits that are needed (or better, the decisions based
545 -- on it) all go into the install plan.
547 -- Notionally, the 'BuildFlags' should be things that do not affect what
548 -- we build, just how we do it. These ones of course do
550 ------------------------------------------------------------------------------
551 -- Taking targets into account, selecting what to build
554 -- | The set of components to build, represented as a mapping from 'UnitId's
555 -- to the 'ComponentTarget's within the unit that will be selected
556 -- (e.g. selected to build, test or repl).
558 -- Associated with each 'ComponentTarget' is the set of 'TargetSelector's that
559 -- matched this target. Typically this is exactly one, but in general it is
560 -- possible to for different selectors to match the same target. This extra
561 -- information is primarily to help make helpful error messages.
562 type TargetsMap
= Map UnitId
[(ComponentTarget
, NonEmpty TargetSelector
)]
564 -- | Get all target selectors.
565 allTargetSelectors
:: TargetsMap
-> [TargetSelector
]
566 allTargetSelectors
= concatMap (NE
.toList
. snd) . concat . Map
.elems
568 -- | Get all unique target selectors.
569 uniqueTargetSelectors
:: TargetsMap
-> [TargetSelector
]
570 uniqueTargetSelectors
= ordNub
. allTargetSelectors
572 -- | Given a set of 'TargetSelector's, resolve which 'UnitId's and
573 -- 'ComponentTarget's they ought to refer to.
575 -- The idea is that every user target identifies one or more roots in the
576 -- 'ElaboratedInstallPlan', which we will use to determine the closure
577 -- of what packages need to be built, dropping everything from the plan
578 -- that is unnecessary. This closure and pruning is done by
579 -- 'pruneInstallPlanToTargets' and this needs to be told the roots in terms
580 -- of 'UnitId's and the 'ComponentTarget's within those.
582 -- This means we first need to translate the 'TargetSelector's into the
583 -- 'UnitId's and 'ComponentTarget's. This translation has to be different for
584 -- the different command line commands, like @build@, @repl@ etc. For example
585 -- the command @build pkgfoo@ could select a different set of components in
586 -- pkgfoo than @repl pkgfoo@. The @build@ command would select any library and
587 -- all executables, whereas @repl@ would select the library or a single
588 -- executable. Furthermore, both of these examples could fail, and fail in
589 -- different ways and each needs to be able to produce helpful error messages.
591 -- So 'resolveTargets' takes two helpers: one to select the targets to be used
592 -- by user targets that refer to a whole package ('TargetPackage'), and
593 -- another to check user targets that refer to a component (or a module or
594 -- file within a component). These helpers can fail, and use their own error
595 -- type. Both helpers get given the 'AvailableTarget' info about the
598 -- While commands vary quite a bit in their behaviour about which components to
599 -- select for a whole-package target, most commands have the same behaviour for
600 -- checking a user target that refers to a specific component. To help with
601 -- this commands can use 'selectComponentTargetBasic', either directly or as
602 -- a basis for their own @selectComponentTarget@ implementation.
607 -> [AvailableTarget k
]
608 -> Either (TargetProblem err
) [k
]
613 -> Either (TargetProblem err
) k
615 -> ElaboratedInstallPlan
616 -> Maybe (SourcePackageDb
)
618 -> Either [TargetProblem err
] TargetsMap
621 selectComponentTarget
625 . either (Left
. toList
) Right
627 . map (\ts
-> (,) ts
<$> checkTarget ts
)
630 :: [(TargetSelector
, [(UnitId
, ComponentTarget
)])]
632 mkTargetsMap targets
=
633 Map
.map nubComponentTargets
$
637 |
(ts
, cts
) <- targets
641 AvailableTargetIndexes
{..} = availableTargetIndexes installPlan
643 checkTarget
:: TargetSelector
-> Either (TargetProblem err
) [(UnitId
, ComponentTarget
)]
645 -- We can ask to build any whole package, project-local or a dependency
646 checkTarget bt
@(TargetPackage _
(ordNub
-> [pkgid
]) mkfilter
)
648 fmap (maybe id filterTargetsKind mkfilter
) $
649 Map
.lookup pkgid availableTargetsByPackageId
=
650 fmap (componentTargets WholeComponent
) $
651 selectPackageTargets bt ats
653 Left
(TargetProblemNoSuchPackage pkgid
)
654 checkTarget
(TargetPackage _ pkgids _
) =
656 ( "TODO: add support for multiple packages in a directory. Got\n"
657 ++ unlines (map prettyShow pkgids
)
659 -- For the moment this error cannot happen here, because it gets
660 -- detected when the package config is being constructed. This case
661 -- will need handling properly when we do add support.
663 -- TODO: how should this use case play together with the
664 -- '--cabal-file' option of 'configure' which allows using multiple
665 -- .cabal files for a single package?
667 checkTarget bt
@(TargetAllPackages mkfilter
) =
668 fmap (componentTargets WholeComponent
)
669 . selectPackageTargets bt
670 . maybe id filterTargetsKind mkfilter
671 . filter availableTargetLocalToProject
672 $ concat (Map
.elems availableTargetsByPackageId
)
673 checkTarget
(TargetComponent pkgid cname subtarget
)
677 availableTargetsByPackageIdAndComponentName
=
678 fmap (componentTargets subtarget
) $
679 selectComponentTargets subtarget ats
680 | Map
.member pkgid availableTargetsByPackageId
=
681 Left
(TargetProblemNoSuchComponent pkgid cname
)
683 Left
(TargetProblemNoSuchPackage pkgid
)
684 checkTarget
(TargetComponentUnknown pkgname ecname subtarget
)
685 | Just ats
<- case ecname
of
689 availableTargetsByPackageNameAndUnqualComponentName
693 availableTargetsByPackageNameAndComponentName
=
694 fmap (componentTargets subtarget
) $
695 selectComponentTargets subtarget ats
696 | Map
.member pkgname availableTargetsByPackageName
=
697 Left
(TargetProblemUnknownComponent pkgname ecname
)
699 Left
(TargetNotInProject pkgname
)
700 checkTarget bt
@(TargetPackageNamed pkgname mkfilter
)
702 fmap (maybe id filterTargetsKind mkfilter
) $
703 Map
.lookup pkgname availableTargetsByPackageName
=
704 fmap (componentTargets WholeComponent
)
705 . selectPackageTargets bt
707 | Just SourcePackageDb
{packageIndex
} <- mPkgDb
708 , let pkg
= lookupPackageName packageIndex pkgname
710 Left
(TargetAvailableInIndex pkgname
)
712 Left
(TargetNotInProject pkgname
)
715 :: SubComponentTarget
716 -> [(b
, ComponentName
)]
717 -> [(b
, ComponentTarget
)]
718 componentTargets subtarget
=
719 map (fmap (\cname
-> ComponentTarget cname subtarget
))
721 selectComponentTargets
722 :: SubComponentTarget
723 -> [AvailableTarget k
]
724 -> Either (TargetProblem err
) [k
]
725 selectComponentTargets subtarget
=
726 either (Left
. NE
.head) Right
728 . map (selectComponentTarget subtarget
)
730 checkErrors
:: [Either e a
] -> Either (NonEmpty e
) [a
]
732 (\(es
, xs
) -> case es
of [] -> Right xs
; (e
: es
') -> Left
(e
:| es
'))
735 data AvailableTargetIndexes
= AvailableTargetIndexes
736 { availableTargetsByPackageIdAndComponentName
737 :: AvailableTargetsMap
(PackageId
, ComponentName
)
738 , availableTargetsByPackageId
739 :: AvailableTargetsMap PackageId
740 , availableTargetsByPackageName
741 :: AvailableTargetsMap PackageName
742 , availableTargetsByPackageNameAndComponentName
743 :: AvailableTargetsMap
(PackageName
, ComponentName
)
744 , availableTargetsByPackageNameAndUnqualComponentName
745 :: AvailableTargetsMap
(PackageName
, UnqualComponentName
)
747 type AvailableTargetsMap k
= Map k
[AvailableTarget
(UnitId
, ComponentName
)]
749 -- We define a bunch of indexes to help 'resolveTargets' with resolving
750 -- 'TargetSelector's to specific 'UnitId's.
752 -- They are all derived from the 'availableTargets' index.
753 -- The 'availableTargetsByPackageIdAndComponentName' is just that main index,
754 -- while the others are derived by re-grouping on the index key.
756 -- They are all constructed lazily because they are not necessarily all used.
758 availableTargetIndexes
:: ElaboratedInstallPlan
-> AvailableTargetIndexes
759 availableTargetIndexes installPlan
= AvailableTargetIndexes
{..}
761 availableTargetsByPackageIdAndComponentName
763 (PackageId
, ComponentName
)
764 [AvailableTarget
(UnitId
, ComponentName
)]
765 availableTargetsByPackageIdAndComponentName
=
766 availableTargets installPlan
768 availableTargetsByPackageId
769 :: Map PackageId
[AvailableTarget
(UnitId
, ComponentName
)]
770 availableTargetsByPackageId
=
773 (\(pkgid
, _cname
) -> pkgid
)
774 availableTargetsByPackageIdAndComponentName
775 `Map
.union` availableTargetsEmptyPackages
777 availableTargetsByPackageName
778 :: Map PackageName
[AvailableTarget
(UnitId
, ComponentName
)]
779 availableTargetsByPackageName
=
783 availableTargetsByPackageId
785 availableTargetsByPackageNameAndComponentName
787 (PackageName
, ComponentName
)
788 [AvailableTarget
(UnitId
, ComponentName
)]
789 availableTargetsByPackageNameAndComponentName
=
792 (\(pkgid
, cname
) -> (packageName pkgid
, cname
))
793 availableTargetsByPackageIdAndComponentName
795 availableTargetsByPackageNameAndUnqualComponentName
797 (PackageName
, UnqualComponentName
)
798 [AvailableTarget
(UnitId
, ComponentName
)]
799 availableTargetsByPackageNameAndUnqualComponentName
=
803 let pname
= packageName pkgid
804 cname
' = unqualComponentName pname cname
807 availableTargetsByPackageIdAndComponentName
810 :: PackageName
-> ComponentName
-> UnqualComponentName
811 unqualComponentName pkgname
=
812 fromMaybe (packageNameToUnqualComponentName pkgname
)
813 . componentNameString
815 -- Add in all the empty packages. These do not appear in the
816 -- availableTargetsByComponent map, since that only contains
817 -- components, so packages with no components are invisible from
818 -- that perspective. The empty packages need to be there for
819 -- proper error reporting, so users can select the empty package
820 -- and then we can report that it is empty, otherwise we falsely
821 -- report there is no such package at all.
822 availableTargetsEmptyPackages
=
824 [ (packageId pkg
, [])
825 | InstallPlan
.Configured pkg
<- InstallPlan
.toList installPlan
826 , case elabPkgOrComp pkg
of
827 ElabComponent _
-> False
828 ElabPackage _
-> null (pkgComponents
(elabPkgDescription pkg
))
831 -- TODO: [research required] what if the solution has multiple
832 -- versions of this package?
833 -- e.g. due to setup deps or due to multiple independent sets
834 -- of packages being built (e.g. ghc + ghcjs in a project)
836 filterTargetsKind
:: ComponentKind
-> [AvailableTarget k
] -> [AvailableTarget k
]
837 filterTargetsKind ckind
= filterTargetsKindWith
(== ckind
)
839 filterTargetsKindWith
840 :: (ComponentKind
-> Bool)
841 -> [AvailableTarget k
]
842 -> [AvailableTarget k
]
843 filterTargetsKindWith p ts
=
844 [ t | t
@(AvailableTarget _ cname _ _
) <- ts
, p
(componentKind cname
)
847 selectBuildableTargets
:: [AvailableTarget k
] -> [k
]
848 selectBuildableTargets
= selectBuildableTargetsWith
(const True)
850 zipBuildableTargetsWith
851 :: (TargetRequested
-> Bool)
852 -> [AvailableTarget k
]
853 -> [(k
, AvailableTarget k
)]
854 zipBuildableTargetsWith p ts
=
855 [(k
, t
) | t
@(AvailableTarget _ _
(TargetBuildable k req
) _
) <- ts
, p req
]
857 selectBuildableTargetsWith
858 :: (TargetRequested
-> Bool)
859 -> [AvailableTarget k
]
861 selectBuildableTargetsWith p
= map fst . zipBuildableTargetsWith p
863 selectBuildableTargets
' :: [AvailableTarget k
] -> ([k
], [AvailableTarget
()])
864 selectBuildableTargets
' = selectBuildableTargetsWith
' (const True)
866 selectBuildableTargetsWith
'
867 :: (TargetRequested
-> Bool)
868 -> [AvailableTarget k
]
869 -> ([k
], [AvailableTarget
()])
870 selectBuildableTargetsWith
' p
=
871 (fmap . map) forgetTargetDetail
. unzip . zipBuildableTargetsWith p
873 forgetTargetDetail
:: AvailableTarget k
-> AvailableTarget
()
874 forgetTargetDetail
= fmap (const ())
876 forgetTargetsDetail
:: [AvailableTarget k
] -> [AvailableTarget
()]
877 forgetTargetsDetail
= map forgetTargetDetail
879 -- | A basic @selectComponentTarget@ implementation to use or pass to
880 -- 'resolveTargets', that does the basic checks that the component is
881 -- buildable and isn't a test suite or benchmark that is disabled. This
882 -- can also be used to do these basic checks as part of a custom impl that
883 selectComponentTargetBasic
884 :: SubComponentTarget
886 -> Either (TargetProblem a
) k
887 selectComponentTargetBasic
890 { availableTargetPackageId
= pkgid
891 , availableTargetComponentName
= cname
892 , availableTargetStatus
894 case availableTargetStatus
of
895 TargetDisabledByUser
->
896 Left
(TargetOptionalStanzaDisabledByUser pkgid cname subtarget
)
897 TargetDisabledBySolver
->
898 Left
(TargetOptionalStanzaDisabledBySolver pkgid cname subtarget
)
900 Left
(TargetComponentNotProjectLocal pkgid cname subtarget
)
901 TargetNotBuildable
->
902 Left
(TargetComponentNotBuildable pkgid cname subtarget
)
903 TargetBuildable targetKey _
->
906 -- | Wrapper around 'ProjectPlanning.pruneInstallPlanToTargets' that adjusts
907 -- for the extra unneeded info in the 'TargetsMap'.
908 pruneInstallPlanToTargets
911 -> ElaboratedInstallPlan
912 -> ElaboratedInstallPlan
913 pruneInstallPlanToTargets targetActionType targetsMap elaboratedPlan
=
914 assert
(Map
.size targetsMap
> 0) $
915 ProjectPlanning
.pruneInstallPlanToTargets
917 (Map
.map (map fst) targetsMap
)
920 -- | Utility used by repl and run to check if the targets spans multiple
921 -- components, since those commands do not support multiple components.
922 distinctTargetComponents
:: TargetsMap
-> Set
.Set
(UnitId
, ComponentName
)
923 distinctTargetComponents targetsMap
=
926 |
(uid
, cts
) <- Map
.toList targetsMap
927 , (ComponentTarget cname _
, _
) <- cts
930 ------------------------------------------------------------------------------
931 -- Displaying what we plan to do
934 -- | Print a user-oriented presentation of the install plan, indicating what
938 -> ProjectBaseContext
939 -> ProjectBuildContext
944 { buildSettings
= BuildTimeSettings
{buildSettingDryRun
}
947 { projectConfigAllPackages
=
948 PackageConfig
{packageConfigOptimization
= globalOptimization
}
949 , projectConfigLocalPackages
=
950 PackageConfig
{packageConfigOptimization
= localOptimization
}
955 { elaboratedPlanToExecute
= elaboratedPlan
959 |
null pkgs
&& currentCommand
== BuildCommand
=
960 notice verbosity
"Up to date"
962 noticeNoWrap verbosity
$
965 ++ "In order, the following "
968 ++ ifNormal
" (use -v for more details)"
971 : map showPkgAndReason pkgs
972 |
otherwise = return ()
974 pkgs
= InstallPlan
.executionOrder elaboratedPlan
977 | verbosity
>= verbose
= s
981 | verbosity
>= verbose
= ""
985 | buildSettingDryRun
= "would"
988 showPkgAndReason
:: ElaboratedReadyPackage
-> String
989 showPkgAndReason
(ReadyPackage elab
) =
991 filter (not . null) $
993 , if verbosity
>= deafening
994 then prettyShow
(installedUnitId elab
)
995 else prettyShow
(packageId elab
)
996 , case elabBuildStyle elab
of
997 BuildInplaceOnly InMemory
-> "(interactive)"
999 , case elabPkgOrComp elab
of
1000 ElabPackage pkg
-> showTargets elab
++ ifVerbose
(showStanzas
(pkgStanzasEnabled pkg
))
1001 ElabComponent comp
->
1002 "(" ++ showComp elab comp
++ ")"
1003 , showFlagAssignment
(nonDefaultFlags elab
)
1004 , showConfigureFlags elab
1005 , let buildStatus
= pkgsBuildStatus Map
.! installedUnitId elab
1006 in "(" ++ showBuildStatus buildStatus
++ ")"
1009 showComp
:: ElaboratedConfiguredPackage
-> ElaboratedComponent
-> String
1010 showComp elab comp
=
1011 maybe "custom" prettyShow
(compComponentName comp
)
1012 ++ if Map
.null (elabInstantiatedWith elab
)
1018 -- TODO: Abbreviate the UnitIds
1019 [ prettyShow k
++ "=" ++ prettyShow v
1020 |
(k
, v
) <- Map
.toList
(elabInstantiatedWith elab
)
1023 nonDefaultFlags
:: ElaboratedConfiguredPackage
-> FlagAssignment
1024 nonDefaultFlags elab
=
1025 elabFlagAssignment elab `diffFlagAssignment` elabFlagDefaults elab
1027 showTargets
:: ElaboratedConfiguredPackage
-> String
1029 |
null (elabBuildTargets elab
) = ""
1034 [ showComponentTarget
(packageId elab
) t
1035 | t
<- elabBuildTargets elab
1039 showConfigureFlags
:: ElaboratedConfiguredPackage
-> String
1040 showConfigureFlags elab
=
1041 let fullConfigureFlags
=
1042 setupHsConfigureFlags
1048 -- \| Given a default value @x@ for a flag, nub @Flag x@
1049 -- into @NoFlag@. This gives us a tidier command line
1051 nubFlag
:: Eq a
=> a
-> Setup
.Flag a
-> Setup
.Flag a
1052 nubFlag x
(Setup
.Flag x
') | x
== x
' = Setup
.NoFlag
1055 (tryLibProfiling
, tryExeProfiling
) =
1056 computeEffectiveProfiling fullConfigureFlags
1058 partialConfigureFlags
=
1061 nubFlag
False (configProf fullConfigureFlags
)
1063 nubFlag tryExeProfiling
(configProfExe fullConfigureFlags
)
1065 nubFlag tryLibProfiling
(configProfLib fullConfigureFlags
)
1066 -- Maybe there are more we can add
1068 in -- Not necessary to "escape" it, it's just for user output
1071 (Setup
.configureCommand
(pkgConfigCompilerProgs elaboratedShared
))
1072 partialConfigureFlags
1074 showBuildStatus
:: BuildStatus
-> String
1075 showBuildStatus status
= case status
of
1076 BuildStatusPreExisting
-> "existing package"
1077 BuildStatusInstalled
-> "already installed"
1078 BuildStatusDownload
{} -> "requires download & build"
1079 BuildStatusUnpack
{} -> "requires build"
1080 BuildStatusRebuild _ rebuild
-> case rebuild
of
1081 BuildStatusConfigure
1082 (MonitoredValueChanged _
) -> "configuration changed"
1083 BuildStatusConfigure mreason
-> showMonitorChangedReason mreason
1084 BuildStatusBuild _ buildreason
-> case buildreason
of
1085 BuildReasonDepsRebuilt
-> "dependency rebuilt"
1086 BuildReasonFilesChanged
1087 mreason
-> showMonitorChangedReason mreason
1088 BuildReasonExtraTargets _
-> "additional components to build"
1089 BuildReasonEphemeralTargets
-> "ephemeral targets"
1090 BuildStatusUpToDate
{} -> "up to date" -- doesn't happen
1091 showMonitorChangedReason
:: MonitorChangedReason a
-> String
1092 showMonitorChangedReason
(MonitoredFileChanged file
) =
1093 "file " ++ file
++ " changed"
1094 showMonitorChangedReason
(MonitoredValueChanged _
) = "value changed"
1095 showMonitorChangedReason MonitorFirstRun
= "first run"
1096 showMonitorChangedReason MonitorCorruptCache
=
1097 "cannot read state cache"
1099 showBuildProfile
:: String
1103 [ "-w " ++ (showCompilerId
. pkgConfigCompiler
) elaboratedShared
1105 ++ ( case globalOptimization
<> localOptimization
of -- if local is not set, read global
1106 Setup
.Flag NoOptimisation
-> "0"
1107 Setup
.Flag NormalOptimisation
-> "1"
1108 Setup
.Flag MaximumOptimisation
-> "2"
1114 writeBuildReports
:: BuildTimeSettings
-> ProjectBuildContext
-> ElaboratedInstallPlan
-> BuildOutcomes
-> IO ()
1115 writeBuildReports settings buildContext plan buildOutcomes
= do
1116 let plat
@(Platform arch os
) = pkgConfigPlatform
. elaboratedShared
$ buildContext
1117 comp
= pkgConfigCompiler
. elaboratedShared
$ buildContext
1118 getRepo
(RepoTarballPackage r _ _
) = Just r
1120 fromPlanPackage
(InstallPlan
.Configured pkg
) (Just result
) =
1121 let installOutcome
= case result
of
1122 Left bf
-> case buildFailureReason bf
of
1123 GracefulFailure _
-> BuildReports
.PlanningFailed
1124 DependentFailed p
-> BuildReports
.DependencyFailed p
1125 DownloadFailed _
-> BuildReports
.DownloadFailed
1126 UnpackFailed _
-> BuildReports
.UnpackFailed
1127 ConfigureFailed _
-> BuildReports
.ConfigureFailed
1128 BuildFailed _
-> BuildReports
.BuildFailed
1129 TestsFailed _
-> BuildReports
.TestsFailed
1130 InstallFailed _
-> BuildReports
.InstallFailed
1131 ReplFailed _
-> BuildReports
.InstallOk
1132 HaddocksFailed _
-> BuildReports
.InstallOk
1133 BenchFailed _
-> BuildReports
.InstallOk
1134 Right _br
-> BuildReports
.InstallOk
1136 docsOutcome
= case result
of
1137 Left bf
-> case buildFailureReason bf
of
1138 HaddocksFailed _
-> BuildReports
.Failed
1139 _
-> BuildReports
.NotTried
1140 Right br
-> case buildResultDocs br
of
1141 DocsNotTried
-> BuildReports
.NotTried
1142 DocsFailed
-> BuildReports
.Failed
1143 DocsOk
-> BuildReports
.Ok
1145 testsOutcome
= case result
of
1146 Left bf
-> case buildFailureReason bf
of
1147 TestsFailed _
-> BuildReports
.Failed
1148 _
-> BuildReports
.NotTried
1149 Right br
-> case buildResultTests br
of
1150 TestsNotTried
-> BuildReports
.NotTried
1151 TestsOk
-> BuildReports
.Ok
1152 in Just
$ (BuildReports
.BuildReport
(packageId pkg
) os arch
(compilerId comp
) cabalInstallID
(elabFlagAssignment pkg
) (map (packageId
. fst) $ elabLibDependencies pkg
) installOutcome docsOutcome testsOutcome
, getRepo
. elabPkgSourceLocation
$ pkg
) -- TODO handle failure log files?
1153 fromPlanPackage _ _
= Nothing
1154 buildReports
= mapMaybe (\x
-> fromPlanPackage x
(InstallPlan
.lookupBuildOutcome x buildOutcomes
)) $ InstallPlan
.toList plan
1156 BuildReports
.storeLocal
1158 (buildSettingSummaryFile settings
)
1162 -- Note this doesn't handle the anonymous build reports set by buildSettingBuildReports but those appear to not be used or missed from v1
1163 -- The usage pattern appears to be that rather than rely on flags to cabal to send build logs to the right place and package them with reports, etc, it is easier to simply capture its output to an appropriate handle.
1165 -- | If there are build failures then report them and throw an exception.
1169 -> ElaboratedInstallPlan
1172 dieOnBuildFailures verbosity currentCommand plan buildOutcomes
1173 |
null failures
= return ()
1174 | isSimpleCase
= exitFailure
1176 -- For failures where we have a build log, print the log plus a header
1181 : renderFailureDetail
False pkg reason
1185 readFile logfile
>>= noticeNoWrap verbosity
1186 |
(pkg
, ShowBuildSummaryAndLog reason logfile
) <-
1187 failuresClassification
1190 -- For all failures, print either a short summary (if we showed the
1191 -- build log) or all details
1192 dieIfNotHaddockFailure verbosity
$
1194 [ case failureClassification
of
1195 ShowBuildSummaryAndLog reason _
1196 | verbosity
> normal
->
1197 renderFailureDetail mentionDepOf pkg reason
1199 renderFailureSummary mentionDepOf pkg reason
1200 ++ ". See the build log above for details."
1201 ShowBuildSummaryOnly reason
->
1202 renderFailureDetail mentionDepOf pkg reason
1203 |
let mentionDepOf
= verbosity
<= normal
1204 , (pkg
, failureClassification
) <- failuresClassification
1207 failures
:: [(UnitId
, BuildFailure
)]
1210 |
(pkgid
, Left failure
) <- Map
.toList buildOutcomes
1213 failuresClassification
:: [(ElaboratedConfiguredPackage
, BuildFailurePresentation
)]
1214 failuresClassification
=
1215 [ (pkg
, classifyBuildFailure failure
)
1216 |
(pkgid
, failure
) <- failures
1217 , case buildFailureReason failure
of
1218 DependentFailed
{} -> verbosity
> normal
1220 , InstallPlan
.Configured pkg
<-
1221 maybeToList (InstallPlan
.lookup plan pkgid
)
1224 dieIfNotHaddockFailure
:: Verbosity
-> String -> IO ()
1225 dieIfNotHaddockFailure verb str
1226 | currentCommand
== HaddockCommand
= dieWithException verb
$ DieIfNotHaddockFailureException str
1227 |
all isHaddockFailure failuresClassification
= warn verb str
1228 |
otherwise = dieWithException verb
$ DieIfNotHaddockFailureException str
1231 (_
, ShowBuildSummaryOnly
(HaddocksFailed _
)) = True
1233 (_
, ShowBuildSummaryAndLog
(HaddocksFailed _
) _
) = True
1237 classifyBuildFailure
:: BuildFailure
-> BuildFailurePresentation
1238 classifyBuildFailure
1240 { buildFailureReason
= reason
1241 , buildFailureLogFile
= mlogfile
1244 (ShowBuildSummaryOnly reason
)
1245 (ShowBuildSummaryAndLog reason
)
1248 e
<- buildFailureException reason
1249 ExitFailure
1 <- fromException e
1252 -- Special case: we don't want to report anything complicated in the case
1253 -- of just doing build on the current package, since it's clear from
1254 -- context which package failed.
1256 -- We generalise this rule as follows:
1257 -- - if only one failure occurs, and it is in a single root
1258 -- package (i.e. a package with nothing else depending on it)
1259 -- - and that failure is of a kind that always reports enough
1260 -- detail itself (e.g. ghc reporting errors on stdout)
1261 -- - then we do not report additional error detail or context.
1263 isSimpleCase
:: Bool
1265 |
[(pkgid
, failure
)] <- failures
1267 , installedUnitId pkg
== pkgid
1268 , isFailureSelfExplanatory
(buildFailureReason failure
)
1269 , currentCommand `
notElem`
[InstallCommand
, BuildCommand
, ReplCommand
] =
1274 -- NB: if the Setup script segfaulted or was interrupted,
1275 -- we should give more detailed information. So only
1276 -- assume that exit code 1 is "pedestrian failure."
1277 isFailureSelfExplanatory
:: BuildFailureReason
-> Bool
1278 isFailureSelfExplanatory
(BuildFailed e
)
1279 | Just
(ExitFailure
1) <- fromException e
= True
1280 isFailureSelfExplanatory
(ConfigureFailed e
)
1281 | Just
(ExitFailure
1) <- fromException e
= True
1282 isFailureSelfExplanatory _
= False
1284 rootpkgs
:: [ElaboratedConfiguredPackage
]
1287 | InstallPlan
.Configured pkg
<- InstallPlan
.toList plan
1288 , hasNoDependents pkg
1293 -> [InstallPlan
.GenericPlanPackage InstalledPackageInfo ElaboratedConfiguredPackage
]
1294 ultimateDeps pkgid
=
1296 (\pkg
-> hasNoDependents pkg
&& installedUnitId pkg
/= pkgid
)
1297 (InstallPlan
.reverseDependencyClosure plan
[pkgid
])
1299 hasNoDependents
:: HasUnitId pkg
=> pkg
-> Bool
1300 hasNoDependents
= null . InstallPlan
.revDirectDeps plan
. installedUnitId
1302 renderFailureDetail
:: Bool -> ElaboratedConfiguredPackage
-> BuildFailureReason
-> String
1303 renderFailureDetail mentionDepOf pkg reason
=
1304 renderFailureSummary mentionDepOf pkg reason
1306 ++ renderFailureExtraDetail reason
1307 ++ maybe "" showException
(buildFailureException reason
)
1309 renderFailureSummary
:: Bool -> ElaboratedConfiguredPackage
-> BuildFailureReason
-> String
1310 renderFailureSummary mentionDepOf pkg reason
=
1312 DownloadFailed _
-> "Failed to download " ++ pkgstr
1313 UnpackFailed _
-> "Failed to unpack " ++ pkgstr
1314 ConfigureFailed _
-> "Failed to build " ++ pkgstr
1315 BuildFailed _
-> "Failed to build " ++ pkgstr
1316 ReplFailed _
-> "repl failed for " ++ pkgstr
1317 HaddocksFailed _
-> "Failed to build documentation for " ++ pkgstr
1318 TestsFailed _
-> "Tests failed for " ++ pkgstr
1319 BenchFailed _
-> "Benchmarks failed for " ++ pkgstr
1320 InstallFailed _
-> "Failed to build " ++ pkgstr
1321 GracefulFailure msg
-> msg
1322 DependentFailed depid
->
1324 ++ prettyShow
(packageId pkg
)
1325 ++ " because it depends on "
1327 ++ " which itself failed to build"
1330 elabConfiguredName verbosity pkg
1332 then renderDependencyOf
(installedUnitId pkg
)
1335 renderFailureExtraDetail
:: BuildFailureReason
-> String
1336 renderFailureExtraDetail
(ConfigureFailed _
) =
1337 " The failure occurred during the configure step."
1338 renderFailureExtraDetail
(InstallFailed _
) =
1339 " The failure occurred during the final install step."
1340 renderFailureExtraDetail _
=
1343 renderDependencyOf
:: UnitId
-> String
1344 renderDependencyOf pkgid
=
1345 case ultimateDeps pkgid
of
1348 " (which is required by " ++ elabPlanPackageName verbosity p1
++ ")"
1350 " (which is required by "
1351 ++ elabPlanPackageName verbosity p1
1353 ++ elabPlanPackageName verbosity p2
1356 " (which is required by "
1357 ++ elabPlanPackageName verbosity p1
1359 ++ elabPlanPackageName verbosity p2
1362 showException e
= case fromException e
of
1363 Just
(ExitFailure
1) -> ""
1365 {- FOURMOLU_DISABLE -}
1366 #ifdef MIN_VERSION_unix
1367 -- Note [Positive "signal" exit code]
1368 -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1369 -- What's the business with the test for negative and positive
1370 -- signal values? The API for process specifies that if the
1371 -- process died due to a signal, it returns a *negative* exit
1372 -- code. So that's the negative test.
1374 -- What about the positive test? Well, when we find out that
1375 -- a process died due to a signal, we ourselves exit with that
1376 -- exit code. However, we don't "kill ourselves" with the
1377 -- signal; we just exit with the same code as the signal: thus
1378 -- the caller sees a *positive* exit code. So that's what
1379 -- happens when we get a positive exit code.
1380 Just
(ExitFailure n
)
1381 |
-n
== fromIntegral sigSEGV
->
1382 " The build process segfaulted (i.e. SIGSEGV)."
1384 | n
== fromIntegral sigSEGV
->
1385 " The build process terminated with exit code " ++ show n
1386 ++ " which may be because some part of it segfaulted. (i.e. SIGSEGV)."
1388 |
-n
== fromIntegral sigKILL
->
1389 " The build process was killed (i.e. SIGKILL). " ++ explanation
1391 | n
== fromIntegral sigKILL
->
1392 " The build process terminated with exit code " ++ show n
1393 ++ " which may be because some part of it was killed "
1394 ++ "(i.e. SIGKILL). " ++ explanation
1397 "The typical reason for this is that there is not "
1398 ++ "enough memory available (e.g. the OS killed a process "
1399 ++ "using lots of memory)."
1401 Just
(ExitFailure n
) ->
1402 " The build process terminated with exit code " ++ show n
1404 _
-> " The exception was:\n "
1405 #if MIN_VERSION_base
(4,8,0)
1406 ++ displayException e
1411 buildFailureException
:: BuildFailureReason
-> Maybe SomeException
1412 buildFailureException reason
=
1414 DownloadFailed e
-> Just e
1415 UnpackFailed e
-> Just e
1416 ConfigureFailed e
-> Just e
1417 BuildFailed e
-> Just e
1418 ReplFailed e
-> Just e
1419 HaddocksFailed e
-> Just e
1420 TestsFailed e
-> Just e
1421 BenchFailed e
-> Just e
1422 InstallFailed e
-> Just e
1423 GracefulFailure _
-> Nothing
1424 DependentFailed _
-> Nothing
1425 {- FOURMOLU_ENABLE -}
1427 data BuildFailurePresentation
1428 = ShowBuildSummaryOnly BuildFailureReason
1429 | ShowBuildSummaryAndLog BuildFailureReason
FilePath
1431 -------------------------------------------------------------------------------
1433 -------------------------------------------------------------------------------
1435 -- | Create a dummy project context, without a .cabal or a .cabal.project file
1436 -- (a place where to put a temporary dist directory is still needed)
1437 establishDummyProjectBaseContext
1440 -- ^ Project configuration including the global config if needed
1442 -- ^ Where to put the dist directory
1443 -> [PackageSpecifier UnresolvedSourcePackage
]
1444 -- ^ The packages to be included in the project
1446 -> IO ProjectBaseContext
1447 establishDummyProjectBaseContext verbosity projectConfig distDirLayout localPackages currentCommand
= do
1448 let ProjectConfigBuildOnly
1449 { projectConfigLogsDir
1450 } = projectConfigBuildOnly projectConfig
1453 { projectConfigStoreDir
1454 } = projectConfigShared projectConfig
1456 mlogsDir
= flagToMaybe projectConfigLogsDir
1457 mstoreDir
= flagToMaybe projectConfigStoreDir
1459 cabalDirLayout
<- mkCabalDirLayout mstoreDir mlogsDir
1461 let buildSettings
:: BuildTimeSettings
1463 resolveBuildTimeSettings
1467 installedPackages
= Nothing
1480 establishDummyDistDirLayout
:: Verbosity
-> ProjectConfig
-> FilePath -> IO DistDirLayout
1481 establishDummyDistDirLayout verbosity cliConfig tmpDir
= do
1482 let distDirLayout
= defaultDistDirLayout projectRoot mdistDirectory Nothing
1484 -- Create the dist directories
1485 createDirectoryIfMissingVerbose verbosity
True $ distDirectory distDirLayout
1486 createDirectoryIfMissingVerbose verbosity
True $ distProjectCacheDirectory distDirLayout
1488 return distDirLayout
1492 projectConfigDistDir
$
1493 projectConfigShared cliConfig
1494 projectRoot
= ProjectRootImplicit tmpDir