diff --git a/Cabal/Cabal.cabal b/Cabal/Cabal.cabal
index dfba3a70e8efc304b617e6229b35dac62102d5fa..a1ba5580e70ca33d95386907510cc1044f17849c 100644
--- a/Cabal/Cabal.cabal
+++ b/Cabal/Cabal.cabal
@@ -120,6 +120,10 @@ extra-source-files:
   tests/PackageTests/TestSuiteTests/LibV09/LibV09.cabal
   tests/PackageTests/TestSuiteTests/LibV09/Lib.hs
   tests/PackageTests/TestSuiteTests/LibV09/tests/Deadlock.hs
+  tests/PackageTests/UniqueIPID/P1/M.hs
+  tests/PackageTests/UniqueIPID/P1/my.cabal
+  tests/PackageTests/UniqueIPID/P2/M.hs
+  tests/PackageTests/UniqueIPID/P2/my.cabal
   tests/Setup.hs
   tests/Test/Distribution/Version.hs
   tests/Test/Laws.hs
@@ -316,6 +320,7 @@ test-suite package-tests
     PackageTests.TestStanza.Check
     PackageTests.TestSuiteTests.ExeV10.Check
     PackageTests.TestSuiteTests.LibV09.Check
+    PackageTests.UniqueIPID.Check
     Test.Distribution.Version
     Test.Laws
     Test.QuickCheck.Utils
diff --git a/Cabal/Distribution/InstalledPackageInfo.hs b/Cabal/Distribution/InstalledPackageInfo.hs
index 2ca113fb96e00192abf5acd43a34a806bd99c544..fa4f721d4b910c6ca5bdbf5b65f6b58c39191b86 100644
--- a/Cabal/Distribution/InstalledPackageInfo.hs
+++ b/Cabal/Distribution/InstalledPackageInfo.hs
@@ -27,8 +27,8 @@
 -- This module is meant to be local-only to Distribution...
 
 module Distribution.InstalledPackageInfo (
+        AbiHash(..),
         InstalledPackageInfo(..),
-        libraryName,
         OriginalModule(..), ExposedModule(..),
         ParseResult(..), PError(..), PWarning,
         emptyInstalledPackageInfo,
@@ -50,9 +50,8 @@ import Distribution.ParseUtils
 import Distribution.License     ( License(..) )
 import Distribution.Package
          ( PackageName(..), PackageIdentifier(..)
-         , PackageId, InstalledPackageId(..)
-         , packageName, packageVersion, PackageKey(..)
-         , LibraryName(..) )
+         , PackageId, ComponentId(..)
+         , packageName, packageVersion, ComponentId(..) )
 import qualified Distribution.Package as Package
 import Distribution.ModuleName
          ( ModuleName )
@@ -66,17 +65,19 @@ import qualified Distribution.Compat.ReadP as Parse
 import Distribution.Compat.Binary  (Binary)
 import Data.Maybe   (fromMaybe)
 import GHC.Generics (Generic)
+import qualified Data.Char as Char
 
 -- -----------------------------------------------------------------------------
 -- The InstalledPackageInfo type
 
-
+-- For BC reasons, we continue to name this record an InstalledPackageInfo;
+-- but it would more accurately be called an InstalledUnitInfo with Backpack
 data InstalledPackageInfo
    = InstalledPackageInfo {
         -- these parts are exactly the same as PackageDescription
-        installedPackageId :: InstalledPackageId,
         sourcePackageId    :: PackageId,
-        packageKey         :: PackageKey,
+        installedComponentId:: ComponentId,
+        compatPackageKey   :: ComponentId,
         license           :: License,
         copyright         :: String,
         maintainer        :: String,
@@ -88,6 +89,7 @@ data InstalledPackageInfo
         description       :: String,
         category          :: String,
         -- these parts are required by an installed package only:
+        abiHash           :: AbiHash,
         exposed           :: Bool,
         exposedModules    :: [ExposedModule],
         instantiatedWith  :: [(ModuleName, OriginalModule)],
@@ -101,7 +103,7 @@ data InstalledPackageInfo
         extraGHCiLibraries:: [String],    -- overrides extraLibraries for GHCi
         includeDirs       :: [FilePath],
         includes          :: [String],
-        depends           :: [InstalledPackageId],
+        depends           :: [ComponentId],
         ccOptions         :: [String],
         ldOptions         :: [String],
         frameworkDirs     :: [FilePath],
@@ -112,16 +114,13 @@ data InstalledPackageInfo
     }
     deriving (Generic, Read, Show)
 
-libraryName :: InstalledPackageInfo -> LibraryName
-libraryName ipi = Package.packageKeyLibraryName (sourcePackageId ipi) (packageKey ipi)
-
 instance Binary InstalledPackageInfo
 
 instance Package.Package InstalledPackageInfo where
    packageId = sourcePackageId
 
-instance Package.HasInstalledPackageId InstalledPackageInfo where
-   installedPackageId = installedPackageId
+instance Package.HasComponentId InstalledPackageInfo where
+   installedComponentId = installedComponentId
 
 instance Package.PackageInstalled InstalledPackageInfo where
    installedDepends = depends
@@ -129,10 +128,9 @@ instance Package.PackageInstalled InstalledPackageInfo where
 emptyInstalledPackageInfo :: InstalledPackageInfo
 emptyInstalledPackageInfo
    = InstalledPackageInfo {
-        installedPackageId = InstalledPackageId "",
         sourcePackageId    = PackageIdentifier (PackageName "") noVersion,
-        packageKey         = OldPackageKey (PackageIdentifier
-                                               (PackageName "") noVersion),
+        installedComponentId         = ComponentId "",
+        compatPackageKey   = ComponentId "",
         license           = UnspecifiedLicense,
         copyright         = "",
         maintainer        = "",
@@ -143,6 +141,7 @@ emptyInstalledPackageInfo
         synopsis          = "",
         description       = "",
         category          = "",
+        abiHash           = AbiHash "",
         exposed           = False,
         exposedModules    = [],
         hiddenModules     = [],
@@ -172,9 +171,20 @@ noVersion = Version [] []
 -- -----------------------------------------------------------------------------
 -- Exposed modules
 
+newtype AbiHash = AbiHash String
+    deriving (Show, Read, Generic)
+instance Binary AbiHash
+
+instance Text AbiHash where
+    disp (AbiHash abi) = Disp.text abi
+    parse = fmap AbiHash (Parse.munch Char.isAlphaNum)
+
+-- -----------------------------------------------------------------------------
+-- Exposed modules
+
 data OriginalModule
    = OriginalModule {
-       originalPackageId :: InstalledPackageId,
+       originalPackageId :: ComponentId,
        originalModuleName :: ModuleName
      }
   deriving (Generic, Eq, Read, Show)
@@ -287,10 +297,10 @@ basicFieldDescrs =
                            packageVersion         (\ver pkg -> pkg{sourcePackageId=(sourcePackageId pkg){pkgVersion=ver}})
  , simpleField "id"
                            disp                   parse
-                           installedPackageId     (\ipid pkg -> pkg{installedPackageId=ipid})
+                           installedComponentId             (\pk pkg -> pkg{installedComponentId=pk})
  , simpleField "key"
                            disp                   parse
-                           packageKey             (\pk pkg -> pkg{packageKey=pk})
+                           compatPackageKey       (\pk pkg -> pkg{compatPackageKey=pk})
  , simpleField "license"
                            disp                   parseLicenseQ
                            license                (\l pkg -> pkg{license=l})
@@ -333,6 +343,9 @@ installedFieldDescrs = [
  , listField   "hidden-modules"
         disp               parseModuleNameQ
         hiddenModules      (\xs    pkg -> pkg{hiddenModules=xs})
+ , simpleField "abi"
+        disp               parse
+        abiHash            (\abi    pkg -> pkg{abiHash=abi})
  , listField   "instantiated-with"
         showInstantiatedWith parseInstantiatedWith
         instantiatedWith   (\xs    pkg -> pkg{instantiatedWith=xs})
diff --git a/Cabal/Distribution/Package.hs b/Cabal/Distribution/Package.hs
index 56682c3fe28c2498eddab3422b8c2ae2acfc6e19..f451d4f218bc18eeb5731ea6800b6a3d9c8c701d 100644
--- a/Cabal/Distribution/Package.hs
+++ b/Cabal/Distribution/Package.hs
@@ -21,18 +21,8 @@ module Distribution.Package (
         PackageIdentifier(..),
         PackageId,
 
-        -- * Installed package identifiers
-        InstalledPackageId(..),
-
-        -- * Package keys (used for linker symbols)
-        PackageKey(..),
-        mkPackageKey,
-        packageKeyHash,
-        packageKeyLibraryName,
-
-        -- * Library name (used for install path, package key)
-        LibraryName(..),
-        emptyLibraryName,
+        -- * Package keys/installed package IDs (used for linker symbols)
+        ComponentId(..),
         getHSLibraryName,
 
         -- * Package source dependencies
@@ -43,7 +33,7 @@ module Distribution.Package (
 
         -- * Package classes
         Package(..), packageName, packageVersion,
-        HasInstalledPackageId(..),
+        HasComponentId(..),
         PackageInstalled(..),
   ) where
 
@@ -51,7 +41,7 @@ import Distribution.Version
          ( Version(..), VersionRange, anyVersion, thisVersion
          , notThisVersion, simplifyVersionRange )
 
-import Distribution.Text (Text(..), display)
+import Distribution.Text (Text(..))
 import qualified Distribution.Compat.ReadP as Parse
 import Distribution.Compat.ReadP ((<++))
 import qualified Text.PrettyPrint as Disp
@@ -59,14 +49,11 @@ import qualified Text.PrettyPrint as Disp
 import Control.DeepSeq (NFData(..))
 import Distribution.Compat.Binary (Binary)
 import qualified Data.Char as Char
-    ( isDigit, isAlphaNum, isUpper, isLower, ord, chr )
+    ( isDigit, isAlphaNum, )
 import Data.Data ( Data )
-import Data.List ( intercalate, foldl', sort )
+import Data.List ( intercalate )
 import Data.Typeable ( Typeable )
-import Data.Word ( Word64 )
-import GHC.Fingerprint ( Fingerprint(..), fingerprintString )
 import GHC.Generics (Generic)
-import Numeric ( showIntAtBase )
 import Text.PrettyPrint ((<>), (<+>), text)
 
 newtype PackageName = PackageName { unPackageName :: String }
@@ -116,188 +103,31 @@ instance NFData PackageIdentifier where
     rnf (PackageIdentifier name version) = rnf name `seq` rnf version
 
 -- ------------------------------------------------------------
--- * Installed Package Ids
+-- * Component Source Hash
 -- ------------------------------------------------------------
 
--- | An InstalledPackageId uniquely identifies an instance of an installed
--- package.  There can be at most one package with a given 'InstalledPackageId'
--- in a package database, or overlay of databases.
+-- | A 'ComponentId' uniquely identifies the transitive source
+-- code closure of a component.  For non-Backpack components, it also
+-- serves as the basis for install paths, symbols, etc.
 --
-newtype InstalledPackageId = InstalledPackageId String
- deriving (Generic, Read,Show,Eq,Ord,Typeable,Data)
-
-instance Binary InstalledPackageId
-
-instance Text InstalledPackageId where
-  disp (InstalledPackageId str) = text str
-
-  parse = InstalledPackageId `fmap` Parse.munch1 abi_char
-   where abi_char c = Char.isAlphaNum c || c `elem` "-_."
-
--- ------------------------------------------------------------
--- * Package Keys
--- ------------------------------------------------------------
-
--- | A 'PackageKey' is the notion of "package ID" which is visible to the
--- compiler. Why is this not a 'PackageId'? The 'PackageId' is a user-visible
--- concept written explicity in Cabal files; on the other hand, a 'PackageKey'
--- may contain, for example, information about the transitive dependency
--- tree of a package.  Why is this not an 'InstalledPackageId'?  A 'PackageKey'
--- should be stable so that we can incrementally recompile after a source edit;
--- however, an 'InstalledPackageId' may change even with source.
---
--- Package keys may be generated either by Cabal or GHC.  In particular,
--- ordinary, "old-style" packages which don't use Backpack features can
--- have their package keys generated directly by Cabal and coincide with
--- 'LibraryName's.  However, Backpack keys are generated by GHC may exhibit
--- more variation than a 'LibraryName'.
---
-data PackageKey
-    -- | Modern package key which is a hash of the PackageId and the transitive
-    -- dependency key.  It's manually inlined here so we can get the instances
-    -- we need.  There's an optional prefix for compatibility with GHC 7.10.
-    = PackageKey (Maybe String) {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64
-    -- | Old-style package key which is just a 'PackageId'.  Required because
-    -- old versions of GHC assume that the 'sourcePackageId' recorded for an
-    -- installed package coincides with the package key it was compiled with.
-    | OldPackageKey !PackageId
+data ComponentId
+    = ComponentId String
     deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)
 
-instance Binary PackageKey
-
--- | Convenience function which converts a fingerprint into a new-style package
--- key.
-fingerprintPackageKey :: Fingerprint -> PackageKey
-fingerprintPackageKey (Fingerprint a b) = PackageKey Nothing a b
-
--- | Generates a 'PackageKey' from a 'PackageId', sorted package keys of the
--- immediate dependencies.
-mkPackageKey :: Bool -- are modern style package keys supported?
-             -> PackageId
-             -> [LibraryName] -- dependencies
-             -> PackageKey
-mkPackageKey True pid deps =
-    fingerprintPackageKey . fingerprintString $
-        display pid ++ "\n" ++
-        concat [ display dep ++ "\n" | dep <- sort deps ]
-mkPackageKey False pid _ = OldPackageKey pid
-
--- The base-62 code is based off of 'locators'
--- ((c) Operational Dynamics Consulting, BSD3 licensed)
-
--- Note: Instead of base-62 encoding a single 128-bit integer
--- (ceil(21.49) characters), we'll base-62 a pair of 64-bit integers
--- (2 * ceil(10.75) characters).  Luckily for us, it's the same number of
--- characters!  In the long term, this should go in GHC.Fingerprint,
--- but not now...
-
--- | Size of a 64-bit word when written as a base-62 string
-word64Base62Len :: Int
-word64Base62Len = 11
-
--- | Converts a 64-bit word into a base-62 string
-toBase62 :: Word64 -> String
-toBase62 w = pad ++ str
-  where
-    pad = replicate len '0'
-    len = word64Base62Len - length str -- 11 == ceil(64 / lg 62)
-    str = showIntAtBase 62 represent w ""
-    represent :: Int -> Char
-    represent x
-        | x < 10 = Char.chr (48 + x)
-        | x < 36 = Char.chr (65 + x - 10)
-        | x < 62 = Char.chr (97 + x - 36)
-        | otherwise = error ("represent (base 62): impossible!")
-
--- | Parses a base-62 string into a 64-bit word
-fromBase62 :: String -> Word64
-fromBase62 ss = foldl' multiply 0 ss
-  where
-    value :: Char -> Int
-    value c
-        | Char.isDigit c = Char.ord c - 48
-        | Char.isUpper c = Char.ord c - 65 + 10
-        | Char.isLower c = Char.ord c - 97 + 36
-        | otherwise = error ("value (base 62): impossible!")
-
-    multiply :: Word64 -> Char -> Word64
-    multiply acc c = acc * 62 + (fromIntegral $ value c)
-
--- | Parses a base-62 string into a fingerprint.
-readBase62Fingerprint :: String -> Fingerprint
-readBase62Fingerprint s = Fingerprint w1 w2
- where (s1,s2) = splitAt word64Base62Len s
-       w1 = fromBase62 s1
-       w2 = fromBase62 (take word64Base62Len s2)
-
--- | Compute the hash (without a prefix) of a package key.  In GHC 7.12
--- this is equivalent to display.
-packageKeyHash :: PackageKey -> String
-packageKeyHash (PackageKey _ w1 w2) = toBase62 w1 ++ toBase62 w2
-packageKeyHash (OldPackageKey pid) = display pid
-
--- | Legacy function for GHC 7.10 to compute a LibraryName based on
--- the package key.
-packageKeyLibraryName :: PackageId -> PackageKey -> LibraryName
-packageKeyLibraryName pid (PackageKey _ w1 w2) =
-  LibraryName (display pid ++ "-" ++ toBase62 w1 ++ toBase62 w2)
-packageKeyLibraryName _ (OldPackageKey pid) = LibraryName (display pid)
-
-instance Text PackageKey where
-  disp (PackageKey mb_prefix w1 w2)
-    = maybe Disp.empty (\r -> Disp.text r <> Disp.char '_') mb_prefix <>
-      Disp.text (toBase62 w1) <> Disp.text (toBase62 w2)
-  disp (OldPackageKey pid) = disp pid
-
-  parse = parseNewWithAnnot <++ parseNew <++ parseOld
-    where parseNew = do
-            fmap (fingerprintPackageKey . readBase62Fingerprint)
-                . Parse.count (word64Base62Len * 2)
-                $ Parse.satisfy Char.isAlphaNum
-          parseNewWithAnnot = do
-            -- this is ignored
-            prefix <- Parse.munch1 (\c -> Char.isAlphaNum c || c `elem` "-")
-            _ <- Parse.char '_' -- if we use '-' it's ambiguous
-            PackageKey _ w1 w2 <- parseNew
-            return (PackageKey (Just prefix) w1 w2)
-          parseOld = do pid <- parse
-                        return (OldPackageKey pid)
-
-instance NFData PackageKey where
-    rnf (PackageKey mb _ _) = rnf mb
-    rnf (OldPackageKey pid) = rnf pid
-
--- ------------------------------------------------------------
--- * Library names
--- ------------------------------------------------------------
+instance Binary ComponentId
 
--- | A library name consists of not only a source package
--- id ('PackageId') but also the library names of all textual
--- dependencies; thus, a library name uniquely identifies an
--- installed package up to the dependency resolution done by Cabal.
--- Create using 'packageKeyLibraryName'.  Library names are opaque,
--- Cabal-defined strings.
-newtype LibraryName
-    = LibraryName String
-    deriving (Generic, Read, Show, Eq, Ord, Typeable, Data)
+instance Text ComponentId where
+  disp (ComponentId str) = text str
 
-instance Binary LibraryName
+  parse = ComponentId `fmap` Parse.munch1 abi_char
+   where abi_char c = Char.isAlphaNum c || c `elem` "-_."
 
--- | Default library name for when it is not known.
-emptyLibraryName :: LibraryName
-emptyLibraryName = LibraryName ""
+instance NFData ComponentId where
+    rnf (ComponentId pk) = rnf pk
 
 -- | Returns library name prefixed with HS, suitable for filenames
-getHSLibraryName :: LibraryName -> String
-getHSLibraryName (LibraryName s) = "HS" ++ s
-
-instance Text LibraryName where
-    disp (LibraryName s) = Disp.text s
-    parse = LibraryName `fmap` Parse.munch1 hash_char
-        where hash_char c = Char.isAlphaNum c || c `elem` "-_."
-
-instance NFData LibraryName where
-    rnf (LibraryName s) = rnf s
+getHSLibraryName :: ComponentId -> String
+getHSLibraryName (ComponentId s) = "HS" ++ s
 
 -- ------------------------------------------------------------
 -- * Package source dependencies
@@ -358,8 +188,8 @@ instance Package PackageIdentifier where
   packageId = id
 
 -- | Packages that have an installed package ID
-class Package pkg => HasInstalledPackageId pkg where
-  installedPackageId :: pkg -> InstalledPackageId
+class Package pkg => HasComponentId pkg where
+  installedComponentId :: pkg -> ComponentId
 
 -- | Class of installed packages.
 --
@@ -367,5 +197,5 @@ class Package pkg => HasInstalledPackageId pkg where
 -- 'InstalledPackageInfo', but when we are doing install plans in Cabal install
 -- we may have other, installed package-like things which contain more metadata.
 -- Installed packages have exact dependencies 'installedDepends'.
-class HasInstalledPackageId pkg => PackageInstalled pkg where
-  installedDepends :: pkg -> [InstalledPackageId]
+class (HasComponentId pkg) => PackageInstalled pkg where
+  installedDepends :: pkg -> [ComponentId]
diff --git a/Cabal/Distribution/Simple/Bench.hs b/Cabal/Distribution/Simple/Bench.hs
index aceb2380bbdd980edbd89647adf947209b7007e2..e08ed3a82601b8dbc3a73d763c106d7f2003bd54 100644
--- a/Cabal/Distribution/Simple/Bench.hs
+++ b/Cabal/Distribution/Simple/Bench.hs
@@ -24,7 +24,6 @@ import Distribution.Simple.InstallDirs
     ( fromPathTemplate, initialPathTemplateEnv, PathTemplateVariable(..)
     , substPathTemplate , toPathTemplate, PathTemplate )
 import qualified Distribution.Simple.LocalBuildInfo as LBI
-    ( LocalBuildInfo(..), localLibraryName )
 import Distribution.Simple.Setup ( BenchmarkFlags(..), fromFlag )
 import Distribution.Simple.UserHooks ( Args )
 import Distribution.Simple.Utils ( die, notice, rawSystemExitCode )
@@ -123,6 +122,6 @@ benchOption pkg_descr lbi bm template =
     fromPathTemplate $ substPathTemplate env template
   where
     env = initialPathTemplateEnv
-          (PD.package pkg_descr) (LBI.localLibraryName lbi)
+          (PD.package pkg_descr) (LBI.localComponentId lbi)
           (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi) ++
           [(BenchmarkNameVar, toPathTemplate $ PD.benchmarkName bm)]
diff --git a/Cabal/Distribution/Simple/Build.hs b/Cabal/Distribution/Simple/Build.hs
index 61d73b8f2162314f6d9dbae8778c0ef91903a7e5..f847ddb7ef66958adffd65d43a5d24966e95237d 100644
--- a/Cabal/Distribution/Simple/Build.hs
+++ b/Cabal/Distribution/Simple/Build.hs
@@ -35,8 +35,8 @@ import qualified Distribution.Simple.Build.PathsModule as Build.PathsModule
 
 import Distribution.Package
          ( Package(..), PackageName(..), PackageIdentifier(..)
-         , Dependency(..), thisPackageVersion, PackageKey(..), packageName
-         , LibraryName(..) )
+         , Dependency(..), thisPackageVersion, packageName
+         , ComponentId(..), ComponentId(..) )
 import Distribution.Simple.Compiler
          ( Compiler, CompilerFlavor(..), compilerFlavor
          , PackageDB(..), PackageDBStack )
@@ -60,8 +60,7 @@ import Distribution.Simple.LocalBuildInfo
          , ComponentLocalBuildInfo(..), pkgEnabledComponents
          , withComponentsInBuildOrder, componentsInBuildOrder
          , ComponentName(..), showComponentName
-         , ComponentDisabledReason(..), componentDisabledReason
-         , inplacePackageId )
+         , ComponentDisabledReason(..), componentDisabledReason )
 import Distribution.Simple.Program.Types
 import Distribution.Simple.Program.Db
 import qualified Distribution.Simple.Program.HcPkg as HcPkg
@@ -207,9 +206,8 @@ buildComponent verbosity numJobs pkg_descr lbi suffixes
     -- on internally defined libraries.
     pwd <- getCurrentDirectory
     let -- The in place registration uses the "-inplace" suffix, not an ABI hash
-        ipkgid           = inplacePackageId (packageId installedPkgInfo)
         installedPkgInfo = inplaceInstalledPackageInfo pwd distPref pkg_descr
-                                                       ipkgid lib' lbi clbi
+                                                       (IPI.AbiHash "") lib' lbi clbi
 
     registerPackage verbosity
       installedPkgInfo pkg_descr lbi True -- True meaning in place
@@ -407,9 +405,9 @@ testSuiteLibV09AsLibAndExe pkg_descr
     libClbi = LibComponentLocalBuildInfo
                 { componentPackageDeps = componentPackageDeps clbi
                 , componentPackageRenaming = componentPackageRenaming clbi
-                , componentLibraryName = LibraryName (testName test)
+                , componentId = ComponentId $ display (packageId pkg)
+                , componentCompatPackageKey = ComponentId $ display (packageId pkg)
                 , componentExposedModules = [IPI.ExposedModule m Nothing Nothing]
-                , componentPackageKey = OldPackageKey (PackageIdentifier (PackageName (testName test)) (pkgVersion (package pkg_descr)))
                 }
     pkg = pkg_descr {
             package      = (package pkg_descr) {
@@ -420,8 +418,7 @@ testSuiteLibV09AsLibAndExe pkg_descr
           , testSuites   = []
           , library      = Just lib
           }
-    ipkgid = inplacePackageId (packageId pkg)
-    ipi    = inplaceInstalledPackageInfo pwd distPref pkg ipkgid lib lbi libClbi
+    ipi    = inplaceInstalledPackageInfo pwd distPref pkg (IPI.AbiHash "") lib lbi libClbi
     testDir = buildDir lbi </> stubName test
           </> stubName test ++ "-tmp"
     testLibDep = thisPackageVersion $ package pkg
@@ -441,7 +438,7 @@ testSuiteLibV09AsLibAndExe pkg_descr
     -- that exposes the relevant test suite library.
     exeClbi = ExeComponentLocalBuildInfo {
                 componentPackageDeps =
-                    (IPI.installedPackageId ipi, packageId ipi)
+                    (IPI.installedComponentId ipi, packageId ipi)
                   : (filter (\(_, x) -> let PackageName name = pkgName x
                                         in name == "Cabal" || name == "base")
                             (componentPackageDeps clbi)),
diff --git a/Cabal/Distribution/Simple/Build/Macros.hs b/Cabal/Distribution/Simple/Build/Macros.hs
index f0429cd47f4c734fb8b83e904013cc1138c8c3fe..19892d2b00739533bc9e43d85cd3b1d20a3f6b20 100644
--- a/Cabal/Distribution/Simple/Build/Macros.hs
+++ b/Cabal/Distribution/Simple/Build/Macros.hs
@@ -33,7 +33,7 @@ import Distribution.PackageDescription
 import Distribution.Simple.Compiler
          ( packageKeySupported )
 import Distribution.Simple.LocalBuildInfo
-         ( LocalBuildInfo(compiler, withPrograms), externalPackageDeps, localPackageKey )
+         ( LocalBuildInfo(compiler, withPrograms), externalPackageDeps, localComponentId )
 import Distribution.Simple.Program.Db
          ( configuredPrograms )
 import Distribution.Simple.Program.Types
@@ -52,7 +52,7 @@ generate _pkg_descr lbi =
   "/* DO NOT EDIT: This file is automatically generated by Cabal */\n\n" ++
   generatePackageVersionMacros (map snd (externalPackageDeps lbi)) ++
   generateToolVersionMacros (configuredPrograms . withPrograms $ lbi) ++
-  generatePackageKeyMacro lbi
+  generateComponentIdMacro lbi
 
 -- | Helper function that generates just the @VERSION_pkg@ and @MIN_VERSION_pkg@
 -- macros for a list of package ids (usually used with the specific deps of
@@ -99,10 +99,10 @@ generateMacros prefix name version =
 -- | Generate the @CURRENT_PACKAGE_KEY@ definition for the package key
 --   of the current package, if supported by the compiler.
 --   NB: this only makes sense for definite packages.
-generatePackageKeyMacro :: LocalBuildInfo -> String
-generatePackageKeyMacro lbi
+generateComponentIdMacro :: LocalBuildInfo -> String
+generateComponentIdMacro lbi
   | packageKeySupported (compiler lbi) =
-      "#define CURRENT_PACKAGE_KEY \"" ++ display (localPackageKey lbi) ++ "\"\n\n"
+      "#define CURRENT_PACKAGE_KEY \"" ++ display (localComponentId lbi) ++ "\"\n\n"
   | otherwise = ""
 
 fixchar :: Char -> Char
diff --git a/Cabal/Distribution/Simple/Build/PathsModule.hs b/Cabal/Distribution/Simple/Build/PathsModule.hs
index 20ed4f16df6cbcdf7ff6cb505a30113a481898fc..28a356ecb2b8b1b970e2e883bf82da7e40af7ce8 100644
--- a/Cabal/Distribution/Simple/Build/PathsModule.hs
+++ b/Cabal/Distribution/Simple/Build/PathsModule.hs
@@ -27,9 +27,6 @@ import Distribution.Package
 import Distribution.PackageDescription
          ( PackageDescription(..), hasLibs )
 import Distribution.Simple.LocalBuildInfo
-         ( LocalBuildInfo(..), InstallDirs(..)
-         , absoluteInstallDirs, prefixRelativeInstallDirs )
-import Distribution.Simple.Setup ( CopyDest(NoCopyDest) )
 import Distribution.Simple.BuildPaths
          ( autogenModuleName )
 import Distribution.Simple.Utils
diff --git a/Cabal/Distribution/Simple/BuildPaths.hs b/Cabal/Distribution/Simple/BuildPaths.hs
index 4ed5790f817b1d12aec09ba9a84b472b6d2067b3..c5dd1ef6f375827e24d50c8a77f1016da4516048 100644
--- a/Cabal/Distribution/Simple/BuildPaths.hs
+++ b/Cabal/Distribution/Simple/BuildPaths.hs
@@ -34,7 +34,7 @@ module Distribution.Simple.BuildPaths (
 import System.FilePath ((</>), (<.>))
 
 import Distribution.Package
-         ( packageName, LibraryName, getHSLibraryName )
+         ( packageName, getHSLibraryName, ComponentId )
 import Distribution.ModuleName (ModuleName)
 import qualified Distribution.ModuleName as ModuleName
 import Distribution.Compiler
@@ -81,16 +81,16 @@ haddockName pkg_descr = display (packageName pkg_descr) <.> "haddock"
 -- ---------------------------------------------------------------------------
 -- Library file names
 
-mkLibName :: LibraryName -> String
+mkLibName :: ComponentId -> String
 mkLibName lib = "lib" ++ getHSLibraryName lib <.> "a"
 
-mkProfLibName :: LibraryName -> String
+mkProfLibName :: ComponentId -> String
 mkProfLibName lib =  "lib" ++ getHSLibraryName lib ++ "_p" <.> "a"
 
 -- Implement proper name mangling for dynamical shared objects
 -- libHS<packagename>-<compilerFlavour><compilerVersion>
 -- e.g. libHSbase-2.1-ghc6.6.1.so
-mkSharedLibName :: CompilerId -> LibraryName -> String
+mkSharedLibName :: CompilerId -> ComponentId -> String
 mkSharedLibName (CompilerId compilerFlavor compilerVersion) lib
   = "lib" ++ getHSLibraryName lib ++ "-" ++ comp <.> dllExtension
   where comp = display compilerFlavor ++ display compilerVersion
diff --git a/Cabal/Distribution/Simple/Compiler.hs b/Cabal/Distribution/Simple/Compiler.hs
index f217d73b404b54a279acce12c97ea5237fdfcd99..b588449d9be1c181da78b63bf7f18bf468742447 100644
--- a/Cabal/Distribution/Simple/Compiler.hs
+++ b/Cabal/Distribution/Simple/Compiler.hs
@@ -53,6 +53,7 @@ module Distribution.Simple.Compiler (
         parmakeSupported,
         reexportedModulesSupported,
         renamingPackageFlagsSupported,
+        unifiedIPIDRequired,
         packageKeySupported,
 
         -- * Support for profiling detail levels
@@ -276,6 +277,10 @@ reexportedModulesSupported = ghcSupported "Support reexported-modules"
 renamingPackageFlagsSupported :: Compiler -> Bool
 renamingPackageFlagsSupported = ghcSupported "Support thinning and renaming package flags"
 
+-- | Does this compiler have unified IPIDs (so no package keys)
+unifiedIPIDRequired :: Compiler -> Bool
+unifiedIPIDRequired = ghcSupported "Requires unified installed package IDs"
+
 -- | Does this compiler support package keys?
 packageKeySupported :: Compiler -> Bool
 packageKeySupported = ghcSupported "Uses package keys"
diff --git a/Cabal/Distribution/Simple/Configure.hs b/Cabal/Distribution/Simple/Configure.hs
index 644a019700ab27d39735c99568462beab30c8142..ed69d000c0246340f68b6236041a3fb031e6b965 100644
--- a/Cabal/Distribution/Simple/Configure.hs
+++ b/Cabal/Distribution/Simple/Configure.hs
@@ -37,6 +37,7 @@ module Distribution.Simple.Configure (configure,
                                       tryGetPersistBuildConfig,
                                       maybeGetPersistBuildConfig,
                                       findDistPref, findDistPrefOrDefault,
+                                      computeComponentId,
                                       localBuildInfoFile,
                                       getInstalledPackages, getPackageDBContents,
                                       configCompiler, configCompilerAux,
@@ -58,14 +59,14 @@ import Distribution.Simple.Compiler
     , compilerInfo, ProfDetailLevel(..), knownProfDetailLevels
     , showCompilerId, unsupportedLanguages, unsupportedExtensions
     , PackageDB(..), PackageDBStack, reexportedModulesSupported
-    , packageKeySupported, renamingPackageFlagsSupported )
+    , packageKeySupported, renamingPackageFlagsSupported
+    , unifiedIPIDRequired )
 import Distribution.Simple.PreProcess ( platformDefines )
 import Distribution.Package
     ( PackageName(PackageName), PackageIdentifier(..), PackageId
     , packageName, packageVersion, Package(..)
     , Dependency(Dependency), simplifyDependency
-    , InstalledPackageId(..), thisPackageVersion
-    , mkPackageKey, packageKeyLibraryName )
+    , ComponentId(..), thisPackageVersion, ComponentId(..) )
 import qualified Distribution.InstalledPackageInfo as Installed
 import Distribution.InstalledPackageInfo (InstalledPackageInfo, emptyInstalledPackageInfo)
 import qualified Distribution.Simple.PackageIndex as PackageIndex
@@ -75,7 +76,7 @@ import Distribution.PackageDescription as PD
     , Library(..), hasLibs, Executable(..), BuildInfo(..), allExtensions
     , HookedBuildInfo, updatePackageDescription, allBuildInfo
     , Flag(flagName), FlagName(..), TestSuite(..), Benchmark(..)
-    , ModuleReexport(..) , defaultRenaming )
+    , ModuleReexport(..) , defaultRenaming, FlagAssignment )
 import Distribution.ModuleName
     ( ModuleName )
 import Distribution.PackageDescription.Configuration
@@ -97,9 +98,10 @@ import Distribution.Simple.InstallDirs
     ( InstallDirs(..), defaultInstallDirs, combineInstallDirs )
 import Distribution.Simple.LocalBuildInfo
     ( LocalBuildInfo(..), Component(..), ComponentLocalBuildInfo(..)
-    , absoluteInstallDirs, prefixRelativeInstallDirs, inplacePackageId
+    , absoluteInstallDirs, prefixRelativeInstallDirs
     , ComponentName(..), showComponentName, pkgEnabledComponents
-    , componentBuildInfo, componentName, checkComponentsCyclic )
+    , componentBuildInfo, componentName, checkComponentsCyclic
+    , lookupComponent )
 import Distribution.Simple.BuildPaths
     ( autogenModulesDir )
 import Distribution.Simple.Utils
@@ -114,6 +116,8 @@ import Distribution.Version
          ( Version(..), anyVersion, orLaterVersion, withinRange, isAnyVersion )
 import Distribution.Verbosity
     ( Verbosity, lessVerbose )
+import Distribution.Simple.InstallDirs
+    ( fromPathTemplate, substPathTemplate, toPathTemplate, packageTemplateEnv )
 
 import qualified Distribution.Simple.GHC   as GHC
 import qualified Distribution.Simple.GHCJS as GHCJS
@@ -134,6 +138,7 @@ import Control.Exception ( ErrorCall(..) )
 import Control.Monad
     ( liftM, when, unless, foldM, filterM )
 import Distribution.Compat.Binary ( decodeOrFailIO, encode )
+import GHC.Fingerprint ( Fingerprint(..), fingerprintString )
 import Data.ByteString.Lazy (ByteString)
 import qualified Data.ByteString            as BS
 import qualified Data.ByteString.Lazy.Char8 as BLC8
@@ -153,6 +158,9 @@ import Data.Map (Map)
 import Data.Traversable
     ( mapM )
 import Data.Typeable
+import Data.Char ( chr, isAlphaNum )
+import Numeric ( showIntAtBase )
+import Data.Bits ( shift )
 import System.Directory
     ( doesFileExist, createDirectoryIfMissing, getTemporaryDirectory )
 import System.FilePath
@@ -404,9 +412,9 @@ configure (pkg_descr0, pbi) cfg
                 --TODO: should use a per-compiler method to map the source
                 --      package ID into an installed package id we can use
                 --      for the internal package set. The open-codes use of
-                --      InstalledPackageId . display here is a hack.
-                Installed.installedPackageId =
-                   InstalledPackageId $ display $ pid,
+                --      ComponentId . display here is a hack.
+                Installed.installedComponentId =
+                   ComponentId $ display $ pid,
                 Installed.sourcePackageId = pid
               }
             internalPackageSet = PackageIndex.fromList [internalPackage]
