summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2020-05-19 16:04:57 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-06-13 02:13:03 -0400
commitfca2d25ff76d442d0825847643ed7448492e0e55 (patch)
tree3138fb3fb6d56f66ec39e7dcefb6ec2d6fe180df /compiler
parent8408d521a67e2af4012d886d6a7e2af02ce42add (diff)
downloadhaskell-fca2d25ff76d442d0825847643ed7448492e0e55.tar.gz
DynFlags: add UnitConfig datatype
Avoid directly querying flags from DynFlags to build the UnitState. Instead go via UnitConfig so that we could reuse this to make another UnitState for plugins.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/GHC.hs6
-rw-r--r--compiler/GHC/Driver/Session.hs12
-rw-r--r--compiler/GHC/Unit/State.hs284
3 files changed, 182 insertions, 120 deletions
diff --git a/compiler/GHC.hs b/compiler/GHC.hs
index 1aebb96c0f..9f9f2ad758 100644
--- a/compiler/GHC.hs
+++ b/compiler/GHC.hs
@@ -1677,9 +1677,11 @@ interpretPackageEnv dflags = do
where
-- Loading environments (by name or by location)
+ platformArchOs = platformMini (targetPlatform dflags)
+
namedEnvPath :: String -> MaybeT IO FilePath
namedEnvPath name = do
- appdir <- versionedAppDir dflags
+ appdir <- versionedAppDir (programName dflags) platformArchOs
return $ appdir </> "environments" </> name
probeEnvName :: String -> MaybeT IO FilePath
@@ -1716,7 +1718,7 @@ interpretPackageEnv dflags = do
-- e.g. .ghc.environment.x86_64-linux-7.6.3
localEnvFileName :: FilePath
- localEnvFileName = ".ghc.environment" <.> versionedFilePath dflags
+ localEnvFileName = ".ghc.environment" <.> versionedFilePath platformArchOs
-- Search for an env file, starting in the current dir and looking upwards.
-- Fail if we get to the users home dir or the filesystem root. That is,
diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs
index d363eb2410..16de0ee89a 100644
--- a/compiler/GHC/Driver/Session.hs
+++ b/compiler/GHC/Driver/Session.hs
@@ -1005,14 +1005,14 @@ tablesNextToCode = platformMisc_tablesNextToCode . platformMisc
-- | The directory for this version of ghc in the user's app directory
-- (typically something like @~/.ghc/x86_64-linux-7.6.3@)
--
-versionedAppDir :: DynFlags -> MaybeT IO FilePath
-versionedAppDir dflags = do
+versionedAppDir :: String -> PlatformMini -> MaybeT IO FilePath
+versionedAppDir appname platform = do
-- Make sure we handle the case the HOME isn't set (see #11678)
- appdir <- tryMaybeT $ getAppUserDataDirectory (programName dflags)
- return $ appdir </> versionedFilePath dflags
+ appdir <- tryMaybeT $ getAppUserDataDirectory appname
+ return $ appdir </> versionedFilePath platform
-versionedFilePath :: DynFlags -> FilePath
-versionedFilePath dflags = uniqueSubdir $ platformMini $ targetPlatform dflags
+versionedFilePath :: PlatformMini -> FilePath
+versionedFilePath platform = uniqueSubdir platform
-- | The target code type of the compilation (if any).
--
diff --git a/compiler/GHC/Unit/State.hs b/compiler/GHC/Unit/State.hs
index 9e441eaf4d..e66e2a5e1e 100644
--- a/compiler/GHC/Unit/State.hs
+++ b/compiler/GHC/Unit/State.hs
@@ -78,6 +78,7 @@ where
import GHC.Prelude
+import GHC.Platform
import GHC.Unit.Database
import GHC.Unit.Info
import GHC.Unit.Types
@@ -306,6 +307,72 @@ instance Monoid UnitVisibility where
}
mappend = (Semigroup.<>)
+
+-- | Unit configuration
+data UnitConfig = UnitConfig
+ { unitConfigPlatformArchOs :: !PlatformMini -- ^ Platform
+ , unitConfigWays :: !(Set Way) -- ^ Ways to use
+ , unitConfigProgramName :: !String
+ -- ^ Name of the compiler (e.g. "GHC", "GHCJS"). Used to fetch environment
+ -- variables such as "GHC[JS]_PACKAGE_PATH".
+
+ , unitConfigGlobalDB :: !FilePath -- ^ Path to global DB
+ , unitConfigGHCDir :: !FilePath -- ^ Main GHC dir: contains settings, etc.
+ , unitConfigDBName :: !String -- ^ User DB name (e.g. "package.conf.d")
+
+ , unitConfigAutoLink :: ![UnitId] -- ^ Units to link automatically (e.g. base, rts)
+ , unitConfigDistrustAll :: !Bool -- ^ Distrust all units by default
+ , unitConfigHideAll :: !Bool -- ^ Hide all units by default
+ , unitConfigHideAllPlugins :: !Bool -- ^ Hide all plugins units by default
+
+ , unitConfigAllowVirtualUnits :: !Bool
+ -- ^ Allow the use of virtual units instantiated on-the-fly (see Note
+ -- [About units] in GHC.Unit). This should only be used when we are
+ -- type-checking an indefinite unit (not producing any code).
+
+ -- command-line flags
+ , unitConfigFlagsDB :: [PackageDBFlag] -- ^ Unit databases flags
+ , unitConfigFlagsExposed :: [PackageFlag] -- ^ Exposed units
+ , unitConfigFlagsIgnored :: [IgnorePackageFlag] -- ^ Ignored units
+ , unitConfigFlagsTrusted :: [TrustFlag] -- ^ Trusted units
+ , unitConfigFlagsPlugins :: [PackageFlag] -- ^ Plugins exposed units
+ }
+
+initUnitConfig :: DynFlags -> IO UnitConfig
+initUnitConfig dflags = do
+
+ let autoLink
+ | not (gopt Opt_AutoLinkPackages dflags) = []
+ -- By default we add base & rts to the preload units (when they are
+ -- found in the unit database) except when we are building them
+ | otherwise = filter (/= homeUnitId dflags) [baseUnitId, rtsUnitId]
+
+ pure $ UnitConfig
+ { unitConfigPlatformArchOs = platformMini (targetPlatform dflags)
+ , unitConfigProgramName = programName dflags
+ , unitConfigWays = ways dflags
+
+ , unitConfigGlobalDB = globalPackageDatabasePath dflags
+ , unitConfigGHCDir = topDir dflags
+ , unitConfigDBName = "package.conf.d"
+
+ , unitConfigAutoLink = autoLink
+ , unitConfigDistrustAll = gopt Opt_DistrustAllPackages dflags
+ , unitConfigHideAll = gopt Opt_HideAllPackages dflags
+ , unitConfigHideAllPlugins = gopt Opt_HideAllPluginPackages dflags
+
+ -- when the home unit is indefinite, it means we are type-checking it
+ -- only (not producing any code). Hence we can use virtual units
+ -- instantiated on-the-fly (see Note [About units] in GHC.Unit)
+ , unitConfigAllowVirtualUnits = homeUnitIsIndefinite dflags
+
+ , unitConfigFlagsDB = packageDBFlags dflags
+ , unitConfigFlagsExposed = packageFlags dflags
+ , unitConfigFlagsIgnored = ignorePackageFlags dflags
+ , unitConfigFlagsTrusted = trustFlags dflags
+ , unitConfigFlagsPlugins = pluginPackageFlags dflags
+ }
+
-- | Map from 'ModuleName' to a set of of module providers (i.e. a 'Module' and
-- its 'ModuleOrigin').
--
@@ -502,26 +569,32 @@ listUnitInfo state = Map.elems (unitInfoMap state)
initUnits :: DynFlags -> IO (DynFlags, [UnitId])
initUnits dflags = do
- let forcePkgDb (state, _) = unitInfoMap state `seq` ()
+ let forceUnitInfoMap (state, _) = unitInfoMap state `seq` ()
(state,raw_dbs) <- withTiming dflags
(text "initializing package database")
- forcePkgDb $ do
+ forceUnitInfoMap $ do
+
+ cfg <- initUnitConfig dflags
+
+ -- init SDocContext used to render exception messages
+ let ctx = initSDocContext dflags defaultUserStyle
+ let printer = debugTraceMsg dflags
-- read the databases if they have not been already read
raw_dbs <- case unitDatabases dflags of
- Nothing -> readUnitDatabases dflags
+ Nothing -> readUnitDatabases printer cfg
Just dbs -> return dbs
-- distrust all units if the flag is set
let distrust_all db = db { unitDatabaseUnits = distrustAllUnits (unitDatabaseUnits db) }
dbs
- | gopt Opt_DistrustAllPackages dflags
+ | unitConfigDistrustAll cfg
= map distrust_all raw_dbs
| otherwise
= raw_dbs
-- create the UnitState
- state <- mkUnitState dflags dbs
+ state <- mkUnitState ctx (printer 2) cfg dbs
return (state, raw_dbs)
@@ -543,18 +616,18 @@ initUnits dflags = do
-- -----------------------------------------------------------------------------
-- Reading the unit database(s)
-readUnitDatabases :: DynFlags -> IO [UnitDatabase UnitId]
-readUnitDatabases dflags = do
- conf_refs <- getUnitDbRefs dflags
- confs <- liftM catMaybes $ mapM (resolveUnitDatabase dflags) conf_refs
- mapM (readUnitDatabase dflags) confs
+readUnitDatabases :: (Int -> SDoc -> IO ()) -> UnitConfig -> IO [UnitDatabase UnitId]
+readUnitDatabases printer cfg = do
+ conf_refs <- getUnitDbRefs cfg
+ confs <- liftM catMaybes $ mapM (resolveUnitDatabase cfg) conf_refs
+ mapM (readUnitDatabase printer cfg) confs
-getUnitDbRefs :: DynFlags -> IO [PkgDbRef]
-getUnitDbRefs dflags = do
+getUnitDbRefs :: UnitConfig -> IO [PkgDbRef]
+getUnitDbRefs cfg = do
let system_conf_refs = [UserPkgDb, GlobalPkgDb]
- e_pkg_path <- tryIO (getEnv $ map toUpper (programName dflags) ++ "_PACKAGE_PATH")
+ e_pkg_path <- tryIO (getEnv $ map toUpper (unitConfigProgramName cfg) ++ "_PACKAGE_PATH")
let base_conf_refs = case e_pkg_path of
Left _ -> system_conf_refs
Right path
@@ -571,7 +644,7 @@ getUnitDbRefs dflags = do
-- * We work with the package DB list in "left shadows right" order
-- * and finally reverse it at the end, to get "right shadows left"
--
- return $ reverse (foldr doFlag base_conf_refs (packageDBFlags dflags))
+ return $ reverse (foldr doFlag base_conf_refs (unitConfigFlagsDB cfg))
where
doFlag (PackageDB p) dbs = p : dbs
doFlag NoUserPackageDB dbs = filter isNotUser dbs
@@ -590,17 +663,17 @@ getUnitDbRefs dflags = do
-- NB: This logic is reimplemented in Cabal, so if you change it,
-- make sure you update Cabal. (Or, better yet, dump it in the
-- compiler info so Cabal can use the info.)
-resolveUnitDatabase :: DynFlags -> PkgDbRef -> IO (Maybe FilePath)
-resolveUnitDatabase dflags GlobalPkgDb = return $ Just (globalPackageDatabasePath dflags)
-resolveUnitDatabase dflags UserPkgDb = runMaybeT $ do
- dir <- versionedAppDir dflags
- let pkgconf = dir </> "package.conf.d"
+resolveUnitDatabase :: UnitConfig -> PkgDbRef -> IO (Maybe FilePath)
+resolveUnitDatabase cfg GlobalPkgDb = return $ Just (unitConfigGlobalDB cfg)
+resolveUnitDatabase cfg UserPkgDb = runMaybeT $ do
+ dir <- versionedAppDir (unitConfigProgramName cfg) (unitConfigPlatformArchOs cfg)
+ let pkgconf = dir </> unitConfigDBName cfg
exist <- tryMaybeT $ doesDirectoryExist pkgconf
if exist then return pkgconf else mzero
resolveUnitDatabase _ (PkgDbPath name) = return $ Just name
-readUnitDatabase :: DynFlags -> FilePath -> IO (UnitDatabase UnitId)
-readUnitDatabase dflags conf_file = do
+readUnitDatabase :: (Int -> SDoc -> IO ()) -> UnitConfig -> FilePath -> IO (UnitDatabase UnitId)
+readUnitDatabase printer cfg conf_file = do
isdir <- doesDirectoryExist conf_file
proto_pkg_configs <-
@@ -624,7 +697,7 @@ readUnitDatabase dflags conf_file = do
let
-- Fix #16360: remove trailing slash from conf_file before calculating pkgroot
conf_file' = dropTrailingPathSeparator conf_file
- top_dir = topDir dflags
+ top_dir = unitConfigGHCDir cfg
pkgroot = takeDirectory conf_file'
pkg_configs1 = map (mungeUnitInfo top_dir pkgroot . mapUnitInfo (\(UnitKey x) -> UnitId x) unitIdFS . mkUnitKeyInfo)
proto_pkg_configs
@@ -636,24 +709,23 @@ readUnitDatabase dflags conf_file = do
cache_exists <- doesFileExist filename
if cache_exists
then do
- debugTraceMsg dflags 2 $ text "Using binary package database:"
- <+> text filename
+ printer 2 $ text "Using binary package database:" <+> text filename
readPackageDbForGhc filename
else do
-- If there is no package.cache file, we check if the database is not
-- empty by inspecting if the directory contains any .conf file. If it
-- does, something is wrong and we fail. Otherwise we assume that the
-- database is empty.
- debugTraceMsg dflags 2 $ text "There is no package.cache in"
- <+> text conf_dir
- <> text ", checking if the database is empty"
+ printer 2 $ text "There is no package.cache in"
+ <+> text conf_dir
+ <> text ", checking if the database is empty"
db_empty <- all (not . isSuffixOf ".conf")
<$> getDirectoryContents conf_dir
if db_empty
then do
- debugTraceMsg dflags 3 $ text "There are no .conf files in"
- <+> text conf_dir <> text ", treating"
- <+> text "package database as empty"
+ printer 3 $ text "There are no .conf files in"
+ <+> text conf_dir <> text ", treating"
+ <+> text "package database as empty"
return []
else do
throwGhcExceptionIO $ InstallationError $
@@ -676,7 +748,7 @@ readUnitDatabase dflags conf_file = do
let conf_dir = conf_file <.> "d"
direxists <- doesDirectoryExist conf_dir
if direxists
- then do debugTraceMsg dflags 2 (text "Ignoring old file-style db and trying:" <+> text conf_dir)
+ then do printer 2 (text "Ignoring old file-style db and trying:" <+> text conf_dir)
liftM Just (readDirStyleUnitInfo conf_dir)
else return (Just []) -- ghc-pkg will create it when it's updated
else return Nothing
@@ -705,25 +777,25 @@ mungeDynLibFields pkg =
-- -trust and -distrust.
applyTrustFlag
- :: DynFlags
+ :: SDocContext
-> UnitPrecedenceMap
-> UnusableUnits
-> [UnitInfo]
-> TrustFlag
-> IO [UnitInfo]
-applyTrustFlag dflags prec_map unusable pkgs flag =
+applyTrustFlag ctx prec_map unusable pkgs flag =
case flag of
-- we trust all matching packages. Maybe should only trust first one?
-- and leave others the same or set them untrusted
TrustPackage str ->
case selectPackages prec_map (PackageArg str) pkgs unusable of
- Left ps -> trustFlagErr dflags flag ps
+ Left ps -> trustFlagErr ctx flag ps
Right (ps,qs) -> return (map trust ps ++ qs)
where trust p = p {unitIsTrusted=True}
DistrustPackage str ->
case selectPackages prec_map (PackageArg str) pkgs unusable of
- Left ps -> trustFlagErr dflags flag ps
+ Left ps -> trustFlagErr ctx flag ps
Right (ps,qs) -> return (distrustAllUnits ps ++ qs)
-- | A little utility to tell if the home unit is indefinite
@@ -737,7 +809,7 @@ homeUnitIsDefinite :: DynFlags -> Bool
homeUnitIsDefinite dflags = unitIsDefinite (homeUnit dflags)
applyPackageFlag
- :: DynFlags
+ :: SDocContext
-> UnitPrecedenceMap
-> UnitInfoMap
-> PreloadUnitClosure
@@ -749,11 +821,11 @@ applyPackageFlag
-> PackageFlag -- flag to apply
-> IO VisibilityMap -- Now exposed
-applyPackageFlag dflags prec_map pkg_map closure unusable no_hide_others pkgs vm flag =
+applyPackageFlag ctx prec_map pkg_map closure unusable no_hide_others pkgs vm flag =
case flag of
ExposePackage _ arg (ModRenaming b rns) ->
case findPackages prec_map pkg_map closure arg pkgs unusable of
- Left ps -> packageFlagErr dflags flag ps
+ Left ps -> packageFlagErr ctx flag ps
Right (p:_) -> return vm'
where
n = fsPackageName p
@@ -817,7 +889,7 @@ applyPackageFlag dflags prec_map pkg_map closure unusable no_hide_others pkgs vm
HidePackage str ->
case findPackages prec_map pkg_map closure (PackageArg str) pkgs unusable of
- Left ps -> packageFlagErr dflags flag ps
+ Left ps -> packageFlagErr ctx flag ps
Right ps -> return vm'
where vm' = foldl' (flip Map.delete) vm (map mkUnit ps)
@@ -946,26 +1018,26 @@ compareByPreference prec_map pkg pkg'
comparing :: Ord a => (t -> a) -> t -> t -> Ordering
comparing f a b = f a `compare` f b
-packageFlagErr :: DynFlags
+packageFlagErr :: SDocContext
-> PackageFlag
-> [(UnitInfo, UnusableUnitReason)]
-> IO a
-packageFlagErr dflags flag reasons
- = packageFlagErr' dflags (pprFlag flag) reasons
+packageFlagErr ctx flag reasons
+ = packageFlagErr' ctx (pprFlag flag) reasons
-trustFlagErr :: DynFlags
+trustFlagErr :: SDocContext
-> TrustFlag
-> [(UnitInfo, UnusableUnitReason)]
-> IO a
-trustFlagErr dflags flag reasons
- = packageFlagErr' dflags (pprTrustFlag flag) reasons
+trustFlagErr ctx flag reasons
+ = packageFlagErr' ctx (pprTrustFlag flag) reasons
-packageFlagErr' :: DynFlags
+packageFlagErr' :: SDocContext
-> SDoc
-> [(UnitInfo, UnusableUnitReason)]
-> IO a
-packageFlagErr' dflags flag_doc reasons
- = throwGhcExceptionIO (CmdLineError (showSDoc dflags $ err))
+packageFlagErr' ctx flag_doc reasons
+ = throwGhcExceptionIO (CmdLineError (renderWithStyle ctx $ err))
where err = text "cannot satisfy " <> flag_doc <>
(if null reasons then Outputable.empty else text ": ") $$
nest 4 (ppr_reasons $$
@@ -1313,12 +1385,12 @@ mergeDatabases printer = foldM merge (Map.empty, Map.empty) . zip [1..]
-- 3. Apply ignore flags
-- 4. Remove all packages which have deps with mismatching ABIs
--
-validateDatabase :: DynFlags -> UnitInfoMap
+validateDatabase :: UnitConfig -> UnitInfoMap
-> (UnitInfoMap, UnusableUnits, [SCC UnitInfo])
-validateDatabase dflags pkg_map1 =
+validateDatabase cfg pkg_map1 =
(pkg_map5, unusable, sccs)
where
- ignore_flags = reverse (ignorePackageFlags dflags)
+ ignore_flags = reverse (unitConfigFlagsIgnored cfg)
-- Compute the reverse dependency index
index = reverseDeps pkg_map1
@@ -1364,12 +1436,14 @@ validateDatabase dflags pkg_map1 =
-- settings and populate the package state.
mkUnitState
- :: DynFlags
+ :: SDocContext -- ^ SDocContext used to render exception messages
+ -> (SDoc -> IO ())
+ -> UnitConfig
-- initial databases, in the order they were specified on
-- the command line (later databases shadow earlier ones)
-> [UnitDatabase UnitId]
-> IO UnitState
-mkUnitState dflags dbs = do
+mkUnitState ctx printer cfg dbs = do
{-
Plan.
@@ -1423,12 +1497,10 @@ mkUnitState dflags dbs = do
we build a mapping saying what every in scope module name points to.
-}
- let printer = debugTraceMsg dflags 2
-
-- This, and the other reverse's that you will see, are due to the fact that
-- packageFlags, pluginPackageFlags, etc. are all specified in *reverse* order
-- than they are on the command line.
- let other_flags = reverse (packageFlags dflags)
+ let other_flags = reverse (unitConfigFlagsExposed cfg)
printer $
text "package flags" <+> ppr other_flags
@@ -1437,15 +1509,15 @@ mkUnitState dflags dbs = do
-- Now that we've merged everything together, prune out unusable
-- packages.
- let (pkg_map2, unusable, sccs) = validateDatabase dflags pkg_map1
+ let (pkg_map2, unusable, sccs) = validateDatabase cfg pkg_map1
reportCycles printer sccs
reportUnusable printer unusable
-- Apply trust flags (these flags apply regardless of whether
-- or not packages are visible or not)
- pkgs1 <- foldM (applyTrustFlag dflags prec_map unusable)
- (Map.elems pkg_map2) (reverse (trustFlags dflags))
+ pkgs1 <- foldM (applyTrustFlag ctx prec_map unusable)
+ (Map.elems pkg_map2) (reverse (unitConfigFlagsTrusted cfg))
let prelim_pkg_db = mkUnitInfoMap pkgs1
--
@@ -1466,7 +1538,7 @@ mkUnitState dflags dbs = do
-- most preferable *units* keyed by package name, which act as stand-ins in
-- for "a package in a database". We use units here because we don't have
-- "a package in a database" as a type currently.
- mostPreferablePackageReps = if gopt Opt_HideAllPackages dflags
+ mostPreferablePackageReps = if unitConfigHideAll cfg
then emptyUDFM
else foldl' addIfMorePreferable emptyUDFM pkgs1
-- When exposing units, we want to consider all of those in the most preferable
@@ -1502,8 +1574,8 @@ mkUnitState dflags dbs = do
-- -hide-package). This needs to know about the unusable packages, since if a
-- user tries to enable an unusable package, we should let them know.
--
- vis_map2 <- foldM (applyPackageFlag dflags prec_map prelim_pkg_db emptyUniqSet unusable
- (gopt Opt_HideAllPackages dflags) pkgs1)
+ vis_map2 <- foldM (applyPackageFlag ctx prec_map prelim_pkg_db emptyUniqSet unusable
+ (unitConfigHideAll cfg) pkgs1)
vis_map1 other_flags
--
@@ -1517,9 +1589,9 @@ mkUnitState dflags dbs = do
-- Update the visibility map, so we treat wired packages as visible.
let vis_map = updateVisibilityMap wired_map vis_map2
- let hide_plugin_pkgs = gopt Opt_HideAllPluginPackages dflags
+ let hide_plugin_pkgs = unitConfigHideAllPlugins cfg
plugin_vis_map <-
- case pluginPackageFlags dflags of
+ case unitConfigFlagsPlugins cfg of
-- common case; try to share the old vis_map
[] | not hide_plugin_pkgs -> return vis_map
| otherwise -> return Map.empty
@@ -1530,10 +1602,10 @@ mkUnitState dflags dbs = do
-- won't work.
| otherwise = vis_map2
plugin_vis_map2
- <- foldM (applyPackageFlag dflags prec_map prelim_pkg_db emptyUniqSet unusable
- (gopt Opt_HideAllPluginPackages dflags) pkgs1)
+ <- foldM (applyPackageFlag ctx prec_map prelim_pkg_db emptyUniqSet unusable
+ hide_plugin_pkgs pkgs1)
plugin_vis_map1
- (reverse (pluginPackageFlags dflags))
+ (reverse (unitConfigFlagsPlugins cfg))
-- Updating based on wired in packages is mostly
-- good hygiene, because it won't matter: no wired in
-- package has a compiler plugin.
@@ -1544,18 +1616,6 @@ mkUnitState dflags dbs = do
-- likely to actually happen.
return (updateVisibilityMap wired_map plugin_vis_map2)
- --
- -- Here we build up a set of the packages mentioned in -package
- -- flags on the command line; these are called the "preload"
- -- packages. we link these packages in eagerly. The preload set
- -- should contain at least rts & base, which is why we pretend that
- -- the command line contains -package rts & -package base.
- --
- -- NB: preload IS important even for type-checking, because we
- -- need the correct include path to be set.
- --
- let preload1 = Map.keys (Map.filter uv_explicit vis_map)
-
let pkgname_map = foldl' add Map.empty pkgs2
where add pn_map p
= Map.insert (unitPackageName p) (unitInstanceOf p) pn_map
@@ -1570,41 +1630,40 @@ mkUnitState dflags dbs = do
$ Map.unionsWith Set.union (map uv_requirements (Map.elems vis_map))
- let preload2 = preload1
+ --
+ -- Here we build up a set of the packages mentioned in -package
+ -- flags on the command line; these are called the "preload"
+ -- packages. we link these packages in eagerly. The preload set
+ -- should contain at least rts & base, which is why we pretend that
+ -- the command line contains -package rts & -package base.
+ --
+ -- NB: preload IS important even for type-checking, because we
+ -- need the correct include path to be set.
+ --
+ let preload1 = Map.keys (Map.filter uv_explicit vis_map)
- let
- -- add base & rts to the preload units
- basicLinkedUnits
- | gopt Opt_AutoLinkPackages dflags
- = fmap (RealUnit . Definite) $
- filter (flip Map.member pkg_db)
- [baseUnitId, rtsUnitId]
- | otherwise = []
- -- but in any case remove the current unit from the set of
- -- preloaded units so that base/rts does not end up in the
- -- set up units package when we are just building it
- -- (NB: since this is only relevant for base/rts it doesn't matter
- -- that homeUnitInstantiations is not wired yet)
- --
- preload3 = ordNub $ filter (/= homeUnit dflags)
- $ (basicLinkedUnits ++ preload2)
+ -- add default preload units if they can be found in the db
+ basicLinkedUnits = fmap (RealUnit . Definite)
+ $ filter (flip Map.member pkg_db)
+ $ unitConfigAutoLink cfg
+ preload3 = ordNub $ (basicLinkedUnits ++ preload1)
-- Close the preload packages with their dependencies
let dep_preload_err = closeUnitDeps pkg_db (zip (map toUnitId preload3) (repeat Nothing))
- dep_preload <- throwErr dflags dep_preload_err
+ dep_preload <- throwErr ctx dep_preload_err
- let mod_map1 = mkModuleNameProvidersMap dflags pkg_db emptyUniqSet vis_map
+ let mod_map1 = mkModuleNameProvidersMap ctx cfg pkg_db emptyUniqSet vis_map
mod_map2 = mkUnusableModuleNameProvidersMap unusable
mod_map = Map.union mod_map1 mod_map2
- -- Force pstate to avoid leaking the dflags passed to mkUnitState
- let !pstate = UnitState
+ -- Force the result to avoid leaking input parameters
+ return $! UnitState
{ preloadUnits = dep_preload
, explicitUnits = explicit_pkgs
, unitInfoMap = pkg_db
, preloadClosure = emptyUniqSet
, moduleNameProvidersMap = mod_map
- , pluginModuleNameProvidersMap = mkModuleNameProvidersMap dflags pkg_db emptyUniqSet plugin_vis_map
+ , pluginModuleNameProvidersMap = mkModuleNameProvidersMap ctx cfg pkg_db emptyUniqSet plugin_vis_map
, packageNameMap = pkgname_map
, wireMap = wired_map
, unwireMap = Map.fromList [ (v,k) | (k,v) <- Map.toList wired_map ]
@@ -1613,9 +1672,8 @@ mkUnitState dflags dbs = do
-- when the home unit is indefinite, it means we are type-checking it
-- only (not producing any code). Hence we can use virtual units
-- instantiated on-the-fly (see Note [About units] in GHC.Unit)
- , allowVirtualUnits = homeUnitIsIndefinite dflags
+ , allowVirtualUnits = unitConfigAllowVirtualUnits cfg
}
- return pstate
-- | Given a wired-in 'Unit', "unwire" it into the 'Unit'
-- that it was recorded as in the package database.
@@ -1625,19 +1683,20 @@ unwireUnit state uid@(RealUnit (Definite def_uid)) =
unwireUnit _ uid = uid
-- -----------------------------------------------------------------------------
--- | Makes the mapping from module to package info
+-- | Makes the mapping from ModuleName to package info
-- Slight irritation: we proceed by leafing through everything
-- in the installed package database, which makes handling indefinite
-- packages a bit bothersome.
mkModuleNameProvidersMap
- :: DynFlags
+ :: SDocContext -- ^ SDocContext used to render exception messages
+ -> UnitConfig
-> UnitInfoMap
-> PreloadUnitClosure
-> VisibilityMap
-> ModuleNameProvidersMap
-mkModuleNameProvidersMap dflags pkg_map closure vis_map =
+mkModuleNameProvidersMap ctx cfg pkg_map closure vis_map =
-- What should we fold on? Both situations are awkward:
--
-- * Folding on the visibility map means that we won't create
@@ -1688,7 +1747,7 @@ mkModuleNameProvidersMap dflags pkg_map closure vis_map =
rnBinding (orig, new) = (new, setOrigins origEntry fromFlag)
where origEntry = case lookupUFM esmap orig of
Just r -> r
- Nothing -> throwGhcException (CmdLineError (showSDoc dflags
+ Nothing -> throwGhcException (CmdLineError (renderWithStyle ctx
(text "package flag: could not find module name" <+>
ppr orig <+> text "in package" <+> ppr pk)))
@@ -1710,7 +1769,7 @@ mkModuleNameProvidersMap dflags pkg_map closure vis_map =
hiddens = [(m, mkModMap pk m ModHidden) | m <- hidden_mods]
pk = mkUnit pkg
- unit_lookup uid = lookupUnit' (homeUnitIsIndefinite dflags) pkg_map closure uid
+ unit_lookup uid = lookupUnit' (unitConfigAllowVirtualUnits cfg) pkg_map closure uid
`orElse` pprPanic "unit_lookup" (ppr uid)
exposed_mods = unitExposedModules pkg
@@ -2022,13 +2081,14 @@ getPreloadUnitsAnd dflags ids0 =
state = unitState dflags
pkg_map = unitInfoMap state
preload = preloadUnits state
+ ctx = initSDocContext dflags defaultUserStyle
in do
- all_pkgs <- throwErr dflags (closeUnitDeps' pkg_map preload (ids `zip` repeat Nothing))
+ all_pkgs <- throwErr ctx (closeUnitDeps' pkg_map preload (ids `zip` repeat Nothing))
return (map (unsafeLookupUnitId state) all_pkgs)
-throwErr :: DynFlags -> MaybeErr MsgDoc a -> IO a
-throwErr dflags m = case m of
- Failed e -> throwGhcExceptionIO (CmdLineError (showSDoc dflags e))
+throwErr :: SDocContext -> MaybeErr MsgDoc a -> IO a
+throwErr ctx m = case m of
+ Failed e -> throwGhcExceptionIO (CmdLineError (renderWithStyle ctx e))
Succeeded r -> return r
-- | Takes a list of UnitIds (and their "parent" dependency, used for error