{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}
module Distribution.Types.PackageDescription (
PackageDescription(..),
specVersion,
descCabalVersion,
emptyPackageDescription,
hasPublicLib,
hasLibs,
allLibraries,
withLib,
hasExes,
withExe,
hasTests,
withTest,
hasBenchmarks,
withBenchmark,
hasForeignLibs,
withForeignLib,
allBuildInfo,
enabledBuildInfos,
updatePackageDescription,
pkgComponents,
pkgBuildableComponents,
enabledComponents,
lookupComponent,
getComponent,
) where
import Prelude ()
import Distribution.Compat.Prelude
import Distribution.Types.Library
import Distribution.Types.TestSuite
import Distribution.Types.Executable
import Distribution.Types.Benchmark
import Distribution.Types.ForeignLib
import Distribution.Types.Component
import Distribution.Types.ComponentRequestedSpec
import Distribution.Types.Dependency
import Distribution.Types.PackageId
import Distribution.Types.ComponentName
import Distribution.Types.PackageName
import Distribution.Types.UnqualComponentName
import Distribution.Types.SetupBuildInfo
import Distribution.Types.BuildInfo
import Distribution.Types.BuildType
import Distribution.Types.SourceRepo
import Distribution.Types.HookedBuildInfo
import Distribution.Package
import Distribution.Version
import Distribution.License
import Distribution.Compiler
data PackageDescription
= PackageDescription {
package :: PackageIdentifier,
license :: License,
licenseFiles :: [FilePath],
copyright :: String,
maintainer :: String,
author :: String,
stability :: String,
testedWith :: [(CompilerFlavor,VersionRange)],
homepage :: String,
pkgUrl :: String,
bugReports :: String,
sourceRepos :: [SourceRepo],
synopsis :: String,
description :: String,
category :: String,
customFieldsPD :: [(String,String)],
buildDepends :: [Dependency],
specVersionRaw :: Either Version VersionRange,
buildType :: Maybe BuildType,
setupBuildInfo :: Maybe SetupBuildInfo,
library :: Maybe Library,
subLibraries :: [Library],
executables :: [Executable],
foreignLibs :: [ForeignLib],
testSuites :: [TestSuite],
benchmarks :: [Benchmark],
dataFiles :: [FilePath],
dataDir :: FilePath,
extraSrcFiles :: [FilePath],
extraTmpFiles :: [FilePath],
extraDocFiles :: [FilePath]
}
deriving (Generic, Show, Read, Eq, Typeable, Data)
instance Binary PackageDescription
instance Package PackageDescription where
packageId = package
specVersion :: PackageDescription -> Version
specVersion pkg = case specVersionRaw pkg of
Left version -> version
Right versionRange -> case asVersionIntervals versionRange of
[] -> mkVersion [0]
((LowerBound version _, _):_) -> version
descCabalVersion :: PackageDescription -> VersionRange
descCabalVersion pkg = case specVersionRaw pkg of
Left version -> orLaterVersion version
Right versionRange -> versionRange
{-# DEPRECATED descCabalVersion "Use specVersion instead" #-}
emptyPackageDescription :: PackageDescription
emptyPackageDescription
= PackageDescription {
package = PackageIdentifier (mkPackageName "")
nullVersion,
license = UnspecifiedLicense,
licenseFiles = [],
specVersionRaw = Right anyVersion,
buildType = Nothing,
copyright = "",
maintainer = "",
author = "",
stability = "",
testedWith = [],
buildDepends = [],
homepage = "",
pkgUrl = "",
bugReports = "",
sourceRepos = [],
synopsis = "",
description = "",
category = "",
customFieldsPD = [],
setupBuildInfo = Nothing,
library = Nothing,
subLibraries = [],
foreignLibs = [],
executables = [],
testSuites = [],
benchmarks = [],
dataFiles = [],
dataDir = "",
extraSrcFiles = [],
extraTmpFiles = [],
extraDocFiles = []
}
hasPublicLib :: PackageDescription -> Bool
hasPublicLib p =
case library p of
Just lib -> buildable (libBuildInfo lib)
Nothing -> False
hasLibs :: PackageDescription -> Bool
hasLibs p = any (buildable . libBuildInfo) (allLibraries p)
allLibraries :: PackageDescription -> [Library]
allLibraries p = maybeToList (library p) ++ subLibraries p
withLib :: PackageDescription -> (Library -> IO ()) -> IO ()
withLib pkg_descr f =
sequence_ [f lib | lib <- allLibraries pkg_descr, buildable (libBuildInfo lib)]
hasExes :: PackageDescription -> Bool
hasExes p = any (buildable . buildInfo) (executables p)
withExe :: PackageDescription -> (Executable -> IO ()) -> IO ()
withExe pkg_descr f =
sequence_ [f exe | exe <- executables pkg_descr, buildable (buildInfo exe)]
hasTests :: PackageDescription -> Bool
hasTests = any (buildable . testBuildInfo) . testSuites
withTest :: PackageDescription -> (TestSuite -> IO ()) -> IO ()
withTest pkg_descr f =
sequence_ [ f test | test <- testSuites pkg_descr, buildable (testBuildInfo test) ]
hasBenchmarks :: PackageDescription -> Bool
hasBenchmarks = any (buildable . benchmarkBuildInfo) . benchmarks
withBenchmark :: PackageDescription -> (Benchmark -> IO ()) -> IO ()
withBenchmark pkg_descr f =
sequence_ [f bench | bench <- benchmarks pkg_descr, buildable (benchmarkBuildInfo bench)]
hasForeignLibs :: PackageDescription -> Bool
hasForeignLibs p = any (buildable . foreignLibBuildInfo) (foreignLibs p)
withForeignLib :: PackageDescription -> (ForeignLib -> IO ()) -> IO ()
withForeignLib pkg_descr f =
sequence_ [ f flib
| flib <- foreignLibs pkg_descr
, buildable (foreignLibBuildInfo flib)
]
allBuildInfo :: PackageDescription -> [BuildInfo]
allBuildInfo pkg_descr = [ bi | lib <- allLibraries pkg_descr
, let bi = libBuildInfo lib
, buildable bi ]
++ [ bi | flib <- foreignLibs pkg_descr
, let bi = foreignLibBuildInfo flib
, buildable bi ]
++ [ bi | exe <- executables pkg_descr
, let bi = buildInfo exe
, buildable bi ]
++ [ bi | tst <- testSuites pkg_descr
, let bi = testBuildInfo tst
, buildable bi ]
++ [ bi | tst <- benchmarks pkg_descr
, let bi = benchmarkBuildInfo tst
, buildable bi ]
enabledBuildInfos :: PackageDescription -> ComponentRequestedSpec -> [BuildInfo]
enabledBuildInfos pkg enabled =
[ componentBuildInfo comp
| comp <- enabledComponents pkg enabled ]
updatePackageDescription :: HookedBuildInfo -> PackageDescription -> PackageDescription
updatePackageDescription (mb_lib_bi, exe_bi) p
= p{ executables = updateExecutables exe_bi (executables p)
, library = updateLibrary mb_lib_bi (library p) }
where
updateLibrary :: Maybe BuildInfo -> Maybe Library -> Maybe Library
updateLibrary (Just bi) (Just lib) = Just (lib{libBuildInfo = bi `mappend` libBuildInfo lib})
updateLibrary Nothing mb_lib = mb_lib
updateLibrary (Just _) Nothing = Nothing
updateExecutables :: [(UnqualComponentName, BuildInfo)]
-> [Executable]
-> [Executable]
updateExecutables exe_bi' executables' = foldr updateExecutable executables' exe_bi'
updateExecutable :: (UnqualComponentName, BuildInfo)
-> [Executable]
-> [Executable]
updateExecutable _ [] = []
updateExecutable exe_bi'@(name,bi) (exe:exes)
| exeName exe == name = exe{buildInfo = bi `mappend` buildInfo exe} : exes
| otherwise = exe : updateExecutable exe_bi' exes
pkgComponents :: PackageDescription -> [Component]
pkgComponents pkg =
[ CLib lib | lib <- allLibraries pkg ]
++ [ CFLib flib | flib <- foreignLibs pkg ]
++ [ CExe exe | exe <- executables pkg ]
++ [ CTest tst | tst <- testSuites pkg ]
++ [ CBench bm | bm <- benchmarks pkg ]
pkgBuildableComponents :: PackageDescription -> [Component]
pkgBuildableComponents = filter componentBuildable . pkgComponents
enabledComponents :: PackageDescription -> ComponentRequestedSpec -> [Component]
enabledComponents pkg enabled = filter (componentEnabled enabled) $ pkgBuildableComponents pkg
lookupComponent :: PackageDescription -> ComponentName -> Maybe Component
lookupComponent pkg CLibName = fmap CLib (library pkg)
lookupComponent pkg (CSubLibName name) =
fmap CLib $ find ((Just name ==) . libName) (subLibraries pkg)
lookupComponent pkg (CFLibName name) =
fmap CFLib $ find ((name ==) . foreignLibName) (foreignLibs pkg)
lookupComponent pkg (CExeName name) =
fmap CExe $ find ((name ==) . exeName) (executables pkg)
lookupComponent pkg (CTestName name) =
fmap CTest $ find ((name ==) . testName) (testSuites pkg)
lookupComponent pkg (CBenchName name) =
fmap CBench $ find ((name ==) . benchmarkName) (benchmarks pkg)
getComponent :: PackageDescription -> ComponentName -> Component
getComponent pkg cname =
case lookupComponent pkg cname of
Just cpnt -> cpnt
Nothing -> missingComponent
where
missingComponent =
error $ "internal error: the package description contains no "
++ "component corresponding to " ++ show cname