@@ -534,12 +542,12 @@ configure (pkg_descr0, pbi) cfg
 
         let installDeps = Map.elems
                         . Map.fromList
-                        . map (\v -> (Installed.installedPackageId v, v))
+                        . map (\v -> (Installed.installedComponentId v, v))
                         $ externalPkgDeps ++ holeDeps
 
         packageDependsIndex <-
           case PackageIndex.dependencyClosure installedPackageSet
-                  (map Installed.installedPackageId installDeps) of
+                  (map Installed.installedComponentId installDeps) of
             Left packageDependsIndex -> return packageDependsIndex
             Right broken ->
               die $ "The following installed packages are broken because other"
@@ -552,11 +560,11 @@ configure (pkg_descr0, pbi) cfg
                             | (pkg, deps) <- broken ]
 
         let pseudoTopPkg = emptyInstalledPackageInfo {
-                Installed.installedPackageId =
-                   InstalledPackageId (display (packageId pkg_descr)),
+                Installed.installedComponentId =
+                   ComponentId (display (packageId pkg_descr)),
                 Installed.sourcePackageId = packageId pkg_descr,
                 Installed.depends =
-                  map Installed.installedPackageId installDeps
+                  map Installed.installedComponentId installDeps
               }
         case PackageIndex.dependencyInconsistencies
            . PackageIndex.insert pseudoTopPkg
@@ -620,10 +628,10 @@ configure (pkg_descr0, pbi) cfg
           case mkComponentsGraph pkg_descr internalPkgDeps of
             Left  componentCycle -> reportComponentCycle componentCycle
             Right components     ->
-              mkComponentsLocalBuildInfo comp packageDependsIndex pkg_descr
+              mkComponentsLocalBuildInfo cfg comp packageDependsIndex pkg_descr
                                          internalPkgDeps externalPkgDeps holeDeps
                                          (Map.fromList hole_insts)
-                                         components
+                                         components (configConfigurationsFlags cfg)
 
         split_objs <-
            if not (fromFlag $ configSplitObjs cfg)
@@ -972,15 +980,15 @@ newPackageDepsBehaviour pkg =
 -- deps in the end. So we still need to remember which installed packages to
 -- pick.
 combinedConstraints :: [Dependency] ->
-                       [(PackageName, InstalledPackageId)] ->
+                       [(PackageName, ComponentId)] ->
                        InstalledPackageIndex ->
                        Either String ([Dependency],
                                       Map PackageName InstalledPackageInfo)
 combinedConstraints constraints dependencies installedPackages = do
 
-    when (not (null badInstalledPackageIds)) $
+    when (not (null badComponentIds)) $
       Left $ render $ text "The following package dependencies were requested"
-         $+$ nest 4 (dispDependencies badInstalledPackageIds)
+         $+$ nest 4 (dispDependencies badComponentIds)
          $+$ text "however the given installed package instance does not exist."
 
     when (not (null badNames)) $
@@ -1004,19 +1012,19 @@ combinedConstraints constraints dependencies installedPackages = do
                         | (_, _, Just pkg) <- dependenciesPkgInfo ]
 
     -- The dependencies along with the installed package info, if it exists
