diff --git a/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/Solver.hs b/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/Solver.hs
index 9619f897fd492915977f9a283549df8007bdb8c9..ac0916cde0c787272c0ce845da234e72a4bee0f5 100644
--- a/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/Solver.hs
+++ b/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/Solver.hs
@@ -5,17 +5,14 @@ module UnitTests.Distribution.Client.Dependency.Modular.Solver (tests, options)
 
 -- base
 import Control.Monad
-import Data.Maybe (catMaybes, isNothing)
 import Data.Either (partitionEithers)
+import Data.Maybe (catMaybes, isNothing)
+import Data.Monoid
 import Data.Proxy
 import Data.Typeable
 import Data.Version
 import qualified Data.Map as Map
 
-#if !MIN_VERSION_base(4,8,0)
-import Data.Monoid
-#endif
-
 -- test-framework
 import Test.Tasty as TF
 import Test.Tasty.HUnit (testCase, assertEqual, assertBool)
@@ -31,11 +28,13 @@ import qualified Distribution.System               as C
 import qualified Distribution.Version              as C
 
 -- cabal-install
+import Distribution.Client.ComponentDeps (ComponentDeps)
 import Distribution.Client.Dependency
 import Distribution.Client.Dependency.Types
 import Distribution.Client.Types
-import qualified Distribution.Client.InstallPlan  as CI.InstallPlan
-import qualified Distribution.Client.PackageIndex as CI.PackageIndex
+import qualified Distribution.Client.InstallPlan   as CI.InstallPlan
+import qualified Distribution.Client.PackageIndex  as CI.PackageIndex
+import qualified Distribution.Client.ComponentDeps as CD
 
 tests :: [TF.TestTree]
 tests = [
@@ -70,6 +69,16 @@ tests = [
         , runTest $         mkTest db6 "depsWithTests1" ["C"]      (Just [("A", 1), ("B", 1), ("C", 1)])
         , runTest $ indep $ mkTest db6 "depsWithTests2" ["C", "D"] (Just [("A", 1), ("B", 1), ("C", 1), ("D", 1)])
         ]
+    , testGroup "Setup dependencies" [
+          runTest $ mkTest db7  "setupDeps1" ["B"] (Just [("A", 2), ("B", 1)])
+        , runTest $ mkTest db7  "setupDeps2" ["C"] (Just [("A", 2), ("C", 1)])
+        , runTest $ mkTest db7  "setupDeps3" ["D"] (Just [("A", 1), ("D", 1)])
+        , runTest $ mkTest db7  "setupDeps4" ["E"] (Just [("A", 1), ("A", 2), ("E", 1)])
+        , runTest $ mkTest db7  "setupDeps5" ["F"] (Just [("A", 1), ("A", 2), ("F", 1)])
+        , runTest $ mkTest db8  "setupDeps6" ["C", "D"] (Just [("A", 1), ("B", 1), ("B", 2), ("C", 1), ("D", 1)])
+        , runTest $ mkTest db9  "setupDeps7" ["F", "G"] (Just [("A", 1), ("B", 1), ("B",2 ), ("C", 1), ("D", 1), ("E", 1), ("E", 2), ("F", 1), ("G", 1)])
+        , runTest $ mkTest db10 "setupDeps8" ["C"] (Just [("C", 1)])
+        ]
     ]
   where
     indep test = test { testIndepGoals = True }
@@ -114,37 +123,37 @@ runTest SolverTest{..} = askOption $ \(OptionShowSolverLog showSolverLog) ->
 
 db1 :: ExampleDb
 db1 =
