Skip to content

Commit c4222ee

Browse files
ezyangEricson2314
authored andcommitted
Distinguish between internal and external libraries in build-depends
Fixes haskell#4155. We create a new `LibDependency` just used for parsing `build-depends` entries for now, but I hope it has a bright future in the brave new per-component world. Already in 'Cabal', this type will be used instead of 'Dependency' in most cases, implemented in the following commits of this PR. Used in: - Condition Trees - Querying the PackageIndex ----- Not sure about which type should have the (not)ThisPackageVersion function Also need to update some comments. Everything builds, however.
1 parent 929d16a commit c4222ee

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+762
-527
lines changed

Cabal/Cabal.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,10 @@ library
216216
Distribution.Types.Dependency
217217
Distribution.Types.ExeDependency
218218
Distribution.Types.LegacyExeDependency
219+
Distribution.Types.LibDependency
219220
Distribution.Types.PkgconfigDependency
220221
Distribution.Types.DependencyMap
222+
Distribution.Types.LibDependencyMap
221223
Distribution.Types.ComponentId
222224
Distribution.Types.MungedPackageId
223225
Distribution.Types.PackageId

Cabal/Distribution/Backpack/ComponentsGraph.hs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ import Distribution.PackageDescription as PD hiding (Flag)
1414
import Distribution.Simple.BuildToolDepends
1515
import Distribution.Simple.LocalBuildInfo
1616
import Distribution.Types.ComponentRequestedSpec
17-
import Distribution.Types.Dependency
18-
import Distribution.Types.UnqualComponentName
17+
import Distribution.Types.LibDependency
1918
import Distribution.Compat.Graph (Node(..))
2019
import qualified Distribution.Compat.Graph as Graph
20+
import Distribution.Types.Mixin
2121

2222
import Distribution.Text
2323
( Text(disp) )
@@ -57,18 +57,16 @@ toComponentsGraph enabled pkg_descr =
5757
-- The dependencies for the given component
5858
componentDeps component =
5959
(CExeName <$> getAllInternalToolDependencies pkg_descr bi)
60-
61-
++ [ if pkgname == packageName pkg_descr
62-
then CLibName
63-
else CSubLibName toolname
64-
| Dependency pkgname _ <- targetBuildDepends bi
65-
, let toolname = packageNameToUnqualComponentName pkgname
66-
, toolname `elem` internalPkgDeps ]
60+
++ mixin_deps
61+
++ [ maybe CLibName CSubLibName (libDepLibraryName ld)
62+
| ld <- targetBuildDepends bi
63+
, libDepPackageName ld == packageName pkg_descr ]
6764
where
6865
bi = componentBuildInfo component
69-
internalPkgDeps = map (conv . libName) (allLibraries pkg_descr)
70-
conv Nothing = packageNameToUnqualComponentName $ packageName pkg_descr
71-
conv (Just s) = s
66+
mixin_deps =
67+
[ maybe CLibName CSubLibName (mixinLibraryName mix)
68+
| mix <- mixins bi
69+
, mixinPackageName mix == packageName pkg_descr ]
7270

7371
-- | Error message when there is a cycle; takes the SCC of components.
7472
componentCycleMsg :: [ComponentName] -> Doc

Cabal/Distribution/Backpack/ConfiguredComponent.hs

Lines changed: 53 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,14 @@ import Distribution.Compat.Prelude hiding ((<>))
1919

2020
import Distribution.Backpack.Id
2121

22-
import Distribution.Types.Dependency
2322
import Distribution.Types.ExeDependency
2423
import Distribution.Types.IncludeRenaming
2524
import Distribution.Types.ComponentId
2625
import Distribution.Types.PackageId
2726
import Distribution.Types.PackageName
27+
import Distribution.Types.LibDependency
2828
import Distribution.Types.Mixin
2929
import Distribution.Types.ComponentName
30-
import Distribution.Types.UnqualComponentName
3130
import Distribution.Types.ComponentInclude
3231
import Distribution.Package
3332
import Distribution.PackageDescription as PD hiding (Flag)
@@ -39,7 +38,6 @@ import Distribution.Utils.LogProgress
3938
import Distribution.Utils.MapAccum
4039

4140
import Control.Monad
42-
import qualified Data.Set as Set
4341
import qualified Data.Map as Map
4442
import Distribution.Text
4543
import Text.PrettyPrint
@@ -85,85 +83,84 @@ dispConfiguredComponent cc =
8583
| incl <- cc_includes cc
8684
])
8785

86+
-- | This is a mapping that keeps track of package-internal libraries
87+
-- and executables. Although a component of the key is a general
88+
-- 'ComponentName', actually only 'CLib', 'CSubLib' and 'CExe' will ever
89+
-- be here.
8890
type ConfiguredComponentMap =
8991
Map PackageName (Map ComponentName (ComponentId, PackageId))
9092

