{-# LANGUAGE CPP, RecordWildCards, FlexibleInstances, MultiParamTypeClasses #-}

-- |
-- Package configuration information: essentially the interface to Cabal, with
-- some utilities
--
-- (c) The University of Glasgow, 2004
--
module PackageConfig (
        -- $package_naming

        -- * UnitId
        packageConfigId,
        expandedPackageConfigId,
        definitePackageConfigId,
        installedPackageConfigId,

        -- * The PackageConfig type: information about a package
        PackageConfig,
        InstalledPackageInfo(..),
        ComponentId(..),
        SourcePackageId(..),
        PackageName(..),
        Version(..),
        defaultPackageConfig,
        sourcePackageIdString,
        packageNameString,
        pprPackageConfig,
    ) where

#include "HsVersions.h"

import GhcPrelude

import GHC.PackageDb
import Data.Version

import FastString
import Outputable
import Module
import Unique

-- -----------------------------------------------------------------------------
-- Our PackageConfig type is the InstalledPackageInfo from ghc-boot,
-- which is similar to a subset of the InstalledPackageInfo type from Cabal.

type PackageConfig = InstalledPackageInfo
                       ComponentId
                       SourcePackageId
                       PackageName
                       Module.InstalledUnitId
                       Module.UnitId
                       Module.ModuleName
                       Module.Module

-- TODO: there's no need for these to be FastString, as we don't need the uniq
--       feature, but ghc doesn't currently have convenient support for any
--       other compact string types, e.g. plain ByteString or Text.

newtype SourcePackageId    = SourcePackageId    FastString deriving (SourcePackageId -> SourcePackageId -> Bool
(SourcePackageId -> SourcePackageId -> Bool)
-> (SourcePackageId -> SourcePackageId -> Bool)
-> Eq SourcePackageId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SourcePackageId -> SourcePackageId -> Bool
$c/= :: SourcePackageId -> SourcePackageId -> Bool
== :: SourcePackageId -> SourcePackageId -> Bool
$c== :: SourcePackageId -> SourcePackageId -> Bool
Eq, Eq SourcePackageId
Eq SourcePackageId =>
(SourcePackageId -> SourcePackageId -> Ordering)
-> (SourcePackageId -> SourcePackageId -> Bool)
-> (SourcePackageId -> SourcePackageId -> Bool)
-> (SourcePackageId -> SourcePackageId -> Bool)
-> (SourcePackageId -> SourcePackageId -> Bool)
-> (SourcePackageId -> SourcePackageId -> SourcePackageId)
-> (SourcePackageId -> SourcePackageId -> SourcePackageId)
-> Ord SourcePackageId
SourcePackageId -> SourcePackageId -> Bool
SourcePackageId -> SourcePackageId -> Ordering
SourcePackageId -> SourcePackageId -> SourcePackageId
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SourcePackageId -> SourcePackageId -> SourcePackageId
$cmin :: SourcePackageId -> SourcePackageId -> SourcePackageId
max :: SourcePackageId -> SourcePackageId -> SourcePackageId
$cmax :: SourcePackageId -> SourcePackageId -> SourcePackageId
>= :: SourcePackageId -> SourcePackageId -> Bool
$c>= :: SourcePackageId -> SourcePackageId -> Bool
> :: SourcePackageId -> SourcePackageId -> Bool
$c> :: SourcePackageId -> SourcePackageId -> Bool
<= :: SourcePackageId -> SourcePackageId -> Bool
$c<= :: SourcePackageId -> SourcePackageId -> Bool
< :: SourcePackageId -> SourcePackageId -> Bool
$c< :: SourcePackageId -> SourcePackageId -> Bool
compare :: SourcePackageId -> SourcePackageId -> Ordering
$ccompare :: SourcePackageId -> SourcePackageId -> Ordering
$cp1Ord :: Eq SourcePackageId
Ord)
newtype PackageName        = PackageName        FastString deriving (PackageName -> PackageName -> Bool
(PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> Bool) -> Eq PackageName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PackageName -> PackageName -> Bool
$c/= :: PackageName -> PackageName -> Bool
== :: PackageName -> PackageName -> Bool
$c== :: PackageName -> PackageName -> Bool
Eq, Eq PackageName
Eq PackageName =>
(PackageName -> PackageName -> Ordering)
-> (PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> Bool)
-> (PackageName -> PackageName -> PackageName)
-> (PackageName -> PackageName -> PackageName)
-> Ord PackageName
PackageName -> PackageName -> Bool
PackageName -> PackageName -> Ordering
PackageName -> PackageName -> PackageName
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: PackageName -> PackageName -> PackageName
$cmin :: PackageName -> PackageName -> PackageName
max :: PackageName -> PackageName -> PackageName
$cmax :: PackageName -> PackageName -> PackageName
>= :: PackageName -> PackageName -> Bool
$c>= :: PackageName -> PackageName -> Bool
> :: PackageName -> PackageName -> Bool
$c> :: PackageName -> PackageName -> Bool
<= :: PackageName -> PackageName -> Bool
$c<= :: PackageName -> PackageName -> Bool
< :: PackageName -> PackageName -> Bool
$c< :: PackageName -> PackageName -> Bool
compare :: PackageName -> PackageName -> Ordering
$ccompare :: PackageName -> PackageName -> Ordering
$cp1Ord :: Eq PackageName
Ord)

instance BinaryStringRep SourcePackageId where
  fromStringRep :: ByteString -> SourcePackageId
fromStringRep = FastString -> SourcePackageId
SourcePackageId (FastString -> SourcePackageId)
-> (ByteString -> FastString) -> ByteString -> SourcePackageId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> FastString
mkFastStringByteString
  toStringRep :: SourcePackageId -> ByteString
toStringRep (SourcePackageId s :: FastString
s) = FastString -> ByteString
fastStringToByteString FastString
s

instance BinaryStringRep PackageName where
  fromStringRep :: ByteString -> PackageName
fromStringRep = FastString -> PackageName
PackageName (FastString -> PackageName)
-> (ByteString -> FastString) -> ByteString -> PackageName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> FastString
mkFastStringByteString
  toStringRep :: PackageName -> ByteString
toStringRep (PackageName s :: FastString
s) = FastString -> ByteString
fastStringToByteString FastString
s

instance Uniquable SourcePackageId where
  getUnique :: SourcePackageId -> Unique
getUnique (SourcePackageId n :: FastString
n) = FastString -> Unique
forall a. Uniquable a => a -> Unique
getUnique FastString
n

instance Uniquable PackageName where
  getUnique :: PackageName -> Unique
getUnique (PackageName n :: FastString
n) = FastString -> Unique
forall a. Uniquable a => a -> Unique
getUnique FastString
n

instance Outputable SourcePackageId where
  ppr :: SourcePackageId -> SDoc
ppr (SourcePackageId str :: FastString
str) = FastString -> SDoc
ftext FastString
str

instance Outputable PackageName where
  ppr :: PackageName -> SDoc
ppr (PackageName str :: FastString
str) = FastString -> SDoc
ftext FastString
str

defaultPackageConfig :: PackageConfig
defaultPackageConfig :: PackageConfig
defaultPackageConfig = PackageConfig
forall a b c d e f g.
RepInstalledPackageInfo a b c d e f g =>
InstalledPackageInfo a b c d e f g
emptyInstalledPackageInfo

sourcePackageIdString :: PackageConfig -> String
sourcePackageIdString :: PackageConfig -> String
sourcePackageIdString pkg :: PackageConfig
pkg = FastString -> String
unpackFS FastString
str
  where
    SourcePackageId str :: FastString
str = PackageConfig -> SourcePackageId
forall compid srcpkgid srcpkgname instunitid unitid modulename mod.
InstalledPackageInfo
  compid srcpkgid srcpkgname instunitid unitid modulename mod
-> srcpkgid
sourcePackageId PackageConfig
pkg

packageNameString :: PackageConfig -> String
packageNameString :: PackageConfig -> String
packageNameString pkg :: PackageConfig
pkg = FastString -> String
unpackFS FastString
str
  where
    PackageName str :: FastString
str = PackageConfig -> PackageName
forall compid srcpkgid srcpkgname instunitid unitid modulename mod.
InstalledPackageInfo
  compid srcpkgid srcpkgname instunitid unitid modulename mod
-> srcpkgname
packageName PackageConfig
pkg

pprPackageConfig :: PackageConfig -> SDoc
pprPackageConfig :: PackageConfig -> SDoc
pprPackageConfig InstalledPackageInfo {..} =
    [SDoc] -> SDoc
vcat [
      String -> SDoc -> SDoc
field "name"                 (PackageName -> SDoc
forall a. Outputable a => a -> SDoc
ppr PackageName
packageName),
      String -> SDoc -> SDoc
field "version"              (String -> SDoc
text (Version -> String
showVersion Version
packageVersion)),
      String -> SDoc -> SDoc
field "id"                   (InstalledUnitId -> SDoc
forall a. Outputable a => a -> SDoc
ppr InstalledUnitId
unitId),
      String -> SDoc -> SDoc
field "exposed"              (Bool -> SDoc
forall a. Outputable a => a -> SDoc
ppr Bool
exposed),
      String -> SDoc -> SDoc
field "exposed-modules"      ([(ModuleName, Maybe Module)] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [(ModuleName, Maybe Module)]
exposedModules),
      String -> SDoc -> SDoc
field "hidden-modules"       ([SDoc] -> SDoc
fsep ((ModuleName -> SDoc) -> [ModuleName] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map ModuleName -> SDoc
forall a. Outputable a => a -> SDoc
ppr [ModuleName]
hiddenModules)),
      String -> SDoc -> SDoc
field "trusted"              (Bool -> SDoc
forall a. Outputable a => a -> SDoc
ppr Bool
trusted),
      String -> SDoc -> SDoc
field "import-dirs"          ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
importDirs)),
      String -> SDoc -> SDoc