-    let a = ExInst "A" 1 "A-1" []
+    let a = exInst "A" 1 "A-1" []
     in [ Left a
-       , Right $ ExAv "B" 1 [ExAny "A"]
-       , Right $ ExAv "B" 2 [ExAny "A"]
-       , Right $ ExAv "C" 1 [ExFix "B" 1]
-       , Right $ ExAv "D" 1 [ExFix "B" 2]
-       , Right $ ExAv "E" 1 [ExAny "B"]
-       , Right $ ExAv "F" 1 [ExFix "B" 1, ExAny "E"]
-       , Right $ ExAv "G" 1 [ExFix "B" 2, ExAny "E"]
-       , Right $ ExAv "Z" 1 []
+       , Right $ exAv "B" 1 [ExAny "A"]
+       , Right $ exAv "B" 2 [ExAny "A"]
+       , Right $ exAv "C" 1 [ExFix "B" 1]
+       , Right $ exAv "D" 1 [ExFix "B" 2]
+       , Right $ exAv "E" 1 [ExAny "B"]
+       , Right $ exAv "F" 1 [ExFix "B" 1, ExAny "E"]
+       , Right $ exAv "G" 1 [ExFix "B" 2, ExAny "E"]
+       , Right $ exAv "Z" 1 []
        ]
 
 -- In this example, we _can_ install C and D as independent goals, but we have
 -- to pick two diferent versions for B (arbitrarily)
 db2 :: ExampleDb
 db2 = [
-    Right $ ExAv "A" 1 []
-  , Right $ ExAv "A" 2 []
-  , Right $ ExAv "B" 1 [ExAny "A"]
-  , Right $ ExAv "B" 2 [ExAny "A"]
-  , Right $ ExAv "C" 1 [ExAny "B", ExFix "A" 1]
-  , Right $ ExAv "D" 1 [ExAny "B", ExFix "A" 2]
+    Right $ exAv "A" 1 []
+  , Right $ exAv "A" 2 []
+  , Right $ exAv "B" 1 [ExAny "A"]
+  , Right $ exAv "B" 2 [ExAny "A"]
+  , Right $ exAv "C" 1 [ExAny "B", ExFix "A" 1]
+  , Right $ exAv "D" 1 [ExAny "B", ExFix "A" 2]
   ]
 
 db3 :: ExampleDb
 db3 = [
-     Right $ ExAv "A" 1 []
-   , Right $ ExAv "A" 2 []
-   , Right $ ExAv "B" 1 [ExFlag "flagB" [ExFix "A" 1] [ExFix "A" 2]]
-   , Right $ ExAv "C" 1 [ExFix "A" 1, ExAny "B"]
-   , Right $ ExAv "D" 1 [ExFix "A" 2, ExAny "B"]
+     Right $ exAv "A" 1 []
+   , Right $ exAv "A" 2 []
+   , Right $ exAv "B" 1 [ExFlag "flagB" [ExFix "A" 1] [ExFix "A" 2]]
+   , Right $ exAv "C" 1 [ExFix "A" 1, ExAny "B"]
+   , Right $ exAv "D" 1 [ExFix "A" 2, ExAny "B"]
    ]
 
 -- | Like exampleDb2, but the flag picks a different package rather than a
