From 930421d4ed09e5389e0ef4c5eef36075a6809cc0 Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Thu, 10 Sep 2009 10:27:03 +0000 Subject: [PATCH] Change the representation of the package database - the package DB is a directory containing one file per package instance (#723) - there is a binary cache of the database (#593, #2089) - the binary package is now a boot package - there is a new package, bin-package-db, containing the Binary instance of InstalledPackageInfo for the binary cache. Also included in this patch - Use colour in 'ghc-pkg list' to indicate broken or hidden packages Broken packages are red, hidden packages are Colour support comes from the terminfo package, and is only used when - not --simple-output - stdout is a TTY - the terminal type has colour capability - Fix the bug that 'ghc-pkg list --user' shows everything as broken --- compiler/ghc.cabal.in | 2 + compiler/main/PackageConfig.hs | 8 +- compiler/main/Packages.lhs | 53 +- compiler/main/SysTools.lhs | 8 +- ghc.mk | 29 +- .../Distribution/InstalledPackageInfo/Binary.hs | 133 ++++++ libraries/bin-package-db/bin-package-db.cabal | 21 + mk/config.mk.in | 2 +- packages | 1 + utils/ghc-cabal/ghc-cabal.hs | 2 +- utils/ghc-pkg/Main.hs | 505 +++++++++++++------- utils/ghc-pkg/ghc-pkg.cabal | 2 +- utils/ghc-pkg/ghc.mk | 11 +- 13 files changed, 560 insertions(+), 217 deletions(-) create mode 100644 libraries/bin-package-db/Distribution/InstalledPackageInfo/Binary.hs create mode 100644 libraries/bin-package-db/bin-package-db.cabal diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in index d05dc1a..bed13f0 100644 --- a/compiler/ghc.cabal.in +++ b/compiler/ghc.cabal.in @@ -88,6 +88,8 @@ Library if !flag(ncg) CPP-Options: -DOMIT_NATIVE_CODEGEN + Build-Depends: bin-package-db + -- GHC 6.4.2 needs to be able to find WCsubst.c, which needs to be -- able to find WCsubst.h Include-Dirs: ../libraries/base/cbits, ../libraries/base/include diff --git a/compiler/main/PackageConfig.hs b/compiler/main/PackageConfig.hs index ac1a9fe..50c1e71 100644 --- a/compiler/main/PackageConfig.hs +++ b/compiler/main/PackageConfig.hs @@ -74,11 +74,9 @@ packageConfigToInstalledPackageInfo -- | Turn an 'InstalledPackageInfo', which contains Cabal 'Distribution.ModuleName.ModuleName's -- into a GHC specific 'PackageConfig' which contains GHC 'Module.ModuleName's -installedPackageInfoToPackageConfig :: InstalledPackageInfo -> PackageConfig +installedPackageInfoToPackageConfig :: InstalledPackageInfo_ String -> PackageConfig installedPackageInfoToPackageConfig (pkgconf@(InstalledPackageInfo { exposedModules = e, hiddenModules = h })) = - pkgconf{ exposedModules = map convert e, - hiddenModules = map convert h } - where convert :: Distribution.ModuleName.ModuleName -> Module.ModuleName - convert = mkModuleName . display + pkgconf{ exposedModules = map mkModuleName e, + hiddenModules = map mkModuleName h } diff --git a/compiler/main/Packages.lhs b/compiler/main/Packages.lhs index 2e91ac8..0cfd00f 100644 --- a/compiler/main/Packages.lhs +++ b/compiler/main/Packages.lhs @@ -51,6 +51,7 @@ 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, Message ) @@ -204,44 +205,40 @@ getSystemPackageConfigs dflags = do -- System one always comes first let system_pkgconf = systemPackageConfig dflags - -- allow package.conf.d to contain a bunch of .conf files - -- containing package specifications. This is an easier way - -- to maintain the package database on systems with a package - -- management system, or systems that don't want to run ghc-pkg - -- to register or unregister packages. Undocumented feature for now. - let system_pkgconf_dir = system_pkgconf <.> "d" - system_pkgconf_dir_exists <- doesDirectoryExist system_pkgconf_dir - system_pkgconfs <- - if system_pkgconf_dir_exists - then do files <- getDirectoryContents system_pkgconf_dir - return [ system_pkgconf_dir file - | file <- files - , takeExtension file == ".conf" ] - else return [] - -- Read user's package conf (eg. ~/.ghc/i386-linux-6.3/package.conf) -- unless the -no-user-package-conf flag was given. - -- We only do this when getAppUserDataDirectory is available - -- (GHC >= 6.3). user_pkgconf <- do + if not (dopt Opt_ReadUserPackageConf dflags) then return [] else do appdir <- getAppUserDataDirectory "ghc" let - pkgconf = appdir - (TARGET_ARCH ++ '-':TARGET_OS ++ '-':cProjectVersion) - "package.conf" - flg <- doesFileExist pkgconf - if (flg && dopt Opt_ReadUserPackageConf dflags) - then return [pkgconf] - else return [] + dir = appdir (TARGET_ARCH ++ '-':TARGET_OS ++ '-':cProjectVersion) + pkgconf = dir "package.conf.d" + -- + exist <- doesDirectoryExist pkgconf + if exist then return [pkgconf] else return [] `catchIO` (\_ -> return []) - return (user_pkgconf ++ system_pkgconfs ++ [system_pkgconf]) - + return (user_pkgconf ++ [system_pkgconf]) readPackageConfig :: DynFlags -> FilePath -> IO [PackageConfig] readPackageConfig dflags conf_file = do - debugTraceMsg dflags 2 (text "Using package config file:" <+> text conf_file) - proto_pkg_configs <- loadPackageConfig dflags conf_file + 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) $ + ghcError $ InstallationError $ + "can't find a package database at " ++ conf_file + debugTraceMsg dflags 2 (text "Using package config file:" <+> text conf_file) + loadPackageConfig dflags conf_file + let top_dir = topDir dflags pkg_configs1 = mungePackagePaths top_dir proto_pkg_configs diff --git a/compiler/main/SysTools.lhs b/compiler/main/SysTools.lhs index f793a17..3a6f9f2 100644 --- a/compiler/main/SysTools.lhs +++ b/compiler/main/SysTools.lhs @@ -160,7 +160,7 @@ initSysTools mbMinusB dflags0 installed file = top_dir file installed_mingw_bin file = top_dir ".." "mingw" "bin" file - ; let pkgconfig_path = installed "package.conf" + ; let pkgconfig_path = installed "package.conf.d" ghc_usage_msg_path = installed "ghc-usage.txt" ghci_usage_msg_path = installed "ghci-usage.txt" @@ -177,12 +177,6 @@ initSysTools mbMinusB dflags0 ; tmpdir <- getTemporaryDirectory ; let dflags1 = setTmpDir tmpdir dflags0 - -- Check that the package config exists - ; config_exists <- doesFileExist pkgconfig_path - ; when (not config_exists) $ - ghcError (InstallationError - ("Can't find package.conf as " ++ pkgconfig_path)) - -- On Windows, mingw is distributed with GHC, -- so we look in TopDir/../mingw/bin ; let diff --git a/ghc.mk b/ghc.mk index 7f653d0..91b5d3d 100644 --- a/ghc.mk +++ b/ghc.mk @@ -171,6 +171,8 @@ libraries/hpc_dist-boot_DO_HADDOCK = NO libraries/Cabal_dist-boot_DO_HADDOCK = NO libraries/extensible-exceptions_dist-boot_DO_HADDOCK = NO libraries/filepath_dist-boot_DO_HADDOCK = NO +libraries/binary_dist-boot_DO_HADDOCK = NO +libraries/bin-package-db_dist-boot_DO_HADDOCK = NO # ----------------------------------------------------------------------------- # Ways @@ -320,6 +322,8 @@ $(eval $(call addPackage,syb)) $(eval $(call addPackage,template-haskell)) $(eval $(call addPackage,base3-compat)) $(eval $(call addPackage,Cabal)) +$(eval $(call addPackage,binary)) +$(eval $(call addPackage,bin-package-db)) $(eval $(call addPackage,mtl)) $(eval $(call addPackage,utf8-string)) @@ -337,7 +341,9 @@ PACKAGES_STAGE2 += \ dph/dph-par endif -BOOT_PKGS = Cabal hpc extensible-exceptions +# We assume that the stage0 compiler has a suitable bytestring package, +# so we don't have to include it below. +BOOT_PKGS = Cabal hpc extensible-exceptions binary bin-package-db # The actual .a and .so/.dll files: needed for dependencies. ALL_STAGE1_LIBS = $(foreach lib,$(PACKAGES),$(libraries/$(lib)_dist-install_v_LIB)) @@ -628,6 +634,8 @@ $(eval $(call clean-target,$(BOOTSTRAPPING_CONF),,$(BOOTSTRAPPING_CONF))) $(eval $(call build-package,libraries/hpc,dist-boot,0)) $(eval $(call build-package,libraries/extensible-exceptions,dist-boot,0)) $(eval $(call build-package,libraries/Cabal,dist-boot,0)) +$(eval $(call build-package,libraries/binary,dist-boot,0)) +$(eval $(call build-package,libraries/bin-package-db,dist-boot,0)) # register the boot packages in strict sequence, because running # multiple ghc-pkgs in parallel doesn't work (registrations may get @@ -638,13 +646,23 @@ $(foreach pkg,$(BOOT_PKGS),$(eval $(call fixed_pkg_dep,$(pkg),dist-boot))) compiler/stage1/package-data.mk : \ libraries/Cabal/dist-boot/package-data.mk \ libraries/hpc/dist-boot/package-data.mk \ - libraries/extensible-exceptions/dist-boot/package-data.mk + libraries/extensible-exceptions/dist-boot/package-data.mk \ + libraries/bin-package-db/dist-boot/package-data.mk # These are necessary because the bootstrapping compiler may not know # about cross-package dependencies: $(compiler_stage1_depfile) : $(BOOT_LIBS) $(ghc_stage1_depfile) : $(compiler_stage1_v_LIB) +# A few careful dependencies between bootstrapping packages. When we +# can rely on the stage 0 compiler being able to generate +# cross-package dependencies with -M (fixed in GHC 6.12.1) we can drop +# these, and also some of the phases. +# +# If you miss any out here, then 'make -j8' will probably tell you. +# +libraries/bin-package-db/dist-boot/build/Distribution/InstalledPackageInfo/Binary.$(v_osuf) : libraries/binary/dist-boot/build/Data/Binary.$(v_hisuf) + $(foreach pkg,$(BOOT_PKGS),$(eval libraries/$(pkg)_dist-boot_HC_OPTS += $$(GhcBootLibHcOpts))) endif @@ -770,7 +788,7 @@ install_docs: $(INSTALL_HEADERS) $(INSTALL_DOC) $(INSTALL_OPTS) $$i/* $(DESTDIR)$(docdir)/html/`basename $$i`; \ done -INSTALLED_PACKAGE_CONF=$(DESTDIR)$(topdir)/package.conf +INSTALLED_PACKAGE_CONF=$(DESTDIR)$(topdir)/package.conf.d # Install packages in the right order, so that ghc-pkg doesn't complain. # Also, install ghc-pkg first. @@ -785,9 +803,8 @@ endif install_packages: install_libexecs install_packages: libffi/package.conf.install rts/package.conf.install $(INSTALL_DIR) $(DESTDIR)$(topdir) - "$(RM)" $(RM_OPTS) $(INSTALLED_PACKAGE_CONF) - $(CREATE_DATA) $(INSTALLED_PACKAGE_CONF) - echo "[]" >> $(INSTALLED_PACKAGE_CONF) + "$(RM)" -r $(RM_OPTS) $(INSTALLED_PACKAGE_CONF) + $(INSTALL_DIR) $(INSTALLED_PACKAGE_CONF) "$(INSTALLED_GHC_PKG_REAL)" --force --global-conf $(INSTALLED_PACKAGE_CONF) update libffi/package.conf.install "$(INSTALLED_GHC_PKG_REAL)" --force --global-conf $(INSTALLED_PACKAGE_CONF) update rts/package.conf.install $(foreach p, $(PACKAGES) $(PACKAGES_STAGE2),\ diff --git a/libraries/bin-package-db/Distribution/InstalledPackageInfo/Binary.hs b/libraries/bin-package-db/Distribution/InstalledPackageInfo/Binary.hs new file mode 100644 index 0000000..212c8f9 --- /dev/null +++ b/libraries/bin-package-db/Distribution/InstalledPackageInfo/Binary.hs @@ -0,0 +1,133 @@ +{-# LANGUAGE RecordWildCards, TypeSynonymInstances, StandaloneDeriving, GeneralizedNewtypeDeriving #-} +----------------------------------------------------------------------------- +-- | +-- Module : Distribution.InstalledPackageInfo.Binary +-- Copyright : (c) The University of Glasgow 2009 +-- +-- Maintainer : cvs-ghc@haskell.org +-- Portability : portable +-- + +module Distribution.InstalledPackageInfo.Binary ( + readBinPackageDB, + writeBinPackageDB + ) where + +import Distribution.Version +import Distribution.Package +import Distribution.License +import Distribution.InstalledPackageInfo as IPI +import Data.Binary as Bin + +readBinPackageDB :: Binary m => FilePath -> IO [InstalledPackageInfo_ m] +readBinPackageDB file = Bin.decodeFile file + +writeBinPackageDB :: Binary m => FilePath -> [InstalledPackageInfo_ m] -> IO () +writeBinPackageDB file ipis = Bin.encodeFile file ipis + +instance Binary m => Binary (InstalledPackageInfo_ m) where + put = putInstalledPackageInfo + get = getInstalledPackageInfo + +putInstalledPackageInfo :: Binary m => InstalledPackageInfo_ m -> Put +putInstalledPackageInfo ipi = do + put (sourcePackageId ipi) + put (installedPackageId ipi) + put (license ipi) + put (copyright ipi) + put (maintainer ipi) + put (author ipi) + put (stability ipi) + put (homepage ipi) + put (pkgUrl ipi) + put (description ipi) + put (category ipi) + put (exposed ipi) + put (exposedModules ipi) + put (hiddenModules ipi) + put (importDirs ipi) + put (libraryDirs ipi) + put (hsLibraries ipi) + put (extraLibraries ipi) + put (extraGHCiLibraries ipi) + put (includeDirs ipi) + put (includes ipi) + put (IPI.depends ipi) + put (hugsOptions ipi) + put (ccOptions ipi) + put (ldOptions ipi) + put (frameworkDirs ipi) + put (frameworks ipi) + put (haddockInterfaces ipi) + put (haddockHTMLs ipi) + +getInstalledPackageInfo :: Binary m => Get (InstalledPackageInfo_ m) +getInstalledPackageInfo = do + sourcePackageId <- get + installedPackageId <- get + license <- get + copyright <- get + maintainer <- get + author <- get + stability <- get + homepage <- get + pkgUrl <- get + description <- get + category <- get + exposed <- get + exposedModules <- get + hiddenModules <- get + importDirs <- get + libraryDirs <- get + hsLibraries <- get + extraLibraries <- get + extraGHCiLibraries <- get + includeDirs <- get + includes <- get + depends <- get + hugsOptions <- get + ccOptions <- get + ldOptions <- get + frameworkDirs <- get + frameworks <- get + haddockInterfaces <- get + haddockHTMLs <- get + return InstalledPackageInfo{..} + +instance Binary PackageIdentifier where + put pid = do put (pkgName pid); put (pkgVersion pid) + get = do + pkgName <- get + pkgVersion <- get + return PackageIdentifier{..} + +instance Binary License where + put (GPL v) = do putWord8 0; put v + put (LGPL v) = do putWord8 1; put v + put BSD3 = do putWord8 2 + put BSD4 = do putWord8 3 + put MIT = do putWord8 4 + put PublicDomain = do putWord8 5 + put AllRightsReserved = do putWord8 6 + put OtherLicense = do putWord8 7 + put (UnknownLicense str) = do putWord8 8; put str + + get = do + n <- getWord8 + case n of + 0 -> do v <- get; return (GPL v) + 1 -> do v <- get; return (LGPL v) + 2 -> return BSD3 + 3 -> return BSD4 + 4 -> return MIT + 5 -> return PublicDomain + 6 -> return AllRightsReserved + 7 -> return OtherLicense + 8 -> do str <- get; return (UnknownLicense str) + +instance Binary Version where + put v = do put (versionBranch v); put (versionTags v) + get = do versionBranch <- get; versionTags <- get; return Version{..} + +deriving instance Binary PackageName +deriving instance Binary InstalledPackageId diff --git a/libraries/bin-package-db/bin-package-db.cabal b/libraries/bin-package-db/bin-package-db.cabal new file mode 100644 index 0000000..abeb9e5 --- /dev/null +++ b/libraries/bin-package-db/bin-package-db.cabal @@ -0,0 +1,21 @@ +name: bin-package-db +version: 0.0.0.0 +license: BSD3 +maintainer: cvs-ghc@haskell.org +bug-reports: glasgow-haskell-bugs@haskell.org +synopsis: A binary format for the package database +cabal-version: >=1.6 +build-type: Simple + +source-repository head + type: darcs + location: http://darcs.haskell.org/ghc + +Library { + exposed-modules: + Distribution.InstalledPackageInfo.Binary + + build-depends: base == 4.*, + binary == 0.5.*, + Cabal == 1.7.* +} diff --git a/mk/config.mk.in b/mk/config.mk.in index 813a912..a120e46 100644 --- a/mk/config.mk.in +++ b/mk/config.mk.in @@ -500,7 +500,7 @@ INSTALL_GHC_STAGE=2 BOOTSTRAPPING_CONF = libraries/bootstrapping.conf -INPLACE_PACKAGE_CONF = $(INPLACE_LIB)/package.conf +INPLACE_PACKAGE_CONF = $(INPLACE_LIB)/package.conf.d GhcVersion = @GhcVersion@ GhcPatchLevel = @GhcPatchLevel@ diff --git a/packages b/packages index 2eea464..be62ec7 100644 --- a/packages +++ b/packages @@ -22,6 +22,7 @@ utils/haddock haddock2 darcs libraries/array packages/array darcs libraries/base packages/base darcs libraries/base3-compat packages/base3-compat darcs +libraries/binary packages/binary darcs libraries/bytestring packages/bytestring darcs libraries/Cabal packages/Cabal darcs libraries/containers packages/containers darcs diff --git a/utils/ghc-cabal/ghc-cabal.hs b/utils/ghc-cabal/ghc-cabal.hs index e97850d..3d9cf13 100644 --- a/utils/ghc-cabal/ghc-cabal.hs +++ b/utils/ghc-cabal/ghc-cabal.hs @@ -155,7 +155,7 @@ doInstall ghc ghcpkg topdir directory distDir myDestDir myPrefix myLibdir myDocd programArgs = ["-B" ++ topdir], programLocation = UserSpecified ghc } - ghcpkgconf = topdir "package.conf" + ghcpkgconf = topdir "package.conf.d" ghcPkgProg = ConfiguredProgram { programId = programName ghcPkgProgram, programVersion = Nothing, diff --git a/utils/ghc-pkg/Main.hs b/utils/ghc-pkg/Main.hs index ee2f319..411dc56 100644 --- a/utils/ghc-pkg/Main.hs +++ b/utils/ghc-pkg/Main.hs @@ -10,6 +10,7 @@ module Main (main) where import Version ( version, targetOS, targetARCH ) +import Distribution.InstalledPackageInfo.Binary import qualified Distribution.Simple.PackageIndex as PackageIndex import Distribution.ModuleName hiding (main) import Distribution.InstalledPackageInfo @@ -20,14 +21,15 @@ import Distribution.Text import Distribution.Version import System.FilePath import System.Cmd ( rawSystem ) -import System.Directory ( getAppUserDataDirectory, createDirectoryIfMissing ) +import System.Directory ( getAppUserDataDirectory, createDirectoryIfMissing, + getModificationTime ) +import Text.Printf import Prelude #include "../../includes/ghcconfig.h" import System.Console.GetOpt -import Text.PrettyPrint #if __GLASGOW_HASKELL__ >= 609 import qualified Control.Exception as Exception #else @@ -67,6 +69,10 @@ import System.Process(runInteractiveCommand) import qualified System.Info(os) #endif +#if __GLASGOW_HASKELL__ >= 611 +import System.Console.Terminfo as Terminfo +#endif + -- ----------------------------------------------------------------------------- -- Entry point @@ -323,23 +329,27 @@ runit verbosity cli nonopts = do listPackages verbosity cli Nothing (Just match) ["latest", pkgid_str] -> do pkgid <- readGlobPkgId pkgid_str - latestPackage cli pkgid + latestPackage verbosity cli pkgid ["describe", pkgid_str] -> case substringCheck pkgid_str of Nothing -> do pkgid <- readGlobPkgId pkgid_str - describePackage cli (Id pkgid) - Just m -> describePackage cli (Substring pkgid_str m) + describePackage verbosity cli (Id pkgid) + Just m -> describePackage verbosity cli (Substring pkgid_str m) ["field", pkgid_str, fields] -> case substringCheck pkgid_str of Nothing -> do pkgid <- readGlobPkgId pkgid_str - describeField cli (Id pkgid) (splitFields fields) - Just m -> describeField cli (Substring pkgid_str m) + describeField verbosity cli (Id pkgid) + (splitFields fields) + Just m -> describeField verbosity cli (Substring pkgid_str m) (splitFields fields) ["check"] -> do - checkConsistency cli + checkConsistency verbosity cli ["dump"] -> do - dumpPackages cli + dumpPackages verbosity cli + + ["recache"] -> do + recache verbosity cli [] -> do die ("missing command\n" ++ @@ -381,19 +391,33 @@ globVersion = Version{ versionBranch=[], versionTags=["*"] } -- Some commands operate on multiple databases, with overlapping semantics: -- list, describe, field -type PackageDBName = FilePath -type PackageDB = [InstalledPackageInfo] +data PackageDB + = PackageDB { location :: FilePath, + packages :: [InstalledPackageInfo] } -type NamedPackageDB = (PackageDBName, PackageDB) -type PackageDBStack = [NamedPackageDB] +type PackageDBStack = [PackageDB] -- A stack of package databases. Convention: head is the topmost - -- in the stack. Earlier entries override later one. + -- in the stack. allPackagesInStack :: PackageDBStack -> [InstalledPackageInfo] -allPackagesInStack = concatMap snd +allPackagesInStack = concatMap packages -getPkgDatabases :: Bool -> [Flag] -> IO (PackageDBStack, Maybe PackageDBName) -getPkgDatabases modify my_flags = do +getPkgDatabases :: Verbosity + -> Bool -- we are modifying, not reading + -> Bool -- read caches, if available + -> [Flag] + -> IO (PackageDBStack, + -- the real package DB stack: [global,user] ++ + -- DBs specified on the command line with -f. + Maybe FilePath, + -- which one to modify, if any + PackageDBStack) + -- the package DBs specified on the command + -- line, or [global,user] otherwise. This + -- is used as the list of package DBs for + -- commands that just read the DB, such as 'list'. + +getPkgDatabases verbosity modify use_cache my_flags = do -- first we determine the location of the global package config. On Windows, -- this is found relative to the ghc-pkg.exe binary, whereas on Unix the -- location is passed to the binary using the --global-config flag by the @@ -403,47 +427,38 @@ getPkgDatabases modify my_flags = do case [ f | FlagGlobalConfig f <- my_flags ] of [] -> do mb_dir <- getLibDir case mb_dir of - Nothing -> die err_msg - Just dir -> - do let path = dir "package.conf" - exists <- doesFileExist path - unless exists $ die "Can't find package.conf" - return path + Nothing -> die err_msg + Just dir -> do + r <- lookForPackageDBIn dir + case r of + Nothing -> die ("Can't find package database in " ++ dir) + Just path -> return path fs -> return (last fs) - let global_conf_dir = global_conf ++ ".d" - global_conf_dir_exists <- doesDirectoryExist global_conf_dir - global_confs <- - if global_conf_dir_exists - then do files <- getDirectoryContents global_conf_dir - return [ global_conf_dir ++ '/' : file - | file <- files - , isSuffixOf ".conf" file] - else return [] - let no_user_db = FlagNoUserDb `elem` my_flags -- get the location of the user package database, and create it if necessary -- getAppUserDataDirectory can fail (e.g. if $HOME isn't set) - appdir <- try $ getAppUserDataDirectory "ghc" + e_appdir <- try $ getAppUserDataDirectory "ghc" mb_user_conf <- if no_user_db then return Nothing else - case appdir of - Right dir -> do - let subdir = targetARCH ++ '-':targetOS ++ '-':Version.version - user_conf = dir subdir "package.conf" - user_exists <- doesFileExist user_conf - return (Just (user_conf,user_exists)) - Left _ -> - return Nothing + case e_appdir of + Left _ -> return Nothing + Right appdir -> do + let subdir = targetARCH ++ '-':targetOS ++ '-':Version.version + dir = appdir subdir + r <- lookForPackageDBIn dir + case r of + Nothing -> return (Just (dir "package.conf.d", False)) + Just f -> return (Just (f, True)) -- If the user database doesn't exist, and this command isn't a -- "modify" command, then we won't attempt to create or use it. let sys_databases | Just (user_conf,user_exists) <- mb_user_conf, - modify || user_exists = user_conf : global_confs ++ [global_conf] - | otherwise = global_confs ++ [global_conf] + modify || user_exists = [user_conf, global_conf] + | otherwise = [global_conf] e_pkg_path <- try (System.Environment.getEnv "GHC_PACKAGE_PATH") let env_stack = @@ -466,52 +481,108 @@ getPkgDatabases modify my_flags = do is_db_flag (FlagConfig f) = Just f is_db_flag _ = Nothing - (final_stack, to_modify) <- - if not modify - then -- For a "read" command, we use all the databases - -- specified on the command line. If there are no - -- command-line flags specifying databases, the default - -- is to use all the ones we know about. - if null db_flags then return (env_stack, Nothing) - else return (reverse (nub db_flags), Nothing) - else let - -- For a "modify" command, treat all the databases as - -- a stack, where we are modifying the top one, but it - -- can refer to packages in databases further down the - -- stack. - - -- -f flags on the command line add to the database - -- stack, unless any of them are present in the stack - -- already. - flag_stack = filter (`notElem` env_stack) - [ f | FlagConfig f <- reverse my_flags ] - ++ env_stack - - -- the database we actually modify is the one mentioned - -- rightmost on the command-line. - to_modify = if null db_flags - then Just virt_global_conf - else Just (last db_flags) - in - return (flag_stack, to_modify) - - db_stack <- mapM (readParseDatabase mb_user_conf) final_stack - return (db_stack, to_modify) - -readParseDatabase :: Maybe (PackageDBName,Bool) - -> PackageDBName - -> IO (PackageDBName,PackageDB) -readParseDatabase mb_user_conf filename + let flag_db_names | null db_flags = env_stack + | otherwise = reverse (nub db_flags) + + -- For a "modify" command, treat all the databases as + -- a stack, where we are modifying the top one, but it + -- can refer to packages in databases further down the + -- stack. + + -- -f flags on the command line add to the database + -- stack, unless any of them are present in the stack + -- already. + let final_stack = filter (`notElem` env_stack) + [ f | FlagConfig f <- reverse my_flags ] + ++ env_stack + + -- the database we actually modify is the one mentioned + -- rightmost on the command-line. + let to_modify + | not modify = Nothing + | null db_flags = Just virt_global_conf + | otherwise = Just (last db_flags) + + db_stack <- mapM (readParseDatabase verbosity mb_user_conf use_cache) final_stack + + let flag_db_stack = [ db | db_name <- flag_db_names, + db <- db_stack, location db == db_name ] + + return (db_stack, to_modify, flag_db_stack) + + +lookForPackageDBIn :: FilePath -> IO (Maybe FilePath) +lookForPackageDBIn dir = do + let path_dir = dir "package.conf.d" + exists_dir <- doesDirectoryExist path_dir + if exists_dir then return (Just path_dir) else do + let path_file = dir "package.conf" + exists_file <- doesFileExist path_file + if exists_file then return (Just path_file) else return Nothing + +readParseDatabase :: Verbosity + -> Maybe (FilePath,Bool) + -> Bool -- use cache + -> FilePath + -> IO PackageDB + +readParseDatabase verbosity mb_user_conf use_cache path -- the user database (only) is allowed to be non-existent - | Just (user_conf,False) <- mb_user_conf, filename == user_conf - = return (filename, []) + | Just (user_conf,False) <- mb_user_conf, path == user_conf + = return PackageDB { location = path, packages = [] } | otherwise - = do str <- readFile filename - let packages = map convertPackageInfoIn $ read str - _ <- Exception.evaluate packages - `catchError` \e-> - die ("error while parsing " ++ filename ++ ": " ++ show e) - return (filename,packages) + = do e <- try $ getDirectoryContents path + case e of + Left _ -> do + pkgs <- parseMultiPackageConf verbosity path + return PackageDB{ location = path, packages = pkgs } + Right fs + | not use_cache -> ignore_cache + | otherwise -> do + let cache = path cachefilename + tdir <- getModificationTime path + e_tcache <- try $ getModificationTime cache + case e_tcache of + Left ex -> do + when (verbosity > Normal) $ + putStrLn ("warning: cannot read cache file " ++ cache ++ ": " ++ show ex) + ignore_cache + Right tcache + | tcache >= tdir -> do + when (verbosity > Normal) $ + putStrLn ("using cache: " ++ cache) + pkgs <- readBinPackageDB cache + let pkgs' = map convertPackageInfoIn pkgs + return PackageDB { location = path, packages = pkgs' } + | otherwise -> do + when (verbosity >= Normal) $ do + putStrLn ("WARNING: cache is out of date: " ++ cache) + putStrLn " use 'ghc-pkg recache' to fix." + ignore_cache + where + ignore_cache = do + let confs = filter (".conf" `isSuffixOf`) fs + pkgs <- mapM (parseSingletonPackageConf verbosity) $ + map (path ) confs + return PackageDB { location = path, packages = pkgs } + + +parseMultiPackageConf :: Verbosity -> FilePath -> IO [InstalledPackageInfo] +parseMultiPackageConf verbosity file = do + when (verbosity > Normal) $ putStrLn ("reading package database: " ++ file) + str <- readFile file + let pkgs = map convertPackageInfoIn $ read str + Exception.evaluate pkgs + `catchError` \e-> + die ("error while parsing " ++ file ++ ": " ++ show e) + +parseSingletonPackageConf :: Verbosity -> FilePath -> IO InstalledPackageInfo +parseSingletonPackageConf verbosity file = do + when (verbosity > Normal) $ putStrLn ("reading package config: " ++ file) + readFile file >>= parsePackageInfo + +cachefilename :: FilePath +cachefilename = "package.cache" -- ----------------------------------------------------------------------------- -- Registering @@ -524,10 +595,12 @@ registerPackage :: FilePath -> Force -> IO () registerPackage input verbosity my_flags auto_ghci_libs update force = do - (db_stack, Just to_modify) <- getPkgDatabases True my_flags + (db_stack, Just to_modify, _flag_dbs) <- + getPkgDatabases verbosity True True my_flags + let db_to_operate_on = my_head "register" $ - filter ((== to_modify).fst) db_stack + filter ((== to_modify).location) db_stack -- s <- case input of @@ -546,13 +619,16 @@ registerPackage input verbosity my_flags auto_ghci_libs update force = do when (verbosity >= Normal) $ putStrLn "done." - let truncated_stack = dropWhile ((/= to_modify).fst) db_stack + let truncated_stack = dropWhile ((/= to_modify).location) db_stack -- truncate the stack for validation, because we don't allow -- packages lower in the stack to refer to those higher up. validatePackageConfig pkg truncated_stack auto_ghci_libs update force - let new_details = filter not_this (snd db_to_operate_on) ++ [pkg] - not_this p = sourcePackageId p /= sourcePackageId pkg - writeNewConfig verbosity to_modify new_details + let + removes = [ RemovePackage p + | p <- packages db_to_operate_on, + sourcePackageId p == sourcePackageId pkg ] + -- + changeDB verbosity (removes ++ [AddPackage pkg]) db_to_operate_on parsePackageInfo :: String @@ -565,41 +641,95 @@ parsePackageInfo str = (Just l, s) -> die (show l ++ ": " ++ s) -- ----------------------------------------------------------------------------- +-- Making changes to a package database + +data DBOp = RemovePackage InstalledPackageInfo + | AddPackage InstalledPackageInfo + | ModifyPackage InstalledPackageInfo + +changeDB :: Verbosity -> [DBOp] -> PackageDB -> IO () +changeDB verbosity cmds db = do + let db' = updateInternalDB db cmds + isfile <- doesFileExist (location db) + if isfile + then writeNewConfig verbosity (location db') (packages db') + else do + createDirectoryIfMissing True (location db) + changeDBDir verbosity cmds db' + +updateInternalDB :: PackageDB -> [DBOp] -> PackageDB +updateInternalDB db cmds = db{ packages = foldl do_cmd (packages db) cmds } + where + do_cmd pkgs (RemovePackage p) = + filter ((/= installedPackageId p) . installedPackageId) pkgs + do_cmd pkgs (AddPackage p) = p : pkgs + do_cmd pkgs (ModifyPackage p) = + do_cmd (do_cmd pkgs (RemovePackage p)) (AddPackage p) + + +changeDBDir :: Verbosity -> [DBOp] -> PackageDB -> IO () +changeDBDir verbosity cmds db = do + mapM_ do_cmd cmds + updateDBCache verbosity db + where + do_cmd (RemovePackage p) = do + let file = location db display (installedPackageId p) <.> "conf" + when (verbosity > Normal) $ putStrLn ("removing " ++ file) + removeFile file + do_cmd (AddPackage p) = do + let file = location db display (installedPackageId p) <.> "conf" + when (verbosity > Normal) $ putStrLn ("writing " ++ file) + writeFileAtomic file (showInstalledPackageInfo p) + do_cmd (ModifyPackage p) = + do_cmd (AddPackage p) + +updateDBCache :: Verbosity -> PackageDB -> IO () +updateDBCache verbosity db = do + let filename = location db cachefilename + when (verbosity > Normal) $ + putStrLn ("writing cache " ++ filename) + writeBinPackageDB filename (map convertPackageInfoOut (packages db)) + `catch` \e -> + if isPermissionError e + then die (filename ++ ": you don't have permission to modify this file") + else ioError e + +-- ----------------------------------------------------------------------------- -- Exposing, Hiding, Unregistering are all similar exposePackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO () -exposePackage = modifyPackage (\p -> [p{exposed=True}]) +exposePackage = modifyPackage (\p -> ModifyPackage p{exposed=True}) hidePackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO () -hidePackage = modifyPackage (\p -> [p{exposed=False}]) +hidePackage = modifyPackage (\p -> ModifyPackage p{exposed=False}) unregisterPackage :: PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO () -unregisterPackage = modifyPackage (\_ -> []) +unregisterPackage = modifyPackage RemovePackage modifyPackage - :: (InstalledPackageInfo -> [InstalledPackageInfo]) + :: (InstalledPackageInfo -> DBOp) -> PackageIdentifier -> Verbosity -> [Flag] -> Force -> IO () modifyPackage fn pkgid verbosity my_flags force = do - (db_stack, Just _to_modify) <- getPkgDatabases True{-modify-} my_flags - ((db_name, pkgs), ps) <- fmap head $ findPackagesByDB db_stack (Id pkgid) --- let ((db_name, pkgs) : rest_of_stack) = db_stack --- ps <- findPackages [(db_name,pkgs)] (Id pkgid) + (db_stack, Just _to_modify, _flag_dbs) <- + getPkgDatabases verbosity True{-modify-} True{-use cache-} my_flags + + (db, ps) <- fmap head $ findPackagesByDB db_stack (Id pkgid) let + db_name = location db + pkgs = packages db + pids = map sourcePackageId ps - modify pkg - | sourcePackageId pkg `elem` pids = fn pkg - | otherwise = [pkg] - new_config = concat (map modify pkgs) - let + cmds = [ fn pkg | pkg <- pkgs, sourcePackageId pkg `elem` pids ] + new_db = updateInternalDB db cmds + old_broken = brokenPackages (allPackagesInStack db_stack) - rest_of_stack = [ (nm, mypkgs) - | (nm, mypkgs) <- db_stack, nm /= db_name ] - new_stack = (db_name,new_config) : rest_of_stack + rest_of_stack = filter ((/= db_name) . location) db_stack + new_stack = new_db : rest_of_stack new_broken = map sourcePackageId (brokenPackages (allPackagesInStack new_stack)) newly_broken = filter (`notElem` map sourcePackageId old_broken) new_broken -- @@ -608,7 +738,17 @@ modifyPackage fn pkgid verbosity my_flags force = do " would break the following packages: " ++ unwords (map display newly_broken)) - writeNewConfig verbosity db_name new_config + changeDB verbosity cmds db + +recache :: Verbosity -> [Flag] -> IO () +recache verbosity my_flags = do + (db_stack, Just to_modify, _flag_dbs) <- + getPkgDatabases verbosity True{-modify-} False{-no cache-} my_flags + let + db_to_operate_on = my_head "recache" $ + filter ((== to_modify).location) db_stack + -- + changeDB verbosity [] db_to_operate_on -- ----------------------------------------------------------------------------- -- Listing packages @@ -618,18 +758,21 @@ listPackages :: Verbosity -> [Flag] -> Maybe PackageArg -> IO () listPackages verbosity my_flags mPackageName mModuleName = do let simple_output = FlagSimpleOutput `elem` my_flags - (db_stack, _) <- getPkgDatabases False my_flags + (db_stack, _, flag_db_stack) <- + getPkgDatabases verbosity False True{-use cache-} my_flags + let db_stack_filtered -- if a package is given, filter out all other packages | Just this <- mPackageName = - map (\(conf,pkgs) -> (conf, filter (this `matchesPkg`) pkgs)) - db_stack + [ db{ packages = filter (this `matchesPkg`) (packages db) } + | db <- flag_db_stack ] | Just match <- mModuleName = -- packages which expose mModuleName - map (\(conf,pkgs) -> (conf, filter (match `exposedInPkg`) pkgs)) - db_stack - | otherwise = db_stack + [ db{ packages = filter (match `exposedInPkg`) (packages db) } + | db <- flag_db_stack ] + | otherwise = flag_db_stack db_stack_sorted - = [ (db, sort_pkgs pkgs) | (db,pkgs) <- db_stack_filtered ] + = [ db{ packages = sort_pkgs (packages db) } + | db <- db_stack_filtered ] where sort_pkgs = sortBy cmpPkgIds cmpPkgIds pkg1 pkg2 = case pkgName p1 `compare` pkgName p2 of @@ -638,38 +781,65 @@ listPackages verbosity my_flags mPackageName mModuleName = do EQ -> pkgVersion p1 `compare` pkgVersion p2 where (p1,p2) = (sourcePackageId pkg1, sourcePackageId pkg2) + stack = reverse db_stack_sorted + match `exposedInPkg` pkg = any match (map display $ exposedModules pkg) pkg_map = allPackagesInStack db_stack broken = map sourcePackageId (brokenPackages pkg_map) - show_func = if simple_output then show_simple else mapM_ show_normal - - show_normal (db_name,pkg_confs) = - hPutStrLn stdout (render $ - text db_name <> colon $$ nest 4 packages - ) - where packages - | verbosity >= Verbose = vcat (map pp_pkg pkg_confs) - | otherwise = fsep (punctuate comma (map pp_pkg pkg_confs)) + show_normal PackageDB{ location = db_name, packages = pkg_confs } = + hPutStrLn stdout $ unlines ((db_name ++ ":") : map (" " ++) pp_pkgs) + where + pp_pkgs = map pp_pkg pkg_confs pp_pkg p - | sourcePackageId p `elem` broken = braces doc + | sourcePackageId p `elem` broken = printf "{%s}" doc | exposed p = doc - | otherwise = parens doc - where doc | verbosity >= Verbose = pkg <+> parens ipid + | otherwise = printf "(%s)" doc + where doc | verbosity >= Verbose = printf "%s (%s)" pkg ipid | otherwise = pkg where - InstalledPackageId ipid_str = installedPackageId p - ipid = text ipid_str - pkg = text (display (sourcePackageId p)) + InstalledPackageId ipid = installedPackageId p + pkg = display (sourcePackageId p) show_simple = simplePackageList my_flags . allPackagesInStack - when (not (null broken) && verbosity /= Silent) $ do + when (not (null broken) && not simple_output && verbosity /= Silent) $ do prog <- getProgramName putStrLn ("WARNING: there are broken packages. Run '" ++ prog ++ " check' for more details.") - show_func (reverse db_stack_sorted) + if simple_output then show_simple stack else do + +#if __GLASGOW_HASKELL__ < 611 + mapM_ show_normal stack +#else + let + show_colour withF db = + mconcat $ map (<#> termText "\n") $ + (termText (location db) : + map (termText " " <#>) (map pp_pkg (packages db))) + where + pp_pkg p + | sourcePackageId p `elem` broken = withF Red doc + | exposed p = doc + | otherwise = withF Blue doc + where doc | verbosity >= Verbose + = termText (printf "%s (%s)" pkg ipid) + | otherwise + = termText pkg + where + InstalledPackageId ipid = installedPackageId p + pkg = display (sourcePackageId p) + + is_tty <- hIsTerminalDevice stdout + if not is_tty + then mapM_ show_normal stack + else do tty <- Terminfo.setupTermFromEnv + case Terminfo.getCapability tty withForegroundColor of + Nothing -> mapM_ show_normal stack + Just w -> runTermOutput tty $ mconcat $ + map (show_colour w) stack +#endif simplePackageList :: [Flag] -> [InstalledPackageInfo] -> IO () simplePackageList my_flags pkgs = do @@ -680,9 +850,11 @@ simplePackageList my_flags pkgs = do hPutStrLn stdout $ concat $ intersperse " " strs showPackageDot :: Verbosity -> [Flag] -> IO () -showPackageDot _verbosity myflags = do - (db_stack, _) <- getPkgDatabases False myflags - let all_pkgs = allPackagesInStack db_stack +showPackageDot verbosity myflags = do + (_, _, flag_db_stack) <- + getPkgDatabases verbosity False True{-use cache-} myflags + + let all_pkgs = allPackagesInStack flag_db_stack ipix = PackageIndex.listToInstalledPackageIndex all_pkgs putStrLn "digraph {" @@ -699,10 +871,12 @@ showPackageDot _verbosity myflags = do -- ----------------------------------------------------------------------------- -- Prints the highest (hidden or exposed) version of a package -latestPackage :: [Flag] -> PackageIdentifier -> IO () -latestPackage my_flags pkgid = do - (db_stack, _) <- getPkgDatabases False my_flags - ps <- findPackages db_stack (Id pkgid) +latestPackage :: Verbosity -> [Flag] -> PackageIdentifier -> IO () +latestPackage verbosity my_flags pkgid = do + (_, _, flag_db_stack) <- + getPkgDatabases verbosity False True{-use cache-} my_flags + + ps <- findPackages flag_db_stack (Id pkgid) show_pkg (sortBy compPkgIdVer (map sourcePackageId ps)) where show_pkg [] = die "no matches" @@ -711,16 +885,18 @@ latestPackage my_flags pkgid = do -- ----------------------------------------------------------------------------- -- Describe -describePackage :: [Flag] -> PackageArg -> IO () -describePackage my_flags pkgarg = do - (db_stack, _) <- getPkgDatabases False my_flags - ps <- findPackages db_stack pkgarg +describePackage :: Verbosity -> [Flag] -> PackageArg -> IO () +describePackage verbosity my_flags pkgarg = do + (_, _, flag_db_stack) <- + getPkgDatabases verbosity False True{-use cache-} my_flags + ps <- findPackages flag_db_stack pkgarg doDump ps -dumpPackages :: [Flag] -> IO () -dumpPackages my_flags = do - (db_stack, _) <- getPkgDatabases False my_flags - doDump (allPackagesInStack db_stack) +dumpPackages :: Verbosity -> [Flag] -> IO () +dumpPackages verbosity my_flags = do + (_, _, flag_db_stack) <- + getPkgDatabases verbosity False True{-use cache-} my_flags + doDump (allPackagesInStack flag_db_stack) doDump :: [InstalledPackageInfo] -> IO () doDump = mapM_ putStrLn . intersperse "---" . map showInstalledPackageInfo @@ -731,11 +907,11 @@ findPackages db_stack pkgarg = fmap (concatMap snd) $ findPackagesByDB db_stack pkgarg findPackagesByDB :: PackageDBStack -> PackageArg - -> IO [(NamedPackageDB, [InstalledPackageInfo])] + -> IO [(PackageDB, [InstalledPackageInfo])] findPackagesByDB db_stack pkgarg = case [ (db, matched) - | db@(_, pkgs) <- db_stack, - let matched = filter (pkgarg `matchesPkg`) pkgs, + | db <- db_stack, + let matched = filter (pkgarg `matchesPkg`) (packages db), not (null matched) ] of [] -> die ("cannot find package " ++ pkg_msg pkgarg) ps -> return ps @@ -762,12 +938,13 @@ compPkgIdVer p1 p2 = pkgVersion p1 `compare` pkgVersion p2 -- ----------------------------------------------------------------------------- -- Field -describeField :: [Flag] -> PackageArg -> [String] -> IO () -describeField my_flags pkgarg fields = do - (db_stack, _) <- getPkgDatabases False my_flags +describeField :: Verbosity -> [Flag] -> PackageArg -> [String] -> IO () +describeField verbosity my_flags pkgarg fields = do + (_, _, flag_db_stack) <- + getPkgDatabases verbosity False True{-use cache-} my_flags fns <- toFields fields - ps <- findPackages db_stack pkgarg - let top_dir = takeDirectory (fst (last db_stack)) + ps <- findPackages flag_db_stack pkgarg + let top_dir = takeDirectory (location (last flag_db_stack)) mapM_ (selectFields fns) (mungePackagePaths top_dir ps) where toFields [] = return [] toFields (f:fs) = case toField f of @@ -828,9 +1005,9 @@ strList = show -- ----------------------------------------------------------------------------- -- Check: Check consistency of installed packages -checkConsistency :: [Flag] -> IO () -checkConsistency my_flags = do - (db_stack, _) <- getPkgDatabases True my_flags +checkConsistency :: Verbosity -> [Flag] -> IO () +checkConsistency verbosity my_flags = do + (db_stack, _, _) <- getPkgDatabases verbosity True True{-use cache-} my_flags -- check behaves like modify for the purposes of deciding which -- databases to use, because ordering is important. @@ -912,12 +1089,12 @@ convertPackageInfoIn where convert = fromJust . simpleParse writeNewConfig :: Verbosity -> FilePath -> [InstalledPackageInfo] -> IO () -writeNewConfig verbosity filename packages = do +writeNewConfig verbosity filename ipis = do when (verbosity >= Normal) $ hPutStr stdout "Writing new package config file... " createDirectoryIfMissing True $ takeDirectory filename let shown = concat $ intersperse ",\n " - $ map (show . convertPackageInfoOut) packages + $ map (show . convertPackageInfoOut) ipis fileContents = "[" ++ shown ++ "\n]" writeFileAtomic filename fileContents `catch` \e -> @@ -1028,7 +1205,7 @@ checkDuplicates :: PackageDBStack -> InstalledPackageInfo -> Bool -> Validate () checkDuplicates db_stack pkg update = do let pkgid = sourcePackageId pkg - (_top_db_name, pkgs) : _ = db_stack + pkgs = packages (head db_stack) -- -- Check whether this package id already exists in this DB -- diff --git a/utils/ghc-pkg/ghc-pkg.cabal b/utils/ghc-pkg/ghc-pkg.cabal index 393e44d..0b8bb37 100644 --- a/utils/ghc-pkg/ghc-pkg.cabal +++ b/utils/ghc-pkg/ghc-pkg.cabal @@ -38,7 +38,7 @@ Executable ghc-pkg if impl(ghc < 6.9) Build-Depends: extensible-exceptions - Build-Depends: haskell98, filepath, Cabal + Build-Depends: haskell98, filepath, Cabal, bin-package-db if !os(windows) Build-Depends: unix if os(windows) diff --git a/utils/ghc-pkg/ghc.mk b/utils/ghc-pkg/ghc.mk index 6c582d0..ae15376 100644 --- a/utils/ghc-pkg/ghc.mk +++ b/utils/ghc-pkg/ghc.mk @@ -31,8 +31,8 @@ endif else $(GHC_PKG_INPLACE) : utils/ghc-pkg/dist/build/$(utils/ghc-pkg_dist_PROG)$(exeext) $(MKDIRHIER) - "$(MKDIRHIER)" $(dir $(INPLACE_PACKAGE_CONF)) - echo "[]" > $(INPLACE_PACKAGE_CONF) + "$(MKDIRHIER)" $(INPLACE_PACKAGE_CONF) + "$(RM)" $(RM_OPTS) $(INPLACE_PACKAGE_CONF)/* ifeq "$(Windows)" "YES" cp $< $@ else @@ -59,7 +59,10 @@ utils/ghc-pkg/dist/build/$(utils/ghc-pkg_dist_PROG)$(exeext): utils/ghc-pkg/Main -ilibraries/Cabal \ -ilibraries/filepath \ -ilibraries/extensible-exceptions \ - -ilibraries/hpc + -ilibraries/hpc \ + -ilibraries/binary/src \ + -ilibraries/bin-package-db \ + utils/ghc-pkg/Version.hs: mk/project.mk "$(RM)" $(RM_OPTS) $@ @@ -78,7 +81,7 @@ $(eval $(call clean-target,utils/ghc-pkg,dist,\ utils/ghc-pkg_dist-install_PROG = ghc-pkg utils/ghc-pkg_dist-install_MODULES = Main Version -utils/ghc-pkg_dist-install_DEPS = Cabal +utils/ghc-pkg_dist-install_DEPS = Cabal terminfo bin-package-db utils/ghc-pkg_dist-install_SHELL_WRAPPER = YES utils/ghc-pkg_dist-install_INSTALL_SHELL_WRAPPER = YES utils/ghc-pkg_dist-install_INSTALL_SHELL_WRAPPER_NAME = ghc-pkg-$(ProjectVersion) -- 1.7.10.4