field "library-dirs"         ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
libraryDirs)),
      String -> SDoc -> SDoc
field "dynamic-library-dirs" ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
libraryDynDirs)),
      String -> SDoc -> SDoc
field "hs-libraries"         ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
hsLibraries)),
      String -> SDoc -> SDoc
field "extra-libraries"      ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
extraLibraries)),
      String -> SDoc -> SDoc
field "extra-ghci-libraries" ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
extraGHCiLibraries)),
      String -> SDoc -> SDoc
field "include-dirs"         ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
includeDirs)),
      String -> SDoc -> SDoc
field "includes"             ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
includes)),
      String -> SDoc -> SDoc
field "depends"              ([SDoc] -> SDoc
fsep ((InstalledUnitId -> SDoc) -> [InstalledUnitId] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map InstalledUnitId -> SDoc
forall a. Outputable a => a -> SDoc
ppr  [InstalledUnitId]
depends)),
      String -> SDoc -> SDoc
field "cc-options"           ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
ccOptions)),
      String -> SDoc -> SDoc
field "ld-options"           ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
ldOptions)),
      String -> SDoc -> SDoc
field "framework-dirs"       ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
frameworkDirs)),
      String -> SDoc -> SDoc
field "frameworks"           ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
frameworks)),
      String -> SDoc -> SDoc