93+
-- Executable map must be different because an executable can
94+
-- have the same name as a library. Ew.
95+
96+
-- | Given some ambient environment of package names that
97+
-- are "in scope", looks at the 'BuildInfo' to decide
98+
-- what the packages actually resolve to, and then builds
99+
-- a 'ConfiguredComponent'.
91100
toConfiguredComponent
92101
:: PackageDescription
93102
-> ComponentId
94103
-> ConfiguredComponentMap
95104
-> Component
96105
-> LogProgress ConfiguredComponent
97106
toConfiguredComponent pkg_descr this_cid dep_map component = do
98-
lib_deps <-
99-
if newPackageDepsBehaviour pkg_descr
100-
then forM (targetBuildDepends bi) $ \(Dependency name _) -> do
101-
let keys@(pn, cn) = fixFakePkgName pkg_descr name
102-
value <- case Map.lookup cn =<< Map.lookup pn dep_map of
103-
Nothing ->
104-
dieProgress $
105-
text "Dependency on unbuildable" <+>
106-
text (showComponentName cn) <+>
107-
text "from" <+> disp pn
108-
Just v -> return v
109-
return (keys, value)
110-
else return old_style_lib_deps
111-
112-
-- Resolve each @mixins@ into the actual dependency
113-
-- from @lib_deps@.
114-
explicit_includes <- forM (mixins bi) $ \(Mixin name rns) -> do
115-
let (pkg, cname) = fixFakePkgName pkg_descr name
116-
(cid, pid) <-
117-
case Map.lookup cname =<< Map.lookup pkg dep_map of
118-
Nothing ->
119-
dieProgress $
120-
text "Mix-in refers to non-existent package" <+>
121-
quotes (disp name) $$
122-
text "(did you forget to add the package to build-depends?)"
123-
Just r -> return r
107+
let reg_lib_deps =
108+
if newPackageDepsBehaviour pkg_descr
109+
then
110+
[ (pn, cn)
111+
| LibDependency pn mb_ln _ <- targetBuildDepends bi
112+
, let cn = libraryComponentName mb_ln ]
113+
else
114+
-- dep_map contains a mix of internal and external deps.
115+
-- We want all the public libraries (dep_cn == CLibName)
116+
-- of all external deps (dep /= pn). Note that this
117+
-- excludes the public library of the current package:
118+
-- this is not supported by old-style deps behavior
119+
-- because it would imply a cyclic dependency for the
120+
-- library itself.
121+
[ (pn, cn)
122+
| (pn, comp_map) <- Map.toList dep_map
123+
, pn /= packageName pkg_descr
124+
, (cn, _) <- Map.toList comp_map
125+
, cn == CLibName ]
126+
127+
reg_lib_map, mixin_map :: Map (PackageName, ComponentName) (IncludeRenaming, Bool)
128+
129+
reg_lib_map = Map.fromList $
130+
reg_lib_deps `zip` repeat (defaultIncludeRenaming, True)
131+
132+
mixin_map = Map.fromList
133+
[ ((pn, cn), (rns, False))
134+
| Mixin pn mb_ln rns <- mixins bi
135+
, let cn = libraryComponentName mb_ln ]
136+
137+
lib_deps = Map.toList $ reg_lib_map `Map.union` mixin_map
138+
139+
mixin_includes <- forM lib_deps $ \((pname, cname), (rns, implicit)) -> do
140+
(cid, pid) <- case Map.lookup cname =<< Map.lookup pname dep_map of
141+
Nothing -> dieProgress $
142+
text "Dependency on unbuildable" <+>
143+
text (showComponentName cname) <+>
144+
text "from" <+> disp pname
145+
Just r -> return r
124146
return ComponentInclude {
125147
ci_id = cid,
126148
ci_pkgid = pid,
127149
ci_compname = cname,
128150
ci_renaming = rns,
129-
ci_implicit = False
151+
ci_implicit = implicit
130152
}
131153

