Skip to content

Commit

Permalink
Merge pull request #5526 from fgaz/multiple-libraries-v4
Browse files Browse the repository at this point in the history
[GSoC2018] Add support for multiple public libraries in a single package
  • Loading branch information
fgaz authored Nov 4, 2018
2 parents e65393b + 533b7cf commit f8fe5d2
Show file tree
Hide file tree
Showing 78 changed files with 1,441 additions and 583 deletions.
3 changes: 3 additions & 0 deletions Cabal/Cabal.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ library
Distribution.Types.ModuleReexport
Distribution.Types.ModuleRenaming
Distribution.Types.ComponentName
Distribution.Types.LibraryName
Distribution.Types.MungedPackageName
Distribution.Types.PackageName
Distribution.Types.PkgconfigName
Expand All @@ -367,6 +368,8 @@ library
Distribution.Types.Version
Distribution.Types.VersionRange
Distribution.Types.VersionInterval
Distribution.Types.GivenComponent
Distribution.Types.PackageVersionConstraint
Distribution.Utils.Generic
Distribution.Utils.NubList
Distribution.Utils.ShortText
Expand Down
6 changes: 3 additions & 3 deletions Cabal/Distribution/Backpack/ComponentsGraph.hs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ mkComponentsGraph enabled pkg_descr =
(CExeName <$> getAllInternalToolDependencies pkg_descr bi)

++ [ if pkgname == packageName pkg_descr
then CLibName
else CSubLibName toolname
| Dependency pkgname _ <- targetBuildDepends bi
then CLibName LMainLibName
else CLibName (LSubLibName toolname)
| Dependency pkgname _ _ <- targetBuildDepends bi
, let toolname = packageNameToUnqualComponentName pkgname
, toolname `elem` internalPkgDeps ]
where
Expand Down
39 changes: 27 additions & 12 deletions Cabal/Distribution/Backpack/ConfiguredComponent.hs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import Distribution.Types.PackageId
import Distribution.Types.PackageName
import Distribution.Types.Mixin
import Distribution.Types.ComponentName
import Distribution.Types.LibraryName
import Distribution.Types.UnqualComponentName
import Distribution.Types.ComponentInclude
import Distribution.Package
Expand Down Expand Up @@ -150,7 +151,7 @@ mkConfiguredComponent pkg_descr this_cid lib_deps exe_deps component = do
bi = componentBuildInfo component
deps_map = Map.fromList [ ((packageName dep, ann_cname dep), dep)
| dep <- lib_deps ]
is_public = componentName component == CLibName
is_public = componentName component == CLibName LMainLibName

