1 -- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>
2 module Distribution
.Backpack
.ComponentsGraph
6 , componentsGraphToList
7 , dispComponentsWithDeps
11 import Distribution
.Compat
.Prelude
14 import Distribution
.Compat
.Graph
(Graph
, Node
(..))
15 import qualified Distribution
.Compat
.Graph
as Graph
16 import qualified Distribution
.Compat
.NonEmptySet
as NES
17 import Distribution
.Package
18 import Distribution
.PackageDescription
19 import Distribution
.Simple
.BuildToolDepends
20 import Distribution
.Simple
.LocalBuildInfo
21 import Distribution
.Types
.ComponentRequestedSpec
22 import Distribution
.Utils
.Generic
24 import Distribution
.Pretty
(pretty
)
25 import Text
.PrettyPrint
27 ------------------------------------------------------------------------------
29 ------------------------------------------------------------------------------
31 -- | A graph of source-level components by their source-level
33 type ComponentsGraph
= Graph
(Node ComponentName Component
)
35 -- | A list of components associated with the source level
36 -- dependencies between them.
37 type ComponentsWithDeps
= [(Component
, [ComponentName
])]
39 -- | Pretty-print 'ComponentsWithDeps'.
40 dispComponentsWithDeps
:: ComponentsWithDeps
-> Doc
41 dispComponentsWithDeps graph
=
44 (text
"component" <+> pretty
(componentName c
))
46 (vcat
[text
"dependency" <+> pretty cdep | cdep
<- cdeps
])
50 -- | Create a 'Graph' of 'Component', or report a cycle if there is a
53 :: ComponentRequestedSpec
55 -> Either [ComponentName
] ComponentsGraph
56 mkComponentsGraph enabled pkg_descr
=
58 Graph
.fromDistinctList
59 [ N c
(componentName c
) (componentDeps c
)
60 | c
<- pkgBuildableComponents pkg_descr
61 , componentEnabled enabled c
63 in case Graph
.cycles g
of
65 ccycles
-> Left
[componentName c | N c _ _
<- concat ccycles
]
67 -- The dependencies for the given component
68 componentDeps component
=
69 toolDependencies
++ libDependencies
71 bi
= componentBuildInfo component
73 toolDependencies
= CExeName
<$> getAllInternalToolDependencies pkg_descr bi
76 Dependency pkgname _ lns
<- targetBuildDepends bi
77 guard (pkgname
== packageName pkg_descr
)
82 -- | Given the package description and a 'PackageDescription' (used
83 -- to determine if a package name is internal or not), sort the
84 -- components in dependency order (fewest dependencies first). This is
85 -- NOT necessarily the build order (although it is in the absence of
90 componentsGraphToList
=
91 map (\(N c _ cs
) -> (c
, cs
)) . Graph
.revTopSort
93 -- | Error message when there is a cycle; takes the SCC of components.
94 componentCycleMsg
:: PackageIdentifier
-> [ComponentName
] -> Doc
95 componentCycleMsg pn cnames
=
96 text
"Components in the package"
98 <+> text
"depend on each other in a cyclic way:"
102 [ "'" ++ showComponentName cname
++ "'"
103 | cname
<- cnames
++ maybeToList (safeHead cnames
)