132-
-- Any @build-depends@ which is not explicitly mentioned in
133-
-- @backpack-include@ is converted into an "implicit" include.
134-
let used_explicitly = Set.fromList (map ci_id explicit_includes)
135-
implicit_includes
136-
= map (\((_, cn), (cid, pid)) -> ComponentInclude {
137-
ci_id = cid,
138-
ci_pkgid = pid,
139-
ci_compname = cn,
140-
ci_renaming = defaultIncludeRenaming,
141-
ci_implicit = True
142-
})
143-
$ filter (flip Set.notMember used_explicitly . fst . snd) lib_deps
144-
145154
return ConfiguredComponent {
146155
cc_cid = this_cid,
147156
cc_pkgid = package pkg_descr,
148157
cc_component = component,
149158
cc_public = componentName component == CLibName,
150159
cc_exe_deps = exe_deps,
151-
cc_includes = explicit_includes ++ implicit_includes
160+
cc_includes = mixin_includes
152161
}
153162
where
154163
bi = componentBuildInfo component
155-
-- dep_map contains a mix of internal and external deps.
156-
-- We want all the public libraries (dep_cn == CLibName)
157-
-- of all external deps (dep /= pn). Note that this
158-
-- excludes the public library of the current package:
159-
-- this is not supported by old-style deps behavior
160-
-- because it would imply a cyclic dependency for the
161-
-- library itself.
162-
old_style_lib_deps = [ ((pn, cn), e)
163-
| (pn, comp_map) <- Map.toList dep_map
164-
, pn /= packageName pkg_descr
165-
, (cn, e) <- Map.toList comp_map
166-
, cn == CLibName ]
167164
exe_deps =
168165
[ exe
169166
| ExeDependency pn cn _ <- getAllToolDependencies pkg_descr bi
@@ -249,16 +246,3 @@ newPackageDepsBehaviourMinVersion = mkVersion [1,7,1]
249246
newPackageDepsBehaviour :: PackageDescription -> Bool
250247
newPackageDepsBehaviour pkg =
251248
specVersion pkg >= newPackageDepsBehaviourMinVersion
252-
253-
-- | 'build-depends:' stanzas are currently ambiguous as the external packages
254-
-- and internal libraries are specified the same. For now, we assume internal
255-
-- libraries shadow, and this function disambiguates accordingly, but soon the
256-
-- underlying ambiguity will be addressed.
257-
fixFakePkgName :: PackageDescription -> PackageName -> (PackageName, ComponentName)
258-
fixFakePkgName pkg_descr pn =
259-
if subLibName `elem` internalLibraries
260-
then (packageName pkg_descr, CSubLibName subLibName)
261-
else (pn, CLibName)
262-
where
263-
subLibName = packageNameToUnqualComponentName pn
264-
internalLibraries = mapMaybe libName (allLibraries pkg_descr)

Cabal/Distribution/Backpack/ReadyComponent.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ instance HasMungedPackageId ReadyComponent where
138138
mungedId ReadyComponent { rc_pkgid = pkgid, rc_component = component }
139139
= computeCompatPackageId pkgid (componentName component)
140140

141+
instance HasComponentName ReadyComponent where
142+
sourceCompName = componentName . rc_component
143+
141144
instance HasUnitId ReadyComponent where
142145
installedUnitId = rc_uid
143146

Cabal/Distribution/InstalledPackageInfo.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import Distribution.Version
6060
import Distribution.Text
6161
import qualified Distribution.Compat.ReadP as Parse
6262
import Distribution.Compat.Graph
63+
import Distribution.Types.ComponentName
6364
import Distribution.Types.MungedPackageId
6465
import Distribution.Types.MungedPackageName
6566
import Distribution.Types.UnqualComponentName
@@ -202,6 +203,9 @@ instance Package.Package InstalledPackageInfo where
202203
packageId ipi = PackageIdentifier (sourcePackageName' ipi) ver
203204
where MungedPackageId _ ver = sourceMungedPackageId ipi
204205

206+
instance Package.HasComponentName InstalledPackageInfo where
207+
sourceCompName = libraryComponentName . sourceLibName
208+
205209
instance Package.HasUnitId InstalledPackageInfo where
206210
installedUnitId = installedUnitId
207211

Cabal/Distribution/Package.hs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module Distribution.Package
2626
, module Distribution.Types.PkgconfigName
2727
, Package(..), packageName, packageVersion
2828
, HasMungedPackageId(..), mungedName', mungedVersion'
29-
, HasUnitId(..)
29+
, HasComponentName(..), HasUnitId(..)
3030
, installedPackageId
3131
, PackageInstalled(..)
3232
) where
@@ -43,6 +43,7 @@ import Distribution.Types.MungedPackageId
4343
import Distribution.Types.PackageId
4444
import Distribution.Types.UnitId
4545
import Distribution.Types.Module
46+
import Distribution.Types.ComponentName
4647
import Distribution.Types.MungedPackageName
4748
import Distribution.Types.PackageName
4849
import Distribution.Types.PkgconfigName
@@ -66,12 +67,12 @@ mungedName' = mungedName . mungedId
6667
mungedVersion' :: HasMungedPackageId munged => munged -> Version
6768
mungedVersion' = mungedVersion . mungedId
6869

69-
class HasMungedPackageId pkg where
70-
mungedId :: pkg -> MungedPackageId
71-
7270
instance Package PackageIdentifier where
7371
packageId = id
7472

73+
class HasMungedPackageId pkg where
74+
mungedId :: pkg -> MungedPackageId
75+
7576
packageName :: Package pkg => pkg -> PackageName
7677
packageName = pkgName . packageId
7778

@@ -81,6 +82,9 @@ packageVersion = pkgVersion . packageId
8182
instance HasMungedPackageId MungedPackageId where
8283
mungedId = id
8384

85+
class Package pkg => HasComponentName pkg where
86+
sourceCompName :: pkg -> ComponentName
87+
8488
-- | Packages that have an installed unit ID
8589
class Package pkg => HasUnitId pkg where
8690
installedUnitId :: pkg -> UnitId
@@ -96,5 +100,5 @@ installedPackageId = installedUnitId
96100
-- 'InstalledPackageInfo', but when we are doing install plans in Cabal install
97101
-- we may have other, installed package-like things which contain more metadata.
98102
-- Installed packages have exact dependencies 'installedDepends'.
99-
class (HasUnitId pkg) => PackageInstalled pkg where
103+
class (HasComponentName pkg, HasUnitId pkg) => PackageInstalled pkg where
100104
installedDepends :: pkg -> [UnitId]

0 commit comments

Comments
 (0)