type ConfiguredComponentMap =
Map PackageName (Map ComponentName (AnnotatedId ComponentId))
Expand All @@ -165,16 +166,28 @@ toConfiguredComponent
toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do
lib_deps <-
if newPackageDepsBehaviour pkg_descr
then forM (targetBuildDepends bi) $ \(Dependency name _) -> do
let (pn, cn) = fixFakePkgName pkg_descr name
value <- case Map.lookup cn =<< Map.lookup pn lib_dep_map of
then fmap concat $ forM (targetBuildDepends bi) $ \(Dependency name _ sublibs) -> do
-- The package name still needs fixing in case of legacy
-- sublibrary dependency syntax
let (pn, _) = fixFakePkgName pkg_descr name
pkg <- case Map.lookup pn lib_dep_map of
Nothing ->
dieProgress $
text "Dependency on unbuildable (i.e. 'buildable: False')" <+>
text (showComponentName cn) <+>
text "from" <+> disp pn
Just v -> return v
return value
text "Dependency on unbuildable" <+>
text "package" <+> disp pn
Just p -> return p
-- Return all library components
forM (Set.toList sublibs) $ \lib ->
let comp = CLibName lib in
case Map.lookup (CLibName $ LSubLibName $ packageNameToUnqualComponentName name) pkg
<|> Map.lookup comp pkg
of
Nothing ->
dieProgress $
text "Dependency on unbuildable" <+>
text (showLibraryName lib) <+>
text "from" <+> disp pn
Just v -> return v
else return old_style_lib_deps
mkConfiguredComponent
pkg_descr this_cid
Expand All @@ -192,7 +205,7 @@ toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do
| (pn, comp_map) <- Map.toList lib_dep_map
, pn /= packageName pkg_descr
, (cn, e) <- Map.toList comp_map
, cn == CLibName ]
, cn == CLibName LMainLibName ]
-- We have to nub here, because 'getAllToolDependencies' may return
-- duplicates (see #4986). (NB: This is not needed for lib_deps,
-- since those elaborate into includes, for which there explicitly
Expand Down Expand Up @@ -293,11 +306,13 @@ newPackageDepsBehaviour pkg =
-- and internal libraries are specified the same. For now, we assume internal
-- libraries shadow, and this function disambiguates accordingly, but soon the
-- underlying ambiguity will be addressed.
-- Multiple public libraries (cabal 3.0) added an unambiguous way of specifying
-- sublibraries, but we still have to support the old syntax for bc reasons.
fixFakePkgName :: PackageDescription -> PackageName -> (PackageName, ComponentName)
fixFakePkgName pkg_descr pn =
if subLibName `elem` internalLibraries
then (packageName pkg_descr, CSubLibName subLibName)
else (pn, CLibName)
then (packageName pkg_descr, CLibName (LSubLibName subLibName))
else (pn, CLibName LMainLibName )
where
subLibName = packageNameToUnqualComponentName pn
internalLibraries = mapMaybe libName (allLibraries pkg_descr)
5 changes: 3 additions & 2 deletions Cabal/Distribution/Backpack/ModuleScope.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import Distribution.ModuleName
import Distribution.Types.IncludeRenaming
import Distribution.Types.PackageName
import Distribution.Types.ComponentName
import Distribution.Types.LibraryName

import Distribution.Backpack
import Distribution.Backpack.ModSubst
Expand Down Expand Up @@ -113,8 +114,8 @@ dispComponent pn cn =
-- should be clear enough. To do source syntax, we'd
-- need to know what the package we're linking is.
case cn of
CLibName -> disp pn
CSubLibName ucn -> disp pn <<>> colon <<>> disp ucn
CLibName LMainLibName -> disp pn
CLibName (LSubLibName ucn) -> disp pn <<>> colon <<>> disp ucn
-- Case below shouldn't happen
_ -> disp pn <+> parens (disp cn)

Expand Down
5 changes: 3 additions & 2 deletions Cabal/Distribution/Backpack/ReadyComponent.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import Distribution.Types.Component
import Distribution.Types.ComponentInclude
import Distribution.Types.ComponentId
import Distribution.Types.ComponentName
import Distribution.Types.LibraryName
import Distribution.Types.PackageId
import Distribution.Types.UnitId
import Distribution.Compat.Graph (IsNode(..))
Expand Down Expand Up @@ -139,8 +140,8 @@ rc_depends rc = ordNub $
computeCompatPackageId
(ci_pkgid ci)
(case ci_cname ci of
CLibName -> Nothing
CSubLibName uqn -> Just uqn
CLibName LMainLibName -> Nothing
CLibName (LSubLibName uqn) -> Just uqn
_ -> error $ display (rc_cid rc) ++
" depends on non-library " ++ display (ci_id ci))

Expand Down
4 changes: 2 additions & 2 deletions Cabal/Distribution/Backpack/UnifyM.hs
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,8 @@ ci_msg ci
pn = pkgName (ci_pkgid ci)
pp_pn =
case ci_cname ci of
CLibName -> disp pn
CSubLibName cn -> disp pn <<>> colon <<>> disp cn
CLibName LMainLibName -> disp pn
CLibName (LSubLibName cn) -> disp pn <<>> colon <<>> disp cn
-- Shouldn't happen
cn -> disp pn <+> parens (disp cn)

Expand Down
14 changes: 13 additions & 1 deletion Cabal/Distribution/CabalSpecVersion.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ data CabalSpecVersion
| CabalSpecV2_0
| CabalSpecV2_2
| CabalSpecV2_4
| CabalSpecV3_0
deriving (Eq, Ord, Show, Read, Enum, Bounded, Typeable, Data, Generic)

cabalSpecLatest :: CabalSpecVersion
cabalSpecLatest = CabalSpecV2_4
cabalSpecLatest = CabalSpecV3_0

cabalSpecFeatures :: CabalSpecVersion -> Set.Set CabalFeature
cabalSpecFeatures CabalSpecOld = Set.empty
Expand All @@ -36,6 +37,12 @@ cabalSpecFeatures CabalSpecV2_4 = Set.fromList
, CommonStanzas
, Globstar
]
cabalSpecFeatures CabalSpecV3_0 = Set.fromList
[ Elif
, CommonStanzas
, Globstar
, MultipleLibraries
]