field "haddock-interfaces"   ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
haddockInterfaces)),
      String -> SDoc -> SDoc
field "haddock-html"         ([SDoc] -> SDoc
fsep ((String -> SDoc) -> [String] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map String -> SDoc
text [String]
haddockHTMLs))
    ]
  where
    field :: String -> SDoc -> SDoc
field name :: String
name body :: SDoc
body = String -> SDoc
text String
name SDoc -> SDoc -> SDoc
<> SDoc
colon SDoc -> SDoc -> SDoc
<+> Int -> SDoc -> SDoc
nest 4 SDoc
body

-- -----------------------------------------------------------------------------
-- UnitId (package names, versions and dep hash)

-- $package_naming
-- #package_naming#
-- Mostly the compiler deals in terms of 'UnitId's, which are md5 hashes
-- of a package ID, keys of its dependencies, and Cabal flags. You're expected
-- to pass in the unit id in the @-this-unit-id@ flag. However, for
-- wired-in packages like @base@ & @rts@, we don't necessarily know what the
-- version is, so these are handled specially; see #wired_in_packages#.

-- | Get the GHC 'UnitId' right out of a Cabalish 'PackageConfig'
installedPackageConfigId :: PackageConfig -> InstalledUnitId
installedPackageConfigId :: PackageConfig -> InstalledUnitId
installedPackageConfigId = PackageConfig -> InstalledUnitId
forall compid srcpkgid srcpkgname instunitid unitid modulename mod.
InstalledPackageInfo
  compid srcpkgid srcpkgname instunitid unitid modulename mod