-    dependenciesPkgInfo :: [(PackageName, InstalledPackageId,
+    dependenciesPkgInfo :: [(PackageName, ComponentId,
                              Maybe InstalledPackageInfo)]
     dependenciesPkgInfo =
       [ (pkgname, ipkgid, mpkg)
       | (pkgname, ipkgid) <- dependencies
-      , let mpkg = PackageIndex.lookupInstalledPackageId
+      , let mpkg = PackageIndex.lookupComponentId
                      installedPackages ipkgid
       ]
 
     -- If we looked up a package specified by an installed package id
     -- (i.e. someone has written a hash) and didn't find it then it's
     -- an error.
-    badInstalledPackageIds =
+    badComponentIds =
       [ (pkgname, ipkgid)
       | (pkgname, ipkgid, Nothing) <- dependenciesPkgInfo ]
 
@@ -1070,7 +1078,7 @@ configureInstantiateWith pkg_descr cfg installedPackageSet = do
         -- TODO: internal dependencies (e.g. the test package depending on the
         -- main library) is not currently supported
         let selectHoleDependency (k,(i,m)) =
-              case PackageIndex.lookupInstalledPackageId installedPackageSet i of
+              case PackageIndex.lookupComponentId installedPackageSet i of
                 Just pkginst -> Right (k,(pkginst, m))
                 Nothing -> Left i
             (failed_hmap, hole_insts) = partitionEithers (map selectHoleDependency hole_insts0)
@@ -1294,7 +1302,46 @@ reportComponentCycle cnames =
             [ "'" ++ showComponentName cname ++ "'"
             | cname <- cnames ++ [head cnames] ]
 
-mkComponentsLocalBuildInfo :: Compiler
+-- | This method computes a default, "good enough" 'ComponentId'
+-- for a package.  The intent is that cabal-install (or the user) will
+-- specify a more detailed IPID via the @--ipid@ flag if necessary.
+computeComponentId :: PackageDescription
+            -> ComponentName
+            -- TODO: careful here!
+            -> [ComponentId] -- IPIDs of the component dependencies
+            -> FlagAssignment
+            -> IO ComponentId
+computeComponentId pkg_descr cname dep_ipids flagAssignment = do
+    -- show is found to be faster than intercalate and then replacement of
+    -- special character used in intercalating. We cannot simply hash by
+    -- doubly concating list, as it just flatten out the nested list, so
+    -- different sources can produce same hash
+    let hash = hashToBase62 $
+                (show $ dep_ipids)
+                      ++ show flagAssignment
+    return . ComponentId $
+                display (package pkg_descr)
+                    ++ "-" ++ hash
+                    ++ (case cname of
+                         CLibName -> ""
+                         -- TODO: these could result in non-parseable IPIDs
+                         -- since the component name format is very flexible
+                         CExeName   s -> "-" ++ s ++ ".exe"
+                         CTestName  s -> "-" ++ s ++ ".test"
+                         CBenchName s -> "-" ++ s ++ ".bench")
+  where
+    representBase62 x
+        | x < 10 = chr (48 + x)
+        | x < 36 = chr (65 + x - 10)
+        | x < 62 = chr (97 + x - 36)
+        | otherwise = '@'
+    fpToInteger (Fingerprint a b) =
+      toInteger a * (shift (1 :: Integer) 64) + toInteger b
+    hashToBase62 s = showIntAtBase 62 representBase62
+                      (fpToInteger $ fingerprintString s) ""
+
+mkComponentsLocalBuildInfo :: ConfigFlags
+                           -> Compiler
                            -> InstalledPackageIndex
                            -> PackageDescription
                            -> [PackageId] -- internal package deps
@@ -1302,49 +1349,80 @@ mkComponentsLocalBuildInfo :: Compiler
                            -> [InstalledPackageInfo] -- hole package deps
                            -> Map ModuleName (InstalledPackageInfo, ModuleName)
                            -> [(Component, [ComponentName])]
+                           -> FlagAssignment
                            -> IO [(ComponentName, ComponentLocalBuildInfo,
                                                   [ComponentName])]
-mkComponentsLocalBuildInfo comp installedPackages pkg_descr
+mkComponentsLocalBuildInfo cfg comp installedPackages pkg_descr
                            internalPkgDeps externalPkgDeps holePkgDeps hole_insts
-                           graph =
+                           graph flagAssignment = do
+    -- Pre-compute library hash so we can setup internal deps
+    lib_hash@(ComponentId str) <-
+      -- TODO configIPID should have name changed
+      case configIPID cfg of
+        Flag lib_hash0 ->
+            -- Hack to reuse install dirs machinery
+            -- NB: no real IPID available at this point
+            let env = packageTemplateEnv (package pkg_descr) (ComponentId "")
+                str = fromPathTemplate (substPathTemplate env (toPathTemplate lib_hash0))
+            in return (ComponentId str)
+        _ ->
+          computeComponentId pkg_descr CLibName (getDeps CLibName) flagAssignment
+    let extractCandidateCompatKey s
+            = case simpleParse s :: Maybe PackageId of
+                -- Something like 'foo-0.1', use it verbatim.
+                -- (NB: hash tags look like tags, so they are parsed,
+                -- so the extra equality check tests if a tag was dropped.)
+                Just pid | display pid == s -> s
+                -- Something like 'foo-0.1-XXX', take the stuff at the end.
+                -- TODO this won't work with component stuff
+                _ -> reverse (takeWhile isAlphaNum (reverse s))
+        cand_compat_key = ComponentId (extractCandidateCompatKey str)
+        old_style_key = ComponentId (display (package pkg_descr))
+        best_key = ComponentId str
+        compat_key =
+            if packageKeySupported comp
+                then if unifiedIPIDRequired comp
+                        then best_key
+                        else cand_compat_key
+                else old_style_key
     sequence
-      [ do clbi <- componentLocalBuildInfo c
+      [ do clbi <- componentLocalBuildInfo lib_hash compat_key c
            return (componentName c, clbi, cdeps)
       | (c, cdeps) <- graph ]
   where
+    getDeps cname =
+          let externalPkgs = maybe [] (\lib -> selectSubset (componentBuildInfo lib)
+                                                            externalPkgDeps)
+                                      (lookupComponent pkg_descr cname)
+          in map Installed.installedComponentId externalPkgs
+
     -- The allPkgDeps contains all the package deps for the whole package
     -- but we need to select the subset for this specific component.
     -- we just take the subset for the package names this component
     -- needs. Note, this only works because we cannot yet depend on two
     -- versions of the same package.
-    componentLocalBuildInfo component =
+    componentLocalBuildInfo lib_hash compat_key component =
       case component of
       CLib lib -> do
         let exports = map (\n -> Installed.ExposedModule n Nothing Nothing)
                           (PD.exposedModules lib)
             esigs = map (\n -> Installed.ExposedModule n Nothing
                                 (fmap (\(pkg,m) -> Installed.OriginalModule
-                                                      (Installed.installedPackageId pkg) m)
+                                                      (Installed.installedComponentId pkg) m)
                                       (Map.lookup n hole_insts)))
                         (PD.exposedSignatures lib)
         let mb_reexports = resolveModuleReexports installedPackages
                                                   (packageId pkg_descr)
+                                                  lib_hash
                                                   externalPkgDeps lib
         reexports <- case mb_reexports of
             Left problems -> reportModuleReexportProblems problems
             Right r -> return r
 
-        -- Calculate the version hash and package key.
-        let externalPkgs = selectSubset bi externalPkgDeps
-            pkg_key = mkPackageKey (packageKeySupported comp)
-                        (package pkg_descr)
-                        (map Installed.libraryName externalPkgs)
-            version_hash = packageKeyLibraryName (package pkg_descr) pkg_key
-
         return LibComponentLocalBuildInfo {
           componentPackageDeps = cpds,
-          componentPackageKey = pkg_key,
-          componentLibraryName = version_hash,
+          componentId = lib_hash,
+          componentCompatPackageKey = compat_key,
           componentPackageRenaming = cprns,
           componentExposedModules = exports ++ reexports ++ esigs
         }
@@ -1368,11 +1446,11 @@ mkComponentsLocalBuildInfo comp installedPackages pkg_descr
         dedup = Map.toList . Map.fromList
         cpds = if newPackageDepsBehaviour pkg_descr
                then dedup $
-                    [ (Installed.installedPackageId pkg, packageId pkg)
+                    [ (Installed.installedComponentId pkg, packageId pkg)
                     | pkg <- selectSubset bi externalPkgDeps ]
-                 ++ [ (inplacePackageId pkgid, pkgid)
+                 ++ [ (lib_hash, pkgid)
                     | pkgid <- selectSubset bi internalPkgDeps ]
-               else [ (Installed.installedPackageId pkg, packageId pkg)
+               else [ (Installed.installedComponentId pkg, packageId pkg)
                     | pkg <- externalPkgDeps ]
         cprns = if newPackageDepsBehaviour pkg_descr
                 then Map.unionWith mappend
@@ -1405,11 +1483,12 @@ mkComponentsLocalBuildInfo comp installedPackages pkg_descr
 --
 resolveModuleReexports :: InstalledPackageIndex
                        -> PackageId
+                       -> ComponentId
                        -> [InstalledPackageInfo]
                        -> Library
                        -> Either [(ModuleReexport, String)] -- errors
                                  [Installed.ExposedModule] -- ok
-resolveModuleReexports installedPackages srcpkgid externalPkgDeps lib =
+resolveModuleReexports installedPackages srcpkgid key externalPkgDeps lib =
     case partitionEithers (map resolveModuleReexport (PD.reexportedModules lib)) of
       ([],  ok) -> Right ok
       (errs, _) -> Left  errs
@@ -1425,9 +1504,9 @@ resolveModuleReexports installedPackages srcpkgid externalPkgDeps lib =
                                                   exposedModule)])
           -- The package index here contains all the indirect deps of the
           -- package we're configuring, but we want just the direct deps
-        | let directDeps = Set.fromList (map Installed.installedPackageId externalPkgDeps)
+        | let directDeps = Set.fromList (map Installed.installedComponentId externalPkgDeps)
         , pkg <- PackageIndex.allPackages installedPackages
-        , Installed.installedPackageId pkg `Set.member` directDeps
+        , Installed.installedComponentId pkg `Set.member` directDeps
         , let exportingPackageName = packageName pkg
         , exposedModule <- visibleModuleDetails pkg
         ]
@@ -1436,9 +1515,7 @@ resolveModuleReexports installedPackages srcpkgid externalPkgDeps lib =
                             ++ otherModules (libBuildInfo lib)
         , let exportingPackageName = packageName srcpkgid
               definingModuleName   = visibleModuleName
-              -- we don't know the InstalledPackageId of this package yet
-              -- we will fill it in later, before registration.
-              definingPackageId    = InstalledPackageId ""
+              definingPackageId    = key
               originalModule = Installed.OriginalModule definingPackageId
                                                         definingModuleName
               exposedModule  = Installed.ExposedModule visibleModuleName
@@ -1457,7 +1534,7 @@ resolveModuleReexports installedPackages srcpkgid externalPkgDeps lib =
         -- The first case is the modules actually defined in this package.
         -- In this case the reexport will point to this package.
             Nothing -> return exposedModule { Installed.exposedReexport =
-                            Just (Installed.OriginalModule (Installed.installedPackageId pkg)
+                            Just (Installed.OriginalModule (Installed.installedComponentId pkg)
                                                  (Installed.exposedName exposedModule)) }
         -- On the other hand, a visible module might actually be itself
         -- a re-export! In this case, the re-export info for the package
diff --git a/Cabal/Distribution/Simple/GHC.hs b/Cabal/Distribution/Simple/GHC.hs
index ee3df77b1c8be35c38fc1cb3afe46e8c8b92f409..4e466dc818514fd52134048266dd564ece45c01f 100644
--- a/Cabal/Distribution/Simple/GHC.hs
+++ b/Cabal/Distribution/Simple/GHC.hs
@@ -428,7 +428,7 @@ buildOrReplLib :: Bool -> Verbosity  -> Cabal.Flag (Maybe Int)
                -> PackageDescription -> LocalBuildInfo
                -> Library            -> ComponentLocalBuildInfo -> IO ()
 buildOrReplLib forRepl verbosity numJobs pkg_descr lbi lib clbi = do
-  let libName = componentLibraryName clbi
+  let libName = componentId clbi
       libTargetDir = buildDir lbi
       whenVanillaLib forceVanilla =
         when (forceVanilla || withVanillaLib lbi)
@@ -1090,7 +1090,7 @@ installLib verbosity lbi targetDir dynlibTargetDir builtDir _pkg lib clbi = do
       >>= installOrdinaryFiles verbosity targetDir
 
     cid = compilerId (compiler lbi)
-    libName = componentLibraryName clbi
+    libName = componentId clbi
     vanillaLibName = mkLibName              libName
     profileLibName = mkProfLibName          libName
     ghciLibName    = Internal.mkGHCiLibName libName
diff --git a/Cabal/Distribution/Simple/GHC/IPI641.hs b/Cabal/Distribution/Simple/GHC/IPI641.hs
index 4bb995dea17497e1193796cc4eee071358234f50..c18ab50bfe6e3ea5974c473c5852454d9d6a29e7 100644
--- a/Cabal/Distribution/Simple/GHC/IPI641.hs
+++ b/Cabal/Distribution/Simple/GHC/IPI641.hs
@@ -14,7 +14,7 @@ module Distribution.Simple.GHC.IPI641 (
   ) where
 
 import qualified Distribution.InstalledPackageInfo as Current
-import qualified Distribution.Package as Current hiding (installedPackageId)
+import qualified Distribution.Package as Current hiding (installedComponentId)
 import Distribution.Text (display)
 
 import Distribution.Simple.GHC.IPI642
@@ -61,17 +61,17 @@ data InstalledPackageInfo = InstalledPackageInfo {
   }
   deriving Read
 
-mkInstalledPackageId :: Current.PackageIdentifier -> Current.InstalledPackageId
-mkInstalledPackageId = Current.InstalledPackageId . display
+mkComponentId :: Current.PackageIdentifier -> Current.ComponentId
+mkComponentId = Current.ComponentId . display
 
 toCurrent :: InstalledPackageInfo -> Current.InstalledPackageInfo
 toCurrent ipi@InstalledPackageInfo{} =
   let pid = convertPackageId (package ipi)
       mkExposedModule m = Current.ExposedModule m Nothing Nothing
   in Current.InstalledPackageInfo {
-    Current.installedPackageId = mkInstalledPackageId (convertPackageId (package ipi)),
     Current.sourcePackageId    = pid,
-    Current.packageKey         = Current.OldPackageKey pid,
+    Current.installedComponentId         = mkComponentId pid,
+    Current.compatPackageKey   = mkComponentId pid,
     Current.license            = convertLicense (license ipi),
     Current.copyright          = copyright ipi,
     Current.maintainer         = maintainer ipi,
@@ -82,6 +82,7 @@ toCurrent ipi@InstalledPackageInfo{} =
     Current.synopsis           = "",
     Current.description        = description ipi,
     Current.category           = category ipi,
+    Current.abiHash            = Current.AbiHash "",
     Current.exposed            = exposed ipi,
     Current.exposedModules     = map (mkExposedModule . convertModuleName) (exposedModules ipi),
     Current.instantiatedWith   = [],
@@ -95,7 +96,7 @@ toCurrent ipi@InstalledPackageInfo{} =
     Current.extraGHCiLibraries = [],
     Current.includeDirs        = includeDirs ipi,
     Current.includes           = includes ipi,
-    Current.depends            = map (mkInstalledPackageId.convertPackageId) (depends ipi),
+    Current.depends            = map (mkComponentId.convertPackageId) (depends ipi),
     Current.ccOptions          = ccOptions ipi,
     Current.ldOptions          = ldOptions ipi,
     Current.frameworkDirs      = frameworkDirs ipi,
diff --git a/Cabal/Distribution/Simple/GHC/IPI642.hs b/Cabal/Distribution/Simple/GHC/IPI642.hs
index 25145f1ab1037fb2f4c73d06c176ffa3118d10c5..eed9a8dfc1f88b04b6bd0aa85123c8a74db370b0 100644
--- a/Cabal/Distribution/Simple/GHC/IPI642.hs
+++ b/Cabal/Distribution/Simple/GHC/IPI642.hs
@@ -19,7 +19,7 @@ module Distribution.Simple.GHC.IPI642 (
   ) where
 
 import qualified Distribution.InstalledPackageInfo as Current
-import qualified Distribution.Package as Current hiding (installedPackageId)
+import qualified Distribution.Package as Current hiding (installedComponentId)
 import qualified Distribution.License as Current
 
 import Distribution.Version (Version)
@@ -84,8 +84,8 @@ convertPackageId :: PackageIdentifier -> Current.PackageIdentifier
 convertPackageId PackageIdentifier { pkgName = n, pkgVersion = v } =
   Current.PackageIdentifier (Current.PackageName n) v
 
-mkInstalledPackageId :: Current.PackageIdentifier -> Current.InstalledPackageId
-mkInstalledPackageId = Current.InstalledPackageId . display
+mkComponentId :: Current.PackageIdentifier -> Current.ComponentId
+mkComponentId = Current.ComponentId . display
 
 convertModuleName :: String -> ModuleName
 convertModuleName s = fromJust $ simpleParse s
@@ -104,9 +104,10 @@ toCurrent ipi@InstalledPackageInfo{} =
   let pid = convertPackageId (package ipi)
       mkExposedModule m = Current.ExposedModule m Nothing Nothing
   in Current.InstalledPackageInfo {
-    Current.installedPackageId = mkInstalledPackageId (convertPackageId (package ipi)),
     Current.sourcePackageId    = pid,
-    Current.packageKey         = Current.OldPackageKey pid,
+    Current.installedComponentId         = mkComponentId pid,
+    Current.compatPackageKey   = mkComponentId pid,
+    Current.abiHash            = Current.AbiHash "", -- bogus but old GHCs don't care.
     Current.license            = convertLicense (license ipi),
     Current.copyright          = copyright ipi,
     Current.maintainer         = maintainer ipi,
@@ -130,7 +131,7 @@ toCurrent ipi@InstalledPackageInfo{} =
     Current.extraGHCiLibraries = extraGHCiLibraries ipi,
     Current.includeDirs        = includeDirs ipi,
     Current.includes           = includes ipi,
-    Current.depends            = map (mkInstalledPackageId.convertPackageId) (depends ipi),
+    Current.depends            = map (mkComponentId.convertPackageId) (depends ipi),
     Current.ccOptions          = ccOptions ipi,
     Current.ldOptions          = ldOptions ipi,
     Current.frameworkDirs      = frameworkDirs ipi,
diff --git a/Cabal/Distribution/Simple/GHC/Internal.hs b/Cabal/Distribution/Simple/GHC/Internal.hs
index 5c412e6879cfbfaa832a3bb4ea978d97b4df5161..ec37692fc3104c1d1aa1028de6ca5b9ae67832a3 100644
--- a/Cabal/Distribution/Simple/GHC/Internal.hs
+++ b/Cabal/Distribution/Simple/GHC/Internal.hs
@@ -31,8 +31,7 @@ module Distribution.Simple.GHC.Internal (
 
 import Distribution.Simple.GHC.ImplInfo ( GhcImplInfo (..) )
 import Distribution.Package
-         ( InstalledPackageId, PackageId, LibraryName
-         , getHSLibraryName )
+         ( PackageId, ComponentId, getHSLibraryName )
 import Distribution.InstalledPackageInfo
          ( InstalledPackageInfo )
 import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo
@@ -374,8 +373,8 @@ componentGhcOptions verbosity lbi bi clbi odir =
       ghcOptVerbosity       = toFlag verbosity,
       ghcOptHideAllPackages = toFlag True,
       ghcOptCabal           = toFlag True,
-      ghcOptPackageKey  = case clbi of
-        LibComponentLocalBuildInfo { componentPackageKey = pk } -> toFlag pk
+      ghcOptComponentId  = case clbi of
+        LibComponentLocalBuildInfo { componentCompatPackageKey = pk } -> toFlag pk
         _ -> mempty,
       ghcOptSigOf           = hole_insts,
       ghcOptPackageDBs      = withPackageDB lbi,
@@ -413,7 +412,7 @@ componentGhcOptions verbosity lbi bi clbi odir =
     toGhcDebugInfo NormalDebugInfo  = toFlag True
     toGhcDebugInfo MaximalDebugInfo = toFlag True
 
-    hole_insts = map (\(k,(p,n)) -> (k, (InstalledPackageInfo.packageKey p,n)))
+    hole_insts = map (\(k,(p,n)) -> (k, (InstalledPackageInfo.installedComponentId p,n)))
                  (instantiatedWith lbi)
 
 -- | Strip out flags that are not supported in ghci
@@ -429,7 +428,7 @@ filterGhciFlags = filter supported
     supported "-unreg"    = False
     supported _           = True
 
-mkGHCiLibName :: LibraryName -> String
+mkGHCiLibName :: ComponentId -> String
 mkGHCiLibName lib = getHSLibraryName lib <.> "o"
 
 ghcLookupProperty :: String -> Compiler -> Bool
@@ -460,7 +459,7 @@ getHaskellObjects implInfo lib lbi pref wanted_obj_ext allow_split_objs
                | x <- libModules lib ]
 
 mkGhcOptPackages :: ComponentLocalBuildInfo
-                 -> [(InstalledPackageId, PackageId, ModuleRenaming)]
+                 -> [(ComponentId, PackageId, ModuleRenaming)]
 mkGhcOptPackages clbi =
   map (\(i,p) -> (i,p,lookupRenaming p (componentPackageRenaming clbi)))
       (componentPackageDeps clbi)
diff --git a/Cabal/Distribution/Simple/GHCJS.hs b/Cabal/Distribution/Simple/GHCJS.hs
index 6b3157d200d978367c3a381c9b4c184fbb1211c0..13a33ecad02ccabb1d6211f1997cf34a56231c17 100644
--- a/Cabal/Distribution/Simple/GHCJS.hs
+++ b/Cabal/Distribution/Simple/GHCJS.hs
@@ -26,7 +26,7 @@ import Distribution.InstalledPackageInfo
          ( InstalledPackageInfo )
 import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo
                                 ( InstalledPackageInfo(..) )
-import Distribution.Package ( LibraryName(..), getHSLibraryName )
+import Distribution.Package ( ComponentId(..), getHSLibraryName )
 import Distribution.Simple.PackageIndex ( InstalledPackageIndex )
 import qualified Distribution.Simple.PackageIndex as PackageIndex
 import Distribution.Simple.LocalBuildInfo
@@ -301,7 +301,7 @@ buildOrReplLib :: Bool -> Verbosity  -> Cabal.Flag (Maybe Int)
                -> PackageDescription -> LocalBuildInfo
                -> Library            -> ComponentLocalBuildInfo -> IO ()
 buildOrReplLib forRepl verbosity numJobs _pkg_descr lbi lib clbi = do
-  let libName@(LibraryName cname) = componentLibraryName clbi
+  let libName@(ComponentId cname) = componentId clbi
       libTargetDir = buildDir lbi
       whenVanillaLib forceVanilla =
         when (not forRepl && (forceVanilla || withVanillaLib lbi))
@@ -312,7 +312,7 @@ buildOrReplLib forRepl verbosity numJobs _pkg_descr lbi lib clbi = do
       ifReplLib = when forRepl
       comp = compiler lbi
       implInfo = getImplInfo comp
-      hole_insts = map (\(k,(p,n)) -> (k,(InstalledPackageInfo.packageKey p,n)))
+      hole_insts = map (\(k,(p,n)) -> (k,(InstalledPackageInfo.installedComponentId p,n)))
                        (instantiatedWith lbi)
       nativeToo = ghcjsNativeToo comp
 
@@ -756,7 +756,7 @@ installLib verbosity lbi targetDir dynlibTargetDir builtDir _pkg lib clbi = do
       >>= installOrdinaryFiles verbosity targetDir
 
     cid = compilerId (compiler lbi)
-    libName = componentLibraryName clbi
+    libName = componentId clbi
     vanillaLibName = mkLibName              libName
     profileLibName = mkProfLibName          libName
     ghciLibName    = Internal.mkGHCiLibName libName
diff --git a/Cabal/Distribution/Simple/Haddock.hs b/Cabal/Distribution/Simple/Haddock.hs
index 3746395af0548dcaf726e9615edb5a25f8d883b8..94c1520b3a8d082819f0bd089ea6a677fe5b48b2 100644
--- a/Cabal/Distribution/Simple/Haddock.hs
+++ b/Cabal/Distribution/Simple/Haddock.hs
@@ -27,7 +27,7 @@ import qualified Distribution.Simple.GHCJS as GHCJS
 import Distribution.Package
          ( PackageIdentifier(..)
          , Package(..)
-         , PackageName(..), packageName, LibraryName(..) )
+         , PackageName(..), packageName, ComponentId(..) )
 import qualified Distribution.ModuleName as ModuleName
 import Distribution.PackageDescription as PD
          ( PackageDescription(..), BuildInfo(..), usedExtensions
@@ -631,7 +631,7 @@ haddockPackageFlags lbi clbi htmlTemplate = do
 haddockTemplateEnv :: LocalBuildInfo -> PackageIdentifier -> PathTemplateEnv
 haddockTemplateEnv lbi pkg_id =
   (PrefixVar, prefix (installDirTemplates lbi))
-  : initialPathTemplateEnv pkg_id (LibraryName (display pkg_id)) (compilerInfo (compiler lbi))
+  : initialPathTemplateEnv pkg_id (ComponentId (display pkg_id)) (compilerInfo (compiler lbi))
   (hostPlatform lbi)
 
 -- ------------------------------------------------------------------------------
diff --git a/Cabal/Distribution/Simple/HaskellSuite.hs b/Cabal/Distribution/Simple/HaskellSuite.hs
index bcfebfa8b68cf26738816064222459801ce446f3..1eea7503e8bc66defed271c28e6e5a0ce3098d88 100644
--- a/Cabal/Distribution/Simple/HaskellSuite.hs
+++ b/Cabal/Distribution/Simple/HaskellSuite.hs
@@ -190,8 +190,9 @@ installLib
   -> FilePath  -- ^Build location
   -> PackageDescription
   -> Library
+  -> ComponentLocalBuildInfo
   -> IO ()
-installLib verbosity lbi targetDir dynlibTargetDir builtDir pkg lib = do
+installLib verbosity lbi targetDir dynlibTargetDir builtDir pkg lib _clbi = do
   let conf = withPrograms lbi
   runDbProgram verbosity haskellSuitePkgProgram conf $
     [ "install-library"
diff --git a/Cabal/Distribution/Simple/Install.hs b/Cabal/Distribution/Simple/Install.hs
index c9c9e68827be199c05ab1fc84a87383f8253c40e..b3d5bcbfc6d8d0778737f9deab9c6571662b3004 100644
--- a/Cabal/Distribution/Simple/Install.hs
+++ b/Cabal/Distribution/Simple/Install.hs
@@ -16,13 +16,9 @@ module Distribution.Simple.Install (
         install,
   ) where
 
-import Distribution.PackageDescription (
-        PackageDescription(..), BuildInfo(..), Library(..),
-        hasLibs, withLib, hasExes, withExe )
+import Distribution.PackageDescription
 import Distribution.Package (Package(..))
-import Distribution.Simple.LocalBuildInfo (
-        LocalBuildInfo(..), InstallDirs(..), absoluteInstallDirs,
-        substPathTemplate, withLibLBI)
+import Distribution.Simple.LocalBuildInfo
 import Distribution.Simple.BuildPaths (haddockName, haddockPref)
 import Distribution.Simple.Utils
          ( createDirectoryIfMissingVerbose
@@ -69,6 +65,8 @@ install pkg_descr lbi flags = do
          htmldir    = htmlPref,
          haddockdir = interfacePref,
          includedir = incPref})
+             -- Using the library clbi for binPref is a hack;
+             -- binPref should be computed per executable
              = absoluteInstallDirs pkg_descr lbi copydest
 
       --TODO: decide if we need the user to be able to control the libdir
@@ -126,32 +124,33 @@ install pkg_descr lbi flags = do
 
   -- install include files for all compilers - they may be needed to compile
   -- haskell files (using the CPP extension)
+  --
   when (hasLibs pkg_descr) $ installIncludeFiles verbosity pkg_descr incPref
 
-  case compilerFlavor (compiler lbi) of
-     GHC  -> do withLibLBI pkg_descr lbi $
-                  GHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr
-                withExe pkg_descr $
-                  GHC.installExe verbosity lbi installDirs buildPref (progPrefixPref, progSuffixPref) pkg_descr
-     GHCJS-> do withLibLBI pkg_descr lbi $
-                  GHCJS.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr
-                withExe pkg_descr $
-                  GHCJS.installExe verbosity lbi installDirs buildPref (progPrefixPref, progSuffixPref) pkg_descr
-     LHC  -> do withLibLBI pkg_descr lbi $
-                  LHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr
-                withExe pkg_descr $
-                  LHC.installExe verbosity lbi installDirs buildPref (progPrefixPref, progSuffixPref) pkg_descr
-     JHC  -> do withLib pkg_descr $
-                  JHC.installLib verbosity libPref buildPref pkg_descr
-                withExe pkg_descr $
-                  JHC.installExe verbosity binPref buildPref (progPrefixPref, progSuffixPref) pkg_descr
-     UHC  -> do withLib pkg_descr $ UHC.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr
-     HaskellSuite {} ->
-       withLib pkg_descr $
-         HaskellSuite.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr
-     _    -> die $ "installing with "
-                ++ display (compilerFlavor (compiler lbi))
-                ++ " is not implemented"
+  withLibLBI pkg_descr lbi $
+    case compilerFlavor (compiler lbi) of
+      GHC   -> GHC.installLib   verbosity lbi libPref dynlibPref buildPref pkg_descr
+      GHCJS -> GHCJS.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr
+      LHC   -> LHC.installLib   verbosity lbi libPref dynlibPref buildPref pkg_descr
+      JHC   -> JHC.installLib   verbosity lbi libPref dynlibPref buildPref pkg_descr
+      UHC   -> UHC.installLib   verbosity lbi libPref dynlibPref buildPref pkg_descr
+      HaskellSuite _ -> HaskellSuite.installLib
+                                verbosity lbi libPref dynlibPref buildPref pkg_descr
+      _ -> \_ _ -> die $ "installing with "
+                      ++ display (compilerFlavor (compiler lbi))
+                      ++ " is not implemented"
+
+  withExe pkg_descr $
+    case compilerFlavor (compiler lbi) of
+      GHC   -> GHC.installExe   verbosity lbi installDirs buildPref (progPrefixPref, progSuffixPref) pkg_descr
+      GHCJS -> GHCJS.installExe verbosity lbi installDirs buildPref (progPrefixPref, progSuffixPref) pkg_descr
+      LHC   -> LHC.installExe   verbosity lbi installDirs buildPref (progPrefixPref, progSuffixPref) pkg_descr
+      JHC   -> JHC.installExe   verbosity binPref buildPref (progPrefixPref, progSuffixPref) pkg_descr
+      UHC   -> \_ -> return ()
+      HaskellSuite {} -> \_ -> return ()
+      _ -> \_ -> die $ "installing with "
+                    ++ display (compilerFlavor (compiler lbi))
+                    ++ " is not implemented"
   -- register step should be performed by caller.
 
 -- | Install the files listed in data-files
diff --git a/Cabal/Distribution/Simple/InstallDirs.hs b/Cabal/Distribution/Simple/InstallDirs.hs
index ac911237d662b4ea465158113ec26581fb5da538..25bb663a927b5e60c55981fdc7eddb7008ea200c 100644
--- a/Cabal/Distribution/Simple/InstallDirs.hs
+++ b/Cabal/Distribution/Simple/InstallDirs.hs
@@ -57,7 +57,7 @@ import System.FilePath ((</>), isPathSeparator, pathSeparator)
 import System.FilePath (dropDrive)
 
 import Distribution.Package
-         ( PackageIdentifier, packageName, packageVersion, LibraryName )
+         ( PackageIdentifier, packageName, packageVersion, ComponentId )
 import Distribution.System
          ( OS(..), buildOS, Platform(..) )
 import Distribution.Compiler
@@ -287,7 +287,7 @@ substituteInstallDirTemplates env dirs = dirs'
 -- substituting for all the variables in the abstract paths, to get real
 -- absolute path.
 absoluteInstallDirs :: PackageIdentifier
-                    -> LibraryName
+                    -> ComponentId
                     -> CompilerInfo
                     -> CopyDest
                     -> Platform
@@ -317,7 +317,7 @@ data CopyDest
 -- independent\" package).
 --
 prefixRelativeInstallDirs :: PackageIdentifier
-                          -> LibraryName
+                          -> ComponentId
                           -> CompilerInfo
                           -> Platform
                           -> InstallDirTemplates
@@ -372,7 +372,7 @@ data PathTemplateVariable =
      | PkgNameVar    -- ^ The @$pkg@ package name path variable
      | PkgVerVar     -- ^ The @$version@ package version path variable
      | PkgIdVar      -- ^ The @$pkgid@ package Id path variable, eg @foo-1.0@
-     | LibNameVar    -- ^ The @$libname@ expanded package key path variable
+     | LibNameVar    -- ^ The @$libname@ path variable
      | CompilerVar   -- ^ The compiler name and version, eg @ghc-6.6.1@
      | OSVar         -- ^ The operating system name, eg @windows@ or @linux@
      | ArchVar       -- ^ The CPU architecture name, eg @i386@ or @x86_64@
@@ -415,7 +415,7 @@ substPathTemplate environment (PathTemplate template) =
 
 -- | The initial environment has all the static stuff but no paths
 initialPathTemplateEnv :: PackageIdentifier
-                       -> LibraryName
+                       -> ComponentId
                        -> CompilerInfo
                        -> Platform
                        -> PathTemplateEnv
@@ -425,7 +425,7 @@ initialPathTemplateEnv pkgId libname compiler platform =
   ++ platformTemplateEnv platform
   ++ abiTemplateEnv compiler platform
 
-packageTemplateEnv :: PackageIdentifier -> LibraryName -> PathTemplateEnv
+packageTemplateEnv :: PackageIdentifier -> ComponentId -> PathTemplateEnv
 packageTemplateEnv pkgId libname =
   [(PkgNameVar,  PathTemplate [Ordinary $ display (packageName pkgId)])
   ,(PkgVerVar,   PathTemplate [Ordinary $ display (packageVersion pkgId)])
@@ -478,7 +478,7 @@ installDirsTemplateEnv dirs =
 
 instance Show PathTemplateVariable where
   show PrefixVar     = "prefix"
-  show LibNameVar     = "libname"
+  show LibNameVar    = "libname"
   show BindirVar     = "bindir"
   show LibdirVar     = "libdir"
   show LibsubdirVar  = "libsubdir"
@@ -515,8 +515,8 @@ instance Read PathTemplateVariable where
                  ,("docdir",     DocdirVar)
                  ,("htmldir",    HtmldirVar)
                  ,("pkgid",      PkgIdVar)
-                 ,("pkgkey",     LibNameVar) -- backwards compatibility
                  ,("libname",    LibNameVar)
+                 ,("pkgkey",     LibNameVar) -- backwards compatibility
                  ,("pkg",        PkgNameVar)
                  ,("version",    PkgVerVar)
                  ,("compiler",   CompilerVar)
diff --git a/Cabal/Distribution/Simple/JHC.hs b/Cabal/Distribution/Simple/JHC.hs
index 0cf8730298e680c6b062ba01b453c5127c6896cf..bb29109a3c019b7d62704299ef001d4c5b5adbe7 100644
--- a/Cabal/Distribution/Simple/JHC.hs
+++ b/Cabal/Distribution/Simple/JHC.hs
@@ -40,7 +40,7 @@ import Distribution.Simple.Program
 import Distribution.Version
          ( Version(..), orLaterVersion )
 import Distribution.Package
-         ( Package(..), InstalledPackageId(InstalledPackageId),
+         ( Package(..), ComponentId(ComponentId),
            pkgName, pkgVersion, )
 import Distribution.Simple.Utils
         ( createDirectoryIfMissingVerbose, writeFileAtomic
@@ -116,8 +116,8 @@ getInstalledPackages verbosity _packageDBs conf = do
    return $
       PackageIndex.fromList $
       map (\p -> emptyInstalledPackageInfo {
-                    InstalledPackageInfo.installedPackageId =
-                       InstalledPackageId (display p),
+                    InstalledPackageInfo.installedComponentId =
+                       ComponentId (display p),
                     InstalledPackageInfo.sourcePackageId = p
                  }) $
       concatMap parseLine $
@@ -181,8 +181,16 @@ jhcPkgConf pd =
              ,sline "hidden-modules" (comma . otherModules . libBuildInfo . lib)
              ]
 
-installLib :: Verbosity -> FilePath -> FilePath -> PackageDescription -> Library -> IO ()
-installLib verb dest build_dir pkg_descr _ = do
+installLib :: Verbosity
+           -> LocalBuildInfo
+           -> FilePath
+           -> FilePath
+           -> FilePath
+           -> PackageDescription
+           -> Library
+           -> ComponentLocalBuildInfo
+           -> IO ()
+installLib verb _lbi dest _dyn_dest build_dir pkg_descr _lib _clbi = do
     let p = display (packageId pkg_descr)++".hl"
     createDirectoryIfMissingVerbose verb True dest
     installOrdinaryFile verb (build_dir </> p) (dest </> p)
diff --git a/Cabal/Distribution/Simple/LHC.hs b/Cabal/Distribution/Simple/LHC.hs
index 1045c9a199bddaf13309165851438b5ba8b7d818..2363ac5cdd81bd443d3e8d57c607576b012ff448 100644
--- a/Cabal/Distribution/Simple/LHC.hs
+++ b/Cabal/Distribution/Simple/LHC.hs
@@ -59,7 +59,7 @@ import Distribution.Simple.InstallDirs
 import Distribution.Simple.BuildPaths
 import Distribution.Simple.Utils
 import Distribution.Package
-         ( Package(..), LibraryName, getHSLibraryName )
+         ( Package(..), getHSLibraryName, ComponentId )
 import qualified Distribution.ModuleName as ModuleName
 import Distribution.Simple.Program
          ( Program(..), ConfiguredProgram(..), ProgramConfiguration
@@ -318,7 +318,7 @@ substTopDir topDir ipo
 buildLib :: Verbosity -> PackageDescription -> LocalBuildInfo
                       -> Library            -> ComponentLocalBuildInfo -> IO ()
 buildLib verbosity pkg_descr lbi lib clbi = do
-  let libName = componentLibraryName clbi
+  let libName = componentId clbi
       pref = buildDir lbi
       pkgid = packageId pkg_descr
       runGhcProg = rawSystemProgramConf verbosity lhcProgram (withPrograms lbi)
@@ -682,7 +682,7 @@ ghcCcOptions lbi bi clbi odir
            _              -> ["-optc-O2"])
      ++ ["-odir", odir]
 
-mkGHCiLibName :: LibraryName -> String
+mkGHCiLibName :: ComponentId -> String
 mkGHCiLibName lib = getHSLibraryName lib <.> "o"
 
 -- -----------------------------------------------------------------------------
@@ -757,7 +757,7 @@ installLib verbosity lbi targetDir dynlibTargetDir builtDir _pkg lib clbi = do
 
   where
     cid = compilerId (compiler lbi)
-    libName = componentLibraryName clbi
+    libName = componentId clbi
     vanillaLibName = mkLibName           libName
     profileLibName = mkProfLibName       libName
     ghciLibName    = mkGHCiLibName       libName
diff --git a/Cabal/Distribution/Simple/LocalBuildInfo.hs b/Cabal/Distribution/Simple/LocalBuildInfo.hs
index 96043ba8adee1d0594707352d40c796a608e9f58..1e3f0cb2f5b38ff0bfe74da7be7b29843a043db1 100644
--- a/Cabal/Distribution/Simple/LocalBuildInfo.hs
+++ b/Cabal/Distribution/Simple/LocalBuildInfo.hs
@@ -20,9 +20,8 @@
 module Distribution.Simple.LocalBuildInfo (
         LocalBuildInfo(..),
         externalPackageDeps,
-        inplacePackageId,
-        localPackageKey,
-        localLibraryName,
+        localComponentId,
+        localCompatPackageKey,
 
         -- * Buildable package components
         Component(..),
@@ -71,8 +70,8 @@ import Distribution.PackageDescription
          , BuildInfo(buildable), Benchmark(..), ModuleRenaming(..) )
 import qualified Distribution.InstalledPackageInfo as Installed
 import Distribution.Package
-         ( PackageId, Package(..), InstalledPackageId(..)
-         , PackageName, LibraryName(..), PackageKey(..) )
+         ( PackageId, Package(..), ComponentId(..)
+         , PackageName, ComponentId(..) )
 import Distribution.Simple.Compiler
          ( Compiler, compilerInfo, PackageDBStack, DebugInfoLevel
          , OptimisationLevel, ProfDetailLevel )
@@ -152,29 +151,29 @@ data LocalBuildInfo = LocalBuildInfo {
 
 instance Binary LocalBuildInfo
 
--- | Extract the 'PackageKey' from the library component of a
+-- | Extract the 'ComponentId' from the library component of a
 -- 'LocalBuildInfo' if it exists, or make a fake package key based
 -- on the package ID.
-localPackageKey :: LocalBuildInfo -> PackageKey
-localPackageKey lbi =
-    foldr go (OldPackageKey (package (localPkgDescr lbi))) (componentsConfigs lbi)
+localComponentId :: LocalBuildInfo -> ComponentId
+localComponentId lbi =
+    foldr go (ComponentId (display (package (localPkgDescr lbi)))) (componentsConfigs lbi)
   where go (_, clbi, _) old_pk = case clbi of
-            LibComponentLocalBuildInfo { componentPackageKey = pk } -> pk
+            LibComponentLocalBuildInfo { componentId = pk } -> pk
             _ -> old_pk
 
--- | Extract the 'LibraryName' from the library component of a
--- 'LocalBuildInfo' if it exists, or make a library name based
+-- | Extract the compatibility 'ComponentId' from the library component of a
+-- 'LocalBuildInfo' if it exists, or make a fake package key based
 -- on the package ID.
-localLibraryName :: LocalBuildInfo -> LibraryName
-localLibraryName lbi =
-    foldr go (LibraryName (display (package (localPkgDescr lbi)))) (componentsConfigs lbi)
-  where go (_, clbi, _) old_n = case clbi of
-            LibComponentLocalBuildInfo { componentLibraryName = n } -> n
-            _ -> old_n
+localCompatPackageKey :: LocalBuildInfo -> ComponentId
+localCompatPackageKey lbi =
+    foldr go (ComponentId (display (package (localPkgDescr lbi)))) (componentsConfigs lbi)
+  where go (_, clbi, _) old_pk = case clbi of
+            LibComponentLocalBuildInfo { componentCompatPackageKey = pk } -> pk
+            _ -> old_pk
 
 -- | External package dependencies for the package as a whole. This is the
 -- union of the individual 'componentPackageDeps', less any internal deps.
-externalPackageDeps :: LocalBuildInfo -> [(InstalledPackageId, PackageId)]
+externalPackageDeps :: LocalBuildInfo -> [(ComponentId, PackageId)]
 externalPackageDeps lbi =
     -- TODO:  what about non-buildable components?
     nub [ (ipkgid, pkgid)
@@ -186,12 +185,6 @@ externalPackageDeps lbi =
     -- defined in the same package).
     internal pkgid = pkgid == packageId (localPkgDescr lbi)
 
--- | The installed package Id we use for local packages registered in the local
--- package db. This is what is used for intra-package deps between components.
---
-inplacePackageId :: PackageId -> InstalledPackageId
-inplacePackageId pkgid = InstalledPackageId (display pkgid ++ "-inplace")
-
 -- -----------------------------------------------------------------------------
 -- Buildable components
 
@@ -221,22 +214,22 @@ data ComponentLocalBuildInfo
     -- The 'BuildInfo' specifies a set of build dependencies that must be
     -- satisfied in terms of version ranges. This field fixes those dependencies
     -- to the specific versions available on this machine for this compiler.
-    componentPackageDeps :: [(InstalledPackageId, PackageId)],
-    componentPackageKey :: PackageKey,
-    componentLibraryName :: LibraryName,
+    componentPackageDeps :: [(ComponentId, PackageId)],
+    componentId :: ComponentId,
+    componentCompatPackageKey :: ComponentId,
     componentExposedModules :: [Installed.ExposedModule],
     componentPackageRenaming :: Map PackageName ModuleRenaming
   }
   | ExeComponentLocalBuildInfo {
-    componentPackageDeps :: [(InstalledPackageId, PackageId)],
+    componentPackageDeps :: [(ComponentId, PackageId)],
     componentPackageRenaming :: Map PackageName ModuleRenaming
   }
   | TestComponentLocalBuildInfo {
-    componentPackageDeps :: [(InstalledPackageId, PackageId)],
+    componentPackageDeps :: [(ComponentId, PackageId)],
     componentPackageRenaming :: Map PackageName ModuleRenaming
   }
   | BenchComponentLocalBuildInfo {
-    componentPackageDeps :: [(InstalledPackageId, PackageId)],
+    componentPackageDeps :: [(ComponentId, PackageId)],
     componentPackageRenaming :: Map PackageName ModuleRenaming
   }
   deriving (Generic, Read, Show)
@@ -492,7 +485,7 @@ absoluteInstallDirs :: PackageDescription -> LocalBuildInfo -> CopyDest
 absoluteInstallDirs pkg lbi copydest =
   InstallDirs.absoluteInstallDirs
     (packageId pkg)
-    (localLibraryName lbi)
+    (localComponentId lbi)
     (compilerInfo (compiler lbi))
     copydest
     (hostPlatform lbi)
@@ -504,7 +497,7 @@ prefixRelativeInstallDirs :: PackageId -> LocalBuildInfo
 prefixRelativeInstallDirs pkg_descr lbi =
   InstallDirs.prefixRelativeInstallDirs
     (packageId pkg_descr)
-    (localLibraryName lbi)
+    (localComponentId lbi)
     (compilerInfo (compiler lbi))
     (hostPlatform lbi)
     (installDirTemplates lbi)
@@ -515,6 +508,6 @@ substPathTemplate pkgid lbi = fromPathTemplate
                                 . ( InstallDirs.substPathTemplate env )
     where env = initialPathTemplateEnv
                    pkgid
-                   (localLibraryName lbi)
+                   (localComponentId lbi)
                    (compilerInfo (compiler lbi))
                    (hostPlatform lbi)
diff --git a/Cabal/Distribution/Simple/PackageIndex.hs b/Cabal/Distribution/Simple/PackageIndex.hs
index f1e2dc13ab699d7733fb008b37c07dd920379bbd..3d70d01e4e4f539fbf30bd52253691fc6329aa56 100644
--- a/Cabal/Distribution/Simple/PackageIndex.hs
+++ b/Cabal/Distribution/Simple/PackageIndex.hs
@@ -26,7 +26,7 @@ module Distribution.Simple.PackageIndex (
 
   insert,
 
-  deleteInstalledPackageId,
+  deleteComponentId,
   deleteSourcePackageId,
   deletePackageName,
 --  deleteDependency,
@@ -34,7 +34,7 @@ module Distribution.Simple.PackageIndex (
   -- * Queries
 
   -- ** Precise lookups
-  lookupInstalledPackageId,
+  lookupComponentId,
   lookupSourcePackageId,
   lookupPackageId,
   lookupPackageName,
@@ -84,8 +84,8 @@ import Distribution.Package
          ( PackageName(..), PackageId
          , Package(..), packageName, packageVersion
          , Dependency(Dependency)--, --PackageFixedDeps(..)
-         , InstalledPackageId(..)
-         , HasInstalledPackageId(..), PackageInstalled(..) )
+         , HasComponentId(..), PackageInstalled(..)
+         , ComponentId )
 import Distribution.ModuleName
          ( ModuleName )
 import Distribution.InstalledPackageInfo
@@ -98,14 +98,14 @@ import Distribution.Simple.Utils (lowercase, comparing, equating)
 -- | The collection of information about packages from one or more 'PackageDB's.
 -- These packages generally should have an instance of 'PackageInstalled'
 --
--- Packages are uniquely identified in by their 'InstalledPackageId', they can
+-- Packages are uniquely identified in by their 'ComponentId', they can
 -- also be efficiently looked up by package name or by name and version.
 --
 data PackageIndex a = PackageIndex
   -- The primary index. Each InstalledPackageInfo record is uniquely identified
-  -- by its InstalledPackageId.
+  -- by its ComponentId.
   --
-  !(Map InstalledPackageId a)
+  !(Map ComponentId a)
 
   -- This auxiliary index maps package names (case-sensitively) to all the
   -- versions and instances of that package. This allows us to find all
@@ -113,7 +113,7 @@ data PackageIndex a = PackageIndex
   --
   -- It is a three-level index. The first level is the package name,
   -- the second is the package version and the final level is instances
-  -- of the same package version. These are unique by InstalledPackageId
+  -- of the same package version. These are unique by ComponentId
   -- and are kept in preference order.
   --
   -- FIXME: Clarify what "preference order" means. Check that this invariant is
@@ -128,24 +128,24 @@ instance Binary a => Binary (PackageIndex a)
 -- use this.
 type InstalledPackageIndex = PackageIndex InstalledPackageInfo
 
-instance HasInstalledPackageId a => Monoid (PackageIndex a) where
+instance HasComponentId a => Monoid (PackageIndex a) where
   mempty  = PackageIndex Map.empty Map.empty
   mappend = merge
   --save one mappend with empty in the common case:
   mconcat [] = mempty
   mconcat xs = foldr1 mappend xs
 
-invariant :: HasInstalledPackageId a => PackageIndex a -> Bool
+invariant :: HasComponentId a => PackageIndex a -> Bool
 invariant (PackageIndex pids pnames) =
-     map installedPackageId (Map.elems pids)
+     map installedComponentId (Map.elems pids)
   == sort
-     [ assert pinstOk (installedPackageId pinst)
+     [ assert pinstOk (installedComponentId pinst)
      | (pname, pvers)  <- Map.toList pnames
      , let pversOk = not (Map.null pvers)
      , (pver,  pinsts) <- assert pversOk $ Map.toList pvers
-     , let pinsts'  = sortBy (comparing installedPackageId) pinsts
+     , let pinsts'  = sortBy (comparing installedComponentId) pinsts
            pinstsOk = all (\g -> length g == 1)
-                          (groupBy (equating installedPackageId) pinsts')
+                          (groupBy (equating installedComponentId) pinsts')
      , pinst           <- assert pinstsOk $ pinsts'
      , let pinstOk = packageName    pinst == pname
                   && packageVersion pinst == pver
@@ -156,8 +156,8 @@ invariant (PackageIndex pids pnames) =
 -- * Internal helpers
 --
 
-mkPackageIndex :: HasInstalledPackageId a
-               => Map InstalledPackageId a
+mkPackageIndex :: HasComponentId a
+               => Map ComponentId a
                -> Map PackageName (Map Version [a])
                -> PackageIndex a
 mkPackageIndex pids pnames = assert (invariant index) index
@@ -170,13 +170,13 @@ mkPackageIndex pids pnames = assert (invariant index) index
 
 -- | Build an index out of a bunch of packages.
 --
--- If there are duplicates by 'InstalledPackageId' then later ones mask earlier
+-- If there are duplicates by 'ComponentId' then later ones mask earlier
 -- ones.
 --
-fromList :: HasInstalledPackageId a => [a] -> PackageIndex a
+fromList :: HasComponentId a => [a] -> PackageIndex a
 fromList pkgs = mkPackageIndex pids pnames
   where
-    pids      = Map.fromList [ (installedPackageId pkg, pkg) | pkg <- pkgs ]
+    pids      = Map.fromList [ (installedComponentId pkg, pkg) | pkg <- pkgs ]
     pnames    =
       Map.fromList
         [ (packageName (head pkgsN), pvers)
@@ -186,7 +186,7 @@ fromList pkgs = mkPackageIndex pids pnames
         , let pvers =
                 Map.fromList
                 [ (packageVersion (head pkgsNV),
-                   nubBy (equating installedPackageId) (reverse pkgsNV))
+                   nubBy (equating installedComponentId) (reverse pkgsNV))
                 | pkgsNV <- groupBy (equating packageVersion) pkgsN
                 ]
         ]
@@ -198,14 +198,14 @@ fromList pkgs = mkPackageIndex pids pnames
 -- | Merge two indexes.
 --
 -- Packages from the second mask packages from the first if they have the exact
--- same 'InstalledPackageId'.
+-- same 'ComponentId'.
 --
 -- For packages with the same source 'PackageId', packages from the second are
 -- \"preferred\" over those from the first. Being preferred means they are top
 -- result when we do a lookup by source 'PackageId'. This is the mechanism we
 -- use to prefer user packages over global packages.
 --
-merge :: HasInstalledPackageId a => PackageIndex a -> PackageIndex a
+merge :: HasComponentId a => PackageIndex a -> PackageIndex a
       -> PackageIndex a
 merge (PackageIndex pids1 pnames1) (PackageIndex pids2 pnames2) =
   mkPackageIndex (Map.unionWith (\_ y -> y) pids1 pids2)
@@ -214,7 +214,7 @@ merge (PackageIndex pids1 pnames1) (PackageIndex pids2 pnames2) =
     -- Packages in the second list mask those in the first, however preferred
     -- packages go first in the list.
     mergeBuckets xs ys = ys ++ (xs \\ ys)
-    (\\) = deleteFirstsBy (equating installedPackageId)
+    (\\) = deleteFirstsBy (equating installedComponentId)
 
 
 -- | Inserts a single package into the index.
@@ -222,12 +222,12 @@ merge (PackageIndex pids1 pnames1) (PackageIndex pids2 pnames2) =
 -- This is equivalent to (but slightly quicker than) using 'mappend' or
 -- 'merge' with a singleton index.
 --
-insert :: HasInstalledPackageId a => a -> PackageIndex a -> PackageIndex a
+insert :: HasComponentId a => a -> PackageIndex a -> PackageIndex a
 insert pkg (PackageIndex pids pnames) =
     mkPackageIndex pids' pnames'
 
   where
-    pids'   = Map.insert (installedPackageId pkg) pkg pids
+    pids'   = Map.insert (installedComponentId pkg) pkg pids
     pnames' = insertPackageName pnames
     insertPackageName =
       Map.insertWith' (\_ -> insertPackageVersion)
@@ -239,15 +239,15 @@ insert pkg (PackageIndex pids pnames) =
                      (packageVersion pkg) [pkg]
 
     insertPackageInstance pkgs =
-      pkg : deleteBy (equating installedPackageId) pkg pkgs
+      pkg : deleteBy (equating installedComponentId) pkg pkgs
 
 
 -- | Removes a single installed package from the index.
 --
-deleteInstalledPackageId :: HasInstalledPackageId a
-                         => InstalledPackageId -> PackageIndex a
+deleteComponentId :: HasComponentId a
+                         => ComponentId -> PackageIndex a
                          -> PackageIndex a
-deleteInstalledPackageId ipkgid original@(PackageIndex pids pnames) =
+deleteComponentId ipkgid original@(PackageIndex pids pnames) =
   case Map.updateLookupWithKey (\_ _ -> Nothing) ipkgid pids of
     (Nothing,     _)     -> original
     (Just spkgid, pids') -> mkPackageIndex pids'
@@ -263,12 +263,12 @@ deleteInstalledPackageId ipkgid original@(PackageIndex pids pnames) =
 
     deletePkgInstance =
         (\xs -> if List.null xs then Nothing else Just xs)
-      . List.deleteBy (\_ pkg -> installedPackageId pkg == ipkgid) undefined
+      . List.deleteBy (\_ pkg -> installedComponentId pkg == ipkgid) undefined
 
 
 -- | Removes all packages with this source 'PackageId' from the index.
 --
-deleteSourcePackageId :: HasInstalledPackageId a => PackageId -> PackageIndex a
+deleteSourcePackageId :: HasComponentId a => PackageId -> PackageIndex a
                       -> PackageIndex a
 deleteSourcePackageId pkgid original@(PackageIndex pids pnames) =
   case Map.lookup (packageName pkgid) pnames of
@@ -276,7 +276,7 @@ deleteSourcePackageId pkgid original@(PackageIndex pids pnames) =
     Just pvers  -> case Map.lookup (packageVersion pkgid) pvers of
       Nothing   -> original
       Just pkgs -> mkPackageIndex
-                     (foldl' (flip (Map.delete . installedPackageId)) pids pkgs)
+                     (foldl' (flip (Map.delete . installedComponentId)) pids pkgs)
                      (deletePkgName pnames)
   where
     deletePkgName =
@@ -289,13 +289,13 @@ deleteSourcePackageId pkgid original@(PackageIndex pids pnames) =
 
 -- | Removes all packages with this (case-sensitive) name from the index.
 --
-deletePackageName :: HasInstalledPackageId a => PackageName -> PackageIndex a
+deletePackageName :: HasComponentId a => PackageName -> PackageIndex a
                   -> PackageIndex a
 deletePackageName name original@(PackageIndex pids pnames) =
   case Map.lookup name pnames of
     Nothing     -> original
     Just pvers  -> mkPackageIndex
-                     (foldl' (flip (Map.delete . installedPackageId)) pids
+                     (foldl' (flip (Map.delete . installedComponentId)) pids
                              (concat (Map.elems pvers)))
                      (Map.delete name pnames)
 
@@ -329,7 +329,7 @@ allPackagesByName (PackageIndex _ pnames) =
 --
 -- They are grouped by source package id (package name and version).
 --
-allPackagesBySourcePackageId :: HasInstalledPackageId a => PackageIndex a
+allPackagesBySourcePackageId :: HasComponentId a => PackageIndex a
                              -> [(PackageId, [a])]
 allPackagesBySourcePackageId (PackageIndex _ pnames) =
   [ (packageId ipkg, ipkgs)
@@ -342,18 +342,18 @@ allPackagesBySourcePackageId (PackageIndex _ pnames) =
 
 -- | Does a lookup by source package id (name & version).
 --
--- Since multiple package DBs mask each other by 'InstalledPackageId',
+-- Since multiple package DBs mask each other by 'ComponentId',
 -- then we get back at most one package.
 --
-lookupInstalledPackageId :: PackageIndex a -> InstalledPackageId
+lookupComponentId :: PackageIndex a -> ComponentId
                          -> Maybe a
-lookupInstalledPackageId (PackageIndex pids _) pid = Map.lookup pid pids
+lookupComponentId (PackageIndex pids _) pid = Map.lookup pid pids
 
 
 -- | Does a lookup by source package id (name & version).
 --
 -- There can be multiple installed packages with the same source 'PackageId'
--- but different 'InstalledPackageId'. They are returned in order of
+-- but different 'ComponentId'. They are returned in order of
 -- preference, with the most preferred first.
 --
 lookupSourcePackageId :: PackageIndex a -> PackageId -> [a]
@@ -457,7 +457,7 @@ dependencyCycles :: PackageInstalled a => PackageIndex a -> [[a]]
 dependencyCycles index =
   [ vs | Graph.CyclicSCC vs <- Graph.stronglyConnComp adjacencyList ]
   where
-    adjacencyList = [ (pkg, installedPackageId pkg, installedDepends pkg)
+    adjacencyList = [ (pkg, installedComponentId pkg, installedDepends pkg)
                     | pkg <- allPackages index ]
 
 
@@ -466,12 +466,12 @@ dependencyCycles index =
 -- Returns such packages along with the dependencies that they're missing.
 --
 brokenPackages :: PackageInstalled a => PackageIndex a
-               -> [(a, [InstalledPackageId])]
+               -> [(a, [ComponentId])]
 brokenPackages index =
   [ (pkg, missing)
   | pkg  <- allPackages index
   , let missing = [ pkg' | pkg' <- installedDepends pkg
-                         , isNothing (lookupInstalledPackageId index pkg') ]
+                         , isNothing (lookupComponentId index pkg') ]
   , not (null missing) ]
 
 -- | Tries to take the transitive closure of the package dependencies.
@@ -483,17 +483,17 @@ brokenPackages index =
 -- the original given 'PackageId's do not occur in the index.
 --
 dependencyClosure :: PackageInstalled a => PackageIndex a
-                  -> [InstalledPackageId]
+                  -> [ComponentId]
                   -> Either (PackageIndex a)
-                            [(a, [InstalledPackageId])]
+                            [(a, [ComponentId])]
 dependencyClosure index pkgids0 = case closure mempty [] pkgids0 of
   (completed, []) -> Left completed
   (completed, _)  -> Right (brokenPackages completed)
  where
     closure completed failed []             = (completed, failed)
-    closure completed failed (pkgid:pkgids) = case lookupInstalledPackageId index pkgid of
+    closure completed failed (pkgid:pkgids) = case lookupComponentId index pkgid of
       Nothing   -> closure completed (pkgid:failed) pkgids
-      Just pkg  -> case lookupInstalledPackageId completed (installedPackageId pkg) of
+      Just pkg  -> case lookupComponentId completed (installedComponentId pkg) of
         Just _  -> closure completed  failed pkgids
         Nothing -> closure completed' failed pkgids'
           where completed' = insert pkg completed
@@ -504,7 +504,7 @@ dependencyClosure index pkgids0 = case closure mempty [] pkgids0 of
 -- * The given 'PackageId's must be in the index.
 --
 reverseDependencyClosure :: PackageInstalled a => PackageIndex a
-                         -> [InstalledPackageId]
+                         -> [ComponentId]
                          -> [a]
 reverseDependencyClosure index =
     map vertexToPkg
@@ -538,7 +538,7 @@ reverseTopologicalOrder index = map toPkgId
 dependencyGraph :: PackageInstalled a => PackageIndex a
                 -> (Graph.Graph,
                     Graph.Vertex -> a,
-                    InstalledPackageId -> Maybe Graph.Vertex)
+                    ComponentId -> Maybe Graph.Vertex)
 dependencyGraph index = (graph, vertex_to_pkg, id_to_vertex)
   where
     graph = Array.listArray bounds
@@ -546,7 +546,7 @@ dependencyGraph index = (graph, vertex_to_pkg, id_to_vertex)
               | pkg <- pkgs ]
 
     pkgs             = sortBy (comparing packageId) (allPackages index)
-    vertices         = zip (map installedPackageId pkgs) [0..]
+    vertices         = zip (map installedComponentId pkgs) [0..]
     vertex_map       = Map.fromList vertices
     id_to_vertex pid = Map.lookup pid vertex_map
 
@@ -583,15 +583,15 @@ dependencyInconsistencies index =
              Map.fromList [(ipid,(dep,[packageId pkg]))])
           | pkg <- allPackages index
           , ipid <- installedDepends pkg
-          , Just dep <- [lookupInstalledPackageId index ipid]
+          , Just dep <- [lookupComponentId index ipid]
           ]
 
         reallyIsInconsistent :: PackageInstalled a => [a] -> Bool
         reallyIsInconsistent []       = False
         reallyIsInconsistent [_p]     = False
         reallyIsInconsistent [p1, p2] =
-          let pid1 = installedPackageId p1
-              pid2 = installedPackageId p2
+          let pid1 = installedComponentId p1
+              pid2 = installedComponentId p2
           in pid1 `notElem` installedDepends p2
           && pid2 `notElem` installedDepends p1
         reallyIsInconsistent _ = True
diff --git a/Cabal/Distribution/Simple/Program/GHC.hs b/Cabal/Distribution/Simple/Program/GHC.hs
index b7a030e2850db14c1f9585ef0721015c9881e900..bdc1c0229c7cbac5075dda998879c244851c8146 100644
--- a/Cabal/Distribution/Simple/Program/GHC.hs
+++ b/Cabal/Distribution/Simple/Program/GHC.hs
@@ -76,7 +76,7 @@ data GhcOptions = GhcOptions {
 
   -- | The package key the modules will belong to; the @ghc -this-package-key@
   -- flag.
-  ghcOptPackageKey   :: Flag PackageKey,
+  ghcOptComponentId   :: Flag ComponentId,
 
   -- | GHC package databases to use, the @ghc -package-conf@ flag.
   ghcOptPackageDBs    :: PackageDBStack,
@@ -85,7 +85,7 @@ data GhcOptions = GhcOptions {
   -- requires both the short and long form of the package id;
   -- the @ghc -package@ or @ghc -package-id@ flags.
   ghcOptPackages      ::
-    NubListR (InstalledPackageId, PackageId, ModuleRenaming),
+    NubListR (ComponentId, PackageId, ModuleRenaming),
 
   -- | Start with a clean package set; the @ghc -hide-all-packages@ flag
   ghcOptHideAllPackages :: Flag Bool,
@@ -95,7 +95,7 @@ data GhcOptions = GhcOptions {
   ghcOptNoAutoLinkPackages :: Flag Bool,
 
   -- | What packages are implementing the signatures
-  ghcOptSigOf :: [(ModuleName, (PackageKey, ModuleName))],
+  ghcOptSigOf :: [(ModuleName, (ComponentId, ModuleName))],
 
   -----------------
   -- Linker stuff
@@ -379,7 +379,7 @@ renderGhcOptions comp opts
   , concat [ [if packageKeySupported comp
                 then "-this-package-key"
                 else "-package-name", display pkgid]
-             | pkgid <- flag ghcOptPackageKey ]
+             | pkgid <- flag ghcOptComponentId ]
 
   , [ "-hide-all-packages"     | flagBool ghcOptHideAllPackages ]
   , [ "-no-auto-link-packages" | flagBool ghcOptNoAutoLinkPackages ]
@@ -503,7 +503,7 @@ instance Monoid GhcOptions where
     ghcOptOutputDynFile      = mempty,
     ghcOptSourcePathClear    = mempty,
     ghcOptSourcePath         = mempty,
-    ghcOptPackageKey         = mempty,
+    ghcOptComponentId         = mempty,
     ghcOptPackageDBs         = mempty,
     ghcOptPackages           = mempty,
     ghcOptHideAllPackages    = mempty,
@@ -557,7 +557,7 @@ instance Monoid GhcOptions where
     ghcOptOutputDynFile      = combine ghcOptOutputDynFile,
     ghcOptSourcePathClear    = combine ghcOptSourcePathClear,
     ghcOptSourcePath         = combine ghcOptSourcePath,
-    ghcOptPackageKey         = combine ghcOptPackageKey,
+    ghcOptComponentId         = combine ghcOptComponentId,
     ghcOptPackageDBs         = combine ghcOptPackageDBs,
     ghcOptPackages           = combine ghcOptPackages,
     ghcOptHideAllPackages    = combine ghcOptHideAllPackages,
diff --git a/Cabal/Distribution/Simple/Program/HcPkg.hs b/Cabal/Distribution/Simple/Program/HcPkg.hs
index 861bc6f08e5c3d77266a930dcbff83c40b7e8764..fca63dc41403705ea406f231eaf06d777c3d3e1c 100644
--- a/Cabal/Distribution/Simple/Program/HcPkg.hs
+++ b/Cabal/Distribution/Simple/Program/HcPkg.hs
@@ -20,6 +20,7 @@ module Distribution.Simple.Program.HcPkg (
     expose,
     hide,
     dump,
+    describe,
     list,
 
     -- * Program invocations
@@ -30,12 +31,13 @@ module Distribution.Simple.Program.HcPkg (
     exposeInvocation,
     hideInvocation,
     dumpInvocation,
+    describeInvocation,
     listInvocation,
   ) where
 
 import Prelude hiding (init)
 import Distribution.Package
-         ( PackageId, InstalledPackageId(..) )
+         ( PackageId, ComponentId(..) )
 import Distribution.InstalledPackageInfo
          ( InstalledPackageInfo, InstalledPackageInfo(..)
          , showInstalledPackageInfo
@@ -55,7 +57,7 @@ import Distribution.Simple.Utils
 import Distribution.Verbosity
          ( Verbosity, deafening, silent )
 import Distribution.Compat.Exception
-         ( catchExit )
+         ( catchIO )
 
 import Data.Char
          ( isSpace )
@@ -138,6 +140,21 @@ expose hpi verbosity packagedb pkgid =
   runProgramInvocation verbosity
     (exposeInvocation hpi verbosity packagedb pkgid)
 
+-- | Call @hc-pkg@ to retrieve a specific package
+--
+-- > hc-pkg describe [pkgid] [--user | --global | --package-db]
+--
+describe :: HcPkgInfo -> Verbosity -> PackageDBStack -> PackageId -> IO [InstalledPackageInfo]
+describe hpi verbosity packagedb pid = do
+
+  output <- getProgramInvocationOutput verbosity
+              (describeInvocation hpi verbosity packagedb pid)
+    `catchIO` \_ -> return ""
+
+  case parsePackages output of
+    Left ok -> return ok
+    _       -> die $ "failed to parse output of '"
+                  ++ programId (hcPkgProgram hpi) ++ " describe " ++ display pid ++ "'"
 
 -- | Call @hc-pkg@ to hide a package.
 --
@@ -157,40 +174,40 @@ dump hpi verbosity packagedb = do
 
   output <- getProgramInvocationOutput verbosity
               (dumpInvocation hpi verbosity packagedb)
-    `catchExit` \_ -> die $ programId (hcPkgProgram hpi) ++ " dump failed"
+    `catchIO` \_ -> die $ programId (hcPkgProgram hpi) ++ " dump failed"
 
   case parsePackages output of
     Left ok -> return ok
     _       -> die $ "failed to parse output of '"
                   ++ programId (hcPkgProgram hpi) ++ " dump'"
 
+parsePackages :: String -> Either [InstalledPackageInfo] [PError]
+parsePackages str =
+  let parsed = map parseInstalledPackageInfo' (splitPkgs str)
+   in case [ msg | ParseFailed msg <- parsed ] of
+        []   -> Left [   setComponentId
+                       . maybe id mungePackagePaths (pkgRoot pkg)
+                       $ pkg
+                     | ParseOk _ pkg <- parsed ]
+        msgs -> Right msgs
   where
-    parsePackages str =
-      let parsed = map parseInstalledPackageInfo' (splitPkgs str)
-       in case [ msg | ParseFailed msg <- parsed ] of
-            []   -> Left [   setInstalledPackageId
-                           . maybe id mungePackagePaths (pkgRoot pkg)
-                           $ pkg
-                         | ParseOk _ pkg <- parsed ]
-            msgs -> Right msgs
-
     parseInstalledPackageInfo' =
       parseFieldsFlat fieldsInstalledPackageInfo emptyInstalledPackageInfo
 
-    --TODO: this could be a lot faster. We're doing normaliseLineEndings twice
-    -- and converting back and forth with lines/unlines.
-    splitPkgs :: String -> [String]
-    splitPkgs = checkEmpty . map unlines . splitWith ("---" ==) . lines
-      where
-        -- Handle the case of there being no packages at all.
-        checkEmpty [s] | all isSpace s = []
-        checkEmpty ss                  = ss
-
-        splitWith :: (a -> Bool) -> [a] -> [[a]]
-        splitWith p xs = ys : case zs of
-                           []   -> []
-                           _:ws -> splitWith p ws
-          where (ys,zs) = break p xs
+--TODO: this could be a lot faster. We're doing normaliseLineEndings twice
+-- and converting back and forth with lines/unlines.
+splitPkgs :: String -> [String]
+splitPkgs = checkEmpty . map unlines . splitWith ("---" ==) . lines
+  where
+    -- Handle the case of there being no packages at all.
+    checkEmpty [s] | all isSpace s = []
+    checkEmpty ss                  = ss
+
+    splitWith :: (a -> Bool) -> [a] -> [[a]]
+    splitWith p xs = ys : case zs of
+                       []   -> []
+                       _:ws -> splitWith p ws
+      where (ys,zs) = break p xs
 
 mungePackagePaths :: FilePath -> InstalledPackageInfo -> InstalledPackageInfo
 -- Perform path/URL variable substitution as per the Cabal ${pkgroot} spec
@@ -230,26 +247,26 @@ mungePackagePaths pkgroot pkginfo =
         _                                  -> Nothing
 
 
--- Older installed package info files did not have the installedPackageId
+-- Older installed package info files did not have the installedComponentId
 -- field, so if it is missing then we fill it as the source package ID.
-setInstalledPackageId :: InstalledPackageInfo -> InstalledPackageInfo
-setInstalledPackageId pkginfo@InstalledPackageInfo {
-                        installedPackageId = InstalledPackageId "",
+setComponentId :: InstalledPackageInfo -> InstalledPackageInfo
+setComponentId pkginfo@InstalledPackageInfo {
+                        installedComponentId = ComponentId "",
                         sourcePackageId    = pkgid
                       }
                     = pkginfo {
                         --TODO use a proper named function for the conversion
                         -- from source package id to installed package id
-                        installedPackageId = InstalledPackageId (display pkgid)
+                        installedComponentId = ComponentId (display pkgid)
                       }
-setInstalledPackageId pkginfo = pkginfo
+setComponentId pkginfo = pkginfo
 
 
 -- | Call @hc-pkg@ to get the source package Id of all the packages in the
 -- given package database.
 --
 -- This is much less information than with 'dump', but also rather quicker.
--- Note in particular that it does not include the 'InstalledPackageId', just
+-- Note in particular that it does not include the 'ComponentId', just
 -- the source 'PackageId' which is not necessarily unique in any package db.
 --
 list :: HcPkgInfo -> Verbosity -> PackageDB
@@ -258,7 +275,7 @@ list hpi verbosity packagedb = do
 
   output <- getProgramInvocationOutput verbosity
               (listInvocation hpi verbosity packagedb)
-    `catchExit` \_ -> die $ programId (hcPkgProgram hpi) ++ " list failed"
+    `catchIO` \_ -> die $ programId (hcPkgProgram hpi) ++ " list failed"
 
   case parsePackageIds output of
     Just ok -> return ok
@@ -327,6 +344,15 @@ exposeInvocation hpi verbosity packagedb pkgid =
        ["expose", packageDbOpts hpi packagedb, display pkgid]
     ++ verbosityOpts hpi verbosity
 
+describeInvocation :: HcPkgInfo -> Verbosity -> PackageDBStack -> PackageId
+                   -> ProgramInvocation
+describeInvocation hpi verbosity packagedbs pkgid =
+  programInvocation (hcPkgProgram hpi) $
+       ["describe", display pkgid]
+    ++ (if noPkgDbStack hpi
+          then [packageDbOpts hpi (last packagedbs)]
+          else packageDbStackOpts hpi packagedbs)
+    ++ verbosityOpts hpi verbosity
 
 hideInvocation :: HcPkgInfo -> Verbosity -> PackageDB -> PackageId
                -> ProgramInvocation
diff --git a/Cabal/Distribution/Simple/Register.hs b/Cabal/Distribution/Simple/Register.hs
index 82b5086b21605cbf182edd0cecfa58349228ea6d..f6a1c53ed8bf086ca91beffa57650d74af8ee320 100644
--- a/Cabal/Distribution/Simple/Register.hs
+++ b/Cabal/Distribution/Simple/Register.hs
@@ -49,7 +49,7 @@ import qualified Distribution.Simple.UHC   as UHC
 import qualified Distribution.Simple.HaskellSuite as HaskellSuite
 
 import Distribution.Simple.Compiler
-         ( compilerVersion, Compiler, CompilerFlavor(..), compilerFlavor
+         ( Compiler, CompilerFlavor(..), compilerFlavor, compilerVersion
          , PackageDB, PackageDBStack, absolutePackageDBPaths
          , registrationPackageDB )
 import Distribution.Simple.Program
@@ -64,11 +64,11 @@ import Distribution.Simple.Setup
 import Distribution.PackageDescription
          ( PackageDescription(..), Library(..), BuildInfo(..), libModules )
 import Distribution.Package
-         ( Package(..), packageName, InstalledPackageId(..)
+         ( Package(..), packageName
          , getHSLibraryName )
 import Distribution.InstalledPackageInfo
          ( InstalledPackageInfo, InstalledPackageInfo(InstalledPackageInfo)
-         , showInstalledPackageInfo )
+         , showInstalledPackageInfo, AbiHash(..) )
 import qualified Distribution.InstalledPackageInfo as IPI
 import Distribution.Simple.Utils
          ( writeUTF8File, writeFileAtomic, setFileExecutable
@@ -77,7 +77,6 @@ import Distribution.System
          ( OS(..), buildOS )
 import Distribution.Text
          ( display )
-import Distribution.Version ( Version(..) )
 import Distribution.Verbosity as Verbosity
          ( Verbosity, normal )
 
@@ -85,6 +84,7 @@ import System.FilePath ((</>), (<.>), isAbsolute)
 import System.Directory
          ( getCurrentDirectory )
 
+import Data.Version
 import Control.Monad (when)
 import Data.Maybe
          ( isJust, fromMaybe, maybeToList )
@@ -108,7 +108,7 @@ register pkg@PackageDescription { library       = Just lib  } lbi regFlags
                            (registrationPackageDB absPackageDBs)
 
     when (fromFlag (regPrintId regFlags)) $ do
-      putStrLn (display (IPI.installedPackageId installedPkgInfo))
+      putStrLn (display (IPI.installedComponentId installedPkgInfo))
 
      -- Three different modes:
     case () of
@@ -166,46 +166,43 @@ generateRegistrationInfo verbosity pkg lib lbi clbi inplace reloc distPref packa
   --TODO: eliminate pwd!
   pwd <- getCurrentDirectory
 
-  --TODO: the method of setting the InstalledPackageId is compiler specific
+  --TODO: the method of setting the ComponentId is compiler specific
   --      this aspect should be delegated to a per-compiler helper.
   let comp = compiler lbi
-  ipid <-
+  abi_hash <-
     case compilerFlavor comp of
      GHC | compilerVersion comp >= Version [6,11] [] -> do
-            s <- GHC.libAbiHash verbosity pkg lbi lib clbi
-            return (InstalledPackageId (display (packageId pkg) ++ '-':s))
+            fmap AbiHash $ GHC.libAbiHash verbosity pkg lbi lib clbi
      GHCJS -> do
-            s <- GHCJS.libAbiHash verbosity pkg lbi lib clbi
-            return (InstalledPackageId (display (packageId pkg) ++ '-':s))
-     _other -> do
-            return (InstalledPackageId (display (packageId pkg)))
+            fmap AbiHash $ GHCJS.libAbiHash verbosity pkg lbi lib clbi
+     _ -> return (AbiHash "")
 
   installedPkgInfo <-
     if inplace
       then return (inplaceInstalledPackageInfo pwd distPref
-                     pkg ipid lib lbi clbi)
+                     pkg abi_hash lib lbi clbi)
     else if reloc
       then relocRegistrationInfo verbosity
-                     pkg lib lbi clbi ipid packageDb
+                     pkg lib lbi clbi abi_hash packageDb
       else return (absoluteInstalledPackageInfo
-                     pkg ipid lib lbi clbi)
+                     pkg abi_hash lib lbi clbi)
 
 
-  return installedPkgInfo{ IPI.installedPackageId = ipid }
+  return installedPkgInfo{ IPI.abiHash = abi_hash }
 
 relocRegistrationInfo :: Verbosity
                       -> PackageDescription
                       -> Library
                       -> LocalBuildInfo
                       -> ComponentLocalBuildInfo
-                      -> InstalledPackageId
+                      -> AbiHash
                       -> PackageDB
                       -> IO InstalledPackageInfo
-relocRegistrationInfo verbosity pkg lib lbi clbi ipid packageDb =
+relocRegistrationInfo verbosity pkg lib lbi clbi abi_hash packageDb =
   case (compilerFlavor (compiler lbi)) of
     GHC -> do fs <- GHC.pkgRoot verbosity lbi packageDb
               return (relocatableInstalledPackageInfo
-                        pkg ipid lib lbi clbi fs)
+                        pkg abi_hash lib lbi clbi fs)
     _   -> die "Distribution.Simple.Register.relocRegistrationInfo: \
                \not implemented for this compiler"
 
@@ -289,17 +286,17 @@ generalInstalledPackageInfo
   :: ([FilePath] -> [FilePath]) -- ^ Translate relative include dir paths to
                                 -- absolute paths.
   -> PackageDescription
-  -> InstalledPackageId
+  -> AbiHash
   -> Library
   -> LocalBuildInfo
   -> ComponentLocalBuildInfo
   -> InstallDirs FilePath
   -> InstalledPackageInfo
-generalInstalledPackageInfo adjustRelIncDirs pkg ipid lib lbi clbi installDirs =
+generalInstalledPackageInfo adjustRelIncDirs pkg abi_hash lib lbi clbi installDirs =
   InstalledPackageInfo {
-    IPI.installedPackageId = ipid,
     IPI.sourcePackageId    = packageId   pkg,
-    IPI.packageKey         = componentPackageKey clbi,
+    IPI.installedComponentId= componentId clbi,
+    IPI.compatPackageKey   = componentCompatPackageKey clbi,
     IPI.license            = license     pkg,
     IPI.copyright          = copyright   pkg,
     IPI.maintainer         = maintainer  pkg,
@@ -310,11 +307,12 @@ generalInstalledPackageInfo adjustRelIncDirs pkg ipid lib lbi clbi installDirs =
     IPI.synopsis           = synopsis    pkg,
     IPI.description        = description pkg,
     IPI.category           = category    pkg,
+    IPI.abiHash            = abi_hash,
     IPI.exposed            = libExposed  lib,
-    IPI.exposedModules     = map fixupSelf (componentExposedModules clbi),
+    IPI.exposedModules     = componentExposedModules clbi,
     IPI.hiddenModules      = otherModules bi,
     IPI.instantiatedWith   = map (\(k,(p,n)) ->
-                                   (k,IPI.OriginalModule (IPI.installedPackageId p) n))
+                                   (k,IPI.OriginalModule (IPI.installedComponentId p) n))
                                  (instantiatedWith lbi),
     IPI.trusted            = IPI.trusted IPI.emptyInstalledPackageInfo,
     IPI.importDirs         = [ libdir installDirs | hasModules ],
@@ -325,7 +323,7 @@ generalInstalledPackageInfo adjustRelIncDirs pkg ipid lib lbi clbi installDirs =
                                else                      extraLibDirs bi,
     IPI.dataDir            = datadir installDirs,
     IPI.hsLibraries        = if hasLibrary
-                               then [getHSLibraryName (componentLibraryName clbi)]
+                               then [getHSLibraryName (componentId clbi)]
                                else [],
     IPI.extraLibraries     = extraLibs bi,
     IPI.extraGHCiLibraries = extraGHCiLibs bi,
@@ -350,18 +348,6 @@ generalInstalledPackageInfo adjustRelIncDirs pkg ipid lib lbi clbi installDirs =
                             || (not (null (jsSources bi)) &&
                                 compilerFlavor (compiler lbi) == GHCJS)
 
-    -- Since we currently don't decide the InstalledPackageId of our package
-    -- until just before we register, we didn't have one for the re-exports
-    -- of modules defined within this package, so we used an empty one that
-    -- we fill in here now that we know what it is. It's a bit of a hack,
-    -- we ought really to decide the InstalledPackageId ahead of time.
-    fixupSelf (IPI.ExposedModule n o o') =
-        IPI.ExposedModule n (fmap fixupOriginalModule o)
-                            (fmap fixupOriginalModule o')
-    fixupOriginalModule (IPI.OriginalModule i m) = IPI.OriginalModule (fixupIpid i) m
-    fixupIpid (InstalledPackageId []) = ipid
-    fixupIpid x = x
-
 -- | Construct 'InstalledPackageInfo' for a library that is in place in the
 -- build tree.
 --
@@ -370,14 +356,14 @@ generalInstalledPackageInfo adjustRelIncDirs pkg ipid lib lbi clbi installDirs =
 inplaceInstalledPackageInfo :: FilePath -- ^ top of the build tree
                             -> FilePath -- ^ location of the dist tree
                             -> PackageDescription
-                            -> InstalledPackageId
+                            -> AbiHash
                             -> Library
                             -> LocalBuildInfo
                             -> ComponentLocalBuildInfo
                             -> InstalledPackageInfo
-inplaceInstalledPackageInfo inplaceDir distPref pkg ipid lib lbi clbi =
+inplaceInstalledPackageInfo inplaceDir distPref pkg abi_hash lib lbi clbi =
     generalInstalledPackageInfo adjustRelativeIncludeDirs
-                                pkg ipid lib lbi clbi installDirs
+                                pkg abi_hash lib lbi clbi installDirs
   where
     adjustRelativeIncludeDirs = map (inplaceDir </>)
     installDirs =
@@ -398,14 +384,14 @@ inplaceInstalledPackageInfo inplaceDir distPref pkg ipid lib lbi clbi =
 -- This function knows about the layout of installed packages.
 --
 absoluteInstalledPackageInfo :: PackageDescription
-                             -> InstalledPackageId
+                             -> AbiHash
                              -> Library
                              -> LocalBuildInfo
                              -> ComponentLocalBuildInfo
                              -> InstalledPackageInfo
-absoluteInstalledPackageInfo pkg ipid lib lbi clbi =
+absoluteInstalledPackageInfo pkg abi_hash lib lbi clbi =
     generalInstalledPackageInfo adjustReativeIncludeDirs
-                                pkg ipid lib lbi clbi installDirs
+                                pkg abi_hash lib lbi clbi installDirs
   where
     -- For installed packages we install all include files into one dir,
     -- whereas in the build tree they may live in multiple local dirs.
@@ -417,15 +403,15 @@ absoluteInstalledPackageInfo pkg ipid lib lbi clbi =
 
 
 relocatableInstalledPackageInfo :: PackageDescription
-                                -> InstalledPackageId
+                                -> AbiHash
                                 -> Library
                                 -> LocalBuildInfo
                                 -> ComponentLocalBuildInfo
                                 -> FilePath
                                 -> InstalledPackageInfo
-relocatableInstalledPackageInfo pkg ipid lib lbi clbi pkgroot =
+relocatableInstalledPackageInfo pkg abi_hash lib lbi clbi pkgroot =
     generalInstalledPackageInfo adjustReativeIncludeDirs
-                                pkg ipid lib lbi clbi installDirs
+                                pkg abi_hash lib lbi clbi installDirs
   where
     -- For installed packages we install all include files into one dir,
     -- whereas in the build tree they may live in multiple local dirs.
diff --git a/Cabal/Distribution/Simple/Setup.hs b/Cabal/Distribution/Simple/Setup.hs
index e571c5c50731f9520e654d56596fc7c88dc1b6a9..5e5e85fc5f488b62d90a3e5245e98f549bf6604c 100644
--- a/Cabal/Distribution/Simple/Setup.hs
+++ b/Cabal/Distribution/Simple/Setup.hs
@@ -76,7 +76,7 @@ import qualified Text.PrettyPrint as Disp
 import Distribution.ModuleName
 import Distribution.Package ( Dependency(..)
                             , PackageName
-                            , InstalledPackageId )
+                            , ComponentId(..) )
 import Distribution.PackageDescription
          ( FlagName(..), FlagAssignment )
 import Distribution.Simple.Command hiding (boolOpt, boolOpt')
@@ -309,6 +309,7 @@ data ConfigFlags = ConfigFlags {
     configScratchDir    :: Flag FilePath,
     configExtraLibDirs  :: [FilePath],   -- ^ path to search for extra libraries
     configExtraIncludeDirs :: [FilePath],   -- ^ path to search for header files
+    configIPID          :: Flag String, -- ^ explicit IPID to be used
 
     configDistPref :: Flag FilePath, -- ^"dist" prefix
     configVerbosity :: Flag Verbosity, -- ^verbosity level
@@ -320,8 +321,8 @@ data ConfigFlags = ConfigFlags {
     configStripLibs :: Flag Bool,      -- ^Enable library stripping
     configConstraints :: [Dependency], -- ^Additional constraints for
                                        -- dependencies.
-    configDependencies :: [(PackageName, InstalledPackageId)],
-    configInstantiateWith :: [(ModuleName, (InstalledPackageId, ModuleName))],
+    configDependencies :: [(PackageName, ComponentId)],
+    configInstantiateWith :: [(ModuleName, (ComponentId, ModuleName))],
       -- ^The packages depended on.
     configConfigurationsFlags :: FlagAssignment,
     configTests               :: Flag Bool, -- ^Enable test suite compilation
@@ -573,6 +574,11 @@ configureOptions showOrParseArgs =
          configExtraIncludeDirs (\v flags -> flags {configExtraIncludeDirs = v})
          (reqArg' "PATH" (\x -> [x]) id)
 
+      ,option "" ["ipid"]
+         "Installed package ID to compile this package as"
+         configIPID (\v flags -> flags {configIPID = v})
+         (reqArgFlag "IPID")
+
       ,option "" ["extra-lib-dirs"]
          "A list of directories to search for external libraries"
          configExtraLibDirs (\v flags -> flags {configExtraLibDirs = v})
@@ -678,14 +684,14 @@ showProfDetailLevelFlag dl =
     Flag (ProfDetailOther other)     -> [other]
 
 
-parseDependency :: Parse.ReadP r (PackageName, InstalledPackageId)
+parseDependency :: Parse.ReadP r (PackageName, ComponentId)
 parseDependency = do
   x <- parse
   _ <- Parse.char '='
   y <- parse
   return (x, y)
 
-parseHoleMapEntry :: Parse.ReadP r (ModuleName, (InstalledPackageId, ModuleName))
+parseHoleMapEntry :: Parse.ReadP r (ModuleName, (ComponentId, ModuleName))
 parseHoleMapEntry = do
   x <- parse
   _ <- Parse.char '='
@@ -795,6 +801,7 @@ instance Monoid ConfigFlags where
     configDependencies  = mempty,
     configInstantiateWith     = mempty,
     configExtraIncludeDirs    = mempty,
+    configIPID          = mempty,
     configConfigurationsFlags = mempty,
     configTests               = mempty,
     configCoverage         = mempty,
@@ -840,6 +847,7 @@ instance Monoid ConfigFlags where
     configDependencies  = combine configDependencies,
     configInstantiateWith     = combine configInstantiateWith,
     configExtraIncludeDirs    = combine configExtraIncludeDirs,
+    configIPID          = combine configIPID,
     configConfigurationsFlags = combine configConfigurationsFlags,
     configTests               = combine configTests,
     configCoverage         = combine configCoverage,
diff --git a/Cabal/Distribution/Simple/Test.hs b/Cabal/Distribution/Simple/Test.hs
index 25fdab5dcf2d68afe7e0efb0a94c68393988dd24..2653bca6424b04dce1bba8077b7a03f3dc283dc8 100644
--- a/Cabal/Distribution/Simple/Test.hs
+++ b/Cabal/Distribution/Simple/Test.hs
@@ -25,7 +25,6 @@ import Distribution.Simple.InstallDirs
     ( fromPathTemplate, initialPathTemplateEnv, substPathTemplate
     , PathTemplate )
 import qualified Distribution.Simple.LocalBuildInfo as LBI
-    ( LocalBuildInfo(..), localLibraryName )
 import Distribution.Simple.Setup ( TestFlags(..), fromFlag, configCoverage )
 import Distribution.Simple.UserHooks ( Args )
 import qualified Distribution.Simple.Test.ExeV10 as ExeV10
@@ -132,5 +131,5 @@ packageLogPath template pkg_descr lbi =
     fromPathTemplate $ substPathTemplate env template
     where
         env = initialPathTemplateEnv
-                (PD.package pkg_descr) (LBI.localLibraryName lbi)
+                (PD.package pkg_descr) (LBI.localComponentId lbi)
                 (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi)
diff --git a/Cabal/Distribution/Simple/Test/ExeV10.hs b/Cabal/Distribution/Simple/Test/ExeV10.hs
index 04fca1ed9b144a195b3caef128a75925ae567264..18c0b2a80652cacf1422dd2174d4bed2bc4e6997 100644
--- a/Cabal/Distribution/Simple/Test/ExeV10.hs
+++ b/Cabal/Distribution/Simple/Test/ExeV10.hs
@@ -163,6 +163,6 @@ testOption pkg_descr lbi suite template =
     fromPathTemplate $ substPathTemplate env template
   where
     env = initialPathTemplateEnv
-          (PD.package pkg_descr) (LBI.localLibraryName lbi)
+          (PD.package pkg_descr) (LBI.localComponentId lbi)
           (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi) ++
           [(TestSuiteNameVar, toPathTemplate $ PD.testName suite)]
diff --git a/Cabal/Distribution/Simple/Test/LibV09.hs b/Cabal/Distribution/Simple/Test/LibV09.hs
index a2417bb53ccd0b6d59bcbde868f37d47d4eaac34..51f613157155aa7e809adf463f3d0b8192329ed8 100644
--- a/Cabal/Distribution/Simple/Test/LibV09.hs
+++ b/Cabal/Distribution/Simple/Test/LibV09.hs
@@ -173,7 +173,7 @@ testOption pkg_descr lbi suite template =
     fromPathTemplate $ substPathTemplate env template
   where
     env = initialPathTemplateEnv
-          (PD.package pkg_descr) (LBI.localLibraryName lbi)
+          (PD.package pkg_descr) (LBI.localComponentId lbi)
           (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi) ++
           [(TestSuiteNameVar, toPathTemplate $ PD.testName suite)]
 
diff --git a/Cabal/Distribution/Simple/Test/Log.hs b/Cabal/Distribution/Simple/Test/Log.hs
index 98de12ca2e76455a433d93119479badd0d169efc..b8fc125c77b1e40a4e1b52f8a0ba65ef9ea967cf 100644
--- a/Cabal/Distribution/Simple/Test/Log.hs
+++ b/Cabal/Distribution/Simple/Test/Log.hs
@@ -113,7 +113,7 @@ testSuiteLogPath template pkg_descr lbi name result =
     fromPathTemplate $ substPathTemplate env template
     where
         env = initialPathTemplateEnv
-                (PD.package pkg_descr) (LBI.localLibraryName lbi)
+                (PD.package pkg_descr) (LBI.localComponentId lbi)
                 (compilerInfo $ LBI.compiler lbi) (LBI.hostPlatform lbi)
                 ++  [ (TestSuiteNameVar, toPathTemplate name)
                     , (TestSuiteResultVar, toPathTemplate $ resultString result)
diff --git a/Cabal/Distribution/Simple/UHC.hs b/Cabal/Distribution/Simple/UHC.hs
index 9544b05ba930838b01b5b6a52a8fcad9b08b8b6b..f59a691e17976fc7ea7ebe5b70dd96d6321f4713 100644
--- a/Cabal/Distribution/Simple/UHC.hs
+++ b/Cabal/Distribution/Simple/UHC.hs
@@ -24,7 +24,7 @@ import Data.List
 import qualified Data.Map as M ( empty )
 import Distribution.Compat.ReadP
 import Distribution.InstalledPackageInfo
-import Distribution.Package hiding (installedPackageId)
+import Distribution.Package hiding (installedComponentId)
 import Distribution.PackageDescription
 import Distribution.Simple.BuildPaths
 import Distribution.Simple.Compiler as C
@@ -150,8 +150,8 @@ parsePackage x = map fst (filter (\ (_,y) -> null y) (readP_to_S parse x))
 -- | Create a trivial package info from a directory name.
 mkInstalledPackageInfo :: PackageId -> InstalledPackageInfo
 mkInstalledPackageInfo p = emptyInstalledPackageInfo
-  { installedPackageId = InstalledPackageId (display p),
-    sourcePackageId    = p }
+  { installedComponentId = ComponentId (display p),
+    sourcePackageId     = p }
 
 
 -- -----------------------------------------------------------------------------
@@ -236,8 +236,8 @@ uhcPackageDbOptions user system db = map (\ x -> "--pkg-searchpath=" ++ x)
 
 installLib :: Verbosity -> LocalBuildInfo
            -> FilePath -> FilePath -> FilePath
-           -> PackageDescription -> Library -> IO ()
-installLib verbosity _lbi targetDir _dynlibTargetDir builtDir pkg _library = do
+           -> PackageDescription -> Library -> ComponentLocalBuildInfo -> IO ()
+installLib verbosity _lbi targetDir _dynlibTargetDir builtDir pkg _library _clbi = do
     -- putStrLn $ "dest:  " ++ targetDir
     -- putStrLn $ "built: " ++ builtDir
     installDirectoryContents verbosity (builtDir </> display (packageId pkg)) targetDir
diff --git a/Cabal/tests/PackageTests.hs b/Cabal/tests/PackageTests.hs
index c7c7b3b473ded6472f08e3f77a5b6104ec633b2f..a8f7f058a0589c93138fb70d52b7f342a0fb907c 100644
--- a/Cabal/tests/PackageTests.hs
+++ b/Cabal/tests/PackageTests.hs
@@ -36,6 +36,7 @@ import PackageTests.TestSuiteTests.ExeV10.Check
 import PackageTests.TestSuiteTests.LibV09.Check
 import PackageTests.OrderFlags.Check
 import PackageTests.ReexportedModules.Check
+import PackageTests.UniqueIPID.Check
 
 import Distribution.Simple.Configure
     ( ConfigStateFileError(..), findDistPrefOrDefault, getConfigStateFile )
@@ -113,6 +114,8 @@ tests config version =
       (PackageTests.TemplateHaskell.Check.dynamic config)
     , testCase "ReexportedModules"
       (PackageTests.ReexportedModules.Check.suite config)
+    , testCase "UniqueIPID"
+      (PackageTests.UniqueIPID.Check.suite config)
     ] ++
     -- These tests are only required to pass on cabal version >= 1.7
     (if version >= Version [1, 7] []
diff --git a/Cabal/tests/PackageTests/.gitignore b/Cabal/tests/PackageTests/.gitignore
index 0ce87ac5726d80aa5919acb89ac9560ab641b847..5c814ce39a5571dffeb4d11bd9efb4656a8bc52f 100644
--- a/Cabal/tests/PackageTests/.gitignore
+++ b/Cabal/tests/PackageTests/.gitignore
@@ -1,3 +1,4 @@
 test-log.txt
 Setup
 /TestSuiteExeV10/dist-*
+tmp.package.conf
diff --git a/Cabal/tests/PackageTests/DeterministicAr/Check.hs b/Cabal/tests/PackageTests/DeterministicAr/Check.hs
index 6e1ea9932c35d83fc378b2b3360ae9f4a313c7f9..e10e798f3dda79a4fd152940d0376250dc401ec2 100644
--- a/Cabal/tests/PackageTests/DeterministicAr/Check.hs
+++ b/Cabal/tests/PackageTests/DeterministicAr/Check.hs
@@ -17,7 +17,7 @@ import Distribution.Package               (getHSLibraryName)
 import Distribution.Version               (Version(..))
 import Distribution.Simple.Compiler       (compilerId)
 import Distribution.Simple.Configure      (getPersistBuildConfig)
-import Distribution.Simple.LocalBuildInfo (LocalBuildInfo, compiler, localLibraryName)
+import Distribution.Simple.LocalBuildInfo (LocalBuildInfo, compiler, localComponentId)
 
 -- Perhaps these should live in PackageTester.
 
@@ -51,7 +51,7 @@ checkMetadata :: LocalBuildInfo -> FilePath -> Assertion
 checkMetadata lbi dir = withBinaryFile path ReadMode $ \ h -> do
     hFileSize h >>= checkArchive h
   where
-    path = dir </> "lib" ++ getHSLibraryName (localLibraryName lbi) ++ ".a"
+    path = dir </> "lib" ++ getHSLibraryName (localComponentId lbi) ++ ".a"
 
     _ghc_7_10 = case compilerId (compiler lbi) of
       CompilerId GHC version | version >= Version [7, 10] [] -> True
diff --git a/Cabal/tests/PackageTests/PackageTester.hs b/Cabal/tests/PackageTests/PackageTester.hs
index f721bc04935a0245bb5f86707cbe6c6dfbcc7958..00d6feff6d62b11607672dd72ffbb5399d3415b9 100644
--- a/Cabal/tests/PackageTests/PackageTester.hs
+++ b/Cabal/tests/PackageTests/PackageTester.hs
@@ -15,6 +15,7 @@ module PackageTests.PackageTester
     , cabal_test
     , cabal_bench
     , cabal_install
+    , cabal_register
     , unregister
     , compileSetup
     , run
@@ -27,6 +28,8 @@ module PackageTests.PackageTester
     , assertTestSucceeded
     , assertTestFailed
     , assertInstallSucceeded
+    , assertRegisterSucceeded
+    , assertRegisterFailed
     , assertOutputContains
     , assertOutputDoesNotContain
     ) where
@@ -72,6 +75,7 @@ data Success = Failure
              | BuildSuccess
              | HaddockSuccess
              | InstallSuccess
+             | RegisterSuccess
              | TestSuccess
              | BenchSuccess
              deriving (Eq, Show)
@@ -176,6 +180,26 @@ cabal_install config spec = do
     record spec res
     return res
 
+cabal_register :: SuiteConfig -> PackageSpec -> [String] -> IO Result
+cabal_register config spec extraArgs = do
+    res <- doCabalRegister config spec extraArgs
+    record spec res
+    return res
+
+doCabalRegister :: SuiteConfig -> PackageSpec -> [String] -> IO Result
+doCabalRegister config spec extraArgs = do
+    configResult <- doCabalConfigure config spec
+    if successful configResult
+        then do
+            buildResult <- doCabalBuild config spec
+            if successful buildResult
+              then do res <- cabal config spec [] ("register" : extraArgs)
+                      return $ recordRun res RegisterSuccess configResult
+              else return buildResult
+        else
+            return configResult
+
+
 cabal_test :: SuiteConfig -> PackageSpec -> [(String, Maybe String)]
            -> [String] -> IO Result
 cabal_test config spec envOverrides extraArgs = do
@@ -310,6 +334,19 @@ assertInstallSucceeded result = unless (successful result) $
     "expected: \'setup install\' should succeed\n" ++
     "  output: " ++ outputText result
 
+assertRegisterSucceeded :: Result -> Assertion
+assertRegisterSucceeded result = unless (successful result) $
+    assertFailure $
+    "expected: \'setup register\' should succeed\n" ++
+    "  output: " ++ outputText result
+
+assertRegisterFailed :: Result -> Assertion
+assertRegisterFailed result = when (successful result) $
+    assertFailure $
+    "expected: \'setup register\' should fail\n" ++
+    "  output: " ++ outputText result
+
+
 assertOutputContains :: String -> Result -> Assertion
 assertOutputContains needle result =
     unless (needle `isInfixOf` (concatOutput output)) $
diff --git a/Cabal/tests/PackageTests/ReexportedModules/LICENSE b/Cabal/tests/PackageTests/ReexportedModules/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/Cabal/tests/PackageTests/TestSuiteTests/ExeV10/Check.hs b/Cabal/tests/PackageTests/TestSuiteTests/ExeV10/Check.hs
index 299e29ccb934338d0f9475a0cbae081bfee0a6a9..50581a9a70cb50d8140d3f970fc64672ba911d89 100644
--- a/Cabal/tests/PackageTests/TestSuiteTests/ExeV10/Check.hs
+++ b/Cabal/tests/PackageTests/TestSuiteTests/ExeV10/Check.hs
@@ -13,7 +13,7 @@ import Distribution.Compiler (CompilerFlavor(..), CompilerId(..))
 import Distribution.PackageDescription (package)
 import Distribution.Simple.Compiler (compilerId)
 import Distribution.Simple.Configure (getPersistBuildConfig)
-import Distribution.Simple.LocalBuildInfo (compiler, localPkgDescr, localPackageKey)
+import Distribution.Simple.LocalBuildInfo (compiler, localPkgDescr, localCompatPackageKey)
 import Distribution.Simple.Hpc
 import Distribution.Simple.Program.Builtin (hpcProgram)
 import Distribution.Simple.Program.Db
@@ -86,7 +86,7 @@ checkTestWithHpc config name extraOpts = do
             CompilerId comp version = compilerId (compiler lbi)
             subdir
               | comp == GHC && version >= Version [7, 10] [] =
-                  display (localPackageKey lbi)
+                  display (localCompatPackageKey lbi)
               | otherwise = display (package $ localPkgDescr lbi)
         mapM_ shouldExist
             [ mixDir distPref' way "my-0.1" </> subdir </> "Foo.mix"
diff --git a/Cabal/tests/PackageTests/UniqueIPID/Check.hs b/Cabal/tests/PackageTests/UniqueIPID/Check.hs
new file mode 100644
index 0000000000000000000000000000000000000000..6a45ce9d92ac70f8f38173d5939acb171274f317
--- /dev/null
+++ b/Cabal/tests/PackageTests/UniqueIPID/Check.hs
@@ -0,0 +1,47 @@
+module PackageTests.UniqueIPID.Check (suite) where
+
+import System.FilePath ((</>))
+
+import PackageTests.PackageTester
+import Test.Tasty.HUnit (Assertion, assertFailure)
+import Data.List
+import Distribution.Compat.Exception
+
+import Control.Monad ( when )
+import System.Directory
+
+this :: String
+this = "UniqueIPID"
+
+suite :: SuiteConfig -> Assertion
+suite config = do
+    let dir = "PackageTests" </> this
+        db = "tmp.package.conf"
+        spec1 = PackageSpec
+                { directory = dir </> "P1"
+                , configOpts = ["--package-db", ".." </> db]
+                , distPref = Nothing
+                }
+        spec2 = PackageSpec
+                { directory = dir </> "P2"
+                , configOpts = ["--package-db", ".." </> db]
+                , distPref = Nothing
+                }
+    removeDirectoryRecursive (dir </> db) `catchIO` const (return ())
+    _ <- run Nothing (ghcPkgPath config) [] ["init", dir </> db]
+    _ <- cabal_configure config spec1
+    _ <- cabal_configure config spec2
+    _ <- cabal_build config spec1
+    _ <- cabal_build config spec1 -- test rebuild cycle works
+    hResult1 <- cabal_register config spec1 ["--print-ipid", "--inplace"]
+    assertRegisterSucceeded hResult1
+    _ <- cabal_build config spec2
+    hResult2 <- cabal_register config spec2 ["--print-ipid", "--inplace"]
+    assertRegisterSucceeded hResult2
+    when ((exIPID $ outputText hResult1) == (exIPID $ outputText hResult2)) $
+      assertFailure $ "cabal has not calculated different Installed " ++
+        "package ID when source is changed."
+  where
+    exIPID s = takeWhile (/= '\n') $
+                 head . filter (isPrefixOf $ this ++ "-0.1-") $ (tails s)
+
diff --git a/Cabal/tests/PackageTests/UniqueIPID/P1/M.hs b/Cabal/tests/PackageTests/UniqueIPID/P1/M.hs
new file mode 100644
index 0000000000000000000000000000000000000000..33b222fbb9084ac4bd1f43348fc421ce831a9a39
--- /dev/null
+++ b/Cabal/tests/PackageTests/UniqueIPID/P1/M.hs
@@ -0,0 +1,3 @@
+module M(m) where
+
+m = print "1"
diff --git a/Cabal/tests/PackageTests/UniqueIPID/P1/my.cabal b/Cabal/tests/PackageTests/UniqueIPID/P1/my.cabal
new file mode 100644
index 0000000000000000000000000000000000000000..2ee178cc52988dc2629d39694846d1a4d9119f40
--- /dev/null
+++ b/Cabal/tests/PackageTests/UniqueIPID/P1/my.cabal
@@ -0,0 +1,15 @@
+name: UniqueIPID
+version: 0.1
+license: BSD3
+author: Vishal Agrawal
+stability: stable
+category: PackageTests
+build-type: Simple
+Cabal-version: >= 1.2
+
+description:
+    Check that Cabal generates unique IPID based on source.
+
+Library
+    exposed-modules: M
+    build-depends: base
diff --git a/Cabal/tests/PackageTests/UniqueIPID/P2/M.hs b/Cabal/tests/PackageTests/UniqueIPID/P2/M.hs
new file mode 100644
index 0000000000000000000000000000000000000000..05d451cda9b9fcd4583e236c94df651d38ace335
--- /dev/null
+++ b/Cabal/tests/PackageTests/UniqueIPID/P2/M.hs
@@ -0,0 +1,3 @@
+module M(m) where
+
+m = print "2"
diff --git a/Cabal/tests/PackageTests/UniqueIPID/P2/my.cabal b/Cabal/tests/PackageTests/UniqueIPID/P2/my.cabal
new file mode 100644
index 0000000000000000000000000000000000000000..ad8691d58630832018e05b93860a36bb98215116
--- /dev/null
+++ b/Cabal/tests/PackageTests/UniqueIPID/P2/my.cabal
@@ -0,0 +1,15 @@
+name: UniqueIPID
+version: 0.1
+license: BSD3
+author: Vishal Agrawal
+stability: stable
+category: PackageTests
+build-type: Simple
+Cabal-version: >= 1.2
+
+description:
+    Check that Cabal generates unique IPID based on source.
+
+Library
+    exposed-modules: M
+    build-depends: base, containers
diff --git a/Cabal/tests/PackageTests/multInst/my.cabal b/Cabal/tests/PackageTests/multInst/my.cabal
new file mode 100644
index 0000000000000000000000000000000000000000..176ced9b4de447c8d6d13330b9f0be61ce1e20fa
--- /dev/null
+++ b/Cabal/tests/PackageTests/multInst/my.cabal
@@ -0,0 +1,16 @@
+name: Haddock
+version: 0.1
+license: BSD3
+author: Iain Nicol
+stability: stable
+category: PackageTests
+build-type: Simple
+Cabal-version: >= 1.2
+
+description:
+    Check that Cabal successfully invokes Haddock.
+
+Library
+    exposed-modules: CPP, Literate, NoCPP, Simple
+    other-extensions: CPP
+    build-depends: base
diff --git a/cabal-install/Distribution/Client/Config.hs b/cabal-install/Distribution/Client/Config.hs
index ebc60301461192c50dae4400afcfbdc7b7768f3c..dbcafe771b483ef8780ef571ebec1c2f973e5b48 100644
--- a/cabal-install/Distribution/Client/Config.hs
+++ b/cabal-install/Distribution/Client/Config.hs
@@ -293,6 +293,7 @@ instance Monoid SavedConfig where
         configExtraLibDirs        = lastNonEmpty configExtraLibDirs,
         -- TODO: NubListify
         configExtraIncludeDirs    = lastNonEmpty configExtraIncludeDirs,
+        configIPID                = combine configIPID,
         configDistPref            = combine configDistPref,
         configVerbosity           = combine configVerbosity,
         configUserInstall         = combine configUserInstall,
diff --git a/cabal-install/Distribution/Client/Configure.hs b/cabal-install/Distribution/Client/Configure.hs
index 677fb50a5c58327f09b947087dd25bdd4467f7a8..4f27911e9e14aea831f75f658dfa1307ce399c82 100644
--- a/cabal-install/Distribution/Client/Configure.hs
+++ b/cabal-install/Distribution/Client/Configure.hs
@@ -49,7 +49,7 @@ import Distribution.Simple.Utils
          ( defaultPackageDesc )
 import qualified Distribution.InstalledPackageInfo as Installed
 import Distribution.Package
-         ( Package(..), InstalledPackageId, packageName
+         ( Package(..), ComponentId, packageName
          , Dependency(..), thisPackageVersion
          )
 import qualified Distribution.PackageDescription as PkgDesc
@@ -217,14 +217,14 @@ configureSetupScript packageDBs
         -- but if the user is using an odd db stack, don't touch it
         _otherwise -> (packageDBs, Just index)
 
-    explicitSetupDeps :: Maybe [(InstalledPackageId, PackageId)]
+    explicitSetupDeps :: Maybe [(ComponentId, PackageId)]
     explicitSetupDeps = do
       ReadyPackage (ConfiguredPackage (SourcePackage _ gpkg _ _) _ _ _) deps
                  <- mpkg
       -- Check if there is an explicit setup stanza
       _buildInfo <- PkgDesc.setupBuildInfo (PkgDesc.packageDescription gpkg)
       -- Return the setup dependencies computed by the solver
-      return [ ( Installed.installedPackageId deppkg
+      return [ ( Installed.installedComponentId deppkg
                , Installed.sourcePackageId    deppkg
                )
              | deppkg <- CD.setupDeps deps
@@ -356,7 +356,7 @@ configurePackage verbosity platform comp scriptOptions configFlags
       configConstraints  = [ thisPackageVersion (packageId deppkg)
                            | deppkg <- CD.nonSetupDeps deps ],
       configDependencies = [ (packageName (Installed.sourcePackageId deppkg),
-                              Installed.installedPackageId deppkg)
+                              Installed.installedComponentId deppkg)
                            | deppkg <- CD.nonSetupDeps deps ],
       -- Use '--exact-configuration' if supported.
       configExactConfiguration = toFlag True,
diff --git a/cabal-install/Distribution/Client/Dependency.hs b/cabal-install/Distribution/Client/Dependency.hs
index 36142ded385542772e8f7f08a138466eb1fd5444..5e122254ebde67096b012828bc4ade70cedb1543 100644
--- a/cabal-install/Distribution/Client/Dependency.hs
+++ b/cabal-install/Distribution/Client/Dependency.hs
@@ -53,7 +53,7 @@ module Distribution.Client.Dependency (
     setStrongFlags,
     setMaxBackjumps,
     addSourcePackages,
-    hideInstalledPackagesSpecificByInstalledPackageId,
+    hideInstalledPackagesSpecificByComponentId,
     hideInstalledPackagesSpecificBySourcePackageId,
     hideInstalledPackagesAllVersions,
     removeUpperBounds
@@ -88,7 +88,7 @@ import qualified Distribution.InstalledPackageInfo as Installed
 import Distribution.Package
          ( PackageName(..), PackageIdentifier(PackageIdentifier), PackageId
          , Package(..), packageName, packageVersion
-         , InstalledPackageId, Dependency(Dependency))
+         , ComponentId, Dependency(Dependency))
 import qualified Distribution.PackageDescription as PD
          ( PackageDescription(..), Library(..), Executable(..)
          , TestSuite(..), Benchmark(..), SetupBuildInfo(..)
@@ -302,14 +302,14 @@ addSourcePackages pkgs params =
               (depResolverSourcePkgIndex params) pkgs
     }
 
-hideInstalledPackagesSpecificByInstalledPackageId :: [InstalledPackageId]
+hideInstalledPackagesSpecificByComponentId :: [ComponentId]
                                                      -> DepResolverParams
                                                      -> DepResolverParams
-hideInstalledPackagesSpecificByInstalledPackageId pkgids params =
+hideInstalledPackagesSpecificByComponentId pkgids params =
     --TODO: this should work using exclude constraints instead
     params {
       depResolverInstalledPkgIndex =
-        foldl' (flip InstalledPackageIndex.deleteInstalledPackageId)
+        foldl' (flip InstalledPackageIndex.deleteComponentId)
                (depResolverInstalledPkgIndex params) pkgids
     }
 
@@ -337,12 +337,12 @@ hideInstalledPackagesAllVersions pkgnames params =
 
 hideBrokenInstalledPackages :: DepResolverParams -> DepResolverParams
 hideBrokenInstalledPackages params =
-    hideInstalledPackagesSpecificByInstalledPackageId pkgids params
+    hideInstalledPackagesSpecificByComponentId pkgids params
   where
-    pkgids = map Installed.installedPackageId
+    pkgids = map Installed.installedComponentId
            . InstalledPackageIndex.reverseDependencyClosure
                             (depResolverInstalledPkgIndex params)
-           . map (Installed.installedPackageId . fst)
+           . map (Installed.installedComponentId . fst)
            . InstalledPackageIndex.brokenPackages
            $ depResolverInstalledPkgIndex params
 
diff --git a/cabal-install/Distribution/Client/Dependency/Modular/ConfiguredConversion.hs b/cabal-install/Distribution/Client/Dependency/Modular/ConfiguredConversion.hs
index 714eb845391afb2ec2d5ea3f77aa096ef4cdd13f..1e562adf2efe89c26a02523b53bdaca83066c096 100644
--- a/cabal-install/Distribution/Client/Dependency/Modular/ConfiguredConversion.hs
+++ b/cabal-install/Distribution/Client/Dependency/Modular/ConfiguredConversion.hs
@@ -19,7 +19,7 @@ convCP :: SI.InstalledPackageIndex -> CI.PackageIndex SourcePackage ->
 convCP iidx sidx (CP qpi fa es ds) =
   case convPI qpi of
     Left  pi -> PreExisting
-                  (fromJust $ SI.lookupInstalledPackageId iidx pi)
+                  (fromJust $ SI.lookupComponentId iidx pi)
     Right pi -> Configured $ ConfiguredPackage
                   (fromJust $ CI.lookupPackageId sidx pi)
                   fa
@@ -29,7 +29,7 @@ convCP iidx sidx (CP qpi fa es ds) =
     ds' :: ComponentDeps [ConfiguredId]
     ds' = fmap (map convConfId) ds
 
-convPI :: PI QPN -> Either InstalledPackageId PackageId
+convPI :: PI QPN -> Either ComponentId PackageId
 convPI (PI _ (I _ (Inst pi))) = Left pi
 convPI qpi                    = Right $ confSrcId $ convConfId qpi
 
@@ -42,4 +42,4 @@ convConfId (PI (Q _ pn) (I v loc)) = ConfiguredId {
     sourceId    = PackageIdentifier pn v
     installedId = case loc of
                     Inst pi    -> pi
-                    _otherwise -> fakeInstalledPackageId sourceId
+                    _otherwise -> fakeComponentId sourceId
diff --git a/cabal-install/Distribution/Client/Dependency/Modular/IndexConversion.hs b/cabal-install/Distribution/Client/Dependency/Modular/IndexConversion.hs
index 6da6efdd2f5d02b2a39957d9a12845f498edc7b9..fcb06896d9a10b49bc0d0403b5f5f3329fb83d17 100644
--- a/cabal-install/Distribution/Client/Dependency/Modular/IndexConversion.hs
+++ b/cabal-install/Distribution/Client/Dependency/Modular/IndexConversion.hs
@@ -65,7 +65,7 @@ convIPI sip = mkIndex . convIPI' sip
 -- | Convert a single installed package into the solver-specific format.
 convIP :: SI.InstalledPackageIndex -> InstalledPackageInfo -> (PN, I, PInfo)
 convIP idx ipi =
-  let ipid = IPI.installedPackageId ipi
+  let ipid = IPI.installedComponentId ipi
       i = I (pkgVersion (sourcePackageId ipi)) (Inst ipid)
       pn = pkgName (sourcePackageId ipi)
   in  case mapM (convIPId pn idx) (IPI.depends ipi) of
@@ -82,9 +82,9 @@ convIP idx ipi =
 -- May return Nothing if the package can't be found in the index. That
 -- indicates that the original package having this dependency is broken
 -- and should be ignored.
-convIPId :: PN -> SI.InstalledPackageIndex -> InstalledPackageId -> Maybe (FlaggedDep () PN)
+convIPId :: PN -> SI.InstalledPackageIndex -> ComponentId -> Maybe (FlaggedDep () PN)
 convIPId pn' idx ipid =
-  case SI.lookupInstalledPackageId idx ipid of
+  case SI.lookupComponentId idx ipid of
     Nothing  -> Nothing
     Just ipi -> let i = I (pkgVersion (sourcePackageId ipi)) (Inst ipid)
                     pn = pkgName (sourcePackageId ipi)
diff --git a/cabal-install/Distribution/Client/Dependency/Modular/Package.hs b/cabal-install/Distribution/Client/Dependency/Modular/Package.hs
index 1d0e328386ce3131cd6b2f7fad857b2a67ec80cd..503950ea915b517c380e6d929e1c5cfd308b4cda 100644
--- a/cabal-install/Distribution/Client/Dependency/Modular/Package.hs
+++ b/cabal-install/Distribution/Client/Dependency/Modular/Package.hs
@@ -24,7 +24,7 @@ type PV = PackageId
 type QPV = Q PV
 
 -- | Package id. Currently just a black-box string.
-type PId = InstalledPackageId
+type PId = ComponentId
 
 -- | Location. Info about whether a package is installed or not, and where
 -- exactly it is located. For installed packages, uniquely identifies the
@@ -41,7 +41,7 @@ data I = I Ver Loc
 -- | String representation of an instance.
 showI :: I -> String
 showI (I v InRepo)   = showVer v
-showI (I v (Inst (InstalledPackageId i))) = showVer v ++ "/installed" ++ shortId i
+showI (I v (Inst (ComponentId i))) = showVer v ++ "/installed" ++ shortId i
   where
     -- A hack to extract the beginning of the package ABI hash
     shortId = snip (splitAt 4) (++ "...") .
diff --git a/cabal-install/Distribution/Client/Dependency/TopDown.hs b/cabal-install/Distribution/Client/Dependency/TopDown.hs
index 52f8fa5822c7d4988f0d31b911027e1795f87447..e7bb9f1077bceea71ec7fcc4810f65eb4fd7db4a 100644
--- a/cabal-install/Distribution/Client/Dependency/TopDown.hs
+++ b/cabal-install/Distribution/Client/Dependency/TopDown.hs
@@ -21,7 +21,7 @@ import Distribution.Client.Dependency.TopDown.Constraints
          ( Satisfiable(..) )
 import Distribution.Client.Types
          ( SourcePackage(..), ConfiguredPackage(..)
-         , enableStanzas, ConfiguredId(..), fakeInstalledPackageId )
+         , enableStanzas, ConfiguredId(..), fakeComponentId )
 import Distribution.Client.Dependency.Types
          ( DependencyResolver, ResolverPackage(..)
          , PackageConstraint(..), unlabelPackageConstraint
@@ -39,7 +39,7 @@ import Distribution.Client.PackageIndex
          ( PackageIndex )
 import Distribution.Package
          ( PackageName(..), PackageId, PackageIdentifier(..)
-         , InstalledPackageId(..)
+         , ComponentId(..)
          , Package(..), packageVersion, packageName
          , Dependency(Dependency), thisPackageVersion, simplifyDependency )
 import Distribution.PackageDescription
@@ -567,9 +567,9 @@ convertInstalledPackageIndex index' = PackageIndex.fromList
     | (_,ipkg:_) <- InstalledPackageIndex.allPackagesBySourcePackageId index' ]
   where
     -- The InstalledPackageInfo only lists dependencies by the
-    -- InstalledPackageId, which means we do not directly know the corresponding
+    -- ComponentId, which means we do not directly know the corresponding
     -- source dependency. The only way to find out is to lookup the
-    -- InstalledPackageId to get the InstalledPackageInfo and look at its
+    -- ComponentId to get the InstalledPackageInfo and look at its
     -- source PackageId. But if the package is broken because it depends on
     -- other packages that do not exist then we have a problem we cannot find
     -- the original source package id. Instead we make up a bogus package id.
@@ -578,10 +578,10 @@ convertInstalledPackageIndex index' = PackageIndex.fromList
     sourceDepsOf index ipkg =
       [ maybe (brokenPackageId depid) packageId mdep
       | let depids = InstalledPackageInfo.depends ipkg
-            getpkg = InstalledPackageIndex.lookupInstalledPackageId index
+            getpkg = InstalledPackageIndex.lookupComponentId index
       , (depid, mdep) <- zip depids (map getpkg depids) ]
 
-    brokenPackageId (InstalledPackageId str) =
+    brokenPackageId (ComponentId str) =
       PackageIdentifier (PackageName (str ++ "-broken")) (Version [] [])
 
 -- ------------------------------------------------------------
@@ -644,7 +644,7 @@ finaliseSelectedPackages pref selected constraints =
     confId :: InstalledOrSource InstalledPackageEx UnconfiguredPackage -> ConfiguredId
     confId pkg = ConfiguredId {
         confSrcId  = packageId pkg
-      , confInstId = fakeInstalledPackageId (packageId pkg)
+      , confInstId = fakeComponentId (packageId pkg)
       }
 
     pickRemaining mipkg dep@(Dependency _name versionRange) =
diff --git a/cabal-install/Distribution/Client/Dependency/TopDown/Types.hs b/cabal-install/Distribution/Client/Dependency/TopDown/Types.hs
index d0988c8e37badc89b5b19776e0c4c52ef99794a1..34ab6c2839de7218317d537d01f6673dad37a3e2 100644
--- a/cabal-install/Distribution/Client/Dependency/TopDown/Types.hs
+++ b/cabal-install/Distribution/Client/Dependency/TopDown/Types.hs
@@ -113,9 +113,9 @@ data InstalledConstraint = InstalledConstraint
 --
 -- The top-down solver uses its down type class for package dependencies,
 -- because it wants to know these dependencies as PackageIds, rather than as
--- InstalledPackageIds (so it cannot use PackageFixedDeps).
+-- ComponentIds (so it cannot use PackageFixedDeps).
 --
--- Ideally we would switch the top-down solver over to use InstalledPackageIds
+-- Ideally we would switch the top-down solver over to use ComponentIds
 -- throughout; that means getting rid of this type class, and changing over the
 -- package index type to use Cabal's rather than cabal-install's. That will
 -- avoid the need for the local definitions of dependencyGraph and
diff --git a/cabal-install/Distribution/Client/IndexUtils.hs b/cabal-install/Distribution/Client/IndexUtils.hs
index 4d95abd5f9dcd5d5076a3ef4a9de5a4fe1983d31..c3594ac483373e654614a8af2b5daff7c12ae71c 100644
--- a/cabal-install/Distribution/Client/IndexUtils.hs
+++ b/cabal-install/Distribution/Client/IndexUtils.hs
@@ -469,8 +469,8 @@ data IndexCacheEntry = CachePackageId PackageId BlockNo
                      | CachePreference Dependency
   deriving (Eq)
 
-packageKey, blocknoKey, buildTreeRefKey, preferredVersionKey :: String
-packageKey = "pkg:"
+installedComponentId, blocknoKey, buildTreeRefKey, preferredVersionKey :: String
+installedComponentId = "pkg:"
 blocknoKey = "b#"
 buildTreeRefKey     = "build-tree-ref:"
 preferredVersionKey = "pref-ver:"
@@ -479,7 +479,7 @@ readIndexCacheEntry :: BSS.ByteString -> Maybe IndexCacheEntry
 readIndexCacheEntry = \line ->
   case BSS.words line of
     [key, pkgnamestr, pkgverstr, sep, blocknostr]
-      | key == BSS.pack packageKey && sep == BSS.pack blocknoKey ->
+      | key == BSS.pack installedComponentId && sep == BSS.pack blocknoKey ->
       case (parseName pkgnamestr, parseVer pkgverstr [],
             parseBlockNo blocknostr) of
         (Just pkgname, Just pkgver, Just blockno)
@@ -522,7 +522,7 @@ readIndexCacheEntry = \line ->
 
 showIndexCacheEntry :: IndexCacheEntry -> String
 showIndexCacheEntry entry = unwords $ case entry of
-   CachePackageId pkgid b -> [ packageKey
+   CachePackageId pkgid b -> [ installedComponentId
                              , display (packageName pkgid)
                              , display (packageVersion pkgid)
                              , blocknoKey
diff --git a/cabal-install/Distribution/Client/Install.hs b/cabal-install/Distribution/Client/Install.hs
index 2f07429c441547fa2445ee81aad55bd923b6f8d9..7ea7a03ffbbef99f8aa805a904b1e10906e00aa7 100644
--- a/cabal-install/Distribution/Client/Install.hs
+++ b/cabal-install/Distribution/Client/Install.hs
@@ -118,6 +118,8 @@ import Distribution.Simple.Program (ProgramConfiguration,
 import qualified Distribution.Simple.InstallDirs as InstallDirs
 import qualified Distribution.Simple.PackageIndex as PackageIndex
 import Distribution.Simple.PackageIndex (InstalledPackageIndex)
+import Distribution.Simple.LocalBuildInfo (ComponentName(CLibName))
+import qualified Distribution.Simple.Configure as Configure
 import Distribution.Simple.Setup
          ( haddockCommand, HaddockFlags(..)
          , buildCommand, BuildFlags(..), emptyBuildFlags
@@ -135,10 +137,10 @@ import Distribution.Simple.InstallDirs as InstallDirs
          , initialPathTemplateEnv, installDirsTemplateEnv )
 import Distribution.Package
          ( PackageIdentifier(..), PackageId, packageName, packageVersion
-         , Package(..), LibraryName
+         , Package(..), ComponentId(..), ComponentId(..)
          , Dependency(..), thisPackageVersion
-         , InstalledPackageId, installedPackageId
-         , HasInstalledPackageId(..) )
+         , ComponentId
+         , HasComponentId(..) )
 import qualified Distribution.PackageDescription as PackageDescription
 import Distribution.PackageDescription
          ( PackageDescription, GenericPackageDescription(..), Flag(..)
@@ -484,16 +486,16 @@ checkPrintPlan verbosity installed installPlan sourcePkgDb
   let reinstalledPkgs = concatMap (extractReinstalls . snd) lPlan
   -- Packages that are already broken.
   let oldBrokenPkgs =
-          map Installed.installedPackageId
+          map Installed.installedComponentId
         . PackageIndex.reverseDependencyClosure installed
-        . map (Installed.installedPackageId . fst)
+        . map (Installed.installedComponentId . fst)
         . PackageIndex.brokenPackages
         $ installed
   let excluded = reinstalledPkgs ++ oldBrokenPkgs
   -- Packages that are reverse dependencies of replaced packages are very
   -- likely to be broken. We exclude packages that are already broken.
   let newBrokenPkgs =
-        filter (\ p -> not (Installed.installedPackageId p `elem` excluded))
+        filter (\ p -> not (Installed.installedComponentId p `elem` excluded))
                (PackageIndex.reverseDependencyClosure installed reinstalledPkgs)
   let containsReinstalls = not (null reinstalledPkgs)
   let breaksPkgs         = not (null newBrokenPkgs)
@@ -559,11 +561,11 @@ linearizeInstallPlan installedPkgIndex plan =
       []      -> Nothing
       (pkg:_) -> Just ((pkg, status), plan'')
         where
-          pkgid  = installedPackageId pkg
+          pkgid  = installedComponentId pkg
           status = packageStatus installedPkgIndex pkg
           ipkg   = Installed.emptyInstalledPackageInfo {
                      Installed.sourcePackageId    = packageId pkg,
-                     Installed.installedPackageId = pkgid
+                     Installed.installedComponentId = pkgid
                    }
           plan'' = InstallPlan.completed pkgid (Just ipkg)
                      (BuildOk DocsNotTried TestsNotTried (Just ipkg))
@@ -575,11 +577,11 @@ linearizeInstallPlan installedPkgIndex plan =
 
 data PackageStatus = NewPackage
                    | NewVersion [Version]
-                   | Reinstall  [InstalledPackageId] [PackageChange]
+                   | Reinstall  [ComponentId] [PackageChange]
 
 type PackageChange = MergeResult PackageIdentifier PackageIdentifier
 
-extractReinstalls :: PackageStatus -> [InstalledPackageId]
+extractReinstalls :: PackageStatus -> [ComponentId]
 extractReinstalls (Reinstall ipids _) = ipids
 extractReinstalls _                   = []
 
@@ -593,7 +595,7 @@ packageStatus installedPkgIndex cpkg =
     ps ->  case filter ((== packageId cpkg)
                         . Installed.sourcePackageId) (concatMap snd ps) of
       []           -> NewVersion (map fst ps)
-      pkgs@(pkg:_) -> Reinstall (map Installed.installedPackageId pkgs)
+      pkgs@(pkg:_) -> Reinstall (map Installed.installedComponentId pkgs)
                                 (changes pkg cpkg)
 
   where
@@ -609,13 +611,13 @@ packageStatus installedPkgIndex cpkg =
         (resolveInstalledIds $ CD.nonSetupDeps (depends pkg'))
 
     -- convert to source pkg ids via index
-    resolveInstalledIds :: [InstalledPackageId] -> [PackageIdentifier]
+    resolveInstalledIds :: [ComponentId] -> [PackageIdentifier]
     resolveInstalledIds =
         nub
       . sort
       . map Installed.sourcePackageId
       . catMaybes
-      . map (PackageIndex.lookupInstalledPackageId installedPkgIndex)
+      . map (PackageIndex.lookupComponentId installedPkgIndex)
 
     changed (InBoth    pkgid pkgid') = pkgid /= pkgid'
     changed _                        = True
@@ -737,7 +739,7 @@ reportPlanningFailure verbosity
     case logFile of
       Nothing -> return ()
       Just template -> forM_ pkgids $ \pkgid ->
-        let env = initialPathTemplateEnv pkgid dummyLibraryName
+        let env = initialPathTemplateEnv pkgid dummyIpid
                     (compilerInfo comp) platform
             path = fromPathTemplate $ substPathTemplate env template
         in  writeFile path message
@@ -746,10 +748,10 @@ reportPlanningFailure verbosity
     reportFailure = fromFlag (installReportPlanningFailure installFlags)
     logFile = flagToMaybe (installLogFile installFlags)
 
-    -- A LibraryName is calculated from the transitive closure of
+    -- A IPID is calculated from the transitive closure of
     -- dependencies, but when the solver fails we don't have that.
     -- So we fail.
-    dummyLibraryName = error "reportPlanningFailure: library name not available"
+    dummyIpid = error "reportPlanningFailure: installed package ID not available"
 
 -- | If a 'PackageSpecifier' refers to a single package, return Just that
 -- package.
@@ -1024,7 +1026,7 @@ data InstallMisc = InstallMisc {
 
 -- | If logging is enabled, contains location of the log file and the verbosity
 -- level for logging.
-type UseLogFile = Maybe (PackageIdentifier -> LibraryName -> FilePath, Verbosity)
+type UseLogFile = Maybe (PackageIdentifier -> ComponentId -> FilePath, Verbosity)
 
 performInstallations :: Verbosity
                      -> InstallArgs
@@ -1053,19 +1055,17 @@ performInstallations verbosity
                (flagToMaybe (globalHttpTransport globalFlags))
 
   executeInstallPlan verbosity comp jobControl useLogFile installPlan $ \rpkg ->
-    -- Calculate the package key (ToDo: Is this right for source install)
-    let libname = readyLibraryName comp rpkg in
     installReadyPackage platform cinfo configFlags
                         rpkg $ \configFlags' src pkg pkgoverride ->
       fetchSourcePackage transport verbosity fetchLimit src $ \src' ->
         installLocalPackage verbosity buildLimit
                             (packageId pkg) src' distPref $ \mpath ->
-          installUnpackedPackage verbosity buildLimit installLock numJobs libname
+          installUnpackedPackage verbosity buildLimit installLock numJobs
                                  (setupScriptOptions installedPkgIndex
                                   cacheLock rpkg)
                                  miscOptions configFlags'
                                  installFlags haddockFlags
-                                 cinfo platform pkg pkgoverride mpath useLogFile
+                                 cinfo platform pkg rpkg pkgoverride mpath useLogFile
 
   where
     cinfo = compilerInfo comp
@@ -1129,12 +1129,12 @@ performInstallations verbosity
           | parallelInstall                   = False
           | otherwise                         = False
 
-    substLogFileName :: PathTemplate -> PackageIdentifier -> LibraryName
-                     -> FilePath
-    substLogFileName template pkg libname = fromPathTemplate
-                                          . substPathTemplate env
-                                          $ template
-      where env = initialPathTemplateEnv (packageId pkg) libname
+    substLogFileName :: PathTemplate -> PackageIdentifier -> ComponentId -> FilePath
+    substLogFileName template pkg ipid = fromPathTemplate
+                                  . substPathTemplate env
+                                  $ template
+      where env = initialPathTemplateEnv (packageId pkg)
+                  ipid
                   (compilerInfo comp) platform
 
     miscOptions  = InstallMisc {
@@ -1149,12 +1149,12 @@ performInstallations verbosity
 
 executeInstallPlan :: Verbosity
                    -> Compiler
-                   -> JobControl IO (PackageId, LibraryName, BuildResult)
+                   -> JobControl IO (PackageId, ComponentId, BuildResult)
                    -> UseLogFile
                    -> InstallPlan
                    -> (ReadyPackage -> IO BuildResult)
                    -> IO InstallPlan
-executeInstallPlan verbosity comp jobCtl useLogFile plan0 installPkg =
+executeInstallPlan verbosity _comp jobCtl useLogFile plan0 installPkg =
     tryNewTasks 0 plan0
   where
     tryNewTasks taskCount plan = do
@@ -1166,10 +1166,13 @@ executeInstallPlan verbosity comp jobCtl useLogFile plan0 installPkg =
             [ do info verbosity $ "Ready to install " ++ display pkgid
                  spawnJob jobCtl $ do
                    buildResult <- installPkg pkg
-                   return (packageId pkg, libname, buildResult)
+                   let ipid = case buildResult of
+                                Right (BuildOk _ _ (Just ipi)) ->
+                                     Installed.installedComponentId ipi
+                                _ -> ComponentId (display (packageId pkg))
+                   return (packageId pkg, ipid, buildResult)
             | pkg <- pkgs
-            , let pkgid = packageId pkg
-                  libname = readyLibraryName comp pkg ]
+            , let pkgid = packageId pkg ]
 
           let taskCount' = taskCount + length pkgs
               plan'      = InstallPlan.processing pkgs plan
@@ -1177,8 +1180,8 @@ executeInstallPlan verbosity comp jobCtl useLogFile plan0 installPkg =
 
     waitForTasks taskCount plan = do
       info verbosity $ "Waiting for install task to finish..."
-      (pkgid, libname, buildResult) <- collectJob jobCtl
-      printBuildResult pkgid libname buildResult
+      (pkgid, ipid, buildResult) <- collectJob jobCtl
+      printBuildResult pkgid ipid buildResult
       let taskCount' = taskCount-1
           plan'      = updatePlan pkgid buildResult plan
       tryNewTasks taskCount' plan'
@@ -1186,11 +1189,11 @@ executeInstallPlan verbosity comp jobCtl useLogFile plan0 installPkg =
     updatePlan :: PackageIdentifier -> BuildResult -> InstallPlan
                -> InstallPlan
     updatePlan pkgid (Right buildSuccess@(BuildOk _ _ mipkg)) =
-        InstallPlan.completed (Source.fakeInstalledPackageId pkgid)
+        InstallPlan.completed (Source.fakeComponentId pkgid)
                               mipkg buildSuccess
 
     updatePlan pkgid (Left buildFailure) =
-        InstallPlan.failed (Source.fakeInstalledPackageId pkgid)
+        InstallPlan.failed (Source.fakeComponentId pkgid)
                            buildFailure depsFailure
       where
         depsFailure = DependentFailed pkgid
@@ -1201,8 +1204,8 @@ executeInstallPlan verbosity comp jobCtl useLogFile plan0 installPkg =
 
     -- Print build log if something went wrong, and 'Installed $PKGID'
     -- otherwise.
-    printBuildResult :: PackageId -> LibraryName -> BuildResult -> IO ()
-    printBuildResult pkgid libname buildResult = case buildResult of
+    printBuildResult :: PackageId -> ComponentId -> BuildResult -> IO ()
+    printBuildResult pkgid ipid buildResult = case buildResult of
         (Right _) -> notice verbosity $ "Installed " ++ display pkgid
         (Left _)  -> do
           notice verbosity $ "Failed to install " ++ display pkgid
@@ -1210,7 +1213,7 @@ executeInstallPlan verbosity comp jobCtl useLogFile plan0 installPkg =
             case useLogFile of
               Nothing                 -> return ()
               Just (mkLogFileName, _) -> do
-                let logName = mkLogFileName pkgid libname
+                let logName = mkLogFileName pkgid ipid
                 putStr $ "Build log ( " ++ logName ++ " ):\n"
                 printFile logName
 
@@ -1247,7 +1250,7 @@ installReadyPackage platform cinfo configFlags
     configConstraints  = [ thisPackageVersion (packageId deppkg)
                          | deppkg <- CD.nonSetupDeps deps ],
     configDependencies = [ (packageName (Installed.sourcePackageId deppkg),
-                            Installed.installedPackageId deppkg)
+                            Installed.installedComponentId deppkg)
                          | deppkg <- CD.nonSetupDeps deps ],
     -- Use '--exact-configuration' if supported.
     configExactConfiguration = toFlag True,
@@ -1363,7 +1366,6 @@ installUnpackedPackage
   -> JobLimit
   -> Lock
   -> Int
-  -> LibraryName
   -> SetupScriptOptions
   -> InstallMisc
   -> ConfigFlags
@@ -1372,14 +1374,15 @@ installUnpackedPackage
   -> CompilerInfo
   -> Platform
   -> PackageDescription
+  -> ReadyPackage
   -> PackageDescriptionOverride
   -> Maybe FilePath -- ^ Directory to change to before starting the installation.
   -> UseLogFile -- ^ File to log output to (if any)
   -> IO BuildResult
-installUnpackedPackage verbosity buildLimit installLock numJobs libname
+installUnpackedPackage verbosity buildLimit installLock numJobs
                        scriptOptions miscOptions
                        configFlags installFlags haddockFlags
-                       cinfo platform pkg pkgoverride workingDir useLogFile = do
+                       cinfo platform pkg rpkg pkgoverride workingDir useLogFile = do
 
   -- Override the .cabal file if necessary
   case pkgoverride of
@@ -1392,9 +1395,15 @@ installUnpackedPackage verbosity buildLimit installLock numJobs libname
                     ++ " with the latest revision from the index."
       writeFileAtomic descFilePath pkgtxt
 
+  -- Compute the IPID
+  let flags (ReadyPackage (ConfiguredPackage _ x _ _) _) = x
+  ipid <- inDir workingDir
+        $ Configure.computeComponentId pkg CLibName
+                (CD.libraryDeps (depends rpkg)) (flags rpkg)
+
   -- Make sure that we pass --libsubdir etc to 'setup configure' (necessary if
   -- the setup script was compiled against an old version of the Cabal lib).
-  configFlags' <- addDefaultInstallDirs configFlags
+  configFlags' <- addDefaultInstallDirs ipid configFlags
   -- Filter out flags not supported by the old versions of the Cabal lib.
   let configureFlags :: Version -> ConfigFlags
       configureFlags  = filterConfigureFlags configFlags' {
@@ -1402,7 +1411,7 @@ installUnpackedPackage verbosity buildLimit installLock numJobs libname
       }
 
   -- Path to the optional log file.
-  mLogPath <- maybeLogPath
+  mLogPath <- maybeLogPath ipid
 
   -- Configure phase
   onFailure ConfigureFailed $ withJobLimit buildLimit $ do
@@ -1438,7 +1447,7 @@ installUnpackedPackage verbosity buildLimit installLock numJobs libname
           maybePkgConf <- maybeGenPkgConf mLogPath
 
           -- Actual installation
-          withWin32SelfUpgrade verbosity libname configFlags
+          withWin32SelfUpgrade verbosity ipid configFlags
                                cinfo platform pkg $ do
             case rootCmd miscOptions of
               (Just cmd) -> reexec cmd
@@ -1478,8 +1487,8 @@ installUnpackedPackage verbosity buildLimit installLock numJobs libname
     verbosity' = maybe verbosity snd useLogFile
     tempTemplate name = name ++ "-" ++ display pkgid
 
-    addDefaultInstallDirs :: ConfigFlags -> IO ConfigFlags
-    addDefaultInstallDirs configFlags' = do
+    addDefaultInstallDirs :: ComponentId -> ConfigFlags -> IO ConfigFlags
+    addDefaultInstallDirs ipid configFlags' = do
       defInstallDirs <- InstallDirs.defaultInstallDirs flavor userInstall False
       return $ configFlags' {
           configInstallDirs = fmap Cabal.Flag .
@@ -1489,7 +1498,7 @@ installUnpackedPackage verbosity buildLimit installLock numJobs libname
           }
         where
           CompilerId flavor _ = compilerInfoId cinfo
-          env         = initialPathTemplateEnv pkgid libname cinfo platform
+          env         = initialPathTemplateEnv pkgid ipid cinfo platform
           userInstall = fromFlagOrDefault defaultUserInstall
                         (configUserInstall configFlags')
 
@@ -1518,12 +1527,12 @@ installUnpackedPackage verbosity buildLimit installLock numJobs libname
       die $ "Couldn't parse the output of 'setup register --gen-pkg-config':"
             ++ show perror
 
-    maybeLogPath :: IO (Maybe FilePath)
-    maybeLogPath =
+    maybeLogPath :: ComponentId -> IO (Maybe FilePath)
+    maybeLogPath ipid =
       case useLogFile of
          Nothing                 -> return Nothing
          Just (mkLogFileName, _) -> do
-           let logFileName = mkLogFileName (packageId pkg) libname
+           let logFileName = mkLogFileName (packageId pkg) ipid
                logDir      = takeDirectory logFileName
            unless (null logDir) $ createDirectoryIfMissing True logDir
            logFileExists <- doesFileExist logFileName
@@ -1571,14 +1580,14 @@ onFailure result action =
 -- ------------------------------------------------------------
 
 withWin32SelfUpgrade :: Verbosity
-                     -> LibraryName
+                     -> ComponentId
                      -> ConfigFlags
                      -> CompilerInfo
                      -> Platform
                      -> PackageDescription
                      -> IO a -> IO a
 withWin32SelfUpgrade _ _ _ _ _ _ action | buildOS /= Windows = action
-withWin32SelfUpgrade verbosity libname configFlags cinfo platform pkg action = do
+withWin32SelfUpgrade verbosity ipid configFlags cinfo platform pkg action = do
 
   defaultDirs <- InstallDirs.defaultInstallDirs
                    compFlavor
@@ -1606,10 +1615,10 @@ withWin32SelfUpgrade verbosity libname configFlags cinfo platform pkg action = d
         templateDirs   = InstallDirs.combineInstallDirs fromFlagOrDefault
                            defaultDirs (configInstallDirs configFlags)
         absoluteDirs   = InstallDirs.absoluteInstallDirs
-                           pkgid libname
+                           pkgid ipid
                            cinfo InstallDirs.NoCopyDest
                            platform templateDirs
         substTemplate  = InstallDirs.fromPathTemplate
                        . InstallDirs.substPathTemplate env
-          where env = InstallDirs.initialPathTemplateEnv pkgid libname
+          where env = InstallDirs.initialPathTemplateEnv pkgid ipid
                       cinfo platform
diff --git a/cabal-install/Distribution/Client/InstallPlan.hs b/cabal-install/Distribution/Client/InstallPlan.hs
index 671cfa903624fa985c0ea3683ca33850c9d1e0ee..55820eea2794fe411a4c4375c2fd64e7abd31c60 100644
--- a/cabal-install/Distribution/Client/InstallPlan.hs
+++ b/cabal-install/Distribution/Client/InstallPlan.hs
@@ -48,11 +48,11 @@ import Distribution.InstalledPackageInfo
          ( InstalledPackageInfo )
 import Distribution.Package
          ( PackageIdentifier(..), PackageName(..), Package(..)
-         , InstalledPackageId, HasInstalledPackageId(..) )
+         , HasComponentId(..), ComponentId(..) )
 import Distribution.Client.Types
          ( BuildSuccess, BuildFailure
          , PackageFixedDeps(..), ConfiguredPackage
-         , GenericReadyPackage(..), fakeInstalledPackageId )
+         , GenericReadyPackage(..), fakeComponentId )
 import Distribution.Version
          ( Version )
 import Distribution.Client.ComponentDeps (ComponentDeps)
@@ -152,7 +152,7 @@ instance (Package ipkg, Package srcpkg) =>
   packageId (Failed      spkg   _) = packageId spkg
 
 instance (PackageFixedDeps srcpkg,
-          PackageFixedDeps ipkg, HasInstalledPackageId ipkg) =>
+          PackageFixedDeps ipkg, HasComponentId ipkg) =>
          PackageFixedDeps (GenericPlanPackage ipkg srcpkg iresult ifailure) where
   depends (PreExisting pkg)     = depends pkg
   depends (Configured  pkg)     = depends pkg
@@ -160,16 +160,16 @@ instance (PackageFixedDeps srcpkg,
   depends (Installed   pkg _ _) = depends pkg
   depends (Failed      pkg   _) = depends pkg
 
-instance (HasInstalledPackageId ipkg, HasInstalledPackageId srcpkg) =>
-         HasInstalledPackageId
+instance (HasComponentId ipkg, HasComponentId srcpkg) =>
+         HasComponentId
          (GenericPlanPackage ipkg srcpkg iresult ifailure) where
-  installedPackageId (PreExisting ipkg ) = installedPackageId ipkg
-  installedPackageId (Configured  spkg)  = installedPackageId spkg
-  installedPackageId (Processing  rpkg)  = installedPackageId rpkg
+  installedComponentId (PreExisting ipkg ) = installedComponentId ipkg
+  installedComponentId (Configured  spkg)  = installedComponentId spkg
+  installedComponentId (Processing  rpkg)  = installedComponentId rpkg
   -- NB: defer to the actual installed package info in this case
-  installedPackageId (Installed _ (Just ipkg) _) = installedPackageId ipkg
-  installedPackageId (Installed rpkg _        _) = installedPackageId rpkg
-  installedPackageId (Failed      spkg        _) = installedPackageId spkg
+  installedComponentId (Installed _ (Just ipkg) _) = installedComponentId ipkg
+  installedComponentId (Installed rpkg _        _) = installedComponentId rpkg
+  installedComponentId (Failed      spkg        _) = installedComponentId spkg
 
 
 data GenericInstallPlan ipkg srcpkg iresult ifailure = GenericInstallPlan {
@@ -179,7 +179,7 @@ data GenericInstallPlan ipkg srcpkg iresult ifailure = GenericInstallPlan {
     planGraphRev   :: Graph,
     planPkgOf      :: Graph.Vertex
                       -> GenericPlanPackage ipkg srcpkg iresult ifailure,
-    planVertexOf   :: InstalledPackageId -> Graph.Vertex,
+    planVertexOf   :: ComponentId -> Graph.Vertex,
     planIndepGoals :: Bool
   }
 
@@ -191,8 +191,8 @@ type InstallPlan = GenericInstallPlan
 type PlanIndex ipkg srcpkg iresult ifailure =
      PackageIndex (GenericPlanPackage ipkg srcpkg iresult ifailure)
 
-invariant :: (HasInstalledPackageId ipkg,   PackageFixedDeps ipkg,
-              HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg)
+invariant :: (HasComponentId ipkg,   PackageFixedDeps ipkg,
+              HasComponentId srcpkg, PackageFixedDeps srcpkg)
           => GenericInstallPlan ipkg srcpkg iresult ifailure -> Bool
 invariant plan =
     valid (planFakeMap plan)
@@ -202,16 +202,16 @@ invariant plan =
 internalError :: String -> a
 internalError msg = error $ "InstallPlan: internal error: " ++ msg
 
-showPlanIndex :: (HasInstalledPackageId ipkg, HasInstalledPackageId srcpkg)
+showPlanIndex :: (HasComponentId ipkg, HasComponentId srcpkg)
               => PlanIndex ipkg srcpkg iresult ifailure -> String
 showPlanIndex index =
     intercalate "\n" (map showPlanPackage (PackageIndex.allPackages index))
   where showPlanPackage p =
             showPlanPackageTag p ++ " "
                 ++ display (packageId p) ++ " ("
-                ++ display (installedPackageId p) ++ ")"
+                ++ display (installedComponentId p) ++ ")"
 
-showInstallPlan :: (HasInstalledPackageId ipkg, HasInstalledPackageId srcpkg)
+showInstallPlan :: (HasComponentId ipkg, HasComponentId srcpkg)
                 => GenericInstallPlan ipkg srcpkg iresult ifailure -> String
 showInstallPlan plan =
     showPlanIndex (planIndex plan) ++ "\n" ++
@@ -228,8 +228,8 @@ showPlanPackageTag (Failed    _   _) = "Failed"
 
 -- | Build an installation plan from a valid set of resolved packages.
 --
-new :: (HasInstalledPackageId ipkg,   PackageFixedDeps ipkg,
-        HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg)
+new :: (HasComponentId ipkg,   PackageFixedDeps ipkg,
+        HasComponentId srcpkg, PackageFixedDeps srcpkg)
     => Bool
     -> PlanIndex ipkg srcpkg iresult ifailure
     -> Either [PlanProblem ipkg srcpkg iresult ifailure]
@@ -240,8 +240,8 @@ new indepGoals index =
   let isPreExisting (PreExisting _) = True
       isPreExisting _ = False
       fakeMap = Map.fromList
-              . map (\p -> (fakeInstalledPackageId (packageId p)
-                           ,installedPackageId p))
+              . map (\p -> (fakeComponentId (packageId p)
+                           ,installedComponentId p))
               . filter isPreExisting
               $ PackageIndex.allPackages index in
   case problems fakeMap indepGoals index of
@@ -269,8 +269,8 @@ toList = PackageIndex.allPackages . planIndex
 -- the dependencies of a package or set of packages without actually
 -- installing the package itself, as when doing development.
 --
-remove :: (HasInstalledPackageId ipkg,   PackageFixedDeps ipkg,
-           HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg)
+remove :: (HasComponentId ipkg,   PackageFixedDeps ipkg,
+           HasComponentId srcpkg, PackageFixedDeps srcpkg)
        => (GenericPlanPackage ipkg srcpkg iresult ifailure -> Bool)
        -> GenericInstallPlan ipkg srcpkg iresult ifailure
        -> Either [PlanProblem ipkg srcpkg iresult ifailure]
@@ -307,11 +307,11 @@ ready plan = assert check readyPackages
     hasAllInstalledDeps :: srcpkg -> Maybe (ComponentDeps [ipkg])
     hasAllInstalledDeps = T.mapM (mapM isInstalledDep) . depends
 
-    isInstalledDep :: InstalledPackageId -> Maybe ipkg
+    isInstalledDep :: ComponentId -> Maybe ipkg
     isInstalledDep pkgid =
       -- NB: Need to check if the ID has been updated in planFakeMap, in which
       -- case we might be dealing with an old pointer
-      case PlanIndex.fakeLookupInstalledPackageId
+      case PlanIndex.fakeLookupComponentId
            (planFakeMap plan) (planIndex plan) pkgid
       of
         Just (PreExisting ipkg)            -> Just ipkg
@@ -329,8 +329,8 @@ ready plan = assert check readyPackages
 --
 -- * The package must exist in the graph and be in the configured state.
 --
-processing :: (HasInstalledPackageId ipkg,   PackageFixedDeps ipkg,
-               HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg)
+processing :: (HasComponentId ipkg,   PackageFixedDeps ipkg,
+               HasComponentId srcpkg, PackageFixedDeps srcpkg)
            => [GenericReadyPackage srcpkg ipkg]
            -> GenericInstallPlan ipkg srcpkg iresult ifailure
            -> GenericInstallPlan ipkg srcpkg iresult ifailure
@@ -347,9 +347,9 @@ processing pkgs plan = assert (invariant plan') plan'
 -- * The package must exist in the graph and be in the processing state.
 -- * The package must have had no uninstalled dependent packages.
 --
-completed :: (HasInstalledPackageId ipkg,   PackageFixedDeps ipkg,
-              HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg)
-          => InstalledPackageId
+completed :: (HasComponentId ipkg,   PackageFixedDeps ipkg,
+              HasComponentId srcpkg, PackageFixedDeps srcpkg)
+          => ComponentId
           -> Maybe ipkg -> iresult
           -> GenericInstallPlan ipkg srcpkg iresult ifailure
           -> GenericInstallPlan ipkg srcpkg iresult ifailure
@@ -361,13 +361,13 @@ completed pkgid mipkg buildResult plan = assert (invariant plan') plan'
                   planFakeMap = insert_fake_mapping mipkg
                               $ planFakeMap plan,
                   planIndex = PackageIndex.insert installed
-                            . PackageIndex.deleteInstalledPackageId pkgid
+                            . PackageIndex.deleteComponentId pkgid
                             $ planIndex plan
                 }
     -- ...but be sure to use the *old* IPID for the lookup for the
     -- preexisting record
     installed = Installed (lookupProcessingPackage plan pkgid) mipkg buildResult
-    insert_fake_mapping (Just ipkg) = Map.insert pkgid (installedPackageId ipkg)
+    insert_fake_mapping (Just ipkg) = Map.insert pkgid (installedComponentId ipkg)
     insert_fake_mapping  _          = id
 
 -- | Marks a package in the graph as having failed. It also marks all the
@@ -376,9 +376,9 @@ completed pkgid mipkg buildResult plan = assert (invariant plan') plan'
 -- * The package must exist in the graph and be in the processing
 -- state.
 --
-failed :: (HasInstalledPackageId ipkg,   PackageFixedDeps ipkg,
-           HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg)
-       => InstalledPackageId -- ^ The id of the package that failed to install
+failed :: (HasComponentId ipkg,   PackageFixedDeps ipkg,
+           HasComponentId srcpkg, PackageFixedDeps srcpkg)
+       => ComponentId         -- ^ The id of the package that failed to install
        -> ifailure           -- ^ The build result to use for the failed package
        -> ifailure           -- ^ The build result to use for its dependencies
        -> GenericInstallPlan ipkg srcpkg iresult ifailure
@@ -399,7 +399,7 @@ failed pkgid buildResult buildResult' plan = assert (invariant plan') plan'
 -- | Lookup the reachable packages in the reverse dependency graph.
 --
 packagesThatDependOn :: GenericInstallPlan ipkg srcpkg iresult ifailure
-                     -> InstalledPackageId
+                     -> ComponentId
                      -> [GenericPlanPackage ipkg srcpkg iresult ifailure]
 packagesThatDependOn plan pkgid = map (planPkgOf plan)
                           . tail
@@ -410,12 +410,12 @@ packagesThatDependOn plan pkgid = map (planPkgOf plan)
 -- | Lookup a package that we expect to be in the processing state.
 --
 lookupProcessingPackage :: GenericInstallPlan ipkg srcpkg iresult ifailure
-                        -> InstalledPackageId
+                        -> ComponentId
                         -> GenericReadyPackage srcpkg ipkg
 lookupProcessingPackage plan pkgid =
   -- NB: processing packages are guaranteed to not indirect through
   -- planFakeMap
-  case PackageIndex.lookupInstalledPackageId (planIndex plan) pkgid of
+  case PackageIndex.lookupComponentId (planIndex plan) pkgid of
     Just (Processing pkg) -> pkg
     _  -> internalError $ "not in processing state or no such pkg " ++
                           display pkgid
@@ -440,8 +440,8 @@ checkConfiguredPackage pkg                =
 --
 -- * if the result is @False@ use 'problems' to get a detailed list.
 --
-valid :: (HasInstalledPackageId ipkg,   PackageFixedDeps ipkg,
-          HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg)
+valid :: (HasComponentId ipkg,   PackageFixedDeps ipkg,
+          HasComponentId srcpkg, PackageFixedDeps srcpkg)
       => FakeMap -> Bool
       -> PlanIndex ipkg srcpkg iresult ifailure
       -> Bool
@@ -492,8 +492,8 @@ showPlanProblem (PackageStateInvalid pkg pkg') =
 -- error messages. This is mainly intended for debugging purposes.
 -- Use 'showPlanProblem' for a human readable explanation.
 --
-problems :: (HasInstalledPackageId ipkg,   PackageFixedDeps ipkg,
-             HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg)
+problems :: (HasComponentId ipkg,   PackageFixedDeps ipkg,
+             HasComponentId srcpkg, PackageFixedDeps srcpkg)
          => FakeMap -> Bool
          -> PlanIndex ipkg srcpkg iresult ifailure
          -> [PlanProblem ipkg srcpkg iresult ifailure]
@@ -502,7 +502,7 @@ problems fakeMap indepGoals index =
      [ PackageMissingDeps pkg
        (catMaybes
         (map
-         (fmap packageId . PlanIndex.fakeLookupInstalledPackageId fakeMap index)
+         (fmap packageId . PlanIndex.fakeLookupComponentId fakeMap index)
          missingDeps))
      | (pkg, missingDeps) <- PlanIndex.brokenPackages fakeMap index ]
 
@@ -515,7 +515,7 @@ problems fakeMap indepGoals index =
 
   ++ [ PackageStateInvalid pkg pkg'
      | pkg <- PackageIndex.allPackages index
-     , Just pkg' <- map (PlanIndex.fakeLookupInstalledPackageId fakeMap index)
+     , Just pkg' <- map (PlanIndex.fakeLookupComponentId fakeMap index)
                     (CD.nonSetupDeps (depends pkg))
      , not (stateDependencyRelation pkg pkg') ]
 
@@ -524,8 +524,8 @@ problems fakeMap indepGoals index =
 -- * if the result is @False@ use 'PackageIndex.dependencyCycles' to find out
 --   which packages are involved in dependency cycles.
 --
-acyclic :: (HasInstalledPackageId ipkg,   PackageFixedDeps ipkg,
-            HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg)
+acyclic :: (HasComponentId ipkg,   PackageFixedDeps ipkg,
+            HasComponentId srcpkg, PackageFixedDeps srcpkg)
         => FakeMap -> PlanIndex ipkg srcpkg iresult ifailure -> Bool
 acyclic fakeMap = null . PlanIndex.dependencyCycles fakeMap
 
@@ -536,7 +536,7 @@ acyclic fakeMap = null . PlanIndex.dependencyCycles fakeMap
 -- * if the result is @False@ use 'PackageIndex.brokenPackages' to find out
 --   which packages depend on packages not in the index.
 --
-closed :: (HasInstalledPackageId ipkg, PackageFixedDeps ipkg,
+closed :: (HasComponentId ipkg, PackageFixedDeps ipkg,
            PackageFixedDeps srcpkg)
        => FakeMap -> PlanIndex ipkg srcpkg iresult ifailure -> Bool
 closed fakeMap = null . PlanIndex.brokenPackages fakeMap
@@ -557,8 +557,8 @@ closed fakeMap = null . PlanIndex.brokenPackages fakeMap
 -- * if the result is @False@ use 'PackageIndex.dependencyInconsistencies' to
 --   find out which packages are.
 --
-consistent :: (HasInstalledPackageId ipkg,   PackageFixedDeps ipkg,
-               HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg)
+consistent :: (HasComponentId ipkg,   PackageFixedDeps ipkg,
+               HasComponentId srcpkg, PackageFixedDeps srcpkg)
            => FakeMap -> PlanIndex ipkg srcpkg iresult ifailure -> Bool
 consistent fakeMap = null . PlanIndex.dependencyInconsistencies fakeMap False
 
@@ -597,19 +597,19 @@ stateDependencyRelation _               _                 = False
 -- | Compute the dependency closure of a _source_ package in a install plan
 --
 -- See `Distribution.Client.PlanIndex.dependencyClosure`
-dependencyClosure :: (HasInstalledPackageId ipkg,   PackageFixedDeps ipkg,
-                      HasInstalledPackageId srcpkg, PackageFixedDeps srcpkg)
+dependencyClosure :: (HasComponentId ipkg,   PackageFixedDeps ipkg,
+                      HasComponentId srcpkg, PackageFixedDeps srcpkg)
                   => GenericInstallPlan ipkg srcpkg iresult ifailure
                   -> [PackageIdentifier]
                   -> Either [(GenericPlanPackage ipkg srcpkg iresult ifailure,
-                              [InstalledPackageId])]
+                              [ComponentId])]
                             (PackageIndex
                              (GenericPlanPackage ipkg srcpkg iresult ifailure))
 dependencyClosure installPlan pids =
     PlanIndex.dependencyClosure
       (planFakeMap installPlan)
       (planIndex installPlan)
-      (map (resolveFakeId . fakeInstalledPackageId) pids)
+      (map (resolveFakeId . fakeComponentId) pids)
   where
-    resolveFakeId :: InstalledPackageId -> InstalledPackageId
+    resolveFakeId :: ComponentId -> ComponentId
     resolveFakeId ipid = Map.findWithDefault ipid ipid (planFakeMap installPlan)
diff --git a/cabal-install/Distribution/Client/InstallSymlink.hs b/cabal-install/Distribution/Client/InstallSymlink.hs
index 16c312792118ce640310867331c8886adccbcc1e..f3c2a4f99f45eb69accacfdeda7b1a3ba529a389 100644
--- a/cabal-install/Distribution/Client/InstallSymlink.hs
+++ b/cabal-install/Distribution/Client/InstallSymlink.hs
@@ -40,19 +40,17 @@ symlinkBinary _ _ _ _ = fail "Symlinking feature not available on Windows"
 import Distribution.Client.Types
          ( SourcePackage(..)
          , GenericReadyPackage(..), ReadyPackage, enableStanzas
-         , ConfiguredPackage(..) )
+         , ConfiguredPackage(..) , fakeComponentId)
 import Distribution.Client.Setup
          ( InstallFlags(installSymlinkBinDir) )
 import qualified Distribution.Client.InstallPlan as InstallPlan
 import Distribution.Client.InstallPlan (InstallPlan)
 
 import Distribution.Package
-         ( PackageIdentifier, Package(packageId), mkPackageKey
-         , packageKeyLibraryName, LibraryName )
+         ( PackageIdentifier, Package(packageId), ComponentId(..) )
 import Distribution.Compiler
          ( CompilerId(..) )
 import qualified Distribution.PackageDescription as PackageDescription
-import qualified Distribution.Client.ComponentDeps as CD
 import Distribution.PackageDescription
          ( PackageDescription )
 import Distribution.PackageDescription.Configuration
@@ -60,9 +58,8 @@ import Distribution.PackageDescription.Configuration
 import Distribution.Simple.Setup
          ( ConfigFlags(..), fromFlag, fromFlagOrDefault, flagToMaybe )
 import qualified Distribution.Simple.InstallDirs as InstallDirs
-import qualified Distribution.InstalledPackageInfo as Installed
 import Distribution.Simple.Compiler
-         ( Compiler, compilerInfo, CompilerInfo(..), packageKeySupported )
+         ( Compiler, compilerInfo, CompilerInfo(..) )
 import Distribution.System
          ( Platform )
 
@@ -118,7 +115,7 @@ symlinkBinaries platform comp configFlags installFlags plan =
 --    TODO: do we want to do this here? :
 --      createDirectoryIfMissing True publicBinDir
       fmap catMaybes $ sequence
-        [ do privateBinDir <- pkgBinDir pkg libname
+        [ do privateBinDir <- pkgBinDir pkg ipid
              ok <- symlinkBinary
                      publicBinDir  privateBinDir
                      publicExeName privateExeName
@@ -126,16 +123,14 @@ symlinkBinaries platform comp configFlags installFlags plan =
                then return Nothing
                else return (Just (pkgid, publicExeName,
                                   privateBinDir </> privateExeName))
-        | (ReadyPackage (ConfiguredPackage _ _flags _ _) deps, pkg, exe) <- exes
+        | (ReadyPackage (ConfiguredPackage _ _flags _ _) _, pkg, exe) <- exes
         , let pkgid  = packageId pkg
-              pkg_key = mkPackageKey (packageKeySupported comp) pkgid
-                                     (map Installed.libraryName
-                                      (CD.nonSetupDeps deps))
-              libname = packageKeyLibraryName pkgid pkg_key
+              -- This is a bit dodgy; probably won't work for Backpack packages
+              ipid = fakeComponentId pkgid
               publicExeName  = PackageDescription.exeName exe
               privateExeName = prefix ++ publicExeName ++ suffix
-              prefix = substTemplate pkgid libname prefixTemplate
-              suffix = substTemplate pkgid libname suffixTemplate ]
+              prefix = substTemplate pkgid ipid prefixTemplate
+              suffix = substTemplate pkgid ipid suffixTemplate ]
   where
     exes =
       [ (cpkg, pkg, exe)
@@ -157,8 +152,8 @@ symlinkBinaries platform comp configFlags installFlags plan =
 
     -- This is sadly rather complicated. We're kind of re-doing part of the
     -- configuration for the package. :-(
-    pkgBinDir :: PackageDescription -> LibraryName -> IO FilePath
-    pkgBinDir pkg libname = do
+    pkgBinDir :: PackageDescription -> ComponentId -> IO FilePath
+    pkgBinDir pkg ipid = do
       defaultDirs <- InstallDirs.defaultInstallDirs
                        compilerFlavor
                        (fromFlag (configUserInstall configFlags))
@@ -166,14 +161,14 @@ symlinkBinaries platform comp configFlags installFlags plan =
       let templateDirs = InstallDirs.combineInstallDirs fromFlagOrDefault
                            defaultDirs (configInstallDirs configFlags)
           absoluteDirs = InstallDirs.absoluteInstallDirs
-                           (packageId pkg) libname
+                           (packageId pkg) ipid
                            cinfo InstallDirs.NoCopyDest
                            platform templateDirs
       canonicalizePath (InstallDirs.bindir absoluteDirs)
 
-    substTemplate pkgid libname = InstallDirs.fromPathTemplate
-                                . InstallDirs.substPathTemplate env
-      where env = InstallDirs.initialPathTemplateEnv pkgid libname
+    substTemplate pkgid ipid = InstallDirs.fromPathTemplate
+                             . InstallDirs.substPathTemplate env
+      where env = InstallDirs.initialPathTemplateEnv pkgid ipid
                                                      cinfo platform
 
     fromFlagTemplate = fromFlagOrDefault (InstallDirs.toPathTemplate "")
diff --git a/cabal-install/Distribution/Client/List.hs b/cabal-install/Distribution/Client/List.hs
index e94e59cceff94da532bed4194020adedd4aff19d..4db1457d1187bd26aa60e0e946ca112d83da46e3 100644
--- a/cabal-install/Distribution/Client/List.hs
+++ b/cabal-install/Distribution/Client/List.hs
@@ -16,7 +16,7 @@ module Distribution.Client.List (
 import Distribution.Package
          ( PackageName(..), Package(..), packageName, packageVersion
          , Dependency(..), simplifyDependency
-         , InstalledPackageId )
+         , ComponentId )
 import Distribution.ModuleName (ModuleName)
 import Distribution.License (License)
 import qualified Distribution.InstalledPackageInfo as Installed
@@ -296,7 +296,7 @@ data PackageDisplayInfo = PackageDisplayInfo {
 -- | Covers source dependencies and installed dependencies in
 -- one type.
 data ExtDependency = SourceDependency Dependency
-                   | InstalledDependency InstalledPackageId
+                   | InstalledDependency ComponentId
 
 showPackageSummaryInfo :: PackageDisplayInfo -> String
 showPackageSummaryInfo pkginfo =
diff --git a/cabal-install/Distribution/Client/PlanIndex.hs b/cabal-install/Distribution/Client/PlanIndex.hs
index 5e837c6eedb3b9b659b2a7831a29a2789eabc988..c8aff6a0209885fca64338a40a7983dde089b88f 100644
--- a/cabal-install/Distribution/Client/PlanIndex.hs
+++ b/cabal-install/Distribution/Client/PlanIndex.hs
@@ -8,7 +8,7 @@ module Distribution.Client.PlanIndex (
     -- * FakeMap and related operations
     FakeMap
   , fakeDepends
-  , fakeLookupInstalledPackageId
+  , fakeLookupComponentId
     -- * Graph traversal functions
   , brokenPackages
   , dependencyClosure
@@ -34,7 +34,7 @@ import Data.Monoid (Monoid(..))
 #endif
 
 import Distribution.Package
-         ( PackageName(..), PackageIdentifier(..), InstalledPackageId(..)
+         ( PackageName(..), PackageIdentifier(..), ComponentId(..)
          , Package(..), packageName, packageVersion
          )
 import Distribution.Version
@@ -45,30 +45,30 @@ import qualified Distribution.Client.ComponentDeps as CD
 import Distribution.Client.Types
          ( PackageFixedDeps(..) )
 import Distribution.Simple.PackageIndex
-         ( PackageIndex, allPackages, insert, lookupInstalledPackageId )
+         ( PackageIndex, allPackages, insert, lookupComponentId )
 import Distribution.Package
-         ( HasInstalledPackageId(..), PackageId )
+         ( HasComponentId(..), PackageId )
 
 -- Note [FakeMap]
 -----------------
 -- We'd like to use the PackageIndex defined in this module for
 -- cabal-install's InstallPlan.  However, at the moment, this
--- data structure is indexed by InstalledPackageId, which we don't
+-- data structure is indexed by ComponentId, which we don't
 -- know until after we've compiled a package (whereas InstallPlan
 -- needs to store not-compiled packages in the index.) Eventually,
--- an InstalledPackageId will be calculatable prior to actually
+-- an ComponentId will be calculatable prior to actually
 -- building the package (making it something of a misnomer), but
 -- at the moment, the "fake installed package ID map" is a workaround
 -- to solve this problem while reusing PackageIndex.  The basic idea
--- is that, since we don't know what an InstalledPackageId is
+-- is that, since we don't know what an ComponentId is
 -- beforehand, we just fake up one based on the package ID (it only
 -- needs to be unique for the particular install plan), and fill
--- it out with the actual generated InstalledPackageId after the
+-- it out with the actual generated ComponentId after the
 -- package is successfully compiled.
 --
 -- However, there is a problem: in the index there may be
 -- references using the old package ID, which are now dangling if
--- we update the InstalledPackageId.  We could map over the entire
+-- we update the ComponentId.  We could map over the entire
 -- index to update these pointers as well (a costly operation), but
 -- instead, we've chosen to parametrize a variety of important functions
 -- by a FakeMap, which records what a fake installed package ID was
@@ -80,24 +80,24 @@ import Distribution.Package
 -- the installed package ID, but I decided this would be hard to
 -- understand.)
 
--- | Map from fake installed package IDs to real ones.  See Note [FakeMap]
-type FakeMap = Map InstalledPackageId InstalledPackageId
+-- | Map from fake package keys to real ones.  See Note [FakeMap]
+type FakeMap = Map ComponentId ComponentId
 
 -- | Variant of `depends` which accepts a `FakeMap`
 --
 -- Analogous to `fakeInstalledDepends`. See Note [FakeMap].
-fakeDepends :: PackageFixedDeps pkg => FakeMap -> pkg -> ComponentDeps [InstalledPackageId]
+fakeDepends :: PackageFixedDeps pkg => FakeMap -> pkg -> ComponentDeps [ComponentId]
 fakeDepends fakeMap = fmap (map resolveFakeId) . depends
   where
-    resolveFakeId :: InstalledPackageId -> InstalledPackageId
+    resolveFakeId :: ComponentId -> ComponentId
     resolveFakeId ipid = Map.findWithDefault ipid ipid fakeMap
 
---- | Variant of 'lookupInstalledPackageId' which accepts a 'FakeMap'.  See Note
+--- | Variant of 'lookupComponentId' which accepts a 'FakeMap'.  See Note
 --- [FakeMap].
-fakeLookupInstalledPackageId :: FakeMap -> PackageIndex a -> InstalledPackageId
+fakeLookupComponentId :: FakeMap -> PackageIndex a -> ComponentId
                              -> Maybe a
-fakeLookupInstalledPackageId fakeMap index pkg =
-  lookupInstalledPackageId index (Map.findWithDefault pkg pkg fakeMap)
+fakeLookupComponentId fakeMap index pkg =
+  lookupComponentId index (Map.findWithDefault pkg pkg fakeMap)
 
 -- | All packages that have dependencies that are not in the index.
 --
@@ -106,13 +106,13 @@ fakeLookupInstalledPackageId fakeMap index pkg =
 brokenPackages :: (PackageFixedDeps pkg)
                => FakeMap
                -> PackageIndex pkg
-               -> [(pkg, [InstalledPackageId])]
+               -> [(pkg, [ComponentId])]
 brokenPackages fakeMap index =
   [ (pkg, missing)
   | pkg  <- allPackages index
   , let missing =
           [ pkg' | pkg' <- CD.nonSetupDeps (depends pkg)
-                 , isNothing (fakeLookupInstalledPackageId fakeMap index pkg') ]
+                 , isNothing (fakeLookupComponentId fakeMap index pkg') ]
   , not (null missing) ]
 
 -- | Compute all roots of the install plan, and verify that the transitive
@@ -122,7 +122,7 @@ brokenPackages fakeMap index =
 -- may be absent from the subplans even if the larger plan contains a dependency
 -- cycle. Such cycles may or may not be an issue; either way, we don't check
 -- for them here.
-dependencyInconsistencies :: forall pkg. (PackageFixedDeps pkg, HasInstalledPackageId pkg)
+dependencyInconsistencies :: forall pkg. (PackageFixedDeps pkg, HasComponentId pkg)
                           => FakeMap
                           -> Bool
                           -> PackageIndex pkg
@@ -141,8 +141,8 @@ dependencyInconsistencies fakeMap indepGoals index  =
 -- This is the set of all top-level library roots (taken together normally, or
 -- as singletons sets if we are considering them as independent goals), along
 -- with all setup dependencies of all packages.
-rootSets :: (PackageFixedDeps pkg, HasInstalledPackageId pkg)
-         => FakeMap -> Bool -> PackageIndex pkg -> [[InstalledPackageId]]
+rootSets :: (PackageFixedDeps pkg, HasComponentId pkg)
+         => FakeMap -> Bool -> PackageIndex pkg -> [[ComponentId]]
 rootSets fakeMap indepGoals index =
        if indepGoals then map (:[]) libRoots else [libRoots]
     ++ setupRoots index
@@ -153,10 +153,10 @@ rootSets fakeMap indepGoals index =
 --
 -- The library roots are the set of packages with no reverse dependencies
 -- (no reverse library dependencies but also no reverse setup dependencies).
-libraryRoots :: (PackageFixedDeps pkg, HasInstalledPackageId pkg)
-             => FakeMap -> PackageIndex pkg -> [InstalledPackageId]
+libraryRoots :: (PackageFixedDeps pkg, HasComponentId pkg)
+             => FakeMap -> PackageIndex pkg -> [ComponentId]
 libraryRoots fakeMap index =
-    map (installedPackageId . toPkgId) roots
+    map (installedComponentId . toPkgId) roots
   where
     (graph, toPkgId, _) = dependencyGraph fakeMap index
     indegree = Graph.indegree graph
@@ -164,7 +164,7 @@ libraryRoots fakeMap index =
     isRoot v = indegree ! v == 0
 
 -- | The setup dependencies of each package in the plan
-setupRoots :: PackageFixedDeps pkg => PackageIndex pkg -> [[InstalledPackageId]]
+setupRoots :: PackageFixedDeps pkg => PackageIndex pkg -> [[ComponentId]]
 setupRoots = filter (not . null)
            . map (CD.setupDeps . depends)
            . allPackages
@@ -180,7 +180,7 @@ setupRoots = filter (not . null)
 -- distinct.
 --
 dependencyInconsistencies' :: forall pkg.
-                              (PackageFixedDeps pkg, HasInstalledPackageId pkg)
+                              (PackageFixedDeps pkg, HasComponentId pkg)
                            => FakeMap
                            -> PackageIndex pkg
                            -> [(PackageName, [(PackageIdentifier, Version)])]
@@ -195,7 +195,7 @@ dependencyInconsistencies' fakeMap index =
     --   and each installed ID of that that package
     --     the associated package instance
     --     and a list of reverse dependencies (as source IDs)
-    inverseIndex :: Map PackageName (Map InstalledPackageId (pkg, [PackageId]))
+    inverseIndex :: Map PackageName (Map ComponentId (pkg, [PackageId]))
     inverseIndex = Map.fromListWith (Map.unionWith (\(a,b) (_,b') -> (a,b++b')))
       [ (packageName dep, Map.fromList [(ipid,(dep,[packageId pkg]))])
       | -- For each package @pkg@
@@ -203,7 +203,7 @@ dependencyInconsistencies' fakeMap index =
         -- Find out which @ipid@ @pkg@ depends on
       , ipid <- CD.nonSetupDeps (fakeDepends fakeMap pkg)
         -- And look up those @ipid@ (i.e., @ipid@ is the ID of @dep@)
-      , Just dep <- [fakeLookupInstalledPackageId fakeMap index ipid]
+      , Just dep <- [fakeLookupComponentId fakeMap index ipid]
       ]
 
     -- If, in a single install plan, we depend on more than one version of a
@@ -215,8 +215,8 @@ dependencyInconsistencies' fakeMap index =
     reallyIsInconsistent []       = False
     reallyIsInconsistent [_p]     = False
     reallyIsInconsistent [p1, p2] =
-      let pid1 = installedPackageId p1
-          pid2 = installedPackageId p2
+      let pid1 = installedComponentId p1
+          pid2 = installedComponentId p2
       in Map.findWithDefault pid1 pid1 fakeMap `notElem` CD.nonSetupDeps (fakeDepends fakeMap p2)
       && Map.findWithDefault pid2 pid2 fakeMap `notElem` CD.nonSetupDeps (fakeDepends fakeMap p1)
     reallyIsInconsistent _ = True
@@ -231,14 +231,14 @@ dependencyInconsistencies' fakeMap index =
 -- list of groups of packages where within each group they all depend on each
 -- other, directly or indirectly.
 --
-dependencyCycles :: (PackageFixedDeps pkg, HasInstalledPackageId pkg)
+dependencyCycles :: (PackageFixedDeps pkg, HasComponentId pkg)
                  => FakeMap
                  -> PackageIndex pkg
                  -> [[pkg]]
 dependencyCycles fakeMap index =
   [ vs | Graph.CyclicSCC vs <- Graph.stronglyConnComp adjacencyList ]
   where
-    adjacencyList = [ (pkg, installedPackageId pkg, CD.nonSetupDeps (fakeDepends fakeMap pkg))
+    adjacencyList = [ (pkg, installedComponentId pkg, CD.nonSetupDeps (fakeDepends fakeMap pkg))
                     | pkg <- allPackages index ]
 
 
@@ -249,11 +249,11 @@ dependencyCycles fakeMap index =
 --
 -- * Note that if the result is @Right []@ it is because at least one of
 -- the original given 'PackageIdentifier's do not occur in the index.
-dependencyClosure :: (PackageFixedDeps pkg, HasInstalledPackageId pkg)
+dependencyClosure :: (PackageFixedDeps pkg, HasComponentId pkg)
                   => FakeMap
                   -> PackageIndex pkg
-                  -> [InstalledPackageId]
-                  -> Either [(pkg, [InstalledPackageId])]
+                  -> [ComponentId]
+                  -> Either [(pkg, [ComponentId])]
                             (PackageIndex pkg)
 dependencyClosure fakeMap index pkgids0 = case closure mempty [] pkgids0 of
   (completed, []) -> Right completed
@@ -261,18 +261,18 @@ dependencyClosure fakeMap index pkgids0 = case closure mempty [] pkgids0 of
  where
     closure completed failed []             = (completed, failed)
     closure completed failed (pkgid:pkgids) =
-      case fakeLookupInstalledPackageId fakeMap index pkgid of
+      case fakeLookupComponentId fakeMap index pkgid of
         Nothing   -> closure completed (pkgid:failed) pkgids
         Just pkg  ->
-          case fakeLookupInstalledPackageId fakeMap completed
-               (installedPackageId pkg) of
+          case fakeLookupComponentId fakeMap completed
+               (installedComponentId pkg) of
             Just _  -> closure completed  failed pkgids
             Nothing -> closure completed' failed pkgids'
               where completed' = insert pkg completed
                     pkgids'    = CD.nonSetupDeps (depends pkg) ++ pkgids
 
 
-topologicalOrder :: (PackageFixedDeps pkg, HasInstalledPackageId pkg)
+topologicalOrder :: (PackageFixedDeps pkg, HasComponentId pkg)
                  => FakeMap -> PackageIndex pkg -> [pkg]
 topologicalOrder fakeMap index = map toPkgId
                                . Graph.topSort
@@ -280,7 +280,7 @@ topologicalOrder fakeMap index = map toPkgId
   where (graph, toPkgId, _) = dependencyGraph fakeMap index
 
 
-reverseTopologicalOrder :: (PackageFixedDeps pkg, HasInstalledPackageId pkg)
+reverseTopologicalOrder :: (PackageFixedDeps pkg, HasComponentId pkg)
                         => FakeMap -> PackageIndex pkg -> [pkg]
 reverseTopologicalOrder fakeMap index = map toPkgId
                                       . Graph.topSort
@@ -293,10 +293,10 @@ reverseTopologicalOrder fakeMap index = map toPkgId
 --
 -- * The given 'PackageIdentifier's must be in the index.
 --
-reverseDependencyClosure :: (PackageFixedDeps pkg, HasInstalledPackageId pkg)
+reverseDependencyClosure :: (PackageFixedDeps pkg, HasComponentId pkg)
                          => FakeMap
                          -> PackageIndex pkg
-                         -> [InstalledPackageId]
+                         -> [ComponentId]
                          -> [pkg]
 reverseDependencyClosure fakeMap index =
     map vertexToPkg
@@ -316,17 +316,17 @@ reverseDependencyClosure fakeMap index =
 -- Dependencies on other packages that are not in the index are discarded.
 -- You can check if there are any such dependencies with 'brokenPackages'.
 --
-dependencyGraph :: (PackageFixedDeps pkg, HasInstalledPackageId pkg)
+dependencyGraph :: (PackageFixedDeps pkg, HasComponentId pkg)
                 => FakeMap
                 -> PackageIndex pkg
                 -> (Graph.Graph,
                     Graph.Vertex -> pkg,
-                    InstalledPackageId -> Maybe Graph.Vertex)
+                    ComponentId -> Maybe Graph.Vertex)
 dependencyGraph fakeMap index = (graph, vertexToPkg, idToVertex)
   where
     (graph, vertexToPkg', idToVertex) = Graph.graphFromEdges edges
     vertexToPkg = fromJust
-                . (\((), key, _targets) -> lookupInstalledPackageId index key)
+                . (\((), key, _targets) -> lookupComponentId index key)
                 . vertexToPkg'
 
     pkgs  = allPackages index
@@ -334,6 +334,6 @@ dependencyGraph fakeMap index = (graph, vertexToPkg, idToVertex)
 
     resolve   pid = Map.findWithDefault pid pid fakeMap
     edgesFrom pkg = ( ()
-                    , resolve (installedPackageId pkg)
+                    , resolve (installedComponentId pkg)
                     , CD.nonSetupDeps (fakeDepends fakeMap pkg)
                     )
diff --git a/cabal-install/Distribution/Client/Setup.hs b/cabal-install/Distribution/Client/Setup.hs
index f189fe960645d2317cea35df58c9a991aa3c0892..b443275d300a0c9a75c56b4c89003c04a76c0369 100644
--- a/cabal-install/Distribution/Client/Setup.hs
+++ b/cabal-install/Distribution/Client/Setup.hs
@@ -411,7 +411,8 @@ filterConfigureFlags flags cabalLibVersion
 
     -- Cabal < 1.23 doesn't know about '--profiling-detail'.
     flags_1_22_0 = flags_latest { configProfDetail    = NoFlag
-                                , configProfLibDetail = NoFlag }
+                                , configProfLibDetail = NoFlag
+                                , configIPID          = NoFlag }
 
     -- Cabal < 1.22 doesn't know about '--disable-debug-info'.
     flags_1_21_0 = flags_1_22_0 { configDebugInfo = NoFlag }
diff --git a/cabal-install/Distribution/Client/SetupWrapper.hs b/cabal-install/Distribution/Client/SetupWrapper.hs
index 8f4c2b8194170c796f74bf7e2f9ab827550b7194..24a04648b4258fa584b268a752a6fdd5d10b2995 100644
--- a/cabal-install/Distribution/Client/SetupWrapper.hs
+++ b/cabal-install/Distribution/Client/SetupWrapper.hs
@@ -27,9 +27,9 @@ import Distribution.Version
          ( Version(..), VersionRange, anyVersion
          , intersectVersionRanges, orLaterVersion
          , withinRange )
-import Distribution.InstalledPackageInfo (installedPackageId)
+import Distribution.InstalledPackageInfo (installedComponentId)
 import Distribution.Package
-         ( InstalledPackageId(..), PackageIdentifier(..), PackageId,
+         ( ComponentId(..), PackageIdentifier(..), PackageId,
            PackageName(..), Package(..), packageName
          , packageVersion, Dependency(..) )
 import Distribution.PackageDescription
@@ -133,7 +133,7 @@ data SetupScriptOptions = SetupScriptOptions {
     forceExternalSetupMethod :: Bool,
 
     -- | List of dependencies to use when building Setup.hs
-    useDependencies :: [(InstalledPackageId, PackageId)],
+    useDependencies :: [(ComponentId, PackageId)],
 
     -- | Is the list of setup dependencies exclusive?
     --
@@ -335,7 +335,7 @@ externalSetupMethod verbosity options pkg bt mkargs = do
       Nothing    -> getInstalledPackages verbosity
                     comp (usePackageDB options') conf
 
-  cabalLibVersionToUse :: IO (Version, (Maybe InstalledPackageId)
+  cabalLibVersionToUse :: IO (Version, (Maybe ComponentId)
                              ,SetupScriptOptions)
   cabalLibVersionToUse = do
     savedVer <- savedVersion
@@ -364,7 +364,7 @@ externalSetupMethod verbosity options pkg bt mkargs = do
           (&&) <$> setupProgFile `existsAndIsMoreRecentThan` setupHs
                <*> setupProgFile `existsAndIsMoreRecentThan` setupVersionFile
 
-      installedVersion :: IO (Version, Maybe InstalledPackageId
+      installedVersion :: IO (Version, Maybe ComponentId
                              ,SetupScriptOptions)
       installedVersion = do
         (comp,    conf,    options')  <- configureCompiler options
@@ -411,7 +411,7 @@ externalSetupMethod verbosity options pkg bt mkargs = do
     UnknownBuildType _ -> error "buildTypeScript UnknownBuildType"
 
   installedCabalVersion :: SetupScriptOptions -> Compiler -> ProgramConfiguration
-                        -> IO (Version, Maybe InstalledPackageId
+                        -> IO (Version, Maybe ComponentId
                               ,SetupScriptOptions)
   installedCabalVersion options' _ _ | packageName pkg == PackageName "Cabal" =
     return (packageVersion pkg, Nothing, options')
@@ -426,7 +426,7 @@ externalSetupMethod verbosity options pkg bt mkargs = do
                  ++ " but no suitable version is installed."
       pkgs -> let ipkginfo = head . snd . bestVersion fst $ pkgs
               in return (packageVersion ipkginfo
-                        ,Just . installedPackageId $ ipkginfo, options'')
+                        ,Just . installedComponentId $ ipkginfo, options'')
 
   bestVersion :: (a -> Version) -> [a] -> a
   bestVersion f = firstMaximumBy (comparing (preference . f))
@@ -499,7 +499,7 @@ externalSetupMethod verbosity options pkg bt mkargs = do
   -- | Look up the setup executable in the cache; update the cache if the setup
   -- executable is not found.
   getCachedSetupExecutable :: SetupScriptOptions
-                           -> Version -> Maybe InstalledPackageId
+                           -> Version -> Maybe ComponentId
                            -> IO FilePath
   getCachedSetupExecutable options' cabalLibVersion
                            maybeCabalLibInstalledPkgId = do
@@ -534,7 +534,7 @@ externalSetupMethod verbosity options pkg bt mkargs = do
   -- Currently this is GHC/GHCJS only. It should really be generalised.
   --
   compileSetupExecutable :: SetupScriptOptions
-                         -> Version -> Maybe InstalledPackageId -> Bool
+                         -> Version -> Maybe ComponentId -> Bool
                          -> IO FilePath
   compileSetupExecutable options' cabalLibVersion maybeCabalLibInstalledPkgId
                          forceCompile = do
diff --git a/cabal-install/Distribution/Client/Types.hs b/cabal-install/Distribution/Client/Types.hs
index abdf2ce65cd35342e900e9207da50f843e11f8f4..a3a215817884604ce7ba717af6e467b44ae2b9ce 100644
--- a/cabal-install/Distribution/Client/Types.hs
+++ b/cabal-install/Distribution/Client/Types.hs
@@ -15,10 +15,9 @@
 module Distribution.Client.Types where
 
 import Distribution.Package
-         ( PackageName, PackageId, Package(..)
-         , mkPackageKey, PackageKey, InstalledPackageId(..)
-         , HasInstalledPackageId(..), PackageInstalled(..)
-         , LibraryName, packageKeyLibraryName )
+         ( PackageName, PackageId, Package(..), ComponentId(..)
+         , ComponentId(..)
+         , HasComponentId(..), PackageInstalled(..) )
 import Distribution.InstalledPackageInfo
          ( InstalledPackageInfo )
 import Distribution.PackageDescription
@@ -33,10 +32,7 @@ import Distribution.Client.ComponentDeps
 import qualified Distribution.Client.ComponentDeps as CD
 import Distribution.Version
          ( VersionRange )
-import Distribution.Simple.Compiler
-         ( Compiler, packageKeySupported )
 import Distribution.Text (display)
-import qualified Distribution.InstalledPackageInfo as Info
 
 import Data.Map (Map)
 import Network.URI (URI, nullURI)
@@ -66,23 +62,23 @@ data SourcePackageDb = SourcePackageDb {
 --  dependency graphs) only make sense on this subclass of package types.
 --
 class Package pkg => PackageFixedDeps pkg where
-  depends :: pkg -> ComponentDeps [InstalledPackageId]
+  depends :: pkg -> ComponentDeps [ComponentId]
 
 instance PackageFixedDeps InstalledPackageInfo where
   depends = CD.fromInstalled . installedDepends
 
 
 -- | In order to reuse the implementation of PackageIndex which relies on
--- 'InstalledPackageId', we need to be able to synthesize these IDs prior
+-- 'ComponentId', we need to be able to synthesize these IDs prior
 -- to installation.  Eventually, we'll move to a representation of
--- 'InstalledPackageId' which can be properly computed before compilation
+-- 'ComponentId' which can be properly computed before compilation
 -- (of course, it's a bit of a misnomer since the packages are not actually
 -- installed yet.)  In any case, we'll synthesize temporary installed package
 -- IDs to use as keys during install planning.  These should never be written
 -- out!  Additionally, they need to be guaranteed unique within the install
 -- plan.
-fakeInstalledPackageId :: PackageId -> InstalledPackageId
-fakeInstalledPackageId = InstalledPackageId . (".fake."++) . display
+fakeComponentId :: PackageId -> ComponentId
+fakeComponentId = ComponentId . (".fake."++) . display
 
 -- | A 'ConfiguredPackage' is a not-yet-installed package along with the
 -- total configuration information. The configuration information is total in
@@ -102,7 +98,7 @@ data ConfiguredPackage = ConfiguredPackage
 
 -- | A ConfiguredId is a package ID for a configured package.
 --
--- Once we configure a source package we know it's InstalledPackageId
+-- Once we configure a source package we know it's ComponentId
 -- (at least, in principle, even if we have to fake it currently). It is still
 -- however useful in lots of places to also know the source ID for the package.
 -- We therefore bundle the two.
@@ -111,10 +107,10 @@ data ConfiguredPackage = ConfiguredPackage
 -- configuration parameters and dependencies have been specified).
 --
 -- TODO: I wonder if it would make sense to promote this datatype to Cabal
--- and use it consistently instead of InstalledPackageIds?
+-- and use it consistently instead of ComponentIds?
 data ConfiguredId = ConfiguredId {
     confSrcId  :: PackageId
-  , confInstId :: InstalledPackageId
+  , confInstId :: ComponentId
   }
 
 instance Show ConfiguredId where
@@ -126,8 +122,8 @@ instance Package ConfiguredPackage where
 instance PackageFixedDeps ConfiguredPackage where
   depends (ConfiguredPackage _ _ _ deps) = fmap (map confInstId) deps
 
-instance HasInstalledPackageId ConfiguredPackage where
-  installedPackageId = fakeInstalledPackageId . packageId
+instance HasComponentId ConfiguredPackage where
+  installedComponentId = fakeComponentId . packageId
 
 -- | Like 'ConfiguredPackage', but with all dependencies guaranteed to be
 -- installed already, hence itself ready to be installed.
@@ -142,27 +138,13 @@ type ReadyPackage = GenericReadyPackage ConfiguredPackage InstalledPackageInfo
 instance Package srcpkg => Package (GenericReadyPackage srcpkg ipkg) where
   packageId (ReadyPackage srcpkg _deps) = packageId srcpkg
 
-instance (Package srcpkg, HasInstalledPackageId ipkg) =>
+instance (Package srcpkg, HasComponentId ipkg) =>
          PackageFixedDeps (GenericReadyPackage srcpkg ipkg) where
-  depends (ReadyPackage _ deps) = fmap (map installedPackageId) deps
+  depends (ReadyPackage _ deps) = fmap (map installedComponentId) deps
 
-instance HasInstalledPackageId srcpkg =>
-         HasInstalledPackageId (GenericReadyPackage srcpkg ipkg) where
-  installedPackageId (ReadyPackage pkg _) = installedPackageId pkg
-
-
--- | Extracts a package key from ReadyPackage, a common operation needed
--- to calculate build paths.
-readyPackageKey :: Compiler -> ReadyPackage -> PackageKey
-readyPackageKey comp (ReadyPackage pkg deps) =
-    mkPackageKey (packageKeySupported comp) (packageId pkg)
-                 (map Info.libraryName (CD.nonSetupDeps deps))
-
--- | Extracts a library name from ReadyPackage, a common operation needed
--- to calculate build paths.
-readyLibraryName :: Compiler -> ReadyPackage -> LibraryName
-readyLibraryName comp ready@(ReadyPackage pkg _) =
-    packageKeyLibraryName (packageId pkg) (readyPackageKey comp ready)
+instance HasComponentId srcpkg =>
+         HasComponentId (GenericReadyPackage srcpkg ipkg) where
+  installedComponentId (ReadyPackage pkg _) = installedComponentId pkg
 
 
 -- | A package description along with the location of the package sources.
diff --git a/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/DSL.hs b/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/DSL.hs
index d76270f8ea43a17fa19494a1af43f1b1390d1503..e505869b91833d3f451da33c2e722d7a8cf7bce0 100644
--- a/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/DSL.hs
+++ b/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/DSL.hs
@@ -21,7 +21,7 @@ import qualified Data.Map as Map
 import qualified Distribution.Compiler             as C
 import qualified Distribution.InstalledPackageInfo as C
 import qualified Distribution.Package              as C
-  hiding (HasInstalledPackageId(..))
+  hiding (HasComponentId(..))
 import qualified Distribution.PackageDescription   as C
 import qualified Distribution.Simple.PackageIndex  as C.PackageIndex
 import qualified Distribution.System               as C
@@ -239,10 +239,9 @@ exAvPkgId ex = C.PackageIdentifier {
 
 exInstInfo :: ExampleInstalled -> C.InstalledPackageInfo
 exInstInfo ex = C.emptyInstalledPackageInfo {
-      C.installedPackageId = C.InstalledPackageId (exInstHash ex)
+      C.installedComponentId = C.ComponentId (exInstHash ex)
     , C.sourcePackageId    = exInstPkgId ex
-    , C.packageKey         = exInstKey ex
-    , C.depends            = map (C.InstalledPackageId . exInstHash)
+    , C.depends            = map (C.ComponentId . exInstHash)
                                  (exInstBuildAgainst ex)
     }
 
@@ -252,15 +251,6 @@ exInstPkgId ex = C.PackageIdentifier {
     , pkgVersion = Version [exInstVersion ex, 0, 0] []
     }
 
-exInstLibName :: ExampleInstalled -> C.LibraryName
-exInstLibName ex = C.packageKeyLibraryName (exInstPkgId ex) (exInstKey ex)
-
-exInstKey :: ExampleInstalled -> C.PackageKey
-exInstKey ex =
-    C.mkPackageKey True
-                   (exInstPkgId ex)
-                   (map exInstLibName (exInstBuildAgainst ex))
-
 exAvIdx :: [ExampleAvailable] -> CI.PackageIndex.PackageIndex SourcePackage
 exAvIdx = CI.PackageIndex.fromList . map exAvSrcPkg