cabalSpecSupports :: CabalSpecVersion -> [Int] -> Bool
cabalSpecSupports CabalSpecOld v = v < [1,21]
Expand All @@ -44,15 +51,18 @@ cabalSpecSupports CabalSpecV1_24 v = v < [1,25]
cabalSpecSupports CabalSpecV2_0 v = v < [2,1]
cabalSpecSupports CabalSpecV2_2 v = v < [2,3]
cabalSpecSupports CabalSpecV2_4 _ = True
cabalSpecSupports CabalSpecV3_0 _ = True

specHasCommonStanzas :: CabalSpecVersion -> HasCommonStanzas
specHasCommonStanzas CabalSpecV2_2 = HasCommonStanzas
specHasCommonStanzas CabalSpecV2_4 = HasCommonStanzas
specHasCommonStanzas CabalSpecV3_0 = HasCommonStanzas
specHasCommonStanzas _ = NoCommonStanzas

specHasElif :: CabalSpecVersion -> HasElif
specHasElif CabalSpecV2_2 = HasElif
specHasElif CabalSpecV2_4 = HasElif
specHasElif CabalSpecV3_0 = HasElif
specHasElif _ = NoElif

-------------------------------------------------------------------------------
Expand All @@ -65,6 +75,8 @@ data CabalFeature
| Globstar
-- ^ Implemented in #5284. Not actually a change to the parser,
-- as filename patterns are opaque to it currently.
| MultipleLibraries
-- ^ Multiple public libraries in a package. Implemented in #5526.
deriving (Eq, Ord, Show, Read, Enum, Bounded, Typeable, Data, Generic)

-------------------------------------------------------------------------------
Expand Down
5 changes: 3 additions & 2 deletions Cabal/Distribution/InstalledPackageInfo.hs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import Distribution.ModuleName
import Distribution.Package hiding (installedPackageId, installedUnitId)
import Distribution.ParseUtils
import Distribution.Types.ComponentName
import Distribution.Types.LibraryName
import Distribution.Utils.Generic (toUTF8BS)

import qualified Data.Map as Map
Expand Down Expand Up @@ -104,8 +105,8 @@ installedPackageId = installedUnitId
sourceComponentName :: InstalledPackageInfo -> ComponentName
sourceComponentName ipi =
case sourceLibName ipi of
Nothing -> CLibName
Just qn -> CSubLibName qn
Nothing -> CLibName LMainLibName
Just qn -> CLibName $ LSubLibName qn

-- -----------------------------------------------------------------------------
-- Parsing
Expand Down
2 changes: 2 additions & 0 deletions Cabal/Distribution/PackageDescription.hs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ module Distribution.PackageDescription (
allBuildDepends,
enabledBuildDepends,
ComponentName(..),
LibraryName(..),
defaultLibName,
HookedBuildInfo,
emptyHookedBuildInfo,
Expand Down Expand Up @@ -135,5 +136,6 @@ import Distribution.Types.CondTree
import Distribution.Types.Condition
import Distribution.Types.PackageDescription
import Distribution.Types.ComponentName
import Distribution.Types.LibraryName
import Distribution.Types.HookedBuildInfo
import Distribution.Types.SourceRepo
34 changes: 17 additions & 17 deletions Cabal/Distribution/PackageDescription/Check.hs
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ checkFields pkg =
, name `elem` map display knownLanguages ]

