- --
- -- Eliminate any packages which have dangling dependencies (perhaps
- -- because the package was removed by -ignore-package).
- --
- let
- elimDanglingDeps pkgs =
- case partition (not.null.snd) (map (getDanglingDeps pkgs) pkgs) of
- ([],ps) -> return (map fst ps)
- (ps,qs) -> do
- mapM_ reportElim ps
- elimDanglingDeps (map fst qs)
-
- reportElim (p, deps) =
- debugTraceMsg dflags 2 $
- (ptext SLIT("package") <+> pprPkg p <+>
- ptext SLIT("will be ignored due to missing dependencies:") $$
- nest 2 (hsep (map (text.showPackageId) deps)))
+-- -----------------------------------------------------------------------------
+
+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 ]
+ -- missing package is not an error for -ignore-package,
+ -- because a common usage is to -ignore-package P as
+ -- a preventative measure just in case P exists.
+ 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
+
+-- -----------------------------------------------------------------------------
+-- When all the command-line options are in, we can process our package
+-- settings and populate the package state.
+
+mkPackageState
+ :: DynFlags
+ -> [PackageConfig] -- initial database
+ -> [PackageId] -- preloaded packages
+ -> PackageId -- this package
+ -> IO (PackageState,
+ [PackageId], -- new packages to preload
+ PackageId) -- this package, might be modified if the current
+
+ -- package is a wired-in package.
+
+mkPackageState dflags pkgs0 preload0 this_package = do
+
+{-
+ Plan.
+
+ 1. P = transitive closure of packages selected by -package-id
+
+ 2. Apply shadowing. When there are multiple packages with the same
+ sourcePackageId,
+ * if one is in P, use that one
+ * otherwise, use the one highest in the package stack
+ [
+ rationale: we cannot use two packages with the same sourcePackageId
+ in the same program, because sourcePackageId is the symbol prefix.
+ Hence we must select a consistent set of packages to use. We have
+ a default algorithm for doing this: packages higher in the stack
+ shadow those lower down. This default algorithm can be overriden
+ by giving explicit -package-id flags; then we have to take these
+ preferences into account when selecting which other packages are
+ made available.
+
+ Our simple algorithm throws away some solutions: there may be other
+ consistent sets that would satisfy the -package flags, but it's
+ not GHC's job to be doing constraint solving.
+ ]
+
+ 3. remove packages selected by -ignore-package
+
+ 4. remove any packages with missing dependencies, or mutually recursive
+ dependencies.
+
+ 5. report (with -v) any packages that were removed by steps 2-4
+
+ 6. apply flags to set exposed/hidden on the resulting packages
+ - if any flag refers to a package which was removed by 2-4, then
+ we can give an error message explaining why
+
+ 7. hide any packages which are superseded by later exposed packages
+-}