From 8646b09502f2983490d8c8a5b79094beeaaf1e49 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 25 Jan 2017 20:28:38 -0500 Subject: [PATCH] Complete the build-depends internal reform in Cabal --- .../Backpack/PreExistingComponent.hs | 13 ++-- .../Distribution/PackageDescription/Parse.hs | 7 +- .../PackageDescription/Parsec/FieldDescr.hs | 4 +- Cabal/Distribution/Simple/Configure.hs | 73 +++++++++++-------- Cabal/Distribution/Types/ExeDependency.hs | 11 +-- Cabal/Distribution/Types/LibDependency.exe | 54 -------------- Cabal/Distribution/Types/LibDependency.hs | 62 ++++++++++++++++ 7 files changed, 123 insertions(+), 101 deletions(-) delete mode 100644 Cabal/Distribution/Types/LibDependency.exe create mode 100644 Cabal/Distribution/Types/LibDependency.hs diff --git a/Cabal/Distribution/Backpack/PreExistingComponent.hs b/Cabal/Distribution/Backpack/PreExistingComponent.hs index 099481ba2ab..6940e612e38 100644 --- a/Cabal/Distribution/Backpack/PreExistingComponent.hs +++ b/Cabal/Distribution/Backpack/PreExistingComponent.hs @@ -8,6 +8,7 @@ import Prelude () import Distribution.Backpack.ModuleShape import Distribution.Backpack +import Distribution.Types.ComponentName import qualified Data.Map as Map import Distribution.Package @@ -18,12 +19,8 @@ import Distribution.InstalledPackageInfo (InstalledPackageInfo) -- we don't need to know how to build. data PreExistingComponent = PreExistingComponent { - -- | The 'PackageName' that, when we see it in 'PackageDescription', - -- we should map this to. This may DISAGREE with 'pc_pkgid' for - -- internal dependencies: e.g., an internal component @lib@ - -- may be munged to @z-pkg-z-lib@, but we still want to use - -- it when we see @lib@ in @build-depends@ pc_pkgname :: PackageName, + pc_compname :: ComponentName, pc_pkgid :: PackageId, pc_uid :: UnitId, pc_cid :: ComponentId, @@ -34,10 +31,11 @@ data PreExistingComponent -- | Convert an 'InstalledPackageInfo' into a 'PreExistingComponent', -- which was brought into scope under the 'PackageName' (important for -- a package qualified reference.) -ipiToPreExistingComponent :: (PackageName, InstalledPackageInfo) -> PreExistingComponent -ipiToPreExistingComponent (pn, ipi) = +ipiToPreExistingComponent :: (PackageName, ComponentName, InstalledPackageInfo) -> PreExistingComponent +ipiToPreExistingComponent (pn, cn, ipi) = PreExistingComponent { pc_pkgname = pn, + pc_compname = cn, pc_pkgid = Installed.sourcePackageId ipi, pc_uid = Installed.installedUnitId ipi, pc_cid = Installed.installedComponentId ipi, @@ -46,4 +44,3 @@ ipiToPreExistingComponent (pn, ipi) = (Map.fromList (Installed.instantiatedWith ipi)), pc_shape = shapeInstalledPackage ipi } - diff --git a/Cabal/Distribution/PackageDescription/Parse.hs b/Cabal/Distribution/PackageDescription/Parse.hs index 9856f1a5bb1..f1d610edc4c 100644 --- a/Cabal/Distribution/PackageDescription/Parse.hs +++ b/Cabal/Distribution/PackageDescription/Parse.hs @@ -55,6 +55,7 @@ import Distribution.Types.ForeignLib import Distribution.Types.ForeignLibType import Distribution.Types.UnqualComponentName import Distribution.Types.LibDependency +import Distribution.Types.CondTree import Distribution.ParseUtils hiding (parseFields) import Distribution.PackageDescription import Distribution.PackageDescription.Utils @@ -425,8 +426,8 @@ binfoFieldDescrs = , commaListFieldWithSep vcat "build-depends" disp parse buildDependencies - (\xs binfo -> binfo{targetBuildDepends=map buildDependencyToDependency xs, - implicitMixins=map buildDependencyToMixin xs}) + (\xs binfo -> binfo{targetBuildDepends=map libDependencyToDependency xs, + implicitMixins=map libDependencyToMixin xs}) , commaListFieldWithSep vcat "mixins" disp parse mixins (\xs binfo -> binfo{mixins=xs}) @@ -1106,7 +1107,7 @@ parsePackageDescription file = do -- to check the CondTree, rather than grovel everywhere -- inside the conditional bits). deps <- liftM concat - . traverse (lift . fmap (map buildDependencyToDependency) . parseConstraint) + . traverse (lift . fmap (map libDependencyToDependency) . parseConstraint) . filter isConstraint $ simplFlds diff --git a/Cabal/Distribution/PackageDescription/Parsec/FieldDescr.hs b/Cabal/Distribution/PackageDescription/Parsec/FieldDescr.hs index 6245f091809..fc5f88726f9 100644 --- a/Cabal/Distribution/PackageDescription/Parsec/FieldDescr.hs +++ b/Cabal/Distribution/PackageDescription/Parsec/FieldDescr.hs @@ -431,8 +431,8 @@ binfoFieldDescrs = , commaListFieldWithSep vcat "build-depends" disp parsec buildDependencies - (\xs binfo -> binfo{targetBuildDepends=map buildDependencyToDependency xs, - implicitMixins=map buildDependencyToMixin xs}) + (\xs binfo -> binfo{targetBuildDepends=map libDependencyToDependency xs, + implicitMixins=map libDependencyToMixin xs}) , commaListFieldWithSep vcat "mixins" disp parsec mixins (\xs binfo -> binfo{mixins=xs}) diff --git a/Cabal/Distribution/Simple/Configure.hs b/Cabal/Distribution/Simple/Configure.hs index 8896394235b..049b1bd437d 100644 --- a/Cabal/Distribution/Simple/Configure.hs +++ b/Cabal/Distribution/Simple/Configure.hs @@ -71,8 +71,10 @@ import Distribution.InstalledPackageInfo (InstalledPackageInfo) import qualified Distribution.Simple.PackageIndex as PackageIndex import Distribution.Simple.PackageIndex (InstalledPackageIndex) import Distribution.PackageDescription as PD hiding (Flag) +import Distribution.Types.BuildInfo (buildDependencies) import Distribution.Types.PackageDescription as PD import Distribution.Types.DependencyMap +import Distribution.Types.LibDependency import Distribution.PackageDescription.PrettyPrint import Distribution.PackageDescription.Configuration import Distribution.PackageDescription.Check hiding (doesFileExist) @@ -132,8 +134,8 @@ import System.IO ( hPutStrLn, hClose ) import Distribution.Text ( Text(disp), defaultStyle, display, simpleParse ) -import Text.PrettyPrint - ( Doc, (<+>), ($+$), char, comma, hsep, nest +import Text.PrettyPrint as PP + ( Doc, (<+>), ($+$), char, comma, empty, hsep, nest , punctuate, quotes, render, renderStyle, sep, text ) import Distribution.Compat.Environment ( lookupEnv ) import Distribution.Compat.Exception ( catchExit, catchIO ) @@ -841,7 +843,7 @@ dependencySatisfiable dependencySatisfiable use_external_internal_deps exact_config pn installedPackageSet allConstraintsMap - d@(Dependency depName vr) + d@(Dependency depName _) -- When we are doing per-component configure, the behavior is very -- uniform: if an exact configuration is requested, check for the @@ -991,7 +993,7 @@ configureDependencies -> IO [(PackageName, ComponentName, InstalledPackageInfo)] configureDependencies verbosity use_external_internal_deps installedPackageSet requiredDepsMap pkg_descr = do - let selectDependencies :: [Dependency] -> + let selectDependencies :: [LibDependency] -> ([FailedDependency], [ResolvedDependency]) selectDependencies = partitionEithers @@ -1000,15 +1002,20 @@ configureDependencies verbosity use_external_internal_deps requiredDepsMap use_external_internal_deps) (failedDeps, allPkgDeps) = - selectDependencies (buildDepends pkg_descr) + selectDependencies (buildDependencies =<< allBuildInfo pkg_descr) - internalPkgDeps = [ pkgid - | InternalDependency _ pkgid <- allPkgDeps ] + internalPkgDeps = + [ pkgid | InternalDependency _ pkgid <- allPkgDeps ] -- NB: we have to SAVE the package name, because this is the only -- way we can be able to resolve package names in the package -- description. - externalPkgDeps = [ (pn, pkg) - | ExternalDependency (Dependency pn _) pkg <- allPkgDeps ] + externalPkgDeps = + [ (pn, cn, pkgid) + | ExternalDependency (LibDependency pn mcn _) pkgid <- allPkgDeps + , let cn = case mcn of + Nothing -> CLibName + Just n -> CSubLibName n + ] when (not (null internalPkgDeps) && not (newPackageDepsBehaviour pkg_descr)) $ @@ -1144,12 +1151,12 @@ data ResolvedDependency -- | An external dependency from the package database, OR an -- internal dependency which we are getting from the package -- database. - = ExternalDependency Dependency InstalledPackageInfo + = ExternalDependency LibDependency InstalledPackageInfo -- | An internal dependency ('PackageId' should be a library name) -- which we are going to have to build. (The -- 'PackageId' here is a hack to get a modest amount of -- polymorphism out of the 'Package' typeclass.) - | InternalDependency Dependency PackageId + | InternalDependency LibDependency PackageId data FailedDependency = DependencyNotExists PackageName | DependencyMissingInternal PackageName PackageName @@ -1163,11 +1170,11 @@ selectDependency :: PackageId -- ^ Package id of current package -- use -> UseExternalInternalDeps -- ^ Are we configuring a -- single component? - -> Dependency + -> LibDependency -> Either FailedDependency ResolvedDependency selectDependency pkgid installedIndex requiredDepsMap use_external_internal_deps - dep@(Dependency dep_pkgname vr) = + dep@(LibDependency dep_pkgname dep_mb_compname vr) = -- If the dependency specification matches anything in the internal package -- index, then we prefer that match to anything in the second. -- For example: @@ -1181,27 +1188,35 @@ selectDependency pkgid installedIndex requiredDepsMap -- -- We want "build-depends: MyLibrary" always to match the internal library -- even if there is a newer installed library "MyLibrary-0.2". - do_external Nothing + case dep_mb_compname of + Just intLibName -> + if use_external_internal_deps + then do_external $ Just intLibName + else do_internal + _ -> do_external Nothing where do_internal = Right (InternalDependency dep (PackageIdentifier dep_pkgname (packageVersion pkgid))) - do_external is_internal = case Map.lookup dep_pkgname requiredDepsMap of + do_external mb_intLibName = case Map.lookup (dep_pkgname, compName) requiredDepsMap of -- If we know the exact pkg to use, then use it. Just pkginstance -> Right (ExternalDependency dep pkginstance) -- Otherwise we just pick an arbitrary instance of the latest version. - Nothing -> case PackageIndex.lookupDependency installedIndex dep' of - [] -> Left $ - case is_internal of - Just cname -> DependencyMissingInternal dep_pkgname - (computeCompatPackageName (packageName pkgid) cname) - Nothing -> DependencyNotExists dep_pkgname - pkgs -> Right $ ExternalDependency dep $ - case last pkgs of + Nothing -> case PackageIndex.lookupDependency installedIndex legacyDep of + [] -> Left errVal + pkgs -> Right $ ExternalDependency dep $ case last pkgs of (_ver, pkginstances) -> head pkginstances where - dep' | Just cname <- is_internal - = Dependency (computeCompatPackageName (packageName pkgid) cname) vr - | otherwise = dep + (legacyDep, compName, errVal) = case mb_intLibName of + Nothing -> ( Dependency dep_pkgname vr + , CLibName + , DependencyNotExists dep_pkgname + ) + Just intLibName -> ( Dependency extIntPkgName vr + , cname + , DependencyMissingInternal dep_pkgname extIntPkgName + ) + where extIntPkgName = computeCompatPackageName (packageName pkgid) cname + cname = CSubLibName intLibName -- NB: here computeCompatPackageName we want to pick up the INDEFINITE ones -- which is why we pass 'Nothing' as 'UnitId' @@ -1209,7 +1224,7 @@ reportSelectedDependencies :: Verbosity -> [ResolvedDependency] -> IO () reportSelectedDependencies verbosity deps = info verbosity $ unlines - [ "Dependency " ++ display (simplifyDependency dep) + [ "Dependency " ++ display (simplifyLibDependency dep) ++ ": using " ++ display pkgid | resolved <- deps , let (dep, pkgid) = case resolved of @@ -1379,8 +1394,8 @@ combinedConstraints constraints dependencies installedPackages = do | (pkgname, mb_cname, cid, Nothing) <- dependenciesPkgInfo ] dispDependencies deps = - hsep [ text "--dependency=" - <<>> quotes (disp pkgname <<>> (maybe empty disp mb_cname) <<>> char '=' <<>> disp cid) + hsep [text "--dependency=" + <<>> quotes (disp pkgname <<>> (maybe PP.empty disp mb_cname) <<>> char '=' <<>> disp cid) | (pkgname, mb_cname, cid) <- deps ] -- ----------------------------------------------------------------------------- diff --git a/Cabal/Distribution/Types/ExeDependency.hs b/Cabal/Distribution/Types/ExeDependency.hs index e7d28fc2ef8..10bb8d3c21e 100644 --- a/Cabal/Distribution/Types/ExeDependency.hs +++ b/Cabal/Distribution/Types/ExeDependency.hs @@ -21,11 +21,12 @@ import Text.PrettyPrint ((<+>), text) -- | Describes a dependency on an executable from a package -- -data ExeDependency = ExeDependency - PackageName - UnqualComponentName -- name of executable component of package - VersionRange - deriving (Generic, Read, Show, Eq, Typeable, Data) +data ExeDependency = ExeDependency { + exeDepPackageName :: PackageName, + exeDepExecutableName :: UnqualComponentName, + libDepVersionRange :: VersionRange + } + deriving (Generic, Read, Show, Eq, Typeable, Data) instance Binary ExeDependency instance NFData ExeDependency where rnf = genericRnf diff --git a/Cabal/Distribution/Types/LibDependency.exe b/Cabal/Distribution/Types/LibDependency.exe deleted file mode 100644 index 3cc9e5d9d7f..00000000000 --- a/Cabal/Distribution/Types/LibDependency.exe +++ /dev/null @@ -1,54 +0,0 @@ -{-# LANGUAGE DeriveGeneric #-} -{-# LANGUAGE DeriveDataTypeable #-} -module Distribution.Types.LibDependency ( - LibDependency(..), - buildDependencyToDependency, - buildDependencyToMixin, -) where - -import Prelude () -import Distribution.Compat.Prelude - -import Distribution.Package -import Distribution.Types.UnqualComponentName -import Distribution.Types.Mixin -import Distribution.Types.Dependency -import Distribution.Types.IncludeRenaming -import Distribution.Version - -import qualified Distribution.Compat.ReadP as Parse -import Distribution.Compat.ReadP -import Distribution.Text -import Text.PrettyPrint ((<+>), text) - --- | Like 'Dependency', but this corresponds exactly to --- the syntax we support in a Cabal file. -data LibDependency = LibDependency { - buildDependsPackageName :: PackageName, - buildDependsLibraryName :: Maybe UnqualComponentName, - buildDependsVersionRange :: VersionRange - } - deriving (Generic, Read, Show, Eq, Typeable, Data) - -instance Binary LibDependency -instance NFData LibDependency where rnf = genericRnf - -instance Text LibDependency where - disp (LibDependency name Nothing vr) = - disp name <+> disp vr - disp (LibDependency name (Just cname) vr) = - disp name <<>> text ":" <<>> disp cname <+> disp vr - - parse = do name <- parse - mb_cname <- option Nothing $ do - _ <- char ':' - fmap Just parse - skipSpaces - ver <- parse <++ return anyVersion - return (LibDependency name mb_cname ver) - -buildDependencyToDependency :: LibDependency -> Dependency -buildDependencyToDependency (LibDependency pn _ vr) = Dependency pn vr - -buildDependencyToMixin :: LibDependency -> Mixin -buildDependencyToMixin (LibDependency pn cn _) = Mixin pn cn defaultIncludeRenaming diff --git a/Cabal/Distribution/Types/LibDependency.hs b/Cabal/Distribution/Types/LibDependency.hs new file mode 100644 index 00000000000..27378b3c11f --- /dev/null +++ b/Cabal/Distribution/Types/LibDependency.hs @@ -0,0 +1,62 @@ +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DeriveDataTypeable #-} +module Distribution.Types.LibDependency ( + LibDependency(..), + libDependencyToDependency, + libDependencyToMixin, + simplifyLibDependency, +) where + +import Prelude () +import Distribution.Compat.Prelude + +import Distribution.Package +import Distribution.Types.UnqualComponentName +import Distribution.Types.Mixin +import Distribution.Types.Dependency +import Distribution.Types.IncludeRenaming +import Distribution.Version + +import Distribution.Compat.ReadP +import Distribution.Text +import Text.PrettyPrint as PP ((<+>), text, empty) + +-- | Like 'Dependency', but this corresponds exactly to the syntax we support in +-- a Cabal file. +data LibDependency = LibDependency { + libDepPackageName :: PackageName, + libDepLibraryName :: Maybe UnqualComponentName, + libDepVersionRange :: VersionRange + } + deriving (Generic, Read, Show, Eq, Typeable, Data) + +instance Binary LibDependency +instance NFData LibDependency where rnf = genericRnf + +instance Text LibDependency where + disp (LibDependency name mCname ver) = + (disp name <<>> dispMaybeCname) <+> disp ver + where + dispMaybeCname = case mCname of + Nothing -> PP.empty + Just cname -> text ":" <<>> disp cname + + parse = do name <- parse + mb_cname <- option Nothing $ do + _ <- char ':' + fmap Just parse + skipSpaces + ver <- parse <++ return anyVersion + return (LibDependency name mb_cname ver) + +libDependencyToDependency :: LibDependency -> Dependency +libDependencyToDependency (LibDependency pn _ vr) = Dependency pn vr + +libDependencyToMixin :: LibDependency -> Mixin +libDependencyToMixin (LibDependency pn cn _) = Mixin pn cn defaultIncludeRenaming +-- | Simplify the 'VersionRange' expression in a 'Dependency'. +-- See 'simplifyVersionRange'. +-- +simplifyLibDependency :: LibDependency -> LibDependency +simplifyLibDependency (LibDependency name mb_cname range) = + LibDependency name mb_cname (simplifyVersionRange range)