HORIZON HASKELLDocslts/ghc-9.10.x248f8f02026-10-05Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05

Modulecabal-install-3.12.1.0Haskell2010

Distribution.Client.ProjectOrchestration

This module deals with building and incrementally rebuilding a collection of packages. It is what backs the cabal build and configure commands, as well as being a core part of run, test, bench and others.

The primary thing is in fact rebuilding (and trying to make that quick by not redoing unnecessary work), so building from scratch is just a special case.

The build process and the code can be understood by breaking it down into three major parts:

As far as possible, the "what to do" phase embodies all the policy, leaving the "do it" phase policy free. The first phase contains more of the complicated logic, but it is contained in code that is either pure or just has read effects (except cache updates). Then the second phase does all the actions to build packages, but as far as possible it just follows the instructions and avoids any logic for deciding what to do (apart from recompilation avoidance in executing the plan).

This division helps us keep the code under control, making it easier to understand, test and debug. So when you are extending these modules, please think about which parts of your change belong in which part. It is perfectly ok to extend the description of what to do (i.e. the ElaboratedInstallPlan) if that helps keep the policy decisions in the first phase. Also, the second phase does not have direct access to any of the input configuration anyway; all the information has to flow via the ElaboratedInstallPlan.

  • 17 types
  • 27 values

Discovery phase: what is in the project?

6 declarations
datadata ProjectBaseContext
#

This holds the context of a project prior to solving: the content of the cabal.project, cabal/config and all the local package .cabal files.

Constructors

datadata BuildTimeSettings
#

Resolved configuration for things that affect how we build and not the value of the things we build. The idea is that this is easier to use than the raw configuration because in the raw configuration everything is optional (monoidial). In the BuildTimeSettings every field is filled in, if only with the defaults.

Use resolveBuildTimeSettings to make one from the project config (by applying defaults etc).

Pre-build phase: decide what to do.

3 declarations
datadata ProjectBuildContext
#

This holds the context between the pre-build, build and post-build phases.

Constructors

Selecting what targets we mean

valuereadTargetSelectors
  1. :: [PackageSpecifier (SourcePackage (PackageLocation a))]
  2. -> Maybe ComponentKindFilter

    This parameter is used when there are ambiguous selectors. If it is Just, then we attempt to resolve ambiguity by applying it, since otherwise there is no way to allow contextually valid yet syntactically ambiguous selectors. (#4676, #5461)

  3. -> [String]
  4. -> IO (Either [TargetSelectorProblem] [TargetSelector])
#

Parse a bunch of command line args as TargetSelectors, failing with an error if any are unrecognised. The possible target selectors are based on the available packages (and their locations).

Given a set of TargetSelectors, resolve which UnitIds and ComponentTargets they ought to refer to.

The idea is that every user target identifies one or more roots in the ElaboratedInstallPlan, which we will use to determine the closure of what packages need to be built, dropping everything from the plan that is unnecessary. This closure and pruning is done by pruneInstallPlanToTargets and this needs to be told the roots in terms of UnitIds and the ComponentTargets within those.

This means we first need to translate the TargetSelectors into the UnitIds and ComponentTargets. This translation has to be different for the different command line commands, like build, repl etc. For example the command build pkgfoo could select a different set of components in pkgfoo than repl pkgfoo. The build command would select any library and all executables, whereas repl would select the library or a single executable. Furthermore, both of these examples could fail, and fail in different ways and each needs to be able to produce helpful error messages.

So resolveTargets takes two helpers: one to select the targets to be used by user targets that refer to a whole package (TargetPackage), and another to check user targets that refer to a component (or a module or file within a component). These helpers can fail, and use their own error type. Both helpers get given the AvailableTarget info about the component(s).

While commands vary quite a bit in their behaviour about which components to select for a whole-package target, most commands have the same behaviour for checking a user target that refers to a specific component. To help with this commands can use selectComponentTargetBasic, either directly or as a basis for their own selectComponentTarget implementation.

The set of components to build, represented as a mapping from UnitIds to the ComponentTargets within the unit that will be selected (e.g. selected to build, test or repl).

Associated with each ComponentTarget is the set of TargetSelectors that matched this target. Typically this is exactly one, but in general it is possible to for different selectors to match the same target. This extra information is primarily to help make helpful error messages.

datadata TargetSelector
#

A target selector is expression selecting a set of components (as targets for a actions like build, run, test etc). A target selector corresponds to the user syntax for referring to targets on the command line.

From the users point of view a target can be many things: packages, dirs, component names, files etc. Internally we consider a target to be a specific component (or module/file within a component), and all the users' notions of targets are just different ways of referring to these component targets.

So target selectors are expressions in the sense that they are interpreted to refer to one or more components. For example a TargetPackage gets interpreted differently by different commands to refer to all or a subset of components within the package.

The syntax has lots of optional parts:

[ package name | package dir | package .cabal file ]
[ [lib:|exe:] component name ]
[ module name | source file ]

Constructors

Instances5Eq, Ord, Show, Generic, Rep
datadata TargetImplicitCwd
#

Does this TargetPackage selector arise from syntax referring to a package in the current directory (e.g. tests or no giving no explicit target at all) or does it come from syntax referring to a package name or location.

Instances5Eq, Ord, Show, Generic, Rep
datadata AvailableTarget k
#

An available target represents a component within a package that a user command could plausibly refer to. In this sense, all the components defined within the package are things the user could refer to, whether or not it would actually be possible to build that component.

In particular the available target contains an AvailableTargetStatus which informs us about whether it's actually possible to select this component to be built, and if not why not. This detail makes it possible for command implementations (like build, test etc) to accurately report why a target cannot be used.

Note that the type parameter is used to help enforce that command implementations can only select targets that can actually be built (by forcing them to return the k value for the selected targets). In particular resolveTargets makes use of this (with k as (UnitId, ComponentName')) to identify the targets thus selected.

Instances3Functor, Eq, Show
datadata AvailableTargetStatus k
#

The status of a an AvailableTarget component. This tells us whether it's actually possible to select this component to be built, and if not why not.

Constructors

Instances4Functor, Eq, Ord, Show
datadata TargetRequested
#

This tells us whether a target ought to be built by default, or only if specifically requested. The policy is that components like libraries and executables are built by default by build, but test suites and benchmarks are not, unless this is overridden in the project configuration.

Constructors

Instances3Eq, Ord, Show
  • Eq TargetRequestedDefined in cabal-install-3.12.1.0 · Distribution.Client.ProjectPlanning
  • Ord TargetRequestedDefined in cabal-install-3.12.1.0 · Distribution.Client.ProjectPlanning
  • Show TargetRequestedDefined in cabal-install-3.12.1.0 · Distribution.Client.ProjectPlanning
datadata ComponentName
#

Constructors

Instances10Eq, Ord, Read, Show, Generic, Binary, …
datadata ComponentTarget
#

Specific targets within a package or component to act on e.g. to build, haddock or open a repl.

Instances7Eq, Ord, Show, Generic, Binary, Structured, …
datadata SubComponentTarget
#

Either the component as a whole or detail about a file or module target within a component.

Constructors

Instances7Eq, Ord, Show, Generic, Binary, Structured, …

Utils for selecting targets

Adjusting the plan

newtypenewtype CannotPruneDependencies
#

It is not always possible to prune to only the dependencies of a set of targets. It may be the case that removing a package leaves something else that still needed the pruned package.

This lists all the packages that would be broken, and their dependencies that would be missing if we did prune.

Instances1Show

Build phase: now do it.

1 declaration

Post build actions

2 declarations

Dummy projects

2 declarations