@@ -181,13 +190,13 @@ db3 = [
 -- we only ever assign to one of these, these constraints are never broken.
 db4 :: ExampleDb
 db4 = [
-     Right $ ExAv "Ax" 1 []
-   , Right $ ExAv "Ax" 2 []
-   , Right $ ExAv "Ay" 1 []
-   , Right $ ExAv "Ay" 2 []
-   , Right $ ExAv "B"  1 [ExFlag "flagB" [ExFix "Ax" 1] [ExFix "Ay" 1]]
-   , Right $ ExAv "C"  1 [ExFix "Ax" 2, ExAny "B"]
-   , Right $ ExAv "D"  1 [ExFix "Ay" 2, ExAny "B"]
+     Right $ exAv "Ax" 1 []
+   , Right $ exAv "Ax" 2 []
+   , Right $ exAv "Ay" 1 []
+   , Right $ exAv "Ay" 2 []
+   , Right $ exAv "B"  1 [ExFlag "flagB" [ExFix "Ax" 1] [ExFix "Ay" 1]]
+   , Right $ exAv "C"  1 [ExFix "Ax" 2, ExAny "B"]
+   , Right $ exAv "D"  1 [ExFix "Ay" 2, ExAny "B"]
    ]
 
 -- | Some tests involving testsuites
@@ -207,14 +216,14 @@ db4 = [
 --     E and G together, unless we regard them as independent goals.
 db5 :: ExampleDb
 db5 = [
-    Right $ ExAv "A" 1 []
-  , Right $ ExAv "A" 2 []
-  , Right $ ExAv "B" 1 []
-  , Right $ ExAv "C" 1 [ExTest "testC" [ExAny "A"]]
-  , Right $ ExAv "D" 1 [ExTest "testD" [ExFix "B" 2]]
-  , Right $ ExAv "E" 1 [ExFix "A" 1, ExTest "testE" [ExAny "A"]]
-  , Right $ ExAv "F" 1 [ExFix "A" 1, ExTest "testF" [ExFix "A" 2]]
-  , Right $ ExAv "G" 1 [ExFix "A" 2, ExTest "testG" [ExAny "A"]]
+    Right $ exAv "A" 1 []
+  , Right $ exAv "A" 2 []
+  , Right $ exAv "B" 1 []
+  , Right $ exAv "C" 1 [ExTest "testC" [ExAny "A"]]
+  , Right $ exAv "D" 1 [ExTest "testD" [ExFix "B" 2]]
+  , Right $ exAv "E" 1 [ExFix "A" 1, ExTest "testE" [ExAny "A"]]
+  , Right $ exAv "F" 1 [ExFix "A" 1, ExTest "testF" [ExFix "A" 2]]
+  , Right $ exAv "G" 1 [ExFix "A" 2, ExTest "testG" [ExAny "A"]]
   ]
 
 -- Now the _dependencies_ have test suites
@@ -227,13 +236,84 @@ db5 = [
 --   set things up, this means that we should also link their test suites.
 db6 :: ExampleDb
 db6 = [
-    Right $ ExAv "A" 1 []
-  , Right $ ExAv "A" 2 []
-  , Right $ ExAv "B" 1 [ExTest "testA" [ExAny "A"]]
-  , Right $ ExAv "C" 1 [ExFix "A" 1, ExAny "B"]
-  , Right $ ExAv "D" 1 [ExAny "B"]
+    Right $ exAv "A" 1 []
+  , Right $ exAv "A" 2 []
+  , Right $ exAv "B" 1 [ExTest "testA" [ExAny "A"]]
+  , Right $ exAv "C" 1 [ExFix "A" 1, ExAny "B"]
+  , Right $ exAv "D" 1 [ExAny "B"]
+  ]
+
+-- Packages with setup dependencies
+--
+-- Install..
+-- * B: Simple example, just make sure setup deps are taken into account at all
+-- * C: Both the package and the setup script depend on any version of A.
+--      In this case we prefer to link
+-- * D: Variation on C.1 where the package requires a specific (not latest)
+--      version but the setup dependency is not fixed. Again, we prefer to
+--      link (picking the older version)
+-- * E: Variation on C.2 with the setup dependency the more inflexible.
+--      Currently, in this case we do not see the opportunity to link because
+--      we consider setup dependencies after normal dependencies; we will
+--      pick A.2 for E, then realize we cannot link E.setup.A to A.2, and pick
+--      A.1 instead. This isn't so easy to fix (if we want to fix it at all);
+--      in particular, considering setup dependencies _before_ other deps is
+--      not an improvement, because in general we would prefer to link setup
+--      setups to package deps, rather than the other way around. (For example,
+--      if we change this ordering then the test for D would start to install
+--      two versions of A).
+-- * F: The package and the setup script depend on different versions of A.
+--      This will only work if setup dependencies are considered independent.
+db7 :: ExampleDb
+db7 = [
+    Right $ exAv "A" 1 []
+  , Right $ exAv "A" 2 []
+  , Right $ exAv "B" 1 []            `withSetupDeps` [ExAny "A"]
+  , Right $ exAv "C" 1 [ExAny "A"  ] `withSetupDeps` [ExAny "A"  ]
+  , Right $ exAv "D" 1 [ExFix "A" 1] `withSetupDeps` [ExAny "A"  ]
+  , Right $ exAv "E" 1 [ExAny "A"  ] `withSetupDeps` [ExFix "A" 1]
+  , Right $ exAv "F" 1 [ExFix "A" 2] `withSetupDeps` [ExFix "A" 1]
+  ]
+
+-- If we install C and D together (not as independent goals), we need to build
+-- both B.1 and B.2, both of which depend on A.
+db8 :: ExampleDb
+db8 = [
+    Right $ exAv "A" 1 []
+  , Right $ exAv "B" 1 [ExAny "A"]
+  , Right $ exAv "B" 2 [ExAny "A"]
+  , Right $ exAv "C" 1 [] `withSetupDeps` [ExFix "B" 1]
+  , Right $ exAv "D" 1 [] `withSetupDeps` [ExFix "B" 2]
   ]
 
+-- Extended version of `db8` so that we have nested setup dependencies
+db9 :: ExampleDb
+db9 = db8 ++ [
+    Right $ exAv "E" 1 [ExAny "C"]
+  , Right $ exAv "E" 2 [ExAny "D"]
+  , Right $ exAv "F" 1 [] `withSetupDeps` [ExFix "E" 1]
+  , Right $ exAv "G" 1 [] `withSetupDeps` [ExFix "E" 2]
+  ]
+
+-- Multiple already-installed packages with inter-dependencies, and one package
+-- (C) that depends on package A-1 for its setup script and package A-2 as a
+-- library dependency.
+db10 :: ExampleDb
+db10 =
+  let rts         = exInst "rts"         1 "rts-inst"         []
+      ghc_prim    = exInst "ghc-prim"    1 "ghc-prim-inst"    [rts]
+      base        = exInst "base"        1 "base-inst"        [rts, ghc_prim]
+      a1          = exInst "A"           1 "A1-inst"          [base]
+      a2          = exInst "A"           2 "A2-inst"          [base]
+  in [
+      Left rts
+    , Left ghc_prim
+    , Left base
+    , Left a1
+    , Left a2
+    , Right $ exAv "C" 1 [ExFix "A" 2] `withSetupDeps` [ExFix "A" 1]
+    ]
+
 {-------------------------------------------------------------------------------
   Example package database DSL
 
@@ -298,9 +378,17 @@ data ExampleDependency =
 data ExampleAvailable = ExAv {
     exAvName    :: ExamplePkgName
   , exAvVersion :: ExamplePkgVersion
-  , exAvDeps    :: [ExampleDependency]
+  , exAvDeps    :: ComponentDeps [ExampleDependency]
   }
 
+exAv :: ExamplePkgName -> ExamplePkgVersion -> [ExampleDependency] -> ExampleAvailable
+exAv n v ds = ExAv { exAvName = n, exAvVersion = v, exAvDeps = CD.fromLibraryDeps ds }
+
+withSetupDeps :: ExampleAvailable -> [ExampleDependency] -> ExampleAvailable
+withSetupDeps ex setupDeps = ex {
+      exAvDeps = exAvDeps ex <> CD.fromSetupDeps setupDeps
+    }
+
 data ExampleInstalled = ExInst {
     exInstName         :: ExamplePkgName
   , exInstVersion      :: ExamplePkgVersion
@@ -308,6 +396,9 @@ data ExampleInstalled = ExInst {
   , exInstBuildAgainst :: [ExampleInstalled]
   }
 
+exInst :: ExamplePkgName -> ExamplePkgVersion -> ExamplePkgHash -> [ExampleInstalled] -> ExampleInstalled
+exInst = ExInst
+
 type ExampleDb = [Either ExampleInstalled ExampleAvailable]
 
 type DependencyTree a = C.CondTree C.ConfVar [C.Dependency] a
@@ -317,21 +408,24 @@ exDbPkgs = map (either exInstName exAvName)
 
 exAvSrcPkg :: ExampleAvailable -> SourcePackage
 exAvSrcPkg ex =
-    let (libraryDeps, testSuites) = splitTopLevel (exAvDeps ex)
+    let (libraryDeps, testSuites) = splitTopLevel (CD.libraryDeps (exAvDeps ex))
     in SourcePackage {
            packageInfoId        = exAvPkgId ex
          , packageSource        = LocalTarballPackage "<<path>>"
          , packageDescrOverride = Nothing
          , packageDescription   = C.GenericPackageDescription{
                C.packageDescription = C.emptyPackageDescription {
-                   C.package      = exAvPkgId ex
-                 , C.library      = error "not yet configured: library"
-                 , C.executables  = error "not yet configured: executables"
-                 , C.testSuites   = error "not yet configured: testSuites"
-                 , C.benchmarks   = error "not yet configured: benchmarks"
-                 , C.buildDepends = error "not yet configured: buildDepends"
+                   C.package        = exAvPkgId ex
+                 , C.library        = error "not yet configured: library"
+                 , C.executables    = error "not yet configured: executables"
+                 , C.testSuites     = error "not yet configured: testSuites"
+                 , C.benchmarks     = error "not yet configured: benchmarks"
+                 , C.buildDepends   = error "not yet configured: buildDepends"
+                 , C.setupBuildInfo = Just C.SetupBuildInfo {
+                       C.setupDepends = mkSetupDeps (CD.setupDeps (exAvDeps ex))
+                     }
                  }
-             , C.genPackageFlags = concatMap extractFlags (exAvDeps ex)
+             , C.genPackageFlags = concatMap extractFlags (CD.libraryDeps (exAvDeps ex))
              , C.condLibrary     = Just $ mkCondTree libraryDeps
              , C.condExecutables = []
              , C.condTestSuites  = map (\(t, deps) -> (t, mkCondTree deps)) testSuites
@@ -402,6 +496,11 @@ exAvSrcPkg ex =
     splitDeps (ExTest _ _:_) =
       error "Unexpected nested test"
 
+    -- Currently we only support simple setup dependencies
+    mkSetupDeps :: [ExampleDependency] -> [C.Dependency]
+    mkSetupDeps deps =
+      let (directDeps, []) = splitDeps deps in map mkDirect directDeps
+
 exAvPkgId :: ExampleAvailable -> C.PackageIdentifier
 exAvPkgId ex = C.PackageIdentifier {
       pkgName    = C.PackageName (exAvName ex)