-> instunitid
unitId

packageConfigId :: PackageConfig -> UnitId
packageConfigId :: PackageConfig -> UnitId
packageConfigId p :: PackageConfig
p =
    if PackageConfig -> Bool
forall compid srcpkgid srcpkgname instunitid unitid modulename mod.
InstalledPackageInfo
  compid srcpkgid srcpkgname instunitid unitid modulename mod
-> Bool
indefinite PackageConfig
p
        then ComponentId -> [(ModuleName, Module)] -> UnitId
newUnitId (PackageConfig -> ComponentId
forall compid srcpkgid srcpkgname instunitid unitid modulename mod.
InstalledPackageInfo
  compid srcpkgid srcpkgname instunitid unitid modulename mod
-> compid
componentId PackageConfig
p) (PackageConfig -> [(ModuleName, Module)]
forall compid srcpkgid srcpkgname instunitid unitid modulename mod.
InstalledPackageInfo
  compid srcpkgid srcpkgname instunitid unitid modulename mod
-> [(modulename, mod)]
instantiatedWith PackageConfig
p)
        else DefUnitId -> UnitId
DefiniteUnitId (InstalledUnitId -> DefUnitId
DefUnitId (PackageConfig -> InstalledUnitId
forall compid srcpkgid srcpkgname instunitid unitid modulename mod.
InstalledPackageInfo
  compid srcpkgid srcpkgname instunitid unitid modulename mod
-> instunitid
unitId PackageConfig
p))

expandedPackageConfigId :: PackageConfig -> UnitId
expandedPackageConfigId :: PackageConfig -> UnitId
expandedPackageConfigId p :: PackageConfig
p =
    ComponentId -> [(ModuleName, Module)] -> UnitId
newUnitId (PackageConfig -> ComponentId
forall compid srcpkgid srcpkgname instunitid unitid modulename mod.
InstalledPackageInfo
  compid srcpkgid srcpkgname instunitid unitid modulename mod
-> compid
componentId PackageConfig
p) (PackageConfig -> [(ModuleName, Module)]
forall compid srcpkgid srcpkgname instunitid unitid modulename mod.
InstalledPackageInfo
  compid srcpkgid srcpkgname instunitid unitid modulename mod
-> [(modulename, mod)]
instantiatedWith PackageConfig
p)

definitePackageConfigId :: PackageConfig -> Maybe DefUnitId
definitePackageConfigId :: PackageConfig -> Maybe DefUnitId
definitePackageConfigId p :: PackageConfig
p =
    case PackageConfig -> UnitId
packageConfigId PackageConfig
p of
        DefiniteUnitId def_uid :: DefUnitId
def_uid -> DefUnitId -> Maybe DefUnitId
forall a. a -> Maybe a
Just DefUnitId
def_uid
        _ -> Maybe DefUnitId
forall a. Maybe a
Nothing