%
% (c) The University of Glasgow, 2006
%
\begin{code}
module Packages (
module PackageConfig,
PackageConfigMap, emptyPackageConfigMap, lookupPackage,
extendPackageConfigMap, dumpPackages,
PackageState(..),
initPackages,
getPackageDetails,
lookupModuleInAllPackages, lookupModuleWithSuggestions,
getPackageIncludePath,
getPackageLibraryPath,
getPackageLinkOpts,
getPackageExtraCcOpts,
getPackageFrameworkPath,
getPackageFrameworks,
getPreloadPackagesAnd,
collectIncludeDirs, collectLibraryPaths, collectLinkOpts,
packageHsLibs,
isDllName
)
where
#include "HsVersions.h"
import PackageConfig
import DynFlags
import Config ( cProjectVersion )
import Name ( Name, nameModule_maybe )
import UniqFM
import Module
import Util
import Panic
import Outputable
import Maybes
import System.Environment ( getEnv )
import Distribution.InstalledPackageInfo
import Distribution.InstalledPackageInfo.Binary
import Distribution.Package hiding (PackageId,depends)
import FastString
import ErrUtils ( debugTraceMsg, putMsg, MsgDoc )
import Exception
import System.Directory
import System.FilePath as FilePath
import qualified System.FilePath.Posix as FilePath.Posix
import Control.Monad
import Data.Char (isSpace)
import Data.List as List
import Data.Map (Map)
import qualified Data.Map as Map
import qualified FiniteMap as Map
import qualified Data.Set as Set
data PackageState = PackageState {
pkgIdMap :: PackageConfigMap,
preloadPackages :: [PackageId],
moduleToPkgConfAll :: UniqFM [(PackageConfig,Bool)],
installedPackageIdMap :: InstalledPackageIdMap
}
type PackageConfigMap = UniqFM PackageConfig
type InstalledPackageIdMap = Map InstalledPackageId PackageId
type InstalledPackageIndex = Map InstalledPackageId PackageConfig
emptyPackageConfigMap :: PackageConfigMap
emptyPackageConfigMap = emptyUFM
lookupPackage :: PackageConfigMap -> PackageId -> Maybe PackageConfig
lookupPackage = lookupUFM
extendPackageConfigMap
:: PackageConfigMap -> [PackageConfig] -> PackageConfigMap
extendPackageConfigMap pkg_map new_pkgs
= foldl add pkg_map new_pkgs
where add pkg_map p = addToUFM pkg_map (packageConfigId p) p
getPackageDetails :: PackageState -> PackageId -> PackageConfig
getPackageDetails ps pid = expectJust "getPackageDetails" (lookupPackage (pkgIdMap ps) pid)
initPackages :: DynFlags -> IO (DynFlags, [PackageId])
initPackages dflags = do
pkg_db <- case pkgDatabase dflags of
Nothing -> readPackageConfigs dflags
Just db -> return $ setBatchPackageFlags dflags db
(pkg_state, preload, this_pkg)
<- mkPackageState dflags pkg_db [] (thisPackage dflags)
return (dflags{ pkgDatabase = Just pkg_db,
pkgState = pkg_state,
thisPackage = this_pkg },
preload)
readPackageConfigs :: DynFlags -> IO [PackageConfig]
readPackageConfigs dflags = do
let system_conf_refs = [UserPkgConf, GlobalPkgConf]
e_pkg_path <- tryIO (getEnv "GHC_PACKAGE_PATH")
let base_conf_refs = case e_pkg_path of
Left _ -> system_conf_refs
Right path
| null (last cs)
-> map PkgConfFile (init cs) ++ system_conf_refs
| otherwise
-> map PkgConfFile cs
where cs = parseSearchPath path
let conf_refs = reverse (extraPkgConfs dflags base_conf_refs)
confs <- liftM catMaybes $ mapM (resolvePackageConfig dflags) conf_refs
liftM concat $ mapM (readPackageConfig dflags) confs
resolvePackageConfig :: DynFlags -> PkgConfRef -> IO (Maybe FilePath)
resolvePackageConfig dflags GlobalPkgConf = return $ Just (systemPackageConfig dflags)
resolvePackageConfig _ UserPkgConf = handleIO (\_ -> return Nothing) $ do
appdir <- getAppUserDataDirectory "ghc"
let dir = appdir </> (TARGET_ARCH ++ '-':TARGET_OS ++ '-':cProjectVersion)
pkgconf = dir </> "package.conf.d"
exist <- doesDirectoryExist pkgconf
return $ if exist then Just pkgconf else Nothing
resolvePackageConfig _ (PkgConfFile name) = return $ Just name
readPackageConfig :: DynFlags -> FilePath -> IO [PackageConfig]
readPackageConfig dflags conf_file = do
isdir <- doesDirectoryExist conf_file
proto_pkg_configs <-
if isdir
then do let filename = conf_file </> "package.cache"
debugTraceMsg dflags 2 (text "Using binary package database:" <+> text filename)
conf <- readBinPackageDB filename
return (map installedPackageInfoToPackageConfig conf)
else do
isfile <- doesFileExist conf_file
when (not isfile) $
throwGhcExceptionIO $ InstallationError $
"can't find a package database at " ++ conf_file
debugTraceMsg dflags 2 (text "Using package config file:" <+> text conf_file)
str <- readFile conf_file
case reads str of
[(configs, rest)]
| all isSpace rest -> return (map installedPackageInfoToPackageConfig configs)
_ -> throwGhcExceptionIO $ InstallationError $
"invalid package database file " ++ conf_file
let
top_dir = topDir dflags
pkgroot = takeDirectory conf_file
pkg_configs1 = map (mungePackagePaths top_dir pkgroot) proto_pkg_configs
pkg_configs2 = setBatchPackageFlags dflags pkg_configs1
return pkg_configs2
setBatchPackageFlags :: DynFlags -> [PackageConfig] -> [PackageConfig]
setBatchPackageFlags dflags pkgs = (maybeDistrustAll . maybeHideAll) pkgs
where
maybeHideAll pkgs'
| gopt Opt_HideAllPackages dflags = map hide pkgs'
| otherwise = pkgs'
maybeDistrustAll pkgs'
| gopt Opt_DistrustAllPackages dflags = map distrust pkgs'
| otherwise = pkgs'
hide pkg = pkg{ exposed = False }
distrust pkg = pkg{ trusted = False }
mungePackagePaths :: FilePath -> FilePath -> PackageConfig -> PackageConfig
mungePackagePaths top_dir pkgroot pkg =
pkg {
importDirs = munge_paths (importDirs pkg),
includeDirs = munge_paths (includeDirs pkg),
libraryDirs = munge_paths (libraryDirs pkg),
frameworkDirs = munge_paths (frameworkDirs pkg),
haddockInterfaces = munge_paths (haddockInterfaces pkg),
haddockHTMLs = munge_urls (haddockHTMLs pkg)
}
where
munge_paths = map munge_path
munge_urls = map munge_url
munge_path p
| Just p' <- stripVarPrefix "${pkgroot}" p = pkgroot ++ p'
| Just p' <- stripVarPrefix "$topdir" p = top_dir ++ p'
| otherwise = p
munge_url p
| Just p' <- stripVarPrefix "${pkgrooturl}" p = toUrlPath pkgroot p'
| Just p' <- stripVarPrefix "$httptopdir" p = toUrlPath top_dir p'
| otherwise = p
toUrlPath r p = "file:///"
++ FilePath.Posix.joinPath
(r :
dropWhile (all isPathSeparator)
(FilePath.splitDirectories p))
stripVarPrefix var path = case stripPrefix var path of
Just [] -> Just []
Just cs@(c : _) | isPathSeparator c -> Just cs
_ -> Nothing
applyPackageFlag
:: DynFlags
-> UnusablePackages
-> [PackageConfig]
-> PackageFlag
-> IO [PackageConfig]
applyPackageFlag dflags unusable pkgs flag =
case flag of
ExposePackage str ->
case selectPackages (matchingStr str) pkgs unusable of
Left ps -> packageFlagErr dflags flag ps
Right (p:ps,qs) -> return (p':ps')
where p' = p {exposed=True}
ps' = hideAll (pkgName (sourcePackageId p)) (ps++qs)
_ -> panic "applyPackageFlag"
ExposePackageId str ->
case selectPackages (matchingId str) pkgs unusable of
Left ps -> packageFlagErr dflags flag ps
Right (p:ps,qs) -> return (p':ps')
where p' = p {exposed=True}
ps' = hideAll (pkgName (sourcePackageId p)) (ps++qs)
_ -> panic "applyPackageFlag"
HidePackage str ->
case selectPackages (matchingStr str) pkgs unusable of
Left ps -> packageFlagErr dflags flag ps
Right (ps,qs) -> return (map hide ps ++ qs)
where hide p = p {exposed=False}
TrustPackage str ->
case selectPackages (matchingStr str) pkgs unusable of
Left ps -> packageFlagErr dflags flag ps
Right (ps,qs) -> return (map trust ps ++ qs)
where trust p = p {trusted=True}
DistrustPackage str ->
case selectPackages (matchingStr str) pkgs unusable of
Left ps -> packageFlagErr dflags flag ps
Right (ps,qs) -> return (map distrust ps ++ qs)
where distrust p = p {trusted=False}
_ -> panic "applyPackageFlag"
where
hideAll name ps = map maybe_hide ps
where maybe_hide p
| pkgName (sourcePackageId p) == name = p {exposed=False}
| otherwise = p
selectPackages :: (PackageConfig -> Bool) -> [PackageConfig]
-> UnusablePackages
-> Either [(PackageConfig, UnusablePackageReason)]
([PackageConfig], [PackageConfig])
selectPackages matches pkgs unusable
= let
(ps,rest) = partition matches pkgs
reasons = [ (p, Map.lookup (installedPackageId p) unusable)
| p <- ps ]
in
if all (isJust.snd) reasons
then Left [ (p, reason) | (p,Just reason) <- reasons ]
else Right (sortByVersion [ p | (p,Nothing) <- reasons ], rest)
matchingStr :: String -> PackageConfig -> Bool
matchingStr str p
= str == display (sourcePackageId p)
|| str == display (pkgName (sourcePackageId p))
matchingId :: String -> PackageConfig -> Bool
matchingId str p = InstalledPackageId str == installedPackageId p
sortByVersion :: [InstalledPackageInfo_ m] -> [InstalledPackageInfo_ m]
sortByVersion = sortBy (flip (comparing (pkgVersion.sourcePackageId)))
comparing :: Ord a => (t -> a) -> t -> t -> Ordering
comparing f a b = f a `compare` f b
packageFlagErr :: DynFlags
-> PackageFlag
-> [(PackageConfig, UnusablePackageReason)]
-> IO a
packageFlagErr dflags (ExposePackage pkg) [] | is_dph_package pkg
= throwGhcExceptionIO (CmdLineError (showSDoc dflags $ dph_err))
where dph_err = text "the " <> text pkg <> text " package is not installed."
$$ text "To install it: \"cabal install dph\"."
is_dph_package pkg = "dph" `isPrefixOf` pkg
packageFlagErr dflags flag reasons
= throwGhcExceptionIO (CmdLineError (showSDoc dflags $ err))
where err = text "cannot satisfy " <> ppr_flag <>
(if null reasons then empty else text ": ") $$
nest 4 (ppr_reasons $$
text "(use -v for more information)")
ppr_flag = case flag of
IgnorePackage p -> text "-ignore-package " <> text p
HidePackage p -> text "-hide-package " <> text p
ExposePackage p -> text "-package " <> text p
ExposePackageId p -> text "-package-id " <> text p
TrustPackage p -> text "-trust " <> text p
DistrustPackage p -> text "-distrust " <> text p
ppr_reasons = vcat (map ppr_reason reasons)
ppr_reason (p, reason) = pprReason (pprIPkg p <+> text "is") reason
hideOldPackages :: DynFlags -> [PackageConfig] -> IO [PackageConfig]
hideOldPackages dflags pkgs = mapM maybe_hide pkgs
where maybe_hide p
| not (exposed p) = return p
| (p' : _) <- later_versions = do
debugTraceMsg dflags 2 $
(ptext (sLit "hiding package") <+> pprSPkg p <+>
ptext (sLit "to avoid conflict with later version") <+>
pprSPkg p')
return (p {exposed=False})
| otherwise = return p
where myname = pkgName (sourcePackageId p)
myversion = pkgVersion (sourcePackageId p)
later_versions = [ p | p <- pkgs, exposed p,
let pkg = sourcePackageId p,
pkgName pkg == myname,
pkgVersion pkg > myversion ]
findWiredInPackages
:: DynFlags
-> [PackageConfig]
-> IO [PackageConfig]
findWiredInPackages dflags pkgs = do
let
wired_in_pkgids :: [String]
wired_in_pkgids = map packageIdString
[ primPackageId,
integerPackageId,
basePackageId,
rtsPackageId,
thPackageId,
dphSeqPackageId,
dphParPackageId ]
matches :: PackageConfig -> String -> Bool
pc `matches` pid = display (pkgName (sourcePackageId pc)) == pid
findWiredInPackage :: [PackageConfig] -> String
-> IO (Maybe InstalledPackageId)
findWiredInPackage pkgs wired_pkg =
let all_ps = [ p | p <- pkgs, p `matches` wired_pkg ] in
case all_ps of
[] -> notfound
many -> pick (head (sortByVersion many))
where
notfound = do
debugTraceMsg dflags 2 $
ptext (sLit "wired-in package ")
<> text wired_pkg
<> ptext (sLit " not found.")
return Nothing
pick :: InstalledPackageInfo_ ModuleName
-> IO (Maybe InstalledPackageId)
pick pkg = do
debugTraceMsg dflags 2 $
ptext (sLit "wired-in package ")
<> text wired_pkg
<> ptext (sLit " mapped to ")
<> pprIPkg pkg
return (Just (installedPackageId pkg))
mb_wired_in_ids <- mapM (findWiredInPackage pkgs) wired_in_pkgids
let
wired_in_ids = catMaybes mb_wired_in_ids
updateWiredInDependencies pkgs = map upd_pkg pkgs
where upd_pkg p
| installedPackageId p `elem` wired_in_ids
= p { sourcePackageId = (sourcePackageId p){ pkgVersion = Version [] [] } }
| otherwise
= p
return $ updateWiredInDependencies pkgs
data UnusablePackageReason
= IgnoredWithFlag
| MissingDependencies [InstalledPackageId]
| ShadowedBy InstalledPackageId
type UnusablePackages = Map InstalledPackageId UnusablePackageReason
pprReason :: SDoc -> UnusablePackageReason -> SDoc
pprReason pref reason = case reason of
IgnoredWithFlag ->
pref <+> ptext (sLit "ignored due to an -ignore-package flag")
MissingDependencies deps ->
pref <+>
ptext (sLit "unusable due to missing or recursive dependencies:") $$
nest 2 (hsep (map (text.display) deps))
ShadowedBy ipid ->
pref <+> ptext (sLit "shadowed by package ") <> text (display ipid)
reportUnusable :: DynFlags -> UnusablePackages -> IO ()
reportUnusable dflags pkgs = mapM_ report (Map.toList pkgs)
where
report (ipid, reason) =
debugTraceMsg dflags 2 $
pprReason
(ptext (sLit "package") <+>
text (display ipid) <+> text "is") reason
findBroken :: [PackageConfig] -> UnusablePackages
findBroken pkgs = go [] Map.empty pkgs
where
go avail ipids not_avail =
case partitionWith (depsAvailable ipids) not_avail of
([], not_avail) ->
Map.fromList [ (installedPackageId p, MissingDependencies deps)
| (p,deps) <- not_avail ]
(new_avail, not_avail) ->
go (new_avail ++ avail) new_ipids (map fst not_avail)
where new_ipids = Map.insertList
[ (installedPackageId p, p) | p <- new_avail ]
ipids
depsAvailable :: InstalledPackageIndex
-> PackageConfig
-> Either PackageConfig (PackageConfig, [InstalledPackageId])
depsAvailable ipids pkg
| null dangling = Left pkg
| otherwise = Right (pkg, dangling)
where dangling = filter (not . (`Map.member` ipids)) (depends pkg)
shadowPackages :: [PackageConfig] -> [InstalledPackageId] -> UnusablePackages
shadowPackages pkgs preferred
= let (shadowed,_) = foldl check ([],emptyUFM) pkgs
in Map.fromList shadowed
where
check (shadowed,pkgmap) pkg
| Just oldpkg <- lookupUFM pkgmap (packageConfigId pkg)
, let
ipid_new = installedPackageId pkg
ipid_old = installedPackageId oldpkg
, ipid_old /= ipid_new
= if ipid_old `elem` preferred
then ( (ipid_new, ShadowedBy ipid_old) : shadowed, pkgmap )
else ( (ipid_old, ShadowedBy ipid_new) : shadowed, pkgmap' )
| otherwise
= (shadowed, pkgmap')
where
pkgmap' = addToUFM pkgmap (packageConfigId pkg) pkg
ignorePackages :: [PackageFlag] -> [PackageConfig] -> UnusablePackages
ignorePackages flags pkgs = Map.fromList (concatMap doit flags)
where
doit (IgnorePackage str) =
case partition (matchingStr str) pkgs of
(ps, _) -> [ (installedPackageId p, IgnoredWithFlag)
| p <- ps ]
doit _ = panic "ignorePackages"
depClosure :: InstalledPackageIndex
-> [InstalledPackageId]
-> [InstalledPackageId]
depClosure index ipids = closure Map.empty ipids
where
closure set [] = Map.keys set
closure set (ipid : ipids)
| ipid `Map.member` set = closure set ipids
| Just p <- Map.lookup ipid index = closure (Map.insert ipid p set)
(depends p ++ ipids)
| otherwise = closure set ipids
mkPackageState
:: DynFlags
-> [PackageConfig]
-> [PackageId]
-> PackageId
-> IO (PackageState,
[PackageId],
PackageId)
mkPackageState dflags pkgs0 preload0 this_package = do
let
flags = reverse (packageFlags dflags)
pkgs0_unique = snd $ foldr del (Set.empty,[]) pkgs0
where del p (s,ps)
| pid `Set.member` s = (s,ps)
| otherwise = (Set.insert pid s, p:ps)
where pid = installedPackageId p
ipid_map = Map.fromList [ (installedPackageId p, p) | p <- pkgs0 ]
ipid_selected = depClosure ipid_map [ InstalledPackageId i
| ExposePackageId i <- flags ]
(ignore_flags, other_flags) = partition is_ignore flags
is_ignore IgnorePackage{} = True
is_ignore _ = False
shadowed = shadowPackages pkgs0_unique ipid_selected
ignored = ignorePackages ignore_flags pkgs0_unique
pkgs0' = filter (not . (`Map.member` (Map.union shadowed ignored)) . installedPackageId) pkgs0_unique
broken = findBroken pkgs0'
unusable = shadowed `Map.union` ignored `Map.union` broken
reportUnusable dflags unusable
pkgs1 <- foldM (applyPackageFlag dflags unusable) pkgs0_unique other_flags
let pkgs2 = filter (not . (`Map.member` unusable) . installedPackageId) pkgs1
let preload1 = [ installedPackageId p | f <- flags, p <- get_exposed f ]
get_exposed (ExposePackage s)
= take 1 $ sortByVersion (filter (matchingStr s) pkgs2)
get_exposed (ExposePackageId s) = filter (matchingId s) pkgs2
get_exposed _ = []
pkgs3 <- hideOldPackages dflags pkgs2
pkgs4 <- findWiredInPackages dflags pkgs3
let pkg_db = extendPackageConfigMap emptyPackageConfigMap pkgs4
ipid_map = Map.fromList [ (installedPackageId p, packageConfigId p)
| p <- pkgs4 ]
lookupIPID ipid@(InstalledPackageId str)
| Just pid <- Map.lookup ipid ipid_map = return pid
| otherwise = missingPackageErr dflags str
preload2 <- mapM lookupIPID preload1
let
basicLinkedPackages
| gopt Opt_AutoLinkPackages dflags
= filter (flip elemUFM pkg_db) [basePackageId, rtsPackageId]
| otherwise = []
preload3 = nub $ filter (/= this_package)
$ (basicLinkedPackages ++ preload2)
dep_preload <- closeDeps dflags pkg_db ipid_map (zip preload3 (repeat Nothing))
let new_dep_preload = filter (`notElem` preload0) dep_preload
let pstate = PackageState{ preloadPackages = dep_preload,
pkgIdMap = pkg_db,
moduleToPkgConfAll = mkModuleMap pkg_db,
installedPackageIdMap = ipid_map
}
return (pstate, new_dep_preload, this_package)
mkModuleMap
:: PackageConfigMap
-> UniqFM [(PackageConfig, Bool)]
mkModuleMap pkg_db = foldr extend_modmap emptyUFM pkgids
where
pkgids = map packageConfigId (eltsUFM pkg_db)
extend_modmap pkgid modmap =
addListToUFM_C (++) modmap
([(m, [(pkg, True)]) | m <- exposed_mods] ++
[(m, [(pkg, False)]) | m <- hidden_mods])
where
pkg = expectJust "mkModuleMap" (lookupPackage pkg_db pkgid)
exposed_mods = exposedModules pkg
hidden_mods = hiddenModules pkg
pprSPkg :: PackageConfig -> SDoc
pprSPkg p = text (display (sourcePackageId p))
pprIPkg :: PackageConfig -> SDoc
pprIPkg p = text (display (installedPackageId p))
getPackageIncludePath :: DynFlags -> [PackageId] -> IO [String]
getPackageIncludePath dflags pkgs =
collectIncludeDirs `fmap` getPreloadPackagesAnd dflags pkgs
collectIncludeDirs :: [PackageConfig] -> [FilePath]
collectIncludeDirs ps = nub (filter notNull (concatMap includeDirs ps))
getPackageLibraryPath :: DynFlags -> [PackageId] -> IO [String]
getPackageLibraryPath dflags pkgs =
collectLibraryPaths `fmap` getPreloadPackagesAnd dflags pkgs
collectLibraryPaths :: [PackageConfig] -> [FilePath]
collectLibraryPaths ps = nub (filter notNull (concatMap libraryDirs ps))
getPackageLinkOpts :: DynFlags -> [PackageId] -> IO ([String], [String], [String])
getPackageLinkOpts dflags pkgs =
collectLinkOpts dflags `fmap` getPreloadPackagesAnd dflags pkgs
collectLinkOpts :: DynFlags -> [PackageConfig] -> ([String], [String], [String])
collectLinkOpts dflags ps =
(
concatMap (map ("-l" ++) . packageHsLibs dflags) ps,
concatMap (map ("-l" ++) . extraLibraries) ps,
concatMap ldOptions ps
)
packageHsLibs :: DynFlags -> PackageConfig -> [String]
packageHsLibs dflags p = map (mkDynName . addSuffix) (hsLibraries p)
where
ways0 = ways dflags
ways1 = filter (/= WayDyn) ways0
ways2 | WayDebug `elem` ways1
= filter (/= WayEventLog) ways1
| otherwise
= ways1
tag = mkBuildTag (filter (not . wayRTSOnly) ways2)
rts_tag = mkBuildTag ways2
mkDynName x
| gopt Opt_Static dflags = x
| "HS" `isPrefixOf` x = x ++ "-ghc" ++ cProjectVersion
| Just x' <- stripPrefix "C" x = x'
| otherwise
= panic ("Don't understand library name " ++ x)
addSuffix rts@"HSrts" = rts ++ (expandTag rts_tag)
addSuffix other_lib = other_lib ++ (expandTag tag)
expandTag t | null t = ""
| otherwise = '_':t
getPackageExtraCcOpts :: DynFlags -> [PackageId] -> IO [String]
getPackageExtraCcOpts dflags pkgs = do
ps <- getPreloadPackagesAnd dflags pkgs
return (concatMap ccOptions ps)
getPackageFrameworkPath :: DynFlags -> [PackageId] -> IO [String]
getPackageFrameworkPath dflags pkgs = do
ps <- getPreloadPackagesAnd dflags pkgs
return (nub (filter notNull (concatMap frameworkDirs ps)))
getPackageFrameworks :: DynFlags -> [PackageId] -> IO [String]
getPackageFrameworks dflags pkgs = do
ps <- getPreloadPackagesAnd dflags pkgs
return (concatMap frameworks ps)
lookupModuleInAllPackages :: DynFlags -> ModuleName -> [(PackageConfig,Bool)]
lookupModuleInAllPackages dflags m
= case lookupModuleWithSuggestions dflags m of
Right pbs -> pbs
Left _ -> []
lookupModuleWithSuggestions
:: DynFlags -> ModuleName
-> Either [Module] [(PackageConfig,Bool)]
lookupModuleWithSuggestions dflags m
= case lookupUFM (moduleToPkgConfAll pkg_state) m of
Nothing -> Left suggestions
Just ps -> Right ps
where
pkg_state = pkgState dflags
suggestions
| gopt Opt_HelpfulErrors dflags = fuzzyLookup (moduleNameString m) all_mods
| otherwise = []
all_mods :: [(String, Module)]
all_mods = [ (moduleNameString mod_nm, mkModule pkg_id mod_nm)
| pkg_config <- eltsUFM (pkgIdMap pkg_state)
, let pkg_id = packageConfigId pkg_config
, mod_nm <- exposedModules pkg_config ]
getPreloadPackagesAnd :: DynFlags -> [PackageId] -> IO [PackageConfig]
getPreloadPackagesAnd dflags pkgids =
let
state = pkgState dflags
pkg_map = pkgIdMap state
ipid_map = installedPackageIdMap state
preload = preloadPackages state
pairs = zip pkgids (repeat Nothing)
in do
all_pkgs <- throwErr dflags (foldM (add_package pkg_map ipid_map) preload pairs)
return (map (getPackageDetails state) all_pkgs)
closeDeps :: DynFlags
-> PackageConfigMap
-> Map InstalledPackageId PackageId
-> [(PackageId, Maybe PackageId)]
-> IO [PackageId]
closeDeps dflags pkg_map ipid_map ps
= throwErr dflags (closeDepsErr pkg_map ipid_map ps)
throwErr :: DynFlags -> MaybeErr MsgDoc a -> IO a
throwErr dflags m
= case m of
Failed e -> throwGhcExceptionIO (CmdLineError (showSDoc dflags e))
Succeeded r -> return r
closeDepsErr :: PackageConfigMap
-> Map InstalledPackageId PackageId
-> [(PackageId,Maybe PackageId)]
-> MaybeErr MsgDoc [PackageId]
closeDepsErr pkg_map ipid_map ps = foldM (add_package pkg_map ipid_map) [] ps
add_package :: PackageConfigMap
-> Map InstalledPackageId PackageId
-> [PackageId]
-> (PackageId,Maybe PackageId)
-> MaybeErr MsgDoc [PackageId]
add_package pkg_db ipid_map ps (p, mb_parent)
| p `elem` ps = return ps
| otherwise =
case lookupPackage pkg_db p of
Nothing -> Failed (missingPackageMsg (packageIdString p) <>
missingDependencyMsg mb_parent)
Just pkg -> do
ps' <- foldM add_package_ipid ps (depends pkg)
return (p : ps')
where
add_package_ipid ps ipid@(InstalledPackageId str)
| Just pid <- Map.lookup ipid ipid_map
= add_package pkg_db ipid_map ps (pid, Just p)
| otherwise
= Failed (missingPackageMsg str <> missingDependencyMsg mb_parent)
missingPackageErr :: DynFlags -> String -> IO a
missingPackageErr dflags p
= throwGhcExceptionIO (CmdLineError (showSDoc dflags (missingPackageMsg p)))
missingPackageMsg :: String -> SDoc
missingPackageMsg p = ptext (sLit "unknown package:") <+> text p
missingDependencyMsg :: Maybe PackageId -> SDoc
missingDependencyMsg Nothing = empty
missingDependencyMsg (Just parent)
= space <> parens (ptext (sLit "dependency of") <+> ftext (packageIdFS parent))
isDllName :: DynFlags -> PackageId -> Module -> Name -> Bool
isDllName dflags this_pkg this_mod name
| gopt Opt_Static dflags = False
| Just mod <- nameModule_maybe name
= if modulePackageId mod /= this_pkg
then True
else case dllSplit dflags of
Nothing -> False
Just ss ->
let findMod m = let modStr = moduleNameString (moduleName m)
in case find (modStr `Set.member`) ss of
Just i -> i
Nothing -> panic ("Can't find " ++ modStr ++ "in DLL split")
in findMod mod /= findMod this_mod
| otherwise = False
dumpPackages :: DynFlags -> IO ()
dumpPackages dflags
= do let pkg_map = pkgIdMap (pkgState dflags)
putMsg dflags $
vcat (map (text . showInstalledPackageInfo
. packageConfigToInstalledPackageInfo)
(eltsUFM pkg_map))
\end{code}