testedWithImpossibleRanges =
[ Dependency (mkPackageName (display compiler)) vr
[ Dependency (mkPackageName (display compiler)) vr Set.empty
| (compiler, vr) <- testedWith pkg
, isNoVersion vr ]

Expand All @@ -598,7 +598,7 @@ checkFields pkg =
internalLibDeps =
[ dep
| bi <- allBuildInfo pkg
, dep@(Dependency name _) <- targetBuildDepends bi
, dep@(Dependency name _ _) <- targetBuildDepends bi
, name `elem` internalLibraries
]

Expand All @@ -611,14 +611,14 @@ checkFields pkg =

depInternalLibraryWithExtraVersion =
[ dep
| dep@(Dependency _ versionRange) <- internalLibDeps
| dep@(Dependency _ versionRange _) <- internalLibDeps
, not $ isAnyVersion versionRange
, packageVersion pkg `withinRange` versionRange
]

depInternalLibraryWithImpossibleVersion =
[ dep
| dep@(Dependency _ versionRange) <- internalLibDeps
| dep@(Dependency _ versionRange _) <- internalLibDeps
, not $ packageVersion pkg `withinRange` versionRange
]

Expand Down Expand Up @@ -1243,8 +1243,8 @@ checkCabalVersion pkg =
++ ". To use this new syntax the package need to specify at least "
++ "'cabal-version: >= 1.6'. Alternatively, if broader compatibility "
++ "is important then use: " ++ commaSep
[ display (Dependency name (eliminateWildcardSyntax versionRange))
| Dependency name versionRange <- depsUsingWildcardSyntax ]
[ display (Dependency name (eliminateWildcardSyntax versionRange) Set.empty)
| Dependency name versionRange _ <- depsUsingWildcardSyntax ]

-- check use of "build-depends: foo ^>= 1.2.3" syntax
, checkVersion [2,0] (not (null depsUsingMajorBoundSyntax)) $
Expand All @@ -1255,8 +1255,8 @@ checkCabalVersion pkg =
++ ". To use this new syntax the package need to specify at least "
++ "'cabal-version: 2.0'. Alternatively, if broader compatibility "
++ "is important then use: " ++ commaSep
[ display (Dependency name (eliminateMajorBoundSyntax versionRange))
| Dependency name versionRange <- depsUsingMajorBoundSyntax ]
[ display (Dependency name (eliminateMajorBoundSyntax versionRange) Set.empty)
| Dependency name versionRange _ <- depsUsingMajorBoundSyntax ]

, checkVersion [2,1] (any (not . null)
(concatMap buildInfoField
Expand Down Expand Up @@ -1292,8 +1292,8 @@ checkCabalVersion pkg =
++ ". To use this new syntax the package need to specify at least "
++ "'cabal-version: >= 1.6'. Alternatively, if broader compatibility "
++ "is important then use: " ++ commaSep
[ display (Dependency name (eliminateWildcardSyntax versionRange))
| Dependency name versionRange <- testedWithUsingWildcardSyntax ]
[ display (Dependency name (eliminateWildcardSyntax versionRange) Set.empty)
| Dependency name versionRange _ <- testedWithUsingWildcardSyntax ]

-- check use of "source-repository" section
, checkVersion [1,6] (not (null (sourceRepos pkg))) $
Expand Down Expand Up @@ -1367,11 +1367,11 @@ checkCabalVersion pkg =
buildInfoField field = map field (allBuildInfo pkg)

versionRangeExpressions =
[ dep | dep@(Dependency _ vr) <- allBuildDepends pkg
[ dep | dep@(Dependency _ vr _) <- allBuildDepends pkg
, usesNewVersionRangeSyntax vr ]

testedWithVersionRangeExpressions =
[ Dependency (mkPackageName (display compiler)) vr
[ Dependency (mkPackageName (display compiler)) vr Set.empty
| (compiler, vr) <- testedWith pkg
, usesNewVersionRangeSyntax vr ]

Expand All @@ -1395,16 +1395,16 @@ checkCabalVersion pkg =
alg (VersionRangeParensF _) = 3
alg _ = 1 :: Int

depsUsingWildcardSyntax = [ dep | dep@(Dependency _ vr) <- allBuildDepends pkg
depsUsingWildcardSyntax = [ dep | dep@(Dependency _ vr _) <- allBuildDepends pkg
, usesWildcardSyntax vr ]

depsUsingMajorBoundSyntax = [ dep | dep@(Dependency _ vr) <- allBuildDepends pkg
depsUsingMajorBoundSyntax = [ dep | dep@(Dependency _ vr _) <- allBuildDepends pkg
, usesMajorBoundSyntax vr ]

usesBackpackIncludes = any (not . null . mixins) (allBuildInfo pkg)

testedWithUsingWildcardSyntax =
[ Dependency (mkPackageName (display compiler)) vr
[ Dependency (mkPackageName (display compiler)) vr Set.empty
| (compiler, vr) <- testedWith pkg
, usesWildcardSyntax vr ]

Expand Down Expand Up @@ -1493,7 +1493,7 @@ checkCabalVersion pkg =
allModuleNamesAutogen = concatMap autogenModules (allBuildInfo pkg)

displayRawDependency :: Dependency -> String
displayRawDependency (Dependency pkg vr) =
displayRawDependency (Dependency pkg vr _sublibs) =
display pkg ++ " " ++ display vr


Expand Down Expand Up @@ -1545,7 +1545,7 @@ checkPackageVersions pkg =
foldr intersectVersionRanges anyVersion baseDeps
where
baseDeps =
[ vr | Dependency pname vr <- allBuildDepends pkg'
[ vr | Dependency pname vr _ <- allBuildDepends pkg'
, pname == mkPackageName "base" ]

-- Just in case finalizePD fails for any reason,
Expand Down
Loading

0 comments on commit f8fe5d2

Please sign in to comment.