module GHC.Unit.Info
( GenericUnitInfo (..)
, GenUnitInfo
, UnitInfo
, UnitKey (..)
, UnitKeyInfo
, mkUnitKeyInfo
, mapUnitInfo
, mkUnitPprInfo
, mkUnit
, PackageId(..)
, PackageName(..)
, Version(..)
, unitPackageNameString
, unitPackageIdString
, pprUnitInfo
, collectIncludeDirs
, collectExtraCcOpts
, collectLibraryDirs
, collectFrameworks
, collectFrameworksDirs
, unitHsLibs
)
where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Platform.Ways
import GHC.Utils.Misc
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Types.Unique
import GHC.Data.FastString
import qualified GHC.Data.ShortText as ST
import GHC.Unit.Module as Module
import GHC.Unit.Ppr
import GHC.Unit.Database
import GHC.Settings
import Data.Version
import Data.Bifunctor
import Data.List (isPrefixOf, stripPrefix)
import qualified Data.Set as Set
type GenUnitInfo unit = GenericUnitInfo (Indefinite unit) PackageId PackageName unit ModuleName (GenModule (GenUnit unit))
type UnitKeyInfo = GenUnitInfo UnitKey
type UnitInfo = GenUnitInfo UnitId
mkUnitKeyInfo :: DbUnitInfo -> UnitKeyInfo
mkUnitKeyInfo = mapGenericUnitInfo
mkUnitKey'
mkIndefUnitKey'
mkPackageIdentifier'
mkPackageName'
mkModuleName'
mkModule'
where
mkPackageIdentifier' = PackageId . mkFastStringByteString
mkPackageName' = PackageName . mkFastStringByteString
mkUnitKey' = UnitKey . mkFastStringByteString
mkModuleName' = mkModuleNameFS . mkFastStringByteString
mkIndefUnitKey' cid = Indefinite (mkUnitKey' cid)
mkVirtUnitKey' i = case i of
DbInstUnitId cid insts -> mkVirtUnit (mkIndefUnitKey' cid) (fmap (bimap mkModuleName' mkModule') insts)
DbUnitId uid -> RealUnit (Definite (mkUnitKey' uid))
mkModule' m = case m of
DbModule uid n -> mkModule (mkVirtUnitKey' uid) (mkModuleName' n)
DbModuleVar n -> mkHoleModule (mkModuleName' n)
mapUnitInfo :: IsUnitId v => (u -> v) -> GenUnitInfo u -> GenUnitInfo v
mapUnitInfo f = mapGenericUnitInfo
f
(fmap f)
id
id
id
(fmap (mapGenUnit f))
newtype PackageId = PackageId FastString deriving (Eq)
newtype PackageName = PackageName
{ unPackageName :: FastString
}
deriving (Eq)
instance Uniquable PackageId where
getUnique (PackageId n) = getUnique n
instance Uniquable PackageName where
getUnique (PackageName n) = getUnique n
instance Outputable PackageId where
ppr (PackageId str) = ftext str
instance Outputable PackageName where
ppr (PackageName str) = ftext str
unitPackageIdString :: GenUnitInfo u -> String
unitPackageIdString pkg = unpackFS str
where
PackageId str = unitPackageId pkg
unitPackageNameString :: GenUnitInfo u -> String
unitPackageNameString pkg = unpackFS str
where
PackageName str = unitPackageName pkg
pprUnitInfo :: UnitInfo -> SDoc
pprUnitInfo GenericUnitInfo {..} =
vcat [
field "name" (ppr unitPackageName),
field "version" (text (showVersion unitPackageVersion)),
field "id" (ppr unitId),
field "exposed" (ppr unitIsExposed),
field "exposed-modules" (ppr unitExposedModules),
field "hidden-modules" (fsep (map ppr unitHiddenModules)),
field "trusted" (ppr unitIsTrusted),
field "import-dirs" (fsep (map (text . ST.unpack) unitImportDirs)),
field "library-dirs" (fsep (map (text . ST.unpack) unitLibraryDirs)),
field "dynamic-library-dirs" (fsep (map (text . ST.unpack) unitLibraryDynDirs)),
field "hs-libraries" (fsep (map (text . ST.unpack) unitLibraries)),
field "extra-libraries" (fsep (map (text . ST.unpack) unitExtDepLibsSys)),
field "extra-ghci-libraries" (fsep (map (text . ST.unpack) unitExtDepLibsGhc)),
field "include-dirs" (fsep (map (text . ST.unpack) unitIncludeDirs)),
field "includes" (fsep (map (text . ST.unpack) unitIncludes)),
field "depends" (fsep (map ppr unitDepends)),
field "cc-options" (fsep (map (text . ST.unpack) unitCcOptions)),
field "ld-options" (fsep (map (text . ST.unpack) unitLinkerOptions)),
field "framework-dirs" (fsep (map (text . ST.unpack) unitExtDepFrameworkDirs)),
field "frameworks" (fsep (map (text . ST.unpack) unitExtDepFrameworks)),
field "haddock-interfaces" (fsep (map (text . ST.unpack) unitHaddockInterfaces)),
field "haddock-html" (fsep (map (text . ST.unpack) unitHaddockHTMLs))
]
where
field name body = text name <> colon <+> nest 4 body
mkUnit :: UnitInfo -> Unit
mkUnit p
| unitIsIndefinite p = mkVirtUnit (unitInstanceOf p) (unitInstantiations p)
| otherwise = RealUnit (Definite (unitId p))
mkUnitPprInfo :: (u -> FastString) -> GenUnitInfo u -> UnitPprInfo
mkUnitPprInfo ufs i = UnitPprInfo
(ufs (unitId i))
(unitPackageNameString i)
(unitPackageVersion i)
((unpackFS . unPackageName) <$> unitComponentName i)
collectIncludeDirs :: [UnitInfo] -> [FilePath]
collectIncludeDirs ps = map ST.unpack $ ordNub (filter (not . ST.null) (concatMap unitIncludeDirs ps))
collectExtraCcOpts :: [UnitInfo] -> [String]
collectExtraCcOpts ps = map ST.unpack (concatMap unitCcOptions ps)
collectLibraryDirs :: Ways -> [UnitInfo] -> [FilePath]
collectLibraryDirs ws = ordNub . filter notNull . concatMap (libraryDirsForWay ws)
collectFrameworks :: [UnitInfo] -> [String]
collectFrameworks ps = map ST.unpack (concatMap unitExtDepFrameworks ps)
collectFrameworksDirs :: [UnitInfo] -> [String]
collectFrameworksDirs ps = map ST.unpack (ordNub (filter (not . ST.null) (concatMap unitExtDepFrameworkDirs ps)))
libraryDirsForWay :: Ways -> UnitInfo -> [String]
libraryDirsForWay ws
| WayDyn `elem` ws = map ST.unpack . unitLibraryDynDirs
| otherwise = map ST.unpack . unitLibraryDirs
unitHsLibs :: GhcNameVersion -> Ways -> UnitInfo -> [String]
unitHsLibs namever ways0 p = map (mkDynName . addSuffix . ST.unpack) (unitLibraries p)
where
ways1 = Set.filter (/= WayDyn) ways0
ways2 | WayDebug `Set.member` ways1 || WayProf `Set.member` ways1
= Set.filter (/= WayTracing) ways1
| otherwise
= ways1
tag = waysTag (fullWays ways2)
rts_tag = waysTag ways2
mkDynName x
| not (ways0 `hasWay` WayDyn) = x
| "HS" `isPrefixOf` x = x ++ dynLibSuffix namever
| Just x' <- stripPrefix "C" x = x'
| otherwise
= panic ("Don't understand library name " ++ x)
addSuffix rts@"HSrts" = rts ++ (expandTag rts_tag)
addSuffix rts@"HSrts-1.0.1" = rts ++ (expandTag rts_tag)
addSuffix other_lib = other_lib ++ (expandTag tag)
expandTag t | null t = ""
| otherwise = '_':t