diff --git a/Cabal2Ebuild.hs b/Cabal2Ebuild.hs
--- a/Cabal2Ebuild.hs
+++ b/Cabal2Ebuild.hs
@@ -22,7 +22,7 @@
         ,convertDependency) where
 
 import qualified Distribution.PackageDescription as Cabal
-                                                (PackageDescription(..))
+                                                (PackageDescription(..), license)
 import qualified Distribution.Package as Cabal  (PackageIdentifier(..)
                                                 , Dependency(..))
 import qualified Distribution.Version as Cabal  (VersionRange, foldVersionRange')
diff --git a/Main.hs b/Main.hs
--- a/Main.hs
+++ b/Main.hs
@@ -19,7 +19,7 @@
 
 import Distribution.Simple.Command -- commandsRun
 import Distribution.Simple.Utils ( die, cabalVersion, warn )
-import qualified Distribution.PackageDescription.Parse as Cabal
+import qualified Distribution.PackageDescription.Parsec as Cabal
 import qualified Distribution.Package as Cabal
 import Distribution.Verbosity (Verbosity, normal)
 import Distribution.Text (display, simpleParse)
@@ -173,7 +173,7 @@
   let verbosity = fromFlag (makeEbuildVerbosity flags)
   overlayPath <- getOverlayPath verbosity (fromFlag $ H.globalPathToOverlay globalFlags)
   forM_ cabals $ \cabalFileName -> do
-    pkg <- Cabal.readPackageDescription normal cabalFileName
+    pkg <- Cabal.readGenericPackageDescription normal cabalFileName
     mergeGenericPackageDescription verbosity overlayPath cat pkg False (fromFlag $ makeEbuildCabalFlags flags)
 
 makeEbuildCommand :: CommandUI MakeEbuildFlags
diff --git a/Merge.hs b/Merge.hs
--- a/Merge.hs
+++ b/Merge.hs
@@ -195,17 +195,20 @@
 -- USE_EXPAND values. If it's not a user-specified rename mangle
 -- it into a hyphen ('-').
 mangle_iuse :: String -> String
-mangle_iuse = map f
+mangle_iuse = drop_prefix . map f
   where f '_' = '-'
         f c   = c
 
--- | Remove "with_" or "with-" from beginning of flag names.
-drop_with :: String -> String
-drop_with = \x ->
+-- | Remove "with" or "use" prefixes from flag names.
+drop_prefix :: String -> String
+drop_prefix = \x ->
   case splitAt 5 x of
     ("with_", b) -> b
     ("with-", b) -> b
-    _ -> x
+    _ -> case splitAt 4 x of
+           ("use_", b) -> b
+           ("use-", b) -> b
+           _ -> x
 
 -- used to be FlagAssignment in Cabal but now it's an opaque type
 type CabalFlags = [(Cabal.FlagName, Bool)]
@@ -260,8 +263,10 @@
                                             , "  $ hackport make-ebuild " ++ cn ++ " " ++ pn ++ ".cabal"
                                             ]
 
-  let (accepted_deps, skipped_deps) = Portage.partition_depends ghc_packages merged_cabal_pkg_name (Cabal.buildDepends pkgDesc0)
-      pkgDesc = pkgDesc0 { Cabal.buildDepends = accepted_deps }
+  let (accepted_deps, skipped_deps) = Portage.partition_depends ghc_packages merged_cabal_pkg_name
+                                      (Merge.exeAndLibDeps pkgDesc0)
+
+      pkgDesc = Merge.RetroPackageDescription pkgDesc0 accepted_deps
       cabal_flag_descs = Cabal.genPackageFlags pkgGenericDesc
       all_flags = map Cabal.flagName cabal_flag_descs
       make_fas  :: [Cabal.Flag] -> [CabalFlags]
@@ -286,26 +291,26 @@
       cfn_to_iuse :: String -> String
       cfn_to_iuse cfn =
           case lookup cfn cf_to_iuse_rename of
-              Nothing  -> mangle_iuse . drop_with $ cfn
+              Nothing  -> mangle_iuse cfn
               Just ein -> ein
-
       -- key idea is to generate all possible list of flags
       deps1 :: [(CabalFlags, Merge.EDep)]
       deps1  = [ ( f `updateFa` Cabal.unFlagAssignment fr
                  , cabal_to_emerge_dep pkgDesc_filtered_bdeps)
                | f <- all_possible_flag_assignments
-               -- TODO: move from 'finalizePackageDescription' to 'finalizePD'
-               , Right (pkgDesc1,fr) <- [GHCCore.finalizePackageDescription (Cabal.mkFlagAssignment f)
-                                                                  (GHCCore.dependencySatisfiable pix)
-                                                                  GHCCore.platform
-                                                                  compiler_info
-                                                                  []
-                                                                  pkgGenericDesc]
+               , Right (pkgDesc1,fr) <- [GHCCore.finalizePD (Cabal.mkFlagAssignment f)
+                                         GHCCore.defaultComponentRequestedSpec
+                                         (GHCCore.dependencySatisfiable pix)
+                                         GHCCore.platform
+                                         compiler_info
+                                         []
+                                         pkgGenericDesc]
                -- drop circular deps and shipped deps
-               , let (ad, _sd) = Portage.partition_depends ghc_packages merged_cabal_pkg_name (Cabal.buildDepends pkgDesc1)
+               , let (ad, _sd) = Portage.partition_depends ghc_packages merged_cabal_pkg_name
+                                 (Merge.exeAndLibDeps pkgDesc1)
                -- TODO: drop ghc libraries from tests depends as well
                -- (see deepseq in hackport-0.3.5 as an example)
-               , let pkgDesc_filtered_bdeps = pkgDesc1 { Cabal.buildDepends = ad }
+               , let pkgDesc_filtered_bdeps = Merge.RetroPackageDescription pkgDesc1 ad
                ]
           where
             updateFa :: CabalFlags -> CabalFlags -> CabalFlags
@@ -375,12 +380,12 @@
                                       id fs
                        in k e
 
-      cabal_to_emerge_dep :: Cabal.PackageDescription -> Merge.EDep
+      cabal_to_emerge_dep :: Merge.RetroPackageDescription -> Merge.EDep
       cabal_to_emerge_dep cabal_pkg = Merge.resolveDependencies overlay cabal_pkg compiler_info ghc_packages merged_cabal_pkg_name
 
   debug verbosity $ "buildDepends pkgDesc0 raw: " ++ Cabal.showPackageDescription pkgDesc0
-  debug verbosity $ "buildDepends pkgDesc0: " ++ show (map display (Cabal.buildDepends pkgDesc0))
-  debug verbosity $ "buildDepends pkgDesc:  " ++ show (map display (Cabal.buildDepends pkgDesc))
+  debug verbosity $ "buildDepends pkgDesc0: " ++ show (map display (Merge.exeAndLibDeps pkgDesc0))
+  debug verbosity $ "buildDepends pkgDesc:  " ++ show (map display (Merge.buildDepends pkgDesc))
 
   notice verbosity $ "Accepted depends: " ++ show (map display accepted_deps)
   notice verbosity $ "Skipped  depends: " ++ show (map display skipped_deps)
@@ -431,11 +436,11 @@
                . ( case requested_cabal_flags of
                        Nothing  -> id
                        Just ucf -> (\e -> e { E.used_options  = E.used_options e ++ [("flags", ucf)] }))
-               $ C2E.cabal2ebuild cat pkgDesc
+               $ C2E.cabal2ebuild cat (Merge.packageDescription pkgDesc)
 
   mergeEbuild verbosity existing_meta pkgdir ebuild active_flag_descs
   when fetch $ do
-    let cabal_pkgId = Cabal.packageId pkgDesc
+    let cabal_pkgId = Cabal.packageId (Merge.packageDescription pkgDesc)
         norm_pkgName = Cabal.packageName (Portage.normalizeCabalPackageId cabal_pkgId)
     fetchDigestAndCheck verbosity (overlayPath </> display cat </> display norm_pkgName)
 
@@ -471,7 +476,7 @@
 
 -- | Generate a list of tuples containing Cabal flag names and descriptions
 metaFlags :: [Cabal.Flag] -> [(String, String)]
-metaFlags flags = zip (mangle_iuse . drop_with . Cabal.unFlagName . Cabal.flagName <$> flags) (Cabal.flagDescription <$> flags)
+metaFlags flags = zip (mangle_iuse . Cabal.unFlagName . Cabal.flagName <$> flags) (Cabal.flagDescription <$> flags)
 
 mergeEbuild :: Verbosity -> EM.EMeta -> FilePath -> E.EBuild -> [Cabal.Flag] -> IO ()
 mergeEbuild verbosity existing_meta pkgdir ebuild flags = do
diff --git a/Merge/Dependencies.hs b/Merge/Dependencies.hs
--- a/Merge/Dependencies.hs
+++ b/Merge/Dependencies.hs
@@ -4,6 +4,9 @@
  -}
 module Merge.Dependencies
   ( EDep(..)
+  , RetroPackageDescription(..)
+  , exeAndLibDeps
+  , mkRetroPD
   , resolveDependencies
   ) where
 
@@ -49,6 +52,26 @@
   }
   deriving (Show, Eq, Ord)
 
+-- | Cabal-1 style PackageDescription, with a top-level buildDepends function
+data RetroPackageDescription = RetroPackageDescription {
+  packageDescription :: Cabal.PackageDescription,
+  buildDepends :: [Cabal.Dependency]
+  } deriving (Show)
+
+-- | Construct a RetroPackageDescription using exeAndLibDeps for the buildDepends.
+mkRetroPD :: Cabal.PackageDescription -> RetroPackageDescription
+mkRetroPD pd = RetroPackageDescription { packageDescription = pd, buildDepends = exeAndLibDeps pd }
+
+-- | extract only the build dependencies for libraries and executables for a given package.
+exeAndLibDeps :: Cabal.PackageDescription -> [Cabal.Dependency]
+exeAndLibDeps pkg = L.union
+                    (concat
+                     $ map Cabal.targetBuildDepends
+                     $ map Cabal.buildInfo (Cabal.executables pkg))
+                    (concat
+                     $ map Cabal.targetBuildDepends
+                     $ map Cabal.libBuildInfo (Cabal.allLibraries pkg))
+
 #if MIN_VERSION_base(4,9,0)
 instance Semigroup EDep where
   (EDep rdepA rdep_eA depA dep_eA) <> (EDep rdepB rdep_eB depB dep_eB) = EDep
@@ -76,41 +99,42 @@
     }
 #endif
 
-resolveDependencies :: Portage.Overlay -> Cabal.PackageDescription -> Cabal.CompilerInfo
+resolveDependencies :: Portage.Overlay -> RetroPackageDescription -> Cabal.CompilerInfo
                     -> [Cabal.PackageName] -> Cabal.PackageName
                     -> EDep
 resolveDependencies overlay pkg compiler_info ghc_package_names merged_cabal_pkg_name = edeps
   where
     -- hasBuildableExes p = any (buildable . buildInfo) . executables $ p
     treatAsLibrary :: Bool
-    treatAsLibrary = isJust (Cabal.library pkg)
+    treatAsLibrary = isJust (Cabal.library (packageDescription pkg))
     -- without slot business
     raw_haskell_deps :: Portage.Dependency
-    raw_haskell_deps = PN.normalize_depend $ Portage.DependAllOf $ haskellDependencies overlay (Cabal.buildDepends pkg)
+    raw_haskell_deps = PN.normalize_depend $ Portage.DependAllOf $ haskellDependencies overlay (buildDepends pkg)
     test_deps :: Portage.Dependency
     test_deps = Portage.mkUseDependency (True, Portage.Use "test") $
                     Portage.DependAllOf $
                     remove_raw_common $
-                    testDependencies overlay pkg ghc_package_names merged_cabal_pkg_name
+                    testDependencies overlay (packageDescription pkg) ghc_package_names merged_cabal_pkg_name
     cabal_dep :: Portage.Dependency
-    cabal_dep = cabalDependency overlay pkg compiler_info
+    cabal_dep = cabalDependency overlay (packageDescription pkg) compiler_info
     ghc_dep :: Portage.Dependency
     ghc_dep = compilerInfoToDependency compiler_info
     extra_libs :: Portage.Dependency
-    extra_libs = Portage.DependAllOf $ findCLibs pkg
+    extra_libs = Portage.DependAllOf $ findCLibs (packageDescription pkg)
     pkg_config_libs :: [Portage.Dependency]
-    pkg_config_libs = pkgConfigDependencies overlay pkg
+    pkg_config_libs = pkgConfigDependencies overlay (packageDescription pkg)
     pkg_config_tools :: Portage.Dependency
     pkg_config_tools = Portage.DependAllOf $ if L.null pkg_config_libs
                            then []
                            else [any_c_p "virtual" "pkgconfig"]
     build_tools :: Portage.Dependency
-    build_tools = Portage.DependAllOf $ pkg_config_tools : legacyBuildToolsDependencies pkg ++ hackageBuildToolsDependencies overlay pkg
+    build_tools = Portage.DependAllOf $ pkg_config_tools : legacyBuildToolsDependencies (packageDescription pkg)
+                  ++ hackageBuildToolsDependencies overlay (packageDescription pkg)
 
     setup_deps :: Portage.Dependency
     setup_deps = PN.normalize_depend $ Portage.DependAllOf $
                      remove_raw_common $
-                     setupDependencies overlay pkg ghc_package_names merged_cabal_pkg_name
+                     setupDependencies overlay (packageDescription pkg) ghc_package_names merged_cabal_pkg_name
 
     edeps :: EDep
     edeps
diff --git a/Portage/Cabal.hs b/Portage/Cabal.hs
--- a/Portage/Cabal.hs
+++ b/Portage/Cabal.hs
@@ -6,13 +6,14 @@
 import qualified Data.List as L
 
 import qualified Distribution.License             as Cabal
+import qualified Distribution.SPDX.License        as SPDX
 import qualified Distribution.Package             as Cabal
 import qualified Distribution.Text                as Cabal
 
 -- map the cabal license type to the gentoo license string format
-convertLicense :: Cabal.License -> Either String String
+convertLicense :: SPDX.License -> Either String String
 convertLicense l =
-    case l of
+    case Cabal.licenseFromSPDX l of
         --  good ones
         Cabal.AGPL mv      -> Right $ "AGPL-" ++ (maybe "3" Cabal.display mv)  -- almost certainly version 3
         Cabal.GPL mv       -> Right $ "GPL-" ++ (maybe "2" Cabal.display mv)  -- almost certainly version 2
diff --git a/Portage/GHCCore.hs b/Portage/GHCCore.hs
--- a/Portage/GHCCore.hs
+++ b/Portage/GHCCore.hs
@@ -3,7 +3,8 @@
 module Portage.GHCCore
         ( minimumGHCVersionToBuildPackage
         , cabalFromGHC
-        , finalizePackageDescription
+        , defaultComponentRequestedSpec
+        , finalizePD
         , platform
         , dependencySatisfiable
         ) where
@@ -19,6 +20,7 @@
 import Distribution.PackageDescription.Configuration
 import Distribution.Compiler (CompilerId(..), CompilerFlavor(GHC))
 import Distribution.System
+import Distribution.Types.ComponentRequestedSpec (defaultComponentRequestedSpec)
 
 import Distribution.Text
 
@@ -31,13 +33,12 @@
 -- It means that first ghc in this list is a minmum default.
 ghcs :: [(DC.CompilerInfo, InstalledPackageIndex)]
 ghcs = modern_ghcs
-    where modern_ghcs  = [ghc741, ghc742, ghc761, ghc762, ghc782, ghc7101, ghc7102, ghc801, ghc802, ghc821, ghc843, ghc861, ghc863, ghc881]
+    where modern_ghcs  = [ghc741, ghc742, ghc762, ghc782, ghc7101, ghc7102, ghc801, ghc802, ghc821, ghc843, ghc863, ghc865, ghc881]
 
 cabalFromGHC :: [Int] -> Maybe Cabal.Version
 cabalFromGHC ver = lookup ver table
   where
   table = [ ([7,4,2],  Cabal.mkVersion [1,14,0])
-          , ([7,6,1],  Cabal.mkVersion [1,16,0])
           , ([7,6,2],  Cabal.mkVersion [1,16,0])
           , ([7,8,2],  Cabal.mkVersion [1,18,1,3])
           , ([7,10,1], Cabal.mkVersion [1,22,2,0])
@@ -46,7 +47,8 @@
           , ([8,0,2],  Cabal.mkVersion [1,24,2,0])
           , ([8,2,1],  Cabal.mkVersion [2,0,0,2])
           , ([8,4,3],  Cabal.mkVersion [2,2,0,1])
-          , ([8,6,1],  Cabal.mkVersion [2,4,0,1])
+          , ([8,6,3],  Cabal.mkVersion [2,4,0,1])
+          , ([8,6,5],  Cabal.mkVersion [2,4,0,1])
           , ([8,8,1],  Cabal.mkVersion [3,0,0,0])
           ]
 
@@ -76,7 +78,7 @@
   -> (DC.CompilerInfo, InstalledPackageIndex)
   -> Either [Cabal.Dependency] (PackageDescription, FlagAssignment)
 packageBuildableWithGHCVersion pkg user_specified_fas (compiler_info, pkgIndex) = trace_failure $
-  finalizePackageDescription user_specified_fas (dependencySatisfiable pkgIndex) platform compiler_info [] pkg
+  finalizePD user_specified_fas defaultComponentRequestedSpec (dependencySatisfiable pkgIndex) platform compiler_info [] pkg
     where trace_failure v = case v of
               (Left deps) -> trace (unwords ["rejecting dep:" , show_compiler compiler_info
                                             , "as", show_deps deps
@@ -120,12 +122,12 @@
 ghc881 :: (DC.CompilerInfo, InstalledPackageIndex)
 ghc881 = (ghc [8,8,1], mkIndex ghc881_pkgs)
 
+ghc865 :: (DC.CompilerInfo, InstalledPackageIndex)
+ghc865 = (ghc [8,6,5], mkIndex ghc865_pkgs)
+
 ghc863 :: (DC.CompilerInfo, InstalledPackageIndex)
 ghc863 = (ghc [8,6,3], mkIndex ghc863_pkgs)
 
-ghc861 :: (DC.CompilerInfo, InstalledPackageIndex)
-ghc861 = (ghc [8,6,1], mkIndex ghc861_pkgs)
-
 ghc843 :: (DC.CompilerInfo, InstalledPackageIndex)
 ghc843 = (ghc [8,4,3], mkIndex ghc843_pkgs)
 
@@ -150,9 +152,6 @@
 ghc762 :: (DC.CompilerInfo, InstalledPackageIndex)
 ghc762 = (ghc [7,6,2], mkIndex ghc762_pkgs)
 
-ghc761 :: (DC.CompilerInfo, InstalledPackageIndex)
-ghc761 = (ghc [7,6,1], mkIndex ghc761_pkgs)
-
 ghc742 :: (DC.CompilerInfo, InstalledPackageIndex)
 ghc742 = (ghc [7,4,2], mkIndex ghc742_pkgs)
 
@@ -160,8 +159,11 @@
 ghc741 = (ghc [7,4,1], mkIndex ghc741_pkgs)
 
 -- | Non-upgradeable core packages
--- Source: http://haskell.org/haskellwiki/Libraries_released_with_GHC
---         and our binary tarballs (package.conf.d.initial subdir)
+-- Sources:
+--  * release notes
+--      example: https://downloads.haskell.org/~ghc/8.6.5/docs/html/users_guide/8.6.5-notes.html
+--  * our binary tarballs (package.conf.d.initial subdir)
+--  * ancient: http://haskell.org/haskellwiki/Libraries_released_with_GHC
 
 ghc881_pkgs :: [Cabal.PackageIdentifier]
 ghc881_pkgs =
@@ -174,8 +176,8 @@
   , p "deepseq" [1,4,4,0] -- used by time
   , p "directory" [1,3,3,2]
   , p "filepath" [1,4,2,1]
-  , p "ghc-boot" [8,8,1] 
-  , p "ghc-boot-th" [8,8,1] 
+  , p "ghc-boot" [8,8,1]
+  , p "ghc-boot-th" [8,8,1]
   , p "ghc-compact" [0,1,0,0]
   , p "ghc-prim" [0,5,3,0]
   , p "ghci" [8,8,1]
@@ -196,8 +198,8 @@
 --  , p "xhtml" [3000,2,2,1]
   ]
 
-ghc863_pkgs :: [Cabal.PackageIdentifier]
-ghc863_pkgs =
+ghc865_pkgs :: [Cabal.PackageIdentifier]
+ghc865_pkgs =
   [ p "array" [0,5,3,0]
   , p "base" [4,12,0,0]
   , p "binary" [0,8,6,0] -- used by libghc
@@ -207,31 +209,31 @@
   , p "deepseq" [1,4,4,0] -- used by time
   , p "directory" [1,3,3,0]
   , p "filepath" [1,4,2,1]
-  , p "ghc-boot" [8,6,3] 
-  , p "ghc-boot-th" [8,6,3] 
+  , p "ghc-boot" [8,6,5]
+  , p "ghc-boot-th" [8,6,5]
   , p "ghc-compact" [0,1,0,0]
   , p "ghc-prim" [0,5,3,0]
-  , p "ghci" [8,6,3]
+  , p "ghci" [8,6,5]
 --  , p "haskeline" [0,7,4,3]  package is upgradeable
   , p "hpc" [0,6,0,3] -- used by libghc
   , p "integer-gmp" [1,0,2,0]
   --  , p "mtl" [2,2,2]  package is upgradeable(?)
   --  , p "parsec" [3,1,13,0]  package is upgradeable(?)
   , p "pretty" [1,1,3,6]
-  , p "process" [1,6,3,0]
+  , p "process" [1,6,5,0]
   --  , p "stm" [2,5,0,0]  package is upgradeable(?)
   , p "template-haskell" [2,14,0,0] -- used by libghc
   -- , p "terminfo" [0,4,1,2]
   -- , p "text" [1,2,3,1] dependency of Cabal library
   , p "time" [1,8,0,2] -- used by unix, directory, hpc, ghc. unsafe to upgrade
-  , p "transformers" [0,5,5,0] -- used by libghc
+  , p "transformers" [0,5,6,2] -- used by libghc
   , p "unix" [2,7,2,2]
 --  , p "xhtml" [3000,2,2,1]
   ]
 
-ghc861_pkgs :: [Cabal.PackageIdentifier]
-ghc861_pkgs =
-  [ p "array" [0,5,2,0]
+ghc863_pkgs :: [Cabal.PackageIdentifier]
+ghc863_pkgs =
+  [ p "array" [0,5,3,0]
   , p "base" [4,12,0,0]
   , p "binary" [0,8,6,0] -- used by libghc
   , p "bytestring" [0,10,8,2]
@@ -240,11 +242,11 @@
   , p "deepseq" [1,4,4,0] -- used by time
   , p "directory" [1,3,3,0]
   , p "filepath" [1,4,2,1]
-  , p "ghc-boot" [8,6,1] 
-  , p "ghc-boot-th" [8,6,1] 
+  , p "ghc-boot" [8,6,3]
+  , p "ghc-boot-th" [8,6,3]
   , p "ghc-compact" [0,1,0,0]
   , p "ghc-prim" [0,5,3,0]
-  , p "ghci" [8,6,1]
+  , p "ghci" [8,6,3]
 --  , p "haskeline" [0,7,4,3]  package is upgradeable
   , p "hpc" [0,6,0,3] -- used by libghc
   , p "integer-gmp" [1,0,2,0]
@@ -486,32 +488,6 @@
   , p "template-haskell" [2,8,0,0] -- used by libghc
   , p "time" [1,4,0,1] -- used by haskell98, unix, directory, hpc, ghc. unsafe to upgrade
   , p "unix" [2,6,0,1]
-  ]
-
-ghc761_pkgs :: [Cabal.PackageIdentifier]
-ghc761_pkgs =
-  [ p "array" [0,4,0,1]
-  , p "base" [4,6,0,0]
-  , p "binary" [0,5,1,1] -- used by libghc
-  , p "bytestring" [0,10,0,0]
---  , p "Cabal" [1,16,0]  package is upgradeable
-  , p "containers" [0,5,0,0]
-  , p "deepseq" [1,3,0,1] -- used by time, haskell98
-  , p "directory" [1,2,0,0]
-  , p "filepath" [1,3,0,1]
-  , p "ghc-prim" [0,3,0,0]
-  , p "haskell2010" [1,1,1,0]
-  , p "haskell98" [2,0,0,2]
-  , p "hoopl" [3,9,0,0] -- used by libghc
-  , p "hpc" [0,6,0,0] -- used by libghc
-  , p "integer-gmp" [0,5,0,0]
-  -- , p "old-locale" [1,0,0,5] -- stopped shipping in 7.10, deprecated
-  -- , p "old-time" [1,1,0,1] -- stopped shipping in 7.10, deprecated
-  , p "pretty" [1,1,1,0]
-  , p "process" [1,1,0,2]
-  , p "template-haskell" [2,8,0,0] -- used by libghc
-  , p "time" [1,4,0,1] -- used by haskell98, unix, directory, hpc, ghc. unsafe to upgrade
-  , p "unix" [2,6,0,0]
   ]
 
 ghc742_pkgs :: [Cabal.PackageIdentifier]
diff --git a/cabal/.ghci b/cabal/.ghci
new file mode 100644
--- /dev/null
+++ b/cabal/.ghci
@@ -0,0 +1,2 @@
+:set -icabal-install -icabal-install/main
+:load Main
diff --git a/cabal/.ghcid b/cabal/.ghcid
new file mode 100644
--- /dev/null
+++ b/cabal/.ghcid
@@ -0,0 +1,1 @@
+--command "ghci -j4 +RTS -A128m"
diff --git a/cabal/.github/PULL_REQUEST_TEMPLATE.md b/cabal/.github/PULL_REQUEST_TEMPLATE.md
--- a/cabal/.github/PULL_REQUEST_TEMPLATE.md
+++ b/cabal/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,3 +1,4 @@
+---
 Please include the following checklist in your PR:
 
 * [ ] Patches conform to the [coding conventions](https://github.com/haskell/cabal/#conventions).
diff --git a/cabal/.gitignore b/cabal/.gitignore
--- a/cabal/.gitignore
+++ b/cabal/.gitignore
@@ -45,6 +45,7 @@
 # TAGS files
 TAGS
 tags
+ctags
 
 # stack artifacts
 /.stack-work/
diff --git a/cabal/.mailmap b/cabal/.mailmap
--- a/cabal/.mailmap
+++ b/cabal/.mailmap
@@ -5,6 +5,11 @@
 # Should be empty list: 'git shortlog -se | cut -f2 | cut -d'<' -f1 | uniq -d'.
 
 Adam Langley                <agl@imperialviolet.org>
+Alex Biehl                  <alexbiehl@gmail.com>
+Alex Biehl                  <alexbiehl@gmail.com>                  Alexander Biehl <abiehl@novomind.com>
+Alex Biehl                  <alexbiehl@gmail.com>                  alexbiehl <alex.biehl@gmail.com>
+Alex Washburn               <github@recursion.ninja>
+Alex Washburn               <github@recursion.ninja>               recursion-ninja <github@recursion.ninja>
 Alistair Bailey             <alistair@abayley.org>                 alistair <alistair@abayley.org>
 Alson Kemp                  <alson@alsonkemp.com>                  alson <alson@alsonkemp.com>
 Andres Löh                  <andres.loeh@gmail.com>
@@ -30,11 +35,14 @@
 Brendan Hay                 <brendan.g.hay@gmail.com>              <brendanhay@users.noreply.github.com>
 Brent Yorgey                <byorgey@gmail.com>                    <byorgey@cis.upenn.edu>
 Brian Smith                 <brianlsmith@gmail.com>                brianlsmith <brianlsmith@gmail.com>
+Daniel Díaz Carrete         <daniel@bogusemailserver.com>
+Daniel Gröber               <dxld@darkboxed.org>                   <daniel@dps.uibk.ac.at>
 Daniel Wagner               <daniel@wagner-home.com>               <dmwit@galois.com>
 David Himmelstrup           <lemmih@gmail.com>
 David Luposchainsky         <dluposchainsky@gmail.com>             <quchen@users.noreply.github.com>
 David Waern                 <davve@dtek.chalmers.se>               David Waern <unknown>
 Dennis Gosnell              <cdep.illabout@gmail.com>
+Dmitry Kovanikov            <kovanikov@gmail.com>                  ChShersh <dmitrii@holmusk.com>
 Don Stewart                 <dons00@gmail.com>                     <dons@galois.com>
 Duncan Coutts               <duncan@community.haskell.org>
 Duncan Coutts               <duncan@community.haskell.org>         <Duncan Coutts duncan@community.haskell.org>
@@ -43,9 +51,11 @@
 Duncan Coutts               <duncan@community.haskell.org>         <duncan@haskell.org>
 Duncan Coutts               <duncan@community.haskell.org>         <duncan@well-typed.com>
 Duncan Coutts               <duncan@community.haskell.org>         unknown <unknown> # 04e9fcc80bc68b72126e33b20f08050df28e727d
+Edward Z. Yang              <ezyang@cs.stanford.edu>               <ezyang@fb.com>
 Edward Z. Yang              <ezyang@cs.stanford.edu>               <ezyang@mit.edu>
 Einar Karttunen             <ekarttun@cs.helsinki.fi>
 Federico Mastellone         <fmaste@users.noreply.github.com>
+Felix Yan                   <felixonmars@archlinux.org>            Felix Yan <felixonmars@gmail.com>
 Francesco Gazzetta          <francygazz@gmail.com>                 <fgaz@users.noreply.github.com>
 Ganesh Sittampalam          <ganesh.sittampalam@credit-suisse.com> <ganesh@earth.li>
 Geoff Nixon                 <geoff-codes@users.noreply.github.com> <geoff.nixon@aol.com>
@@ -55,6 +65,8 @@
 Gershom Bazerman            <gershomb@gmail.com>                   gbaz <gershomb@gmail.com>
 Gleb Alexeev                <gleb.alexeev@gmail.com>
 Gleb Alexeev                <gleb.alexeev@gmail.com>               gleb.alexeev <gleb.alexeev@gmail.com>
+Gleb Popov                  <6yearold@gmail.com>
+Gleb Popov                  <6yearold@gmail.com>                   arrowd <6yearold@gmail.com>
 Gwern Branwen               <gwern0@gmail.com>                     gwern0 <gwern0@gmail.com>
 Heather                     <heather@live.ru>                      <Heather@cynede.net>
 Heather                     <heather@live.ru>                      <Heather@users.noreply.github.com>
@@ -73,15 +85,17 @@
 Jeremy Shaw                 <jeremy.shaw@linspireinc.com>
 Jeremy Shaw                 <jeremy.shaw@linspireinc.com>          <jeremy@n-heptane.com>
 Jim Burton                  <jim@sdf-eu.org>
+Joe Quinn                   <headprogrammingczar@gmail.com>
 Joel Bitrauser              <jo.da@posteo.de>                      <bitrauser@users.noreply.github.com>
 Joel Bitrauser              <jo.da@posteo.de>                      Bitrauser <jo.da@posteo.de>
-Joe Quinn                   <headprogrammingczar@gmail.com>
 Joel Stanley                <intractable@gmail.com>
 Joeri van Eekelen           <tchakkazulu@gmail.com>
 John D. Ramsdell            <ramsdell@mitre.org>
 John Dias                   <dias@eecs.harvard.edu>                dias <dias@eecs.harvard.edu>
-John Ericson                <Ericson2314@yahoo.com>                <Ericson2314@Yahoo.con>
+John Ericson                <Ericson2314@yahoo.com>
+John Ericson                <Ericson2314@yahoo.com>                <John.Ericson@Obsidian.Systems>
 John Ericson                <Ericson2314@yahoo.com>                <jericson@galois.com>
+John Ericson                <Ericson2314@yahoo.com>                John Ericson <Ericson2314@Yahoo.com>
 Josh Hoyt                   <josh.hoyt@galois.com>
 Judah Jacobson              <judah.jacobson@gmail.com>
 Jürgen Nicklisch-Franken    <jnf@arcor.de>
@@ -93,13 +107,16 @@
 Lennart Kolmodin            <kolmodin@gmail.com>                   <kolmodin@dtek.chalmers.se>
 Lennart Kolmodin            <kolmodin@gmail.com>                   <kolmodin@gentoo.org>
 Lennart Kolmodin            <kolmodin@gmail.com>                   <kolmodin@google.com>
-Lennart Spitzner            <lsp@informatik.uni-kiel.de>
+Lennart Spitzner            <hexagoxel@hexagoxel.de>
+Lennart Spitzner            <hexagoxel@hexagoxel.de>               <lsp@informatik.uni-kiel.de>
+Li-yao Xia                  <lysxia@gmail.com>
 Malcolm Wallace             <Malcolm.Wallace@me.com>               Malcolm.Wallace <Malcolm.Wallace@cs.york.ac.uk>
 Mark Weber                  <marco-oweber@gmx.de>                  marco-oweber <marco-oweber@gmx.de>
 Martin Sjögren              <msjogren@gmail.com>                   md9ms <md9ms@mdstud.chalmers.se>
 Mikhail Glushenkov          <mikhail.glushenkov@gmail.com>         <c05mgv@cs.umu.se>
 Mikhail Glushenkov          <mikhail.glushenkov@gmail.com>         <mikhail@scrive.com>
 Mikhail Glushenkov          <mikhail.glushenkov@gmail.com>         <the.dead.shall.rise@gmail.com>
+Nathan Conroy               <nathanconroydev@gmail.com>
 Neil Mitchell               <ndmitchell@gmail.com>                 Neil Mitchell <unknown>
 Niklas Broberg              <niklas.broberg@gmail.com>             <d00nibro@chalmers.se>
 Niklas Broberg              <niklas.broberg@gmail.com>             <git@nand.wakku.to>
@@ -122,7 +139,18 @@
 Stephen Blackheath          <stephen.blackheath@ipwnstudios.com>   <grossly.sensitive.stephen@blacksapphire.com>
 Stephen Blackheath          <stephen.blackheath@ipwnstudios.com>   <oversensitive.pastors.stephen@blacksapphire.com>
 Stephen Blackheath          <stephen.blackheath@ipwnstudios.com>   rubbernecking.trumpet.stephen <rubbernecking.trumpet.stephen@blacksapphire.com>
+Suzumiya                    <suzumiyasmith@gmail.com>              # Goes by that name online
 Sven Panne                  <sven.panne@aedion.de>
+Tamar Christina             <tamar@zhox.com>
+Tamar Christina             <tamar@zhox.com>                       <Mistuke@users.noreply.github.com>
 Thomas M. DuBuisson         <thomas.dubuisson@gmail.com>
 Thomas M. DuBuisson         <thomas.dubuisson@gmail.com>           Thomas M. DuBuisson <tommd@galois.com>
 Thomas Schilling            <nominolo@gmail.com>                   <nominolo@googlemail.com>
+Thomas Tuegel               <ttuegel@gmail.com>
+Thomas Tuegel               <ttuegel@gmail.com>                    <ttuegel@mailbox.org>
+Thomas Tuegel               <ttuegel@gmail.com>                    <ttuegel@secure.mailbox.org>
+Veronika Romashkina         <vrom911@gmail.com>
+capsjac                     <capsjac@gmail.com>                              # Goes by that name online
+ghthrowaway7                <41365123+ghthrowaway7@users.noreply.github.com> # Goes by that name online
+quasicomputational          <quasicomputational@gmail.com>                   # Goes by that name online
+vedksah                     <31156362+vedksah@users.noreply.github.com>      # Goes by that name online
diff --git a/cabal/.projectile b/cabal/.projectile
new file mode 100644
--- /dev/null
+++ b/cabal/.projectile
diff --git a/cabal/.travis.yml b/cabal/.travis.yml
--- a/cabal/.travis.yml
+++ b/cabal/.travis.yml
@@ -4,13 +4,17 @@
 
 dist: trusty
 
-sudo: false
+# This sets the default config for each job to use full VMs.
+# The VMs have 2 cores and 8 gigs of ram. Larger VMs are also available.
+sudo: true
 
-# Remember to add release branches
-# we whitelist branches, as we don't really need to build dev-branches.
+# We whitelist branches, as we don't really need to build dev-branches.
+# Remember to add release branches, both here and to appveyor.yml.
 branches:
   only:
     - master
+    - "2.4"
+    - "2.2"
     - "2.0"
     - "1.24"
     - "1.22"
@@ -26,18 +30,16 @@
 # TAGSUFFIX to help travis/upload.sh disambiguate the matrix entry.
 matrix:
   include:
-   - env: GHCVER=8.2.1 SCRIPT=meta BUILDER=none
+   - env: GHCVER=8.4.4 SCRIPT=meta BUILDER=none
      os: linux
      sudo: required
    # These don't have -dyn/-prof whitelisted yet, so we have to
    # do the old-style installation
-   - env: GHCVER=7.4.2 SCRIPT=script CABAL_LIB_ONLY=YES TEST_OTHER_VERSIONS=YES
-     os: linux
-     sudo: required
-   - env: GHCVER=7.6.3 SCRIPT=script
+   # NB: TEST_OTHER_VERSIONS doesn't work with USE_GOLD=YES.
+   - env: GHCVER=7.6.3 SCRIPT=script CABAL_LIB_ONLY=YES TEST_OTHER_VERSIONS=YES
      os: linux
      sudo: required
-   - env: GHCVER=7.8.4 SCRIPT=script USE_GOLD=YES
+   - env: GHCVER=7.8.4 SCRIPT=script CABAL_LIB_ONLY=YES TEST_OTHER_VERSIONS=YES
      os: linux
      sudo: required
    # Ugh, we'd like to drop 'sudo: required' and use the
@@ -47,30 +49,36 @@
    - env: GHCVER=7.10.3 SCRIPT=script USE_GOLD=YES
      os: linux
      sudo: required
-   - env: GHCVER=8.0.2 SCRIPT=script DEPLOY_DOCS=YES USE_GOLD=YES TEST_SOLVER_BENCHMARKS=YES
+   - env: GHCVER=8.0.2 SCRIPT=script USE_GOLD=YES TEST_SOLVER_BENCHMARKS=YES
      sudo: required
      os: linux
+   - env: GHCVER=8.2.2 SCRIPT=script USE_GOLD=YES
+     os: linux
+     sudo: required
+   - env: GHCVER=8.4.4 SCRIPT=script USE_GOLD=YES DEPLOY_DOCS=YES
+     os: linux
+     sudo: required
+   - env: GHCVER=8.6.2 SCRIPT=script USE_GOLD=YES
+     os: linux
+     sudo: required
 
-   - env: GHCVER=8.0.2 SCRIPT=solver-debug-flags USE_GOLD=YES
+   - env: GHCVER=8.4.4 SCRIPT=solver-debug-flags USE_GOLD=YES
      sudo: required
      os: linux
-   - env: GHCVER=8.0.2 SCRIPT=script DEBUG_EXPENSIVE_ASSERTIONS=YES TAGSUFFIX="-fdebug-expensive-assertions" USE_GOLD=YES
+   - env: GHCVER=8.4.4 SCRIPT=script DEBUG_EXPENSIVE_ASSERTIONS=YES TAGSUFFIX="-fdebug-expensive-assertions" USE_GOLD=YES
      os: linux
      sudo: required
    - env: GHCVER=8.0.2 SCRIPT=bootstrap USE_GOLD=YES
      sudo: required
      os: linux
-   - env: GHCVER=8.2.2 SCRIPT=bootstrap USE_GOLD=YES
+   - env: GHCVER=8.4.4 SCRIPT=bootstrap USE_GOLD=YES
      sudo: required
      os: linux
-   - env: GHCVER=8.2.1 SCRIPT=script
-     os: linux
-     sudo: required
 
    # We axed GHC 7.6 and earlier because it's not worth the trouble to
    # make older GHC work with clang's cpp.  See
    # https://ghc.haskell.org/trac/ghc/ticket/8493
-   - env: GHCVER=7.8.4 SCRIPT=script
+   - env: GHCVER=7.8.4 SCRIPT=script CABAL_LIB_ONLY=YES
      os: osx
      # Keep this synced with travis/upload.sh
      osx_image: xcode6.4 # We need 10.10
@@ -84,15 +92,13 @@
    - env: GHCVER=8.0.2 SCRIPT=bootstrap
      os: osx
 
-   - env: GHCVER=via-stack SCRIPT=stack STACKAGE_RESOLVER=lts
+   - env: GHCVER=via-stack SCRIPT=stack STACK_CONFIG=stack.yaml
      os: linux
-     addons:
-        apt:
-            packages:
-                - libgmp-dev
 
+   # See https://github.com/haskell/cabal/pull/4667#issuecomment-321036564
+   # for why failures are allowed.
   allow_failures:
-   - env: GHCVER=via-stack SCRIPT=stack STACKAGE_RESOLVER=lts
+   - env: GHCVER=via-stack SCRIPT=stack STACK_CONFIG=stack.yaml
 
  # TODO add PARSEC_BUNDLED=YES when it's so
  # It seems pointless to run head if we're going to ignore the results.
@@ -105,8 +111,7 @@
  - export PATH=$HOME/bin:$PATH
  - export PATH=$HOME/.cabal/bin:$PATH
  - export PATH=$HOME/.local/bin:$PATH
- - export PATH=/opt/cabal/2.0/bin:$PATH
- - export PATH=/opt/happy/1.19.5/bin:$PATH
+ - export PATH=/opt/cabal/2.4/bin:$PATH
  - export PATH=/opt/alex/3.1.7/bin:$PATH
  - if [ "$USE_GOLD" = "YES" ]; then sudo update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.gold" 20; fi
  - if [ "$USE_GOLD" = "YES" ]; then sudo update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.bfd" 10; fi
@@ -145,6 +150,8 @@
  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index*
  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index*
  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/*.json
+ # avoid clashing or stale locks being cached
+ - rm -rfv $HOME/.cabal/packages/hackage.haskell.org/hackage-security-lock
 
 # Deploy Haddocks to the haskell/cabal-website repo.
 after_success:
diff --git a/cabal/AUTHORS b/cabal/AUTHORS
--- a/cabal/AUTHORS
+++ b/cabal/AUTHORS
@@ -6,10 +6,15 @@
 Adam Sandberg Eriksson   <adam@sandbergericsson.se>
 Alan Zimmerman           <alan.zimm@gmail.com>
 Albert Krewinkel         <tarleb@moltkeplatz.de>
+Alec Theriault           <alec.theriault@gmail.com>
 Alex Biehl               <alexbiehl@gmail.com>
+Alex Hirsch              <w4rh4wk@bluephoenix.at>
+Alex Lang                <me@alang.ca>
+Alex Washburn            <github@recursion.ninja>
 Alexander Kjeldaas       <alexander.kjeldaas@gmail.com>
 Alexander Vershilov      <alexander.vershilov@gmail.com>
 Alexei Pastuchov         <alexei.pastuchov@telecolumbus.de>
+Alexis Williams          <alexis@typedr.at>
 Alistair Bailey          <alistair@abayley.org>
 Alson Kemp               <alson@alsonkemp.com>
 Amir Mohammad Saied      <amirsaied@gmail.com>
@@ -50,6 +55,7 @@
 Bryan O'Sullivan         <bos@serpentine.com>
 Bryan Richter            <bryan.richter@gmail.com>
 Carter Tazio Schonwald   <carter.schonwald@gmail.com>
+Chang Yang Jiao          <jiaochangyang@gmail.com>
 Chris Allen              <cma@bitemyapp.com>
 Chris Wong               <lambda.fairy@gmail.com>
 Christiaan Baaij         <christiaan.baaij@gmail.com>
@@ -60,11 +66,13 @@
 Curtis Gagliardi         <curtis@curtis.io>
 Dan Burton               <danburton.email@gmail.com>
 Daniel Buckmaster        <dan.buckmaster@gmail.com>
+Daniel Díaz Carrete      <daniel@bogusemailserver.com>
 Daniel Gröber            <dxld@darkboxed.org>
 Daniel Trstenjak         <daniel.trstenjak@gmail.com>
 Daniel Velkov            <norcobg@gmail.com>
 Daniel Wagner            <daniel@wagner-home.com>
 Danny Navarro            <j@dannynavarro.net>
+Dave Laing               <dave.laing.80@gmail.com>
 David Feuer              <David.Feuer@gmail.com>
 David Fox                <dsf@seereason.com>
 David Himmelstrup        <lemmih@gmail.com>
@@ -76,6 +84,7 @@
 Dennis Gosnell           <cdep.illabout@gmail.com>
 Dino Morelli             <dino@ui3.info>
 Dmitry Astapov           <dastapov@gmail.com>
+Dmitry Kovanikov         <kovanikov@gmail.com>
 Dominic Steinitz         <dominic@steinitz.org>
 Don Stewart              <dons00@gmail.com>
 Doug Beardsley           <mightybyte@gmail.com>
@@ -95,7 +104,9 @@
 Eyal Lotem               <eyal.lotem@gmail.com>
 Fabián Orccón            <fabian.orccon@pucp.pe>
 Federico Mastellone      <fmaste@users.noreply.github.com>
+Felix Yan                <felixonmars@archlinux.org>
 Florian Hartwig          <florian.j.hartwig@gmail.com>
+Francesco Ariis          <fa-ml@ariis.it>
 Francesco Gazzetta       <francygazz@gmail.com>
 Franz Thoma              <franz.thoma@tngtech.com>
 Fujimura Daisuke         <me@fujimuradaisuke.com>
@@ -103,9 +114,11 @@
 Gabor Pali               <pali.gabor@gmail.com>
 Ganesh Sittampalam       <ganesh.sittampalam@credit-suisse.com>
 Geoff Nixon              <geoff-codes@users.noreply.github.com>
+George Wilson            <george@wils.online>
 Gershom Bazerman         <gershomb@gmail.com>
 Getty Ritter             <gdritter@galois.com>
 Gleb Alexeev             <gleb.alexeev@gmail.com>
+Gleb Popov               <6yearold@gmail.com>
 Gregory Collins          <greg@gregorycollins.net>
 Gwern Branwen            <gwern0@gmail.com>
 Haisheng.Wu              <freizl@gmail.com>
@@ -143,7 +156,6 @@
 John Chee                <cheecheeo@gmail.com>
 John D. Ramsdell         <ramsdell@mitre.org>
 John Dias                <dias@eecs.harvard.edu>
-John Ericson             <Ericson2314@Yahoo.com>
 John Ericson             <Ericson2314@yahoo.com>
 John Lato                <jwlato@tsurucapital.com>
 John Wiegley             <johnw@fpcomplete.com>
@@ -156,17 +168,21 @@
 Karel Gardas             <karel.gardas@centrum.cz>
 Keegan McAllister        <mcallister.keegan@gmail.com>
 Ken Bateman              <novadenizen@gmail.com>
+Ken Micklas              <kmicklas@gmail.com>
 Keshav Kini              <kkini@galois.com>
 Kido Takahiro            <shelarcy@gmail.com>
 Krasimir Angelov         <kr.angelov@gmail.com>
 Kristen Kozak            <grayjay@wordroute.com>
 Lennart Kolmodin         <kolmodin@gmail.com>
-Lennart Spitzner         <lsp@informatik.uni-kiel.de>
+Lennart Spitzner         <hexagoxel@hexagoxel.de>
+Leon Isenberg            <ljli@users.noreply.github.com>
 Leonid Onokhov           <sopvop@gmail.com>
+Li-yao Xia               <lysxia@gmail.com>
 Liyang HU                <git@liyang.hu>
 Luite Stegeman           <stegeman@gmail.com>
 Luke Iannini             <lukexi@me.com>
 M Farkas-Dyck            <strake888@gmail.com>
+Maciej Bielecki          <maciej.bielecki@skubacz.pl>
 Maciek Makowski          <maciek.makowski@gmail.com>
 Magnus Jonsson           <magnus@smartelectronix.com>
 Malcolm Wallace          <Malcolm.Wallace@me.com>
@@ -196,7 +212,9 @@
 Miëtek Bak               <mietek@bak.io>
 Mohit Agarwal            <mohit@sdf.org>
 Moritz Angermann         <moritz.angermann@gmail.com>
+Moritz Drexl             <mdrexl@fastmail.fm>
 Moritz Kiefer            <moritz.kiefer@purelyfunctional.org>
+Nathan Conroy            <nathanconroydev@gmail.com>
 Nathan Howell            <nhowell@alphaheavy.com>
 Neil Mitchell            <ndmitchell@gmail.com>
 Neil Vice                <sardonicpresence@gmail.com>
@@ -221,6 +239,8 @@
 Peter Robinson           <thaldyron@gmail.com>
 Peter Selinger           <selinger@mathstat.dal.ca>
 Peter Simons             <simons@cryp.to>
+Peter Siska              <siska.pe@gmail.com>
+Peter Trommler           <ptrommler@acm.org>
 Peter Trško              <peter.trsko@gmail.com>
 Phil Ruffwind            <rf@rufflewind.com>
 Philipp Schumann         <philipp.schumann@gmail.com>
@@ -237,6 +257,7 @@
 Robin Green              <greenrd@greenrd.org>
 Robin KAY                <komadori@gekkou.co.uk>
 Roman Cheplyaka          <roma@ro-che.info>
+Roman Kashitcyn          <rkashitsyn@rkashitsyn.zrh.corp.google.com>
 Ross Paterson            <ross@soi.city.ac.uk>
 Rudy Matela              <rudy@matela.com.br>
 Ryan Desfosses           <ryan@desfo.org>
@@ -258,10 +279,14 @@
 Spencer Janssen          <sjanssen@cse.unl.edu>
 Stephen Blackheath       <stephen.blackheath@ipwnstudios.com>
 Stuart Popejoy           <spopejoy@panix.com>
+Suzumiya                 <suzumiyasmith@gmail.com>
 Sven Panne               <sven.panne@aedion.de>
 Sönke Hahn               <shahn@joyridelabs.de>
+Takano Akio              <tak@anoak.io>
+Takenobu Tani            <takenobu.hs@gmail.com>
 Tamar Christina          <tamar@zhox.com>
 Taru Karttunen           <taruti@taruti.net>
+Taylor Fausak            <taylor.fausak@verizonwireless.com>
 Thomas Dziedzic          <gostrc@gmail.com>
 Thomas M. DuBuisson      <thomas.dubuisson@gmail.com>
 Thomas Miedema           <thomasmiedema@gmail.com>
@@ -270,14 +295,22 @@
 Tillmann Rendel          <rendel@informatik.uni-marburg.de>
 Tim Chevalier            <chevalier@alum.wellesley.edu>
 Tim Humphries            <tim.humphries@ambiata.com>
+Tim McGilchrist          <timmcgil@gmail.com>
 Tomas Vestelind          <tomas.vestelind@gmail.com>
 Toshio Ito               <debug.ito@gmail.com>
 Travis Cardwell          <travis.cardwell@extellisys.com>
 Tuncer Ayaz              <tuncer.ayaz@gmail.com>
+Vaibhav Sagar            <vaibhavsagar@gmail.com>
+Veronika Romashkina      <vrom911@gmail.com>
 Vincent Hanquez          <vincent@snarc.org>
+Vladislav Zavialov       <vlad.z.4096@gmail.com>
 Vo Minh Thu              <noteed@gmail.com>
 Wojciech Danilo          <wojtek.danilo@gmail.com>
 Yitzchak Gale            <gale@sefer.org>
 Yuras Shumovich          <shumovichy@gmail.com>
+Yuriy Syrovetskiy        <cblp@cblp.su>
 capsjac                  <capsjac@gmail.com>
+ghthrowaway7             <41365123+ghthrowaway7@users.noreply.github.com>
+quasicomputational       <quasicomputational@gmail.com>
+vedksah                  <31156362+vedksah@users.noreply.github.com>
 Łukasz Dąbek             <sznurek@gmail.com>
diff --git a/cabal/Cabal/Cabal.cabal b/cabal/Cabal/Cabal.cabal
--- a/cabal/Cabal/Cabal.cabal
+++ b/cabal/Cabal/Cabal.cabal
@@ -1,6 +1,6 @@
 name:          Cabal
-version:       2.1.0.0
-copyright:     2003-2017, Cabal Development Team (see AUTHORS file)
+version:       2.4.1.0
+copyright:     2003-2018, Cabal Development Team (see AUTHORS file)
 license:       BSD3
 license-file:  LICENSE
 author:        Cabal Development Team <cabal-devel@haskell.org>
@@ -22,34 +22,145 @@
 -- we can bootstrap.
 
 extra-source-files:
-  README.md tests/README.md changelog
+  README.md tests/README.md ChangeLog.md
   doc/bugs-and-stability.rst doc/concepts-and-development.rst
   doc/conf.py doc/config-and-install.rst doc/developing-packages.rst
   doc/images/Cabal-dark.png doc/index.rst doc/installing-packages.rst
   doc/intro.rst doc/misc.rst doc/nix-local-build-overview.rst
-  doc/nix-local-build.rst doc/README.md doc/references.inc
+  doc/nix-local-build.rst doc/file-format-changelog.rst doc/README.md
+  doc/references.inc
 
-  -- Generated with 'misc/gen-extra-source-files.sh'
+  -- Generated with 'make gen-extra-source-files'
   -- Do NOT edit this section manually; instead, run the script.
   -- BEGIN gen-extra-source-files
+  tests/ParserTests/errors/common1.cabal
+  tests/ParserTests/errors/common1.errors
+  tests/ParserTests/errors/common2.cabal
+  tests/ParserTests/errors/common2.errors
+  tests/ParserTests/errors/common3.cabal
+  tests/ParserTests/errors/common3.errors
+  tests/ParserTests/errors/forward-compat.cabal
+  tests/ParserTests/errors/forward-compat.errors
+  tests/ParserTests/errors/forward-compat2.cabal
+  tests/ParserTests/errors/forward-compat2.errors
+  tests/ParserTests/errors/forward-compat3.cabal
+  tests/ParserTests/errors/forward-compat3.errors
+  tests/ParserTests/errors/issue-5055-2.cabal
+  tests/ParserTests/errors/issue-5055-2.errors
+  tests/ParserTests/errors/issue-5055.cabal
+  tests/ParserTests/errors/issue-5055.errors
+  tests/ParserTests/errors/leading-comma.cabal
+  tests/ParserTests/errors/leading-comma.errors
+  tests/ParserTests/errors/noVersion.cabal
+  tests/ParserTests/errors/noVersion.errors
+  tests/ParserTests/errors/noVersion2.cabal
+  tests/ParserTests/errors/noVersion2.errors
+  tests/ParserTests/errors/range-ge-wild.cabal
+  tests/ParserTests/errors/range-ge-wild.errors
+  tests/ParserTests/errors/spdx-1.cabal
+  tests/ParserTests/errors/spdx-1.errors
+  tests/ParserTests/errors/spdx-2.cabal
+  tests/ParserTests/errors/spdx-2.errors
+  tests/ParserTests/errors/spdx-3.cabal
+  tests/ParserTests/errors/spdx-3.errors
+  tests/ParserTests/ipi/Includes2.cabal
+  tests/ParserTests/ipi/Includes2.expr
+  tests/ParserTests/ipi/Includes2.format
+  tests/ParserTests/ipi/internal-preprocessor-test.cabal
+  tests/ParserTests/ipi/internal-preprocessor-test.expr
+  tests/ParserTests/ipi/internal-preprocessor-test.format
+  tests/ParserTests/ipi/issue-2276-ghc-9885.cabal
+  tests/ParserTests/ipi/issue-2276-ghc-9885.expr
+  tests/ParserTests/ipi/issue-2276-ghc-9885.format
+  tests/ParserTests/ipi/transformers.cabal
+  tests/ParserTests/ipi/transformers.expr
+  tests/ParserTests/ipi/transformers.format
+  tests/ParserTests/regressions/MiniAgda.cabal
+  tests/ParserTests/regressions/MiniAgda.check
   tests/ParserTests/regressions/Octree-0.5.cabal
+  tests/ParserTests/regressions/Octree-0.5.expr
+  tests/ParserTests/regressions/Octree-0.5.format
+  tests/ParserTests/regressions/bad-glob-syntax.cabal
+  tests/ParserTests/regressions/bad-glob-syntax.check
+  tests/ParserTests/regressions/cc-options-with-optimization.cabal
+  tests/ParserTests/regressions/cc-options-with-optimization.check
+  tests/ParserTests/regressions/common.cabal
+  tests/ParserTests/regressions/common.expr
+  tests/ParserTests/regressions/common.format
+  tests/ParserTests/regressions/common2.cabal
+  tests/ParserTests/regressions/common2.expr
+  tests/ParserTests/regressions/common2.format
+  tests/ParserTests/regressions/cxx-options-with-optimization.cabal
+  tests/ParserTests/regressions/cxx-options-with-optimization.check
   tests/ParserTests/regressions/elif.cabal
+  tests/ParserTests/regressions/elif.expr
+  tests/ParserTests/regressions/elif.format
   tests/ParserTests/regressions/elif2.cabal
+  tests/ParserTests/regressions/elif2.expr
+  tests/ParserTests/regressions/elif2.format
   tests/ParserTests/regressions/encoding-0.8.cabal
+  tests/ParserTests/regressions/encoding-0.8.expr
+  tests/ParserTests/regressions/encoding-0.8.format
+  tests/ParserTests/regressions/extensions-paths-5054.cabal
+  tests/ParserTests/regressions/extensions-paths-5054.check
   tests/ParserTests/regressions/generics-sop.cabal
+  tests/ParserTests/regressions/generics-sop.expr
+  tests/ParserTests/regressions/generics-sop.format
+  tests/ParserTests/regressions/ghc-option-j.cabal
+  tests/ParserTests/regressions/ghc-option-j.check
   tests/ParserTests/regressions/haddock-api-2.18.1-check.cabal
+  tests/ParserTests/regressions/haddock-api-2.18.1-check.check
+  tests/ParserTests/regressions/issue-5055.cabal
+  tests/ParserTests/regressions/issue-5055.expr
+  tests/ParserTests/regressions/issue-5055.format
   tests/ParserTests/regressions/issue-774.cabal
+  tests/ParserTests/regressions/issue-774.check
+  tests/ParserTests/regressions/issue-774.expr
+  tests/ParserTests/regressions/issue-774.format
+  tests/ParserTests/regressions/leading-comma.cabal
+  tests/ParserTests/regressions/leading-comma.expr
+  tests/ParserTests/regressions/leading-comma.format
+  tests/ParserTests/regressions/noVersion.cabal
+  tests/ParserTests/regressions/noVersion.expr
+  tests/ParserTests/regressions/noVersion.format
   tests/ParserTests/regressions/nothing-unicode.cabal
+  tests/ParserTests/regressions/nothing-unicode.check
+  tests/ParserTests/regressions/nothing-unicode.expr
+  tests/ParserTests/regressions/nothing-unicode.format
+  tests/ParserTests/regressions/pre-1.6-glob.cabal
+  tests/ParserTests/regressions/pre-1.6-glob.check
+  tests/ParserTests/regressions/pre-2.4-globstar.cabal
+  tests/ParserTests/regressions/pre-2.4-globstar.check
   tests/ParserTests/regressions/shake.cabal
+  tests/ParserTests/regressions/shake.expr
+  tests/ParserTests/regressions/shake.format
+  tests/ParserTests/regressions/spdx-1.cabal
+  tests/ParserTests/regressions/spdx-1.expr
+  tests/ParserTests/regressions/spdx-1.format
+  tests/ParserTests/regressions/spdx-2.cabal
+  tests/ParserTests/regressions/spdx-2.expr
+  tests/ParserTests/regressions/spdx-2.format
+  tests/ParserTests/regressions/spdx-3.cabal
+  tests/ParserTests/regressions/spdx-3.expr
+  tests/ParserTests/regressions/spdx-3.format
+  tests/ParserTests/regressions/th-lift-instances.cabal
+  tests/ParserTests/regressions/th-lift-instances.expr
+  tests/ParserTests/regressions/th-lift-instances.format
+  tests/ParserTests/regressions/wl-pprint-indef.cabal
+  tests/ParserTests/regressions/wl-pprint-indef.expr
+  tests/ParserTests/regressions/wl-pprint-indef.format
   tests/ParserTests/warnings/bom.cabal
   tests/ParserTests/warnings/bool.cabal
   tests/ParserTests/warnings/deprecatedfield.cabal
+  tests/ParserTests/warnings/doubledash.cabal
   tests/ParserTests/warnings/extratestmodule.cabal
   tests/ParserTests/warnings/gluedop.cabal
+  tests/ParserTests/warnings/multiplesingular.cabal
   tests/ParserTests/warnings/nbsp.cabal
   tests/ParserTests/warnings/newsyntax.cabal
   tests/ParserTests/warnings/oldsyntax.cabal
   tests/ParserTests/warnings/subsection.cabal
+  tests/ParserTests/warnings/tab.cabal
   tests/ParserTests/warnings/trailingfield.cabal
   tests/ParserTests/warnings/unknownfield.cabal
   tests/ParserTests/warnings/unknownsection.cabal
@@ -69,50 +180,28 @@
 flag bundled-binary-generic
   default: False
 
-flag old-directory
-  description:  Use directory < 1.2 and old-time
-  default:      False
-
-flag parsec-struct-diff
-  description:  Use StructDiff in parsec tests. Affects only parsec tests.
-  default:      False
-  manual:       True
-
 library
   build-depends:
-    array      >= 0.1 && < 0.6,
-    base       >= 4.5 && < 5,
-    bytestring >= 0.9 && < 1,
-    containers >= 0.4 && < 0.6,
-    deepseq    >= 1.3 && < 1.5,
-    filepath   >= 1.3 && < 1.5,
-    pretty     >= 1.1 && < 1.2,
-    process    >= 1.1.0.1 && < 1.7,
-    time       >= 1.4 && < 1.9
-
-  if flag(old-directory)
-    build-depends: directory >= 1.1 && < 1.2, old-time >= 1 && < 1.2,
-                   process   >= 1.0.1.1  && < 1.1.0.2
-  else
-    build-depends: directory >= 1.2 && < 1.4,
-                   process   >= 1.1.0.2  && < 1.7
+    array      >= 0.4.0.1  && < 0.6,
+    base       >= 4.6      && < 5,
+    bytestring >= 0.10.0.0 && < 0.11,
+    containers >= 0.5.0.0  && < 0.7,
+    deepseq    >= 1.3.0.1  && < 1.5,
+    directory  >= 1.2      && < 1.4,
+    filepath   >= 1.3.0.1  && < 1.5,
+    pretty     >= 1.1.1    && < 1.2,
+    process    >= 1.1.0.2  && < 1.7,
+    time       >= 1.4.0.1  && < 1.10
 
   if flag(bundled-binary-generic)
-    build-depends: binary >= 0.5 && < 0.7
+    build-depends: binary >= 0.5.1.1 && < 0.7
   else
     build-depends: binary >= 0.7 && < 0.9
 
-  -- Needed for GHC.Generics before GHC 7.6
-  if impl(ghc < 7.6)
-    build-depends: ghc-prim >= 0.2 && < 0.3
-
-  if !os(windows)
-    build-depends:
-      unix >= 2.5 && < 2.8
-
   if os(windows)
-    build-depends:
-      Win32 >= 2.2 && < 2.7
+    build-depends: Win32 >= 2.3.0.0 && < 2.9
+  else
+    build-depends: unix  >= 2.6.0.0 && < 2.8
 
   ghc-options: -Wall -fno-ignore-asserts -fwarn-tabs
   if impl(ghc >= 8.0)
@@ -130,15 +219,16 @@
     Distribution.Backpack.ModSubst
     Distribution.Backpack.ModuleShape
     Distribution.Backpack.PreModuleShape
+    Distribution.CabalSpecVersion
     Distribution.Utils.IOData
     Distribution.Utils.LogProgress
     Distribution.Utils.MapAccum
     Distribution.Compat.CreatePipe
+    Distribution.Compat.Directory
     Distribution.Compat.Environment
     Distribution.Compat.Exception
     Distribution.Compat.Graph
     Distribution.Compat.Internal.TempFile
-    Distribution.Compat.Map.Strict
     Distribution.Compat.Newtype
     Distribution.Compat.Prelude.Internal
     Distribution.Compat.ReadP
@@ -148,6 +238,10 @@
     Distribution.Compat.DList
     Distribution.Compiler
     Distribution.InstalledPackageInfo
+    Distribution.Types.AbiDependency
+    Distribution.Types.ExposedModule
+    Distribution.Types.InstalledPackageInfo
+    Distribution.Types.InstalledPackageInfo.FieldGrammar
     Distribution.License
     Distribution.Make
     Distribution.ModuleName
@@ -155,7 +249,6 @@
     Distribution.PackageDescription
     Distribution.PackageDescription.Check
     Distribution.PackageDescription.Configuration
-    Distribution.PackageDescription.Parse
     Distribution.PackageDescription.PrettyPrint
     Distribution.PackageDescription.Utils
     Distribution.ParseUtils
@@ -173,16 +266,16 @@
     Distribution.Simple.Command
     Distribution.Simple.Compiler
     Distribution.Simple.Configure
+    Distribution.Simple.Flag
     Distribution.Simple.GHC
     Distribution.Simple.GHCJS
     Distribution.Simple.Haddock
     Distribution.Simple.Doctest
+    Distribution.Simple.Glob
     Distribution.Simple.HaskellSuite
     Distribution.Simple.Hpc
     Distribution.Simple.Install
     Distribution.Simple.InstallDirs
-    Distribution.Simple.JHC
-    Distribution.Simple.LHC
     Distribution.Simple.LocalBuildInfo
     Distribution.Simple.PackageIndex
     Distribution.Simple.PreProcess
@@ -212,6 +305,13 @@
     Distribution.Simple.UHC
     Distribution.Simple.UserHooks
     Distribution.Simple.Utils
+    Distribution.SPDX
+    Distribution.SPDX.License
+    Distribution.SPDX.LicenseId
+    Distribution.SPDX.LicenseExceptionId
+    Distribution.SPDX.LicenseExpression
+    Distribution.SPDX.LicenseListVersion
+    Distribution.SPDX.LicenseReference
     Distribution.System
     Distribution.TestSuite
     Distribution.Text
@@ -276,15 +376,20 @@
     Language.Haskell.Extension
     Distribution.Compat.Binary
 
-  -- Parsec parser relatedmodules
+  -- Parsec parser-related modules
   build-depends:
-    transformers,
-    mtl >= 2.1 && <2.3,
-    parsec >= 3.1.9 && <3.2
+    -- transformers-0.4.0.0 doesn't have record syntax e.g. for Identity
+    -- See also https://github.com/ekmett/transformers-compat/issues/35
+    transformers (>= 0.3      && < 0.4) || (>=0.4.1.0 && <0.6),
+    mtl           >= 2.1      && < 2.3,
+    text          >= 1.2.3.0  && < 1.3,
+    parsec        >= 3.1.13.0 && < 3.2
   exposed-modules:
-    Distribution.Compat.Parsec
+    Distribution.Compat.Parsing
+    Distribution.Compat.CharParsing
     Distribution.FieldGrammar
     Distribution.FieldGrammar.Class
+    Distribution.FieldGrammar.FieldDescrs
     Distribution.FieldGrammar.Parsec
     Distribution.FieldGrammar.Pretty
     Distribution.PackageDescription.FieldGrammar
@@ -294,6 +399,7 @@
     Distribution.Parsec.Common
     Distribution.Parsec.ConfVar
     Distribution.Parsec.Field
+    Distribution.Parsec.FieldLineStream
     Distribution.Parsec.Lexer
     Distribution.Parsec.LexerMonad
     Distribution.Parsec.Newtypes
@@ -309,6 +415,7 @@
     Distribution.Types.Executable.Lens
     Distribution.Types.ForeignLib.Lens
     Distribution.Types.GenericPackageDescription.Lens
+    Distribution.Types.InstalledPackageInfo.Lens
     Distribution.Types.Library.Lens
     Distribution.Types.PackageDescription.Lens
     Distribution.Types.PackageId.Lens
@@ -333,9 +440,8 @@
     Distribution.GetOpt
     Distribution.Lex
     Distribution.Utils.String
+    Distribution.Simple.GHC.EnvironmentParser
     Distribution.Simple.GHC.Internal
-    Distribution.Simple.GHC.IPI642
-    Distribution.Simple.GHC.IPIConvert
     Distribution.Simple.GHC.ImplInfo
     Paths_Cabal
 
@@ -386,9 +492,12 @@
     UnitTests.Distribution.Compat.ReadP
     UnitTests.Distribution.Compat.Time
     UnitTests.Distribution.Compat.Graph
+    UnitTests.Distribution.Simple.Glob
     UnitTests.Distribution.Simple.Program.Internal
     UnitTests.Distribution.Simple.Utils
+    UnitTests.Distribution.SPDX
     UnitTests.Distribution.System
+    UnitTests.Distribution.Types.GenericPackageDescription
     UnitTests.Distribution.Utils.Generic
     UnitTests.Distribution.Utils.NubList
     UnitTests.Distribution.Utils.ShortText
@@ -402,13 +511,14 @@
     directory,
     filepath,
     integer-logarithms >= 1.0.2 && <1.1,
-    tasty,
+    tasty >= 1.1.0.3 && < 1.2,
     tasty-hunit,
     tasty-quickcheck,
     tagged,
+    temporary,
     text,
     pretty,
-    QuickCheck >= 2.7 && < 2.11,
+    QuickCheck >= 2.11.3 && < 2.12,
     Cabal
   ghc-options: -Wall
   default-language: Haskell2010
@@ -417,12 +527,12 @@
   type: exitcode-stdio-1.0
   hs-source-dirs: tests
   main-is: ParserTests.hs
-  build-depends: containers
   build-depends:
     base,
+    base-compat >=0.10.4 && <0.11,
     bytestring,
     filepath,
-    tasty,
+    tasty >= 1.1.0.3 && < 1.2,
     tasty-hunit,
     tasty-quickcheck,
     tasty-golden >=2.3.1.1 && <2.4,
@@ -431,6 +541,15 @@
   ghc-options: -Wall
   default-language: Haskell2010
 
+  if impl(ghc >= 7.8)
+    build-depends:
+      tree-diff      >= 0.0.1 && <0.1
+    other-modules:
+      Instances.TreeDiff
+      Instances.TreeDiff.Language
+      Instances.TreeDiff.SPDX
+      Instances.TreeDiff.Version
+
 test-suite check-tests
   type: exitcode-stdio-1.0
   hs-source-dirs: tests
@@ -439,44 +558,62 @@
     base,
     bytestring,
     filepath,
-    tasty,
+    tasty >= 1.1.0.3 && < 1.2,
     tasty-golden >=2.3.1.1 && <2.4,
     Diff >=0.3.4 && <0.4,
     Cabal
   ghc-options: -Wall
   default-language: Haskell2010
 
-test-suite parser-hackage-tests
+test-suite custom-setup-tests
   type: exitcode-stdio-1.0
-  main-is: ParserHackageTests.hs
+  hs-source-dirs: tests/custom-setup
+  main-is: CustomSetupTests.hs
+  other-modules:
+    CabalDoctestSetup
+    IdrisSetup
+  build-depends:
+    Cabal,
+    base,
+    directory,
+    filepath,
+    process
+  default-language: Haskell2010
 
+test-suite hackage-tests
+  type: exitcode-stdio-1.0
+  main-is: HackageTests.hs
+
   -- TODO: need to get 01-index.tar on appveyor
   if os(windows)
     buildable: False
 
   hs-source-dirs: tests
+
   build-depends:
     base,
-    base-orphans == 0.6.*,
-    base-compat >=0.9.3 && <0.10,
-    containers,
-    tar >=0.5 && <0.6,
+    Cabal,
     bytestring,
+    deepseq,
+    containers,
     directory,
-    filepath,
-    Cabal
+    filepath
 
-  if flag(parsec-struct-diff)
+  build-depends:
+    base-compat          >=0.10.4   && <0.11,
+    base-orphans         >=0.6      && <0.9,
+    optparse-applicative >=0.13.2.0 && <0.15,
+    tar                  >=0.5.0.3  && <0.6
+
+  if impl(ghc >= 7.8)
     build-depends:
-      generics-sop >= 0.3.1.0 && <0.4,
-      these >=0.7.1 && <0.8,
-      singleton-bool >=0.1.1.0 && <0.2,
-      keys
+      tree-diff      >= 0.0.1 && <0.1
     other-modules:
-      DiffInstances
-      StructDiff
-    cpp-options: -DHAS_STRUCT_DIFF
+      Instances.TreeDiff
+      Instances.TreeDiff.Language
+      Instances.TreeDiff.SPDX
+      Instances.TreeDiff.Version
 
-  ghc-options: -Wall -rtsopts
+  ghc-options: -Wall -rtsopts -threaded
   default-extensions: CPP
   default-language: Haskell2010
diff --git a/cabal/Cabal/ChangeLog.md b/cabal/Cabal/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/ChangeLog.md
@@ -0,0 +1,888 @@
+### 2.4.1.0 [Mikhail Glushenkov](mailto:mikhail.glushenkov@gmail.com) November 2018
+
+  * Warnings in autogenerated files are now silenced
+    ([#5678](https://github.com/haskell/cabal/pulls/5678)).
+  * Improved recompilation avoidance, especially when using GHC 8.6
+    ([#5589](https://github.com/haskell/cabal/pulls/5589)).
+  * Do not error on empty packagedbs in `getInstalledPackages`
+    ([#5516](https://github.com/haskell/cabal/issues/5516)).
+
+
+### 2.4.0.1 [Mikhail Glushenkov](mailto:mikhail.glushenkov@gmail.com) September 2018
+
+  * Allow arguments to be passed to `Setup.hs haddock` for `build-type:configure`
+    ([#5503](https://github.com/haskell/cabal/issues/5503)).
+
+# 2.4.0.0 [Mikhail Glushenkov](mailto:mikhail.glushenkov@gmail.com) September 2018
+
+  * Due to [#5119](https://github.com/haskell/cabal/issues/5119), the
+    `cabal check` warning for bounds on internal libraries has been
+    disabled.
+  * `Distribution.Simple.Haddock` now checks to ensure that it
+    does not erroneously call Haddock with no target modules.
+    ([#5232](https://github.com/haskell/cabal/issues/5232),
+    [#5459](https://github.com/haskell/cabal/issues/5459)).
+  * Add `getting` (less general than `to`) Lens combinator,
+    `non`) and an optics to access the modules in a component
+    of a `PackageDescription` by the `ComponentName`:
+    `componentBuildInfo` and `componentModules`
+  * Add `readGhcEnvironmentFile` to parse GHC environment files.
+  * Drop support for GHC 7.4, since it is out of our support window
+    (and has been for over a year!)
+  * Deprecate `preSDist`, `sDistHook`, and `postSDist` in service of
+    `new-sdist`, since they violate key invariants of the new-build
+    ecosystem. Use `autogen-modules` and `build-tool-depends` instead.
+    ([#5389](https://github.com/haskell/cabal/pull/5389)).
+  * Added `--repl-options` flag to `Setup repl` used to pass flags to the
+    underlying repl without affecting the `LocalBuildInfo`
+    ([#4247](https://github.com/haskell/cabal/issues/4247),
+    [#5287](https://github.com/haskell/cabal/pull/5287))
+  * `KnownExtension`: added new extensions `BlockArguments`
+    ([#5101](https://github.com/haskell/cabal/issues/5101)),
+    `NumericUnderscores`
+    ([#5130]((https://github.com/haskell/cabal/issues/5130)),
+    `QuantifiedConstraints`, and `StarIsType`.
+  * `buildDepends` is removed from `PackageDescription`. It had long been
+    uselessly hanging about as top-level build-depends already got put
+    into per-component condition trees anyway. Now it's finally been put
+    out of its misery
+    ([#4383](https://github.com/haskell/cabal/issues/4283)).
+  * Added `Eta` to `CompilerFlavor` and to known compilers.
+  * `cabal haddock` now generates per-component documentation
+    ([#5226](https://github.com/haskell/cabal/issues/5226)).
+  * Wildcard improvements:
+    * Allow `**` wildcards in `data-files`, `extra-source-files` and
+      `extra-doc-files`. These allow a limited form of recursive
+      matching, and require `cabal-version: 2.4`.
+      ([#5284](https://github.com/haskell/cabal/issues/5284),
+      [#3178](https://github.com/haskell/cabal/issues/3178), et al.)
+    * With `cabal-version: 2.4`, when matching a wildcard, the
+      requirement for the full extension to match exactly has been
+      loosened. Instead, if the wildcard's extension is a suffix of the
+      file's extension, the file will be selected. For example,
+      previously `foo.en.html` would not match `*.html`, and
+      `foo.solaris.tar.gz` would not match `*.tar.gz`, but now both
+      do. This may lead to files unexpectedly being included by `sdist`;
+      please audit your package descriptions if you rely on this
+      behaviour to keep sensitive data out of distributed packages
+      ([#5372](https://github.com/haskell/cabal/pull/5372),
+      [#784](https://github.com/haskell/cabal/issues/784),
+      [#5057](https://github.com/haskell/cabal/issues/5057)).
+    * Wildcard syntax errors (misplaced `*`, etc), wildcards that
+      refer to missing directoies, and wildcards that do not match
+      anything are now all detected by `cabal check`.
+    * Wildcard ('globbing') functions have been moved from
+      `Distribution.Simple.Utils` to `Distribution.Simple.Glob` and
+      have been refactored.
+  * Fixed `cxx-options` and `cxx-sources` buildinfo fields for
+    separate compilation of C++ source files to correctly build and link
+    non-library components ([#5309](https://github.com/haskell/cabal/issues/5309)).
+  * Reduced warnings generated by hsc2hs and c2hs when `cxx-options` field
+    is present in a component.
+  * `cabal check` now warns if `-j` is used in `ghc-options` in a Cabal
+    file. ([#5277](https://github.com/haskell/cabal/issues/5277))
+  * `install-includes` now works as expected with foreign libraries
+    ([#5302](https://github.com/haskell/cabal/issues/5299)).
+  * Removed support for JHC.
+  * Options listed in `ghc-options`, `cc-options`, `ld-options`,
+    `cxx-options`, `cpp-options` are not deduplicated anymore
+    ([#4449](https://github.com/haskell/cabal/issues/4449)).
+  * Deprecated `cabal hscolour` in favour of `cabal haddock --hyperlink-source` ([#5236](https://github.com/haskell/cabal/pull/5236/)).
+  * Recognize `powerpc64le` as architecture PPC64.
+  * Cabal now deduplicates more `-I` and `-L` and flags to avoid `E2BIG`
+    ([#5356](https://github.com/haskell/cabal/issues/5356)).
+  * With `build-type: configure`, avoid using backslashes to delimit
+    path components on Windows and warn about other unsafe characters
+    in the path to the source directory on all platforms
+    ([#5386](https://github.com/haskell/cabal/issues/5386)).
+  * `Distribution.PackageDescription.Check.checkPackageFiles` now
+    accepts a `Verbosity` argument.
+  * Added a parameter to
+    `Distribution.Backpack.ConfiguredComponent.toConfiguredComponent` in order to fix
+    [#5409](https://github.com/haskell/cabal/issues/5409).
+  * Partially silence `abi-depends` warnings
+    ([#5465](https://github.com/haskell/cabal/issues/5465)).
+  * Foreign libraries are now linked against the threaded RTS when the
+    'ghc-options: -threaded' flag is used
+    ([#5431](https://github.com/haskell/cabal/pull/5431)).
+  * Pass command line arguments to `hsc2hs` using response files when possible
+    ([#3122](https://github.com/haskell/cabal/issues/3122)).
+
+----
+
+## 2.2.0.1 [Mikhail Glushenkov](mailto:mikhail.glushenkov@gmail.com) March 2018
+
+  * Fix `checkPackageFiles` for relative directories ([#5206](https://github.com/haskell/cabal/issues/5206))
+
+
+# 2.2.0.0 [Mikhail Glushenkov](mailto:mikhail.glushenkov@gmail.com) March 2018
+
+  * The 2.2 migration guide gives advice on adapting Custom setup
+    scripts to backwards-incompatible changes in this release:
+    https://github.com/haskell/cabal/wiki/2.2-migration-guide.
+  * New Parsec-based parser for `.cabal` files is now the
+    default. This brings memory consumption and speed improvements, as
+    well as making new syntax extensions easier to implement.
+  * Support for common stanzas (#4751).
+  * Added elif-conditionals to `.cabal` syntax (#4750).
+  * The package license information can now be specified using the
+    SPDX syntax. This requires setting `cabal-version` to 2.2+ (#2547,
+    #5050).
+  * Support for GHC's numeric -g debug levels (#4673).
+  * Compilation with section splitting is now supported via the
+    `--enable-split-sections` flag (#4819)
+  * Fields with mandatory commas (e.g. build-depends) may now have a
+    leading or a trailing comma (either one, not both) (#4953)
+  * Added `virtual-modules` field, to allow modules that are not built
+    but registered (#4875).
+  * Use better defaulting for `build-type`; rename `PackageDescription`'s
+    `buildType` field to `buildTypeRaw` and introduce new `buildType`
+    function (#4958)
+  * `D.T.PackageDescription.allBuildInfo` now returns all build infos, not
+    only for buildable components (#5087).
+  * Removed `UnknownBuildType` constructor from `BuildType` (#5003).
+  * Added `HexFloatLiterals` to `KnownExtension`.
+  * Cabal will no longer try to build an empty set of `inputModules`
+    (#4890).
+  * `copyComponent` and `installIncludeFiles` will now look for
+    include headers in the build directory (`dist/build/...` by
+    default) as well (#4866).
+  * Added `cxx-options` and `cxx-sources` buildinfo fields for
+    separate compilation of C++ source files (#3700).
+  * Removed unused `--allow-newer`/`--allow-older` support from
+    `Setup configure` (#4527).
+  * Changed `FlagAssignment` to be an opaque `newtype` (#4849).
+  * Changed `rawSystemStdInOut` to use proper type to represent
+    binary and textual data; new `Distribution.Utils.IOData` module;
+    removed obsolete `startsWithBOM`, `fileHasBOM`, `fromUTF8`,
+    and `toUTF8` functions; add new `toUTF8BS`/`toUTF8LBS`
+    encoding functions. (#4666)
+  * Added a `cabal check` warning when the `.cabal` file name does
+    not match package name (#4592).
+  * The `ar` program now receives its arguments via a response file
+    (`@file`).  Old behaviour can be restored with
+    `--disable-response-files` argument to `configure` or
+    `install` (#4596).
+  * Added `.Lens` modules, with optics for package description data
+    types (#4701).
+  * Support for building with Win32 version 2.6 (#4835).
+  * Change `compilerExtensions` and `ghcOptExtensionMap` to contain
+    `Maybe Flag`s, since a supported extention can lack a flag (#4443).
+  * Pretty-printing of `.cabal` files is slightly different due to
+    parser changes. For an example, see
+    https://mail.haskell.org/pipermail/cabal-devel/2017-December/010414.html.
+  * `--hyperlink-source` now uses Haddock's hyperlinker backend when
+    Haddock is new enough, falling back to HsColour otherwise.
+  * `D.S.defaultHookedPackageDesc` has been deprecated in favour of
+    `D.S.findHookedPackageDesc` (#4874).
+  * `D.S.getHookedBuildInfo` now takes an additional parameter
+    specifying the build directory path (#4874).
+  * Emit warning when encountering unknown GHC versions (#415).
+
+### 2.0.1.1 [Mikhail Glushenkov](mailto:mikhail.glushenkov@gmail.com) December 2017
+
+  * Don't pass `other-modules` to stub executable for detailed-0.9
+  (#4918).
+  * Hpc: Use relative .mix search paths (#4917).
+
+## 2.0.1.0 [Mikhail Glushenkov](mailto:mikhail.glushenkov@gmail.com) November 2017
+
+  * Support for GHC's numeric -g debug levels (#4673).
+  * Added a new `Distribution.Verbosity.modifyVerbosity` combinator
+    (#4724).
+  * Added a new `cabal check` warning about unused, undeclared or
+    non-Unicode flags.  Also, it warns about leading dash, which is
+    unusable but accepted if it's unused in conditionals. (#4687)
+  * Modify `allBuildInfo` to include foreign library info (#4763).
+  * Documentation fixes.
+
+### 2.0.0.2 [Mikhail Glushenkov](mailto:mikhail.glushenkov@gmail.com) July 2017
+
+  * See http://coldwa.st/e/blog/2017-09-09-Cabal-2-0.html
+    for more detailed release notes.
+  * The 2.0 migration guide gives advice on adapting Custom setup
+    scripts to backwards-incompatible changes in this release:
+    https://github.com/haskell/cabal/wiki/2.0-migration-guide
+  * Add CURRENT_PACKAGE_VERSION to cabal_macros.h (#4319)
+  * Dropped support for versions of GHC earlier than 6.12 (#3111).
+  * GHC compatibility window for the Cabal library has been extended
+    to five years (#3838).
+  * Convenience/internal libraries are now supported (#269).
+    An internal library is declared using the stanza `library
+    'libname'`.  Packages which use internal libraries can
+    result in multiple registrations; thus `--gen-pkg-config`
+    can now output a directory of registration scripts rather than
+    a single file.
+  * Backwards incompatible change to preprocessor interface:
+    the function in `PPSuffixHandler` now takes an additional
+    `ComponentLocalBuildInfo` specifying the build information
+    of the component being preprocessed.
+  * Backwards incompatible change to `cabal_macros.h` (#1893): we now
+    generate a macro file for each component which contains only
+    information about the direct dependencies of that component.
+    Consequently, `dist/build/autogen/cabal_macros.h` contains
+    only the macros for the library, and is not generated if a
+    package has no library; to find the macros for an executable
+    named `foobar`, look in `dist/build/foobar/autogen/cabal_macros.h`.
+    Similarly, if you used `autogenModulesDir` you should now
+    use `autogenComponentModulesDir`, which now requires a
+    `ComponentLocalBuildInfo` argument as well in order to
+    disambiguate which component the autogenerated files are for.
+  * Backwards incompatible change to `Component`: `TestSuite` and
+    `Benchmark` no longer have `testEnabled` and
+    `benchmarkEnabled`.  If you used
+    `enabledTests` or `enabledBenchmarks`, please instead use
+    `enabledTestLBIs` and `enabledBenchLBIs`
+    (you will need a `LocalBuildInfo` for these functions.)
+    Additionally, the semantics of `withTest` and `withBench`
+    have changed: they now iterate over all buildable
+    such components, regardless of whether or not they have
+    been enabled; if you only want enabled components,
+    use `withTestLBI` and `withBenchLBI`.
+    `finalizePackageDescription` is deprecated:
+    its replacement `finalizePD` now takes an extra argument
+    `ComponentRequestedSpec` which specifies what components
+    are to be enabled: use this instead of modifying the
+    `Component` in a `GenericPackageDescription`.  (As
+    it's not possible now, `finalizePackageDescription`
+    will assume tests/benchmarks are disabled.)
+    If you only need to test if a component is buildable
+    (i.e., it is marked buildable in the Cabal file)
+    use the new function `componentBuildable`.
+  * Backwards incompatible change to `PackageName` (#3896):
+    `PackageName` is now opaque; conversion to/from `String` now works
+    via (old) `unPackageName` and (new) `mkPackageName` functions.
+  * Backwards incompatible change to `ComponentId` (#3917):
+    `ComponentId` is now opaque; conversion to/from `String` now works
+    via `unComponentId` and `mkComponentId` functions.
+  * Backwards incompatible change to `AbiHash` (#3921):
+    `AbiHash` is now opaque; conversion to/from `String` now works
+    via `unAbiHash` and `mkAbiHash` functions.
+  * Backwards incompatible change to `FlagName` (#4062):
+    `FlagName` is now opaque; conversion to/from `String` now works
+    via `unFlagName` and `mkFlagName` functions.
+  * Backwards incompatible change to `Version` (#3905):
+    Version is now opaque; conversion to/from `[Int]` now works
+    via `versionNumbers` and `mkVersion` functions.
+  * Add support for `--allow-older` (dual to `--allow-newer`) (#3466)
+  * Improved an error message for process output decoding errors
+  (#3408).
+  * `getComponentLocalBuildInfo`, `withComponentsInBuildOrder`
+    and `componentsInBuildOrder` are deprecated in favor of a
+    new interface in `Distribution.Types.LocalBuildInfo`.
+  * New `autogen-modules` field. Modules that are built automatically at
+    setup, like Paths_PACKAGENAME or others created with a build-type
+    custom, appear on `other-modules` for the Library, Executable,
+    Test-Suite or Benchmark stanzas or also on `exposed-modules` for
+    libraries but are not really on the package when distributed. This
+    makes commands like sdist fail because the file is not found, so with
+    this new field modules that appear there are treated the same way as
+    Paths_PACKAGENAME was and there is no need to create complex build
+    hooks. Just add the module names on `other-modules` and
+    `exposed-modules` as always and on the new `autogen-modules` besides.
+  (#3656).
+  * New `./Setup configure` flag `--cabal-file`, allowing multiple
+  `.cabal` files in a single directory (#3553). Primarily intended for
+  internal use.
+  * Macros in `cabal_macros.h` are now ifndef'd, so that they
+  don't cause an error if the macro is already defined. (#3041)
+  * `./Setup configure` now accepts a single argument specifying
+    the component to be configured.  The semantics of this mode
+    of operation are described in
+    <https://github.com/ghc-proposals/ghc-proposals/pull/4>
+  * Internal `build-tools` dependencies are now added to PATH
+    upon invocation of GHC, so that they can be conveniently
+    used via `-pgmF`. (#1541)
+  * Add support for new caret-style version range operator `^>=` (#3705)
+  * Verbosity `-v` now takes an extended format which allows
+    specifying exactly what you want to be logged.  The format is
+    `[silent|normal|verbose|debug] flags`, where flags is a space
+    separated list of flags. At the moment, only the flags
+    +callsite and +callstack are supported; these report the
+    call site/stack of a logging output respectively (these
+    are only supported if Cabal is built with GHC 8.0/7.10.2
+    or greater, respectively).
+  * New `Distribution.Utils.ShortText.ShortText` type for representing
+    short text strings compactly (#3898)
+  * Cabal no longer supports using a version bound to disambiguate
+    between an internal and external package (#4020).  This should
+    not affect many people, as this mode of use already did not
+    work with the dependency solver.
+  * Support for "foreign libraries" (#2540), which are Haskell
+    libraries intended to be used by foreign languages like C.
+    Foreign libraries only work with GHC 7.8 and later.
+  * Added a technical preview version of integrated doctest support (#4480).
+  * Added a new `scope` field to the executable stanza. Executables
+    with `scope: private` get installed into
+    $libexecdir/$libexecsubdir. Additionally $libexecdir now has a
+    subdir structure similar to $lib(sub)dir to allow installing
+    private executables of different packages and package versions
+    alongside one another.  Private executables are those that are
+    expected to be run by other programs rather than users. (#3461)
+
+## 1.24.2.0 [Mikhail Glushenkov](mailto:mikhail.glushenkov@gmail.com) December 2016
+  * Fixed a bug in the handling of non-buildable components (#4094).
+  * Reverted a PVP-noncompliant API change in 1.24.1.0 (#4123).
+  * Bumped the directory upper bound to < 1.4 (#4158).
+
+## 1.24.1.0 [Ryan Thomas](mailto:ryan@ryant.org) October 2016
+  * API addition: `differenceVersionRanges` (#3519).
+  * Fixed reexported-modules display mangling (#3928).
+  * Check that the correct cabal-version is specified when the
+  extra-doc-files field is present (#3825).
+  * Fixed an incorrect invocation of GetShortPathName that was
+  causing build failures on Windows (#3649).
+  * Linker flags are now set correctly on GHC >= 7.8 (#3443).
+
+# 1.24.0.0 [Ryan Thomas](mailto:ryan@ryant.org) March 2016
+  * Support GHC 8.
+  * Deal with extra C sources from preprocessors (#238).
+  * Include cabal_macros.h when running c2hs (#2600).
+  * Don't recompile C sources unless needed (#2601).
+  * Read `builddir` option from `CABAL_BUILDDIR` environment variable.
+  * Add `--profiling-detail=$level` flag with a default for libraries
+    and executables of `exported-functions` and `toplevel-functions`
+    respectively (GHC's `-fprof-auto-{exported,top}` flags) (#193).
+  * New `custom-setup` stanza to specify setup deps. Setup is also built
+    with the cabal_macros.h style macros, for conditional compilation.
+  * Support Haddock response files (#2746).
+  * Fixed a bug in the Text instance for Platform (#2862).
+  * New `setup haddock` option: `--for-hackage` (#2852).
+  * New `--show-detail=direct`; like streaming, but allows the test
+    program to detect that is connected to a terminal, and works
+    reliable with a non-threaded runtime (#2911, and serves as a
+    work-around for #2398)
+  * Library support for multi-instance package DBs (#2948).
+  * Improved the `./Setup configure` solver (#3082, #3076).
+  * The `--allow-newer` option can be now used with `./Setup
+  configure` (#3163).
+  * Added a way to specify extra locations to find OS X frameworks
+  in (`extra-framework-dirs`). Can be used both in `.cabal` files and
+  as an argument to `./Setup configure` (#3158).
+  * Macros `VERSION_$pkgname` and `MIN_VERSION_$pkgname` are now
+  also generated for the current package. (#3235).
+  * Backpack is supported!  Two new fields supported in Cabal
+  files: signatures and mixins; and a new flag
+  to setup scripts, `--instantiate-with`.  See
+  https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst
+  for more details.
+
+----
+
+## 1.22.8.0 [Ryan Thomas](mailto:ryan@ryant.org) March 2016
+  * Distribution.Simple.Setup: remove job cap. Fixes #3191.
+  * Check all object file suffixes for recompilation. Fixes #3128.
+  * Move source files under `src/`. Fixes #3003.
+
+## 1.22.7.0 [Ryan Thomas](mailto:ryan@ryant.org) January 2016
+  * Backport #3012 to the 1.22 branch
+  * Cabal.cabal: change build-type to Simple
+  * Add foldl' import
+  * The Cabal part for fully gcc-like response files
+
+## 1.22.6.0 [Ryan Thomas](mailto:ryan@ryant.org) December 2015
+  * Relax upper bound to allow upcoming binary-0.8
+
+## 1.22.5.0 [Ryan Thomas](mailto:ryan@ryant.org) November 2015
+  * Don't recompile C sources unless needed (#2601). (Luke Iannini)
+  * Support Haddock response files.
+  * Add frameworks when linking a dynamic library.
+
+## 1.22.4.0 [Ryan Thomas](mailto:ryan@ryant.org) June 2015
+  * Add libname install-dirs variable, use it by default. Fixes #2437. (Edward Z. Yang)
+  * Reduce temporary directory name length, fixes #2502. (Edward Z. Yang)
+  * Workaround for #2527. (Mikhail Glushenkov)
+
+## 1.22.3.0 [Ryan Thomas](mailto:ryan@ryant.org) April 2015
+  * Fix for the ghcjs-pkg version number handling (Luite Stegeman)
+  * filterConfigureFlags: filter more flags (Mikhail Glushenkov)
+  * Cabal check will fail on -fprof-auto passed as a ghc-option - Fixes #2479 (John Chee)
+
+## 1.22.2.0 [Ryan Thomas](mailto:ryan@ryant.org) March 2015
+  * Don't pass `--{en,dis}able-profiling` to old setup.
+  * Add -Wall police
+  * Fix dependencies on `old-time`
+  * Fix test interface detailed-0.9 with GHC 7.10
+  * Fix HPC tests with GHC 7.10
+  * Make sure to pass the package key to ghc
+  * Use `--package-{name|version}` when available for Haddock when available
+  * Put full package name and version in library names
+  * Fully specify package key format, so external tools can generate it.
+
+# 1.22.0.0 [Johan Tibell](mailto:johan.tibell@gmail.com) January 2015
+  * Support GHC 7.10.
+  * Experimental support for emitting DWARF debug info.
+  * Preliminary support for relocatable packages.
+  * Allow cabal to be used inside cabal exec enviroments.
+  * hpc: support mutliple "ways" (e.g. profiling and vanilla).
+  * Support GHCJS.
+  * Improved command line documentation.
+  * Add `-none` constraint syntax for version ranges (#2093).
+  * Make the default doc index file path compiler/arch/os-dependent
+  (#2136).
+  * Warn instead of dying when generating documentation and hscolour
+  isn't installed (455f51622fa38347db62197a04bb0fa5b928ff17).
+  * Support the new BinaryLiterals extension
+  (1f25ab3c5eff311ada73c6c987061b80e9bbebd9).
+  * Warn about `ghc-prof-options: -auto-all` in `cabal check` (#2162).
+  * Add preliminary support for multiple instances of the same package
+  version installed side-by-side (#2002).
+  * New binary build config format - faster build times (#2076).
+  * Support module thinning and renaming (#2038).
+  * Add a new license type: UnspecifiedLicense (#2141).
+  * Remove support for Hugs and nhc98 (#2168).
+  * Invoke `tar` with `--formar ustar` if possible in `sdist` (#1903).
+  * Replace `--enable-library-coverage` with `--enable-coverage`, which
+  enables program coverage for all components (#1945).
+  * Suggest that `ExitFailure 9` is probably due to memory
+  exhaustion (#1522).
+  * Drop support for Haddock < 2.0 (#1808, #1718).
+  * Make `cabal test`/`cabal bench` build only what's needed for
+  running tests/benchmarks (#1821).
+  * Build shared libraries by default when linking executables dynamically.
+  * Build profiled libraries by default when profiling executables.
+
+----
+
+### 1.20.0.4 [Ryan Thomas](mailto:ryan@ryant.org) January 2016
+  * Cabal.cabal: change build-type to Simple.
+
+### 1.20.0.1 [Johan Tibell](mailto:johan.tibell@gmail.com) May 2014
+  * Fix streaming test output.
+
+# 1.20.0.0 [Johan Tibell](mailto:johan.tibell@gmail.com) April 2014
+  * Rewrite user guide
+  * Fix repl Ctrl+C handling
+  * Add haskell-suite compiler support
+  * Add __HADDOCK_VERSION__ define
+  * Allow specifying exact dependency version using hash
+  * Rename extra-html-files to extra-doc-files
+  * Add parallel build support for GHC 7.8 and later
+  * Don't call ranlib on OS X
+  * Avoid re-linking executables, test suites, and benchmarks
+  unnecessarily, shortening build times
+  * Add `--allow-newer` which allows upper version bounds to be
+  ignored
+  * Add `--enable-library-stripping`
+  * Add command for freezing dependencies
+  * Allow repl to be used outside Cabal packages
+  * Add `--require-sandbox`
+  * Don't use `--strip-unneeded` on OS X or iOS
+  * Add new license-files field got additional licenses
+  * Fix if(solaris) on some Solaris versions
+  * Don't use -dylib-install-name on OS X with GHC > 7.8
+  * Add DragonFly as a known OS
+  * Improve pretty-printing of Cabal files
+  * Add test flag `--show-details=streaming` for real-time test output
+  * Add exec command
+
+----
+
+## 1.10.2.0 [Duncan Coutts](mailto:duncan@community.haskell.org) June 2011
+  * Include test suites in cabal sdist
+  * Fix for conditionals in test suite stanzas in `.cabal` files
+  * Fix permissions of directories created during install
+  * Fix for global builds when $HOME env var is not set
+
+## 1.10.1.0 [Duncan Coutts](mailto:duncan@community.haskell.org) February 2011
+  * Improved error messages when test suites are not enabled
+  * Template parameters allowed in test `--test-option(s)` flag
+  * Improved documentation of the test feature
+  * Relaxed QA check on cabal-version when using test-suite sections
+  * `haddock` command now allows both `--hoogle` and `--html` at the same time
+  * Find ghc-version-specific instances of the hsc2hs program
+  * Preserve file executable permissions in sdist tarballs
+  * Pass gcc location and flags to ./configure scripts
+  * Get default gcc flags from ghc
+
+# 1.10.0.0 [Duncan Coutts](mailto:duncan@haskell.org) November 2010
+  * New cabal test feature
+  * Initial support for UHC
+  * New default-language and other-languages fields (e.g. Haskell98/2010)
+  * New default-extensions and other-extensions fields
+  * Deprecated extensions field (for packages using cabal-version >=1.10)
+  * Cabal-version field must now only be of the form `>= x.y`
+  * Removed deprecated `--copy-prefix=` feature
+  * Auto-reconfigure when `.cabal` file changes
+  * Workaround for haddock overwriting .hi and .o files when using TH
+  * Extra cpp flags used with hsc2hs and c2hs (-D${os}_BUILD_OS etc)
+  * New cpp define VERSION_<package> gives string version of dependencies
+  * User guide source now in markdown format for easier editing
+  * Improved checks and error messages for C libraries and headers
+  * Removed BSD4 from the list of suggested licenses
+  * Updated list of known language extensions
+  * Fix for include paths to allow C code to import FFI stub.h files
+  * Fix for intra-package dependencies on OSX
+  * Stricter checks on various bits of `.cabal` file syntax
+  * Minor fixes for c2hs
+
+----
+
+### 1.8.0.6 [Duncan Coutts](mailto:duncan@haskell.org) June 2010
+  * Fix `register --global/--user`
+
+### 1.8.0.4 [Duncan Coutts](mailto:duncan@haskell.org) March 2010
+  * Set dylib-install-name for dynalic libs on OSX
+  * Stricter configure check that compiler supports a package's extensions
+  * More configure-time warnings
+  * Hugs can compile Cabal lib again
+  * Default datadir now follows prefix on Windows
+  * Support for finding installed packages for hugs
+  * Cabal version macros now have proper parenthesis
+  * Reverted change to filter out deps of non-buildable components
+  * Fix for registering implace when using a specific package db
+  * Fix mismatch between $os and $arch path template variables
+  * Fix for finding ar.exe on Windows, always pick ghc's version
+  * Fix for intra-package dependencies with ghc-6.12
+
+# 1.8.0.2 [Duncan Coutts](mailto:duncan@haskell.org) December 2009
+  * Support for GHC-6.12
+  * New unique installed package IDs which use a package hash
+  * Allow executables to depend on the lib within the same package
+  * Dependencies for each component apply only to that component
+    (previously applied to all the other components too)
+  * Added new known license MIT and versioned GPL and LGPL
+  * More liberal package version range syntax
+  * Package registration files are now UTF8
+  * Support for LHC and JHC-0.7.2
+  * Deprecated RecordPuns extension in favour of NamedFieldPuns
+  * Deprecated PatternSignatures extension in favor of ScopedTypeVariables
+  * New VersionRange semantic view as a sequence of intervals
+  * Improved package quality checks
+  * Minor simplification in a couple `Setup.hs` hooks
+  * Beginnings of a unit level testsuite using QuickCheck
+  * Various bug fixes
+  * Various internal cleanups
+
+----
+
+### 1.6.0.2 [Duncan Coutts](mailto:duncan@haskell.org) February 2009
+  * New configure-time check for C headers and libraries
+  * Added language extensions present in ghc-6.10
+  * Added support for NamedFieldPuns extension in ghc-6.8
+  * Fix in configure step for ghc-6.6 on Windows
+  * Fix warnings in `Path_pkgname.hs` module on Windows
+  * Fix for exotic flags in ld-options field
+  * Fix for using pkg-config in a package with a lib and an executable
+  * Fix for building haddock docs for exes that use the Paths module
+  * Fix for installing header files in subdirectories
+  * Fix for the case of building profiling libs but not ordinary libs
+  * Fix read-only attribute of installed files on Windows
+  * Ignore ghc -threaded flag when profiling in ghc-6.8 and older
+
+### 1.6.0.1 [Duncan Coutts](mailto:duncan@haskell.org) October 2008
+  * Export a compat function to help alex and happy
+
+# 1.6.0.0 [Duncan Coutts](mailto:duncan@haskell.org) October 2008
+  * Support for ghc-6.10
+  * Source control repositories can now be specified in `.cabal` files
+  * Bug report URLs can be now specified in `.cabal` files
+  * Wildcards now allowed in data-files and extra-source-files fields
+  * New syntactic sugar for dependencies `build-depends: foo ==1.2.*`
+  * New cabal_macros.h provides macros to test versions of dependencies
+  * Relocatable bindists now possible on unix via env vars
+  * New `exposed` field allows packages to be not exposed by default
+  * Install dir flags can now use $os and $arch variables
+  * New `--builddir` flag allows multiple builds from a single sources dir
+  * cc-options now only apply to .c files, not for -fvia-C
+  * cc-options are not longer propagated to dependent packages
+  * The cpp/cc/ld-options fields no longer use `,` as a separator
+  * hsc2hs is now called using gcc instead of using ghc as gcc
+  * New api for manipulating sets and graphs of packages
+  * Internal api improvements and code cleanups
+  * Minor improvements to the user guide
+  * Miscellaneous minor bug fixes
+
+----
+
+### 1.4.0.2 [Duncan Coutts](mailto:duncan@haskell.org) August 2008
+  * Fix executable stripping default
+  * Fix striping exes on OSX that export dynamic symbols (like ghc)
+  * Correct the order of arguments given by `--prog-options=`
+  * Fix corner case with overlapping user and global packages
+  * Fix for modules that use pre-processing and `.hs-boot` files
+  * Clarify some points in the user guide and readme text
+  * Fix verbosity flags passed to sub-command like haddock
+  * Fix `sdist --snapshot`
+  * Allow meta-packages that contain no modules or C code
+  * Make the generated Paths module -Wall clean on Windows
+
+### 1.4.0.1 [Duncan Coutts](mailto:duncan@haskell.org) June 2008
+  * Fix a bug which caused `.` to always be in the sources search path
+  * Haddock-2.2 and later do now support the `--hoogle` flag
+
+# 1.4.0.0 [Duncan Coutts](mailto:duncan@haskell.org) June 2008
+  * Rewritten command line handling support
+  * Command line completion with bash
+  * Better support for Haddock 2
+  * Improved support for nhc98
+  * Removed support for ghc-6.2
+  * Haddock markup in `.lhs` files now supported
+  * Default colour scheme for highlighted source code
+  * Default prefix for `--user` installs is now `$HOME/.cabal`
+  * All `.cabal` files are treaded as UTF-8 and must be valid
+  * Many checks added for common mistakes
+  * New `--package-db=` option for specific package databases
+  * Many internal changes to support cabal-install
+  * Stricter parsing for version strings, eg dissalows "1.05"
+  * Improved user guide introduction
+  * Programatica support removed
+  * New options `--program-prefix/suffix` allows eg versioned programs
+  * Support packages that use `.hs-boot` files
+  * Fix sdist for Main modules that require preprocessing
+  * New configure -O flag with optimisation level 0--2
+  * Provide access to "`x-`" extension fields through the Cabal api
+  * Added check for broken installed packages
+  * Added warning about using inconsistent versions of dependencies
+  * Strip binary executable files by default with an option to disable
+  * New options to add site-specific include and library search paths
+  * Lift the restriction that libraries must have exposed-modules
+  * Many bugs fixed.
+  * Many internal structural improvements and code cleanups
+
+----
+
+## 1.2.4.0 [Duncan Coutts](mailto:duncan@haskell.org) June 2008
+  * Released with GHC 6.8.3
+  * Backported several fixes and minor improvements from Cabal-1.4
+  * Use a default colour scheme for sources with hscolour >=1.9
+  * Support `--hyperlink-source` for Haddock >= 2.0
+  * Fix for running in a non-writable directory
+  * Add OSX -framework arguments when linking executables
+  * Updates to the user guide
+  * Allow build-tools names to include + and _
+  * Export autoconfUserHooks and simpleUserHooks
+  * Export ccLdOptionsBuildInfo for `Setup.hs` scripts
+  * Export unionBuildInfo and make BuildInfo an instance of Monoid
+  * Fix to allow the `main-is` module to use a pre-processor
+
+## 1.2.3.0 [Duncan Coutts](mailto:duncan@haskell.org) Nov 2007
+  * Released with GHC 6.8.2
+  * Includes full list of GHC language extensions
+  * Fix infamous `dist/conftest.c` bug
+  * Fix `configure --interfacedir=`
+  * Find ld.exe on Windows correctly
+  * Export PreProcessor constructor and mkSimplePreProcessor
+  * Fix minor bug in unlit code
+  * Fix some markup in the haddock docs
+
+## 1.2.2.0 [Duncan Coutts](mailto:duncan@haskell.org) Nov 2007
+  * Released with GHC 6.8.1
+  * Support haddock-2.0
+  * Support building DSOs with GHC
+  * Require reconfiguring if the `.cabal` file has changed
+  * Fix os(windows) configuration test
+  * Fix building documentation
+  * Fix building packages on Solaris
+  * Other minor bug fixes
+
+## 1.2.1 [Duncan Coutts](mailto:duncan@haskell.org) Oct 2007
+  * To be included in GHC 6.8.1
+  * New field `cpp-options` used when preprocessing Haskell modules
+  * Fixes for hsc2hs when using ghc
+  * C source code gets compiled with -O2 by default
+  * OS aliases, to allow os(windows) rather than requiring os(mingw32)
+  * Fix cleaning of `stub` files
+  * Fix cabal-setup, command line ui that replaces `runhaskell Setup.hs`
+  * Build docs even when dependent packages docs are missing
+  * Allow the `--html-dir` to be specified at configure time
+  * Fix building with ghc-6.2
+  * Other minor bug fixes and build fixes
+
+# 1.2.0  [Duncan Coutts](mailto:duncan.coutts@worc.ox.ac.uk) Sept 2007
+  * To be included in GHC 6.8.x
+  * New configurations feature
+  * Can make haddock docs link to hilighted sources (with hscolour)
+  * New flag to allow linking to haddock docs on the web
+  * Supports pkg-config
+  * New field `build-tools` for tool dependencies
+  * Improved c2hs support
+  * Preprocessor output no longer clutters source dirs
+  * Separate `includes` and `install-includes` fields
+  * Makefile command to generate makefiles for building libs with GHC
+  * New `--docdir` configure flag
+  * Generic `--with-prog` `--prog-args` configure flags
+  * Better default installation paths on Windows
+  * Install paths can be specified relative to each other
+  * License files now installed
+  * Initial support for NHC (incomplete)
+  * Consistent treatment of verbosity
+  * Reduced verbosity of configure step by default
+  * Improved helpfulness of output messages
+  * Help output now clearer and fits in 80 columns
+  * New setup register `--gen-pkg-config` flag for distros
+  * Major internal refactoring, hooks api has changed
+  * Dozens of bug fixes
+
+----
+
+### 1.1.6.2 [Duncan Coutts](mailto:duncan.coutts@worc.ox.ac.uk) May 2007
+
+  * Released with GHC 6.6.1
+  * Handle windows text file encoding for `.cabal` files
+  * Fix compiling a executable for profiling that uses Template Haskell
+  * Other minor bug fixes and user guide clarifications
+
+### 1.1.6.1 [Duncan Coutts](mailto:duncan.coutts@worc.ox.ac.uk) Oct 2006
+
+  * fix unlit code
+  * fix escaping in register.sh
+
+## 1.1.6  [Duncan Coutts](mailto:duncan.coutts@worc.ox.ac.uk) Oct 2006
+
+  * Released with GHC 6.6
+  * Added support for hoogle
+  * Allow profiling and normal builds of libs to be chosen indepentantly
+  * Default installation directories on Win32 changed
+  * Register haddock docs with ghc-pkg
+  * Get haddock to make hyperlinks to dependent package docs
+  * Added BangPatterns language extension
+  * Various bug fixes
+
+## 1.1.4  [Duncan Coutts](mailto:duncan.coutts@worc.ox.ac.uk) May 2006
+
+  * Released with GHC 6.4.2
+  * Better support for packages that need to install header files
+  * cabal-setup added, but not installed by default yet
+  * Implemented `setup register --inplace`
+  * Have packages exposed by default with ghc-6.2
+  * It is no longer necessary to run `configure` before `clean` or `sdist`
+  * Added support for ghc's `-split-objs`
+  * Initial support for JHC
+  * Ignore extension fields in `.cabal` files (fields begining with "`x-`")
+  * Some changes to command hooks API to improve consistency
+  * Hugs support improvements
+  * Added GeneralisedNewtypeDeriving language extension
+  * Added cabal-version field
+  * Support hidden modules with haddock
+  * Internal code refactoring
+  * More bug fixes
+
+## 1.1.3  [Isaac Jones](mailto:ijones@syntaxpolice.org) Sept 2005
+
+  * WARNING: Interfaces not documented in the user's guide may
+    change in future releases.
+  * Move building of GHCi .o libs to the build phase rather than
+  register phase. (from Duncan Coutts)
+  * Use .tar.gz for source package extension
+  * Uses GHC instead of cpphs if the latter is not available
+  * Added experimental "command hooks" which completely override the
+  default behavior of a command.
+  * Some bugfixes
+
+# 1.1.1  [Isaac Jones](mailto:ijones@syntaxpolice.org) July 2005
+
+  * WARNING: Interfaces not documented in the user's guide may
+    change in future releases.
+  * Handles recursive modules for GHC 6.2 and GHC 6.4.
+  * Added `setup test` command (Used with UserHook)
+  * implemented handling of _stub.{c,h,o} files
+  * Added support for profiling
+  * Changed install prefix of libraries (pref/pkgname-version
+    to prefix/pkgname-version/compname-version)
+  * Added pattern guards as a language extension
+  * Moved some functionality to Language.Haskell.Extension
+  * Register / unregister .bat files for windows
+  * Exposed more of the API
+  * Added support for the hide-all-packages flag in GHC > 6.4
+  * Several bug fixes
+
+----
+
+# 1.0  [Isaac Jones](mailto:ijones@syntaxpolice.org) March 11 2005
+
+  * Released with GHC 6.4, Hugs March 2005, and nhc98 1.18
+  * Some sanity checking
+
+----
+
+# 0.5  [Isaac Jones](mailto:ijones@syntaxpolice.org) Wed Feb 19 2005
+
+  * __WARNING__: this is a pre-release and the interfaces are
+    still likely to change until we reach a 1.0 release.
+  * Hooks interfaces changed
+  * Added preprocessors to user hooks
+  * No more executable-modules or hidden-modules.  Use
+    `other-modules` instead.
+  * Certain fields moved into BuildInfo, much refactoring
+  * `extra-libs` -> `extra-libraries`
+  * Added `--gen-script` to configure and unconfigure.
+  * `modules-ghc` (etc) now `ghc-modules` (etc)
+  * added new fields including `synopsis`
+  * Lots of bug fixes
+  * spaces can sometimes be used instead of commas
+  * A user manual has appeared (Thanks, ross!)
+  * for ghc 6.4, configures versionsed depends properly
+  * more features to `./setup haddock`
+
+----
+
+# 0.4  [Isaac Jones](mailto:ijones@syntaxpolice.org) Sun Jan 16 2005
+
+  * Much thanks to all the awesome fptools hackers who have been
+  working hard to build the Haskell Cabal!
+
+  * __Interface Changes__:
+
+    * __WARNING__: this is a pre-release and the interfaces are still
+    likely to change until we reach a 1.0 release.
+
+    * Instead of Package.description, you should name your
+    description files <something>.cabal.  In particular, we suggest
+    that you name it <packagename>.cabal, but this is not enforced
+    (yet).  Multiple `.cabal` files in the same directory is an error,
+    at least for now.
+
+    * `./setup install --install-prefix` is gone.  Use `./setup copy`
+    `--copy-prefix` instead.
+
+    * The `Modules` field is gone.  Use `hidden-modules`,
+    `exposed-modules`, and `executable-modules`.
+
+    * `Build-depends` is now a package-only field, and can't go into
+    executable stanzas.  Build-depends is a package-to-package
+    relationship.
+
+    * Some new fields.  Use the Source.
+
+  * __New Features__
+
+    * Cabal is now included as a package in the CVS version of
+    fptools.  That means it'll be released as `-package Cabal` in
+    future versions of the compilers, and if you are a bleeding-edge
+    user, you can grab it from the CVS repository with the compilers.
+
+    * Hugs compatibility and NHC98 compatibility should both be
+    improved.
+
+    * Hooks Interface / Autoconf compatibility: Most of the hooks
+    interface is hidden for now, because it's not finalized.  I have
+    exposed only `defaultMainWithHooks` and `defaultUserHooks`.  This
+    allows you to use a ./configure script to preprocess
+    `foo.buildinfo`, which gets merged with `foo.cabal`.  In future
+    releases, we'll expose UserHooks, but we're definitely going to
+    change the interface to those.  The interface to the two functions
+    I've exposed should stay the same, though.
+
+    * ./setup haddock is a baby feature which pre-processes the
+    source code with hscpp and runs haddock on it.  This is brand new
+    and hardly tested, so you get to knock it around and see what you
+    think.
+
+    * Some commands now actually implement verbosity.
+
+    * The preprocessors have been tested a bit more, and seem to work
+    OK.  Please give feedback if you use these.
+
+----
+
+# 0.3  [Isaac Jones](mailto:ijones@syntaxpolice.org) Sun Jan 16 2005
+
+  * Unstable snapshot release
+  * From now on, stable releases are even.
+
+----
+
+# 0.2  [Isaac Jones](mailto:ijones@syntaxpolice.org)
+
+  * Adds more HUGS support and preprocessor support.
diff --git a/cabal/Cabal/Distribution/Backpack.hs b/cabal/Cabal/Distribution/Backpack.hs
--- a/cabal/Cabal/Distribution/Backpack.hs
+++ b/cabal/Cabal/Distribution/Backpack.hs
@@ -1,9 +1,9 @@
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE PatternGuards #-}
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveDataTypeable         #-}
+{-# LANGUAGE DeriveGeneric              #-}
+{-# LANGUAGE FlexibleInstances          #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE PatternGuards              #-}
+{-# LANGUAGE RankNTypes                 #-}
 
 -- | This module defines the core data types for Backpack.  For more
 -- details, see:
@@ -31,6 +31,8 @@
     dispOpenModuleSubstEntry,
     parseOpenModuleSubst,
     parseOpenModuleSubstEntry,
+    parsecOpenModuleSubst,
+    parsecOpenModuleSubstEntry,
     openModuleSubstFreeHoles,
 
     -- * Conversions to 'UnitId'
@@ -38,22 +40,26 @@
     hashModuleSubst,
 ) where
 
-import Prelude ()
 import Distribution.Compat.Prelude hiding (mod)
-import Distribution.Compat.ReadP
-import qualified Distribution.Compat.ReadP as Parse
-import qualified Text.PrettyPrint as Disp
-import Text.PrettyPrint (hcat)
+import Distribution.Compat.ReadP   ((<++))
+import Distribution.Parsec.Class
+import Distribution.Pretty
+import Prelude ()
+import Text.PrettyPrint            (hcat)
 
+import qualified Distribution.Compat.CharParsing as P
+import qualified Distribution.Compat.ReadP       as Parse
+import qualified Text.PrettyPrint                as Disp
+
 import Distribution.ModuleName
 import Distribution.Text
 import Distribution.Types.ComponentId
-import Distribution.Types.UnitId
 import Distribution.Types.Module
+import Distribution.Types.UnitId
 import Distribution.Utils.Base62
 
 import qualified Data.Map as Map
-import Data.Set (Set)
+import           Data.Set (Set)
 import qualified Data.Set as Set
 
 -----------------------------------------------------------------------
@@ -103,13 +109,32 @@
     rnf (IndefFullUnitId cid subst) = rnf cid `seq` rnf subst
     rnf (DefiniteUnitId uid) = rnf uid
 
-instance Text OpenUnitId where
-    disp (IndefFullUnitId cid insts)
+instance Pretty OpenUnitId where
+    pretty (IndefFullUnitId cid insts)
         -- TODO: arguably a smart constructor to enforce invariant would be
         -- better
-        | Map.null insts = disp cid
-        | otherwise      = disp cid <<>> Disp.brackets (dispOpenModuleSubst insts)
-    disp (DefiniteUnitId uid) = disp uid
+        | Map.null insts = pretty cid
+        | otherwise      = pretty cid <<>> Disp.brackets (dispOpenModuleSubst insts)
+    pretty (DefiniteUnitId uid) = pretty uid
+
+-- |
+--
+-- >>> eitherParsec "foobar" :: Either String OpenUnitId
+--Right (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "foobar"}))
+--
+-- >>> eitherParsec "foo[Str=text-1.2.3:Data.Text.Text]" :: Either String OpenUnitId
+-- Right (IndefFullUnitId (ComponentId "foo") (fromList [(ModuleName ["Str"],OpenModule (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "text-1.2.3"})) (ModuleName ["Data","Text","Text"]))]))
+--
+instance Parsec OpenUnitId where
+    parsec = P.try parseOpenUnitId <|> fmap DefiniteUnitId parsec
+      where
+        parseOpenUnitId = do
+            cid <- parsec
+            insts <- P.between (P.char '[') (P.char ']')
+                       parsecOpenModuleSubst
+            return (IndefFullUnitId cid insts)
+
+instance Text OpenUnitId where
     parse = parseOpenUnitId <++ fmap DefiniteUnitId parse
       where
         parseOpenUnitId = do
@@ -160,11 +185,33 @@
     rnf (OpenModule uid mod_name) = rnf uid `seq` rnf mod_name
     rnf (OpenModuleVar mod_name) = rnf mod_name
 
+instance Pretty OpenModule where
+    pretty (OpenModule uid mod_name) =
+        hcat [pretty uid, Disp.text ":", pretty mod_name]
+    pretty (OpenModuleVar mod_name) =
+        hcat [Disp.char '<', pretty mod_name, Disp.char '>']
+
+-- |
+--
+-- >>> eitherParsec "Includes2-0.1.0.0-inplace-mysql:Database.MySQL" :: Either String OpenModule
+-- Right (OpenModule (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "Includes2-0.1.0.0-inplace-mysql"})) (ModuleName ["Database","MySQL"]))
+--
+instance Parsec OpenModule where
+    parsec = parsecModuleVar <|> parsecOpenModule
+      where
+        parsecOpenModule = do
+            uid <- parsec
+            _ <- P.char ':'
+            mod_name <- parsec
+            return (OpenModule uid mod_name)
+
+        parsecModuleVar = do
+            _ <- P.char '<'
+            mod_name <- parsec
+            _ <- P.char '>'
+            return (OpenModuleVar mod_name)
+
 instance Text OpenModule where
-    disp (OpenModule uid mod_name) =
-        hcat [disp uid, Disp.text ":", disp mod_name]
-    disp (OpenModuleVar mod_name) =
-        hcat [Disp.char '<', disp mod_name, Disp.char '>']
     parse = parseModuleVar <++ parseOpenModule
       where
         parseOpenModule = do
@@ -205,17 +252,35 @@
 dispOpenModuleSubstEntry (k, v) = disp k <<>> Disp.char '=' <<>> disp v
 
 -- | Inverse to 'dispModSubst'.
-parseOpenModuleSubst :: ReadP r OpenModuleSubst
+parseOpenModuleSubst :: Parse.ReadP r OpenModuleSubst
 parseOpenModuleSubst = fmap Map.fromList
       . flip Parse.sepBy (Parse.char ',')
       $ parseOpenModuleSubstEntry
 
 -- | Inverse to 'dispModSubstEntry'.
-parseOpenModuleSubstEntry :: ReadP r (ModuleName, OpenModule)
+parseOpenModuleSubstEntry :: Parse.ReadP r (ModuleName, OpenModule)
 parseOpenModuleSubstEntry =
     do k <- parse
        _ <- Parse.char '='
        v <- parse
+       return (k, v)
+
+-- | Inverse to 'dispModSubst'.
+--
+-- @since 2.2
+parsecOpenModuleSubst :: CabalParsing m => m OpenModuleSubst
+parsecOpenModuleSubst = fmap Map.fromList
+      . flip P.sepBy (P.char ',')
+      $ parsecOpenModuleSubstEntry
+
+-- | Inverse to 'dispModSubstEntry'.
+--
+-- @since 2.2
+parsecOpenModuleSubstEntry :: CabalParsing m => m (ModuleName, OpenModule)
+parsecOpenModuleSubstEntry =
+    do k <- parsec
+       _ <- P.char '='
+       v <- parsec
        return (k, v)
 
 -- | Get the set of holes ('ModuleVar') embedded in a 'OpenModuleSubst'.
diff --git a/cabal/Cabal/Distribution/Backpack/ConfiguredComponent.hs b/cabal/Cabal/Distribution/Backpack/ConfiguredComponent.hs
--- a/cabal/Cabal/Distribution/Backpack/ConfiguredComponent.hs
+++ b/cabal/Cabal/Distribution/Backpack/ConfiguredComponent.hs
@@ -40,6 +40,7 @@
 import Distribution.Version
 import Distribution.Utils.LogProgress
 import Distribution.Utils.MapAccum
+import Distribution.Utils.Generic
 
 import Control.Monad
 import qualified Data.Set as Set
@@ -158,17 +159,18 @@
     :: PackageDescription
     -> ComponentId
     -> ConfiguredComponentMap
+    -> ConfiguredComponentMap
     -> Component
     -> LogProgress ConfiguredComponent
-toConfiguredComponent pkg_descr this_cid dep_map component = do
+toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do
     lib_deps <-
         if newPackageDepsBehaviour pkg_descr
             then forM (targetBuildDepends bi) $ \(Dependency name _) -> do
                     let (pn, cn) = fixFakePkgName pkg_descr name
-                    value <- case Map.lookup cn =<< Map.lookup pn dep_map of
+                    value <- case Map.lookup cn =<< Map.lookup pn lib_dep_map of
                         Nothing ->
                             dieProgress $
-                                text "Dependency on unbuildable" <+>
+                                text "Dependency on unbuildable (i.e. 'buildable: False')" <+>
                                 text (showComponentName cn) <+>
                                 text "from" <+> disp pn
                         Just v -> return v
@@ -179,7 +181,7 @@
        lib_deps exe_deps component
   where
     bi = componentBuildInfo component
-    -- dep_map contains a mix of internal and external deps.
+    -- lib_dep_map contains a mix of internal and external deps.
     -- We want all the public libraries (dep_cn == CLibName)
     -- of all external deps (dep /= pn).  Note that this
     -- excludes the public library of the current package:
@@ -187,11 +189,15 @@
     -- because it would imply a cyclic dependency for the
     -- library itself.
     old_style_lib_deps = [ e
-                         | (pn, comp_map) <- Map.toList dep_map
+                         | (pn, comp_map) <- Map.toList lib_dep_map
                          , pn /= packageName pkg_descr
                          , (cn, e) <- Map.toList comp_map
                          , cn == CLibName ]
-    exe_deps =
+    -- We have to nub here, because 'getAllToolDependencies' may return
+    -- duplicates (see #4986).  (NB: This is not needed for lib_deps,
+    -- since those elaborate into includes, for which there explicitly
+    -- may be multiple instances of a package)
+    exe_deps = ordNub $
         [ exe
         | ExeDependency pn cn _ <- getAllToolDependencies pkg_descr bi
         -- The error suppression here is important, because in general
@@ -199,7 +205,7 @@
         -- which the package is attempting to use (those deps are only
         -- fed in when cabal-install uses this codepath.)
         -- TODO: Let cabal-install request errors here
-        , Just exe <- [Map.lookup (CExeName cn) =<< Map.lookup pn dep_map]
+        , Just exe <- [Map.lookup (CExeName cn) =<< Map.lookup pn exe_dep_map]
         ]
 
 -- | Also computes the 'ComponentId', and sets cc_public if necessary.
@@ -219,7 +225,7 @@
                 dep_map component = do
     cc <- toConfiguredComponent
                 pkg_descr this_cid
-                dep_map component
+                dep_map dep_map component
     return $ if use_external_internal_deps
                 then cc { cc_public = True }
                 else cc
@@ -243,6 +249,11 @@
 -- list of internal components must be topologically sorted
 -- based on internal package dependencies, so that any internal
 -- dependency points to an entry earlier in the list.
+--
+-- TODO: This function currently restricts the input configured components to
+-- one version per package, by using the type ConfiguredComponentMap.  It cannot
+-- be used to configure a component that depends on one version of a package for
+-- a library and another version for a build-tool.
 toConfiguredComponents
     :: Bool -- use_external_internal_deps
     -> FlagAssignment
diff --git a/cabal/Cabal/Distribution/CabalSpecVersion.hs b/cabal/Cabal/Distribution/CabalSpecVersion.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/CabalSpecVersion.hs
@@ -0,0 +1,80 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+module Distribution.CabalSpecVersion where
+
+import Prelude ()
+import Distribution.Compat.Prelude
+import qualified Data.Set as Set
+
+-- | Different Cabal-the-spec versions.
+--
+-- We branch based on this at least in the parser.
+--
+data CabalSpecVersion
+    = CabalSpecOld
+    | CabalSpecV1_22
+    | CabalSpecV1_24
+    | CabalSpecV2_0
+    | CabalSpecV2_2
+    | CabalSpecV2_4
+  deriving (Eq, Ord, Show, Read, Enum, Bounded, Typeable, Data, Generic)
+
+cabalSpecLatest :: CabalSpecVersion
+cabalSpecLatest = CabalSpecV2_4
+
+cabalSpecFeatures :: CabalSpecVersion -> Set.Set CabalFeature
+cabalSpecFeatures CabalSpecOld   = Set.empty
+cabalSpecFeatures CabalSpecV1_22 = Set.empty
+cabalSpecFeatures CabalSpecV1_24 = Set.empty
+cabalSpecFeatures CabalSpecV2_0  = Set.empty
+cabalSpecFeatures CabalSpecV2_2  = Set.fromList
+    [ Elif
+    , CommonStanzas
+    ]
+cabalSpecFeatures CabalSpecV2_4  = Set.fromList
+    [ Elif
+    , CommonStanzas
+    , Globstar
+    ]
+
+cabalSpecSupports :: CabalSpecVersion -> [Int] -> Bool
+cabalSpecSupports CabalSpecOld v   = v < [1,21]
+cabalSpecSupports CabalSpecV1_22 v = v < [1,23]
+cabalSpecSupports CabalSpecV1_24 v = v < [1,25]
+cabalSpecSupports CabalSpecV2_0 v  = v < [2,1]
+cabalSpecSupports CabalSpecV2_2 v  = v < [2,3]
+cabalSpecSupports CabalSpecV2_4 _  = True
+
+specHasCommonStanzas :: CabalSpecVersion -> HasCommonStanzas
+specHasCommonStanzas CabalSpecV2_2 = HasCommonStanzas
+specHasCommonStanzas CabalSpecV2_4 = HasCommonStanzas
+specHasCommonStanzas _             = NoCommonStanzas
+
+specHasElif :: CabalSpecVersion -> HasElif
+specHasElif CabalSpecV2_2 = HasElif
+specHasElif CabalSpecV2_4 = HasElif
+specHasElif _             = NoElif
+
+-------------------------------------------------------------------------------
+-- Features
+-------------------------------------------------------------------------------
+
+data CabalFeature
+    = Elif
+    | CommonStanzas
+    | Globstar
+      -- ^ Implemented in #5284. Not actually a change to the parser,
+      -- as filename patterns are opaque to it currently.
+  deriving (Eq, Ord, Show, Read, Enum, Bounded, Typeable, Data, Generic)
+
+-------------------------------------------------------------------------------
+-- Booleans
+-------------------------------------------------------------------------------
+
+data HasElif = HasElif | NoElif
+  deriving (Eq, Show)
+
+data HasCommonStanzas = HasCommonStanzas | NoCommonStanzas
+  deriving (Eq, Show)
+
+data HasGlobstar = HasGlobstar | NoGlobstar
diff --git a/cabal/Cabal/Distribution/Compat/Binary.hs b/cabal/Cabal/Distribution/Compat/Binary.hs
--- a/cabal/Cabal/Distribution/Compat/Binary.hs
+++ b/cabal/Cabal/Distribution/Compat/Binary.hs
@@ -18,10 +18,6 @@
 #endif
        ) where
 
-#if __GLASGOW_HASKELL__ < 706
-import Prelude hiding (catch)
-#endif
-
 import Control.Exception (catch, evaluate)
 #if __GLASGOW_HASKELL__ >= 711
 import Control.Exception (pattern ErrorCall)
diff --git a/cabal/Cabal/Distribution/Compat/CharParsing.hs b/cabal/Cabal/Distribution/Compat/CharParsing.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/Compat/CharParsing.hs
@@ -0,0 +1,356 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -fspec-constr -fspec-constr-count=8 #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Distribution.Compat.CharParsing
+-- Copyright   :  (c) Edward Kmett 2011
+-- License     :  BSD3
+--
+-- Maintainer  :  ekmett@gmail.com
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-- Parsers for character streams
+--
+-- Originally in @parsers@ package.
+--
+-----------------------------------------------------------------------------
+module Distribution.Compat.CharParsing
+  (
+  -- * Combinators
+    oneOf        -- :: CharParsing m => [Char] -> m Char
+  , noneOf       -- :: CharParsing m => [Char] -> m Char
+  , spaces       -- :: CharParsing m => m ()
+  , space        -- :: CharParsing m => m Char
+  , newline      -- :: CharParsing m => m Char
+  , tab          -- :: CharParsing m => m Char
+  , upper        -- :: CharParsing m => m Char
+  , lower        -- :: CharParsing m => m Char
+  , alphaNum     -- :: CharParsing m => m Char
+  , letter       -- :: CharParsing m => m Char
+  , digit        -- :: CharParsing m => m Char
+  , hexDigit     -- :: CharParsing m => m Char
+  , octDigit     -- :: CharParsing m => m Char
+  , satisfyRange -- :: CharParsing m => Char -> Char -> m Char
+  -- * Class
+  , CharParsing(..)
+  -- * Cabal additions
+  , integral
+  , munch1
+  , munch
+  , skipSpaces1
+  , module Distribution.Compat.Parsing
+  ) where
+
+import Prelude ()
+import Distribution.Compat.Prelude
+
+import Control.Monad.Trans.Class (lift)
+import Control.Monad.Trans.State.Lazy as Lazy
+import Control.Monad.Trans.State.Strict as Strict
+import Control.Monad.Trans.Writer.Lazy as Lazy
+import Control.Monad.Trans.Writer.Strict as Strict
+import Control.Monad.Trans.RWS.Lazy as Lazy
+import Control.Monad.Trans.RWS.Strict as Strict
+import Control.Monad.Trans.Reader (ReaderT (..))
+import Control.Monad.Trans.Identity (IdentityT (..))
+import Data.Char
+import Data.Text (Text, unpack)
+
+import qualified Text.Parsec as Parsec
+import qualified Distribution.Compat.ReadP as ReadP
+
+import Distribution.Compat.Parsing
+
+-- | @oneOf cs@ succeeds if the current character is in the supplied
+-- list of characters @cs@. Returns the parsed character. See also
+-- 'satisfy'.
+--
+-- >   vowel  = oneOf "aeiou"
+oneOf :: CharParsing m => [Char] -> m Char
+oneOf xs = satisfy (\c -> c `elem` xs)
+{-# INLINE oneOf #-}
+
+-- | As the dual of 'oneOf', @noneOf cs@ succeeds if the current
+-- character is /not/ in the supplied list of characters @cs@. Returns the
+-- parsed character.
+--
+-- >  consonant = noneOf "aeiou"
+noneOf :: CharParsing m => [Char] -> m Char
+noneOf xs = satisfy (\c -> c `notElem` xs)
+{-# INLINE noneOf #-}
+
+-- | Skips /zero/ or more white space characters. See also 'skipMany'.
+spaces :: CharParsing m => m ()
+spaces = skipMany space <?> "white space"
+{-# INLINE spaces #-}
+
+-- | Parses a white space character (any character which satisfies 'isSpace')
+-- Returns the parsed character.
+space :: CharParsing m => m Char
+space = satisfy isSpace <?> "space"
+{-# INLINE space #-}
+
+-- | Parses a newline character (\'\\n\'). Returns a newline character.
+newline :: CharParsing m => m Char
+newline = char '\n' <?> "new-line"
+{-# INLINE newline #-}
+
+-- | Parses a tab character (\'\\t\'). Returns a tab character.
+tab :: CharParsing m => m Char
+tab = char '\t' <?> "tab"
+{-# INLINE tab #-}
+
+-- | Parses an upper case letter. Returns the parsed character.
+upper :: CharParsing m => m Char
+upper = satisfy isUpper <?> "uppercase letter"
+{-# INLINE upper #-}
+
+-- | Parses a lower case character. Returns the parsed character.
+lower :: CharParsing m => m Char
+lower = satisfy isLower <?> "lowercase letter"
+{-# INLINE lower #-}
+
+-- | Parses a letter or digit. Returns the parsed character.
+alphaNum :: CharParsing m => m Char
+alphaNum = satisfy isAlphaNum <?> "letter or digit"
+{-# INLINE alphaNum #-}
+
+-- | Parses a letter (an upper case or lower case character). Returns the
+-- parsed character.
+letter :: CharParsing m => m Char
+letter = satisfy isAlpha <?> "letter"
+{-# INLINE letter #-}
+
+-- | Parses a digit. Returns the parsed character.
+digit :: CharParsing m => m Char
+digit = satisfy isDigit <?> "digit"
+{-# INLINE digit #-}
+
+-- | Parses a hexadecimal digit (a digit or a letter between \'a\' and
+-- \'f\' or \'A\' and \'F\'). Returns the parsed character.
+hexDigit :: CharParsing m => m Char
+hexDigit = satisfy isHexDigit <?> "hexadecimal digit"
+{-# INLINE hexDigit #-}
+
+-- | Parses an octal digit (a character between \'0\' and \'7\'). Returns
+-- the parsed character.
+octDigit :: CharParsing m => m Char
+octDigit = satisfy isOctDigit <?> "octal digit"
+{-# INLINE octDigit #-}
+
+satisfyRange :: CharParsing m => Char -> Char -> m Char
+satisfyRange a z = satisfy (\c -> c >= a && c <= z)
+{-# INLINE satisfyRange #-}
+
+-- | Additional functionality needed to parse character streams.
+class Parsing m => CharParsing m where
+  -- | Parse a single character of the input, with UTF-8 decoding
+  satisfy :: (Char -> Bool) -> m Char
+
+  -- | @char c@ parses a single character @c@. Returns the parsed
+  -- character (i.e. @c@).
+  --
+  -- /e.g./
+  --
+  -- @semiColon = 'char' ';'@
+  char :: Char -> m Char
+  char c = satisfy (c ==) <?> show [c]
+  {-# INLINE char #-}
+
+  -- | @notChar c@ parses any single character other than @c@. Returns the parsed
+  -- character.
+  notChar :: Char -> m Char
+  notChar c = satisfy (c /=)
+  {-# INLINE notChar #-}
+
+  -- | This parser succeeds for any character. Returns the parsed character.
+  anyChar :: m Char
+  anyChar = satisfy (const True)
+  {-# INLINE anyChar #-}
+
+  -- | @string s@ parses a sequence of characters given by @s@. Returns
+  -- the parsed string (i.e. @s@).
+  --
+  -- >  divOrMod    =   string "div"
+  -- >              <|> string "mod"
+  string :: String -> m String
+  string s = s <$ try (traverse_ char s) <?> show s
+  {-# INLINE string #-}
+
+  -- | @text t@ parses a sequence of characters determined by the text @t@ Returns
+  -- the parsed text fragment (i.e. @t@).
+  --
+  -- Using @OverloadedStrings@:
+  --
+  -- >  divOrMod    =   text "div"
+  -- >              <|> text "mod"
+  text :: Text -> m Text
+  text t = t <$ string (unpack t)
+  {-# INLINE text #-}
+
+instance (CharParsing m, MonadPlus m) => CharParsing (Lazy.StateT s m) where
+  satisfy = lift . satisfy
+  {-# INLINE satisfy #-}
+  char    = lift . char
+  {-# INLINE char #-}
+  notChar = lift . notChar
+  {-# INLINE notChar #-}
+  anyChar = lift anyChar
+  {-# INLINE anyChar #-}
+  string  = lift . string
+  {-# INLINE string #-}
+  text = lift . text
+  {-# INLINE text #-}
+
+instance (CharParsing m, MonadPlus m) => CharParsing (Strict.StateT s m) where
+  satisfy = lift . satisfy
+  {-# INLINE satisfy #-}
+  char    = lift . char
+  {-# INLINE char #-}
+  notChar = lift . notChar
+  {-# INLINE notChar #-}
+  anyChar = lift anyChar
+  {-# INLINE anyChar #-}
+  string  = lift . string
+  {-# INLINE string #-}
+  text = lift . text
+  {-# INLINE text #-}
+
+instance (CharParsing m, MonadPlus m) => CharParsing (ReaderT e m) where
+  satisfy = lift . satisfy
+  {-# INLINE satisfy #-}
+  char    = lift . char
+  {-# INLINE char #-}
+  notChar = lift . notChar
+  {-# INLINE notChar #-}
+  anyChar = lift anyChar
+  {-# INLINE anyChar #-}
+  string  = lift . string
+  {-# INLINE string #-}
+  text = lift . text
+  {-# INLINE text #-}
+
+instance (CharParsing m, MonadPlus m, Monoid w) => CharParsing (Strict.WriterT w m) where
+  satisfy = lift . satisfy
+  {-# INLINE satisfy #-}
+  char    = lift . char
+  {-# INLINE char #-}
+  notChar = lift . notChar
+  {-# INLINE notChar #-}
+  anyChar = lift anyChar
+  {-# INLINE anyChar #-}
+  string  = lift . string
+  {-# INLINE string #-}
+  text = lift . text
+  {-# INLINE text #-}
+
+instance (CharParsing m, MonadPlus m, Monoid w) => CharParsing (Lazy.WriterT w m) where
+  satisfy = lift . satisfy
+  {-# INLINE satisfy #-}
+  char    = lift . char
+  {-# INLINE char #-}
+  notChar = lift . notChar
+  {-# INLINE notChar #-}
+  anyChar = lift anyChar
+  {-# INLINE anyChar #-}
+  string  = lift . string
+  {-# INLINE string #-}
+  text = lift . text
+  {-# INLINE text #-}
+
+instance (CharParsing m, MonadPlus m, Monoid w) => CharParsing (Lazy.RWST r w s m) where
+  satisfy = lift . satisfy
+  {-# INLINE satisfy #-}
+  char    = lift . char
+  {-# INLINE char #-}
+  notChar = lift . notChar
+  {-# INLINE notChar #-}
+  anyChar = lift anyChar
+  {-# INLINE anyChar #-}
+  string  = lift . string
+  {-# INLINE string #-}
+  text = lift . text
+  {-# INLINE text #-}
+
+instance (CharParsing m, MonadPlus m, Monoid w) => CharParsing (Strict.RWST r w s m) where
+  satisfy = lift . satisfy
+  {-# INLINE satisfy #-}
+  char    = lift . char
+  {-# INLINE char #-}
+  notChar = lift . notChar
+  {-# INLINE notChar #-}
+  anyChar = lift anyChar
+  {-# INLINE anyChar #-}
+  string  = lift . string
+  {-# INLINE string #-}
+  text = lift . text
+  {-# INLINE text #-}
+
+instance (CharParsing m, MonadPlus m) => CharParsing (IdentityT m) where
+  satisfy = lift . satisfy
+  {-# INLINE satisfy #-}
+  char    = lift . char
+  {-# INLINE char #-}
+  notChar = lift . notChar
+  {-# INLINE notChar #-}
+  anyChar = lift anyChar
+  {-# INLINE anyChar #-}
+  string  = lift . string
+  {-# INLINE string #-}
+  text = lift . text
+  {-# INLINE text #-}
+
+instance Parsec.Stream s m Char => CharParsing (Parsec.ParsecT s u m) where
+  satisfy   = Parsec.satisfy
+  char      = Parsec.char
+  notChar c = Parsec.satisfy (/= c)
+  anyChar   = Parsec.anyChar
+  string    = Parsec.string
+
+instance t ~ Char => CharParsing (ReadP.Parser r t) where
+  satisfy   = ReadP.satisfy
+  char      = ReadP.char
+  notChar c = ReadP.satisfy (/= c)
+  anyChar   = ReadP.get
+  string    = ReadP.string
+
+-------------------------------------------------------------------------------
+-- Our additions
+-------------------------------------------------------------------------------
+
+integral :: (CharParsing m, Integral a) => m a
+integral = toNumber <$> some d <?> "integral"
+  where
+    toNumber = foldl' (\a b -> a * 10 + b) 0
+    d = f <$> satisfyRange '0' '9'
+    f '0' = 0
+    f '1' = 1
+    f '2' = 2
+    f '3' = 3
+    f '4' = 4
+    f '5' = 5
+    f '6' = 6
+    f '7' = 7
+    f '8' = 8
+    f '9' = 9
+    f _   = error "panic! integral"
+{-# INLINE integral #-}
+
+-- | Greedily munch characters while predicate holds.
+-- Require at least one character.
+munch1 :: CharParsing m => (Char -> Bool) -> m String
+munch1 = some . satisfy
+{-# INLINE munch1 #-}
+
+-- | Greedely munch characters while predicate holds.
+-- Always succeeds.
+munch :: CharParsing m => (Char -> Bool) -> m String
+munch = many . satisfy
+{-# INLINE munch #-}
+
+skipSpaces1 :: CharParsing m => m ()
+skipSpaces1 = skipSome space
+{-# INLINE skipSpaces1 #-}
diff --git a/cabal/Cabal/Distribution/Compat/CopyFile.hs b/cabal/Cabal/Distribution/Compat/CopyFile.hs
--- a/cabal/Cabal/Distribution/Compat/CopyFile.hs
+++ b/cabal/Cabal/Distribution/Compat/CopyFile.hs
@@ -15,6 +15,8 @@
 import Distribution.Compat.Prelude
 
 import Distribution.Compat.Exception
+
+#ifndef mingw32_HOST_OS
 import Distribution.Compat.Internal.TempFile
 
 import Control.Exception
@@ -32,13 +34,29 @@
 import Foreign
          ( allocaBytes )
 
-#ifndef mingw32_HOST_OS
 import System.Posix.Types
          ( FileMode )
 import System.Posix.Internals
          ( c_chmod, withFilePath )
 import Foreign.C
          ( throwErrnoPathIfMinus1_ )
+
+#else /* else mingw32_HOST_OS */
+
+import Control.Exception
+  ( throwIO )
+import qualified Data.ByteString.Lazy as BSL
+import System.IO.Error
+  ( ioeSetLocation )
+import System.Directory
+  ( doesFileExist )
+import System.FilePath
+  ( isRelative, normalise )
+import System.IO
+  ( IOMode(ReadMode), hFileSize
+  , withBinaryFile )
+
+import qualified System.Win32.File as Win32 ( copyFile )
 #endif /* mingw32_HOST_OS */
 
 copyOrdinaryFile, copyExecutableFile :: FilePath -> FilePath -> NoCallStackIO ()
@@ -67,22 +85,45 @@
 copyFile fromFPath toFPath =
   copy
     `catchIO` (\ioe -> throwIO (ioeSetLocation ioe "copyFile"))
-    where copy = withBinaryFile fromFPath ReadMode $ \hFrom ->
-                 bracketOnError openTmp cleanTmp $ \(tmpFPath, hTmp) ->
-                 do allocaBytes bufferSize $ copyContents hFrom hTmp
-                    hClose hTmp
-                    renameFile tmpFPath toFPath
-          openTmp = openBinaryTempFile (takeDirectory toFPath) ".copyFile.tmp"
-          cleanTmp (tmpFPath, hTmp) = do
-            hClose hTmp          `catchIO` \_ -> return ()
-            removeFile tmpFPath  `catchIO` \_ -> return ()
-          bufferSize = 4096
+    where
+#ifndef mingw32_HOST_OS
+      copy = withBinaryFile fromFPath ReadMode $ \hFrom ->
+             bracketOnError openTmp cleanTmp $ \(tmpFPath, hTmp) ->
+             do allocaBytes bufferSize $ copyContents hFrom hTmp
+                hClose hTmp
+                renameFile tmpFPath toFPath
+      openTmp = openBinaryTempFile (takeDirectory toFPath) ".copyFile.tmp"
+      cleanTmp (tmpFPath, hTmp) = do
+        hClose hTmp          `catchIO` \_ -> return ()
+        removeFile tmpFPath  `catchIO` \_ -> return ()
+      bufferSize = 4096
 
-          copyContents hFrom hTo buffer = do
-                  count <- hGetBuf hFrom buffer bufferSize
-                  when (count > 0) $ do
-                          hPutBuf hTo buffer count
-                          copyContents hFrom hTo buffer
+      copyContents hFrom hTo buffer = do
+              count <- hGetBuf hFrom buffer bufferSize
+              when (count > 0) $ do
+                      hPutBuf hTo buffer count
+                      copyContents hFrom hTo buffer
+#else
+      copy = Win32.copyFile (toExtendedLengthPath fromFPath)
+                            (toExtendedLengthPath toFPath)
+                            False
+
+-- NOTE: Shamelessly lifted from System.Directory.Internal.Windows
+
+-- | Add the @"\\\\?\\"@ prefix if necessary or possible.  The path remains
+-- unchanged if the prefix is not added.  This function can sometimes be used
+-- to bypass the @MAX_PATH@ length restriction in Windows API calls.
+toExtendedLengthPath :: FilePath -> FilePath
+toExtendedLengthPath path
+  | isRelative path = path
+  | otherwise =
+      case normalise path of
+        '\\' : '?'  : '?' : '\\' : _ -> path
+        '\\' : '\\' : '?' : '\\' : _ -> path
+        '\\' : '\\' : '.' : '\\' : _ -> path
+        '\\' : subpath@('\\' : _) -> "\\\\?\\UNC" <> subpath
+        normalisedPath -> "\\\\?\\" <> normalisedPath
+#endif /* mingw32_HOST_OS */
 
 -- | Like `copyFile`, but does not touch the target if source and destination
 -- are already byte-identical. This is recommended as it is useful for
diff --git a/cabal/Cabal/Distribution/Compat/DList.hs b/cabal/Cabal/Distribution/Compat/DList.hs
--- a/cabal/Cabal/Distribution/Compat/DList.hs
+++ b/cabal/Cabal/Distribution/Compat/DList.hs
@@ -14,6 +14,7 @@
     runDList,
     singleton,
     fromList,
+    toList,
     snoc,
 ) where
 
@@ -32,6 +33,9 @@
 
 fromList :: [a] -> DList a
 fromList as = DList (as ++)
+
+toList :: DList a -> [a]
+toList = runDList
 
 snoc :: DList a -> a -> DList a
 snoc xs x = xs <> singleton x
diff --git a/cabal/Cabal/Distribution/Compat/Directory.hs b/cabal/Cabal/Distribution/Compat/Directory.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/Compat/Directory.hs
@@ -0,0 +1,44 @@
+{-# LANGUAGE CPP #-}
+
+module Distribution.Compat.Directory
+( listDirectory
+, makeAbsolute
+, doesPathExist
+) where
+
+#if MIN_VERSION_directory(1,2,7)
+import System.Directory as Dir hiding (doesPathExist)
+import System.Directory (doesPathExist)
+#else
+import System.Directory as Dir
+#endif
+#if !MIN_VERSION_directory(1,2,2)
+import System.FilePath as Path
+#endif
+
+#if !MIN_VERSION_directory(1,2,5)
+
+listDirectory :: FilePath -> IO [FilePath]
+listDirectory path =
+  filter f `fmap` Dir.getDirectoryContents path
+  where f filename = filename /= "." && filename /= ".."
+
+#endif
+
+#if !MIN_VERSION_directory(1,2,2)
+
+makeAbsolute :: FilePath -> IO FilePath
+makeAbsolute p | Path.isAbsolute p = return p
+               | otherwise         = do
+    cwd <- Dir.getCurrentDirectory
+    return $ cwd </> p
+
+#endif
+
+#if !MIN_VERSION_directory(1,2,7)
+
+doesPathExist :: FilePath -> IO Bool
+doesPathExist path = (||) <$> doesDirectoryExist path <*> doesFileExist path
+
+#endif
+
diff --git a/cabal/Cabal/Distribution/Compat/Environment.hs b/cabal/Cabal/Distribution/Compat/Environment.hs
--- a/cabal/Cabal/Distribution/Compat/Environment.hs
+++ b/cabal/Cabal/Distribution/Compat/Environment.hs
@@ -19,19 +19,18 @@
 #endif
 
 import qualified System.Environment as System
-#if __GLASGOW_HASKELL__ >= 706
 import System.Environment (lookupEnv)
 #if __GLASGOW_HASKELL__ >= 708
 import System.Environment (unsetEnv)
 #endif
-#else
-import Distribution.Compat.Exception (catchIO)
-#endif
 
 import Distribution.Compat.Stack
 
 #ifdef mingw32_HOST_OS
 import Foreign.C
+#if __GLASGOW_HASKELL__ < 708
+import Foreign.Ptr (nullPtr)
+#endif
 import GHC.Windows
 #else
 import Foreign.C.Types
@@ -53,13 +52,6 @@
 getEnvironment = System.getEnvironment
 #endif
 
-#if __GLASGOW_HASKELL__ < 706
--- | @lookupEnv var@ returns the value of the environment variable @var@, or
--- @Nothing@ if there is no such value.
-lookupEnv :: String -> IO (Maybe String)
-lookupEnv name = (Just `fmap` System.getEnv name) `catchIO` const (return Nothing)
-#endif /* __GLASGOW_HASKELL__ < 706 */
-
 -- | @setEnv name value@ sets the specified environment variable to @value@.
 --
 -- Throws `Control.Exception.IOException` if either @name@ or @value@ is the
@@ -124,6 +116,12 @@
     err <- c_GetLastError
     unless (err == eRROR_ENVVAR_NOT_FOUND) $ do
       throwGetLastError "unsetEnv"
+
+eRROR_ENVVAR_NOT_FOUND :: DWORD
+eRROR_ENVVAR_NOT_FOUND = 203
+
+foreign import WINDOWS_CCONV unsafe "windows.h GetLastError"
+    c_GetLastError:: IO DWORD
 #else
 unsetEnv key = withFilePath key (throwErrnoIf_ (/= 0) "unsetEnv" . c_unsetenv)
 #if __GLASGOW_HASKELL__ > 706
diff --git a/cabal/Cabal/Distribution/Compat/Graph.hs b/cabal/Cabal/Distribution/Compat/Graph.hs
--- a/cabal/Cabal/Distribution/Compat/Graph.hs
+++ b/cabal/Cabal/Distribution/Compat/Graph.hs
@@ -83,13 +83,6 @@
     nodeValue,
 ) where
 
--- For bootstrapping GHC
-#ifdef MIN_VERSION_containers
-#if MIN_VERSION_containers(0,5,0)
-#define HAVE_containers_050
-#endif
-#endif
-
 import Prelude ()
 import qualified Distribution.Compat.Prelude as Prelude
 import Distribution.Compat.Prelude hiding (lookup, null, empty)
@@ -97,11 +90,7 @@
 import Data.Graph (SCC(..))
 import qualified Data.Graph as G
 
-#ifdef HAVE_containers_050
 import qualified Data.Map.Strict as Map
-#else
-import qualified Data.Map as Map
-#endif
 import qualified Data.Set as Set
 import qualified Data.Array as Array
 import Data.Array ((!))
@@ -148,11 +137,9 @@
     foldr f z = Foldable.foldr f z . graphMap
     foldl f z = Foldable.foldl f z . graphMap
     foldMap f = Foldable.foldMap f . graphMap
-#ifdef MIN_VERSION_base
-#if MIN_VERSION_base(4,6,0)
     foldl' f z = Foldable.foldl' f z . graphMap
     foldr' f z = Foldable.foldr' f z . graphMap
-#endif
+#ifdef MIN_VERSION_base
 #if MIN_VERSION_base(4,8,0)
     length = Foldable.length . graphMap
     null   = Foldable.null   . graphMap
@@ -182,7 +169,7 @@
 -- type @'Key' a@; given a node we can determine its key ('nodeKey')
 -- and the keys of its neighbors ('nodeNeighbors').
 class Ord (Key a) => IsNode a where
-    type Key a :: *
+    type Key a
     nodeKey :: a -> Key a
     nodeNeighbors :: a -> [Key a]
 
diff --git a/cabal/Cabal/Distribution/Compat/Internal/TempFile.hs b/cabal/Cabal/Distribution/Compat/Internal/TempFile.hs
--- a/cabal/Cabal/Distribution/Compat/Internal/TempFile.hs
+++ b/cabal/Cabal/Distribution/Compat/Internal/TempFile.hs
@@ -33,7 +33,6 @@
 
 -- This is here for Haskell implementations that do not come with
 -- System.IO.openTempFile. This includes nhc-1.20, hugs-2006.9.
--- TODO: Not sure about JHC
 -- TODO: This file should probably be removed.
 
 -- This is a copy/paste of the openBinaryTempFile definition, but
diff --git a/cabal/Cabal/Distribution/Compat/Lens.hs b/cabal/Cabal/Distribution/Compat/Lens.hs
--- a/cabal/Cabal/Distribution/Compat/Lens.hs
+++ b/cabal/Cabal/Distribution/Compat/Lens.hs
@@ -21,6 +21,7 @@
     -- * Getter
     view,
     use,
+    getting,
     -- * Setter
     set,
     over,
@@ -33,8 +34,6 @@
     aview,
     -- * Common lenses
     _1, _2,
-    non,
-    fromNon,
     -- * Operators
     (&),
     (^.),
@@ -91,6 +90,14 @@
 use l = gets (view l)
 {-# INLINE use #-}
 
+-- | @since 2.4
+--
+-- >>> (3 :: Int) ^. getting (+2) . getting show
+-- "5"
+getting :: (s -> a) -> Getting r s a
+getting k f = Const . getConst . f . k
+{-# INLINE getting #-}
+
 -------------------------------------------------------------------------------
 -- Setter
 -------------------------------------------------------------------------------
@@ -121,6 +128,7 @@
 aview :: ALens s t a b -> s -> a
 aview l = pretextPos  . l pretextSell
 {-# INLINE aview #-}
+
 {-
 lens :: (s -> a) -> (s -> a -> s) -> Lens' s a
 lens sa sbt afb s = sbt s <$> afb (sa s)
@@ -136,24 +144,6 @@
 _2 ::  Lens (c, a) (c, b) a b
 _2 f (c, a) = (,) c <$> f a
 
--- | /Note:/ not an isomorphism here.
-non :: Eq a => a -> Lens' (Maybe a) a
-non def f s = wrap <$> f (unwrap s)
-  where
-    wrap x | x == def = Nothing
-    wrap x            = Just x
-
-    unwrap = fromMaybe def
-
-
-fromNon :: Eq a =>  a -> Lens' a (Maybe a)
-fromNon def f s = unwrap <$> f (wrap s)
-  where
-    wrap x | x == def = Nothing
-    wrap x            = Just x
-
-    unwrap = fromMaybe def
-
 -------------------------------------------------------------------------------
 -- Operators
 -------------------------------------------------------------------------------
@@ -250,7 +240,7 @@
 --
 -- First start a repl
 --
--- > cabal new-repl Cabal:parser-hackage-tests -fparsec-struct-diff
+-- > cabal new-repl Cabal:hackage-tests
 --
 -- Because @--extra-package@ isn't yet implemented, we use a test-suite
 -- with @generics-sop@ dependency.
diff --git a/cabal/Cabal/Distribution/Compat/Map/Strict.hs b/cabal/Cabal/Distribution/Compat/Map/Strict.hs
deleted file mode 100644
--- a/cabal/Cabal/Distribution/Compat/Map/Strict.hs
+++ /dev/null
@@ -1,31 +0,0 @@
-{-# LANGUAGE CPP #-}
-
--- For bootstrapping GHC
-#ifdef MIN_VERSION_containers
-#if MIN_VERSION_containers(0,5,0)
-#define HAVE_containers_050
-#endif
-#endif
-
-module Distribution.Compat.Map.Strict
-    ( module X
-#ifdef HAVE_containers_050
-#else
-    , insertWith
-    , fromSet
-#endif
-    ) where
-
-#ifdef HAVE_containers_050
-import Data.Map.Strict as X
-#else
-import Data.Map as X hiding (insertWith, insertWith')
-import qualified Data.Map
-import qualified Data.Set
-
-insertWith :: Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
-insertWith = Data.Map.insertWith'
-
-fromSet :: (k -> a) -> Data.Set.Set k -> Map k a
-fromSet f = Data.Map.fromDistinctAscList . Prelude.map (\k -> (k, f k)) . Data.Set.toList
-#endif
diff --git a/cabal/Cabal/Distribution/Compat/Parsec.hs b/cabal/Cabal/Distribution/Compat/Parsec.hs
deleted file mode 100644
--- a/cabal/Cabal/Distribution/Compat/Parsec.hs
+++ /dev/null
@@ -1,78 +0,0 @@
-{-# LANGUAGE FlexibleContexts #-}
-module Distribution.Compat.Parsec (
-    P.Parsec,
-    P.ParsecT,
-    P.Stream,
-    (P.<?>),
-
-    P.runParser,
-
-    -- * Combinators
-    P.between,
-    P.option,
-    P.optional,
-    P.optionMaybe,
-    P.try,
-    P.sepBy,
-    P.sepBy1,
-    P.choice,
-    P.eof,
-
-    -- * Char
-    integral,
-    P.char,
-    P.anyChar,
-    P.satisfy,
-    P.space,
-    P.spaces,
-    skipSpaces1,
-    P.string,
-    munch,
-    munch1,
-    P.oneOf,
-    ) where
-
-import           Distribution.Compat.Prelude
-import           Prelude ()
-
-import qualified Text.Parsec                 as P
-import qualified Text.Parsec.Pos             as P
-
-integral :: (P.Stream s m Char, Integral a) => P.ParsecT s u m a
-integral = toNumber <$> some d P.<?> "integral"
-  where
-    toNumber = foldl' (\a b -> a * 10 + b) 0
-    d = P.tokenPrim
-          (\c -> show [c])
-          (\pos c _cs -> P.updatePosChar pos c)
-          f
-    f '0' = Just 0
-    f '1' = Just 1
-    f '2' = Just 2
-    f '3' = Just 3
-    f '4' = Just 4
-    f '5' = Just 5
-    f '6' = Just 6
-    f '7' = Just 7
-    f '8' = Just 8
-    f '9' = Just 9
-    f _   = Nothing
-
--- | Greedily munch characters while predicate holds.
--- Require at least one character.
-munch1
-    :: P.Stream s m Char
-    => (Char -> Bool)
-    -> P.ParsecT s u m String
-munch1 = some . P.satisfy
-
--- | Greedely munch characters while predicate holds.
--- Always succeeds.
-munch
-    :: P.Stream s m Char
-    => (Char -> Bool)
-    -> P.ParsecT s u m String
-munch = many . P.satisfy
-
-skipSpaces1 :: P.Stream s m Char => P.ParsecT s u m ()
-skipSpaces1 = P.skipMany1 P.space
diff --git a/cabal/Cabal/Distribution/Compat/Parsing.hs b/cabal/Cabal/Distribution/Compat/Parsing.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/Compat/Parsing.hs
@@ -0,0 +1,403 @@
+{-# LANGUAGE GADTs, UndecidableInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Distribution.Compat.Parsing
+-- Copyright   :  (c) Edward Kmett 2011-2012
+-- License     :  BSD3
+--
+-- Maintainer  :  ekmett@gmail.com
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-- Alternative parser combinators.
+--
+-- Originally in @parsers@ package.
+--
+-----------------------------------------------------------------------------
+module Distribution.Compat.Parsing
+  (
+  -- * Parsing Combinators
+    choice
+  , option
+  , optional -- from Control.Applicative, parsec optionMaybe
+  , skipOptional -- parsec optional
+  , between
+  , some     -- from Control.Applicative, parsec many1
+  , many     -- from Control.Applicative
+  , sepBy
+  , sepBy1
+  -- , sepByNonEmpty
+  , sepEndBy1
+  -- , sepEndByNonEmpty
+  , sepEndBy
+  , endBy1
+  -- , endByNonEmpty
+  , endBy
+  , count
+  , chainl
+  , chainr
+  , chainl1
+  , chainr1
+  , manyTill
+  -- * Parsing Class
+  , Parsing(..)
+  ) where
+
+import Prelude ()
+import Distribution.Compat.Prelude
+
+import Control.Applicative ((<**>), optional)
+import Control.Monad.Trans.Class (lift)
+import Control.Monad.Trans.State.Lazy as Lazy
+import Control.Monad.Trans.State.Strict as Strict
+import Control.Monad.Trans.Writer.Lazy as Lazy
+import Control.Monad.Trans.Writer.Strict as Strict
+import Control.Monad.Trans.RWS.Lazy as Lazy
+import Control.Monad.Trans.RWS.Strict as Strict
+import Control.Monad.Trans.Reader (ReaderT (..))
+import Control.Monad.Trans.Identity (IdentityT (..))
+import Data.Foldable (asum)
+
+import qualified Text.Parsec as Parsec
+import qualified Distribution.Compat.ReadP as ReadP
+
+-- | @choice ps@ tries to apply the parsers in the list @ps@ in order,
+-- until one of them succeeds. Returns the value of the succeeding
+-- parser.
+choice :: Alternative m => [m a] -> m a
+choice = asum
+{-# INLINE choice #-}
+
+-- | @option x p@ tries to apply parser @p@. If @p@ fails without
+-- consuming input, it returns the value @x@, otherwise the value
+-- returned by @p@.
+--
+-- >  priority = option 0 (digitToInt <$> digit)
+option :: Alternative m => a -> m a -> m a
+option x p = p <|> pure x
+{-# INLINE option #-}
+
+-- | @skipOptional p@ tries to apply parser @p@.  It will parse @p@ or nothing.
+-- It only fails if @p@ fails after consuming input. It discards the result
+-- of @p@. (Plays the role of parsec's optional, which conflicts with Applicative's optional)
+skipOptional :: Alternative m => m a -> m ()
+skipOptional p = (() <$ p) <|> pure ()
+{-# INLINE skipOptional #-}
+
+-- | @between open close p@ parses @open@, followed by @p@ and @close@.
+-- Returns the value returned by @p@.
+--
+-- >  braces  = between (symbol "{") (symbol "}")
+between :: Applicative m => m bra -> m ket -> m a -> m a
+between bra ket p = bra *> p <* ket
+{-# INLINE between #-}
+
+-- | @sepBy p sep@ parses /zero/ or more occurrences of @p@, separated
+-- by @sep@. Returns a list of values returned by @p@.
+--
+-- >  commaSep p  = p `sepBy` (symbol ",")
+sepBy :: Alternative m => m a -> m sep -> m [a]
+sepBy p sep = sepBy1 p sep <|> pure []
+{-# INLINE sepBy #-}
+
+-- | @sepBy1 p sep@ parses /one/ or more occurrences of @p@, separated
+-- by @sep@. Returns a list of values returned by @p@.
+sepBy1 :: Alternative m => m a -> m sep -> m [a]
+sepBy1 p sep = (:) <$> p <*> many (sep *> p)
+-- toList <$> sepByNonEmpty p sep
+{-# INLINE sepBy1 #-}
+
+{-
+-- | @sepByNonEmpty p sep@ parses /one/ or more occurrences of @p@, separated
+-- by @sep@. Returns a non-empty list of values returned by @p@.
+sepByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a)
+sepByNonEmpty p sep = (:|) <$> p <*> many (sep *> p)
+{-# INLINE sepByNonEmpty #-}
+-}
+
+-- | @sepEndBy1 p sep@ parses /one/ or more occurrences of @p@,
+-- separated and optionally ended by @sep@. Returns a list of values
+-- returned by @p@.
+sepEndBy1 :: Alternative m => m a -> m sep -> m [a]
+sepEndBy1 p sep = (:) <$> p <*> ((sep *> sepEndBy p sep) <|> pure [])
+-- toList <$> sepEndByNonEmpty p sep
+
+{-
+-- | @sepEndByNonEmpty p sep@ parses /one/ or more occurrences of @p@,
+-- separated and optionally ended by @sep@. Returns a non-empty list of values
+-- returned by @p@.
+sepEndByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a)
+sepEndByNonEmpty p sep = (:|) <$> p <*> ((sep *> sepEndBy p sep) <|> pure [])
+-}
+
+-- | @sepEndBy p sep@ parses /zero/ or more occurrences of @p@,
+-- separated and optionally ended by @sep@, ie. haskell style
+-- statements. Returns a list of values returned by @p@.
+--
+-- >  haskellStatements  = haskellStatement `sepEndBy` semi
+sepEndBy :: Alternative m => m a -> m sep -> m [a]
+sepEndBy p sep = sepEndBy1 p sep <|> pure []
+{-# INLINE sepEndBy #-}
+
+-- | @endBy1 p sep@ parses /one/ or more occurrences of @p@, separated
+-- and ended by @sep@. Returns a list of values returned by @p@.
+endBy1 :: Alternative m => m a -> m sep -> m [a]
+endBy1 p sep = some (p <* sep)
+{-# INLINE endBy1 #-}
+
+{-
+-- | @endByNonEmpty p sep@ parses /one/ or more occurrences of @p@, separated
+-- and ended by @sep@. Returns a non-empty list of values returned by @p@.
+endByNonEmpty :: Alternative m => m a -> m sep -> m (NonEmpty a)
+endByNonEmpty p sep = some1 (p <* sep)
+{-# INLINE endByNonEmpty #-}
+-}
+
+-- | @endBy p sep@ parses /zero/ or more occurrences of @p@, separated
+-- and ended by @sep@. Returns a list of values returned by @p@.
+--
+-- >   cStatements  = cStatement `endBy` semi
+endBy :: Alternative m => m a -> m sep -> m [a]
+endBy p sep = many (p <* sep)
+{-# INLINE endBy #-}
+
+-- | @count n p@ parses @n@ occurrences of @p@. If @n@ is smaller or
+-- equal to zero, the parser equals to @return []@. Returns a list of
+-- @n@ values returned by @p@.
+count :: Applicative m => Int -> m a -> m [a]
+count n p | n <= 0    = pure []
+          | otherwise = sequenceA (replicate n p)
+{-# INLINE count #-}
+
+-- | @chainr p op x@ parses /zero/ or more occurrences of @p@,
+-- separated by @op@ Returns a value obtained by a /right/ associative
+-- application of all functions returned by @op@ to the values returned
+-- by @p@. If there are no occurrences of @p@, the value @x@ is
+-- returned.
+chainr :: Alternative m => m a -> m (a -> a -> a) -> a -> m a
+chainr p op x = chainr1 p op <|> pure x
+{-# INLINE chainr #-}
+
+-- | @chainl p op x@ parses /zero/ or more occurrences of @p@,
+-- separated by @op@. Returns a value obtained by a /left/ associative
+-- application of all functions returned by @op@ to the values returned
+-- by @p@. If there are zero occurrences of @p@, the value @x@ is
+-- returned.
+chainl :: Alternative m => m a -> m (a -> a -> a) -> a -> m a
+chainl p op x = chainl1 p op <|> pure x
+{-# INLINE chainl #-}
+
+-- | @chainl1 p op x@ parses /one/ or more occurrences of @p@,
+-- separated by @op@ Returns a value obtained by a /left/ associative
+-- application of all functions returned by @op@ to the values returned
+-- by @p@. . This parser can for example be used to eliminate left
+-- recursion which typically occurs in expression grammars.
+--
+-- >  expr   = term   `chainl1` addop
+-- >  term   = factor `chainl1` mulop
+-- >  factor = parens expr <|> integer
+-- >
+-- >  mulop  = (*) <$ symbol "*"
+-- >       <|> div <$ symbol "/"
+-- >
+-- >  addop  = (+) <$ symbol "+"
+-- >       <|> (-) <$ symbol "-"
+chainl1 :: Alternative m => m a -> m (a -> a -> a) -> m a
+chainl1 p op = scan where
+  scan = p <**> rst
+  rst = (\f y g x -> g (f x y)) <$> op <*> p <*> rst <|> pure id
+{-# INLINE chainl1 #-}
+
+-- | @chainr1 p op x@ parses /one/ or more occurrences of @p@,
+-- separated by @op@ Returns a value obtained by a /right/ associative
+-- application of all functions returned by @op@ to the values returned
+-- by @p@.
+chainr1 :: Alternative m => m a -> m (a -> a -> a) -> m a
+chainr1 p op = scan where
+  scan = p <**> rst
+  rst = (flip <$> op <*> scan) <|> pure id
+{-# INLINE chainr1 #-}
+
+-- | @manyTill p end@ applies parser @p@ /zero/ or more times until
+-- parser @end@ succeeds. Returns the list of values returned by @p@.
+-- This parser can be used to scan comments:
+--
+-- >  simpleComment   = do{ string "<!--"
+-- >                      ; manyTill anyChar (try (string "-->"))
+-- >                      }
+--
+--    Note the overlapping parsers @anyChar@ and @string \"-->\"@, and
+--    therefore the use of the 'try' combinator.
+manyTill :: Alternative m => m a -> m end -> m [a]
+manyTill p end = go where go = ([] <$ end) <|> ((:) <$> p <*> go)
+{-# INLINE manyTill #-}
+
+infixr 0 <?>
+
+-- | Additional functionality needed to describe parsers independent of input type.
+class Alternative m => Parsing m where
+  -- | Take a parser that may consume input, and on failure, go back to
+  -- where we started and fail as if we didn't consume input.
+  try :: m a -> m a
+
+  -- | Give a parser a name
+  (<?>) :: m a -> String -> m a
+
+  -- | A version of many that discards its input. Specialized because it
+  -- can often be implemented more cheaply.
+  skipMany :: m a -> m ()
+  skipMany p = () <$ many p
+  {-# INLINE skipMany #-}
+
+  -- | @skipSome p@ applies the parser @p@ /one/ or more times, skipping
+  -- its result. (aka skipMany1 in parsec)
+  skipSome :: m a -> m ()
+  skipSome p = p *> skipMany p
+  {-# INLINE skipSome #-}
+
+  -- | Used to emit an error on an unexpected token
+  unexpected :: String -> m a
+
+  -- | This parser only succeeds at the end of the input. This is not a
+  -- primitive parser but it is defined using 'notFollowedBy'.
+  --
+  -- >  eof  = notFollowedBy anyChar <?> "end of input"
+  eof :: m ()
+
+  -- | @notFollowedBy p@ only succeeds when parser @p@ fails. This parser
+  -- does not consume any input. This parser can be used to implement the
+  -- \'longest match\' rule. For example, when recognizing keywords (for
+  -- example @let@), we want to make sure that a keyword is not followed
+  -- by a legal identifier character, in which case the keyword is
+  -- actually an identifier (for example @lets@). We can program this
+  -- behaviour as follows:
+  --
+  -- >  keywordLet  = try $ string "let" <* notFollowedBy alphaNum
+  notFollowedBy :: Show a => m a -> m ()
+
+instance (Parsing m, MonadPlus m) => Parsing (Lazy.StateT s m) where
+  try (Lazy.StateT m) = Lazy.StateT $ try . m
+  {-# INLINE try #-}
+  Lazy.StateT m <?> l = Lazy.StateT $ \s -> m s <?> l
+  {-# INLINE (<?>) #-}
+  unexpected = lift . unexpected
+  {-# INLINE unexpected #-}
+  eof = lift eof
+  {-# INLINE eof #-}
+  notFollowedBy (Lazy.StateT m) = Lazy.StateT
+    $ \s -> notFollowedBy (fst <$> m s) >> return ((),s)
+  {-# INLINE notFollowedBy #-}
+
+instance (Parsing m, MonadPlus m) => Parsing (Strict.StateT s m) where
+  try (Strict.StateT m) = Strict.StateT $ try . m
+  {-# INLINE try #-}
+  Strict.StateT m <?> l = Strict.StateT $ \s -> m s <?> l
+  {-# INLINE (<?>) #-}
+  unexpected = lift . unexpected
+  {-# INLINE unexpected #-}
+  eof = lift eof
+  {-# INLINE eof #-}
+  notFollowedBy (Strict.StateT m) = Strict.StateT
+    $ \s -> notFollowedBy (fst <$> m s) >> return ((),s)
+  {-# INLINE notFollowedBy #-}
+
+instance (Parsing m, MonadPlus m) => Parsing (ReaderT e m) where
+  try (ReaderT m) = ReaderT $ try . m
+  {-# INLINE try #-}
+  ReaderT m <?> l = ReaderT $ \e -> m e <?> l
+  {-# INLINE (<?>) #-}
+  skipMany (ReaderT m) = ReaderT $ skipMany . m
+  {-# INLINE skipMany #-}
+  unexpected = lift . unexpected
+  {-# INLINE unexpected #-}
+  eof = lift eof
+  {-# INLINE eof #-}
+  notFollowedBy (ReaderT m) = ReaderT $ notFollowedBy . m
+  {-# INLINE notFollowedBy #-}
+
+instance (Parsing m, MonadPlus m, Monoid w) => Parsing (Strict.WriterT w m) where
+  try (Strict.WriterT m) = Strict.WriterT $ try m
+  {-# INLINE try #-}
+  Strict.WriterT m <?> l = Strict.WriterT (m <?> l)
+  {-# INLINE (<?>) #-}
+  unexpected = lift . unexpected
+  {-# INLINE unexpected #-}
+  eof = lift eof
+  {-# INLINE eof #-}
+  notFollowedBy (Strict.WriterT m) = Strict.WriterT
+    $ notFollowedBy (fst <$> m) >>= \x -> return (x, mempty)
+  {-# INLINE notFollowedBy #-}
+
+instance (Parsing m, MonadPlus m, Monoid w) => Parsing (Lazy.WriterT w m) where
+  try (Lazy.WriterT m) = Lazy.WriterT $ try m
+  {-# INLINE try #-}
+  Lazy.WriterT m <?> l = Lazy.WriterT (m <?> l)
+  {-# INLINE (<?>) #-}
+  unexpected = lift . unexpected
+  {-# INLINE unexpected #-}
+  eof = lift eof
+  {-# INLINE eof #-}
+  notFollowedBy (Lazy.WriterT m) = Lazy.WriterT
+    $ notFollowedBy (fst <$> m) >>= \x -> return (x, mempty)
+  {-# INLINE notFollowedBy #-}
+
+instance (Parsing m, MonadPlus m, Monoid w) => Parsing (Lazy.RWST r w s m) where
+  try (Lazy.RWST m) = Lazy.RWST $ \r s -> try (m r s)
+  {-# INLINE try #-}
+  Lazy.RWST m <?> l = Lazy.RWST $ \r s -> m r s <?> l
+  {-# INLINE (<?>) #-}
+  unexpected = lift . unexpected
+  {-# INLINE unexpected #-}
+  eof = lift eof
+  {-# INLINE eof #-}
+  notFollowedBy (Lazy.RWST m) = Lazy.RWST
+    $ \r s -> notFollowedBy ((\(a,_,_) -> a) <$> m r s) >>= \x -> return (x, s, mempty)
+  {-# INLINE notFollowedBy #-}
+
+instance (Parsing m, MonadPlus m, Monoid w) => Parsing (Strict.RWST r w s m) where
+  try (Strict.RWST m) = Strict.RWST $ \r s -> try (m r s)
+  {-# INLINE try #-}
+  Strict.RWST m <?> l = Strict.RWST $ \r s -> m r s <?> l
+  {-# INLINE (<?>) #-}
+  unexpected = lift . unexpected
+  {-# INLINE unexpected #-}
+  eof = lift eof
+  {-# INLINE eof #-}
+  notFollowedBy (Strict.RWST m) = Strict.RWST
+    $ \r s -> notFollowedBy ((\(a,_,_) -> a) <$> m r s) >>= \x -> return (x, s, mempty)
+  {-# INLINE notFollowedBy #-}
+
+instance (Parsing m, Monad m) => Parsing (IdentityT m) where
+  try = IdentityT . try . runIdentityT
+  {-# INLINE try #-}
+  IdentityT m <?> l = IdentityT (m <?> l)
+  {-# INLINE (<?>) #-}
+  skipMany = IdentityT . skipMany . runIdentityT
+  {-# INLINE skipMany #-}
+  unexpected = lift . unexpected
+  {-# INLINE unexpected #-}
+  eof = lift eof
+  {-# INLINE eof #-}
+  notFollowedBy (IdentityT m) = IdentityT $ notFollowedBy m
+  {-# INLINE notFollowedBy #-}
+
+instance (Parsec.Stream s m t, Show t) => Parsing (Parsec.ParsecT s u m) where
+  try           = Parsec.try
+  (<?>)         = (Parsec.<?>)
+  skipMany      = Parsec.skipMany
+  skipSome      = Parsec.skipMany1
+  unexpected    = Parsec.unexpected
+  eof           = Parsec.eof
+  notFollowedBy = Parsec.notFollowedBy
+
+instance t ~ Char => Parsing (ReadP.Parser r t) where
+  try        = id
+  (<?>)      = const
+  skipMany   = ReadP.skipMany
+  skipSome   = ReadP.skipMany1
+  unexpected = const ReadP.pfail
+  eof        = ReadP.eof
+
+  -- TODO: we would like to have <++ here
+  notFollowedBy p = ((Just <$> p) ReadP.+++ pure Nothing)
+    >>= maybe (pure ()) (unexpected . show)
diff --git a/cabal/Cabal/Distribution/Compat/Prelude.hs b/cabal/Cabal/Distribution/Compat/Prelude.hs
--- a/cabal/Cabal/Distribution/Compat/Prelude.hs
+++ b/cabal/Cabal/Distribution/Compat/Prelude.hs
@@ -6,11 +6,9 @@
 #ifdef MIN_VERSION_base
 #define MINVER_base_48 MIN_VERSION_base(4,8,0)
 #define MINVER_base_47 MIN_VERSION_base(4,7,0)
-#define MINVER_base_46 MIN_VERSION_base(4,6,0)
 #else
 #define MINVER_base_48 (__GLASGOW_HASKELL__ >= 710)
 #define MINVER_base_47 (__GLASGOW_HASKELL__ >= 708)
-#define MINVER_base_46 (__GLASGOW_HASKELL__ >= 706)
 #endif
 
 -- | This module does two things:
diff --git a/cabal/Cabal/Distribution/Compat/ReadP.hs b/cabal/Cabal/Distribution/Compat/ReadP.hs
--- a/cabal/Cabal/Distribution/Compat/ReadP.hs
+++ b/cabal/Cabal/Distribution/Compat/ReadP.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE GADTs #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Distribution.Compat.ReadP
@@ -69,21 +70,18 @@
   readP_to_S, -- :: ReadP a -> ReadS a
   readS_to_P, -- :: ReadS a -> ReadP a
 
-  -- ** Parsec
-  parsecToReadP,
+  -- ** Internal
+  Parser,
   )
  where
 
 import Prelude ()
 import Distribution.Compat.Prelude hiding (many, get)
-import Control.Applicative (liftA2)
 
 import qualified Distribution.Compat.MonadFail as Fail
 
 import Control.Monad( replicateM, (>=>) )
 
-import qualified Text.Parsec as P
-
 infixr 5 +++, <++
 
 -- ---------------------------------------------------------------------------
@@ -168,6 +166,10 @@
   pure x  = R (\k -> k x)
   (<*>) = ap
 
+instance s ~ Char => Alternative (Parser r s) where
+  empty = pfail
+  (<|>) = (+++)
+
 instance Monad (Parser r s) where
   return = pure
   fail = Fail.fail
@@ -176,9 +178,9 @@
 instance Fail.MonadFail (Parser r s) where
   fail _    = R (const Fail)
 
---instance MonadPlus (Parser r s) where
---  mzero = pfail
---  mplus = (+++)
+instance s ~ Char => MonadPlus (Parser r s) where
+  mzero = pfail
+  mplus = (+++)
 
 -- ---------------------------------------------------------------------------
 -- Operations over P
@@ -420,16 +422,3 @@
 --   parser, and therefore a possible inefficiency.
 readS_to_P r =
   R (\k -> Look (\s -> final [bs'' | (a,s') <- r s, bs'' <- run (k a) s']))
-
--- ---------------------------------------------------------------------------
--- Converting from Parsec to ReadP
---
--- | Convert @Parsec@ parser to 'ReadP'.
-parsecToReadP
-    :: P.Parsec [Char] u a
-    -> u                 -- ^ initial user state
-    -> ReadP r a
-parsecToReadP p u = R $ \k -> Look $ \s ->
-    case P.runParser (liftA2 (,) p P.getInput) u "<parsecToReadP>" s of
-        Right (x, s') -> final (run (k x) s')
-        Left _        -> Fail
diff --git a/cabal/Cabal/Distribution/Compat/Time.hs b/cabal/Cabal/Distribution/Compat/Time.hs
--- a/cabal/Cabal/Distribution/Compat/Time.hs
+++ b/cabal/Cabal/Distribution/Compat/Time.hs
@@ -23,13 +23,9 @@
 
 import Data.Time.Clock.POSIX ( POSIXTime, getPOSIXTime )
 import Data.Time             ( diffUTCTime, getCurrentTime )
-#if MIN_VERSION_directory(1,2,0)
 import Data.Time.Clock.POSIX ( posixDayLength )
-#else
-import System.Time ( getClockTime, diffClockTimes
-                   , normalizeTimeDiff, tdDay, tdHour )
-#endif
 
+
 #if defined mingw32_HOST_OS
 
 import qualified Prelude
@@ -135,12 +131,7 @@
     return $! (extractFileTime st)
 
 extractFileTime :: FileStatus -> ModTime
-#if MIN_VERSION_unix(2,6,0)
 extractFileTime x = posixTimeToModTime (modificationTimeHiRes x)
-#else
-extractFileTime x = posixSecondsToModTime $ fromIntegral $ fromEnum $
-                    modificationTime x
-#endif
 
 #endif
 
@@ -162,14 +153,8 @@
 getFileAge :: FilePath -> NoCallStackIO Double
 getFileAge file = do
   t0 <- getModificationTime file
-#if MIN_VERSION_directory(1,2,0)
   t1 <- getCurrentTime
   return $ realToFrac (t1 `diffUTCTime` t0) / realToFrac posixDayLength
-#else
-  t1 <- getClockTime
-  let dt = normalizeTimeDiff (t1 `diffClockTimes` t0)
-  return $ fromIntegral ((24 * tdDay dt) + tdHour dt) / 24.0
-#endif
 
 -- | Return the current time as 'ModTime'.
 getCurTime :: NoCallStackIO ModTime
diff --git a/cabal/Cabal/Distribution/Compiler.hs b/cabal/Cabal/Distribution/Compiler.hs
--- a/cabal/Cabal/Distribution/Compiler.hs
+++ b/cabal/Cabal/Distribution/Compiler.hs
@@ -16,7 +16,6 @@
 --
 -- > case compilerFlavor comp of
 -- >   GHC -> GHC.getInstalledPackages verbosity packageDb progdb
--- >   JHC -> JHC.getInstalledPackages verbosity packageDb progdb
 --
 -- Obviously it would be better to use the proper 'Compiler' abstraction
 -- because that would keep all the compiler-specific code together.
@@ -33,6 +32,7 @@
   defaultCompilerFlavor,
   parseCompilerFlavorCompat,
   classifyCompilerFlavor,
+  knownCompilerFlavors,
 
   -- * Compiler id
   CompilerId(..),
@@ -55,19 +55,22 @@
 import Distribution.Pretty (Pretty (..))
 import Distribution.Text (Text(..), display)
 import qualified Distribution.Compat.ReadP as Parse
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import qualified Text.PrettyPrint as Disp
 
 data CompilerFlavor =
-  GHC | GHCJS | NHC | YHC | Hugs | HBC | Helium | JHC | LHC | UHC
+  GHC | GHCJS | NHC | YHC | Hugs | HBC | Helium | JHC | LHC | UHC | Eta
   | HaskellSuite String -- string is the id of the actual compiler
   | OtherCompiler String
   deriving (Generic, Show, Read, Eq, Ord, Typeable, Data)
 
 instance Binary CompilerFlavor
 
+instance NFData CompilerFlavor where rnf = genericRnf
+
 knownCompilerFlavors :: [CompilerFlavor]
-knownCompilerFlavors = [GHC, GHCJS, NHC, YHC, Hugs, HBC, Helium, JHC, LHC, UHC]
+knownCompilerFlavors =
+  [GHC, GHCJS, NHC, YHC, Hugs, HBC, Helium, JHC, LHC, UHC, Eta]
 
 instance Pretty CompilerFlavor where
   pretty (OtherCompiler name) = Disp.text name
@@ -148,6 +151,8 @@
   deriving (Eq, Generic, Ord, Read, Show)
 
 instance Binary CompilerId
+
+instance NFData CompilerId where rnf = genericRnf
 
 instance Text CompilerId where
   disp (CompilerId f v)
diff --git a/cabal/Cabal/Distribution/FieldGrammar.hs b/cabal/Cabal/Distribution/FieldGrammar.hs
--- a/cabal/Cabal/Distribution/FieldGrammar.hs
+++ b/cabal/Cabal/Distribution/FieldGrammar.hs
@@ -8,7 +8,6 @@
     uniqueField,
     optionalField,
     optionalFieldDef,
-    optionalFieldDefAla,
     monoidalField,
     deprecatedField',
     -- * Concrete grammar implementations
@@ -32,7 +31,7 @@
 import Distribution.Compat.Prelude
 import Prelude ()
 
-import qualified Distribution.Compat.Map.Strict as Map
+import qualified Data.Map.Strict as Map
 
 import Distribution.FieldGrammar.Class
 import Distribution.FieldGrammar.Parsec
diff --git a/cabal/Cabal/Distribution/FieldGrammar/Class.hs b/cabal/Cabal/Distribution/FieldGrammar/Class.hs
--- a/cabal/Cabal/Distribution/FieldGrammar/Class.hs
+++ b/cabal/Cabal/Distribution/FieldGrammar/Class.hs
@@ -3,7 +3,6 @@
     uniqueField,
     optionalField,
     optionalFieldDef,
-    optionalFieldDefAla,
     monoidalField,
     deprecatedField',
     ) where
@@ -55,6 +54,15 @@
         -> ALens' s (Maybe a) -- ^ lens into the field
         -> g s (Maybe a)
 
+    -- | Optional field with default value.
+    optionalFieldDefAla
+        :: (Parsec b, Pretty b, Newtype b a, Eq a)
+        => FieldName   -- ^ field name
+        -> (a -> b)    -- ^ 'Newtype' pack
+        -> ALens' s a  -- ^ @'Lens'' s a@: lens into the field
+        -> a           -- ^ default value
+        -> g s a
+
     -- | Monoidal field.
     --
     -- Values are combined with 'mappend'.
@@ -90,6 +98,7 @@
     -- | Annotate field with since spec-version.
     availableSince
         :: [Int]  -- ^ spec version
+        -> a      -- ^ default value
         -> g s a
         -> g s a
 
@@ -111,23 +120,12 @@
 
 -- | Optional field with default value.
 optionalFieldDef
-    :: (FieldGrammar g, Functor (g s), Parsec a, Pretty a, Eq a, Show a)
+    :: (FieldGrammar g, Functor (g s), Parsec a, Pretty a, Eq a)
     => FieldName   -- ^ field name
-    -> LensLike' (Pretext (Maybe a) (Maybe a)) s a -- ^ @'Lens'' s a@: lens into the field
+    -> ALens' s a  -- ^ @'Lens'' s a@: lens into the field
     -> a           -- ^ default value
     -> g s a
 optionalFieldDef fn = optionalFieldDefAla fn Identity
-
--- | Optional field with default value.
-optionalFieldDefAla
-    :: (FieldGrammar g, Functor (g s), Parsec b, Pretty b, Newtype b a, Eq a, Show a)
-    => FieldName   -- ^ field name
-    -> (a -> b)    -- ^ 'Newtype' pack
-    -> LensLike' (Pretext (Maybe a) (Maybe a)) s a -- ^ @'Lens'' s a@: lens into the field
-    -> a           -- ^ default value
-    -> g s a
-optionalFieldDefAla fn pack l def =
-    fromMaybe def <$> optionalFieldAla fn pack (l . fromNon def)
 
 -- | Field which can be define multiple times, and the results are @mappend@ed.
 monoidalField
diff --git a/cabal/Cabal/Distribution/FieldGrammar/FieldDescrs.hs b/cabal/Cabal/Distribution/FieldGrammar/FieldDescrs.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/FieldGrammar/FieldDescrs.hs
@@ -0,0 +1,87 @@
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE RankNTypes    #-}
+{-# LANGUAGE NoMonoLocalBinds #-}
+module Distribution.FieldGrammar.FieldDescrs (
+    FieldDescrs,
+    fieldDescrPretty,
+    fieldDescrParse,
+    fieldDescrsToList,
+    ) where
+
+import Distribution.Compat.Prelude
+import Prelude ()
+
+import Distribution.Compat.Lens    (aview, cloneLens)
+import Distribution.Compat.Newtype
+import Distribution.FieldGrammar
+import Distribution.Pretty         (pretty)
+import Distribution.Utils.Generic  (fromUTF8BS)
+
+import qualified Data.Map                   as Map
+import qualified Distribution.Parsec.Class  as P
+import qualified Distribution.Parsec.Field  as P
+import qualified Text.PrettyPrint           as Disp
+
+-- strict pair
+data SP s = SP
+    { pPretty :: !(s -> Disp.Doc)
+    , pParse  :: !(forall m. P.CabalParsing m => s -> m s)
+    }
+
+-- | A collection field parsers and pretty-printers.
+newtype FieldDescrs s a = F { runF :: Map String (SP s) }
+  deriving (Functor)
+
+instance Applicative (FieldDescrs s) where
+    pure _  = F mempty
+    f <*> x = F (mappend (runF f) (runF x))
+
+singletonF :: P.FieldName -> (s -> Disp.Doc) -> (forall m. P.CabalParsing m => s -> m s) -> FieldDescrs s a
+singletonF fn f g = F $ Map.singleton (fromUTF8BS fn) (SP f g)
+
+-- | Lookup a field value pretty-printer.
+fieldDescrPretty :: FieldDescrs s a -> String -> Maybe (s -> Disp.Doc)
+fieldDescrPretty (F m) fn = pPretty <$> Map.lookup fn m
+
+-- | Lookup a field value parser.
+fieldDescrParse :: P.CabalParsing m => FieldDescrs s a -> String -> Maybe (s -> m s)
+fieldDescrParse (F m) fn = pParse <$> Map.lookup fn m
+
+fieldDescrsToList
+    :: P.CabalParsing m
+    => FieldDescrs s a
+    -> [(String, s -> Disp.Doc, s -> m s)]
+fieldDescrsToList = map mk . Map.toList . runF where
+    mk (name, SP ppr parse) = (name, ppr, parse)
+
+-- | /Note:/ default values are printed.
+instance FieldGrammar FieldDescrs where
+    blurFieldGrammar l (F m) = F (fmap blur m) where
+        blur (SP f g) = SP (f . aview l) (cloneLens l g)
+
+    booleanFieldDef fn l _def = singletonF fn f g where
+        f s = Disp.text (show (aview l s))
+        g s = cloneLens l (const P.parsec) s
+      -- Note: eta expansion is needed for RankNTypes type-checking to work.
+
+    uniqueFieldAla fn _pack l = singletonF fn f g where
+        f s = pretty (pack' _pack (aview l s))
+        g s = cloneLens l (const (unpack' _pack <$> P.parsec)) s
+
+    optionalFieldAla fn _pack l = singletonF fn f g where
+        f s = maybe mempty (pretty . pack' _pack) (aview l s)
+        g s = cloneLens l (const (Just . unpack' _pack <$> P.parsec)) s
+
+    optionalFieldDefAla fn _pack l _def = singletonF fn f g where
+        f s = pretty (pack' _pack (aview l s))
+        g s = cloneLens l (const (unpack' _pack <$> P.parsec)) s
+
+    monoidalFieldAla fn _pack l = singletonF fn f g where
+        f s = pretty (pack' _pack (aview l s))
+        g s = cloneLens l (\x -> mappend x . unpack' _pack <$> P.parsec) s
+
+    prefixedFields _fnPfx _l = F mempty
+    knownField _           = pure ()
+    deprecatedSince _  _ x = x
+    availableSince _ _     = id
+    hiddenField _          = F mempty
diff --git a/cabal/Cabal/Distribution/FieldGrammar/Parsec.hs b/cabal/Cabal/Distribution/FieldGrammar/Parsec.hs
--- a/cabal/Cabal/Distribution/FieldGrammar/Parsec.hs
+++ b/cabal/Cabal/Distribution/FieldGrammar/Parsec.hs
@@ -1,5 +1,6 @@
-{-# LANGUAGE DeriveFunctor     #-}
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE DeriveFunctor       #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 -- | This module provides a 'FieldGrammarParser', one way to parse
 -- @.cabal@ -like files.
 --
@@ -56,28 +57,32 @@
     -- * Auxiliary
     Fields,
     NamelessField (..),
+    namelessFieldAnn,
     Section (..),
     runFieldParser,
     runFieldParser',
     )  where
 
-import qualified Data.ByteString                as BS
-import           Data.List                      (dropWhileEnd)
-import           Data.Ord                       (comparing)
-import           Data.Set                       (Set)
-import qualified Data.Set                       as Set
-import qualified Distribution.Compat.Map.Strict as Map
-import           Distribution.Compat.Prelude
-import           Distribution.Compat.Newtype
-import           Distribution.Simple.Utils      (fromUTF8BS)
-import           Prelude ()
-import qualified Text.Parsec                    as P
-import qualified Text.Parsec.Error              as P
+import Data.List                   (dropWhileEnd)
+import Data.Ord                    (comparing)
+import Data.Set                    (Set)
+import Distribution.Compat.Newtype
+import Distribution.Compat.Prelude
+import Distribution.Simple.Utils   (fromUTF8BS)
+import Prelude ()
 
+import qualified Data.ByteString   as BS
+import qualified Data.Set          as Set
+import qualified Data.Map.Strict   as Map
+import qualified Text.Parsec       as P
+import qualified Text.Parsec.Error as P
+
+import Distribution.CabalSpecVersion
 import Distribution.FieldGrammar.Class
 import Distribution.Parsec.Class
 import Distribution.Parsec.Common
 import Distribution.Parsec.Field
+import Distribution.Parsec.FieldLineStream
 import Distribution.Parsec.ParseResult
 
 -------------------------------------------------------------------------------
@@ -90,6 +95,9 @@
 data NamelessField ann = MkNamelessField !ann [FieldLine ann]
   deriving (Eq, Show, Functor)
 
+namelessFieldAnn :: NamelessField ann -> ann
+namelessFieldAnn (MkNamelessField ann _) = ann
+
 -- | The 'Section' constructor of 'Field'.
 data Section ann = MkSection !(Name ann) [SectionArg ann] [Field ann]
   deriving (Eq, Show, Functor)
@@ -101,19 +109,19 @@
 data ParsecFieldGrammar s a = ParsecFG
     { fieldGrammarKnownFields   :: !(Set FieldName)
     , fieldGrammarKnownPrefixes :: !(Set FieldName)
-    , fieldGrammarParser        :: !(Fields Position -> ParseResult a)
+    , fieldGrammarParser        :: !(CabalSpecVersion -> Fields Position -> ParseResult a)
     }
   deriving (Functor)
 
-parseFieldGrammar :: Fields Position -> ParsecFieldGrammar s a -> ParseResult a
-parseFieldGrammar fields grammar = do
+parseFieldGrammar :: CabalSpecVersion -> Fields Position -> ParsecFieldGrammar s a -> ParseResult a
+parseFieldGrammar v fields grammar = do
     for_ (Map.toList (Map.filterWithKey isUnknownField fields)) $ \(name, nfields) ->
         for_ nfields $ \(MkNamelessField pos _) ->
             parseWarning pos PWTUnknownField $ "Unknown field: " ++ show name
             -- TODO: fields allowed in this section
 
     -- parse
-    fieldGrammarParser grammar fields
+    fieldGrammarParser grammar v fields
 
   where
     isUnknownField k _ = not $
@@ -124,73 +132,94 @@
 fieldGrammarKnownFieldList = Set.toList . fieldGrammarKnownFields
 
 instance Applicative (ParsecFieldGrammar s) where
-    pure x = ParsecFG mempty mempty (\_ ->  pure x)
+    pure x = ParsecFG mempty mempty (\_ _  -> pure x)
     {-# INLINE pure  #-}
 
     ParsecFG f f' f'' <*> ParsecFG x x' x'' = ParsecFG
         (mappend f x)
         (mappend f' x')
-        (\fields -> f'' fields <*> x'' fields)
+        (\v fields -> f'' v fields <*> x'' v fields)
     {-# INLINE (<*>) #-}
 
+warnMultipleSingularFields :: FieldName -> [NamelessField Position] -> ParseResult ()
+warnMultipleSingularFields _ [] = pure ()
+warnMultipleSingularFields fn (x : xs) = do
+    let pos  = namelessFieldAnn x
+        poss = map namelessFieldAnn xs
+    parseWarning pos PWTMultipleSingularField $
+        "The field " <> show fn <> " is specified more than once at positions " ++ intercalate ", " (map showPos (pos : poss))
+
 instance FieldGrammar ParsecFieldGrammar where
     blurFieldGrammar _ (ParsecFG s s' parser) = ParsecFG s s' parser
 
     uniqueFieldAla fn _pack _extract = ParsecFG (Set.singleton fn) Set.empty parser
       where
-        parser fields = case Map.lookup fn fields of
-            Nothing -> parseFatalFailure zeroPos $ show fn ++ " field missing:"
-            Just [] -> parseFatalFailure zeroPos $ show fn ++ " field foo"
-            Just [x] -> parseOne x
-            -- TODO: parse all
-            -- TODO: warn about duplicate fields?
-            Just xs-> parseOne (last xs)
+        parser v fields = case Map.lookup fn fields of
+            Nothing -> parseFatalFailure zeroPos $ show fn ++ " field missing"
+            Just [] -> parseFatalFailure zeroPos $ show fn ++ " field missing"
+            Just [x] -> parseOne v x
+            Just xs -> do
+                warnMultipleSingularFields fn xs
+                last <$> traverse (parseOne v) xs
 
-        parseOne (MkNamelessField pos fls) =
-            unpack' _pack <$> runFieldParser pos parsec fls
+        parseOne v (MkNamelessField pos fls) =
+            unpack' _pack <$> runFieldParser pos parsec v fls
 
     booleanFieldDef fn _extract def = ParsecFG (Set.singleton fn) Set.empty parser
       where
-        parser :: Fields Position -> ParseResult Bool
-        parser fields = case Map.lookup fn fields of
+        parser v fields = case Map.lookup fn fields of
             Nothing  -> pure def
             Just []  -> pure def
-            Just [x] -> parseOne x
-            -- TODO: parse all
-            -- TODO: warn about duplicate optional fields?
-            Just xs  -> parseOne (last xs)
+            Just [x] -> parseOne v x
+            Just xs  -> do
+                warnMultipleSingularFields fn xs
+                last <$> traverse (parseOne v) xs
 
-        parseOne (MkNamelessField pos fls) = runFieldParser pos parsec fls
+        parseOne v (MkNamelessField pos fls) = runFieldParser pos parsec v fls
 
     optionalFieldAla fn _pack _extract = ParsecFG (Set.singleton fn) Set.empty parser
       where
-        parser fields = case Map.lookup fn fields of
+        parser v fields = case Map.lookup fn fields of
             Nothing  -> pure Nothing
             Just []  -> pure Nothing
-            Just [x] -> parseOne x
-            -- TODO: parse all!
-            Just xs  -> parseOne (last xs) -- TODO: warn about duplicate optional fields?
+            Just [x] -> parseOne v x
+            Just xs  -> do
+                warnMultipleSingularFields fn xs
+                last <$> traverse (parseOne v) xs
 
-        parseOne (MkNamelessField pos fls)
+        parseOne v (MkNamelessField pos fls)
             | null fls  = pure Nothing
-            | otherwise = Just . (unpack' _pack) <$> runFieldParser pos parsec fls
+            | otherwise = Just . unpack' _pack <$> runFieldParser pos parsec v fls
 
+    optionalFieldDefAla fn _pack _extract def = ParsecFG (Set.singleton fn) Set.empty parser
+      where
+        parser v fields = case Map.lookup fn fields of
+            Nothing  -> pure def
+            Just []  -> pure def
+            Just [x] -> parseOne v x
+            Just xs  -> do
+                warnMultipleSingularFields fn xs
+                last <$> traverse (parseOne v) xs
+
+        parseOne v (MkNamelessField pos fls)
+            | null fls  = pure def
+            | otherwise = unpack' _pack <$> runFieldParser pos parsec v fls
+
     monoidalFieldAla fn _pack _extract = ParsecFG (Set.singleton fn) Set.empty parser
       where
-        parser fields = case Map.lookup fn fields of
+        parser v fields = case Map.lookup fn fields of
             Nothing -> pure mempty
-            Just xs -> foldMap (unpack' _pack) <$> traverse parseOne xs
+            Just xs -> foldMap (unpack' _pack) <$> traverse (parseOne v) xs
 
-        parseOne (MkNamelessField pos fls) = runFieldParser pos parsec fls
+        parseOne v (MkNamelessField pos fls) = runFieldParser pos parsec v fls
 
-    prefixedFields fnPfx _extract = ParsecFG mempty (Set.singleton fnPfx) (pure . parser)
+    prefixedFields fnPfx _extract = ParsecFG mempty (Set.singleton fnPfx) (\_ fs -> pure (parser fs))
       where
         parser :: Fields Position -> [(String, String)]
         parser values = reorder $ concatMap convert $ filter match $ Map.toList values
 
         match (fn, _) = fnPfx `BS.isPrefixOf` fn
         convert (fn, fields) =
-            -- TODO: warn about invalid UTF8
             [ (pos, (fromUTF8BS fn, trim $ fromUTF8BS $ fieldlinesToBS fls))
             | MkNamelessField pos fls <- fields
             ]
@@ -199,21 +228,33 @@
         trim :: String -> String
         trim = dropWhile isSpace . dropWhileEnd isSpace
 
-    availableSince _ = id
+    availableSince vs def (ParsecFG names prefixes parser) = ParsecFG names prefixes parser'
+      where
+        parser' v values
+            | cabalSpecSupports v vs = parser v values
+            | otherwise = do
+                let unknownFields = Map.intersection values $ Map.fromSet (const ()) names
+                for_ (Map.toList unknownFields) $ \(name, fields) ->
+                    for_ fields $ \(MkNamelessField pos _) ->
+                        parseWarning pos PWTUnknownField $
+                            "The field " <> show name <> " is available since Cabal " ++ show vs
 
+                pure def
+
+    -- todo we know about this field
     deprecatedSince (_ : _) _ grammar = grammar -- pass on non-empty version
     deprecatedSince _ msg (ParsecFG names prefixes parser) = ParsecFG names prefixes parser'
       where
-        parser' values = do
+        parser' v values = do
             let deprecatedFields = Map.intersection values $ Map.fromSet (const ()) names
             for_ (Map.toList deprecatedFields) $ \(name, fields) ->
                 for_ fields $ \(MkNamelessField pos _) ->
                     parseWarning pos PWTDeprecatedField $
                         "The field " <> show name <> " is deprecated. " ++ msg
 
-            parser values
+            parser v values
 
-    knownField fn = ParsecFG (Set.singleton fn) Set.empty (\_ -> pure ())
+    knownField fn = ParsecFG (Set.singleton fn) Set.empty (\_ _ -> pure ())
 
     hiddenField = id
 
@@ -221,8 +262,8 @@
 -- Parsec
 -------------------------------------------------------------------------------
 
-runFieldParser' :: Position -> FieldParser a -> String -> ParseResult a
-runFieldParser' (Position row col) p str = case P.runParser p' [] "<field>" str of
+runFieldParser' :: Position -> ParsecParser a -> CabalSpecVersion -> FieldLineStream -> ParseResult a
+runFieldParser' (Position row col) p v str = case P.runParser p' [] "<field>" str of
     Right (pok, ws) -> do
         -- TODO: map pos
         traverse_ (\(PWarning t pos w) -> parseWarning pos t w) ws
@@ -234,13 +275,18 @@
         let msg = P.showErrorMessages
                 "or" "unknown parse error" "expecting" "unexpected" "end of input"
                 (P.errorMessages err)
+        let str' = unlines (filter (not . all isSpace) (fieldLineStreamToLines str))
 
-        parseFatalFailure epos $ msg ++ ": " ++ show str
+        parseFatalFailure epos $ msg ++ "\n" ++ "\n" ++ str'
   where
-    p' = (,) <$ P.spaces <*> p <* P.spaces <* P.eof <*> P.getState
+    p' = (,) <$ P.spaces <*> unPP p v <* P.spaces <* P.eof <*> P.getState
 
-runFieldParser :: Position -> FieldParser a -> [FieldLine Position] -> ParseResult a
-runFieldParser pp p ls = runFieldParser' pos p =<< fieldlinesToString pos ls
+fieldLineStreamToLines :: FieldLineStream -> [String]
+fieldLineStreamToLines (FLSLast bs)   = [ fromUTF8BS bs ]
+fieldLineStreamToLines (FLSCons bs s) = fromUTF8BS bs : fieldLineStreamToLines s
+
+runFieldParser :: Position -> ParsecParser a -> CabalSpecVersion -> [FieldLine Position] -> ParseResult a
+runFieldParser pp p v ls = runFieldParser' pos p v (fieldLinesToStream ls)
   where
     -- TODO: make per line lookup
     pos = case ls of
@@ -249,12 +295,3 @@
 
 fieldlinesToBS :: [FieldLine ann] -> BS.ByteString
 fieldlinesToBS = BS.intercalate "\n" . map (\(FieldLine _ bs) -> bs)
-
--- TODO: Take position  from FieldLine
--- TODO: Take field name
-fieldlinesToString :: Position -> [FieldLine ann] -> ParseResult String
-fieldlinesToString pos fls =
-    let str = intercalate "\n" . map (\(FieldLine _ bs') -> fromUTF8BS bs') $ fls
-    in if '\xfffd' `elem` str
-        then str <$ parseWarning pos PWTUTF "Invalid UTF8 encoding"
-        else pure str
diff --git a/cabal/Cabal/Distribution/FieldGrammar/Pretty.hs b/cabal/Cabal/Distribution/FieldGrammar/Pretty.hs
--- a/cabal/Cabal/Distribution/FieldGrammar/Pretty.hs
+++ b/cabal/Cabal/Distribution/FieldGrammar/Pretty.hs
@@ -26,6 +26,8 @@
     PrettyFG f <*> PrettyFG x = PrettyFG (\s -> f s PP.$$ x s)
 
 -- | We can use 'PrettyFieldGrammar' to pp print the @s@.
+--
+-- /Note:/ there is not trailing @($+$ text "")@.
 prettyFieldGrammar :: PrettyFieldGrammar s a -> s -> Doc
 prettyFieldGrammar = fieldGrammarPretty
 
@@ -49,6 +51,14 @@
             Nothing -> mempty
             Just a  -> ppField (fromUTF8BS fn) (pretty (pack' _pack a))
 
+    optionalFieldDefAla fn _pack l def = PrettyFG pp
+      where
+        pp s
+            | x == def  = mempty
+            | otherwise = ppField (fromUTF8BS fn) (pretty (pack' _pack x))
+          where
+            x = aview l s
+
     monoidalFieldAla fn _pack l = PrettyFG pp
       where
         pp s = ppField  (fromUTF8BS fn) (pretty (pack' _pack (aview l s)))
@@ -66,5 +76,5 @@
     knownField _           = pure ()
     deprecatedSince [] _ _ = PrettyFG (\_ -> mempty)
     deprecatedSince _  _ x = x
-    availableSince _       = id
+    availableSince _ _     = id
     hiddenField _          = PrettyFG (\_ -> mempty)
diff --git a/cabal/Cabal/Distribution/InstalledPackageInfo.hs b/cabal/Cabal/Distribution/InstalledPackageInfo.hs
--- a/cabal/Cabal/Distribution/InstalledPackageInfo.hs
+++ b/cabal/Cabal/Distribution/InstalledPackageInfo.hs
@@ -1,7 +1,3 @@
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE TypeFamilies #-}
-
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Distribution.InstalledPackageInfo
@@ -41,94 +37,38 @@
         emptyInstalledPackageInfo,
         parseInstalledPackageInfo,
         showInstalledPackageInfo,
+        showFullInstalledPackageInfo,
         showInstalledPackageInfoField,
         showSimpleInstalledPackageInfoField,
-        fieldsInstalledPackageInfo,
   ) where
 
-import Prelude ()
 import Distribution.Compat.Prelude
+import Prelude ()
 
-import Distribution.ParseUtils
-import Distribution.License
-import Distribution.Package hiding (installedUnitId, installedPackageId)
+import Data.Set                              (Set)
 import Distribution.Backpack
-import qualified Distribution.Package as Package
+import Distribution.CabalSpecVersion         (cabalSpecLatest)
+import Distribution.FieldGrammar
+import Distribution.FieldGrammar.FieldDescrs
 import Distribution.ModuleName
-import Distribution.Version
-import Distribution.Text
-import qualified Distribution.Compat.ReadP as Parse
-import Distribution.Compat.Graph
-import Distribution.Types.MungedPackageId
+import Distribution.Package                  hiding (installedPackageId, installedUnitId)
+import Distribution.ParseUtils
 import Distribution.Types.ComponentName
-import Distribution.Types.MungedPackageName
-import Distribution.Types.UnqualComponentName
+import Distribution.Utils.Generic            (toUTF8BS)
 
-import Text.PrettyPrint as Disp
-import qualified Data.Char as Char
-import qualified Data.Map as Map
-import Data.Set (Set)
+import qualified Data.Map                        as Map
+import qualified Distribution.Parsec.Common      as P
+import qualified Distribution.Parsec.Parser      as P
+import qualified Distribution.Parsec.ParseResult as P
+import qualified Text.Parsec.Error               as Parsec
+import qualified Text.Parsec.Pos                 as Parsec
+import qualified Text.PrettyPrint                as Disp
 
--- -----------------------------------------------------------------------------
--- The InstalledPackageInfo type
+import Distribution.Types.InstalledPackageInfo
+import Distribution.Types.InstalledPackageInfo.FieldGrammar
 
--- 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
-        sourcePackageId   :: PackageId,
-        installedUnitId   :: UnitId,
-        installedComponentId_ :: ComponentId,
-        -- INVARIANT: if this package is definite, OpenModule's
-        -- OpenUnitId directly records UnitId.  If it is
-        -- indefinite, OpenModule is always an OpenModuleVar
-        -- with the same ModuleName as the key.
-        instantiatedWith  :: [(ModuleName, OpenModule)],
-        sourceLibName     :: Maybe UnqualComponentName,
-        compatPackageKey  :: String,
-        license           :: License,
-        copyright         :: String,
-        maintainer        :: String,
-        author            :: String,
-        stability         :: String,
-        homepage          :: String,
-        pkgUrl            :: String,
-        synopsis          :: String,
-        description       :: String,
-        category          :: String,
-        -- these parts are required by an installed package only:
-        abiHash           :: AbiHash,
-        indefinite        :: Bool,
-        exposed           :: Bool,
-        -- INVARIANT: if the package is definite, OpenModule's
-        -- OpenUnitId directly records UnitId.
-        exposedModules    :: [ExposedModule],
-        hiddenModules     :: [ModuleName],
-        trusted           :: Bool,
-        importDirs        :: [FilePath],
-        libraryDirs       :: [FilePath],
-        libraryDynDirs    :: [FilePath],  -- ^ overrides 'libraryDirs'
-        dataDir           :: FilePath,
-        hsLibraries       :: [String],
-        extraLibraries    :: [String],
-        extraGHCiLibraries:: [String],    -- overrides extraLibraries for GHCi
-        includeDirs       :: [FilePath],
-        includes          :: [String],
-        -- INVARIANT: if the package is definite, UnitId is NOT
-        -- a ComponentId of an indefinite package
-        depends           :: [UnitId],
-        abiDepends        :: [AbiDependency],
-        ccOptions         :: [String],
-        ldOptions         :: [String],
-        frameworkDirs     :: [FilePath],
-        frameworks        :: [String],
-        haddockInterfaces :: [FilePath],
-        haddockHTMLs      :: [FilePath],
-        pkgRoot           :: Maybe FilePath
-    }
-    deriving (Eq, Generic, Typeable, Read, Show)
 
+
 installedComponentId :: InstalledPackageInfo -> ComponentId
 installedComponentId ipi =
     case unComponentId (installedComponentId_ ipi) of
@@ -158,151 +98,7 @@
 installedPackageId :: InstalledPackageInfo -> UnitId
 installedPackageId = installedUnitId
 
-instance Binary InstalledPackageInfo
-
-instance Package.HasMungedPackageId InstalledPackageInfo where
-   mungedId = mungedPackageId
-
-instance Package.Package InstalledPackageInfo where
-   packageId = sourcePackageId
-
-instance Package.HasUnitId InstalledPackageInfo where
-   installedUnitId = installedUnitId
-
-instance Package.PackageInstalled InstalledPackageInfo where
-   installedDepends = depends
-
-instance IsNode InstalledPackageInfo where
-    type Key InstalledPackageInfo = UnitId
-    nodeKey       = installedUnitId
-    nodeNeighbors = depends
-
-emptyInstalledPackageInfo :: InstalledPackageInfo
-emptyInstalledPackageInfo
-   = InstalledPackageInfo {
-        sourcePackageId   = PackageIdentifier (mkPackageName "") nullVersion,
-        installedUnitId   = mkUnitId "",
-        installedComponentId_ = mkComponentId "",
-        instantiatedWith  = [],
-        sourceLibName     = Nothing,
-        compatPackageKey  = "",
-        license           = UnspecifiedLicense,
-        copyright         = "",
-        maintainer        = "",
-        author            = "",
-        stability         = "",
-        homepage          = "",
-        pkgUrl            = "",
-        synopsis          = "",
-        description       = "",
-        category          = "",
-        abiHash           = mkAbiHash "",
-        indefinite        = False,
-        exposed           = False,
-        exposedModules    = [],
-        hiddenModules     = [],
-        trusted           = False,
-        importDirs        = [],
-        libraryDirs       = [],
-        libraryDynDirs    = [],
-        dataDir           = "",
-        hsLibraries       = [],
-        extraLibraries    = [],
-        extraGHCiLibraries= [],
-        includeDirs       = [],
-        includes          = [],
-        depends           = [],
-        abiDepends        = [],
-        ccOptions         = [],
-        ldOptions         = [],
-        frameworkDirs     = [],
-        frameworks        = [],
-        haddockInterfaces = [],
-        haddockHTMLs      = [],
-        pkgRoot           = Nothing
-    }
-
 -- -----------------------------------------------------------------------------
--- Exposed modules
-
-data ExposedModule
-   = ExposedModule {
-       exposedName      :: ModuleName,
-       exposedReexport  :: Maybe OpenModule
-     }
-  deriving (Eq, Generic, Read, Show)
-
-instance Text ExposedModule where
-    disp (ExposedModule m reexport) =
-        Disp.hsep [ disp m
-                  , case reexport of
-                     Just m' -> Disp.hsep [Disp.text "from", disp m']
-                     Nothing -> Disp.empty
-                  ]
-    parse = do
-        m <- parseModuleNameQ
-        Parse.skipSpaces
-        reexport <- Parse.option Nothing $ do
-            _ <- Parse.string "from"
-            Parse.skipSpaces
-            fmap Just parse
-        return (ExposedModule m reexport)
-
-instance Binary ExposedModule
-
--- To maintain backwards-compatibility, we accept both comma/non-comma
--- separated variants of this field.  You SHOULD use the comma syntax if you
--- use any new functions, although actually it's unambiguous due to a quirk
--- of the fact that modules must start with capital letters.
-
-showExposedModules :: [ExposedModule] -> Disp.Doc
-showExposedModules xs
-    | all isExposedModule xs = fsep (map disp xs)
-    | otherwise = fsep (Disp.punctuate comma (map disp xs))
-    where isExposedModule (ExposedModule _ Nothing) = True
-          isExposedModule _ = False
-
-parseExposedModules :: Parse.ReadP r [ExposedModule]
-parseExposedModules = parseOptCommaList parse
-
-dispMaybe :: Text a => Maybe a -> Disp.Doc
-dispMaybe Nothing = Disp.empty
-dispMaybe (Just x) = disp x
-
-parseMaybe :: Text a => Parse.ReadP r (Maybe a)
-parseMaybe = fmap Just parse Parse.<++ return Nothing
-
--- -----------------------------------------------------------------------------
--- ABI dependency
-
--- | An ABI dependency is a dependency on a library which also
--- records the ABI hash ('abiHash') of the library it depends
--- on.
---
--- The primary utility of this is to enable an extra sanity when
--- GHC loads libraries: it can check if the dependency has a matching
--- ABI and if not, refuse to load this library.  This information
--- is critical if we are shadowing libraries; differences in the
--- ABI hash let us know what packages get shadowed by the new version
--- of a package.
-data AbiDependency = AbiDependency {
-        depUnitId  :: UnitId,
-        depAbiHash :: AbiHash
-    }
-  deriving (Eq, Generic, Read, Show)
-
-instance Text AbiDependency where
-    disp (AbiDependency uid abi) =
-        disp uid <<>> Disp.char '=' <<>> disp abi
-    parse = do
-        uid <- parse
-        _ <- Parse.char '='
-        abi <- parse
-        return (AbiDependency uid abi)
-
-instance Binary AbiDependency
-
--- -----------------------------------------------------------------------------
 -- Munging
 
 sourceComponentName :: InstalledPackageInfo -> ComponentName
@@ -311,207 +107,44 @@
         Nothing -> CLibName
         Just qn -> CSubLibName qn
 
--- | Returns @Just@ if the @name@ field of the IPI record would not contain
--- the package name verbatim.  This helps us avoid writing @package-name@
--- when it's redundant.
-maybePackageName :: InstalledPackageInfo -> Maybe PackageName
-maybePackageName ipi =
-    case sourceLibName ipi of
-        Nothing -> Nothing
-        Just _ -> Just (packageName ipi)
-
--- | Setter for the @package-name@ field.  It should be acceptable for this
--- to be a no-op.
-setMaybePackageName :: Maybe PackageName -> InstalledPackageInfo -> InstalledPackageInfo
-setMaybePackageName Nothing ipi = ipi
-setMaybePackageName (Just pn) ipi = ipi {
-        sourcePackageId=(sourcePackageId ipi){pkgName=pn}
-    }
-
--- | Returns the munged package name, which we write into @name@ for
--- compatibility with old versions of GHC.
-mungedPackageName :: InstalledPackageInfo -> MungedPackageName
-mungedPackageName ipi =
-    computeCompatPackageName
-        (packageName ipi)
-        (sourceLibName ipi)
-
-setMungedPackageName :: MungedPackageName -> InstalledPackageInfo -> InstalledPackageInfo
-setMungedPackageName mpn ipi =
-    let (pn, mb_uqn) = decodeCompatPackageName mpn
-    in ipi {
-            sourcePackageId = (sourcePackageId ipi) {pkgName=pn},
-            sourceLibName   = mb_uqn
-        }
-
-mungedPackageId :: InstalledPackageInfo -> MungedPackageId
-mungedPackageId ipi =
-    MungedPackageId (mungedPackageName ipi) (packageVersion ipi)
-
 -- -----------------------------------------------------------------------------
 -- Parsing
 
 parseInstalledPackageInfo :: String -> ParseResult InstalledPackageInfo
-parseInstalledPackageInfo =
-    parseFieldsFlat (fieldsInstalledPackageInfo ++ deprecatedFieldDescrs)
-    emptyInstalledPackageInfo
+parseInstalledPackageInfo s = case P.readFields (toUTF8BS s) of
+    Left err -> ParseFailed (NoParse (show err) $ Parsec.sourceLine $ Parsec.errorPos err)
+    Right fs -> case partitionFields fs of
+        (fs', _) -> case P.runParseResult $ parseFieldGrammar cabalSpecLatest fs' ipiFieldGrammar of
+            (ws, Right x) -> ParseOk ws' x where
+                ws' = map (PWarning . P.showPWarning "") ws
+            (_,  Left (_, errs)) -> ParseFailed (NoParse errs' 0) where
+                errs' = intercalate "; " $ map (\(P.PError _ msg) -> msg) errs
 
 -- -----------------------------------------------------------------------------
 -- Pretty-printing
 
+-- | Pretty print 'InstalledPackageInfo'.
+--
+-- @pkgRoot@ isn't printed, as ghc-pkg prints it manually (as GHC-8.4).
 showInstalledPackageInfo :: InstalledPackageInfo -> String
-showInstalledPackageInfo = showFields fieldsInstalledPackageInfo
+showInstalledPackageInfo ipi =
+    showFullInstalledPackageInfo ipi { pkgRoot = Nothing }
 
+-- | The variant of 'showInstalledPackageInfo' which outputs @pkgroot@ field too.
+showFullInstalledPackageInfo :: InstalledPackageInfo -> String
+showFullInstalledPackageInfo = Disp.render . (Disp.$+$ Disp.text "") . prettyFieldGrammar ipiFieldGrammar
+
+-- |
+--
+-- >>> let ipi = emptyInstalledPackageInfo { maintainer = "Tester" }
+-- >>> fmap ($ ipi) $ showInstalledPackageInfoField "maintainer"
+-- Just "maintainer: Tester"
 showInstalledPackageInfoField :: String -> Maybe (InstalledPackageInfo -> String)
-showInstalledPackageInfoField = showSingleNamedField fieldsInstalledPackageInfo
+showInstalledPackageInfoField fn =
+    fmap (\g -> Disp.render . ppField fn . g) $ fieldDescrPretty ipiFieldGrammar fn
 
 showSimpleInstalledPackageInfoField :: String -> Maybe (InstalledPackageInfo -> String)
-showSimpleInstalledPackageInfoField = showSimpleSingleNamedField fieldsInstalledPackageInfo
-
-dispCompatPackageKey :: String -> Doc
-dispCompatPackageKey = text
-
-parseCompatPackageKey :: Parse.ReadP r String
-parseCompatPackageKey = Parse.munch1 uid_char
-    where uid_char c = Char.isAlphaNum c || c `elem` "-_.=[],:<>+"
-
--- -----------------------------------------------------------------------------
--- Description of the fields, for parsing/printing
-
-fieldsInstalledPackageInfo :: [FieldDescr InstalledPackageInfo]
-fieldsInstalledPackageInfo = basicFieldDescrs ++ installedFieldDescrs
-
-basicFieldDescrs :: [FieldDescr InstalledPackageInfo]
-basicFieldDescrs =
- [ simpleField "name"
-                           disp                   (parseMaybeQuoted parse)
-                           mungedPackageName      setMungedPackageName
- , simpleField "version"
-                           disp                   parseOptVersion
-                           packageVersion         (\ver pkg -> pkg{sourcePackageId=(sourcePackageId pkg){pkgVersion=ver}})
- , simpleField "id"
-                           disp                   parse
-                           installedUnitId        (\pk pkg -> pkg{installedUnitId=pk})
- , simpleField "instantiated-with"
-        (dispOpenModuleSubst . Map.fromList)    (fmap Map.toList parseOpenModuleSubst)
-        instantiatedWith   (\iw    pkg -> pkg{instantiatedWith=iw})
- , simpleField "package-name"
-                           dispMaybe              parseMaybe
-                           maybePackageName       setMaybePackageName
- , simpleField "lib-name"
-                           dispMaybe              parseMaybe
-                           sourceLibName          (\n pkg -> pkg{sourceLibName=n})
- , simpleField "key"
-                           dispCompatPackageKey   parseCompatPackageKey
-                           compatPackageKey       (\pk pkg -> pkg{compatPackageKey=pk})
- , simpleField "license"
-                           disp                   parseLicenseQ
-                           license                (\l pkg -> pkg{license=l})
- , simpleField "copyright"
-                           showFreeText           parseFreeText
-                           copyright              (\val pkg -> pkg{copyright=val})
- , simpleField "maintainer"
-                           showFreeText           parseFreeText
-                           maintainer             (\val pkg -> pkg{maintainer=val})
- , simpleField "stability"
-                           showFreeText           parseFreeText
-                           stability              (\val pkg -> pkg{stability=val})
- , simpleField "homepage"
-                           showFreeText           parseFreeText
-                           homepage               (\val pkg -> pkg{homepage=val})
- , simpleField "package-url"
-                           showFreeText           parseFreeText
-                           pkgUrl                 (\val pkg -> pkg{pkgUrl=val})
- , simpleField "synopsis"
-                           showFreeText           parseFreeText
-                           synopsis               (\val pkg -> pkg{synopsis=val})
- , simpleField "description"
-                           showFreeText           parseFreeText
-                           description            (\val pkg -> pkg{description=val})
- , simpleField "category"
-                           showFreeText           parseFreeText
-                           category               (\val pkg -> pkg{category=val})
- , simpleField "author"
-                           showFreeText           parseFreeText
-                           author                 (\val pkg -> pkg{author=val})
- ]
-
-installedFieldDescrs :: [FieldDescr InstalledPackageInfo]
-installedFieldDescrs = [
-   boolField "exposed"
-        exposed            (\val pkg -> pkg{exposed=val})
- , boolField "indefinite"
-        indefinite         (\val pkg -> pkg{indefinite=val})
- , simpleField "exposed-modules"
-        showExposedModules parseExposedModules
-        exposedModules     (\xs    pkg -> pkg{exposedModules=xs})
- , listField   "hidden-modules"
-        disp               parseModuleNameQ
-        hiddenModules      (\xs    pkg -> pkg{hiddenModules=xs})
- , simpleField "abi"
-        disp               parse
-        abiHash            (\abi    pkg -> pkg{abiHash=abi})
- , boolField   "trusted"
-        trusted            (\val pkg -> pkg{trusted=val})
- , listField   "import-dirs"
-        showFilePath       parseFilePathQ
-        importDirs         (\xs pkg -> pkg{importDirs=xs})
- , listField   "library-dirs"
-        showFilePath       parseFilePathQ
-        libraryDirs        (\xs pkg -> pkg{libraryDirs=xs})
- , listField   "dynamic-library-dirs"
-        showFilePath       parseFilePathQ
-        libraryDynDirs     (\xs pkg -> pkg{libraryDynDirs=xs})
- , simpleField "data-dir"
-        showFilePath       (parseFilePathQ Parse.<++ return "")
-        dataDir            (\val pkg -> pkg{dataDir=val})
- , listField   "hs-libraries"
-        showFilePath       parseTokenQ
-        hsLibraries        (\xs pkg -> pkg{hsLibraries=xs})
- , listField   "extra-libraries"
-        showToken          parseTokenQ
-        extraLibraries     (\xs pkg -> pkg{extraLibraries=xs})
- , listField   "extra-ghci-libraries"
-        showToken          parseTokenQ
-        extraGHCiLibraries (\xs pkg -> pkg{extraGHCiLibraries=xs})
- , listField   "include-dirs"
-        showFilePath       parseFilePathQ
-        includeDirs        (\xs pkg -> pkg{includeDirs=xs})
- , listField   "includes"
-        showFilePath       parseFilePathQ
-        includes           (\xs pkg -> pkg{includes=xs})
- , listField   "depends"
-        disp               parse
-        depends            (\xs pkg -> pkg{depends=xs})
- , listField   "abi-depends"
-        disp               parse
-        abiDepends         (\xs pkg -> pkg{abiDepends=xs})
- , listField   "cc-options"
-        showToken          parseTokenQ
-        ccOptions          (\path  pkg -> pkg{ccOptions=path})
- , listField   "ld-options"
-        showToken          parseTokenQ
-        ldOptions          (\path  pkg -> pkg{ldOptions=path})
- , listField   "framework-dirs"
-        showFilePath       parseFilePathQ
-        frameworkDirs      (\xs pkg -> pkg{frameworkDirs=xs})
- , listField   "frameworks"
-        showToken          parseTokenQ
-        frameworks         (\xs pkg -> pkg{frameworks=xs})
- , listField   "haddock-interfaces"
-        showFilePath       parseFilePathQ
-        haddockInterfaces  (\xs pkg -> pkg{haddockInterfaces=xs})
- , listField   "haddock-html"
-        showFilePath       parseFilePathQ
-        haddockHTMLs       (\xs pkg -> pkg{haddockHTMLs=xs})
- , simpleField "pkgroot"
-        (const Disp.empty)        parseFilePathQ
-        (fromMaybe "" . pkgRoot)  (\xs pkg -> pkg{pkgRoot=Just xs})
- ]
-
-deprecatedFieldDescrs :: [FieldDescr InstalledPackageInfo]
-deprecatedFieldDescrs = [
-   listField   "hugs-options"
-        showToken          parseTokenQ
-        (const [])        (const id)
-  ]
+showSimpleInstalledPackageInfoField fn =
+    fmap (Disp.renderStyle myStyle .) $ fieldDescrPretty ipiFieldGrammar fn
+  where
+    myStyle = Disp.style { Disp.mode = Disp.LeftMode }
diff --git a/cabal/Cabal/Distribution/License.hs b/cabal/Cabal/Distribution/License.hs
--- a/cabal/Cabal/Distribution/License.hs
+++ b/cabal/Cabal/Distribution/License.hs
@@ -45,6 +45,8 @@
 module Distribution.License (
     License(..),
     knownLicenses,
+    licenseToSPDX,
+    licenseFromSPDX,
   ) where
 
 import Distribution.Compat.Prelude
@@ -55,9 +57,11 @@
 import Distribution.Text
 import Distribution.Version
 
-import qualified Distribution.Compat.Parsec as P
-import qualified Distribution.Compat.ReadP  as Parse
-import qualified Text.PrettyPrint           as Disp
+import qualified Distribution.Compat.CharParsing as P
+import qualified Data.Map.Strict                 as Map
+import qualified Distribution.Compat.ReadP       as Parse
+import qualified Distribution.SPDX               as SPDX
+import qualified Text.PrettyPrint                as Disp
 
 -- | Indicates the license under which a package's source code is released.
 -- Versions of the licenses not listed here will be rejected by Hackage and
@@ -127,6 +131,8 @@
 
 instance Binary License
 
+instance NFData License where rnf = genericRnf
+
 -- | The list of all currently recognised licenses.
 knownLicenses :: [License]
 knownLicenses = [ GPL  unversioned, GPL  (version [2]),    GPL  (version [3])
@@ -136,10 +142,80 @@
                 , MPL (mkVersion [2, 0])
                 , Apache unversioned, Apache (version [2, 0])
                 , PublicDomain, AllRightsReserved, OtherLicense]
- where
-   unversioned = Nothing
-   version     = Just . mkVersion
+  where
+    unversioned = Nothing
+    version     = Just . mkVersion
 
+-- | Convert old 'License' to SPDX 'SPDX.License'.
+-- Non-SPDX licenses are converted to 'SPDX.LicenseRef'.
+--
+-- @since 2.2.0.0
+licenseToSPDX :: License -> SPDX.License
+licenseToSPDX l = case l of
+    GPL v | v == version [2]      -> spdx SPDX.GPL_2_0_only
+    GPL v | v == version [3]      -> spdx SPDX.GPL_3_0_only
+    LGPL v | v == version [2,1]   -> spdx SPDX.LGPL_2_1_only
+    LGPL v | v == version [3]     -> spdx SPDX.LGPL_3_0_only
+    AGPL v | v == version [3]     -> spdx SPDX.AGPL_3_0_only
+    BSD2                          -> spdx SPDX.BSD_2_Clause
+    BSD3                          -> spdx SPDX.BSD_3_Clause
+    BSD4                          -> spdx SPDX.BSD_4_Clause
+    MIT                           -> spdx SPDX.MIT
+    ISC                           -> spdx SPDX.ISC
+    MPL v | v == mkVersion [2,0]  -> spdx SPDX.MPL_2_0
+    Apache v | v == version [2,0] -> spdx SPDX.Apache_2_0
+    AllRightsReserved             -> SPDX.NONE
+    UnspecifiedLicense            -> SPDX.NONE
+    OtherLicense                  -> ref (SPDX.mkLicenseRef' Nothing "OtherLicense")
+    PublicDomain                  -> ref (SPDX.mkLicenseRef' Nothing "PublicDomain")
+    UnknownLicense str            -> ref (SPDX.mkLicenseRef' Nothing str)
+    _                             -> ref (SPDX.mkLicenseRef' Nothing $ prettyShow l)
+  where
+    version = Just . mkVersion
+    spdx    = SPDX.License . SPDX.simpleLicenseExpression
+    ref  r  = SPDX.License $ SPDX.ELicense (SPDX.ELicenseRef r) Nothing
+
+-- | Convert 'SPDX.License' to 'License',
+--
+-- This is lossy conversion. We try our best.
+--
+-- >>> licenseFromSPDX . licenseToSPDX $ BSD3
+-- BSD3
+--
+-- >>> licenseFromSPDX . licenseToSPDX $ GPL (Just (mkVersion [3]))
+-- GPL (Just (mkVersion [3]))
+--
+-- >>> licenseFromSPDX . licenseToSPDX $ PublicDomain
+-- UnknownLicense "LicenseRefPublicDomain"
+--
+-- >>> licenseFromSPDX $ SPDX.License $ SPDX.simpleLicenseExpression SPDX.EUPL_1_1
+-- UnknownLicense "EUPL-1.1"
+--
+-- >>> licenseFromSPDX . licenseToSPDX $ AllRightsReserved
+-- AllRightsReserved
+--
+-- >>> licenseFromSPDX <$> simpleParsec "BSD-3-Clause OR GPL-3.0-only"
+-- Just (UnknownLicense "BSD3ClauseORGPL30only")
+--
+-- @since 2.2.0.0
+licenseFromSPDX :: SPDX.License -> License
+licenseFromSPDX SPDX.NONE = AllRightsReserved
+licenseFromSPDX l =
+    fromMaybe (mungle $ prettyShow l) $ Map.lookup l m
+  where
+    m :: Map.Map SPDX.License License
+    m = Map.fromList $ filter (isSimple . fst ) $
+        map (\x -> (licenseToSPDX x, x)) knownLicenses
+
+    isSimple (SPDX.License (SPDX.ELicense (SPDX.ELicenseId _) Nothing)) = True
+    isSimple _ = False
+
+    mungle name = fromMaybe (UnknownLicense (mapMaybe mangle name)) (simpleParsec name)
+
+    mangle c
+        | isAlphaNum c = Just c
+        | otherwise = Nothing
+
 instance Pretty License where
   pretty (GPL  version)         = Disp.text "GPL"    <<>> dispOptVersion version
   pretty (LGPL version)         = Disp.text "LGPL"   <<>> dispOptVersion version
@@ -152,7 +228,7 @@
 instance Parsec License where
   parsec = do
     name    <- P.munch1 isAlphaNum
-    version <- P.optionMaybe (P.char '-' *> parsec)
+    version <- P.optional (P.char '-' *> parsec)
     return $! case (name, version :: Maybe Version) of
       ("GPL",               _      )  -> GPL  version
       ("LGPL",              _      )  -> LGPL version
diff --git a/cabal/Cabal/Distribution/Make.hs b/cabal/Cabal/Distribution/Make.hs
--- a/cabal/Cabal/Distribution/Make.hs
+++ b/cabal/Cabal/Distribution/Make.hs
@@ -146,6 +146,8 @@
   let destArgs = case fromFlag $ copyDest flags of
         NoCopyDest      -> ["install"]
         CopyTo path     -> ["copy", "destdir=" ++ path]
+        CopyToDb _      -> error "CopyToDb not supported via Make"
+
   rawSystemExit (fromFlag $ copyVerbosity flags) "make" destArgs
 
 installAction :: InstallFlags -> [String] -> IO ()
diff --git a/cabal/Cabal/Distribution/ModuleName.hs b/cabal/Cabal/Distribution/ModuleName.hs
--- a/cabal/Cabal/Distribution/ModuleName.hs
+++ b/cabal/Cabal/Distribution/ModuleName.hs
@@ -34,8 +34,8 @@
 import Distribution.Parsec.Class
 import Distribution.Text
 
-import qualified Distribution.Compat.Parsec as P
-import qualified Distribution.Compat.ReadP as Parse
+import qualified Distribution.Compat.CharParsing as P
+import qualified Distribution.Compat.ReadP       as Parse
 import qualified Text.PrettyPrint as Disp
 
 -- | A valid Haskell module name.
@@ -79,7 +79,7 @@
 validModuleComponent (c:cs) = isUpper c
                            && all validModuleChar cs
 
-{-# DEPRECATED simple "use ModuleName.fromString instead" #-}
+{-# DEPRECATED simple "use ModuleName.fromString instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 simple :: String -> ModuleName
 simple str = ModuleName (stlFromStrings [str])
 
diff --git a/cabal/Cabal/Distribution/Package.hs b/cabal/Cabal/Distribution/Package.hs
--- a/cabal/Cabal/Distribution/Package.hs
+++ b/cabal/Cabal/Distribution/Package.hs
@@ -87,7 +87,7 @@
 class Package pkg => HasUnitId pkg where
   installedUnitId :: pkg -> UnitId
 
-{-# DEPRECATED installedPackageId "Use installedUnitId instead" #-}
+{-# DEPRECATED installedPackageId "Use installedUnitId instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 -- | Compatibility wrapper for Cabal pre-1.24.
 installedPackageId :: HasUnitId pkg => pkg -> UnitId
 installedPackageId = installedUnitId
diff --git a/cabal/Cabal/Distribution/PackageDescription.hs b/cabal/Cabal/Distribution/PackageDescription.hs
--- a/cabal/Cabal/Distribution/PackageDescription.hs
+++ b/cabal/Cabal/Distribution/PackageDescription.hs
@@ -1,7 +1,6 @@
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE NoMonoLocalBinds #-}
-
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Distribution.PackageDescription
@@ -19,6 +18,8 @@
         PackageDescription(..),
         emptyPackageDescription,
         specVersion,
+        buildType,
+        license,
         descCabalVersion,
         BuildType(..),
         knownBuildTypes,
@@ -85,6 +86,8 @@
         hcStaticOptions,
 
         -- ** Supplementary build information
+        allBuildDepends,
+        enabledBuildDepends,
         ComponentName(..),
         defaultLibName,
         HookedBuildInfo,
@@ -99,6 +102,7 @@
         nullFlagAssignment, showFlagValue,
         diffFlagAssignment, lookupFlagAssignment, insertFlagAssignment,
         dispFlagAssignment, parseFlagAssignment, parsecFlagAssignment,
+        findDuplicateFlagAssignments,
         CondTree(..), ConfVar(..), Condition(..),
         cNot, cAnd, cOr,
 
diff --git a/cabal/Cabal/Distribution/PackageDescription/Check.hs b/cabal/Cabal/Distribution/PackageDescription/Check.hs
--- a/cabal/Cabal/Distribution/PackageDescription/Check.hs
+++ b/cabal/Cabal/Distribution/PackageDescription/Check.hs
@@ -34,52 +34,50 @@
         checkPackageFileNames,
   ) where
 
-import Prelude ()
 import Distribution.Compat.Prelude
+import Prelude ()
 
-import Distribution.PackageDescription
-import Distribution.PackageDescription.Configuration
-import qualified Distribution.Compat.DList as DList
+import Control.Monad                                 (mapM)
+import Data.List                                     (group)
+import Distribution.Compat.Lens
 import Distribution.Compiler
-import Distribution.System
 import Distribution.License
-import Distribution.Simple.BuildPaths (autogenPathsModuleName)
+import Distribution.Package
+import Distribution.PackageDescription
+import Distribution.PackageDescription.Configuration
+import Distribution.Pretty                           (prettyShow)
+import Distribution.Simple.BuildPaths                (autogenPathsModuleName)
 import Distribution.Simple.BuildToolDepends
 import Distribution.Simple.CCompiler
+import Distribution.Simple.Glob
+import Distribution.Simple.Utils                     hiding (findPackageDesc, notice)
+import Distribution.System
+import Distribution.Text
 import Distribution.Types.ComponentRequestedSpec
 import Distribution.Types.CondTree
-import Distribution.Types.Dependency
 import Distribution.Types.ExeDependency
-import Distribution.Types.PackageName
-import Distribution.Types.ExecutableScope
 import Distribution.Types.UnqualComponentName
-import Distribution.Simple.Utils hiding (findPackageDesc, notice)
+import Distribution.Utils.Generic                    (isAscii)
+import Distribution.Verbosity
 import Distribution.Version
-import Distribution.Package
-import Distribution.Text
-import Distribution.Utils.Generic (isAscii)
 import Language.Haskell.Extension
+import System.FilePath
+       (splitDirectories, splitExtension, splitPath, takeExtension, takeFileName, (<.>), (</>))
 
-import Control.Monad (mapM)
-import qualified Data.ByteString.Lazy as BS
-import Data.List  (group)
-import qualified System.Directory as System
-         ( doesFileExist, doesDirectoryExist )
-import qualified Data.Map as Map
+import qualified Data.ByteString.Lazy      as BS
+import qualified Data.Map                  as Map
+import qualified Distribution.Compat.DList as DList
+import qualified Distribution.SPDX         as SPDX
+import qualified System.Directory          as System
 
-import qualified System.Directory (getDirectoryContents)
-import System.FilePath
-         ( (</>), (<.>), takeExtension, takeFileName, splitDirectories
-         , splitPath, splitExtension )
-import System.FilePath.Windows as FilePath.Windows
-         ( isValid )
+import qualified System.Directory        (getDirectoryContents)
+import qualified System.FilePath.Windows as FilePath.Windows (isValid)
 
 import qualified Data.Set as Set
 
-import Distribution.Compat.Lens
-import qualified Distribution.Types.BuildInfo.Lens as L
-import qualified Distribution.Types.PackageDescription.Lens as L
+import qualified Distribution.Types.BuildInfo.Lens                 as L
 import qualified Distribution.Types.GenericPackageDescription.Lens as L
+import qualified Distribution.Types.PackageDescription.Lens        as L
 
 -- | Results of some kind of failed package check.
 --
@@ -115,7 +113,7 @@
        -- quite legitimately refuse to publicly distribute packages with these
        -- problems.
      | PackageDistInexcusable { explanation :: String }
-  deriving (Eq)
+  deriving (Eq, Ord)
 
 instance Show PackageCheck where
     show notice = explanation notice
@@ -155,6 +153,7 @@
   ++ checkFlagNames gpkg
   ++ checkUnusedFlags gpkg
   ++ checkUnicodeXFields gpkg
+  ++ checkPathsModuleExtensions pkg
   where
     pkg = fromMaybe (flattenPackageDescription gpkg) mpkg
 
@@ -168,6 +167,7 @@
  ++ checkSourceRepos pkg
  ++ checkGhcOptions pkg
  ++ checkCCOptions pkg
+ ++ checkCxxOptions pkg
  ++ checkCPPOptions pkg
  ++ checkPaths pkg
  ++ checkCabalVersion pkg
@@ -265,7 +265,7 @@
   , checkVersion [1,25] (not (null (signatures lib))) $
       PackageDistInexcusable $
            "To use the 'signatures' field the package needs to specify "
-        ++ "at least 'cabal-version: >= 1.25'."
+        ++ "at least 'cabal-version: 2.0'."
 
     -- check that all autogen-modules appear on other-modules or exposed-modules
   , check
@@ -319,12 +319,6 @@
       PackageBuildImpossible $
            "On executable '" ++ display (exeName exe) ++ "' an 'autogen-module' is not "
         ++ "on 'other-modules'"
-
-  , checkSpecVersion pkg [2,0] (exeScope exe /= ExecutableScopeUnknown) $
-      PackageDistSuspiciousWarn $
-           "To use the 'scope' field the package needs to specify "
-        ++ "at least 'cabal-version: >= 2.0'."
-
   ]
   where
     moduleDuplicates = dups (exeModules exe)
@@ -449,20 +443,12 @@
            "Package names with the prefix 'z-' are reserved by Cabal and "
         ++ "cannot be used."
 
-  , check (isNothing (buildType pkg)) $
+  , check (isNothing (buildTypeRaw pkg) && specVersion pkg < mkVersion [2,1]) $
       PackageBuildWarning $
            "No 'build-type' specified. If you do not need a custom Setup.hs or "
         ++ "./configure script then use 'build-type: Simple'."
 
-  , case buildType pkg of
-      Just (UnknownBuildType unknown) -> Just $
-        PackageBuildWarning $
-             quote unknown ++ " is not a known 'build-type'. "
-          ++ "The known build types are: "
-          ++ commaSep (map display knownBuildTypes)
-      _ -> Nothing
-
-  , check (isJust (setupBuildInfo pkg) && buildType pkg /= Just Custom) $
+  , check (isJust (setupBuildInfo pkg) && buildType pkg /= Custom) $
       PackageBuildWarning $
            "Ignoring the 'custom-setup' section because the 'build-type' is "
         ++ "not 'Custom'. Use 'build-type: Custom' if you need to use a "
@@ -546,7 +532,10 @@
         ++ "for example 'tested-with: GHC==6.10.4, GHC==6.12.3' and not "
         ++ "'tested-with: GHC==6.10.4 && ==6.12.3'."
 
-  , check (not (null depInternalLibraryWithExtraVersion)) $
+  -- Disabled due to #5119: we generate loads of spurious instances of
+  -- this warning. Re-enabling this check should be part of the fix to
+  -- #5119.
+  , check (False && not (null depInternalLibraryWithExtraVersion)) $
       PackageBuildWarning $
            "The package has an extraneous version range for a dependency on an "
         ++ "internal library: "
@@ -658,17 +647,35 @@
 
 
 checkLicense :: PackageDescription -> [PackageCheck]
-checkLicense pkg =
-  catMaybes [
+checkLicense pkg = case licenseRaw pkg of
+    Right l -> checkOldLicense pkg l
+    Left  l -> checkNewLicense pkg l
 
-    check (license pkg == UnspecifiedLicense) $
+checkNewLicense :: PackageDescription -> SPDX.License -> [PackageCheck]
+checkNewLicense _pkg lic = catMaybes
+    [ check (lic == SPDX.NONE) $
+        PackageDistInexcusable
+            "The 'license' field is missing or is NONE."
+    ]
+
+checkOldLicense :: PackageDescription -> License -> [PackageCheck]
+checkOldLicense pkg lic = catMaybes
+  [ check (lic == UnspecifiedLicense) $
       PackageDistInexcusable
         "The 'license' field is missing."
 
-  , check (license pkg == AllRightsReserved) $
+  , check (lic == AllRightsReserved) $
       PackageDistSuspicious
         "The 'license' is AllRightsReserved. Is that really what you want?"
-  , case license pkg of
+
+  , checkVersion [1,4] (lic `notElem` compatLicenses) $
+      PackageDistInexcusable $
+           "Unfortunately the license " ++ quote (prettyShow (license pkg))
+        ++ " messes up the parser in earlier Cabal versions so you need to "
+        ++ "specify 'cabal-version: >= 1.4'. Alternatively if you require "
+        ++ "compatibility with earlier Cabal versions then use 'OtherLicense'."
+
+  , case lic of
       UnknownLicense l -> Just $
         PackageBuildWarning $
              quote ("license: " ++ l) ++ " is not a recognised license. The "
@@ -676,23 +683,23 @@
           ++ commaSep (map display knownLicenses)
       _ -> Nothing
 
-  , check (license pkg == BSD4) $
+  , check (lic == BSD4) $
       PackageDistSuspicious $
            "Using 'license: BSD4' is almost always a misunderstanding. 'BSD4' "
         ++ "refers to the old 4-clause BSD license with the advertising "
         ++ "clause. 'BSD3' refers the new 3-clause BSD license."
 
-  , case unknownLicenseVersion (license pkg) of
+  , case unknownLicenseVersion (lic) of
       Just knownVersions -> Just $
         PackageDistSuspicious $
-             "'license: " ++ display (license pkg) ++ "' is not a known "
+             "'license: " ++ display (lic) ++ "' is not a known "
           ++ "version of that license. The known versions are "
           ++ commaSep (map display knownVersions)
           ++ ". If this is not a mistake and you think it should be a known "
           ++ "version then please file a ticket."
       _ -> Nothing
 
-  , check (license pkg `notElem` [ AllRightsReserved
+  , check (lic `notElem` [ AllRightsReserved
                                  , UnspecifiedLicense, PublicDomain]
            -- AllRightsReserved and PublicDomain are not strictly
            -- licenses so don't need license files.
@@ -714,6 +721,15 @@
       where knownVersions = [ v' | Apache  (Just v') <- knownLicenses ]
     unknownLicenseVersion _ = Nothing
 
+    checkVersion :: [Int] -> Bool -> PackageCheck -> Maybe PackageCheck
+    checkVersion ver cond pc
+      | specVersion pkg >= mkVersion ver       = Nothing
+      | otherwise                              = check cond pc
+
+    compatLicenses = [ GPL Nothing, LGPL Nothing, AGPL Nothing, BSD3, BSD4
+                     , PublicDomain, AllRightsReserved
+                     , UnspecifiedLicense, OtherLicense ]
+
 checkSourceRepos :: PackageDescription -> [PackageCheck]
 checkSourceRepos pkg =
   catMaybes $ concat [[
@@ -795,11 +811,16 @@
       PackageDistSuspicious $
       "'ghc-options: -main-is' is not portable."
 
-  , checkFlags ["-O0", "-Onot"] $
+  , checkNonTestAndBenchmarkFlags ["-O0", "-Onot"] $
       PackageDistSuspicious $
       "'ghc-options: -O0' is not needed. "
       ++ "Use the --disable-optimization configure flag."
 
+  , checkTestAndBenchmarkFlags ["-O0", "-Onot"] $
+      PackageDistSuspiciousWarn $
+      "'ghc-options: -O0' is not needed. "
+      ++ "Use the --disable-optimization configure flag."
+
   , checkFlags [ "-O", "-O1"] $
       PackageDistInexcusable $
       "'ghc-options: -O' is not needed. "
@@ -886,9 +907,26 @@
     get_ghc_options bi = hcOptions GHC bi ++ hcProfOptions GHC bi
                          ++ hcSharedOptions GHC bi
 
+    test_ghc_options      = concatMap (get_ghc_options . testBuildInfo)
+                            (testSuites pkg)
+    benchmark_ghc_options = concatMap (get_ghc_options . benchmarkBuildInfo)
+                            (benchmarks pkg)
+    test_and_benchmark_ghc_options     = test_ghc_options ++
+                                         benchmark_ghc_options
+    non_test_and_benchmark_ghc_options = concatMap get_ghc_options
+                                         (allBuildInfo (pkg { testSuites = []
+                                                            , benchmarks = []
+                                                            }))
+
     checkFlags :: [String] -> PackageCheck -> Maybe PackageCheck
     checkFlags flags = check (any (`elem` flags) all_ghc_options)
 
+    checkTestAndBenchmarkFlags :: [String] -> PackageCheck -> Maybe PackageCheck
+    checkTestAndBenchmarkFlags flags = check (any (`elem` flags) test_and_benchmark_ghc_options)
+
+    checkNonTestAndBenchmarkFlags :: [String] -> PackageCheck -> Maybe PackageCheck
+    checkNonTestAndBenchmarkFlags flags = check (any (`elem` flags) non_test_and_benchmark_ghc_options)
+
     ghcExtension ('-':'f':name) = case name of
       "allow-overlapping-instances"    -> enable  OverlappingInstances
       "no-allow-overlapping-instances" -> disable OverlappingInstances
@@ -928,17 +966,23 @@
     disable e = Just (DisableExtension e)
 
 checkCCOptions :: PackageDescription -> [PackageCheck]
-checkCCOptions pkg =
+checkCCOptions = checkCLikeOptions "C" "cc-options" ccOptions
+
+checkCxxOptions :: PackageDescription -> [PackageCheck]
+checkCxxOptions = checkCLikeOptions "C++" "cxx-options" cxxOptions
+
+checkCLikeOptions :: String -> String -> (BuildInfo -> [String]) -> PackageDescription -> [PackageCheck]
+checkCLikeOptions label prefix accessor pkg =
   catMaybes [
 
-    checkAlternatives "cc-options" "include-dirs"
-      [ (flag, dir) | flag@('-':'I':dir) <- all_ccOptions ]
+    checkAlternatives prefix "include-dirs"
+      [ (flag, dir) | flag@('-':'I':dir) <- all_cLikeOptions ]
 
-  , checkAlternatives "cc-options" "extra-libraries"
-      [ (flag, lib) | flag@('-':'l':lib) <- all_ccOptions ]
+  , checkAlternatives prefix "extra-libraries"
+      [ (flag, lib) | flag@('-':'l':lib) <- all_cLikeOptions ]
 
-  , checkAlternatives "cc-options" "extra-lib-dirs"
-      [ (flag, dir) | flag@('-':'L':dir) <- all_ccOptions ]
+  , checkAlternatives prefix "extra-lib-dirs"
+      [ (flag, dir) | flag@('-':'L':dir) <- all_cLikeOptions ]
 
   , checkAlternatives "ld-options" "extra-libraries"
       [ (flag, lib) | flag@('-':'l':lib) <- all_ldOptions ]
@@ -948,19 +992,18 @@
 
   , checkCCFlags [ "-O", "-Os", "-O0", "-O1", "-O2", "-O3" ] $
       PackageDistSuspicious $
-           "'cc-options: -O[n]' is generally not needed. When building with "
-        ++ " optimisations Cabal automatically adds '-O2' for C code. "
-        ++ "Setting it yourself interferes with the --disable-optimization "
-        ++ "flag."
+           "'"++prefix++": -O[n]' is generally not needed. When building with "
+        ++ " optimisations Cabal automatically adds '-O2' for "++label++" code. "
+        ++ "Setting it yourself interferes with the --disable-optimization flag."
   ]
 
-  where all_ccOptions = [ opts | bi <- allBuildInfo pkg
-                              , opts <- ccOptions bi ]
+  where all_cLikeOptions = [ opts | bi <- allBuildInfo pkg
+                                  , opts <- accessor bi ]
         all_ldOptions = [ opts | bi <- allBuildInfo pkg
                                , opts <- ldOptions bi ]
 
         checkCCFlags :: [String] -> PackageCheck -> Maybe PackageCheck
-        checkCCFlags flags = check (any (`elem` flags) all_ccOptions)
+        checkCCFlags flags = check (any (`elem` flags) all_cLikeOptions)
 
 checkCPPOptions :: PackageDescription -> [PackageCheck]
 checkCPPOptions pkg =
@@ -1014,6 +1057,24 @@
   , (GHC, flags) <- options bi
   , path <- flags
   , isInsideDist path ]
+  ++
+  [ PackageDistInexcusable $
+        "In the 'data-files' field: " ++ explainGlobSyntaxError pat err
+  | pat <- dataFiles pkg
+  , Left err <- [parseFileGlob (specVersion pkg) pat]
+  ]
+  ++
+  [ PackageDistInexcusable $
+        "In the 'extra-source-files' field: " ++ explainGlobSyntaxError pat err
+  | pat <- extraSrcFiles pkg
+  , Left err <- [parseFileGlob (specVersion pkg) pat]
+  ]
+  ++
+  [ PackageDistInexcusable $
+        "In the 'extra-doc-files' field: " ++ explainGlobSyntaxError pat err
+  | pat <- extraDocFiles pkg
+  , Left err <- [parseFileGlob (specVersion pkg) pat]
+  ]
   where
     isOutsideTree path = case splitDirectories path of
       "..":_     -> True
@@ -1025,12 +1086,12 @@
       _            -> False
     -- paths that must be relative
     relPaths =
-         [ (path, "extra-src-files") | path <- extraSrcFiles pkg ]
-      ++ [ (path, "extra-tmp-files") | path <- extraTmpFiles pkg ]
-      ++ [ (path, "extra-doc-files") | path <- extraDocFiles pkg ]
-      ++ [ (path, "data-files")      | path <- dataFiles     pkg ]
-      ++ [ (path, "data-dir")        | path <- [dataDir      pkg]]
-      ++ [ (path, "license-file")    | path <- licenseFiles  pkg ]
+         [ (path, "extra-source-files") | path <- extraSrcFiles pkg ]
+      ++ [ (path, "extra-tmp-files")    | path <- extraTmpFiles pkg ]
+      ++ [ (path, "extra-doc-files")    | path <- extraDocFiles pkg ]
+      ++ [ (path, "data-files")         | path <- dataFiles     pkg ]
+      ++ [ (path, "data-dir")           | path <- [dataDir      pkg]]
+      ++ [ (path, "license-file")       | path <- licenseFiles  pkg ]
       ++ concat
          [    [ (path, "asm-sources")      | path <- asmSources      bi ]
            ++ [ (path, "cmm-sources")      | path <- cmmSources      bi ]
@@ -1084,6 +1145,15 @@
         ++ "range syntax rather than a simple version number. Use "
         ++ "'cabal-version: >= " ++ display (specVersion pkg) ++ "'."
 
+    -- check syntax of cabal-version field
+  , check (specVersion pkg >= mkVersion [1,12]
+           && not simpleSpecVersionSyntax) $
+      (if specVersion pkg >= mkVersion [2,0] then PackageDistSuspicious else PackageDistSuspiciousWarn) $
+           "Packages relying on Cabal 1.12 or later should specify a "
+        ++ "specific version of the Cabal spec of the form "
+        ++ "'cabal-version: x.y'. "
+        ++ "Use 'cabal-version: " ++ display (specVersion pkg) ++ "'."
+
     -- check use of test suite sections
   , checkVersion [1,8] (not (null $ testSuites pkg)) $
       PackageDistInexcusable $
@@ -1115,31 +1185,31 @@
            "To use the 'extra-doc-files' field the package needs to specify "
         ++ "at least 'cabal-version: >= 1.18'."
 
-  , checkVersion [1,23]
+  , checkVersion [2,0]
     (not (null (subLibraries pkg))) $
       PackageDistInexcusable $
            "To use multiple 'library' sections or a named library section "
-        ++ "the package needs to specify at least 'cabal-version >= 1.23'."
+        ++ "the package needs to specify at least 'cabal-version: 2.0'."
 
     -- check use of reexported-modules sections
   , checkVersion [1,21]
     (any (not.null.reexportedModules) (allLibraries pkg)) $
       PackageDistInexcusable $
            "To use the 'reexported-module' field the package needs to specify "
-        ++ "at least 'cabal-version: >= 1.21'."
+        ++ "at least 'cabal-version: >= 1.22'."
 
     -- check use of thinning and renaming
   , checkVersion [1,25] usesBackpackIncludes $
       PackageDistInexcusable $
            "To use the 'mixins' field the package needs to specify "
-        ++ "at least 'cabal-version: >= 1.25'."
+        ++ "at least 'cabal-version: 2.0'."
 
     -- check use of 'extra-framework-dirs' field
   , checkVersion [1,23] (any (not . null) (buildInfoField extraFrameworkDirs)) $
       -- Just a warning, because this won't break on old Cabal versions.
       PackageDistSuspiciousWarn $
            "To use the 'extra-framework-dirs' field the package needs to specify"
-        ++ " at least 'cabal-version: >= 1.23'."
+        ++ " at least 'cabal-version: >= 1.24'."
 
     -- check use of default-extensions field
     -- don't need to do the equivalent check for other-extensions
@@ -1187,7 +1257,7 @@
         ++ "'build-depends' field: "
         ++ commaSep (map display depsUsingMajorBoundSyntax)
         ++ ". To use this new syntax the package need to specify at least "
-        ++ "'cabal-version: >= 2.0'. Alternatively, if broader compatibility "
+        ++ "'cabal-version: 2.0'. Alternatively, if broader compatibility "
         ++ "is important then use: " ++ commaSep
            [ display (Dependency name (eliminateMajorBoundSyntax versionRange))
            | Dependency name versionRange <- depsUsingMajorBoundSyntax ]
@@ -1208,7 +1278,7 @@
       PackageDistInexcusable $
            "The use of 'virtual-modules' requires the package "
         ++ " to specify at least 'cabal-version: >= 2.1'."
- 
+
     -- check use of "tested-with: GHC (>= 1.0 && < 1.4) || >=1.8 " syntax
   , checkVersion [1,8] (not (null testedWithVersionRangeExpressions)) $
       PackageDistInexcusable $
@@ -1229,25 +1299,6 @@
            [ display (Dependency name (eliminateWildcardSyntax versionRange))
            | Dependency name versionRange <- testedWithUsingWildcardSyntax ]
 
-    -- check use of "data-files: data/*.txt" syntax
-  , checkVersion [1,6] (not (null dataFilesUsingGlobSyntax)) $
-      PackageDistInexcusable $
-           "Using wildcards like "
-        ++ commaSep (map quote $ take 3 dataFilesUsingGlobSyntax)
-        ++ " in the 'data-files' field requires 'cabal-version: >= 1.6'. "
-        ++ "Alternatively if you require compatibility with earlier Cabal "
-        ++ "versions then list all the files explicitly."
-
-    -- check use of "extra-source-files: mk/*.in" syntax
-  , checkVersion [1,6] (not (null extraSrcFilesUsingGlobSyntax)) $
-      PackageDistInexcusable $
-           "Using wildcards like "
-        ++ commaSep (map quote $ take 3 extraSrcFilesUsingGlobSyntax)
-        ++ " in the 'extra-source-files' field requires "
-        ++ "'cabal-version: >= 1.6'. Alternatively if you require "
-        ++ "compatibility with earlier Cabal versions then list all the files "
-        ++ "explicitly."
-
     -- check use of "source-repository" section
   , checkVersion [1,6] (not (null (sourceRepos pkg))) $
       PackageDistInexcusable $
@@ -1255,14 +1306,6 @@
         ++ "Unfortunately it messes up the parser in earlier Cabal versions "
         ++ "so you need to specify 'cabal-version: >= 1.6'."
 
-    -- check for new licenses
-  , checkVersion [1,4] (license pkg `notElem` compatLicenses) $
-      PackageDistInexcusable $
-           "Unfortunately the license " ++ quote (display (license pkg))
-        ++ " messes up the parser in earlier Cabal versions so you need to "
-        ++ "specify 'cabal-version: >= 1.4'. Alternatively if you require "
-        ++ "compatibility with earlier Cabal versions then use 'OtherLicense'."
-
     -- check for new language extensions
   , checkVersion [1,2,3] (not (null mentionedExtensionsThatNeedCabal12)) $
       PackageDistInexcusable $
@@ -1284,9 +1327,9 @@
 
   , check (specVersion pkg >= mkVersion [1,23]
            && isNothing (setupBuildInfo pkg)
-           && buildType pkg == Just Custom) $
+           && buildType pkg == Custom) $
       PackageBuildWarning $
-           "Packages using 'cabal-version: >= 1.23' with 'build-type: Custom' "
+           "Packages using 'cabal-version: >= 1.24' with 'build-type: Custom' "
         ++ "must use a 'custom-setup' section with a 'setup-depends' field "
         ++ "that specifies the dependencies of the Setup.hs script itself. "
         ++ "The 'setup-depends' field uses the same syntax as 'build-depends', "
@@ -1294,10 +1337,10 @@
 
   , check (specVersion pkg < mkVersion [1,23]
            && isNothing (setupBuildInfo pkg)
-           && buildType pkg == Just Custom) $
+           && buildType pkg == Custom) $
       PackageDistSuspiciousWarn $
-           "From version 1.23 cabal supports specifiying explicit dependencies "
-        ++ "for Custom setup scripts. Consider using cabal-version >= 1.23 and "
+           "From version 1.24 cabal supports specifiying explicit dependencies "
+        ++ "for Custom setup scripts. Consider using cabal-version >= 1.24 and "
         ++ "adding a 'custom-setup' section with a 'setup-depends' field "
         ++ "that specifies the dependencies of the Setup.hs script itself. "
         ++ "The 'setup-depends' field uses the same syntax as 'build-depends', "
@@ -1307,7 +1350,7 @@
            && elem (autogenPathsModuleName pkg) allModuleNames
            && not (elem (autogenPathsModuleName pkg) allModuleNamesAutogen) ) $
       PackageDistInexcusable $
-           "Packages using 'cabal-version: >= 1.25' and the autogenerated "
+           "Packages using 'cabal-version: 2.0' and the autogenerated "
         ++ "module Paths_* must include it also on the 'autogen-modules' field "
         ++ "besides 'exposed-modules' and 'other-modules'. This specifies that "
         ++ "the module does not come with the package and is generated on "
@@ -1326,14 +1369,9 @@
       | otherwise                              = check cond pc
 
     buildInfoField field         = map field (allBuildInfo pkg)
-    dataFilesUsingGlobSyntax     = filter usesGlobSyntax (dataFiles pkg)
-    extraSrcFilesUsingGlobSyntax = filter usesGlobSyntax (extraSrcFiles pkg)
-    usesGlobSyntax str = case parseFileGlob str of
-      Just (FileGlob _ _) -> True
-      _                   -> False
 
     versionRangeExpressions =
-        [ dep | dep@(Dependency _ vr) <- buildDepends pkg
+        [ dep | dep@(Dependency _ vr) <- allBuildDepends pkg
               , usesNewVersionRangeSyntax vr ]
 
     testedWithVersionRangeExpressions =
@@ -1361,11 +1399,11 @@
         alg (VersionRangeParensF _) = 3
         alg _ = 1 :: Int
 
-    depsUsingWildcardSyntax = [ dep | dep@(Dependency _ vr) <- buildDepends pkg
+    depsUsingWildcardSyntax = [ dep | dep@(Dependency _ vr) <- allBuildDepends pkg
                                     , usesWildcardSyntax vr ]
 
-    depsUsingMajorBoundSyntax = [ dep | dep@(Dependency _ vr) <- buildDepends pkg
-                                  , usesMajorBoundSyntax vr ]
+    depsUsingMajorBoundSyntax = [ dep | dep@(Dependency _ vr) <- allBuildDepends pkg
+                                      , usesMajorBoundSyntax vr ]
 
     usesBackpackIncludes = any (not . null . mixins) (allBuildInfo pkg)
 
@@ -1408,10 +1446,6 @@
             (orLaterVersion v) (earlierVersion (majorUpperBound v))
         embed vr = embedVersionRange vr
 
-    compatLicenses = [ GPL Nothing, LGPL Nothing, AGPL Nothing, BSD3, BSD4
-                     , PublicDomain, AllRightsReserved
-                     , UnspecifiedLicense, OtherLicense ]
-
     mentionedExtensions = [ ext | bi <- allBuildInfo pkg
                                 , ext <- allExtensions bi ]
     mentionedExtensionsThatNeedCabal12 =
@@ -1515,7 +1549,7 @@
           foldr intersectVersionRanges anyVersion baseDeps
         where
           baseDeps =
-            [ vr | Dependency pname vr <- buildDepends pkg'
+            [ vr | Dependency pname vr <- allBuildDepends pkg'
                  , pname == mkPackageName "base" ]
 
       -- Just in case finalizePD fails for any reason,
@@ -1629,9 +1663,39 @@
     xfields :: [(String,String)]
     xfields = DList.runDList $ mconcat
         [ toDListOf (L.packageDescription . L.customFieldsPD . traverse) gpd
-        , toDListOf (L.buildInfos         . L.customFieldsBI . traverse) gpd
+        , toDListOf (L.traverseBuildInfos . L.customFieldsBI . traverse) gpd
         ]
 
+-- | cabal-version <2.2 + Paths_module + default-extensions: doesn't build.
+checkPathsModuleExtensions :: PackageDescription -> [PackageCheck]
+checkPathsModuleExtensions pd
+    | specVersion pd >= mkVersion [2,1] = []
+    | any checkBI (allBuildInfo pd) || any checkLib (allLibraries pd)
+        = return $ PackageBuildImpossible $ unwords
+            [ "The package uses RebindableSyntax with OverloadedStrings or OverloadedLists"
+            , "in default-extensions, and also Paths_ autogen module."
+            , "That configuration is known to cause compile failures with Cabal < 2.2."
+            , "To use these default-extensions with Paths_ autogen module"
+            , "specify at least 'cabal-version: 2.2'."
+            ]
+    | otherwise = []
+  where
+    mn = autogenPathsModuleName pd
+
+    checkLib :: Library -> Bool
+    checkLib l = mn `elem` exposedModules l && checkExts (l ^. L.defaultExtensions)
+
+    checkBI :: BuildInfo -> Bool
+    checkBI bi =
+        (mn `elem` otherModules bi || mn `elem` autogenModules bi) &&
+        checkExts (bi ^. L.defaultExtensions)
+
+    checkExts exts = rebind `elem` exts && (strings `elem` exts || lists `elem` exts)
+      where
+        rebind  = EnableExtension RebindableSyntax
+        strings = EnableExtension OverloadedStrings
+        lists   = EnableExtension OverloadedLists
+
 checkDevelopmentOnlyFlagsBuildInfo :: BuildInfo -> [PackageCheck]
 checkDevelopmentOnlyFlagsBuildInfo bi =
   catMaybes [
@@ -1650,6 +1714,12 @@
         ++ "add new warnings. "
         ++ extraExplanation
 
+  , check (has_J) $
+      PackageDistInexcusable $
+           "'ghc-options: -j[N]' can make sense for specific user's setup,"
+        ++ " but it is not appropriate for a distributed package."
+        ++ extraExplanation
+
   , checkFlags ["-fdefer-type-errors"] $
       PackageDistInexcusable $
            "'ghc-options: -fdefer-type-errors' is fine during development but "
@@ -1687,6 +1757,13 @@
     has_Werror       = "-Werror" `elem` ghc_options
     has_Wall         = "-Wall"   `elem` ghc_options
     has_W            = "-W"      `elem` ghc_options
+    has_J            = any
+                         (\o -> case o of
+                           "-j"                -> True
+                           ('-' : 'j' : d : _) -> isDigit d
+                           _                   -> False
+                         )
+                         ghc_options
     ghc_options      = hcOptions GHC bi ++ hcProfOptions GHC bi
                        ++ hcSharedOptions GHC bi
 
@@ -1767,14 +1844,20 @@
 -- | Sanity check things that requires IO. It looks at the files in the
 -- package and expects to find the package unpacked in at the given file path.
 --
-checkPackageFiles :: PackageDescription -> FilePath -> NoCallStackIO [PackageCheck]
-checkPackageFiles pkg root = checkPackageContent checkFilesIO pkg
+checkPackageFiles :: Verbosity -> PackageDescription -> FilePath -> NoCallStackIO [PackageCheck]
+checkPackageFiles verbosity pkg root = do
+  contentChecks <- checkPackageContent checkFilesIO pkg
+  preDistributionChecks <- checkPackageFilesPreDistribution verbosity pkg root
+  -- Sort because different platforms will provide files from
+  -- `getDirectoryContents` in different orders, and we'd like to be
+  -- stable for test output.
+  return (sort contentChecks ++ sort preDistributionChecks)
   where
     checkFilesIO = CheckPackageContentOps {
       doesFileExist        = System.doesFileExist                  . relative,
       doesDirectoryExist   = System.doesDirectoryExist             . relative,
       getDirectoryContents = System.Directory.getDirectoryContents . relative,
-      getFileContents      = BS.readFile
+      getFileContents      = BS.readFile                           . relative
     }
     relative path = root </> path
 
@@ -1904,7 +1987,7 @@
                  -> PackageDescription
                  -> m (Maybe PackageCheck)
 checkSetupExists ops pkg = do
-  let simpleBuild = buildType pkg == Just Simple
+  let simpleBuild = buildType pkg == Simple
   hsexists  <- doesFileExist ops "Setup.hs"
   lhsexists <- doesFileExist ops "Setup.lhs"
   return $ check (not simpleBuild && not hsexists && not lhsexists) $
@@ -1914,13 +1997,14 @@
 checkConfigureExists :: Monad m => CheckPackageContentOps m
                      -> PackageDescription
                      -> m (Maybe PackageCheck)
-checkConfigureExists ops PackageDescription { buildType = Just Configure } = do
-  exists <- doesFileExist ops "configure"
-  return $ check (not exists) $
-    PackageBuildWarning $
-      "The 'build-type' is 'Configure' but there is no 'configure' script. "
-      ++ "You probably need to run 'autoreconf -i' to generate it."
-checkConfigureExists _ _ = return Nothing
+checkConfigureExists ops pd
+  | buildType pd == Configure = do
+      exists <- doesFileExist ops "configure"
+      return $ check (not exists) $
+        PackageBuildWarning $
+          "The 'build-type' is 'Configure' but there is no 'configure' script. "
+          ++ "You probably need to run 'autoreconf -i' to generate it."
+  | otherwise = return Nothing
 
 checkLocalPathsExist :: Monad m => CheckPackageContentOps m
                      -> PackageDescription
@@ -2062,6 +2146,82 @@
          "Encountered a file with an empty name, something is very wrong! "
       ++ "Files with an empty name cannot be stored in a tar archive or in "
       ++ "standard file systems."
+
+-- --------------------------------------------------------------
+-- * Checks for missing content and other pre-distribution checks
+-- --------------------------------------------------------------
+
+-- | Similar to 'checkPackageContent', 'checkPackageFilesPreDistribution'
+-- inspects the files included in the package, but is primarily looking for
+-- files in the working tree that may have been missed or other similar
+-- problems that can only be detected pre-distribution.
+--
+-- Because Hackage necessarily checks the uploaded tarball, it is too late to
+-- check these on the server; these checks only make sense in the development
+-- and package-creation environment. Hence we can use IO, rather than needing
+-- to pass a 'CheckPackageContentOps' dictionary around.
+checkPackageFilesPreDistribution :: Verbosity -> PackageDescription -> FilePath -> NoCallStackIO [PackageCheck]
+-- Note: this really shouldn't return any 'Inexcusable' warnings,
+-- because that will make us say that Hackage would reject the package.
+-- But, because Hackage doesn't run these tests, that will be a lie!
+checkPackageFilesPreDistribution = checkGlobFiles
+
+-- | Discover problems with the package's wildcards.
+checkGlobFiles :: Verbosity
+               -> PackageDescription
+               -> FilePath
+               -> NoCallStackIO [PackageCheck]
+checkGlobFiles verbosity pkg root =
+  fmap concat $ for allGlobs $ \(field, dir, glob) ->
+    -- Note: we just skip over parse errors here; they're reported elsewhere.
+    case parseFileGlob (specVersion pkg) glob of
+      Left _ -> return []
+      Right parsedGlob -> do
+        results <- runDirFileGlob verbosity (root </> dir) parsedGlob
+        let individualWarnings = results >>= getWarning field glob
+            noMatchesWarning =
+              [ PackageDistSuspiciousWarn $
+                     "In '" ++ field ++ "': the pattern '" ++ glob ++ "' does not"
+                  ++ " match any files."
+              | all (not . suppressesNoMatchesWarning) results
+              ]
+        return (noMatchesWarning ++ individualWarnings)
+  where
+    adjustedDataDir = if null (dataDir pkg) then "." else dataDir pkg
+    allGlobs = concat
+      [ (,,) "extra-source-files" "." <$> extraSrcFiles pkg
+      , (,,) "extra-doc-files" "." <$> extraDocFiles pkg
+      , (,,) "data-files" adjustedDataDir <$> dataFiles pkg
+      ]
+
+    -- If there's a missing directory in play, since our globs don't
+    -- (currently) support disjunction, that will always mean there are no
+    -- matches. The no matches error in this case is strictly less informative
+    -- than the missing directory error, so sit on it.
+    suppressesNoMatchesWarning (GlobMatch _) = True
+    suppressesNoMatchesWarning (GlobWarnMultiDot _) = False
+    suppressesNoMatchesWarning (GlobMissingDirectory _) = True
+
+    getWarning :: String -> FilePath -> GlobResult FilePath -> [PackageCheck]
+    getWarning _ _ (GlobMatch _) =
+      []
+    -- Before Cabal 2.4, the extensions of globs had to match the file
+    -- exactly. This has been relaxed in 2.4 to allow matching only the
+    -- suffix. This warning detects when pre-2.4 package descriptions are
+    -- omitting files purely because of the stricter check.
+    getWarning field glob (GlobWarnMultiDot file) =
+      [ PackageDistSuspiciousWarn $
+             "In '" ++ field ++ "': the pattern '" ++ glob ++ "' does not"
+          ++ " match the file '" ++ file ++ "' because the extensions do not"
+          ++ " exactly match (e.g., foo.en.html does not exactly match *.html)."
+          ++ " To enable looser suffix-only matching, set 'cabal-version: 2.4' or higher."
+      ]
+    getWarning field glob (GlobMissingDirectory dir) =
+      [ PackageDistSuspiciousWarn $
+             "In '" ++ field ++ "': the pattern '" ++ glob ++ "' attempts to"
+          ++ " match files in the directory '" ++ dir ++ "', but there is no"
+          ++ " directory by that name."
+      ]
 
 -- ------------------------------------------------------------
 -- * Utils
diff --git a/cabal/Cabal/Distribution/PackageDescription/Configuration.hs b/cabal/Cabal/Distribution/PackageDescription/Configuration.hs
--- a/cabal/Cabal/Distribution/PackageDescription/Configuration.hs
+++ b/cabal/Cabal/Distribution/PackageDescription/Configuration.hs
@@ -37,6 +37,12 @@
 import Prelude ()
 import Distribution.Compat.Prelude
 
+-- lens
+import qualified Distribution.Types.BuildInfo.Lens as L
+import qualified Distribution.Types.GenericPackageDescription.Lens as L
+import qualified Distribution.Types.PackageDescription.Lens as L
+import qualified Distribution.Types.SetupBuildInfo.Lens as L
+
 import Distribution.PackageDescription
 import Distribution.PackageDescription.Utils
 import Distribution.Version
@@ -44,6 +50,7 @@
 import Distribution.System
 import Distribution.Simple.Utils
 import Distribution.Text
+import Distribution.Compat.Lens
 import Distribution.Compat.ReadP as ReadP hiding ( char )
 import qualified Distribution.Compat.ReadP as ReadP ( char )
 import Distribution.Types.ComponentRequestedSpec
@@ -57,7 +64,7 @@
 import Distribution.Types.DependencyMap
 
 import qualified Data.Map.Strict as Map.Strict
-import qualified Data.Map.Lazy as Map
+import qualified Data.Map.Lazy   as Map
 import Data.Tree ( Tree(Node) )
 
 ------------------------------------------------------------------------------
@@ -352,18 +359,18 @@
 -- | Collect up the targets in a TargetSet of tagged targets, storing the
 -- dependencies as we go.
 flattenTaggedTargets :: TargetSet PDTagged -> (Maybe Library, [(UnqualComponentName, Component)])
-flattenTaggedTargets (TargetSet targets) = foldr untag (Nothing, []) targets
-  where
-    untag (_, Lib _) (Just _, _) = userBug "Only one library expected"
-    untag (_, Lib l) (Nothing, comps) = (Just l, comps)
-    untag (_, SubComp n c) (mb_lib, comps)
-        | any ((== n) . fst) comps =
-          userBug $ "There exist several components with the same name: '" ++ unUnqualComponentName n ++ "'"
-
-        | otherwise = (mb_lib, (n, c) : comps)
-
-    untag (_, PDNull) x = x  -- actually this should not happen, but let's be liberal
-
+flattenTaggedTargets (TargetSet targets) = foldr untag (Nothing, []) targets where
+  untag (depMap, pdTagged) accum = case (pdTagged, accum) of
+    (Lib _, (Just _, _)) -> userBug "Only one library expected"
+    (Lib l, (Nothing, comps)) -> (Just $ redoBD l, comps)
+    (SubComp n c, (mb_lib, comps))
+      | any ((== n) . fst) comps ->
+        userBug $ "There exist several components with the same name: '" ++ display n ++ "'"
+      | otherwise -> (mb_lib, (n, redoBD c) : comps)
+    (PDNull, x) -> x  -- actually this should not happen, but let's be liberal
+    where
+      redoBD :: L.HasBuildInfo a => a -> a
+      redoBD = set L.targetBuildDepends $ fromDepMap depMap
 
 ------------------------------------------------------------------------------
 -- Convert GenericPackageDescription to PackageDescription
@@ -448,7 +455,6 @@
                , executables = exes'
                , testSuites = tests'
                , benchmarks = bms'
-               , buildDepends = fromDepMap (overallDependencies enabled targetSet)
                }
          , flagVals )
   where
@@ -472,7 +478,7 @@
                       then DepOk
                       else MissingDeps missingDeps
 
-{-# DEPRECATED finalizePackageDescription "This function now always assumes tests and benchmarks are disabled; use finalizePD with ComponentRequestedSpec to specify something more specific." #-}
+{-# DEPRECATED finalizePackageDescription "This function now always assumes tests and benchmarks are disabled; use finalizePD with ComponentRequestedSpec to specify something more specific. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 finalizePackageDescription ::
      FlagAssignment  -- ^ Explicitly specified flag assignments
   -> (Dependency -> Bool) -- ^ Is a given dependency satisfiable from the set of
@@ -518,38 +524,25 @@
         , executables  = reverse exes
         , testSuites   = reverse tests
         , benchmarks   = reverse bms
-        , buildDepends = ldeps
-                      ++ reverse sub_ldeps
-                      ++ reverse pldeps
-                      ++ reverse edeps
-                      ++ reverse tdeps
-                      ++ reverse bdeps
         }
   where
-    (mlib, ldeps) = case mlib0 of
-        Just lib -> let (l,ds) = ignoreConditions lib in
-                    (Just ((libFillInDefaults l) { libName = Nothing }), ds)
-        Nothing -> (Nothing, [])
-    (sub_libs, sub_ldeps) = foldr flattenLib  ([],[]) sub_libs0
-    (flibs,    pldeps)    = foldr flattenFLib ([],[]) flibs0
-    (exes,     edeps)     = foldr flattenExe  ([],[]) exes0
-    (tests,    tdeps)     = foldr flattenTst  ([],[]) tests0
-    (bms,      bdeps)     = foldr flattenBm   ([],[]) bms0
-    flattenLib (n, t) (es, ds) =
-        let (e, ds') = ignoreConditions t in
-        ( (libFillInDefaults $ e { libName = Just n, libExposed = False }) : es, ds' ++ ds )
-    flattenFLib (n, t) (es, ds) =
-        let (e, ds') = ignoreConditions t in
-        ( (flibFillInDefaults $ e { foreignLibName = n }) : es, ds' ++ ds )
-    flattenExe (n, t) (es, ds) =
-        let (e, ds') = ignoreConditions t in
-        ( (exeFillInDefaults $ e { exeName = n }) : es, ds' ++ ds )
-    flattenTst (n, t) (es, ds) =
-        let (e, ds') = ignoreConditions t in
-        ( (testFillInDefaults $ e { testName = n }) : es, ds' ++ ds )
-    flattenBm (n, t) (es, ds) =
-        let (e, ds') = ignoreConditions t in
-        ( (benchFillInDefaults $ e { benchmarkName = n }) : es, ds' ++ ds )
+    mlib = f <$> mlib0
+      where f lib = (libFillInDefaults . fst . ignoreConditions $ lib) { libName = Nothing }
+    sub_libs = flattenLib  <$> sub_libs0
+    flibs    = flattenFLib <$> flibs0
+    exes     = flattenExe  <$> exes0
+    tests    = flattenTst  <$> tests0
+    bms      = flattenBm   <$> bms0
+    flattenLib (n, t) = libFillInDefaults $ (fst $ ignoreConditions t)
+      { libName = Just n, libExposed = False }
+    flattenFLib (n, t) = flibFillInDefaults $ (fst $ ignoreConditions t)
+      { foreignLibName = n }
+    flattenExe (n, t) = exeFillInDefaults $ (fst $ ignoreConditions t)
+      { exeName = n }
+    flattenTst (n, t) = testFillInDefaults $ (fst $ ignoreConditions t)
+      { testName = n }
+    flattenBm (n, t) = benchFillInDefaults $ (fst $ ignoreConditions t)
+      { benchmarkName = n }
 
 -- This is in fact rather a hack.  The original version just overrode the
 -- default values, however, when adding conditions we had to switch to a
@@ -590,79 +583,17 @@
                        -> (SetupBuildInfo -> SetupBuildInfo)
                        -> GenericPackageDescription
                        -> GenericPackageDescription
-transformAllBuildInfos onBuildInfo onSetupBuildInfo gpd = gpd'
-  where
-    onLibrary    lib  = lib { libBuildInfo  = onBuildInfo $ libBuildInfo  lib }
-    onExecutable exe  = exe { buildInfo     = onBuildInfo $ buildInfo     exe }
-    onTestSuite  tst  = tst { testBuildInfo = onBuildInfo $ testBuildInfo tst }
-    onBenchmark  bmk  = bmk { benchmarkBuildInfo =
-                                 onBuildInfo $ benchmarkBuildInfo bmk }
-
-    pd = packageDescription gpd
-    pd'  = pd {
-      library        = fmap onLibrary        (library pd),
-      subLibraries   = map  onLibrary        (subLibraries pd),
-      executables    = map  onExecutable     (executables pd),
-      testSuites     = map  onTestSuite      (testSuites pd),
-      benchmarks     = map  onBenchmark      (benchmarks pd),
-      setupBuildInfo = fmap onSetupBuildInfo (setupBuildInfo pd)
-      }
-
-    gpd' = transformAllCondTrees onLibrary onExecutable
-           onTestSuite onBenchmark id
-           $ gpd { packageDescription = pd' }
+transformAllBuildInfos onBuildInfo onSetupBuildInfo =
+  over L.traverseBuildInfos onBuildInfo
+  . over (L.packageDescription . L.setupBuildInfo . traverse) onSetupBuildInfo
 
 -- | Walk a 'GenericPackageDescription' and apply @f@ to all nested
 -- @build-depends@ fields.
 transformAllBuildDepends :: (Dependency -> Dependency)
                          -> GenericPackageDescription
                          -> GenericPackageDescription
-transformAllBuildDepends f gpd = gpd'
-  where
-    onBI  bi  = bi  { targetBuildDepends = map f $ targetBuildDepends bi }
-    onSBI stp = stp { setupDepends       = map f $ setupDepends stp      }
-    onPD  pd  = pd  { buildDepends       = map f $ buildDepends pd       }
-
-    pd'   = onPD $ packageDescription gpd
-    gpd'  = transformAllCondTrees id id id id (map f)
-            . transformAllBuildInfos onBI onSBI
-            $ gpd { packageDescription = pd' }
-
--- | Walk all 'CondTree's inside a 'GenericPackageDescription' and apply
--- appropriate transformations to all nodes. Helper function used by
--- 'transformAllBuildDepends' and 'transformAllBuildInfos'.
-transformAllCondTrees :: (Library -> Library)
-                      -> (Executable -> Executable)
-                      -> (TestSuite -> TestSuite)
-                      -> (Benchmark -> Benchmark)
-                      -> ([Dependency] -> [Dependency])
-                      -> GenericPackageDescription -> GenericPackageDescription
-transformAllCondTrees onLibrary onExecutable
-  onTestSuite onBenchmark onDepends gpd = gpd'
-  where
-    gpd'    = gpd {
-      condLibrary        = condLib',
-      condSubLibraries   = condSubLibs',
-      condExecutables    = condExes',
-      condTestSuites     = condTests',
-      condBenchmarks     = condBenchs'
-      }
-
-    condLib    = condLibrary        gpd
-    condSubLibs = condSubLibraries  gpd
-    condExes   = condExecutables    gpd
-    condTests  = condTestSuites     gpd
-    condBenchs = condBenchmarks     gpd
-
-    condLib'    = fmap (onCondTree onLibrary) condLib
-    condSubLibs' = map (mapSnd $ onCondTree onLibrary)    condSubLibs
-    condExes'   = map  (mapSnd $ onCondTree onExecutable) condExes
-    condTests'  = map  (mapSnd $ onCondTree onTestSuite)  condTests
-    condBenchs' = map  (mapSnd $ onCondTree onBenchmark)  condBenchs
-
-    mapSnd :: (a -> b) -> (c,a) -> (c,b)
-    mapSnd = fmap
-
-    onCondTree :: (a -> b) -> CondTree v [Dependency] a
-               -> CondTree v [Dependency] b
-    onCondTree g = mapCondTree g onDepends id
+transformAllBuildDepends f =
+  over (L.traverseBuildInfos . L.targetBuildDepends . traverse) f
+  . over (L.packageDescription . L.setupBuildInfo . traverse . L.setupDepends . traverse) f
+  -- cannot be point-free as normal because of higher rank
+  . over (\f' -> L.allCondTrees $ traverseCondTreeC f') (map f)
diff --git a/cabal/Cabal/Distribution/PackageDescription/FieldGrammar.hs b/cabal/Cabal/Distribution/PackageDescription/FieldGrammar.hs
--- a/cabal/Cabal/Distribution/PackageDescription/FieldGrammar.hs
+++ b/cabal/Cabal/Distribution/PackageDescription/FieldGrammar.hs
@@ -45,7 +45,6 @@
 
 import Distribution.Compiler                  (CompilerFlavor (..))
 import Distribution.FieldGrammar
-import Distribution.License                   (License (..))
 import Distribution.ModuleName                (ModuleName)
 import Distribution.Package
 import Distribution.PackageDescription
@@ -53,11 +52,14 @@
 import Distribution.Parsec.Newtypes
 import Distribution.Parsec.ParseResult
 import Distribution.Text                      (display)
+import Distribution.Types.ExecutableScope
 import Distribution.Types.ForeignLib
 import Distribution.Types.ForeignLibType
 import Distribution.Types.UnqualComponentName
 import Distribution.Version                   (anyVersion)
 
+import qualified Distribution.SPDX as SPDX
+
 import qualified Distribution.Types.Lens as L
 
 -------------------------------------------------------------------------------
@@ -68,8 +70,9 @@
     :: (FieldGrammar g, Applicative (g PackageDescription), Applicative (g PackageIdentifier))
     => g PackageDescription PackageDescription
 packageDescriptionFieldGrammar = PackageDescription
-    <$> blurFieldGrammar L.package packageIdentifierGrammar
-    <*> optionalFieldDef    "license"                                  L.license UnspecifiedLicense
+    <$> optionalFieldDefAla "cabal-version" SpecVersion                L.specVersionRaw (Right anyVersion)
+    <*> blurFieldGrammar L.package packageIdentifierGrammar
+    <*> optionalFieldDefAla "license"       SpecLicense                L.licenseRaw (Left SPDX.NONE)
     <*> licenseFilesGrammar
     <*> optionalFieldDefAla "copyright"     FreeText                   L.copyright ""
     <*> optionalFieldDefAla "maintainer"    FreeText                   L.maintainer ""
@@ -84,9 +87,7 @@
     <*> optionalFieldDefAla "description"   FreeText                   L.description ""
     <*> optionalFieldDefAla "category"      FreeText                   L.category ""
     <*> prefixedFields      "x-"                                       L.customFieldsPD
-    <*> pure [] -- build-depends
-    <*> optionalFieldDefAla "cabal-version" SpecVersion                L.specVersionRaw (Right anyVersion)
-    <*> optionalField       "build-type"                               L.buildType
+    <*> optionalField       "build-type"                               L.buildTypeRaw
     <*> pure Nothing -- custom-setup
     -- components
     <*> pure Nothing  -- lib
@@ -125,6 +126,7 @@
     <$> monoidalFieldAla  "exposed-modules"    (alaList' VCat MQuoted) L.exposedModules
     <*> monoidalFieldAla  "reexported-modules" (alaList  CommaVCat)    L.reexportedModules
     <*> monoidalFieldAla  "signatures"         (alaList' VCat MQuoted) L.signatures
+        ^^^ availableSince [2,0] []
     <*> booleanFieldDef   "exposed"                                    L.libExposed True
     <*> blurFieldGrammar L.libBuildInfo buildInfoFieldGrammar
 {-# SPECIALIZE libraryFieldGrammar :: Maybe UnqualComponentName -> ParsecFieldGrammar' Library #-}
@@ -157,7 +159,8 @@
 executableFieldGrammar n = Executable n
     -- main-is is optional as conditional blocks don't have it
     <$> optionalFieldDefAla "main-is" FilePathNT L.modulePath ""
-    <*> monoidalField       "scope"              L.exeScope
+    <*> optionalFieldDef    "scope"              L.exeScope ExecutablePublic
+        ^^^ availableSince [2,0] ExecutablePublic
     <*> blurFieldGrammar L.buildInfo buildInfoFieldGrammar
 {-# SPECIALIZE executableFieldGrammar :: UnqualComponentName -> ParsecFieldGrammar' Executable #-}
 {-# SPECIALIZE executableFieldGrammar :: UnqualComponentName -> PrettyFieldGrammar' Executable #-}
@@ -175,6 +178,9 @@
     , _testStanzaBuildInfo  :: BuildInfo
     }
 
+instance L.HasBuildInfo TestSuiteStanza where
+    buildInfo = testStanzaBuildInfo
+
 testStanzaTestType :: Lens' TestSuiteStanza (Maybe TestType)
 testStanzaTestType f s = fmap (\x -> s { _testStanzaTestType = x }) (f (_testStanzaTestType s))
 {-# INLINE testStanzaTestType #-}
@@ -274,6 +280,9 @@
     , _benchmarkStanzaBuildInfo       :: BuildInfo
     }
 
+instance L.HasBuildInfo BenchmarkStanza where
+    buildInfo = benchmarkStanzaBuildInfo
+
 benchmarkStanzaBenchmarkType :: Lens' BenchmarkStanza (Maybe BenchmarkType)
 benchmarkStanzaBenchmarkType f s = fmap (\x -> s { _benchmarkStanzaBenchmarkType = x }) (f (_benchmarkStanzaBenchmarkType s))
 {-# INLINE benchmarkStanzaBenchmarkType #-}
@@ -358,12 +367,17 @@
     <*> monoidalFieldAla "build-tools"          (alaList  CommaFSep)          L.buildTools
         ^^^ deprecatedSince [2,0] "Please use 'build-tool-depends' field"
     <*> monoidalFieldAla "build-tool-depends"   (alaList  CommaFSep)          L.buildToolDepends
-        ^^^ availableSince [2,0]
+        -- {- ^^^ availableSince [2,0] [] -}
+        -- here, we explicitly want to recognise build-tool-depends for all Cabal files
+        -- as otherwise cabal new-build cannot really work.
+        --
+        -- I.e. we don't want trigger unknown field warning
     <*> monoidalFieldAla "cpp-options"          (alaList' NoCommaFSep Token') L.cppOptions
     <*> monoidalFieldAla "asm-options"          (alaList' NoCommaFSep Token') L.asmOptions
     <*> monoidalFieldAla "cmm-options"          (alaList' NoCommaFSep Token') L.cmmOptions
     <*> monoidalFieldAla "cc-options"           (alaList' NoCommaFSep Token') L.ccOptions
     <*> monoidalFieldAla "cxx-options"          (alaList' NoCommaFSep Token') L.cxxOptions
+        ^^^ availableSince [2,1] [] -- TODO change to 2,2 when version is bumped
     <*> monoidalFieldAla "ld-options"           (alaList' NoCommaFSep Token') L.ldOptions
     <*> monoidalFieldAla "pkgconfig-depends"    (alaList  CommaFSep)          L.pkgconfigDepends
     <*> monoidalFieldAla "frameworks"           (alaList' FSep Token)         L.frameworks
@@ -372,10 +386,12 @@
     <*> monoidalFieldAla "cmm-sources"          (alaList' VCat FilePathNT)    L.cmmSources
     <*> monoidalFieldAla "c-sources"            (alaList' VCat FilePathNT)    L.cSources
     <*> monoidalFieldAla "cxx-sources"          (alaList' VCat FilePathNT)    L.cxxSources
+        ^^^ availableSince [2,1] [] -- TODO change to 2,2 when version is bumped
     <*> monoidalFieldAla "js-sources"           (alaList' VCat FilePathNT)    L.jsSources
     <*> hsSourceDirsGrammar
     <*> monoidalFieldAla "other-modules"        (alaList' VCat MQuoted)       L.otherModules
     <*> monoidalFieldAla "virtual-modules"      (alaList' VCat MQuoted)       L.virtualModules
+        ^^^ availableSince [2,1] [] -- TODO change to 2,2 when version is bumped
     <*> monoidalFieldAla "autogen-modules"      (alaList' VCat MQuoted)       L.autogenModules
     <*> optionalFieldAla "default-language"     MQuoted                       L.defaultLanguage
     <*> monoidalFieldAla "other-languages"      (alaList' FSep MQuoted)       L.otherLanguages
@@ -398,6 +414,7 @@
     <*> prefixedFields   "x-"                                                 L.customFieldsBI
     <*> monoidalFieldAla "build-depends"        (alaList  CommaVCat)          L.targetBuildDepends
     <*> monoidalFieldAla "mixins"               (alaList  CommaVCat)          L.mixins
+        ^^^ availableSince [2,0] []
 {-# SPECIALIZE buildInfoFieldGrammar :: ParsecFieldGrammar' BuildInfo #-}
 {-# SPECIALIZE buildInfoFieldGrammar :: PrettyFieldGrammar' BuildInfo #-}
 
@@ -415,17 +432,18 @@
 optionsFieldGrammar = combine
     <$> monoidalFieldAla "ghc-options"   (alaList' NoCommaFSep Token') (extract GHC)
     <*> monoidalFieldAla "ghcjs-options" (alaList' NoCommaFSep Token') (extract GHCJS)
-    <*> monoidalFieldAla "jhc-options"   (alaList' NoCommaFSep Token') (extract JHC)
-    -- NOTE: Hugs and NHC are not supported anymore, but these fields are kept
-    -- around for backwards compatibility.
+    -- NOTE: Hugs, NHC and JHC are not supported anymore, but these
+    -- fields are kept around so that we can still parse legacy .cabal
+    -- files that have them.
+    <*  knownField "jhc-options"
     <*  knownField "hugs-options"
     <*  knownField "nhc98-options"
   where
     extract :: CompilerFlavor -> ALens' BuildInfo [String]
     extract flavor = L.options . lookupLens flavor
 
-    combine ghc ghcjs jhs =
-        f GHC ghc ++ f GHCJS ghcjs ++ f JHC jhs
+    combine ghc ghcjs =
+        f GHC ghc ++ f GHCJS ghcjs
       where
         f _flavor []   = []
         f  flavor opts = [(flavor, opts)]
diff --git a/cabal/Cabal/Distribution/PackageDescription/Parse.hs b/cabal/Cabal/Distribution/PackageDescription/Parse.hs
deleted file mode 100644
--- a/cabal/Cabal/Distribution/PackageDescription/Parse.hs
+++ /dev/null
@@ -1,1336 +0,0 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE ScopedTypeVariables #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Distribution.PackageDescription.Parse
--- Copyright   :  Isaac Jones 2003-2005
--- License     :  BSD3
---
--- Maintainer  :  cabal-devel@haskell.org
--- Portability :  portable
---
--- This defined parsers and partial pretty printers for the @.cabal@ format.
--- Some of the complexity in this module is due to the fact that we have to be
--- backwards compatible with old @.cabal@ files, so there's code to translate
--- into the newer structure.
-
-module Distribution.PackageDescription.Parse (
-        -- * Package descriptions
-        readGenericPackageDescription,
-        parseGenericPackageDescription,
-
-        -- ** Deprecated names
-        readPackageDescription,
-        parsePackageDescription,
-
-        -- ** Parsing
-        ParseResult(..),
-        FieldDescr(..),
-        LineNo,
-
-        -- ** Private, but needed for pretty-printer
-        TestSuiteStanza(..),
-        BenchmarkStanza(..),
-
-        -- ** Supplementary build information
-        readHookedBuildInfo,
-        parseHookedBuildInfo,
-
-        pkgDescrFieldDescrs,
-        libFieldDescrs,
-        foreignLibFieldDescrs,
-        executableFieldDescrs,
-        binfoFieldDescrs,
-        sourceRepoFieldDescrs,
-        testSuiteFieldDescrs,
-        benchmarkFieldDescrs,
-        flagFieldDescrs
-  ) where
-
-import Prelude ()
-import Distribution.Compat.Prelude
-
-import Distribution.Types.Dependency
-import Distribution.Types.ForeignLib
-import Distribution.Types.ForeignLibType
-import Distribution.Types.UnqualComponentName
-import Distribution.Types.CondTree
-import Distribution.Types.PackageId
-import Distribution.ParseUtils hiding (parseFields)
-import Distribution.PackageDescription
-import Distribution.PackageDescription.Utils
-import Distribution.Package
-import Distribution.ModuleName
-import Distribution.Version
-import Distribution.Verbosity
-import Distribution.Compiler
-import Distribution.PackageDescription.Configuration
-import Distribution.Simple.Utils
-import Distribution.Text
-import Distribution.Compat.ReadP hiding (get)
-
-import Data.List        (partition, (\\))
-import System.Directory (doesFileExist)
-import Control.Monad    (mapM)
-
-import Text.PrettyPrint
-       (vcat, ($$), (<+>), text, render,
-        comma, fsep, nest, ($+$), punctuate)
-
-
--- -----------------------------------------------------------------------------
--- The PackageDescription type
-
-pkgDescrFieldDescrs :: [FieldDescr PackageDescription]
-pkgDescrFieldDescrs =
-    [ simpleField "name"
-           disp                   parse
-           packageName            (\name pkg -> pkg{package=(package pkg){pkgName=name}})
- , simpleField "version"
-           disp                   parse
-           packageVersion         (\ver pkg -> pkg{package=(package pkg){pkgVersion=ver}})
- , simpleField "cabal-version"
-           (either disp disp)     (liftM Left parse +++ liftM Right parse)
-           specVersionRaw         (\v pkg -> pkg{specVersionRaw=v})
- , simpleField "build-type"
-           (maybe mempty disp)  (fmap Just parse)
-           buildType              (\t pkg -> pkg{buildType=t})
- , simpleField "license"
-           disp                   parseLicenseQ
-           license                (\l pkg -> pkg{license=l})
-   -- We have both 'license-file' and 'license-files' fields.
-   -- Rather than declaring license-file to be deprecated, we will continue
-   -- to allow both. The 'license-file' will continue to only allow single
-   -- tokens, while 'license-files' allows multiple. On pretty-printing, we
-   -- will use 'license-file' if there's just one, and use 'license-files'
-   -- otherwise.
- , simpleField "license-file"
-           showFilePath           parseFilePathQ
-           (\pkg -> case licenseFiles pkg of
-                      [x] -> x
-                      _   -> "")
-           (\l pkg -> pkg{licenseFiles=licenseFiles pkg ++ [l]})
- , listField "license-files"
-           showFilePath           parseFilePathQ
-           (\pkg -> case licenseFiles pkg of
-                      [_] -> []
-                      xs  -> xs)
-           (\ls pkg -> pkg{licenseFiles=licenseFiles pkg ++ ls})
- , simpleField "copyright"
-           showFreeText           parseFreeText
-           copyright              (\val pkg -> pkg{copyright=val})
- , simpleField "maintainer"
-           showFreeText           parseFreeText
-           maintainer             (\val pkg -> pkg{maintainer=val})
- , simpleField "stability"
-           showFreeText           parseFreeText
-           stability              (\val pkg -> pkg{stability=val})
- , simpleField "homepage"
-           showFreeText           parseFreeText
-           homepage               (\val pkg -> pkg{homepage=val})
- , simpleField "package-url"
-           showFreeText           parseFreeText
-           pkgUrl                 (\val pkg -> pkg{pkgUrl=val})
- , simpleField "bug-reports"
-           showFreeText           parseFreeText
-           bugReports             (\val pkg -> pkg{bugReports=val})
- , simpleField "synopsis"
-           showFreeText           parseFreeText
-           synopsis               (\val pkg -> pkg{synopsis=val})
- , simpleField "description"
-           showFreeText           parseFreeText
-           description            (\val pkg -> pkg{description=val})
- , simpleField "category"
-           showFreeText           parseFreeText
-           category               (\val pkg -> pkg{category=val})
- , simpleField "author"
-           showFreeText           parseFreeText
-           author                 (\val pkg -> pkg{author=val})
- , listField "tested-with"
-           showTestedWith         parseTestedWithQ
-           testedWith             (\val pkg -> pkg{testedWith=val})
- , listFieldWithSep vcat "data-files"
-           showFilePath           parseFilePathQ
-           dataFiles              (\val pkg -> pkg{dataFiles=val})
- , simpleField "data-dir"
-           showFilePath           parseFilePathQ
-           dataDir                (\val pkg -> pkg{dataDir=val})
- , listFieldWithSep vcat "extra-source-files"
-           showFilePath    parseFilePathQ
-           extraSrcFiles          (\val pkg -> pkg{extraSrcFiles=val})
- , listFieldWithSep vcat "extra-tmp-files"
-           showFilePath       parseFilePathQ
-           extraTmpFiles          (\val pkg -> pkg{extraTmpFiles=val})
- , listFieldWithSep vcat "extra-doc-files"
-           showFilePath    parseFilePathQ
-           extraDocFiles          (\val pkg -> pkg{extraDocFiles=val})
- ]
-
--- | Store any fields beginning with "x-" in the customFields field of
---   a PackageDescription.  All other fields will generate a warning.
-storeXFieldsPD :: UnrecFieldParser PackageDescription
-storeXFieldsPD (f@('x':'-':_),val) pkg =
-  Just pkg{ customFieldsPD =
-               customFieldsPD pkg ++ [(f,val)]}
-storeXFieldsPD _ _ = Nothing
-
--- ---------------------------------------------------------------------------
--- The Library type
-
-libFieldDescrs :: [FieldDescr Library]
-libFieldDescrs =
-  [ listFieldWithSep vcat "exposed-modules" disp parseModuleNameQ
-      exposedModules (\mods lib -> lib{exposedModules=mods})
-
-  , commaListFieldWithSep vcat "reexported-modules" disp parse
-      reexportedModules (\mods lib -> lib{reexportedModules=mods})
-
-  , listFieldWithSep vcat "signatures" disp parseModuleNameQ
-      signatures (\mods lib -> lib{signatures=mods})
-
-  , boolField "exposed"
-      libExposed     (\val lib -> lib{libExposed=val})
-  ] ++ map biToLib binfoFieldDescrs
-  where biToLib = liftField libBuildInfo (\bi lib -> lib{libBuildInfo=bi})
-
-storeXFieldsLib :: UnrecFieldParser Library
-storeXFieldsLib (f@('x':'-':_), val) l@(Library { libBuildInfo = bi }) =
-    Just $ l {libBuildInfo =
-                 bi{ customFieldsBI = customFieldsBI bi ++ [(f,val)]}}
-storeXFieldsLib _ _ = Nothing
-
--- ---------------------------------------------------------------------------
--- Foreign libraries
-
-foreignLibFieldDescrs :: [FieldDescr ForeignLib]
-foreignLibFieldDescrs =
-  [ simpleField "type"
-      disp                   parse
-      foreignLibType         (\x flib -> flib { foreignLibType = x })
-  , listField "options"
-      disp                   parse
-      foreignLibOptions      (\x flib -> flib { foreignLibOptions = x })
-  , simpleField "lib-version-info"
-      (maybe mempty disp)    (fmap Just parse)
-      foreignLibVersionInfo  (\x flib -> flib { foreignLibVersionInfo = x })
-  , simpleField "lib-version-linux"
-      (maybe mempty disp)    (fmap Just parse)
-      foreignLibVersionLinux (\x flib -> flib { foreignLibVersionLinux = x })
-  , listField "mod-def-file"
-      showFilePath           parseFilePathQ
-      foreignLibModDefFile   (\x flib -> flib { foreignLibModDefFile = x })
-  ]
-  ++ map biToFLib binfoFieldDescrs
-  where biToFLib = liftField foreignLibBuildInfo $ \bi flib ->
-          flib { foreignLibBuildInfo = bi }
-
-storeXFieldsForeignLib :: UnrecFieldParser ForeignLib
-storeXFieldsForeignLib (f@('x':'-':_), val)
-                        l@(ForeignLib { foreignLibBuildInfo = bi }) =
-    Just $ l { foreignLibBuildInfo = bi {
-                   customFieldsBI = (f,val):customFieldsBI bi
-                 }
-             }
-storeXFieldsForeignLib _ _ = Nothing
-
--- ---------------------------------------------------------------------------
--- The Executable type
-
-
-executableFieldDescrs :: [FieldDescr Executable]
-executableFieldDescrs =
-  [ simpleField "main-is"
-                           showFilePath       parseFilePathQ
-                           modulePath         (\xs    exe -> exe{modulePath=xs})
-  , simpleField "scope"
-                           disp               parse
-                           exeScope           (\sc    exe -> exe{exeScope=sc})
-  ]
-  ++ map biToExe binfoFieldDescrs
-  where biToExe = liftField buildInfo (\bi exe -> exe{buildInfo=bi})
-
-storeXFieldsExe :: UnrecFieldParser Executable
-storeXFieldsExe (f@('x':'-':_), val) e@(Executable { buildInfo = bi }) =
-    Just $ e {buildInfo = bi{ customFieldsBI = (f,val):customFieldsBI bi}}
-storeXFieldsExe _ _ = Nothing
-
--- ---------------------------------------------------------------------------
--- The TestSuite type
-
--- | An intermediate type just used for parsing the test-suite stanza.
--- After validation it is converted into the proper 'TestSuite' type.
-data TestSuiteStanza = TestSuiteStanza {
-       testStanzaTestType   :: Maybe TestType,
-       testStanzaMainIs     :: Maybe FilePath,
-       testStanzaTestModule :: Maybe ModuleName,
-       testStanzaBuildInfo  :: BuildInfo
-     }
-
-emptyTestStanza :: TestSuiteStanza
-emptyTestStanza = TestSuiteStanza Nothing Nothing Nothing mempty
-
-testSuiteFieldDescrs :: [FieldDescr TestSuiteStanza]
-testSuiteFieldDescrs =
-    [ simpleField "type"
-        (maybe mempty disp) (fmap Just parse)
-        testStanzaTestType    (\x suite -> suite { testStanzaTestType = x })
-    , simpleField "main-is"
-        (maybe mempty showFilePath)  (fmap Just parseFilePathQ)
-        testStanzaMainIs      (\x suite -> suite { testStanzaMainIs = x })
-    , simpleField "test-module"
-        (maybe mempty disp) (fmap Just parseModuleNameQ)
-        testStanzaTestModule  (\x suite -> suite { testStanzaTestModule = x })
-    ]
-    ++ map biToTest binfoFieldDescrs
-  where
-    biToTest = liftField testStanzaBuildInfo
-                         (\bi suite -> suite { testStanzaBuildInfo = bi })
-
-storeXFieldsTest :: UnrecFieldParser TestSuiteStanza
-storeXFieldsTest (f@('x':'-':_), val) t@(TestSuiteStanza { testStanzaBuildInfo = bi }) =
-    Just $ t {testStanzaBuildInfo = bi{ customFieldsBI = (f,val):customFieldsBI bi}}
-storeXFieldsTest _ _ = Nothing
-
-validateTestSuite :: LineNo -> TestSuiteStanza -> ParseResult TestSuite
-validateTestSuite line stanza =
-    case testStanzaTestType stanza of
-      Nothing -> return $
-        emptyTestSuite { testBuildInfo = testStanzaBuildInfo stanza }
-
-      Just tt@(TestTypeUnknown _ _) ->
-        return emptyTestSuite {
-          testInterface = TestSuiteUnsupported tt,
-          testBuildInfo = testStanzaBuildInfo stanza
-        }
-
-      Just tt | tt `notElem` knownTestTypes ->
-        return emptyTestSuite {
-          testInterface = TestSuiteUnsupported tt,
-          testBuildInfo = testStanzaBuildInfo stanza
-        }
-
-      Just tt@(TestTypeExe ver) ->
-        case testStanzaMainIs stanza of
-          Nothing   -> syntaxError line (missingField "main-is" tt)
-          Just file -> do
-            when (isJust (testStanzaTestModule stanza)) $
-              warning (extraField "test-module" tt)
-            return emptyTestSuite {
-              testInterface = TestSuiteExeV10 ver file,
-              testBuildInfo = testStanzaBuildInfo stanza
-            }
-
-      Just tt@(TestTypeLib ver) ->
-        case testStanzaTestModule stanza of
-          Nothing      -> syntaxError line (missingField "test-module" tt)
-          Just module_ -> do
-            when (isJust (testStanzaMainIs stanza)) $
-              warning (extraField "main-is" tt)
-            return emptyTestSuite {
-              testInterface = TestSuiteLibV09 ver module_,
-              testBuildInfo = testStanzaBuildInfo stanza
-            }
-
-  where
-    missingField name tt = "The '" ++ name ++ "' field is required for the "
-                        ++ display tt ++ " test suite type."
-
-    extraField   name tt = "The '" ++ name ++ "' field is not used for the '"
-                        ++ display tt ++ "' test suite type."
-
-
--- ---------------------------------------------------------------------------
--- The Benchmark type
-
--- | An intermediate type just used for parsing the benchmark stanza.
--- After validation it is converted into the proper 'Benchmark' type.
-data BenchmarkStanza = BenchmarkStanza {
-       benchmarkStanzaBenchmarkType   :: Maybe BenchmarkType,
-       benchmarkStanzaMainIs          :: Maybe FilePath,
-       benchmarkStanzaBenchmarkModule :: Maybe ModuleName,
-       benchmarkStanzaBuildInfo       :: BuildInfo
-     }
-
-emptyBenchmarkStanza :: BenchmarkStanza
-emptyBenchmarkStanza = BenchmarkStanza Nothing Nothing Nothing mempty
-
-benchmarkFieldDescrs :: [FieldDescr BenchmarkStanza]
-benchmarkFieldDescrs =
-    [ simpleField "type"
-        (maybe mempty disp)    (fmap Just parse)
-        benchmarkStanzaBenchmarkType
-        (\x suite -> suite { benchmarkStanzaBenchmarkType = x })
-    , simpleField "main-is"
-        (maybe mempty showFilePath)  (fmap Just parseFilePathQ)
-        benchmarkStanzaMainIs
-        (\x suite -> suite { benchmarkStanzaMainIs = x })
-    ]
-    ++ map biToBenchmark binfoFieldDescrs
-  where
-    biToBenchmark = liftField benchmarkStanzaBuildInfo
-                    (\bi suite -> suite { benchmarkStanzaBuildInfo = bi })
-
-storeXFieldsBenchmark :: UnrecFieldParser BenchmarkStanza
-storeXFieldsBenchmark (f@('x':'-':_), val)
-    t@(BenchmarkStanza { benchmarkStanzaBuildInfo = bi }) =
-        Just $ t {benchmarkStanzaBuildInfo =
-                       bi{ customFieldsBI = (f,val):customFieldsBI bi}}
-storeXFieldsBenchmark _ _ = Nothing
-
-validateBenchmark :: LineNo -> BenchmarkStanza -> ParseResult Benchmark
-validateBenchmark line stanza =
-    case benchmarkStanzaBenchmarkType stanza of
-      Nothing -> return $
-        emptyBenchmark { benchmarkBuildInfo = benchmarkStanzaBuildInfo stanza }
-
-      Just tt@(BenchmarkTypeUnknown _ _) ->
-        return emptyBenchmark {
-          benchmarkInterface = BenchmarkUnsupported tt,
-          benchmarkBuildInfo = benchmarkStanzaBuildInfo stanza
-        }
-
-      Just tt | tt `notElem` knownBenchmarkTypes ->
-        return emptyBenchmark {
-          benchmarkInterface = BenchmarkUnsupported tt,
-          benchmarkBuildInfo = benchmarkStanzaBuildInfo stanza
-        }
-
-      Just tt@(BenchmarkTypeExe ver) ->
-        case benchmarkStanzaMainIs stanza of
-          Nothing   -> syntaxError line (missingField "main-is" tt)
-          Just file -> do
-            when (isJust (benchmarkStanzaBenchmarkModule stanza)) $
-              warning (extraField "benchmark-module" tt)
-            return emptyBenchmark {
-              benchmarkInterface = BenchmarkExeV10 ver file,
-              benchmarkBuildInfo = benchmarkStanzaBuildInfo stanza
-            }
-
-  where
-    missingField name tt = "The '" ++ name ++ "' field is required for the "
-                        ++ display tt ++ " benchmark type."
-
-    extraField   name tt = "The '" ++ name ++ "' field is not used for the '"
-                        ++ display tt ++ "' benchmark type."
-
--- ---------------------------------------------------------------------------
--- The BuildInfo type
-
-binfoFieldDescrs :: [FieldDescr BuildInfo]
-binfoFieldDescrs =
- [ boolField "buildable"
-           buildable          (\val binfo -> binfo{buildable=val})
- , commaListField  "build-tools"
-           disp               parse
-           buildTools         (\xs  binfo -> binfo{buildTools=xs})
- , commaListField  "build-tool-depends"
-           disp               parse
-           buildToolDepends   (\xs  binfo -> binfo{buildToolDepends=xs})
- , commaListFieldWithSep vcat "build-depends"
-           disp               parse
-           targetBuildDepends (\xs binfo -> binfo{targetBuildDepends=xs})
- , commaListFieldWithSep vcat "mixins"
-           disp               parse
-           mixins             (\xs binfo -> binfo{mixins=xs})
- , spaceListField "cpp-options"
-           showToken          parseTokenQ'
-           cppOptions         (\val binfo -> binfo{cppOptions=val})
- , spaceListField "asm-options"
-           showToken          parseTokenQ'
-           asmOptions         (\val binfo -> binfo{asmOptions=val})
- , spaceListField "cmm-options"
-           showToken          parseTokenQ'
-           cmmOptions         (\val binfo -> binfo{cmmOptions=val})
- , spaceListField "cc-options"
-           showToken          parseTokenQ'
-           ccOptions          (\val binfo -> binfo{ccOptions=val})
- , spaceListField "cxx-options"
-           showToken          parseTokenQ'
-           cxxOptions         (\val binfo -> binfo{cxxOptions=val})
- , spaceListField "ld-options"
-           showToken          parseTokenQ'
-           ldOptions          (\val binfo -> binfo{ldOptions=val})
- , commaListField  "pkgconfig-depends"
-           disp               parse
-           pkgconfigDepends   (\xs  binfo -> binfo{pkgconfigDepends=xs})
- , listField "frameworks"
-           showToken          parseTokenQ
-           frameworks         (\val binfo -> binfo{frameworks=val})
- , listField "extra-framework-dirs"
-           showToken          parseFilePathQ
-           extraFrameworkDirs (\val binfo -> binfo{extraFrameworkDirs=val})
- , listFieldWithSep vcat "asm-sources"
-           showFilePath       parseFilePathQ
-           asmSources         (\paths binfo -> binfo{asmSources=paths})
- , listFieldWithSep vcat "cmm-sources"
-           showFilePath       parseFilePathQ
-           cmmSources         (\paths binfo -> binfo{cmmSources=paths})
- , listFieldWithSep vcat "c-sources"
-           showFilePath       parseFilePathQ
-           cSources           (\paths binfo -> binfo{cSources=paths})
- , listFieldWithSep vcat "cxx-sources"
-           showFilePath       parseFilePathQ
-           cxxSources         (\paths binfo -> binfo{cxxSources=paths})
- , listFieldWithSep vcat "js-sources"
-           showFilePath       parseFilePathQ
-           jsSources          (\paths binfo -> binfo{jsSources=paths})
- , simpleField "default-language"
-           (maybe mempty disp) (option Nothing (fmap Just parseLanguageQ))
-           defaultLanguage    (\lang  binfo -> binfo{defaultLanguage=lang})
- , listField   "other-languages"
-           disp               parseLanguageQ
-           otherLanguages     (\langs binfo -> binfo{otherLanguages=langs})
- , listField   "default-extensions"
-           disp               parseExtensionQ
-           defaultExtensions  (\exts  binfo -> binfo{defaultExtensions=exts})
- , listField   "other-extensions"
-           disp               parseExtensionQ
-           otherExtensions    (\exts  binfo -> binfo{otherExtensions=exts})
- , listField   "extensions"
-           disp               parseExtensionQ
-           oldExtensions      (\exts  binfo -> binfo{oldExtensions=exts})
-
- , listFieldWithSep vcat "extra-libraries"
-           showToken          parseTokenQ
-           extraLibs          (\xs    binfo -> binfo{extraLibs=xs})
- , listFieldWithSep vcat "extra-ghci-libraries"
-           showToken          parseTokenQ
-           extraGHCiLibs      (\xs    binfo -> binfo{extraGHCiLibs=xs})
- , listFieldWithSep vcat "extra-bundled-libraries"
-           showToken          parseTokenQ
-           extraBundledLibs   (\xs binfo -> binfo{extraBundledLibs=xs})
- , listFieldWithSep vcat "extra-library-flavours"
-           showToken          parseTokenQ
-           extraLibFlavours   (\xs binfo -> binfo{extraLibFlavours=xs})
- , listField   "extra-lib-dirs"
-           showFilePath       parseFilePathQ
-           extraLibDirs       (\xs    binfo -> binfo{extraLibDirs=xs})
- , listFieldWithSep vcat "includes"
-           showFilePath       parseFilePathQ
-           includes           (\paths binfo -> binfo{includes=paths})
- , listFieldWithSep vcat "install-includes"
-           showFilePath       parseFilePathQ
-           installIncludes    (\paths binfo -> binfo{installIncludes=paths})
- , listField   "include-dirs"
-           showFilePath       parseFilePathQ
-           includeDirs        (\paths binfo -> binfo{includeDirs=paths})
- , listField   "hs-source-dirs"
-           showFilePath       parseFilePathQ
-           hsSourceDirs       (\paths binfo -> binfo{hsSourceDirs=paths})
- , listFieldWithSep vcat "other-modules"
-           disp               parseModuleNameQ
-           otherModules       (\val binfo -> binfo{otherModules=val})
- , listFieldWithSep vcat "virtual-modules"
-           disp               parseModuleNameQ
-           virtualModules       (\val binfo -> binfo{virtualModules=val})
- , listFieldWithSep vcat "autogen-modules"
-           disp               parseModuleNameQ
-           autogenModules       (\val binfo -> binfo{autogenModules=val})
- , optsField   "ghc-prof-options" GHC
-           profOptions        (\val binfo -> binfo{profOptions=val})
- , optsField   "ghcjs-prof-options" GHCJS
-           profOptions        (\val binfo -> binfo{profOptions=val})
- , optsField   "ghc-shared-options" GHC
-           sharedOptions      (\val binfo -> binfo{sharedOptions=val})
- , optsField   "ghcjs-shared-options" GHCJS
-           sharedOptions      (\val binfo -> binfo{sharedOptions=val})
- , optsField   "ghc-options"  GHC
-           options            (\path  binfo -> binfo{options=path})
- , optsField   "ghcjs-options" GHCJS
-           options            (\path  binfo -> binfo{options=path})
- , optsField   "jhc-options"  JHC
-           options            (\path  binfo -> binfo{options=path})
-
- -- NOTE: Hugs and NHC are not supported anymore, but these fields are kept
- -- around for backwards compatibility.
- , optsField   "hugs-options" Hugs
-           options            (const id)
- , optsField   "nhc98-options" NHC
-           options            (const id)
- ]
-
-storeXFieldsBI :: UnrecFieldParser BuildInfo
-storeXFieldsBI (f@('x':'-':_),val) bi = Just bi{ customFieldsBI = (f,val):customFieldsBI bi }
-storeXFieldsBI _ _ = Nothing
-
-------------------------------------------------------------------------------
-
-flagFieldDescrs :: [FieldDescr Flag]
-flagFieldDescrs =
-    [ simpleField "description"
-        showFreeText     parseFreeText
-        flagDescription  (\val fl -> fl{ flagDescription = val })
-    , boolField "default"
-        flagDefault      (\val fl -> fl{ flagDefault = val })
-    , boolField "manual"
-        flagManual       (\val fl -> fl{ flagManual = val })
-    ]
-
-------------------------------------------------------------------------------
-
-sourceRepoFieldDescrs :: [FieldDescr SourceRepo]
-sourceRepoFieldDescrs =
-    [ simpleField "type"
-        (maybe mempty disp)         (fmap Just parse)
-        repoType                   (\val repo -> repo { repoType = val })
-    , simpleField "location"
-        (maybe mempty showFreeText) (fmap Just parseFreeText)
-        repoLocation               (\val repo -> repo { repoLocation = val })
-    , simpleField "module"
-        (maybe mempty showToken)    (fmap Just parseTokenQ)
-        repoModule                 (\val repo -> repo { repoModule = val })
-    , simpleField "branch"
-        (maybe mempty showToken)    (fmap Just parseTokenQ)
-        repoBranch                 (\val repo -> repo { repoBranch = val })
-    , simpleField "tag"
-        (maybe mempty showToken)    (fmap Just parseTokenQ)
-        repoTag                    (\val repo -> repo { repoTag = val })
-    , simpleField "subdir"
-        (maybe mempty showFilePath) (fmap Just parseFilePathQ)
-        repoSubdir                 (\val repo -> repo { repoSubdir = val })
-    ]
-
-------------------------------------------------------------------------------
-
-setupBInfoFieldDescrs :: [FieldDescr SetupBuildInfo]
-setupBInfoFieldDescrs =
-    [ commaListFieldWithSep vcat "setup-depends"
-        disp         parse
-        setupDepends (\xs binfo -> binfo{setupDepends=xs})
-    ]
-
--- ---------------------------------------------------------------
--- Parsing
-
--- | Given a parser and a filename, return the parse of the file,
--- after checking if the file exists.
-readAndParseFile :: (FilePath -> (String -> IO a) -> IO a)
-                 -> (String -> ParseResult a)
-                 -> Verbosity
-                 -> FilePath -> IO a
-readAndParseFile withFileContents' parser verbosity fpath = do
-  exists <- doesFileExist fpath
-  unless exists $
-    die' verbosity $
-      "Error Parsing: file \"" ++ fpath ++ "\" doesn't exist. Cannot continue."
-  withFileContents' fpath $ \str -> case parser str of
-    ParseFailed e -> do
-        let (line, message) = locatedErrorMsg e
-        dieWithLocation' verbosity fpath line message
-    ParseOk warnings x -> do
-        traverse_ (warn verbosity . showPWarning fpath) $ reverse warnings
-        return x
-
-readHookedBuildInfo :: Verbosity -> FilePath -> IO HookedBuildInfo
-readHookedBuildInfo =
-    readAndParseFile withFileContents parseHookedBuildInfo
-
-readPackageDescription :: Verbosity -> FilePath -> IO GenericPackageDescription
-readPackageDescription = readGenericPackageDescription
-{-# DEPRECATED readPackageDescription "Use readGenericPackageDescription, old name is misleading." #-}
-
--- | Parse the given package file.
-readGenericPackageDescription :: Verbosity -> FilePath -> IO GenericPackageDescription
-readGenericPackageDescription =
-    readAndParseFile withUTF8FileContents parseGenericPackageDescription
-
-stanzas :: [Field] -> [[Field]]
-stanzas [] = []
-stanzas (f:fields) = (f:this) : stanzas rest
-  where
-    (this, rest) = break isStanzaHeader fields
-
-isStanzaHeader :: Field -> Bool
-isStanzaHeader (F _ f _) = f == "executable"
-isStanzaHeader _ = False
-
-------------------------------------------------------------------------------
-
-
-mapSimpleFields :: (Field -> ParseResult Field) -> [Field]
-                -> ParseResult [Field]
-mapSimpleFields f = traverse walk
-  where
-    walk fld@F{} = f fld
-    walk (IfBlock l c fs1 fs2) = do
-      fs1' <- traverse walk fs1
-      fs2' <- traverse walk fs2
-      return (IfBlock l c fs1' fs2')
-    walk (Section ln n l fs1) = do
-      fs1' <-  traverse walk fs1
-      return (Section ln n l fs1')
-
--- prop_isMapM fs = mapSimpleFields return fs == return fs
-
-
--- names of fields that represents dependencies
--- TODO: maybe build-tools should go here too?
-constraintFieldNames :: [String]
-constraintFieldNames = ["build-depends"]
-
--- Possible refactoring would be to have modifiers be explicit about what
--- they add and define an accessor that specifies what the dependencies
--- are.  This way we would completely reuse the parsing knowledge from the
--- field descriptor.
-parseConstraint :: Field -> ParseResult [Dependency]
-parseConstraint (F l n v)
-    | n `elem` constraintFieldNames = runP l n (parseCommaList parse) v
-parseConstraint f = userBug $ "Constraint was expected (got: " ++ show f ++ ")"
-
-{-
-headerFieldNames :: [String]
-headerFieldNames = filter (\n -> not (n `elem` constraintFieldNames))
-                 . map fieldName $ pkgDescrFieldDescrs
--}
-
-libFieldNames :: [String]
-libFieldNames = map fieldName libFieldDescrs
-                ++ buildInfoNames ++ constraintFieldNames
-
--- exeFieldNames :: [String]
--- exeFieldNames = map fieldName executableFieldDescrs
---                 ++ buildInfoNames
-
-buildInfoNames :: [String]
-buildInfoNames = map fieldName binfoFieldDescrs
-                ++ map fst deprecatedFieldsBuildInfo
-
--- A minimal implementation of the StateT monad transformer to avoid depending
--- on the 'mtl' package.
-newtype StT s m a = StT { runStT :: s -> m (a,s) }
-
-instance Functor f => Functor (StT s f) where
-    fmap g (StT f) = StT $ fmap (first g)  . f
-
-#if __GLASGOW_HASKELL__ >= 710
-instance (Monad m) => Applicative (StT s m) where
-#else
-instance (Monad m, Functor m) => Applicative (StT s m) where
-#endif
-    pure a = StT (\s -> return (a,s))
-    (<*>) = ap
-
-
-instance Monad m => Monad (StT s m) where
-#if __GLASGOW_HASKELL__ < 710
-    return a = StT (\s -> return (a,s))
-#endif
-    StT f >>= g = StT $ \s -> do
-                        (a,s') <- f s
-                        runStT (g a) s'
-
-getSt :: Monad m => StT s m s
-getSt = StT $ \s -> return (s, s)
-
-modify :: Monad m => (s -> s) -> StT s m ()
-modify f = StT $ \s -> return ((),f s)
-
-lift :: Monad m => m a -> StT s m a
-lift m = StT $ \s -> m >>= \a -> return (a,s)
-
-evalStT :: Monad m => StT s m a -> s -> m a
-evalStT st s = liftM fst $ runStT st s
-
--- Our monad for parsing a list/tree of fields.
---
--- The state represents the remaining fields to be processed.
-type PM a = StT [Field] ParseResult a
-
-
-
--- return look-ahead field or nothing if we're at the end of the file
-peekField :: PM (Maybe Field)
-peekField = liftM listToMaybe getSt
-
--- Unconditionally discard the first field in our state.  Will error when it
--- reaches end of file.  (Yes, that's evil.)
-skipField :: PM ()
-skipField = modify tail
-
---FIXME: this should take a ByteString, not a String. We have to be able to
--- decode UTF8 and handle the BOM.
-
-parsePackageDescription :: String -> ParseResult GenericPackageDescription
-parsePackageDescription = parseGenericPackageDescription
-{-# DEPRECATED parsePackageDescription "Use parseGenericPackageDescription, old name is misleading" #-}
-
--- | Parses the given file into a 'GenericPackageDescription'.
---
--- In Cabal 1.2 the syntax for package descriptions was changed to a format
--- with sections and possibly indented property descriptions.
-parseGenericPackageDescription :: String -> ParseResult GenericPackageDescription
-parseGenericPackageDescription file = do
-
-    -- This function is quite complex because it needs to be able to parse
-    -- both pre-Cabal-1.2 and post-Cabal-1.2 files.  Additionally, it contains
-    -- a lot of parser-related noise since we do not want to depend on Parsec.
-    --
-    -- If we detect an pre-1.2 file we implicitly convert it to post-1.2
-    -- style.  See 'sectionizeFields' below for details about the conversion.
-
-    fields0 <- readFields file `catchParseError` \err ->
-                 let tabs = findIndentTabs file in
-                 case err of
-                   -- In case of a TabsError report them all at once.
-                   TabsError tabLineNo -> reportTabsError
-                   -- but only report the ones including and following
-                   -- the one that caused the actual error
-                                            [ t | t@(lineNo',_) <- tabs
-                                                , lineNo' >= tabLineNo ]
-                   _ -> parseFail err
-
-    let cabalVersionNeeded =
-          head $ [ minVersionBound versionRange
-                 | Just versionRange <- [ simpleParse v
-                                        | F _ "cabal-version" v <- fields0 ] ]
-              ++ [mkVersion [0]]
-        minVersionBound versionRange =
-          case asVersionIntervals versionRange of
-            []                            -> mkVersion [0]
-            ((LowerBound version _, _):_) -> version
-
-    handleFutureVersionParseFailure cabalVersionNeeded $ do
-
-      let sf = sectionizeFields fields0  -- ensure 1.2 format
-
-        -- figure out and warn about deprecated stuff (warnings are collected
-        -- inside our parsing monad)
-      fields <- mapSimpleFields deprecField sf
-
-        -- Our parsing monad takes the not-yet-parsed fields as its state.
-        -- After each successful parse we remove the field from the state
-        -- ('skipField') and move on to the next one.
-        --
-        -- Things are complicated a bit, because fields take a tree-like
-        -- structure -- they can be sections or "if"/"else" conditionals.
-
-      flip evalStT fields $ do
-
-          -- The header consists of all simple fields up to the first section
-          -- (flag, library, executable).
-        header_fields <- getHeader []
-
-          -- Parses just the header fields and stores them in a
-          -- 'PackageDescription'.  Note that our final result is a
-          -- 'GenericPackageDescription'; for pragmatic reasons we just store
-          -- the partially filled-out 'PackageDescription' inside the
-          -- 'GenericPackageDescription'.
-        pkg <- lift $ parseFields pkgDescrFieldDescrs
-                                  storeXFieldsPD
-                                  emptyPackageDescription
-                                  header_fields
-
-          -- 'getBody' assumes that the remaining fields only consist of
-          -- flags, lib and exe sections.
-        (repos, flags, mcsetup, mlib, sub_libs, flibs, exes, tests, bms) <- getBody pkg
-        warnIfRest  -- warn if getBody did not parse up to the last field.
-          -- warn about using old/new syntax with wrong cabal-version:
-        maybeWarnCabalVersion (not $ oldSyntax fields0) pkg
-        checkForUndefinedFlags flags mlib sub_libs exes tests
-        return $ GenericPackageDescription
-                   pkg { sourceRepos = repos, setupBuildInfo = mcsetup }
-                   flags mlib sub_libs flibs exes tests bms
-
-  where
-    oldSyntax = all isSimpleField
-    reportTabsError tabs =
-        syntaxError (fst (head tabs)) $
-          "Do not use tabs for indentation (use spaces instead)\n"
-          ++ "  Tabs were used at (line,column): " ++ show tabs
-
-    maybeWarnCabalVersion newsyntax pkg
-      | newsyntax && specVersion pkg < mkVersion [1,2]
-      = lift $ warning $
-             "A package using section syntax must specify at least\n"
-          ++ "'cabal-version: >= 1.2'."
-
-    maybeWarnCabalVersion newsyntax pkg
-      | not newsyntax && specVersion pkg >= mkVersion [1,2]
-      = lift $ warning $
-             "A package using 'cabal-version: "
-          ++ displaySpecVersion (specVersionRaw pkg)
-          ++ "' must use section syntax. See the Cabal user guide for details."
-      where
-        displaySpecVersion (Left version)       = display version
-        displaySpecVersion (Right versionRange) =
-          case asVersionIntervals versionRange of
-            [] {- impossible -}           -> display versionRange
-            ((LowerBound version _, _):_) -> display (orLaterVersion version)
-
-    maybeWarnCabalVersion _ _ = return ()
-
-
-    handleFutureVersionParseFailure cabalVersionNeeded parseBody =
-      (unless versionOk (warning message) >> parseBody)
-        `catchParseError` \parseError -> case parseError of
-        TabsError _   -> parseFail parseError
-        _ | versionOk -> parseFail parseError
-          | otherwise -> fail message
-      where versionOk = cabalVersionNeeded <= cabalVersion
-            message   = "This package requires at least Cabal version "
-                     ++ display cabalVersionNeeded
-
-    -- "Sectionize" an old-style Cabal file.  A sectionized file has:
-    --
-    --  * all global fields at the beginning, followed by
-    --
-    --  * all flag declarations, followed by
-    --
-    --  * an optional library section, and an arbitrary number of executable
-    --    sections (in any order).
-    --
-    -- The current implementation just gathers all library-specific fields
-    -- in a library section and wraps all executable stanzas in an executable
-    -- section.
-    sectionizeFields :: [Field] -> [Field]
-    sectionizeFields fs
-      | oldSyntax fs =
-          let
-            -- "build-depends" is a local field now.  To be backwards
-            -- compatible, we still allow it as a global field in old-style
-            -- package description files and translate it to a local field by
-            -- adding it to every non-empty section
-            (hdr0, exes0) = break ((=="executable") . fName) fs
-            (hdr, libfs0) = partition (not . (`elem` libFieldNames) . fName) hdr0
-
-            (deps, libfs) = partition ((== "build-depends") . fName)
-                                       libfs0
-
-            exes = unfoldr toExe exes0
-            toExe [] = Nothing
-            toExe (F l e n : r)
-              | e == "executable" =
-                  let (efs, r') = break ((=="executable") . fName) r
-                  in Just (Section l "executable" n (deps ++ efs), r')
-            toExe _ = cabalBug "unexpected input to 'toExe'"
-          in
-            hdr ++
-           (if null libfs then []
-            else [Section (lineNo (head libfs)) "library" "" (deps ++ libfs)])
-            ++ exes
-      | otherwise = fs
-
-    isSimpleField F{} = True
-    isSimpleField _ = False
-
-    -- warn if there's something at the end of the file
-    warnIfRest :: PM ()
-    warnIfRest = do
-      s <- getSt
-      case s of
-        [] -> return ()
-        _ -> lift $ warning "Ignoring trailing declarations."  -- add line no.
-
-    -- all simple fields at the beginning of the file are (considered) header
-    -- fields
-    getHeader :: [Field] -> PM [Field]
-    getHeader acc = peekField >>= \mf -> case mf of
-        Just f@F{} -> skipField >> getHeader (f:acc)
-        _ -> return (reverse acc)
-
-    --
-    -- body ::= { repo | flag | library | sub library | foreign library
-    --          | executable | test | bench }+
-    --
-    -- The body consists of an optional sequence of declarations of flags and
-    -- an arbitrary number of components
-    --
-    -- TODO: This method is long due for a rewrite to use a accumulator
-    -- data type, or perhaps some more general way of balling the
-    -- components up.
-    getBody :: PackageDescription
-            -> PM ([SourceRepo], [Flag]
-                  ,Maybe SetupBuildInfo
-                  ,(Maybe (CondTree ConfVar [Dependency] Library))
-                  ,[(UnqualComponentName, CondTree ConfVar [Dependency] Library)]
-                  ,[(UnqualComponentName, CondTree ConfVar [Dependency] ForeignLib)]
-                  ,[(UnqualComponentName, CondTree ConfVar [Dependency] Executable)]
-                  ,[(UnqualComponentName, CondTree ConfVar [Dependency] TestSuite)]
-                  ,[(UnqualComponentName, CondTree ConfVar [Dependency] Benchmark)])
-    getBody pkg = peekField >>= \mf -> case mf of
-      Just (Section line_no sec_type sec_label sec_fields)
-        | sec_type == "executable" -> do
-            when (null sec_label) $ lift $ syntaxError line_no
-              "'executable' needs one argument (the executable's name)"
-            exename <- lift $ runP line_no "executable" parseTokenQ sec_label
-            flds <- collectFields parseExeFields sec_fields
-            skipField
-            (repos, flags, csetup, mlib, sub_libs, flibs, exes, tests, bms) <- getBody pkg
-            return (repos, flags, csetup, mlib, sub_libs, flibs, (mkUnqualComponentName exename, flds): exes, tests, bms)
-
-        | sec_type == "foreign-library" -> do
-            when (null sec_label) $ lift $ syntaxError line_no
-              "'foreign-library' needs one argument (the library's name)"
-            libname <- lift $ runP line_no "foreign-library" parseTokenQ sec_label
-            flds <- collectFields parseForeignLibFields sec_fields
-
-            -- Check that a valid foreign library type has been chosen. A type
-            -- field may be given inside a conditional block, so we must check
-            -- for that before complaining that a type field has not been given.
-            -- The foreign library must always have a valid type, so we need to
-            -- check both the 'then' and 'else' blocks, though the blocks need
-            -- not have the same type.
-            let hasType ts = foreignLibType ts /= foreignLibType mempty
-            if onAllBranches hasType flds
-                then do
-                    skipField
-                    (repos, flags, csetup, mlib, sub_libs, flibs, exes, tests, bms) <- getBody pkg
-                    return (repos, flags, csetup, mlib, sub_libs, (mkUnqualComponentName libname, flds):flibs, exes, tests, bms)
-                else lift $ syntaxError line_no $
-                         "Foreign library \"" ++ libname
-                      ++ "\" is missing required field \"type\" or the field "
-                      ++ "is not present in all conditional branches. The "
-                      ++ "available test types are: "
-                      ++ intercalate ", " (map display knownForeignLibTypes)
-
-        | sec_type == "test-suite" -> do
-            when (null sec_label) $ lift $ syntaxError line_no
-                "'test-suite' needs one argument (the test suite's name)"
-            testname <- lift $ runP line_no "test" parseTokenQ sec_label
-            flds <- collectFields (parseTestFields line_no) sec_fields
-
-            -- Check that a valid test suite type has been chosen. A type field
-            -- may be given inside a conditional block, so we must check for
-            -- that before complaining that a type field has not been given. The
-            -- test suite must always have a valid type, so we need to check
-            -- both the 'then' and 'else' blocks, though the blocks need not
-            -- have the same type.
-            let hasType ts = testInterface ts /= testInterface mempty
-            if onAllBranches hasType flds
-                then do
-                    skipField
-                    (repos, flags, csetup, mlib, sub_libs, flibs, exes, tests, bms) <- getBody pkg
-                    return (repos, flags, csetup, mlib, sub_libs, flibs, exes,
-                            (mkUnqualComponentName testname, flds) : tests, bms)
-                else lift $ syntaxError line_no $
-                         "Test suite \"" ++ testname
-                      ++ "\" is missing required field \"type\" or the field "
-                      ++ "is not present in all conditional branches. The "
-                      ++ "available test types are: "
-                      ++ intercalate ", " (map display knownTestTypes)
-
-        | sec_type == "benchmark" -> do
-            when (null sec_label) $ lift $ syntaxError line_no
-                "'benchmark' needs one argument (the benchmark's name)"
-            benchname <- lift $ runP line_no "benchmark" parseTokenQ sec_label
-            flds <- collectFields (parseBenchmarkFields line_no) sec_fields
-
-            -- Check that a valid benchmark type has been chosen. A type field
-            -- may be given inside a conditional block, so we must check for
-            -- that before complaining that a type field has not been given. The
-            -- benchmark must always have a valid type, so we need to check both
-            -- the 'then' and 'else' blocks, though the blocks need not have the
-            -- same type.
-            let hasType ts = benchmarkInterface ts /= benchmarkInterface mempty
-            if onAllBranches hasType flds
-                then do
-                    skipField
-                    (repos, flags, csetup, mlib, sub_libs, flibs, exes, tests, bms) <- getBody pkg
-                    return (repos, flags, csetup, mlib, sub_libs, flibs, exes,
-                            tests, (mkUnqualComponentName benchname, flds) : bms)
-                else lift $ syntaxError line_no $
-                         "Benchmark \"" ++ benchname
-                      ++ "\" is missing required field \"type\" or the field "
-                      ++ "is not present in all conditional branches. The "
-                      ++ "available benchmark types are: "
-                      ++ intercalate ", " (map display knownBenchmarkTypes)
-
-        | sec_type == "library" -> do
-            mb_libname <- if null sec_label
-                            then return Nothing
-                            -- TODO: relax this parsing so that scoping is handled
-                            -- correctly
-                            else fmap Just . lift
-                                  $ runP line_no "library" parseTokenQ sec_label
-            flds <- collectFields parseLibFields sec_fields
-            skipField
-            (repos, flags, csetup, mlib, sub_libs, flibs, exes, tests, bms) <- getBody pkg
-            case mb_libname of
-                Just libname ->
-                    return (repos, flags, csetup, mlib, (mkUnqualComponentName libname, flds) : sub_libs, flibs, exes, tests, bms)
-                Nothing -> do
-                    when (isJust mlib) $ lift $ syntaxError line_no
-                      "There can only be one (public) library section in a package description."
-                    return (repos, flags, csetup, Just flds, sub_libs, flibs, exes, tests, bms)
-
-        | sec_type == "flag" -> do
-            when (null sec_label) $ lift $
-              syntaxError line_no "'flag' needs one argument (the flag's name)"
-            flag <- lift $ parseFields
-                    flagFieldDescrs
-                    warnUnrec
-                    (emptyFlag (mkFlagName (lowercase sec_label)))
-                    sec_fields
-            skipField
-            (repos, flags, csetup, mlib, sub_libs, flibs, exes, tests, bms) <- getBody pkg
-            return (repos, flag:flags, csetup, mlib, sub_libs, flibs, exes, tests, bms)
-
-        | sec_type == "source-repository" -> do
-            when (null sec_label) $ lift $ syntaxError line_no $
-                 "'source-repository' needs one argument, "
-              ++ "the repo kind which is usually 'head' or 'this'"
-            kind <- case simpleParse sec_label of
-              Just kind -> return kind
-              Nothing   -> lift $ syntaxError line_no $
-                             "could not parse repo kind: " ++ sec_label
-            repo <- lift $ parseFields
-                    sourceRepoFieldDescrs
-                    warnUnrec
-                    (emptySourceRepo kind)
-                    sec_fields
-            skipField
-            (repos, flags, csetup, mlib, sub_libs, flibs, exes, tests, bms) <- getBody pkg
-            return (repo:repos, flags, csetup, mlib, sub_libs, flibs, exes, tests, bms)
-
-        | sec_type == "custom-setup" -> do
-            unless (null sec_label) $ lift $
-              syntaxError line_no "'setup' expects no argument"
-            flds <- lift $ parseFields
-                             setupBInfoFieldDescrs
-                             warnUnrec
-                             mempty
-                             sec_fields
-            skipField
-            (repos, flags, csetup0, mlib, sub_libs, flibs, exes, tests, bms) <- getBody pkg
-            when (isJust csetup0) $ lift $ syntaxError line_no
-              "There can only be one 'custom-setup' section in a package description."
-            return (repos, flags, Just flds, mlib, sub_libs, flibs, exes, tests, bms)
-
-        | otherwise -> do
-            lift $ warning $ "Ignoring unknown section type: " ++ sec_type
-            skipField
-            getBody pkg
-      Just f@(F {}) -> do
-            _ <- lift $ syntaxError (lineNo f) $
-              "Plain fields are not allowed in between stanzas: " ++ show f
-            skipField
-            getBody pkg
-      Just f@(IfBlock {}) -> do
-            _ <- lift $ syntaxError (lineNo f) $
-              "If-blocks are not allowed in between stanzas: " ++ show f
-            skipField
-            getBody pkg
-      Nothing -> return ([], [], Nothing, Nothing, [], [], [], [], [])
-
-    -- Extracts all fields in a block and returns a 'CondTree'.
-    --
-    -- We have to recurse down into conditionals and we treat fields that
-    -- describe dependencies specially.
-    collectFields :: ([Field] -> PM a) -> [Field]
-                  -> PM (CondTree ConfVar [Dependency] a)
-    collectFields parser allflds = do
-
-        let simplFlds = [ F l n v | F l n v <- allflds ]
-            condFlds = [ f | f@IfBlock{} <- allflds ]
-            sections = [ s | s@Section{} <- allflds ]
-
-        traverse_
-            (\(Section l n _ _) -> lift . warning $
-                "Unexpected section '" ++ n ++ "' on line " ++ show l)
-            sections
-
-        a <- parser simplFlds
-
-        -- Dependencies must be treated specially: when we
-        -- parse into a CondTree, not only do we parse them into
-        -- the targetBuildDepends/etc field inside the
-        -- PackageDescription, but we also have to put the
-        -- combined dependencies into CondTree.
-        --
-        -- This information is, in principle, redundant, but
-        -- putting it here makes it easier for the constraint
-        -- solver to pick a flag assignment which supports
-        -- all of the dependencies (because it only has
-        -- to check the CondTree, rather than grovel everywhere
-        -- inside the conditional bits).
-        deps <- liftM concat
-              . traverse (lift . parseConstraint)
-              . filter isConstraint
-              $ simplFlds
-
-        ifs <- traverse processIfs condFlds
-
-        return (CondNode a deps ifs)
-      where
-        isConstraint (F _ n _) = n `elem` constraintFieldNames
-        isConstraint _ = False
-
-        processIfs (IfBlock l c t e) = do
-            cnd <- lift $ runP l "if" parseCondition c
-            t' <- collectFields parser t
-            e' <- case e of
-                   [] -> return Nothing
-                   es -> do fs <- collectFields parser es
-                            return (Just fs)
-            return (CondBranch cnd t' e')
-        processIfs _ = cabalBug "processIfs called with wrong field type"
-
-    parseLibFields :: [Field] -> PM Library
-    parseLibFields = lift . parseFields libFieldDescrs storeXFieldsLib emptyLibrary
-
-    -- Note: we don't parse the "executable" field here, hence the tail hack.
-    parseExeFields :: [Field] -> PM Executable
-    parseExeFields = lift . parseFields executableFieldDescrs
-                                        storeXFieldsExe emptyExecutable
-
-    parseForeignLibFields :: [Field] -> PM ForeignLib
-    parseForeignLibFields =
-        lift . parseFields foreignLibFieldDescrs
-                           storeXFieldsForeignLib
-                           emptyForeignLib
-
-    parseTestFields :: LineNo -> [Field] -> PM TestSuite
-    parseTestFields line fields = do
-        x <- lift $ parseFields testSuiteFieldDescrs storeXFieldsTest
-                                emptyTestStanza fields
-        lift $ validateTestSuite line x
-
-    parseBenchmarkFields :: LineNo -> [Field] -> PM Benchmark
-    parseBenchmarkFields line fields = do
-        x <- lift $ parseFields benchmarkFieldDescrs storeXFieldsBenchmark
-                                emptyBenchmarkStanza fields
-        lift $ validateBenchmark line x
-
-    checkForUndefinedFlags ::
-        [Flag] ->
-        Maybe (CondTree ConfVar [Dependency] Library) ->
-        [(UnqualComponentName, CondTree ConfVar [Dependency] Library)] ->
-        [(UnqualComponentName, CondTree ConfVar [Dependency] Executable)] ->
-        [(UnqualComponentName, CondTree ConfVar [Dependency] TestSuite)] ->
-        PM ()
-    checkForUndefinedFlags flags mlib sub_libs exes tests = do
-        let definedFlags = map flagName flags
-        traverse_ (checkCondTreeFlags definedFlags) (maybeToList mlib)
-        traverse_ (checkCondTreeFlags definedFlags . snd) sub_libs
-        traverse_ (checkCondTreeFlags definedFlags . snd) exes
-        traverse_ (checkCondTreeFlags definedFlags . snd) tests
-
-    checkCondTreeFlags :: [FlagName] -> CondTree ConfVar c a -> PM ()
-    checkCondTreeFlags definedFlags ct = do
-        let fv = nub $ freeVars ct
-        unless (all (`elem` definedFlags) fv) $
-            fail $ "These flags are used without having been defined: "
-                ++ intercalate ", " [ unFlagName fn | fn <- fv \\ definedFlags ]
-
--- Check that a property holds on all branches of a condition tree
-onAllBranches :: forall v c a. Monoid a => (a -> Bool) -> CondTree v c a -> Bool
-onAllBranches p = go mempty
-  where
-    -- If the current level of the tree satisfies the property, then we are
-    -- done. If not, then one of the conditional branches below the current node
-    -- must satisfy it. Each node may have multiple immediate children; we only
-    -- one need one to satisfy the property because the configure step uses
-    -- 'mappend' to join together the results of flag resolution.
-    go :: a -> CondTree v c a -> Bool
-    go acc ct = let acc' = acc `mappend` condTreeData ct
-                in p acc' || any (goBranch acc') (condTreeComponents ct)
-
-    -- Both the 'true' and the 'false' block must satisfy the property.
-    goBranch :: a -> CondBranch v c a -> Bool
-    goBranch _   (CondBranch _ _ Nothing) = False
-    goBranch acc (CondBranch _ t (Just e))  = go acc t && go acc e
-
--- | Parse a list of fields, given a list of field descriptions,
---   a structure to accumulate the parsed fields, and a function
---   that can decide what to do with fields which don't match any
---   of the field descriptions.
-parseFields :: [FieldDescr a]      -- ^ descriptions of fields we know how to
-                                   --   parse
-            -> UnrecFieldParser a  -- ^ possibly do something with
-                                   --   unrecognized fields
-            -> a                   -- ^ accumulator
-            -> [Field]             -- ^ fields to be parsed
-            -> ParseResult a
-parseFields descrs unrec ini fields =
-    do (a, unknowns) <- foldM (parseField descrs unrec) (ini, []) fields
-       unless (null unknowns) $ warning $ render $
-         text "Unknown fields:" <+>
-              commaSep (map (\(l,u) -> u ++ " (line " ++ show l ++ ")")
-                            (reverse unknowns))
-         $+$
-         text "Fields allowed in this section:" $$
-           nest 4 (commaSep $ map fieldName descrs)
-       return a
-  where
-    commaSep = fsep . punctuate comma . map text
-
-parseField :: [FieldDescr a]     -- ^ list of parseable fields
-           -> UnrecFieldParser a -- ^ possibly do something with
-                                 --   unrecognized fields
-           -> (a,[(Int,String)]) -- ^ accumulated result and warnings
-           -> Field              -- ^ the field to be parsed
-           -> ParseResult (a, [(Int,String)])
-parseField (FieldDescr name _ parser : fields) unrec (a, us) (F line f val)
-  | name == f = parser line val a >>= \a' -> return (a',us)
-  | otherwise = parseField fields unrec (a,us) (F line f val)
-parseField [] unrec (a,us) (F l f val) = return $
-  case unrec (f,val) a of        -- no fields matched, see if the 'unrec'
-    Just a' -> (a',us)           -- function wants to do anything with it
-    Nothing -> (a, (l,f):us)
-parseField _ _ _ _ = cabalBug "'parseField' called on a non-field"
-
-deprecatedFields :: [(String,String)]
-deprecatedFields =
-    deprecatedFieldsPkgDescr ++ deprecatedFieldsBuildInfo
-
-deprecatedFieldsPkgDescr :: [(String,String)]
-deprecatedFieldsPkgDescr = [ ("other-files", "extra-source-files") ]
-
-deprecatedFieldsBuildInfo :: [(String,String)]
-deprecatedFieldsBuildInfo = [ ("hs-source-dir","hs-source-dirs") ]
-
--- Handle deprecated fields
-deprecField :: Field -> ParseResult Field
-deprecField (F line fld val) = do
-  fld' <- case lookup fld deprecatedFields of
-            Nothing -> return fld
-            Just newName -> do
-              warning $ "The field \"" ++ fld
-                      ++ "\" is deprecated, please use \"" ++ newName ++ "\""
-              return newName
-  return (F line fld' val)
-deprecField _ = cabalBug "'deprecField' called on a non-field"
-
-
-parseHookedBuildInfo :: String -> ParseResult HookedBuildInfo
-parseHookedBuildInfo inp = do
-  fields <- readFields inp
-  let ss@(mLibFields:exes) = stanzas fields
-  mLib <- parseLib mLibFields
-  biExes <- mapM parseExe (maybe ss (const exes) mLib)
-  return (mLib, biExes)
-  where
-    parseLib :: [Field] -> ParseResult (Maybe BuildInfo)
-    parseLib (bi@(F _ inFieldName _:_))
-        | lowercase inFieldName /= "executable" = liftM Just (parseBI bi)
-    parseLib _ = return Nothing
-
-    parseExe :: [Field] -> ParseResult (UnqualComponentName, BuildInfo)
-    parseExe (F line inFieldName mName:bi)
-        | lowercase inFieldName == "executable"
-            = do bis <- parseBI bi
-                 return (mkUnqualComponentName mName, bis)
-        | otherwise = syntaxError line "expecting 'executable' at top of stanza"
-    parseExe (_:_) = cabalBug "`parseExe' called on a non-field"
-    parseExe [] = syntaxError 0 "error in parsing buildinfo file. Expected executable stanza"
-
-    parseBI st = parseFields binfoFieldDescrs storeXFieldsBI emptyBuildInfo st
-
--- replace all tabs used as indentation with whitespace, also return where
--- tabs were found
-findIndentTabs :: String -> [(Int,Int)]
-findIndentTabs = concatMap checkLine
-               . zip [1..]
-               . lines
-    where
-      checkLine (lineno, l) =
-          let (indent, _content) = span isSpace l
-              tabCols = map fst . filter ((== '\t') . snd) . zip [0..]
-              addLineNo = map (\col -> (lineno,col))
-          in addLineNo (tabCols indent)
-
---test_findIndentTabs = findIndentTabs $ unlines $
---    [ "foo", "  bar", " \t baz", "\t  biz\t", "\t\t \t mib" ]
diff --git a/cabal/Cabal/Distribution/PackageDescription/Parsec.hs b/cabal/Cabal/Distribution/PackageDescription/Parsec.hs
--- a/cabal/Cabal/Distribution/PackageDescription/Parsec.hs
+++ b/cabal/Cabal/Distribution/PackageDescription/Parsec.hs
@@ -3,7 +3,6 @@
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE Rank2Types          #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TupleSections       #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Distribution.PackageDescription.Parsec
@@ -25,6 +24,9 @@
     ParseResult,
     runParseResult,
 
+    -- * New-style spec-version
+    scanSpecVersion,
+
     -- ** Supplementary build information
     readHookedBuildInfo,
     parseHookedBuildInfo,
@@ -33,64 +35,54 @@
 import Distribution.Compat.Prelude
 import Prelude ()
 
-import           Control.Monad.State.Strict                   (StateT, execStateT)
-import           Control.Monad.Trans.Class                    (lift)
-import qualified Data.ByteString                              as BS
-import           Data.List                                    (partition)
-import qualified Distribution.Compat.Map.Strict               as Map
-import           Distribution.FieldGrammar
-import           Distribution.PackageDescription
-import           Distribution.PackageDescription.FieldGrammar
-import           Distribution.PackageDescription.Quirks       (patchQuirks)
-import           Distribution.Parsec.Class                    (parsec)
-import           Distribution.Parsec.Common
-import           Distribution.Parsec.ConfVar                  (parseConditionConfVar)
-import           Distribution.Parsec.Field                    (FieldName, getName)
-import           Distribution.Parsec.LexerMonad               (LexWarning, toPWarning)
-import           Distribution.Parsec.Parser
-import           Distribution.Parsec.ParseResult
-import           Distribution.Simple.Utils                    (die', fromUTF8BS, warn)
-import           Distribution.Text                            (display)
-import           Distribution.Types.CondTree
-import           Distribution.Types.ForeignLib
-import           Distribution.Types.UnqualComponentName
-                 (UnqualComponentName, mkUnqualComponentName)
-import           Distribution.Utils.Generic                   (breakMaybe, unfoldrM)
-import           Distribution.Verbosity                       (Verbosity)
-import           Distribution.Version
-                 (LowerBound (..), Version, asVersionIntervals, mkVersion, orLaterVersion)
-import           System.Directory                             (doesFileExist)
+import Control.Monad                                (guard)
+import Control.Monad.State.Strict                   (StateT, execStateT)
+import Control.Monad.Trans.Class                    (lift)
+import Data.List                                    (partition)
+import Distribution.CabalSpecVersion
+import Distribution.Compat.Lens
+import Distribution.FieldGrammar
+import Distribution.FieldGrammar.Parsec             (NamelessField (..))
+import Distribution.PackageDescription
+import Distribution.PackageDescription.FieldGrammar
+import Distribution.PackageDescription.Quirks       (patchQuirks)
+import Distribution.Parsec.Class                    (parsec, simpleParsec)
+import Distribution.Parsec.Common
+import Distribution.Parsec.ConfVar                  (parseConditionConfVar)
+import Distribution.Parsec.Field                    (FieldName, getName)
+import Distribution.Parsec.FieldLineStream          (fieldLineStreamFromBS)
+import Distribution.Parsec.LexerMonad               (LexWarning, toPWarnings)
+import Distribution.Parsec.Newtypes                 (CommaFSep, List, SpecVersion (..), Token)
+import Distribution.Parsec.Parser
+import Distribution.Parsec.ParseResult
+import Distribution.Pretty                          (prettyShow)
+import Distribution.Simple.Utils                    (fromUTF8BS)
+import Distribution.Text                            (display)
+import Distribution.Types.CondTree
+import Distribution.Types.Dependency                (Dependency)
+import Distribution.Types.ForeignLib
+import Distribution.Types.ForeignLibType            (knownForeignLibTypes)
+import Distribution.Types.GenericPackageDescription (emptyGenericPackageDescription)
+import Distribution.Types.PackageDescription        (specVersion')
+import Distribution.Types.UnqualComponentName       (UnqualComponentName, mkUnqualComponentName)
+import Distribution.Utils.Generic                   (breakMaybe, unfoldrM, validateUTF8)
+import Distribution.Verbosity                       (Verbosity)
+import Distribution.Version
+       (LowerBound (..), Version, asVersionIntervals, mkVersion, orLaterVersion, version0,
+       versionNumbers)
 
-import           Distribution.Compat.Lens
+import qualified Data.ByteString                                   as BS
+import qualified Data.ByteString.Char8                             as BS8
+import qualified Data.Map.Strict                                   as Map
+import qualified Distribution.Compat.Newtype                       as Newtype
+import qualified Distribution.Types.BuildInfo.Lens                 as L
 import qualified Distribution.Types.GenericPackageDescription.Lens as L
 import qualified Distribution.Types.PackageDescription.Lens        as L
+import qualified Text.Parsec                                       as P
 
 -- ---------------------------------------------------------------
 -- Parsing
-
--- | Helper combinator to do parsing plumbing for files.
---
--- Given a parser and a filename, return the parse of the file,
--- after checking if the file exists.
---
--- Argument order is chosen to encourage partial application.
-readAndParseFile
-    :: (BS.ByteString -> ParseResult a)  -- ^ File contents to final value parser
-    -> Verbosity                         -- ^ Verbosity level
-    -> FilePath                          -- ^ File to read
-    -> IO a
-readAndParseFile parser verbosity fpath = do
-    exists <- doesFileExist fpath
-    unless exists $
-      die' verbosity $
-        "Error Parsing: file \"" ++ fpath ++ "\" doesn't exist. Cannot continue."
-    bs <- BS.readFile fpath
-    let (warnings, errors, result) = runParseResult (parser bs)
-    traverse_ (warn verbosity . showPWarning fpath) warnings
-    traverse_ (warn verbosity . showPError fpath) errors
-    case result of
-        Nothing -> die' verbosity $ "Failing parsing \"" ++ fpath ++ "\"."
-        Just x  -> return x
+-- ---------------------------------------------------------------
 
 -- | Parse the given package file.
 readGenericPackageDescription :: Verbosity -> FilePath -> IO GenericPackageDescription
@@ -103,56 +95,113 @@
 -- with sections and possibly indented property descriptions.
 --
 parseGenericPackageDescription :: BS.ByteString -> ParseResult GenericPackageDescription
-parseGenericPackageDescription bs = case readFields' bs' of
-    Right (fs, lexWarnings) -> do
-        when patched $
-            parseWarning zeroPos PWTQuirkyCabalFile "Legacy cabal file"
-        parseGenericPackageDescription' lexWarnings fs
-    -- TODO: better marshalling of errors
-    Left perr -> parseFatalFailure zeroPos (show perr)
+parseGenericPackageDescription bs = do
+    -- set scanned version
+    setCabalSpecVersion ver
+    -- if we get too new version, fail right away
+    case ver of
+        Just v | v > mkVersion [2,4] -> parseFailure zeroPos
+            "Unsupported cabal-version. See https://github.com/haskell/cabal/issues/4899."
+        _ -> pure ()
+
+    case readFields' bs' of
+        Right (fs, lexWarnings) -> do
+            when patched $
+                parseWarning zeroPos PWTQuirkyCabalFile "Legacy cabal file"
+            -- UTF8 is validated in a prepass step, afterwards parsing is lenient.
+            parseGenericPackageDescription' ver lexWarnings (validateUTF8 bs') fs
+        -- TODO: better marshalling of errors
+        Left perr -> parseFatalFailure pos (show perr) where
+            ppos = P.errorPos perr
+            pos  = Position (P.sourceLine ppos) (P.sourceColumn ppos)
   where
     (patched, bs') = patchQuirks bs
+    ver = scanSpecVersion bs'
 
 -- | 'Maybe' variant of 'parseGenericPackageDescription'
 parseGenericPackageDescriptionMaybe :: BS.ByteString -> Maybe GenericPackageDescription
 parseGenericPackageDescriptionMaybe =
-    trdOf3 . runParseResult . parseGenericPackageDescription
-  where
-    trdOf3 (_, _, x) = x
+    either (const Nothing) Just . snd . runParseResult . parseGenericPackageDescription
 
 fieldlinesToBS :: [FieldLine ann] -> BS.ByteString
 fieldlinesToBS = BS.intercalate "\n" . map (\(FieldLine _ bs) -> bs)
 
 -- Monad in which sections are parsed
-type SectionParser = StateT GenericPackageDescription ParseResult
+type SectionParser = StateT SectionS ParseResult
 
+-- | State of section parser
+data SectionS = SectionS
+    { _stateGpd           :: !GenericPackageDescription
+    , _stateCommonStanzas :: !(Map String CondTreeBuildInfo)
+    }
+
+stateGpd :: Lens' SectionS GenericPackageDescription
+stateGpd f (SectionS gpd cs) = (\x -> SectionS x cs) <$> f gpd
+{-# INLINE stateGpd #-}
+
+stateCommonStanzas :: Lens' SectionS (Map String CondTreeBuildInfo)
+stateCommonStanzas f (SectionS gpd cs) = SectionS gpd <$> f cs
+{-# INLINE stateCommonStanzas #-}
+
 -- Note [Accumulating parser]
 --
 -- This parser has two "states":
 -- * first we parse fields of PackageDescription
 -- * then we parse sections (libraries, executables, etc)
 parseGenericPackageDescription'
-    :: [LexWarning]
+    :: Maybe Version
+    -> [LexWarning]
+    -> Maybe Int
     -> [Field Position]
     -> ParseResult GenericPackageDescription
-parseGenericPackageDescription' lexWarnings fs = do
-    parseWarnings (fmap toPWarning lexWarnings)
+parseGenericPackageDescription' cabalVerM lexWarnings utf8WarnPos fs = do
+    parseWarnings (toPWarnings lexWarnings)
+    for_ utf8WarnPos $ \pos ->
+        parseWarning zeroPos PWTUTF $ "UTF8 encoding problem at byte offset " ++ show pos
     let (syntax, fs') = sectionizeFields fs
-
-    -- PackageDescription
     let (fields, sectionFields) = takeFields fs'
-    pd <- parseFieldGrammar fields packageDescriptionFieldGrammar
+
+    -- cabal-version
+    cabalVer <- case cabalVerM of
+        Just v  -> return v
+        Nothing -> case Map.lookup "cabal-version" fields >>= safeLast of
+            Nothing                        -> return version0
+            Just (MkNamelessField pos fls) -> do
+                v <- specVersion' . Newtype.unpack' SpecVersion <$> runFieldParser pos parsec cabalSpecLatest fls
+                when (v >= mkVersion [2,1]) $ parseFailure pos $
+                    "cabal-version should be at the beginning of the file starting with spec version 2.2. " ++
+                    "See https://github.com/haskell/cabal/issues/4899"
+
+                return v
+
+    let specVer
+          | cabalVer >= mkVersion [2,3]  = CabalSpecV2_4
+          | cabalVer >= mkVersion [2,1]  = CabalSpecV2_2
+          | cabalVer >= mkVersion [1,25] = CabalSpecV2_0
+          | cabalVer >= mkVersion [1,23] = CabalSpecV1_24
+          | cabalVer >= mkVersion [1,21] = CabalSpecV1_22
+          | otherwise = CabalSpecOld
+
+    -- reset cabal version
+    setCabalSpecVersion (Just cabalVer)
+
+    -- Package description
+    pd <- parseFieldGrammar specVer fields packageDescriptionFieldGrammar
+
+    -- Check that scanned and parsed versions match.
+    unless (cabalVer == specVersion pd) $ parseFailure zeroPos $
+        "Scanned and parsed cabal-versions don't match " ++
+        prettyShow cabalVer ++ " /= " ++ prettyShow (specVersion pd)
+
     maybeWarnCabalVersion syntax pd
 
     -- Sections
-    let gpd = emptyGpd & L.packageDescription .~ pd
+    let gpd = emptyGenericPackageDescription & L.packageDescription .~ pd
 
-    -- elif conditional is accepted if spec version is >= 2.1
-    let hasElif = if specVersion pd >= mkVersion [2,1] then HasElif else NoElif
-    execStateT (goSections hasElif sectionFields) gpd
+    view stateGpd <$> execStateT (goSections specVer sectionFields) (SectionS gpd Map.empty)
   where
-    emptyGpd :: GenericPackageDescription
-    emptyGpd = GenericPackageDescription emptyPackageDescription [] Nothing [] [] [] [] []
+    safeLast :: [a] -> Maybe a
+    safeLast = listToMaybe . reverse
 
     newSyntaxVersion :: Version
     newSyntaxVersion = mkVersion [1, 2]
@@ -160,13 +209,13 @@
     maybeWarnCabalVersion :: Syntax -> PackageDescription -> ParseResult ()
     maybeWarnCabalVersion syntax pkg
       | syntax == NewSyntax && specVersion pkg < newSyntaxVersion
-      = parseWarning (Position 0 0) PWTNewSyntax $
+      = parseWarning zeroPos PWTNewSyntax $
              "A package using section syntax must specify at least\n"
           ++ "'cabal-version: >= 1.2'."
 
     maybeWarnCabalVersion syntax pkg
       | syntax == OldSyntax && specVersion pkg >= newSyntaxVersion
-      = parseWarning (Position 0 0) PWTOldSyntax $
+      = parseWarning zeroPos PWTOldSyntax $
              "A package using 'cabal-version: "
           ++ displaySpecVersion (specVersionRaw pkg)
           ++ "' must use section syntax. See the Cabal user guide for details."
@@ -179,9 +228,8 @@
 
     maybeWarnCabalVersion _ _ = return ()
 
-    -- Sections
-goSections :: HasElif -> [Field Position] -> SectionParser ()
-goSections hasElif = traverse_ process
+goSections :: CabalSpecVersion -> [Field Position] -> SectionParser ()
+goSections specVer = traverse_ process
   where
     process (Field (Name pos name) _) =
         lift $ parseWarning pos PWTTrailingFields $
@@ -191,62 +239,123 @@
 
     snoc x xs = xs ++ [x]
 
+    hasCommonStanzas = specHasCommonStanzas specVer
+
+    -- we need signature, because this is polymorphic, but not-closed
+    parseCondTree'
+        :: FromBuildInfo a
+        => ParsecFieldGrammar' a       -- ^ grammar
+        -> Map String CondTreeBuildInfo  -- ^ common stanzas
+        -> [Field Position]
+        -> ParseResult (CondTree ConfVar [Dependency] a)
+    parseCondTree' = parseCondTreeWithCommonStanzas specVer
+
     parseSection :: Name Position -> [SectionArg Position] -> [Field Position] -> SectionParser ()
     parseSection (Name pos name) args fields
+        | hasCommonStanzas == NoCommonStanzas, name == "common" = lift $ do
+          parseWarning pos PWTUnknownSection $ "Ignoring section: common. You should set cabal-version: 2.2 or larger to use common stanzas."
+
+        | name == "common" = do
+            commonStanzas <- use stateCommonStanzas
+            name' <- lift $ parseCommonName pos args
+            biTree <- lift $ parseCondTree' buildInfoFieldGrammar commonStanzas fields
+
+            case Map.lookup name' commonStanzas of
+                Nothing -> stateCommonStanzas .= Map.insert name' biTree commonStanzas
+                Just _  -> lift $ parseFailure pos $
+                    "Duplicate common stanza: " ++ name'
+
         | name == "library" && null args = do
-            lib <- lift $ parseCondTree hasElif (libraryFieldGrammar Nothing) (targetBuildDepends . libBuildInfo) fields
+            commonStanzas <- use stateCommonStanzas
+            lib <- lift $ parseCondTree' (libraryFieldGrammar Nothing) commonStanzas fields
             -- TODO: check that library is defined once
-            L.condLibrary ?= lib
+            stateGpd . L.condLibrary ?= lib
 
         -- Sublibraries
+        -- TODO: check cabal-version
         | name == "library" = do
-            -- TODO: check cabal-version
+            commonStanzas <- use stateCommonStanzas
             name' <- parseUnqualComponentName pos args
-            lib   <- lift $ parseCondTree hasElif (libraryFieldGrammar $ Just name') (targetBuildDepends . libBuildInfo) fields
+            lib   <- lift $ parseCondTree' (libraryFieldGrammar $ Just name') commonStanzas fields
             -- TODO check duplicate name here?
-            L.condSubLibraries %= snoc (name', lib)
+            stateGpd . L.condSubLibraries %= snoc (name', lib)
 
+        -- TODO: check cabal-version
         | name == "foreign-library" = do
+            commonStanzas <- use stateCommonStanzas
             name' <- parseUnqualComponentName pos args
-            flib  <- lift $ parseCondTree hasElif (foreignLibFieldGrammar name') (targetBuildDepends . foreignLibBuildInfo) fields
+            flib  <- lift $ parseCondTree' (foreignLibFieldGrammar name')  commonStanzas fields
+
+            let hasType ts = foreignLibType ts /= foreignLibType mempty
+            unless (onAllBranches hasType flib) $ lift $ parseFailure pos $ concat
+                [ "Foreign library " ++ show (display name')
+                , " is missing required field \"type\" or the field "
+                , "is not present in all conditional branches. The "
+                , "available test types are: "
+                , intercalate ", " (map display knownForeignLibTypes)
+                ]
+
             -- TODO check duplicate name here?
-            L.condForeignLibs %= snoc (name', flib)
+            stateGpd . L.condForeignLibs %= snoc (name', flib)
 
         | name == "executable" = do
+            commonStanzas <- use stateCommonStanzas
             name' <- parseUnqualComponentName pos args
-            exe   <- lift $ parseCondTree hasElif (executableFieldGrammar name') (targetBuildDepends . buildInfo) fields
+            exe   <- lift $ parseCondTree' (executableFieldGrammar name') commonStanzas fields
             -- TODO check duplicate name here?
-            L.condExecutables %= snoc (name', exe)
+            stateGpd . L.condExecutables %= snoc (name', exe)
 
         | name == "test-suite" = do
+            commonStanzas <- use stateCommonStanzas
             name'      <- parseUnqualComponentName pos args
-            testStanza <- lift $ parseCondTree hasElif testSuiteFieldGrammar (targetBuildDepends . _testStanzaBuildInfo) fields
+            testStanza <- lift $ parseCondTree' testSuiteFieldGrammar commonStanzas fields
             testSuite  <- lift $ traverse (validateTestSuite pos) testStanza
+
+            let hasType ts = testInterface ts /= testInterface mempty
+            unless (onAllBranches hasType testSuite) $ lift $ parseFailure pos $ concat
+                [ "Test suite " ++ show (display name')
+                , " is missing required field \"type\" or the field "
+                , "is not present in all conditional branches. The "
+                , "available test types are: "
+                , intercalate ", " (map display knownTestTypes)
+                ]
+
             -- TODO check duplicate name here?
-            L.condTestSuites %= snoc (name', testSuite)
+            stateGpd . L.condTestSuites %= snoc (name', testSuite)
 
         | name == "benchmark" = do
+            commonStanzas <- use stateCommonStanzas
             name'       <- parseUnqualComponentName pos args
-            benchStanza <- lift $ parseCondTree hasElif benchmarkFieldGrammar (targetBuildDepends . _benchmarkStanzaBuildInfo) fields
+            benchStanza <- lift $ parseCondTree' benchmarkFieldGrammar commonStanzas fields
             bench       <- lift $ traverse (validateBenchmark pos) benchStanza
+
+            let hasType ts = benchmarkInterface ts /= benchmarkInterface mempty
+            unless (onAllBranches hasType bench) $ lift $ parseFailure pos $ concat
+                [ "Benchmark " ++ show (display name')
+                , " is missing required field \"type\" or the field "
+                , "is not present in all conditional branches. The "
+                , "available benchmark types are: "
+                , intercalate ", " (map display knownBenchmarkTypes)
+                ]
+
             -- TODO check duplicate name here?
-            L.condBenchmarks %= snoc (name', bench)
+            stateGpd . L.condBenchmarks %= snoc (name', bench)
 
         | name == "flag" = do
-            name'  <- parseName pos args
-            name'' <- lift $ runFieldParser' pos parsec name' `recoverWith` mkFlagName ""
-            flag   <- lift $ parseFields fields (flagFieldGrammar name'')
+            name'  <- parseNameBS pos args
+            name'' <- lift $ runFieldParser' pos parsec specVer (fieldLineStreamFromBS name') `recoverWith` mkFlagName ""
+            flag   <- lift $ parseFields specVer fields (flagFieldGrammar name'')
             -- Check default flag
-            L.genPackageFlags %= snoc flag
+            stateGpd . L.genPackageFlags %= snoc flag
 
         | name == "custom-setup" && null args = do
-            sbi <- lift $ parseFields fields  (setupBInfoFieldGrammar False)
-            L.packageDescription . L.setupBuildInfo ?= sbi
+            sbi <- lift $ parseFields specVer fields  (setupBInfoFieldGrammar False)
+            stateGpd . L.packageDescription . L.setupBuildInfo ?= sbi
 
         | name == "source-repository" = do
             kind <- lift $ case args of
                 [SecArgName spos secName] ->
-                    runFieldParser' spos parsec (fromUTF8BS secName) `recoverWith` RepoHead
+                    runFieldParser' spos parsec specVer (fieldLineStreamFromBS secName) `recoverWith` RepoHead
                 [] -> do
                     parseFailure pos "'source-repository' requires exactly one argument"
                     pure RepoHead
@@ -254,59 +363,76 @@
                     parseFailure pos $ "Invalid source-repository kind " ++ show args
                     pure RepoHead
 
-            sr <- lift $ parseFields fields (sourceRepoFieldGrammar kind)
-            L.packageDescription . L.sourceRepos %= snoc sr
+            sr <- lift $ parseFields specVer fields (sourceRepoFieldGrammar kind)
+            stateGpd . L.packageDescription . L.sourceRepos %= snoc sr
 
         | otherwise = lift $
             parseWarning pos PWTUnknownSection $ "Ignoring section: " ++ show name
 
 parseName :: Position -> [SectionArg Position] -> SectionParser String
-parseName pos args = case args of
+parseName pos args = fromUTF8BS <$> parseNameBS pos args
+
+parseNameBS :: Position -> [SectionArg Position] -> SectionParser BS.ByteString
+-- TODO: use strict parser
+parseNameBS pos args = case args of
     [SecArgName _pos secName] ->
+         pure secName
+    [SecArgStr _pos secName] ->
+         pure secName
+    [] -> do
+         lift $ parseFailure pos "name required"
+         pure ""
+    _ -> do
+         -- TODO: pretty print args
+         lift $ parseFailure pos $ "Invalid name " ++ show args
+         pure ""
+
+parseCommonName :: Position -> [SectionArg Position] -> ParseResult String
+parseCommonName pos args = case args of
+    [SecArgName _pos secName] ->
          pure $ fromUTF8BS secName
     [SecArgStr _pos secName] ->
          pure $ fromUTF8BS secName
     [] -> do
-         lift $ parseFailure pos $ "name required"
+         parseFailure pos $ "name required"
          pure ""
     _ -> do
          -- TODO: pretty print args
-         lift $ parseFailure pos $ "Invalid name " ++ show args
+         parseFailure pos $ "Invalid name " ++ show args
          pure ""
 
+-- TODO: avoid conversion to 'String'.
 parseUnqualComponentName :: Position -> [SectionArg Position] -> SectionParser UnqualComponentName
 parseUnqualComponentName pos args = mkUnqualComponentName <$> parseName pos args
 
 -- | Parse a non-recursive list of fields.
 parseFields
-    :: [Field Position] -- ^ fields to be parsed
+    :: CabalSpecVersion
+    -> [Field Position] -- ^ fields to be parsed
     -> ParsecFieldGrammar' a
     -> ParseResult a
-parseFields fields grammar = do
+parseFields v fields grammar = do
     let (fs0, ss) = partitionFields fields
     traverse_ (traverse_ warnInvalidSubsection) ss
-    parseFieldGrammar fs0 grammar
+    parseFieldGrammar v fs0 grammar
 
 warnInvalidSubsection :: Section Position -> ParseResult ()
 warnInvalidSubsection (MkSection (Name pos name) _ _) =
     void (parseFailure pos $ "invalid subsection " ++ show name)
 
-
-data HasElif = HasElif | NoElif
-  deriving (Eq, Show)
-
 parseCondTree
     :: forall a c.
-       HasElif                -- ^ accept @elif@
+       CabalSpecVersion
+    -> HasElif                  -- ^ accept @elif@
     -> ParsecFieldGrammar' a  -- ^ grammar
-    -> (a -> c)               -- ^ condition extractor
+    -> (a -> c)                 -- ^ condition extractor
     -> [Field Position]
     -> ParseResult (CondTree ConfVar c a)
-parseCondTree hasElif grammar cond = go
+parseCondTree v hasElif grammar cond = go
   where
     go fields = do
         let (fs, ss) = partitionFields fields
-        x <- parseFieldGrammar fs grammar
+        x <- parseFieldGrammar v fs grammar
         branches <- concat <$> traverse parseIfs ss
         return (CondNode x (cond x) branches) -- TODO: branches
 
@@ -333,15 +459,21 @@
         sections' <- parseIfs sections
         return (Just elseFields, sections')
 
+
+
     parseElseIfs (MkSection (Name _ name) test fields : sections) | hasElif == HasElif, name == "elif" = do
         -- TODO: check cabal-version
         test' <- parseConditionConfVar test
         fields' <- go fields
         (elseFields, sections') <- parseElseIfs sections
         -- we parse an empty 'Fields', to get empty value for a node
-        a <- parseFieldGrammar mempty grammar
+        a <- parseFieldGrammar v mempty grammar
         return (Just $ CondNode a (cond a) [CondBranch test' fields' elseFields], sections')
 
+    parseElseIfs (MkSection (Name pos name) _ _ : sections) | name == "elif" = do
+        parseWarning pos PWTInvalidSubsection $ "invalid subsection \"elif\". You should set cabal-version: 2.2 or larger to use elif-conditionals."
+        (,) Nothing <$> parseIfs sections
+
     parseElseIfs sections = (,) Nothing <$> parseIfs sections
 
 {- Note [Accumulating parser]
@@ -367,6 +499,138 @@
 -}
 
 -------------------------------------------------------------------------------
+-- Common stanzas
+-------------------------------------------------------------------------------
+
+-- $commonStanzas
+--
+-- [Note: Common stanzas]
+--
+-- In Cabal 2.2 we support simple common stanzas:
+--
+-- * Commons stanzas define 'BuildInfo'
+--
+-- * import "fields" can only occur at top of other stanzas (think: imports)
+--
+-- In particular __there aren't__
+--
+-- * implicit stanzas
+--
+-- * More specific common stanzas (executable, test-suite).
+--
+--
+-- The approach uses the fact that 'BuildInfo' is a 'Monoid':
+--
+-- @
+-- mergeCommonStanza' :: HasBuildInfo comp => BuildInfo -> comp -> comp
+-- mergeCommonStanza' bi = over L.BuildInfo (bi <>)
+-- @
+--
+-- Real 'mergeCommonStanza' is more complicated as we have to deal with
+-- conditional trees.
+--
+-- The approach is simple, and have good properties:
+--
+-- * Common stanzas are parsed exactly once, even if not-used. Thus we report errors in them.
+--
+type CondTreeBuildInfo = CondTree ConfVar [Dependency] BuildInfo
+
+-- | Create @a@ from 'BuildInfo'.
+--
+-- Law: @view buildInfo . fromBuildInfo = id@
+class L.HasBuildInfo a => FromBuildInfo a where
+    fromBuildInfo :: BuildInfo -> a
+
+instance FromBuildInfo BuildInfo  where fromBuildInfo = id
+instance FromBuildInfo Library    where fromBuildInfo bi = set L.buildInfo bi emptyLibrary
+instance FromBuildInfo ForeignLib where fromBuildInfo bi = set L.buildInfo bi emptyForeignLib
+instance FromBuildInfo Executable where fromBuildInfo bi = set L.buildInfo bi emptyExecutable
+
+instance FromBuildInfo TestSuiteStanza where
+    fromBuildInfo = TestSuiteStanza Nothing Nothing Nothing
+
+instance FromBuildInfo BenchmarkStanza where
+    fromBuildInfo = BenchmarkStanza Nothing Nothing Nothing
+
+parseCondTreeWithCommonStanzas
+    :: forall a. FromBuildInfo a
+    => CabalSpecVersion
+    -> ParsecFieldGrammar' a       -- ^ grammar
+    -> Map String CondTreeBuildInfo  -- ^ common stanzas
+    -> [Field Position]
+    -> ParseResult (CondTree ConfVar [Dependency] a)
+parseCondTreeWithCommonStanzas v grammar commonStanzas = goImports []
+  where
+    hasElif = specHasElif v
+    hasCommonStanzas = specHasCommonStanzas v
+
+    getList' :: List CommaFSep Token String -> [String]
+    getList' = Newtype.unpack
+
+    -- parse leading imports
+    -- not supported:
+    goImports acc (Field (Name pos name) _ : fields) | name == "import", hasCommonStanzas == NoCommonStanzas = do
+        parseWarning pos PWTUnknownField "Unknown field: import. You should set cabal-version: 2.2 or larger to use common stanzas"
+        goImports acc fields
+    -- supported:
+    goImports acc (Field (Name pos name) fls : fields) | name == "import" = do
+        names <- getList' <$> runFieldParser pos parsec v fls
+        names' <- for names $ \commonName ->
+            case Map.lookup commonName commonStanzas of
+                Nothing -> do
+                    parseFailure pos $ "Undefined common stanza imported: " ++ commonName
+                    pure Nothing
+                Just commonTree ->
+                    pure (Just commonTree)
+
+        goImports (acc ++ catMaybes names') fields
+
+    -- Go to parsing condTree after first non-import 'Field'.
+    goImports acc fields = go acc fields
+
+    -- parse actual CondTree
+    go :: [CondTreeBuildInfo] -> [Field Position] -> ParseResult (CondTree ConfVar [Dependency] a)
+    go bis fields = do
+        x <- parseCondTree v hasElif grammar (view L.targetBuildDepends) fields
+        pure $ foldr mergeCommonStanza x bis
+
+mergeCommonStanza
+    :: forall a. FromBuildInfo a
+    => CondTree ConfVar [Dependency] BuildInfo
+    -> CondTree ConfVar [Dependency] a
+    -> CondTree ConfVar [Dependency] a
+mergeCommonStanza (CondNode bi _ bis) (CondNode x _ cs) =
+    CondNode x' (x' ^. L.targetBuildDepends) cs'
+  where
+    -- new value is old value with buildInfo field _prepended_.
+    x' = x & L.buildInfo %~ (bi <>)
+
+    -- tree components are appended together.
+    cs' = map (fmap fromBuildInfo) bis ++ cs
+
+-------------------------------------------------------------------------------
+-- Branches
+-------------------------------------------------------------------------------
+
+-- Check that a property holds on all branches of a condition tree
+onAllBranches :: forall v c a. Monoid a => (a -> Bool) -> CondTree v c a -> Bool
+onAllBranches p = go mempty
+  where
+    -- If the current level of the tree satisfies the property, then we are
+    -- done. If not, then one of the conditional branches below the current node
+    -- must satisfy it. Each node may have multiple immediate children; we only
+    -- one need one to satisfy the property because the configure step uses
+    -- 'mappend' to join together the results of flag resolution.
+    go :: a -> CondTree v c a -> Bool
+    go acc ct = let acc' = acc `mappend` condTreeData ct
+                in p acc' || any (goBranch acc') (condTreeComponents ct)
+
+    -- Both the 'true' and the 'false' block must satisfy the property.
+    goBranch :: a -> CondBranch v c a -> Bool
+    goBranch _   (CondBranch _ _ Nothing) = False
+    goBranch acc (CondBranch _ t (Just e))  = go acc t && go acc e
+
+-------------------------------------------------------------------------------
 -- Old syntax
 -------------------------------------------------------------------------------
 
@@ -432,6 +696,7 @@
 data Syntax = OldSyntax | NewSyntax
     deriving (Eq, Show)
 
+-- TODO:
 libFieldNames :: [FieldName]
 libFieldNames = fieldGrammarKnownFieldList (libraryFieldGrammar Nothing)
 
@@ -443,22 +708,18 @@
 readHookedBuildInfo = readAndParseFile parseHookedBuildInfo
 
 parseHookedBuildInfo :: BS.ByteString -> ParseResult HookedBuildInfo
-parseHookedBuildInfo bs = case readFields' bs' of
+parseHookedBuildInfo bs = case readFields' bs of
     Right (fs, lexWarnings) -> do
-        when patched $
-            parseWarning zeroPos PWTQuirkyCabalFile "Legacy cabal file"
         parseHookedBuildInfo' lexWarnings fs
     -- TODO: better marshalling of errors
     Left perr -> parseFatalFailure zeroPos (show perr)
-  where
-    (patched, bs') = patchQuirks bs
 
 parseHookedBuildInfo'
     :: [LexWarning]
     -> [Field Position]
     -> ParseResult HookedBuildInfo
 parseHookedBuildInfo' lexWarnings fs = do
-    parseWarnings (fmap toPWarning lexWarnings)
+    parseWarnings (toPWarnings lexWarnings)
     (mLibFields, exes) <- stanzas fs
     mLib <- parseLib mLibFields
     biExes <- traverse parseExe exes
@@ -467,11 +728,11 @@
     parseLib :: Fields Position -> ParseResult (Maybe BuildInfo)
     parseLib fields
         | Map.null fields = pure Nothing
-        | otherwise       = Just <$> parseFieldGrammar fields buildInfoFieldGrammar
+        | otherwise       = Just <$> parseFieldGrammar cabalSpecLatest fields buildInfoFieldGrammar
 
     parseExe :: (UnqualComponentName, Fields Position) -> ParseResult (UnqualComponentName, BuildInfo)
     parseExe (n, fields) = do
-        bi <- parseFieldGrammar fields buildInfoFieldGrammar
+        bi <- parseFieldGrammar cabalSpecLatest fields buildInfoFieldGrammar
         pure (n, bi)
 
     stanzas :: [Field Position] -> ParseResult (Fields Position, [(UnqualComponentName, Fields Position)])
@@ -491,7 +752,7 @@
         :: ([FieldLine Position], [Field Position])
         -> ParseResult ((UnqualComponentName, Fields Position), Maybe ([FieldLine Position], [Field Position]))
     toExe (fss, fields) = do
-        name <- runFieldParser zeroPos parsec fss
+        name <- runFieldParser zeroPos parsec cabalSpecLatest fss
         let (hdr0, rest) = breakMaybe isExecutableField fields
         hdr <- toFields hdr0
         pure ((name, hdr), rest)
@@ -500,3 +761,46 @@
         | name == "executable" = Just fss
         | otherwise            = Nothing
     isExecutableField _ = Nothing
+
+-- | Quickly scan new-style spec-version
+--
+-- A new-style spec-version declaration begins the .cabal file and
+-- follow the following case-insensitive grammar (expressed in
+-- RFC5234 ABNF):
+--
+-- @
+-- newstyle-spec-version-decl = "cabal-version" *WS ":" *WS newstyle-pec-version *WS
+--
+-- spec-version               = NUM "." NUM [ "." NUM ]
+--
+-- NUM    = DIGIT0 / DIGITP 1*DIGIT0
+-- DIGIT0 = %x30-39
+-- DIGITP = %x31-39
+-- WS = %20
+-- @
+--
+scanSpecVersion :: BS.ByteString -> Maybe Version
+scanSpecVersion bs = do
+    fstline':_ <- pure (BS8.lines bs)
+
+    -- parse <newstyle-spec-version-decl>
+    -- normalise: remove all whitespace, convert to lower-case
+    let fstline = BS.map toLowerW8 $ BS.filter (/= 0x20) fstline'
+    ["cabal-version",vers] <- pure (BS8.split ':' fstline)
+
+    -- parse <spec-version>
+    --
+    -- This is currently more tolerant regarding leading 0 digits.
+    --
+    ver <- simpleParsec (BS8.unpack vers)
+    guard $ case versionNumbers ver of
+              [_,_]   -> True
+              [_,_,_] -> True
+              _       -> False
+
+    pure ver
+  where
+    -- | Translate ['A'..'Z'] to ['a'..'z']
+    toLowerW8 :: Word8 -> Word8
+    toLowerW8 w | 0x40 < w && w < 0x5b = w+0x20
+                | otherwise            = w
diff --git a/cabal/Cabal/Distribution/PackageDescription/PrettyPrint.hs b/cabal/Cabal/Distribution/PackageDescription/PrettyPrint.hs
--- a/cabal/Cabal/Distribution/PackageDescription/PrettyPrint.hs
+++ b/cabal/Cabal/Distribution/PackageDescription/PrettyPrint.hs
@@ -60,7 +60,7 @@
 
 -- | Writes a generic package description to a string
 showGenericPackageDescription :: GenericPackageDescription -> String
-showGenericPackageDescription            = render . ppGenericPackageDescription
+showGenericPackageDescription            = render . ($+$ text "") . ppGenericPackageDescription
 
 ppGenericPackageDescription :: GenericPackageDescription -> Doc
 ppGenericPackageDescription gpd          =
@@ -244,3 +244,4 @@
         $$  prettyFieldGrammar buildInfoFieldGrammar bi
         | (name, bi) <- ex_bis
         ]
+    $+$ text ""
diff --git a/cabal/Cabal/Distribution/Parsec/Class.hs b/cabal/Cabal/Distribution/Parsec/Class.hs
--- a/cabal/Cabal/Distribution/Parsec/Class.hs
+++ b/cabal/Cabal/Distribution/Parsec/Class.hs
@@ -1,10 +1,17 @@
-{-# LANGUAGE RankNTypes, FlexibleContexts #-}
+{-# LANGUAGE GADTs               #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE RankNTypes          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 module Distribution.Parsec.Class (
     Parsec(..),
-    ParsecParser,
+    ParsecParser (..),
+    runParsecParser,
     simpleParsec,
-    -- * Warnings
-    parsecWarning,
+    lexemeParsec,
+    eitherParsec,
+    explicitEitherParsec,
+    -- * CabalParsing & warnings
+    CabalParsing (..),
     PWarnType (..),
     -- * Utilities
     parsecToken,
@@ -13,48 +20,153 @@
     parsecQuoted,
     parsecMaybeQuoted,
     parsecCommaList,
+    parsecLeadingCommaList,
     parsecOptCommaList,
     parsecStandard,
     parsecUnqualComponentName,
     ) where
 
-import           Data.Functor.Identity       (Identity (..))
-import qualified Distribution.Compat.Parsec  as P
-import           Distribution.Compat.Prelude
-import           Distribution.Parsec.Common  (PWarnType (..), PWarning (..), Position (..))
-import           Prelude ()
-import qualified Text.Parsec                 as Parsec
-import qualified Text.Parsec.Language        as Parsec
-import qualified Text.Parsec.Token           as Parsec
+import Data.Char                     (digitToInt, intToDigit)
+import Data.Functor.Identity         (Identity (..))
+import Data.List                     (transpose)
+import Distribution.CabalSpecVersion
+import Distribution.Compat.Prelude
+import Distribution.Parsec.FieldLineStream
+import Distribution.Parsec.Common    (PWarnType (..), PWarning (..), Position (..))
+import Numeric                       (showIntAtBase)
+import Prelude ()
 
+import qualified Distribution.Compat.CharParsing as P
+import qualified Distribution.Compat.MonadFail   as Fail
+import qualified Distribution.Compat.ReadP       as ReadP
+import qualified Text.Parsec                     as Parsec
+
 -------------------------------------------------------------------------------
 -- Class
 -------------------------------------------------------------------------------
 
--- |
---
--- TODO: implementation details: should be careful about consuming
--- trailing whitespace?
--- Should we always consume it?
+-- | Class for parsing with @parsec@. Mainly used for @.cabal@ file fields.
 class Parsec a where
-    parsec :: ParsecParser a
+    parsec :: CabalParsing m => m a
 
-    -- | 'parsec' /could/ consume trailing spaces, this function /must/ consume.
-    lexemeParsec :: ParsecParser a
-    lexemeParsec = parsec <* P.spaces
+-- | Parsing class which
+--
+-- * can report Cabal parser warnings.
+--
+-- * knows @cabal-version@ we work with
+--
+class (P.CharParsing m, MonadPlus m) => CabalParsing m where
+    parsecWarning :: PWarnType -> String -> m ()
 
-type ParsecParser a = forall s. P.Stream s Identity Char => P.Parsec s [PWarning] a
+    parsecHaskellString :: m String
+    parsecHaskellString = stringLiteral
 
+    askCabalSpecVersion :: m CabalSpecVersion
+
+instance t ~ Char => CabalParsing (ReadP.Parser r t) where
+    parsecWarning _ _   = pure ()
+    askCabalSpecVersion = pure cabalSpecLatest
+
+-- | 'parsec' /could/ consume trailing spaces, this function /will/ consume.
+lexemeParsec :: (CabalParsing m, Parsec a) => m a
+lexemeParsec = parsec <* P.spaces
+
+newtype ParsecParser a = PP { unPP
+    :: CabalSpecVersion -> Parsec.Parsec FieldLineStream [PWarning] a
+    }
+
+liftParsec :: Parsec.Parsec FieldLineStream [PWarning] a -> ParsecParser a
+liftParsec p = PP $ \_ -> p
+
+instance Functor ParsecParser where
+    fmap f p = PP $ \v -> fmap f (unPP p v)
+    {-# INLINE fmap #-}
+
+    x <$ p = PP $ \v -> x <$ unPP p v
+    {-# INLINE (<$) #-}
+
+instance Applicative ParsecParser where
+    pure = liftParsec . pure
+    {-# INLINE pure #-}
+
+    f <*> x = PP $ \v -> unPP f v <*> unPP x v
+    {-# INLINE (<*>) #-}
+    f  *> x = PP $ \v -> unPP f v  *> unPP x v
+    {-# INLINE (*>) #-}
+    f <*  x = PP $ \v -> unPP f v <*  unPP x v
+    {-# INLINE (<*) #-}
+
+instance Alternative ParsecParser where
+    empty = liftParsec empty
+
+    a <|> b = PP $ \v -> unPP a v <|> unPP b v
+    {-# INLINE (<|>) #-}
+
+    many p = PP $ \v -> many (unPP p v)
+    {-# INLINE many #-}
+
+    some p = PP $ \v -> some (unPP p v)
+    {-# INLINE some #-}
+
+instance Monad ParsecParser where
+    return = pure
+
+    m >>= k = PP $ \v -> unPP m v >>= \x -> unPP (k x) v
+    {-# INLINE (>>=) #-}
+    (>>) = (*>)
+    {-# INLINE (>>) #-}
+
+    fail = Fail.fail
+
+instance MonadPlus ParsecParser where
+    mzero = empty
+    mplus = (<|>)
+
+instance Fail.MonadFail ParsecParser where
+    fail = P.unexpected
+
+instance P.Parsing ParsecParser where
+    try p           = PP $ \v -> P.try (unPP p v)
+    p <?> d         = PP $ \v -> unPP p v P.<?> d
+    skipMany p      = PP $ \v -> P.skipMany (unPP p v)
+    skipSome p      = PP $ \v -> P.skipSome (unPP p v)
+    unexpected      = liftParsec . P.unexpected
+    eof             = liftParsec P.eof
+    notFollowedBy p = PP $ \v -> P.notFollowedBy (unPP p v)
+
+instance P.CharParsing ParsecParser where
+    satisfy   = liftParsec . P.satisfy
+    char      = liftParsec . P.char
+    notChar   = liftParsec . P.notChar
+    anyChar   = liftParsec P.anyChar
+    string    = liftParsec . P.string
+
+instance CabalParsing ParsecParser where
+    parsecWarning t w = liftParsec $ Parsec.modifyState (PWarning t (Position 0 0) w :)
+    askCabalSpecVersion = PP pure
+
 -- | Parse a 'String' with 'lexemeParsec'.
 simpleParsec :: Parsec a => String -> Maybe a
 simpleParsec
     = either (const Nothing) Just
-    . P.runParser (lexemeParsec <* P.eof) [] "<simpleParsec>"
+    . runParsecParser lexemeParsec "<simpleParsec>"
+    . fieldLineStreamFromString
 
-parsecWarning :: PWarnType -> String -> P.Parsec s [PWarning] ()
-parsecWarning t w =
-    Parsec.modifyState (PWarning t (Position 0 0) w :)
+-- | Parse a 'String' with 'lexemeParsec'.
+eitherParsec :: Parsec a => String -> Either String a
+eitherParsec = explicitEitherParsec parsec
 
+-- | Parse a 'String' with given 'ParsecParser'. Trailing whitespace is accepted.
+explicitEitherParsec :: ParsecParser a -> String -> Either String a
+explicitEitherParsec parser
+    = either (Left . show) Right
+    . runParsecParser (parser <* P.spaces) "<eitherParsec>"
+    . fieldLineStreamFromString
+
+-- | Run 'ParsecParser' with 'cabalSpecLatest'.
+runParsecParser :: ParsecParser a -> FilePath -> FieldLineStream -> Either Parsec.ParseError a
+runParsecParser p n = Parsec.runParser (unPP p cabalSpecLatest <* P.eof) [] n
+
 instance Parsec a => Parsec (Identity a) where
     parsec = Identity <$> parsec
 
@@ -73,21 +185,28 @@
                 "Boolean values are case sensitive, use 'True' or 'False'."
 
 -- | @[^ ,]@
-parsecToken :: P.Stream s Identity Char => P.Parsec s [PWarning] String
-parsecToken = parsecHaskellString <|> (P.munch1 (\x -> not (isSpace x) && x /= ',')  P.<?> "identifier" )
+parsecToken :: CabalParsing m => m String
+parsecToken = parsecHaskellString <|> ((P.munch1 (\x -> not (isSpace x) && x /= ',')  P.<?> "identifier" ) >>= checkNotDoubleDash)
 
 -- | @[^ ]@
-parsecToken' :: P.Stream s Identity Char => P.Parsec s [PWarning] String
-parsecToken' = parsecHaskellString <|> (P.munch1 (not . isSpace) P.<?> "token")
+parsecToken' :: CabalParsing m => m String
+parsecToken' = parsecHaskellString <|> ((P.munch1 (not . isSpace) P.<?> "token") >>= checkNotDoubleDash)
 
-parsecFilePath :: P.Stream s Identity Char => P.Parsec s [PWarning] FilePath
+checkNotDoubleDash ::  CabalParsing m => String -> m String
+checkNotDoubleDash s = do
+    when (s == "--") $ parsecWarning PWTDoubleDash $ unwords
+        [ "Double-dash token found."
+        , "Note: there are no end-of-line comments in .cabal files, only whole line comments."
+        , "Use \"--\" (quoted double dash) to silence this warning, if you actually want -- token"
+        ]
+
+    return s
+
+parsecFilePath :: CabalParsing m => m FilePath
 parsecFilePath = parsecToken
 
 -- | Parse a benchmark/test-suite types.
-parsecStandard
-    :: (Parsec ver, P.Stream s Identity Char)
-    => (ver -> String -> a)
-    -> P.Parsec s [PWarning] a
+parsecStandard :: (CabalParsing m, Parsec ver) => (ver -> String -> a) -> m a
 parsecStandard f = do
     cs   <- some $ P.try (component <* P.char '-')
     ver  <- parsec
@@ -100,57 +219,135 @@
       -- each component must contain an alphabetic character, to avoid
       -- ambiguity in identifiers like foo-1 (the 1 is the version number).
 
-parsecCommaList
-    :: P.Stream s Identity Char
-    => P.Parsec s [PWarning] a
-    -> P.Parsec s [PWarning] [a]
-parsecCommaList p = P.sepBy (p <* P.spaces) (P.char ',' *> P.spaces)
+parsecCommaList :: CabalParsing m => m a -> m [a]
+parsecCommaList p = P.sepBy (p <* P.spaces) (P.char ',' *> P.spaces P.<?> "comma")
 
-parsecOptCommaList
-    :: P.Stream s Identity Char
-    => P.Parsec s [PWarning] a
-    -> P.Parsec s [PWarning] [a]
+-- | Like 'parsecCommaList' but accept leading or trailing comma.
+--
+-- @
+-- p (comma p)*  -- p `sepBy` comma
+-- (comma p)*    -- leading comma
+-- (p comma)*    -- trailing comma
+-- @
+parsecLeadingCommaList :: CabalParsing m => m a -> m [a]
+parsecLeadingCommaList p = do
+    c <- P.optional comma
+    case c of
+        Nothing -> P.sepEndBy1 lp comma <|> pure []
+        Just _  -> P.sepBy1 lp comma
+  where
+    lp = p <* P.spaces
+    comma = P.char ',' *> P.spaces P.<?> "comma"
+
+parsecOptCommaList :: CabalParsing m => m a -> m [a]
 parsecOptCommaList p = P.sepBy (p <* P.spaces) (P.optional comma)
   where
     comma = P.char ',' *>  P.spaces
 
 -- | Content isn't unquoted
-parsecQuoted
-     :: P.Stream s Identity Char
-     => P.Parsec s [PWarning] a
-     -> P.Parsec s [PWarning] a
+parsecQuoted :: CabalParsing m => m a -> m a
 parsecQuoted = P.between (P.char '"') (P.char '"')
 
 -- | @parsecMaybeQuoted p = 'parsecQuoted' p <|> p@.
-parsecMaybeQuoted
-     :: P.Stream s Identity Char
-     => P.Parsec s [PWarning] a
-     -> P.Parsec s [PWarning] a
+parsecMaybeQuoted :: CabalParsing m => m a -> m a
 parsecMaybeQuoted p = parsecQuoted p <|> p
 
-parsecHaskellString :: P.Stream s Identity Char => P.Parsec s [PWarning] String
-parsecHaskellString = Parsec.stringLiteral $ Parsec.makeTokenParser Parsec.emptyDef
-    { Parsec.commentStart   = "{-"
-    , Parsec.commentEnd     = "-}"
-    , Parsec.commentLine    = "--"
-    , Parsec.nestedComments = True
-    , Parsec.identStart     = P.satisfy isAlphaNum
-    , Parsec.identLetter    = P.satisfy isAlphaNum <|> P.oneOf "_'"
-    , Parsec.opStart        = opl
-    , Parsec.opLetter       = opl
-    , Parsec.reservedOpNames= []
-    , Parsec.reservedNames  = []
-    , Parsec.caseSensitive  = True
-    }
-  where
-    opl = P.oneOf ":!#$%&*+./<=>?@\\^|-~"
-
-parsecUnqualComponentName :: P.Stream s Identity Char => P.Parsec s [PWarning] String
+parsecUnqualComponentName :: CabalParsing m => m String
 parsecUnqualComponentName = intercalate "-" <$> P.sepBy1 component (P.char '-')
   where
-    component :: P.Stream s Identity Char => P.Parsec s [PWarning] String
+    component :: CabalParsing m => m String
     component = do
       cs <- P.munch1 isAlphaNum
       if all isDigit cs
         then fail "all digits in portion of unqualified component name"
         else return cs
+
+stringLiteral :: forall m. P.CharParsing m => m String
+stringLiteral = lit where
+    lit :: m String
+    lit = foldr (maybe id (:)) ""
+        <$> P.between (P.char '"') (P.char '"' P.<?> "end of string") (many stringChar)
+        P.<?> "string"
+
+    stringChar :: m (Maybe Char)
+    stringChar = Just <$> stringLetter
+         <|> stringEscape
+         P.<?> "string character"
+
+    stringLetter :: m Char
+    stringLetter = P.satisfy (\c -> (c /= '"') && (c /= '\\') && (c > '\026'))
+
+    stringEscape :: m (Maybe Char)
+    stringEscape = P.char '\\' *> esc where
+        esc :: m (Maybe Char)
+        esc = Nothing <$ escapeGap
+            <|> Nothing <$ escapeEmpty
+            <|> Just <$> escapeCode
+
+    escapeEmpty, escapeGap :: m Char
+    escapeEmpty = P.char '&'
+    escapeGap = P.skipSpaces1 *> (P.char '\\' P.<?> "end of string gap")
+
+escapeCode :: forall m. P.CharParsing m => m Char
+escapeCode = (charEsc <|> charNum <|> charAscii <|> charControl) P.<?> "escape code"
+  where
+  charControl, charNum :: m Char
+  charControl = (\c -> toEnum (fromEnum c - fromEnum '@')) <$> (P.char '^' *> (P.upper <|> P.char '@'))
+  charNum = toEnum <$> num
+    where
+      num :: m Int
+      num = bounded 10 maxchar
+        <|> (P.char 'o' *> bounded 8 maxchar)
+        <|> (P.char 'x' *> bounded 16 maxchar)
+      maxchar = fromEnum (maxBound :: Char)
+
+  bounded :: Int -> Int -> m Int
+  bounded base bnd = foldl' (\x d -> base * x + digitToInt d) 0
+                 <$> bounded' (take base thedigits) (map digitToInt $ showIntAtBase base intToDigit bnd "")
+    where
+      thedigits :: [m Char]
+      thedigits = map P.char ['0'..'9'] ++ map P.oneOf (transpose [['A'..'F'],['a'..'f']])
+
+      toomuch :: m a
+      toomuch = P.unexpected "out-of-range numeric escape sequence"
+
+      bounded', bounded'' :: [m Char] -> [Int] -> m [Char]
+      bounded' dps@(zero:_) bds = P.skipSome zero *> ([] <$ P.notFollowedBy (P.choice dps) <|> bounded'' dps bds)
+                              <|> bounded'' dps bds
+      bounded' []           _   = error "bounded called with base 0"
+      bounded'' dps []         = [] <$ P.notFollowedBy (P.choice dps) <|> toomuch
+      bounded'' dps (bd : bds) = let anyd :: m Char
+                                     anyd = P.choice dps
+
+                                     nomore :: m ()
+                                     nomore = P.notFollowedBy anyd <|> toomuch
+
+                                     (low, ex : high) = splitAt bd dps
+                                  in ((:) <$> P.choice low <*> atMost (length bds) anyd) <* nomore
+                                     <|> ((:) <$> ex <*> ([] <$ nomore <|> bounded'' dps bds))
+                                     <|> if not (null bds)
+                                            then (:) <$> P.choice high <*> atMost (length bds - 1) anyd <* nomore
+                                            else empty
+      atMost n p | n <= 0    = pure []
+                 | otherwise = ((:) <$> p <*> atMost (n - 1) p) <|> pure []
+
+  charEsc :: m Char
+  charEsc = P.choice $ parseEsc <$> escMap
+
+  parseEsc (c,code) = code <$ P.char c
+  escMap = zip "abfnrtv\\\"\'" "\a\b\f\n\r\t\v\\\"\'"
+
+  charAscii :: m Char
+  charAscii = P.choice $ parseAscii <$> asciiMap
+
+  parseAscii (asc,code) = P.try $ code <$ P.string asc
+  asciiMap = zip (ascii3codes ++ ascii2codes) (ascii3 ++ ascii2)
+  ascii2codes, ascii3codes :: [String]
+  ascii2codes = [ "BS","HT","LF","VT","FF","CR","SO"
+                , "SI","EM","FS","GS","RS","US","SP"]
+  ascii3codes = ["NUL","SOH","STX","ETX","EOT","ENQ","ACK"
+                ,"BEL","DLE","DC1","DC2","DC3","DC4","NAK"
+                ,"SYN","ETB","CAN","SUB","ESC","DEL"]
+  ascii2, ascii3 :: String
+  ascii2 = "\BS\HT\LF\VT\FF\CR\SO\SI\EM\FS\GS\RS\US\SP"
+  ascii3 = "\NUL\SOH\STX\ETX\EOT\ENQ\ACK\BEL\DLE\DC1\DC2\DC3\DC4\NAK\SYN\ETB\CAN\SUB\ESC\DEL"
diff --git a/cabal/Cabal/Distribution/Parsec/Common.hs b/cabal/Cabal/Distribution/Parsec/Common.hs
--- a/cabal/Cabal/Distribution/Parsec/Common.hs
+++ b/cabal/Cabal/Distribution/Parsec/Common.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DeriveGeneric #-}
 -- | Module containing small types
 module Distribution.Parsec.Common (
     -- * Diagnostics
@@ -6,8 +7,6 @@
     PWarning (..),
     PWarnType (..),
     showPWarning,
-    -- * Field parser
-    FieldParser,
     -- * Position
     Position (..),
     incPos,
@@ -16,15 +15,17 @@
     zeroPos,
     ) where
 
-import           Prelude ()
-import           Distribution.Compat.Prelude
-import           System.FilePath             (normalise)
-import qualified Text.Parsec                 as Parsec
+import Distribution.Compat.Prelude
+import Prelude ()
+import System.FilePath             (normalise)
 
 -- | Parser error.
 data PError = PError Position String
-    deriving (Show)
+    deriving (Show, Generic)
 
+instance Binary PError
+instance NFData PError where rnf = genericRnf
+
 -- | Type of parser warning. We do classify warnings.
 --
 -- Different application may decide not to show some, or have fatal behaviour on others
@@ -45,13 +46,24 @@
     | PWTExtraBenchmarkModule  -- ^ extra benchmark-module field
     | PWTLexNBSP
     | PWTLexBOM
+    | PWTLexTab
     | PWTQuirkyCabalFile       -- ^ legacy cabal file that we know how to patch
-    deriving (Eq, Ord, Show, Enum, Bounded)
+    | PWTDoubleDash            -- ^ Double dash token, most likely it's a mistake - it's not a comment
+    | PWTMultipleSingularField -- ^ e.g. name or version should be specified only once.
+    | PWTBuildTypeDefault      -- ^ Workaround for derive-package having build-type: Default. See <https://github.com/haskell/cabal/issues/5020>.
+    | PWTVersionLeadingZeros   -- ^ See https://github.com/haskell-infra/hackage-trustees/issues/128
+    deriving (Eq, Ord, Show, Enum, Bounded, Generic)
 
+instance Binary PWarnType
+instance NFData PWarnType where rnf = genericRnf
+
 -- | Parser warning.
 data PWarning = PWarning !PWarnType !Position String
-    deriving (Show)
+    deriving (Show, Generic)
 
+instance Binary PWarning
+instance NFData PWarning where rnf = genericRnf
+
 showPWarning :: FilePath -> PWarning -> String
 showPWarning fpath (PWarning _ pos msg) =
   normalise fpath ++ ":" ++ showPos pos ++ ": " ++ msg
@@ -61,14 +73,6 @@
   normalise fpath ++ ":" ++ showPos pos ++ ": " ++ msg
 
 -------------------------------------------------------------------------------
--- Field parser
--------------------------------------------------------------------------------
-
--- | Field value parsers.
-type FieldParser = Parsec.Parsec String [PWarning] -- :: * -> *
-
-
--------------------------------------------------------------------------------
 -- Position
 -------------------------------------------------------------------------------
 
@@ -76,7 +80,10 @@
 data Position = Position
     {-# UNPACK #-}  !Int           -- row
     {-# UNPACK #-}  !Int           -- column
-  deriving (Eq, Ord, Show)
+  deriving (Eq, Ord, Show, Generic)
+
+instance Binary Position
+instance NFData Position where rnf = genericRnf
 
 -- | Shift position by n columns to the right.
 incPos :: Int -> Position -> Position
diff --git a/cabal/Cabal/Distribution/Parsec/ConfVar.hs b/cabal/Cabal/Distribution/Parsec/ConfVar.hs
--- a/cabal/Cabal/Distribution/Parsec/ConfVar.hs
+++ b/cabal/Cabal/Distribution/Parsec/ConfVar.hs
@@ -2,23 +2,24 @@
 {-# LANGUAGE NoMonoLocalBinds #-}
 module Distribution.Parsec.ConfVar (parseConditionConfVar) where
 
-import           Distribution.Compat.Parsec                   (integral)
-import           Distribution.Compat.Prelude
-import           Distribution.Parsec.Class                    (Parsec (..))
-import           Distribution.Parsec.Common
-import           Distribution.Parsec.Field                    (SectionArg (..))
-import           Distribution.Parsec.ParseResult
-import           Distribution.Simple.Utils                    (fromUTF8BS)
-import           Distribution.Types.Condition
-import           Distribution.Types.GenericPackageDescription (ConfVar (..))
-import           Distribution.Version
-                 (anyVersion, earlierVersion, intersectVersionRanges, laterVersion,
-                 majorBoundVersion, mkVersion, noVersion, orEarlierVersion, orLaterVersion,
-                 thisVersion, unionVersionRanges, withinVersion)
-import           Prelude ()
-import qualified Text.Parsec                                  as P
-import qualified Text.Parsec.Error                            as P
+import Distribution.Compat.CharParsing              (char, integral)
+import Distribution.Compat.Prelude
+import Distribution.Parsec.Class                    (Parsec (..), runParsecParser)
+import Distribution.Parsec.Common
+import Distribution.Parsec.FieldLineStream
+import Distribution.Parsec.Field                    (SectionArg (..))
+import Distribution.Parsec.ParseResult
+import Distribution.Types.Condition
+import Distribution.Types.GenericPackageDescription (ConfVar (..))
+import Distribution.Version
+       (anyVersion, earlierVersion, intersectVersionRanges, laterVersion, majorBoundVersion,
+       mkVersion, noVersion, orEarlierVersion, orLaterVersion, thisVersion, unionVersionRanges,
+       withinVersion)
+import Prelude ()
 
+import qualified Text.Parsec       as P
+import qualified Text.Parsec.Error as P
+
 -- | Parse @'Condition' 'ConfVar'@ from section arguments provided by parsec
 -- based outline parser.
 parseConditionConfVar :: [SectionArg Position] -> ParseResult (Condition ConfVar)
@@ -60,7 +61,7 @@
 
     version = fromParsec
     versionStar  = mkVersion <$> fromParsec' versionStar' <* oper "*"
-    versionStar' = some (integral <* P.char '.')
+    versionStar' = some (integral <* char '.')
 
     versionRange = expr
       where
@@ -88,8 +89,8 @@
                      ("==", thisVersion) ]
 
     -- Number token can have many dots in it: SecArgNum (Position 65 15) "7.6.1"
-    ident = tokenPrim $ \t -> case t of
-        SecArgName _ s -> Just $ fromUTF8BS s
+    identBS = tokenPrim $ \t -> case t of
+        SecArgName _ s -> Just s
         _              -> Nothing
 
     boolLiteral' = tokenPrim $ \t -> case t of
@@ -119,8 +120,6 @@
     fromParsec = fromParsec' parsec
 
     fromParsec' p = do
-        i <- ident
-        case P.runParser (p <* P.eof) [] "<ident>" i of
-            Right x  -> pure x
-            -- TODO: better lifting or errors / warnings
-            Left err -> fail $ show err
+        bs <- identBS
+        let fls = fieldLineStreamFromBS bs
+        either (fail . show) pure (runParsecParser p "<fromParsec'>" fls)
diff --git a/cabal/Cabal/Distribution/Parsec/FieldLineStream.hs b/cabal/Cabal/Distribution/Parsec/FieldLineStream.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/Parsec/FieldLineStream.hs
@@ -0,0 +1,96 @@
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings    , ScopedTypeVariables #-}
+{-# OPTIONS_GHC -Wall -Werror #-}
+module Distribution.Parsec.FieldLineStream (
+    FieldLineStream (..),
+    fieldLinesToStream,
+    fieldLineStreamFromString,
+    fieldLineStreamFromBS,
+    ) where
+
+import Data.Bits
+import Data.ByteString             (ByteString)
+import Distribution.Compat.Prelude
+import Distribution.Parsec.Field   (FieldLine (..))
+import Distribution.Utils.Generic  (toUTF8BS)
+import Prelude ()
+
+import qualified Data.ByteString as BS
+import qualified Text.Parsec     as Parsec
+
+-- | This is essentially a lazy bytestring, but chunks are glued with newline '\n'.
+data FieldLineStream
+    = FLSLast !ByteString
+    | FLSCons {-# UNPACK #-} !ByteString FieldLineStream
+  deriving Show
+
+fieldLinesToStream :: [FieldLine ann] -> FieldLineStream
+fieldLinesToStream []                    = end
+fieldLinesToStream [FieldLine _ bs]      = FLSLast bs
+fieldLinesToStream (FieldLine _ bs : fs) = FLSCons bs (fieldLinesToStream fs)
+
+end :: FieldLineStream
+end = FLSLast ""
+
+-- | Convert 'String' to 'FieldLineStream'.
+--
+-- /Note:/ inefficient!
+fieldLineStreamFromString :: String -> FieldLineStream
+fieldLineStreamFromString = FLSLast . toUTF8BS
+
+fieldLineStreamFromBS :: ByteString -> FieldLineStream
+fieldLineStreamFromBS = FLSLast
+
+instance Monad m => Parsec.Stream FieldLineStream m Char where
+    uncons (FLSLast bs) = return $ case BS.uncons bs of
+        Nothing       -> Nothing
+        Just (c, bs') -> Just (unconsChar c bs' (\bs'' -> FLSLast bs'') end)
+
+    uncons (FLSCons bs s) = return $ case BS.uncons bs of
+        -- as lines are glued with '\n', we return '\n' here!
+        Nothing -> Just ('\n', s)
+        Just (c, bs') -> Just (unconsChar c bs' (\bs'' -> FLSCons bs'' s) s)
+
+-- Bssed on implementation 'decodeStringUtf8'
+unconsChar :: forall a. Word8 -> ByteString -> (ByteString -> a) -> a -> (Char, a)
+unconsChar c0 bs0 f next
+    | c0 <= 0x7F = (chr (fromIntegral c0), f bs0)
+    | c0 <= 0xBF = (replacementChar, f bs0)
+    | c0 <= 0xDF = twoBytes
+    | c0 <= 0xEF = moreBytes 3 0x800     bs0 (fromIntegral $ c0 .&. 0xF)
+    | c0 <= 0xF7 = moreBytes 4 0x10000   bs0 (fromIntegral $ c0 .&. 0x7)
+    | c0 <= 0xFB = moreBytes 5 0x200000  bs0 (fromIntegral $ c0 .&. 0x3)
+    | c0 <= 0xFD = moreBytes 6 0x4000000 bs0 (fromIntegral $ c0 .&. 0x1)
+    | otherwise = error $ "not implemented " ++ show c0
+  where
+    twoBytes = case BS.uncons bs0 of
+        Nothing -> (replacementChar, next)
+        Just (c1, bs1)
+            | c1 .&. 0xC0 == 0x80 ->
+                if d >= 0x80
+                then  (chr d, f bs1)
+                else  (replacementChar, f bs1)
+            | otherwise -> (replacementChar, f bs1)
+          where
+            d = (fromIntegral (c0 .&. 0x1F) `shiftL` 6) .|. fromIntegral (c1 .&. 0x3F)
+
+    moreBytes :: Int -> Int -> ByteString -> Int -> (Char, a)
+    moreBytes 1 overlong bs' acc
+        | overlong <= acc, acc <= 0x10FFFF, acc < 0xD800 || 0xDFFF < acc
+            = (chr acc, f bs')
+        | otherwise
+            = (replacementChar, f bs')
+
+    moreBytes byteCount overlong bs' acc = case BS.uncons bs' of
+        Nothing                   -> (replacementChar, f bs')
+        Just (cn, bs1)
+            | cn .&. 0xC0 == 0x80 -> moreBytes
+                (byteCount-1)
+                overlong
+                bs1
+                ((acc `shiftL` 6) .|. fromIntegral cn .&. 0x3F)
+            | otherwise           -> (replacementChar, f bs1)
+
+replacementChar :: Char
+replacementChar = '\xfffd'
diff --git a/cabal/Cabal/Distribution/Parsec/Lexer.hs b/cabal/Cabal/Distribution/Parsec/Lexer.hs
--- a/cabal/Cabal/Distribution/Parsec/Lexer.hs
+++ b/cabal/Cabal/Distribution/Parsec/Lexer.hs
@@ -53,7 +53,6 @@
 import qualified Data.Text.Encoding.Error as T
 #endif
 
-
 #if __GLASGOW_HASKELL__ >= 603
 #include "ghcconfig.h"
 #elif defined(__GLASGOW_HASKELL__)
@@ -85,8 +84,7 @@
 alex_deflt = AlexA# "\xff\xff\xff\xff\xff\xff\xff\xff\x2b\x00\x27\x00\x1b\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0d\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x13\x00\xff\xff\xff\xff\xff\xff\xff\xff\x18\x00\x1b\x00\x1b\x00\x1b\x00\xff\xff\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x27\x00\xff\xff\xff\xff\xff\xff\x2b\x00\xff\xff\xff\xff\xff\xff\xff\xff"#
 
 alex_accept = listArray (0::Int,47) [AlexAcc (alex_action_0),AlexAcc (alex_action_20),AlexAcc (alex_action_16),AlexAcc (alex_action_3),AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAcc (alex_action_1),AlexAcc (alex_action_1),AlexAccSkip,AlexAcc (alex_action_3),AlexAcc (alex_action_4),AlexAcc (alex_action_5),AlexAccSkip,AlexAccSkip,AlexAcc (alex_action_8),AlexAcc (alex_action_8),AlexAcc (alex_action_8),AlexAcc (alex_action_9),AlexAcc (alex_action_9),AlexAcc (alex_action_10),AlexAcc (alex_action_11),AlexAcc (alex_action_12),AlexAcc (alex_action_13),AlexAcc (alex_action_14),AlexAcc (alex_action_15),AlexAcc (alex_action_15),AlexAcc (alex_action_16),AlexAccSkip,AlexAcc (alex_action_18),AlexAcc (alex_action_19),AlexAcc (alex_action_19),AlexAccSkip,AlexAcc (alex_action_22),AlexAcc (alex_action_23),AlexAcc (alex_action_24),AlexAcc (alex_action_25),AlexAcc (alex_action_25)]
-{-# LINE 152 "boot/Lexer.x" #-}
-
+{-# LINE 151 "boot/Lexer.x" #-}
 
 -- | Tokens of outer cabal file structure. Field values are treated opaquely.
 data Token = TokSym   !ByteString       -- ^ Haskell-like identifier, number or operator
@@ -110,10 +108,17 @@
 tok :: Token -> Position -> Int -> ByteString -> Lex LToken
 tok  t pos _len _input = return $! L pos t
 
+checkLeadingWhitespace :: Int -> ByteString -> Lex Int
+checkLeadingWhitespace len bs
+    | B.any (== 9) (B.take len bs) = do
+        addWarning LexWarningTab
+        checkWhitespace len bs
+    | otherwise = checkWhitespace len bs
+
 checkWhitespace :: Int -> ByteString -> Lex Int
 checkWhitespace len bs
     | B.any (== 194) (B.take len bs) = do
-        addWarning LexWarningNBSP "Non-breaking space found"
+        addWarning LexWarningNBSP
         return $ len - B.count 194 (B.take len bs)
     | otherwise = return len
 
@@ -159,7 +164,6 @@
         --traceShow t $ return tok
         return t
 
-
 checkPosition :: Position -> ByteString -> ByteString -> Int -> Lex ()
 #ifdef CABAL_PARSEC_DEBUG
 checkPosition pos@(Position lineno colno) inp inp' len_chars = do
@@ -190,7 +194,6 @@
   let (ws, xs) = execLexer (setStartCode code >> lexAll) (B.Char8.pack s)
    in traverse_ print ws >> traverse_ print xs
 
-
 mkLexState :: ByteString -> LexState
 mkLexState input = LexState
   { curPos   = Position 1 1
@@ -216,7 +219,6 @@
                          -> [l]
 #endif
 
-
 bol_field_braces,bol_field_layout,bol_section,in_field_braces,in_field_layout,in_section :: Int
 bol_field_braces = 1
 bol_field_layout = 2
@@ -225,12 +227,12 @@
 in_field_layout = 5
 in_section = 6
 alex_action_0 =  \_ len _ -> do
-              when (len /= 0) $ addWarning LexWarningBOM "Byte-order mark found at the beginning of the file"
+              when (len /= 0) $ addWarning LexWarningBOM
               setStartCode bol_section
               lexToken
          
 alex_action_1 =  \_pos len inp -> checkWhitespace len inp >> adjustPos retPos >> lexToken 
-alex_action_3 =  \pos len inp -> checkWhitespace len inp >>
+alex_action_3 =  \pos len inp -> checkLeadingWhitespace len inp >>
                                      if B.length inp == len
                                        then return (L pos EOF)
                                        else setStartCode in_section
@@ -245,7 +247,7 @@
 alex_action_13 =  tok  OpenBrace 
 alex_action_14 =  tok  CloseBrace 
 alex_action_15 =  \_ _ _ -> adjustPos retPos >> setStartCode bol_section >> lexToken 
-alex_action_16 =  \pos len inp -> checkWhitespace len inp >>= \len' ->
+alex_action_16 =  \pos len inp -> checkLeadingWhitespace len inp >>= \len' ->
                                   if B.length inp == len
                                     then return (L pos EOF)
                                     else setStartCode in_field_layout
@@ -266,67 +268,9 @@
 
 # 17 "/usr/include/stdc-predef.h" 3 4
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 {-# LINE 10 "<command-line>" #-}
 {-# LINE 1 "/opt/ghc/7.10.3/lib/ghc-7.10.3/include/ghcversion.h" #-}
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 {-# LINE 10 "<command-line>" #-}
 {-# LINE 1 "templates/GenericTemplate.hs" #-}
 -- -----------------------------------------------------------------------------
@@ -340,10 +284,6 @@
 
 {-# LINE 21 "templates/GenericTemplate.hs" #-}
 
-
-
-
-
 -- Do not remove this comment. Required to fix CPP parsing when using GCC and a clang-compiled alex.
 #if __GLASGOW_HASKELL__ > 706
 #define GTE(n,m) (tagToEnum# (n >=# m))
@@ -354,7 +294,6 @@
 #endif
 {-# LINE 51 "templates/GenericTemplate.hs" #-}
 
-
 data AlexAddr = AlexA# Addr#
 -- Do not remove this comment. Required to fix CPP parsing when using GCC and a clang-compiled alex.
 #if __GLASGOW_HASKELL__ < 503
@@ -374,10 +313,6 @@
   indexInt16OffAddr# arr off
 #endif
 
-
-
-
-
 {-# INLINE alexIndexInt32OffAddr #-}
 alexIndexInt32OffAddr (AlexA# arr) off = 
 #ifdef WORDS_BIGENDIAN
@@ -395,11 +330,6 @@
   indexInt32OffAddr# arr off
 #endif
 
-
-
-
-
-
 #if __GLASGOW_HASKELL__ < 503
 quickIndex arr i = arr ! i
 #else
@@ -407,9 +337,6 @@
 quickIndex = unsafeAt
 #endif
 
-
-
-
 -- -----------------------------------------------------------------------------
 -- Main lexing routines
 
@@ -429,28 +356,19 @@
                 case alexGetByte input of
                         Nothing -> 
 
-
-
                                    AlexEOF
                         Just _ ->
 
-
-
                                    AlexError input'
 
         (AlexLastSkip input'' len, _) ->
 
-
-
                 AlexSkip input'' len
 
         (AlexLastAcc k input''' len, _) ->
 
-
-
                 AlexToken input''' len k
 
-
 -- Push the input through the DFA, remembering the most recent accepting
 -- state it encountered.
 
@@ -463,8 +381,6 @@
   case alexGetByte input of
      Nothing -> (new_acc, input)
      Just (c, new_input) -> 
-
-
 
       case fromIntegral c of { (I# (ord_c)) ->
         let
diff --git a/cabal/Cabal/Distribution/Parsec/LexerMonad.hs b/cabal/Cabal/Distribution/Parsec/LexerMonad.hs
--- a/cabal/Cabal/Distribution/Parsec/LexerMonad.hs
+++ b/cabal/Cabal/Distribution/Parsec/LexerMonad.hs
@@ -27,15 +27,17 @@
     LexWarning(..),
     LexWarningType(..),
     addWarning,
-    toPWarning,
+    toPWarnings,
 
   ) where
 
 import qualified Data.ByteString             as B
 import           Distribution.Compat.Prelude
-import           Distribution.Parsec.Common  (PWarnType (..), PWarning (..), Position (..))
+import           Distribution.Parsec.Common  (PWarnType (..), PWarning (..), Position (..), showPos)
 import           Prelude ()
 
+import qualified Data.Map.Strict as Map
+
 #ifdef CABAL_PARSEC_DEBUG
 -- testing only:
 import qualified Data.Text          as T
@@ -62,19 +64,26 @@
 data LexWarningType
     = LexWarningNBSP  -- ^ Encountered non breaking space
     | LexWarningBOM   -- ^ BOM at the start of the cabal file
-  deriving (Show)
+    | LexWarningTab   -- ^ Leading tags
+  deriving (Eq, Ord, Show)
 
 data LexWarning = LexWarning                !LexWarningType
                              {-# UNPACK #-} !Position
-                                            !String
   deriving (Show)
 
-toPWarning :: LexWarning -> PWarning
-toPWarning (LexWarning t p s) = PWarning t' p s
+toPWarnings :: [LexWarning] -> [PWarning]
+toPWarnings
+    = map (uncurry toWarning)
+    . Map.toList
+    . Map.fromListWith (++)
+    . map (\(LexWarning t p) -> (t, [p]))
   where
-    t' = case t of
-        LexWarningNBSP -> PWTLexNBSP
-        LexWarningBOM  -> PWTLexBOM
+    toWarning LexWarningBOM poss =
+        PWarning PWTLexBOM (head poss) "Byte-order mark found at the beginning of the file"
+    toWarning LexWarningNBSP poss =
+        PWarning PWTLexNBSP (head poss) $ "Non breaking spaces at " ++ intercalate ", " (map showPos poss)
+    toWarning LexWarningTab poss =
+        PWarning PWTLexTab (head poss) $ "Tabs used as indentation at " ++ intercalate ", " (map showPos poss)
 
 data LexState = LexState {
         curPos   :: {-# UNPACK #-} !Position,        -- ^ position at current input location
@@ -139,6 +148,6 @@
 setStartCode c = Lex $ \s -> LexResult s{ curCode = c } ()
 
 -- | Add warning at the current position
-addWarning :: LexWarningType -> String -> Lex ()
-addWarning wt msg = Lex $ \s@LexState{ curPos = pos, warnings = ws  } ->
-    LexResult s{ warnings = LexWarning wt pos msg : ws } ()
+addWarning :: LexWarningType -> Lex ()
+addWarning wt = Lex $ \s@LexState{ curPos = pos, warnings = ws  } ->
+    LexResult s{ warnings = LexWarning wt pos : ws } ()
diff --git a/cabal/Cabal/Distribution/Parsec/Newtypes.hs b/cabal/Cabal/Distribution/Parsec/Newtypes.hs
--- a/cabal/Cabal/Distribution/Parsec/Newtypes.hs
+++ b/cabal/Cabal/Distribution/Parsec/Newtypes.hs
@@ -17,9 +17,10 @@
     NoCommaFSep (..),
     -- ** Type
     List,
-    -- * Version
+    -- * Version & License
     SpecVersion (..),
     TestedWith (..),
+    SpecLicense (..),
     -- * Identifiers
     Token (..),
     Token' (..),
@@ -32,16 +33,20 @@
 import Distribution.Compat.Prelude
 import Prelude ()
 
-import           Data.Functor.Identity      (Identity (..))
-import           Data.List                  (dropWhileEnd)
-import qualified Distribution.Compat.Parsec as P
-import           Distribution.Compiler      (CompilerFlavor)
-import           Distribution.Parsec.Class
-import           Distribution.Parsec.Common (PWarning)
-import           Distribution.Pretty
-import           Distribution.Version       (Version, VersionRange, anyVersion)
-import           Text.PrettyPrint           (Doc, comma, fsep, punctuate, vcat, (<+>))
+import Data.Functor.Identity         (Identity (..))
+import Data.List                     (dropWhileEnd)
+import Distribution.CabalSpecVersion
+import Distribution.Compiler         (CompilerFlavor)
+import Distribution.License          (License)
+import Distribution.Parsec.Class
+import Distribution.Pretty
+import Distribution.Version
+       (LowerBound (..), Version, VersionRange, anyVersion, asVersionIntervals, mkVersion)
+import Text.PrettyPrint              (Doc, comma, fsep, punctuate, vcat, (<+>))
 
+import qualified Distribution.Compat.CharParsing as P
+import qualified Distribution.SPDX               as SPDX
+
 -- | Vertical list with commas. Displayed with 'vcat'
 data CommaVCat = CommaVCat
 
@@ -62,25 +67,27 @@
 
 class    Sep sep  where
     prettySep :: P sep -> [Doc] -> Doc
-    parseSep
-        :: P sep -> P.Stream s Identity Char
-        => P.Parsec s [PWarning] a
-        -> P.Parsec s [PWarning] [a]
 
+    parseSep :: CabalParsing m => P sep -> m a -> m [a]
+
 instance Sep CommaVCat where
-    prettySep _ = vcat . punctuate comma
-    parseSep  _ = parsecCommaList
+    prettySep  _ = vcat . punctuate comma
+    parseSep   _ p = do
+        v <- askCabalSpecVersion
+        if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p
 instance Sep CommaFSep where
     prettySep _ = fsep . punctuate comma
-    parseSep  _ = parsecCommaList
+    parseSep   _ p = do
+        v <- askCabalSpecVersion
+        if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p
 instance Sep VCat where
-    prettySep _ = vcat
-    parseSep  _ = parsecOptCommaList
+    prettySep _  = vcat
+    parseSep  _  = parsecOptCommaList
 instance Sep FSep where
-    prettySep _ = fsep
-    parseSep  _ = parsecOptCommaList
+    prettySep _  = fsep
+    parseSep  _  = parsecOptCommaList
 instance Sep NoCommaFSep where
-    prettySep _ = fsep
+    prettySep _   = fsep
     parseSep  _ p = many (p <* P.spaces)
 
 -- | List separated with optional commas. Displayed with @sep@, arguments of
@@ -90,7 +97,7 @@
 -- | 'alaList' and 'alaList'' are simply 'List', with additional phantom
 -- arguments to constraint the resulting type
 --
--- >>> :t alaList VCat 
+-- >>> :t alaList VCat
 -- alaList VCat :: [a] -> List VCat (Identity a) a
 --
 -- >>> :t alaList' FSep Token
@@ -108,7 +115,7 @@
     unpack = getList
 
 instance (Newtype b a, Sep sep, Parsec b) => Parsec (List sep b a) where
-    parsec = pack . map (unpack :: b -> a) <$> parseSep (P :: P sep) parsec
+    parsec   = pack . map (unpack :: b -> a) <$> parseSep (P :: P sep) parsec
 
 instance (Newtype b a, Sep sep, Pretty b) => Pretty (List sep b a) where
     pretty = prettySep (P :: P sep) . map (pretty . (pack :: a -> b)) . unpack
@@ -152,7 +159,15 @@
 instance Pretty a => Pretty (MQuoted a)  where
     pretty = pretty . unpack
 
--- | Version range or just version
+-- | Version range or just version, i.e. @cabal-version@ field.
+--
+-- There are few things to consider:
+--
+-- * Starting with 2.2 the cabal-version field should be the first field in the
+--   file and only exact version is accepted. Therefore if we get e.g.
+--   @>= 2.2@, we fail.
+--   See <https://github.com/haskell/cabal/issues/4899>
+--
 newtype SpecVersion = SpecVersion { getSpecVersion :: Either Version VersionRange }
 
 instance Newtype SpecVersion (Either Version VersionRange) where
@@ -162,11 +177,38 @@
 instance Parsec SpecVersion where
     parsec = pack <$> parsecSpecVersion
       where
-        parsecSpecVersion = Left <$> parsec <|> Right <$> parsec
+        parsecSpecVersion = Left <$> parsec <|> Right <$> range
+        range = do
+            vr <- parsec
+            if specVersionFromRange vr >= mkVersion [2,1]
+            then fail "cabal-version higher than 2.2 cannot be specified as a range. See https://github.com/haskell/cabal/issues/4899"
+            else return vr
 
 instance Pretty SpecVersion where
     pretty = either pretty pretty . unpack
 
+specVersionFromRange :: VersionRange -> Version
+specVersionFromRange versionRange = case asVersionIntervals versionRange of
+    []                            -> mkVersion [0]
+    ((LowerBound version _, _):_) -> version
+
+-- | SPDX License expression or legacy license
+newtype SpecLicense = SpecLicense { getSpecLicense :: Either SPDX.License License }
+
+instance Newtype SpecLicense (Either SPDX.License License) where
+    pack = SpecLicense
+    unpack = getSpecLicense
+
+instance Parsec SpecLicense where
+    parsec = do
+        v <- askCabalSpecVersion
+        if v >= CabalSpecV2_2
+        then SpecLicense . Left <$> parsec
+        else SpecLicense . Right <$> parsec
+
+instance Pretty SpecLicense where
+    pretty = either pretty pretty . unpack
+
 -- | Version range or just version
 newtype TestedWith = TestedWith { getTestedWith :: (CompilerFlavor, VersionRange) }
 
@@ -229,7 +271,7 @@
 -- Internal
 -------------------------------------------------------------------------------
 
-parsecTestedWith :: P.Stream s Identity Char => P.Parsec s [PWarning] (CompilerFlavor, VersionRange)
+parsecTestedWith :: CabalParsing m => m (CompilerFlavor, VersionRange)
 parsecTestedWith = do
     name <- lexemeParsec
     ver  <- parsec <|> pure anyVersion
diff --git a/cabal/Cabal/Distribution/Parsec/ParseResult.hs b/cabal/Cabal/Distribution/Parsec/ParseResult.hs
--- a/cabal/Cabal/Distribution/Parsec/ParseResult.hs
+++ b/cabal/Cabal/Distribution/Parsec/ParseResult.hs
@@ -1,6 +1,7 @@
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP          #-}
-{-# LANGUAGE RankNTypes   #-}
+{-# LANGUAGE BangPatterns     #-}
+{-# LANGUAGE CPP              #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE RankNTypes       #-}
 -- | A parse result type for parsers from AST to Haskell types.
 module Distribution.Parsec.ParseResult (
     ParseResult,
@@ -11,12 +12,22 @@
     parseFailure,
     parseFatalFailure,
     parseFatalFailure',
+    getCabalSpecVersion,
+    setCabalSpecVersion,
+    readAndParseFile,
+    parseString
     ) where
 
+import qualified Data.ByteString.Char8 as BS
 import Distribution.Compat.Prelude
 import Distribution.Parsec.Common
-       (PError (..), PWarnType (..), PWarning (..), Position (..), zeroPos)
+       ( PError (..), PWarnType (..), PWarning (..), Position (..), zeroPos
+       , showPWarning, showPError)
+import Distribution.Simple.Utils   (die', warn)
+import Distribution.Verbosity      (Verbosity)
+import Distribution.Version        (Version)
 import Prelude ()
+import System.Directory            (doesFileExist)
 
 #if MIN_VERSION_base(4,10,0)
 import Control.Applicative (Applicative (..))
@@ -26,25 +37,26 @@
 newtype ParseResult a = PR
     { unPR
         :: forall r. PRState
-        -> (PRState -> r)       -- failure
-        -> (PRState -> a -> r)  -- success
+        -> (PRState -> r) -- failure, but we were able to recover a new-style spec-version declaration
+        -> (PRState -> a -> r)             -- success
         -> r
     }
 
-data PRState = PRState ![PWarning] ![PError]
+data PRState = PRState ![PWarning] ![PError] !(Maybe Version)
 
 emptyPRState :: PRState
-emptyPRState = PRState [] []
+emptyPRState = PRState [] [] Nothing
 
--- | Destruct a 'ParseResult' into the emitted warnings and errors, and
--- possibly the final result if there were no errors.
-runParseResult :: ParseResult a -> ([PWarning], [PError], Maybe a)
+-- | Destruct a 'ParseResult' into the emitted warnings and either
+-- a successful value or
+-- list of errors and possibly recovered a spec-version declaration.
+runParseResult :: ParseResult a -> ([PWarning], Either (Maybe Version, [PError]) a)
 runParseResult pr = unPR pr emptyPRState failure success
   where
-    failure (PRState warns errs)   = (warns, errs, Nothing)
-    success (PRState warns [])   x = (warns, [], Just x)
+    failure (PRState warns errs v)   = (warns, Left (v, errs))
+    success (PRState warns [] _)   x = (warns, Right x)
     -- If there are any errors, don't return the result
-    success (PRState warns errs) _ = (warns, errs, Nothing)
+    success (PRState warns errs v) _ = (warns, Left (v, errs))
 
 instance Functor ParseResult where
     fmap f (PR pr) = PR $ \ !s failure success ->
@@ -96,33 +108,77 @@
 recoverWith (PR pr) x = PR $ \ !s _failure success ->
     pr s (\ !s' -> success s' x) success
 
+-- | Set cabal spec version.
+setCabalSpecVersion :: Maybe Version -> ParseResult ()
+setCabalSpecVersion v = PR $ \(PRState warns errs _) _failure success ->
+    success (PRState warns errs v) ()
+
+-- | Get cabal spec version.
+getCabalSpecVersion :: ParseResult (Maybe Version)
+getCabalSpecVersion = PR $ \s@(PRState _ _ v) _failure success ->
+    success s v
+
 -- | Add a warning. This doesn't fail the parsing process.
 parseWarning :: Position -> PWarnType -> String -> ParseResult ()
-parseWarning pos t msg = PR $ \(PRState warns errs) _failure success ->
-    success (PRState (PWarning t pos msg : warns) errs) ()
+parseWarning pos t msg = PR $ \(PRState warns errs v) _failure success ->
+    success (PRState (PWarning t pos msg : warns) errs v) ()
 
 -- | Add multiple warnings at once.
 parseWarnings :: [PWarning] -> ParseResult ()
-parseWarnings newWarns = PR $ \(PRState warns errs) _failure success ->
-    success (PRState (newWarns ++ warns) errs) ()
+parseWarnings newWarns = PR $ \(PRState warns errs v) _failure success ->
+    success (PRState (newWarns ++ warns) errs v) ()
 
 -- | Add an error, but not fail the parser yet.
 --
 -- For fatal failure use 'parseFatalFailure'
 parseFailure :: Position -> String -> ParseResult ()
-parseFailure pos msg = PR $ \(PRState warns errs) _failure success ->
-    success (PRState warns (PError pos msg : errs)) ()
+parseFailure pos msg = PR $ \(PRState warns errs v) _failure success ->
+    success (PRState warns (PError pos msg : errs) v) ()
 
 -- | Add an fatal error.
 parseFatalFailure :: Position -> String -> ParseResult a
-parseFatalFailure pos msg = PR $ \(PRState warns errs) failure _success ->
-    failure (PRState warns (PError pos msg : errs))
+parseFatalFailure pos msg = PR $ \(PRState warns errs v) failure _success ->
+    failure (PRState warns (PError pos msg : errs) v)
 
 -- | A 'mzero'.
 parseFatalFailure' :: ParseResult a
 parseFatalFailure' = PR pr
   where
-    pr (PRState warns []) failure _success = failure (PRState warns [err])
-    pr s                  failure _success = failure s
+    pr (PRState warns [] v) failure _success = failure (PRState warns [err] v)
+    pr s                    failure _success = failure s
 
     err = PError zeroPos "Unknown fatal error"
+
+-- | Helper combinator to do parsing plumbing for files.
+--
+-- Given a parser and a filename, return the parse of the file,
+-- after checking if the file exists.
+--
+-- Argument order is chosen to encourage partial application.
+readAndParseFile
+    :: (BS.ByteString -> ParseResult a)  -- ^ File contents to final value parser
+    -> Verbosity                         -- ^ Verbosity level
+    -> FilePath                          -- ^ File to read
+    -> IO a
+readAndParseFile parser verbosity fpath = do
+    exists <- doesFileExist fpath
+    unless exists $
+      die' verbosity $
+        "Error Parsing: file \"" ++ fpath ++ "\" doesn't exist. Cannot continue."
+    bs <- BS.readFile fpath
+    parseString parser verbosity fpath bs
+
+parseString
+    :: (BS.ByteString -> ParseResult a)  -- ^ File contents to final value parser
+    -> Verbosity                         -- ^ Verbosity level
+    -> String                            -- ^ File name
+    -> BS.ByteString
+    -> IO a
+parseString parser verbosity name bs = do
+    let (warnings, result) = runParseResult (parser bs)
+    traverse_ (warn verbosity . showPWarning name) warnings
+    case result of
+        Right x -> return x
+        Left (_, errors) -> do
+            traverse_ (warn verbosity . showPError name) errors
+            die' verbosity $ "Failed parsing \"" ++ name ++ "\"."
diff --git a/cabal/Cabal/Distribution/Parsec/Parser.hs b/cabal/Cabal/Distribution/Parsec/Parser.hs
--- a/cabal/Cabal/Distribution/Parsec/Parser.hs
+++ b/cabal/Cabal/Distribution/Parsec/Parser.hs
@@ -221,7 +221,7 @@
 
 -- An individual element, ie a field or a section. These can either use
 -- layout style or braces style. For layout style then it must start on
--- a line on it's own (so that we know its indentation level).
+-- a line on its own (so that we know its indentation level).
 --
 -- element ::= '\n' name elementInLayoutContext
 --           |      name elementInNonLayoutContext
diff --git a/cabal/Cabal/Distribution/PrettyUtils.hs b/cabal/Cabal/Distribution/PrettyUtils.hs
--- a/cabal/Cabal/Distribution/PrettyUtils.hs
+++ b/cabal/Cabal/Distribution/PrettyUtils.hs
@@ -9,7 +9,7 @@
 --
 -- Utilities for pretty printing.
 {-# OPTIONS_HADDOCK hide #-}
-module Distribution.PrettyUtils {-# DEPRECATED "Use Distribution.Pretty" #-} (
+module Distribution.PrettyUtils {-# DEPRECATED "Use Distribution.Pretty. This module will be removed in Cabal-3.0 (est. Mar 2019)." #-} (
     Separator,
     -- * Internal
     showFilePath,
diff --git a/cabal/Cabal/Distribution/ReadE.hs b/cabal/Cabal/Distribution/ReadE.hs
--- a/cabal/Cabal/Distribution/ReadE.hs
+++ b/cabal/Cabal/Distribution/ReadE.hs
@@ -18,11 +18,12 @@
    parsecToReadE,
   ) where
 
-import Prelude ()
 import Distribution.Compat.Prelude
+import Prelude ()
 
 import Distribution.Compat.ReadP
-import qualified Distribution.Compat.Parsec as P
+import Distribution.Parsec.Class
+import Distribution.Parsec.FieldLineStream
 
 -- | Parser with simple error reporting
 newtype ReadE a = ReadE {runReadE :: String -> Either ErrorMsg a}
@@ -47,7 +48,7 @@
 readEOrFail :: ReadE a -> String -> a
 readEOrFail r = either error id . runReadE r
 
--- {-# DEPRECATED readP_to_E "Use parsecToReadE" #-}
+-- {-# DEPRECATED readP_to_E "Use parsecToReadE. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 readP_to_E :: (String -> ErrorMsg) -> ReadP a a -> ReadE a
 readP_to_E err r =
     ReadE $ \txt -> case [ p | (p, s) <- readP_to_S r txt
@@ -55,9 +56,9 @@
                     of [] -> Left (err txt)
                        (p:_) -> Right p
 
-parsecToReadE :: (String -> ErrorMsg) -> P.Parsec String [w] a -> ReadE a
+parsecToReadE :: (String -> ErrorMsg) -> ParsecParser a -> ReadE a
 parsecToReadE err p = ReadE $ \txt ->
-    case P.runParser (p <* P.spaces <* P.eof) [] "<parsecToReadE>" txt of
+    case runParsecParser p "<parsecToReadE>" (fieldLineStreamFromString txt) of
         Right x -> Right x
         Left _e -> Left (err txt)
 -- TODO: use parsec error to make 'ErrorMsg'.
diff --git a/cabal/Cabal/Distribution/SPDX.hs b/cabal/Cabal/Distribution/SPDX.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/SPDX.hs
@@ -0,0 +1,40 @@
+-- | This module implements SPDX specification version 2.1 with a version 3.0 license list.
+--
+-- Specification is available on <https://spdx.org/specifications>
+module Distribution.SPDX (
+    -- * License
+    License (..),
+    -- * License expression
+    LicenseExpression (..),
+    SimpleLicenseExpression (..),
+    simpleLicenseExpression,
+    -- * License identifier
+    LicenseId (..),
+    licenseId,
+    licenseName,
+    licenseIsOsiApproved,
+    mkLicenseId,
+    licenseIdList,
+    -- * License exception
+    LicenseExceptionId (..),
+    licenseExceptionId,
+    licenseExceptionName,
+    mkLicenseExceptionId,
+    licenseExceptionIdList,
+    -- * License reference
+    LicenseRef,
+    licenseRef,
+    licenseDocumentRef,
+    mkLicenseRef,
+    mkLicenseRef',
+    -- * License list version
+    LicenseListVersion (..),
+    cabalSpecVersionToSPDXListVersion,
+    ) where
+
+import Distribution.SPDX.LicenseExceptionId
+import Distribution.SPDX.License
+import Distribution.SPDX.LicenseId
+import Distribution.SPDX.LicenseExpression
+import Distribution.SPDX.LicenseReference
+import Distribution.SPDX.LicenseListVersion
diff --git a/cabal/Cabal/Distribution/SPDX/License.hs b/cabal/Cabal/Distribution/SPDX/License.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/SPDX/License.hs
@@ -0,0 +1,64 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+module Distribution.SPDX.License (
+    License (..),
+    ) where
+
+import Prelude ()
+import Distribution.Compat.Prelude
+
+import Distribution.Pretty
+import Distribution.Parsec.Class
+import Distribution.SPDX.LicenseExpression
+
+import qualified Distribution.Compat.CharParsing as P
+import qualified Text.PrettyPrint as Disp
+
+-- | Declared license.
+-- See [section 3.15 of SPDX Specification 2.1](https://spdx.org/spdx-specification-21-web-version#h.1hmsyys)
+--
+-- /Note:/ the NOASSERTION case is omitted.
+--
+-- Old 'License' can be migrated using following rules:
+--
+-- * @AllRightsReserved@ and @UnspecifiedLicense@ to 'NONE'.
+--   No license specified which legally defaults to /All Rights Reserved/.
+--   The package may not be legally modified or redistributed by anyone but
+--   the rightsholder.
+--
+-- * @OtherLicense@ can be converted to 'LicenseRef' pointing to the file
+--   in the package.
+--
+-- * @UnknownLicense@ i.e. other licenses of the form @name-x.y@, should be
+--   covered by SPDX license list, otherwise use 'LicenseRef'.
+--
+-- * @PublicDomain@ isn't covered. Consider using CC0.
+--   See <https://wiki.spdx.org/view/Legal_Team/Decisions/Dealing_with_Public_Domain_within_SPDX_Files>
+--   for more information.
+--
+data License
+    = NONE
+      -- ^ if the package contains no license information whatsoever; or
+    | License LicenseExpression
+      -- ^ A valid SPDX License Expression as defined in Appendix IV.
+  deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)
+
+instance Binary License
+
+instance NFData License where
+    rnf NONE        = ()
+    rnf (License l) = rnf l
+
+instance Pretty License where
+    pretty NONE        = Disp.text "NONE"
+    pretty (License l) = pretty l
+
+-- |
+-- >>> eitherParsec "BSD-3-Clause AND MIT" :: Either String License
+-- Right (License (EAnd (ELicense (ELicenseId BSD_3_Clause) Nothing) (ELicense (ELicenseId MIT) Nothing)))
+--
+-- >>> eitherParsec "NONE" :: Either String License
+-- Right NONE
+--
+instance Parsec License where
+    parsec = NONE <$ P.try (P.string "NONE") <|> License <$> parsec
diff --git a/cabal/Cabal/Distribution/SPDX/LicenseExceptionId.hs b/cabal/Cabal/Distribution/SPDX/LicenseExceptionId.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/SPDX/LicenseExceptionId.hs
@@ -0,0 +1,213 @@
+-- This file is generated. See Makefile's spdx rule
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+module Distribution.SPDX.LicenseExceptionId (
+    LicenseExceptionId (..),
+    licenseExceptionId,
+    licenseExceptionName,
+    mkLicenseExceptionId,
+    licenseExceptionIdList,
+    ) where
+
+import Distribution.Compat.Prelude
+import Prelude ()
+
+import Distribution.Pretty
+import Distribution.Parsec.Class
+import Distribution.Utils.Generic (isAsciiAlphaNum)
+import Distribution.SPDX.LicenseListVersion
+
+import qualified Data.Map.Strict as Map
+import qualified Distribution.Compat.CharParsing as P
+import qualified Text.PrettyPrint as Disp
+
+-------------------------------------------------------------------------------
+-- LicenseExceptionId
+-------------------------------------------------------------------------------
+
+-- | SPDX License identifier
+data LicenseExceptionId
+    = DS389_exception -- ^ @389-exception@, 389 Directory Server Exception
+    | Autoconf_exception_2_0 -- ^ @Autoconf-exception-2.0@, Autoconf exception 2.0
+    | Autoconf_exception_3_0 -- ^ @Autoconf-exception-3.0@, Autoconf exception 3.0
+    | Bison_exception_2_2 -- ^ @Bison-exception-2.2@, Bison exception 2.2
+    | Bootloader_exception -- ^ @Bootloader-exception@, Bootloader Distribution Exception
+    | Classpath_exception_2_0 -- ^ @Classpath-exception-2.0@, Classpath exception 2.0
+    | CLISP_exception_2_0 -- ^ @CLISP-exception-2.0@, CLISP exception 2.0
+    | DigiRule_FOSS_exception -- ^ @DigiRule-FOSS-exception@, DigiRule FOSS License Exception
+    | ECos_exception_2_0 -- ^ @eCos-exception-2.0@, eCos exception 2.0
+    | Fawkes_Runtime_exception -- ^ @Fawkes-Runtime-exception@, Fawkes Runtime Exception
+    | FLTK_exception -- ^ @FLTK-exception@, FLTK exception
+    | Font_exception_2_0 -- ^ @Font-exception-2.0@, Font exception 2.0
+    | Freertos_exception_2_0 -- ^ @freertos-exception-2.0@, FreeRTOS Exception 2.0
+    | GCC_exception_2_0 -- ^ @GCC-exception-2.0@, GCC Runtime Library exception 2.0
+    | GCC_exception_3_1 -- ^ @GCC-exception-3.1@, GCC Runtime Library exception 3.1
+    | Gnu_javamail_exception -- ^ @gnu-javamail-exception@, GNU JavaMail exception
+    | I2p_gpl_java_exception -- ^ @i2p-gpl-java-exception@, i2p GPL+Java Exception
+    | Libtool_exception -- ^ @Libtool-exception@, Libtool Exception
+    | Linux_syscall_note -- ^ @Linux-syscall-note@, Linux Syscall Note
+    | LLVM_exception -- ^ @LLVM-exception@, LLVM Exception, SPDX License List 3.2
+    | LZMA_exception -- ^ @LZMA-exception@, LZMA exception
+    | Mif_exception -- ^ @mif-exception@, Macros and Inline Functions Exception
+    | Nokia_Qt_exception_1_1 -- ^ @Nokia-Qt-exception-1.1@, Nokia Qt LGPL exception 1.1
+    | OCCT_exception_1_0 -- ^ @OCCT-exception-1.0@, Open CASCADE Exception 1.0
+    | OpenJDK_assembly_exception_1_0 -- ^ @OpenJDK-assembly-exception-1.0@, OpenJDK Assembly exception 1.0, SPDX License List 3.2
+    | Openvpn_openssl_exception -- ^ @openvpn-openssl-exception@, OpenVPN OpenSSL Exception
+    | PS_or_PDF_font_exception_20170817 -- ^ @PS-or-PDF-font-exception-20170817@, PS/PDF font exception (2017-08-17), SPDX License List 3.2
+    | Qt_GPL_exception_1_0 -- ^ @Qt-GPL-exception-1.0@, Qt GPL exception 1.0, SPDX License List 3.2
+    | Qt_LGPL_exception_1_1 -- ^ @Qt-LGPL-exception-1.1@, Qt LGPL exception 1.1, SPDX License List 3.2
+    | Qwt_exception_1_0 -- ^ @Qwt-exception-1.0@, Qwt exception 1.0
+    | U_boot_exception_2_0 -- ^ @u-boot-exception-2.0@, U-Boot exception 2.0
+    | WxWindows_exception_3_1 -- ^ @WxWindows-exception-3.1@, WxWindows Library Exception 3.1
+  deriving (Eq, Ord, Enum, Bounded, Show, Read, Typeable, Data, Generic)
+
+instance Binary LicenseExceptionId
+
+instance Pretty LicenseExceptionId where
+    pretty = Disp.text . licenseExceptionId
+
+instance Parsec LicenseExceptionId where
+    parsec = do
+        n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'
+        v <- askCabalSpecVersion
+        maybe (fail $ "Unknown SPDX license exception identifier: " ++ n) return $
+            mkLicenseExceptionId (cabalSpecVersionToSPDXListVersion v) n
+
+instance NFData LicenseExceptionId where
+    rnf l = l `seq` ()
+
+-------------------------------------------------------------------------------
+-- License Data
+-------------------------------------------------------------------------------
+
+-- | License SPDX identifier, e.g. @"BSD-3-Clause"@.
+licenseExceptionId :: LicenseExceptionId -> String
+licenseExceptionId DS389_exception = "389-exception"
+licenseExceptionId Autoconf_exception_2_0 = "Autoconf-exception-2.0"
+licenseExceptionId Autoconf_exception_3_0 = "Autoconf-exception-3.0"
+licenseExceptionId Bison_exception_2_2 = "Bison-exception-2.2"
+licenseExceptionId Bootloader_exception = "Bootloader-exception"
+licenseExceptionId Classpath_exception_2_0 = "Classpath-exception-2.0"
+licenseExceptionId CLISP_exception_2_0 = "CLISP-exception-2.0"
+licenseExceptionId DigiRule_FOSS_exception = "DigiRule-FOSS-exception"
+licenseExceptionId ECos_exception_2_0 = "eCos-exception-2.0"
+licenseExceptionId Fawkes_Runtime_exception = "Fawkes-Runtime-exception"
+licenseExceptionId FLTK_exception = "FLTK-exception"
+licenseExceptionId Font_exception_2_0 = "Font-exception-2.0"
+licenseExceptionId Freertos_exception_2_0 = "freertos-exception-2.0"
+licenseExceptionId GCC_exception_2_0 = "GCC-exception-2.0"
+licenseExceptionId GCC_exception_3_1 = "GCC-exception-3.1"
+licenseExceptionId Gnu_javamail_exception = "gnu-javamail-exception"
+licenseExceptionId I2p_gpl_java_exception = "i2p-gpl-java-exception"
+licenseExceptionId Libtool_exception = "Libtool-exception"
+licenseExceptionId Linux_syscall_note = "Linux-syscall-note"
+licenseExceptionId LLVM_exception = "LLVM-exception"
+licenseExceptionId LZMA_exception = "LZMA-exception"
+licenseExceptionId Mif_exception = "mif-exception"
+licenseExceptionId Nokia_Qt_exception_1_1 = "Nokia-Qt-exception-1.1"
+licenseExceptionId OCCT_exception_1_0 = "OCCT-exception-1.0"
+licenseExceptionId OpenJDK_assembly_exception_1_0 = "OpenJDK-assembly-exception-1.0"
+licenseExceptionId Openvpn_openssl_exception = "openvpn-openssl-exception"
+licenseExceptionId PS_or_PDF_font_exception_20170817 = "PS-or-PDF-font-exception-20170817"
+licenseExceptionId Qt_GPL_exception_1_0 = "Qt-GPL-exception-1.0"
+licenseExceptionId Qt_LGPL_exception_1_1 = "Qt-LGPL-exception-1.1"
+licenseExceptionId Qwt_exception_1_0 = "Qwt-exception-1.0"
+licenseExceptionId U_boot_exception_2_0 = "u-boot-exception-2.0"
+licenseExceptionId WxWindows_exception_3_1 = "WxWindows-exception-3.1"
+
+-- | License name, e.g. @"GNU General Public License v2.0 only"@
+licenseExceptionName :: LicenseExceptionId -> String
+licenseExceptionName DS389_exception = "389 Directory Server Exception"
+licenseExceptionName Autoconf_exception_2_0 = "Autoconf exception 2.0"
+licenseExceptionName Autoconf_exception_3_0 = "Autoconf exception 3.0"
+licenseExceptionName Bison_exception_2_2 = "Bison exception 2.2"
+licenseExceptionName Bootloader_exception = "Bootloader Distribution Exception"
+licenseExceptionName Classpath_exception_2_0 = "Classpath exception 2.0"
+licenseExceptionName CLISP_exception_2_0 = "CLISP exception 2.0"
+licenseExceptionName DigiRule_FOSS_exception = "DigiRule FOSS License Exception"
+licenseExceptionName ECos_exception_2_0 = "eCos exception 2.0"
+licenseExceptionName Fawkes_Runtime_exception = "Fawkes Runtime Exception"
+licenseExceptionName FLTK_exception = "FLTK exception"
+licenseExceptionName Font_exception_2_0 = "Font exception 2.0"
+licenseExceptionName Freertos_exception_2_0 = "FreeRTOS Exception 2.0"
+licenseExceptionName GCC_exception_2_0 = "GCC Runtime Library exception 2.0"
+licenseExceptionName GCC_exception_3_1 = "GCC Runtime Library exception 3.1"
+licenseExceptionName Gnu_javamail_exception = "GNU JavaMail exception"
+licenseExceptionName I2p_gpl_java_exception = "i2p GPL+Java Exception"
+licenseExceptionName Libtool_exception = "Libtool Exception"
+licenseExceptionName Linux_syscall_note = "Linux Syscall Note"
+licenseExceptionName LLVM_exception = "LLVM Exception"
+licenseExceptionName LZMA_exception = "LZMA exception"
+licenseExceptionName Mif_exception = "Macros and Inline Functions Exception"
+licenseExceptionName Nokia_Qt_exception_1_1 = "Nokia Qt LGPL exception 1.1"
+licenseExceptionName OCCT_exception_1_0 = "Open CASCADE Exception 1.0"
+licenseExceptionName OpenJDK_assembly_exception_1_0 = "OpenJDK Assembly exception 1.0"
+licenseExceptionName Openvpn_openssl_exception = "OpenVPN OpenSSL Exception"
+licenseExceptionName PS_or_PDF_font_exception_20170817 = "PS/PDF font exception (2017-08-17)"
+licenseExceptionName Qt_GPL_exception_1_0 = "Qt GPL exception 1.0"
+licenseExceptionName Qt_LGPL_exception_1_1 = "Qt LGPL exception 1.1"
+licenseExceptionName Qwt_exception_1_0 = "Qwt exception 1.0"
+licenseExceptionName U_boot_exception_2_0 = "U-Boot exception 2.0"
+licenseExceptionName WxWindows_exception_3_1 = "WxWindows Library Exception 3.1"
+
+-------------------------------------------------------------------------------
+-- Creation
+-------------------------------------------------------------------------------
+
+licenseExceptionIdList :: LicenseListVersion -> [LicenseExceptionId]
+licenseExceptionIdList LicenseListVersion_3_0 =
+    []
+    ++ bulkOfLicenses
+licenseExceptionIdList LicenseListVersion_3_2 =
+    [ LLVM_exception
+    , OpenJDK_assembly_exception_1_0
+    , PS_or_PDF_font_exception_20170817
+    , Qt_GPL_exception_1_0
+    , Qt_LGPL_exception_1_1
+    ]
+    ++ bulkOfLicenses
+
+-- | Create a 'LicenseExceptionId' from a 'String'.
+mkLicenseExceptionId :: LicenseListVersion -> String -> Maybe LicenseExceptionId
+mkLicenseExceptionId LicenseListVersion_3_0 s = Map.lookup s stringLookup_3_0
+mkLicenseExceptionId LicenseListVersion_3_2 s = Map.lookup s stringLookup_3_2
+
+stringLookup_3_0 :: Map String LicenseExceptionId
+stringLookup_3_0 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $
+    licenseExceptionIdList LicenseListVersion_3_0
+
+stringLookup_3_2 :: Map String LicenseExceptionId
+stringLookup_3_2 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $
+    licenseExceptionIdList LicenseListVersion_3_2
+
+--  | License exceptions in all SPDX License lists
+bulkOfLicenses :: [LicenseExceptionId]
+bulkOfLicenses =
+    [ DS389_exception
+    , Autoconf_exception_2_0
+    , Autoconf_exception_3_0
+    , Bison_exception_2_2
+    , Bootloader_exception
+    , Classpath_exception_2_0
+    , CLISP_exception_2_0
+    , DigiRule_FOSS_exception
+    , ECos_exception_2_0
+    , Fawkes_Runtime_exception
+    , FLTK_exception
+    , Font_exception_2_0
+    , Freertos_exception_2_0
+    , GCC_exception_2_0
+    , GCC_exception_3_1
+    , Gnu_javamail_exception
+    , I2p_gpl_java_exception
+    , Libtool_exception
+    , Linux_syscall_note
+    , LZMA_exception
+    , Mif_exception
+    , Nokia_Qt_exception_1_1
+    , OCCT_exception_1_0
+    , Openvpn_openssl_exception
+    , Qwt_exception_1_0
+    , U_boot_exception_2_0
+    , WxWindows_exception_3_1
+    ]
diff --git a/cabal/Cabal/Distribution/SPDX/LicenseExpression.hs b/cabal/Cabal/Distribution/SPDX/LicenseExpression.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/SPDX/LicenseExpression.hs
@@ -0,0 +1,161 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+module Distribution.SPDX.LicenseExpression (
+    LicenseExpression (..),
+    SimpleLicenseExpression (..),
+    simpleLicenseExpression,
+    ) where
+
+import Distribution.Compat.Prelude
+import Prelude ()
+
+import Distribution.Parsec.Class
+import Distribution.Pretty
+import Distribution.SPDX.LicenseExceptionId
+import Distribution.SPDX.LicenseId
+import Distribution.SPDX.LicenseListVersion
+import Distribution.SPDX.LicenseReference
+import Distribution.Utils.Generic           (isAsciiAlphaNum)
+import Text.PrettyPrint                     ((<+>))
+
+import qualified Distribution.Compat.CharParsing as P
+import qualified Text.PrettyPrint                as Disp
+
+-- | SPDX License Expression.
+--
+-- @
+-- idstring              = 1*(ALPHA \/ DIGIT \/ "-" \/ "." )
+-- license id            = \<short form license identifier inAppendix I.1>
+-- license exception id  = \<short form license exception identifier inAppendix I.2>
+-- license ref           = [\"DocumentRef-"1*(idstring)":"]\"LicenseRef-"1*(idstring)
+--
+-- simple expression     = license id \/ license id"+" \/ license ref
+--
+-- compound expression   = 1*1(simple expression \/
+--                         simple expression \"WITH" license exception id \/
+--                         compound expression \"AND" compound expression \/
+--                         compound expression \"OR" compound expression ) \/
+--                         "(" compound expression ")" )
+--
+-- license expression    = 1*1(simple expression / compound expression)
+-- @
+data LicenseExpression
+    = ELicense !SimpleLicenseExpression !(Maybe LicenseExceptionId)
+    | EAnd !LicenseExpression !LicenseExpression
+    | EOr !LicenseExpression !LicenseExpression
+    deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)
+
+-- | Simple License Expressions.
+data SimpleLicenseExpression
+    = ELicenseId LicenseId
+      -- ^ An SPDX License List Short Form Identifier. For example: @GPL-2.0-only@
+    | ELicenseIdPlus LicenseId
+      -- ^ An SPDX License List Short Form Identifier with a unary"+" operator suffix to represent the current version of the license or any later version.  For example: @GPL-2.0+@
+    | ELicenseRef LicenseRef
+      -- ^ A SPDX user defined license reference: For example: @LicenseRef-23@, @LicenseRef-MIT-Style-1@, or @DocumentRef-spdx-tool-1.2:LicenseRef-MIT-Style-2@
+    deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)
+
+simpleLicenseExpression :: LicenseId -> LicenseExpression
+simpleLicenseExpression i = ELicense (ELicenseId i) Nothing
+
+instance Binary LicenseExpression
+instance Binary SimpleLicenseExpression
+
+instance Pretty LicenseExpression where
+    pretty = go 0
+      where
+        go :: Int -> LicenseExpression -> Disp.Doc
+        go _ (ELicense lic exc) =
+            let doc = pretty lic
+            in maybe id (\e d -> d <+> Disp.text "WITH" <+> pretty e) exc doc
+        go d (EAnd e1 e2) = parens (d < 0) $ go 0 e1 <+> Disp.text "AND" <+> go 0 e2
+        go d (EOr  e1 e2) = parens (d < 1) $ go 1 e1 <+> Disp.text "OR" <+> go 1 e2
+
+
+        parens False doc = doc
+        parens True  doc = Disp.parens doc
+
+instance Pretty SimpleLicenseExpression where
+    pretty (ELicenseId i)     = pretty i
+    pretty (ELicenseIdPlus i) = pretty i <<>> Disp.char '+'
+    pretty (ELicenseRef r)    = pretty r
+
+instance Parsec SimpleLicenseExpression where
+    parsec = idstring >>= simple where
+        simple n
+            | Just l <- "LicenseRef-" `isPrefixOfMaybe` n =
+                maybe (fail $ "Incorrect LicenseRef format: " ++ n) (return . ELicenseRef) $ mkLicenseRef Nothing l
+            | Just d <- "DocumentRef-" `isPrefixOfMaybe` n = do
+                _ <- P.string ":LicenseRef-"
+                l <- idstring
+                maybe (fail $ "Incorrect LicenseRef format:" ++ n) (return . ELicenseRef) $ mkLicenseRef (Just d) l
+            | otherwise = do
+                v <- askCabalSpecVersion
+                l <- maybe (fail $ "Unknown SPDX license identifier: '" ++  n ++ "' " ++ licenseIdMigrationMessage n) return $
+                    mkLicenseId (cabalSpecVersionToSPDXListVersion v) n
+                orLater <- isJust <$> P.optional (P.char '+')
+                if orLater
+                then return (ELicenseIdPlus l)
+                else return (ELicenseId l)
+
+idstring :: P.CharParsing m => m String
+idstring = P.munch1 $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'
+
+-- returns suffix part
+isPrefixOfMaybe :: Eq a => [a] -> [a] -> Maybe [a]
+isPrefixOfMaybe pfx s
+    | pfx `isPrefixOf` s = Just (drop (length pfx) s)
+    | otherwise          = Nothing
+
+instance Parsec LicenseExpression where
+    parsec = expr
+      where
+        expr = compoundOr
+
+        simple = do
+            s <- parsec
+            exc <- exception
+            return $ ELicense s exc
+
+        exception = P.optional $ P.try (spaces1 *> P.string "WITH" *> spaces1) *> parsec
+
+        compoundOr = do
+            x <- compoundAnd
+            l <- P.optional $ P.try (spaces1 *> P.string "OR" *> spaces1) *> compoundOr
+            return $ maybe id (flip EOr) l x
+
+        compoundAnd = do
+            x <- compound
+            l <- P.optional $ P.try (spaces1 *> P.string "AND" *> spaces1) *> compoundAnd
+            return $ maybe id (flip EAnd) l x
+
+        compound = braces <|> simple
+
+        -- NOTE: we require that there's a space around AND & OR operators,
+        -- i.e. @(MIT)AND(MIT)@ will cause parse-error.
+        braces = do
+            _ <- P.char '('
+            _ <- P.spaces
+            x <- expr
+            _ <- P.char ')'
+            return x
+
+        spaces1 = P.space *> P.spaces
+
+-- notes:
+--
+-- There MUST NOT be whitespace between a license­id and any following "+".  This supports easy parsing and
+-- backwards compatibility.  There MUST be whitespace on either side of the operator "WITH".  There MUST be
+-- whitespace and/or parentheses on either side of the operators "AND" and "OR".
+--
+-- We handle that by having greedy 'idstring' parser, so MITAND would parse as invalid license identifier.
+
+instance NFData LicenseExpression where
+    rnf (ELicense s e) = rnf s `seq` rnf e
+    rnf (EAnd x y)     = rnf x `seq` rnf y
+    rnf (EOr x y)      = rnf x `seq` rnf y
+
+instance NFData SimpleLicenseExpression where
+    rnf (ELicenseId i)     = rnf i
+    rnf (ELicenseIdPlus i) = rnf i
+    rnf (ELicenseRef r)    = rnf r
diff --git a/cabal/Cabal/Distribution/SPDX/LicenseId.hs b/cabal/Cabal/Distribution/SPDX/LicenseId.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/SPDX/LicenseId.hs
@@ -0,0 +1,1885 @@
+-- This file is generated. See Makefile's spdx rule
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+module Distribution.SPDX.LicenseId (
+    LicenseId (..),
+    licenseId,
+    licenseName,
+    licenseIsOsiApproved,
+    mkLicenseId,
+    licenseIdList,
+    -- * Helpers
+    licenseIdMigrationMessage,
+    ) where
+
+import Distribution.Compat.Prelude
+import Prelude ()
+
+import Distribution.Pretty
+import Distribution.Parsec.Class
+import Distribution.Utils.Generic (isAsciiAlphaNum)
+import Distribution.SPDX.LicenseListVersion
+
+import qualified Data.Map.Strict as Map
+import qualified Distribution.Compat.CharParsing as P
+import qualified Text.PrettyPrint as Disp
+
+-------------------------------------------------------------------------------
+-- LicenseId
+-------------------------------------------------------------------------------
+
+-- | SPDX License identifier
+data LicenseId
+    = NullBSD -- ^ @0BSD@, BSD Zero Clause License
+    | AAL -- ^ @AAL@, Attribution Assurance License
+    | Abstyles -- ^ @Abstyles@, Abstyles License
+    | Adobe_2006 -- ^ @Adobe-2006@, Adobe Systems Incorporated Source Code License Agreement
+    | Adobe_Glyph -- ^ @Adobe-Glyph@, Adobe Glyph List License
+    | ADSL -- ^ @ADSL@, Amazon Digital Services License
+    | AFL_1_1 -- ^ @AFL-1.1@, Academic Free License v1.1
+    | AFL_1_2 -- ^ @AFL-1.2@, Academic Free License v1.2
+    | AFL_2_0 -- ^ @AFL-2.0@, Academic Free License v2.0
+    | AFL_2_1 -- ^ @AFL-2.1@, Academic Free License v2.1
+    | AFL_3_0 -- ^ @AFL-3.0@, Academic Free License v3.0
+    | Afmparse -- ^ @Afmparse@, Afmparse License
+    | AGPL_1_0 -- ^ @AGPL-1.0@, Affero General Public License v1.0, SPDX License List 3.0
+    | AGPL_1_0_only -- ^ @AGPL-1.0-only@, Affero General Public License v1.0 only, SPDX License List 3.2
+    | AGPL_1_0_or_later -- ^ @AGPL-1.0-or-later@, Affero General Public License v1.0 or later, SPDX License List 3.2
+    | AGPL_3_0_only -- ^ @AGPL-3.0-only@, GNU Affero General Public License v3.0 only
+    | AGPL_3_0_or_later -- ^ @AGPL-3.0-or-later@, GNU Affero General Public License v3.0 or later
+    | Aladdin -- ^ @Aladdin@, Aladdin Free Public License
+    | AMDPLPA -- ^ @AMDPLPA@, AMD's plpa_map.c License
+    | AML -- ^ @AML@, Apple MIT License
+    | AMPAS -- ^ @AMPAS@, Academy of Motion Picture Arts and Sciences BSD
+    | ANTLR_PD -- ^ @ANTLR-PD@, ANTLR Software Rights Notice
+    | Apache_1_0 -- ^ @Apache-1.0@, Apache License 1.0
+    | Apache_1_1 -- ^ @Apache-1.1@, Apache License 1.1
+    | Apache_2_0 -- ^ @Apache-2.0@, Apache License 2.0
+    | APAFML -- ^ @APAFML@, Adobe Postscript AFM License
+    | APL_1_0 -- ^ @APL-1.0@, Adaptive Public License 1.0
+    | APSL_1_0 -- ^ @APSL-1.0@, Apple Public Source License 1.0
+    | APSL_1_1 -- ^ @APSL-1.1@, Apple Public Source License 1.1
+    | APSL_1_2 -- ^ @APSL-1.2@, Apple Public Source License 1.2
+    | APSL_2_0 -- ^ @APSL-2.0@, Apple Public Source License 2.0
+    | Artistic_1_0_cl8 -- ^ @Artistic-1.0-cl8@, Artistic License 1.0 w/clause 8
+    | Artistic_1_0_Perl -- ^ @Artistic-1.0-Perl@, Artistic License 1.0 (Perl)
+    | Artistic_1_0 -- ^ @Artistic-1.0@, Artistic License 1.0
+    | Artistic_2_0 -- ^ @Artistic-2.0@, Artistic License 2.0
+    | Bahyph -- ^ @Bahyph@, Bahyph License
+    | Barr -- ^ @Barr@, Barr License
+    | Beerware -- ^ @Beerware@, Beerware License
+    | BitTorrent_1_0 -- ^ @BitTorrent-1.0@, BitTorrent Open Source License v1.0
+    | BitTorrent_1_1 -- ^ @BitTorrent-1.1@, BitTorrent Open Source License v1.1
+    | Borceux -- ^ @Borceux@, Borceux license
+    | BSD_1_Clause -- ^ @BSD-1-Clause@, BSD 1-Clause License
+    | BSD_2_Clause_FreeBSD -- ^ @BSD-2-Clause-FreeBSD@, BSD 2-Clause FreeBSD License
+    | BSD_2_Clause_NetBSD -- ^ @BSD-2-Clause-NetBSD@, BSD 2-Clause NetBSD License
+    | BSD_2_Clause_Patent -- ^ @BSD-2-Clause-Patent@, BSD-2-Clause Plus Patent License
+    | BSD_2_Clause -- ^ @BSD-2-Clause@, BSD 2-Clause "Simplified" License
+    | BSD_3_Clause_Attribution -- ^ @BSD-3-Clause-Attribution@, BSD with attribution
+    | BSD_3_Clause_Clear -- ^ @BSD-3-Clause-Clear@, BSD 3-Clause Clear License
+    | BSD_3_Clause_LBNL -- ^ @BSD-3-Clause-LBNL@, Lawrence Berkeley National Labs BSD variant license
+    | BSD_3_Clause_No_Nuclear_License_2014 -- ^ @BSD-3-Clause-No-Nuclear-License-2014@, BSD 3-Clause No Nuclear License 2014
+    | BSD_3_Clause_No_Nuclear_License -- ^ @BSD-3-Clause-No-Nuclear-License@, BSD 3-Clause No Nuclear License
+    | BSD_3_Clause_No_Nuclear_Warranty -- ^ @BSD-3-Clause-No-Nuclear-Warranty@, BSD 3-Clause No Nuclear Warranty
+    | BSD_3_Clause -- ^ @BSD-3-Clause@, BSD 3-Clause "New" or "Revised" License
+    | BSD_4_Clause_UC -- ^ @BSD-4-Clause-UC@, BSD-4-Clause (University of California-Specific)
+    | BSD_4_Clause -- ^ @BSD-4-Clause@, BSD 4-Clause "Original" or "Old" License
+    | BSD_Protection -- ^ @BSD-Protection@, BSD Protection License
+    | BSD_Source_Code -- ^ @BSD-Source-Code@, BSD Source Code Attribution
+    | BSL_1_0 -- ^ @BSL-1.0@, Boost Software License 1.0
+    | Bzip2_1_0_5 -- ^ @bzip2-1.0.5@, bzip2 and libbzip2 License v1.0.5
+    | Bzip2_1_0_6 -- ^ @bzip2-1.0.6@, bzip2 and libbzip2 License v1.0.6
+    | Caldera -- ^ @Caldera@, Caldera License
+    | CATOSL_1_1 -- ^ @CATOSL-1.1@, Computer Associates Trusted Open Source License 1.1
+    | CC_BY_1_0 -- ^ @CC-BY-1.0@, Creative Commons Attribution 1.0 Generic
+    | CC_BY_2_0 -- ^ @CC-BY-2.0@, Creative Commons Attribution 2.0 Generic
+    | CC_BY_2_5 -- ^ @CC-BY-2.5@, Creative Commons Attribution 2.5 Generic
+    | CC_BY_3_0 -- ^ @CC-BY-3.0@, Creative Commons Attribution 3.0 Unported
+    | CC_BY_4_0 -- ^ @CC-BY-4.0@, Creative Commons Attribution 4.0 International
+    | CC_BY_NC_1_0 -- ^ @CC-BY-NC-1.0@, Creative Commons Attribution Non Commercial 1.0 Generic
+    | CC_BY_NC_2_0 -- ^ @CC-BY-NC-2.0@, Creative Commons Attribution Non Commercial 2.0 Generic
+    | CC_BY_NC_2_5 -- ^ @CC-BY-NC-2.5@, Creative Commons Attribution Non Commercial 2.5 Generic
+    | CC_BY_NC_3_0 -- ^ @CC-BY-NC-3.0@, Creative Commons Attribution Non Commercial 3.0 Unported
+    | CC_BY_NC_4_0 -- ^ @CC-BY-NC-4.0@, Creative Commons Attribution Non Commercial 4.0 International
+    | CC_BY_NC_ND_1_0 -- ^ @CC-BY-NC-ND-1.0@, Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic
+    | CC_BY_NC_ND_2_0 -- ^ @CC-BY-NC-ND-2.0@, Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic
+    | CC_BY_NC_ND_2_5 -- ^ @CC-BY-NC-ND-2.5@, Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic
+    | CC_BY_NC_ND_3_0 -- ^ @CC-BY-NC-ND-3.0@, Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported
+    | CC_BY_NC_ND_4_0 -- ^ @CC-BY-NC-ND-4.0@, Creative Commons Attribution Non Commercial No Derivatives 4.0 International
+    | CC_BY_NC_SA_1_0 -- ^ @CC-BY-NC-SA-1.0@, Creative Commons Attribution Non Commercial Share Alike 1.0 Generic
+    | CC_BY_NC_SA_2_0 -- ^ @CC-BY-NC-SA-2.0@, Creative Commons Attribution Non Commercial Share Alike 2.0 Generic
+    | CC_BY_NC_SA_2_5 -- ^ @CC-BY-NC-SA-2.5@, Creative Commons Attribution Non Commercial Share Alike 2.5 Generic
+    | CC_BY_NC_SA_3_0 -- ^ @CC-BY-NC-SA-3.0@, Creative Commons Attribution Non Commercial Share Alike 3.0 Unported
+    | CC_BY_NC_SA_4_0 -- ^ @CC-BY-NC-SA-4.0@, Creative Commons Attribution Non Commercial Share Alike 4.0 International
+    | CC_BY_ND_1_0 -- ^ @CC-BY-ND-1.0@, Creative Commons Attribution No Derivatives 1.0 Generic
+    | CC_BY_ND_2_0 -- ^ @CC-BY-ND-2.0@, Creative Commons Attribution No Derivatives 2.0 Generic
+    | CC_BY_ND_2_5 -- ^ @CC-BY-ND-2.5@, Creative Commons Attribution No Derivatives 2.5 Generic
+    | CC_BY_ND_3_0 -- ^ @CC-BY-ND-3.0@, Creative Commons Attribution No Derivatives 3.0 Unported
+    | CC_BY_ND_4_0 -- ^ @CC-BY-ND-4.0@, Creative Commons Attribution No Derivatives 4.0 International
+    | CC_BY_SA_1_0 -- ^ @CC-BY-SA-1.0@, Creative Commons Attribution Share Alike 1.0 Generic
+    | CC_BY_SA_2_0 -- ^ @CC-BY-SA-2.0@, Creative Commons Attribution Share Alike 2.0 Generic
+    | CC_BY_SA_2_5 -- ^ @CC-BY-SA-2.5@, Creative Commons Attribution Share Alike 2.5 Generic
+    | CC_BY_SA_3_0 -- ^ @CC-BY-SA-3.0@, Creative Commons Attribution Share Alike 3.0 Unported
+    | CC_BY_SA_4_0 -- ^ @CC-BY-SA-4.0@, Creative Commons Attribution Share Alike 4.0 International
+    | CC0_1_0 -- ^ @CC0-1.0@, Creative Commons Zero v1.0 Universal
+    | CDDL_1_0 -- ^ @CDDL-1.0@, Common Development and Distribution License 1.0
+    | CDDL_1_1 -- ^ @CDDL-1.1@, Common Development and Distribution License 1.1
+    | CDLA_Permissive_1_0 -- ^ @CDLA-Permissive-1.0@, Community Data License Agreement Permissive 1.0
+    | CDLA_Sharing_1_0 -- ^ @CDLA-Sharing-1.0@, Community Data License Agreement Sharing 1.0
+    | CECILL_1_0 -- ^ @CECILL-1.0@, CeCILL Free Software License Agreement v1.0
+    | CECILL_1_1 -- ^ @CECILL-1.1@, CeCILL Free Software License Agreement v1.1
+    | CECILL_2_0 -- ^ @CECILL-2.0@, CeCILL Free Software License Agreement v2.0
+    | CECILL_2_1 -- ^ @CECILL-2.1@, CeCILL Free Software License Agreement v2.1
+    | CECILL_B -- ^ @CECILL-B@, CeCILL-B Free Software License Agreement
+    | CECILL_C -- ^ @CECILL-C@, CeCILL-C Free Software License Agreement
+    | ClArtistic -- ^ @ClArtistic@, Clarified Artistic License
+    | CNRI_Jython -- ^ @CNRI-Jython@, CNRI Jython License
+    | CNRI_Python_GPL_Compatible -- ^ @CNRI-Python-GPL-Compatible@, CNRI Python Open Source GPL Compatible License Agreement
+    | CNRI_Python -- ^ @CNRI-Python@, CNRI Python License
+    | Condor_1_1 -- ^ @Condor-1.1@, Condor Public License v1.1
+    | CPAL_1_0 -- ^ @CPAL-1.0@, Common Public Attribution License 1.0
+    | CPL_1_0 -- ^ @CPL-1.0@, Common Public License 1.0
+    | CPOL_1_02 -- ^ @CPOL-1.02@, Code Project Open License 1.02
+    | Crossword -- ^ @Crossword@, Crossword License
+    | CrystalStacker -- ^ @CrystalStacker@, CrystalStacker License
+    | CUA_OPL_1_0 -- ^ @CUA-OPL-1.0@, CUA Office Public License v1.0
+    | Cube -- ^ @Cube@, Cube License
+    | Curl -- ^ @curl@, curl License
+    | D_FSL_1_0 -- ^ @D-FSL-1.0@, Deutsche Freie Software Lizenz
+    | Diffmark -- ^ @diffmark@, diffmark license
+    | DOC -- ^ @DOC@, DOC License
+    | Dotseqn -- ^ @Dotseqn@, Dotseqn License
+    | DSDP -- ^ @DSDP@, DSDP License
+    | Dvipdfm -- ^ @dvipdfm@, dvipdfm License
+    | ECL_1_0 -- ^ @ECL-1.0@, Educational Community License v1.0
+    | ECL_2_0 -- ^ @ECL-2.0@, Educational Community License v2.0
+    | EFL_1_0 -- ^ @EFL-1.0@, Eiffel Forum License v1.0
+    | EFL_2_0 -- ^ @EFL-2.0@, Eiffel Forum License v2.0
+    | EGenix -- ^ @eGenix@, eGenix.com Public License 1.1.0
+    | Entessa -- ^ @Entessa@, Entessa Public License v1.0
+    | EPL_1_0 -- ^ @EPL-1.0@, Eclipse Public License 1.0
+    | EPL_2_0 -- ^ @EPL-2.0@, Eclipse Public License 2.0
+    | ErlPL_1_1 -- ^ @ErlPL-1.1@, Erlang Public License v1.1
+    | EUDatagrid -- ^ @EUDatagrid@, EU DataGrid Software License
+    | EUPL_1_0 -- ^ @EUPL-1.0@, European Union Public License 1.0
+    | EUPL_1_1 -- ^ @EUPL-1.1@, European Union Public License 1.1
+    | EUPL_1_2 -- ^ @EUPL-1.2@, European Union Public License 1.2
+    | Eurosym -- ^ @Eurosym@, Eurosym License
+    | Fair -- ^ @Fair@, Fair License
+    | Frameworx_1_0 -- ^ @Frameworx-1.0@, Frameworx Open License 1.0
+    | FreeImage -- ^ @FreeImage@, FreeImage Public License v1.0
+    | FSFAP -- ^ @FSFAP@, FSF All Permissive License
+    | FSFUL -- ^ @FSFUL@, FSF Unlimited License
+    | FSFULLR -- ^ @FSFULLR@, FSF Unlimited License (with License Retention)
+    | FTL -- ^ @FTL@, Freetype Project License
+    | GFDL_1_1_only -- ^ @GFDL-1.1-only@, GNU Free Documentation License v1.1 only
+    | GFDL_1_1_or_later -- ^ @GFDL-1.1-or-later@, GNU Free Documentation License v1.1 or later
+    | GFDL_1_2_only -- ^ @GFDL-1.2-only@, GNU Free Documentation License v1.2 only
+    | GFDL_1_2_or_later -- ^ @GFDL-1.2-or-later@, GNU Free Documentation License v1.2 or later
+    | GFDL_1_3_only -- ^ @GFDL-1.3-only@, GNU Free Documentation License v1.3 only
+    | GFDL_1_3_or_later -- ^ @GFDL-1.3-or-later@, GNU Free Documentation License v1.3 or later
+    | Giftware -- ^ @Giftware@, Giftware License
+    | GL2PS -- ^ @GL2PS@, GL2PS License
+    | Glide -- ^ @Glide@, 3dfx Glide License
+    | Glulxe -- ^ @Glulxe@, Glulxe License
+    | Gnuplot -- ^ @gnuplot@, gnuplot License
+    | GPL_1_0_only -- ^ @GPL-1.0-only@, GNU General Public License v1.0 only
+    | GPL_1_0_or_later -- ^ @GPL-1.0-or-later@, GNU General Public License v1.0 or later
+    | GPL_2_0_only -- ^ @GPL-2.0-only@, GNU General Public License v2.0 only
+    | GPL_2_0_or_later -- ^ @GPL-2.0-or-later@, GNU General Public License v2.0 or later
+    | GPL_3_0_only -- ^ @GPL-3.0-only@, GNU General Public License v3.0 only
+    | GPL_3_0_or_later -- ^ @GPL-3.0-or-later@, GNU General Public License v3.0 or later
+    | GSOAP_1_3b -- ^ @gSOAP-1.3b@, gSOAP Public License v1.3b
+    | HaskellReport -- ^ @HaskellReport@, Haskell Language Report License
+    | HPND -- ^ @HPND@, Historical Permission Notice and Disclaimer
+    | IBM_pibs -- ^ @IBM-pibs@, IBM PowerPC Initialization and Boot Software
+    | ICU -- ^ @ICU@, ICU License
+    | IJG -- ^ @IJG@, Independent JPEG Group License
+    | ImageMagick -- ^ @ImageMagick@, ImageMagick License
+    | IMatix -- ^ @iMatix@, iMatix Standard Function Library Agreement
+    | Imlib2 -- ^ @Imlib2@, Imlib2 License
+    | Info_ZIP -- ^ @Info-ZIP@, Info-ZIP License
+    | Intel_ACPI -- ^ @Intel-ACPI@, Intel ACPI Software License Agreement
+    | Intel -- ^ @Intel@, Intel Open Source License
+    | Interbase_1_0 -- ^ @Interbase-1.0@, Interbase Public License v1.0
+    | IPA -- ^ @IPA@, IPA Font License
+    | IPL_1_0 -- ^ @IPL-1.0@, IBM Public License v1.0
+    | ISC -- ^ @ISC@, ISC License
+    | JasPer_2_0 -- ^ @JasPer-2.0@, JasPer License
+    | JSON -- ^ @JSON@, JSON License
+    | LAL_1_2 -- ^ @LAL-1.2@, Licence Art Libre 1.2
+    | LAL_1_3 -- ^ @LAL-1.3@, Licence Art Libre 1.3
+    | Latex2e -- ^ @Latex2e@, Latex2e License
+    | Leptonica -- ^ @Leptonica@, Leptonica License
+    | LGPL_2_0_only -- ^ @LGPL-2.0-only@, GNU Library General Public License v2 only
+    | LGPL_2_0_or_later -- ^ @LGPL-2.0-or-later@, GNU Library General Public License v2 or later
+    | LGPL_2_1_only -- ^ @LGPL-2.1-only@, GNU Lesser General Public License v2.1 only
+    | LGPL_2_1_or_later -- ^ @LGPL-2.1-or-later@, GNU Lesser General Public License v2.1 or later
+    | LGPL_3_0_only -- ^ @LGPL-3.0-only@, GNU Lesser General Public License v3.0 only
+    | LGPL_3_0_or_later -- ^ @LGPL-3.0-or-later@, GNU Lesser General Public License v3.0 or later
+    | LGPLLR -- ^ @LGPLLR@, Lesser General Public License For Linguistic Resources
+    | Libpng -- ^ @Libpng@, libpng License
+    | Libtiff -- ^ @libtiff@, libtiff License
+    | LiLiQ_P_1_1 -- ^ @LiLiQ-P-1.1@, Licence Libre du Québec – Permissive version 1.1
+    | LiLiQ_R_1_1 -- ^ @LiLiQ-R-1.1@, Licence Libre du Québec – Réciprocité version 1.1
+    | LiLiQ_Rplus_1_1 -- ^ @LiLiQ-Rplus-1.1@, Licence Libre du Québec – Réciprocité forte version 1.1
+    | Linux_OpenIB -- ^ @Linux-OpenIB@, Linux Kernel Variant of OpenIB.org license, SPDX License List 3.2
+    | LPL_1_0 -- ^ @LPL-1.0@, Lucent Public License Version 1.0
+    | LPL_1_02 -- ^ @LPL-1.02@, Lucent Public License v1.02
+    | LPPL_1_0 -- ^ @LPPL-1.0@, LaTeX Project Public License v1.0
+    | LPPL_1_1 -- ^ @LPPL-1.1@, LaTeX Project Public License v1.1
+    | LPPL_1_2 -- ^ @LPPL-1.2@, LaTeX Project Public License v1.2
+    | LPPL_1_3a -- ^ @LPPL-1.3a@, LaTeX Project Public License v1.3a
+    | LPPL_1_3c -- ^ @LPPL-1.3c@, LaTeX Project Public License v1.3c
+    | MakeIndex -- ^ @MakeIndex@, MakeIndex License
+    | MirOS -- ^ @MirOS@, MirOS License
+    | MIT_0 -- ^ @MIT-0@, MIT No Attribution, SPDX License List 3.2
+    | MIT_advertising -- ^ @MIT-advertising@, Enlightenment License (e16)
+    | MIT_CMU -- ^ @MIT-CMU@, CMU License
+    | MIT_enna -- ^ @MIT-enna@, enna License
+    | MIT_feh -- ^ @MIT-feh@, feh License
+    | MIT -- ^ @MIT@, MIT License
+    | MITNFA -- ^ @MITNFA@, MIT +no-false-attribs license
+    | Motosoto -- ^ @Motosoto@, Motosoto License
+    | Mpich2 -- ^ @mpich2@, mpich2 License
+    | MPL_1_0 -- ^ @MPL-1.0@, Mozilla Public License 1.0
+    | MPL_1_1 -- ^ @MPL-1.1@, Mozilla Public License 1.1
+    | MPL_2_0_no_copyleft_exception -- ^ @MPL-2.0-no-copyleft-exception@, Mozilla Public License 2.0 (no copyleft exception)
+    | MPL_2_0 -- ^ @MPL-2.0@, Mozilla Public License 2.0
+    | MS_PL -- ^ @MS-PL@, Microsoft Public License
+    | MS_RL -- ^ @MS-RL@, Microsoft Reciprocal License
+    | MTLL -- ^ @MTLL@, Matrix Template Library License
+    | Multics -- ^ @Multics@, Multics License
+    | Mup -- ^ @Mup@, Mup License
+    | NASA_1_3 -- ^ @NASA-1.3@, NASA Open Source Agreement 1.3
+    | Naumen -- ^ @Naumen@, Naumen Public License
+    | NBPL_1_0 -- ^ @NBPL-1.0@, Net Boolean Public License v1
+    | NCSA -- ^ @NCSA@, University of Illinois/NCSA Open Source License
+    | Net_SNMP -- ^ @Net-SNMP@, Net-SNMP License
+    | NetCDF -- ^ @NetCDF@, NetCDF license
+    | Newsletr -- ^ @Newsletr@, Newsletr License
+    | NGPL -- ^ @NGPL@, Nethack General Public License
+    | NLOD_1_0 -- ^ @NLOD-1.0@, Norwegian Licence for Open Government Data
+    | NLPL -- ^ @NLPL@, No Limit Public License
+    | Nokia -- ^ @Nokia@, Nokia Open Source License
+    | NOSL -- ^ @NOSL@, Netizen Open Source License
+    | Noweb -- ^ @Noweb@, Noweb License
+    | NPL_1_0 -- ^ @NPL-1.0@, Netscape Public License v1.0
+    | NPL_1_1 -- ^ @NPL-1.1@, Netscape Public License v1.1
+    | NPOSL_3_0 -- ^ @NPOSL-3.0@, Non-Profit Open Software License 3.0
+    | NRL -- ^ @NRL@, NRL License
+    | NTP -- ^ @NTP@, NTP License
+    | OCCT_PL -- ^ @OCCT-PL@, Open CASCADE Technology Public License
+    | OCLC_2_0 -- ^ @OCLC-2.0@, OCLC Research Public License 2.0
+    | ODbL_1_0 -- ^ @ODbL-1.0@, ODC Open Database License v1.0
+    | ODC_By_1_0 -- ^ @ODC-By-1.0@, Open Data Commons Attribution License v1.0, SPDX License List 3.2
+    | OFL_1_0 -- ^ @OFL-1.0@, SIL Open Font License 1.0
+    | OFL_1_1 -- ^ @OFL-1.1@, SIL Open Font License 1.1
+    | OGTSL -- ^ @OGTSL@, Open Group Test Suite License
+    | OLDAP_1_1 -- ^ @OLDAP-1.1@, Open LDAP Public License v1.1
+    | OLDAP_1_2 -- ^ @OLDAP-1.2@, Open LDAP Public License v1.2
+    | OLDAP_1_3 -- ^ @OLDAP-1.3@, Open LDAP Public License v1.3
+    | OLDAP_1_4 -- ^ @OLDAP-1.4@, Open LDAP Public License v1.4
+    | OLDAP_2_0_1 -- ^ @OLDAP-2.0.1@, Open LDAP Public License v2.0.1
+    | OLDAP_2_0 -- ^ @OLDAP-2.0@, Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)
+    | OLDAP_2_1 -- ^ @OLDAP-2.1@, Open LDAP Public License v2.1
+    | OLDAP_2_2_1 -- ^ @OLDAP-2.2.1@, Open LDAP Public License v2.2.1
+    | OLDAP_2_2_2 -- ^ @OLDAP-2.2.2@, Open LDAP Public License 2.2.2
+    | OLDAP_2_2 -- ^ @OLDAP-2.2@, Open LDAP Public License v2.2
+    | OLDAP_2_3 -- ^ @OLDAP-2.3@, Open LDAP Public License v2.3
+    | OLDAP_2_4 -- ^ @OLDAP-2.4@, Open LDAP Public License v2.4
+    | OLDAP_2_5 -- ^ @OLDAP-2.5@, Open LDAP Public License v2.5
+    | OLDAP_2_6 -- ^ @OLDAP-2.6@, Open LDAP Public License v2.6
+    | OLDAP_2_7 -- ^ @OLDAP-2.7@, Open LDAP Public License v2.7
+    | OLDAP_2_8 -- ^ @OLDAP-2.8@, Open LDAP Public License v2.8
+    | OML -- ^ @OML@, Open Market License
+    | OpenSSL -- ^ @OpenSSL@, OpenSSL License
+    | OPL_1_0 -- ^ @OPL-1.0@, Open Public License v1.0
+    | OSET_PL_2_1 -- ^ @OSET-PL-2.1@, OSET Public License version 2.1
+    | OSL_1_0 -- ^ @OSL-1.0@, Open Software License 1.0
+    | OSL_1_1 -- ^ @OSL-1.1@, Open Software License 1.1
+    | OSL_2_0 -- ^ @OSL-2.0@, Open Software License 2.0
+    | OSL_2_1 -- ^ @OSL-2.1@, Open Software License 2.1
+    | OSL_3_0 -- ^ @OSL-3.0@, Open Software License 3.0
+    | PDDL_1_0 -- ^ @PDDL-1.0@, ODC Public Domain Dedication & License 1.0
+    | PHP_3_0 -- ^ @PHP-3.0@, PHP License v3.0
+    | PHP_3_01 -- ^ @PHP-3.01@, PHP License v3.01
+    | Plexus -- ^ @Plexus@, Plexus Classworlds License
+    | PostgreSQL -- ^ @PostgreSQL@, PostgreSQL License
+    | Psfrag -- ^ @psfrag@, psfrag License
+    | Psutils -- ^ @psutils@, psutils License
+    | Python_2_0 -- ^ @Python-2.0@, Python License 2.0
+    | Qhull -- ^ @Qhull@, Qhull License
+    | QPL_1_0 -- ^ @QPL-1.0@, Q Public License 1.0
+    | Rdisc -- ^ @Rdisc@, Rdisc License
+    | RHeCos_1_1 -- ^ @RHeCos-1.1@, Red Hat eCos Public License v1.1
+    | RPL_1_1 -- ^ @RPL-1.1@, Reciprocal Public License 1.1
+    | RPL_1_5 -- ^ @RPL-1.5@, Reciprocal Public License 1.5
+    | RPSL_1_0 -- ^ @RPSL-1.0@, RealNetworks Public Source License v1.0
+    | RSA_MD -- ^ @RSA-MD@, RSA Message-Digest License 
+    | RSCPL -- ^ @RSCPL@, Ricoh Source Code Public License
+    | Ruby -- ^ @Ruby@, Ruby License
+    | SAX_PD -- ^ @SAX-PD@, Sax Public Domain Notice
+    | Saxpath -- ^ @Saxpath@, Saxpath License
+    | SCEA -- ^ @SCEA@, SCEA Shared Source License
+    | Sendmail -- ^ @Sendmail@, Sendmail License
+    | SGI_B_1_0 -- ^ @SGI-B-1.0@, SGI Free Software License B v1.0
+    | SGI_B_1_1 -- ^ @SGI-B-1.1@, SGI Free Software License B v1.1
+    | SGI_B_2_0 -- ^ @SGI-B-2.0@, SGI Free Software License B v2.0
+    | SimPL_2_0 -- ^ @SimPL-2.0@, Simple Public License 2.0
+    | SISSL_1_2 -- ^ @SISSL-1.2@, Sun Industry Standards Source License v1.2
+    | SISSL -- ^ @SISSL@, Sun Industry Standards Source License v1.1
+    | Sleepycat -- ^ @Sleepycat@, Sleepycat License
+    | SMLNJ -- ^ @SMLNJ@, Standard ML of New Jersey License
+    | SMPPL -- ^ @SMPPL@, Secure Messaging Protocol Public License
+    | SNIA -- ^ @SNIA@, SNIA Public License 1.1
+    | Spencer_86 -- ^ @Spencer-86@, Spencer License 86
+    | Spencer_94 -- ^ @Spencer-94@, Spencer License 94
+    | Spencer_99 -- ^ @Spencer-99@, Spencer License 99
+    | SPL_1_0 -- ^ @SPL-1.0@, Sun Public License v1.0
+    | SugarCRM_1_1_3 -- ^ @SugarCRM-1.1.3@, SugarCRM Public License v1.1.3
+    | SWL -- ^ @SWL@, Scheme Widget Library (SWL) Software License Agreement
+    | TCL -- ^ @TCL@, TCL/TK License
+    | TCP_wrappers -- ^ @TCP-wrappers@, TCP Wrappers License
+    | TMate -- ^ @TMate@, TMate Open Source License
+    | TORQUE_1_1 -- ^ @TORQUE-1.1@, TORQUE v2.5+ Software License v1.1
+    | TOSL -- ^ @TOSL@, Trusster Open Source License
+    | TU_Berlin_1_0 -- ^ @TU-Berlin-1.0@, Technische Universitaet Berlin License 1.0, SPDX License List 3.2
+    | TU_Berlin_2_0 -- ^ @TU-Berlin-2.0@, Technische Universitaet Berlin License 2.0, SPDX License List 3.2
+    | Unicode_DFS_2015 -- ^ @Unicode-DFS-2015@, Unicode License Agreement - Data Files and Software (2015)
+    | Unicode_DFS_2016 -- ^ @Unicode-DFS-2016@, Unicode License Agreement - Data Files and Software (2016)
+    | Unicode_TOU -- ^ @Unicode-TOU@, Unicode Terms of Use
+    | Unlicense -- ^ @Unlicense@, The Unlicense
+    | UPL_1_0 -- ^ @UPL-1.0@, Universal Permissive License v1.0
+    | Vim -- ^ @Vim@, Vim License
+    | VOSTROM -- ^ @VOSTROM@, VOSTROM Public License for Open Source
+    | VSL_1_0 -- ^ @VSL-1.0@, Vovida Software License v1.0
+    | W3C_19980720 -- ^ @W3C-19980720@, W3C Software Notice and License (1998-07-20)
+    | W3C_20150513 -- ^ @W3C-20150513@, W3C Software Notice and Document License (2015-05-13)
+    | W3C -- ^ @W3C@, W3C Software Notice and License (2002-12-31)
+    | Watcom_1_0 -- ^ @Watcom-1.0@, Sybase Open Watcom Public License 1.0
+    | Wsuipa -- ^ @Wsuipa@, Wsuipa License
+    | WTFPL -- ^ @WTFPL@, Do What The F*ck You Want To Public License
+    | X11 -- ^ @X11@, X11 License
+    | Xerox -- ^ @Xerox@, Xerox License
+    | XFree86_1_1 -- ^ @XFree86-1.1@, XFree86 License 1.1
+    | Xinetd -- ^ @xinetd@, xinetd License
+    | Xnet -- ^ @Xnet@, X.Net License
+    | Xpp -- ^ @xpp@, XPP License
+    | XSkat -- ^ @XSkat@, XSkat License
+    | YPL_1_0 -- ^ @YPL-1.0@, Yahoo! Public License v1.0
+    | YPL_1_1 -- ^ @YPL-1.1@, Yahoo! Public License v1.1
+    | Zed -- ^ @Zed@, Zed License
+    | Zend_2_0 -- ^ @Zend-2.0@, Zend License v2.0
+    | Zimbra_1_3 -- ^ @Zimbra-1.3@, Zimbra Public License v1.3
+    | Zimbra_1_4 -- ^ @Zimbra-1.4@, Zimbra Public License v1.4
+    | Zlib_acknowledgement -- ^ @zlib-acknowledgement@, zlib/libpng License with Acknowledgement
+    | Zlib -- ^ @Zlib@, zlib License
+    | ZPL_1_1 -- ^ @ZPL-1.1@, Zope Public License 1.1
+    | ZPL_2_0 -- ^ @ZPL-2.0@, Zope Public License 2.0
+    | ZPL_2_1 -- ^ @ZPL-2.1@, Zope Public License 2.1
+  deriving (Eq, Ord, Enum, Bounded, Show, Read, Typeable, Data, Generic)
+
+instance Binary LicenseId
+
+instance Pretty LicenseId where
+    pretty = Disp.text . licenseId
+
+-- |
+-- >>> eitherParsec "BSD-3-Clause" :: Either String LicenseId
+-- Right BSD_3_Clause
+--
+-- >>> eitherParsec "BSD3" :: Either String LicenseId
+-- Left "...Unknown SPDX license identifier: 'BSD3' Do you mean BSD-3-Clause?"
+--
+instance Parsec LicenseId where
+    parsec = do
+        n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'
+        v <- askCabalSpecVersion
+        maybe (fail $ "Unknown SPDX license identifier: '" ++  n ++ "' " ++ licenseIdMigrationMessage n) return $
+            mkLicenseId (cabalSpecVersionToSPDXListVersion v) n
+
+instance NFData LicenseId where
+    rnf l = l `seq` ()
+
+-- | Help message for migrating from non-SPDX license identifiers.
+--
+-- Old 'License' is almost SPDX, except for 'BSD2', 'BSD3'. This function
+-- suggests SPDX variant:
+--
+-- >>> licenseIdMigrationMessage "BSD3"
+-- "Do you mean BSD-3-Clause?"
+--
+-- Also 'OtherLicense', 'AllRightsReserved', and 'PublicDomain' aren't
+-- valid SPDX identifiers
+--
+-- >>> traverse_ (print . licenseIdMigrationMessage) [ "OtherLicense", "AllRightsReserved", "PublicDomain" ]
+-- "SPDX license list contains plenty of licenses. See https://spdx.org/licenses/. Also they can be combined into complex expressions with AND and OR."
+-- "You can use NONE as a value of license field."
+-- "Public Domain is a complex matter. See https://wiki.spdx.org/view/Legal_Team/Decisions/Dealing_with_Public_Domain_within_SPDX_Files. Consider using a proper license."
+--
+-- SPDX License list version 3.0 introduced "-only" and "-or-later" variants for GNU family of licenses.
+-- See <https://spdx.org/news/news/2018/01/license-list-30-released>
+-- >>> licenseIdMigrationMessage "GPL-2.0"
+-- "SPDX license list 3.0 deprecated suffixless variants of GNU family of licenses. Use GPL-2.0-only or GPL-2.0-or-later."
+--
+-- For other common licenses their old license format coincides with the SPDX identifiers:
+--
+-- >>> traverse eitherParsec ["GPL-2.0-only", "GPL-3.0-only", "LGPL-2.1-only", "MIT", "ISC", "MPL-2.0", "Apache-2.0"] :: Either String [LicenseId]
+-- Right [GPL_2_0_only,GPL_3_0_only,LGPL_2_1_only,MIT,ISC,MPL_2_0,Apache_2_0]
+--
+licenseIdMigrationMessage :: String -> String
+licenseIdMigrationMessage = go where
+    go l | gnuVariant l    = "SPDX license list 3.0 deprecated suffixless variants of GNU family of licenses. Use " ++ l ++ "-only or " ++ l ++ "-or-later."
+    go "BSD3"              = "Do you mean BSD-3-Clause?"
+    go "BSD2"              = "Do you mean BSD-2-Clause?"
+    go "AllRightsReserved" = "You can use NONE as a value of license field."
+    go "OtherLicense"      = "SPDX license list contains plenty of licenses. See https://spdx.org/licenses/. Also they can be combined into complex expressions with AND and OR."
+    go "PublicDomain"      = "Public Domain is a complex matter. See https://wiki.spdx.org/view/Legal_Team/Decisions/Dealing_with_Public_Domain_within_SPDX_Files. Consider using a proper license."
+
+    -- otherwise, we don't know
+    go _ = ""
+
+    gnuVariant = flip elem ["GPL-2.0", "GPL-3.0", "LGPL-2.1", "LGPL-3.0", "AGPL-3.0" ]
+
+-------------------------------------------------------------------------------
+-- License Data
+-------------------------------------------------------------------------------
+
+-- | License SPDX identifier, e.g. @"BSD-3-Clause"@.
+licenseId :: LicenseId -> String
+licenseId NullBSD = "0BSD"
+licenseId AAL = "AAL"
+licenseId Abstyles = "Abstyles"
+licenseId Adobe_2006 = "Adobe-2006"
+licenseId Adobe_Glyph = "Adobe-Glyph"
+licenseId ADSL = "ADSL"
+licenseId AFL_1_1 = "AFL-1.1"
+licenseId AFL_1_2 = "AFL-1.2"
+licenseId AFL_2_0 = "AFL-2.0"
+licenseId AFL_2_1 = "AFL-2.1"
+licenseId AFL_3_0 = "AFL-3.0"
+licenseId Afmparse = "Afmparse"
+licenseId AGPL_1_0 = "AGPL-1.0"
+licenseId AGPL_1_0_only = "AGPL-1.0-only"
+licenseId AGPL_1_0_or_later = "AGPL-1.0-or-later"
+licenseId AGPL_3_0_only = "AGPL-3.0-only"
+licenseId AGPL_3_0_or_later = "AGPL-3.0-or-later"
+licenseId Aladdin = "Aladdin"
+licenseId AMDPLPA = "AMDPLPA"
+licenseId AML = "AML"
+licenseId AMPAS = "AMPAS"
+licenseId ANTLR_PD = "ANTLR-PD"
+licenseId Apache_1_0 = "Apache-1.0"
+licenseId Apache_1_1 = "Apache-1.1"
+licenseId Apache_2_0 = "Apache-2.0"
+licenseId APAFML = "APAFML"
+licenseId APL_1_0 = "APL-1.0"
+licenseId APSL_1_0 = "APSL-1.0"
+licenseId APSL_1_1 = "APSL-1.1"
+licenseId APSL_1_2 = "APSL-1.2"
+licenseId APSL_2_0 = "APSL-2.0"
+licenseId Artistic_1_0_cl8 = "Artistic-1.0-cl8"
+licenseId Artistic_1_0_Perl = "Artistic-1.0-Perl"
+licenseId Artistic_1_0 = "Artistic-1.0"
+licenseId Artistic_2_0 = "Artistic-2.0"
+licenseId Bahyph = "Bahyph"
+licenseId Barr = "Barr"
+licenseId Beerware = "Beerware"
+licenseId BitTorrent_1_0 = "BitTorrent-1.0"
+licenseId BitTorrent_1_1 = "BitTorrent-1.1"
+licenseId Borceux = "Borceux"
+licenseId BSD_1_Clause = "BSD-1-Clause"
+licenseId BSD_2_Clause_FreeBSD = "BSD-2-Clause-FreeBSD"
+licenseId BSD_2_Clause_NetBSD = "BSD-2-Clause-NetBSD"
+licenseId BSD_2_Clause_Patent = "BSD-2-Clause-Patent"
+licenseId BSD_2_Clause = "BSD-2-Clause"
+licenseId BSD_3_Clause_Attribution = "BSD-3-Clause-Attribution"
+licenseId BSD_3_Clause_Clear = "BSD-3-Clause-Clear"
+licenseId BSD_3_Clause_LBNL = "BSD-3-Clause-LBNL"
+licenseId BSD_3_Clause_No_Nuclear_License_2014 = "BSD-3-Clause-No-Nuclear-License-2014"
+licenseId BSD_3_Clause_No_Nuclear_License = "BSD-3-Clause-No-Nuclear-License"
+licenseId BSD_3_Clause_No_Nuclear_Warranty = "BSD-3-Clause-No-Nuclear-Warranty"
+licenseId BSD_3_Clause = "BSD-3-Clause"
+licenseId BSD_4_Clause_UC = "BSD-4-Clause-UC"
+licenseId BSD_4_Clause = "BSD-4-Clause"
+licenseId BSD_Protection = "BSD-Protection"
+licenseId BSD_Source_Code = "BSD-Source-Code"
+licenseId BSL_1_0 = "BSL-1.0"
+licenseId Bzip2_1_0_5 = "bzip2-1.0.5"
+licenseId Bzip2_1_0_6 = "bzip2-1.0.6"
+licenseId Caldera = "Caldera"
+licenseId CATOSL_1_1 = "CATOSL-1.1"
+licenseId CC_BY_1_0 = "CC-BY-1.0"
+licenseId CC_BY_2_0 = "CC-BY-2.0"
+licenseId CC_BY_2_5 = "CC-BY-2.5"
+licenseId CC_BY_3_0 = "CC-BY-3.0"
+licenseId CC_BY_4_0 = "CC-BY-4.0"
+licenseId CC_BY_NC_1_0 = "CC-BY-NC-1.0"
+licenseId CC_BY_NC_2_0 = "CC-BY-NC-2.0"
+licenseId CC_BY_NC_2_5 = "CC-BY-NC-2.5"
+licenseId CC_BY_NC_3_0 = "CC-BY-NC-3.0"
+licenseId CC_BY_NC_4_0 = "CC-BY-NC-4.0"
+licenseId CC_BY_NC_ND_1_0 = "CC-BY-NC-ND-1.0"
+licenseId CC_BY_NC_ND_2_0 = "CC-BY-NC-ND-2.0"
+licenseId CC_BY_NC_ND_2_5 = "CC-BY-NC-ND-2.5"
+licenseId CC_BY_NC_ND_3_0 = "CC-BY-NC-ND-3.0"
+licenseId CC_BY_NC_ND_4_0 = "CC-BY-NC-ND-4.0"
+licenseId CC_BY_NC_SA_1_0 = "CC-BY-NC-SA-1.0"
+licenseId CC_BY_NC_SA_2_0 = "CC-BY-NC-SA-2.0"
+licenseId CC_BY_NC_SA_2_5 = "CC-BY-NC-SA-2.5"
+licenseId CC_BY_NC_SA_3_0 = "CC-BY-NC-SA-3.0"
+licenseId CC_BY_NC_SA_4_0 = "CC-BY-NC-SA-4.0"
+licenseId CC_BY_ND_1_0 = "CC-BY-ND-1.0"
+licenseId CC_BY_ND_2_0 = "CC-BY-ND-2.0"
+licenseId CC_BY_ND_2_5 = "CC-BY-ND-2.5"
+licenseId CC_BY_ND_3_0 = "CC-BY-ND-3.0"
+licenseId CC_BY_ND_4_0 = "CC-BY-ND-4.0"
+licenseId CC_BY_SA_1_0 = "CC-BY-SA-1.0"
+licenseId CC_BY_SA_2_0 = "CC-BY-SA-2.0"
+licenseId CC_BY_SA_2_5 = "CC-BY-SA-2.5"
+licenseId CC_BY_SA_3_0 = "CC-BY-SA-3.0"
+licenseId CC_BY_SA_4_0 = "CC-BY-SA-4.0"
+licenseId CC0_1_0 = "CC0-1.0"
+licenseId CDDL_1_0 = "CDDL-1.0"
+licenseId CDDL_1_1 = "CDDL-1.1"
+licenseId CDLA_Permissive_1_0 = "CDLA-Permissive-1.0"
+licenseId CDLA_Sharing_1_0 = "CDLA-Sharing-1.0"
+licenseId CECILL_1_0 = "CECILL-1.0"
+licenseId CECILL_1_1 = "CECILL-1.1"
+licenseId CECILL_2_0 = "CECILL-2.0"
+licenseId CECILL_2_1 = "CECILL-2.1"
+licenseId CECILL_B = "CECILL-B"
+licenseId CECILL_C = "CECILL-C"
+licenseId ClArtistic = "ClArtistic"
+licenseId CNRI_Jython = "CNRI-Jython"
+licenseId CNRI_Python_GPL_Compatible = "CNRI-Python-GPL-Compatible"
+licenseId CNRI_Python = "CNRI-Python"
+licenseId Condor_1_1 = "Condor-1.1"
+licenseId CPAL_1_0 = "CPAL-1.0"
+licenseId CPL_1_0 = "CPL-1.0"
+licenseId CPOL_1_02 = "CPOL-1.02"
+licenseId Crossword = "Crossword"
+licenseId CrystalStacker = "CrystalStacker"
+licenseId CUA_OPL_1_0 = "CUA-OPL-1.0"
+licenseId Cube = "Cube"
+licenseId Curl = "curl"
+licenseId D_FSL_1_0 = "D-FSL-1.0"
+licenseId Diffmark = "diffmark"
+licenseId DOC = "DOC"
+licenseId Dotseqn = "Dotseqn"
+licenseId DSDP = "DSDP"
+licenseId Dvipdfm = "dvipdfm"
+licenseId ECL_1_0 = "ECL-1.0"
+licenseId ECL_2_0 = "ECL-2.0"
+licenseId EFL_1_0 = "EFL-1.0"
+licenseId EFL_2_0 = "EFL-2.0"
+licenseId EGenix = "eGenix"
+licenseId Entessa = "Entessa"
+licenseId EPL_1_0 = "EPL-1.0"
+licenseId EPL_2_0 = "EPL-2.0"
+licenseId ErlPL_1_1 = "ErlPL-1.1"
+licenseId EUDatagrid = "EUDatagrid"
+licenseId EUPL_1_0 = "EUPL-1.0"
+licenseId EUPL_1_1 = "EUPL-1.1"
+licenseId EUPL_1_2 = "EUPL-1.2"
+licenseId Eurosym = "Eurosym"
+licenseId Fair = "Fair"
+licenseId Frameworx_1_0 = "Frameworx-1.0"
+licenseId FreeImage = "FreeImage"
+licenseId FSFAP = "FSFAP"
+licenseId FSFUL = "FSFUL"
+licenseId FSFULLR = "FSFULLR"
+licenseId FTL = "FTL"
+licenseId GFDL_1_1_only = "GFDL-1.1-only"
+licenseId GFDL_1_1_or_later = "GFDL-1.1-or-later"
+licenseId GFDL_1_2_only = "GFDL-1.2-only"
+licenseId GFDL_1_2_or_later = "GFDL-1.2-or-later"
+licenseId GFDL_1_3_only = "GFDL-1.3-only"
+licenseId GFDL_1_3_or_later = "GFDL-1.3-or-later"
+licenseId Giftware = "Giftware"
+licenseId GL2PS = "GL2PS"
+licenseId Glide = "Glide"
+licenseId Glulxe = "Glulxe"
+licenseId Gnuplot = "gnuplot"
+licenseId GPL_1_0_only = "GPL-1.0-only"
+licenseId GPL_1_0_or_later = "GPL-1.0-or-later"
+licenseId GPL_2_0_only = "GPL-2.0-only"
+licenseId GPL_2_0_or_later = "GPL-2.0-or-later"
+licenseId GPL_3_0_only = "GPL-3.0-only"
+licenseId GPL_3_0_or_later = "GPL-3.0-or-later"
+licenseId GSOAP_1_3b = "gSOAP-1.3b"
+licenseId HaskellReport = "HaskellReport"
+licenseId HPND = "HPND"
+licenseId IBM_pibs = "IBM-pibs"
+licenseId ICU = "ICU"
+licenseId IJG = "IJG"
+licenseId ImageMagick = "ImageMagick"
+licenseId IMatix = "iMatix"
+licenseId Imlib2 = "Imlib2"
+licenseId Info_ZIP = "Info-ZIP"
+licenseId Intel_ACPI = "Intel-ACPI"
+licenseId Intel = "Intel"
+licenseId Interbase_1_0 = "Interbase-1.0"
+licenseId IPA = "IPA"
+licenseId IPL_1_0 = "IPL-1.0"
+licenseId ISC = "ISC"
+licenseId JasPer_2_0 = "JasPer-2.0"
+licenseId JSON = "JSON"
+licenseId LAL_1_2 = "LAL-1.2"
+licenseId LAL_1_3 = "LAL-1.3"
+licenseId Latex2e = "Latex2e"
+licenseId Leptonica = "Leptonica"
+licenseId LGPL_2_0_only = "LGPL-2.0-only"
+licenseId LGPL_2_0_or_later = "LGPL-2.0-or-later"
+licenseId LGPL_2_1_only = "LGPL-2.1-only"
+licenseId LGPL_2_1_or_later = "LGPL-2.1-or-later"
+licenseId LGPL_3_0_only = "LGPL-3.0-only"
+licenseId LGPL_3_0_or_later = "LGPL-3.0-or-later"
+licenseId LGPLLR = "LGPLLR"
+licenseId Libpng = "Libpng"
+licenseId Libtiff = "libtiff"
+licenseId LiLiQ_P_1_1 = "LiLiQ-P-1.1"
+licenseId LiLiQ_R_1_1 = "LiLiQ-R-1.1"
+licenseId LiLiQ_Rplus_1_1 = "LiLiQ-Rplus-1.1"
+licenseId Linux_OpenIB = "Linux-OpenIB"
+licenseId LPL_1_0 = "LPL-1.0"
+licenseId LPL_1_02 = "LPL-1.02"
+licenseId LPPL_1_0 = "LPPL-1.0"
+licenseId LPPL_1_1 = "LPPL-1.1"
+licenseId LPPL_1_2 = "LPPL-1.2"
+licenseId LPPL_1_3a = "LPPL-1.3a"
+licenseId LPPL_1_3c = "LPPL-1.3c"
+licenseId MakeIndex = "MakeIndex"
+licenseId MirOS = "MirOS"
+licenseId MIT_0 = "MIT-0"
+licenseId MIT_advertising = "MIT-advertising"
+licenseId MIT_CMU = "MIT-CMU"
+licenseId MIT_enna = "MIT-enna"
+licenseId MIT_feh = "MIT-feh"
+licenseId MIT = "MIT"
+licenseId MITNFA = "MITNFA"
+licenseId Motosoto = "Motosoto"
+licenseId Mpich2 = "mpich2"
+licenseId MPL_1_0 = "MPL-1.0"
+licenseId MPL_1_1 = "MPL-1.1"
+licenseId MPL_2_0_no_copyleft_exception = "MPL-2.0-no-copyleft-exception"
+licenseId MPL_2_0 = "MPL-2.0"
+licenseId MS_PL = "MS-PL"
+licenseId MS_RL = "MS-RL"
+licenseId MTLL = "MTLL"
+licenseId Multics = "Multics"
+licenseId Mup = "Mup"
+licenseId NASA_1_3 = "NASA-1.3"
+licenseId Naumen = "Naumen"
+licenseId NBPL_1_0 = "NBPL-1.0"
+licenseId NCSA = "NCSA"
+licenseId Net_SNMP = "Net-SNMP"
+licenseId NetCDF = "NetCDF"
+licenseId Newsletr = "Newsletr"
+licenseId NGPL = "NGPL"
+licenseId NLOD_1_0 = "NLOD-1.0"
+licenseId NLPL = "NLPL"
+licenseId Nokia = "Nokia"
+licenseId NOSL = "NOSL"
+licenseId Noweb = "Noweb"
+licenseId NPL_1_0 = "NPL-1.0"
+licenseId NPL_1_1 = "NPL-1.1"
+licenseId NPOSL_3_0 = "NPOSL-3.0"
+licenseId NRL = "NRL"
+licenseId NTP = "NTP"
+licenseId OCCT_PL = "OCCT-PL"
+licenseId OCLC_2_0 = "OCLC-2.0"
+licenseId ODbL_1_0 = "ODbL-1.0"
+licenseId ODC_By_1_0 = "ODC-By-1.0"
+licenseId OFL_1_0 = "OFL-1.0"
+licenseId OFL_1_1 = "OFL-1.1"
+licenseId OGTSL = "OGTSL"
+licenseId OLDAP_1_1 = "OLDAP-1.1"
+licenseId OLDAP_1_2 = "OLDAP-1.2"
+licenseId OLDAP_1_3 = "OLDAP-1.3"
+licenseId OLDAP_1_4 = "OLDAP-1.4"
+licenseId OLDAP_2_0_1 = "OLDAP-2.0.1"
+licenseId OLDAP_2_0 = "OLDAP-2.0"
+licenseId OLDAP_2_1 = "OLDAP-2.1"
+licenseId OLDAP_2_2_1 = "OLDAP-2.2.1"
+licenseId OLDAP_2_2_2 = "OLDAP-2.2.2"
+licenseId OLDAP_2_2 = "OLDAP-2.2"
+licenseId OLDAP_2_3 = "OLDAP-2.3"
+licenseId OLDAP_2_4 = "OLDAP-2.4"
+licenseId OLDAP_2_5 = "OLDAP-2.5"
+licenseId OLDAP_2_6 = "OLDAP-2.6"
+licenseId OLDAP_2_7 = "OLDAP-2.7"
+licenseId OLDAP_2_8 = "OLDAP-2.8"
+licenseId OML = "OML"
+licenseId OpenSSL = "OpenSSL"
+licenseId OPL_1_0 = "OPL-1.0"
+licenseId OSET_PL_2_1 = "OSET-PL-2.1"
+licenseId OSL_1_0 = "OSL-1.0"
+licenseId OSL_1_1 = "OSL-1.1"
+licenseId OSL_2_0 = "OSL-2.0"
+licenseId OSL_2_1 = "OSL-2.1"
+licenseId OSL_3_0 = "OSL-3.0"
+licenseId PDDL_1_0 = "PDDL-1.0"
+licenseId PHP_3_0 = "PHP-3.0"
+licenseId PHP_3_01 = "PHP-3.01"
+licenseId Plexus = "Plexus"
+licenseId PostgreSQL = "PostgreSQL"
+licenseId Psfrag = "psfrag"
+licenseId Psutils = "psutils"
+licenseId Python_2_0 = "Python-2.0"
+licenseId Qhull = "Qhull"
+licenseId QPL_1_0 = "QPL-1.0"
+licenseId Rdisc = "Rdisc"
+licenseId RHeCos_1_1 = "RHeCos-1.1"
+licenseId RPL_1_1 = "RPL-1.1"
+licenseId RPL_1_5 = "RPL-1.5"
+licenseId RPSL_1_0 = "RPSL-1.0"
+licenseId RSA_MD = "RSA-MD"
+licenseId RSCPL = "RSCPL"
+licenseId Ruby = "Ruby"
+licenseId SAX_PD = "SAX-PD"
+licenseId Saxpath = "Saxpath"
+licenseId SCEA = "SCEA"
+licenseId Sendmail = "Sendmail"
+licenseId SGI_B_1_0 = "SGI-B-1.0"
+licenseId SGI_B_1_1 = "SGI-B-1.1"
+licenseId SGI_B_2_0 = "SGI-B-2.0"
+licenseId SimPL_2_0 = "SimPL-2.0"
+licenseId SISSL_1_2 = "SISSL-1.2"
+licenseId SISSL = "SISSL"
+licenseId Sleepycat = "Sleepycat"
+licenseId SMLNJ = "SMLNJ"
+licenseId SMPPL = "SMPPL"
+licenseId SNIA = "SNIA"
+licenseId Spencer_86 = "Spencer-86"
+licenseId Spencer_94 = "Spencer-94"
+licenseId Spencer_99 = "Spencer-99"
+licenseId SPL_1_0 = "SPL-1.0"
+licenseId SugarCRM_1_1_3 = "SugarCRM-1.1.3"
+licenseId SWL = "SWL"
+licenseId TCL = "TCL"
+licenseId TCP_wrappers = "TCP-wrappers"
+licenseId TMate = "TMate"
+licenseId TORQUE_1_1 = "TORQUE-1.1"
+licenseId TOSL = "TOSL"
+licenseId TU_Berlin_1_0 = "TU-Berlin-1.0"
+licenseId TU_Berlin_2_0 = "TU-Berlin-2.0"
+licenseId Unicode_DFS_2015 = "Unicode-DFS-2015"
+licenseId Unicode_DFS_2016 = "Unicode-DFS-2016"
+licenseId Unicode_TOU = "Unicode-TOU"
+licenseId Unlicense = "Unlicense"
+licenseId UPL_1_0 = "UPL-1.0"
+licenseId Vim = "Vim"
+licenseId VOSTROM = "VOSTROM"
+licenseId VSL_1_0 = "VSL-1.0"
+licenseId W3C_19980720 = "W3C-19980720"
+licenseId W3C_20150513 = "W3C-20150513"
+licenseId W3C = "W3C"
+licenseId Watcom_1_0 = "Watcom-1.0"
+licenseId Wsuipa = "Wsuipa"
+licenseId WTFPL = "WTFPL"
+licenseId X11 = "X11"
+licenseId Xerox = "Xerox"
+licenseId XFree86_1_1 = "XFree86-1.1"
+licenseId Xinetd = "xinetd"
+licenseId Xnet = "Xnet"
+licenseId Xpp = "xpp"
+licenseId XSkat = "XSkat"
+licenseId YPL_1_0 = "YPL-1.0"
+licenseId YPL_1_1 = "YPL-1.1"
+licenseId Zed = "Zed"
+licenseId Zend_2_0 = "Zend-2.0"
+licenseId Zimbra_1_3 = "Zimbra-1.3"
+licenseId Zimbra_1_4 = "Zimbra-1.4"
+licenseId Zlib_acknowledgement = "zlib-acknowledgement"
+licenseId Zlib = "Zlib"
+licenseId ZPL_1_1 = "ZPL-1.1"
+licenseId ZPL_2_0 = "ZPL-2.0"
+licenseId ZPL_2_1 = "ZPL-2.1"
+
+-- | License name, e.g. @"GNU General Public License v2.0 only"@
+licenseName :: LicenseId -> String
+licenseName NullBSD = "BSD Zero Clause License"
+licenseName AAL = "Attribution Assurance License"
+licenseName Abstyles = "Abstyles License"
+licenseName Adobe_2006 = "Adobe Systems Incorporated Source Code License Agreement"
+licenseName Adobe_Glyph = "Adobe Glyph List License"
+licenseName ADSL = "Amazon Digital Services License"
+licenseName AFL_1_1 = "Academic Free License v1.1"
+licenseName AFL_1_2 = "Academic Free License v1.2"
+licenseName AFL_2_0 = "Academic Free License v2.0"
+licenseName AFL_2_1 = "Academic Free License v2.1"
+licenseName AFL_3_0 = "Academic Free License v3.0"
+licenseName Afmparse = "Afmparse License"
+licenseName AGPL_1_0 = "Affero General Public License v1.0"
+licenseName AGPL_1_0_only = "Affero General Public License v1.0 only"
+licenseName AGPL_1_0_or_later = "Affero General Public License v1.0 or later"
+licenseName AGPL_3_0_only = "GNU Affero General Public License v3.0 only"
+licenseName AGPL_3_0_or_later = "GNU Affero General Public License v3.0 or later"
+licenseName Aladdin = "Aladdin Free Public License"
+licenseName AMDPLPA = "AMD's plpa_map.c License"
+licenseName AML = "Apple MIT License"
+licenseName AMPAS = "Academy of Motion Picture Arts and Sciences BSD"
+licenseName ANTLR_PD = "ANTLR Software Rights Notice"
+licenseName Apache_1_0 = "Apache License 1.0"
+licenseName Apache_1_1 = "Apache License 1.1"
+licenseName Apache_2_0 = "Apache License 2.0"
+licenseName APAFML = "Adobe Postscript AFM License"
+licenseName APL_1_0 = "Adaptive Public License 1.0"
+licenseName APSL_1_0 = "Apple Public Source License 1.0"
+licenseName APSL_1_1 = "Apple Public Source License 1.1"
+licenseName APSL_1_2 = "Apple Public Source License 1.2"
+licenseName APSL_2_0 = "Apple Public Source License 2.0"
+licenseName Artistic_1_0_cl8 = "Artistic License 1.0 w/clause 8"
+licenseName Artistic_1_0_Perl = "Artistic License 1.0 (Perl)"
+licenseName Artistic_1_0 = "Artistic License 1.0"
+licenseName Artistic_2_0 = "Artistic License 2.0"
+licenseName Bahyph = "Bahyph License"
+licenseName Barr = "Barr License"
+licenseName Beerware = "Beerware License"
+licenseName BitTorrent_1_0 = "BitTorrent Open Source License v1.0"
+licenseName BitTorrent_1_1 = "BitTorrent Open Source License v1.1"
+licenseName Borceux = "Borceux license"
+licenseName BSD_1_Clause = "BSD 1-Clause License"
+licenseName BSD_2_Clause_FreeBSD = "BSD 2-Clause FreeBSD License"
+licenseName BSD_2_Clause_NetBSD = "BSD 2-Clause NetBSD License"
+licenseName BSD_2_Clause_Patent = "BSD-2-Clause Plus Patent License"
+licenseName BSD_2_Clause = "BSD 2-Clause \"Simplified\" License"
+licenseName BSD_3_Clause_Attribution = "BSD with attribution"
+licenseName BSD_3_Clause_Clear = "BSD 3-Clause Clear License"
+licenseName BSD_3_Clause_LBNL = "Lawrence Berkeley National Labs BSD variant license"
+licenseName BSD_3_Clause_No_Nuclear_License_2014 = "BSD 3-Clause No Nuclear License 2014"
+licenseName BSD_3_Clause_No_Nuclear_License = "BSD 3-Clause No Nuclear License"
+licenseName BSD_3_Clause_No_Nuclear_Warranty = "BSD 3-Clause No Nuclear Warranty"
+licenseName BSD_3_Clause = "BSD 3-Clause \"New\" or \"Revised\" License"
+licenseName BSD_4_Clause_UC = "BSD-4-Clause (University of California-Specific)"
+licenseName BSD_4_Clause = "BSD 4-Clause \"Original\" or \"Old\" License"
+licenseName BSD_Protection = "BSD Protection License"
+licenseName BSD_Source_Code = "BSD Source Code Attribution"
+licenseName BSL_1_0 = "Boost Software License 1.0"
+licenseName Bzip2_1_0_5 = "bzip2 and libbzip2 License v1.0.5"
+licenseName Bzip2_1_0_6 = "bzip2 and libbzip2 License v1.0.6"
+licenseName Caldera = "Caldera License"
+licenseName CATOSL_1_1 = "Computer Associates Trusted Open Source License 1.1"
+licenseName CC_BY_1_0 = "Creative Commons Attribution 1.0 Generic"
+licenseName CC_BY_2_0 = "Creative Commons Attribution 2.0 Generic"
+licenseName CC_BY_2_5 = "Creative Commons Attribution 2.5 Generic"
+licenseName CC_BY_3_0 = "Creative Commons Attribution 3.0 Unported"
+licenseName CC_BY_4_0 = "Creative Commons Attribution 4.0 International"
+licenseName CC_BY_NC_1_0 = "Creative Commons Attribution Non Commercial 1.0 Generic"
+licenseName CC_BY_NC_2_0 = "Creative Commons Attribution Non Commercial 2.0 Generic"
+licenseName CC_BY_NC_2_5 = "Creative Commons Attribution Non Commercial 2.5 Generic"
+licenseName CC_BY_NC_3_0 = "Creative Commons Attribution Non Commercial 3.0 Unported"
+licenseName CC_BY_NC_4_0 = "Creative Commons Attribution Non Commercial 4.0 International"
+licenseName CC_BY_NC_ND_1_0 = "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic"
+licenseName CC_BY_NC_ND_2_0 = "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic"
+licenseName CC_BY_NC_ND_2_5 = "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic"
+licenseName CC_BY_NC_ND_3_0 = "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported"
+licenseName CC_BY_NC_ND_4_0 = "Creative Commons Attribution Non Commercial No Derivatives 4.0 International"
+licenseName CC_BY_NC_SA_1_0 = "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic"
+licenseName CC_BY_NC_SA_2_0 = "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic"
+licenseName CC_BY_NC_SA_2_5 = "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic"
+licenseName CC_BY_NC_SA_3_0 = "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported"
+licenseName CC_BY_NC_SA_4_0 = "Creative Commons Attribution Non Commercial Share Alike 4.0 International"
+licenseName CC_BY_ND_1_0 = "Creative Commons Attribution No Derivatives 1.0 Generic"
+licenseName CC_BY_ND_2_0 = "Creative Commons Attribution No Derivatives 2.0 Generic"
+licenseName CC_BY_ND_2_5 = "Creative Commons Attribution No Derivatives 2.5 Generic"
+licenseName CC_BY_ND_3_0 = "Creative Commons Attribution No Derivatives 3.0 Unported"
+licenseName CC_BY_ND_4_0 = "Creative Commons Attribution No Derivatives 4.0 International"
+licenseName CC_BY_SA_1_0 = "Creative Commons Attribution Share Alike 1.0 Generic"
+licenseName CC_BY_SA_2_0 = "Creative Commons Attribution Share Alike 2.0 Generic"
+licenseName CC_BY_SA_2_5 = "Creative Commons Attribution Share Alike 2.5 Generic"
+licenseName CC_BY_SA_3_0 = "Creative Commons Attribution Share Alike 3.0 Unported"
+licenseName CC_BY_SA_4_0 = "Creative Commons Attribution Share Alike 4.0 International"
+licenseName CC0_1_0 = "Creative Commons Zero v1.0 Universal"
+licenseName CDDL_1_0 = "Common Development and Distribution License 1.0"
+licenseName CDDL_1_1 = "Common Development and Distribution License 1.1"
+licenseName CDLA_Permissive_1_0 = "Community Data License Agreement Permissive 1.0"
+licenseName CDLA_Sharing_1_0 = "Community Data License Agreement Sharing 1.0"
+licenseName CECILL_1_0 = "CeCILL Free Software License Agreement v1.0"
+licenseName CECILL_1_1 = "CeCILL Free Software License Agreement v1.1"
+licenseName CECILL_2_0 = "CeCILL Free Software License Agreement v2.0"
+licenseName CECILL_2_1 = "CeCILL Free Software License Agreement v2.1"
+licenseName CECILL_B = "CeCILL-B Free Software License Agreement"
+licenseName CECILL_C = "CeCILL-C Free Software License Agreement"
+licenseName ClArtistic = "Clarified Artistic License"
+licenseName CNRI_Jython = "CNRI Jython License"
+licenseName CNRI_Python_GPL_Compatible = "CNRI Python Open Source GPL Compatible License Agreement"
+licenseName CNRI_Python = "CNRI Python License"
+licenseName Condor_1_1 = "Condor Public License v1.1"
+licenseName CPAL_1_0 = "Common Public Attribution License 1.0"
+licenseName CPL_1_0 = "Common Public License 1.0"
+licenseName CPOL_1_02 = "Code Project Open License 1.02"
+licenseName Crossword = "Crossword License"
+licenseName CrystalStacker = "CrystalStacker License"
+licenseName CUA_OPL_1_0 = "CUA Office Public License v1.0"
+licenseName Cube = "Cube License"
+licenseName Curl = "curl License"
+licenseName D_FSL_1_0 = "Deutsche Freie Software Lizenz"
+licenseName Diffmark = "diffmark license"
+licenseName DOC = "DOC License"
+licenseName Dotseqn = "Dotseqn License"
+licenseName DSDP = "DSDP License"
+licenseName Dvipdfm = "dvipdfm License"
+licenseName ECL_1_0 = "Educational Community License v1.0"
+licenseName ECL_2_0 = "Educational Community License v2.0"
+licenseName EFL_1_0 = "Eiffel Forum License v1.0"
+licenseName EFL_2_0 = "Eiffel Forum License v2.0"
+licenseName EGenix = "eGenix.com Public License 1.1.0"
+licenseName Entessa = "Entessa Public License v1.0"
+licenseName EPL_1_0 = "Eclipse Public License 1.0"
+licenseName EPL_2_0 = "Eclipse Public License 2.0"
+licenseName ErlPL_1_1 = "Erlang Public License v1.1"
+licenseName EUDatagrid = "EU DataGrid Software License"
+licenseName EUPL_1_0 = "European Union Public License 1.0"
+licenseName EUPL_1_1 = "European Union Public License 1.1"
+licenseName EUPL_1_2 = "European Union Public License 1.2"
+licenseName Eurosym = "Eurosym License"
+licenseName Fair = "Fair License"
+licenseName Frameworx_1_0 = "Frameworx Open License 1.0"
+licenseName FreeImage = "FreeImage Public License v1.0"
+licenseName FSFAP = "FSF All Permissive License"
+licenseName FSFUL = "FSF Unlimited License"
+licenseName FSFULLR = "FSF Unlimited License (with License Retention)"
+licenseName FTL = "Freetype Project License"
+licenseName GFDL_1_1_only = "GNU Free Documentation License v1.1 only"
+licenseName GFDL_1_1_or_later = "GNU Free Documentation License v1.1 or later"
+licenseName GFDL_1_2_only = "GNU Free Documentation License v1.2 only"
+licenseName GFDL_1_2_or_later = "GNU Free Documentation License v1.2 or later"
+licenseName GFDL_1_3_only = "GNU Free Documentation License v1.3 only"
+licenseName GFDL_1_3_or_later = "GNU Free Documentation License v1.3 or later"
+licenseName Giftware = "Giftware License"
+licenseName GL2PS = "GL2PS License"
+licenseName Glide = "3dfx Glide License"
+licenseName Glulxe = "Glulxe License"
+licenseName Gnuplot = "gnuplot License"
+licenseName GPL_1_0_only = "GNU General Public License v1.0 only"
+licenseName GPL_1_0_or_later = "GNU General Public License v1.0 or later"
+licenseName GPL_2_0_only = "GNU General Public License v2.0 only"
+licenseName GPL_2_0_or_later = "GNU General Public License v2.0 or later"
+licenseName GPL_3_0_only = "GNU General Public License v3.0 only"
+licenseName GPL_3_0_or_later = "GNU General Public License v3.0 or later"
+licenseName GSOAP_1_3b = "gSOAP Public License v1.3b"
+licenseName HaskellReport = "Haskell Language Report License"
+licenseName HPND = "Historical Permission Notice and Disclaimer"
+licenseName IBM_pibs = "IBM PowerPC Initialization and Boot Software"
+licenseName ICU = "ICU License"
+licenseName IJG = "Independent JPEG Group License"
+licenseName ImageMagick = "ImageMagick License"
+licenseName IMatix = "iMatix Standard Function Library Agreement"
+licenseName Imlib2 = "Imlib2 License"
+licenseName Info_ZIP = "Info-ZIP License"
+licenseName Intel_ACPI = "Intel ACPI Software License Agreement"
+licenseName Intel = "Intel Open Source License"
+licenseName Interbase_1_0 = "Interbase Public License v1.0"
+licenseName IPA = "IPA Font License"
+licenseName IPL_1_0 = "IBM Public License v1.0"
+licenseName ISC = "ISC License"
+licenseName JasPer_2_0 = "JasPer License"
+licenseName JSON = "JSON License"
+licenseName LAL_1_2 = "Licence Art Libre 1.2"
+licenseName LAL_1_3 = "Licence Art Libre 1.3"
+licenseName Latex2e = "Latex2e License"
+licenseName Leptonica = "Leptonica License"
+licenseName LGPL_2_0_only = "GNU Library General Public License v2 only"
+licenseName LGPL_2_0_or_later = "GNU Library General Public License v2 or later"
+licenseName LGPL_2_1_only = "GNU Lesser General Public License v2.1 only"
+licenseName LGPL_2_1_or_later = "GNU Lesser General Public License v2.1 or later"
+licenseName LGPL_3_0_only = "GNU Lesser General Public License v3.0 only"
+licenseName LGPL_3_0_or_later = "GNU Lesser General Public License v3.0 or later"
+licenseName LGPLLR = "Lesser General Public License For Linguistic Resources"
+licenseName Libpng = "libpng License"
+licenseName Libtiff = "libtiff License"
+licenseName LiLiQ_P_1_1 = "Licence Libre du Qu\233bec \8211 Permissive version 1.1"
+licenseName LiLiQ_R_1_1 = "Licence Libre du Qu\233bec \8211 R\233ciprocit\233 version 1.1"
+licenseName LiLiQ_Rplus_1_1 = "Licence Libre du Qu\233bec \8211 R\233ciprocit\233 forte version 1.1"
+licenseName Linux_OpenIB = "Linux Kernel Variant of OpenIB.org license"
+licenseName LPL_1_0 = "Lucent Public License Version 1.0"
+licenseName LPL_1_02 = "Lucent Public License v1.02"
+licenseName LPPL_1_0 = "LaTeX Project Public License v1.0"
+licenseName LPPL_1_1 = "LaTeX Project Public License v1.1"
+licenseName LPPL_1_2 = "LaTeX Project Public License v1.2"
+licenseName LPPL_1_3a = "LaTeX Project Public License v1.3a"
+licenseName LPPL_1_3c = "LaTeX Project Public License v1.3c"
+licenseName MakeIndex = "MakeIndex License"
+licenseName MirOS = "MirOS License"
+licenseName MIT_0 = "MIT No Attribution"
+licenseName MIT_advertising = "Enlightenment License (e16)"
+licenseName MIT_CMU = "CMU License"
+licenseName MIT_enna = "enna License"
+licenseName MIT_feh = "feh License"
+licenseName MIT = "MIT License"
+licenseName MITNFA = "MIT +no-false-attribs license"
+licenseName Motosoto = "Motosoto License"
+licenseName Mpich2 = "mpich2 License"
+licenseName MPL_1_0 = "Mozilla Public License 1.0"
+licenseName MPL_1_1 = "Mozilla Public License 1.1"
+licenseName MPL_2_0_no_copyleft_exception = "Mozilla Public License 2.0 (no copyleft exception)"
+licenseName MPL_2_0 = "Mozilla Public License 2.0"
+licenseName MS_PL = "Microsoft Public License"
+licenseName MS_RL = "Microsoft Reciprocal License"
+licenseName MTLL = "Matrix Template Library License"
+licenseName Multics = "Multics License"
+licenseName Mup = "Mup License"
+licenseName NASA_1_3 = "NASA Open Source Agreement 1.3"
+licenseName Naumen = "Naumen Public License"
+licenseName NBPL_1_0 = "Net Boolean Public License v1"
+licenseName NCSA = "University of Illinois/NCSA Open Source License"
+licenseName Net_SNMP = "Net-SNMP License"
+licenseName NetCDF = "NetCDF license"
+licenseName Newsletr = "Newsletr License"
+licenseName NGPL = "Nethack General Public License"
+licenseName NLOD_1_0 = "Norwegian Licence for Open Government Data"
+licenseName NLPL = "No Limit Public License"
+licenseName Nokia = "Nokia Open Source License"
+licenseName NOSL = "Netizen Open Source License"
+licenseName Noweb = "Noweb License"
+licenseName NPL_1_0 = "Netscape Public License v1.0"
+licenseName NPL_1_1 = "Netscape Public License v1.1"
+licenseName NPOSL_3_0 = "Non-Profit Open Software License 3.0"
+licenseName NRL = "NRL License"
+licenseName NTP = "NTP License"
+licenseName OCCT_PL = "Open CASCADE Technology Public License"
+licenseName OCLC_2_0 = "OCLC Research Public License 2.0"
+licenseName ODbL_1_0 = "ODC Open Database License v1.0"
+licenseName ODC_By_1_0 = "Open Data Commons Attribution License v1.0"
+licenseName OFL_1_0 = "SIL Open Font License 1.0"
+licenseName OFL_1_1 = "SIL Open Font License 1.1"
+licenseName OGTSL = "Open Group Test Suite License"
+licenseName OLDAP_1_1 = "Open LDAP Public License v1.1"
+licenseName OLDAP_1_2 = "Open LDAP Public License v1.2"
+licenseName OLDAP_1_3 = "Open LDAP Public License v1.3"
+licenseName OLDAP_1_4 = "Open LDAP Public License v1.4"
+licenseName OLDAP_2_0_1 = "Open LDAP Public License v2.0.1"
+licenseName OLDAP_2_0 = "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)"
+licenseName OLDAP_2_1 = "Open LDAP Public License v2.1"
+licenseName OLDAP_2_2_1 = "Open LDAP Public License v2.2.1"
+licenseName OLDAP_2_2_2 = "Open LDAP Public License 2.2.2"
+licenseName OLDAP_2_2 = "Open LDAP Public License v2.2"
+licenseName OLDAP_2_3 = "Open LDAP Public License v2.3"
+licenseName OLDAP_2_4 = "Open LDAP Public License v2.4"
+licenseName OLDAP_2_5 = "Open LDAP Public License v2.5"
+licenseName OLDAP_2_6 = "Open LDAP Public License v2.6"
+licenseName OLDAP_2_7 = "Open LDAP Public License v2.7"
+licenseName OLDAP_2_8 = "Open LDAP Public License v2.8"
+licenseName OML = "Open Market License"
+licenseName OpenSSL = "OpenSSL License"
+licenseName OPL_1_0 = "Open Public License v1.0"
+licenseName OSET_PL_2_1 = "OSET Public License version 2.1"
+licenseName OSL_1_0 = "Open Software License 1.0"
+licenseName OSL_1_1 = "Open Software License 1.1"
+licenseName OSL_2_0 = "Open Software License 2.0"
+licenseName OSL_2_1 = "Open Software License 2.1"
+licenseName OSL_3_0 = "Open Software License 3.0"
+licenseName PDDL_1_0 = "ODC Public Domain Dedication & License 1.0"
+licenseName PHP_3_0 = "PHP License v3.0"
+licenseName PHP_3_01 = "PHP License v3.01"
+licenseName Plexus = "Plexus Classworlds License"
+licenseName PostgreSQL = "PostgreSQL License"
+licenseName Psfrag = "psfrag License"
+licenseName Psutils = "psutils License"
+licenseName Python_2_0 = "Python License 2.0"
+licenseName Qhull = "Qhull License"
+licenseName QPL_1_0 = "Q Public License 1.0"
+licenseName Rdisc = "Rdisc License"
+licenseName RHeCos_1_1 = "Red Hat eCos Public License v1.1"
+licenseName RPL_1_1 = "Reciprocal Public License 1.1"
+licenseName RPL_1_5 = "Reciprocal Public License 1.5"
+licenseName RPSL_1_0 = "RealNetworks Public Source License v1.0"
+licenseName RSA_MD = "RSA Message-Digest License "
+licenseName RSCPL = "Ricoh Source Code Public License"
+licenseName Ruby = "Ruby License"
+licenseName SAX_PD = "Sax Public Domain Notice"
+licenseName Saxpath = "Saxpath License"
+licenseName SCEA = "SCEA Shared Source License"
+licenseName Sendmail = "Sendmail License"
+licenseName SGI_B_1_0 = "SGI Free Software License B v1.0"
+licenseName SGI_B_1_1 = "SGI Free Software License B v1.1"
+licenseName SGI_B_2_0 = "SGI Free Software License B v2.0"
+licenseName SimPL_2_0 = "Simple Public License 2.0"
+licenseName SISSL_1_2 = "Sun Industry Standards Source License v1.2"
+licenseName SISSL = "Sun Industry Standards Source License v1.1"
+licenseName Sleepycat = "Sleepycat License"
+licenseName SMLNJ = "Standard ML of New Jersey License"
+licenseName SMPPL = "Secure Messaging Protocol Public License"
+licenseName SNIA = "SNIA Public License 1.1"
+licenseName Spencer_86 = "Spencer License 86"
+licenseName Spencer_94 = "Spencer License 94"
+licenseName Spencer_99 = "Spencer License 99"
+licenseName SPL_1_0 = "Sun Public License v1.0"
+licenseName SugarCRM_1_1_3 = "SugarCRM Public License v1.1.3"
+licenseName SWL = "Scheme Widget Library (SWL) Software License Agreement"
+licenseName TCL = "TCL/TK License"
+licenseName TCP_wrappers = "TCP Wrappers License"
+licenseName TMate = "TMate Open Source License"
+licenseName TORQUE_1_1 = "TORQUE v2.5+ Software License v1.1"
+licenseName TOSL = "Trusster Open Source License"
+licenseName TU_Berlin_1_0 = "Technische Universitaet Berlin License 1.0"
+licenseName TU_Berlin_2_0 = "Technische Universitaet Berlin License 2.0"
+licenseName Unicode_DFS_2015 = "Unicode License Agreement - Data Files and Software (2015)"
+licenseName Unicode_DFS_2016 = "Unicode License Agreement - Data Files and Software (2016)"
+licenseName Unicode_TOU = "Unicode Terms of Use"
+licenseName Unlicense = "The Unlicense"
+licenseName UPL_1_0 = "Universal Permissive License v1.0"
+licenseName Vim = "Vim License"
+licenseName VOSTROM = "VOSTROM Public License for Open Source"
+licenseName VSL_1_0 = "Vovida Software License v1.0"
+licenseName W3C_19980720 = "W3C Software Notice and License (1998-07-20)"
+licenseName W3C_20150513 = "W3C Software Notice and Document License (2015-05-13)"
+licenseName W3C = "W3C Software Notice and License (2002-12-31)"
+licenseName Watcom_1_0 = "Sybase Open Watcom Public License 1.0"
+licenseName Wsuipa = "Wsuipa License"
+licenseName WTFPL = "Do What The F*ck You Want To Public License"
+licenseName X11 = "X11 License"
+licenseName Xerox = "Xerox License"
+licenseName XFree86_1_1 = "XFree86 License 1.1"
+licenseName Xinetd = "xinetd License"
+licenseName Xnet = "X.Net License"
+licenseName Xpp = "XPP License"
+licenseName XSkat = "XSkat License"
+licenseName YPL_1_0 = "Yahoo! Public License v1.0"
+licenseName YPL_1_1 = "Yahoo! Public License v1.1"
+licenseName Zed = "Zed License"
+licenseName Zend_2_0 = "Zend License v2.0"
+licenseName Zimbra_1_3 = "Zimbra Public License v1.3"
+licenseName Zimbra_1_4 = "Zimbra Public License v1.4"
+licenseName Zlib_acknowledgement = "zlib/libpng License with Acknowledgement"
+licenseName Zlib = "zlib License"
+licenseName ZPL_1_1 = "Zope Public License 1.1"
+licenseName ZPL_2_0 = "Zope Public License 2.0"
+licenseName ZPL_2_1 = "Zope Public License 2.1"
+
+-- | Whether the license is approved by Open Source Initiative (OSI).
+--
+-- See <https://opensource.org/licenses/alphabetical>.
+licenseIsOsiApproved :: LicenseId -> Bool
+licenseIsOsiApproved NullBSD = False
+licenseIsOsiApproved AAL = True
+licenseIsOsiApproved Abstyles = False
+licenseIsOsiApproved Adobe_2006 = False
+licenseIsOsiApproved Adobe_Glyph = False
+licenseIsOsiApproved ADSL = False
+licenseIsOsiApproved AFL_1_1 = True
+licenseIsOsiApproved AFL_1_2 = True
+licenseIsOsiApproved AFL_2_0 = True
+licenseIsOsiApproved AFL_2_1 = True
+licenseIsOsiApproved AFL_3_0 = True
+licenseIsOsiApproved Afmparse = False
+licenseIsOsiApproved AGPL_1_0 = False
+licenseIsOsiApproved AGPL_1_0_only = False
+licenseIsOsiApproved AGPL_1_0_or_later = False
+licenseIsOsiApproved AGPL_3_0_only = True
+licenseIsOsiApproved AGPL_3_0_or_later = True
+licenseIsOsiApproved Aladdin = False
+licenseIsOsiApproved AMDPLPA = False
+licenseIsOsiApproved AML = False
+licenseIsOsiApproved AMPAS = False
+licenseIsOsiApproved ANTLR_PD = False
+licenseIsOsiApproved Apache_1_0 = False
+licenseIsOsiApproved Apache_1_1 = True
+licenseIsOsiApproved Apache_2_0 = True
+licenseIsOsiApproved APAFML = False
+licenseIsOsiApproved APL_1_0 = True
+licenseIsOsiApproved APSL_1_0 = True
+licenseIsOsiApproved APSL_1_1 = True
+licenseIsOsiApproved APSL_1_2 = True
+licenseIsOsiApproved APSL_2_0 = True
+licenseIsOsiApproved Artistic_1_0_cl8 = True
+licenseIsOsiApproved Artistic_1_0_Perl = True
+licenseIsOsiApproved Artistic_1_0 = True
+licenseIsOsiApproved Artistic_2_0 = True
+licenseIsOsiApproved Bahyph = False
+licenseIsOsiApproved Barr = False
+licenseIsOsiApproved Beerware = False
+licenseIsOsiApproved BitTorrent_1_0 = False
+licenseIsOsiApproved BitTorrent_1_1 = False
+licenseIsOsiApproved Borceux = False
+licenseIsOsiApproved BSD_1_Clause = False
+licenseIsOsiApproved BSD_2_Clause_FreeBSD = False
+licenseIsOsiApproved BSD_2_Clause_NetBSD = False
+licenseIsOsiApproved BSD_2_Clause_Patent = True
+licenseIsOsiApproved BSD_2_Clause = True
+licenseIsOsiApproved BSD_3_Clause_Attribution = False
+licenseIsOsiApproved BSD_3_Clause_Clear = False
+licenseIsOsiApproved BSD_3_Clause_LBNL = False
+licenseIsOsiApproved BSD_3_Clause_No_Nuclear_License_2014 = False
+licenseIsOsiApproved BSD_3_Clause_No_Nuclear_License = False
+licenseIsOsiApproved BSD_3_Clause_No_Nuclear_Warranty = False
+licenseIsOsiApproved BSD_3_Clause = True
+licenseIsOsiApproved BSD_4_Clause_UC = False
+licenseIsOsiApproved BSD_4_Clause = False
+licenseIsOsiApproved BSD_Protection = False
+licenseIsOsiApproved BSD_Source_Code = False
+licenseIsOsiApproved BSL_1_0 = True
+licenseIsOsiApproved Bzip2_1_0_5 = False
+licenseIsOsiApproved Bzip2_1_0_6 = False
+licenseIsOsiApproved Caldera = False
+licenseIsOsiApproved CATOSL_1_1 = True
+licenseIsOsiApproved CC_BY_1_0 = False
+licenseIsOsiApproved CC_BY_2_0 = False
+licenseIsOsiApproved CC_BY_2_5 = False
+licenseIsOsiApproved CC_BY_3_0 = False
+licenseIsOsiApproved CC_BY_4_0 = False
+licenseIsOsiApproved CC_BY_NC_1_0 = False
+licenseIsOsiApproved CC_BY_NC_2_0 = False
+licenseIsOsiApproved CC_BY_NC_2_5 = False
+licenseIsOsiApproved CC_BY_NC_3_0 = False
+licenseIsOsiApproved CC_BY_NC_4_0 = False
+licenseIsOsiApproved CC_BY_NC_ND_1_0 = False
+licenseIsOsiApproved CC_BY_NC_ND_2_0 = False
+licenseIsOsiApproved CC_BY_NC_ND_2_5 = False
+licenseIsOsiApproved CC_BY_NC_ND_3_0 = False
+licenseIsOsiApproved CC_BY_NC_ND_4_0 = False
+licenseIsOsiApproved CC_BY_NC_SA_1_0 = False
+licenseIsOsiApproved CC_BY_NC_SA_2_0 = False
+licenseIsOsiApproved CC_BY_NC_SA_2_5 = False
+licenseIsOsiApproved CC_BY_NC_SA_3_0 = False
+licenseIsOsiApproved CC_BY_NC_SA_4_0 = False
+licenseIsOsiApproved CC_BY_ND_1_0 = False
+licenseIsOsiApproved CC_BY_ND_2_0 = False
+licenseIsOsiApproved CC_BY_ND_2_5 = False
+licenseIsOsiApproved CC_BY_ND_3_0 = False
+licenseIsOsiApproved CC_BY_ND_4_0 = False
+licenseIsOsiApproved CC_BY_SA_1_0 = False
+licenseIsOsiApproved CC_BY_SA_2_0 = False
+licenseIsOsiApproved CC_BY_SA_2_5 = False
+licenseIsOsiApproved CC_BY_SA_3_0 = False
+licenseIsOsiApproved CC_BY_SA_4_0 = False
+licenseIsOsiApproved CC0_1_0 = False
+licenseIsOsiApproved CDDL_1_0 = True
+licenseIsOsiApproved CDDL_1_1 = False
+licenseIsOsiApproved CDLA_Permissive_1_0 = False
+licenseIsOsiApproved CDLA_Sharing_1_0 = False
+licenseIsOsiApproved CECILL_1_0 = False
+licenseIsOsiApproved CECILL_1_1 = False
+licenseIsOsiApproved CECILL_2_0 = False
+licenseIsOsiApproved CECILL_2_1 = True
+licenseIsOsiApproved CECILL_B = False
+licenseIsOsiApproved CECILL_C = False
+licenseIsOsiApproved ClArtistic = False
+licenseIsOsiApproved CNRI_Jython = False
+licenseIsOsiApproved CNRI_Python_GPL_Compatible = False
+licenseIsOsiApproved CNRI_Python = True
+licenseIsOsiApproved Condor_1_1 = False
+licenseIsOsiApproved CPAL_1_0 = True
+licenseIsOsiApproved CPL_1_0 = True
+licenseIsOsiApproved CPOL_1_02 = False
+licenseIsOsiApproved Crossword = False
+licenseIsOsiApproved CrystalStacker = False
+licenseIsOsiApproved CUA_OPL_1_0 = True
+licenseIsOsiApproved Cube = False
+licenseIsOsiApproved Curl = False
+licenseIsOsiApproved D_FSL_1_0 = False
+licenseIsOsiApproved Diffmark = False
+licenseIsOsiApproved DOC = False
+licenseIsOsiApproved Dotseqn = False
+licenseIsOsiApproved DSDP = False
+licenseIsOsiApproved Dvipdfm = False
+licenseIsOsiApproved ECL_1_0 = True
+licenseIsOsiApproved ECL_2_0 = True
+licenseIsOsiApproved EFL_1_0 = True
+licenseIsOsiApproved EFL_2_0 = True
+licenseIsOsiApproved EGenix = False
+licenseIsOsiApproved Entessa = True
+licenseIsOsiApproved EPL_1_0 = True
+licenseIsOsiApproved EPL_2_0 = True
+licenseIsOsiApproved ErlPL_1_1 = False
+licenseIsOsiApproved EUDatagrid = True
+licenseIsOsiApproved EUPL_1_0 = False
+licenseIsOsiApproved EUPL_1_1 = True
+licenseIsOsiApproved EUPL_1_2 = True
+licenseIsOsiApproved Eurosym = False
+licenseIsOsiApproved Fair = True
+licenseIsOsiApproved Frameworx_1_0 = True
+licenseIsOsiApproved FreeImage = False
+licenseIsOsiApproved FSFAP = False
+licenseIsOsiApproved FSFUL = False
+licenseIsOsiApproved FSFULLR = False
+licenseIsOsiApproved FTL = False
+licenseIsOsiApproved GFDL_1_1_only = False
+licenseIsOsiApproved GFDL_1_1_or_later = False
+licenseIsOsiApproved GFDL_1_2_only = False
+licenseIsOsiApproved GFDL_1_2_or_later = False
+licenseIsOsiApproved GFDL_1_3_only = False
+licenseIsOsiApproved GFDL_1_3_or_later = False
+licenseIsOsiApproved Giftware = False
+licenseIsOsiApproved GL2PS = False
+licenseIsOsiApproved Glide = False
+licenseIsOsiApproved Glulxe = False
+licenseIsOsiApproved Gnuplot = False
+licenseIsOsiApproved GPL_1_0_only = False
+licenseIsOsiApproved GPL_1_0_or_later = False
+licenseIsOsiApproved GPL_2_0_only = True
+licenseIsOsiApproved GPL_2_0_or_later = True
+licenseIsOsiApproved GPL_3_0_only = True
+licenseIsOsiApproved GPL_3_0_or_later = True
+licenseIsOsiApproved GSOAP_1_3b = False
+licenseIsOsiApproved HaskellReport = False
+licenseIsOsiApproved HPND = True
+licenseIsOsiApproved IBM_pibs = False
+licenseIsOsiApproved ICU = False
+licenseIsOsiApproved IJG = False
+licenseIsOsiApproved ImageMagick = False
+licenseIsOsiApproved IMatix = False
+licenseIsOsiApproved Imlib2 = False
+licenseIsOsiApproved Info_ZIP = False
+licenseIsOsiApproved Intel_ACPI = False
+licenseIsOsiApproved Intel = True
+licenseIsOsiApproved Interbase_1_0 = False
+licenseIsOsiApproved IPA = True
+licenseIsOsiApproved IPL_1_0 = True
+licenseIsOsiApproved ISC = True
+licenseIsOsiApproved JasPer_2_0 = False
+licenseIsOsiApproved JSON = False
+licenseIsOsiApproved LAL_1_2 = False
+licenseIsOsiApproved LAL_1_3 = False
+licenseIsOsiApproved Latex2e = False
+licenseIsOsiApproved Leptonica = False
+licenseIsOsiApproved LGPL_2_0_only = True
+licenseIsOsiApproved LGPL_2_0_or_later = True
+licenseIsOsiApproved LGPL_2_1_only = True
+licenseIsOsiApproved LGPL_2_1_or_later = True
+licenseIsOsiApproved LGPL_3_0_only = True
+licenseIsOsiApproved LGPL_3_0_or_later = True
+licenseIsOsiApproved LGPLLR = False
+licenseIsOsiApproved Libpng = False
+licenseIsOsiApproved Libtiff = False
+licenseIsOsiApproved LiLiQ_P_1_1 = True
+licenseIsOsiApproved LiLiQ_R_1_1 = True
+licenseIsOsiApproved LiLiQ_Rplus_1_1 = True
+licenseIsOsiApproved Linux_OpenIB = False
+licenseIsOsiApproved LPL_1_0 = True
+licenseIsOsiApproved LPL_1_02 = True
+licenseIsOsiApproved LPPL_1_0 = False
+licenseIsOsiApproved LPPL_1_1 = False
+licenseIsOsiApproved LPPL_1_2 = False
+licenseIsOsiApproved LPPL_1_3a = False
+licenseIsOsiApproved LPPL_1_3c = True
+licenseIsOsiApproved MakeIndex = False
+licenseIsOsiApproved MirOS = True
+licenseIsOsiApproved MIT_0 = True
+licenseIsOsiApproved MIT_advertising = False
+licenseIsOsiApproved MIT_CMU = False
+licenseIsOsiApproved MIT_enna = False
+licenseIsOsiApproved MIT_feh = False
+licenseIsOsiApproved MIT = True
+licenseIsOsiApproved MITNFA = False
+licenseIsOsiApproved Motosoto = True
+licenseIsOsiApproved Mpich2 = False
+licenseIsOsiApproved MPL_1_0 = True
+licenseIsOsiApproved MPL_1_1 = True
+licenseIsOsiApproved MPL_2_0_no_copyleft_exception = True
+licenseIsOsiApproved MPL_2_0 = True
+licenseIsOsiApproved MS_PL = True
+licenseIsOsiApproved MS_RL = True
+licenseIsOsiApproved MTLL = False
+licenseIsOsiApproved Multics = True
+licenseIsOsiApproved Mup = False
+licenseIsOsiApproved NASA_1_3 = True
+licenseIsOsiApproved Naumen = True
+licenseIsOsiApproved NBPL_1_0 = False
+licenseIsOsiApproved NCSA = True
+licenseIsOsiApproved Net_SNMP = False
+licenseIsOsiApproved NetCDF = False
+licenseIsOsiApproved Newsletr = False
+licenseIsOsiApproved NGPL = True
+licenseIsOsiApproved NLOD_1_0 = False
+licenseIsOsiApproved NLPL = False
+licenseIsOsiApproved Nokia = True
+licenseIsOsiApproved NOSL = False
+licenseIsOsiApproved Noweb = False
+licenseIsOsiApproved NPL_1_0 = False
+licenseIsOsiApproved NPL_1_1 = False
+licenseIsOsiApproved NPOSL_3_0 = True
+licenseIsOsiApproved NRL = False
+licenseIsOsiApproved NTP = True
+licenseIsOsiApproved OCCT_PL = False
+licenseIsOsiApproved OCLC_2_0 = True
+licenseIsOsiApproved ODbL_1_0 = False
+licenseIsOsiApproved ODC_By_1_0 = False
+licenseIsOsiApproved OFL_1_0 = False
+licenseIsOsiApproved OFL_1_1 = True
+licenseIsOsiApproved OGTSL = True
+licenseIsOsiApproved OLDAP_1_1 = False
+licenseIsOsiApproved OLDAP_1_2 = False
+licenseIsOsiApproved OLDAP_1_3 = False
+licenseIsOsiApproved OLDAP_1_4 = False
+licenseIsOsiApproved OLDAP_2_0_1 = False
+licenseIsOsiApproved OLDAP_2_0 = False
+licenseIsOsiApproved OLDAP_2_1 = False
+licenseIsOsiApproved OLDAP_2_2_1 = False
+licenseIsOsiApproved OLDAP_2_2_2 = False
+licenseIsOsiApproved OLDAP_2_2 = False
+licenseIsOsiApproved OLDAP_2_3 = False
+licenseIsOsiApproved OLDAP_2_4 = False
+licenseIsOsiApproved OLDAP_2_5 = False
+licenseIsOsiApproved OLDAP_2_6 = False
+licenseIsOsiApproved OLDAP_2_7 = False
+licenseIsOsiApproved OLDAP_2_8 = False
+licenseIsOsiApproved OML = False
+licenseIsOsiApproved OpenSSL = False
+licenseIsOsiApproved OPL_1_0 = False
+licenseIsOsiApproved OSET_PL_2_1 = True
+licenseIsOsiApproved OSL_1_0 = True
+licenseIsOsiApproved OSL_1_1 = False
+licenseIsOsiApproved OSL_2_0 = True
+licenseIsOsiApproved OSL_2_1 = True
+licenseIsOsiApproved OSL_3_0 = True
+licenseIsOsiApproved PDDL_1_0 = False
+licenseIsOsiApproved PHP_3_0 = True
+licenseIsOsiApproved PHP_3_01 = False
+licenseIsOsiApproved Plexus = False
+licenseIsOsiApproved PostgreSQL = True
+licenseIsOsiApproved Psfrag = False
+licenseIsOsiApproved Psutils = False
+licenseIsOsiApproved Python_2_0 = True
+licenseIsOsiApproved Qhull = False
+licenseIsOsiApproved QPL_1_0 = True
+licenseIsOsiApproved Rdisc = False
+licenseIsOsiApproved RHeCos_1_1 = False
+licenseIsOsiApproved RPL_1_1 = True
+licenseIsOsiApproved RPL_1_5 = True
+licenseIsOsiApproved RPSL_1_0 = True
+licenseIsOsiApproved RSA_MD = False
+licenseIsOsiApproved RSCPL = True
+licenseIsOsiApproved Ruby = False
+licenseIsOsiApproved SAX_PD = False
+licenseIsOsiApproved Saxpath = False
+licenseIsOsiApproved SCEA = False
+licenseIsOsiApproved Sendmail = False
+licenseIsOsiApproved SGI_B_1_0 = False
+licenseIsOsiApproved SGI_B_1_1 = False
+licenseIsOsiApproved SGI_B_2_0 = False
+licenseIsOsiApproved SimPL_2_0 = True
+licenseIsOsiApproved SISSL_1_2 = False
+licenseIsOsiApproved SISSL = True
+licenseIsOsiApproved Sleepycat = True
+licenseIsOsiApproved SMLNJ = False
+licenseIsOsiApproved SMPPL = False
+licenseIsOsiApproved SNIA = False
+licenseIsOsiApproved Spencer_86 = False
+licenseIsOsiApproved Spencer_94 = False
+licenseIsOsiApproved Spencer_99 = False
+licenseIsOsiApproved SPL_1_0 = True
+licenseIsOsiApproved SugarCRM_1_1_3 = False
+licenseIsOsiApproved SWL = False
+licenseIsOsiApproved TCL = False
+licenseIsOsiApproved TCP_wrappers = False
+licenseIsOsiApproved TMate = False
+licenseIsOsiApproved TORQUE_1_1 = False
+licenseIsOsiApproved TOSL = False
+licenseIsOsiApproved TU_Berlin_1_0 = False
+licenseIsOsiApproved TU_Berlin_2_0 = False
+licenseIsOsiApproved Unicode_DFS_2015 = False
+licenseIsOsiApproved Unicode_DFS_2016 = False
+licenseIsOsiApproved Unicode_TOU = False
+licenseIsOsiApproved Unlicense = False
+licenseIsOsiApproved UPL_1_0 = True
+licenseIsOsiApproved Vim = False
+licenseIsOsiApproved VOSTROM = False
+licenseIsOsiApproved VSL_1_0 = True
+licenseIsOsiApproved W3C_19980720 = False
+licenseIsOsiApproved W3C_20150513 = False
+licenseIsOsiApproved W3C = True
+licenseIsOsiApproved Watcom_1_0 = True
+licenseIsOsiApproved Wsuipa = False
+licenseIsOsiApproved WTFPL = False
+licenseIsOsiApproved X11 = False
+licenseIsOsiApproved Xerox = False
+licenseIsOsiApproved XFree86_1_1 = False
+licenseIsOsiApproved Xinetd = False
+licenseIsOsiApproved Xnet = True
+licenseIsOsiApproved Xpp = False
+licenseIsOsiApproved XSkat = False
+licenseIsOsiApproved YPL_1_0 = False
+licenseIsOsiApproved YPL_1_1 = False
+licenseIsOsiApproved Zed = False
+licenseIsOsiApproved Zend_2_0 = False
+licenseIsOsiApproved Zimbra_1_3 = False
+licenseIsOsiApproved Zimbra_1_4 = False
+licenseIsOsiApproved Zlib_acknowledgement = False
+licenseIsOsiApproved Zlib = True
+licenseIsOsiApproved ZPL_1_1 = False
+licenseIsOsiApproved ZPL_2_0 = True
+licenseIsOsiApproved ZPL_2_1 = False
+
+-------------------------------------------------------------------------------
+-- Creation
+-------------------------------------------------------------------------------
+
+licenseIdList :: LicenseListVersion -> [LicenseId]
+licenseIdList LicenseListVersion_3_0 =
+    [ AGPL_1_0
+    ]
+    ++ bulkOfLicenses
+licenseIdList LicenseListVersion_3_2 =
+    [ AGPL_1_0_only
+    , AGPL_1_0_or_later
+    , Linux_OpenIB
+    , MIT_0
+    , ODC_By_1_0
+    , TU_Berlin_1_0
+    , TU_Berlin_2_0
+    ]
+    ++ bulkOfLicenses
+
+-- | Create a 'LicenseId' from a 'String'.
+mkLicenseId :: LicenseListVersion -> String -> Maybe LicenseId
+mkLicenseId LicenseListVersion_3_0 s = Map.lookup s stringLookup_3_0
+mkLicenseId LicenseListVersion_3_2 s = Map.lookup s stringLookup_3_2
+
+stringLookup_3_0 :: Map String LicenseId
+stringLookup_3_0 = Map.fromList $ map (\i -> (licenseId i, i)) $
+    licenseIdList LicenseListVersion_3_0
+
+stringLookup_3_2 :: Map String LicenseId
+stringLookup_3_2 = Map.fromList $ map (\i -> (licenseId i, i)) $
+    licenseIdList LicenseListVersion_3_2
+
+--  | Licenses in all SPDX License lists
+bulkOfLicenses :: [LicenseId]
+bulkOfLicenses =
+    [ NullBSD
+    , AAL
+    , Abstyles
+    , Adobe_2006
+    , Adobe_Glyph
+    , ADSL
+    , AFL_1_1
+    , AFL_1_2
+    , AFL_2_0
+    , AFL_2_1
+    , AFL_3_0
+    , Afmparse
+    , AGPL_3_0_only
+    , AGPL_3_0_or_later
+    , Aladdin
+    , AMDPLPA
+    , AML
+    , AMPAS
+    , ANTLR_PD
+    , Apache_1_0
+    , Apache_1_1
+    , Apache_2_0
+    , APAFML
+    , APL_1_0
+    , APSL_1_0
+    , APSL_1_1
+    , APSL_1_2
+    , APSL_2_0
+    , Artistic_1_0_cl8
+    , Artistic_1_0_Perl
+    , Artistic_1_0
+    , Artistic_2_0
+    , Bahyph
+    , Barr
+    , Beerware
+    , BitTorrent_1_0
+    , BitTorrent_1_1
+    , Borceux
+    , BSD_1_Clause
+    , BSD_2_Clause_FreeBSD
+    , BSD_2_Clause_NetBSD
+    , BSD_2_Clause_Patent
+    , BSD_2_Clause
+    , BSD_3_Clause_Attribution
+    , BSD_3_Clause_Clear
+    , BSD_3_Clause_LBNL
+    , BSD_3_Clause_No_Nuclear_License_2014
+    , BSD_3_Clause_No_Nuclear_License
+    , BSD_3_Clause_No_Nuclear_Warranty
+    , BSD_3_Clause
+    , BSD_4_Clause_UC
+    , BSD_4_Clause
+    , BSD_Protection
+    , BSD_Source_Code
+    , BSL_1_0
+    , Bzip2_1_0_5
+    , Bzip2_1_0_6
+    , Caldera
+    , CATOSL_1_1
+    , CC_BY_1_0
+    , CC_BY_2_0
+    , CC_BY_2_5
+    , CC_BY_3_0
+    , CC_BY_4_0
+    , CC_BY_NC_1_0
+    , CC_BY_NC_2_0
+    , CC_BY_NC_2_5
+    , CC_BY_NC_3_0
+    , CC_BY_NC_4_0
+    , CC_BY_NC_ND_1_0
+    , CC_BY_NC_ND_2_0
+    , CC_BY_NC_ND_2_5
+    , CC_BY_NC_ND_3_0
+    , CC_BY_NC_ND_4_0
+    , CC_BY_NC_SA_1_0
+    , CC_BY_NC_SA_2_0
+    , CC_BY_NC_SA_2_5
+    , CC_BY_NC_SA_3_0
+    , CC_BY_NC_SA_4_0
+    , CC_BY_ND_1_0
+    , CC_BY_ND_2_0
+    , CC_BY_ND_2_5
+    , CC_BY_ND_3_0
+    , CC_BY_ND_4_0
+    , CC_BY_SA_1_0
+    , CC_BY_SA_2_0
+    , CC_BY_SA_2_5
+    , CC_BY_SA_3_0
+    , CC_BY_SA_4_0
+    , CC0_1_0
+    , CDDL_1_0
+    , CDDL_1_1
+    , CDLA_Permissive_1_0
+    , CDLA_Sharing_1_0
+    , CECILL_1_0
+    , CECILL_1_1
+    , CECILL_2_0
+    , CECILL_2_1
+    , CECILL_B
+    , CECILL_C
+    , ClArtistic
+    , CNRI_Jython
+    , CNRI_Python_GPL_Compatible
+    , CNRI_Python
+    , Condor_1_1
+    , CPAL_1_0
+    , CPL_1_0
+    , CPOL_1_02
+    , Crossword
+    , CrystalStacker
+    , CUA_OPL_1_0
+    , Cube
+    , Curl
+    , D_FSL_1_0
+    , Diffmark
+    , DOC
+    , Dotseqn
+    , DSDP
+    , Dvipdfm
+    , ECL_1_0
+    , ECL_2_0
+    , EFL_1_0
+    , EFL_2_0
+    , EGenix
+    , Entessa
+    , EPL_1_0
+    , EPL_2_0
+    , ErlPL_1_1
+    , EUDatagrid
+    , EUPL_1_0
+    , EUPL_1_1
+    , EUPL_1_2
+    , Eurosym
+    , Fair
+    , Frameworx_1_0
+    , FreeImage
+    , FSFAP
+    , FSFUL
+    , FSFULLR
+    , FTL
+    , GFDL_1_1_only
+    , GFDL_1_1_or_later
+    , GFDL_1_2_only
+    , GFDL_1_2_or_later
+    , GFDL_1_3_only
+    , GFDL_1_3_or_later
+    , Giftware
+    , GL2PS
+    , Glide
+    , Glulxe
+    , Gnuplot
+    , GPL_1_0_only
+    , GPL_1_0_or_later
+    , GPL_2_0_only
+    , GPL_2_0_or_later
+    , GPL_3_0_only
+    , GPL_3_0_or_later
+    , GSOAP_1_3b
+    , HaskellReport
+    , HPND
+    , IBM_pibs
+    , ICU
+    , IJG
+    , ImageMagick
+    , IMatix
+    , Imlib2
+    , Info_ZIP
+    , Intel_ACPI
+    , Intel
+    , Interbase_1_0
+    , IPA
+    , IPL_1_0
+    , ISC
+    , JasPer_2_0
+    , JSON
+    , LAL_1_2
+    , LAL_1_3
+    , Latex2e
+    , Leptonica
+    , LGPL_2_0_only
+    , LGPL_2_0_or_later
+    , LGPL_2_1_only
+    , LGPL_2_1_or_later
+    , LGPL_3_0_only
+    , LGPL_3_0_or_later
+    , LGPLLR
+    , Libpng
+    , Libtiff
+    , LiLiQ_P_1_1
+    , LiLiQ_R_1_1
+    , LiLiQ_Rplus_1_1
+    , LPL_1_0
+    , LPL_1_02
+    , LPPL_1_0
+    , LPPL_1_1
+    , LPPL_1_2
+    , LPPL_1_3a
+    , LPPL_1_3c
+    , MakeIndex
+    , MirOS
+    , MIT_advertising
+    , MIT_CMU
+    , MIT_enna
+    , MIT_feh
+    , MIT
+    , MITNFA
+    , Motosoto
+    , Mpich2
+    , MPL_1_0
+    , MPL_1_1
+    , MPL_2_0_no_copyleft_exception
+    , MPL_2_0
+    , MS_PL
+    , MS_RL
+    , MTLL
+    , Multics
+    , Mup
+    , NASA_1_3
+    , Naumen
+    , NBPL_1_0
+    , NCSA
+    , Net_SNMP
+    , NetCDF
+    , Newsletr
+    , NGPL
+    , NLOD_1_0
+    , NLPL
+    , Nokia
+    , NOSL
+    , Noweb
+    , NPL_1_0
+    , NPL_1_1
+    , NPOSL_3_0
+    , NRL
+    , NTP
+    , OCCT_PL
+    , OCLC_2_0
+    , ODbL_1_0
+    , OFL_1_0
+    , OFL_1_1
+    , OGTSL
+    , OLDAP_1_1
+    , OLDAP_1_2
+    , OLDAP_1_3
+    , OLDAP_1_4
+    , OLDAP_2_0_1
+    , OLDAP_2_0
+    , OLDAP_2_1
+    , OLDAP_2_2_1
+    , OLDAP_2_2_2
+    , OLDAP_2_2
+    , OLDAP_2_3
+    , OLDAP_2_4
+    , OLDAP_2_5
+    , OLDAP_2_6
+    , OLDAP_2_7
+    , OLDAP_2_8
+    , OML
+    , OpenSSL
+    , OPL_1_0
+    , OSET_PL_2_1
+    , OSL_1_0
+    , OSL_1_1
+    , OSL_2_0
+    , OSL_2_1
+    , OSL_3_0
+    , PDDL_1_0
+    , PHP_3_0
+    , PHP_3_01
+    , Plexus
+    , PostgreSQL
+    , Psfrag
+    , Psutils
+    , Python_2_0
+    , Qhull
+    , QPL_1_0
+    , Rdisc
+    , RHeCos_1_1
+    , RPL_1_1
+    , RPL_1_5
+    , RPSL_1_0
+    , RSA_MD
+    , RSCPL
+    , Ruby
+    , SAX_PD
+    , Saxpath
+    , SCEA
+    , Sendmail
+    , SGI_B_1_0
+    , SGI_B_1_1
+    , SGI_B_2_0
+    , SimPL_2_0
+    , SISSL_1_2
+    , SISSL
+    , Sleepycat
+    , SMLNJ
+    , SMPPL
+    , SNIA
+    , Spencer_86
+    , Spencer_94
+    , Spencer_99
+    , SPL_1_0
+    , SugarCRM_1_1_3
+    , SWL
+    , TCL
+    , TCP_wrappers
+    , TMate
+    , TORQUE_1_1
+    , TOSL
+    , Unicode_DFS_2015
+    , Unicode_DFS_2016
+    , Unicode_TOU
+    , Unlicense
+    , UPL_1_0
+    , Vim
+    , VOSTROM
+    , VSL_1_0
+    , W3C_19980720
+    , W3C_20150513
+    , W3C
+    , Watcom_1_0
+    , Wsuipa
+    , WTFPL
+    , X11
+    , Xerox
+    , XFree86_1_1
+    , Xinetd
+    , Xnet
+    , Xpp
+    , XSkat
+    , YPL_1_0
+    , YPL_1_1
+    , Zed
+    , Zend_2_0
+    , Zimbra_1_3
+    , Zimbra_1_4
+    , Zlib_acknowledgement
+    , Zlib
+    , ZPL_1_1
+    , ZPL_2_0
+    , ZPL_2_1
+    ]
diff --git a/cabal/Cabal/Distribution/SPDX/LicenseListVersion.hs b/cabal/Cabal/Distribution/SPDX/LicenseListVersion.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/SPDX/LicenseListVersion.hs
@@ -0,0 +1,16 @@
+module Distribution.SPDX.LicenseListVersion (
+    LicenseListVersion (..),
+    cabalSpecVersionToSPDXListVersion,
+    ) where
+
+import Distribution.CabalSpecVersion
+
+-- | SPDX License List version @Cabal@ is aware of.
+data LicenseListVersion
+    = LicenseListVersion_3_0
+    | LicenseListVersion_3_2
+  deriving (Eq, Ord, Show, Enum, Bounded)
+
+cabalSpecVersionToSPDXListVersion :: CabalSpecVersion -> LicenseListVersion
+cabalSpecVersionToSPDXListVersion CabalSpecV2_4 = LicenseListVersion_3_2
+cabalSpecVersionToSPDXListVersion _             = LicenseListVersion_3_0
diff --git a/cabal/Cabal/Distribution/SPDX/LicenseReference.hs b/cabal/Cabal/Distribution/SPDX/LicenseReference.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/SPDX/LicenseReference.hs
@@ -0,0 +1,79 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+module Distribution.SPDX.LicenseReference (
+    LicenseRef,
+    licenseRef,
+    licenseDocumentRef,
+    mkLicenseRef,
+    mkLicenseRef',
+    ) where
+
+import Prelude ()
+import Distribution.Compat.Prelude
+
+import Distribution.Utils.Generic (isAsciiAlphaNum)
+import Distribution.Pretty
+import Distribution.Parsec.Class
+
+import qualified Distribution.Compat.CharParsing as P
+import qualified Text.PrettyPrint as Disp
+
+-- | A user defined license reference denoted by @LicenseRef-[idstring]@ (for a license not on the SPDX License List);
+data LicenseRef = LicenseRef
+    { _lrDocument :: !(Maybe String)
+    , _lrLicense  :: !String
+    }
+  deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)
+
+-- | License reference.
+licenseRef :: LicenseRef -> String
+licenseRef = _lrLicense
+
+-- | Document reference.
+licenseDocumentRef :: LicenseRef -> Maybe String
+licenseDocumentRef = _lrDocument
+
+instance Binary LicenseRef
+
+instance NFData LicenseRef where
+    rnf (LicenseRef d l) = rnf d `seq` rnf l
+
+instance Pretty LicenseRef where
+    pretty (LicenseRef Nothing l) = Disp.text "LicenseRef-" <<>> Disp.text l
+    pretty (LicenseRef (Just d) l) =
+        Disp.text "DocumentRef-" <<>> Disp.text d <<>> Disp.char ':' <<>> Disp.text "LicenseRef-" <<>> Disp.text l
+
+instance Parsec LicenseRef where
+    parsec = name <|> doc
+      where
+        name = do
+            _ <- P.string "LicenseRef-"
+            n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'
+            pure (LicenseRef Nothing n)
+
+        doc = do
+            _ <- P.string "DocumentRef-"
+            d <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'
+            _ <- P.char ':'
+            _ <- P.string "LicenseRef-"
+            n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'
+            pure (LicenseRef (Just d) n)
+
+-- | Create 'LicenseRef' from optional document ref and name.
+mkLicenseRef :: Maybe String -> String -> Maybe LicenseRef
+mkLicenseRef d l = do
+    d' <- traverse checkIdString d
+    l' <- checkIdString l
+    pure (LicenseRef d' l')
+  where
+    checkIdString s
+        | all (\c -> isAsciiAlphaNum c || c == '-' || c == '.') s = Just s
+        | otherwise = Nothing
+
+-- | Like 'mkLicenseRef' but convert invalid characters into @-@.
+mkLicenseRef' :: Maybe String -> String -> LicenseRef
+mkLicenseRef' d l = LicenseRef (fmap f d) (f l)
+  where
+    f = map g
+    g c | isAsciiAlphaNum c || c == '-' || c == '.' = c
+        | otherwise                                 = '-'
diff --git a/cabal/Cabal/Distribution/Simple.hs b/cabal/Cabal/Distribution/Simple.hs
--- a/cabal/Cabal/Distribution/Simple.hs
+++ b/cabal/Cabal/Distribution/Simple.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE RankNTypes #-}
 
@@ -59,6 +58,7 @@
   ) where
 
 import Prelude ()
+import Control.Exception (try)
 import Distribution.Compat.Prelude
 
 -- local
@@ -99,7 +99,8 @@
 import System.Directory   (removeFile, doesFileExist
                           ,doesDirectoryExist, removeDirectoryRecursive)
 import System.Exit                          (exitWith,ExitCode(..))
-import System.FilePath                      (searchPathSeparator)
+import System.FilePath                      (searchPathSeparator, takeDirectory, (</>), splitDirectories, dropDrive)
+import Distribution.Compat.Directory        (makeAbsolute)
 import Distribution.Compat.Environment      (getEnvironment)
 import Distribution.Compat.GetShortPathName (getShortPathName)
 
@@ -248,9 +249,10 @@
 buildAction hooks flags args = do
   distPref <- findDistPrefOrDefault (buildDistPref flags)
   let verbosity = fromFlag $ buildVerbosity flags
-      flags' = flags { buildDistPref = toFlag distPref }
-
   lbi <- getBuildConfig hooks verbosity distPref
+  let flags' = flags { buildDistPref = toFlag distPref
+                     , buildCabalFilePath = maybeToFlag (cabalFilePath lbi)}
+
   progs <- reconfigurePrograms verbosity
              (buildProgramPaths flags')
              (buildProgramArgs flags')
@@ -288,7 +290,10 @@
 hscolourAction hooks flags args = do
     distPref <- findDistPrefOrDefault (hscolourDistPref flags)
     let verbosity = fromFlag $ hscolourVerbosity flags
-        flags' = flags { hscolourDistPref = toFlag distPref }
+    lbi <- getBuildConfig hooks verbosity distPref
+    let flags' = flags { hscolourDistPref = toFlag distPref
+                       , hscolourCabalFilePath = maybeToFlag (cabalFilePath lbi)}
+
     hookedAction preHscolour hscolourHook postHscolour
                  (getBuildConfig hooks verbosity distPref)
                  hooks flags' args
@@ -313,9 +318,10 @@
 haddockAction hooks flags args = do
   distPref <- findDistPrefOrDefault (haddockDistPref flags)
   let verbosity = fromFlag $ haddockVerbosity flags
-      flags' = flags { haddockDistPref = toFlag distPref }
-
   lbi <- getBuildConfig hooks verbosity distPref
+  let flags' = flags { haddockDistPref = toFlag distPref
+                     , haddockCabalFilePath = maybeToFlag (cabalFilePath lbi)}
+
   progs <- reconfigurePrograms verbosity
              (haddockProgramPaths flags')
              (haddockProgramArgs flags')
@@ -323,13 +329,18 @@
 
   hookedAction preHaddock haddockHook postHaddock
                (return lbi { withPrograms = progs })
-               hooks flags' args
+               hooks flags' { haddockArgs = args } args
 
 cleanAction :: UserHooks -> CleanFlags -> Args -> IO ()
 cleanAction hooks flags args = do
     distPref <- findDistPrefOrDefault (cleanDistPref flags)
-    let flags' = flags { cleanDistPref = toFlag distPref }
 
+    elbi <- tryGetBuildConfig hooks verbosity distPref
+    let flags' = flags { cleanDistPref = toFlag distPref
+                       , cleanCabalFilePath = case elbi of
+                           Left _ -> mempty
+                           Right lbi -> maybeToFlag (cabalFilePath lbi)}
+
     pbi <- preClean hooks args flags'
 
     (_, ppd) <- confPkgDescr hooks verbosity Nothing
@@ -354,7 +365,9 @@
 copyAction hooks flags args = do
     distPref <- findDistPrefOrDefault (copyDistPref flags)
     let verbosity = fromFlag $ copyVerbosity flags
-        flags' = flags { copyDistPref = toFlag distPref }
+    lbi <- getBuildConfig hooks verbosity distPref
+    let flags' = flags { copyDistPref = toFlag distPref
+                       , copyCabalFilePath = maybeToFlag (cabalFilePath lbi)}
     hookedAction preCopy copyHook postCopy
                  (getBuildConfig hooks verbosity distPref)
                  hooks flags' { copyArgs = args } args
@@ -363,7 +376,9 @@
 installAction hooks flags args = do
     distPref <- findDistPrefOrDefault (installDistPref flags)
     let verbosity = fromFlag $ installVerbosity flags
-        flags' = flags { installDistPref = toFlag distPref }
+    lbi <- getBuildConfig hooks verbosity distPref
+    let flags' = flags { installDistPref = toFlag distPref
+                       , installCabalFilePath = maybeToFlag (cabalFilePath lbi)}
     hookedAction preInst instHook postInst
                  (getBuildConfig hooks verbosity distPref)
                  hooks flags' args
@@ -427,7 +442,9 @@
 registerAction hooks flags args = do
     distPref <- findDistPrefOrDefault (regDistPref flags)
     let verbosity = fromFlag $ regVerbosity flags
-        flags' = flags { regDistPref = toFlag distPref }
+    lbi <- getBuildConfig hooks verbosity distPref
+    let flags' = flags { regDistPref = toFlag distPref
+                       , regCabalFilePath = maybeToFlag (cabalFilePath lbi)}
     hookedAction preReg regHook postReg
                  (getBuildConfig hooks verbosity distPref)
                  hooks flags' { regArgs = args } args
@@ -436,7 +453,9 @@
 unregisterAction hooks flags args = do
     distPref <- findDistPrefOrDefault (regDistPref flags)
     let verbosity = fromFlag $ regVerbosity flags
-        flags' = flags { regDistPref = toFlag distPref }
+    lbi <- getBuildConfig hooks verbosity distPref
+    let flags' = flags { regDistPref = toFlag distPref
+                       , regCabalFilePath = maybeToFlag (cabalFilePath lbi)}
     hookedAction preUnreg unregHook postUnreg
                  (getBuildConfig hooks verbosity distPref)
                  hooks flags' args
@@ -487,7 +506,13 @@
 
 sanityCheckHookedBuildInfo _ _ = return ()
 
+-- | Try to read the 'localBuildInfoFile'
+tryGetBuildConfig :: UserHooks -> Verbosity -> FilePath
+                  -> IO (Either ConfigStateFileError LocalBuildInfo)
+tryGetBuildConfig u v = try . getBuildConfig u v
 
+
+-- | Read the 'localBuildInfoFile' or throw an exception.
 getBuildConfig :: UserHooks -> Verbosity -> FilePath -> IO LocalBuildInfo
 getBuildConfig hooks verbosity distPref = do
   lbi_wo_programs <- getPersistBuildConfig distPref
@@ -618,12 +643,14 @@
     -- https://github.com/haskell/cabal/issues/158
     where oldCompatPostConf args flags pkg_descr lbi
               = do let verbosity = fromFlag (configVerbosity flags)
-                   confExists <- doesFileExist "configure"
+                       baseDir lbi' = fromMaybe "" (takeDirectory <$> cabalFilePath lbi')
+
+                   confExists <- doesFileExist $ (baseDir lbi) </> "configure"
                    when confExists $
                        runConfigureScript verbosity
                          backwardsCompatHack flags lbi
 
-                   pbi <- getHookedBuildInfo verbosity
+                   pbi <- getHookedBuildInfo (buildDir lbi) verbosity
                    sanityCheckHookedBuildInfo pkg_descr pbi
                    let pkg_descr' = updatePackageDescription pbi pkg_descr
                        lbi' = lbi { localPkgDescr = pkg_descr' }
@@ -636,26 +663,27 @@
     = simpleUserHooks
       {
        postConf    = defaultPostConf,
-       preBuild    = readHookWithArgs buildVerbosity,
-       preCopy     = readHookWithArgs copyVerbosity,
-       preClean    = readHook cleanVerbosity,
-       preInst     = readHook installVerbosity,
-       preHscolour = readHook hscolourVerbosity,
-       preHaddock  = readHook haddockVerbosity,
-       preReg      = readHook regVerbosity,
-       preUnreg    = readHook regVerbosity
+       preBuild    = readHookWithArgs buildVerbosity buildDistPref, -- buildCabalFilePath,
+       preCopy     = readHookWithArgs copyVerbosity copyDistPref,
+       preClean    = readHook cleanVerbosity cleanDistPref,
+       preInst     = readHook installVerbosity installDistPref,
+       preHscolour = readHook hscolourVerbosity hscolourDistPref,
+       preHaddock  = readHookWithArgs haddockVerbosity haddockDistPref,
+       preReg      = readHook regVerbosity regDistPref,
+       preUnreg    = readHook regVerbosity regDistPref
       }
     where defaultPostConf :: Args -> ConfigFlags -> PackageDescription
                           -> LocalBuildInfo -> IO ()
           defaultPostConf args flags pkg_descr lbi
               = do let verbosity = fromFlag (configVerbosity flags)
-                   confExists <- doesFileExist "configure"
+                       baseDir lbi' = fromMaybe "" (takeDirectory <$> cabalFilePath lbi')
+                   confExists <- doesFileExist $ (baseDir lbi) </> "configure"
                    if confExists
                      then runConfigureScript verbosity
                             backwardsCompatHack flags lbi
                      else die "configure script not found."
 
-                   pbi <- getHookedBuildInfo verbosity
+                   pbi <- getHookedBuildInfo (buildDir lbi) verbosity
                    sanityCheckHookedBuildInfo pkg_descr pbi
                    let pkg_descr' = updatePackageDescription pbi pkg_descr
                        lbi' = lbi { localPkgDescr = pkg_descr' }
@@ -663,17 +691,23 @@
 
           backwardsCompatHack = False
 
-          readHookWithArgs :: (a -> Flag Verbosity) -> Args -> a
+          readHookWithArgs :: (a -> Flag Verbosity)
+                           -> (a -> Flag FilePath)
+                           -> Args -> a
                            -> IO HookedBuildInfo
-          readHookWithArgs get_verbosity _ flags = do
-              getHookedBuildInfo verbosity
+          readHookWithArgs get_verbosity get_dist_pref _ flags = do
+              dist_dir <- findDistPrefOrDefault (get_dist_pref flags)
+              getHookedBuildInfo (dist_dir </> "build") verbosity
             where
               verbosity = fromFlag (get_verbosity flags)
 
-          readHook :: (a -> Flag Verbosity) -> Args -> a -> IO HookedBuildInfo
-          readHook get_verbosity a flags = do
+          readHook :: (a -> Flag Verbosity)
+                   -> (a -> Flag FilePath)
+                   -> Args -> a -> IO HookedBuildInfo
+          readHook get_verbosity get_dist_pref a flags = do
               noExtraFlags a
-              getHookedBuildInfo verbosity
+              dist_dir <- findDistPrefOrDefault (get_dist_pref flags)
+              getHookedBuildInfo (dist_dir </> "build") verbosity
             where
               verbosity = fromFlag (get_verbosity flags)
 
@@ -690,6 +724,29 @@
   -- to ccFlags
   -- We don't try and tell configure which ld to use, as we don't have
   -- a way to pass its flags too
+  configureFile <- makeAbsolute $
+    fromMaybe "." (takeDirectory <$> cabalFilePath lbi) </> "configure"
+  -- autoconf is fussy about filenames, and has a set of forbidden
+  -- characters that can't appear in the build directory, etc:
+  -- https://www.gnu.org/software/autoconf/manual/autoconf.html#File-System-Conventions
+  --
+  -- This has caused hard-to-debug failures in the past (#5368), so we
+  -- detect some cases early and warn with a clear message. Windows's
+  -- use of backslashes is problematic here, so we'll switch to
+  -- slashes, but we do still want to fail on backslashes in POSIX
+  -- paths.
+  --
+  -- TODO: We don't check for colons, tildes or leading dashes. We
+  -- also should check the builddir's path, destdir, and all other
+  -- paths as well.
+  let configureFile' = intercalate "/" $ splitDirectories configureFile
+  for_ badAutoconfCharacters $ \(c, cname) ->
+    when (c `elem` dropDrive configureFile') $
+      warn verbosity $
+           "The path to the './configure' script, '" ++ configureFile'
+        ++ "', contains the character '" ++ [c] ++ "' (" ++ cname ++ ")."
+        ++ " This may cause the script to fail with an obscure error, or for"
+        ++ " building the package to fail later."
   let extraPath = fromNubList $ configProgramPathExtra flags
   let cflagsEnv = maybe (unwords ccFlags) (++ (" " ++ unwords ccFlags))
                   $ lookup "CFLAGS" env
@@ -698,29 +755,54 @@
                 ((intercalate spSep extraPath ++ spSep)++) $ lookup "PATH" env
       overEnv = ("CFLAGS", Just cflagsEnv) :
                 [("PATH", Just pathEnv) | not (null extraPath)]
-      args' = args ++ ["CC=" ++ ccProgShort]
+      args' = configureFile':args ++ ["CC=" ++ ccProgShort]
       shProg = simpleProgram "sh"
       progDb = modifyProgramSearchPath
                (\p -> map ProgramSearchPathDir extraPath ++ p) emptyProgramDb
   shConfiguredProg <- lookupProgram shProg
                       `fmap` configureProgram  verbosity shProg progDb
   case shConfiguredProg of
-      Just sh -> runProgramInvocation verbosity
+      Just sh -> runProgramInvocation verbosity $
                  (programInvocation (sh {programOverrideEnv = overEnv}) args')
+                 { progInvokeCwd = Just (buildDir lbi) }
       Nothing -> die notFoundMsg
 
   where
-    args = "./configure" : configureArgs backwardsCompatHack flags
+    args = configureArgs backwardsCompatHack flags
 
+    badAutoconfCharacters =
+      [ (' ', "space")
+      , ('\t', "tab")
+      , ('\n', "newline")
+      , ('\0', "null")
+      , ('"', "double quote")
+      , ('#', "hash")
+      , ('$', "dollar sign")
+      , ('&', "ampersand")
+      , ('\'', "single quote")
+      , ('(', "left bracket")
+      , (')', "right bracket")
+      , ('*', "star")
+      , (';', "semicolon")
+      , ('<', "less-than sign")
+      , ('=', "equals sign")
+      , ('>', "greater-than sign")
+      , ('?', "question mark")
+      , ('[', "left square bracket")
+      , ('\\', "backslash")
+      , ('`', "backtick")
+      , ('|', "pipe")
+      ]
+
     notFoundMsg = "The package has a './configure' script. "
                ++ "If you are on Windows, This requires a "
                ++ "Unix compatibility toolchain such as MinGW+MSYS or Cygwin. "
                ++ "If you are not on Windows, ensure that an 'sh' command "
                ++ "is discoverable in your path."
 
-getHookedBuildInfo :: Verbosity -> IO HookedBuildInfo
-getHookedBuildInfo verbosity = do
-  maybe_infoFile <- defaultHookedPackageDesc
+getHookedBuildInfo :: FilePath -> Verbosity -> IO HookedBuildInfo
+getHookedBuildInfo build_dir verbosity = do
+  maybe_infoFile <- findHookedPackageDesc build_dir
   case maybe_infoFile of
     Nothing       -> return emptyHookedBuildInfo
     Just infoFile -> do
@@ -742,7 +824,7 @@
 defaultInstallHook pkg_descr localbuildinfo _ flags = do
   let copyFlags = defaultCopyFlags {
                       copyDistPref   = installDistPref flags,
-                      copyDest       = toFlag NoCopyDest,
+                      copyDest       = installDest     flags,
                       copyVerbosity  = installVerbosity flags
                   }
   install pkg_descr localbuildinfo copyFlags
diff --git a/cabal/Cabal/Distribution/Simple/Bench.hs b/cabal/Cabal/Distribution/Simple/Bench.hs
--- a/cabal/Cabal/Distribution/Simple/Bench.hs
+++ b/cabal/Cabal/Distribution/Simple/Bench.hs
@@ -53,7 +53,7 @@
         doBench bm =
             case PD.benchmarkInterface bm of
               PD.BenchmarkExeV10 _ _ -> do
-                  let cmd = LBI.buildDir lbi </> name </> name <.> exeExtension
+                  let cmd = LBI.buildDir lbi </> name </> name <.> exeExtension (LBI.hostPlatform lbi)
                       options = map (benchOption pkg_descr lbi bm) $
                                 benchmarkOptions flags
                   -- Check that the benchmark executable exists.
diff --git a/cabal/Cabal/Distribution/Simple/Build.hs b/cabal/Cabal/Distribution/Simple/Build.hs
--- a/cabal/Cabal/Distribution/Simple/Build.hs
+++ b/cabal/Cabal/Distribution/Simple/Build.hs
@@ -23,6 +23,7 @@
     startInterpreter,
 
     initialBuildSteps,
+    createInternalPackageDB,
     componentInitialBuildSteps,
     writeAutogenFiles,
   ) where
@@ -46,8 +47,6 @@
 import Distribution.Backpack.DescribeUnitId
 import qualified Distribution.Simple.GHC   as GHC
 import qualified Distribution.Simple.GHCJS as GHCJS
-import qualified Distribution.Simple.JHC   as JHC
-import qualified Distribution.Simple.LHC   as LHC
 import qualified Distribution.Simple.UHC   as UHC
 import qualified Distribution.Simple.HaskellSuite as HaskellSuite
 import qualified Distribution.Simple.PackageIndex as Index
@@ -172,8 +171,9 @@
   let clbi = targetCLBI target
       comp = targetComponent target
       lbi' = lbiForComponent comp lbi
+      replFlags = replReplOptions flags
   componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity
-  replComponent verbosity pkg_descr lbi' suffixes comp clbi distPref
+  replComponent replFlags verbosity pkg_descr lbi' suffixes comp clbi distPref
 
 
 -- | Start an interpreter without loading any package files.
@@ -341,7 +341,8 @@
         exs = Set.fromList extras
 
 
-replComponent :: Verbosity
+replComponent :: [String]
+              -> Verbosity
               -> PackageDescription
               -> LocalBuildInfo
               -> [PPSuffixHandler]
@@ -349,29 +350,29 @@
               -> ComponentLocalBuildInfo
               -> FilePath
               -> IO ()
-replComponent verbosity pkg_descr lbi suffixes
+replComponent replFlags verbosity pkg_descr lbi suffixes
                comp@(CLib lib) clbi _ = do
     preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes
     extras <- preprocessExtras verbosity comp lbi
     let libbi = libBuildInfo lib
         lib' = lib { libBuildInfo = libbi { cSources = cSources libbi ++ extras } }
-    replLib verbosity pkg_descr lbi lib' clbi
+    replLib replFlags verbosity pkg_descr lbi lib' clbi
 
-replComponent verbosity pkg_descr lbi suffixes
+replComponent replFlags verbosity pkg_descr lbi suffixes
                comp@(CFLib flib) clbi _ = do
     preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes
-    replFLib verbosity pkg_descr lbi flib clbi
+    replFLib replFlags verbosity pkg_descr lbi flib clbi
 
-replComponent verbosity pkg_descr lbi suffixes
+replComponent replFlags verbosity pkg_descr lbi suffixes
                comp@(CExe exe) clbi _ = do
     preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes
     extras <- preprocessExtras verbosity comp lbi
     let ebi = buildInfo exe
         exe' = exe { buildInfo = ebi { cSources = cSources ebi ++ extras } }
-    replExe verbosity pkg_descr lbi exe' clbi
+    replExe replFlags verbosity pkg_descr lbi exe' clbi
 
 
-replComponent verbosity pkg_descr lbi suffixes
+replComponent replFlags verbosity pkg_descr lbi suffixes
                comp@(CTest test@TestSuite { testInterface = TestSuiteExeV10{} })
                clbi _distPref = do
     let exe = testSuiteExeV10AsExe test
@@ -379,10 +380,10 @@
     extras <- preprocessExtras verbosity comp lbi
     let ebi = buildInfo exe
         exe' = exe { buildInfo = ebi { cSources = cSources ebi ++ extras } }
-    replExe verbosity pkg_descr lbi exe' clbi
+    replExe replFlags verbosity pkg_descr lbi exe' clbi
 
 
-replComponent verbosity pkg_descr lbi0 suffixes
+replComponent replFlags verbosity pkg_descr lbi0 suffixes
                comp@(CTest
                  test@TestSuite { testInterface = TestSuiteLibV09{} })
                clbi distPref = do
@@ -393,16 +394,16 @@
     extras <- preprocessExtras verbosity comp lbi
     let libbi = libBuildInfo lib
         lib' = lib { libBuildInfo = libbi { cSources = cSources libbi ++ extras } }
-    replLib verbosity pkg lbi lib' libClbi
+    replLib replFlags verbosity pkg lbi lib' libClbi
 
 
-replComponent verbosity _ _ _
+replComponent _ verbosity _ _ _
               (CTest TestSuite { testInterface = TestSuiteUnsupported tt })
               _ _ =
     die' verbosity $ "No support for building test suite type " ++ display tt
 
 
-replComponent verbosity pkg_descr lbi suffixes
+replComponent replFlags verbosity pkg_descr lbi suffixes
                comp@(CBench bm@Benchmark { benchmarkInterface = BenchmarkExeV10 {} })
                clbi _ = do
     let (exe, exeClbi) = benchmarkExeV10asExe bm clbi
@@ -410,10 +411,10 @@
     extras <- preprocessExtras verbosity comp lbi
     let ebi = buildInfo exe
         exe' = exe { buildInfo = ebi { cSources = cSources ebi ++ extras } }
-    replExe verbosity pkg_descr lbi exe' exeClbi
+    replExe replFlags verbosity pkg_descr lbi exe' exeClbi
 
 
-replComponent verbosity _ _ _
+replComponent _ verbosity _ _ _
               (CBench Benchmark { benchmarkInterface = BenchmarkUnsupported tt })
               _ _ =
     die' verbosity $ "No support for building benchmark type " ++ display tt
@@ -481,7 +482,6 @@
                 }
     pkg = pkg_descr {
             package      = (package pkg_descr) { pkgName = mkPackageName $ unMungedPackageName compat_name }
-          , buildDepends = targetBuildDepends $ testBuildInfo test
           , executables  = []
           , testSuites   = []
           , subLibraries = [lib]
@@ -569,7 +569,7 @@
       [ simpleConfiguredProgram toolName' (FoundOnSystem toolLocation)
       | toolName <- getAllInternalToolDependencies pkg bi
       , let toolName' = unUnqualComponentName toolName
-      , let toolLocation = buildDir lbi </> toolName' </> toolName' <.> exeExtension ]
+      , let toolLocation = buildDir lbi </> toolName' </> toolName' <.> exeExtension (hostPlatform lbi) ]
 
 
 -- TODO: build separate libs in separate dirs so that we can build
@@ -581,8 +581,6 @@
   case compilerFlavor (compiler lbi) of
     GHC   -> GHC.buildLib   verbosity numJobs pkg_descr lbi lib clbi
     GHCJS -> GHCJS.buildLib verbosity numJobs pkg_descr lbi lib clbi
-    JHC   -> JHC.buildLib   verbosity         pkg_descr lbi lib clbi
-    LHC   -> LHC.buildLib   verbosity         pkg_descr lbi lib clbi
     UHC   -> UHC.buildLib   verbosity         pkg_descr lbi lib clbi
     HaskellSuite {} -> HaskellSuite.buildLib verbosity pkg_descr lbi lib clbi
     _    -> die' verbosity "Building is not supported with this compiler."
@@ -606,34 +604,35 @@
   case compilerFlavor (compiler lbi) of
     GHC   -> GHC.buildExe   verbosity numJobs pkg_descr lbi exe clbi
     GHCJS -> GHCJS.buildExe verbosity numJobs pkg_descr lbi exe clbi
-    JHC   -> JHC.buildExe   verbosity         pkg_descr lbi exe clbi
-    LHC   -> LHC.buildExe   verbosity         pkg_descr lbi exe clbi
     UHC   -> UHC.buildExe   verbosity         pkg_descr lbi exe clbi
     _     -> die' verbosity "Building is not supported with this compiler."
 
-replLib :: Verbosity -> PackageDescription -> LocalBuildInfo
-                     -> Library            -> ComponentLocalBuildInfo -> IO ()
-replLib verbosity pkg_descr lbi lib clbi =
+replLib :: [String]        -> Verbosity -> PackageDescription
+        -> LocalBuildInfo  -> Library   -> ComponentLocalBuildInfo
+        -> IO ()
+replLib replFlags verbosity pkg_descr lbi lib clbi =
   case compilerFlavor (compiler lbi) of
     -- 'cabal repl' doesn't need to support 'ghc --make -j', so we just pass
     -- NoFlag as the numJobs parameter.
-    GHC   -> GHC.replLib   verbosity NoFlag pkg_descr lbi lib clbi
-    GHCJS -> GHCJS.replLib verbosity NoFlag pkg_descr lbi lib clbi
+    GHC   -> GHC.replLib   replFlags verbosity NoFlag pkg_descr lbi lib clbi
+    GHCJS -> GHCJS.replLib replFlags verbosity NoFlag pkg_descr lbi lib clbi
     _     -> die' verbosity "A REPL is not supported for this compiler."
 
-replExe :: Verbosity -> PackageDescription -> LocalBuildInfo
-                     -> Executable         -> ComponentLocalBuildInfo -> IO ()
-replExe verbosity pkg_descr lbi exe clbi =
+replExe :: [String]        -> Verbosity  -> PackageDescription
+        -> LocalBuildInfo  -> Executable -> ComponentLocalBuildInfo
+        -> IO ()
+replExe replFlags verbosity pkg_descr lbi exe clbi =
   case compilerFlavor (compiler lbi) of
-    GHC   -> GHC.replExe   verbosity NoFlag pkg_descr lbi exe clbi
-    GHCJS -> GHCJS.replExe verbosity NoFlag pkg_descr lbi exe clbi
+    GHC   -> GHC.replExe   replFlags verbosity NoFlag pkg_descr lbi exe clbi
+    GHCJS -> GHCJS.replExe replFlags verbosity NoFlag pkg_descr lbi exe clbi
     _     -> die' verbosity "A REPL is not supported for this compiler."
 
-replFLib :: Verbosity -> PackageDescription -> LocalBuildInfo
-                      -> ForeignLib         -> ComponentLocalBuildInfo -> IO ()
-replFLib verbosity pkg_descr lbi exe clbi =
+replFLib :: [String]        -> Verbosity  -> PackageDescription
+         -> LocalBuildInfo  -> ForeignLib -> ComponentLocalBuildInfo
+         -> IO ()
+replFLib replFlags verbosity pkg_descr lbi exe clbi =
   case compilerFlavor (compiler lbi) of
-    GHC -> GHC.replFLib verbosity NoFlag pkg_descr lbi exe clbi
+    GHC -> GHC.replFLib replFlags verbosity NoFlag pkg_descr lbi exe clbi
     _   -> die' verbosity "A REPL is not supported for this compiler."
 
 -- | Runs 'componentInitialBuildSteps' on every configured component.
@@ -673,7 +672,7 @@
       pathsModuleDir = takeDirectory pathsModulePath
   -- Ensure that the directory exists!
   createDirectoryIfMissingVerbose verbosity True pathsModuleDir
-  rewriteFile verbosity pathsModulePath (Build.PathsModule.generate pkg lbi clbi)
+  rewriteFileEx verbosity pathsModulePath (Build.PathsModule.generate pkg lbi clbi)
 
   --TODO: document what we're doing here, and move it to its own function
   case clbi of
@@ -688,10 +687,11 @@
             let sigPath = autogenComponentModulesDir lbi clbi
                       </> ModuleName.toFilePath mod_name <.> "hsig"
             createDirectoryIfMissingVerbose verbosity True (takeDirectory sigPath)
-            rewriteFile verbosity sigPath $
+            rewriteFileEx verbosity sigPath $
+                "{-# OPTIONS_GHC -w #-}\n" ++
                 "{-# LANGUAGE NoImplicitPrelude #-}\n" ++
                 "signature " ++ display mod_name ++ " where"
     _ -> return ()
 
   let cppHeaderPath = autogenComponentModulesDir lbi clbi </> cppHeaderName
-  rewriteFile verbosity cppHeaderPath (Build.Macros.generate pkg lbi clbi)
+  rewriteFileEx verbosity cppHeaderPath (Build.Macros.generate pkg lbi clbi)
diff --git a/cabal/Cabal/Distribution/Simple/Build/PathsModule.hs b/cabal/Cabal/Distribution/Simple/Build/PathsModule.hs
--- a/cabal/Cabal/Distribution/Simple/Build/PathsModule.hs
+++ b/cabal/Cabal/Distribution/Simple/Build/PathsModule.hs
@@ -39,22 +39,33 @@
 
 generate :: PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> String
 generate pkg_descr lbi clbi =
-   let pragmas = cpp_pragma ++ ffi_pragmas ++ warning_pragmas
+   let pragmas =
+            cpp_pragma
+         ++ no_rebindable_syntax_pragma
+         ++ ffi_pragmas
+         ++ warning_pragmas
 
-       cpp_pragma | supports_cpp = "{-# LANGUAGE CPP #-}\n"
-                  | otherwise    = ""
+       cpp_pragma
+         | supports_cpp = "{-# LANGUAGE CPP #-}\n"
+         | otherwise    = ""
 
+       -- -XRebindableSyntax is problematic because when paired with
+       -- -XOverloadedLists, 'fromListN' is not in scope,
+       -- or -XOverloadedStrings 'fromString' is not in scope,
+       -- so we disable 'RebindableSyntax'.
+       no_rebindable_syntax_pragma
+         | supports_rebindable_syntax = "{-# LANGUAGE NoRebindableSyntax #-}\n"
+         | otherwise                  = ""
+
        ffi_pragmas
         | absolute = ""
         | supports_language_pragma =
           "{-# LANGUAGE ForeignFunctionInterface #-}\n"
         | otherwise =
-          "{-# OPTIONS_GHC -fffi #-}\n"++
-          "{-# OPTIONS_JHC -fffi #-}\n"
+          "{-# OPTIONS_GHC -fffi #-}\n"
 
        warning_pragmas =
-        "{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}\n"++
-        "{-# OPTIONS_GHC -fno-warn-implicit-prelude #-}\n"
+        "{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}\n"
 
        foreign_imports
         | absolute = ""
@@ -231,17 +242,18 @@
 
         paths_modulename = autogenPathsModuleName pkg_descr
 
-        get_prefix_stuff = get_prefix_win32 buildArch
+        get_prefix_stuff = get_prefix_win32 supports_cpp buildArch
 
         path_sep = show [pathSeparator]
 
-        supports_cpp = compilerFlavor (compiler lbi) == GHC
+        supports_cpp = supports_language_pragma
+        supports_rebindable_syntax= ghc_newer_than (mkVersion [7,0,1])
+        supports_language_pragma = ghc_newer_than (mkVersion [6,6,1])
 
-        supports_language_pragma =
-          (compilerFlavor (compiler lbi) == GHC &&
-            (compilerVersion (compiler lbi)
-              `withinRange` orLaterVersion (mkVersion [6,6,1]))) ||
-           compilerFlavor (compiler lbi) == GHCJS
+        ghc_newer_than minVersion =
+          case compilerCompatVersion GHC (compiler lbi) of
+            Nothing -> False
+            Just version -> version `withinRange` orLaterVersion minVersion
 
 -- | Generates the name of the environment variable controlling the path
 -- component of interest.
@@ -267,8 +279,8 @@
   "  let (bindir,_) = splitFileName exePath\n"++
   "  return ((bindir `minusFileName` bindirrel) `joinFileName` dirRel)\n"
 
-get_prefix_win32 :: Arch -> String
-get_prefix_win32 arch =
+get_prefix_win32 :: Bool -> Arch -> String
+get_prefix_win32 supports_cpp arch =
   "getPrefixDirRel :: FilePath -> IO FilePath\n"++
   "getPrefixDirRel dirRel = try_size 2048 -- plenty, PATH_MAX is 512 under Win32.\n"++
   "  where\n"++
@@ -282,12 +294,23 @@
   "              return ((bindir `minusFileName` bindirrel) `joinFileName` dirRel)\n"++
   "            | otherwise  -> try_size (size * 2)\n"++
   "\n"++
+  (case supports_cpp of
+    False -> ""
+    True  -> "#if defined(i386_HOST_ARCH)\n"++
+             "# define WINDOWS_CCONV stdcall\n"++
+             "#elif defined(x86_64_HOST_ARCH)\n"++
+             "# define WINDOWS_CCONV ccall\n"++
+             "#else\n"++
+             "# error Unknown mingw32 arch\n"++
+             "#endif\n")++
   "foreign import " ++ cconv ++ " unsafe \"windows.h GetModuleFileNameW\"\n"++
   "  c_GetModuleFileName :: Ptr () -> CWString -> Int32 -> IO Int32\n"
-    where cconv = case arch of
-                  I386 -> "stdcall"
-                  X86_64 -> "ccall"
-                  _ -> error "win32 supported only with I386, X86_64"
+    where cconv = if supports_cpp
+                     then "WINDOWS_CCONV"
+                     else case arch of
+                            I386 -> "stdcall"
+                            X86_64 -> "ccall"
+                            _ -> error "win32 supported only with I386, X86_64"
 
 filename_stuff :: String
 filename_stuff =
diff --git a/cabal/Cabal/Distribution/Simple/BuildPaths.hs b/cabal/Cabal/Distribution/Simple/BuildPaths.hs
--- a/cabal/Cabal/Distribution/Simple/BuildPaths.hs
+++ b/cabal/Cabal/Distribution/Simple/BuildPaths.hs
@@ -199,23 +199,23 @@
 -- | Create a library name for a shared lirbary from a given name.
 -- Prepends 'lib' and appends the '-<compilerFlavour><compilerVersion>'
 -- as well as the shared library extension.
-mkGenericSharedLibName :: CompilerId -> String -> String
-mkGenericSharedLibName (CompilerId compilerFlavor compilerVersion) lib
-  = mconcat [ "lib", lib, "-", comp <.> dllExtension ]
+mkGenericSharedLibName :: Platform -> CompilerId -> String -> String
+mkGenericSharedLibName platform (CompilerId compilerFlavor compilerVersion) lib
+  = mconcat [ "lib", lib, "-", comp <.> dllExtension platform ]
   where comp = display compilerFlavor ++ display compilerVersion
 
 -- Implement proper name mangling for dynamical shared objects
 -- libHS<packagename>-<compilerFlavour><compilerVersion>
 -- e.g. libHSbase-2.1-ghc6.6.1.so
-mkSharedLibName :: CompilerId -> UnitId -> String
-mkSharedLibName comp lib
-  = mkGenericSharedLibName comp (getHSLibraryName lib)
+mkSharedLibName :: Platform -> CompilerId -> UnitId -> String
+mkSharedLibName platform comp lib
+  = mkGenericSharedLibName platform comp (getHSLibraryName lib)
 
 -- Static libs are named the same as shared libraries, only with
 -- a different extension.
-mkStaticLibName :: CompilerId -> UnitId -> String
-mkStaticLibName (CompilerId compilerFlavor compilerVersion) lib
-  = "lib" ++ getHSLibraryName lib ++ "-" ++ comp <.> staticLibExtension
+mkStaticLibName :: Platform -> CompilerId -> UnitId -> String
+mkStaticLibName platform (CompilerId compilerFlavor compilerVersion) lib
+  = "lib" ++ getHSLibraryName lib ++ "-" ++ comp <.> staticLibExtension platform
   where comp = display compilerFlavor ++ display compilerVersion
 
 -- ------------------------------------------------------------
@@ -224,8 +224,8 @@
 
 -- | Default extension for executable files on the current platform.
 -- (typically @\"\"@ on Unix and @\"exe\"@ on Windows or OS\/2)
-exeExtension :: String
-exeExtension = case buildOS of
+exeExtension :: Platform -> String
+exeExtension (Platform _arch os) = case os of
                    Windows -> "exe"
                    _       -> ""
 
@@ -235,8 +235,8 @@
 
 -- | Extension for dynamically linked (or shared) libraries
 -- (typically @\"so\"@ on Unix and @\"dll\"@ on Windows)
-dllExtension :: String
-dllExtension = case buildOS of
+dllExtension :: Platform -> String
+dllExtension (Platform _arch os)= case os of
                    Windows -> "dll"
                    OSX     -> "dylib"
                    _       -> "so"
@@ -245,7 +245,7 @@
 --
 -- TODO: Here, as well as in dllExtension, it's really the target OS that we're
 -- interested in, not the build OS.
-staticLibExtension :: String
-staticLibExtension = case buildOS of
+staticLibExtension :: Platform -> String
+staticLibExtension (Platform _arch os) = case os of
                        Windows -> "lib"
                        _       -> "a"
diff --git a/cabal/Cabal/Distribution/Simple/BuildTarget.hs b/cabal/Cabal/Distribution/Simple/BuildTarget.hs
--- a/cabal/Cabal/Distribution/Simple/BuildTarget.hs
+++ b/cabal/Cabal/Distribution/Simple/BuildTarget.hs
@@ -453,6 +453,7 @@
        cinfoAsmFiles:: [FilePath],
        cinfoCmmFiles:: [FilePath],
        cinfoCFiles  :: [FilePath],
+       cinfoCxxFiles:: [FilePath],
        cinfoJsFiles :: [FilePath]
      }
 
@@ -469,6 +470,7 @@
         cinfoAsmFiles= asmSources bi,
         cinfoCmmFiles= cmmSources bi,
         cinfoCFiles  = cSources bi,
+        cinfoCxxFiles= cxxSources bi,
         cinfoJsFiles = jsSources bi
       }
     | c <- pkgComponents pkg
diff --git a/cabal/Cabal/Distribution/Simple/Compiler.hs b/cabal/Cabal/Distribution/Simple/Compiler.hs
--- a/cabal/Cabal/Distribution/Simple/Compiler.hs
+++ b/cabal/Cabal/Distribution/Simple/Compiler.hs
@@ -11,7 +11,7 @@
 -- Portability :  portable
 --
 -- This should be a much more sophisticated abstraction than it is. Currently
--- it's just a bit of data about the compiler, like it's flavour and name and
+-- it's just a bit of data about the compiler, like its flavour and name and
 -- version. The reason it's just data is because currently it has to be in
 -- 'Read' and 'Show' so it can be saved along with the 'LocalBuildInfo'. The
 -- only interesting bit of info it contains is a mapping between language
@@ -80,6 +80,7 @@
 import Language.Haskell.Extension
 import Distribution.Simple.Utils
 
+import Control.Monad (join)
 import qualified Data.Map as Map (lookup)
 import System.Directory (canonicalizePath)
 
@@ -94,7 +95,7 @@
         -- compatible with.
         compilerLanguages       :: [(Language, Flag)],
         -- ^ Supported language standards.
-        compilerExtensions      :: [(Extension, Flag)],
+        compilerExtensions      :: [(Extension, Maybe Flag)],
         -- ^ Supported extensions.
         compilerProperties      :: Map String String
         -- ^ A key-value map for properties not covered by the above fields.
@@ -286,7 +287,7 @@
 unsupportedExtensions :: Compiler -> [Extension] -> [Extension]
 unsupportedExtensions comp exts =
   [ ext | ext <- exts
-        , isNothing (extensionToFlag comp ext) ]
+        , isNothing (extensionToFlag' comp ext) ]
 
 type Flag = String
 
@@ -295,9 +296,23 @@
 extensionsToFlags comp = nub . filter (not . null)
                        . catMaybes . map (extensionToFlag comp)
 
+-- | Looks up the flag for a given extension, for a given compiler.
+-- Ignores the subtlety of extensions which lack associated flags.
 extensionToFlag :: Compiler -> Extension -> Maybe Flag
-extensionToFlag comp ext = lookup ext (compilerExtensions comp)
+extensionToFlag comp ext = join (extensionToFlag' comp ext)
 
+-- | Looks up the flag for a given extension, for a given compiler.
+-- However, the extension may be valid for the compiler but not have a flag.
+-- For example, NondecreasingIndentation is enabled by default on GHC 7.0.4,
+-- hence it is considered a supported extension but not an accepted flag.
+--
+-- The outer layer of Maybe indicates whether the extensions is supported, while
+-- the inner layer indicates whether it has a flag.
+-- When building strings, it is often more convenient to use 'extensionToFlag',
+-- which ignores the difference.
+extensionToFlag' :: Compiler -> Extension -> Maybe (Maybe Flag)
+extensionToFlag' comp ext = lookup ext (compilerExtensions comp)
+
 -- | Does this compiler support parallel --make mode?
 parmakeSupported :: Compiler -> Bool
 parmakeSupported = ghcSupported "Support parallel --make"
@@ -359,7 +374,6 @@
   case compilerFlavor comp of
     GHC   -> True
     GHCJS -> True
-    LHC   -> True
     _     -> False
 
 -- | Utility function for GHC only features
@@ -422,4 +436,3 @@
     ProfDetailToplevelFunctions -> "toplevel-functions"
     ProfDetailAllFunctions      -> "all-functions"
     ProfDetailOther other       -> other
-
diff --git a/cabal/Cabal/Distribution/Simple/Configure.hs b/cabal/Cabal/Distribution/Simple/Configure.hs
--- a/cabal/Cabal/Distribution/Simple/Configure.hs
+++ b/cabal/Cabal/Distribution/Simple/Configure.hs
@@ -106,26 +106,29 @@
 
 import qualified Distribution.Simple.GHC   as GHC
 import qualified Distribution.Simple.GHCJS as GHCJS
-import qualified Distribution.Simple.JHC   as JHC
-import qualified Distribution.Simple.LHC   as LHC
 import qualified Distribution.Simple.UHC   as UHC
 import qualified Distribution.Simple.HaskellSuite as HaskellSuite
 
 import Control.Exception
     ( ErrorCall, Exception, evaluate, throw, throwIO, try )
-import Distribution.Compat.Binary ( decodeOrFailIO, encode )
-import Data.ByteString.Lazy (ByteString)
+import Control.Monad ( forM, forM_ )
+import Distribution.Compat.Binary    ( decodeOrFailIO, encode )
+import Distribution.Compat.Directory ( listDirectory )
+import Data.ByteString.Lazy          ( ByteString )
 import qualified Data.ByteString            as BS
 import qualified Data.ByteString.Lazy.Char8 as BLC8
 import Data.List
-    ( (\\), partition, inits, stripPrefix )
+    ( (\\), partition, inits, stripPrefix, intersect )
 import Data.Either
     ( partitionEithers )
 import qualified Data.Map as Map
 import System.Directory
-    ( doesFileExist, createDirectoryIfMissing, getTemporaryDirectory )
+    ( doesFileExist, createDirectoryIfMissing, getTemporaryDirectory
+    , removeFile)
 import System.FilePath
-    ( (</>), isAbsolute )
+    ( (</>), isAbsolute, takeDirectory )
+import Distribution.Compat.Directory
+    ( doesPathExist )
 import qualified System.Info
     ( compilerName, compilerVersion )
 import System.IO
@@ -138,6 +141,7 @@
 import Distribution.Compat.Environment ( lookupEnv )
 import Distribution.Compat.Exception ( catchExit, catchIO )
 
+
 type UseExternalInternalDeps = Bool
 
 -- | The errors that can be thrown when reading the @setup-config@ file.
@@ -471,18 +475,11 @@
 
     debug verbosity $ "Finalized package description:\n"
                   ++ showPackageDescription pkg_descr
-    -- NB: showPackageDescription does not display the AWFUL HACK GLOBAL
-    -- buildDepends, so we have to display it separately.  See #2066
-    -- Some day, we should eliminate this, so that
-    -- configureFinalizedPackage returns the set of overall dependencies
-    -- separately.  Then 'configureDependencies' and
-    -- 'Distribution.PackageDescription.Check' need to be adjusted
-    -- accordingly.
-    debug verbosity $ "Finalized build-depends: "
-                  ++ intercalate ", " (map display (buildDepends pkg_descr))
 
+    let cabalFileDir = maybe "." takeDirectory $
+          flagToMaybe (configCabalFilePath cfg)
     checkCompilerProblems verbosity comp pkg_descr enabled
-    checkPackageProblems verbosity pkg_descr0
+    checkPackageProblems verbosity cabalFileDir pkg_descr0
         (updatePackageDescription pbi pkg_descr)
 
     -- The list of 'InstalledPackageInfo' recording the selected
@@ -514,6 +511,7 @@
                 installedPackageSet
                 requiredDepsMap
                 pkg_descr
+                enabled
 
     -- Compute installation directory templates, based on user
     -- configuration.
@@ -632,7 +630,7 @@
                                       "--enable-split-objs are mutually" ++
                                       "exclusive; ignoring the latter")
                                 return False
-                        GHC | compilerVersion comp >= mkVersion [6,5]
+                        GHC
                           -> return True
                         GHCJS
                           -> return True
@@ -711,6 +709,7 @@
                 compiler            = comp,
                 hostPlatform        = compPlatform,
                 buildDir            = buildDir,
+                cabalFilePath       = flagToMaybe (configCabalFilePath cfg),
                 componentGraph      = Graph.fromDistinctList buildComponents,
                 componentNameMap    = buildComponentsMap,
                 installedPkgs       = packageDependsIndex,
@@ -748,9 +747,25 @@
     let dirs = absoluteInstallDirs pkg_descr lbi NoCopyDest
         relative = prefixRelativeInstallDirs (packageId pkg_descr) lbi
 
-    unless (isAbsolute (prefix dirs)) $ die' verbosity $
+    -- PKGROOT: allowing ${pkgroot} to be passed as --prefix to
+    -- cabal configure, is only a hidden option. It allows packages
+    -- to be relocatable with their package database.  This however
+    -- breaks when the Paths_* or other includes are used that
+    -- contain hard coded paths. This is still an open TODO.
+    --
+    -- Allowing ${pkgroot} here, however requires less custom hooks
+    -- in scripts that *really* want ${pkgroot}. See haskell/cabal/#4872
+    unless (isAbsolute (prefix dirs)
+           || "${pkgroot}" `isPrefixOf` prefix dirs) $ die' verbosity $
         "expected an absolute directory name for --prefix: " ++ prefix dirs
 
+    when ("${pkgroot}" `isPrefixOf` prefix dirs) $
+      warn verbosity $ "Using ${pkgroot} in prefix " ++ prefix dirs
+                    ++ " will not work if you rely on the Path_* module "
+                    ++ " or other hard coded paths.  Cabal does not yet "
+                    ++ " support fully  relocatable builds! "
+                    ++ " See #462 #2302 #2994 #3305 #3473 #3586 #3909 #4097 #4291 #4872"
+
     info verbosity $ "Using " ++ display currentCabalId
                   ++ " compiled by " ++ display currentCompilerId
     info verbosity $ "Using compiler: " ++ showCompilerId comp
@@ -955,14 +970,24 @@
         let extraBi = mempty { extraLibDirs = configExtraLibDirs cfg
                              , extraFrameworkDirs = configExtraFrameworkDirs cfg
                              , PD.includeDirs = configExtraIncludeDirs cfg}
-            modifyLib l        = l{ libBuildInfo = libBuildInfo l
-                                                   `mappend` extraBi }
-            modifyExecutable e = e{ buildInfo    = buildInfo e
-                                                   `mappend` extraBi}
-        in pkg_descr{ library = modifyLib `fmap` library pkg_descr
-                    , subLibraries = modifyLib `map` subLibraries pkg_descr
-                    , executables = modifyExecutable  `map`
-                                      executables pkg_descr}
+            modifyLib l        = l{ libBuildInfo        = libBuildInfo l
+                                                          `mappend` extraBi }
+            modifyExecutable e = e{ buildInfo           = buildInfo e
+                                                          `mappend` extraBi}
+            modifyForeignLib f = f{ foreignLibBuildInfo = foreignLibBuildInfo f
+                                                          `mappend` extraBi}
+            modifyTestsuite  t = t{ testBuildInfo      = testBuildInfo t
+                                                          `mappend` extraBi}
+            modifyBenchmark  b = b{ benchmarkBuildInfo  = benchmarkBuildInfo b
+                                                          `mappend` extraBi}
+        in pkg_descr
+             { library      = modifyLib        `fmap` library      pkg_descr
+             , subLibraries = modifyLib        `map`  subLibraries pkg_descr
+             , executables  = modifyExecutable `map`  executables  pkg_descr
+             , foreignLibs  = modifyForeignLib `map`  foreignLibs  pkg_descr
+             , testSuites   = modifyTestsuite  `map`  testSuites   pkg_descr
+             , benchmarks   = modifyBenchmark  `map`  benchmarks   pkg_descr
+             }
 
 -- | Check for use of Cabal features which require compiler support
 checkCompilerProblems :: Verbosity -> Compiler -> PackageDescription -> ComponentRequestedSpec -> IO ()
@@ -992,14 +1017,15 @@
     -> InstalledPackageIndex -- ^ installed packages
     -> Map PackageName InstalledPackageInfo -- ^ required deps
     -> PackageDescription
+    -> ComponentRequestedSpec
     -> IO [PreExistingComponent]
 configureDependencies verbosity use_external_internal_deps
-  internalPackageSet installedPackageSet requiredDepsMap pkg_descr = do
+  internalPackageSet installedPackageSet requiredDepsMap pkg_descr enableSpec = do
     let failedDeps :: [FailedDependency]
         allPkgDeps :: [ResolvedDependency]
         (failedDeps, allPkgDeps) = partitionEithers
           [ (\s -> (dep, s)) <$> status
-          | dep <- buildDepends pkg_descr
+          | dep <- enabledBuildDepends pkg_descr enableSpec
           , let status = selectDependency (package pkg_descr)
                   internalPackageSet installedPackageSet
                   requiredDepsMap use_external_internal_deps dep ]
@@ -1253,6 +1279,9 @@
         "cannot satisfy dependency " ++ display (simplifyDependency dep) ++ "\n"
 
 -- | List all installed packages in the given package databases.
+-- Non-existent package databases do not cause errors, they just get skipped
+-- with a warning and treated as empty ones, since technically they do not
+-- contain any package.
 getInstalledPackages :: Verbosity -> Compiler
                      -> PackageDBStack -- ^ The stack of package databases.
                      -> ProgramDb
@@ -1264,16 +1293,27 @@
        ++ "with 'global', 'user' or a specific file."
 
   info verbosity "Reading installed packages..."
+  -- do not check empty packagedbs (ghc-pkg would error out)
+  packageDBs' <- filterM packageDBExists packageDBs
   case compilerFlavor comp of
-    GHC   -> GHC.getInstalledPackages verbosity comp packageDBs progdb
-    GHCJS -> GHCJS.getInstalledPackages verbosity packageDBs progdb
-    JHC   -> JHC.getInstalledPackages verbosity packageDBs progdb
-    LHC   -> LHC.getInstalledPackages verbosity packageDBs progdb
-    UHC   -> UHC.getInstalledPackages verbosity comp packageDBs progdb
+    GHC   -> GHC.getInstalledPackages verbosity comp packageDBs' progdb
+    GHCJS -> GHCJS.getInstalledPackages verbosity packageDBs' progdb
+    UHC   -> UHC.getInstalledPackages verbosity comp packageDBs' progdb
     HaskellSuite {} ->
-      HaskellSuite.getInstalledPackages verbosity packageDBs progdb
+      HaskellSuite.getInstalledPackages verbosity packageDBs' progdb
     flv -> die' verbosity $ "don't know how to find the installed packages for "
               ++ display flv
+  where
+    packageDBExists (SpecificPackageDB path) = do
+      exists <- doesPathExist path
+      unless exists $
+        warn verbosity $ "Package db " <> path <> " does not exist yet"
+      return exists
+    -- Checking the user and global package dbs is more complicated and needs
+    -- way more data. Also ghc-pkg won't error out unless the user/global
+    -- pkgdb is overridden with an empty one, so we just don't check for them.
+    packageDBExists UserPackageDB            = pure True
+    packageDBExists GlobalPackageDB          = pure True
 
 -- | Like 'getInstalledPackages', but for a single package DB.
 --
@@ -1580,9 +1620,6 @@
   (comp, maybePlatform, programDb) <- case hcFlavor of
     GHC   -> GHC.configure  verbosity hcPath hcPkg progdb
     GHCJS -> GHCJS.configure verbosity hcPath hcPkg progdb
-    JHC   -> JHC.configure  verbosity hcPath hcPkg progdb
-    LHC   -> do (_, _, ghcConf) <- GHC.configure  verbosity Nothing hcPkg progdb
-                LHC.configure  verbosity hcPath Nothing ghcConf
     UHC   -> UHC.configure  verbosity hcPath hcPkg progdb
     HaskellSuite {} -> HaskellSuite.configure verbosity hcPath hcPkg progdb
     _    -> die' verbosity "Unknown compiler"
@@ -1628,9 +1665,41 @@
         allLibs    = collectField PD.extraLibs
 
         ifBuildsWith headers args success failure = do
+            checkDuplicateHeaders
             ok <- builds (makeProgram headers) args
             if ok then success else failure
 
+        -- Ensure that there is only one header with a given name
+        -- in either the generated (most likely by `configure`)
+        -- build directory (e.g. `dist/build`) or in the source directory.
+        --
+        -- If it exists in both, we'll remove the one in the source
+        -- directory, as the generated should take precedence.
+        --
+        -- C compilers like to prefer source local relative includes,
+        -- so the search paths provided to the compiler via -I are
+        -- ignored if the included file can be found relative to the
+        -- including file.  As such we need to take drastic measures
+        -- and delete the offending file in the source directory.
+        checkDuplicateHeaders = do
+          let relIncDirs = filter (not . isAbsolute) (collectField PD.includeDirs)
+              isHeader   = isSuffixOf ".h"
+          genHeaders <- forM relIncDirs $ \dir ->
+            fmap (dir </>) . filter isHeader <$> listDirectory (buildDir lbi </> dir)
+                                                 `catchIO` (\_ -> return [])
+          srcHeaders <- forM relIncDirs $ \dir ->
+            fmap (dir </>) . filter isHeader <$> listDirectory (baseDir lbi </> dir)
+                                                 `catchIO` (\_ -> return [])
+          let commonHeaders = concat genHeaders `intersect` concat srcHeaders
+          forM_ commonHeaders $ \hdr -> do
+            warn verbosity $ "Duplicate header found in "
+                          ++ (buildDir lbi </> hdr)
+                          ++ " and "
+                          ++ (baseDir lbi </> hdr)
+                          ++ "; removing "
+                          ++ (baseDir lbi </> hdr)
+            removeFile (baseDir lbi </> hdr)
+
         findOffendingHdr =
             ifBuildsWith allHeaders ccArgs
                          (return Nothing)
@@ -1655,14 +1724,23 @@
 
         libExists lib = builds (makeProgram []) (makeLdArgs [lib])
 
+        baseDir lbi' = fromMaybe "." (takeDirectory <$> cabalFilePath lbi')
+
         commonCppArgs = platformDefines lbi
                      -- TODO: This is a massive hack, to work around the
                      -- fact that the test performed here should be
                      -- PER-component (c.f. the "I'm Feeling Lucky"; we
                      -- should NOT be glomming everything together.)
                      ++ [ "-I" ++ buildDir lbi </> "autogen" ]
-                     ++ [ "-I" ++ dir | dir <- collectField PD.includeDirs ]
-                     ++ ["-I."]
+                     -- `configure' may generate headers in the build directory
+                     ++ [ "-I" ++ buildDir lbi </> dir | dir <- ordNub (collectField PD.includeDirs)
+                                                       , not (isAbsolute dir)]
+                     -- we might also reference headers from the packages directory.
+                     ++ [ "-I" ++ baseDir lbi </> dir | dir <- ordNub (collectField PD.includeDirs)
+                                                      , not (isAbsolute dir)]
+                     ++ [ "-I" ++ dir | dir <- ordNub (collectField PD.includeDirs)
+                                      , isAbsolute dir]
+                     ++ ["-I" ++ baseDir lbi]
                      ++ collectField PD.cppOptions
                      ++ collectField PD.ccOptions
                      ++ [ "-I" ++ dir
@@ -1682,7 +1760,7 @@
                         | dep <- deps
                         , opt <- Installed.ccOptions dep ]
 
-        commonLdArgs  = [ "-L" ++ dir | dir <- collectField PD.extraLibDirs ]
+        commonLdArgs  = [ "-L" ++ dir | dir <- ordNub (collectField PD.extraLibDirs) ]
                      ++ collectField PD.ldOptions
                      ++ [ "-L" ++ dir
                         | dir <- ordNub [ dir
@@ -1784,11 +1862,13 @@
 
 -- | Output package check warnings and errors. Exit if any errors.
 checkPackageProblems :: Verbosity
+                     -> FilePath
+                        -- ^ Path to the @.cabal@ file's directory
                      -> GenericPackageDescription
                      -> PackageDescription
                      -> IO ()
-checkPackageProblems verbosity gpkg pkg = do
-  ioChecks      <- checkPackageFiles pkg "."
+checkPackageProblems verbosity dir gpkg pkg = do
+  ioChecks      <- checkPackageFiles verbosity pkg dir
   let pureChecks = checkPackage gpkg (Just pkg)
       errors   = [ e | PackageBuildImpossible e <- pureChecks ++ ioChecks ]
       warnings = [ w | PackageBuildWarning    w <- pureChecks ++ ioChecks ]
@@ -1901,9 +1981,6 @@
 
     goGhcOsx :: ForeignLibType -> Maybe String
     goGhcOsx ForeignLibNativeShared
-      | standalone = unsupported [
-            "We cannot build standalone libraries on OSX"
-          ]
       | not (null (foreignLibModDefFile flib)) = unsupported [
             "Module definition file not supported on OSX"
           ]
@@ -1918,9 +1995,6 @@
 
     goGhcLinux :: ForeignLibType -> Maybe String
     goGhcLinux ForeignLibNativeShared
-      | standalone = unsupported [
-            "We cannot build standalone libraries on Linux"
-          ]
       | not (null (foreignLibModDefFile flib)) = unsupported [
             "Module definition file not supported on Linux"
           ]
diff --git a/cabal/Cabal/Distribution/Simple/Doctest.hs b/cabal/Cabal/Distribution/Simple/Doctest.hs
--- a/cabal/Cabal/Distribution/Simple/Doctest.hs
+++ b/cabal/Cabal/Distribution/Simple/Doctest.hs
@@ -37,7 +37,6 @@
 import Distribution.Simple.BuildPaths
 import Distribution.Simple.Utils
 import Distribution.System
-import Distribution.Utils.NubList
 import Distribution.Version
 import Distribution.Verbosity
 
@@ -132,7 +131,7 @@
         , ghcOptFPic        = toFlag True
         , ghcOptHiSuffix    = toFlag "dyn_hi"
         , ghcOptObjSuffix   = toFlag "dyn_o"
-        , ghcOptExtra       = toNubListR (hcSharedOptions GHC bi)}
+        , ghcOptExtra       = hcSharedOptions GHC bi}
   opts <- if withVanillaLib lbi
           then return vanillaOpts
           else if withSharedLib lbi
diff --git a/cabal/Cabal/Distribution/Simple/Flag.hs b/cabal/Cabal/Distribution/Simple/Flag.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/Simple/Flag.hs
@@ -0,0 +1,124 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE FlexibleContexts #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Distribution.Simple.Flag
+-- Copyright   :  Isaac Jones 2003-2004
+--                Duncan Coutts 2007
+-- License     :  BSD3
+--
+-- Maintainer  :  cabal-devel@haskell.org
+-- Portability :  portable
+--
+-- Defines the 'Flag' type and it's 'Monoid' instance,  see
+-- <http://www.haskell.org/pipermail/cabal-devel/2007-December/001509.html>
+-- for an explanation.
+--
+-- Split off from "Distribution.Simple.Setup" to break import cycles.
+module Distribution.Simple.Flag (
+  Flag(..),
+  allFlags,
+  toFlag,
+  fromFlag,
+  fromFlagOrDefault,
+  flagToMaybe,
+  flagToList,
+  maybeToFlag,
+  BooleanFlag(..) ) where
+
+import Prelude ()
+import Distribution.Compat.Prelude hiding (get)
+import Distribution.Compat.Stack
+
+-- ------------------------------------------------------------
+-- * Flag type
+-- ------------------------------------------------------------
+
+-- | All flags are monoids, they come in two flavours:
+--
+-- 1. list flags eg
+--
+-- > --ghc-option=foo --ghc-option=bar
+--
+-- gives us all the values ["foo", "bar"]
+--
+-- 2. singular value flags, eg:
+--
+-- > --enable-foo --disable-foo
+--
+-- gives us Just False
+-- So this Flag type is for the latter singular kind of flag.
+-- Its monoid instance gives us the behaviour where it starts out as
+-- 'NoFlag' and later flags override earlier ones.
+--
+data Flag a = Flag a | NoFlag deriving (Eq, Generic, Show, Read)
+
+instance Binary a => Binary (Flag a)
+
+instance Functor Flag where
+  fmap f (Flag x) = Flag (f x)
+  fmap _ NoFlag  = NoFlag
+
+instance Applicative Flag where
+  (Flag x) <*> y = x <$> y
+  NoFlag   <*> _ = NoFlag
+  pure = Flag
+
+instance Monoid (Flag a) where
+  mempty = NoFlag
+  mappend = (<>)
+
+instance Semigroup (Flag a) where
+  _ <> f@(Flag _) = f
+  f <> NoFlag     = f
+
+instance Bounded a => Bounded (Flag a) where
+  minBound = toFlag minBound
+  maxBound = toFlag maxBound
+
+instance Enum a => Enum (Flag a) where
+  fromEnum = fromEnum . fromFlag
+  toEnum   = toFlag   . toEnum
+  enumFrom (Flag a) = map toFlag . enumFrom $ a
+  enumFrom _        = []
+  enumFromThen (Flag a) (Flag b) = toFlag `map` enumFromThen a b
+  enumFromThen _        _        = []
+  enumFromTo   (Flag a) (Flag b) = toFlag `map` enumFromTo a b
+  enumFromTo   _        _        = []
+  enumFromThenTo (Flag a) (Flag b) (Flag c) = toFlag `map` enumFromThenTo a b c
+  enumFromThenTo _        _        _        = []
+
+toFlag :: a -> Flag a
+toFlag = Flag
+
+fromFlag :: WithCallStack (Flag a -> a)
+fromFlag (Flag x) = x
+fromFlag NoFlag   = error "fromFlag NoFlag. Use fromFlagOrDefault"
+
+fromFlagOrDefault :: a -> Flag a -> a
+fromFlagOrDefault _   (Flag x) = x
+fromFlagOrDefault def NoFlag   = def
+
+flagToMaybe :: Flag a -> Maybe a
+flagToMaybe (Flag x) = Just x
+flagToMaybe NoFlag   = Nothing
+
+flagToList :: Flag a -> [a]
+flagToList (Flag x) = [x]
+flagToList NoFlag   = []
+
+allFlags :: [Flag Bool] -> Flag Bool
+allFlags flags = if all (\f -> fromFlagOrDefault False f) flags
+                 then Flag True
+                 else NoFlag
+
+maybeToFlag :: Maybe a -> Flag a
+maybeToFlag Nothing  = NoFlag
+maybeToFlag (Just x) = Flag x
+
+-- | Types that represent boolean flags.
+class BooleanFlag a where
+    asBool :: a -> Bool
+
+instance BooleanFlag Bool where
+  asBool = id
diff --git a/cabal/Cabal/Distribution/Simple/GHC.hs b/cabal/Cabal/Distribution/Simple/GHC.hs
--- a/cabal/Cabal/Distribution/Simple/GHC.hs
+++ b/cabal/Cabal/Distribution/Simple/GHC.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE TupleSections #-}
 {-# LANGUAGE CPP #-}
 
 -----------------------------------------------------------------------------
@@ -53,10 +54,15 @@
         isDynamic,
         getGlobalPackageDB,
         pkgRoot,
-        -- * Constructing GHC environment files
+        -- * Constructing and deconstructing GHC environment files
         Internal.GhcEnvironmentFileEntry(..),
         Internal.simpleGhcEnvironmentFile,
+        Internal.renderGhcEnvironmentFile,
         Internal.writeGhcEnvironmentFile,
+        Internal.ghcPlatformAndVersionString,
+        readGhcEnvironmentFile,
+        parseGhcEnvironmentFile,
+        ParseErrorExc(..),
         -- * Version-specific implementation quirks
         getImplInfo,
         GhcImplInfo(..)
@@ -65,9 +71,9 @@
 import Prelude ()
 import Distribution.Compat.Prelude
 
-import qualified Distribution.Simple.GHC.IPI642 as IPI642
 import qualified Distribution.Simple.GHC.Internal as Internal
 import Distribution.Simple.GHC.ImplInfo
+import Distribution.Simple.GHC.EnvironmentParser
 import Distribution.PackageDescription.Utils (cabalBug)
 import Distribution.PackageDescription as PD
 import Distribution.InstalledPackageInfo (InstalledPackageInfo)
@@ -127,10 +133,17 @@
 
   (ghcProg, ghcVersion, progdb1) <-
     requireProgramVersion verbosity ghcProgram
-      (orLaterVersion (mkVersion [6,11]))
+      (orLaterVersion (mkVersion [7,0,1]))
       (userMaybeSpecifyPath "ghc" hcPath conf0)
   let implInfo = ghcVersionImplInfo ghcVersion
 
+  -- Cabal currently supports ghc >= 7.0.1 && < 8.7
+  unless (ghcVersion < mkVersion [8,7]) $
+    warn verbosity $
+         "Unknown/unsupported 'ghc' version detected "
+      ++ "(Cabal " ++ display cabalVersion ++ " supports 'ghc' version < 8.7): "
+      ++ programPath ghcProg ++ " is version " ++ display ghcVersion
+
   -- This is slightly tricky, we have to configure ghc first, then we use the
   -- location of ghc to help find ghc-pkg in the case that the user did not
   -- specify the location of ghc-pkg directly:
@@ -217,11 +230,11 @@
            versionSuffix path = takeVersionSuffix (dropExeExtension path)
            given_suf = versionSuffix given_path
            real_suf  = versionSuffix real_path
-           guessNormal       dir = dir </> toolname <.> exeExtension
+           guessNormal       dir = dir </> toolname <.> exeExtension buildPlatform
            guessGhcVersioned dir suf = dir </> (toolname ++ "-ghc" ++ suf)
-                                           <.> exeExtension
+                                           <.> exeExtension buildPlatform
            guessVersioned    dir suf = dir </> (toolname ++ suf)
-                                           <.> exeExtension
+                                           <.> exeExtension buildPlatform
            mkGuesses dir suf | null suf  = [guessNormal dir]
                              | otherwise = [guessGhcVersioned dir suf,
                                             guessVersioned dir suf,
@@ -380,9 +393,7 @@
   where
     platformAndVersion = Internal.ghcPlatformAndVersionString
                            platform ghcVersion
-    packageConfFileName
-      | ghcVersion >= mkVersion [6,12]   = "package.conf.d"
-      | otherwise                        = "package.conf"
+    packageConfFileName = "package.conf.d"
     Just ghcVersion = programVersion ghcProg
 
 checkPackageDbEnvVar :: Verbosity -> IO ()
@@ -430,47 +441,12 @@
 --
 getInstalledPackages' :: Verbosity -> [PackageDB] -> ProgramDb
                      -> IO [(PackageDB, [InstalledPackageInfo])]
-getInstalledPackages' verbosity packagedbs progdb
-  | ghcVersion >= mkVersion [6,9] =
+getInstalledPackages' verbosity packagedbs progdb =
   sequenceA
     [ do pkgs <- HcPkg.dump (hcPkgInfo progdb) verbosity packagedb
          return (packagedb, pkgs)
     | packagedb <- packagedbs ]
 
-  where
-    Just ghcProg    = lookupProgram ghcProgram progdb
-    Just ghcVersion = programVersion ghcProg
-
-getInstalledPackages' verbosity packagedbs progdb = do
-    str <- getDbProgramOutput verbosity ghcPkgProgram progdb ["list"]
-    let pkgFiles = [ init line | line <- lines str, last line == ':' ]
-        dbFile packagedb = case (packagedb, pkgFiles) of
-          (GlobalPackageDB, global:_)      -> return $ Just global
-          (UserPackageDB,  _global:user:_) -> return $ Just user
-          (UserPackageDB,  _global:_)      -> return $ Nothing
-          (SpecificPackageDB specific, _)  -> return $ Just specific
-          _ -> die' verbosity "cannot read ghc-pkg package listing"
-    pkgFiles' <- traverse dbFile packagedbs
-    sequenceA [ withFileContents file $ \content -> do
-                  pkgs <- readPackages file content
-                  return (db, pkgs)
-              | (db , Just file) <- zip packagedbs pkgFiles' ]
-  where
-    -- Depending on the version of ghc we use a different type's Read
-    -- instance to parse the package file and then convert.
-    -- It's a bit yuck. But that's what we get for using Read/Show.
-    readPackages
-      | ghcVersion >= mkVersion [6,4,2]
-      = \file content -> case reads content of
-          [(pkgs, _)] -> return (map IPI642.toCurrent pkgs)
-          _           -> failToRead file
-      -- We dropped support for 6.4.2 and earlier.
-      | otherwise
-      = \file _ -> failToRead file
-    Just ghcProg = lookupProgram ghcProgram progdb
-    Just ghcVersion = programVersion ghcProg
-    failToRead file = die' verbosity $ "cannot read ghc package database " ++ file
-
 getInstalledPackagesMonitorFiles :: Verbosity -> Platform
                                  -> ProgramDb
                                  -> [PackageDB]
@@ -502,16 +478,22 @@
 -- -----------------------------------------------------------------------------
 -- Building a library
 
-buildLib, replLib :: Verbosity          -> Cabal.Flag (Maybe Int)
-                  -> PackageDescription -> LocalBuildInfo
-                  -> Library            -> ComponentLocalBuildInfo -> IO ()
-buildLib = buildOrReplLib False
-replLib  = buildOrReplLib True
+buildLib :: Verbosity          -> Cabal.Flag (Maybe Int)
+         -> PackageDescription -> LocalBuildInfo
+         -> Library            -> ComponentLocalBuildInfo -> IO ()
+buildLib = buildOrReplLib Nothing
 
-buildOrReplLib :: Bool -> Verbosity  -> Cabal.Flag (Maybe Int)
-               -> PackageDescription -> LocalBuildInfo
-               -> Library            -> ComponentLocalBuildInfo -> IO ()
-buildOrReplLib forRepl verbosity numJobs pkg_descr lbi lib clbi = do
+replLib :: [String]                -> Verbosity
+        -> Cabal.Flag (Maybe Int)  -> PackageDescription
+        -> LocalBuildInfo          -> Library
+        -> ComponentLocalBuildInfo -> IO ()
+replLib = buildOrReplLib . Just
+
+buildOrReplLib :: Maybe [String] -> Verbosity
+               -> Cabal.Flag (Maybe Int) -> PackageDescription
+               -> LocalBuildInfo -> Library
+               -> ComponentLocalBuildInfo -> IO ()
+buildOrReplLib mReplFlags verbosity numJobs pkg_descr lbi lib clbi = do
   let uid = componentUnitId clbi
       libTargetDir = componentBuildDir lbi clbi
       whenVanillaLib forceVanilla =
@@ -521,8 +503,10 @@
         when (forceShared || withSharedLib lbi)
       whenStaticLib forceStatic =
         when (forceStatic || withStaticLib lbi)
-      whenGHCiLib = when (withGHCiLib lbi && withVanillaLib lbi)
+      whenGHCiLib = when (withGHCiLib lbi)
+      forRepl = maybe False (const True) mReplFlags
       ifReplLib = when forRepl
+      replFlags = fromMaybe mempty mReplFlags
       comp = compiler lbi
       ghcVersion = compilerVersion comp
       implInfo  = getImplInfo comp
@@ -532,8 +516,7 @@
   (ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi)
   let runGhcProg = runGHC verbosity ghcProg comp platform
 
-  libBi <- hackThreadedFlag verbosity
-             comp (withProfLib lbi) (libBuildInfo lib)
+  let libBi = libBuildInfo lib
 
   let isGhcDynamic        = isDynamic comp
       dynamicTooSupported = supportsDynamicToo comp
@@ -575,7 +558,7 @@
                                               (withProfLibDetail lbi),
                       ghcOptHiSuffix      = toFlag "p_hi",
                       ghcOptObjSuffix     = toFlag "p_o",
-                      ghcOptExtra         = toNubListR $ hcProfOptions GHC libBi,
+                      ghcOptExtra         = hcProfOptions GHC libBi,
                       ghcOptHPCDir        = hpcdir Hpc.Prof
                     }
 
@@ -584,24 +567,22 @@
                       ghcOptFPic        = toFlag True,
                       ghcOptHiSuffix    = toFlag "dyn_hi",
                       ghcOptObjSuffix   = toFlag "dyn_o",
-                      ghcOptExtra       = toNubListR $ hcSharedOptions GHC libBi,
+                      ghcOptExtra       = hcSharedOptions GHC libBi,
                       ghcOptHPCDir      = hpcdir Hpc.Dyn
                     }
       linkerOpts = mempty {
-                      ghcOptLinkOptions       = toNubListR $ PD.ldOptions libBi,
-                      ghcOptLinkLibs          = toNubListR $ extraLibs libBi,
+                      ghcOptLinkOptions       = PD.ldOptions libBi,
+                      ghcOptLinkLibs          = extraLibs libBi,
                       ghcOptLinkLibPath       = toNubListR $ extraLibDirs libBi,
-                      ghcOptLinkFrameworks    = toNubListR $
-                                                PD.frameworks libBi,
-                      ghcOptLinkFrameworkDirs = toNubListR $
-                                                PD.extraFrameworkDirs libBi,
+                      ghcOptLinkFrameworks    = toNubListR $ PD.frameworks libBi,
+                      ghcOptLinkFrameworkDirs = toNubListR $ PD.extraFrameworkDirs libBi,
                       ghcOptInputFiles     = toNubListR
                                              [libTargetDir </> x | x <- cObjs]
                    }
       replOpts    = vanillaOpts {
-                      ghcOptExtra        = overNubListR
-                                           Internal.filterGhciFlags $
-                                           ghcOptExtra vanillaOpts,
+                      ghcOptExtra        = Internal.filterGhciFlags
+                                           (ghcOptExtra vanillaOpts)
+                                           <> replFlags,
                       ghcOptNumJobs      = mempty
                     }
                     `mappend` linkerOpts
@@ -645,19 +626,19 @@
             else do vanilla; shared
        whenProfLib (runGhcProg profOpts)
 
-  -- build any C++ sources seperately
+  -- Build any C++ sources separately.
   unless (not has_code || null (cxxSources libBi)) $ do
     info verbosity "Building C++ Sources..."
     sequence_
       [ do let baseCxxOpts    = Internal.componentCxxGhcOptions verbosity implInfo
-                               lbi libBi clbi libTargetDir filename
+                                lbi libBi clbi libTargetDir filename
                vanillaCxxOpts = if isGhcDynamic
                                 then baseCxxOpts { ghcOptFPic = toFlag True }
                                 else baseCxxOpts
                profCxxOpts    = vanillaCxxOpts `mappend` mempty {
-                                 ghcOptProfilingMode = toFlag True,
-                                 ghcOptObjSuffix     = toFlag "p_o"
-                               }
+                                  ghcOptProfilingMode = toFlag True,
+                                  ghcOptObjSuffix     = toFlag "p_o"
+                                }
                sharedCxxOpts  = vanillaCxxOpts `mappend` mempty {
                                  ghcOptFPic        = toFlag True,
                                  ghcOptDynLinkMode = toFlag GhcDynamicOnly,
@@ -674,7 +655,7 @@
            unless forRepl $ whenProfLib   (runGhcProgIfNeeded   profCxxOpts)
       | filename <- cxxSources libBi]
 
-  when has_code . ifReplLib $ do
+  ifReplLib $ do
     when (null (allLibModules lib clbi)) $ warn verbosity "No exposed modules"
     ifReplLib (runGhcProg replOpts)
 
@@ -724,11 +705,12 @@
         compiler_id = compilerId (compiler lbi)
         vanillaLibFilePath = libTargetDir </> mkLibName uid
         profileLibFilePath = libTargetDir </> mkProfLibName uid
-        sharedLibFilePath  = libTargetDir </> mkSharedLibName compiler_id uid
-        staticLibFilePath  = libTargetDir </> mkStaticLibName compiler_id uid
+        sharedLibFilePath  = libTargetDir </> mkSharedLibName (hostPlatform lbi) compiler_id uid
+        staticLibFilePath  = libTargetDir </> mkStaticLibName (hostPlatform lbi) compiler_id uid
         ghciLibFilePath    = libTargetDir </> Internal.mkGHCiLibName uid
+        ghciProfLibFilePath = libTargetDir </> Internal.mkGHCiProfLibName uid
         libInstallPath = libdir $ absoluteComponentInstallDirs pkg_descr lbi uid NoCopyDest
-        sharedLibInstallPath = libInstallPath </> mkSharedLibName compiler_id uid
+        sharedLibInstallPath = libInstallPath </> mkSharedLibName (hostPlatform lbi) compiler_id uid
 
     stubObjs <- catMaybes <$> sequenceA
       [ findFileWithExtension [objExtension] [libTargetDir]
@@ -770,10 +752,6 @@
                  hProfObjs
               ++ map (libTargetDir </>) cProfObjs
               ++ stubProfObjs
-          ghciObjFiles =
-                 hObjs
-              ++ map (libTargetDir </>) cObjs
-              ++ stubObjs
           dynamicObjectFiles =
                  hSharedObjs
               ++ map (libTargetDir </>) cSharedObjs
@@ -787,8 +765,7 @@
                 ghcOptDynLinkMode        = toFlag GhcDynamicOnly,
                 ghcOptInputFiles         = toNubListR dynamicObjectFiles,
                 ghcOptOutputFile         = toFlag sharedLibFilePath,
-                ghcOptExtra              = toNubListR $
-                                           hcSharedOptions GHC libBi,
+                ghcOptExtra              = hcSharedOptions GHC libBi,
                 -- For dynamic libs, Mac OS/X needs to know the install location
                 -- at build time. This only applies to GHC < 7.8 - see the
                 -- discussion in #1660.
@@ -815,7 +792,7 @@
                     _ -> [],
                 ghcOptPackages           = toNubListR $
                                            Internal.mkGhcOptPackages clbi ,
-                ghcOptLinkLibs           = toNubListR $ extraLibs libBi,
+                ghcOptLinkLibs           = extraLibs libBi,
                 ghcOptLinkLibPath        = toNubListR $ extraLibDirs libBi,
                 ghcOptLinkFrameworks     = toNubListR $ PD.frameworks libBi,
                 ghcOptLinkFrameworkDirs  =
@@ -827,8 +804,7 @@
                 ghcOptStaticLib          = toFlag True,
                 ghcOptInputFiles         = toNubListR staticObjectFiles,
                 ghcOptOutputFile         = toFlag staticLibFilePath,
-                ghcOptExtra              = toNubListR $
-                                           hcStaticOptions GHC libBi,
+                ghcOptExtra              = hcStaticOptions GHC libBi,
                 ghcOptHideAllPackages    = toFlag True,
                 ghcOptNoAutoLinkPackages = toFlag True,
                 ghcOptPackageDBs         = withPackageDB lbi,
@@ -848,22 +824,25 @@
                     _ -> [],
                 ghcOptPackages           = toNubListR $
                                            Internal.mkGhcOptPackages clbi ,
-                ghcOptLinkLibs           = toNubListR $ extraLibs libBi,
+                ghcOptLinkLibs           = extraLibs libBi,
                 ghcOptLinkLibPath        = toNubListR $ extraLibDirs libBi
               }
 
       info verbosity (show (ghcOptPackages ghcSharedLinkArgs))
 
-      whenVanillaLib False $
+      whenVanillaLib False $ do
         Ar.createArLibArchive verbosity lbi vanillaLibFilePath staticObjectFiles
+        whenGHCiLib $ do
+          (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)
+          Ld.combineObjectFiles verbosity lbi ldProg
+            ghciLibFilePath staticObjectFiles
 
-      whenProfLib $
+      whenProfLib $ do
         Ar.createArLibArchive verbosity lbi profileLibFilePath profObjectFiles
-
-      whenGHCiLib $ do
-        (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)
-        Ld.combineObjectFiles verbosity lbi ldProg
-          ghciLibFilePath ghciObjFiles
+        whenGHCiLib $ do
+          (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)
+          Ld.combineObjectFiles verbosity lbi ldProg
+            ghciProfLibFilePath profObjectFiles
 
       whenSharedLib False $
         runGhcProg ghcSharedLinkArgs
@@ -887,51 +866,65 @@
 -- Building an executable or foreign library
 
 -- | Build a foreign library
-buildFLib, replFLib
+buildFLib
   :: Verbosity          -> Cabal.Flag (Maybe Int)
   -> PackageDescription -> LocalBuildInfo
   -> ForeignLib         -> ComponentLocalBuildInfo -> IO ()
 buildFLib v njobs pkg lbi = gbuild v njobs pkg lbi . GBuildFLib
-replFLib  v njobs pkg lbi = gbuild v njobs pkg lbi . GReplFLib
 
+replFLib
+  :: [String]                -> Verbosity
+  -> Cabal.Flag (Maybe Int)  -> PackageDescription
+  -> LocalBuildInfo          -> ForeignLib
+  -> ComponentLocalBuildInfo -> IO ()
+replFLib replFlags  v njobs pkg lbi =
+  gbuild v njobs pkg lbi . GReplFLib replFlags
+
 -- | Build an executable with GHC.
 --
-buildExe, replExe
+buildExe
   :: Verbosity          -> Cabal.Flag (Maybe Int)
   -> PackageDescription -> LocalBuildInfo
   -> Executable         -> ComponentLocalBuildInfo -> IO ()
 buildExe v njobs pkg lbi = gbuild v njobs pkg lbi . GBuildExe
-replExe  v njobs pkg lbi = gbuild v njobs pkg lbi . GReplExe
 
+replExe
+  :: [String]                -> Verbosity
+  -> Cabal.Flag (Maybe Int)  -> PackageDescription
+  -> LocalBuildInfo          -> Executable
+  -> ComponentLocalBuildInfo -> IO ()
+replExe replFlags v njobs pkg lbi =
+  gbuild v njobs pkg lbi . GReplExe replFlags
+
 -- | Building an executable, starting the REPL, and building foreign
 -- libraries are all very similar and implemented in 'gbuild'. The
 -- 'GBuildMode' distinguishes between the various kinds of operation.
 data GBuildMode =
     GBuildExe  Executable
-  | GReplExe   Executable
+  | GReplExe   [String] Executable
   | GBuildFLib ForeignLib
-  | GReplFLib  ForeignLib
+  | GReplFLib  [String] ForeignLib
 
 gbuildInfo :: GBuildMode -> BuildInfo
 gbuildInfo (GBuildExe  exe)  = buildInfo exe
-gbuildInfo (GReplExe   exe)  = buildInfo exe
+gbuildInfo (GReplExe   _ exe)  = buildInfo exe
 gbuildInfo (GBuildFLib flib) = foreignLibBuildInfo flib
-gbuildInfo (GReplFLib  flib) = foreignLibBuildInfo flib
+gbuildInfo (GReplFLib  _ flib) = foreignLibBuildInfo flib
 
 gbuildName :: GBuildMode -> String
 gbuildName (GBuildExe  exe)  = unUnqualComponentName $ exeName exe
-gbuildName (GReplExe   exe)  = unUnqualComponentName $ exeName exe
+gbuildName (GReplExe   _ exe)  = unUnqualComponentName $ exeName exe
 gbuildName (GBuildFLib flib) = unUnqualComponentName $ foreignLibName flib
-gbuildName (GReplFLib  flib) = unUnqualComponentName $ foreignLibName flib
+gbuildName (GReplFLib  _ flib) = unUnqualComponentName $ foreignLibName flib
 
 gbuildTargetName :: LocalBuildInfo -> GBuildMode -> String
-gbuildTargetName _lbi (GBuildExe  exe)  = exeTargetName exe
-gbuildTargetName _lbi (GReplExe   exe)  = exeTargetName exe
-gbuildTargetName  lbi (GBuildFLib flib) = flibTargetName lbi flib
-gbuildTargetName  lbi (GReplFLib  flib) = flibTargetName lbi flib
+gbuildTargetName lbi (GBuildExe  exe)  = exeTargetName (hostPlatform lbi) exe
+gbuildTargetName lbi (GReplExe   _ exe)  = exeTargetName (hostPlatform lbi) exe
+gbuildTargetName lbi (GBuildFLib flib) = flibTargetName lbi flib
+gbuildTargetName lbi (GReplFLib  _ flib) = flibTargetName lbi flib
 
-exeTargetName :: Executable -> String
-exeTargetName exe = unUnqualComponentName (exeName exe) `withExt` exeExtension
+exeTargetName :: Platform -> Executable -> String
+exeTargetName platform exe = unUnqualComponentName (exeName exe) `withExt` exeExtension platform
 
 -- | Target name for a foreign library (the actual file name)
 --
@@ -948,8 +941,8 @@
       (Windows, ForeignLibNativeShared) -> nm <.> "dll"
       (Windows, ForeignLibNativeStatic) -> nm <.> "lib"
       (Linux,   ForeignLibNativeShared) -> "lib" ++ nm <.> versionedExt
-      (_other,  ForeignLibNativeShared) -> "lib" ++ nm <.> dllExtension
-      (_other,  ForeignLibNativeStatic) -> "lib" ++ nm <.> staticLibExtension
+      (_other,  ForeignLibNativeShared) -> "lib" ++ nm <.> dllExtension (hostPlatform lbi)
+      (_other,  ForeignLibNativeStatic) -> "lib" ++ nm <.> staticLibExtension (hostPlatform lbi)
       (_any,    ForeignLibTypeUnknown)  -> cabalBug "unknown foreign lib type"
   where
     nm :: String
@@ -1003,17 +996,17 @@
 
 gbuildIsRepl :: GBuildMode -> Bool
 gbuildIsRepl (GBuildExe  _) = False
-gbuildIsRepl (GReplExe   _) = True
+gbuildIsRepl (GReplExe _ _) = True
 gbuildIsRepl (GBuildFLib _) = False
-gbuildIsRepl (GReplFLib  _) = True
+gbuildIsRepl (GReplFLib _ _) = True
 
 gbuildNeedDynamic :: LocalBuildInfo -> GBuildMode -> Bool
 gbuildNeedDynamic lbi bm =
     case bm of
       GBuildExe  _    -> withDynExe lbi
-      GReplExe   _    -> withDynExe lbi
+      GReplExe   _ _  -> withDynExe lbi
       GBuildFLib flib -> withDynFLib flib
-      GReplFLib  flib -> withDynFLib flib
+      GReplFLib  _ flib -> withDynFLib flib
   where
     withDynFLib flib =
       case foreignLibType flib of
@@ -1026,9 +1019,9 @@
 
 gbuildModDefFiles :: GBuildMode -> [FilePath]
 gbuildModDefFiles (GBuildExe _)     = []
-gbuildModDefFiles (GReplExe  _)     = []
+gbuildModDefFiles (GReplExe  _ _)     = []
 gbuildModDefFiles (GBuildFLib flib) = foreignLibModDefFile flib
-gbuildModDefFiles (GReplFLib  flib) = foreignLibModDefFile flib
+gbuildModDefFiles (GReplFLib _ flib) = foreignLibModDefFile flib
 
 -- | "Main" module name when overridden by @ghc-options: -main-is ...@
 -- or 'Nothing' if no @-main-is@ flag could be found.
@@ -1076,20 +1069,35 @@
                            -- 'tail' drops the char satisfying 'pred'
       where (r_suf, r_pre) = break pred' (reverse str)
 
--- | Return C sources, GHC input files and GHC input modules
+
+-- | A collection of:
+--    * C input files
+--    * C++ input files
+--    * GHC input files
+--    * GHC input modules
+--
+-- Used to correctly build and link sources.
+data BuildSources = BuildSources {
+        cSourcesFiles      :: [FilePath],
+        cxxSourceFiles     :: [FilePath],
+        inputSourceFiles   :: [FilePath],
+        inputSourceModules :: [ModuleName]
+    }
+
+-- | Locate and return the 'BuildSources' required to build and link.
 gbuildSources :: Verbosity
               -> Version -- ^ specVersion
               -> FilePath
               -> GBuildMode
-              -> IO ([FilePath], [FilePath], [ModuleName])
+              -> IO BuildSources
 gbuildSources verbosity specVer tmpDir bm =
     case bm of
       GBuildExe  exe  -> exeSources exe
-      GReplExe   exe  -> exeSources exe
+      GReplExe   _ exe  -> exeSources exe
       GBuildFLib flib -> return $ flibSources flib
-      GReplFLib  flib -> return $ flibSources flib
+      GReplFLib  _ flib -> return $ flibSources flib
   where
-    exeSources :: Executable -> IO ([FilePath], [FilePath], [ModuleName])
+    exeSources :: Executable -> IO BuildSources
     exeSources exe@Executable{buildInfo = bnfo, modulePath = modPath} = do
       main <- findFile (tmpDir : hsSourceDirs bnfo) modPath
       let mainModName = fromMaybe ModuleName.main $ exeMainModuleName exe
@@ -1114,32 +1122,67 @@
                             ++ display mainModName
                             ++ "' listed in 'other-modules' illegally!"
 
-             return   (cSources bnfo, [main],
-                       filter (/= mainModName) (exeModules exe))
+             return BuildSources {
+                        cSourcesFiles      = cSources bnfo,
+                        cxxSourceFiles     = cxxSources bnfo,
+                        inputSourceFiles   = [main],
+                        inputSourceModules = filter (/= mainModName) $ exeModules exe
+                    }
 
-          else return (cSources bnfo, [main], exeModules exe)
-        else return (main : cSources bnfo, [], exeModules exe)
+          else return BuildSources {
+                          cSourcesFiles      = cSources bnfo,
+                          cxxSourceFiles     = cxxSources bnfo,
+                          inputSourceFiles   = [main],
+                          inputSourceModules = exeModules exe
+                      }
+        else let (csf, cxxsf)
+                   | isCxx main = (       cSources bnfo, main : cxxSources bnfo)
+                   -- if main is not a Haskell source
+                   -- and main is not a C++ source
+                   -- then we assume that it is a C source
+                   | otherwise  = (main : cSources bnfo,        cxxSources bnfo)
 
-    flibSources :: ForeignLib -> ([FilePath], [FilePath], [ModuleName])
+             in  return BuildSources {
+                            cSourcesFiles      = csf,
+                            cxxSourceFiles     = cxxsf,
+                            inputSourceFiles   = [],
+                            inputSourceModules = exeModules exe
+                        }
+
+    flibSources :: ForeignLib -> BuildSources
     flibSources flib@ForeignLib{foreignLibBuildInfo = bnfo} =
-      (cSources bnfo, [], foreignLibModules flib)
+        BuildSources {
+            cSourcesFiles      = cSources bnfo,
+            cxxSourceFiles     = cxxSources bnfo,
+            inputSourceFiles   = [],
+            inputSourceModules = foreignLibModules flib
+        }
 
     isHaskell :: FilePath -> Bool
     isHaskell fp = elem (takeExtension fp) [".hs", ".lhs"]
 
+    isCxx :: FilePath -> Bool
+    isCxx fp = elem (takeExtension fp) [".cpp", ".cxx", ".c++"]
+
 -- | Generic build function. See comment for 'GBuildMode'.
 gbuild :: Verbosity          -> Cabal.Flag (Maybe Int)
        -> PackageDescription -> LocalBuildInfo
        -> GBuildMode         -> ComponentLocalBuildInfo -> IO ()
 gbuild verbosity numJobs pkg_descr lbi bm clbi = do
   (ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi)
-  let comp       = compiler lbi
+  let replFlags = case bm of
+          GReplExe flags _  -> flags
+          GReplFLib flags _ -> flags
+          GBuildExe{}       -> mempty
+          GBuildFLib{}      -> mempty
+      comp       = compiler lbi
       platform   = hostPlatform lbi
       implInfo   = getImplInfo comp
       runGhcProg = runGHC verbosity ghcProg comp platform
 
-  bnfo <- hackThreadedFlag verbosity
-            comp (withProfExe lbi) (gbuildInfo bm)
+  let (bnfo, threaded) = case bm of
+        GBuildFLib _ -> popThreadedFlag (gbuildInfo bm)
+        _            -> (gbuildInfo bm, False)
 
   -- the name that GHC really uses (e.g., with .exe on Windows for executables)
   let targetName = gbuildTargetName lbi bm
@@ -1161,12 +1204,16 @@
         | otherwise         = mempty
 
   rpaths <- getRPaths lbi clbi
-  (cSrcs, inputFiles, inputModules) <- gbuildSources verbosity
-                                       (specVersion pkg_descr) tmpDir bm
+  buildSources <- gbuildSources verbosity (specVersion pkg_descr) tmpDir bm
 
-  let isGhcDynamic        = isDynamic comp
+  let cSrcs               = cSourcesFiles buildSources
+      cxxSrcs             = cxxSourceFiles buildSources
+      inputFiles          = inputSourceFiles buildSources
+      inputModules        = inputSourceModules buildSources
+      isGhcDynamic        = isDynamic comp
       dynamicTooSupported = supportsDynamicToo comp
       cObjs               = map (`replaceExtension` objExtension) cSrcs
+      cxxObjs             = map (`replaceExtension` objExtension) cxxSrcs
       needDynamic         = gbuildNeedDynamic lbi bm
       needProfiling       = withProfExe lbi
 
@@ -1187,8 +1234,7 @@
                                              (withProfExeDetail lbi),
                       ghcOptHiSuffix       = toFlag "p_hi",
                       ghcOptObjSuffix      = toFlag "p_o",
-                      ghcOptExtra          = toNubListR
-                                             (hcProfOptions GHC bnfo),
+                      ghcOptExtra          = hcProfOptions GHC bnfo,
                       ghcOptHPCDir         = hpcdir Hpc.Prof
                     }
       dynOpts    = baseOpts `mappend` mempty {
@@ -1197,8 +1243,7 @@
                       ghcOptFPic           = toFlag True,
                       ghcOptHiSuffix       = toFlag "dyn_hi",
                       ghcOptObjSuffix      = toFlag "dyn_o",
-                      ghcOptExtra          = toNubListR $
-                                             hcSharedOptions GHC bnfo,
+                      ghcOptExtra          = hcSharedOptions GHC bnfo,
                       ghcOptHPCDir         = hpcdir Hpc.Dyn
                     }
       dynTooOpts = staticOpts `mappend` mempty {
@@ -1208,23 +1253,23 @@
                       ghcOptHPCDir         = hpcdir Hpc.Dyn
                     }
       linkerOpts = mempty {
-                      ghcOptLinkOptions       = toNubListR $ PD.ldOptions bnfo,
-                      ghcOptLinkLibs          = toNubListR $ extraLibs bnfo,
+                      ghcOptLinkOptions       = PD.ldOptions bnfo,
+                      ghcOptLinkLibs          = extraLibs bnfo,
                       ghcOptLinkLibPath       = toNubListR $ extraLibDirs bnfo,
                       ghcOptLinkFrameworks    = toNubListR $
                                                 PD.frameworks bnfo,
                       ghcOptLinkFrameworkDirs = toNubListR $
                                                 PD.extraFrameworkDirs bnfo,
                       ghcOptInputFiles     = toNubListR
-                                             [tmpDir </> x | x <- cObjs]
+                                             [tmpDir </> x | x <- cObjs ++ cxxObjs]
                     }
       dynLinkerOpts = mempty {
                       ghcOptRPaths         = rpaths
                    }
       replOpts   = baseOpts {
-                    ghcOptExtra            = overNubListR
-                                             Internal.filterGhciFlags
+                    ghcOptExtra            = Internal.filterGhciFlags
                                              (ghcOptExtra baseOpts)
+                                             <> replFlags
                    }
                    -- For a normal compile we do separate invocations of ghc for
                    -- compiling as for linking. But for repl we have to do just
@@ -1276,6 +1321,38 @@
     runGhcProg compileOpts { ghcOptNoLink  = toFlag True
                            , ghcOptNumJobs = numJobs }
 
+  -- build any C++ sources
+  unless (null cxxSrcs) $ do
+   info verbosity "Building C++ Sources..."
+   sequence_
+     [ do let baseCxxOpts    = Internal.componentCxxGhcOptions verbosity implInfo
+                               lbi bnfo clbi tmpDir filename
+              vanillaCxxOpts = if isGhcDynamic
+                                -- Dynamic GHC requires C++ sources to be built
+                                -- with -fPIC for REPL to work. See #2207.
+                               then baseCxxOpts { ghcOptFPic = toFlag True }
+                               else baseCxxOpts
+              profCxxOpts    = vanillaCxxOpts `mappend` mempty {
+                                 ghcOptProfilingMode = toFlag True
+                               }
+              sharedCxxOpts  = vanillaCxxOpts `mappend` mempty {
+                                 ghcOptFPic        = toFlag True,
+                                 ghcOptDynLinkMode = toFlag GhcDynamicOnly
+                               }
+              opts | needProfiling = profCxxOpts
+                   | needDynamic   = sharedCxxOpts
+                   | otherwise     = vanillaCxxOpts
+              -- TODO: Placing all Haskell, C, & C++ objects in a single directory
+              --       Has the potential for file collisions. In general we would
+              --       consider this a user error. However, we should strive to
+              --       add a warning if this occurs.
+              odir = fromFlag (ghcOptObjDir opts)
+          createDirectoryIfMissingVerbose verbosity True odir
+          needsRecomp <- checkNeedsRecompilation filename opts
+          when needsRecomp $
+            runGhcProg opts
+     | filename <- cxxSrcs ]
+
   -- build any C sources
   unless (null cSrcs) $ do
    info verbosity "Building C Sources..."
@@ -1308,8 +1385,8 @@
   -- with ghci, but .c files can depend on .h files generated by ghc by ffi
   -- exports.
   case bm of
-    GReplExe  _ -> runGhcProg replOpts
-    GReplFLib _ -> runGhcProg replOpts
+    GReplExe  _ _ -> runGhcProg replOpts
+    GReplFLib _ _ -> runGhcProg replOpts
     GBuildExe _ -> do
       let linkOpts = commonOpts
                    `mappend` linkerOpts
@@ -1328,6 +1405,15 @@
       runGhcProg linkOpts { ghcOptOutputFile = toFlag target }
     GBuildFLib flib -> do
       let rtsInfo  = extractRtsInfo lbi
+          rtsOptLinkLibs = [
+              if needDynamic
+                  then if threaded
+                            then dynRtsThreadedLib (rtsDynamicInfo rtsInfo)
+                            else dynRtsVanillaLib (rtsDynamicInfo rtsInfo)
+                  else if threaded
+                           then statRtsThreadedLib (rtsStaticInfo rtsInfo)
+                           else statRtsVanillaLib (rtsStaticInfo rtsInfo)
+              ]
           linkOpts = case foreignLibType flib of
             ForeignLibNativeShared ->
                         commonOpts
@@ -1336,19 +1422,15 @@
               `mappend` mempty {
                  ghcOptLinkNoHsMain    = toFlag True,
                  ghcOptShared          = toFlag True,
-                 ghcOptLinkLibs        = toNubListR [
-                                           if needDynamic
-                                             then rtsDynamicLib rtsInfo
-                                             else rtsStaticLib  rtsInfo
-                                           ],
+                 ghcOptLinkLibs        = rtsOptLinkLibs,
                  ghcOptLinkLibPath     = toNubListR $ rtsLibPaths rtsInfo,
                  ghcOptFPic            = toFlag True,
                  ghcOptLinkModDefFiles = toNubListR $ gbuildModDefFiles bm
                 }
               -- See Note [RPATH]
               `mappend` ifNeedsRPathWorkaround lbi mempty {
-                  ghcOptLinkOptions = toNubListR ["-Wl,--no-as-needed"]
-                , ghcOptLinkLibs    = toNubListR ["ffi"]
+                  ghcOptLinkOptions = ["-Wl,--no-as-needed"]
+                , ghcOptLinkLibs    = ["ffi"]
                 }
             ForeignLibNativeStatic ->
               -- this should be caught by buildFLib
@@ -1441,10 +1523,30 @@
     Platform _ Linux -> a
     _otherwise       -> mempty
 
+data DynamicRtsInfo = DynamicRtsInfo {
+    dynRtsVanillaLib          :: FilePath
+  , dynRtsThreadedLib         :: FilePath
+  , dynRtsDebugLib            :: FilePath
+  , dynRtsEventlogLib         :: FilePath
+  , dynRtsThreadedDebugLib    :: FilePath
+  , dynRtsThreadedEventlogLib :: FilePath
+  }
+
+data StaticRtsInfo = StaticRtsInfo {
+    statRtsVanillaLib           :: FilePath
+  , statRtsThreadedLib          :: FilePath
+  , statRtsDebugLib             :: FilePath
+  , statRtsEventlogLib          :: FilePath
+  , statRtsThreadedDebugLib     :: FilePath
+  , statRtsThreadedEventlogLib  :: FilePath
+  , statRtsProfilingLib         :: FilePath
+  , statRtsThreadedProfilingLib :: FilePath
+  }
+
 data RtsInfo = RtsInfo {
-    rtsDynamicLib :: FilePath
-  , rtsStaticLib  :: FilePath
-  , rtsLibPaths   :: [FilePath]
+    rtsDynamicInfo :: DynamicRtsInfo
+  , rtsStaticInfo  :: StaticRtsInfo
+  , rtsLibPaths    :: [FilePath]
   }
 
 -- | Extract (and compute) information about the RTS library
@@ -1461,12 +1563,27 @@
   where
     aux :: InstalledPackageInfo -> RtsInfo
     aux rts = RtsInfo {
-        rtsDynamicLib = "HSrts-ghc" ++ display ghcVersion
-      , rtsStaticLib  = "HSrts"
+        rtsDynamicInfo = DynamicRtsInfo {
+            dynRtsVanillaLib          = withGhcVersion "HSrts"
+          , dynRtsThreadedLib         = withGhcVersion "HSrts_thr"
+          , dynRtsDebugLib            = withGhcVersion "HSrts_debug"
+          , dynRtsEventlogLib         = withGhcVersion "HSrts_l"
+          , dynRtsThreadedDebugLib    = withGhcVersion "HSrts_thr_debug"
+          , dynRtsThreadedEventlogLib = withGhcVersion "HSrts_thr_l"
+          }
+      , rtsStaticInfo = StaticRtsInfo {
+            statRtsVanillaLib           = "HSrts"
+          , statRtsThreadedLib          = "HSrts_thr"
+          , statRtsDebugLib             = "HSrts_debug"
+          , statRtsEventlogLib          = "HSrts_l"
+          , statRtsThreadedDebugLib     = "HSrts_thr_debug"
+          , statRtsThreadedEventlogLib  = "HSrts_thr_l"
+          , statRtsProfilingLib         = "HSrts_p"
+          , statRtsThreadedProfilingLib = "HSrts_thr_p"
+          }
       , rtsLibPaths   = InstalledPackageInfo.libraryDirs rts
       }
-    ghcVersion :: Version
-    ghcVersion = compilerVersion (compiler lbi)
+    withGhcVersion = (++ ("-ghc" ++ display (compilerVersion (compiler lbi))))
 
 -- | Returns True if the modification date of the given source file is newer than
 -- the object file we last compiled for it, or if no object file exists yet.
@@ -1531,22 +1648,27 @@
 
 getRPaths _ _ = return mempty
 
--- | Filter the "-threaded" flag when profiling as it does not
---   work with ghc-6.8 and older.
-hackThreadedFlag :: Verbosity -> Compiler -> Bool -> BuildInfo -> IO BuildInfo
-hackThreadedFlag verbosity comp prof bi
-  | not mustFilterThreaded = return bi
-  | otherwise              = do
-    warn verbosity $ "The ghc flag '-threaded' is not compatible with "
-                  ++ "profiling in ghc-6.8 and older. It will be disabled."
-    return bi { options = filterHcOptions (/= "-threaded") (options bi) }
+-- | Remove the "-threaded" flag when building a foreign library, as it has no
+--   effect when used with "-shared". Returns the updated 'BuildInfo', along
+--   with whether or not the flag was present, so we can use it to link against
+--   the appropriate RTS on our own.
+popThreadedFlag :: BuildInfo -> (BuildInfo, Bool)
+popThreadedFlag bi =
+  ( bi { options = filterHcOptions (/= "-threaded") (options bi) }
+  , hasThreaded (options bi))
+
   where
-    mustFilterThreaded = prof && compilerVersion comp < mkVersion [6, 10]
-                      && "-threaded" `elem` hcOptions GHC bi
+    filterHcOptions :: (String -> Bool)
+                    -> [(CompilerFlavor, [String])]
+                    -> [(CompilerFlavor, [String])]
     filterHcOptions p hcoptss =
       [ (hc, if hc == GHC then filter p opts else opts)
       | (hc, opts) <- hcoptss ]
 
+    hasThreaded :: [(CompilerFlavor, [String])] -> Bool
+    hasThreaded hcoptss =
+      or [ if hc == GHC then elem "-threaded" opts else False
+         | (hc, opts) <- hcoptss ]
 
 -- | Extracts a String representing a hash of the ABI of a built
 -- library.  It can fail if the library has not yet been built.
@@ -1554,9 +1676,8 @@
 libAbiHash :: Verbosity -> PackageDescription -> LocalBuildInfo
            -> Library -> ComponentLocalBuildInfo -> IO String
 libAbiHash verbosity _pkg_descr lbi lib clbi = do
-  libBi <- hackThreadedFlag verbosity
-             (compiler lbi) (withProfLib lbi) (libBuildInfo lib)
   let
+      libBi = libBuildInfo lib
       comp        = compiler lbi
       platform    = hostPlatform lbi
       vanillaArgs0 =
@@ -1576,7 +1697,7 @@
                        ghcOptFPic        = toFlag True,
                        ghcOptHiSuffix    = toFlag "dyn_hi",
                        ghcOptObjSuffix   = toFlag "dyn_o",
-                       ghcOptExtra       = toNubListR $ hcSharedOptions GHC libBi
+                       ghcOptExtra       = hcSharedOptions GHC libBi
                    }
       profArgs   = vanillaArgs `mappend` mempty {
                      ghcOptProfilingMode = toFlag True,
@@ -1584,7 +1705,7 @@
                                              (withProfLibDetail lbi),
                      ghcOptHiSuffix      = toFlag "p_hi",
                      ghcOptObjSuffix     = toFlag "p_o",
-                     ghcOptExtra         = toNubListR $ hcProfOptions GHC libBi
+                     ghcOptExtra         = hcProfOptions GHC libBi
                    }
       ghcArgs
         | withVanillaLib lbi = vanillaArgs
@@ -1632,15 +1753,15 @@
   (progprefix, progsuffix) _pkg exe = do
   createDirectoryIfMissingVerbose verbosity True binDir
   let exeName' = unUnqualComponentName $ exeName exe
-      exeFileName = exeTargetName exe
+      exeFileName = exeTargetName (hostPlatform lbi) exe
       fixedExeBaseName = progprefix ++ exeName' ++ progsuffix
       installBinary dest = do
           installExecutableFile verbosity
             (buildPref </> exeName' </> exeFileName)
-            (dest <.> exeExtension)
+            (dest <.> exeExtension (hostPlatform lbi))
           when (stripExes lbi) $
             Strip.stripExe verbosity (hostPlatform lbi) (withPrograms lbi)
-                           (dest <.> exeExtension)
+                           (dest <.> exeExtension (hostPlatform lbi))
   installBinary (binDir </> fixedExeBaseName)
 
 -- |Install foreign library for GHC.
@@ -1715,9 +1836,11 @@
                 | l <- getHSLibraryName (componentUnitId clbi):(extraBundledLibs (libBuildInfo lib))
                 , f <- "":extraLibFlavours (libBuildInfo lib)
                 ]
-    whenProf    $ installOrdinary builtDir targetDir       profileLibName
-    whenGHCi    $ installOrdinary builtDir targetDir       ghciLibName
-    whenShared  $ installShared   builtDir dynlibTargetDir sharedLibName
+      whenGHCi $ installOrdinary builtDir targetDir ghciLibName
+    whenProf $ do
+      installOrdinary builtDir targetDir profileLibName
+      whenGHCi $ installOrdinary builtDir targetDir ghciProfLibName
+    whenShared  $ installShared builtDir dynlibTargetDir sharedLibName
 
   where
     builtDir = componentBuildDir lbi clbi
@@ -1746,10 +1869,12 @@
     uid = componentUnitId clbi
     profileLibName = mkProfLibName          uid
     ghciLibName    = Internal.mkGHCiLibName uid
-    sharedLibName  = (mkSharedLibName compiler_id) uid
+    ghciProfLibName = Internal.mkGHCiProfLibName uid
+    sharedLibName  = (mkSharedLibName (hostPlatform lbi) compiler_id) uid
 
     hasLib    = not $ null (allLibModules lib clbi)
                    && null (cSources (libBuildInfo lib))
+                   && null (cxxSources (libBuildInfo lib))
     has_code = not (componentIsIndefinite clbi)
     whenHasCode = when has_code
     whenVanilla = when (hasLib && withVanillaLib lbi)
diff --git a/cabal/Cabal/Distribution/Simple/GHC/EnvironmentParser.hs b/cabal/Cabal/Distribution/Simple/GHC/EnvironmentParser.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/Simple/GHC/EnvironmentParser.hs
@@ -0,0 +1,51 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+module Distribution.Simple.GHC.EnvironmentParser
+    ( parseGhcEnvironmentFile, readGhcEnvironmentFile, ParseErrorExc(..) ) where
+
+import Prelude ()
+import Distribution.Compat.Prelude
+
+import Distribution.Simple.Compiler
+    ( PackageDB(..) )
+import Distribution.Simple.GHC.Internal
+    ( GhcEnvironmentFileEntry(..) )
+import Distribution.Types.UnitId
+    ( mkUnitId )
+
+import Control.Exception
+    ( Exception, throwIO )
+import qualified Text.Parsec as P
+import Text.Parsec.String
+    ( Parser, parseFromFile )
+
+parseEnvironmentFileLine :: Parser GhcEnvironmentFileEntry
+parseEnvironmentFileLine =      GhcEnvFileComment             <$> comment
+                       <|>      GhcEnvFilePackageId           <$> unitId
+                       <|>      GhcEnvFilePackageDb           <$> packageDb
+                       <|> pure GhcEnvFileClearPackageDbStack <*  clearDb
+    where
+        comment = P.string "--" *> P.many (P.noneOf "\r\n")
+        unitId = P.try $ P.string "package-id" *> P.spaces *>
+            (mkUnitId <$> P.many1 (P.satisfy $ \c -> isAlphaNum c || c `elem` "-_.+"))
+        packageDb = (P.string "global-package-db"      *> pure GlobalPackageDB)
+                <|> (P.string "user-package-db"        *> pure UserPackageDB)
+                <|> (P.string "package-db" *> P.spaces *> (SpecificPackageDB <$> P.many1 (P.noneOf "\r\n") <* P.lookAhead P.endOfLine))
+        clearDb = P.string "clear-package-db"
+
+newtype ParseErrorExc = ParseErrorExc P.ParseError
+                      deriving (Show, Typeable)
+
+instance Exception ParseErrorExc
+
+parseGhcEnvironmentFile :: Parser [GhcEnvironmentFileEntry]
+parseGhcEnvironmentFile = parseEnvironmentFileLine `P.sepEndBy` P.endOfLine <* P.eof
+
+readGhcEnvironmentFile :: FilePath -> IO [GhcEnvironmentFileEntry]
+readGhcEnvironmentFile path =
+    either (throwIO . ParseErrorExc) return =<<
+        parseFromFile parseGhcEnvironmentFile path
diff --git a/cabal/Cabal/Distribution/Simple/GHC/IPI642.hs b/cabal/Cabal/Distribution/Simple/GHC/IPI642.hs
deleted file mode 100644
--- a/cabal/Cabal/Distribution/Simple/GHC/IPI642.hs
+++ /dev/null
@@ -1,114 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Distribution.Simple.GHC.IPI642
--- Copyright   :  (c) The University of Glasgow 2004
--- License     :  BSD3
---
--- Maintainer  :  cabal-devel@haskell.org
--- Portability :  portable
---
-
-module Distribution.Simple.GHC.IPI642 (
-    InstalledPackageInfo(..),
-    toCurrent,
-  ) where
-
-import Prelude ()
-import Distribution.Compat.Prelude
-
-import qualified Distribution.InstalledPackageInfo as Current
-import qualified Distribution.Types.AbiHash        as Current
-import qualified Distribution.Types.ComponentId    as Current
-import qualified Distribution.Types.UnitId         as Current
-import Distribution.Simple.GHC.IPIConvert
-import Distribution.Text
-
--- | This is the InstalledPackageInfo type used by ghc-6.4.2 and later.
---
--- It's here purely for the 'Read' instance so that we can read the package
--- database used by those ghc versions. It is a little hacky to read the
--- package db directly, but we do need the info and until ghc-6.9 there was
--- no better method.
---
--- In ghc-6.4.1 and before the format was slightly different.
--- See "Distribution.Simple.GHC.IPI642"
---
-data InstalledPackageInfo = InstalledPackageInfo {
-    package           :: PackageIdentifier,
-    license           :: License,
-    copyright         :: String,
-    maintainer        :: String,
-    author            :: String,
-    stability         :: String,
-    homepage          :: String,
-    pkgUrl            :: String,
-    description       :: String,
-    category          :: String,
-    exposed           :: Bool,
-    exposedModules    :: [String],
-    hiddenModules     :: [String],
-    importDirs        :: [FilePath],
-    libraryDirs       :: [FilePath],
-    hsLibraries       :: [String],
-    extraLibraries    :: [String],
-    extraGHCiLibraries:: [String],
-    includeDirs       :: [FilePath],
-    includes          :: [String],
-    depends           :: [PackageIdentifier],
-    hugsOptions       :: [String],
-    ccOptions         :: [String],
-    ldOptions         :: [String],
-    frameworkDirs     :: [FilePath],
-    frameworks        :: [String],
-    haddockInterfaces :: [FilePath],
-    haddockHTMLs      :: [FilePath]
-  }
-  deriving Read
-
-toCurrent :: InstalledPackageInfo -> Current.InstalledPackageInfo
-toCurrent ipi@InstalledPackageInfo{} =
-  let mkExposedModule m = Current.ExposedModule m Nothing
-      pid = convertPackageId (package ipi)
-  in Current.InstalledPackageInfo {
-    Current.sourcePackageId    = pid,
-    Current.installedUnitId    = Current.mkLegacyUnitId pid,
-    Current.installedComponentId_ = Current.mkComponentId (display pid),
-    Current.instantiatedWith   = [],
-    -- Internal libraries not supported!
-    Current.sourceLibName      = Nothing,
-    Current.compatPackageKey   = "",
-    Current.abiHash            = Current.mkAbiHash "", -- bogus but old GHCs don't care.
-    Current.license            = convertLicense (license ipi),
-    Current.copyright          = copyright ipi,
-    Current.maintainer         = maintainer ipi,
-    Current.author             = author ipi,
-    Current.stability          = stability ipi,
-    Current.homepage           = homepage ipi,
-    Current.pkgUrl             = pkgUrl ipi,
-    Current.synopsis           = "",
-    Current.description        = description ipi,
-    Current.category           = category ipi,
-    Current.indefinite         = False,
-    Current.exposed            = exposed ipi,
-    Current.exposedModules     = map (mkExposedModule . convertModuleName) (exposedModules ipi),
-    Current.hiddenModules      = map convertModuleName (hiddenModules ipi),
-    Current.trusted            = Current.trusted Current.emptyInstalledPackageInfo,
-    Current.importDirs         = importDirs ipi,
-    Current.libraryDirs        = libraryDirs ipi,
-    Current.libraryDynDirs     = [],
-    Current.dataDir            = "",
-    Current.hsLibraries        = hsLibraries ipi,
-    Current.extraLibraries     = extraLibraries ipi,
-    Current.extraGHCiLibraries = extraGHCiLibraries ipi,
-    Current.includeDirs        = includeDirs ipi,
-    Current.includes           = includes ipi,
-    Current.depends            = map (Current.mkLegacyUnitId . convertPackageId) (depends ipi),
-    Current.abiDepends         = [],
-    Current.ccOptions          = ccOptions ipi,
-    Current.ldOptions          = ldOptions ipi,
-    Current.frameworkDirs      = frameworkDirs ipi,
-    Current.frameworks         = frameworks ipi,
-    Current.haddockInterfaces  = haddockInterfaces ipi,
-    Current.haddockHTMLs       = haddockHTMLs ipi,
-    Current.pkgRoot            = Nothing
-  }
diff --git a/cabal/Cabal/Distribution/Simple/GHC/IPIConvert.hs b/cabal/Cabal/Distribution/Simple/GHC/IPIConvert.hs
deleted file mode 100644
--- a/cabal/Cabal/Distribution/Simple/GHC/IPIConvert.hs
+++ /dev/null
@@ -1,54 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Distribution.Simple.GHC.IPI642
--- Copyright   :  (c) The University of Glasgow 2004
--- License     :  BSD3
---
--- Maintainer  :  cabal-devel@haskell.org
--- Portability :  portable
---
--- Helper functions for 'Distribution.Simple.GHC.IPI642'.
-module Distribution.Simple.GHC.IPIConvert (
-    PackageIdentifier, convertPackageId,
-    License, convertLicense,
-    convertModuleName
-  ) where
-
-import Prelude ()
-import Distribution.Compat.Prelude
-
-import qualified Distribution.Types.PackageId as Current
-import qualified Distribution.Types.PackageName as Current
-import qualified Distribution.License as Current
-
-import Distribution.Version
-import Distribution.ModuleName
-import Distribution.Text
-
--- | This is a indeed a munged package id, but the constructor name cannot be
--- changed or the Read instance (the entire point of this type) will break.
-data PackageIdentifier = PackageIdentifier {
-    pkgName    :: String,
-    pkgVersion :: Version
-  }
-  deriving Read
-
-convertPackageId :: PackageIdentifier -> Current.PackageId
-convertPackageId PackageIdentifier { pkgName = n, pkgVersion = v } =
-  Current.PackageIdentifier (Current.mkPackageName n) v
-
-data License = GPL | LGPL | BSD3 | BSD4
-             | PublicDomain | AllRightsReserved | OtherLicense
-  deriving Read
-
-convertModuleName :: String -> ModuleName
-convertModuleName s = fromMaybe (error "convertModuleName") $ simpleParse s
-
-convertLicense :: License -> Current.License
-convertLicense GPL  = Current.GPL  Nothing
-convertLicense LGPL = Current.LGPL Nothing
-convertLicense BSD3 = Current.BSD3
-convertLicense BSD4 = Current.BSD4
-convertLicense PublicDomain = Current.PublicDomain
-convertLicense AllRightsReserved = Current.AllRightsReserved
-convertLicense OtherLicense = Current.OtherLicense
diff --git a/cabal/Cabal/Distribution/Simple/GHC/ImplInfo.hs b/cabal/Cabal/Distribution/Simple/GHC/ImplInfo.hs
--- a/cabal/Cabal/Distribution/Simple/GHC/ImplInfo.hs
+++ b/cabal/Cabal/Distribution/Simple/GHC/ImplInfo.hs
@@ -11,7 +11,7 @@
 
 module Distribution.Simple.GHC.ImplInfo (
         GhcImplInfo(..), getImplInfo,
-        ghcVersionImplInfo, ghcjsVersionImplInfo, lhcVersionImplInfo
+        ghcVersionImplInfo, ghcjsVersionImplInfo
         ) where
 
 import Prelude ()
@@ -50,13 +50,12 @@
 getImplInfo comp =
   case compilerFlavor comp of
     GHC   -> ghcVersionImplInfo (compilerVersion comp)
-    LHC   -> lhcVersionImplInfo (compilerVersion comp)
     GHCJS -> case compilerCompatVersion GHC comp of
               Just ghcVer -> ghcjsVersionImplInfo (compilerVersion comp) ghcVer
               _  -> error ("Distribution.Simple.GHC.Props.getImplProps: " ++
                            "could not find GHC version for GHCJS compiler")
     x     -> error ("Distribution.Simple.GHC.Props.getImplProps only works" ++
-                    "for GHC-like compilers (GHC, GHCJS, LHC)" ++
+                    "for GHC-like compilers (GHC, GHCJS)" ++
                     ", but found " ++ show x)
 
 ghcVersionImplInfo :: Version -> GhcImplInfo
@@ -88,10 +87,7 @@
   , flagDebugInfo        = False
   , supportsDebugLevels  = ghcv >= [8,0]
   , supportsPkgEnvFiles  = ghcv >= [8,0,2] --TODO: check this works in ghcjs
-  , flagWarnMissingHomeModules = False
+  , flagWarnMissingHomeModules = ghcv >= [8,2]
   }
   where
     ghcv = versionNumbers ghcver
-
-lhcVersionImplInfo :: Version -> GhcImplInfo
-lhcVersionImplInfo = ghcVersionImplInfo
diff --git a/cabal/Cabal/Distribution/Simple/GHC/Internal.hs b/cabal/Cabal/Distribution/Simple/GHC/Internal.hs
--- a/cabal/Cabal/Distribution/Simple/GHC/Internal.hs
+++ b/cabal/Cabal/Distribution/Simple/GHC/Internal.hs
@@ -22,6 +22,7 @@
         componentCxxGhcOptions,
         componentGhcOptions,
         mkGHCiLibName,
+        mkGHCiProfLibName,
         filterGhciFlags,
         ghcLookupProperty,
         getHaskellObjects,
@@ -107,8 +108,8 @@
     }
   where
     compilerDir = takeDirectory (programPath ghcProg)
-    baseDir     = takeDirectory compilerDir
-    mingwBinDir = baseDir </> "mingw" </> "bin"
+    base_dir     = takeDirectory compilerDir
+    mingwBinDir = base_dir </> "mingw" </> "bin"
     isWindows   = case buildOS of Windows -> True; _ -> False
     binPrefix   = ""
 
@@ -232,7 +233,7 @@
           die' verbosity "Can't parse --info output of GHC"
 
 getExtensions :: Verbosity -> GhcImplInfo -> ConfiguredProgram
-              -> IO [(Extension, String)]
+              -> IO [(Extension, Maybe String)]
 getExtensions verbosity implInfo ghcProg = do
     str <- getProgramOutput verbosity (suppressOverrideArgs ghcProg)
               ["--supported-languages"]
@@ -247,14 +248,16 @@
                                        _              -> "No" ++ extStr
                        , extStr'' <- [extStr, extStr']
                        ]
-    let extensions0 = [ (ext, "-X" ++ display ext)
+    let extensions0 = [ (ext, Just $ "-X" ++ display ext)
                       | Just ext <- map simpleParse extStrs ]
         extensions1 = if alwaysNondecIndent implInfo
                       then -- ghc-7.2 split NondecreasingIndentation off
                            -- into a proper extension. Before that it
                            -- was always on.
-                           (EnableExtension  NondecreasingIndentation, "") :
-                           (DisableExtension NondecreasingIndentation, "") :
+                           -- Since it was not a proper extension, it could
+                           -- not be turned off, hence we omit a
+                           -- DisableExtension entry here.
+                           (EnableExtension NondecreasingIndentation, Nothing) :
                            extensions0
                       else extensions0
     return extensions1
@@ -274,12 +277,15 @@
       ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi clbi
                                           ,autogenPackageModulesDir lbi
                                           ,odir]
-                                          ++ PD.includeDirs bi,
+                                          -- includes relative to the package
+                                          ++ PD.includeDirs bi
+                                          -- potential includes generated by `configure'
+                                          -- in the build directory
+                                          ++ [buildDir lbi </> dir | dir <- PD.includeDirs bi],
       ghcOptHideAllPackages= toFlag True,
       ghcOptPackageDBs     = withPackageDB lbi,
       ghcOptPackages       = toNubListR $ mkGhcOptPackages clbi,
-      ghcOptCcOptions      = toNubListR $
-                             (case withOptimization lbi of
+      ghcOptCcOptions      = (case withOptimization lbi of
                                   NoOptimisation -> []
                                   _              -> ["-O2"]) ++
                              (case withDebugInfo lbi of
@@ -296,7 +302,7 @@
                       -> BuildInfo -> ComponentLocalBuildInfo
                       -> FilePath -> FilePath
                       -> GhcOptions
-componentCxxGhcOptions verbosity _implInfo lbi bi cxxlbi odir filename =
+componentCxxGhcOptions verbosity _implInfo lbi bi clbi odir filename =
     mempty {
       -- Respect -v0, but don't crank up verbosity on GHC if
       -- Cabal verbosity is requested. For that, use --ghc-option=-v instead!
@@ -304,15 +310,18 @@
       ghcOptMode           = toFlag GhcModeCompile,
       ghcOptInputFiles     = toNubListR [filename],
 
-      ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi cxxlbi
+      ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi clbi
                                           ,autogenPackageModulesDir lbi
                                           ,odir]
-                                          ++ PD.includeDirs bi,
+                                          -- includes relative to the package
+                                          ++ PD.includeDirs bi
+                                          -- potential includes generated by `configure'
+                                          -- in the build directory
+                                          ++ [buildDir lbi </> dir | dir <- PD.includeDirs bi],
       ghcOptHideAllPackages= toFlag True,
       ghcOptPackageDBs     = withPackageDB lbi,
-      ghcOptPackages       = toNubListR $ mkGhcOptPackages cxxlbi,
-      ghcOptCxxOptions     = toNubListR $
-                             (case withOptimization lbi of
+      ghcOptPackages       = toNubListR $ mkGhcOptPackages clbi,
+      ghcOptCxxOptions     = (case withOptimization lbi of
                                   NoOptimisation -> []
                                   _              -> ["-O2"]) ++
                              (case withDebugInfo lbi of
@@ -363,8 +372,12 @@
       ghcOptCppIncludePath  = toNubListR $ [autogenComponentModulesDir lbi clbi
                                            ,autogenPackageModulesDir lbi
                                            ,odir]
-                                           ++ PD.includeDirs bi,
-      ghcOptCppOptions      = toNubListR $ cppOptions bi,
+                                           -- includes relative to the package
+                                           ++ PD.includeDirs bi
+                                           -- potential includes generated by `configure'
+                                           -- in the build directory
+                                           ++ [buildDir lbi </> dir | dir <- PD.includeDirs bi],
+      ghcOptCppOptions      = cppOptions bi,
       ghcOptCppIncludes     = toNubListR $
                               [autogenComponentModulesDir lbi clbi </> cppHeaderName],
       ghcOptFfiIncludes     = toNubListR $ PD.includes bi,
@@ -374,7 +387,7 @@
       ghcOptOutputDir       = toFlag odir,
       ghcOptOptimisation    = toGhcOptimisation (withOptimization lbi),
       ghcOptDebugInfo       = toFlag (withDebugInfo lbi),
-      ghcOptExtra           = toNubListR $ hcOptions GHC bi,
+      ghcOptExtra           = hcOptions GHC bi,
       ghcOptExtraPath       = toNubListR $ exe_paths,
       ghcOptLanguage        = toFlag (fromMaybe Haskell98 (defaultLanguage bi)),
       -- Unsupported extensions have already been checked by configure
@@ -407,6 +420,9 @@
 mkGHCiLibName :: UnitId -> String
 mkGHCiLibName lib = getHSLibraryName lib <.> "o"
 
+mkGHCiProfLibName :: UnitId -> String
+mkGHCiProfLibName lib = getHSLibraryName lib <.> "p_o"
+
 ghcLookupProperty :: String -> Compiler -> Bool
 ghcLookupProperty prop comp =
   case Map.lookup prop (compilerProperties comp) of
@@ -499,7 +515,7 @@
 -- -----------------------------------------------------------------------------
 -- GHC platform and version strings
 
--- | GHC's rendering of it's host or target 'Arch' as used in its platform
+-- | GHC's rendering of its host or target 'Arch' as used in its platform
 -- strings and certain file locations (such as user package db location).
 --
 ghcArchString :: Arch -> String
@@ -507,7 +523,7 @@
 ghcArchString PPC64 = "powerpc64"
 ghcArchString other = display other
 
--- | GHC's rendering of it's host or target 'OS' as used in its platform
+-- | GHC's rendering of its host or target 'OS' as used in its platform
 -- strings and certain file locations (such as user package db location).
 --
 ghcOsString :: OS -> String
@@ -516,7 +532,7 @@
 ghcOsString Solaris = "solaris2"
 ghcOsString other   = display other
 
--- | GHC's rendering of it's platform and compiler version string as used in
+-- | GHC's rendering of its platform and compiler version string as used in
 -- certain file locations (such as user package db location).
 -- For example @x86_64-linux-7.10.4@
 --
@@ -537,6 +553,7 @@
                                       --   @user-package-db@ or
                                       --   @package-db blah/package.conf.d/@
      | GhcEnvFileClearPackageDbStack  -- ^ @clear-package-db@
+     deriving (Eq, Ord, Show)
 
 -- | Make entries for a GHC environment file based on a 'PackageDBStack' and
 -- a bunch of package (unit) ids.
diff --git a/cabal/Cabal/Distribution/Simple/GHCJS.hs b/cabal/Cabal/Distribution/Simple/GHCJS.hs
--- a/cabal/Cabal/Distribution/Simple/GHCJS.hs
+++ b/cabal/Cabal/Distribution/Simple/GHCJS.hs
@@ -150,12 +150,12 @@
            path              = programPath ghcjsProg
            dir               = takeDirectory path
            versionSuffix     = takeVersionSuffix (dropExeExtension path)
-           guessNormal       = dir </> toolname <.> exeExtension
+           guessNormal       = dir </> toolname <.> exeExtension buildPlatform
            guessGhcjsVersioned = dir </> (toolname ++ "-ghcjs" ++ versionSuffix)
-                                 <.> exeExtension
+                                 <.> exeExtension buildPlatform
            guessGhcjs        = dir </> (toolname ++ "-ghcjs")
-                               <.> exeExtension
-           guessVersioned    = dir </> (toolname ++ versionSuffix) <.> exeExtension
+                               <.> exeExtension buildPlatform
+           guessVersioned    = dir </> (toolname ++ versionSuffix) <.> exeExtension buildPlatform
            guesses | null versionSuffix = [guessGhcjs, guessNormal]
                    | otherwise          = [guessGhcjsVersioned,
                                            guessGhcjs,
@@ -259,16 +259,22 @@
   | takeExtension lib == ".a" = replaceExtension lib "js_a"
   | otherwise                 = lib <.> "js_a"
 
-buildLib, replLib :: Verbosity -> Cabal.Flag (Maybe Int) -> PackageDescription
-                  -> LocalBuildInfo -> Library -> ComponentLocalBuildInfo
-                  -> IO ()
-buildLib = buildOrReplLib False
-replLib  = buildOrReplLib True
+buildLib :: Verbosity -> Cabal.Flag (Maybe Int) -> PackageDescription
+         -> LocalBuildInfo -> Library -> ComponentLocalBuildInfo
+         -> IO ()
+buildLib = buildOrReplLib Nothing
 
-buildOrReplLib :: Bool -> Verbosity  -> Cabal.Flag (Maybe Int)
-               -> PackageDescription -> LocalBuildInfo
-               -> Library            -> ComponentLocalBuildInfo -> IO ()
-buildOrReplLib forRepl verbosity numJobs pkg_descr lbi lib clbi = do
+replLib :: [String]                -> Verbosity
+        -> Cabal.Flag (Maybe Int)  -> PackageDescription
+        -> LocalBuildInfo          -> Library
+        -> ComponentLocalBuildInfo -> IO ()
+replLib = buildOrReplLib . Just
+
+buildOrReplLib :: Maybe [String] -> Verbosity
+               -> Cabal.Flag (Maybe Int)  -> PackageDescription
+               -> LocalBuildInfo          -> Library
+               -> ComponentLocalBuildInfo -> IO ()
+buildOrReplLib mReplFlags verbosity numJobs pkg_descr lbi lib clbi = do
   let uid = componentUnitId clbi
       libTargetDir = buildDir lbi
       whenVanillaLib forceVanilla =
@@ -276,8 +282,10 @@
       whenProfLib = when (not forRepl && withProfLib lbi)
       whenSharedLib forceShared =
         when (not forRepl &&  (forceShared || withSharedLib lbi))
-      whenGHCiLib = when (not forRepl && withGHCiLib lbi && withVanillaLib lbi)
+      whenGHCiLib = when (not forRepl && withGHCiLib lbi)
+      forRepl = maybe False (const True) mReplFlags
       ifReplLib = when forRepl
+      replFlags = fromMaybe mempty mReplFlags
       comp      = compiler lbi
       platform  = hostPlatform lbi
       implInfo  = getImplInfo comp
@@ -309,10 +317,10 @@
       jsSrcs      = jsSources libBi
       baseOpts    = componentGhcOptions verbosity lbi libBi clbi libTargetDir
       linkJsLibOpts = mempty {
-                        ghcOptExtra = toNubListR $
+                        ghcOptExtra =
                           [ "-link-js-lib"     , getHSLibraryName uid
                           , "-js-lib-outputdir", libTargetDir ] ++
-                          concatMap (\x -> ["-js-lib-src",x]) jsSrcs
+                          jsSrcs
                       }
       vanillaOptsNoJsLib = baseOpts `mappend` mempty {
                       ghcOptMode         = toFlag GhcModeMake,
@@ -324,29 +332,27 @@
 
       profOpts    = adjustExts "p_hi" "p_o" vanillaOpts `mappend` mempty {
                         ghcOptProfilingMode = toFlag True,
-                        ghcOptExtra         = toNubListR $
-                                              ghcjsProfOptions libBi,
+                        ghcOptExtra         = ghcjsProfOptions libBi,
                         ghcOptHPCDir        = hpcdir Hpc.Prof
                       }
       sharedOpts  = adjustExts "dyn_hi" "dyn_o" vanillaOpts `mappend` mempty {
                         ghcOptDynLinkMode = toFlag GhcDynamicOnly,
                         ghcOptFPic        = toFlag True,
-                        ghcOptExtra       = toNubListR $
-                                            ghcjsSharedOptions libBi,
+                        ghcOptExtra       = ghcjsSharedOptions libBi,
                         ghcOptHPCDir      = hpcdir Hpc.Dyn
                       }
       linkerOpts = mempty {
-                      ghcOptLinkOptions    = toNubListR $ PD.ldOptions libBi,
-                      ghcOptLinkLibs       = toNubListR $ extraLibs libBi,
+                      ghcOptLinkOptions    = PD.ldOptions libBi,
+                      ghcOptLinkLibs       = extraLibs libBi,
                       ghcOptLinkLibPath    = toNubListR $ extraLibDirs libBi,
                       ghcOptLinkFrameworks = toNubListR $ PD.frameworks libBi,
                       ghcOptInputFiles     =
                         toNubListR $ [libTargetDir </> x | x <- cObjs] ++ jsSrcs
                    }
       replOpts    = vanillaOptsNoJsLib {
-                      ghcOptExtra        = overNubListR
-                                           Internal.filterGhciFlags
-                                           (ghcOptExtra vanillaOpts),
+                      ghcOptExtra        = Internal.filterGhciFlags
+                                           (ghcOptExtra vanillaOpts)
+                                           <> replFlags,
                       ghcOptNumJobs      = mempty
                     }
                     `mappend` linkerOpts
@@ -427,8 +433,9 @@
         compiler_id = compilerId (compiler lbi)
         vanillaLibFilePath = libTargetDir </> mkLibName            uid
         profileLibFilePath = libTargetDir </> mkProfLibName        uid
-        sharedLibFilePath  = libTargetDir </> mkSharedLibName compiler_id uid
+        sharedLibFilePath  = libTargetDir </> mkSharedLibName (hostPlatform lbi) compiler_id uid
         ghciLibFilePath    = libTargetDir </> Internal.mkGHCiLibName uid
+        ghciProfLibFilePath = libTargetDir </> Internal.mkGHCiProfLibName uid
 
     hObjs     <- Internal.getHaskellObjects implInfo lib lbi clbi
                       libTargetDir objExtension True
@@ -451,9 +458,6 @@
           profObjectFiles =
                  hProfObjs
               ++ map (libTargetDir </>) cProfObjs
-          ghciObjFiles =
-                 hObjs
-              ++ map (libTargetDir </>) cObjs
           dynamicObjectFiles =
                  hSharedObjs
               ++ map (libTargetDir </>) cSharedObjs
@@ -466,26 +470,28 @@
                 ghcOptDynLinkMode        = toFlag GhcDynamicOnly,
                 ghcOptInputFiles         = toNubListR dynamicObjectFiles,
                 ghcOptOutputFile         = toFlag sharedLibFilePath,
-                ghcOptExtra              = toNubListR $
-                                           ghcjsSharedOptions libBi,
+                ghcOptExtra              = ghcjsSharedOptions libBi,
                 ghcOptNoAutoLinkPackages = toFlag True,
                 ghcOptPackageDBs         = withPackageDB lbi,
                 ghcOptPackages           = toNubListR $
                                            Internal.mkGhcOptPackages clbi,
-                ghcOptLinkLibs           = toNubListR $ extraLibs libBi,
+                ghcOptLinkLibs           = extraLibs libBi,
                 ghcOptLinkLibPath        = toNubListR $ extraLibDirs libBi
               }
 
       whenVanillaLib False $ do
         Ar.createArLibArchive verbosity lbi vanillaLibFilePath staticObjectFiles
+        whenGHCiLib $ do
+          (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)
+          Ld.combineObjectFiles verbosity lbi ldProg
+            ghciLibFilePath staticObjectFiles
 
       whenProfLib $ do
         Ar.createArLibArchive verbosity lbi profileLibFilePath profObjectFiles
-
-      whenGHCiLib $ do
-        (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)
-        Ld.combineObjectFiles verbosity lbi ldProg
-          ghciLibFilePath ghciObjFiles
+        whenGHCiLib $ do
+          (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)
+          Ld.combineObjectFiles verbosity lbi ldProg
+            ghciProfLibFilePath profObjectFiles
 
       whenSharedLib False $
         runGhcjsProg ghcSharedLinkArgs
@@ -502,20 +508,28 @@
   (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram progdb
   runGHC verbosity ghcjsProg comp platform replOpts
 
-buildExe, replExe :: Verbosity          -> Cabal.Flag (Maybe Int)
-                  -> PackageDescription -> LocalBuildInfo
-                  -> Executable         -> ComponentLocalBuildInfo -> IO ()
-buildExe = buildOrReplExe False
-replExe  = buildOrReplExe True
+buildExe :: Verbosity          -> Cabal.Flag (Maybe Int)
+         -> PackageDescription -> LocalBuildInfo
+         -> Executable         -> ComponentLocalBuildInfo -> IO ()
+buildExe = buildOrReplExe Nothing
 
-buildOrReplExe :: Bool -> Verbosity  -> Cabal.Flag (Maybe Int)
-               -> PackageDescription -> LocalBuildInfo
-               -> Executable         -> ComponentLocalBuildInfo -> IO ()
-buildOrReplExe forRepl verbosity numJobs _pkg_descr lbi
+replExe :: [String]                -> Verbosity
+        -> Cabal.Flag (Maybe Int)  -> PackageDescription
+        -> LocalBuildInfo          -> Executable
+        -> ComponentLocalBuildInfo -> IO ()
+replExe = buildOrReplExe . Just
+
+buildOrReplExe :: Maybe [String] -> Verbosity
+               -> Cabal.Flag (Maybe Int) -> PackageDescription
+               -> LocalBuildInfo -> Executable
+               -> ComponentLocalBuildInfo -> IO ()
+buildOrReplExe mReplFlags verbosity numJobs _pkg_descr lbi
   exe@Executable { exeName = exeName', modulePath = modPath } clbi = do
 
   (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram (withPrograms lbi)
-  let comp         = compiler lbi
+  let forRepl = maybe False (const True) mReplFlags
+      replFlags = fromMaybe mempty mReplFlags
+      comp         = compiler lbi
       platform     = hostPlatform lbi
       implInfo     = getImplInfo comp
       runGhcjsProg = runGHC verbosity ghcjsProg comp platform
@@ -524,8 +538,8 @@
   let exeName'' = unUnqualComponentName exeName'
   -- exeNameReal, the name that GHC really uses (with .exe on Windows)
   let exeNameReal = exeName'' <.>
-                    (if takeExtension exeName'' /= ('.':exeExtension)
-                       then exeExtension
+                    (if takeExtension exeName'' /= ('.':exeExtension buildPlatform)
+                       then exeExtension buildPlatform
                        else "")
 
   let targetDir = (buildDir lbi) </> exeName''
@@ -564,7 +578,7 @@
                       ghcOptInputModules = toNubListR $
                         [ m | not isHaskellMain, m <- exeModules exe],
                       ghcOptExtra =
-                        if buildRunner then toNubListR ["-build-runner"]
+                        if buildRunner then ["-build-runner"]
                                        else mempty
                     }
       staticOpts = baseOpts `mappend` mempty {
@@ -573,13 +587,12 @@
                    }
       profOpts   = adjustExts "p_hi" "p_o" baseOpts `mappend` mempty {
                       ghcOptProfilingMode  = toFlag True,
-                      ghcOptExtra          = toNubListR $ ghcjsProfOptions exeBi,
+                      ghcOptExtra          = ghcjsProfOptions exeBi,
                       ghcOptHPCDir         = hpcdir Hpc.Prof
                     }
       dynOpts    = adjustExts "dyn_hi" "dyn_o" baseOpts `mappend` mempty {
                       ghcOptDynLinkMode    = toFlag GhcDynamicOnly,
-                      ghcOptExtra          = toNubListR $
-                                             ghcjsSharedOptions exeBi,
+                      ghcOptExtra          = ghcjsSharedOptions exeBi,
                       ghcOptHPCDir         = hpcdir Hpc.Dyn
                     }
       dynTooOpts = adjustExts "dyn_hi" "dyn_o" staticOpts `mappend` mempty {
@@ -587,17 +600,17 @@
                       ghcOptHPCDir         = hpcdir Hpc.Dyn
                     }
       linkerOpts = mempty {
-                      ghcOptLinkOptions    = toNubListR $ PD.ldOptions exeBi,
-                      ghcOptLinkLibs       = toNubListR $ extraLibs exeBi,
+                      ghcOptLinkOptions    = PD.ldOptions exeBi,
+                      ghcOptLinkLibs       = extraLibs exeBi,
                       ghcOptLinkLibPath    = toNubListR $ extraLibDirs exeBi,
                       ghcOptLinkFrameworks = toNubListR $ PD.frameworks exeBi,
                       ghcOptInputFiles     = toNubListR $
                                              [exeDir </> x | x <- cObjs] ++ jsSrcs
                    }
       replOpts   = baseOpts {
-                      ghcOptExtra          = overNubListR
-                                             Internal.filterGhciFlags
+                      ghcOptExtra          = Internal.filterGhciFlags
                                              (ghcOptExtra baseOpts)
+                                             <> replFlags
                    }
                    -- For a normal compile we do separate invocations of ghc for
                    -- compiling as for linking. But for repl we have to do just
@@ -701,10 +714,13 @@
     whenShared  $ copyModuleFiles "dyn_hi"
 
     -- copy the built library files over:
-    whenVanilla $ installOrdinaryNative builtDir targetDir       vanillaLibName
-    whenProf    $ installOrdinaryNative builtDir targetDir       profileLibName
-    whenGHCi    $ installOrdinaryNative builtDir targetDir       ghciLibName
-    whenShared  $ installSharedNative   builtDir dynlibTargetDir sharedLibName
+    whenVanilla $ do
+      installOrdinaryNative builtDir targetDir vanillaLibName
+      whenGHCi $ installOrdinaryNative builtDir targetDir ghciLibName
+    whenProf $ do
+      installOrdinaryNative builtDir targetDir profileLibName
+      whenGHCi $ installOrdinaryNative builtDir targetDir ghciProfLibName
+    whenShared $ installSharedNative builtDir dynlibTargetDir sharedLibName
 
   where
     install isShared isJS srcDir dstDir name = do
@@ -735,7 +751,8 @@
     vanillaLibName = mkLibName              uid
     profileLibName = mkProfLibName          uid
     ghciLibName    = Internal.mkGHCiLibName uid
-    sharedLibName  = (mkSharedLibName compiler_id)  uid
+    ghciProfLibName = Internal.mkGHCiProfLibName uid
+    sharedLibName  = (mkSharedLibName (hostPlatform lbi) compiler_id)  uid
 
     hasLib    = not $ null (allLibModules lib clbi)
                    && null (cSources (libBuildInfo lib))
@@ -784,7 +801,7 @@
         }
       profArgs = adjustExts "js_p_hi" "js_p_o" vanillaArgs `mappend` mempty {
                      ghcOptProfilingMode = toFlag True,
-                     ghcOptExtra         = toNubListR (ghcjsProfOptions libBi)
+                     ghcOptExtra         = ghcjsProfOptions libBi
                  }
       ghcArgs | withVanillaLib lbi = vanillaArgs
               | withProfLib    lbi = profArgs
@@ -819,8 +836,7 @@
   let opts = Internal.componentGhcOptions verbosity implInfo lbi bi clbi odir
       comp = compiler lbi
       implInfo = getImplInfo comp
-  in  opts { ghcOptExtra = ghcOptExtra opts `mappend` toNubListR
-                             (hcOptions GHCJS bi)
+  in  opts { ghcOptExtra = ghcOptExtra opts `mappend` hcOptions GHCJS bi
            }
 
 ghcjsProfOptions :: BuildInfo -> [String]
diff --git a/cabal/Cabal/Distribution/Simple/Glob.hs b/cabal/Cabal/Distribution/Simple/Glob.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/Simple/Glob.hs
@@ -0,0 +1,295 @@
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE RankNTypes #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Distribution.Simple.Glob
+-- Copyright   :  Isaac Jones, Simon Marlow 2003-2004
+-- License     :  BSD3
+--                portions Copyright (c) 2007, Galois Inc.
+--
+-- Maintainer  :  cabal-devel@haskell.org
+-- Portability :  portable
+--
+-- Simple file globbing.
+
+module Distribution.Simple.Glob (
+        GlobSyntaxError(..),
+        GlobResult(..),
+        matchDirFileGlob,
+        runDirFileGlob,
+        fileGlobMatches,
+        parseFileGlob,
+        explainGlobSyntaxError,
+        Glob,
+  ) where
+
+import Prelude ()
+import Distribution.Compat.Prelude
+
+import Control.Monad (guard)
+
+import Distribution.Simple.Utils
+import Distribution.Verbosity
+import Distribution.Version
+
+import System.Directory (getDirectoryContents, doesDirectoryExist, doesFileExist)
+import System.FilePath (joinPath, splitExtensions, splitDirectories, takeFileName, (</>), (<.>))
+
+-- Note throughout that we use splitDirectories, not splitPath. On
+-- Posix, this makes no difference, but, because Windows accepts both
+-- slash and backslash as its path separators, if we left in the
+-- separators from the glob we might not end up properly normalised.
+
+data GlobResult a
+  = GlobMatch a
+    -- ^ The glob matched the value supplied.
+  | GlobWarnMultiDot a
+    -- ^ The glob did not match the value supplied because the
+    --   cabal-version is too low and the extensions on the file did
+    --   not precisely match the glob's extensions, but rather the
+    --   glob was a proper suffix of the file's extensions; i.e., if
+    --   not for the low cabal-version, it would have matched.
+  | GlobMissingDirectory FilePath
+    -- ^ The glob couldn't match because the directory named doesn't
+    --   exist. The directory will be as it appears in the glob (i.e.,
+    --   relative to the directory passed to 'matchDirFileGlob', and,
+    --   for 'data-files', relative to 'data-dir').
+  deriving (Show, Eq, Ord, Functor)
+
+-- | Extract the matches from a list of 'GlobResult's.
+--
+-- Note: throws away the 'GlobMissingDirectory' results; chances are
+-- that you want to check for these and error out if any are present.
+globMatches :: [GlobResult a] -> [a]
+globMatches input = [ a | GlobMatch a <- input ]
+
+data GlobSyntaxError
+  = StarInDirectory
+  | StarInFileName
+  | StarInExtension
+  | NoExtensionOnStar
+  | EmptyGlob
+  | LiteralFileNameGlobStar
+  | VersionDoesNotSupportGlobStar
+  | VersionDoesNotSupportGlob
+  deriving (Eq, Show)
+
+explainGlobSyntaxError :: FilePath -> GlobSyntaxError -> String
+explainGlobSyntaxError filepath StarInDirectory =
+     "invalid file glob '" ++ filepath
+  ++ "'. A wildcard '**' is only allowed as the final parent"
+  ++ " directory. Stars must not otherwise appear in the parent"
+  ++ " directories."
+explainGlobSyntaxError filepath StarInExtension =
+     "invalid file glob '" ++ filepath
+  ++ "'. Wildcards '*' are only allowed as the"
+  ++ " file's base name, not in the file extension."
+explainGlobSyntaxError filepath StarInFileName =
+     "invalid file glob '" ++ filepath
+  ++ "'. Wildcards '*' may only totally replace the"
+  ++ " file's base name, not only parts of it."
+explainGlobSyntaxError filepath NoExtensionOnStar =
+     "invalid file glob '" ++ filepath
+  ++ "'. If a wildcard '*' is used it must be with an file extension."
+explainGlobSyntaxError filepath LiteralFileNameGlobStar =
+     "invalid file glob '" ++ filepath
+  ++ "'. If a wildcard '**' is used as a parent directory, the"
+  ++ " file's base name must be a wildcard '*'."
+explainGlobSyntaxError _ EmptyGlob =
+     "invalid file glob. A glob cannot be the empty string."
+explainGlobSyntaxError filepath VersionDoesNotSupportGlobStar =
+     "invalid file glob '" ++ filepath
+  ++ "'. Using the double-star syntax requires 'cabal-version: 2.4'"
+  ++ " or greater. Alternatively, for compatibility with earlier Cabal"
+  ++ " versions, list the included directories explicitly."
+explainGlobSyntaxError filepath VersionDoesNotSupportGlob =
+     "invalid file glob '" ++ filepath
+  ++ "'. Using star wildcards requires 'cabal-version: >= 1.6'. "
+  ++ "Alternatively if you require compatibility with earlier Cabal "
+  ++ "versions then list all the files explicitly."
+
+data IsRecursive = Recursive | NonRecursive
+
+data MultiDot = MultiDotDisabled | MultiDotEnabled
+
+data Glob
+  = GlobStem FilePath Glob
+    -- ^ A single subdirectory component + remainder.
+  | GlobFinal GlobFinal
+
+data GlobFinal
+  = FinalMatch IsRecursive MultiDot String
+    -- ^ First argument: Is this a @**/*.ext@ pattern?
+    --   Second argument: should we match against the exact extensions, or accept a suffix?
+    --   Third argument: the extensions to accept.
+  | FinalLit FilePath
+    -- ^ Literal file name.
+
+reconstructGlob :: Glob -> FilePath
+reconstructGlob (GlobStem dir glob) =
+  dir </> reconstructGlob glob
+reconstructGlob (GlobFinal final) = case final of
+  FinalMatch Recursive _ exts -> "**" </> "*" <.> exts
+  FinalMatch NonRecursive _ exts -> "*" <.> exts
+  FinalLit path -> path
+
+-- | Returns 'Nothing' if the glob didn't match at all, or 'Just' the
+--   result if the glob matched (or would have matched with a higher
+--   cabal-version).
+fileGlobMatches :: Glob -> FilePath -> Maybe (GlobResult FilePath)
+fileGlobMatches pat candidate = do
+  match <- fileGlobMatchesSegments pat (splitDirectories candidate)
+  return (candidate <$ match)
+
+fileGlobMatchesSegments :: Glob -> [FilePath] -> Maybe (GlobResult ())
+fileGlobMatchesSegments _ [] = Nothing
+fileGlobMatchesSegments pat (seg : segs) = case pat of
+  GlobStem dir pat' -> do
+    guard (dir == seg)
+    fileGlobMatchesSegments pat' segs
+  GlobFinal final -> case final of
+    FinalMatch Recursive multidot ext -> do
+      let (candidateBase, candidateExts) = splitExtensions (last $ seg:segs)
+      guard (not (null candidateBase))
+      checkExt multidot ext candidateExts
+    FinalMatch NonRecursive multidot ext -> do
+      let (candidateBase, candidateExts) = splitExtensions seg
+      guard (null segs && not (null candidateBase))
+      checkExt multidot ext candidateExts
+    FinalLit filename -> do
+      guard (null segs && filename == seg)
+      return (GlobMatch ())
+
+checkExt
+  :: MultiDot
+  -> String -- ^ The pattern's extension
+  -> String -- ^ The candidate file's extension
+  -> Maybe (GlobResult ())
+checkExt multidot ext candidate
+  | ext == candidate = Just (GlobMatch ())
+  | ext `isSuffixOf` candidate = case multidot of
+      MultiDotDisabled -> Just (GlobWarnMultiDot ())
+      MultiDotEnabled -> Just (GlobMatch ())
+  | otherwise = Nothing
+
+parseFileGlob :: Version -> FilePath -> Either GlobSyntaxError Glob
+parseFileGlob version filepath = case reverse (splitDirectories filepath) of
+  [] ->
+        Left EmptyGlob
+  (filename : "**" : segments)
+    | allowGlobStar -> do
+        ext <- case splitExtensions filename of
+          ("*", ext) | '*' `elem` ext -> Left StarInExtension
+                     | null ext       -> Left NoExtensionOnStar
+                     | otherwise      -> Right ext
+          _                           -> Left LiteralFileNameGlobStar
+        foldM addStem (GlobFinal $ FinalMatch Recursive multidot ext) segments
+    | otherwise -> Left VersionDoesNotSupportGlobStar
+  (filename : segments) -> do
+        pat <- case splitExtensions filename of
+          ("*", ext) | not allowGlob       -> Left VersionDoesNotSupportGlob
+                     | '*' `elem` ext      -> Left StarInExtension
+                     | null ext            -> Left NoExtensionOnStar
+                     | otherwise           -> Right (FinalMatch NonRecursive multidot ext)
+          (_, ext)   | '*' `elem` ext      -> Left StarInExtension
+                     | '*' `elem` filename -> Left StarInFileName
+                     | otherwise           -> Right (FinalLit filename)
+        foldM addStem (GlobFinal pat) segments
+  where
+    allowGlob = version >= mkVersion [1,6]
+    allowGlobStar = version >= mkVersion [2,4]
+    addStem pat seg
+      | '*' `elem` seg = Left StarInDirectory
+      | otherwise      = Right (GlobStem seg pat)
+    multidot
+      | version >= mkVersion [2,4] = MultiDotEnabled
+      | otherwise = MultiDotDisabled
+
+-- | This will 'die'' when the glob matches no files, or if the glob
+-- refers to a missing directory, or if the glob fails to parse.
+--
+-- The returned values do not include the supplied @dir@ prefix, which
+-- must itself be a valid directory (hence, it can't be the empty
+-- string).
+matchDirFileGlob :: Verbosity -> Version -> FilePath -> FilePath -> IO [FilePath]
+matchDirFileGlob verbosity version dir filepath = case parseFileGlob version filepath of
+  Left err -> die' verbosity $ explainGlobSyntaxError filepath err
+  Right glob -> do
+    results <- runDirFileGlob verbosity dir glob
+    let missingDirectories =
+          [ missingDir | GlobMissingDirectory missingDir <- results ]
+        matches = globMatches results
+    -- Check for missing directories first, since we'll obviously have
+    -- no matches in that case.
+    for_ missingDirectories $ \ missingDir ->
+      die' verbosity $
+           "filepath wildcard '" ++ filepath ++ "' refers to the directory"
+        ++ " '" ++ missingDir ++ "', which does not exist or is not a directory."
+    when (null matches) $ die' verbosity $
+         "filepath wildcard '" ++ filepath
+      ++ "' does not match any files."
+    return matches
+
+-- | Match files against a pre-parsed glob, starting in a directory.
+--
+-- The returned values do not include the supplied @dir@ prefix, which
+-- must itself be a valid directory (hence, it can't be the empty
+-- string).
+runDirFileGlob :: Verbosity -> FilePath -> Glob -> IO [GlobResult FilePath]
+runDirFileGlob verbosity rawDir pat = do
+  -- The default data-dir is null. Our callers -should- be
+  -- converting that to '.' themselves, but it's a certainty that
+  -- some future call-site will forget and trigger a really
+  -- hard-to-debug failure if we don't check for that here.
+  when (null rawDir) $
+    warn verbosity $
+         "Null dir passed to runDirFileGlob; interpreting it "
+      ++ "as '.'. This is probably an internal error."
+  let dir = if null rawDir then "." else rawDir
+  debug verbosity $ "Expanding glob '" ++ reconstructGlob pat ++ "' in directory '" ++ dir ++ "'."
+  -- This function might be called from the project root with dir as
+  -- ".". Walking the tree starting there involves going into .git/
+  -- and dist-newstyle/, which is a lot of work for no reward, so
+  -- extract the constant prefix from the pattern and start walking
+  -- there, and only walk as much as we need to: recursively if **,
+  -- the whole directory if *, and just the specific file if it's a
+  -- literal.
+  let (prefixSegments, final) = splitConstantPrefix pat
+      joinedPrefix = joinPath prefixSegments
+  case final of
+    FinalMatch recursive multidot exts -> do
+      let prefix = dir </> joinedPrefix
+      directoryExists <- doesDirectoryExist prefix
+      if directoryExists
+        then do
+          candidates <- case recursive of
+            Recursive -> getDirectoryContentsRecursive prefix
+            NonRecursive -> filterM (doesFileExist . (prefix </>)) =<< getDirectoryContents prefix
+          let checkName candidate = do
+                let (candidateBase, candidateExts) = splitExtensions $ takeFileName candidate
+                guard (not (null candidateBase))
+                match <- checkExt multidot exts candidateExts
+                return (joinedPrefix </> candidate <$ match)
+          return $ mapMaybe checkName candidates
+        else
+          return [ GlobMissingDirectory joinedPrefix ]
+    FinalLit fn -> do
+      exists <- doesFileExist (dir </> joinedPrefix </> fn)
+      return [ GlobMatch (joinedPrefix </> fn) | exists ]
+
+unfoldr' :: (a -> Either r (b, a)) -> a -> ([b], r)
+unfoldr' f a = case f a of
+  Left r -> ([], r)
+  Right (b, a') -> case unfoldr' f a' of
+    (bs, r) -> (b : bs, r)
+
+-- | Extract the (possibly null) constant prefix from the pattern.
+-- This has the property that, if @(pref, final) = splitConstantPrefix pat@,
+-- then @pat === foldr GlobStem (GlobFinal final) pref@.
+splitConstantPrefix :: Glob -> ([FilePath], GlobFinal)
+splitConstantPrefix = unfoldr' step
+  where
+    step (GlobStem seg pat) = Right (seg, pat)
+    step (GlobFinal pat) = Left pat
diff --git a/cabal/Cabal/Distribution/Simple/Haddock.hs b/cabal/Cabal/Distribution/Simple/Haddock.hs
--- a/cabal/Cabal/Distribution/Simple/Haddock.hs
+++ b/cabal/Cabal/Distribution/Simple/Haddock.hs
@@ -36,19 +36,25 @@
 import Distribution.Types.UnqualComponentName
 import Distribution.Types.ComponentLocalBuildInfo
 import Distribution.Types.ExecutableScope
+import Distribution.Types.LocalBuildInfo
+import Distribution.Types.TargetInfo
 import Distribution.Package
 import qualified Distribution.ModuleName as ModuleName
 import Distribution.PackageDescription as PD hiding (Flag)
 import Distribution.Simple.Compiler hiding (Flag)
+import Distribution.Simple.Glob
 import Distribution.Simple.Program.GHC
 import Distribution.Simple.Program.ResponseFile
 import Distribution.Simple.Program
 import Distribution.Simple.PreProcess
 import Distribution.Simple.Setup
 import Distribution.Simple.Build
+import Distribution.Simple.BuildTarget
 import Distribution.Simple.InstallDirs
 import Distribution.Simple.LocalBuildInfo hiding (substPathTemplate)
 import Distribution.Simple.BuildPaths
+import Distribution.Simple.Register
+import qualified Distribution.Simple.Program.HcPkg as HcPkg
 import qualified Distribution.Simple.PackageIndex as PackageIndex
 import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo
 import Distribution.InstalledPackageInfo ( InstalledPackageInfo )
@@ -62,9 +68,10 @@
 
 import Distribution.Compat.Semigroup (All (..), Any (..))
 
+import Control.Monad
 import Data.Either      ( rights )
 
-import System.Directory (doesFileExist)
+import System.Directory (getCurrentDirectory, doesDirectoryExist, doesFileExist)
 import System.FilePath  ( (</>), (<.>), normalise, isAbsolute )
 import System.IO        (hClose, hPutStrLn, hSetEncoding, utf8)
 
@@ -84,6 +91,10 @@
  -- ^ Ignore export lists in modules?
  argLinkSource :: Flag (Template,Template,Template),
  -- ^ (Template for modules, template for symbols, template for lines).
+ argLinkedSource :: Flag Bool,
+ -- ^ Generate hyperlinked sources
+ argQuickJump :: Flag Bool,
+ -- ^ Generate quickjump index
  argCssFile :: Flag FilePath,
  -- ^ Optional custom CSS file.
  argContents :: Flag String,
@@ -91,15 +102,15 @@
  argVerbose :: Any,
  argOutput :: Flag [Output],
  -- ^ HTML or Hoogle doc or both? Required.
- argInterfaces :: [(FilePath, Maybe String)],
- -- ^ [(Interface file, URL to the HTML docs for links)].
+ argInterfaces :: [(FilePath, Maybe String, Maybe String)],
+ -- ^ [(Interface file, URL to the HTML docs and hyperlinked-source for links)].
  argOutputDir :: Directory,
  -- ^ Where to generate the documentation.
  argTitle :: Flag String,
  -- ^ Page title, required.
  argPrologue :: Flag String,
  -- ^ Prologue text, required.
- argGhcOptions :: Flag (GhcOptions, Version),
+ argGhcOptions :: GhcOptions,
  -- ^ Additional flags to pass to GHC.
  argGhcLibDir :: Flag FilePath,
  -- ^ To find the correct GHC, required.
@@ -142,6 +153,7 @@
         comp          = compiler lbi
         platform      = hostPlatform lbi
 
+        quickJmpFlag  = haddockQuickJump flags'
         flags = case haddockTarget of
           ForDevelopment -> flags'
           ForHackage -> flags'
@@ -149,7 +161,8 @@
             , haddockHtml         = Flag True
             , haddockHtmlLocation = Flag (pkg_url ++ "/docs")
             , haddockContents     = Flag (toPathTemplate pkg_url)
-            , haddockHscolour     = Flag True
+            , haddockLinkedSource = Flag True
+            , haddockQuickJump    = Flag True
             }
         pkg_url       = "/package/$pkg-$version"
         flag f        = fromFlag $ f flags
@@ -166,10 +179,17 @@
         (orLaterVersion (mkVersion [2,0])) (withPrograms lbi)
 
     -- various sanity checks
-    when ( flag haddockHoogle
-           && version < mkVersion [2,2]) $
-         die' verbosity "haddock 2.0 and 2.1 do not support the --hoogle flag."
+    when (flag haddockHoogle && version < mkVersion [2,2]) $
+      die' verbosity "Haddock 2.0 and 2.1 do not support the --hoogle flag."
 
+
+    when (flag haddockQuickJump && version < mkVersion [2,19]) $ do
+      let msg = "Haddock prior to 2.19 does not support the --quickjump flag."
+          alt = "The generated documentation won't have the QuickJump feature."
+      if Flag True == quickJmpFlag
+        then die' verbosity msg
+        else warn verbosity (msg ++ "\n" ++ alt)
+
     haddockGhcVersionStr <- getProgramOutput verbosity haddockProg
                               ["--ghc-version"]
     case (simpleParse haddockGhcVersionStr, compilerCompatVersion GHC comp) of
@@ -185,7 +205,9 @@
 
     -- the tools match the requests, we can proceed
 
-    when (flag haddockHscolour) $
+    -- We fall back to using HsColour only for versions of Haddock which don't
+    -- support '--hyperlinked-sources'.
+    when (flag haddockLinkedSource && version < mkVersion [2,17]) $
       hscolour' (warn verbosity) haddockTarget pkg_descr lbi suffixes
       (defaultHscolourFlags `mappend` haddockToHscolour flags)
 
@@ -195,15 +217,37 @@
             , fromFlags (haddockTemplateEnv lbi (packageId pkg_descr)) flags
             , fromPackageDescription haddockTarget pkg_descr ]
 
-    withAllComponentsInBuildOrder pkg_descr lbi $ \component clbi -> do
+    targets <- readTargetInfos verbosity pkg_descr lbi (haddockArgs flags)
+
+    let
+      targets' =
+        case targets of
+          [] -> allTargetsInBuildOrder' pkg_descr lbi
+          _  -> targets
+
+    internalPackageDB <-
+      createInternalPackageDB verbosity lbi (flag haddockDistPref)
+
+    (\f -> foldM_ f (installedPkgs lbi) targets') $ \index target -> do
+
+      let component = targetComponent target
+          clbi      = targetCLBI target
+
       componentInitialBuildSteps (flag haddockDistPref) pkg_descr lbi clbi verbosity
-      preprocessComponent pkg_descr component lbi clbi False verbosity suffixes
+
       let
+        lbi' = lbi {
+          withPackageDB = withPackageDB lbi ++ [internalPackageDB],
+          installedPkgs = index
+          }
+
+      preprocessComponent pkg_descr component lbi' clbi False verbosity suffixes
+      let
         doExe com = case (compToExe com) of
           Just exe -> do
-            withTempDirectoryEx verbosity tmpFileOpts (buildDir lbi) "tmp" $
+            withTempDirectoryEx verbosity tmpFileOpts (buildDir lbi') "tmp" $
               \tmp -> do
-                exeArgs <- fromExecutable verbosity tmp lbi clbi htmlTemplate
+                exeArgs <- fromExecutable verbosity tmp lbi' clbi htmlTemplate
                              version exe
                 let exeArgs' = commonArgs `mappend` exeArgs
                 runHaddock verbosity tmpFileOpts comp platform
@@ -223,24 +267,50 @@
           withTempDirectoryEx verbosity tmpFileOpts (buildDir lbi) "tmp" $
             \tmp -> do
               smsg
-              libArgs <- fromLibrary verbosity tmp lbi clbi htmlTemplate
+              libArgs <- fromLibrary verbosity tmp lbi' clbi htmlTemplate
                            version lib
               let libArgs' = commonArgs `mappend` libArgs
               runHaddock verbosity tmpFileOpts comp platform haddockProg libArgs'
-        CFLib flib -> when (flag haddockForeignLibs) $ do
-          withTempDirectoryEx verbosity tmpFileOpts (buildDir lbi) "tmp" $
+
+              case libName lib of
+                Just _ -> do
+                  pwd <- getCurrentDirectory
+
+                  let
+                    ipi = inplaceInstalledPackageInfo
+                            pwd (flag haddockDistPref) pkg_descr
+                            (mkAbiHash "inplace") lib lbi' clbi
+
+                  debug verbosity $ "Registering inplace:\n"
+                    ++ (InstalledPackageInfo.showInstalledPackageInfo ipi)
+
+                  registerPackage verbosity (compiler lbi') (withPrograms lbi')
+                    (withPackageDB lbi') ipi
+                    HcPkg.defaultRegisterOptions {
+                      HcPkg.registerMultiInstance = True
+                    }
+
+                  return $ PackageIndex.insert ipi index
+                Nothing ->
+                  pure index
+
+        CFLib flib -> (when (flag haddockForeignLibs) $ do
+          withTempDirectoryEx verbosity tmpFileOpts (buildDir lbi') "tmp" $
             \tmp -> do
               smsg
-              flibArgs <- fromForeignLib verbosity tmp lbi clbi htmlTemplate
+              flibArgs <- fromForeignLib verbosity tmp lbi' clbi htmlTemplate
                             version flib
               let libArgs' = commonArgs `mappend` flibArgs
-              runHaddock verbosity tmpFileOpts comp platform haddockProg libArgs'
-        CExe   _ -> when (flag haddockExecutables) $ smsg >> doExe component
-        CTest  _ -> when (flag haddockTestSuites)  $ smsg >> doExe component
-        CBench _ -> when (flag haddockBenchmarks)  $ smsg >> doExe component
+              runHaddock verbosity tmpFileOpts comp platform haddockProg libArgs')
 
+          >> return index
+
+        CExe   _ -> (when (flag haddockExecutables) $ smsg >> doExe component) >> return index
+        CTest  _ -> (when (flag haddockTestSuites)  $ smsg >> doExe component) >> return index
+        CBench _ -> (when (flag haddockBenchmarks)  $ smsg >> doExe component) >> return index
+
     for_ (extraDocFiles pkg_descr) $ \ fpath -> do
-      files <- matchFileGlob fpath
+      files <- matchDirFileGlob verbosity (specVersion pkg_descr) "." fpath
       for_ files $ copyFileTo verbosity (unDir $ argOutputDir commonArgs)
 
 -- ------------------------------------------------------------------------------
@@ -251,11 +321,13 @@
     mempty {
       argHideModules = (maybe mempty (All . not)
                         $ flagToMaybe (haddockInternal flags), mempty),
-      argLinkSource = if fromFlag (haddockHscolour flags)
+      argLinkSource = if fromFlag (haddockLinkedSource flags)
                                then Flag ("src/%{MODULE/./-}.html"
                                          ,"src/%{MODULE/./-}.html#%{NAME}"
                                          ,"src/%{MODULE/./-}.html#line-%{LINE}")
                                else NoFlag,
+      argLinkedSource = haddockLinkedSource flags,
+      argQuickJump = haddockQuickJump flags,
       argCssFile = haddockCss flags,
       argContents = fmap (fromPathTemplate . substPathTemplate env)
                     (haddockContents flags),
@@ -266,8 +338,12 @@
                       [ Hoogle | Flag True <- [haddockHoogle flags] ]
                  of [] -> [ Html ]
                     os -> os,
-      argOutputDir = maybe mempty Dir . flagToMaybe $ haddockDistPref flags
+      argOutputDir = maybe mempty Dir . flagToMaybe $ haddockDistPref flags,
+
+      argGhcOptions = mempty { ghcOptExtra = ghcArgs }
     }
+    where
+      ghcArgs = fromMaybe [] . lookup "ghc" . haddockProgramArgs $ flags
 
 fromPackageDescription :: HaddockTarget -> PackageDescription -> HaddockArgs
 fromPackageDescription haddockTarget pkg_descr =
@@ -322,8 +398,7 @@
                          ghcOptFPic        = toFlag True,
                          ghcOptHiSuffix    = toFlag "dyn_hi",
                          ghcOptObjSuffix   = toFlag "dyn_o",
-                         ghcOptExtra       =
-                           toNubListR $ hcSharedOptions GHC bi
+                         ghcOptExtra       = hcSharedOptions GHC bi
 
                      }
     opts <- if withVanillaLib lbi
@@ -332,12 +407,9 @@
             then return sharedOpts
             else die' verbosity $ "Must have vanilla or shared libraries "
                        ++ "enabled in order to run haddock"
-    ghcVersion <- maybe (die' verbosity "Compiler has no GHC version")
-                        return
-                        (compilerCompatVersion GHC (compiler lbi))
 
     return ifaceArgs {
-      argGhcOptions  = toFlag (opts, ghcVersion),
+      argGhcOptions  = opts,
       argTargets     = inFiles
     }
 
@@ -429,7 +501,7 @@
 getGhcCppOpts haddockVersion bi =
     mempty {
         ghcOptExtensions   = toNubListR [EnableExtension CPP | needsCpp],
-        ghcOptCppOptions   = toNubListR defines
+        ghcOptCppOptions   = defines
     }
   where
     needsCpp             = EnableExtension CPP `elem` usedExtensions bi
@@ -457,15 +529,19 @@
               -> ConfiguredProgram
               -> HaddockArgs
               -> IO ()
-runHaddock verbosity tmpFileOpts comp platform haddockProg args = do
-  let haddockVersion = fromMaybe (error "unable to determine haddock version")
-                       (programVersion haddockProg)
-  renderArgs verbosity tmpFileOpts haddockVersion comp platform args $
-    \(flags,result)-> do
+runHaddock verbosity tmpFileOpts comp platform haddockProg args
+  | null (argTargets args) = warn verbosity $
+       "Haddocks are being requested, but there aren't any modules given "
+    ++ "to create documentation for."
+  | otherwise = do
+    let haddockVersion = fromMaybe (error "unable to determine haddock version")
+                        (programVersion haddockProg)
+    renderArgs verbosity tmpFileOpts haddockVersion comp platform args $
+      \(flags,result)-> do
 
-      runProgram verbosity haddockProg flags
+        runProgram verbosity haddockProg flags
 
-      notice verbosity $ "Documentation created: " ++ result
+        notice verbosity $ "Documentation created: " ++ result
 
 
 renderArgs :: Verbosity
@@ -525,6 +601,14 @@
              . fromFlag . argPackageName $ args
         else []
 
+    , [ "--since-qual=external" | isVersion 2 20 ]
+
+    , [ "--quickjump" | isVersion 2 19
+                      , fromFlag . argQuickJump $ args ]
+
+    , [ "--hyperlinked-source" | isVersion 2 17
+                               , fromFlag . argLinkedSource $ args ]
+
     , (\(All b,xs) -> bool (map (("--hide=" ++). display) xs) [] b)
                      . argHideModules $ args
 
@@ -555,7 +639,7 @@
          id (getAny $ argIgnoreExports args))
       . fromFlag . argTitle $ args
 
-    , [ "--optghc=" ++ opt | (opts, _ghcVer) <- flagToList (argGhcOptions args)
+    , [ "--optghc=" ++ opt | let opts = argGhcOptions args
                            , opt <- renderGhcOptions comp platform opts ]
 
     , maybe [] (\l -> ["-B"++l]) $
@@ -564,9 +648,22 @@
     , argTargets $ args
     ]
     where
-      renderInterfaces =
-        map (\(i,mh) -> "--read-interface=" ++
-          maybe "" (++",") mh ++ i)
+      renderInterfaces = map renderInterface
+
+      renderInterface :: (FilePath, Maybe FilePath, Maybe FilePath) -> String
+      renderInterface (i, html, hypsrc) = "--read-interface=" ++
+        (intercalate "," $ concat [ [ x | Just x <- [html] ]
+                                  , [ x | Just _ <- [html]
+                                        -- only render hypsrc path if html path
+                                        -- is given and hyperlinked-source is
+                                        -- enabled
+                                        , Just x <- [hypsrc]
+                                        , isVersion 2 17
+                                        , fromFlag . argLinkedSource $ args
+                                        ]
+                                  , [ i ]
+                                  ])
+
       bool a b c = if c then a else b
       isVersion major minor  = version >= mkVersion [major,minor]
       verbosityFlag
@@ -579,15 +676,39 @@
 -- HTML paths, and an optional warning for packages with missing documentation.
 haddockPackagePaths :: [InstalledPackageInfo]
                     -> Maybe (InstalledPackageInfo -> FilePath)
-                    -> NoCallStackIO ([(FilePath, Maybe FilePath)], Maybe String)
+                    -> NoCallStackIO ([( FilePath        -- path to interface
+                                                         -- file
+
+                                       , Maybe FilePath  -- url to html
+                                                         -- documentation
+
+                                       , Maybe FilePath  -- url to hyperlinked
+                                                         -- source
+                                       )]
+                                     , Maybe String      -- warning about
+                                                         -- missing documentation
+                                     )
 haddockPackagePaths ipkgs mkHtmlPath = do
   interfaces <- sequenceA
     [ case interfaceAndHtmlPath ipkg of
         Nothing -> return (Left (packageId ipkg))
         Just (interface, html) -> do
+
+          (html', hypsrc') <-
+            case html of
+              Just htmlPath -> do
+                let hypSrcPath = htmlPath </> defaultHyperlinkedSourceDirectory
+                hypSrcExists <- doesDirectoryExist hypSrcPath
+                return $ ( Just (fixFileUrl htmlPath)
+                         , if hypSrcExists
+                           then Just (fixFileUrl hypSrcPath)
+                           else Nothing
+                         )
+              Nothing -> return (Nothing, Nothing)
+
           exists <- doesFileExist interface
           if exists
-            then return (Right (interface, html))
+            then return (Right (interface, html', hypsrc'))
             else return (Left pkgid)
     | ipkg <- ipkgs, let pkgid = packageId ipkg
     , pkgName pkgid `notElem` noHaddockWhitelist
@@ -611,21 +732,38 @@
     interfaceAndHtmlPath pkg = do
       interface <- listToMaybe (InstalledPackageInfo.haddockInterfaces pkg)
       html <- case mkHtmlPath of
-        Nothing -> fmap fixFileUrl
-                        (listToMaybe (InstalledPackageInfo.haddockHTMLs pkg))
+        Nothing     -> listToMaybe (InstalledPackageInfo.haddockHTMLs pkg)
         Just mkPath -> Just (mkPath pkg)
       return (interface, if null html then Nothing else Just html)
-      where
-        -- The 'haddock-html' field in the hc-pkg output is often set as a
-        -- native path, but we need it as a URL. See #1064.
-        fixFileUrl f | isAbsolute f = "file://" ++ f
-                     | otherwise    = f
 
+    -- The 'haddock-html' field in the hc-pkg output is often set as a
+    -- native path, but we need it as a URL. See #1064. Also don't "fix"
+    -- the path if it is an interpolated one.
+    fixFileUrl f | Nothing <- mkHtmlPath
+                 , isAbsolute f = "file://" ++ f
+                 | otherwise    = f
+
+    -- 'src' is the default hyperlinked source directory ever since. It is
+    -- not possible to configure that directory in any way in haddock.
+    defaultHyperlinkedSourceDirectory = "src"
+
+
 haddockPackageFlags :: Verbosity
                     -> LocalBuildInfo
                     -> ComponentLocalBuildInfo
                     -> Maybe PathTemplate
-                    -> IO ([(FilePath, Maybe FilePath)], Maybe String)
+                    -> IO ([( FilePath        -- path to interface
+                                              -- file
+
+                            , Maybe FilePath  -- url to html
+                                              -- documentation
+
+                            , Maybe FilePath  -- url to hyperlinked
+                                              -- source
+                            )]
+                          , Maybe String      -- warning about
+                                              -- missing documentation
+                          )
 haddockPackageFlags verbosity lbi clbi htmlTemplate = do
   let allPkgs = installedPkgs lbi
       directDeps = map fst (componentPackageDeps clbi)
@@ -676,6 +814,11 @@
   where
     go :: ConfiguredProgram -> IO ()
     go hscolourProg = do
+      warn verbosity $
+        "the 'cabal hscolour' command is deprecated in favour of 'cabal " ++
+        "haddock --hyperlink-source' and will be removed in the next major " ++
+        "release."
+
       setupMessage verbosity "Running hscolour for" (packageId pkg_descr)
       createDirectoryIfMissingVerbose verbosity True $
         hscolourPref haddockTarget distPref pkg_descr
@@ -736,7 +879,8 @@
       hscolourBenchmarks  = haddockBenchmarks  flags,
       hscolourForeignLibs = haddockForeignLibs flags,
       hscolourVerbosity   = haddockVerbosity   flags,
-      hscolourDistPref    = haddockDistPref    flags
+      hscolourDistPref    = haddockDistPref    flags,
+      hscolourCabalFilePath = haddockCabalFilePath flags
     }
 
 -- ------------------------------------------------------------------------------
diff --git a/cabal/Cabal/Distribution/Simple/HaskellSuite.hs b/cabal/Cabal/Distribution/Simple/HaskellSuite.hs
--- a/cabal/Cabal/Distribution/Simple/HaskellSuite.hs
+++ b/cabal/Cabal/Distribution/Simple/HaskellSuite.hs
@@ -102,13 +102,13 @@
       simpleParse versionStr
   return (name, version)
 
-getExtensions :: Verbosity -> ConfiguredProgram -> IO [(Extension, Compiler.Flag)]
+getExtensions :: Verbosity -> ConfiguredProgram -> IO [(Extension, Maybe Compiler.Flag)]
 getExtensions verbosity prog = do
   extStrs <-
     lines `fmap`
     rawSystemStdout verbosity (programPath prog) ["--supported-extensions"]
   return
-    [ (ext, "-X" ++ display ext) | Just ext <- map simpleParse extStrs ]
+    [ (ext, Just $ "-X" ++ display ext) | Just ext <- map simpleParse extStrs ]
 
 getLanguages :: Verbosity -> ConfiguredProgram -> IO [(Language, Compiler.Flag)]
 getLanguages verbosity prog = do
diff --git a/cabal/Cabal/Distribution/Simple/Install.hs b/cabal/Cabal/Distribution/Simple/Install.hs
--- a/cabal/Cabal/Distribution/Simple/Install.hs
+++ b/cabal/Cabal/Distribution/Simple/Install.hs
@@ -33,10 +33,11 @@
 import Distribution.PackageDescription
 import Distribution.Simple.LocalBuildInfo
 import Distribution.Simple.BuildPaths (haddockName, haddockPref)
+import Distribution.Simple.Glob (matchDirFileGlob)
 import Distribution.Simple.Utils
          ( createDirectoryIfMissingVerbose
          , installDirectoryContents, installOrdinaryFile, isInSearchPath
-         , die', info, noticeNoWrap, warn, matchDirFileGlob )
+         , die', info, noticeNoWrap, warn )
 import Distribution.Simple.Compiler
          ( CompilerFlavor(..), compilerFlavor )
 import Distribution.Simple.Setup
@@ -45,8 +46,6 @@
 
 import qualified Distribution.Simple.GHC   as GHC
 import qualified Distribution.Simple.GHCJS as GHCJS
-import qualified Distribution.Simple.JHC   as JHC
-import qualified Distribution.Simple.LHC   as LHC
 import qualified Distribution.Simple.UHC   as UHC
 import qualified Distribution.Simple.HaskellSuite as HaskellSuite
 import Distribution.Compat.Graph (IsNode(..))
@@ -171,13 +170,11 @@
 
     -- install include files for all compilers - they may be needed to compile
     -- haskell files (using the CPP extension)
-    installIncludeFiles verbosity lib buildPref incPref
+    installIncludeFiles verbosity (libBuildInfo lib) lbi buildPref incPref
 
     case compilerFlavor (compiler lbi) of
       GHC   -> GHC.installLib   verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi
       GHCJS -> GHCJS.installLib verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi
-      LHC   -> LHC.installLib   verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi
-      JHC   -> JHC.installLib   verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi
       UHC   -> UHC.installLib   verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi
       HaskellSuite _ -> HaskellSuite.installLib
                                 verbosity lbi libPref dynlibPref buildPref pkg_descr lib clbi
@@ -187,11 +184,13 @@
 
 copyComponent verbosity pkg_descr lbi (CFLib flib) clbi copydest = do
     let InstallDirs{
-            flibdir = flibPref
+            flibdir = flibPref,
+            includedir = incPref
             } = absoluteComponentInstallDirs pkg_descr lbi (componentUnitId clbi) copydest
         buildPref = componentBuildDir lbi clbi
 
     noticeNoWrap verbosity ("Installing foreign library " ++ unUnqualComponentName (foreignLibName flib) ++ " in " ++ flibPref)
+    installIncludeFiles verbosity (foreignLibBuildInfo flib) lbi buildPref incPref
 
     case compilerFlavor (compiler lbi) of
       GHC   -> GHC.installFLib   verbosity lbi flibPref buildPref pkg_descr flib
@@ -220,8 +219,6 @@
     case compilerFlavor (compiler lbi) of
       GHC   -> GHC.installExe   verbosity lbi binPref buildPref progFix pkg_descr exe
       GHCJS -> GHCJS.installExe verbosity lbi binPref buildPref progFix pkg_descr exe
-      LHC   -> LHC.installExe   verbosity lbi binPref buildPref progFix pkg_descr exe
-      JHC   -> JHC.installExe   verbosity     binPref buildPref progFix pkg_descr exe
       UHC   -> return ()
       HaskellSuite {} -> return ()
       _ -> die' verbosity $ "installing with "
@@ -237,8 +234,11 @@
 installDataFiles :: Verbosity -> PackageDescription -> FilePath -> IO ()
 installDataFiles verbosity pkg_descr destDataDir =
   flip traverse_ (dataFiles pkg_descr) $ \ file -> do
-    let srcDataDir = dataDir pkg_descr
-    files <- matchDirFileGlob srcDataDir file
+    let srcDataDirRaw = dataDir pkg_descr
+        srcDataDir = if null srcDataDirRaw
+          then "."
+          else srcDataDirRaw
+    files <- matchDirFileGlob verbosity (specVersion pkg_descr) srcDataDir file
     let dir = takeDirectory file
     createDirectoryIfMissingVerbose verbosity True (destDataDir </> dir)
     sequence_ [ installOrdinaryFile verbosity (srcDataDir  </> file')
@@ -247,12 +247,12 @@
 
 -- | Install the files listed in install-includes for a library
 --
-installIncludeFiles :: Verbosity -> Library -> FilePath -> FilePath -> IO ()
-installIncludeFiles verbosity lib buildPref destIncludeDir = do
-    let relincdirs = "." : filter isRelative (includeDirs lbi)
-        lbi = libBuildInfo lib
-        incdirs = relincdirs ++ [ buildPref </> dir | dir <- relincdirs ]
-    incs <- traverse (findInc incdirs) (installIncludes lbi)
+installIncludeFiles :: Verbosity -> BuildInfo -> LocalBuildInfo -> FilePath -> FilePath -> IO ()
+installIncludeFiles verbosity libBi lbi buildPref destIncludeDir = do
+    let relincdirs = "." : filter isRelative (includeDirs libBi)
+        incdirs = [ baseDir lbi </> dir | dir <- relincdirs ]
+                  ++ [ buildPref </> dir | dir <- relincdirs ]
+    incs <- traverse (findInc incdirs) (installIncludes libBi)
     sequence_
       [ do createDirectoryIfMissingVerbose verbosity True destDir
            installOrdinaryFile verbosity srcFile destFile
@@ -260,7 +260,7 @@
       , let destFile = destIncludeDir </> relFile
             destDir  = takeDirectory destFile ]
   where
-
+   baseDir lbi' = fromMaybe "" (takeDirectory <$> cabalFilePath lbi')
    findInc []         file = die' verbosity ("can't find include file " ++ file)
    findInc (dir:dirs) file = do
      let path = dir </> file
diff --git a/cabal/Cabal/Distribution/Simple/InstallDirs.hs b/cabal/Cabal/Distribution/Simple/InstallDirs.hs
--- a/cabal/Cabal/Distribution/Simple/InstallDirs.hs
+++ b/cabal/Cabal/Distribution/Simple/InstallDirs.hs
@@ -51,6 +51,7 @@
 import Prelude ()
 import Distribution.Compat.Prelude
 
+import Distribution.Compat.Environment (lookupEnv)
 import Distribution.Package
 import Distribution.System
 import Distribution.Compiler
@@ -59,7 +60,8 @@
 import System.Directory (getAppUserDataDirectory)
 import System.FilePath
   ( (</>), isPathSeparator
-  , pathSeparator, dropDrive )
+  , pathSeparator, dropDrive
+  , takeDirectory )
 
 #ifdef mingw32_HOST_OS
 import qualified Prelude
@@ -180,7 +182,11 @@
 defaultInstallDirs' False comp userInstall _hasLibs = do
   installPrefix <-
       if userInstall
-      then getAppUserDataDirectory "cabal"
+      then do
+        mDir <- lookupEnv "CABAL_DIR"
+        case mDir of
+          Nothing -> getAppUserDataDirectory "cabal"
+          Just dir -> return dir
       else case buildOS of
            Windows -> do windowsProgramFilesDir <- getWindowsProgramFilesDir
                          return (windowsProgramFilesDir </> "Haskell")
@@ -188,21 +194,15 @@
   installLibDir <-
       case buildOS of
       Windows -> return "$prefix"
-      _       -> case comp of
-                 LHC | userInstall -> getAppUserDataDirectory "lhc"
-                 _                 -> return ("$prefix" </> "lib")
+      _       -> return ("$prefix" </> "lib")
   return $ fmap toPathTemplate $ InstallDirs {
       prefix       = installPrefix,
       bindir       = "$prefix" </> "bin",
       libdir       = installLibDir,
       libsubdir    = case comp of
-           JHC    -> "$compiler"
-           LHC    -> "$compiler"
            UHC    -> "$pkgid"
            _other -> "$abi" </> "$libname",
       dynlibdir    = "$libdir" </> case comp of
-           JHC    -> "$compiler"
-           LHC    -> "$compiler"
            UHC    -> "$pkgid"
            _other -> "$abi",
       libexecsubdir= "$abi" </> "$pkgid",
@@ -287,19 +287,29 @@
 absoluteInstallDirs pkgId libname compilerId copydest platform dirs =
     (case copydest of
        CopyTo destdir -> fmap ((destdir </>) . dropDrive)
+       CopyToDb dbdir -> fmap (substPrefix "${pkgroot}" (takeDirectory dbdir))
        _              -> id)
   . appendSubdirs (</>)
   . fmap fromPathTemplate
   $ substituteInstallDirTemplates env dirs
   where
     env = initialPathTemplateEnv pkgId libname compilerId platform
+    substPrefix pre root path
+      | pre `isPrefixOf` path = root ++ drop (length pre) path
+      | otherwise             = path
 
 
 -- |The location prefix for the /copy/ command.
 data CopyDest
   = NoCopyDest
   | CopyTo FilePath
-  deriving (Eq, Show)
+  | CopyToDb FilePath
+  -- ^ when using the ${pkgroot} as prefix. The CopyToDb will
+  --   adjust the paths to be relative to the provided package
+  --   database when copying / installing.
+  deriving (Eq, Show, Generic)
+
+instance Binary CopyDest
 
 -- | Check which of the paths are relative to the installation $prefix.
 --
diff --git a/cabal/Cabal/Distribution/Simple/JHC.hs b/cabal/Cabal/Distribution/Simple/JHC.hs
deleted file mode 100644
--- a/cabal/Cabal/Distribution/Simple/JHC.hs
+++ /dev/null
@@ -1,195 +0,0 @@
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE RankNTypes #-}
-
------------------------------------------------------------------------------
--- |
--- Module      :  Distribution.Simple.JHC
--- Copyright   :  Isaac Jones 2003-2006
--- License     :  BSD3
---
--- Maintainer  :  cabal-devel@haskell.org
--- Portability :  portable
---
--- This module contains most of the JHC-specific code for configuring, building
--- and installing packages.
-
-module Distribution.Simple.JHC (
-        configure, getInstalledPackages,
-        buildLib, buildExe,
-        installLib, installExe
- ) where
-
-import Prelude ()
-import Distribution.Compat.Prelude
-
-import Distribution.PackageDescription as PD hiding (Flag)
-import Distribution.InstalledPackageInfo
-import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo
-import Distribution.Simple.PackageIndex (InstalledPackageIndex)
-import qualified Distribution.Simple.PackageIndex as PackageIndex
-import Distribution.Simple.LocalBuildInfo
-import Distribution.Simple.BuildPaths
-import Distribution.Simple.Compiler
-import Language.Haskell.Extension
-import Distribution.Simple.Program
-import Distribution.Types.MungedPackageId (mungedName)
-import Distribution.Types.PackageId
-import Distribution.Types.UnitId
-import Distribution.Version
-import Distribution.Package
-import Distribution.Simple.Utils
-import Distribution.Verbosity
-import Distribution.Text
-
-import System.FilePath          ( (</>) )
-import Distribution.Compat.ReadP
-    ( readP_to_S, string, skipSpaces )
-import Distribution.System ( Platform )
-
-import qualified Data.Map as Map  ( empty )
-
-import qualified Data.ByteString.Lazy.Char8 as BS.Char8
-
-
--- -----------------------------------------------------------------------------
--- Configuring
-
-configure :: Verbosity -> Maybe FilePath -> Maybe FilePath
-          -> ProgramDb -> IO (Compiler, Maybe Platform, ProgramDb)
-configure verbosity hcPath _hcPkgPath progdb = do
-
-  (jhcProg, _, progdb') <- requireProgramVersion verbosity
-                           jhcProgram (orLaterVersion (mkVersion [0,7,2]))
-                           (userMaybeSpecifyPath "jhc" hcPath progdb)
-
-  let Just version = programVersion jhcProg
-      comp = Compiler {
-        compilerId             = CompilerId JHC version,
-        compilerAbiTag         = NoAbiTag,
-        compilerCompat         = [],
-        compilerLanguages      = jhcLanguages,
-        compilerExtensions     = jhcLanguageExtensions,
-        compilerProperties     = Map.empty
-      }
-      compPlatform = Nothing
-  return (comp, compPlatform, progdb')
-
-jhcLanguages :: [(Language, Flag)]
-jhcLanguages = [(Haskell98, "")]
-
--- | The flags for the supported extensions
-jhcLanguageExtensions :: [(Extension, Flag)]
-jhcLanguageExtensions =
-    [(EnableExtension  TypeSynonymInstances       , "")
-    ,(DisableExtension TypeSynonymInstances       , "")
-    ,(EnableExtension  ForeignFunctionInterface   , "")
-    ,(DisableExtension ForeignFunctionInterface   , "")
-    ,(EnableExtension  ImplicitPrelude            , "") -- Wrong
-    ,(DisableExtension ImplicitPrelude            , "--noprelude")
-    ,(EnableExtension  CPP                        , "-fcpp")
-    ,(DisableExtension CPP                        , "-fno-cpp")
-    ]
-
-getInstalledPackages :: Verbosity -> PackageDBStack -> ProgramDb
-                    -> IO InstalledPackageIndex
-getInstalledPackages verbosity _packageDBs progdb = do
-   -- jhc --list-libraries lists all available libraries.
-   -- How shall I find out, whether they are global or local
-   -- without checking all files and locations?
-   str <- getDbProgramOutput verbosity jhcProgram progdb ["--list-libraries"]
-   let pCheck :: [(a, String)] -> [a]
-       pCheck rs = [ r | (r,s) <- rs, all isSpace s ]
-   let parseLine ln =
-          pCheck (readP_to_S
-             (skipSpaces >> string "Name:" >> skipSpaces >> parse) ln)
-   return $
-      PackageIndex.fromList $
-      map (\p -> emptyInstalledPackageInfo {
-                    InstalledPackageInfo.installedUnitId = mkLegacyUnitId p,
-                    InstalledPackageInfo.sourcePackageId = p
-                 }) $
-      concatMap parseLine $
-      lines str
-
--- -----------------------------------------------------------------------------
--- Building
-
--- | Building a package for JHC.
--- Currently C source files are not supported.
-buildLib :: Verbosity -> PackageDescription -> LocalBuildInfo
-                      -> Library            -> ComponentLocalBuildInfo -> IO ()
-buildLib verbosity pkg_descr lbi lib clbi = do
-  let Just jhcProg = lookupProgram jhcProgram (withPrograms lbi)
-  let libBi = libBuildInfo lib
-  let args  = constructJHCCmdLine lbi libBi clbi (buildDir lbi) verbosity
-  let pkgid = display (packageId pkg_descr)
-      pfile = buildDir lbi </> "jhc-pkg.conf"
-      hlfile= buildDir lbi </> (pkgid ++ ".hl")
-  writeFileAtomic pfile . BS.Char8.pack $ jhcPkgConf pkg_descr
-  runProgram verbosity jhcProg $
-     ["--build-hl="++pfile, "-o", hlfile] ++
-     args ++ map display (allLibModules lib clbi)
-
--- | Building an executable for JHC.
--- Currently C source files are not supported.
-buildExe :: Verbosity -> PackageDescription -> LocalBuildInfo
-                      -> Executable         -> ComponentLocalBuildInfo -> IO ()
-buildExe verbosity _pkg_descr lbi exe clbi = do
-  let Just jhcProg = lookupProgram jhcProgram (withPrograms lbi)
-  let exeBi = buildInfo exe
-  let out   = buildDir lbi </> display (exeName exe)
-  let args  = constructJHCCmdLine lbi exeBi clbi (buildDir lbi) verbosity
-  runProgram verbosity jhcProg (["-o",out] ++ args ++ [modulePath exe])
-
-constructJHCCmdLine :: LocalBuildInfo -> BuildInfo -> ComponentLocalBuildInfo
-                    -> FilePath -> Verbosity -> [String]
-constructJHCCmdLine lbi bi clbi _odir verbosity =
-        (if verbosity >= deafening then ["-v"] else [])
-     ++ hcOptions JHC bi
-     ++ languageToFlags (compiler lbi) (defaultLanguage bi)
-     ++ extensionsToFlags (compiler lbi) (usedExtensions bi)
-     ++ ["--noauto","-i-"]
-     ++ concat [["-i", l] | l <- nub (hsSourceDirs bi)]
-     ++ ["-i", autogenComponentModulesDir lbi clbi]
-     ++ ["-i", autogenPackageModulesDir lbi]
-     ++ ["-optc" ++ opt | opt <- PD.ccOptions bi]
-     -- It would be better if JHC would accept package names with versions,
-     -- but JHC-0.7.2 doesn't accept this.
-     -- Thus, we have to strip the version with 'pkgName'.
-     ++ (concat [ ["-p", display (mungedName pkgid)]
-                | (_, pkgid) <- componentPackageDeps clbi ])
-
-jhcPkgConf :: PackageDescription -> String
-jhcPkgConf pd =
-  let sline name sel = name ++ ": "++sel pd
-      lib pd' = case library pd' of
-                Just lib' -> lib'
-                Nothing -> error "no library available"
-      comma = intercalate "," . map display
-  in unlines [sline "name" (display . pkgName . packageId)
-             ,sline "version" (display . pkgVersion . packageId)
-             ,sline "exposed-modules" (comma . PD.exposedModules . lib)
-             ,sline "hidden-modules" (comma . otherModules . libBuildInfo . lib)
-             ]
-
-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)
-
-installExe :: Verbosity -> FilePath -> FilePath -> (FilePath,FilePath) -> PackageDescription -> Executable -> IO ()
-installExe verb dest build_dir (progprefix,progsuffix) _ exe = do
-    let exe_name = display $ exeName exe
-        src = exe_name </> exeExtension
-        out   = (progprefix ++ exe_name ++ progsuffix) </> exeExtension
-    createDirectoryIfMissingVerbose verb True dest
-    installExecutableFile verb (build_dir </> src) (dest </> out)
diff --git a/cabal/Cabal/Distribution/Simple/LHC.hs b/cabal/Cabal/Distribution/Simple/LHC.hs
deleted file mode 100644
--- a/cabal/Cabal/Distribution/Simple/LHC.hs
+++ /dev/null
@@ -1,778 +0,0 @@
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE RankNTypes #-}
-
------------------------------------------------------------------------------
--- |
--- Module      :  Distribution.Simple.LHC
--- Copyright   :  Isaac Jones 2003-2007
--- License     :  BSD3
---
--- Maintainer  :  cabal-devel@haskell.org
--- Portability :  portable
---
--- This is a fairly large module. It contains most of the GHC-specific code for
--- configuring, building and installing packages. It also exports a function
--- for finding out what packages are already installed. Configuring involves
--- finding the @ghc@ and @ghc-pkg@ programs, finding what language extensions
--- this version of ghc supports and returning a 'Compiler' value.
---
--- 'getInstalledPackages' involves calling the @ghc-pkg@ program to find out
--- what packages are installed.
---
--- Building is somewhat complex as there is quite a bit of information to take
--- into account. We have to build libs and programs, possibly for profiling and
--- shared libs. We have to support building libraries that will be usable by
--- GHCi and also ghc's @-split-objs@ feature. We have to compile any C files
--- using ghc. Linking, especially for @split-objs@ is remarkably complex,
--- partly because there tend to be 1,000's of @.o@ files and this can often be
--- more than we can pass to the @ld@ or @ar@ programs in one go.
---
--- Installing for libs and exes involves finding the right files and copying
--- them to the right places. One of the more tricky things about this module is
--- remembering the layout of files in the build directory (which is not
--- explicitly documented) and thus what search dirs are used for various kinds
--- of files.
-
-module Distribution.Simple.LHC (
-        configure, getInstalledPackages,
-        buildLib, buildExe,
-        installLib, installExe,
-        registerPackage,
-        hcPkgInfo,
-        ghcOptions,
-        ghcVerbosityOptions
- ) where
-
-import Prelude ()
-import Distribution.Compat.Prelude
-
-import Distribution.Types.UnqualComponentName
-import Distribution.PackageDescription as PD hiding (Flag)
-import Distribution.InstalledPackageInfo
-import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo
-import Distribution.Simple.PackageIndex
-import qualified Distribution.Simple.PackageIndex as PackageIndex
-import Distribution.Simple.LocalBuildInfo
-import Distribution.Simple.BuildPaths
-import Distribution.Simple.Utils
-import Distribution.Package
-import qualified Distribution.ModuleName as ModuleName
-import Distribution.Simple.Program
-import qualified Distribution.Simple.Program.HcPkg as HcPkg
-import Distribution.Simple.Compiler
-import Distribution.Version
-import Distribution.Verbosity
-import Distribution.Text
-import Distribution.Compat.Exception
-import Distribution.System
-import Language.Haskell.Extension
-
-import qualified Data.Map as Map ( empty )
-import System.Directory         ( removeFile, renameFile,
-                                  getDirectoryContents, doesFileExist,
-                                  getTemporaryDirectory )
-import System.FilePath          ( (</>), (<.>), takeExtension,
-                                  takeDirectory, replaceExtension )
-import System.IO (hClose, hPutStrLn)
-
--- -----------------------------------------------------------------------------
--- Configuring
-
-configure :: Verbosity -> Maybe FilePath -> Maybe FilePath
-          -> ProgramDb -> IO (Compiler, Maybe Platform, ProgramDb)
-configure verbosity hcPath hcPkgPath progdb = do
-
-  (lhcProg, lhcVersion, progdb') <-
-    requireProgramVersion verbosity lhcProgram
-      (orLaterVersion (mkVersion [0,7]))
-      (userMaybeSpecifyPath "lhc" hcPath progdb)
-
-  (lhcPkgProg, lhcPkgVersion, progdb'') <-
-    requireProgramVersion verbosity lhcPkgProgram
-      (orLaterVersion (mkVersion [0,7]))
-      (userMaybeSpecifyPath "lhc-pkg" hcPkgPath progdb')
-
-  when (lhcVersion /= lhcPkgVersion) $ die' verbosity $
-       "Version mismatch between lhc and lhc-pkg: "
-    ++ programPath lhcProg ++ " is version " ++ display lhcVersion ++ " "
-    ++ programPath lhcPkgProg ++ " is version " ++ display lhcPkgVersion
-
-  languages  <- getLanguages  verbosity lhcProg
-  extensions <- getExtensions verbosity lhcProg
-
-  let comp = Compiler {
-        compilerId             = CompilerId LHC lhcVersion,
-        compilerAbiTag         = NoAbiTag,
-        compilerCompat         = [],
-        compilerLanguages      = languages,
-        compilerExtensions     = extensions,
-        compilerProperties     = Map.empty
-      }
-      progdb''' = configureToolchain lhcProg progdb'' -- configure gcc and ld
-      compPlatform = Nothing
-  return (comp, compPlatform, progdb''')
-
--- | Adjust the way we find and configure gcc and ld
---
-configureToolchain :: ConfiguredProgram -> ProgramDb
-                                        -> ProgramDb
-configureToolchain lhcProg =
-    addKnownProgram gccProgram {
-      programFindLocation = findProg gccProgram (baseDir </> "gcc.exe"),
-      programPostConf     = configureGcc
-    }
-  . addKnownProgram ldProgram {
-      programFindLocation = findProg ldProgram (gccLibDir </> "ld.exe"),
-      programPostConf     = configureLd
-    }
-  where
-    compilerDir = takeDirectory (programPath lhcProg)
-    baseDir     = takeDirectory compilerDir
-    gccLibDir      = baseDir </> "gcc-lib"
-    includeDir  = baseDir </> "include" </> "mingw"
-    isWindows   = case buildOS of Windows -> True; _ -> False
-
-    -- on Windows finding and configuring ghc's gcc and ld is a bit special
-    findProg :: Program -> FilePath
-             -> Verbosity -> ProgramSearchPath
-             -> IO (Maybe (FilePath, [FilePath]))
-    findProg prog location | isWindows = \verbosity searchpath -> do
-        exists <- doesFileExist location
-        if exists then return (Just (location, []))
-                  else do warn verbosity ("Couldn't find " ++ programName prog ++ " where I expected it. Trying the search path.")
-                          programFindLocation prog verbosity searchpath
-      | otherwise = programFindLocation prog
-
-    configureGcc :: Verbosity -> ConfiguredProgram -> NoCallStackIO ConfiguredProgram
-    configureGcc
-      | isWindows = \_ gccProg -> case programLocation gccProg of
-          -- if it's found on system then it means we're using the result
-          -- of programFindLocation above rather than a user-supplied path
-          -- that means we should add this extra flag to tell ghc's gcc
-          -- where it lives and thus where gcc can find its various files:
-          FoundOnSystem {} -> return gccProg {
-                                programDefaultArgs = ["-B" ++ gccLibDir,
-                                                      "-I" ++ includeDir]
-                              }
-          UserSpecified {} -> return gccProg
-      | otherwise = \_ gccProg -> return gccProg
-
-    -- we need to find out if ld supports the -x flag
-    configureLd :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram
-    configureLd verbosity ldProg = do
-      tempDir <- getTemporaryDirectory
-      ldx <- withTempFile tempDir ".c" $ \testcfile testchnd ->
-             withTempFile tempDir ".o" $ \testofile testohnd -> do
-               hPutStrLn testchnd "int foo() { return 0; }"
-               hClose testchnd; hClose testohnd
-               runProgram verbosity lhcProg ["-c", testcfile,
-                                                   "-o", testofile]
-               withTempFile tempDir ".o" $ \testofile' testohnd' ->
-                 do
-                   hClose testohnd'
-                   _ <- getProgramOutput verbosity ldProg
-                     ["-x", "-r", testofile, "-o", testofile']
-                   return True
-                 `catchIO`   (\_ -> return False)
-                 `catchExit` (\_ -> return False)
-      if ldx
-        then return ldProg { programDefaultArgs = ["-x"] }
-        else return ldProg
-
-getLanguages :: Verbosity -> ConfiguredProgram -> NoCallStackIO [(Language, Flag)]
-getLanguages _ _ = return [(Haskell98, "")]
---FIXME: does lhc support -XHaskell98 flag? from what version?
-
-getExtensions :: Verbosity -> ConfiguredProgram -> IO [(Extension, Flag)]
-getExtensions verbosity lhcProg = do
-    exts <- rawSystemStdout verbosity (programPath lhcProg)
-              ["--supported-languages"]
-    -- GHC has the annoying habit of inverting some of the extensions
-    -- so we have to try parsing ("No" ++ ghcExtensionName) first
-    let readExtension str = do
-          ext <- simpleParse ("No" ++ str)
-          case ext of
-            UnknownExtension _ -> simpleParse str
-            _                  -> return ext
-    return $ [ (ext, "-X" ++ display ext)
-             | Just ext <- map readExtension (lines exts) ]
-
-getInstalledPackages :: Verbosity -> PackageDBStack -> ProgramDb
-                     -> IO InstalledPackageIndex
-getInstalledPackages verbosity packagedbs progdb = do
-  checkPackageDbStack verbosity packagedbs
-  pkgss <- getInstalledPackages' lhcPkg verbosity packagedbs progdb
-  let indexes = [ PackageIndex.fromList (map (substTopDir topDir) pkgs)
-                | (_, pkgs) <- pkgss ]
-  return $! (mconcat indexes)
-
-  where
-    -- On Windows, various fields have $topdir/foo rather than full
-    -- paths. We need to substitute the right value in so that when
-    -- we, for example, call gcc, we have proper paths to give it
-    Just ghcProg = lookupProgram lhcProgram progdb
-    Just lhcPkg  = lookupProgram lhcPkgProgram progdb
-    compilerDir  = takeDirectory (programPath ghcProg)
-    topDir       = takeDirectory compilerDir
-
-checkPackageDbStack :: Verbosity -> PackageDBStack -> IO ()
-checkPackageDbStack _ (GlobalPackageDB:rest)
-  | GlobalPackageDB `notElem` rest = return ()
-checkPackageDbStack verbosity _ =
-  die' verbosity $
-        "GHC.getInstalledPackages: the global package db must be "
-     ++ "specified first and cannot be specified multiple times"
-
--- | Get the packages from specific PackageDBs, not cumulative.
---
-getInstalledPackages' :: ConfiguredProgram -> Verbosity
-                      -> [PackageDB] -> ProgramDb
-                      -> IO [(PackageDB, [InstalledPackageInfo])]
-getInstalledPackages' lhcPkg verbosity packagedbs progdb
-  =
-  sequenceA
-    [ do str <- getDbProgramOutput verbosity lhcPkgProgram progdb
-                  ["dump", packageDbGhcPkgFlag packagedb]
-           `catchExit` \_ -> die' verbosity $ "ghc-pkg dump failed"
-         case parsePackages str of
-           Left ok -> return (packagedb, ok)
-           _       -> die' verbosity "failed to parse output of 'ghc-pkg dump'"
-    | packagedb <- packagedbs ]
-
-  where
-    parsePackages str =
-      let parsed = map parseInstalledPackageInfo (splitPkgs str)
-       in case [ msg | ParseFailed msg <- parsed ] of
-            []   -> Left [ pkg | ParseOk _ pkg <- parsed ]
-            msgs -> Right msgs
-
-    splitPkgs :: String -> [String]
-    splitPkgs = map unlines . splitWith ("---" ==) . lines
-      where
-        splitWith :: (a -> Bool) -> [a] -> [[a]]
-        splitWith p xs = ys : case zs of
-                           []   -> []
-                           _:ws -> splitWith p ws
-          where (ys,zs) = break p xs
-
-    packageDbGhcPkgFlag GlobalPackageDB          = "--global"
-    packageDbGhcPkgFlag UserPackageDB            = "--user"
-    packageDbGhcPkgFlag (SpecificPackageDB path) = "--" ++ packageDbFlag ++ "=" ++ path
-
-    packageDbFlag
-      | programVersion lhcPkg < Just (mkVersion [7,5])
-      = "package-conf"
-      | otherwise
-      = "package-db"
-
-
-substTopDir :: FilePath -> InstalledPackageInfo -> InstalledPackageInfo
-substTopDir topDir ipo
- = ipo {
-       InstalledPackageInfo.importDirs
-           = map f (InstalledPackageInfo.importDirs ipo),
-       InstalledPackageInfo.libraryDirs
-           = map f (InstalledPackageInfo.libraryDirs ipo),
-       InstalledPackageInfo.includeDirs
-           = map f (InstalledPackageInfo.includeDirs ipo),
-       InstalledPackageInfo.frameworkDirs
-           = map f (InstalledPackageInfo.frameworkDirs ipo),
-       InstalledPackageInfo.haddockInterfaces
-           = map f (InstalledPackageInfo.haddockInterfaces ipo),
-       InstalledPackageInfo.haddockHTMLs
-           = map f (InstalledPackageInfo.haddockHTMLs ipo)
-   }
-    where f ('$':'t':'o':'p':'d':'i':'r':rest) = topDir ++ rest
-          f x = x
-
--- -----------------------------------------------------------------------------
--- Building
-
--- | Build a library with LHC.
---
-buildLib :: Verbosity -> PackageDescription -> LocalBuildInfo
-                      -> Library            -> ComponentLocalBuildInfo -> IO ()
-buildLib verbosity pkg_descr lbi lib clbi = do
-  let lib_name = componentUnitId clbi
-      pref = componentBuildDir lbi clbi
-      pkgid = packageId pkg_descr
-      runGhcProg = runDbProgram verbosity lhcProgram (withPrograms lbi)
-      ifVanillaLib forceVanilla = when (forceVanilla || withVanillaLib lbi)
-      ifProfLib = when (withProfLib lbi)
-      ifSharedLib = when (withSharedLib lbi)
-      ifGHCiLib = when (withGHCiLib lbi && withVanillaLib lbi)
-
-  libBi <- hackThreadedFlag verbosity
-             (compiler lbi) (withProfLib lbi) (libBuildInfo lib)
-
-  let libTargetDir = pref
-      forceVanillaLib = usesTemplateHaskellOrQQ libBi
-      -- TH always needs vanilla libs, even when building for profiling
-
-  createDirectoryIfMissingVerbose verbosity True libTargetDir
-  -- TODO: do we need to put hs-boot files into place for mutually recursive modules?
-  let ghcArgs =
-             ["-package-name", display pkgid ]
-          ++ constructGHCCmdLine lbi libBi clbi libTargetDir verbosity
-          ++ map display (allLibModules lib clbi)
-      lhcWrap x = ["--build-library", "--ghc-opts=" ++ unwords x]
-      ghcArgsProf = ghcArgs
-          ++ ["-prof",
-              "-hisuf", "p_hi",
-              "-osuf", "p_o"
-             ]
-          ++ hcProfOptions GHC libBi
-      ghcArgsShared = ghcArgs
-          ++ ["-dynamic",
-              "-hisuf", "dyn_hi",
-              "-osuf", "dyn_o", "-fPIC"
-             ]
-          ++ hcSharedOptions GHC libBi
-  unless (null (allLibModules lib clbi)) $
-    do ifVanillaLib forceVanillaLib (runGhcProg $ lhcWrap ghcArgs)
-       ifProfLib (runGhcProg $ lhcWrap ghcArgsProf)
-       ifSharedLib (runGhcProg $ lhcWrap ghcArgsShared)
-
-  -- build any C sources
-  unless (null (cSources libBi)) $ do
-     info verbosity "Building C Sources..."
-     sequence_ [do let (odir,args) = constructCcCmdLine lbi libBi clbi pref
-                                                        filename verbosity
-                   createDirectoryIfMissingVerbose verbosity True odir
-                   runGhcProg args
-                   ifSharedLib (runGhcProg (args ++ ["-fPIC", "-osuf dyn_o"]))
-               | filename <- cSources libBi]
-
-  -- link:
-  info verbosity "Linking..."
-  let cObjs = map (`replaceExtension` objExtension) (cSources libBi)
-      cSharedObjs = map (`replaceExtension` ("dyn_" ++ objExtension)) (cSources libBi)
-      cid = compilerId (compiler lbi)
-      vanillaLibFilePath = libTargetDir </> mkLibName           lib_name
-      profileLibFilePath = libTargetDir </> mkProfLibName       lib_name
-      sharedLibFilePath  = libTargetDir </> mkSharedLibName cid lib_name
-      ghciLibFilePath    = libTargetDir </> mkGHCiLibName       lib_name
-
-  stubObjs <- fmap catMaybes $ sequenceA
-    [ findFileWithExtension [objExtension] [libTargetDir]
-        (ModuleName.toFilePath x ++"_stub")
-    | x <- allLibModules lib clbi ]
-  stubProfObjs <- fmap catMaybes $ sequenceA
-    [ findFileWithExtension ["p_" ++ objExtension] [libTargetDir]
-        (ModuleName.toFilePath x ++"_stub")
-    | x <- allLibModules lib clbi ]
-  stubSharedObjs <- fmap catMaybes $ sequenceA
-    [ findFileWithExtension ["dyn_" ++ objExtension] [libTargetDir]
-        (ModuleName.toFilePath x ++"_stub")
-    | x <- allLibModules lib clbi ]
-
-  hObjs     <- getHaskellObjects lib lbi clbi
-                    pref objExtension True
-  hProfObjs <-
-    if (withProfLib lbi)
-            then getHaskellObjects lib lbi clbi
-                    pref ("p_" ++ objExtension) True
-            else return []
-  hSharedObjs <-
-    if (withSharedLib lbi)
-            then getHaskellObjects lib lbi clbi
-                    pref ("dyn_" ++ objExtension) False
-            else return []
-
-  unless (null hObjs && null cObjs && null stubObjs) $ do
-    -- first remove library files if they exists
-    sequence_
-      [ removeFile libFilePath `catchIO` \_ -> return ()
-      | libFilePath <- [vanillaLibFilePath, profileLibFilePath
-                       ,sharedLibFilePath,  ghciLibFilePath] ]
-
-    let arVerbosity | verbosity >= deafening = "v"
-                    | verbosity >= normal = ""
-                    | otherwise = "c"
-        arArgs = ["q"++ arVerbosity]
-            ++ [vanillaLibFilePath]
-        arObjArgs =
-               hObjs
-            ++ map (pref </>) cObjs
-            ++ stubObjs
-        arProfArgs = ["q"++ arVerbosity]
-            ++ [profileLibFilePath]
-        arProfObjArgs =
-               hProfObjs
-            ++ map (pref </>) cObjs
-            ++ stubProfObjs
-        ldArgs = ["-r"]
-            ++ ["-o", ghciLibFilePath <.> "tmp"]
-        ldObjArgs =
-               hObjs
-            ++ map (pref </>) cObjs
-            ++ stubObjs
-        ghcSharedObjArgs =
-               hSharedObjs
-            ++ map (pref </>) cSharedObjs
-            ++ stubSharedObjs
-        -- After the relocation lib is created we invoke ghc -shared
-        -- with the dependencies spelled out as -package arguments
-        -- and ghc invokes the linker with the proper library paths
-        ghcSharedLinkArgs =
-            [ "-no-auto-link-packages",
-              "-shared",
-              "-dynamic",
-              "-o", sharedLibFilePath ]
-            ++ ghcSharedObjArgs
-            ++ ["-package-name", display pkgid ]
-            ++ ghcPackageFlags lbi clbi
-            ++ ["-l"++extraLib | extraLib <- extraLibs libBi]
-            ++ ["-L"++extraLibDir | extraLibDir <- extraLibDirs libBi]
-
-        runLd ldLibName args = do
-          exists <- doesFileExist ldLibName
-            -- This method is called iteratively by xargs. The
-            -- output goes to <ldLibName>.tmp, and any existing file
-            -- named <ldLibName> is included when linking. The
-            -- output is renamed to <lib_name>.
-          runDbProgram verbosity ldProgram (withPrograms lbi)
-            (args ++ if exists then [ldLibName] else [])
-          renameFile (ldLibName <.> "tmp") ldLibName
-
-        runAr = runDbProgram verbosity arProgram (withPrograms lbi)
-
-         --TODO: discover this at configure time or runtime on Unix
-         -- The value is 32k on Windows and POSIX specifies a minimum of 4k
-         -- but all sensible Unixes use more than 4k.
-         -- we could use getSysVar ArgumentLimit but that's in the Unix lib
-        maxCommandLineSize = 30 * 1024
-
-    ifVanillaLib False $ xargs maxCommandLineSize
-      runAr arArgs arObjArgs
-
-    ifProfLib $ xargs maxCommandLineSize
-      runAr arProfArgs arProfObjArgs
-
-    ifGHCiLib $ xargs maxCommandLineSize
-      (runLd ghciLibFilePath) ldArgs ldObjArgs
-
-    ifSharedLib $ runGhcProg ghcSharedLinkArgs
-
-
--- | Build an executable with LHC.
---
-buildExe :: Verbosity -> PackageDescription -> LocalBuildInfo
-                      -> Executable         -> ComponentLocalBuildInfo -> IO ()
-buildExe verbosity _pkg_descr lbi
-  exe@Executable { exeName = exeName', modulePath = modPath } clbi = do
-  let exeName'' = unUnqualComponentName exeName'
-  let pref = buildDir lbi
-      runGhcProg = runDbProgram verbosity lhcProgram (withPrograms lbi)
-
-  exeBi <- hackThreadedFlag verbosity
-             (compiler lbi) (withProfExe lbi) (buildInfo exe)
-
-  -- exeNameReal, the name that GHC really uses (with .exe on Windows)
-  let exeNameReal = exeName'' <.>
-                    (if null $ takeExtension exeName'' then exeExtension else "")
-
-  let targetDir = pref </> exeName''
-  let exeDir    = targetDir </> (exeName'' ++ "-tmp")
-  createDirectoryIfMissingVerbose verbosity True targetDir
-  createDirectoryIfMissingVerbose verbosity True exeDir
-  -- TODO: do we need to put hs-boot files into place for mutually recursive modules?
-  -- FIX: what about exeName.hi-boot?
-
-  -- build executables
-  unless (null (cSources exeBi)) $ do
-   info verbosity "Building C Sources."
-   sequence_ [do let (odir,args) = constructCcCmdLine lbi exeBi clbi
-                                          exeDir filename verbosity
-                 createDirectoryIfMissingVerbose verbosity True odir
-                 runGhcProg args
-             | filename <- cSources exeBi]
-
-  srcMainFile <- findFile (exeDir : hsSourceDirs exeBi) modPath
-
-  let cObjs = map (`replaceExtension` objExtension) (cSources exeBi)
-  let lhcWrap x = ("--ghc-opts\"":x) ++ ["\""]
-  let binArgs linkExe profExe =
-             (if linkExe
-                 then ["-o", targetDir </> exeNameReal]
-                 else ["-c"])
-          ++ constructGHCCmdLine lbi exeBi clbi exeDir verbosity
-          ++ [exeDir </> x | x <- cObjs]
-          ++ [srcMainFile]
-          ++ ["-optl" ++ opt | opt <- PD.ldOptions exeBi]
-          ++ ["-l"++lib | lib <- extraLibs exeBi]
-          ++ ["-L"++extraLibDir | extraLibDir <- extraLibDirs exeBi]
-          ++ concat [["-framework", f] | f <- PD.frameworks exeBi]
-          ++ if profExe
-                then ["-prof",
-                      "-hisuf", "p_hi",
-                      "-osuf", "p_o"
-                     ] ++ hcProfOptions GHC exeBi
-                else []
-
-  -- For building exe's for profiling that use TH we actually
-  -- have to build twice, once without profiling and the again
-  -- with profiling. This is because the code that TH needs to
-  -- run at compile time needs to be the vanilla ABI so it can
-  -- be loaded up and run by the compiler.
-  when (withProfExe lbi && usesTemplateHaskellOrQQ exeBi)
-     (runGhcProg $ lhcWrap (binArgs False False))
-
-  runGhcProg (binArgs True (withProfExe lbi))
-
--- | Filter the "-threaded" flag when profiling as it does not
---   work with ghc-6.8 and older.
-hackThreadedFlag :: Verbosity -> Compiler -> Bool -> BuildInfo -> IO BuildInfo
-hackThreadedFlag verbosity comp prof bi
-  | not mustFilterThreaded = return bi
-  | otherwise              = do
-    warn verbosity $ "The ghc flag '-threaded' is not compatible with "
-                  ++ "profiling in ghc-6.8 and older. It will be disabled."
-    return bi { options = filterHcOptions (/= "-threaded") (options bi) }
-  where
-    mustFilterThreaded = prof && compilerVersion comp < mkVersion [6, 10]
-                      && "-threaded" `elem` hcOptions GHC bi
-    filterHcOptions p hcoptss =
-      [ (hc, if hc == GHC then filter p opts else opts)
-      | (hc, opts) <- hcoptss ]
-
--- when using -split-objs, we need to search for object files in the
--- Module_split directory for each module.
-getHaskellObjects :: Library -> LocalBuildInfo -> ComponentLocalBuildInfo
-                  -> FilePath -> String -> Bool -> NoCallStackIO [FilePath]
-getHaskellObjects lib lbi clbi pref wanted_obj_ext allow_split_objs
-  | splitObjs lbi && allow_split_objs = do
-        let dirs = [ pref </> (ModuleName.toFilePath x ++ "_split")
-                   | x <- allLibModules lib clbi ]
-        objss <- traverse getDirectoryContents dirs
-        let objs = [ dir </> obj
-                   | (objs',dir) <- zip objss dirs, obj <- objs',
-                     let obj_ext = takeExtension obj,
-                     '.':wanted_obj_ext == obj_ext ]
-        return objs
-  | otherwise  =
-        return [ pref </> ModuleName.toFilePath x <.> wanted_obj_ext
-               | x <- allLibModules lib clbi ]
-
-
-constructGHCCmdLine
-        :: LocalBuildInfo
-        -> BuildInfo
-        -> ComponentLocalBuildInfo
-        -> FilePath
-        -> Verbosity
-        -> [String]
-constructGHCCmdLine lbi bi clbi odir verbosity =
-        ["--make"]
-     ++ ghcVerbosityOptions verbosity
-        -- Unsupported extensions have already been checked by configure
-     ++ ghcOptions lbi bi clbi odir
-
-ghcVerbosityOptions :: Verbosity -> [String]
-ghcVerbosityOptions verbosity
-     | verbosity >= deafening = ["-v"]
-     | verbosity >= normal    = []
-     | otherwise              = ["-w", "-v0"]
-
-ghcOptions :: LocalBuildInfo -> BuildInfo -> ComponentLocalBuildInfo
-           -> FilePath -> [String]
-ghcOptions lbi bi clbi odir
-     =  ["-hide-all-packages"]
-     ++ ghcPackageDbOptions lbi
-     ++ (if splitObjs lbi then ["-split-objs"] else [])
-     ++ ["-i"]
-     ++ ["-i" ++ odir]
-     ++ ["-i" ++ l | l <- nub (hsSourceDirs bi)]
-     ++ ["-i" ++ autogenComponentModulesDir lbi clbi]
-     ++ ["-i" ++ autogenPackageModulesDir lbi]
-     ++ ["-I" ++ autogenComponentModulesDir lbi clbi]
-     ++ ["-I" ++ autogenPackageModulesDir lbi]
-     ++ ["-I" ++ odir]
-     ++ ["-I" ++ dir | dir <- PD.includeDirs bi]
-     ++ ["-optP" ++ opt | opt <- cppOptions bi]
-     ++ [ "-optP-include", "-optP"++ (autogenComponentModulesDir lbi clbi </> cppHeaderName) ]
-     ++ [ "-#include \"" ++ inc ++ "\"" | inc <- PD.includes bi ]
-     ++ [ "-odir",  odir, "-hidir", odir ]
-     ++ (if compilerVersion c >= mkVersion [6,8]
-           then ["-stubdir", odir] else [])
-     ++ ghcPackageFlags lbi clbi
-     ++ (case withOptimization lbi of
-           NoOptimisation      -> []
-           NormalOptimisation  -> ["-O"]
-           MaximumOptimisation -> ["-O2"])
-     ++ hcOptions GHC bi
-     ++ languageToFlags c (defaultLanguage bi)
-     ++ extensionsToFlags c (usedExtensions bi)
-    where c = compiler lbi
-
-ghcPackageFlags :: LocalBuildInfo -> ComponentLocalBuildInfo -> [String]
-ghcPackageFlags lbi clbi
-  | ghcVer >= mkVersion [6,11]
-              = concat [ ["-package-id", display ipkgid]
-                       | (ipkgid, _) <- componentPackageDeps clbi ]
-
-  | otherwise = concat [ ["-package", display pkgid]
-                       | (_, pkgid)  <- componentPackageDeps clbi ]
-    where
-      ghcVer = compilerVersion (compiler lbi)
-
-ghcPackageDbOptions :: LocalBuildInfo -> [String]
-ghcPackageDbOptions lbi = case dbstack of
-  (GlobalPackageDB:UserPackageDB:dbs) -> concatMap specific dbs
-  (GlobalPackageDB:dbs)               -> ("-no-user-" ++ packageDbFlag)
-                                       : concatMap specific dbs
-  _                                   -> ierror
- where
-    specific (SpecificPackageDB db) = [ '-':packageDbFlag, db ]
-    specific _ = ierror
-    ierror     = error ("internal error: unexpected package db stack: " ++ show dbstack)
-
-    dbstack = withPackageDB lbi
-    packageDbFlag
-      | compilerVersion (compiler lbi) < mkVersion [7,5]
-      = "package-conf"
-      | otherwise
-      = "package-db"
-
-constructCcCmdLine :: LocalBuildInfo -> BuildInfo -> ComponentLocalBuildInfo
-                   -> FilePath -> FilePath -> Verbosity -> (FilePath,[String])
-constructCcCmdLine lbi bi clbi pref filename verbosity
-  =  let odir | compilerVersion (compiler lbi) >= mkVersion [6,4,1] = pref
-              | otherwise = pref </> takeDirectory filename
-                        -- ghc 6.4.1 fixed a bug in -odir handling
-                        -- for C compilations.
-     in
-        (odir,
-         ghcCcOptions lbi bi clbi odir
-         ++ (if verbosity >= deafening then ["-v"] else [])
-         ++ ["-c",filename])
-
-
-ghcCcOptions :: LocalBuildInfo -> BuildInfo -> ComponentLocalBuildInfo
-             -> FilePath -> [String]
-ghcCcOptions lbi bi clbi odir
-     =  ["-I" ++ dir | dir <- PD.includeDirs bi]
-     ++ ghcPackageDbOptions lbi
-     ++ ghcPackageFlags lbi clbi
-     ++ ["-optc" ++ opt | opt <- PD.ccOptions bi]
-     ++ (case withOptimization lbi of
-           NoOptimisation -> []
-           _              -> ["-optc-O2"])
-     ++ ["-odir", odir]
-
-mkGHCiLibName :: UnitId -> String
-mkGHCiLibName lib = getHSLibraryName lib <.> "o"
-
--- -----------------------------------------------------------------------------
--- Installing
-
--- |Install executables for GHC.
-installExe :: Verbosity
-           -> LocalBuildInfo
-           -> FilePath -- ^Where to copy the files to
-           -> FilePath  -- ^Build location
-           -> (FilePath, FilePath)  -- ^Executable (prefix,suffix)
-           -> PackageDescription
-           -> Executable
-           -> IO ()
-installExe verbosity lbi binDir buildPref (progprefix, progsuffix) _pkg exe = do
-  createDirectoryIfMissingVerbose verbosity True binDir
-  let exeFileName = unUnqualComponentName (exeName exe) <.> exeExtension
-      fixedExeBaseName = progprefix ++ unUnqualComponentName (exeName exe) ++ progsuffix
-      installBinary dest = do
-          installExecutableFile verbosity
-            (buildPref </> unUnqualComponentName (exeName exe) </> exeFileName)
-            (dest <.> exeExtension)
-          stripExe verbosity lbi exeFileName (dest <.> exeExtension)
-  installBinary (binDir </> fixedExeBaseName)
-
-stripExe :: Verbosity -> LocalBuildInfo -> FilePath -> FilePath -> IO ()
-stripExe verbosity lbi name path = when (stripExes lbi) $
-  case lookupProgram stripProgram (withPrograms lbi) of
-    Just strip -> runProgram verbosity strip args
-    Nothing    -> unless (buildOS == Windows) $
-                  -- Don't bother warning on windows, we don't expect them to
-                  -- have the strip program anyway.
-                  warn verbosity $ "Unable to strip executable '" ++ name
-                                ++ "' (missing the 'strip' program)"
-  where
-    args = path : case buildOS of
-       OSX -> ["-x"] -- By default, stripping the ghc binary on at least
-                     -- some OS X installations causes:
-                     --     HSbase-3.0.o: unknown symbol `_environ'"
-                     -- The -x flag fixes that.
-       _   -> []
-
--- |Install for ghc, .hi, .a and, if --with-ghci given, .o
-installLib    :: Verbosity
-              -> LocalBuildInfo
-              -> FilePath  -- ^install location
-              -> FilePath  -- ^install location for dynamic libraries
-              -> FilePath  -- ^Build location
-              -> PackageDescription
-              -> Library
-              -> ComponentLocalBuildInfo
-              -> IO ()
-installLib verbosity lbi targetDir dynlibTargetDir builtDir _pkg lib clbi = do
-  -- copy .hi files over:
-  let copy src dst n = do
-        createDirectoryIfMissingVerbose verbosity True dst
-        installOrdinaryFile verbosity (src </> n) (dst </> n)
-      copyModuleFiles ext =
-        findModuleFiles [builtDir] [ext] (allLibModules lib clbi)
-          >>= installOrdinaryFiles verbosity targetDir
-  ifVanilla $ copyModuleFiles "hi"
-  ifProf    $ copyModuleFiles "p_hi"
-  hcrFiles <- findModuleFiles (builtDir : hsSourceDirs (libBuildInfo lib)) ["hcr"] (allLibModules lib clbi)
-  flip traverse_ hcrFiles $ \(srcBase, srcFile) -> runLhc ["--install-library", srcBase </> srcFile]
-
-  -- copy the built library files over:
-  ifVanilla $ copy builtDir targetDir       vanillaLibName
-  ifProf    $ copy builtDir targetDir       profileLibName
-  ifGHCi    $ copy builtDir targetDir       ghciLibName
-  ifShared  $ copy builtDir dynlibTargetDir sharedLibName
-
-  where
-    cid = compilerId (compiler lbi)
-    lib_name = componentUnitId clbi
-    vanillaLibName = mkLibName           lib_name
-    profileLibName = mkProfLibName       lib_name
-    ghciLibName    = mkGHCiLibName       lib_name
-    sharedLibName  = mkSharedLibName cid lib_name
-
-    hasLib    = not $ null (allLibModules lib clbi)
-                   && null (cSources (libBuildInfo lib))
-    ifVanilla = when (hasLib && withVanillaLib lbi)
-    ifProf    = when (hasLib && withProfLib    lbi)
-    ifGHCi    = when (hasLib && withGHCiLib    lbi)
-    ifShared  = when (hasLib && withSharedLib  lbi)
-
-    runLhc    = runDbProgram verbosity lhcProgram (withPrograms lbi)
-
--- -----------------------------------------------------------------------------
--- Registering
-
-registerPackage
-  :: Verbosity
-  -> ProgramDb
-  -> PackageDBStack
-  -> InstalledPackageInfo
-  -> HcPkg.RegisterOptions
-  -> IO ()
-registerPackage verbosity progdb packageDbs installedPkgInfo registerOptions =
-    HcPkg.register (hcPkgInfo progdb) verbosity packageDbs
-                   installedPkgInfo registerOptions
-
-hcPkgInfo :: ProgramDb -> HcPkg.HcPkgInfo
-hcPkgInfo progdb = HcPkg.HcPkgInfo { HcPkg.hcPkgProgram    = lhcPkgProg
-                                   , HcPkg.noPkgDbStack    = False
-                                   , HcPkg.noVerboseFlag   = False
-                                   , HcPkg.flagPackageConf = False
-                                   , HcPkg.supportsDirDbs  = True
-                                   , HcPkg.requiresDirDbs  = True
-                                   , HcPkg.nativeMultiInstance  = False -- ?
-                                   , HcPkg.recacheMultiInstance = False -- ?
-                                   , HcPkg.suppressFilesCheck   = True
-                                   }
-  where
-    Just lhcPkgProg = lookupProgram lhcPkgProgram progdb
diff --git a/cabal/Cabal/Distribution/Simple/PackageIndex.hs b/cabal/Cabal/Distribution/Simple/PackageIndex.hs
--- a/cabal/Cabal/Distribution/Simple/PackageIndex.hs
+++ b/cabal/Cabal/Distribution/Simple/PackageIndex.hs
@@ -101,7 +101,7 @@
 
 import Prelude ()
 import Distribution.Compat.Prelude hiding (lookup)
-import qualified Distribution.Compat.Map.Strict as Map
+import qualified Data.Map.Strict as Map
 
 import Distribution.Package
 import Distribution.Backpack
@@ -303,7 +303,7 @@
       . List.deleteBy (\_ pkg -> installedUnitId pkg == ipkgid) undefined
 
 -- | Backwards compatibility wrapper for Cabal pre-1.24.
-{-# DEPRECATED deleteInstalledPackageId "Use deleteUnitId instead" #-}
+{-# DEPRECATED deleteInstalledPackageId "Use deleteUnitId instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 deleteInstalledPackageId :: UnitId -> InstalledPackageIndex
                          -> InstalledPackageIndex
 deleteInstalledPackageId = deleteUnitId
@@ -419,7 +419,7 @@
     Map.lookup (newSimpleUnitId cid) (unitIdIndex index)
 
 -- | Backwards compatibility for Cabal pre-1.24.
-{-# DEPRECATED lookupInstalledPackageId "Use lookupUnitId instead" #-}
+{-# DEPRECATED lookupInstalledPackageId "Use lookupUnitId instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 lookupInstalledPackageId :: PackageIndex a -> UnitId
                          -> Maybe a
 lookupInstalledPackageId = lookupUnitId
diff --git a/cabal/Cabal/Distribution/Simple/PreProcess.hs b/cabal/Cabal/Distribution/Simple/PreProcess.hs
--- a/cabal/Cabal/Distribution/Simple/PreProcess.hs
+++ b/cabal/Cabal/Distribution/Simple/PreProcess.hs
@@ -47,6 +47,7 @@
 import Distribution.Simple.BuildPaths
 import Distribution.Simple.Utils
 import Distribution.Simple.Program
+import Distribution.Simple.Program.ResponseFile
 import Distribution.Simple.Test.LibV09
 import Distribution.System
 import Distribution.Text
@@ -102,11 +103,11 @@
   -- Is the output of the pre-processor platform independent? eg happy output
   -- is portable haskell but c2hs's output is platform dependent.
   -- This matters since only platform independent generated code can be
-  -- inlcuded into a source tarball.
+  -- included into a source tarball.
   platformIndependent :: Bool,
 
-  -- TODO: deal with pre-processors that have implementaion dependent output
-  --       eg alex and happy have --ghc flags. However we can't really inlcude
+  -- TODO: deal with pre-processors that have implementation dependent output
+  --       eg alex and happy have --ghc flags. However we can't really include
   --       ghc-specific code into supposedly portable source tarballs.
 
   runPreProcessor :: (FilePath, FilePath) -- Location of the source file relative to a base dir
@@ -343,8 +344,8 @@
 ppCpp' :: [String] -> BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor
 ppCpp' extraArgs bi lbi clbi =
   case compilerFlavor (compiler lbi) of
-    GHC   -> ppGhcCpp ghcProgram   (>= mkVersion [6,6])  args bi lbi clbi
-    GHCJS -> ppGhcCpp ghcjsProgram (const True)          args bi lbi clbi
+    GHC   -> ppGhcCpp ghcProgram   (const True) args bi lbi clbi
+    GHCJS -> ppGhcCpp ghcjsProgram (const True) args bi lbi clbi
     _     -> ppCpphs  args bi lbi clbi
   where cppArgs = getCppOptions bi lbi
         args    = cppArgs ++ extraArgs
@@ -392,7 +393,28 @@
     platformIndependent = False,
     runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity -> do
       (gccProg, _) <- requireProgram verbosity gccProgram (withPrograms lbi)
-      runDbProgram verbosity hsc2hsProgram (withPrograms lbi) $
+      (hsc2hsProg, hsc2hsVersion, _) <- requireProgramVersion verbosity
+                                          hsc2hsProgram anyVersion (withPrograms lbi)
+      -- See Trac #13896 and https://github.com/haskell/cabal/issues/3122.
+      let hsc2hsSupportsResponseFiles = hsc2hsVersion >= mkVersion [0,68,4]
+          pureArgs = genPureArgs gccProg inFile outFile
+      if hsc2hsSupportsResponseFiles
+      then withResponseFile
+             verbosity
+             defaultTempFileOptions
+             (takeDirectory outFile)
+             "hsc2hs-response.txt"
+             Nothing
+             pureArgs
+             (\responseFileName ->
+                runProgram verbosity hsc2hsProg ["@"++ responseFileName])
+      else runProgram verbosity hsc2hsProg pureArgs
+  }
+  where
+    -- Returns a list of command line arguments that can either be passed
+    -- directly, or via a response file.
+    genPureArgs :: ConfiguredProgram -> String -> String -> [String]
+    genPureArgs gccProg inFile outFile =
           [ "--cc=" ++ programPath gccProg
           , "--ld=" ++ programPath gccProg ]
 
@@ -421,8 +443,18 @@
 
           -- Options from the current package:
        ++ [ "--cflag=-I" ++ dir | dir <- PD.includeDirs  bi ]
+       ++ [ "--cflag=-I" ++ buildDir lbi </> dir | dir <- PD.includeDirs bi ]
        ++ [ "--cflag="   ++ opt | opt <- PD.ccOptions    bi
-                                      ++ PD.cppOptions   bi ]
+                                      ++ PD.cppOptions   bi
+                                      -- hsc2hs uses the C ABI
+                                      -- We assume that there are only C sources
+                                      -- and C++ functions are exported via a C
+                                      -- interface and wrapped in a C source file.
+                                      -- Therefore we do not supply C++ flags
+                                      -- because there will not be C++ sources.
+                                      --
+                                      -- DO NOT add PD.cxxOptions unless this changes!
+                                      ]
        ++ [ "--cflag="   ++ opt | opt <-
                [ "-I" ++ autogenComponentModulesDir lbi clbi,
                  "-I" ++ autogenPackageModulesDir lbi,
@@ -446,8 +478,7 @@
                 ++ [ "-l" ++ opt | opt <- Installed.extraLibraries pkg ]
                 ++ [         opt | opt <- Installed.ldOptions      pkg ] ]
        ++ ["-o", outFile, inFile]
-  }
-  where
+
     hacked_index = packageHacks (installedPkgs lbi)
     -- Look only at the dependencies of the current component
     -- being built!  This relies on 'installedPkgs' maintaining
@@ -466,7 +497,7 @@
       _     -> id
     -- We don't link in the actual Haskell libraries of our dependencies, so
     -- the -u flags in the ldOptions of the rts package mean linking fails on
-    -- OS X (it's ld is a tad stricter than gnu ld). Thus we remove the
+    -- OS X (its ld is a tad stricter than gnu ld). Thus we remove the
     -- ldOptions for GHC's rts package:
     hackRtsPackage index =
       case PackageIndex.lookupPackageName index (mkPackageName "rts") of
@@ -501,6 +532,15 @@
           | pkg <- pkgs
           , opt <- [ "-I" ++ opt | opt <- Installed.includeDirs pkg ]
                 ++ [         opt | opt@('-':c:_) <- Installed.ccOptions pkg
+                                                 -- c2hs uses the C ABI
+                                                 -- We assume that there are only C sources
+                                                 -- and C++ functions are exported via a C
+                                                 -- interface and wrapped in a C source file.
+                                                 -- Therefore we do not supply C++ flags
+                                                 -- because there will not be C++ sources.
+                                                 --
+                                                 --
+                                                 -- DO NOT add Installed.cxxOptions unless this changes!
                                  , c `elem` "DIU" ] ]
           --TODO: install .chi files for packages, so we can --include
           -- those dirs here, for the dependencies
@@ -519,12 +559,15 @@
 
 --TODO: perhaps use this with hsc2hs too
 --TODO: remove cc-options from cpphs for cabal-version: >= 1.10
+--TODO: Refactor and add separate getCppOptionsForHs, getCppOptionsForCxx, & getCppOptionsForC
+--      instead of combining all these cases in a single function. This blind combination can
+--      potentially lead to compilation inconsistencies.
 getCppOptions :: BuildInfo -> LocalBuildInfo -> [String]
 getCppOptions bi lbi
     = platformDefines lbi
    ++ cppOptions bi
    ++ ["-I" ++ dir | dir <- PD.includeDirs bi]
-   ++ [opt | opt@('-':c:_) <- PD.ccOptions bi, c `elem` "DIU"]
+   ++ [opt | opt@('-':c:_) <- PD.ccOptions bi ++ PD.cxxOptions bi, c `elem` "DIU"]
 
 platformDefines :: LocalBuildInfo -> [String]
 platformDefines lbi =
@@ -542,7 +585,6 @@
       ["-D" ++ arch ++ "_BUILD_ARCH=1"] ++
       map (\os'   -> "-D" ++ os'   ++ "_HOST_OS=1")   osStr ++
       map (\arch' -> "-D" ++ arch' ++ "_HOST_ARCH=1") archStr
-    JHC  -> ["-D__JHC__=" ++ versionInt version]
     HaskellSuite {} ->
       ["-D__HASKELL_SUITE__"] ++
         map (\os'   -> "-D" ++ os'   ++ "_HOST_OS=1")   osStr ++
@@ -597,6 +639,7 @@
       PPC64       -> ["powerpc64"]
       Sparc       -> ["sparc"]
       Arm         -> ["arm"]
+      AArch64     -> ["aarch64"]
       Mips        -> ["mips"]
       SH          -> []
       IA64        -> ["ia64"]
diff --git a/cabal/Cabal/Distribution/Simple/Program.hs b/cabal/Cabal/Distribution/Simple/Program.hs
--- a/cabal/Cabal/Distribution/Simple/Program.hs
+++ b/cabal/Cabal/Distribution/Simple/Program.hs
@@ -98,8 +98,6 @@
     , ghcPkgProgram
     , ghcjsProgram
     , ghcjsPkgProgram
-    , lhcProgram
-    , lhcPkgProgram
     , hmakeProgram
     , jhcProgram
     , uhcProgram
@@ -200,42 +198,41 @@
 -- Deprecated aliases
 --
 
-{-# DEPRECATED rawSystemProgram "use runProgram instead" #-}
+{-# DEPRECATED rawSystemProgram "use runProgram instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 rawSystemProgram :: Verbosity -> ConfiguredProgram
                  -> [ProgArg] -> IO ()
 rawSystemProgram = runProgram
 
-{-# DEPRECATED rawSystemProgramStdout "use getProgramOutput instead" #-}
+{-# DEPRECATED rawSystemProgramStdout "use getProgramOutput instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 rawSystemProgramStdout :: Verbosity -> ConfiguredProgram
                        -> [ProgArg] -> IO String
 rawSystemProgramStdout = getProgramOutput
 
-{-# DEPRECATED rawSystemProgramConf "use runDbProgram instead" #-}
+{-# DEPRECATED rawSystemProgramConf "use runDbProgram instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 rawSystemProgramConf :: Verbosity  -> Program -> ProgramConfiguration
                      -> [ProgArg] -> IO ()
 rawSystemProgramConf = runDbProgram
 
-{-# DEPRECATED rawSystemProgramStdoutConf "use getDbProgramOutput instead" #-}
+{-# DEPRECATED rawSystemProgramStdoutConf "use getDbProgramOutput instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 rawSystemProgramStdoutConf :: Verbosity -> Program -> ProgramConfiguration
                            -> [ProgArg] -> IO String
 rawSystemProgramStdoutConf = getDbProgramOutput
 
-{-# DEPRECATED ProgramConfiguration "use ProgramDb instead" #-}
+{-# DEPRECATED ProgramConfiguration "use ProgramDb instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 type ProgramConfiguration = ProgramDb
 
-{-# DEPRECATED emptyProgramConfiguration "use emptyProgramDb instead" #-}
-{-# DEPRECATED defaultProgramConfiguration "use defaultProgramDb instead" #-}
+{-# DEPRECATED emptyProgramConfiguration "use emptyProgramDb instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
+{-# DEPRECATED defaultProgramConfiguration "use defaultProgramDb instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 emptyProgramConfiguration, defaultProgramConfiguration :: ProgramConfiguration
 emptyProgramConfiguration   = emptyProgramDb
 defaultProgramConfiguration = defaultProgramDb
 
-{-# DEPRECATED restoreProgramConfiguration
-               "use restoreProgramDb instead" #-}
+{-# DEPRECATED restoreProgramConfiguration "use restoreProgramDb instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 restoreProgramConfiguration :: [Program] -> ProgramConfiguration
                                          -> ProgramConfiguration
 restoreProgramConfiguration = restoreProgramDb
 
-{-# DEPRECATED findProgramOnPath "use findProgramOnSearchPath instead" #-}
+{-# DEPRECATED findProgramOnPath "use findProgramOnSearchPath instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 findProgramOnPath :: String -> Verbosity -> IO (Maybe FilePath)
 findProgramOnPath name verbosity =
     fmap (fmap fst) $
diff --git a/cabal/Cabal/Distribution/Simple/Program/Builtin.hs b/cabal/Cabal/Distribution/Simple/Program/Builtin.hs
--- a/cabal/Cabal/Distribution/Simple/Program/Builtin.hs
+++ b/cabal/Cabal/Distribution/Simple/Program/Builtin.hs
@@ -21,8 +21,6 @@
     runghcProgram,
     ghcjsProgram,
     ghcjsPkgProgram,
-    lhcProgram,
-    lhcPkgProgram,
     hmakeProgram,
     jhcProgram,
     haskellSuiteProgram,
@@ -50,6 +48,7 @@
 import Prelude ()
 import Distribution.Compat.Prelude
 
+import Distribution.Simple.Program.GHC
 import Distribution.Simple.Program.Find
 import Distribution.Simple.Program.Internal
 import Distribution.Simple.Program.Run
@@ -80,8 +79,6 @@
     , haskellSuitePkgProgram
     , hmakeProgram
     , jhcProgram
-    , lhcProgram
-    , lhcPkgProgram
     , uhcProgram
     , hpcProgram
     -- preprocessors
@@ -122,7 +119,9 @@
        return $ maybe ghcProg
          (\v -> if withinRange v affectedVersionRange
                 then ghcProg' else ghcProg)
-         (programVersion ghcProg)
+         (programVersion ghcProg),
+
+    programNormaliseArgs = normaliseGhcArgs
   }
 
 runghcProgram :: Program
@@ -160,21 +159,6 @@
         _               -> ""
   }
 
-lhcProgram :: Program
-lhcProgram = (simpleProgram "lhc") {
-    programFindVersion = findProgramVersion "--numeric-version" id
-  }
-
-lhcPkgProgram :: Program
-lhcPkgProgram = (simpleProgram "lhc-pkg") {
-    programFindVersion = findProgramVersion "--version" $ \str ->
-      -- Invoking "lhc-pkg --version" gives a string like
-      -- "LHC package manager version 0.7"
-      case words str of
-        (_:_:_:_:ver:_) -> ver
-        _               -> ""
-  }
-
 hmakeProgram :: Program
 hmakeProgram = (simpleProgram "hmake") {
     programFindVersion = findProgramVersion "--version" $ \str ->
@@ -330,7 +314,9 @@
       -- "Haddock version 0.8, (c) Simon Marlow 2006"
       case words str of
         (_:_:ver:_) -> takeWhile (`elem` ('.':['0'..'9'])) ver
-        _           -> ""
+        _           -> "",
+
+    programNormaliseArgs = \_ _ args -> args
   }
 
 greencardProgram :: Program
diff --git a/cabal/Cabal/Distribution/Simple/Program/GHC.hs b/cabal/Cabal/Distribution/Simple/Program/GHC.hs
--- a/cabal/Cabal/Distribution/Simple/Program/GHC.hs
+++ b/cabal/Cabal/Distribution/Simple/Program/GHC.hs
@@ -1,8 +1,9 @@
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE NoMonoLocalBinds #-}
-
 module Distribution.Simple.Program.GHC (
     GhcOptions(..),
     GhcMode(..),
@@ -16,6 +17,7 @@
     runGHC,
 
     packageDbArgsDb,
+    normaliseGhcArgs
 
   ) where
 
@@ -27,20 +29,279 @@
 import Distribution.PackageDescription hiding (Flag)
 import Distribution.ModuleName
 import Distribution.Simple.Compiler hiding (Flag)
-import Distribution.Simple.Setup
+import qualified Distribution.Simple.Compiler as Compiler (Flag)
+import Distribution.Simple.Flag
 import Distribution.Simple.Program.Types
 import Distribution.Simple.Program.Run
 import Distribution.System
 import Distribution.Text
 import Distribution.Types.ComponentId
 import Distribution.Verbosity
+import Distribution.Version
 import Distribution.Utils.NubList
 import Language.Haskell.Extension
 
+import Data.List (stripPrefix)
 import qualified Data.Map as Map
+import Data.Monoid (All(..), Any(..), Endo(..), First(..), Last(..))
+import Data.Set (Set)
+import qualified Data.Set as Set
 
+normaliseGhcArgs :: Maybe Version -> PackageDescription -> [String] -> [String]
+normaliseGhcArgs (Just ghcVersion) PackageDescription{..} ghcArgs
+   | ghcVersion `withinRange` supportedGHCVersions
+   = argumentFilters . filter simpleFilters . filterRtsOpts $ ghcArgs
+  where
+    supportedGHCVersions :: VersionRange
+    supportedGHCVersions = intersectVersionRanges
+        (orLaterVersion (mkVersion [8,0]))
+        (earlierVersion (mkVersion [8,7]))
+
+    from :: Monoid m => [Int] -> m -> m
+    from version flags
+      | ghcVersion `withinRange` orLaterVersion (mkVersion version) = flags
+      | otherwise = mempty
+
+    to :: Monoid m => [Int] -> m -> m
+    to version flags
+      | ghcVersion `withinRange` earlierVersion (mkVersion version) = flags
+      | otherwise = mempty
+
+    checkGhcFlags :: forall m . Monoid m => ([String] -> m) -> m
+    checkGhcFlags fun = mconcat
+        [ fun ghcArgs
+        , checkComponentFlags libBuildInfo pkgLibs
+        , checkComponentFlags buildInfo executables
+        , checkComponentFlags testBuildInfo testSuites
+        , checkComponentFlags benchmarkBuildInfo benchmarks
+        ]
+      where
+        pkgLibs = maybeToList library ++ subLibraries
+
+        checkComponentFlags :: (a -> BuildInfo) -> [a] -> m
+        checkComponentFlags getInfo = foldMap (checkComponent . getInfo)
+          where
+            checkComponent :: BuildInfo -> m
+            checkComponent = foldMap fun . filterGhcOptions . allGhcOptions
+
+            allGhcOptions :: BuildInfo -> [(CompilerFlavor, [String])]
+            allGhcOptions =
+                mconcat [options, profOptions, sharedOptions, staticOptions]
+
+            filterGhcOptions :: [(CompilerFlavor, [String])] -> [[String]]
+            filterGhcOptions l = [opts | (GHC, opts) <- l]
+
+    safeToFilterWarnings :: Bool
+    safeToFilterWarnings = getAll $ checkGhcFlags checkWarnings
+      where
+        checkWarnings :: [String] -> All
+        checkWarnings = All . Set.null . foldr alter Set.empty
+
+        alter :: String -> Set String -> Set String
+        alter flag = appEndo $ mconcat
+            [ \s -> Endo $ if s == "-Werror" then Set.insert s else id
+            , \s -> Endo $ if s == "-Wwarn" then const Set.empty else id
+            , \s -> from [8,6] . Endo $
+                    if s == "-Werror=compat"
+                    then Set.union compatWarningSet else id
+            , \s -> from [8,6] . Endo $
+                    if s == "-Wno-error=compat"
+                    then (`Set.difference` compatWarningSet) else id
+            , \s -> from [8,6] . Endo $
+                    if s == "-Wwarn=compat"
+                    then (`Set.difference` compatWarningSet) else id
+            , from [8,4] $ markFlag "-Werror=" Set.insert
+            , from [8,4] $ markFlag "-Wwarn=" Set.delete
+            , from [8,4] $ markFlag "-Wno-error=" Set.delete
+            ] flag
+
+        markFlag
+            :: String
+            -> (String -> Set String -> Set String)
+            -> String
+            -> Endo (Set String)
+        markFlag name update flag = Endo $ case stripPrefix name flag of
+            Just rest | not (null rest) && rest /= "compat" -> update rest
+            _ -> id
+
+    flagArgumentFilter :: [String] -> [String] -> [String]
+    flagArgumentFilter flags = go
+      where
+        makeFilter :: String -> String -> First ([String] -> [String])
+        makeFilter flag arg = First $ filterRest <$> stripPrefix flag arg
+          where
+            filterRest leftOver = case dropEq leftOver of
+                [] -> drop 1
+                _ -> id
+
+        checkFilter :: String -> Maybe ([String] -> [String])
+        checkFilter = getFirst . mconcat (map makeFilter flags)
+
+        go :: [String] -> [String]
+        go [] = []
+        go (arg:args) = case checkFilter arg of
+            Just f -> go (f args)
+            Nothing -> arg : go args
+
+    argumentFilters :: [String] -> [String]
+    argumentFilters = flagArgumentFilter
+        ["-ghci-script", "-H", "-interactive-print"]
+
+    filterRtsOpts :: [String] -> [String]
+    filterRtsOpts = go False
+      where
+        go :: Bool -> [String] -> [String]
+        go _ [] = []
+        go _ ("+RTS":opts) = go True opts
+        go _ ("-RTS":opts) = go False opts
+        go isRTSopts (opt:opts) = addOpt $ go isRTSopts opts
+          where
+            addOpt | isRTSopts = id
+                   | otherwise = (opt:)
+
+    simpleFilters :: String -> Bool
+    simpleFilters = not . getAny . mconcat
+      [ flagIn simpleFlags
+      , Any . isPrefixOf "-ddump-"
+      , Any . isPrefixOf "-dsuppress-"
+      , Any . isPrefixOf "-dno-suppress-"
+      , flagIn $ invertibleFlagSet "-" ["ignore-dot-ghci"]
+      , flagIn . invertibleFlagSet "-f" . mconcat $
+            [ [ "reverse-errors", "warn-unused-binds", "break-on-error"
+              , "break-on-exception", "print-bind-result"
+              , "print-bind-contents", "print-evld-with-show"
+              , "implicit-import-qualified", "error-spans"
+              ]
+            , from [8,2]
+                [ "diagnostics-show-caret", "local-ghci-history"
+                , "show-warning-groups", "hide-source-paths"
+                , "show-hole-constraints"
+                ]
+            , from [8,4] ["show-loaded-modules"]
+            , from [8,6] [ "ghci-leak-check", "no-it" ]
+            ]
+      , flagIn . invertibleFlagSet "-d" $ [ "ppr-case-as-let", "ppr-ticks" ]
+      , isOptIntFlag
+      , isIntFlag
+      , if safeToFilterWarnings
+           then isWarning <> (Any . ("-w"==))
+           else mempty
+      , from [8,6] $
+        if safeToFilterHoles
+           then isTypedHoleFlag
+           else mempty
+      ]
+
+    flagIn :: Set String -> String -> Any
+    flagIn set flag = Any $ Set.member flag set
+
+    isWarning :: String -> Any
+    isWarning = mconcat $ map ((Any .) . isPrefixOf)
+        ["-fwarn-", "-fno-warn-", "-W", "-Wno-"]
+
+    simpleFlags :: Set String
+    simpleFlags = Set.fromList . mconcat $
+      [ [ "-n", "-#include", "-Rghc-timing", "-dsuppress-all", "-dstg-stats"
+        , "-dth-dec-file", "-dsource-stats", "-dverbose-core2core"
+        , "-dverbose-stg2stg", "-dcore-lint", "-dstg-lint", "-dcmm-lint"
+        , "-dasm-lint", "-dannot-lint", "-dshow-passes", "-dfaststring-stats"
+        , "-fno-max-relevant-binds", "-recomp", "-no-recomp", "-fforce-recomp"
+        , "-fno-force-recomp"
+        ]
+
+      , from [8,2]
+          [ "-fno-max-errors", "-fdiagnostics-color=auto"
+          , "-fdiagnostics-color=always", "-fdiagnostics-color=never"
+          , "-dppr-debug", "-dno-debug-output"
+          ]
+
+      , from [8,4] [ "-ddebug-output" ]
+      , from [8,4] $ to [8,6] [ "-fno-max-valid-substitutions" ]
+      , from [8,6] [ "-dhex-word-literals" ]
+      ]
+
+    isOptIntFlag :: String -> Any
+    isOptIntFlag = mconcat . map (dropIntFlag True) $ ["-v", "-j"]
+
+    isIntFlag :: String -> Any
+    isIntFlag = mconcat . map (dropIntFlag False) . mconcat $
+        [ [ "-fmax-relevant-binds", "-ddpr-user-length", "-ddpr-cols"
+          , "-dtrace-level", "-fghci-hist-size" ]
+        , from [8,2] ["-fmax-uncovered-patterns", "-fmax-errors"]
+        , from [8,4] $ to [8,6] ["-fmax-valid-substitutions"]
+        ]
+
+    dropIntFlag :: Bool -> String -> String -> Any
+    dropIntFlag isOpt flag input = Any $ case stripPrefix flag input of
+        Nothing -> False
+        Just rest | isOpt && null rest -> True
+                  | otherwise -> case parseInt rest of
+                        Just _ -> True
+                        Nothing -> False
+      where
+        parseInt :: String -> Maybe Int
+        parseInt = readMaybe . dropEq
+
+        readMaybe :: Read a => String -> Maybe a
+        readMaybe s = case reads s of
+            [(x, "")] -> Just x
+            _ -> Nothing
+
+    dropEq :: String -> String
+    dropEq ('=':s) = s
+    dropEq s = s
+
+    invertibleFlagSet :: String -> [String] -> Set String
+    invertibleFlagSet prefix flagNames =
+      Set.fromList $ (++) <$> [prefix, prefix ++ "no-"] <*> flagNames
+
+    compatWarningSet :: Set String
+    compatWarningSet = Set.fromList $ mconcat
+        [ from [8,6]
+            [ "missing-monadfail-instances", "semigroup"
+            , "noncanonical-monoid-instances", "implicit-kind-vars" ]
+        ]
+
+    safeToFilterHoles :: Bool
+    safeToFilterHoles = getAll . checkGhcFlags $ fromLast . foldMap notDeferred
+      where
+        fromLast :: Last All -> All
+        fromLast = fromMaybe (All True) . getLast
+
+        notDeferred :: String -> Last All
+        notDeferred "-fdefer-typed-holes" = Last . Just . All $ False
+        notDeferred "-fno-defer-typed-holes" = Last . Just . All $ True
+        notDeferred _ = Last Nothing
+
+    isTypedHoleFlag :: String -> Any
+    isTypedHoleFlag = mconcat
+        [ flagIn . invertibleFlagSet "-f" $
+            [ "show-hole-constraints", "show-valid-substitutions"
+            , "show-valid-hole-fits", "sort-valid-hole-fits"
+            , "sort-by-size-hole-fits", "sort-by-subsumption-hole-fits"
+            , "abstract-refinement-hole-fits", "show-provenance-of-hole-fits"
+            , "show-hole-matches-of-hole-fits", "show-type-of-hole-fits"
+            , "show-type-app-of-hole-fits", "show-type-app-vars-of-hole-fits"
+            , "unclutter-valid-hole-fits"
+            ]
+        , flagIn . Set.fromList $
+            [ "-fno-max-valid-hole-fits", "-fno-max-refinement-hole-fits"
+            , "-fno-refinement-level-hole-fits" ]
+        , mconcat . map (dropIntFlag False) $
+            [ "-fmax-valid-hole-fits", "-fmax-refinement-hole-fits"
+            , "-frefinement-level-hole-fits" ]
+        ]
+
+normaliseGhcArgs _ _ args = args
+
 -- | A structured set of GHC options/flags
 --
+-- Note that options containing lists fall into two categories:
+--
+--  * options that can be safely deduplicated, e.g. input modules or
+--    enabled extensions;
+--  * options that cannot be deduplicated in general without changing
+--    semantics, e.g. extra ghc options or linking options.
 data GhcOptions = GhcOptions {
 
   -- | The major mode for the ghc invocation.
@@ -48,11 +309,11 @@
 
   -- | Any extra options to pass directly to ghc. These go at the end and hence
   -- override other stuff.
-  ghcOptExtra         :: NubListR String,
+  ghcOptExtra         :: [String],
 
   -- | Extra default flags to pass directly to ghc. These go at the beginning
   -- and so can be overridden by other stuff.
-  ghcOptExtraDefault  :: NubListR String,
+  ghcOptExtraDefault  :: [String],
 
   -----------------------
   -- Inputs and outputs
@@ -71,7 +332,7 @@
   ghcOptOutputDynFile :: Flag FilePath,
 
   -- | Start with an empty search path for Haskell source files;
-  -- the @ghc -i@ flag (@-i@ on it's own with no path argument).
+  -- the @ghc -i@ flag (@-i@ on its own with no path argument).
   ghcOptSourcePathClear :: Flag Bool,
 
   -- | Search path for Haskell source files; the @ghc -i@ flag.
@@ -124,13 +385,13 @@
   -- Linker stuff
 
   -- | Names of libraries to link in; the @ghc -l@ flag.
-  ghcOptLinkLibs      :: NubListR FilePath,
+  ghcOptLinkLibs      :: [FilePath],
 
   -- | Search path for libraries to link in; the @ghc -L@ flag.
   ghcOptLinkLibPath  :: NubListR FilePath,
 
   -- | Options to pass through to the linker; the @ghc -optl@ flag.
-  ghcOptLinkOptions   :: NubListR String,
+  ghcOptLinkOptions   :: [String],
 
   -- | OSX only: frameworks to link in; the @ghc -framework@ flag.
   ghcOptLinkFrameworks :: NubListR String,
@@ -153,13 +414,13 @@
   -- C and CPP stuff
 
   -- | Options to pass through to the C compiler; the @ghc -optc@ flag.
-  ghcOptCcOptions     :: NubListR String,
+  ghcOptCcOptions     :: [String],
 
   -- | Options to pass through to the C++ compiler.
-  ghcOptCxxOptions     :: NubListR String,
+  ghcOptCxxOptions     :: [String],
 
   -- | Options to pass through to CPP; the @ghc -optP@ flag.
-  ghcOptCppOptions    :: NubListR String,
+  ghcOptCppOptions    :: [String],
 
   -- | Search path for CPP includes like header files; the @ghc -I@ flag.
   ghcOptCppIncludePath :: NubListR FilePath,
@@ -181,7 +442,7 @@
 
   -- | A GHC version-dependent mapping of extensions to flags. This must be
   -- set to be able to make use of the 'ghcOptExtensions'.
-  ghcOptExtensionMap    :: Map Extension String,
+  ghcOptExtensionMap    :: Map Extension (Maybe Compiler.Flag),
 
   ----------------
   -- Compilation
@@ -214,7 +475,7 @@
   -- GHCi
 
   -- | Extra GHCi startup scripts; the @-ghci-script@ flag
-  ghcOptGHCiScripts    :: NubListR FilePath,
+  ghcOptGHCiScripts    :: [FilePath],
 
   ------------------------
   -- Redirecting outputs
@@ -310,7 +571,7 @@
 --     Just GhcModeDepAnalysis -> ["-M"]
 --     Just GhcModeEvaluate    -> ["-e", expr]
 
-  , flags ghcOptExtraDefault
+  , ghcOptExtraDefault opts
 
   , [ "-no-link" | flagBool ghcOptNoLink ]
 
@@ -354,7 +615,7 @@
         | flagProfAuto implInfo -> ["-fprof-auto-exported"]
         | otherwise             -> ["-auto"]
 
-  , [ "-split-sections" | flagBool ghcOptSplitObjs ]
+  , [ "-split-sections" | flagBool ghcOptSplitSections ]
   , [ "-split-objs" | flagBool ghcOptSplitObjs ]
 
   , case flagToMaybe (ghcOptHPCDir opts) of
@@ -405,17 +666,17 @@
   -- CPP, C, and C++ stuff
 
   , [ "-I"    ++ dir | dir <- flags ghcOptCppIncludePath ]
-  , [ "-optP" ++ opt | opt <- flags ghcOptCppOptions ]
+  , [ "-optP" ++ opt | opt <- ghcOptCppOptions opts]
   , concat [ [ "-optP-include", "-optP" ++ inc]
            | inc <- flags ghcOptCppIncludes ]
-  , [ "-optc" ++ opt | opt <- flags ghcOptCcOptions ]
-  , [ "-optc" ++ opt | opt <- flags ghcOptCxxOptions ]
+  , [ "-optc" ++ opt | opt <- ghcOptCcOptions opts]
+  , [ "-optc" ++ opt | opt <- ghcOptCxxOptions opts]
 
   -----------------
   -- Linker stuff
 
-  , [ "-optl" ++ opt | opt <- flags ghcOptLinkOptions ]
-  , ["-l" ++ lib     | lib <- flags ghcOptLinkLibs ]
+  , [ "-optl" ++ opt | opt <- ghcOptLinkOptions opts]
+  , ["-l" ++ lib     | lib <- ghcOptLinkLibs opts]
   , ["-L" ++ dir     | dir <- flags ghcOptLinkLibPath ]
   , if isOSX
     then concat [ ["-framework", fmwk]
@@ -472,16 +733,20 @@
     then [ "-X" ++ display lang | lang <- flag ghcOptLanguage ]
     else []
 
-  , [ case Map.lookup ext (ghcOptExtensionMap opts) of
-        Just arg -> arg
-        Nothing  -> error $ "Distribution.Simple.Program.GHC.renderGhcOptions: "
-                          ++ display ext ++ " not present in ghcOptExtensionMap."
-    | ext <- flags ghcOptExtensions ]
+  , [ ext'
+    | ext  <- flags ghcOptExtensions
+    , ext' <- case Map.lookup ext (ghcOptExtensionMap opts) of
+        Just (Just arg) -> [arg]
+        Just Nothing    -> []
+        Nothing         ->
+            error $ "Distribution.Simple.Program.GHC.renderGhcOptions: "
+                  ++ display ext ++ " not present in ghcOptExtensionMap."
+    ]
 
   ----------------
   -- GHCi
 
-  , concat [ [ "-ghci-script", script ] | script <- flags  ghcOptGHCiScripts
+  , concat [ [ "-ghci-script", script ] | script <- ghcOptGHCiScripts opts
                                         , flagGhciScript implInfo ]
 
   ---------------
@@ -496,7 +761,7 @@
   ---------------
   -- Extra
 
-  , flags ghcOptExtra
+  , ghcOptExtra opts
 
   ]
 
diff --git a/cabal/Cabal/Distribution/Simple/Program/HcPkg.hs b/cabal/Cabal/Distribution/Simple/Program/HcPkg.hs
--- a/cabal/Cabal/Distribution/Simple/Program/HcPkg.hs
+++ b/cabal/Cabal/Distribution/Simple/Program/HcPkg.hs
@@ -10,7 +10,7 @@
 -- Portability :  portable
 --
 -- This module provides an library interface to the @hc-pkg@ program.
--- Currently only GHC, GHCJS and LHC have hc-pkg programs.
+-- Currently only GHC and GHCJS have hc-pkg programs.
 
 module Distribution.Simple.Program.HcPkg (
     -- * Types
@@ -46,7 +46,6 @@
 import Distribution.Compat.Prelude hiding (init)
 
 import Distribution.InstalledPackageInfo
-import Distribution.ParseUtils
 import Distribution.Simple.Compiler
 import Distribution.Simple.Program.Types
 import Distribution.Simple.Program.Run
@@ -259,16 +258,13 @@
 
 parsePackages :: String -> Either [InstalledPackageInfo] [PError]
 parsePackages str =
-  let parsed = map parseInstalledPackageInfo' (splitPkgs str)
+  let parsed = map parseInstalledPackageInfo (splitPkgs str)
    in case [ msg | ParseFailed msg <- parsed ] of
         []   -> Left [   setUnitId
                        . maybe id mungePackagePaths (pkgRoot pkg)
                        $ pkg
                      | ParseOk _ pkg <- parsed ]
         msgs -> Right msgs
-  where
-    parseInstalledPackageInfo' =
-      parseFieldsFlat fieldsInstalledPackageInfo emptyInstalledPackageInfo
 
 --TODO: this could be a lot faster. We're doing normaliseLineEndings twice
 -- and converting back and forth with lines/unlines.
@@ -295,6 +291,7 @@
       importDirs        = mungePaths (importDirs  pkginfo),
       includeDirs       = mungePaths (includeDirs pkginfo),
       libraryDirs       = mungePaths (libraryDirs pkginfo),
+      libraryDynDirs    = mungePaths (libraryDynDirs pkginfo),
       frameworkDirs     = mungePaths (frameworkDirs pkginfo),
       haddockInterfaces = mungePaths (haddockInterfaces pkginfo),
       haddockHTMLs      = mungeUrls  (haddockHTMLs pkginfo)
@@ -496,4 +493,3 @@
   | v >= deafening = ["-v2"]
   | v == silent    = ["-v0"]
   | otherwise      = []
-
diff --git a/cabal/Cabal/Distribution/Simple/Program/Types.hs b/cabal/Cabal/Distribution/Simple/Program/Types.hs
--- a/cabal/Cabal/Distribution/Simple/Program/Types.hs
+++ b/cabal/Cabal/Distribution/Simple/Program/Types.hs
@@ -38,6 +38,7 @@
 import Prelude ()
 import Distribution.Compat.Prelude
 
+import Distribution.PackageDescription
 import Distribution.Simple.Program.Find
 import Distribution.Version
 import Distribution.Verbosity
@@ -74,10 +75,14 @@
        -- | A function to do any additional configuration after we have
        -- located the program (and perhaps identified its version). For example
        -- it could add args, or environment vars.
-       programPostConf :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram
+       programPostConf :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram,
+       -- | A function that filters any arguments that don't impact the output
+       -- from a commandline. Used to limit the volatility of dependency hashes
+       -- when using new-build.
+       programNormaliseArgs :: Maybe Version -> PackageDescription -> [String] -> [String]
      }
 instance Show Program where
-  show (Program name _ _ _) = "Program: " ++ name
+  show (Program name _ _ _ _) = "Program: " ++ name
 
 type ProgArg = String
 
@@ -161,7 +166,8 @@
     programName         = name,
     programFindLocation = \v p -> findProgramOnSearchPath v p name,
     programFindVersion  = \_ _ -> return Nothing,
-    programPostConf     = \_ p -> return p
+    programPostConf     = \_ p -> return p,
+    programNormaliseArgs   = \_ _ -> id
   }
 
 -- | Make a simple 'ConfiguredProgram'.
diff --git a/cabal/Cabal/Distribution/Simple/Register.hs b/cabal/Cabal/Distribution/Simple/Register.hs
--- a/cabal/Cabal/Distribution/Simple/Register.hs
+++ b/cabal/Cabal/Distribution/Simple/Register.hs
@@ -61,7 +61,6 @@
 
 import qualified Distribution.Simple.GHC   as GHC
 import qualified Distribution.Simple.GHCJS as GHCJS
-import qualified Distribution.Simple.LHC   as LHC
 import qualified Distribution.Simple.UHC   as UHC
 import qualified Distribution.Simple.HaskellSuite as HaskellSuite
 import qualified Distribution.Simple.PackageIndex as Index
@@ -74,6 +73,7 @@
 import Distribution.Simple.Setup
 import Distribution.PackageDescription
 import Distribution.Package
+import Distribution.License (licenseToSPDX, licenseFromSPDX)
 import qualified Distribution.InstalledPackageInfo as IPI
 import Distribution.InstalledPackageInfo (InstalledPackageInfo)
 import Distribution.Simple.Utils
@@ -206,7 +206,6 @@
 
     writeRegisterScript =
       case compilerFlavor (compiler lbi) of
-        JHC -> notice verbosity "Registration scripts not needed for jhc"
         UHC -> notice verbosity "Registration scripts not needed for uhc"
         _   -> withHcPkg verbosity
                "Registration scripts are not implemented for this compiler"
@@ -256,7 +255,7 @@
         -> IO AbiHash
 abiHash verbosity pkg distPref lbi lib clbi =
     case compilerFlavor comp of
-     GHC | compilerVersion comp >= mkVersion [6,11] -> do
+     GHC -> do
             fmap mkAbiHash $ GHC.libAbiHash verbosity pkg lbi' lib clbi
      GHCJS -> do
             fmap mkAbiHash $ GHCJS.libAbiHash verbosity pkg lbi' lib clbi
@@ -296,7 +295,6 @@
     case compilerFlavor comp of
       GHC   -> HcPkg.init (GHC.hcPkgInfo   progdb) verbosity preferCompat dbPath
       GHCJS -> HcPkg.init (GHCJS.hcPkgInfo progdb) verbosity False dbPath
-      LHC   -> HcPkg.init (LHC.hcPkgInfo   progdb) verbosity False dbPath
       UHC   -> return ()
       HaskellSuite _ -> HaskellSuite.initPackageDB verbosity progdb dbPath
       _              -> die' verbosity $
@@ -334,7 +332,6 @@
   case compilerFlavor comp of
     GHC   -> f (GHC.hcPkgInfo progdb)
     GHCJS -> f (GHCJS.hcPkgInfo progdb)
-    LHC   -> f (LHC.hcPkgInfo progdb)
     _     -> die' verbosity ("Distribution.Simple.Register." ++ name ++ ":\
                   \not implemented for this compiler")
 
@@ -349,13 +346,11 @@
   case compilerFlavor comp of
     GHC   -> GHC.registerPackage   verbosity progdb packageDbs installedPkgInfo registerOptions
     GHCJS -> GHCJS.registerPackage verbosity progdb packageDbs installedPkgInfo registerOptions
+    HaskellSuite {} ->
+      HaskellSuite.registerPackage verbosity      progdb packageDbs installedPkgInfo
     _ | HcPkg.registerMultiInstance registerOptions
           -> die' verbosity "Registering multiple package instances is not yet supported for this compiler"
-    LHC   -> LHC.registerPackage   verbosity      progdb packageDbs installedPkgInfo registerOptions
     UHC   -> UHC.registerPackage   verbosity comp progdb packageDbs installedPkgInfo
-    JHC   -> notice verbosity "Registering for jhc (nothing to do)"
-    HaskellSuite {} ->
-      HaskellSuite.registerPackage verbosity      progdb packageDbs installedPkgInfo
     _    -> die' verbosity "Registering is not implemented for this compiler"
 
 writeHcPkgRegisterScript :: Verbosity
@@ -407,7 +402,11 @@
     IPI.instantiatedWith   = componentInstantiatedWith clbi,
     IPI.sourceLibName      = libName lib,
     IPI.compatPackageKey   = componentCompatPackageKey clbi,
-    IPI.license            = license     pkg,
+    -- If GHC >= 8.4 we register with SDPX, otherwise with legacy license
+    IPI.license            =
+        if ghc84
+        then Left $ either id licenseToSPDX $ licenseRaw pkg
+        else Right $ either licenseFromSPDX id $ licenseRaw pkg,
     IPI.copyright          = copyright   pkg,
     IPI.maintainer         = maintainer  pkg,
     IPI.author             = author      pkg,
@@ -438,10 +437,11 @@
     IPI.includeDirs        = absinc ++ adjustRelIncDirs relinc,
     IPI.includes           = includes bi,
     IPI.depends            = depends,
-    IPI.abiDepends         = abi_depends,
+    IPI.abiDepends         = [], -- due to #5465
     IPI.ccOptions          = [], -- Note. NOT ccOptions bi!
                                  -- We don't want cc-options to be propagated
                                  -- to C compilations in other packages.
+    IPI.cxxOptions         = [], -- Also. NOT cxxOptions bi!
     IPI.ldOptions          = ldOptions bi,
     IPI.frameworks         = frameworks bi,
     IPI.frameworkDirs      = extraFrameworkDirs bi,
@@ -450,17 +450,14 @@
     IPI.pkgRoot            = Nothing
   }
   where
+    ghc84 = case compilerId $ compiler lbi of
+        CompilerId GHC v -> v >= mkVersion [8, 4]
+        _                -> False
+
     bi = libBuildInfo lib
     --TODO: unclear what the root cause of the
     -- duplication is, but we nub it here for now:
     depends = ordNub $ map fst (componentPackageDeps clbi)
-    abi_depends = map add_abi depends
-    add_abi uid = IPI.AbiDependency uid abi
-      where
-        abi = case Index.lookupUnitId (installedPkgs lbi) uid of
-                Nothing -> error $
-                  "generalInstalledPackageInfo: missing IPI for " ++ display uid
-                Just ipi -> IPI.abiHash ipi
     (absinc, relinc) = partition isAbsolute (includeDirs bi)
     hasModules = not $ null (allLibModules lib clbi)
     comp = compiler lbi
diff --git a/cabal/Cabal/Distribution/Simple/Setup.hs b/cabal/Cabal/Distribution/Simple/Setup.hs
--- a/cabal/Cabal/Distribution/Simple/Setup.hs
+++ b/cabal/Cabal/Distribution/Simple/Setup.hs
@@ -61,6 +61,8 @@
   buildOptions, haddockOptions, installDirsOptions,
   programDbOptions, programDbPaths',
   programConfigurationOptions, programConfigurationPaths',
+  programFlagsDescription,
+  replOptions,
   splitArgs,
 
   defaultDistPref, optionDistPref,
@@ -85,7 +87,7 @@
 import Distribution.Parsec.Class
 import Distribution.Pretty
 import qualified Distribution.Compat.ReadP as Parse
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import Distribution.ParseUtils (readPToMaybe)
 import qualified Text.PrettyPrint as Disp
 import Distribution.ModuleName
@@ -93,6 +95,7 @@
 import Distribution.Simple.Command hiding (boolOpt, boolOpt')
 import qualified Distribution.Simple.Command as Command
 import Distribution.Simple.Compiler hiding (Flag)
+import Distribution.Simple.Flag
 import Distribution.Simple.Utils
 import Distribution.Simple.Program
 import Distribution.Simple.InstallDirs
@@ -113,94 +116,6 @@
 defaultDistPref = "dist"
 
 -- ------------------------------------------------------------
--- * Flag type
--- ------------------------------------------------------------
-
--- | All flags are monoids, they come in two flavours:
---
--- 1. list flags eg
---
--- > --ghc-option=foo --ghc-option=bar
---
--- gives us all the values ["foo", "bar"]
---
--- 2. singular value flags, eg:
---
--- > --enable-foo --disable-foo
---
--- gives us Just False
--- So this Flag type is for the latter singular kind of flag.
--- Its monoid instance gives us the behaviour where it starts out as
--- 'NoFlag' and later flags override earlier ones.
---
-data Flag a = Flag a | NoFlag deriving (Eq, Generic, Show, Read)
-
-instance Binary a => Binary (Flag a)
-
-instance Functor Flag where
-  fmap f (Flag x) = Flag (f x)
-  fmap _ NoFlag  = NoFlag
-
-instance Monoid (Flag a) where
-  mempty = NoFlag
-  mappend = (<>)
-
-instance Semigroup (Flag a) where
-  _ <> f@(Flag _) = f
-  f <> NoFlag     = f
-
-instance Bounded a => Bounded (Flag a) where
-  minBound = toFlag minBound
-  maxBound = toFlag maxBound
-
-instance Enum a => Enum (Flag a) where
-  fromEnum = fromEnum . fromFlag
-  toEnum   = toFlag   . toEnum
-  enumFrom (Flag a) = map toFlag . enumFrom $ a
-  enumFrom _        = []
-  enumFromThen (Flag a) (Flag b) = toFlag `map` enumFromThen a b
-  enumFromThen _        _        = []
-  enumFromTo   (Flag a) (Flag b) = toFlag `map` enumFromTo a b
-  enumFromTo   _        _        = []
-  enumFromThenTo (Flag a) (Flag b) (Flag c) = toFlag `map` enumFromThenTo a b c
-  enumFromThenTo _        _        _        = []
-
-toFlag :: a -> Flag a
-toFlag = Flag
-
-fromFlag :: WithCallStack (Flag a -> a)
-fromFlag (Flag x) = x
-fromFlag NoFlag   = error "fromFlag NoFlag. Use fromFlagOrDefault"
-
-fromFlagOrDefault :: a -> Flag a -> a
-fromFlagOrDefault _   (Flag x) = x
-fromFlagOrDefault def NoFlag   = def
-
-flagToMaybe :: Flag a -> Maybe a
-flagToMaybe (Flag x) = Just x
-flagToMaybe NoFlag   = Nothing
-
-flagToList :: Flag a -> [a]
-flagToList (Flag x) = [x]
-flagToList NoFlag   = []
-
-allFlags :: [Flag Bool] -> Flag Bool
-allFlags flags = if all (\f -> fromFlagOrDefault False f) flags
-                 then Flag True
-                 else NoFlag
-
-maybeToFlag :: Maybe a -> Flag a
-maybeToFlag Nothing  = NoFlag
-maybeToFlag (Just x) = Flag x
-
--- | Types that represent boolean flags.
-class BooleanFlag a where
-    asBool :: a -> Bool
-
-instance BooleanFlag Bool where
-  asBool = id
-
--- ------------------------------------------------------------
 -- * Global flags
 -- ------------------------------------------------------------
 
@@ -296,8 +211,7 @@
     configProgramArgs   :: [(String, [String])], -- ^user specified programs args
     configProgramPathExtra :: NubList FilePath,  -- ^Extend the $PATH
     configHcFlavor      :: Flag CompilerFlavor, -- ^The \"flavor\" of the
-                                                -- compiler, such as GHC or
-                                                -- JHC.
+                                                -- compiler, e.g. GHC.
     configHcPath        :: Flag FilePath, -- ^given compiler location
     configHcPkg         :: Flag FilePath, -- ^given hc-pkg location
     configVanillaLib    :: Flag Bool,     -- ^Enable vanilla library
@@ -522,8 +436,6 @@
          configHcFlavor (\v flags -> flags { configHcFlavor = v })
          (choiceOpt [ (Flag GHC,   ("g", ["ghc"]),   "compile with GHC")
                     , (Flag GHCJS, ([] , ["ghcjs"]), "compile with GHCJS")
-                    , (Flag JHC,   ([] , ["jhc"]),   "compile with JHC")
-                    , (Flag LHC,   ([] , ["lhc"]),   "compile with LHC")
                     , (Flag UHC,   ([] , ["uhc"]),   "compile with UHC")
                     -- "haskell-suite" compiler id string will be replaced
                     -- by a more specific one during the configure stage
@@ -576,7 +488,7 @@
          "Static library"
          configStaticLib (\v flags -> flags { configStaticLib = v })
          (boolOpt [] [])
-      
+
       ,option "" ["executable-dynamic"]
          "Executable dynamic linking"
          configDynExe (\v flags -> flags { configDynExe = v })
@@ -919,7 +831,8 @@
     -- This is the same hack as in 'buildArgs'.  But I (ezyang) don't
     -- think it's a hack, it's the right way to make hooks more robust
     -- TODO: Stop using this eventually when 'UserHooks' gets changed
-    copyArgs :: [String]
+    copyArgs :: [String],
+    copyCabalFilePath :: Flag FilePath
   }
   deriving (Show, Generic)
 
@@ -928,7 +841,8 @@
     copyDest      = Flag NoCopyDest,
     copyDistPref  = NoFlag,
     copyVerbosity = Flag normal,
-    copyArgs      = []
+    copyArgs      = [],
+    copyCabalFilePath = mempty
   }
 
 copyCommand :: CommandUI CopyFlags
@@ -936,35 +850,52 @@
   { commandName         = "copy"
   , commandSynopsis     = "Copy the files of all/specific components to install locations."
   , commandDescription  = Just $ \_ -> wrapText $
-          "Components encompass executables and libraries."
+          "Components encompass executables and libraries. "
        ++ "Does not call register, and allows a prefix at install time. "
        ++ "Without the --destdir flag, configure determines location.\n"
   , commandNotes        = Just $ \pname ->
        "Examples:\n"
-        ++ "  " ++ pname ++ " build           "
+        ++ "  " ++ pname ++ " copy           "
         ++ "    All the components in the package\n"
-        ++ "  " ++ pname ++ " build foo       "
+        ++ "  " ++ pname ++ " copy foo       "
         ++ "    A component (i.e. lib, exe, test suite)"
   , commandUsage        = usageAlternatives "copy" $
       [ "[FLAGS]"
       , "COMPONENTS [FLAGS]"
       ]
   , commandDefaultFlags = defaultCopyFlags
-  , commandOptions      = \showOrParseArgs ->
-      [optionVerbosity copyVerbosity (\v flags -> flags { copyVerbosity = v })
+  , commandOptions      = \showOrParseArgs -> case showOrParseArgs of
+      ShowArgs -> filter ((`notElem` ["target-package-db"])
+                          . optionName) $ copyOptions ShowArgs
+      ParseArgs -> copyOptions ParseArgs
+}
 
-      ,optionDistPref
-         copyDistPref (\d flags -> flags { copyDistPref = d })
-         showOrParseArgs
+copyOptions ::  ShowOrParseArgs -> [OptionField CopyFlags]
+copyOptions showOrParseArgs =
+  [optionVerbosity copyVerbosity (\v flags -> flags { copyVerbosity = v })
 
-      ,option "" ["destdir"]
-         "directory to copy files to, prepended to installation directories"
-         copyDest (\v flags -> flags { copyDest = v })
-         (reqArg "DIR" (succeedReadE (Flag . CopyTo))
-                       (\f -> case f of Flag (CopyTo p) -> [p]; _ -> []))
-      ]
-  }
+  ,optionDistPref
+    copyDistPref (\d flags -> flags { copyDistPref = d })
+    showOrParseArgs
 
+  ,option "" ["destdir"]
+    "directory to copy files to, prepended to installation directories"
+    copyDest (\v flags -> case copyDest flags of
+                 Flag (CopyToDb _) -> error "Use either 'destdir' or 'target-package-db'."
+                 _ -> flags { copyDest = v })
+    (reqArg "DIR" (succeedReadE (Flag . CopyTo))
+      (\f -> case f of Flag (CopyTo p) -> [p]; _ -> []))
+
+  ,option "" ["target-package-db"]
+    "package database to copy files into. Required when using ${pkgroot} prefix."
+    copyDest (\v flags -> case copyDest flags of
+                 NoFlag -> flags { copyDest = v }
+                 Flag NoCopyDest -> flags { copyDest = v }
+                 _ -> error "Use either 'destdir' or 'target-package-db'.")
+    (reqArg "DATABASE" (succeedReadE (Flag . CopyToDb))
+      (\f -> case f of Flag (CopyToDb p) -> [p]; _ -> []))
+  ]
+
 emptyCopyFlags :: CopyFlags
 emptyCopyFlags = mempty
 
@@ -982,20 +913,26 @@
 -- | Flags to @install@: (package db, verbosity)
 data InstallFlags = InstallFlags {
     installPackageDB :: Flag PackageDB,
+    installDest      :: Flag CopyDest,
     installDistPref  :: Flag FilePath,
     installUseWrapper :: Flag Bool,
     installInPlace    :: Flag Bool,
-    installVerbosity :: Flag Verbosity
+    installVerbosity :: Flag Verbosity,
+    -- this is only here, because we can not
+    -- change the hooks API.
+    installCabalFilePath :: Flag FilePath
   }
   deriving (Show, Generic)
 
 defaultInstallFlags :: InstallFlags
 defaultInstallFlags  = InstallFlags {
     installPackageDB = NoFlag,
+    installDest      = Flag NoCopyDest,
     installDistPref  = NoFlag,
     installUseWrapper = Flag False,
     installInPlace    = Flag False,
-    installVerbosity = Flag normal
+    installVerbosity = Flag normal,
+    installCabalFilePath = mempty
   }
 
 installCommand :: CommandUI InstallFlags
@@ -1011,31 +948,42 @@
   , commandUsage        = \pname ->
       "Usage: " ++ pname ++ " install [FLAGS]\n"
   , commandDefaultFlags = defaultInstallFlags
-  , commandOptions      = \showOrParseArgs ->
-      [optionVerbosity installVerbosity (\v flags -> flags { installVerbosity = v })
-      ,optionDistPref
-         installDistPref (\d flags -> flags { installDistPref = d })
-         showOrParseArgs
+  , commandOptions      = \showOrParseArgs -> case showOrParseArgs of
+      ShowArgs -> filter ((`notElem` ["target-package-db"])
+                          . optionName) $ installOptions ShowArgs
+      ParseArgs -> installOptions ParseArgs
+  }
 
-      ,option "" ["inplace"]
-         "install the package in the install subdirectory of the dist prefix, so it can be used without being installed"
-         installInPlace (\v flags -> flags { installInPlace = v })
-         trueArg
+installOptions ::  ShowOrParseArgs -> [OptionField InstallFlags]
+installOptions showOrParseArgs =
+  [optionVerbosity installVerbosity (\v flags -> flags { installVerbosity = v })
+  ,optionDistPref
+    installDistPref (\d flags -> flags { installDistPref = d })
+    showOrParseArgs
 
-      ,option "" ["shell-wrappers"]
-         "using shell script wrappers around executables"
-         installUseWrapper (\v flags -> flags { installUseWrapper = v })
-         (boolOpt [] [])
+  ,option "" ["inplace"]
+    "install the package in the install subdirectory of the dist prefix, so it can be used without being installed"
+    installInPlace (\v flags -> flags { installInPlace = v })
+    trueArg
 
-      ,option "" ["package-db"] ""
-         installPackageDB (\v flags -> flags { installPackageDB = v })
-         (choiceOpt [ (Flag UserPackageDB, ([],["user"]),
-                      "upon configuration register this package in the user's local package database")
-                    , (Flag GlobalPackageDB, ([],["global"]),
-                      "(default) upon configuration register this package in the system-wide package database")])
-      ]
-  }
+  ,option "" ["shell-wrappers"]
+    "using shell script wrappers around executables"
+    installUseWrapper (\v flags -> flags { installUseWrapper = v })
+    (boolOpt [] [])
 
+  ,option "" ["package-db"] ""
+    installPackageDB (\v flags -> flags { installPackageDB = v })
+    (choiceOpt [ (Flag UserPackageDB, ([],["user"]),
+                   "upon configuration register this package in the user's local package database")
+               , (Flag GlobalPackageDB, ([],["global"]),
+                   "(default) upon configuration register this package in the system-wide package database")])
+  ,option "" ["target-package-db"]
+    "package database to install into. Required when using ${pkgroot} prefix."
+    installDest (\v flags -> flags { installDest = v })
+    (reqArg "DATABASE" (succeedReadE (Flag . CopyToDb))
+      (\f -> case f of Flag (CopyToDb p) -> [p]; _ -> []))
+  ]
+
 emptyInstallFlags :: InstallFlags
 emptyInstallFlags = mempty
 
@@ -1128,7 +1076,8 @@
     regPrintId     :: Flag Bool,
     regVerbosity   :: Flag Verbosity,
     -- Same as in 'buildArgs' and 'copyArgs'
-    regArgs        :: [String]
+    regArgs        :: [String],
+    regCabalFilePath :: Flag FilePath
   }
   deriving (Show, Generic)
 
@@ -1141,6 +1090,7 @@
     regDistPref    = NoFlag,
     regPrintId     = Flag False,
     regArgs        = [],
+    regCabalFilePath = mempty,
     regVerbosity   = Flag normal
   }
 
@@ -1240,8 +1190,9 @@
     hscolourBenchmarks  :: Flag Bool,
     hscolourForeignLibs :: Flag Bool,
     hscolourDistPref    :: Flag FilePath,
-    hscolourVerbosity   :: Flag Verbosity
-  }
+    hscolourVerbosity   :: Flag Verbosity,
+    hscolourCabalFilePath :: Flag FilePath
+    }
   deriving (Show, Generic)
 
 emptyHscolourFlags :: HscolourFlags
@@ -1255,7 +1206,8 @@
     hscolourBenchmarks  = Flag False,
     hscolourDistPref    = NoFlag,
     hscolourForeignLibs = Flag False,
-    hscolourVerbosity   = Flag normal
+    hscolourVerbosity   = Flag normal,
+    hscolourCabalFilePath = mempty
   }
 
 instance Monoid HscolourFlags where
@@ -1271,7 +1223,8 @@
   , commandSynopsis     =
       "Generate HsColour colourised code, in HTML format."
   , commandDescription  = Just (\_ -> "Requires the hscolour program.\n")
-  , commandNotes        = Nothing
+  , commandNotes        = Just $ \_ ->
+      "Deprecated in favour of 'cabal haddock --hyperlink-source'."
   , commandUsage        = \pname ->
       "Usage: " ++ pname ++ " hscolour [FLAGS]\n"
   , commandDefaultFlags = defaultHscolourFlags
@@ -1425,12 +1378,15 @@
     haddockForeignLibs  :: Flag Bool,
     haddockInternal     :: Flag Bool,
     haddockCss          :: Flag FilePath,
-    haddockHscolour     :: Flag Bool,
+    haddockLinkedSource :: Flag Bool,
+    haddockQuickJump    :: Flag Bool,
     haddockHscolourCss  :: Flag FilePath,
     haddockContents     :: Flag PathTemplate,
     haddockDistPref     :: Flag FilePath,
     haddockKeepTempFiles:: Flag Bool,
-    haddockVerbosity    :: Flag Verbosity
+    haddockVerbosity    :: Flag Verbosity,
+    haddockCabalFilePath :: Flag FilePath,
+    haddockArgs         :: [String]
   }
   deriving (Show, Generic)
 
@@ -1448,12 +1404,15 @@
     haddockForeignLibs  = Flag False,
     haddockInternal     = Flag False,
     haddockCss          = NoFlag,
-    haddockHscolour     = Flag False,
+    haddockLinkedSource = Flag False,
+    haddockQuickJump    = Flag False,
     haddockHscolourCss  = NoFlag,
     haddockContents     = NoFlag,
     haddockDistPref     = NoFlag,
     haddockKeepTempFiles= Flag False,
-    haddockVerbosity    = Flag normal
+    haddockVerbosity    = Flag normal,
+    haddockCabalFilePath = mempty,
+    haddockArgs         = mempty
   }
 
 haddockCommand :: CommandUI HaddockFlags
@@ -1463,8 +1422,10 @@
   , commandDescription  = Just $ \_ ->
       "Requires the program haddock, version 2.x.\n"
   , commandNotes        = Nothing
-  , commandUsage        = \pname ->
-      "Usage: " ++ pname ++ " haddock [FLAGS]\n"
+  , commandUsage        = usageAlternatives "haddock" $
+      [ "[FLAGS]"
+      , "COMPONENTS [FLAGS]"
+      ]
   , commandDefaultFlags = defaultHaddockFlags
   , commandOptions      = \showOrParseArgs ->
          haddockOptions showOrParseArgs
@@ -1557,11 +1518,16 @@
    haddockCss (\v flags -> flags { haddockCss = v })
    (reqArgFlag "PATH")
 
-  ,option "" ["hyperlink-source","hyperlink-sources"]
-   "Hyperlink the documentation to the source code (using HsColour)"
-   haddockHscolour (\v flags -> flags { haddockHscolour = v })
+  ,option "" ["hyperlink-source","hyperlink-sources","hyperlinked-source"]
+   "Hyperlink the documentation to the source code"
+   haddockLinkedSource (\v flags -> flags { haddockLinkedSource = v })
    trueArg
 
+  ,option "" ["quickjump"]
+   "Generate an index for interactive documentation navigation"
+   haddockQuickJump (\v flags -> flags { haddockQuickJump = v })
+   trueArg
+
   ,option "" ["hscolour-css"]
    "Use PATH as the HsColour stylesheet"
    haddockHscolourCss (\v flags -> flags { haddockHscolourCss = v })
@@ -1592,7 +1558,8 @@
 data CleanFlags = CleanFlags {
     cleanSaveConf  :: Flag Bool,
     cleanDistPref  :: Flag FilePath,
-    cleanVerbosity :: Flag Verbosity
+    cleanVerbosity :: Flag Verbosity,
+    cleanCabalFilePath :: Flag FilePath
   }
   deriving (Show, Generic)
 
@@ -1600,7 +1567,8 @@
 defaultCleanFlags  = CleanFlags {
     cleanSaveConf  = Flag False,
     cleanDistPref  = NoFlag,
-    cleanVerbosity = Flag normal
+    cleanVerbosity = Flag normal,
+    cleanCabalFilePath = mempty
   }
 
 cleanCommand :: CommandUI CleanFlags
@@ -1648,7 +1616,8 @@
     buildNumJobs     :: Flag (Maybe Int),
     -- TODO: this one should not be here, it's just that the silly
     -- UserHooks stop us from passing extra info in other ways
-    buildArgs :: [String]
+    buildArgs :: [String],
+    buildCabalFilePath :: Flag FilePath
   }
   deriving (Read, Show, Generic)
 
@@ -1663,7 +1632,8 @@
     buildDistPref    = mempty,
     buildVerbosity   = Flag normal,
     buildNumJobs     = mempty,
-    buildArgs        = []
+    buildArgs        = [],
+    buildCabalFilePath = mempty
   }
 
 buildCommand :: ProgramDb -> CommandUI BuildFlags
@@ -1740,7 +1710,8 @@
     replProgramArgs :: [(String, [String])],
     replDistPref    :: Flag FilePath,
     replVerbosity   :: Flag Verbosity,
-    replReload      :: Flag Bool
+    replReload      :: Flag Bool,
+    replReplOptions :: [String]
   }
   deriving (Show, Generic)
 
@@ -1750,7 +1721,8 @@
     replProgramArgs = [],
     replDistPref    = NoFlag,
     replVerbosity   = Flag normal,
-    replReload      = Flag False
+    replReload      = Flag False,
+    replReplOptions = []
   }
 
 instance Monoid ReplFlags where
@@ -1790,7 +1762,7 @@
       ++ "    The first component in the package\n"
       ++ "  " ++ pname ++ " repl foo       "
       ++ "    A named component (i.e. lib, exe, test suite)\n"
-      ++ "  " ++ pname ++ " repl --ghc-options=\"-lstdc++\""
+      ++ "  " ++ pname ++ " repl --repl-options=\"-lstdc++\""
       ++ "  Specifying flags for interpreter\n"
 --TODO: re-enable once we have support for module/file targets
 --        ++ "  " ++ pname ++ " repl Foo.Bar   "
@@ -1826,7 +1798,14 @@
               trueArg
             ]
           _ -> []
+     ++ map liftReplOption (replOptions showOrParseArgs)
   }
+  where
+    liftReplOption = liftOption replReplOptions (\v flags -> flags { replReplOptions = v })
+
+replOptions :: ShowOrParseArgs -> [OptionField [String]]
+replOptions _ = [ option [] ["repl-options"] "use this option for the repl" id
+              const (reqArg "FLAG" (succeedReadE (:[])) id) ]
 
 -- ------------------------------------------------------------
 -- * Test flags
diff --git a/cabal/Cabal/Distribution/Simple/SrcDist.hs b/cabal/Cabal/Distribution/Simple/SrcDist.hs
--- a/cabal/Cabal/Distribution/Simple/SrcDist.hs
+++ b/cabal/Cabal/Distribution/Simple/SrcDist.hs
@@ -52,6 +52,7 @@
 import Distribution.ModuleName
 import qualified Distribution.ModuleName as ModuleName
 import Distribution.Version
+import Distribution.Simple.Glob
 import Distribution.Simple.Utils
 import Distribution.Simple.Setup
 import Distribution.Simple.PreProcess
@@ -137,16 +138,17 @@
 listPackageSources verbosity pkg_descr0 pps = do
   -- Call helpers that actually do all work.
   ordinary        <- listPackageSourcesOrdinary        verbosity pkg_descr pps
-  maybeExecutable <- listPackageSourcesMaybeExecutable pkg_descr
+  maybeExecutable <- listPackageSourcesMaybeExecutable verbosity pkg_descr
   return (ordinary, maybeExecutable)
   where
     pkg_descr = filterAutogenModules pkg_descr0
 
 -- | List those source files that may be executable (e.g. the configure script).
-listPackageSourcesMaybeExecutable :: PackageDescription -> IO [FilePath]
-listPackageSourcesMaybeExecutable pkg_descr =
+listPackageSourcesMaybeExecutable :: Verbosity -> PackageDescription -> IO [FilePath]
+listPackageSourcesMaybeExecutable verbosity pkg_descr =
   -- Extra source files.
-  fmap concat . for (extraSrcFiles pkg_descr) $ \fpath -> matchFileGlob fpath
+  fmap concat . for (extraSrcFiles pkg_descr) $ \fpath ->
+    matchDirFileGlob verbosity (specVersion pkg_descr) "." fpath
 
 -- | List those source files that should be copied with ordinary permissions.
 listPackageSourcesOrdinary :: Verbosity
@@ -208,12 +210,17 @@
     -- Data files.
   , fmap concat
     . for (dataFiles pkg_descr) $ \filename ->
-       matchFileGlob (dataDir pkg_descr </> filename)
+        let srcDataDirRaw = dataDir pkg_descr
+            srcDataDir = if null srcDataDirRaw
+              then "."
+              else srcDataDirRaw
+        in fmap (fmap (srcDataDir </>)) $
+             matchDirFileGlob verbosity (specVersion pkg_descr) srcDataDir filename
 
     -- Extra doc files.
   , fmap concat
     . for (extraDocFiles pkg_descr) $ \ filename ->
-      matchFileGlob filename
+        matchDirFileGlob verbosity (specVersion pkg_descr) "." filename
 
     -- License file(s).
   , return (licenseFiles pkg_descr)
@@ -447,7 +454,7 @@
       in findFileWithExtension fileExts (hsSourceDirs bi) file
     | module_ <- modules ++ otherModules bi ]
 
-  return $ sources ++ catMaybes bootFiles ++ cSources bi ++ jsSources bi
+  return $ sources ++ catMaybes bootFiles ++ cSources bi ++ cxxSources bi ++ jsSources bi
 
   where
     nonEmpty x _ [] = x
@@ -458,9 +465,11 @@
                  ++ "is autogenerated it should be added to 'autogen-modules'."
 
 
+-- | Note: must be called with the CWD set to the directory containing
+-- the '.cabal' file.
 printPackageProblems :: Verbosity -> PackageDescription -> IO ()
 printPackageProblems verbosity pkg_descr = do
-  ioChecks      <- checkPackageFiles pkg_descr "."
+  ioChecks      <- checkPackageFiles verbosity pkg_descr "."
   let pureChecks = checkConfiguredPackage pkg_descr
       isDistError (PackageDistSuspicious     _) = False
       isDistError (PackageDistSuspiciousWarn _) = False
diff --git a/cabal/Cabal/Distribution/Simple/Test/ExeV10.hs b/cabal/Cabal/Distribution/Simple/Test/ExeV10.hs
--- a/cabal/Cabal/Distribution/Simple/Test/ExeV10.hs
+++ b/cabal/Cabal/Distribution/Simple/Test/ExeV10.hs
@@ -50,7 +50,7 @@
     existingEnv <- getEnvironment
 
     let cmd = LBI.buildDir lbi </> testName'
-                  </> testName' <.> exeExtension
+                  </> testName' <.> exeExtension (LBI.hostPlatform lbi)
     -- Check that the test executable exists.
     exists <- doesFileExist cmd
     unless exists $ die' verbosity $ "Error: Could not find test program \"" ++ cmd
diff --git a/cabal/Cabal/Distribution/Simple/Test/LibV09.hs b/cabal/Cabal/Distribution/Simple/Test/LibV09.hs
--- a/cabal/Cabal/Distribution/Simple/Test/LibV09.hs
+++ b/cabal/Cabal/Distribution/Simple/Test/LibV09.hs
@@ -58,7 +58,7 @@
     existingEnv <- getEnvironment
 
     let cmd = LBI.buildDir lbi </> stubName suite
-                  </> stubName suite <.> exeExtension
+                  </> stubName suite <.> exeExtension (LBI.hostPlatform lbi)
     -- Check that the test executable exists.
     exists <- doesFileExist cmd
     unless exists $
diff --git a/cabal/Cabal/Distribution/Simple/UHC.hs b/cabal/Cabal/Distribution/Simple/UHC.hs
--- a/cabal/Cabal/Distribution/Simple/UHC.hs
+++ b/cabal/Cabal/Distribution/Simple/UHC.hs
@@ -73,13 +73,13 @@
 uhcLanguages = [(Haskell98, "")]
 
 -- | The flags for the supported extensions.
-uhcLanguageExtensions :: [(Extension, C.Flag)]
+uhcLanguageExtensions :: [(Extension, Maybe C.Flag)]
 uhcLanguageExtensions =
     let doFlag (f, (enable, disable)) = [(EnableExtension  f, enable),
                                          (DisableExtension f, disable)]
-        alwaysOn = ("", ""{- wrong -})
+        alwaysOn = (Nothing, Nothing{- wrong -})
     in concatMap doFlag
-    [(CPP,                          ("--cpp", ""{- wrong -})),
+    [(CPP,                          (Just "--cpp", Nothing{- wrong -})),
      (PolymorphicComponents,        alwaysOn),
      (ExistentialQuantification,    alwaysOn),
      (ForeignFunctionInterface,     alwaysOn),
@@ -88,7 +88,7 @@
      (Rank2Types,                   alwaysOn),
      (PatternSignatures,            alwaysOn),
      (EmptyDataDecls,               alwaysOn),
-     (ImplicitPrelude,              ("", "--no-prelude"{- wrong -})),
+     (ImplicitPrelude,              (Nothing, Just "--no-prelude"{- wrong -})),
      (TypeOperators,                alwaysOn),
      (OverlappingInstances,         alwaysOn),
      (FlexibleInstances,            alwaysOn)]
diff --git a/cabal/Cabal/Distribution/Simple/UserHooks.hs b/cabal/Cabal/Distribution/Simple/UserHooks.hs
--- a/cabal/Cabal/Distribution/Simple/UserHooks.hs
+++ b/cabal/Cabal/Distribution/Simple/UserHooks.hs
@@ -165,6 +165,9 @@
   }
 
 {-# DEPRECATED runTests "Please use the new testing interface instead!" #-}
+{-# DEPRECATED preSDist  "SDist hooks violate the invariants of new-sdist. Use 'autogen-modules' and 'build-tool-depends' instead." #-}
+{-# DEPRECATED sDistHook "SDist hooks violate the invariants of new-sdist. Use 'autogen-modules' and 'build-tool-depends' instead." #-}
+{-# DEPRECATED postSDist "SDist hooks violate the invariants of new-sdist. Use 'autogen-modules' and 'build-tool-depends' instead." #-}
 
 -- |Empty 'UserHooks' which do nothing.
 emptyUserHooks :: UserHooks
@@ -207,7 +210,7 @@
       preDoctest   = rn,
       doctestHook  = ru,
       postDoctest  = ru,
-      preHaddock   = rn,
+      preHaddock   = rn',
       haddockHook  = ru,
       postHaddock  = ru,
       preTest  = rn',
diff --git a/cabal/Cabal/Distribution/Simple/Utils.hs b/cabal/Cabal/Distribution/Simple/Utils.hs
--- a/cabal/Cabal/Distribution/Simple/Utils.hs
+++ b/cabal/Cabal/Distribution/Simple/Utils.hs
@@ -41,6 +41,7 @@
         chattyTry,
         annotateIO,
         printRawCommandAndArgs, printRawCommandAndArgsAndEnv,
+        withOutputMarker,
 
         -- * exceptions
         handleDoesNotExist,
@@ -109,12 +110,6 @@
         isInSearchPath,
         addLibraryPath,
 
-        -- * simple file globbing
-        matchFileGlob,
-        matchDirFileGlob,
-        parseFileGlob,
-        FileGlob(..),
-
         -- * modification time
         moreRecentFile,
         existsAndIsMoreRecentThan,
@@ -123,6 +118,7 @@
         TempFileOptions(..), defaultTempFileOptions,
         withTempFile, withTempFileEx,
         withTempDirectory, withTempDirectoryEx,
+        createTempDirectory,
 
         -- * .cabal and .buildinfo files
         defaultPackageDesc,
@@ -135,6 +131,7 @@
         withFileContents,
         writeFileAtomic,
         rewriteFile,
+        rewriteFileEx,
 
         -- * Unicode
         fromUTF8BS,
@@ -219,9 +216,8 @@
     ( exitWith, ExitCode(..) )
 import System.FilePath
     ( normalise, (</>), (<.>)
-    , getSearchPath, joinPath, takeDirectory, splitFileName
-    , splitExtension, splitExtensions, splitDirectories
-    , searchPathSeparator )
+    , getSearchPath, joinPath, takeDirectory, splitExtension
+    , splitDirectories, searchPathSeparator )
 import System.IO
     ( Handle, hSetBinaryMode, hGetContents, stderr, stdout, hPutStr, hFlush
     , hClose, hSetBuffering, BufferMode(..) )
@@ -1111,48 +1107,6 @@
              else (key,value ++ (searchPathSeparator:pathsString)):xs
       | otherwise     = (key,value):addEnv xs
 
-----------------
--- File globbing
-
-data FileGlob
-   -- | No glob at all, just an ordinary file
-   = NoGlob FilePath
-
-   -- | dir prefix and extension, like @\"foo\/bar\/\*.baz\"@ corresponds to
-   --    @FileGlob \"foo\/bar\" \".baz\"@
-   | FileGlob FilePath String
-
-parseFileGlob :: FilePath -> Maybe FileGlob
-parseFileGlob filepath = case splitExtensions filepath of
-  (filepath', ext) -> case splitFileName filepath' of
-    (dir, "*") | '*' `elem` dir
-              || '*' `elem` ext
-              || null ext            -> Nothing
-               | null dir            -> Just (FileGlob "." ext)
-               | otherwise           -> Just (FileGlob dir ext)
-    _          | '*' `elem` filepath -> Nothing
-               | otherwise           -> Just (NoGlob filepath)
-
-matchFileGlob :: FilePath -> IO [FilePath]
-matchFileGlob = matchDirFileGlob "."
-
-matchDirFileGlob :: FilePath -> FilePath -> IO [FilePath]
-matchDirFileGlob dir filepath = case parseFileGlob filepath of
-  Nothing -> die $ "invalid file glob '" ++ filepath
-                ++ "'. Wildcards '*' are only allowed in place of the file"
-                ++ " name, not in the directory name or file extension."
-                ++ " If a wildcard is used it must be with an file extension."
-  Just (NoGlob filepath') -> return [filepath']
-  Just (FileGlob dir' ext) -> do
-    files <- getDirectoryContents (dir </> dir')
-    case   [ dir' </> file
-           | file <- files
-           , let (name, ext') = splitExtensions file
-           , not (null name) && ext' == ext ] of
-      []      -> die $ "filepath wildcard '" ++ filepath
-                    ++ "' does not match any files."
-      matches -> return matches
-
 --------------------
 -- Modification time
 
@@ -1438,13 +1392,17 @@
 -----------------------------------
 -- Safely reading and writing files
 
+{-# DEPRECATED rewriteFile "Use rewriteFileEx so that Verbosity is respected" #-}
+rewriteFile :: FilePath -> String -> IO ()
+rewriteFile = rewriteFileEx normal
+
 -- | Write a file but only if it would have new content. If we would be writing
 -- the same as the existing content then leave the file as is so that we do not
 -- update the file's modification time.
 --
 -- NB: the file is assumed to be ASCII-encoded.
-rewriteFile :: Verbosity -> FilePath -> String -> IO ()
-rewriteFile verbosity path newContent =
+rewriteFileEx :: Verbosity -> FilePath -> String -> IO ()
+rewriteFileEx verbosity path newContent =
   flip catchIO mightNotExist $ do
     existingContent <- annotateIO verbosity $ readFile path
     _ <- evaluate (length existingContent)
@@ -1532,6 +1490,7 @@
 tryFindPackageDesc :: FilePath -> IO FilePath
 tryFindPackageDesc dir = either die return =<< findPackageDesc dir
 
+{-# DEPRECATED defaultHookedPackageDesc "Use findHookedPackageDesc with the proper base directory instead" #-}
 -- |Optional auxiliary package information file (/pkgname/@.buildinfo@)
 defaultHookedPackageDesc :: IO (Maybe FilePath)
 defaultHookedPackageDesc = findHookedPackageDesc currentDir
diff --git a/cabal/Cabal/Distribution/System.hs b/cabal/Cabal/Distribution/System.hs
--- a/cabal/Cabal/Distribution/System.hs
+++ b/cabal/Cabal/Distribution/System.hs
@@ -53,7 +53,7 @@
 import Distribution.Text
 
 import qualified Distribution.Compat.ReadP as Parse
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import qualified Text.PrettyPrint as Disp
 
 -- | How strict to be when classifying strings into the 'OS' and 'Arch' enums.
@@ -104,6 +104,8 @@
 
 instance Binary OS
 
+instance NFData OS where rnf = genericRnf
+
 knownOSs :: [OS]
 knownOSs = [Linux, Windows, OSX
            ,FreeBSD, OpenBSD, NetBSD, DragonFly
@@ -122,6 +124,7 @@
 osAliases Compat     FreeBSD = ["kfreebsdgnu"]
 osAliases Permissive Solaris = ["solaris2"]
 osAliases Compat     Solaris = ["solaris2"]
+osAliases _          Android = ["linux-android"]
 osAliases _          _       = []
 
 instance Pretty OS where
@@ -149,21 +152,22 @@
 -- * Machine Architecture
 -- ------------------------------------------------------------
 
--- | These are the known Arches: I386, X86_64, PPC, PPC64, Sparc
--- ,Arm, Mips, SH, IA64, S39, Alpha, Hppa, Rs6000, M68k, Vax
--- and JavaScript.
+-- | These are the known Arches: I386, X86_64, PPC, PPC64, Sparc,
+-- Arm, AArch64, Mips, SH, IA64, S39, Alpha, Hppa, Rs6000, M68k,
+-- Vax, and JavaScript.
 --
 -- The following aliases can also be used:
 --    * PPC alias: powerpc
---    * PPC64 alias : powerpc64
+--    * PPC64 alias : powerpc64, powerpc64le
 --    * Sparc aliases: sparc64, sun4
 --    * Mips aliases: mipsel, mipseb
 --    * Arm aliases: armeb, armel
+--    * AArch64 aliases: arm64
 --
-data Arch = I386  | X86_64 | PPC | PPC64 | Sparc
-          | Arm   | Mips   | SH
+data Arch = I386  | X86_64  | PPC  | PPC64 | Sparc
+          | Arm   | AArch64 | Mips | SH
           | IA64  | S390
-          | Alpha | Hppa   | Rs6000
+          | Alpha | Hppa    | Rs6000
           | M68k  | Vax
           | JavaScript
           | OtherArch String
@@ -171,23 +175,26 @@
 
 instance Binary Arch
 
+instance NFData Arch where rnf = genericRnf
+
 knownArches :: [Arch]
 knownArches = [I386, X86_64, PPC, PPC64, Sparc
-              ,Arm, Mips, SH
+              ,Arm, AArch64, Mips, SH
               ,IA64, S390
               ,Alpha, Hppa, Rs6000
               ,M68k, Vax
               ,JavaScript]
 
 archAliases :: ClassificationStrictness -> Arch -> [String]
-archAliases Strict _     = []
-archAliases Compat _     = []
-archAliases _      PPC   = ["powerpc"]
-archAliases _      PPC64 = ["powerpc64"]
-archAliases _      Sparc = ["sparc64", "sun4"]
-archAliases _      Mips  = ["mipsel", "mipseb"]
-archAliases _      Arm   = ["armeb", "armel"]
-archAliases _      _     = []
+archAliases Strict _       = []
+archAliases Compat _       = []
+archAliases _      PPC     = ["powerpc"]
+archAliases _      PPC64   = ["powerpc64", "powerpc64le"]
+archAliases _      Sparc   = ["sparc64", "sun4"]
+archAliases _      Mips    = ["mipsel", "mipseb"]
+archAliases _      Arm     = ["armeb", "armel"]
+archAliases _      AArch64 = ["arm64"]
+archAliases _      _       = []
 
 instance Pretty Arch where
   pretty (OtherArch name) = Disp.text name
@@ -219,6 +226,8 @@
 
 instance Binary Platform
 
+instance NFData Platform where rnf = genericRnf
+
 instance Pretty Platform where
   pretty (Platform arch os) = pretty arch <<>> Disp.char '-' <<>> pretty os
 
@@ -271,7 +280,7 @@
   where firstChar = Parse.satisfy isAlpha
         rest = Parse.munch (\c -> isAlphaNum c || c == '_' || c == '-')
 
-parsecIdent :: ParsecParser String
+parsecIdent :: CabalParsing m => m String
 parsecIdent = (:) <$> firstChar <*> rest
   where
     firstChar = P.satisfy isAlpha
diff --git a/cabal/Cabal/Distribution/Text.hs b/cabal/Cabal/Distribution/Text.hs
--- a/cabal/Cabal/Distribution/Text.hs
+++ b/cabal/Cabal/Distribution/Text.hs
@@ -8,7 +8,7 @@
 -- Portability :  portable
 --
 -- This defines a 'Text' class which is a bit like the 'Read' and 'Show'
--- classes. The difference is that is uses a modern pretty printer and parser
+-- classes. The difference is that it uses a modern pretty printer and parser
 -- system and the format is not expected to be Haskell concrete syntax but
 -- rather the external human readable representation used by Cabal.
 --
@@ -41,7 +41,7 @@
 
   parse :: Parse.ReadP r a
   default parse :: Parsec a => Parse.ReadP r a
-  parse = Parse.parsecToReadP parsec []
+  parse = parsec
 
 -- | Pretty-prints with the default style.
 display :: Text a => a -> String
diff --git a/cabal/Cabal/Distribution/Types/AbiDependency.hs b/cabal/Cabal/Distribution/Types/AbiDependency.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/Types/AbiDependency.hs
@@ -0,0 +1,52 @@
+{-# LANGUAGE DeriveGeneric #-}
+module Distribution.Types.AbiDependency where
+
+import Distribution.Compat.Prelude
+import Prelude ()
+
+import Distribution.Parsec.Class
+import Distribution.Pretty
+import Distribution.Text
+
+import qualified Distribution.Compat.CharParsing as P
+import qualified Distribution.Compat.ReadP       as Parse
+import qualified Distribution.Package            as Package
+import qualified Text.PrettyPrint                as Disp
+
+-- | An ABI dependency is a dependency on a library which also
+-- records the ABI hash ('abiHash') of the library it depends
+-- on.
+--
+-- The primary utility of this is to enable an extra sanity when
+-- GHC loads libraries: it can check if the dependency has a matching
+-- ABI and if not, refuse to load this library.  This information
+-- is critical if we are shadowing libraries; differences in the
+-- ABI hash let us know what packages get shadowed by the new version
+-- of a package.
+data AbiDependency = AbiDependency {
+        depUnitId  :: Package.UnitId,
+        depAbiHash :: Package.AbiHash
+    }
+  deriving (Eq, Generic, Read, Show)
+
+instance Pretty AbiDependency where
+    pretty (AbiDependency uid abi) =
+        disp uid <<>> Disp.char '=' <<>> disp abi
+
+instance  Parsec AbiDependency where
+    parsec = do
+        uid <- parsec
+        _ <- P.char '='
+        abi <- parsec
+        return (AbiDependency uid abi)
+
+instance Text AbiDependency where
+    parse = do
+        uid <- parse
+        _ <- Parse.char '='
+        abi <- parse
+        return (AbiDependency uid abi)
+
+instance Binary AbiDependency
+
+instance NFData AbiDependency where rnf = genericRnf
diff --git a/cabal/Cabal/Distribution/Types/AbiHash.hs b/cabal/Cabal/Distribution/Types/AbiHash.hs
--- a/cabal/Cabal/Distribution/Types/AbiHash.hs
+++ b/cabal/Cabal/Distribution/Types/AbiHash.hs
@@ -11,9 +11,13 @@
 import Distribution.Utils.ShortText
 
 import qualified Distribution.Compat.ReadP as Parse
-import qualified Text.PrettyPrint as Disp
+import qualified Distribution.Compat.CharParsing as P
 import Distribution.Text
+import Distribution.Pretty
+import Distribution.Parsec.Class
 
+import Text.PrettyPrint (text)
+
 -- | ABI Hashes
 --
 -- Use 'mkAbiHash' and 'unAbiHash' to convert from/to a
@@ -50,6 +54,13 @@
 
 instance Binary AbiHash
 
+instance NFData AbiHash where rnf = genericRnf
+
+instance Pretty AbiHash where
+    pretty = text . unAbiHash
+
+instance Parsec AbiHash where
+    parsec = fmap mkAbiHash (P.munch isAlphaNum)
+
 instance Text AbiHash where
-    disp = Disp.text . unAbiHash
     parse = fmap mkAbiHash (Parse.munch isAlphaNum)
diff --git a/cabal/Cabal/Distribution/Types/AnnotatedId.hs b/cabal/Cabal/Distribution/Types/AnnotatedId.hs
--- a/cabal/Cabal/Distribution/Types/AnnotatedId.hs
+++ b/cabal/Cabal/Distribution/Types/AnnotatedId.hs
@@ -11,12 +11,21 @@
 -- | An 'AnnotatedId' is a 'ComponentId', 'UnitId', etc.
 -- which is annotated with some other useful information
 -- that is useful for printing to users, etc.
+--
+-- Invariant: if ann_id x == ann_id y, then ann_pid x == ann_pid y
+-- and ann_cname x == ann_cname y
 data AnnotatedId id = AnnotatedId {
         ann_pid   :: PackageId,
         ann_cname :: ComponentName,
         ann_id    :: id
     }
     deriving (Show)
+
+instance Eq id => Eq (AnnotatedId id) where
+    x == y = ann_id x == ann_id y
+
+instance Ord id => Ord (AnnotatedId id) where
+    compare x y = compare (ann_id x) (ann_id y)
 
 instance Package (AnnotatedId id) where
     packageId = ann_pid
diff --git a/cabal/Cabal/Distribution/Types/Benchmark.hs b/cabal/Cabal/Distribution/Types/Benchmark.hs
--- a/cabal/Cabal/Distribution/Types/Benchmark.hs
+++ b/cabal/Cabal/Distribution/Types/Benchmark.hs
@@ -33,6 +33,8 @@
 
 instance Binary Benchmark
 
+instance NFData Benchmark where rnf = genericRnf
+
 instance L.HasBuildInfo Benchmark where
     buildInfo f (Benchmark x1 x2 x3) = fmap (\y1 -> Benchmark x1 x2 y1) (f x3)
 
diff --git a/cabal/Cabal/Distribution/Types/BenchmarkInterface.hs b/cabal/Cabal/Distribution/Types/BenchmarkInterface.hs
--- a/cabal/Cabal/Distribution/Types/BenchmarkInterface.hs
+++ b/cabal/Cabal/Distribution/Types/BenchmarkInterface.hs
@@ -35,6 +35,8 @@
 
 instance Binary BenchmarkInterface
 
+instance NFData BenchmarkInterface where rnf = genericRnf
+
 instance Monoid BenchmarkInterface where
     mempty  =  BenchmarkUnsupported (BenchmarkTypeUnknown mempty nullVersion)
     mappend = (<>)
diff --git a/cabal/Cabal/Distribution/Types/BenchmarkType.hs b/cabal/Cabal/Distribution/Types/BenchmarkType.hs
--- a/cabal/Cabal/Distribution/Types/BenchmarkType.hs
+++ b/cabal/Cabal/Distribution/Types/BenchmarkType.hs
@@ -25,6 +25,8 @@
 
 instance Binary BenchmarkType
 
+instance NFData BenchmarkType where rnf = genericRnf
+
 knownBenchmarkTypes :: [BenchmarkType]
 knownBenchmarkTypes = [ BenchmarkTypeExe (mkVersion [1,0]) ]
 
diff --git a/cabal/Cabal/Distribution/Types/BuildInfo.hs b/cabal/Cabal/Distribution/Types/BuildInfo.hs
--- a/cabal/Cabal/Distribution/Types/BuildInfo.hs
+++ b/cabal/Cabal/Distribution/Types/BuildInfo.hs
@@ -36,7 +36,7 @@
         buildable         :: Bool,
         -- | Tools needed to build this bit.
         --
-        -- This is a legacy field that 'buildToolDepends' larely supersedes.
+        -- This is a legacy field that 'buildToolDepends' largely supersedes.
         --
         -- Unless use are very sure what you are doing, use the functions in
         -- "Distribution.Simple.BuildToolDepends" rather than accessing this
@@ -107,6 +107,8 @@
 
 instance Binary BuildInfo
 
+instance NFData BuildInfo where rnf = genericRnf
+
 instance Monoid BuildInfo where
   mempty = BuildInfo {
     buildable           = True,
@@ -149,7 +151,7 @@
     staticOptions       = [],
     customFieldsBI      = [],
     targetBuildDepends  = [],
-    mixins    = []
+    mixins              = []
   }
   mappend = (<>)
 
@@ -195,7 +197,7 @@
     staticOptions       = combine    staticOptions,
     customFieldsBI      = combine    customFieldsBI,
     targetBuildDepends  = combineNub targetBuildDepends,
-    mixins    = combine mixins
+    mixins              = combine    mixins
   }
     where
       combine    field = field a `mappend` field b
diff --git a/cabal/Cabal/Distribution/Types/BuildInfo/Lens.hs b/cabal/Cabal/Distribution/Types/BuildInfo/Lens.hs
--- a/cabal/Cabal/Distribution/Types/BuildInfo/Lens.hs
+++ b/cabal/Cabal/Distribution/Types/BuildInfo/Lens.hs
@@ -1,6 +1,7 @@
 module Distribution.Types.BuildInfo.Lens (
     BuildInfo,
     HasBuildInfo (..),
+    HasBuildInfos (..),
     ) where
 
 import Prelude ()
@@ -314,3 +315,6 @@
 
     mixins f s = fmap (\x -> s { T.mixins = x }) (f (T.mixins s))
     {-# INLINE mixins #-}
+
+class HasBuildInfos a where
+  traverseBuildInfos :: Traversal' a BuildInfo
diff --git a/cabal/Cabal/Distribution/Types/BuildType.hs b/cabal/Cabal/Distribution/Types/BuildType.hs
--- a/cabal/Cabal/Distribution/Types/BuildType.hs
+++ b/cabal/Cabal/Distribution/Types/BuildType.hs
@@ -9,11 +9,12 @@
 import Prelude ()
 import Distribution.Compat.Prelude
 
+import Distribution.CabalSpecVersion (CabalSpecVersion (..))
 import Distribution.Pretty
 import Distribution.Parsec.Class
 import Distribution.Text
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import qualified Distribution.Compat.ReadP as Parse
 import qualified Text.PrettyPrint as Disp
 
@@ -25,38 +26,42 @@
                 -- information used by later phases.
   | Make        -- ^ calls @Distribution.Make.defaultMain@
   | Custom      -- ^ uses user-supplied @Setup.hs@ or @Setup.lhs@ (default)
-  | UnknownBuildType String
-                -- ^ a package that uses an unknown build type cannot actually
-                --   be built. Doing it this way rather than just giving a
-                --   parse error means we get better error messages and allows
-                --   you to inspect the rest of the package description.
                 deriving (Generic, Show, Read, Eq, Typeable, Data)
 
 instance Binary BuildType
 
+instance NFData BuildType where rnf = genericRnf
+
 knownBuildTypes :: [BuildType]
 knownBuildTypes = [Simple, Configure, Make, Custom]
 
 instance Pretty BuildType where
-  pretty (UnknownBuildType other) = Disp.text other
-  pretty other                    = Disp.text (show other)
+  pretty = Disp.text . show
 
 instance Parsec BuildType where
   parsec = do
     name <- P.munch1 isAlphaNum
-    return $ case name of
-      "Simple"    -> Simple
-      "Configure" -> Configure
-      "Custom"    -> Custom
-      "Make"      -> Make
-      _           -> UnknownBuildType name
+    case name of
+      "Simple"    -> return Simple
+      "Configure" -> return Configure
+      "Custom"    -> return Custom
+      "Make"      -> return Make
+      "Default"   -> do
+          v <- askCabalSpecVersion
+          if v <= CabalSpecOld
+          then do
+              parsecWarning PWTBuildTypeDefault "build-type: Default is parsed as Custom for legacy reasons. See https://github.com/haskell/cabal/issues/5020"
+              return Custom
+          else fail ("unknown build-type: '" ++ name ++ "'")
+      _           -> fail ("unknown build-type: '" ++ name ++ "'")
 
 instance Text BuildType where
   parse = do
     name <- Parse.munch1 isAlphaNum
-    return $ case name of
-      "Simple"    -> Simple
-      "Configure" -> Configure
-      "Custom"    -> Custom
-      "Make"      -> Make
-      _           -> UnknownBuildType name
+    case name of
+      "Simple"    -> return Simple
+      "Configure" -> return Configure
+      "Custom"    -> return Custom
+      "Make"      -> return Make
+      "Default"   -> return Custom
+      _           -> fail ("unknown build-type: '" ++ name ++ "'")
diff --git a/cabal/Cabal/Distribution/Types/ComponentId.hs b/cabal/Cabal/Distribution/Types/ComponentId.hs
--- a/cabal/Cabal/Distribution/Types/ComponentId.hs
+++ b/cabal/Cabal/Distribution/Types/ComponentId.hs
@@ -11,7 +11,7 @@
 import Distribution.Utils.ShortText
 
 import qualified Distribution.Compat.ReadP as Parse
-import qualified Distribution.Compat.Parsec as  P
+import qualified Distribution.Compat.CharParsing as P
 import Distribution.Text
 import Distribution.Pretty
 import Distribution.Parsec.Class
diff --git a/cabal/Cabal/Distribution/Types/CondTree.hs b/cabal/Cabal/Distribution/Types/CondTree.hs
--- a/cabal/Cabal/Distribution/Types/CondTree.hs
+++ b/cabal/Cabal/Distribution/Types/CondTree.hs
@@ -15,6 +15,8 @@
     mapTreeData,
     traverseCondTreeV,
     traverseCondBranchV,
+    traverseCondTreeC,
+    traverseCondBranchC,
     extractCondition,
     simplifyCondTree,
     ignoreConditions,
@@ -25,6 +27,9 @@
 
 import Distribution.Types.Condition
 
+import qualified Distribution.Compat.Lens as L
+
+
 -- | A 'CondTree' is used to represent the conditional structure of
 -- a Cabal file, reflecting a syntax element subject to constraints,
 -- and then any number of sub-elements which may be enabled subject
@@ -59,6 +64,8 @@
 
 instance (Binary v, Binary c, Binary a) => Binary (CondTree v c a)
 
+instance (NFData v, NFData c, NFData a) => NFData (CondTree v c a) where rnf = genericRnf
+
 -- | A 'CondBranch' represents a conditional branch, e.g., @if
 -- flag(foo)@ on some syntax @a@.  It also has an optional false
 -- branch.
@@ -79,6 +86,8 @@
 
 instance (Binary v, Binary c, Binary a) => Binary (CondBranch v c a)
 
+instance (NFData v, NFData c, NFData a) => NFData (CondBranch v c a) where rnf = genericRnf
+
 condIfThen :: Condition v -> CondTree v c a -> CondBranch v c a
 condIfThen c t = CondBranch c t Nothing
 
@@ -104,17 +113,29 @@
 mapTreeData :: (a -> b) -> CondTree v c a -> CondTree v c b
 mapTreeData f = mapCondTree f id id
 
--- | @Traversal (CondTree v c a) (CondTree w c a) v w@
-traverseCondTreeV :: Applicative f => (v -> f w) -> CondTree v c a -> f (CondTree w c a)
+-- | @@Traversal@@ for the variables
+traverseCondTreeV :: L.Traversal (CondTree v c a) (CondTree w c a) v w
 traverseCondTreeV f (CondNode a c ifs) =
     CondNode a c <$> traverse (traverseCondBranchV f) ifs
 
--- | @Traversal (CondBranch v c a) (CondBranch w c a) v w@
-traverseCondBranchV :: Applicative f => (v -> f w) -> CondBranch v c a -> f (CondBranch w c a)
+-- | @@Traversal@@ for the variables
+traverseCondBranchV :: L.Traversal (CondBranch v c a) (CondBranch w c a) v w
 traverseCondBranchV f (CondBranch cnd t me) = CondBranch
     <$> traverse f cnd
     <*> traverseCondTreeV f t
     <*> traverse (traverseCondTreeV f) me
+
+-- | @@Traversal@@ for the aggregated constraints
+traverseCondTreeC :: L.Traversal (CondTree v c a) (CondTree v d a) c d
+traverseCondTreeC f (CondNode a c ifs) =
+    CondNode a <$> f c <*> traverse (traverseCondBranchC f) ifs
+
+-- | @@Traversal@@ for the aggregated constraints
+traverseCondBranchC :: L.Traversal (CondBranch v c a) (CondBranch v d a) c d
+traverseCondBranchC f (CondBranch cnd t me) = CondBranch cnd
+    <$> traverseCondTreeC f t
+    <*> traverse (traverseCondTreeC f) me
+
 
 -- | Extract the condition matched by the given predicate from a cond tree.
 --
diff --git a/cabal/Cabal/Distribution/Types/Condition.hs b/cabal/Cabal/Distribution/Types/Condition.hs
--- a/cabal/Cabal/Distribution/Types/Condition.hs
+++ b/cabal/Cabal/Distribution/Types/Condition.hs
@@ -98,6 +98,8 @@
 
 instance Binary c => Binary (Condition c)
 
+instance NFData c => NFData (Condition c) where rnf = genericRnf
+
 -- | Simplify the condition and return its free variables.
 simplifyCondition :: Condition c
                   -> (c -> Either d Bool)   -- ^ (partial) variable assignment
diff --git a/cabal/Cabal/Distribution/Types/DependencyMap.hs b/cabal/Cabal/Distribution/Types/DependencyMap.hs
--- a/cabal/Cabal/Distribution/Types/DependencyMap.hs
+++ b/cabal/Cabal/Distribution/Types/DependencyMap.hs
@@ -1,17 +1,3 @@
-{-# LANGUAGE CPP #-}
-
-#ifdef MIN_VERSION_containers
-#if MIN_VERSION_containers(0,5,0)
-#define MIN_VERSION_containers_0_5_0
-#endif
-#endif
-
-#ifndef MIN_VERSION_containers
-#if __GLASGOW_HASKELL__ >= 706
-#define MIN_VERSION_containers_0_5_0
-#endif
-#endif
-
 module Distribution.Types.DependencyMap (
     DependencyMap,
     toDepMap,
@@ -26,11 +12,7 @@
 import Distribution.Types.PackageName
 import Distribution.Version
 
-#ifdef MIN_VERSION_containers_0_5_0
 import qualified Data.Map.Lazy as Map
-#else
-import qualified Data.Map as Map
-#endif
 
 -- | A map of dependencies.  Newtyped since the default monoid instance is not
 --   appropriate.  The monoid instance uses 'intersectVersionRanges'.
@@ -61,13 +43,8 @@
             -> DependencyMap
 constrainBy left extra =
     DependencyMap $
-#ifdef MIN_VERSION_containers_0_5_0
       Map.foldrWithKey tightenConstraint (unDependencyMap left)
                                          (unDependencyMap extra)
-#else
-      Map.foldWithKey tightenConstraint (unDependencyMap left)
-                                        (unDependencyMap extra)
-#endif
   where tightenConstraint n c l =
             case Map.lookup n l of
               Nothing -> l
diff --git a/cabal/Cabal/Distribution/Types/ExeDependency.hs b/cabal/Cabal/Distribution/Types/ExeDependency.hs
--- a/cabal/Cabal/Distribution/Types/ExeDependency.hs
+++ b/cabal/Cabal/Distribution/Types/ExeDependency.hs
@@ -16,7 +16,7 @@
 import Distribution.Types.UnqualComponentName
 import Distribution.Version                   (VersionRange, anyVersion)
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import           Distribution.Compat.ReadP  ((<++))
 import qualified Distribution.Compat.ReadP  as Parse
 import           Text.PrettyPrint           (text, (<+>))
diff --git a/cabal/Cabal/Distribution/Types/Executable.hs b/cabal/Cabal/Distribution/Types/Executable.hs
--- a/cabal/Cabal/Distribution/Types/Executable.hs
+++ b/cabal/Cabal/Distribution/Types/Executable.hs
@@ -32,6 +32,8 @@
 
 instance Binary Executable
 
+instance NFData Executable where rnf = genericRnf
+
 instance Monoid Executable where
   mempty = gmempty
   mappend = (<>)
diff --git a/cabal/Cabal/Distribution/Types/Executable/Lens.hs b/cabal/Cabal/Distribution/Types/Executable/Lens.hs
--- a/cabal/Cabal/Distribution/Types/Executable/Lens.hs
+++ b/cabal/Cabal/Distribution/Types/Executable/Lens.hs
@@ -7,6 +7,7 @@
 import Distribution.Compat.Prelude
 import Prelude ()
 
+import Distribution.Types.BuildInfo           (BuildInfo)
 import Distribution.Types.Executable          (Executable)
 import Distribution.Types.ExecutableScope     (ExecutableScope)
 import Distribution.Types.UnqualComponentName (UnqualComponentName)
@@ -25,8 +26,6 @@
 exeScope f s = fmap (\x -> s { T.exeScope = x }) (f (T.exeScope s))
 {-# INLINE exeScope #-}
 
-{-
-buildInfo :: Lens' Executable BuildInfo
-buildInfo f s = fmap (\x -> s { T.buildInfo = x }) (f (T.buildInfo s))
-{-# INLINE buildInfo #-}
--}
+exeBuildInfo :: Lens' Executable BuildInfo
+exeBuildInfo f s = fmap (\x -> s { T.buildInfo = x }) (f (T.buildInfo s))
+{-# INLINE exeBuildInfo #-}
diff --git a/cabal/Cabal/Distribution/Types/ExecutableScope.hs b/cabal/Cabal/Distribution/Types/ExecutableScope.hs
--- a/cabal/Cabal/Distribution/Types/ExecutableScope.hs
+++ b/cabal/Cabal/Distribution/Types/ExecutableScope.hs
@@ -12,27 +12,22 @@
 import Distribution.Parsec.Class
 import Distribution.Text
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import qualified Distribution.Compat.ReadP as Parse
 import qualified Text.PrettyPrint as Disp
 
-data ExecutableScope = ExecutableScopeUnknown
-                     | ExecutablePublic
+data ExecutableScope = ExecutablePublic
                      | ExecutablePrivate
     deriving (Generic, Show, Read, Eq, Typeable, Data)
 
 instance Pretty ExecutableScope where
     pretty ExecutablePublic       = Disp.text "public"
     pretty ExecutablePrivate      = Disp.text "private"
-    pretty ExecutableScopeUnknown = Disp.text "unknown"
 
 instance Parsec ExecutableScope where
-    parsec = do
-        name <- P.munch1 (\c -> isAlphaNum c || c == '-')
-        return $ case name of
-              "public"  -> ExecutablePublic
-              "private" -> ExecutablePrivate
-              _         -> ExecutableScopeUnknown
+    parsec = P.try pub <|> pri where
+        pub = ExecutablePublic  <$ P.string "public"
+        pri = ExecutablePrivate <$ P.string "private"
 
 instance Text ExecutableScope where
     parse = Parse.choice
@@ -42,12 +37,14 @@
 
 instance Binary ExecutableScope
 
-instance Monoid ExecutableScope where
-    mempty = ExecutableScopeUnknown
-    mappend = (<>)
+instance NFData ExecutableScope where rnf = genericRnf
 
+-- | 'Any' like semigroup, where 'ExecutablePrivate' is 'Any True'
 instance Semigroup ExecutableScope where
-    ExecutableScopeUnknown <> x = x
-    x <> ExecutableScopeUnknown = x
-    x <> y | x == y             = x
-           | otherwise          = error "Ambiguous executable scope"
+    ExecutablePublic    <> x = x
+    x@ExecutablePrivate <> _ = x
+
+-- | 'mempty' = 'ExecutablePublic'
+instance Monoid ExecutableScope where
+    mempty = ExecutablePublic
+    mappend = (<>)
diff --git a/cabal/Cabal/Distribution/Types/ExposedModule.hs b/cabal/Cabal/Distribution/Types/ExposedModule.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/Types/ExposedModule.hs
@@ -0,0 +1,57 @@
+{-# LANGUAGE DeriveGeneric #-}
+module Distribution.Types.ExposedModule where
+
+import Distribution.Compat.Prelude
+import Prelude ()
+
+import Distribution.Backpack
+import Distribution.ModuleName
+import Distribution.Parsec.Class
+import Distribution.ParseUtils   (parseModuleNameQ)
+import Distribution.Pretty
+import Distribution.Text
+
+import qualified Distribution.Compat.CharParsing as P
+import qualified Distribution.Compat.ReadP       as Parse
+import qualified Text.PrettyPrint                as Disp
+
+data ExposedModule
+   = ExposedModule {
+       exposedName      :: ModuleName,
+       exposedReexport  :: Maybe OpenModule
+     }
+  deriving (Eq, Generic, Read, Show)
+
+instance Pretty ExposedModule where
+    pretty (ExposedModule m reexport) =
+        Disp.hsep [ pretty m
+                  , case reexport of
+                     Just m' -> Disp.hsep [Disp.text "from", disp m']
+                     Nothing -> Disp.empty
+                  ]
+
+instance Parsec ExposedModule where
+    parsec = do
+        m <- parsecMaybeQuoted parsec
+        P.spaces
+
+        reexport <- P.optional $ do
+            _ <- P.string "from"
+            P.skipSpaces1
+            parsec
+
+        return (ExposedModule m reexport)
+
+instance Text ExposedModule where
+    parse = do
+        m <- parseModuleNameQ
+        Parse.skipSpaces
+        reexport <- Parse.option Nothing $ do
+            _ <- Parse.string "from"
+            Parse.skipSpaces
+            fmap Just parse
+        return (ExposedModule m reexport)
+
+instance Binary ExposedModule
+
+instance NFData ExposedModule where rnf = genericRnf
diff --git a/cabal/Cabal/Distribution/Types/ForeignLib.hs b/cabal/Cabal/Distribution/Types/ForeignLib.hs
--- a/cabal/Cabal/Distribution/Types/ForeignLib.hs
+++ b/cabal/Cabal/Distribution/Types/ForeignLib.hs
@@ -31,7 +31,7 @@
 import Distribution.Types.UnqualComponentName
 import Distribution.Version
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import qualified Distribution.Compat.ReadP  as Parse
 import qualified Text.PrettyPrint           as Disp
 import qualified Text.Read                  as Read
@@ -86,6 +86,8 @@
 
 instance Binary LibVersionInfo
 
+instance NFData LibVersionInfo where rnf = genericRnf
+
 instance Pretty LibVersionInfo where
     pretty (LibVersionInfo c r a)
       = Disp.hcat $ Disp.punctuate (Disp.char ':') $ map Disp.int [c,r,a]
@@ -148,6 +150,8 @@
     buildInfo f l = (\x -> l { foreignLibBuildInfo = x }) <$> f (foreignLibBuildInfo l)
 
 instance Binary ForeignLib
+
+instance NFData ForeignLib where rnf = genericRnf
 
 instance Semigroup ForeignLib where
   a <> b = ForeignLib {
diff --git a/cabal/Cabal/Distribution/Types/ForeignLibOption.hs b/cabal/Cabal/Distribution/Types/ForeignLibOption.hs
--- a/cabal/Cabal/Distribution/Types/ForeignLibOption.hs
+++ b/cabal/Cabal/Distribution/Types/ForeignLibOption.hs
@@ -12,7 +12,7 @@
 import Distribution.Parsec.Class
 import Distribution.Text
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import qualified Distribution.Compat.ReadP as Parse
 import qualified Text.PrettyPrint as Disp
 
@@ -41,3 +41,5 @@
     ]
 
 instance Binary ForeignLibOption
+
+instance NFData ForeignLibOption where rnf = genericRnf
diff --git a/cabal/Cabal/Distribution/Types/ForeignLibType.hs b/cabal/Cabal/Distribution/Types/ForeignLibType.hs
--- a/cabal/Cabal/Distribution/Types/ForeignLibType.hs
+++ b/cabal/Cabal/Distribution/Types/ForeignLibType.hs
@@ -15,7 +15,7 @@
 import Distribution.Parsec.Class
 import Distribution.Text
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import qualified Distribution.Compat.ReadP as Parse
 import qualified Text.PrettyPrint as Disp
 
@@ -50,6 +50,8 @@
     ]
 
 instance Binary ForeignLibType
+
+instance NFData ForeignLibType where rnf = genericRnf
 
 instance Semigroup ForeignLibType where
   ForeignLibTypeUnknown <> b = b
diff --git a/cabal/Cabal/Distribution/Types/GenericPackageDescription.hs b/cabal/Cabal/Distribution/Types/GenericPackageDescription.hs
--- a/cabal/Cabal/Distribution/Types/GenericPackageDescription.hs
+++ b/cabal/Cabal/Distribution/Types/GenericPackageDescription.hs
@@ -5,6 +5,7 @@
 
 module Distribution.Types.GenericPackageDescription (
     GenericPackageDescription(..),
+    emptyGenericPackageDescription,
     Flag(..),
     emptyFlag,
     FlagName,
@@ -16,6 +17,7 @@
     lookupFlagAssignment,
     insertFlagAssignment,
     diffFlagAssignment,
+    findDuplicateFlagAssignments,
     nullFlagAssignment,
     showFlagValue,
     dispFlagAssignment,
@@ -25,15 +27,19 @@
 ) where
 
 import Prelude ()
-import Data.List ((\\))
 import Distribution.Compat.Prelude
 import Distribution.Utils.ShortText
 import Distribution.Utils.Generic (lowercase)
 import qualified Text.PrettyPrint as Disp
+import qualified Data.Map as Map
 import qualified Distribution.Compat.ReadP as Parse
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import Distribution.Compat.ReadP ((+++))
 
+-- lens
+import Distribution.Compat.Lens                     as L
+import qualified Distribution.Types.BuildInfo.Lens  as L
+
 import Distribution.Types.PackageDescription
 
 import Distribution.Types.Dependency
@@ -54,19 +60,24 @@
 import Distribution.Text
 
 -- ---------------------------------------------------------------------------
--- The GenericPackageDescription type
+-- The 'GenericPackageDescription' type
 
 data GenericPackageDescription =
-    GenericPackageDescription {
-        packageDescription :: PackageDescription,
-        genPackageFlags    :: [Flag],
-        condLibrary        :: Maybe (CondTree ConfVar [Dependency] Library),
-        condSubLibraries   :: [(UnqualComponentName, CondTree ConfVar [Dependency] Library)],
-        condForeignLibs    :: [(UnqualComponentName, CondTree ConfVar [Dependency] ForeignLib)],
-        condExecutables    :: [(UnqualComponentName, CondTree ConfVar [Dependency] Executable)],
-        condTestSuites     :: [(UnqualComponentName, CondTree ConfVar [Dependency] TestSuite)],
-        condBenchmarks     :: [(UnqualComponentName, CondTree ConfVar [Dependency] Benchmark)]
-      }
+  GenericPackageDescription
+  { packageDescription :: PackageDescription
+  , genPackageFlags    :: [Flag]
+  , condLibrary        :: Maybe (CondTree ConfVar [Dependency] Library)
+  , condSubLibraries   :: [( UnqualComponentName
+                           , CondTree ConfVar [Dependency] Library )]
+  , condForeignLibs    :: [( UnqualComponentName
+                           , CondTree ConfVar [Dependency] ForeignLib )]
+  , condExecutables    :: [( UnqualComponentName
+                           , CondTree ConfVar [Dependency] Executable )]
+  , condTestSuites     :: [( UnqualComponentName
+                           , CondTree ConfVar [Dependency] TestSuite )]
+  , condBenchmarks     :: [( UnqualComponentName
+                           , CondTree ConfVar [Dependency] Benchmark )]
+  }
     deriving (Show, Eq, Typeable, Data, Generic)
 
 instance Package GenericPackageDescription where
@@ -74,6 +85,29 @@
 
 instance Binary GenericPackageDescription
 
+instance NFData GenericPackageDescription where rnf = genericRnf
+
+emptyGenericPackageDescription :: GenericPackageDescription
+emptyGenericPackageDescription = GenericPackageDescription emptyPackageDescription [] Nothing [] [] [] [] []
+
+-- -----------------------------------------------------------------------------
+-- Traversal Instances
+
+instance L.HasBuildInfos GenericPackageDescription where
+  traverseBuildInfos f (GenericPackageDescription p a1 x1 x2 x3 x4 x5 x6) =
+    GenericPackageDescription
+        <$> L.traverseBuildInfos f p
+        <*> pure a1
+        <*> (traverse . traverse . L.buildInfo) f x1
+        <*> (traverse . L._2 . traverse . L.buildInfo) f x2
+        <*> (traverse . L._2 . traverse . L.buildInfo) f x3
+        <*> (traverse . L._2 . traverse . L.buildInfo) f x4
+        <*> (traverse . L._2 . traverse . L.buildInfo) f x5
+        <*> (traverse . L._2 . traverse . L.buildInfo) f x6
+
+-- -----------------------------------------------------------------------------
+-- The Flag' type
+
 -- | A flag can represent a feature to be included, or a way of linking
 --   a target against its dependencies, or in fact whatever you can think of.
 data Flag = MkFlag
@@ -86,6 +120,8 @@
 
 instance Binary Flag
 
+instance NFData Flag where rnf = genericRnf
+
 -- | A 'Flag' initialized with default parameters.
 emptyFlag :: FlagName -> Flag
 emptyFlag name = MkFlag
@@ -103,7 +139,7 @@
 --
 -- @since 2.0.0.2
 newtype FlagName = FlagName ShortText
-    deriving (Eq, Generic, Ord, Show, Read, Typeable, Data)
+    deriving (Eq, Generic, Ord, Show, Read, Typeable, Data, NFData)
 
 -- | Construct a 'FlagName' from a 'String'
 --
@@ -154,38 +190,64 @@
 -- discovered during configuration. For example @--flags=foo --flags=-bar@
 -- becomes @[("foo", True), ("bar", False)]@
 --
-newtype FlagAssignment = FlagAssignment [(FlagName, Bool)]
-    deriving (Binary,Eq,Ord,Semigroup,Monoid)
+newtype FlagAssignment
+  = FlagAssignment { getFlagAssignment :: Map.Map FlagName (Int, Bool) }
+  deriving (Binary, Generic, NFData)
 
--- TODO: the Semigroup/Monoid/Ord/Eq instances would benefit from
--- [(FlagName,Bool)] being in a normal form, i.e. sorted. We could
--- e.g.  switch to a `Data.Map.Map` representation, but see duplicates
--- check in `configuredPackageProblems`.
+instance Eq FlagAssignment where
+  (==) (FlagAssignment m1) (FlagAssignment m2)
+    = fmap snd m1 == fmap snd m2
+
+instance Ord FlagAssignment where
+  compare (FlagAssignment m1) (FlagAssignment m2)
+    = fmap snd m1 `compare` fmap snd m2
+
+-- | Combines pairs of values contained in the 'FlagAssignment' Map.
 --
--- Also, the 'Semigroup' instance currently is left-biased as entries
--- in the left-hand 'FlagAssignment' shadow those occuring in the
--- right-hand side 'FlagAssignment' for the same flagnames.
+-- The last flag specified takes precedence, and we record the number
+-- of times we have seen the flag.
+--
+combineFlagValues :: (Int, Bool) -> (Int, Bool) -> (Int, Bool)
+combineFlagValues (c1, _) (c2, b2) = (c1 + c2, b2)
 
+-- The 'Semigroup' instance currently is right-biased.
+--
+-- If duplicate flags are specified, we want the last flag specified to
+-- take precedence and we want to know how many times the flag has been
+-- specified so that we have the option of warning the user about
+-- supplying duplicate flags.
+instance Semigroup FlagAssignment where
+  (<>) (FlagAssignment m1) (FlagAssignment m2)
+    = FlagAssignment (Map.unionWith combineFlagValues m1 m2)
+
+instance Monoid FlagAssignment where
+  mempty = FlagAssignment Map.empty
+  mappend = (<>)
+
 -- | Construct a 'FlagAssignment' from a list of flag/value pairs.
 --
+-- If duplicate flags occur in the input list, the later entries
+-- in the list will take precedence.
+--
 -- @since 2.2.0
 mkFlagAssignment :: [(FlagName, Bool)] -> FlagAssignment
-mkFlagAssignment = FlagAssignment
+mkFlagAssignment =
+  FlagAssignment .
+  Map.fromListWith (flip combineFlagValues) . fmap (fmap (\b -> (1, b)))
 
 -- | Deconstruct a 'FlagAssignment' into a list of flag/value pairs.
 --
--- @ ('mkFlagAssignment' . 'unFlagAssignment') fa == fa @
+-- @ 'null' ('findDuplicateFlagAssignments' fa) ==> ('mkFlagAssignment' . 'unFlagAssignment') fa == fa @
 --
 -- @since 2.2.0
 unFlagAssignment :: FlagAssignment -> [(FlagName, Bool)]
-unFlagAssignment (FlagAssignment xs) = xs
+unFlagAssignment = fmap (fmap snd) . Map.toList . getFlagAssignment
 
 -- | Test whether 'FlagAssignment' is empty.
 --
 -- @since 2.2.0
 nullFlagAssignment :: FlagAssignment -> Bool
-nullFlagAssignment (FlagAssignment []) = True
-nullFlagAssignment _                   = False
+nullFlagAssignment = Map.null . getFlagAssignment
 
 -- | Lookup the value for a flag
 --
@@ -193,16 +255,23 @@
 --
 -- @since 2.2.0
 lookupFlagAssignment :: FlagName -> FlagAssignment -> Maybe Bool
-lookupFlagAssignment fn = lookup fn . unFlagAssignment
+lookupFlagAssignment fn = fmap snd . Map.lookup fn . getFlagAssignment
 
 -- | Insert or update the boolean value of a flag.
 --
+-- If the flag is already present in the 'FlagAssigment', the
+-- value will be updated and the fact that multiple values have
+-- been provided for that flag will be recorded so that a
+-- warning can be generated later on.
+--
 -- @since 2.2.0
 insertFlagAssignment :: FlagName -> Bool -> FlagAssignment -> FlagAssignment
--- TODO: this currently just shadows prior values for an existing flag;
--- rather than enforcing uniqueness at construction, it's verified lateron via
--- `D.C.Dependency.configuredPackageProblems`
-insertFlagAssignment flag val = mkFlagAssignment . ((flag,val):) . unFlagAssignment
+-- TODO: this currently just shadows prior values for an existing
+-- flag; rather than enforcing uniqueness at construction, it's
+-- verified later on via `D.C.Dependency.configuredPackageProblems`
+insertFlagAssignment flag val =
+  FlagAssignment .
+  Map.insertWith (flip combineFlagValues) flag (1, val) .  getFlagAssignment
 
 -- | Remove all flag-assignments from the first 'FlagAssignment' that
 -- are contained in the second 'FlagAssignment'
@@ -214,8 +283,16 @@
 --
 -- @since 2.2.0
 diffFlagAssignment :: FlagAssignment -> FlagAssignment -> FlagAssignment
-diffFlagAssignment fa1 fa2 = mkFlagAssignment (unFlagAssignment fa1 \\ unFlagAssignment fa2)
+diffFlagAssignment fa1 fa2 = FlagAssignment
+  (Map.difference (getFlagAssignment fa1) (getFlagAssignment fa2))
 
+-- | Find the 'FlagName's that have been listed more than once.
+--
+-- @since 2.2.0
+findDuplicateFlagAssignments :: FlagAssignment -> [FlagName]
+findDuplicateFlagAssignments =
+  Map.keys . Map.filter ((> 1) . fst) . getFlagAssignment
+
 -- | @since 2.2.0
 instance Read FlagAssignment where
     readsPrec p s = [ (FlagAssignment x, rest) | (x,rest) <- readsPrec p s ]
@@ -235,10 +312,11 @@
 
 -- | Parses a flag assignment.
 parsecFlagAssignment :: ParsecParser FlagAssignment
-parsecFlagAssignment = FlagAssignment <$> P.sepBy (onFlag <|> offFlag) P.skipSpaces1
+parsecFlagAssignment = mkFlagAssignment <$>
+                       P.sepBy (onFlag <|> offFlag) P.skipSpaces1
   where
     onFlag = do
-        P.optional (P.char '+')
+        _ <- P.optional (P.char '+')
         f <- parsec
         return (f, True)
     offFlag = do
@@ -248,7 +326,8 @@
 
 -- | Parses a flag assignment.
 parseFlagAssignment :: Parse.ReadP r FlagAssignment
-parseFlagAssignment = FlagAssignment <$> Parse.sepBy parseFlagValue Parse.skipSpaces1
+parseFlagAssignment = mkFlagAssignment <$>
+                      Parse.sepBy parseFlagValue Parse.skipSpaces1
   where
     parseFlagValue =
           (do Parse.optional (Parse.char '+')
@@ -257,8 +336,11 @@
       +++ (do _ <- Parse.char '-'
               f <- parse
               return (f, False))
--- {-# DEPRECATED parseFlagAssignment "Use parsecFlagAssignment" #-}
+-- {-# DEPRECATED parseFlagAssignment "Use parsecFlagAssignment. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 
+-- -----------------------------------------------------------------------------
+-- The 'CondVar' type
+
 -- | A @ConfVar@ represents the variable type used.
 data ConfVar = OS OS
              | Arch Arch
@@ -267,3 +349,5 @@
     deriving (Eq, Show, Typeable, Data, Generic)
 
 instance Binary ConfVar
+
+instance NFData ConfVar where rnf = genericRnf
diff --git a/cabal/Cabal/Distribution/Types/GenericPackageDescription/Lens.hs b/cabal/Cabal/Distribution/Types/GenericPackageDescription/Lens.hs
--- a/cabal/Cabal/Distribution/Types/GenericPackageDescription/Lens.hs
+++ b/cabal/Cabal/Distribution/Types/GenericPackageDescription/Lens.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE Rank2Types #-}
 module Distribution.Types.GenericPackageDescription.Lens (
     GenericPackageDescription,
     Flag,
@@ -10,11 +11,6 @@
 import Distribution.Compat.Prelude
 import Distribution.Compat.Lens
 
-import Distribution.Types.GenericPackageDescription (GenericPackageDescription(GenericPackageDescription), Flag(MkFlag), FlagName, ConfVar (..))
-
--- lens
-import Distribution.Types.BuildInfo.Lens
-
 -- We import types from their packages, so we can remove unused imports
 -- and have wider inter-module dependency graph
 import Distribution.Types.CondTree (CondTree)
@@ -23,6 +19,9 @@
 import Distribution.Types.PackageDescription (PackageDescription)
 import Distribution.Types.Benchmark (Benchmark)
 import Distribution.Types.ForeignLib (ForeignLib)
+import Distribution.Types.GenericPackageDescription
+  ( GenericPackageDescription(GenericPackageDescription)
+  , Flag(MkFlag), FlagName, ConfVar (..))
 import Distribution.Types.Library (Library)
 import Distribution.Types.TestSuite (TestSuite)
 import Distribution.Types.UnqualComponentName (UnqualComponentName)
@@ -66,19 +65,23 @@
 packageDescription f (GenericPackageDescription x1 x2 x3 x4 x5 x6 x7 x8) = fmap (\y1 -> GenericPackageDescription y1 x2 x3 x4 x5 x6 x7 x8) (f x1)
 {-# INLINE packageDescription #-}
 
--------------------------------------------------------------------------------
--- BuildInfos
--------------------------------------------------------------------------------
+allCondTrees
+  :: Applicative f
+  => (forall a. CondTree ConfVar [Dependency] a
+          -> f (CondTree ConfVar [Dependency] a))
+  -> GenericPackageDescription
+  -> f GenericPackageDescription
+allCondTrees f (GenericPackageDescription p a1 x1 x2 x3 x4 x5 x6) =
+    GenericPackageDescription
+        <$> pure p
+        <*> pure a1
+        <*> traverse f x1
+        <*> (traverse . _2) f x2
+        <*> (traverse . _2) f x3
+        <*> (traverse . _2) f x4
+        <*> (traverse . _2) f x5
+        <*> (traverse . _2) f x6
 
-buildInfos :: Traversal' GenericPackageDescription BuildInfo
-buildInfos f (GenericPackageDescription x1 x2 x3 x4 x5 x6 x7 x8) =
-    GenericPackageDescription x1 x2
-        <$> (traverse . traverse . buildInfo) f x3
-        <*> (traverse . _2 . traverse . buildInfo) f x4
-        <*> (traverse . _2 . traverse . buildInfo) f x5
-        <*> (traverse . _2 . traverse . buildInfo) f x6
-        <*> (traverse . _2 . traverse . buildInfo) f x7
-        <*> (traverse . _2 . traverse . buildInfo) f x8
 
 -------------------------------------------------------------------------------
 -- Flag
diff --git a/cabal/Cabal/Distribution/Types/IncludeRenaming.hs b/cabal/Cabal/Distribution/Types/IncludeRenaming.hs
--- a/cabal/Cabal/Distribution/Types/IncludeRenaming.hs
+++ b/cabal/Cabal/Distribution/Types/IncludeRenaming.hs
@@ -12,7 +12,7 @@
 
 import Distribution.Types.ModuleRenaming
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import           Distribution.Compat.ReadP  ((<++))
 import qualified Distribution.Compat.ReadP  as Parse
 import           Distribution.Parsec.Class
@@ -33,6 +33,8 @@
     deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)
 
 instance Binary IncludeRenaming
+
+instance NFData IncludeRenaming where rnf = genericRnf
 
 -- | The 'defaultIncludeRenaming' applied when you only @build-depends@
 -- on a package.
diff --git a/cabal/Cabal/Distribution/Types/InstalledPackageInfo.hs b/cabal/Cabal/Distribution/Types/InstalledPackageInfo.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/Types/InstalledPackageInfo.hs
@@ -0,0 +1,170 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE TypeFamilies       #-}
+module Distribution.Types.InstalledPackageInfo (
+    InstalledPackageInfo (..),
+    emptyInstalledPackageInfo,
+    mungedPackageId,
+    mungedPackageName,
+    AbiDependency (..),
+    ExposedModule (..),
+    ) where
+
+import Distribution.Compat.Prelude
+import Prelude ()
+
+import Distribution.Backpack
+import Distribution.Compat.Graph              (IsNode (..))
+import Distribution.License
+import Distribution.ModuleName
+import Distribution.Package                   hiding (installedUnitId)
+import Distribution.Types.AbiDependency
+import Distribution.Types.ExposedModule
+import Distribution.Types.MungedPackageId
+import Distribution.Types.MungedPackageName
+import Distribution.Types.UnqualComponentName
+import Distribution.Version                   (nullVersion)
+
+import qualified Distribution.Package as Package
+import qualified Distribution.SPDX    as SPDX
+
+-- -----------------------------------------------------------------------------
+-- 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 (sourcePackageId, installedUnitId) are
+        -- exactly the same as PackageDescription
+        sourcePackageId   :: PackageId,
+        sourceLibName     :: Maybe UnqualComponentName,
+        installedComponentId_ :: ComponentId,
+        installedUnitId   :: UnitId,
+        -- INVARIANT: if this package is definite, OpenModule's
+        -- OpenUnitId directly records UnitId.  If it is
+        -- indefinite, OpenModule is always an OpenModuleVar
+        -- with the same ModuleName as the key.
+        instantiatedWith  :: [(ModuleName, OpenModule)],
+        compatPackageKey  :: String,
+        license           :: Either SPDX.License License,
+        copyright         :: String,
+        maintainer        :: String,
+        author            :: String,
+        stability         :: String,
+        homepage          :: String,
+        pkgUrl            :: String,
+        synopsis          :: String,
+        description       :: String,
+        category          :: String,
+        -- these parts are required by an installed package only:
+        abiHash           :: AbiHash,
+        indefinite        :: Bool,
+        exposed           :: Bool,
+        -- INVARIANT: if the package is definite, OpenModule's
+        -- OpenUnitId directly records UnitId.
+        exposedModules    :: [ExposedModule],
+        hiddenModules     :: [ModuleName],
+        trusted           :: Bool,
+        importDirs        :: [FilePath],
+        libraryDirs       :: [FilePath],
+        libraryDynDirs    :: [FilePath],  -- ^ overrides 'libraryDirs'
+        dataDir           :: FilePath,
+        hsLibraries       :: [String],
+        extraLibraries    :: [String],
+        extraGHCiLibraries:: [String],    -- overrides extraLibraries for GHCi
+        includeDirs       :: [FilePath],
+        includes          :: [String],
+        -- INVARIANT: if the package is definite, UnitId is NOT
+        -- a ComponentId of an indefinite package
+        depends           :: [UnitId],
+        abiDepends        :: [AbiDependency],
+        ccOptions         :: [String],
+        cxxOptions        :: [String],
+        ldOptions         :: [String],
+        frameworkDirs     :: [FilePath],
+        frameworks        :: [String],
+        haddockInterfaces :: [FilePath],
+        haddockHTMLs      :: [FilePath],
+        pkgRoot           :: Maybe FilePath
+    }
+    deriving (Eq, Generic, Typeable, Read, Show)
+
+instance Binary InstalledPackageInfo
+
+instance NFData InstalledPackageInfo where rnf = genericRnf
+
+instance Package.HasMungedPackageId InstalledPackageInfo where
+   mungedId = mungedPackageId
+
+instance Package.Package InstalledPackageInfo where
+   packageId = sourcePackageId
+
+instance Package.HasUnitId InstalledPackageInfo where
+   installedUnitId = installedUnitId
+
+instance Package.PackageInstalled InstalledPackageInfo where
+   installedDepends = depends
+
+instance IsNode InstalledPackageInfo where
+    type Key InstalledPackageInfo = UnitId
+    nodeKey       = installedUnitId
+    nodeNeighbors = depends
+
+mungedPackageId :: InstalledPackageInfo -> MungedPackageId
+mungedPackageId ipi =
+    MungedPackageId (mungedPackageName ipi) (packageVersion ipi)
+
+-- | Returns the munged package name, which we write into @name@ for
+-- compatibility with old versions of GHC.
+mungedPackageName :: InstalledPackageInfo -> MungedPackageName
+mungedPackageName ipi =
+    computeCompatPackageName
+        (packageName ipi)
+        (sourceLibName ipi)
+
+emptyInstalledPackageInfo :: InstalledPackageInfo
+emptyInstalledPackageInfo
+   = InstalledPackageInfo {
+        sourcePackageId   = PackageIdentifier (mkPackageName "") nullVersion,
+        sourceLibName     = Nothing,
+        installedComponentId_ = mkComponentId "",
+        installedUnitId   = mkUnitId "",
+        instantiatedWith  = [],
+        compatPackageKey  = "",
+        license           = Left SPDX.NONE,
+        copyright         = "",
+        maintainer        = "",
+        author            = "",
+        stability         = "",
+        homepage          = "",
+        pkgUrl            = "",
+        synopsis          = "",
+        description       = "",
+        category          = "",
+        abiHash           = mkAbiHash "",
+        indefinite        = False,
+        exposed           = False,
+        exposedModules    = [],
+        hiddenModules     = [],
+        trusted           = False,
+        importDirs        = [],
+        libraryDirs       = [],
+        libraryDynDirs    = [],
+        dataDir           = "",
+        hsLibraries       = [],
+        extraLibraries    = [],
+        extraGHCiLibraries= [],
+        includeDirs       = [],
+        includes          = [],
+        depends           = [],
+        abiDepends        = [],
+        ccOptions         = [],
+        cxxOptions        = [],
+        ldOptions         = [],
+        frameworkDirs     = [],
+        frameworks        = [],
+        haddockInterfaces = [],
+        haddockHTMLs      = [],
+        pkgRoot           = Nothing
+    }
diff --git a/cabal/Cabal/Distribution/Types/InstalledPackageInfo/FieldGrammar.hs b/cabal/Cabal/Distribution/Types/InstalledPackageInfo/FieldGrammar.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/Types/InstalledPackageInfo/FieldGrammar.hs
@@ -0,0 +1,263 @@
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE RecordWildCards       #-}
+module Distribution.Types.InstalledPackageInfo.FieldGrammar (
+    ipiFieldGrammar,
+    ) where
+
+import Distribution.Compat.Prelude
+import Prelude ()
+
+import Distribution.Backpack
+import Distribution.Compat.Lens               (Lens', (&), (.~))
+import Distribution.Compat.Newtype
+import Distribution.FieldGrammar
+import Distribution.FieldGrammar.FieldDescrs
+import Distribution.License
+import Distribution.ModuleName
+import Distribution.Package
+import Distribution.Parsec.Class
+import Distribution.Parsec.Newtypes
+import Distribution.Pretty
+import Distribution.Text
+import Distribution.Types.MungedPackageName
+import Distribution.Types.UnqualComponentName
+import Distribution.Version
+
+import qualified Data.Char                       as Char
+import qualified Data.Map                        as Map
+import qualified Distribution.Compat.CharParsing as P
+import qualified Distribution.SPDX               as SPDX
+import qualified Text.PrettyPrint                as Disp
+
+import Distribution.Types.InstalledPackageInfo
+
+import qualified Distribution.Types.InstalledPackageInfo.Lens as L
+import qualified Distribution.Types.PackageId.Lens            as L
+
+-- Note: GHC goes nuts and inlines everything,
+-- One can see e.g. in -ddump-simpl-stats:
+--
+-- 34886 KnownBranch
+--  8197 wild1_ixF0
+--
+-- https://ghc.haskell.org/trac/ghc/ticket/13253 might be the cause.
+--
+-- The workaround is to prevent GHC optimising the code:
+infixl 4 <+>
+(<+>) :: Applicative f => f (a -> b) -> f a -> f b
+f <+> x = f <*> x
+{-# NOINLINE (<+>) #-}
+
+ipiFieldGrammar
+    :: (FieldGrammar g, Applicative (g InstalledPackageInfo), Applicative (g Basic))
+    => g InstalledPackageInfo InstalledPackageInfo
+ipiFieldGrammar = mkInstalledPackageInfo
+    -- Deprecated fields
+    <$> monoidalFieldAla    "hugs-options"         (alaList' FSep Token)         unitedList
+        ^^^ deprecatedField' "hugs isn't supported anymore"
+    -- Very basic fields: name, version, package-name and lib-name
+    <+> blurFieldGrammar basic basicFieldGrammar
+    -- Basic fields
+    <+> optionalFieldDef    "id"                                                 L.installedUnitId (mkUnitId "")
+    <+> optionalFieldDefAla "instantiated-with"    InstWith                      L.instantiatedWith []
+    <+> optionalFieldDefAla "key"                  CompatPackageKey              L.compatPackageKey ""
+    <+> optionalFieldDefAla "license"              SpecLicenseLenient            L.license (Left SPDX.NONE)
+    <+> optionalFieldDefAla "copyright"            FreeText                      L.copyright ""
+    <+> optionalFieldDefAla "maintainer"           FreeText                      L.maintainer ""
+    <+> optionalFieldDefAla "author"               FreeText                      L.author ""
+    <+> optionalFieldDefAla "stability"            FreeText                      L.stability ""
+    <+> optionalFieldDefAla "homepage"             FreeText                      L.homepage ""
+    <+> optionalFieldDefAla "package-url"          FreeText                      L.pkgUrl ""
+    <+> optionalFieldDefAla "synopsis"             FreeText                      L.synopsis ""
+    <+> optionalFieldDefAla "description"          FreeText                      L.description ""
+    <+> optionalFieldDefAla "category"             FreeText                      L.category ""
+    -- Installed fields
+    <+> optionalFieldDef    "abi"                                                L.abiHash (mkAbiHash "")
+    <+> booleanFieldDef     "indefinite"                                         L.indefinite False
+    <+> booleanFieldDef     "exposed"                                            L.exposed False
+    <+> monoidalFieldAla    "exposed-modules"      ExposedModules                L.exposedModules
+    <+> monoidalFieldAla    "hidden-modules"       (alaList' FSep MQuoted)       L.hiddenModules
+    <+> booleanFieldDef     "trusted"                                            L.trusted False
+    <+> monoidalFieldAla    "import-dirs"          (alaList' FSep FilePathNT)    L.importDirs
+    <+> monoidalFieldAla    "library-dirs"         (alaList' FSep FilePathNT)    L.libraryDirs
+    <+> monoidalFieldAla    "dynamic-library-dirs" (alaList' FSep FilePathNT)    L.libraryDynDirs
+    <+> optionalFieldDefAla "data-dir"             FilePathNT                    L.dataDir ""
+    <+> monoidalFieldAla    "hs-libraries"         (alaList' FSep Token)         L.hsLibraries
+    <+> monoidalFieldAla    "extra-libraries"      (alaList' FSep Token)         L.extraLibraries
+    <+> monoidalFieldAla    "extra-ghci-libraries" (alaList' FSep Token)         L.extraGHCiLibraries
+    <+> monoidalFieldAla    "include-dirs"         (alaList' FSep FilePathNT)    L.includeDirs
+    <+> monoidalFieldAla    "includes"             (alaList' FSep FilePathNT)    L.includes
+    <+> monoidalFieldAla    "depends"              (alaList FSep)                L.depends
+    <+> monoidalFieldAla    "abi-depends"          (alaList FSep)                L.abiDepends
+    <+> monoidalFieldAla    "cc-options"           (alaList' FSep Token)         L.ccOptions
+    <+> monoidalFieldAla    "cxx-options"          (alaList' FSep Token)         L.cxxOptions
+    <+> monoidalFieldAla    "ld-options"           (alaList' FSep Token)         L.ldOptions
+    <+> monoidalFieldAla    "framework-dirs"       (alaList' FSep FilePathNT)    L.frameworkDirs
+    <+> monoidalFieldAla    "frameworks"           (alaList' FSep Token)         L.frameworks
+    <+> monoidalFieldAla    "haddock-interfaces"   (alaList' FSep FilePathNT)    L.haddockInterfaces
+    <+> monoidalFieldAla    "haddock-html"         (alaList' FSep FilePathNT)    L.haddockHTMLs
+    <+> optionalFieldAla    "pkgroot"              FilePathNT                    L.pkgRoot
+  where
+    mkInstalledPackageInfo _ Basic {..} = InstalledPackageInfo
+        -- _basicPkgName is not used
+        -- setMaybePackageId says it can be no-op.
+        (PackageIdentifier pn _basicVersion)
+        (mb_uqn <|> _basicLibName)
+        (mkComponentId "") -- installedComponentId_, not in use
+      where
+        (pn, mb_uqn) = decodeCompatPackageName _basicName
+{-# SPECIALIZE ipiFieldGrammar :: FieldDescrs InstalledPackageInfo InstalledPackageInfo #-}
+{-# SPECIALIZE ipiFieldGrammar :: ParsecFieldGrammar InstalledPackageInfo InstalledPackageInfo #-}
+{-# SPECIALIZE ipiFieldGrammar :: PrettyFieldGrammar InstalledPackageInfo InstalledPackageInfo #-}
+
+-- (forall b. [b]) ~ ()
+unitedList :: Lens' a [b]
+unitedList f s = s <$ f []
+
+-------------------------------------------------------------------------------
+-- Helper functions
+-------------------------------------------------------------------------------
+
+-- To maintain backwards-compatibility, we accept both comma/non-comma
+-- separated variants of this field.  You SHOULD use the comma syntax if you
+-- use any new functions, although actually it's unambiguous due to a quirk
+-- of the fact that modules must start with capital letters.
+
+showExposedModules :: [ExposedModule] -> Disp.Doc
+showExposedModules xs
+    | all isExposedModule xs = Disp.fsep (map disp xs)
+    | otherwise = Disp.fsep (Disp.punctuate Disp.comma (map disp xs))
+    where isExposedModule (ExposedModule _ Nothing) = True
+          isExposedModule _ = False
+
+-- | Returns @Just@ if the @name@ field of the IPI record would not contain
+-- the package name verbatim.  This helps us avoid writing @package-name@
+-- when it's redundant.
+maybePackageName :: InstalledPackageInfo -> Maybe PackageName
+maybePackageName ipi =
+    case sourceLibName ipi of
+        Nothing -> Nothing
+        Just _ -> Just (packageName ipi)
+
+-- | Setter for the @package-name@ field.  It should be acceptable for this
+-- to be a no-op.
+setMaybePackageName :: Maybe PackageName -> InstalledPackageInfo -> InstalledPackageInfo
+setMaybePackageName Nothing ipi = ipi
+setMaybePackageName (Just pn) ipi = ipi {
+        sourcePackageId=(sourcePackageId ipi){pkgName=pn}
+    }
+
+setMungedPackageName :: MungedPackageName -> InstalledPackageInfo -> InstalledPackageInfo
+setMungedPackageName mpn ipi =
+    let (pn, mb_uqn) = decodeCompatPackageName mpn
+    in ipi {
+            sourcePackageId = (sourcePackageId ipi) {pkgName=pn},
+            sourceLibName   = mb_uqn
+        }
+
+-------------------------------------------------------------------------------
+-- Auxiliary types
+-------------------------------------------------------------------------------
+
+newtype ExposedModules = ExposedModules { getExposedModules :: [ExposedModule] }
+
+instance Newtype ExposedModules [ExposedModule] where
+    pack   = ExposedModules
+    unpack = getExposedModules
+
+instance Parsec ExposedModules where
+    parsec = ExposedModules <$> parsecOptCommaList parsec
+
+instance Pretty ExposedModules where
+    pretty = showExposedModules . getExposedModules
+
+
+newtype CompatPackageKey = CompatPackageKey { getCompatPackageKey :: String }
+
+instance Newtype CompatPackageKey String where
+    pack = CompatPackageKey
+    unpack = getCompatPackageKey
+
+instance Pretty CompatPackageKey where
+    pretty = Disp.text . getCompatPackageKey
+
+instance Parsec CompatPackageKey where
+    parsec = CompatPackageKey <$> P.munch1 uid_char where
+        uid_char c = Char.isAlphaNum c || c `elem` ("-_.=[],:<>+" :: String)
+
+
+newtype InstWith = InstWith { getInstWith :: [(ModuleName,OpenModule)] }
+
+instance Newtype InstWith [(ModuleName, OpenModule)] where
+    pack = InstWith
+    unpack = getInstWith
+
+instance Pretty InstWith where
+    pretty = dispOpenModuleSubst . Map.fromList . getInstWith
+
+instance Parsec InstWith where
+    parsec = InstWith . Map.toList <$> parsecOpenModuleSubst
+
+
+-- | SPDX License expression or legacy license. Lenient parser, accepts either.
+newtype SpecLicenseLenient = SpecLicenseLenient { getSpecLicenseLenient :: Either SPDX.License License }
+
+instance Newtype SpecLicenseLenient (Either SPDX.License License) where
+    pack = SpecLicenseLenient
+    unpack = getSpecLicenseLenient
+
+instance Parsec SpecLicenseLenient where
+    parsec = fmap SpecLicenseLenient $ Left <$> P.try parsec <|> Right <$> parsec
+
+instance Pretty SpecLicenseLenient where
+    pretty = either pretty pretty . unpack
+
+
+data Basic = Basic
+    { _basicName    :: MungedPackageName
+    , _basicVersion :: Version
+    , _basicPkgName :: Maybe PackageName
+    , _basicLibName :: Maybe UnqualComponentName
+    }
+
+basic :: Lens' InstalledPackageInfo Basic
+basic f ipi = g <$> f b
+  where
+    b = Basic
+        (mungedPackageName ipi)
+        (packageVersion ipi)
+        (maybePackageName ipi)
+        (sourceLibName ipi)
+
+    g (Basic n v pn ln) = ipi
+        & setMungedPackageName n
+        & L.sourcePackageId . L.pkgVersion .~ v
+        & setMaybePackageName pn
+        & L.sourceLibName .~ ln
+
+basicName :: Lens' Basic MungedPackageName
+basicName f b = (\x -> b { _basicName = x }) <$> f (_basicName b)
+{-# INLINE basicName #-}
+
+basicVersion :: Lens' Basic Version
+basicVersion f b = (\x -> b { _basicVersion = x }) <$> f (_basicVersion b)
+{-# INLINE basicVersion #-}
+
+basicPkgName :: Lens' Basic (Maybe PackageName)
+basicPkgName f b = (\x -> b { _basicPkgName = x }) <$> f (_basicPkgName b)
+{-# INLINE basicPkgName #-}
+
+basicLibName :: Lens' Basic (Maybe UnqualComponentName)
+basicLibName f b = (\x -> b { _basicLibName = x }) <$> f (_basicLibName b)
+{-# INLINE basicLibName #-}
+
+basicFieldGrammar
+    :: (FieldGrammar g, Applicative (g Basic))
+    => g Basic Basic
+basicFieldGrammar = Basic
+    <$> optionalFieldDefAla "name"          MQuoted  basicName (mungedPackageName emptyInstalledPackageInfo)
+    <*> optionalFieldDefAla "version"       MQuoted  basicVersion nullVersion
+    <*> optionalField       "package-name"           basicPkgName
+    <*> optionalField       "lib-name"               basicLibName
diff --git a/cabal/Cabal/Distribution/Types/InstalledPackageInfo/Lens.hs b/cabal/Cabal/Distribution/Types/InstalledPackageInfo/Lens.hs
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/Distribution/Types/InstalledPackageInfo/Lens.hs
@@ -0,0 +1,183 @@
+module Distribution.Types.InstalledPackageInfo.Lens (
+    InstalledPackageInfo,
+    module Distribution.Types.InstalledPackageInfo.Lens
+    ) where
+
+import Distribution.Compat.Lens
+import Distribution.Compat.Prelude
+import Prelude ()
+
+import Distribution.Backpack                   (OpenModule)
+import Distribution.License                    (License)
+import Distribution.ModuleName                 (ModuleName)
+import Distribution.Package                    (AbiHash, ComponentId, PackageIdentifier, UnitId)
+import Distribution.Types.InstalledPackageInfo (AbiDependency, ExposedModule, InstalledPackageInfo)
+import Distribution.Types.UnqualComponentName  (UnqualComponentName)
+
+import qualified Distribution.SPDX                       as SPDX
+import qualified Distribution.Types.InstalledPackageInfo as T
+
+sourcePackageId :: Lens' InstalledPackageInfo PackageIdentifier
+sourcePackageId f s = fmap (\x -> s { T.sourcePackageId = x }) (f (T.sourcePackageId s))
+{-# INLINE sourcePackageId #-}
+
+installedUnitId :: Lens' InstalledPackageInfo UnitId
+installedUnitId f s = fmap (\x -> s { T.installedUnitId = x }) (f (T.installedUnitId s))
+{-# INLINE installedUnitId #-}
+
+installedComponentId_ :: Lens' InstalledPackageInfo ComponentId
+installedComponentId_ f s = fmap (\x -> s { T.installedComponentId_ = x }) (f (T.installedComponentId_ s))
+{-# INLINE installedComponentId_ #-}
+
+instantiatedWith :: Lens' InstalledPackageInfo [(ModuleName,OpenModule)]
+instantiatedWith f s = fmap (\x -> s { T.instantiatedWith = x }) (f (T.instantiatedWith s))
+{-# INLINE instantiatedWith #-}
+
+sourceLibName :: Lens' InstalledPackageInfo (Maybe UnqualComponentName)
+sourceLibName f s = fmap (\x -> s { T.sourceLibName = x }) (f (T.sourceLibName s))
+{-# INLINE sourceLibName #-}
+
+compatPackageKey :: Lens' InstalledPackageInfo String
+compatPackageKey f s = fmap (\x -> s { T.compatPackageKey = x }) (f (T.compatPackageKey s))
+{-# INLINE compatPackageKey #-}
+
+license :: Lens' InstalledPackageInfo (Either SPDX.License License)
+license f s = fmap (\x -> s { T.license = x }) (f (T.license s))
+{-# INLINE license #-}
+
+copyright :: Lens' InstalledPackageInfo String
+copyright f s = fmap (\x -> s { T.copyright = x }) (f (T.copyright s))
+{-# INLINE copyright #-}
+
+maintainer :: Lens' InstalledPackageInfo String
+maintainer f s = fmap (\x -> s { T.maintainer = x }) (f (T.maintainer s))
+{-# INLINE maintainer #-}
+
+author :: Lens' InstalledPackageInfo String
+author f s = fmap (\x -> s { T.author = x }) (f (T.author s))
+{-# INLINE author #-}
+
+stability :: Lens' InstalledPackageInfo String
+stability f s = fmap (\x -> s { T.stability = x }) (f (T.stability s))
+{-# INLINE stability #-}
+
+homepage :: Lens' InstalledPackageInfo String
+homepage f s = fmap (\x -> s { T.homepage = x }) (f (T.homepage s))
+{-# INLINE homepage #-}
+
+pkgUrl :: Lens' InstalledPackageInfo String
+pkgUrl f s = fmap (\x -> s { T.pkgUrl = x }) (f (T.pkgUrl s))
+{-# INLINE pkgUrl #-}
+
+synopsis :: Lens' InstalledPackageInfo String
+synopsis f s = fmap (\x -> s { T.synopsis = x }) (f (T.synopsis s))
+{-# INLINE synopsis #-}
+
+description :: Lens' InstalledPackageInfo String
+description f s = fmap (\x -> s { T.description = x }) (f (T.description s))
+{-# INLINE description #-}
+
+category :: Lens' InstalledPackageInfo String
+category f s = fmap (\x -> s { T.category = x }) (f (T.category s))
+{-# INLINE category #-}
+
+abiHash :: Lens' InstalledPackageInfo AbiHash
+abiHash f s = fmap (\x -> s { T.abiHash = x }) (f (T.abiHash s))
+{-# INLINE abiHash #-}
+
+indefinite :: Lens' InstalledPackageInfo Bool
+indefinite f s = fmap (\x -> s { T.indefinite = x }) (f (T.indefinite s))
+{-# INLINE indefinite #-}
+
+exposed :: Lens' InstalledPackageInfo Bool
+exposed f s = fmap (\x -> s { T.exposed = x }) (f (T.exposed s))
+{-# INLINE exposed #-}
+
+exposedModules :: Lens' InstalledPackageInfo [ExposedModule]
+exposedModules f s = fmap (\x -> s { T.exposedModules = x }) (f (T.exposedModules s))
+{-# INLINE exposedModules #-}
+
+hiddenModules :: Lens' InstalledPackageInfo [ModuleName]
+hiddenModules f s = fmap (\x -> s { T.hiddenModules = x }) (f (T.hiddenModules s))
+{-# INLINE hiddenModules #-}
+
+trusted :: Lens' InstalledPackageInfo Bool
+trusted f s = fmap (\x -> s { T.trusted = x }) (f (T.trusted s))
+{-# INLINE trusted #-}
+
+importDirs :: Lens' InstalledPackageInfo [FilePath]
+importDirs f s = fmap (\x -> s { T.importDirs = x }) (f (T.importDirs s))
+{-# INLINE importDirs #-}
+
+libraryDirs :: Lens' InstalledPackageInfo [FilePath]
+libraryDirs f s = fmap (\x -> s { T.libraryDirs = x }) (f (T.libraryDirs s))
+{-# INLINE libraryDirs #-}
+
+libraryDynDirs :: Lens' InstalledPackageInfo [FilePath]
+libraryDynDirs f s = fmap (\x -> s { T.libraryDynDirs = x }) (f (T.libraryDynDirs s))
+{-# INLINE libraryDynDirs #-}
+
+dataDir :: Lens' InstalledPackageInfo FilePath
+dataDir f s = fmap (\x -> s { T.dataDir = x }) (f (T.dataDir s))
+{-# INLINE dataDir #-}
+
+hsLibraries :: Lens' InstalledPackageInfo [String]
+hsLibraries f s = fmap (\x -> s { T.hsLibraries = x }) (f (T.hsLibraries s))
+{-# INLINE hsLibraries #-}
+
+extraLibraries :: Lens' InstalledPackageInfo [String]
+extraLibraries f s = fmap (\x -> s { T.extraLibraries = x }) (f (T.extraLibraries s))
+{-# INLINE extraLibraries #-}
+
+extraGHCiLibraries :: Lens' InstalledPackageInfo [String]
+extraGHCiLibraries f s = fmap (\x -> s { T.extraGHCiLibraries = x }) (f (T.extraGHCiLibraries s))
+{-# INLINE extraGHCiLibraries #-}
+
+includeDirs :: Lens' InstalledPackageInfo [FilePath]
+includeDirs f s = fmap (\x -> s { T.includeDirs = x }) (f (T.includeDirs s))
+{-# INLINE includeDirs #-}
+
+includes :: Lens' InstalledPackageInfo [String]
+includes f s = fmap (\x -> s { T.includes = x }) (f (T.includes s))
+{-# INLINE includes #-}
+
+depends :: Lens' InstalledPackageInfo [UnitId]
+depends f s = fmap (\x -> s { T.depends = x }) (f (T.depends s))
+{-# INLINE depends #-}
+
+abiDepends :: Lens' InstalledPackageInfo [AbiDependency]
+abiDepends f s = fmap (\x -> s { T.abiDepends = x }) (f (T.abiDepends s))
+{-# INLINE abiDepends #-}
+
+ccOptions :: Lens' InstalledPackageInfo [String]
+ccOptions f s = fmap (\x -> s { T.ccOptions = x }) (f (T.ccOptions s))
+{-# INLINE ccOptions #-}
+
+cxxOptions :: Lens' InstalledPackageInfo [String]
+cxxOptions f s = fmap (\x -> s { T.cxxOptions = x }) (f (T.cxxOptions s))
+{-# INLINE cxxOptions #-}
+
+ldOptions :: Lens' InstalledPackageInfo [String]
+ldOptions f s = fmap (\x -> s { T.ldOptions = x }) (f (T.ldOptions s))
+{-# INLINE ldOptions #-}
+
+frameworkDirs :: Lens' InstalledPackageInfo [FilePath]
+frameworkDirs f s = fmap (\x -> s { T.frameworkDirs = x }) (f (T.frameworkDirs s))
+{-# INLINE frameworkDirs #-}
+
+frameworks :: Lens' InstalledPackageInfo [String]
+frameworks f s = fmap (\x -> s { T.frameworks = x }) (f (T.frameworks s))
+{-# INLINE frameworks #-}
+
+haddockInterfaces :: Lens' InstalledPackageInfo [FilePath]
+haddockInterfaces f s = fmap (\x -> s { T.haddockInterfaces = x }) (f (T.haddockInterfaces s))
+{-# INLINE haddockInterfaces #-}
+
+haddockHTMLs :: Lens' InstalledPackageInfo [FilePath]
+haddockHTMLs f s = fmap (\x -> s { T.haddockHTMLs = x }) (f (T.haddockHTMLs s))
+{-# INLINE haddockHTMLs #-}
+
+pkgRoot :: Lens' InstalledPackageInfo (Maybe FilePath)
+pkgRoot f s = fmap (\x -> s { T.pkgRoot = x }) (f (T.pkgRoot s))
+{-# INLINE pkgRoot #-}
+
diff --git a/cabal/Cabal/Distribution/Types/LegacyExeDependency.hs b/cabal/Cabal/Distribution/Types/LegacyExeDependency.hs
--- a/cabal/Cabal/Distribution/Types/LegacyExeDependency.hs
+++ b/cabal/Cabal/Distribution/Types/LegacyExeDependency.hs
@@ -13,7 +13,7 @@
 import Distribution.Text
 import Distribution.Version      (VersionRange, anyVersion)
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import           Distribution.Compat.ReadP  ((<++))
 import qualified Distribution.Compat.ReadP  as Parse
 import           Text.PrettyPrint           (text, (<+>))
diff --git a/cabal/Cabal/Distribution/Types/Library.hs b/cabal/Cabal/Distribution/Types/Library.hs
--- a/cabal/Cabal/Distribution/Types/Library.hs
+++ b/cabal/Cabal/Distribution/Types/Library.hs
@@ -35,6 +35,8 @@
 
 instance Binary Library
 
+instance NFData Library where rnf = genericRnf
+
 instance Monoid Library where
   mempty = Library {
     libName = mempty,
@@ -81,6 +83,6 @@
 -- in the package description ('explicitLibModules'); unfortunately, the
 -- type signature for 'allLibModules' is incompatible since we need a
 -- 'ComponentLocalBuildInfo'.
-{-# DEPRECATED libModules "If you want all modules that are built with a library, use 'allLibModules'.  Otherwise, use 'explicitLibModules' for ONLY the modules explicitly mentioned in the package description." #-}
+{-# DEPRECATED libModules "If you want all modules that are built with a library, use 'allLibModules'.  Otherwise, use 'explicitLibModules' for ONLY the modules explicitly mentioned in the package description. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 libModules :: Library -> [ModuleName]
 libModules = explicitLibModules
diff --git a/cabal/Cabal/Distribution/Types/LocalBuildInfo.hs b/cabal/Cabal/Distribution/Types/LocalBuildInfo.hs
--- a/cabal/Cabal/Distribution/Types/LocalBuildInfo.hs
+++ b/cabal/Cabal/Distribution/Types/LocalBuildInfo.hs
@@ -103,6 +103,8 @@
                 -- ^ The platform we're building for
         buildDir      :: FilePath,
                 -- ^ Where to build the package.
+        cabalFilePath :: Maybe FilePath,
+                -- ^ Path to the cabal file, if given during configuration.
         componentGraph :: Graph ComponentLocalBuildInfo,
                 -- ^ All the components to build, ordered by topological
                 -- sort, and with their INTERNAL dependencies over the
@@ -307,7 +309,7 @@
 -------------------------------------------------------------------------------
 -- Backwards compatibility
 
-{-# DEPRECATED componentsConfigs "Use 'componentGraph' instead; you can get a list of 'ComponentLocalBuildInfo' with 'Distribution.Compat.Graph.toList'. There's not a good way to get the list of 'ComponentName's the 'ComponentLocalBuildInfo' depends on because this query doesn't make sense; the graph is indexed by 'UnitId' not 'ComponentName'.  Given a 'UnitId' you can lookup the 'ComponentLocalBuildInfo' ('getCLBI') and then get the 'ComponentName' ('componentLocalName]). To be removed in Cabal 2.2" #-}
+{-# DEPRECATED componentsConfigs "Use 'componentGraph' instead; you can get a list of 'ComponentLocalBuildInfo' with 'Distribution.Compat.Graph.toList'. There's not a good way to get the list of 'ComponentName's the 'ComponentLocalBuildInfo' depends on because this query doesn't make sense; the graph is indexed by 'UnitId' not 'ComponentName'.  Given a 'UnitId' you can lookup the 'ComponentLocalBuildInfo' ('getCLBI') and then get the 'ComponentName' ('componentLocalName]). To be removed in Cabal 3.0" #-}
 componentsConfigs :: LocalBuildInfo -> [(ComponentName, ComponentLocalBuildInfo, [ComponentName])]
 componentsConfigs lbi =
     [ (componentLocalName clbi,
@@ -320,7 +322,7 @@
 
 -- | External package dependencies for the package as a whole. This is the
 -- union of the individual 'componentPackageDeps', less any internal deps.
-{-# DEPRECATED externalPackageDeps "You almost certainly don't want this function, which agglomerates the dependencies of ALL enabled components.  If you're using this to write out information on your dependencies, read off the dependencies directly from the actual component in question.  To be removed in Cabal 2.2" #-}
+{-# DEPRECATED externalPackageDeps "You almost certainly don't want this function, which agglomerates the dependencies of ALL enabled components.  If you're using this to write out information on your dependencies, read off the dependencies directly from the actual component in question.  To be removed in Cabal 3.0" #-}
 externalPackageDeps :: LocalBuildInfo -> [(UnitId, MungedPackageId)]
 externalPackageDeps lbi =
     -- TODO:  what about non-buildable components?
diff --git a/cabal/Cabal/Distribution/Types/Mixin.hs b/cabal/Cabal/Distribution/Types/Mixin.hs
--- a/cabal/Cabal/Distribution/Types/Mixin.hs
+++ b/cabal/Cabal/Distribution/Types/Mixin.hs
@@ -16,7 +16,7 @@
 import Distribution.Types.IncludeRenaming
 import Distribution.Types.PackageName
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import qualified Distribution.Compat.ReadP  as Parse
 
 data Mixin = Mixin { mixinPackageName :: PackageName
@@ -24,6 +24,8 @@
     deriving (Show, Read, Eq, Ord, Typeable, Data, Generic)
 
 instance Binary Mixin
+
+instance NFData Mixin where rnf = genericRnf
 
 instance Pretty Mixin where
     pretty (Mixin pkg_name incl) = pretty pkg_name <+> pretty incl
diff --git a/cabal/Cabal/Distribution/Types/Module.hs b/cabal/Cabal/Distribution/Types/Module.hs
--- a/cabal/Cabal/Distribution/Types/Module.hs
+++ b/cabal/Cabal/Distribution/Types/Module.hs
@@ -10,7 +10,7 @@
 import Distribution.Compat.Prelude
 
 import qualified Distribution.Compat.ReadP as Parse
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import qualified Text.PrettyPrint as Disp
 import Distribution.Pretty
 import Distribution.Parsec.Class
diff --git a/cabal/Cabal/Distribution/Types/ModuleReexport.hs b/cabal/Cabal/Distribution/Types/ModuleReexport.hs
--- a/cabal/Cabal/Distribution/Types/ModuleReexport.hs
+++ b/cabal/Cabal/Distribution/Types/ModuleReexport.hs
@@ -14,7 +14,7 @@
 import Distribution.Text
 import Distribution.Types.PackageName
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import qualified Distribution.Compat.ReadP  as Parse
 import           Text.PrettyPrint           ((<+>))
 import qualified Text.PrettyPrint           as Disp
@@ -31,6 +31,8 @@
 
 instance Binary ModuleReexport
 
+instance NFData ModuleReexport where rnf = genericRnf
+
 instance Pretty ModuleReexport where
     pretty (ModuleReexport mpkgname origname newname) =
           maybe Disp.empty (\pkgname -> pretty pkgname <<>> Disp.char ':') mpkgname
@@ -41,7 +43,7 @@
 
 instance Parsec ModuleReexport where
     parsec = do
-        mpkgname <- P.optionMaybe (P.try $ parsec <* P.char ':')
+        mpkgname <- P.optional (P.try $ parsec <* P.char ':')
         origname <- parsec
         newname  <- P.option origname $ P.try $ do
             P.spaces
diff --git a/cabal/Cabal/Distribution/Types/ModuleRenaming.hs b/cabal/Cabal/Distribution/Types/ModuleRenaming.hs
--- a/cabal/Cabal/Distribution/Types/ModuleRenaming.hs
+++ b/cabal/Cabal/Distribution/Types/ModuleRenaming.hs
@@ -18,7 +18,7 @@
 
 import qualified Data.Map                   as Map
 import qualified Data.Set                   as Set
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import           Distribution.Compat.ReadP  ((<++))
 import qualified Distribution.Compat.ReadP  as Parse
 import           Text.PrettyPrint           (hsep, parens, punctuate, text, (<+>), comma)
@@ -69,6 +69,8 @@
 
 instance Binary ModuleRenaming where
 
+instance NFData ModuleRenaming where rnf = genericRnf
+
 -- NB: parentheses are mandatory, because later we may extend this syntax
 -- to allow "hiding (A, B)" or other modifier words.
 instance Pretty ModuleRenaming where
@@ -110,7 +112,7 @@
 
 
 instance Text ModuleRenaming where
-  parse = do fmap ModuleRenaming parseRns
+  parse = fmap ModuleRenaming parseRns
              <++ parseHidingRenaming
              <++ return DefaultRenaming
     where parseRns = do
diff --git a/cabal/Cabal/Distribution/Types/MungedPackageName.hs b/cabal/Cabal/Distribution/Types/MungedPackageName.hs
--- a/cabal/Cabal/Distribution/Types/MungedPackageName.hs
+++ b/cabal/Cabal/Distribution/Types/MungedPackageName.hs
@@ -1,23 +1,25 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE DeriveDataTypeable         #-}
+{-# LANGUAGE DeriveGeneric              #-}
 module Distribution.Types.MungedPackageName
   ( MungedPackageName, unMungedPackageName, mkMungedPackageName
   , computeCompatPackageName
   , decodeCompatPackageName
   ) where
 
-import Prelude ()
 import Distribution.Compat.Prelude
 import Distribution.Utils.ShortText
+import Prelude ()
 
-import qualified Text.PrettyPrint as Disp
-import qualified Distribution.Compat.ReadP as Parse
+import Distribution.Parsec.Class
 import Distribution.ParseUtils
+import Distribution.Pretty
 import Distribution.Text
 import Distribution.Types.PackageName
 import Distribution.Types.UnqualComponentName
 
+import qualified Distribution.Compat.ReadP       as Parse
+import qualified Text.PrettyPrint                as Disp
+
 -- | A combination of a package and component name used in various legacy
 -- interfaces, chiefly bundled with a version as 'MungedPackageId'. It's generally
 -- better to use a 'UnitId' to opaquely refer to some compilation/packing unit,
@@ -53,8 +55,13 @@
 
 instance Binary MungedPackageName
 
+instance Pretty MungedPackageName where
+  pretty = Disp.text . unMungedPackageName
+
+instance Parsec MungedPackageName where
+  parsec = mkMungedPackageName <$> parsecUnqualComponentName
+
 instance Text MungedPackageName where
-  disp = Disp.text . unMungedPackageName
   parse = mkMungedPackageName <$> parsePackageName
 
 instance NFData MungedPackageName where
diff --git a/cabal/Cabal/Distribution/Types/PackageDescription.hs b/cabal/Cabal/Distribution/Types/PackageDescription.hs
--- a/cabal/Cabal/Distribution/Types/PackageDescription.hs
+++ b/cabal/Cabal/Distribution/Types/PackageDescription.hs
@@ -29,7 +29,11 @@
 module Distribution.Types.PackageDescription (
     PackageDescription(..),
     specVersion,
+    specVersion',
+    license,
+    license',
     descCabalVersion,
+    buildType,
     emptyPackageDescription,
     hasPublicLib,
     hasLibs,
@@ -45,6 +49,8 @@
     withForeignLib,
     allBuildInfo,
     enabledBuildInfos,
+    allBuildDepends,
+    enabledBuildDepends,
     updatePackageDescription,
     pkgComponents,
     pkgBuildableComponents,
@@ -56,6 +62,10 @@
 import Prelude ()
 import Distribution.Compat.Prelude
 
+import Control.Monad ((<=<))
+
+-- lens
+import qualified Distribution.Types.BuildInfo.Lens  as L
 import Distribution.Types.Library
 import Distribution.Types.TestSuite
 import Distribution.Types.Executable
@@ -75,11 +85,13 @@
 import Distribution.Types.SourceRepo
 import Distribution.Types.HookedBuildInfo
 
+import Distribution.Compiler
+import Distribution.License
 import Distribution.Package
 import Distribution.Version
-import Distribution.License
-import Distribution.Compiler
 
+import qualified Distribution.SPDX as SPDX
+
 -- -----------------------------------------------------------------------------
 -- The PackageDescription type
 
@@ -92,8 +104,15 @@
 data PackageDescription
     =  PackageDescription {
         -- the following are required by all packages:
+
+        -- | The version of the Cabal spec that this package description uses.
+        -- For historical reasons this is specified with a version range but
+        -- only ranges of the form @>= v@ make sense. We are in the process of
+        -- transitioning to specifying just a single version, not a range.
+        -- See also 'specVersion'.
+        specVersionRaw :: Either Version VersionRange,
         package        :: PackageIdentifier,
-        license        :: License,
+        licenseRaw     :: Either SPDX.License License,
         licenseFiles   :: [FilePath],
         copyright      :: String,
         maintainer     :: String,
@@ -111,24 +130,11 @@
                                              -- with x-, stored in a
                                              -- simple assoc-list.
 
-        -- | YOU PROBABLY DON'T WANT TO USE THIS FIELD. This field is
-        -- special! Depending on how far along processing the
-        -- PackageDescription we are, the contents of this field are
-        -- either nonsense, or the collected dependencies of *all* the
-        -- components in this package.  buildDepends is initialized by
-        -- 'finalizePD' and 'flattenPackageDescription';
-        -- prior to that, dependency info is stored in the 'CondTree'
-        -- built around a 'GenericPackageDescription'.  When this
-        -- resolution is done, dependency info is written to the inner
-        -- 'BuildInfo' and this field.  This is all horrible, and #2066
-        -- tracks progress to get rid of this field.
-        buildDepends   :: [Dependency],
-        -- | The version of the Cabal spec that this package description uses.
-        -- For historical reasons this is specified with a version range but
-        -- only ranges of the form @>= v@ make sense. We are in the process of
-        -- transitioning to specifying just a single version, not a range.
-        specVersionRaw :: Either Version VersionRange,
-        buildType      :: Maybe BuildType,
+        -- | The original @build-type@ value as parsed from the
+        -- @.cabal@ file without defaulting. See also 'buildType'.
+        --
+        -- @since 2.2
+        buildTypeRaw   :: Maybe BuildType,
         setupBuildInfo :: Maybe SetupBuildInfo,
         -- components
         library        :: Maybe Library,
@@ -148,6 +154,8 @@
 
 instance Binary PackageDescription
 
+instance NFData PackageDescription where rnf = genericRnf
+
 instance Package PackageDescription where
   packageId = package
 
@@ -159,12 +167,29 @@
 -- version by ignoring upper bounds in the version range.
 --
 specVersion :: PackageDescription -> Version
-specVersion pkg = case specVersionRaw pkg of
-  Left  version      -> version
-  Right versionRange -> case asVersionIntervals versionRange of
-                          []                            -> mkVersion [0]
-                          ((LowerBound version _, _):_) -> version
+specVersion = specVersion' . specVersionRaw
 
+-- |
+--
+-- @since 2.2.0.0
+specVersion' :: Either Version VersionRange -> Version
+specVersion' (Left version) = version
+specVersion' (Right versionRange) = case asVersionIntervals versionRange of
+    []                            -> mkVersion [0]
+    ((LowerBound version _, _):_) -> version
+
+-- | The SPDX 'LicenseExpression' of the package.
+--
+-- @since 2.2.0.0
+license :: PackageDescription -> SPDX.License
+license = license' . licenseRaw
+
+-- | See 'license'.
+--
+-- @since 2.2.0.0
+license' :: Either SPDX.License License -> SPDX.License
+license' = either id licenseToSPDX
+
 -- | The range of versions of the Cabal tools that this package is intended to
 -- work with.
 --
@@ -175,23 +200,47 @@
 descCabalVersion pkg = case specVersionRaw pkg of
   Left  version      -> orLaterVersion version
   Right versionRange -> versionRange
-{-# DEPRECATED descCabalVersion "Use specVersion instead" #-}
+{-# DEPRECATED descCabalVersion "Use specVersion instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 
+-- | The effective @build-type@ after applying defaulting rules.
+--
+-- The original @build-type@ value parsed is stored in the
+-- 'buildTypeRaw' field.  However, the @build-type@ field is optional
+-- and can therefore be empty in which case we need to compute the
+-- /effective/ @build-type@. This function implements the following
+-- defaulting rules:
+--
+--  * For @cabal-version:2.0@ and below, default to the @Custom@
+--    build-type unconditionally.
+--
+--  * Otherwise, if a @custom-setup@ stanza is defined, default to
+--    the @Custom@ build-type; else default to @Simple@ build-type.
+--
+-- @since 2.2
+buildType :: PackageDescription -> BuildType
+buildType pkg
+  | specVersion pkg >= mkVersion [2,1]
+    = fromMaybe newDefault (buildTypeRaw pkg)
+  | otherwise -- cabal-version < 2.1
+    = fromMaybe Custom (buildTypeRaw pkg)
+  where
+    newDefault | isNothing (setupBuildInfo pkg) = Simple
+               | otherwise                      = Custom
+
 emptyPackageDescription :: PackageDescription
 emptyPackageDescription
     =  PackageDescription {
                       package      = PackageIdentifier (mkPackageName "")
                                                        nullVersion,
-                      license      = UnspecifiedLicense,
+                      licenseRaw   = Right UnspecifiedLicense, -- TODO:
                       licenseFiles = [],
                       specVersionRaw = Right anyVersion,
-                      buildType    = Nothing,
+                      buildTypeRaw = Nothing,
                       copyright    = "",
                       maintainer   = "",
                       author       = "",
                       stability    = "",
                       testedWith   = [],
-                      buildDepends = [],
                       homepage     = "",
                       pkgUrl       = "",
                       bugReports   = "",
@@ -308,27 +357,21 @@
 -- ---------------------------------------------------------------------------
 -- The BuildInfo type
 
--- | The 'BuildInfo' for the library (if there is one and it's buildable), and
--- all buildable executables, test suites and benchmarks.  Useful for gathering
--- dependencies.
+-- | All 'BuildInfo' in the 'PackageDescription':
+-- libraries, executables, test-suites and benchmarks.
+--
+-- Useful for implementing package checks.
 allBuildInfo :: PackageDescription -> [BuildInfo]
 allBuildInfo pkg_descr = [ bi | lib <- allLibraries pkg_descr
-                              , let bi = libBuildInfo lib
-                              , buildable bi ]
-                      ++ [ bi | flib <- foreignLibs pkg_descr
-                              , let bi = foreignLibBuildInfo flib
-                              , buildable bi ]
-                      ++ [ bi | exe <- executables pkg_descr
-                              , let bi = buildInfo exe
-                              , buildable bi ]
-                      ++ [ bi | tst <- testSuites pkg_descr
-                              , let bi = testBuildInfo tst
-                              , buildable bi ]
-                      ++ [ bi | tst <- benchmarks pkg_descr
-                              , let bi = benchmarkBuildInfo tst
-                              , buildable bi ]
-  --FIXME: many of the places where this is used, we actually want to look at
-  --       unbuildable bits too, probably need separate functions
+                               , let bi = libBuildInfo lib ]
+                       ++ [ bi | flib <- foreignLibs pkg_descr
+                               , let bi = foreignLibBuildInfo flib ]
+                       ++ [ bi | exe <- executables pkg_descr
+                               , let bi = buildInfo exe ]
+                       ++ [ bi | tst <- testSuites pkg_descr
+                               , let bi = testBuildInfo tst ]
+                       ++ [ bi | tst <- benchmarks pkg_descr
+                               , let bi = benchmarkBuildInfo tst ]
 
 -- | Return all of the 'BuildInfo's of enabled components, i.e., all of
 -- the ones that would be built if you run @./Setup build@.
@@ -342,6 +385,16 @@
 -- * Utils
 -- ------------------------------------------------------------
 
+-- | Get the combined build-depends entries of all components.
+allBuildDepends :: PackageDescription -> [Dependency]
+allBuildDepends = targetBuildDepends <=< allBuildInfo
+
+-- | Get the combined build-depends entries of all enabled components, per the
+-- given request spec.
+enabledBuildDepends :: PackageDescription -> ComponentRequestedSpec -> [Dependency]
+enabledBuildDepends spec pd = targetBuildDepends =<< enabledBuildInfos spec pd
+
+
 updatePackageDescription :: HookedBuildInfo -> PackageDescription -> PackageDescription
 updatePackageDescription (mb_lib_bi, exe_bi) p
     = p{ executables = updateExecutables exe_bi    (executables p)
@@ -417,3 +470,23 @@
     missingComponent =
       error $ "internal error: the package description contains no "
            ++ "component corresponding to " ++ show cname
+
+-- -----------------------------------------------------------------------------
+-- Traversal Instances
+
+instance L.HasBuildInfos PackageDescription where
+  traverseBuildInfos f (PackageDescription a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19
+                                   x1 x2 x3 x4 x5 x6
+                                   a20 a21 a22 a23 a24) =
+    PackageDescription a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19
+        <$> (traverse . L.buildInfo) f x1 -- library
+        <*> (traverse . L.buildInfo) f x2 -- sub libraries
+        <*> (traverse . L.buildInfo) f x3 -- executables
+        <*> (traverse . L.buildInfo) f x4 -- foreign libs
+        <*> (traverse . L.buildInfo) f x5 -- test suites
+        <*> (traverse . L.buildInfo) f x6 -- benchmarks
+        <*> pure a20                      -- data files
+        <*> pure a21                      -- data dir
+        <*> pure a22                      -- exta src files
+        <*> pure a23                      -- extra temp files
+        <*> pure a24                      -- extra doc files
diff --git a/cabal/Cabal/Distribution/Types/PackageDescription/Lens.hs b/cabal/Cabal/Distribution/Types/PackageDescription/Lens.hs
--- a/cabal/Cabal/Distribution/Types/PackageDescription/Lens.hs
+++ b/cabal/Cabal/Distribution/Types/PackageDescription/Lens.hs
@@ -1,36 +1,47 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
 module Distribution.Types.PackageDescription.Lens (
     PackageDescription,
     module Distribution.Types.PackageDescription.Lens,
     ) where
 
-import Prelude ()
-import Distribution.Compat.Prelude
 import Distribution.Compat.Lens
+import Distribution.Compat.Prelude
+import Prelude ()
 
-import Distribution.Compiler                 (CompilerFlavor)
-import Distribution.License                  (License)
-import Distribution.Types.Benchmark          (Benchmark)
-import Distribution.Types.BuildType          (BuildType)
-import Distribution.Types.Dependency         (Dependency)
-import Distribution.Types.Executable         (Executable)
-import Distribution.Types.ForeignLib         (ForeignLib)
-import Distribution.Types.Library            (Library)
-import Distribution.Types.PackageDescription (PackageDescription)
-import Distribution.Types.PackageId          (PackageIdentifier)
-import Distribution.Types.SetupBuildInfo     (SetupBuildInfo)
-import Distribution.Types.SourceRepo         (SourceRepo)
-import Distribution.Types.TestSuite          (TestSuite)
-import Distribution.Version                  (Version, VersionRange)
+import Distribution.Compiler                  (CompilerFlavor)
+import Distribution.License                   (License)
+import Distribution.ModuleName                (ModuleName)
+import Distribution.Types.Benchmark           (Benchmark, benchmarkModules)
+import Distribution.Types.Benchmark.Lens      (benchmarkName, benchmarkBuildInfo)
+import Distribution.Types.BuildInfo           (BuildInfo)
+import Distribution.Types.BuildType           (BuildType)
+import Distribution.Types.ComponentName       (ComponentName(..))
+import Distribution.Types.Executable          (Executable, exeModules)
+import Distribution.Types.Executable.Lens     (exeName, exeBuildInfo)
+import Distribution.Types.ForeignLib          (ForeignLib, foreignLibModules)
+import Distribution.Types.ForeignLib.Lens     (foreignLibName, foreignLibBuildInfo)
+import Distribution.Types.Library             (Library, explicitLibModules)
+import Distribution.Types.Library.Lens        (libName, libBuildInfo)
+import Distribution.Types.PackageDescription  (PackageDescription)
+import Distribution.Types.PackageId           (PackageIdentifier)
+import Distribution.Types.SetupBuildInfo      (SetupBuildInfo)
+import Distribution.Types.SourceRepo          (SourceRepo)
+import Distribution.Types.TestSuite           (TestSuite, testModules)
+import Distribution.Types.TestSuite.Lens      (testName, testBuildInfo)
+import Distribution.Types.UnqualComponentName ( UnqualComponentName )
+import Distribution.Version                   (Version, VersionRange)
 
+import qualified Distribution.SPDX                     as SPDX
 import qualified Distribution.Types.PackageDescription as T
 
 package :: Lens' PackageDescription PackageIdentifier
 package f s = fmap (\x -> s { T.package = x }) (f (T.package s))
 {-# INLINE package #-}
 
-license :: Lens' PackageDescription License
-license f s = fmap (\x -> s { T.license = x }) (f (T.license s))
-{-# INLINE license #-}
+licenseRaw :: Lens' PackageDescription (Either SPDX.License License)
+licenseRaw f s = fmap (\x -> s { T.licenseRaw = x }) (f (T.licenseRaw s))
+{-# INLINE licenseRaw #-}
 
 licenseFiles :: Lens' PackageDescription [String]
 licenseFiles f s = fmap (\x -> s { T.licenseFiles = x }) (f (T.licenseFiles s))
@@ -88,17 +99,13 @@
 customFieldsPD f s = fmap (\x -> s { T.customFieldsPD = x }) (f (T.customFieldsPD s))
 {-# INLINE customFieldsPD #-}
 
-buildDepends :: Lens' PackageDescription [Dependency]
-buildDepends f s = fmap (\x -> s { T.buildDepends = x }) (f (T.buildDepends s))
-{-# INLINE buildDepends #-}
-
 specVersionRaw :: Lens' PackageDescription (Either Version VersionRange)
 specVersionRaw f s = fmap (\x -> s { T.specVersionRaw = x }) (f (T.specVersionRaw s))
 {-# INLINE specVersionRaw #-}
 
-buildType :: Lens' PackageDescription (Maybe BuildType)
-buildType f s = fmap (\x -> s { T.buildType = x }) (f (T.buildType s))
-{-# INLINE buildType #-}
+buildTypeRaw :: Lens' PackageDescription (Maybe BuildType)
+buildTypeRaw f s = fmap (\x -> s { T.buildTypeRaw = x }) (f (T.buildTypeRaw s))
+{-# INLINE buildTypeRaw #-}
 
 setupBuildInfo :: Lens' PackageDescription (Maybe SetupBuildInfo)
 setupBuildInfo f s = fmap (\x -> s { T.setupBuildInfo = x }) (f (T.setupBuildInfo s))
@@ -147,3 +154,75 @@
 extraDocFiles :: Lens' PackageDescription [String]
 extraDocFiles f s = fmap (\x -> s { T.extraDocFiles = x }) (f (T.extraDocFiles s))
 {-# INLINE extraDocFiles #-}
+
+-- | @since 2.4
+componentModules :: Monoid r => ComponentName -> Getting r PackageDescription [ModuleName]
+componentModules cname = case cname of
+    CLibName         -> library  . traverse . getting explicitLibModules
+    CSubLibName name -> 
+      componentModules' name subLibraries (libName . non "") explicitLibModules
+    CFLibName   name -> 
+      componentModules' name foreignLibs  foreignLibName     foreignLibModules
+    CExeName    name -> 
+      componentModules' name executables  exeName            exeModules
+    CTestName   name -> 
+      componentModules' name testSuites   testName           testModules
+    CBenchName  name ->
+      componentModules' name benchmarks   benchmarkName      benchmarkModules
+  where
+    componentModules'
+        :: Monoid r
+        => UnqualComponentName
+        -> Traversal' PackageDescription [a]
+        -> Traversal' a UnqualComponentName
+        -> (a -> [ModuleName])
+        -> Getting r PackageDescription [ModuleName]
+    componentModules' name pdL nameL modules =
+        pdL
+      . traverse
+      . filtered ((== name) . view nameL)
+      . getting modules
+
+    -- This are easily wrongly used, so we have them here locally only.
+    non :: Eq a => a -> Lens' (Maybe a) a
+    non x afb s = f <$> afb (fromMaybe x s)
+        where f y = if x == y then Nothing else Just y
+
+    filtered :: (a -> Bool) -> Traversal' a a
+    filtered p f s = if p s then f s else pure s
+
+-- | @since 2.4
+componentBuildInfo :: ComponentName -> Traversal' PackageDescription BuildInfo
+componentBuildInfo cname = case cname of
+    CLibName         -> 
+      library  . traverse . libBuildInfo
+    CSubLibName name -> 
+      componentBuildInfo' name subLibraries (libName . non "") libBuildInfo
+    CFLibName   name -> 
+      componentBuildInfo' name foreignLibs  foreignLibName     foreignLibBuildInfo
+    CExeName    name -> 
+      componentBuildInfo' name executables  exeName            exeBuildInfo
+    CTestName   name -> 
+      componentBuildInfo' name testSuites   testName           testBuildInfo
+    CBenchName  name ->
+      componentBuildInfo' name benchmarks   benchmarkName      benchmarkBuildInfo
+  where
+    componentBuildInfo' :: UnqualComponentName
+                         -> Traversal' PackageDescription [a]
+                         -> Traversal' a UnqualComponentName
+                         -> Traversal' a BuildInfo
+                         -> Traversal' PackageDescription BuildInfo
+    componentBuildInfo' name pdL nameL biL =
+        pdL
+      . traverse
+      . filtered ((== name) . view nameL)
+      . biL
+
+    -- This are easily wrongly used, so we have them here locally only.
+    -- We have to repeat these, as everything is exported from this module.
+    non :: Eq a => a -> Lens' (Maybe a) a
+    non x afb s = f <$> afb (fromMaybe x s)
+        where f y = if x == y then Nothing else Just y
+
+    filtered :: (a -> Bool) -> Traversal' a a
+    filtered p f s = if p s then f s else pure s
diff --git a/cabal/Cabal/Distribution/Types/PackageId.hs b/cabal/Cabal/Distribution/Types/PackageId.hs
--- a/cabal/Cabal/Distribution/Types/PackageId.hs
+++ b/cabal/Cabal/Distribution/Types/PackageId.hs
@@ -13,9 +13,12 @@
          ( Version, nullVersion )
 
 import qualified Distribution.Compat.ReadP as Parse
+import qualified Distribution.Compat.CharParsing as P
 import qualified Text.PrettyPrint as Disp
 import Distribution.Compat.ReadP
 import Distribution.Text
+import Distribution.Parsec.Class
+    ( Parsec(..) )
 import Distribution.Pretty
 import Distribution.Types.PackageName
 
@@ -42,6 +45,10 @@
     n <- parse
     v <- (Parse.char '-' >> parse) <++ return nullVersion
     return (PackageIdentifier n v)
+
+instance Parsec PackageIdentifier where
+  parsec = PackageIdentifier <$> 
+    parsec <*> (P.char '-' *> parsec <|> pure nullVersion)
 
 instance NFData PackageIdentifier where
     rnf (PackageIdentifier name version) = rnf name `seq` rnf version
diff --git a/cabal/Cabal/Distribution/Types/PkgconfigDependency.hs b/cabal/Cabal/Distribution/Types/PkgconfigDependency.hs
--- a/cabal/Cabal/Distribution/Types/PkgconfigDependency.hs
+++ b/cabal/Cabal/Distribution/Types/PkgconfigDependency.hs
@@ -15,7 +15,7 @@
 import Distribution.Pretty
 import Distribution.Text
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import           Distribution.Compat.ReadP  ((<++))
 import qualified Distribution.Compat.ReadP  as Parse
 import           Text.PrettyPrint           ((<+>))
diff --git a/cabal/Cabal/Distribution/Types/PkgconfigName.hs b/cabal/Cabal/Distribution/Types/PkgconfigName.hs
--- a/cabal/Cabal/Distribution/Types/PkgconfigName.hs
+++ b/cabal/Cabal/Distribution/Types/PkgconfigName.hs
@@ -13,7 +13,7 @@
 import Distribution.Parsec.Class
 import Distribution.Text
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import qualified Distribution.Compat.ReadP as Parse
 import qualified Text.PrettyPrint as Disp
 
diff --git a/cabal/Cabal/Distribution/Types/SetupBuildInfo.hs b/cabal/Cabal/Distribution/Types/SetupBuildInfo.hs
--- a/cabal/Cabal/Distribution/Types/SetupBuildInfo.hs
+++ b/cabal/Cabal/Distribution/Types/SetupBuildInfo.hs
@@ -29,6 +29,8 @@
 
 instance Binary SetupBuildInfo
 
+instance NFData SetupBuildInfo where rnf = genericRnf
+
 instance Monoid SetupBuildInfo where
     mempty  = SetupBuildInfo [] False
     mappend = (<>)
diff --git a/cabal/Cabal/Distribution/Types/SourceRepo.hs b/cabal/Cabal/Distribution/Types/SourceRepo.hs
--- a/cabal/Cabal/Distribution/Types/SourceRepo.hs
+++ b/cabal/Cabal/Distribution/Types/SourceRepo.hs
@@ -20,7 +20,7 @@
 import Distribution.Parsec.Class
 import Distribution.Text
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import qualified Distribution.Compat.ReadP as Parse
 import qualified Text.PrettyPrint as Disp
 
@@ -83,7 +83,7 @@
   -- given the default is \".\" ie no subdirectory.
   repoSubdir   :: Maybe FilePath
 }
-  deriving (Eq, Generic, Read, Show, Typeable, Data)
+  deriving (Eq, Ord, Generic, Read, Show, Typeable, Data)
 
 emptySourceRepo :: RepoKind -> SourceRepo
 emptySourceRepo kind = SourceRepo
@@ -98,6 +98,8 @@
 
 instance Binary SourceRepo
 
+instance NFData SourceRepo where rnf = genericRnf
+
 -- | What this repo info is for, what it represents.
 --
 data RepoKind =
@@ -116,6 +118,8 @@
 
 instance Binary RepoKind
 
+instance NFData RepoKind where rnf = genericRnf
+
 -- | An enumeration of common source control systems. The fields used in the
 -- 'SourceRepo' depend on the type of repo. The tools and methods used to
 -- obtain and track the repo depend on the repo type.
@@ -126,6 +130,8 @@
   deriving (Eq, Generic, Ord, Read, Show, Typeable, Data)
 
 instance Binary RepoType
+
+instance NFData RepoType where rnf = genericRnf
 
 knownRepoTypes :: [RepoType]
 knownRepoTypes = [Darcs, Git, SVN, CVS
diff --git a/cabal/Cabal/Distribution/Types/TestSuite.hs b/cabal/Cabal/Distribution/Types/TestSuite.hs
--- a/cabal/Cabal/Distribution/Types/TestSuite.hs
+++ b/cabal/Cabal/Distribution/Types/TestSuite.hs
@@ -36,6 +36,8 @@
 
 instance Binary TestSuite
 
+instance NFData TestSuite where rnf = genericRnf
+
 instance Monoid TestSuite where
     mempty = TestSuite {
         testName      = mempty,
diff --git a/cabal/Cabal/Distribution/Types/TestSuiteInterface.hs b/cabal/Cabal/Distribution/Types/TestSuiteInterface.hs
--- a/cabal/Cabal/Distribution/Types/TestSuiteInterface.hs
+++ b/cabal/Cabal/Distribution/Types/TestSuiteInterface.hs
@@ -40,6 +40,7 @@
 
 instance Binary TestSuiteInterface
 
+instance NFData TestSuiteInterface where rnf = genericRnf
 
 instance Monoid TestSuiteInterface where
     mempty  =  TestSuiteUnsupported (TestTypeUnknown mempty nullVersion)
diff --git a/cabal/Cabal/Distribution/Types/TestType.hs b/cabal/Cabal/Distribution/Types/TestType.hs
--- a/cabal/Cabal/Distribution/Types/TestType.hs
+++ b/cabal/Cabal/Distribution/Types/TestType.hs
@@ -24,6 +24,8 @@
 
 instance Binary TestType
 
+instance NFData TestType where rnf = genericRnf
+
 knownTestTypes :: [TestType]
 knownTestTypes = [ TestTypeExe (mkVersion [1,0])
                  , TestTypeLib (mkVersion [0,9]) ]
diff --git a/cabal/Cabal/Distribution/Types/UnitId.hs b/cabal/Cabal/Distribution/Types/UnitId.hs
--- a/cabal/Cabal/Distribution/Types/UnitId.hs
+++ b/cabal/Cabal/Distribution/Types/UnitId.hs
@@ -19,7 +19,7 @@
 import Distribution.Utils.ShortText
 
 import qualified Distribution.Compat.ReadP as Parse
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import Distribution.Pretty
 import Distribution.Parsec.Class
 import Distribution.Text
@@ -68,7 +68,7 @@
 newtype UnitId = UnitId ShortText
   deriving (Generic, Read, Show, Eq, Ord, Typeable, Data, NFData)
 
-{-# DEPRECATED InstalledPackageId "Use UnitId instead" #-}
+{-# DEPRECATED InstalledPackageId "Use UnitId instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 type InstalledPackageId = UnitId
 
 instance Binary UnitId
diff --git a/cabal/Cabal/Distribution/Types/Version.hs b/cabal/Cabal/Distribution/Types/Version.hs
--- a/cabal/Cabal/Distribution/Types/Version.hs
+++ b/cabal/Cabal/Distribution/Types/Version.hs
@@ -9,6 +9,10 @@
     nullVersion,
     alterVersion,
     version0,
+
+    -- ** Backwards compatibility
+    showVersion,
+
     -- * Internal
     validVersion,
     ) where
@@ -17,15 +21,16 @@
 import Distribution.Compat.Prelude
 import Prelude ()
 
+import Distribution.CabalSpecVersion
 import Distribution.Parsec.Class
 import Distribution.Pretty
 import Distribution.Text
 
-import qualified Data.Version               as Base
-import qualified Distribution.Compat.Parsec as P
-import qualified Distribution.Compat.ReadP  as Parse
-import qualified Text.PrettyPrint           as Disp
-import qualified Text.Read                  as Read
+import qualified Data.Version                    as Base
+import qualified Distribution.Compat.CharParsing as P
+import qualified Distribution.Compat.ReadP       as Parse
+import qualified Text.PrettyPrint                as Disp
+import qualified Text.Read                       as Read
 
 -- | A 'Version' represents the version of a software entity.
 --
@@ -92,8 +97,25 @@
                                 (map Disp.int $ versionNumbers ver))
 
 instance Parsec Version where
-    parsec = mkVersion <$> P.sepBy1 P.integral (P.char '.') <* tags
+    parsec = do
+        digit <- digitParser <$> askCabalSpecVersion
+        mkVersion <$> P.sepBy1 digit (P.char '.') <* tags
       where
+        digitParser v
+            | v >= CabalSpecV2_0 = P.integral
+            | otherwise          = (some d >>= toNumber) P.<?> "non-leading-zero integral"
+          where
+            toNumber :: CabalParsing m => [Int] -> m Int
+            toNumber [0] = return 0
+            toNumber xs@(0:_) = do
+                parsecWarning PWTVersionLeadingZeros "Version digit with leading zero. Use cabal-version: 2.0 or later to write such versions. For more information see https://github.com/haskell/cabal/issues/5092"
+                return $ foldl' (\a b -> a * 10 + b) 0 xs
+            toNumber xs = return $ foldl' (\a b -> a * 10 + b) 0 xs
+
+            d :: P.CharParsing m => m Int
+            d = f <$> P.satisfyRange '0' '9'
+            f c = ord c - ord '0'
+
         tags = do
             ts <- many $ P.char '-' *> some (P.satisfy isAlphaNum)
             case ts of
@@ -176,8 +198,8 @@
 inWord16 :: Int -> Bool
 inWord16 x = (fromIntegral x :: Word) <= 0xffff
 
--- | Variant of 'Version' which converts a "Data.Version" 'Version'
--- into Cabal's 'Version' type.
+-- | Variant of 'mkVersion' which converts a "Data.Version"
+-- 'Base.Version' into Cabal's 'Version' type.
 --
 -- @since 2.0.0.2
 mkVersion' :: Base.Version -> Version
@@ -228,4 +250,6 @@
 validVersion :: Version -> Bool
 validVersion v = v /= nullVersion && all (>=0) (versionNumbers v)
 
-
+showVersion :: Version -> String
+showVersion = prettyShow
+{-# DEPRECATED showVersion "Use prettyShow. This function will be removed in Cabal-3.0 (estimated Mar 2019)" #-}
diff --git a/cabal/Cabal/Distribution/Types/VersionRange.hs b/cabal/Cabal/Distribution/Types/VersionRange.hs
--- a/cabal/Cabal/Distribution/Types/VersionRange.hs
+++ b/cabal/Cabal/Distribution/Types/VersionRange.hs
@@ -1,9 +1,9 @@
 {-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE DeriveFunctor #-}
-{-# LANGUAGE DeriveFoldable #-}
-{-# LANGUAGE DeriveTraversable #-}
-{-# LANGUAGE DeriveGeneric #-}
-{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE DeriveFoldable     #-}
+{-# LANGUAGE DeriveFunctor      #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE DeriveTraversable  #-}
+{-# LANGUAGE FlexibleContexts   #-}
 module Distribution.Types.VersionRange (
     -- * Version ranges
     VersionRange(..),
@@ -42,17 +42,19 @@
     ) where
 
 import Distribution.Compat.Prelude
-import Prelude ()
 import Distribution.Types.Version
+import Prelude ()
 
-import Distribution.Pretty
+import Distribution.CabalSpecVersion
 import Distribution.Parsec.Class
+import Distribution.Pretty
 import Distribution.Text
-import Text.PrettyPrint ((<+>))
+import Text.PrettyPrint          ((<+>))
 
-import qualified Text.PrettyPrint as Disp
-import qualified Distribution.Compat.ReadP as Parse
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
+import qualified Distribution.Compat.DList       as DList
+import qualified Distribution.Compat.ReadP       as Parse
+import qualified Text.PrettyPrint                as Disp
 
 data VersionRange
   = AnyVersion
@@ -411,37 +413,95 @@
                         return (intersectVersionRanges f t)
                      <|>
                      return f)
-        factor = P.choice
-            $ parens expr
-            : parseAnyVersion
-            : parseNoVersion
-            : parseWildcardRange
-            : map parseRangeOp rangeOps
-        parseAnyVersion    = P.string "-any" >> return anyVersion
-        parseNoVersion     = P.string "-none" >> return noVersion
+        factor = parens expr <|> prim
 
-        parseWildcardRange = P.try $ do
-          _ <- P.string "=="
-          P.spaces
-          branch <- some (P.integral <* P.char '.')
-          _ <- P.char '*'
-          return (withinVersion (mkVersion branch))
+        prim = do
+            op <- P.munch1 (`elem` "<>=^-") P.<?> "operator"
+            case op of
+                "-" -> anyVersion <$ P.string "any" <|> P.string "none" *> noVersion'
 
+                "==" -> do
+                    P.spaces
+                    (wild, v) <- verOrWild
+                    pure $ (if wild then withinVersion else thisVersion) v
+
+                _ -> do
+                    P.spaces
+                    (wild, v) <- verOrWild
+                    when wild $ P.unexpected $
+                        "wild-card version after non-== operator: " ++ show op
+                    case op of
+                        ">="  -> pure $ orLaterVersion v
+                        "<"   -> pure $ earlierVersion v
+                        "^>=" -> majorBoundVersion' v
+                        "<="  -> pure $ orEarlierVersion v
+                        ">"   -> pure $ laterVersion v
+                        _ -> fail $ "Unknown version operator " ++ show op
+
+        -- Note: There are other features:
+        -- && and || since 1.8
+        -- x.y.* (wildcard) since 1.6
+
+        -- -none version range is available since 1.22
+        noVersion' = do
+            csv <- askCabalSpecVersion
+            if csv >= CabalSpecV1_22
+            then pure noVersion
+            else fail $ unwords
+                [ "-none version range used."
+                , "To use this syntax the package needs to specify at least 'cabal-version: 1.22'."
+                , "Alternatively, if broader compatibility is important then use"
+                , "<0 or other empty range."
+                ]
+
+        -- ^>= is available since 2.0
+        majorBoundVersion' v = do
+            csv <- askCabalSpecVersion
+            if csv >= CabalSpecV2_0
+            then pure $ majorBoundVersion v
+            else fail $ unwords
+                [ "major bounded version syntax (caret, ^>=) used."
+                , "To use this syntax the package need to specify at least 'cabal-version: 2.0'."
+                , "Alternatively, if broader compatibility is important then use:"
+                , prettyShow $ eliminateMajorBoundSyntax $ majorBoundVersion v
+                ]
+          where
+            eliminateMajorBoundSyntax = hyloVersionRange embed projectVersionRange
+            embed (MajorBoundVersionF u) = intersectVersionRanges
+                (orLaterVersion u) (earlierVersion (majorUpperBound u))
+            embed vr = embedVersionRange vr
+
+        -- either wildcard or normal version
+        verOrWild :: CabalParsing m => m (Bool, Version)
+        verOrWild = do
+            x <- P.integral
+            verLoop (DList.singleton x)
+
+        -- trailing: wildcard (.y.*) or normal version (optional tags) (.y.z-tag)
+        verLoop :: CabalParsing m => DList.DList Int -> m (Bool, Version)
+        verLoop acc = verLoop' acc <|> (tags *> pure (False, mkVersion (DList.toList acc)))
+
+        verLoop' :: CabalParsing m => DList.DList Int -> m (Bool, Version)
+        verLoop' acc = do
+            _ <- P.char '.'
+            let digit = P.integral >>= verLoop . DList.snoc acc
+            let wild  = (True, mkVersion (DList.toList acc)) <$ P.char '*'
+            digit <|> wild
+
         parens p = P.between
-            (P.char '(' >> P.spaces)
+            ((P.char '(' P.<?> "opening paren") >> P.spaces)
             (P.char ')' >> P.spaces)
             (do a <- p
                 P.spaces
                 return (VersionRangeParens a))
 
-        -- TODO: make those non back-tracking
-        parseRangeOp (s,f) = P.try (P.string s *> P.spaces *> fmap f parsec)
-        rangeOps = [ ("<",  earlierVersion),
-                     ("<=", orEarlierVersion),
-                     (">",  laterVersion),
-                     (">=", orLaterVersion),
-                     ("^>=", majorBoundVersion),
-                     ("==", thisVersion) ]
+        tags :: CabalParsing m => m ()
+        tags = do
+            ts <- many $ P.char '-' *> some (P.satisfy isAlphaNum)
+            case ts of
+                []      -> pure ()
+                (_ : _) -> parsecWarning PWTVersionTag "version with tags"
+
 
 instance Text VersionRange where
   parse = expr
diff --git a/cabal/Cabal/Distribution/Utils/Generic.hs b/cabal/Cabal/Distribution/Utils/Generic.hs
--- a/cabal/Cabal/Distribution/Utils/Generic.hs
+++ b/cabal/Cabal/Distribution/Utils/Generic.hs
@@ -35,6 +35,8 @@
         toUTF8BS,
         toUTF8LBS,
 
+        validateUTF8,
+
         -- ** File I/O
         readUTF8File,
         withUTF8FileContents,
@@ -80,6 +82,7 @@
 
 import Distribution.Utils.String
 
+import Data.Bits ((.&.), (.|.), shiftL)
 import Data.List
     ( isInfixOf )
 import Data.Ord
@@ -189,6 +192,46 @@
 toUTF8LBS :: String -> BS.ByteString
 toUTF8LBS = BS.pack . encodeStringUtf8
 
+-- | Check that strict 'ByteString' is valid UTF8. Returns 'Just offset' if it's not.
+validateUTF8 :: SBS.ByteString -> Maybe Int
+validateUTF8 = go 0 where
+    go off bs = case SBS.uncons bs of
+        Nothing -> Nothing
+        Just (c, bs')
+            | c <= 0x7F -> go (off + 1) bs'
+            | c <= 0xBF -> Just off
+            | c <= 0xDF -> twoBytes off c bs'
+            | c <= 0xEF -> moreBytes off 3 0x800     bs' (fromIntegral $ c .&. 0xF)
+            | c <= 0xF7 -> moreBytes off 4 0x10000   bs' (fromIntegral $ c .&. 0x7)
+            | c <= 0xFB -> moreBytes off 5 0x200000  bs' (fromIntegral $ c .&. 0x3)
+            | c <= 0xFD -> moreBytes off 6 0x4000000 bs' (fromIntegral $ c .&. 0x1)
+            | otherwise -> Just off
+
+    twoBytes off c0 bs = case SBS.uncons bs of
+        Nothing        -> Just off
+        Just (c1, bs')
+            | c1 .&. 0xC0 == 0x80 ->
+                if d >= (0x80 :: Int)
+                then go (off + 2) bs'
+                else Just off
+            | otherwise -> Just off
+          where
+            d = (fromIntegral (c0 .&. 0x1F) `shiftL` 6) .|. fromIntegral (c1 .&. 0x3F)
+
+    moreBytes :: Int -> Int -> Int -> SBS.ByteString -> Int -> Maybe Int
+    moreBytes off 1 overlong cs' acc
+      | overlong <= acc, acc <= 0x10FFFF, acc < 0xD800 || 0xDFFF < acc
+      = go (off + 1) cs'
+
+      | otherwise
+      = Just off
+
+    moreBytes off byteCount overlong bs acc = case SBS.uncons bs of
+        Just (cn, bs') | cn .&. 0xC0 == 0x80 ->
+            moreBytes (off + 1) (byteCount-1) overlong bs' ((acc `shiftL` 6) .|. fromIntegral cn .&. 0x3F)
+        _ -> Just off
+        
+
 -- | Ignore a Unicode byte order mark (BOM) at the beginning of the input
 --
 ignoreBOM :: String -> String
@@ -353,7 +396,7 @@
 -- False
 --
 isAsciiAlphaNum :: Char -> Bool
-isAsciiAlphaNum c = isAscii c ||  isDigit c
+isAsciiAlphaNum c = isAscii c && isAlphaNum c
 
 unintersperse :: Char -> String -> [String]
 unintersperse mark = unfoldr unintersperse1 where
diff --git a/cabal/Cabal/Distribution/Utils/IOData.hs b/cabal/Cabal/Distribution/Utils/IOData.hs
--- a/cabal/Cabal/Distribution/Utils/IOData.hs
+++ b/cabal/Cabal/Distribution/Utils/IOData.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE CPP #-}
-
 -- | @since 2.2.0
 module Distribution.Utils.IOData
     ( -- * 'IOData' & 'IODataMode' type
@@ -33,11 +31,7 @@
 
 instance NFData IOData where
     rnf (IODataText s) = rnf s
-#if MIN_VERSION_bytestring(0,10,0)
     rnf (IODataBinary bs) = rnf bs
-#else
-    rnf (IODataBinary bs) = rnf (BS.length bs)
-#endif
 
 data IODataMode = IODataModeText | IODataModeBinary
 
diff --git a/cabal/Cabal/Distribution/Utils/String.hs b/cabal/Cabal/Distribution/Utils/String.hs
--- a/cabal/Cabal/Distribution/Utils/String.hs
+++ b/cabal/Cabal/Distribution/Utils/String.hs
@@ -41,7 +41,7 @@
 
     moreBytes :: Int -> Int -> [Word8] -> Int -> [Char]
     moreBytes 1 overlong cs' acc
-      | overlong <= acc, acc <= 0x10FFFF, (acc < 0xD800 || 0xDFFF < acc)
+      | overlong <= acc, acc <= 0x10FFFF, acc < 0xD800 || 0xDFFF < acc
       = chr acc : go cs'
 
       | otherwise
diff --git a/cabal/Cabal/Distribution/Version.hs b/cabal/Cabal/Distribution/Version.hs
--- a/cabal/Cabal/Distribution/Version.hs
+++ b/cabal/Cabal/Distribution/Version.hs
@@ -22,6 +22,9 @@
   nullVersion,
   alterVersion,
 
+  -- ** Backwards compatibility
+  showVersion,
+
   -- * Version ranges
   VersionRange(..),
 
diff --git a/cabal/Cabal/Language/Haskell/Extension.hs b/cabal/Cabal/Language/Haskell/Extension.hs
--- a/cabal/Cabal/Language/Haskell/Extension.hs
+++ b/cabal/Cabal/Language/Haskell/Extension.hs
@@ -33,7 +33,7 @@
 import Distribution.Pretty
 import Distribution.Text
 
-import qualified Distribution.Compat.Parsec as P
+import qualified Distribution.Compat.CharParsing as P
 import qualified Distribution.Compat.ReadP as Parse
 import qualified Text.PrettyPrint as Disp
 
@@ -62,6 +62,8 @@
 
 instance Binary Language
 
+instance NFData Language where rnf = genericRnf
+
 knownLanguages :: [Language]
 knownLanguages = [Haskell98, Haskell2010]
 
@@ -92,7 +94,7 @@
 -- Note: if you add a new 'KnownExtension':
 --
 -- * also add it to the Distribution.Simple.X.languageExtensions lists
---   (where X is each compiler: GHC, JHC, LHC, UHC, HaskellSuite)
+--   (where X is each compiler: GHC, UHC, HaskellSuite)
 --
 -- | This represents language extensions beyond a base 'Language' definition
 -- (such as 'Haskell98') that are supported by some implementations, usually
@@ -116,6 +118,8 @@
 
 instance Binary Extension
 
+instance NFData Extension where rnf = genericRnf
+
 data KnownExtension =
 
   -- | Allow overlapping class instances, provided there is a unique
@@ -805,12 +809,26 @@
   -- | Allow use of hexadecimal literal notation for floating-point values.
   | HexFloatLiterals
 
+  -- | Allow @do@ blocks etc. in argument position.
+  | BlockArguments
+
+  -- | Allow use of underscores in numeric literals.
+  | NumericUnderscores
+
+  -- | Allow @forall@ in constraints.
+  | QuantifiedConstraints
+
+  -- | Have @*@ refer to @Type@.
+  | StarIsType
+
   deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded, Typeable, Data)
 
 instance Binary KnownExtension
 
+instance NFData KnownExtension where rnf = genericRnf
+
 {-# DEPRECATED knownExtensions
-   "KnownExtension is an instance of Enum and Bounded, use those instead." #-}
+   "KnownExtension is an instance of Enum and Bounded, use those instead. This symbol will be removed in Cabal-3.0 (est. Mar 2019)." #-}
 knownExtensions :: [KnownExtension]
 knownExtensions = [minBound..maxBound]
 
diff --git a/cabal/Cabal/Makefile b/cabal/Cabal/Makefile
--- a/cabal/Cabal/Makefile
+++ b/cabal/Cabal/Makefile
@@ -1,5 +1,5 @@
 
-VERSION=2.1.0.0
+VERSION=2.4.1.0
 
 #KIND=devel
 KIND=rc
@@ -101,12 +101,12 @@
 	mkdir -p $(DISTLOC)/Cabal-$(VERSION)/doc
 	cp -r dist/doc/html $(DISTLOC)/Cabal-$(VERSION)/doc/API
 	cp -r dist/doc/users-guide $(DISTLOC)/Cabal-$(VERSION)/doc/
-	cp changelog $(DISTLOC)/Cabal-$(VERSION)/
+	cp ChangeLog.md $(DISTLOC)/Cabal-$(VERSION)/
 	tar --format=ustar -C $(DISTLOC) -czf $(DISTLOC)/Cabal-$(VERSION).tar.gz Cabal-$(VERSION)
 	mkdir $(DISTLOC)/doc
 	mv $(DISTLOC)/Cabal-$(VERSION)/doc/users-guide $(DISTLOC)/doc
 	mv $(DISTLOC)/Cabal-$(VERSION)/doc/API $(DISTLOC)/doc
-	mv $(DISTLOC)/Cabal-$(VERSION)/changelog $(DISTLOC)/
+	mv $(DISTLOC)/Cabal-$(VERSION)/ChangeLog.md $(DISTLOC)/
 	rm -r $(DISTLOC)/Cabal-$(VERSION)/
 	@echo "Cabal tarball built: $(DIST_STAMP)"
 	@echo "Release fileset prepared: $(DISTLOC)/"
diff --git a/cabal/Cabal/README.md b/cabal/Cabal/README.md
--- a/cabal/Cabal/README.md
+++ b/cabal/Cabal/README.md
@@ -155,21 +155,10 @@
 Credits
 =======
 
-Cabal developers (in alphabetical order):
-
-- Krasimir Angelov
-- Bjorn Bringert
-- Duncan Coutts
-- Isaac Jones
-- David Himmelstrup ("Lemmih")
-- Simon Marlow
-- Ross Patterson
-- Thomas Schilling
-- Martin Sjögren
-- Malcolm Wallace
-- and nearly 30 other people have contributed occasional patches
+See the `AUTHORS` file.
 
-Cabal specification authors:
+Authors of the [original Cabal
+specification](https://www.haskell.org/cabal/proposal/pkg-spec.pdf):
 
 - Isaac Jones
 - Simon Marlow
diff --git a/cabal/Cabal/changelog b/cabal/Cabal/changelog
deleted file mode 100644
--- a/cabal/Cabal/changelog
+++ /dev/null
@@ -1,702 +0,0 @@
--*-change-log-*-
-
-2.2.0.0 (current development version)
-	* Cabal does not try to build an empty set of `inputModules` (#4890).
-	* Add `HexFloatLiterals` to `KnownExtension`
-	* Added `virtual-module` field, to allow modules that are not built
-	  but registered (#4875).
-	* `copyComponent` and `installIncludeFiles` will look for include
-	  headers in the build directory ('dist/build/...' by default)
-	  as well (#4866).
-	* Added cxx-options and cxx-sources build info fields for seperate
-	  compilation of C++ source files (#3700)
-	* Remove unused '--allow-newer'/'--allow-older' support (#4527)
-	* Change `FlagAssignment` to be an opaque `newtype`.
-	* Change `rawSystemStdInOut` to use proper type to represent
-	  binary and textual data; new 'Distribution.Utils.IOData' module;
-	  removed obsolete 'startsWithBOM', 'fileHasBOM', 'fromUTF8',
-	  and 'toUTF8' functions; add new `toUTF8BS`/`toUTF8LBS`
-	  encoding functions. (#4666)
-	* Warn about `.cabal` file-name not matching package name
-	  in 'cabal check' (#4592)
-	* By default 'ar' program receives arguments via '@file' format.
-	  Old behavior can be restored with '--ar-does-not-support-at-arguments'
-	  argument to 'configure' or 'install'. (#4596)
-	* Added '.Lens' modules, with optics for package description data
-	  types. (#4701)
-	* Support for GHC's numeric -g debug levels (#4673).
-	* Added elif-conditionals to .cabal syntax (#4750).
-	* Support for building with Win32 version 2.6 (#4835).
-	* Compilation with section splitting is now supported via the
-	'--enable-split-sections' flag (#4819)
-	* TODO
-
-2.0.1.1 Mikhail Glushenkov <mikhail.glushenkov@gmail.com> December 2017
-	* Don't pass `other-modules` to stub executable for detailed-0.9
-	(#4918).
-	* Hpc: Use relative .mix search paths (#4917).
-
-2.0.1.0 Mikhail Glushenkov <mikhail.glushenkov@gmail.com> November 2017
-	* Support for GHC's numeric -g debug levels (#4673).
-	* Added a new 'Distribution.Verbosity.modifyVerbosity' combinator
-	(#4724).
-	* Added a new 'cabal check' warning about unused, undeclared or
-	non-Unicode flags.  Also, it warns about leading dash, which is
-	unusable but accepted if it's unused in conditionals. (#4687)
-	* Modify `allBuildInfo` to include foreign library info (#4763).
-	* Documentation fixes.
-
-2.0.0.2 Mikhail Glushenkov <mikhail.glushenkov@gmail.com> July 2017
-	* See http://coldwa.st/e/blog/2017-09-09-Cabal-2-0.html
-	  for more detailed release notes.
-	* The 2.0 migration guide gives advice on adapting Custom setup
-	  scripts to backwards-incompatible changes in this release:
-	  https://github.com/haskell/cabal/wiki/2.0-migration-guide
-	* Add CURRENT_PACKAGE_VERSION to cabal_macros.h (#4319)
-	* Dropped support for versions of GHC earlier than 6.12 (#3111).
-	* GHC compatibility window for the Cabal library has been extended
-	  to five years (#3838).
-	* Convenience/internal libraries are now supported (#269).
-	  An internal library is declared using the stanza "library
-	  'libname'".  Packages which use internal libraries can
-	  result in multiple registrations; thus '--gen-pkg-config'
-	  can now output a directory of registration scripts rather than
-	  a single file.
-	* Backwards incompatible change to preprocessor interface:
-	  the function in 'PPSuffixHandler' now takes an additional
-	  'ComponentLocalBuildInfo' specifying the build information
-	  of the component being preprocessed.
-	* Backwards incompatible change to 'cabal_macros.h' (#1893): we now
-	  generate a macro file for each component which contains only
-	  information about the direct dependencies of that component.
-	  Consequently, 'dist/build/autogen/cabal_macros.h' contains
-	  only the macros for the library, and is not generated if a
-	  package has no library; to find the macros for an executable
-	  named 'foobar', look in 'dist/build/foobar/autogen/cabal_macros.h'.
-	  Similarly, if you used 'autogenModulesDir' you should now
-	  use 'autogenComponentModulesDir', which now requires a
-	  'ComponentLocalBuildInfo' argument as well in order to
-	  disambiguate which component the autogenerated files are for.
-	* Backwards incompatible change to 'Component': 'TestSuite' and
-	  'Benchmark' no longer have 'testEnabled' and
-	  'benchmarkEnabled'.  If you used
-	  'enabledTests' or 'enabledBenchmarks', please instead use
-	  'enabledTestLBIs' and 'enabledBenchLBIs'
-	  (you will need a 'LocalBuildInfo' for these functions.)
-	  Additionally, the semantics of 'withTest' and 'withBench'
-	  have changed: they now iterate over all buildable
-	  such components, regardless of whether or not they have
-	  been enabled; if you only want enabled components,
-	  use 'withTestLBI' and 'withBenchLBI'.
-	  'finalizePackageDescription' is deprecated:
-	  its replacement 'finalizePD' now takes an extra argument
-	  'ComponentRequestedSpec' which specifies what components
-	  are to be enabled: use this instead of modifying the
-	  'Component' in a 'GenericPackageDescription'.  (As
-	  it's not possible now, 'finalizePackageDescription'
-	  will assume tests/benchmarks are disabled.)
-	  If you only need to test if a component is buildable
-	  (i.e., it is marked buildable in the Cabal file)
-	  use the new function 'componentBuildable'.
-	* Backwards incompatible change to 'PackageName' (#3896):
-	  'PackageName' is now opaque; conversion to/from 'String' now works
-	  via (old) 'unPackageName' and (new) 'mkPackageName' functions.
-	* Backwards incompatible change to 'ComponentId' (#3917):
-	  'ComponentId' is now opaque; conversion to/from 'String' now works
-	  via 'unComponentId' and 'mkComponentId' functions.
-	* Backwards incompatible change to 'AbiHash' (#3921):
-	  'AbiHash' is now opaque; conversion to/from 'String' now works
-	  via 'unAbiHash' and 'mkAbiHash' functions.
-	* Backwards incompatible change to 'FlagName' (#4062):
-	  'FlagName' is now opaque; conversion to/from 'String' now works
-	  via 'unFlagName' and 'mkFlagName' functions.
-	* Backwards incompatible change to 'Version' (#3905):
-	  Version is now opaque; conversion to/from '[Int]' now works
-	  via 'versionNumbers' and 'mkVersion' functions.
-	* Add support for `--allow-older` (dual to `--allow-newer`) (#3466)
-	* Improved an error message for process output decoding errors
-	(#3408).
-	* 'getComponentLocalBuildInfo', 'withComponentsInBuildOrder'
-	  and 'componentsInBuildOrder' are deprecated in favor of a
-	  new interface in "Distribution.Types.LocalBuildInfo".
-	* New 'autogen-modules' field. Modules that are built automatically at
-	  setup, like Paths_PACKAGENAME or others created with a build-type
-	  custom, appear on 'other-modules' for the Library, Executable,
-	  Test-Suite or Benchmark stanzas or also on 'exposed-modules' for
-	  libraries but are not really on the package when distributed. This
-	  makes commands like sdist fail because the file is not found, so with
-	  this new field modules that appear there are treated the same way as
-	  Paths_PACKAGENAME was and there is no need to create complex build
-	  hooks. Just add the module names on 'other-modules' and
-	  'exposed-modules' as always and on the new 'autogen-modules' besides.
-	(#3656).
-	* New './Setup configure' flag '--cabal-file', allowing multiple
-	.cabal files in a single directory (#3553). Primarily intended for
-	internal use.
-	* Macros in 'cabal_macros.h' are now ifndef'd, so that they
-	don't cause an error if the macro is already defined. (#3041)
-	* './Setup configure' now accepts a single argument specifying
-	  the component to be configured.  The semantics of this mode
-	  of operation are described in
-	  <https://github.com/ghc-proposals/ghc-proposals/pull/4>
-	* Internal 'build-tools' dependencies are now added to PATH
-	  upon invocation of GHC, so that they can be conveniently
-	  used via `-pgmF`. (#1541)
-	* Add support for new caret-style version range operator `^>=` (#3705)
-	* Verbosity `-v` now takes an extended format which allows
-	  specifying exactly what you want to be logged.  The format is
-	  "[silent|normal|verbose|debug] flags", where flags is a space
-	  separated list of flags. At the moment, only the flags
-	  +callsite and +callstack are supported; these report the
-	  call site/stack of a logging output respectively (these
-	  are only supported if Cabal is built with GHC 8.0/7.10.2
-	  or greater, respectively).
-	* New `Distribution.Utils.ShortText.ShortText` type for representing
-	  short text strings compactly (#3898)
-	* Cabal no longer supports using a version bound to disambiguate
-	  between an internal and external package (#4020).  This should
-	  not affect many people, as this mode of use already did not
-	  work with the dependency solver.
-	* Support for "foreign libraries" (#2540), which are Haskell
-	  libraries intended to be used by foreign languages like C.
-	  Foreign libraries only work with GHC 7.8 and later.
-	* Added a technical preview version of integrated doctest support (#4480).
-	* Added a new 'scope' field to the executable stanza. Executables
-	  with 'scope: private' get installed into
-	  $libexecdir/$libexecsubdir. Additionally $libexecdir now has a
-	  subdir structure similar to $lib(sub)dir to allow installing
-	  private executables of different packages and package versions
-	  alongside one another.  Private executables are those that are
-	  expected to be run by other programs rather than users. (#3461)
-
-1.24.2.0 Mikhail Glushenkov <mikhail.glushenkov@gmail.com> December 2016
-	* Fixed a bug in the handling of non-buildable components (#4094).
-	* Reverted a PVP-noncompliant API change in 1.24.1.0 (#4123).
-	* Bumped the directory upper bound to < 1.4 (#4158).
-
-1.24.1.0 Ryan Thomas <ryan@ryant.org> October 2016
-	* API addition: 'differenceVersionRanges' (#3519).
-	* Fixed reexported-modules display mangling (#3928).
-	* Check that the correct cabal-version is specified when the
-	extra-doc-files field is present (#3825).
-	* Fixed an incorrect invocation of GetShortPathName that was
-	causing build failures on Windows (#3649).
-	* Linker flags are now set correctly on GHC >= 7.8 (#3443).
-
-1.24.0.0 Ryan Thomas <ryan@ryant.org> March 2016
-	* Support GHC 8.
-	* Deal with extra C sources from preprocessors (#238).
-	* Include cabal_macros.h when running c2hs (#2600).
-	* Don't recompile C sources unless needed (#2601).
-	* Read 'builddir' option from 'CABAL_BUILDDIR' environment variable.
-	* Add '--profiling-detail=$level' flag with a default for libraries
-	  and executables of 'exported-functions' and 'toplevel-functions'
-	  respectively (GHC's '-fprof-auto-{exported,top}' flags) (#193).
-	* New 'custom-setup' stanza to specify setup deps. Setup is also built
-	  with the cabal_macros.h style macros, for conditional compilation.
-	* Support Haddock response files (#2746).
-	* Fixed a bug in the Text instance for Platform (#2862).
-	* New 'setup haddock' option: '--for-hackage' (#2852).
-	* New --show-detail=direct; like streaming, but allows the test
-	  program to detect that is connected to a terminal, and works
-	  reliable with a non-threaded runtime (#2911, and serves as a
-	  work-around for #2398)
-	* Library support for multi-instance package DBs (#2948).
-	* Improved the './Setup configure' solver (#3082, #3076).
-	* The '--allow-newer' option can be now used with './Setup
-	configure' (#3163).
-	* Added a way to specify extra locations to find OS X frameworks
-	in ('extra-framework-dirs'). Can be used both in .cabal files and
-	as an argument to './Setup configure' (#3158).
-	* Macros 'VERSION_$pkgname' and 'MIN_VERSION_$pkgname' are now
-	also generated for the current package. (#3235).
-	* Backpack is supported!  Two new fields supported in Cabal
-	files: signatures and mixins; and a new flag
-	to setup scripts, '--instantiate-with'.  See
-	https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst
-	for more details.
-
-1.22.8.0 Ryan Thomas <ryan@ryant.org> March 2016
-	* Distribution.Simple.Setup: remove job cap. Fixes #3191.
-	* Check all object file suffixes for recompilation. Fixes #3128.
-	* Move source files under 'src/'. Fixes #3003.
-
-1.22.7.0 Ryan Thomas <ryan@ryant.org> January 2016
-	* Backport #3012 to the 1.22 branch
-	* Cabal.cabal: change build-type to Simple
-	* Add foldl' import
-	* The Cabal part for fully gcc-like response files
-
-1.22.6.0 Ryan Thomas <ryan@ryant.org> December 2015
-	* Relax upper bound to allow upcoming binary-0.8
-
-1.22.5.0 Ryan Thomas <ryan@ryant.org> November 2015
-	* Don't recompile C sources unless needed (#2601). (Luke Iannini)
-	* Support Haddock response files.
-	* Add frameworks when linking a dynamic library.
-
-1.22.4.0 Ryan Thomas <ryan@ryant.org> June 2015
-	* Add libname install-dirs variable, use it by default. Fixes #2437. (Edward Z. Yang)
-	* Reduce temporary directory name length, fixes #2502. (Edward Z. Yang)
-	* Workaround for #2527. (Mikhail Glushenkov)
-
-1.22.3.0 Ryan Thomas <ryan@ryant.org> April 2015
-	* Fix for the ghcjs-pkg version number handling (Luite Stegeman)
-	* filterConfigureFlags: filter more flags (Mikhail Glushenkov)
-	* Cabal check will fail on -fprof-auto passed as a ghc-option - Fixes #2479 (John Chee)
-
-1.22.2.0 Ryan Thomas <ryan@ryant.org> March 2015
-	* Don't pass '--{en,dis}able-profiling' to old setup.
-	* Add -Wall police
-	* Fix dependencies on 'old-time'
-	* Fix test interface detailed-0.9 with GHC 7.10
-	* Fix HPC tests with GHC 7.10
-	* Make sure to pass the package key to ghc
-	* Use --package-{name|version} when available for Haddock when available
-	* Put full package name and version in library names
-	* Fully specify package key format, so external tools can generate it.
-
-1.22.0.0 Johan Tibell <johan.tibell@gmail.com> January 2015
-	* Support GHC 7.10.
-	* Experimental support for emitting DWARF debug info.
-	* Preliminary support for relocatable packages.
-	* Allow cabal to be used inside cabal exec enviroments.
-	* hpc: support mutliple "ways" (e.g. profiling and vanilla).
-	* Support GHCJS.
-	* Improved command line documentation.
-	* Add '-none' constraint syntax for version ranges (#2093).
-	* Make the default doc index file path compiler/arch/os-dependent
-	(#2136).
-	* Warn instead of dying when generating documentation and hscolour
-	isn't installed (455f51622fa38347db62197a04bb0fa5b928ff17).
-	* Support the new BinaryLiterals extension
-	(1f25ab3c5eff311ada73c6c987061b80e9bbebd9).
-	* Warn about 'ghc-prof-options: -auto-all' in 'cabal check' (#2162).
-	* Add preliminary support for multiple instances of the same package
-	version installed side-by-side (#2002).
-	* New binary build config format - faster build times (#2076).
-	* Support module thinning and renaming (#2038).
-	* Add a new license type: UnspecifiedLicense (#2141).
-	* Remove support for Hugs and nhc98 (#2168).
-	* Invoke 'tar' with '--formar ustar' if possible in 'sdist' (#1903).
-	* Replace --enable-library-coverage with --enable-coverage, which
-	enables program coverage for all components (#1945).
-	* Suggest that `ExitFailure 9` is probably due to memory
-	exhaustion (#1522).
-	* Drop support for Haddock < 2.0 (#1808, #1718).
-	* Make 'cabal test'/'cabal bench' build only what's needed for
-	running tests/benchmarks (#1821).
-	* Build shared libraries by default when linking executables dynamically.
-	* Build profiled libraries by default when profiling executables.
-
-1.20.0.4 Ryan Thomas <ryan@ryant.org> January 2016
-	* Cabal.cabal: change build-type to Simple.
-
-1.20.0.1 Johan Tibell <johan.tibell@gmail.com> May 2014
-	* Fix streaming test output.
-
-1.20.0.0 Johan Tibell <johan.tibell@gmail.com> April 2014
-	* Rewrite user guide
-	* Fix repl Ctrl+C handling
-	* Add haskell-suite compiler support
-	* Add __HADDOCK_VERSION__ define
-	* Allow specifying exact dependency version using hash
-	* Rename extra-html-files to extra-doc-files
-	* Add parallel build support for GHC 7.8 and later
-	* Don't call ranlib on OS X
-	* Avoid re-linking executables, test suites, and benchmarks
-	unnecessarily, shortening build times
-	* Add --allow-newer which allows upper version bounds to be
-	ignored
-	* Add --enable-library-stripping
-	* Add command for freezing dependencies
-	* Allow repl to be used outside Cabal packages
-	* Add --require-sandbox
-	* Don't use --strip-unneeded on OS X or iOS
-	* Add new license-files field got additional licenses
-	* Fix if(solaris) on some Solaris versions
-	* Don't use -dylib-install-name on OS X with GHC > 7.8
-	* Add DragonFly as a known OS
-	* Improve pretty-printing of Cabal files
-	* Add test flag --show-details=streaming for real-time test output
-	* Add exec command
-
-1.10.2.0 Duncan Coutts <duncan@community.haskell.org> June 2011
-	* Include test suites in cabal sdist
-	* Fix for conditionals in test suite stanzas in .cabal files
-	* Fix permissions of directories created during install
-	* Fix for global builds when $HOME env var is not set
-
-1.10.1.0 Duncan Coutts <duncan@community.haskell.org> February 2011
-	* Improved error messages when test suites are not enabled
-	* Template parameters allowed in test --test-option(s) flag
-	* Improved documentation of the test feature
-	* Relaxed QA check on cabal-version when using test-suite sections
-	* haddock command now allows both --hoogle and --html at the same time
-	* Find ghc-version-specific instances of the hsc2hs program
-	* Preserve file executable permissions in sdist tarballs
-	* Pass gcc location and flags to ./configure scripts
-	* Get default gcc flags from ghc
-
-1.10.0.0 Duncan Coutts <duncan@haskell.org> November 2010
-	* New cabal test feature
-	* Initial support for UHC
-	* New default-language and other-languages fields (e.g. Haskell98/2010)
-	* New default-extensions and other-extensions fields
-	* Deprecated extensions field (for packages using cabal-version >=1.10)
-	* Cabal-version field must now only be of the form ">= x.y"
-	* Removed deprecated --copy-prefix= feature
-	* Auto-reconfigure when .cabal file changes
-	* Workaround for haddock overwriting .hi and .o files when using TH
-	* Extra cpp flags used with hsc2hs and c2hs (-D${os}_BUILD_OS etc)
-	* New cpp define VERSION_<package> gives string version of dependencies
-	* User guide source now in markdown format for easier editing
-	* Improved checks and error messages for C libraries and headers
-	* Removed BSD4 from the list of suggested licenses
-	* Updated list of known language extensions
-	* Fix for include paths to allow C code to import FFI stub.h files
-	* Fix for intra-package dependencies on OSX
-	* Stricter checks on various bits of .cabal file syntax
-	* Minor fixes for c2hs
-
-1.8.0.6 Duncan Coutts <duncan@haskell.org> June 2010
-	* Fix 'register --global/--user'
-
-1.8.0.4 Duncan Coutts <duncan@haskell.org> March 2010
-	* Set dylib-install-name for dynalic libs on OSX
-	* Stricter configure check that compiler supports a package's extensions
-	* More configure-time warnings
-	* Hugs can compile Cabal lib again
-	* Default datadir now follows prefix on Windows
-	* Support for finding installed packages for hugs
-	* Cabal version macros now have proper parenthesis
-	* Reverted change to filter out deps of non-buildable components
-	* Fix for registering implace when using a specific package db
-	* Fix mismatch between $os and $arch path template variables
-	* Fix for finding ar.exe on Windows, always pick ghc's version
-	* Fix for intra-package dependencies with ghc-6.12
-
-1.8.0.2 Duncan Coutts <duncan@haskell.org> December 2009
-	* Support for GHC-6.12
-	* New unique installed package IDs which use a package hash
-	* Allow executables to depend on the lib within the same package
-	* Dependencies for each component apply only to that component
-	  (previously applied to all the other components too)
-	* Added new known license MIT and versioned GPL and LGPL
-	* More liberal package version range syntax
-	* Package registration files are now UTF8
-	* Support for LHC and JHC-0.7.2
-	* Deprecated RecordPuns extension in favour of NamedFieldPuns
-	* Deprecated PatternSignatures extension in favor of ScopedTypeVariables
-	* New VersionRange semantic view as a sequence of intervals
-	* Improved package quality checks
-	* Minor simplification in a couple Setup.hs hooks
-	* Beginnings of a unit level testsuite using QuickCheck
-	* Various bug fixes
-	* Various internal cleanups
-
-1.6.0.2 Duncan Coutts <duncan@haskell.org> February 2009
-	* New configure-time check for C headers and libraries
-	* Added language extensions present in ghc-6.10
-	* Added support for NamedFieldPuns extension in ghc-6.8
-	* Fix in configure step for ghc-6.6 on Windows
-	* Fix warnings in Path_pkgname.hs module on Windows
-	* Fix for exotic flags in ld-options field
-	* Fix for using pkg-config in a package with a lib and an executable
-	* Fix for building haddock docs for exes that use the Paths module
-	* Fix for installing header files in subdirectories
-	* Fix for the case of building profiling libs but not ordinary libs
-	* Fix read-only attribute of installed files on Windows
-	* Ignore ghc -threaded flag when profiling in ghc-6.8 and older
-
-1.6.0.1 Duncan Coutts <duncan@haskell.org> October 2008
-	* Export a compat function to help alex and happy
-
-1.6.0.0 Duncan Coutts <duncan@haskell.org> October 2008
-	* Support for ghc-6.10
-	* Source control repositories can now be specified in .cabal files
-	* Bug report URLs can be now specified in .cabal files
-	* Wildcards now allowed in data-files and extra-source-files fields
-	* New syntactic sugar for dependencies "build-depends: foo ==1.2.*"
-	* New cabal_macros.h provides macros to test versions of dependencies
-	* Relocatable bindists now possible on unix via env vars
-	* New 'exposed' field allows packages to be not exposed by default
-	* Install dir flags can now use $os and $arch variables
-	* New --builddir flag allows multiple builds from a single sources dir
-	* cc-options now only apply to .c files, not for -fvia-C
-	* cc-options are not longer propagated to dependent packages
-	* The cpp/cc/ld-options fields no longer use ',' as a separator
-	* hsc2hs is now called using gcc instead of using ghc as gcc
-	* New api for manipulating sets and graphs of packages
-	* Internal api improvements and code cleanups
-	* Minor improvements to the user guide
-	* Miscellaneous minor bug fixes
-
-1.4.0.2 Duncan Coutts <duncan@haskell.org> August 2008
-	* Fix executable stripping default
-	* Fix striping exes on OSX that export dynamic symbols (like ghc)
-	* Correct the order of arguments given by --prog-options=
-	* Fix corner case with overlapping user and global packages
-	* Fix for modules that use pre-processing and .hs-boot files
-	* Clarify some points in the user guide and readme text
-	* Fix verbosity flags passed to sub-command like haddock
-	* Fix sdist --snapshot
-	* Allow meta-packages that contain no modules or C code
-	* Make the generated Paths module -Wall clean on Windows
-
-1.4.0.1 Duncan Coutts <duncan@haskell.org> June 2008
-	* Fix a bug which caused '.' to always be in the sources search path
-	* Haddock-2.2 and later do now support the --hoogle flag
-
-1.4.0.0 Duncan Coutts <duncan@haskell.org> June 2008
-	* Rewritten command line handling support
-	* Command line completion with bash
-	* Better support for Haddock 2
-	* Improved support for nhc98
-	* Removed support for ghc-6.2
-	* Haddock markup in .lhs files now supported
-	* Default colour scheme for highlighted source code
-	* Default prefix for --user installs is now $HOME/.cabal
-	* All .cabal files are treaded as UTF-8 and must be valid
-	* Many checks added for common mistakes
-	* New --package-db= option for specific package databases
-	* Many internal changes to support cabal-install
-	* Stricter parsing for version strings, eg dissalows "1.05"
-	* Improved user guide introduction
-	* Programatica support removed
-	* New options --program-prefix/suffix allows eg versioned programs
-	* Support packages that use .hs-boot files
-	* Fix sdist for Main modules that require preprocessing
-	* New configure -O flag with optimisation level 0--2
-	* Provide access to "x-" extension fields through the Cabal api
-	* Added check for broken installed packages
-	* Added warning about using inconsistent versions of dependencies
-	* Strip binary executable files by default with an option to disable
-	* New options to add site-specific include and library search paths
-	* Lift the restriction that libraries must have exposed-modules
-	* Many bugs fixed.
-	* Many internal structural improvements and code cleanups
-
-1.2.4.0 Duncan Coutts <duncan@haskell.org> June 2008
-	* Released with GHC 6.8.3
-	* Backported several fixes and minor improvements from Cabal-1.4
-	* Use a default colour scheme for sources with hscolour >=1.9
-	* Support --hyperlink-source for Haddock >= 2.0
-	* Fix for running in a non-writable directory
-	* Add OSX -framework arguments when linking executables
-	* Updates to the user guide
-	* Allow build-tools names to include + and _
-	* Export autoconfUserHooks and simpleUserHooks
-	* Export ccLdOptionsBuildInfo for Setup.hs scripts
-	* Export unionBuildInfo and make BuildInfo an instance of Monoid
-	* Fix to allow the 'main-is' module to use a pre-processor
-
-1.2.3.0 Duncan Coutts <duncan@haskell.org> Nov 2007
-	* Released with GHC 6.8.2
-	* Includes full list of GHC language extensions
-	* Fix infamous "dist/conftest.c" bug
-	* Fix configure --interfacedir=
-	* Find ld.exe on Windows correctly
-	* Export PreProcessor constructor and mkSimplePreProcessor
-	* Fix minor bug in unlit code
-	* Fix some markup in the haddock docs
-
-1.2.2.0 Duncan Coutts <duncan@haskell.org> Nov 2007
-	* Released with GHC 6.8.1
-	* Support haddock-2.0
-	* Support building DSOs with GHC
-	* Require reconfiguring if the .cabal file has changed
-	* Fix os(windows) configuration test
-	* Fix building documentation
-	* Fix building packages on Solaris
-	* Other minor bug fixes
-
-1.2.1 Duncan Coutts <duncan@haskell.org> Oct 2007
-	* To be included in GHC 6.8.1
-	* New field "cpp-options" used when preprocessing Haskell modules
-	* Fixes for hsc2hs when using ghc
-	* C source code gets compiled with -O2 by default
-	* OS aliases, to allow os(windows) rather than requiring os(mingw32)
-	* Fix cleaning of 'stub' files
-	* Fix cabal-setup, command line ui that replaces "runhaskell Setup.hs"
-	* Build docs even when dependent packages docs are missing
-	* Allow the --html-dir to be specified at configure time
-	* Fix building with ghc-6.2
-	* Other minor bug fixes and build fixes
-
-1.2.0  Duncan Coutts <duncan.coutts@worc.ox.ac.uk> Sept 2007
-	* To be included in GHC 6.8.x
-	* New configurations feature
-	* Can make haddock docs link to hilighted sources (with hscolour)
-	* New flag to allow linking to haddock docs on the web
-	* Supports pkg-config
-	* New field "build-tools" for tool dependencies
-	* Improved c2hs support
-	* Preprocessor output no longer clutters source dirs
-	* Separate "includes" and "install-includes" fields
-	* Makefile command to generate makefiles for building libs with GHC
-	* New --docdir configure flag
-	* Generic --with-prog --prog-args configure flags
-	* Better default installation paths on Windows
-	* Install paths can be specified relative to each other
-	* License files now installed
-	* Initial support for NHC (incomplete)
-	* Consistent treatment of verbosity
-	* Reduced verbosity of configure step by default
-	* Improved helpfulness of output messages
-	* Help output now clearer and fits in 80 columns
-	* New setup register --gen-pkg-config flag for distros
-	* Major internal refactoring, hooks api has changed
-	* Dozens of bug fixes
-
-1.1.6.2 Duncan Coutts <duncan.coutts@worc.ox.ac.uk> May 2007
-	* Released with GHC 6.6.1
-	* Handle windows text file encoding for .cabal files
-	* Fix compiling a executable for profiling that uses Template Haskell
-	* Other minor bug fixes and user guide clarifications
-
-1.1.6.1 Duncan Coutts <duncan.coutts@worc.ox.ac.uk> Oct 2006
-	* fix unlit code
-	* fix escaping in register.sh
-
-1.1.6  Duncan Coutts <duncan.coutts@worc.ox.ac.uk> Oct 2006
-	* Released with GHC 6.6
-	* Added support for hoogle
-	* Allow profiling and normal builds of libs to be chosen indepentantly
-	* Default installation directories on Win32 changed
-	* Register haddock docs with ghc-pkg
-	* Get haddock to make hyperlinks to dependent package docs
-	* Added BangPatterns language extension
-	* Various bug fixes
-
-1.1.4  Duncan Coutts <duncan.coutts@worc.ox.ac.uk> May 2006
-	* Released with GHC 6.4.2
-	* Better support for packages that need to install header files
-	* cabal-setup added, but not installed by default yet
-	* Implemented "setup register --inplace"
-	* Have packages exposed by default with ghc-6.2
-	* It is no longer necessary to run 'configure' before 'clean' or 'sdist'
-	* Added support for ghc's -split-objs
-	* Initial support for JHC
-	* Ignore extension fields in .cabal files (fields begining with "x-")
-	* Some changes to command hooks API to improve consistency
-	* Hugs support improvements
-	* Added GeneralisedNewtypeDeriving language extension
-	* Added cabal-version field
-	* Support hidden modules with haddock
-	* Internal code refactoring
-	* More bug fixes
-
-1.1.3  Isaac Jones  <ijones@syntaxpolice.org> Sept 2005
-	* WARNING: Interfaces not documented in the user's guide may
-	  change in future releases.
-	* Move building of GHCi .o libs to the build phase rather than
-	register phase. (from Duncan Coutts)
-	* Use .tar.gz for source package extension
-	* Uses GHC instead of cpphs if the latter is not available
-	* Added experimental "command hooks" which completely override the
-	default behavior of a command.
-	* Some bugfixes
-
-1.1.1  Isaac Jones  <ijones@syntaxpolice.org> July 2005
-	* WARNING: Interfaces not documented in the user's guide may
-	  change in future releases.
-	* Handles recursive modules for GHC 6.2 and GHC 6.4.
-	* Added "setup test" command (Used with UserHook)
-	* implemented handling of _stub.{c,h,o} files
-	* Added support for profiling
-	* Changed install prefix of libraries (pref/pkgname-version
-	  to prefix/pkgname-version/compname-version)
-	* Added pattern guards as a language extension
-	* Moved some functionality to Language.Haskell.Extension
-	* Register / unregister .bat files for windows
-	* Exposed more of the API
-	* Added support for the hide-all-packages flag in GHC > 6.4
-	* Several bug fixes
-
-1.0  Isaac Jones  <ijones@syntaxpolice.org> March 11 2005
-	* Released with GHC 6.4, Hugs March 2005, and nhc98 1.18
-	* Some sanity checking
-
-0.5  Isaac Jones  <ijones@syntaxpolice.org> Wed Feb 19 2005
-	* WARNING: this is a pre-release and the interfaces are still
-	likely to change until we reach a 1.0 release.
-	* Hooks interfaces changed
-	* Added preprocessors to user hooks
-	* No more executable-modules or hidden-modules.  Use
-	"other-modules" instead.
-	* Certain fields moved into BuildInfo, much refactoring
-	* extra-libs -> extra-libraries
-	* Added --gen-script to configure and unconfigure.
-	* modules-ghc (etc) now ghc-modules (etc)
-	* added new fields including "synopsis"
-	* Lots of bug fixes
-	* spaces can sometimes be used instead of commas
-	* A user manual has appeared (Thanks, ross!)
-	* for ghc 6.4, configures versionsed depends properly
-	* more features to ./setup haddock
-
-0.4  Isaac Jones  <ijones@syntaxpolice.org> Sun Jan 16 2005
-
-	* Much thanks to all the awesome fptools hackers who have been
-	working hard to build the Haskell Cabal!
-
-	* Interface Changes:
-
-	** WARNING: this is a pre-release and the interfaces are still
-	likely to change until we reach a 1.0 release.
-
-	** Instead of Package.description, you should name your
-	description files <something>.cabal.  In particular, we suggest
-	that you name it <packagename>.cabal, but this is not enforced
-	(yet).  Multiple .cabal files in the same directory is an error,
-	at least for now.
-
-	** ./setup install --install-prefix is gone.  Use ./setup copy
-	--copy-prefix instead.
-
-	** The "Modules" field is gone.  Use "hidden-modules",
-	"exposed-modules", and "executable-modules".
-
-	** Build-depends is now a package-only field, and can't go into
-	executable stanzas.  Build-depends is a package-to-package
-	relationship.
-
-	** Some new fields.  Use the Source.
-
-	* New Features
-
-	** Cabal is now included as a package in the CVS version of
-	fptools.  That means it'll be released as "-package Cabal" in
-	future versions of the compilers, and if you are a bleeding-edge
-	user, you can grab it from the CVS repository with the compilers.
-
-	** Hugs compatibility and NHC98 compatibility should both be
-	improved.
-
-	** Hooks Interface / Autoconf compatibility: Most of the hooks
-	interface is hidden for now, because it's not finalized.  I have
-	exposed only "defaultMainWithHooks" and "defaultUserHooks".  This
-	allows you to use a ./configure script to preprocess
-	"foo.buildinfo", which gets merged with "foo.cabal".  In future
-	releases, we'll expose UserHooks, but we're definitely going to
-	change the interface to those.  The interface to the two functions
-	I've exposed should stay the same, though.
-
-	** ./setup haddock is a baby feature which pre-processes the
-	source code with hscpp and runs haddock on it.  This is brand new
-	and hardly tested, so you get to knock it around and see what you
-	think.
-
-	** Some commands now actually implement verbosity.
-
-	** The preprocessors have been tested a bit more, and seem to work
-	OK.  Please give feedback if you use these.
-
-0.3  Isaac Jones  <ijones@syntaxpolice.org> Sun Jan 16 2005
-	* Unstable snapshot release
-	* From now on, stable releases are even.
-
-0.2  Isaac Jones  <ijones@syntaxpolice.org>
-
-	* Adds more HUGS support and preprocessor support.
diff --git a/cabal/Cabal/doc/cabaldomain.py b/cabal/Cabal/doc/cabaldomain.py
--- a/cabal/Cabal/doc/cabaldomain.py
+++ b/cabal/Cabal/doc/cabaldomain.py
@@ -54,7 +54,7 @@
 
 .. rst:directive:: .. cabal:cfg-field::
 
-   Describes a project.cabal field.
+   Describes a cabal.project field.
 
    Can have multiple arguments, if arguments start with '-' then it is treated
    as a cabal flag.
@@ -522,7 +522,7 @@
 
 class CabalPackageFieldXRef(CabalFieldXRef):
     '''
-    Role referencing project.cabal section
+    Role referencing cabal.project section
     '''
     section_key = 'cabal:pkg-section'
 
@@ -530,7 +530,7 @@
     """
     Marks section in package.cabal file
     """
-    indextemplate = '%s; project.cabal section'
+    indextemplate = '%s; cabal.project section'
     section_key = 'cabal:cfg-section'
     target_prefix = 'cfg-section-'
 
@@ -638,7 +638,7 @@
         '''
 
         # (title, section store, fields store)
-        entries = [('project.cabal fields', 'cfg-section', 'cfg-field'),
+        entries = [('cabal.project fields', 'cfg-section', 'cfg-field'),
                    ('cabal project flags', 'cfg-section', 'cfg-flag'),
                    ('package.cabal fields', 'pkg-section', 'pkg-field')]
 
@@ -742,11 +742,11 @@
         return base + render_meta_title(meta)
 
     elif typ == 'cfg-section':
-        return "project.cabal " + key + " section " + render_meta_title(meta)
+        return "cabal.project " + key + " section " + render_meta_title(meta)
 
     elif typ == 'cfg-field':
         section, name = key
-        return "project.cabal " + name + " field " + render_meta_title(meta)
+        return "cabal.project " + name + " field " + render_meta_title(meta)
 
     elif typ == 'cfg-flag':
         section, name = key
diff --git a/cabal/Cabal/doc/conf.py b/cabal/Cabal/doc/conf.py
--- a/cabal/Cabal/doc/conf.py
+++ b/cabal/Cabal/doc/conf.py
@@ -13,9 +13,9 @@
 sys.path.insert(0, os.path.abspath('.'))
 import cabaldomain
 
-version = "2.1"
+version = "2.4.1.0"
 
-extensions = ['sphinx.ext.extlinks']
+extensions = ['sphinx.ext.extlinks', 'sphinx.ext.todo']
 
 templates_path = ['_templates']
 source_suffix = '.rst'
@@ -120,6 +120,8 @@
 # If true, show page references after internal links.
 latex_show_pagerefs = True
 
+# http://www.sphinx-doc.org/en/master/usage/extensions/todo.html
+todo_include_todos = True
 
 # -- Options for manual page output ---------------------------------------
 
diff --git a/cabal/Cabal/doc/developing-packages.rst b/cabal/Cabal/doc/developing-packages.rst
--- a/cabal/Cabal/doc/developing-packages.rst
+++ b/cabal/Cabal/doc/developing-packages.rst
@@ -409,6 +409,15 @@
 management means that Cabal's conditional dependencies system is a bit
 less flexible than with the "./configure" approach.
 
+.. note::
+   `GNU autoconf places restrictions on paths, including the
+   path that the user builds a package from.
+   <https://www.gnu.org/software/autoconf/manual/autoconf.html#File-System-Conventions>`_
+   Package authors using ``build-type: configure`` should be aware of
+   these restrictions; because users may be unexpectedly constrained and
+   face mysterious errors, it is recommended that ``build-type: configure``
+   is only used where strictly necessary.
+
 Portability
 -----------
 
@@ -707,7 +716,7 @@
 *identifier*
     A letter followed by zero or more alphanumerics or underscores.
 *compiler*
-    A compiler flavor (one of: ``GHC``, ``JHC``, ``UHC`` or ``LHC``)
+    A compiler flavor (one of: ``GHC``, ``UHC`` or ``LHC``)
     followed by a version range. For example, ``GHC ==6.10.3``, or
     ``LHC >=0.6 && <0.8``.
 
@@ -756,11 +765,35 @@
     tools require the package-name specified for this field to match
     the package description's file-name :file:`{package-name}.cabal`.
 
+    Package names are case-sensitive and must match the regular expression
+    (i.e. alphanumeric "words" separated by dashes; each alphanumeric
+    word must contain at least one letter):
+    ``[[:digit:]]*[[:alpha:]][[:alnum:]]*(-[[:digit:]]*[[:alpha:]][[:alnum:]]*)*``.
+
+    Or, expressed in ABNF_:
+
+    .. code-block:: abnf
+
+        package-name      = package-name-part *("-" package-name-part)
+        package-name-part = *DIGIT UALPHA *UALNUM
+
+        UALNUM = UALPHA / DIGIT
+        UALPHA = ... ; set of alphabetic Unicode code-points
+
+    .. note::
+
+        Hackage restricts package names to the ASCII subset.
+
 .. pkg-field:: version: numbers (required)
 
     The package version number, usually consisting of a sequence of
-    natural numbers separated by dots.
+    natural numbers separated by dots, i.e. as the regular
+    expression ``[0-9]+([.][0-9]+)*`` or expressed in ABNF_:
 
+    .. code-block:: abnf
+
+        package-version = 1*DIGIT *("." 1*DIGIT)
+
 .. pkg-field:: cabal-version: >= x.y
 
     The version of the Cabal specification that this package description
@@ -798,13 +831,21 @@
 
 .. pkg-field:: build-type: identifier
 
-    :default: ``Custom``
+    :default: ``Custom`` or ``Simple``
 
     The type of build used by this package. Build types are the
     constructors of the
     `BuildType <../release/cabal-latest/doc/API/Cabal/Distribution-PackageDescription.html#t:BuildType>`__
-    type, defaulting to ``Custom``.
+    type. This field is optional and when missing, its default value
+    is inferred according to the following rules:
 
+     - When :pkg-field:`cabal-version` is set to ``2.2`` or higher,
+       the default is ``Simple`` unless a :pkg-section:`custom-setup`
+       exists, in which case the inferred default is ``Custom``.
+
+     - For lower :pkg-field:`cabal-version` values, the default is
+       ``Custom`` unconditionally.
+
     If the build type is anything other than ``Custom``, then the
     ``Setup.hs`` file *must* be exactly the standardized content
     discussed below. This is because in these cases, ``cabal`` will
@@ -945,27 +986,54 @@
     A list of files to be installed for run-time use by the package.
     This is useful for packages that use a large amount of static data,
     such as tables of values or code templates. Cabal provides a way to
-    `find these files at run-time <accessing data files from package code>`_.
+    `find these files at run-time <#accessing-data-files-from-package-code>`_.
 
     A limited form of ``*`` wildcards in file names, for example
     ``data-files: images/*.png`` matches all the ``.png`` files in the
-    ``images`` directory.
+    ``images`` directory. ``data-files: audio/**/*.mp3`` matches all
+    the ``.mp3`` files in the ``audio`` directory, including
+    subdirectories.
 
-    The limitation is that ``*`` wildcards are only allowed in place of
-    the file name, not in the directory name or file extension. In
-    particular, wildcards do not include directories contents
-    recursively. Furthermore, if a wildcard is used it must be used with
-    an extension, so ``data-files: data/*`` is not allowed. When
-    matching a wildcard plus extension, a file's full extension must
-    match exactly, so ``*.gz`` matches ``foo.gz`` but not
-    ``foo.tar.gz``. A wildcard that does not match any files is an
-    error.
+    The specific limitations of this wildcard syntax are
 
+    - ``*`` wildcards are only allowed in place of the file name, not
+      in the directory name or file extension. It must replace the
+      whole file name (e.g., ``*.html`` is allowed, but
+      ``chapter-*.html`` is not). If a wildcard is used, it must be
+      used with an extension, so ``data-files: data/*`` is not
+      allowed.
+
+    - Prior to Cabal 2.4, when matching a wildcard plus extension, a
+      file's full extension must match exactly, so ``*.gz`` matches
+      ``foo.gz`` but not ``foo.tar.gz``. This restriction has been
+      lifted when ``cabal-version: 2.4`` or greater so that ``*.gz``
+      does match ``foo.tar.gz``
+
+    - ``*`` wildcards will not match if the file name is empty (e.g.,
+      ``*.html`` will not match ``foo/.html``).
+
+    - ``**`` wildcards can only appear as the final path component
+      before the file name (e.g., ``data/**/images/*.jpg`` is not
+      allowed). If a ``**`` wildcard is used, then the file name must
+      include a ``*`` wildcard (e.g., ``data/**/README.rst`` is not
+      allowed).
+
+    - A wildcard that does not match any files is an error.
+
     The reason for providing only a very limited form of wildcard is to
     concisely express the common case of a large number of related files
     of the same file type without making it too easy to accidentally
     include unwanted files.
 
+    On efficiency: if you use ``**`` patterns, the directory tree will
+    be walked starting with the parent directory of the ``**``. If
+    that's the root of the project, this might include ``.git/``,
+    ``dist-newstyle/``, or other large directories! To avoid this
+    behaviour, put the files that wildcards will match against in
+    their own folder.
+
+    ``**`` wildcards are available starting in Cabal 2.4.
+
 .. pkg-field:: data-dir: directory
 
     The directory where Cabal looks for data files to install, relative
@@ -995,13 +1063,21 @@
 Library
 ^^^^^^^
 
-.. pkg-section:: library
+.. pkg-section:: library name
     :synopsis: Library build information.
 
-    Build information for libraries. There can be only one library in a
-    package, and it's name is the same as package name set by global
-    :pkg-field:`name` field.
+    Build information for libraries.
 
+    Currently, there can only be one publicly exposed library in a
+    package, and its name is the same as package name set by global
+    :pkg-field:`name` field. In this case, the ``name`` argument to
+    the :pkg-section:`library` section must be omitted.
+
+    Starting with Cabal 2.0, private internal sub-library components
+    can be defined by using setting the ``name`` field to a name
+    different from the current package's name; see section on
+    :ref:`Internal Libraries <sublibs>` for more information.
+
 The library section should contain the following fields:
 
 .. pkg-field:: exposed-modules: identifier list
@@ -1011,6 +1087,7 @@
     A list of modules added by this package.
 
 .. pkg-field:: virtual-modules: identifier list
+    :since: 2.2
 
     A list of virtual modules provided by this package.  Virtual modules
     are modules without a source file.  See for example the ``GHC.Prim``
@@ -1037,6 +1114,7 @@
     exposed modules would clash with other common modules.
 
 .. pkg-field:: reexported-modules: exportlist
+    :since: 1.22
 
     Supported only in GHC 7.10 and later. A list of modules to
     *reexport* from this package. The syntax of this field is
@@ -1054,9 +1132,29 @@
     conflict (as would be the case with a stub module.) They can also be
     used to resolve name conflicts.
 
+.. pkg-field:: signatures: signature list
+    :since: 2.0
+
+    Supported only in GHC 8.2 and later. A list of `module signatures <https://downloads.haskell.org/~ghc/master/users-guide/separate_compilation.html#module-signatures>`__ required by this package.
+
+    Module signatures are part of the
+    `Backpack <https://ghc.haskell.org/trac/ghc/wiki/Backpack>`__ extension to
+    the Haskell module system.
+
+    Packages that do not export any modules and only export required signatures
+    are called "signature-only packages", and their signatures are subjected to
+    `signature thinning
+    <https://wiki.haskell.org/Module_signature#How_to_use_a_signature_package>`__.
+
+    
+
 The library section may also contain build information fields (see the
 section on `build information`_).
 
+.. _sublibs:
+
+**Internal Libraries**
+
 Cabal 2.0 and later support "internal libraries", which are extra named
 libraries (as opposed to the usual unnamed library section). For
 example, suppose that your test suite needs access to some internal
@@ -1067,10 +1165,10 @@
 
 ::
 
+    cabal-version:  2.0
     name:           foo
-    version:        1.0
+    version:        0.1.0.0
     license:        BSD3
-    cabal-version:  >= 1.23
     build-type:     Simple
 
     library foo-internal
@@ -1095,9 +1193,56 @@
 libraries are only visible internally in the package (so they can only
 be added to the :pkg-field:`build-depends` of same-package libraries,
 executables, test suites, etc.) Internal libraries locally shadow any
-packages which have the same name (so don't name an internal library
-with the same name as an external dependency.)
+packages which have the same name; consequently, don't name an internal
+library with the same name as an external dependency if you need to be
+able to refer to the external dependency in a
+:pkg-field:`build-depends` declaration.
 
+Shadowing can be used to vendor an external dependency into a package
+and thus emulate *private dependencies*. Below is an example based on
+a real-world use case:
+
+::
+
+    cabal-version: 2.2
+    name: haddock-library
+    version: 1.6.0
+
+    library
+      build-depends:
+        , base         ^>= 4.11.1.0
+        , bytestring   ^>= 0.10.2.0
+        , containers   ^>= 0.4.2.1 || ^>= 0.5.0.0
+        , transformers ^>= 0.5.0.0
+
+      hs-source-dirs:       src
+
+      -- internal sub-lib
+      build-depends:        attoparsec
+
+      exposed-modules:
+        Documentation.Haddock
+
+    library attoparsec
+      build-depends:
+        , base         ^>= 4.11.1.0
+        , bytestring   ^>= 0.10.2.0
+        , deepseq      ^>= 1.4.0.0
+
+      hs-source-dirs:       vendor/attoparsec-0.13.1.0
+
+      -- NB: haddock-library needs only small part of lib:attoparsec
+      --     internally, so we only bundle that subset here
+      exposed-modules:
+        Data.Attoparsec.ByteString
+        Data.Attoparsec.Combinator
+
+      other-modules:
+        Data.Attoparsec.Internal
+
+      ghc-options: -funbox-strict-fields -Wall -fwarn-tabs -O2
+
+
 Opening an interpreter session
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -1188,9 +1333,20 @@
 ``--freeze-file``
     Read dependency version bounds from the freeze file (``cabal.config``)
     instead of the package description file (``$PACKAGENAME.cabal``).
+    ``--v1-freeze-file`` is an alias for this flag starting in Cabal 2.4.
 ``--new-freeze-file``
     Read dependency version bounds from the new-style freeze file
-    (``cabal.project.freeze``) instead of the package description file.
+    (by default, ``cabal.project.freeze``) instead of the package
+    description file. ``--v2-freeze-file`` is an alias for this flag
+    starting in Cabal 2.4.
+``--project-file`` *PROJECTFILE*
+    :since: 2.4
+
+    Read dependendency version bounds from the new-style freeze file
+    related to the named project file (i.e., ``$PROJECTFILE.freeze``)
+    instead of the package desctription file. If multiple ``--project-file``
+    flags are provided, only the final one is considered. This flag
+    must only be passed in when ``--new-freeze-file`` is present.
 ``--simple-output``
     Print only the names of outdated dependencies, one per line.
 ``--exit-code``
@@ -1251,7 +1407,7 @@
 ^^^^^^^^^^^
 
 .. pkg-section:: executable name
-    :synopsis: Exectuable build info section.
+    :synopsis: Executable build info section.
 
     Executable sections (if present) describe executable programs contained
     in the package and must have an argument after the section label, which
@@ -1267,7 +1423,8 @@
     module. Note that it is the ``.hs`` filename that must be listed,
     even if that file is generated using a preprocessor. The source file
     must be relative to one of the directories listed in
-    :pkg-field:`hs-source-dirs`.
+    :pkg-field:`hs-source-dirs`. Further, while the name of the file may
+    vary, the module itself must be named ``Main``.
 
 .. pkg-field:: scope: token
     :since: 2.0
@@ -1483,7 +1640,8 @@
     even if that file is generated using a preprocessor. The source file
     must be relative to one of the directories listed in
     :pkg-field:`hs-source-dirs`. This field is analogous to the ``main-is``
-    field of an executable section.
+    field of an executable section. Further, while the name of the file may
+    vary, the module itself must be named ``Main``.
 
 Example: Package using ``exitcode-stdio-1.0`` interface
 """""""""""""""""""""""""""""""""""""""""""""""""""""""
@@ -1689,11 +1847,29 @@
 `system-dependent parameters`_ and `configurations`_ for a way to supply
 system-dependent values for these fields.
 
-.. pkg-field:: build-depends: package list
+.. pkg-field:: build-depends: library list
 
-    A list of packages needed to build this one. Each package can be
-    annotated with a version constraint.
+    Declares the *library* dependencies required to build the current
+    package component; see :pkg-field:`build-tool-depends` for
+    declaring build-time *tool* dependencies. External library
+    dependencies should be annotated with a version constraint.
 
+    **Library Names**
+
+    External libraries are identified by the package's name they're
+    provided by (currently a package can only publically expose its
+    main library compeonent; in future, packages with multiple exposed
+    public library components will be supported and a syntax for
+    referring to public sub-libraries will be provided).
+
+    In order to specify an intra-package dependency on an internal
+    library component you can use the unqualified name of the
+    component library component. Note that locally defined sub-library
+    names shadow external package names of the same name. See section on
+    :ref:`Internal Libraries <sublibs>` for examples and more information.
+
+    **Version Constraints**
+
     Version constraints use the operators ``==, >=, >, <, <=`` and a
     version number. Multiple constraints can be combined using ``&&`` or
     ``||``. If no version constraint is specified, any version is
@@ -1729,9 +1905,8 @@
        than ``1.0``. This is not an issue with the caret-operator
        ``^>=`` described below.
 
-    Starting with Cabal 2.0, there's a new syntactic sugar to express
-    PVP_-style
-    major upper bounds conveniently, and is inspired by similar
+    Starting with Cabal 2.0, there's a new version operator to express
+    PVP_-style major upper bounds conveniently, and is inspired by similar
     syntactic sugar found in other language ecosystems where it's often
     called the "Caret" operator:
 
@@ -1741,22 +1916,64 @@
           foo ^>= 1.2.3.4,
           bar ^>= 1
 
-    This allows to express the intent that this packages requires
-    versions of ``foo`` and ``bar`` which are semantically compatible
-    to ``foo-1.2.3.4`` and ``bar-1`` respectively. This subtle but important
-    difference in signaling allows tooling to treat *"hard"* ``<``-style
-    and *"weak"* ``^>=``-style upper bounds differently. For instance,
-    :option:`--allow-newer`'s ``^``-modifier allows to relax only *"weak"*
-    ``^>=``-style bounds while leaving ``<``-bounds unaffected.
+    This allows to assert the positive knowledge that this package is
+    *known* to be semantically compatible with the releases
+    ``foo-1.2.3.4`` and ``bar-1`` respectively. The information
+    encoded via such ``^>=``-assertions is used by the cabal solver to
+    infer version constraints describing semantically compatible
+    version ranges according to the PVP_ contract (see below).
 
-    Ignoring the signaling intent, the equivalences are
+    Another way to say this is that ``foo < 1.3`` expresses *negative*
+    information, i.e. "``foo-1.3`` or ``foo-1.4.2`` will *not* be
+    compatible"; whereas ``foo ^>= 1.2.3.4`` asserts the *positive*
+    information that "``foo-1.2.3.4`` is *known* to be compatible" and (in
+    the absence of additional information) according to the PVP_
+    contract we can (positively) infer right away that all versions
+    satisfying ``foo >= 1.2.3.4 && < 1.3`` will be compatible as well.
 
+    .. Note::
+
+       More generally, the PVP_ contract implies that we can safely
+       relax the lower bound to ``>= 1.2``, because if we know that
+       ``foo-1.2.3.4`` is semantically compatible, then so is
+       ``foo-1.2`` (if it typechecks). But we'd need to perform
+       additional static analysis (i.e. perform typechecking) in order
+       to know if our package in the role of an API consumer will
+       successfully typecheck against the dependency ``foo-1.2``.  But
+       since we cannot do this analysis during constraint solving and
+       to keep things simple, we pragmatically use ``foo >= 1.2.3.4``
+       as the initially inferred approximation for the lower bound
+       resulting from the assertion ``foo ^>= 1.2.3.4``. If further
+       evidence becomes available that e.g. ``foo-1.2`` typechecks,
+       one can simply revise the dependency specification to include
+       the assertion ``foo ^>= 1.2``.
+
+    The subtle but important difference in signaling allows tooling to
+    treat explicitly expressed ``<``-style constraints and inferred
+    (``^>=``-style) upper bounds differently.  For instance,
+    :option:`--allow-newer`'s ``^``-modifier allows to relax only
+    ``^>=``-style bounds while leaving explicitly stated
+    ``<``-constraints unaffected.
+
+    Ignoring the signaling intent, the default syntactic desugaring rules are
+
     - ``^>= x`` == ``>= x && < x.1``
     - ``^>= x.y`` == ``>= x.y && < x.(y+1)``
     - ``^>= x.y.z`` == ``>= x.y.z && < x.(y+1)``
     - ``^>= x.y.z.u`` == ``>= x.y.z.u && < x.(y+1)``
     - etc.
 
+    .. Note::
+
+       One might expected the desugaring to truncate all version
+       components below (and including) the patch-level, i.e.
+       ``^>= x.y.z.u`` == ``>= x.y.z && < x.(y+1)``,
+       as the major and minor version components alone are supposed to
+       uniquely identify the API according to the PVP_.  However, by
+       designing ``^>=`` to be closer to the ``>=`` operator, we avoid
+       the potentially confusing effect of ``^>=`` being more liberal
+       than ``>=`` in the presence of patch-level versions.
+
     Consequently, the example declaration above is equivalent to
 
     ::
@@ -2033,13 +2250,14 @@
     source tree. Cabal looks in these directories when attempting to
     locate files listed in :pkg-field:`includes` and
     :pkg-field:`install-includes`.
- 
+
 .. pkg-field:: c-sources: filename list
 
     A list of C source files to be compiled and linked with the Haskell
     files.
 
 .. pkg-field:: cxx-sources: filename list
+    :since: 2.2
 
     A list of C++ source files to be compiled and linked with the Haskell
     files. Useful for segregating C and C++ sources when supplying different
@@ -2048,7 +2266,7 @@
     :pkg-field:`cxx-sources` can reference files listed in the
     :pkg-field:`c-sources` field and vice-versa. The object files will be linked
     appropriately.
-    
+
 .. pkg-field:: asm-sources: filename list
 
     A list of assembly source files to be compiled and linked with the
@@ -2076,7 +2294,7 @@
 .. pkg-field:: extra-bundled-libraries: token list
 
    A list of libraries that are supposed to be copied from the build
-   directory alongside the produced haskell libraries.  Note that you
+   directory alongside the produced Haskell libraries.  Note that you
    are under the obligation to produce those lirbaries in the build
    directory (e.g. via a custom setup).  Libraries listed here will
    be included when ``copy``-ing packages and be listed in the
@@ -2095,10 +2313,11 @@
 .. pkg-field:: cpp-options: token list
 
     Command-line arguments for pre-processing Haskell code. Applies to
-    haskell source and other pre-processed Haskell source like .hsc
+    Haskell source and other pre-processed Haskell source like .hsc
     .chs. Does not apply to C code, that's what cc-options is for.
 
 .. pkg-field:: cxx-options: token list
+    :since: 2.2
 
     Command-line arguments to be passed to the compiler when compiling
     C++ code. The C++ sources to which these command-line arguments
@@ -2143,6 +2362,107 @@
     On Darwin/MacOS X, a list of directories to search for frameworks.
     This entry is ignored on all other platforms.
 
+.. pkg-field:: mixins: mixin list
+    :since: 2.0
+
+    Supported only in GHC 8.2 and later. A list of packages mentioned in the
+    :pkg-field:`build-depends` field, each optionally accompanied by a list of
+    module and module signature renamings.
+
+    The simplest mixin syntax is simply the name of a package mentioned in the
+    :pkg-field:`build-depends` field. For example:
+
+    ::
+
+        library
+          build-depends:
+            foo >= 1.2.3 && < 1.3
+          mixins:
+            foo
+
+    But this doesn't have any effect. More interesting is to use the mixin
+    entry to rename one or more modules from the package, like this:
+
+    ::
+
+        library
+          mixins:
+            foo (Foo.Bar as AnotherFoo.Bar, Foo.Baz as AnotherFoo.Baz)
+
+    Note that renaming a module like this will hide all the modules
+    that are not explicitly named.
+
+    Modules can also be hidden:
+
+    ::
+
+        library:
+          mixins:
+            foo hiding (Foo.Bar)
+
+    Hiding modules exposes everything that is not explicitly hidden.
+
+    .. Note::
+
+       The current version of Cabal suffers from an infelicity in how the
+       entries of :pkg-field:`mixins` are parsed: an entry will fail to parse
+       if the provided renaming clause has whitespace after the opening
+       parenthesis. This will be fixed in future versions of Cabal.
+
+       See issues `#5150 <https://github.com/haskell/cabal/issues/5150>`__,
+       `#4864 <https://github.com/haskell/cabal/issues/4864>`__, and
+       `#5293 <https://github.com/haskell/cabal/pull/5293>`__.
+
+    There can be multiple mixin entries for a given package, in effect creating
+    multiple copies of the dependency:
+
+    ::
+
+        library
+          mixins:
+            foo (Foo.Bar as AnotherFoo.Bar, Foo.Baz as AnotherFoo.Baz),
+            foo (Foo.Bar as YetAnotherFoo.Bar)
+
+    The ``requires`` clause is used to rename the module signatures required by
+    a package:
+
+    ::
+
+        library
+          mixins:
+            foo (Foo.Bar as AnotherFoo.Bar) requires (Foo.SomeSig as AnotherFoo.SomeSig)
+
+    Signature-only packages don't have any modules, so only the signatures can
+    be renamed, with the following syntax:
+
+    ::
+
+        library
+          mixins:
+            sigonly requires (SigOnly.SomeSig as AnotherSigOnly.SomeSig)
+
+    See the :pkg-field:`signatures` field for more details.
+
+    Mixin packages are part of the `Backpack
+    <https://ghc.haskell.org/trac/ghc/wiki/Backpack>`__ extension to the
+    Haskell module system.
+
+    The matching of the module signatures required by a
+    :pkg-field:`build-depends` dependency with the implementation modules
+    present in another dependency is triggered by a coincidence of names. When
+    the names of the signature and of the implementation are already the same,
+    the matching is automatic. But when the names don't coincide, or we want to
+    instantiate a signature in two different ways, adding mixin entries that
+    perform renamings becomes necessary.  
+
+    .. Warning::
+
+       Backpack has the limitation that implementation modules that instantiate
+       signatures required by a :pkg-field:`build-depends` dependency can't
+       reside in the same component that has the dependency. They must reside
+       in a different package dependency, or at least in a separate internal
+       library.
+
 Configurations
 ^^^^^^^^^^^^^^
 
@@ -2267,17 +2587,24 @@
 """""""""""""""""""
 
 .. pkg-section:: flag name
-   :synopsis: Flag declaration.
+    :synopsis: Flag declaration.
 
-   Flag section declares a flag which can be used in `conditional blocks`_.
+    Flag section declares a flag which can be used in `conditional blocks`_.
 
-Flag names are case-insensitive and must match ``[[:alnum:]_][[:alnum:]_-]*``
-regular expression.
+    Flag names are case-insensitive and must match ``[[:alnum:]_][[:alnum:]_-]*``
+    regular expression, or expressed as ABNF_:
 
-.. note::
+    .. code-block:: abnf
 
-    Hackage accepts ASCII-only flags, ``[a-zA-Z0-9_][a-zA-Z0-9_-]*`` regexp.
+       flag-name = (UALNUM / "_") *(UALNUM / "_" / "-")
 
+       UALNUM = UALPHA / DIGIT
+       UALPHA = ... ; set of alphabetic Unicode code-points
+
+    .. note::
+
+        Hackage accepts ASCII-only flags, ``[a-zA-Z0-9_][a-zA-Z0-9_-]*`` regexp.
+
 .. pkg-field:: description: freeform
 
     The description of this flag.
@@ -2301,6 +2628,7 @@
 .. pkg-field:: manual: boolean
 
     :default: ``False``
+    :since: 1.6
 
     By default, Cabal will first try to satisfy dependencies with the
     default flag value and then, if that is not possible, with the
@@ -2479,10 +2807,51 @@
        else
          Main-is: Main.hs
 
+Common stanzas
+^^^^^^^^^^^^^^
+
+.. pkg-section:: common name
+    :since: 2.2
+    :synopsis: Common build info section
+
+Starting with Cabal-2.2 it's possible to use common build info stanzas.
+
+::
+
+      common deps
+        build-depends: base ^>= 4.11
+        ghc-options: -Wall
+
+      common test-deps
+        build-depends: tasty
+
+      library
+        import: deps
+        exposed-modules: Foo
+
+      test-suite tests
+        import: deps, test-deps
+        type: exitcode-stdio-1.0
+        main-is: Tests.hs
+        build-depends: foo
+
+-  You can use `build information`_ fields in common stanzas.
+
+-  Common stanzas must be defined before use.
+
+-  Common stanzas can import other common stanzas.
+
+-  You can import multiple stanzas at once. Stanza names must be separated by commas.
+
+.. Note::
+
+    The name `import` was chosen, because there is ``includes`` field.
+
 Source Repositories
 ^^^^^^^^^^^^^^^^^^^
 
 .. pkg-section:: source-repository
+    :since: 1.6
 
 It is often useful to be able to specify a source revision control
 repository for a package. Cabal lets you specifying this information in
diff --git a/cabal/Cabal/doc/file-format-changelog.rst b/cabal/Cabal/doc/file-format-changelog.rst
new file mode 100644
--- /dev/null
+++ b/cabal/Cabal/doc/file-format-changelog.rst
@@ -0,0 +1,144 @@
+Cabal file format changelog
+===========================
+
+Changes in 2.4
+--------------
+
+* Wildcard matching has been expanded. All previous wildcard
+  expressions are still valid; some will match strictly more files
+  than before. Specifically:
+
+  * Double-star (``**``) wildcards are now accepted for recursive
+    matching immediately before the final slash; they must be followed
+    by a filename wildcard (e.g., ``foo/**/*.html`` is valid;
+    ``foo/**/bar/*.html`` and ``foo/**/**/*.html``,
+    ``foo/**/bar.html`` are all invalid). As ``**`` was an error in
+    globs before, this does not affect any existing ``.cabal`` files
+    that previously worked.
+
+  * Wildcards now match when the pattern's extensions form a suffix of
+    the candidate file's extension, rather than requiring strict
+    equality (e.g., previously ``*.html`` did not match
+    ``foo.en.html``, but now it does).
+
+* License fields use identifiers from SPDX License List version
+  ``3.2 2018-07-10``
+
+
+``cabal-version: 2.2``
+----------------------
+
+* New :pkg-section:`common` stanzas and :pkg-field:`import`
+  pseudo-field added.
+
+* New :pkg-field:`library:virtual-modules` field added.
+
+* New :pkg-field:`cxx-sources` and :pkg-field:`cxx-options` fields
+  added for suppporting bundled foreign routines implemented in C++.
+
+* New :pkg-field:`asm-sources` and :pkg-field:`asm-options` fields
+  added for suppporting bundled foreign routines implemented in
+  assembler.
+
+* New :pkg-field:`extra-bundled-libraries` field for specifying
+  additional custom library objects to be installed.
+
+* Extended ``if`` control structure with support for ``elif`` keyword.
+
+* Changed default rules of :pkg-field:`build-type` field to infer
+  "build-type:" for "Simple"/"Custom" automatically.
+
+* :pkg-field:`license` field syntax changed to require SPDX
+  expression syntax (using SPDX license list version ``3.0 2017-12-28``).
+
+* Allow redundant leading or trailing commas in package fields (which
+  require commas) such as :pkg-field:`build-depends`.
+
+
+``cabal-version: 2.0``
+----------------------
+
+* New :pkg-field:`library:signatures` and :pkg-field:`mixins` fields
+  added for supporting Backpack_.
+
+* New :pkg-field:`build-tool-depends` field added for adding
+  build-time dependencies of executable components.
+
+* New :pkg-field:`custom-setup:autogen-modules` field added for declaring modules
+  which are generated at build time.
+
+* Support for new PVP_ caret-style version operator (``^>=``) added to
+  :pkg-field:`build-depends`.
+
+* Add support for new :pkg-section:`foreign-library` stanza.
+
+* Add support for :ref:`internal library stanzas <sublibs>`.
+
+* New CPP Macro ``CURRENT_PACKAGE_VERSION``.
+
+``cabal-version: 1.24``
+----------------------
+
+* New :pkg-section:`custom-setup` stanza and
+  :pkg-field:`custom-setup:setup-depends` field added for specifying dependencies
+  of custom ``Setup.hs`` scripts.
+
+* CPP Macros ``VERSION_$pkgname`` and ``MIN_VERSION_$pkgname`` are now
+  also generated for the current package.
+
+* New CPP Macros ``CURRENT_COMPONENT_ID`` and ``CURRENT_PACKAGE_KEY``.
+
+* New :pkg-field:`extra-framework-dirs` field added for specifying
+  extra locations to find OS X frameworks.
+
+``cabal-version: 1.22``
+----------------------
+
+* New :pkg-field:`library:reexported-modules` field.
+
+* Support for ``-none`` version constraint added to
+  :pkg-field:`build-depends`.
+
+* New :pkg-field:`license` type ``ISC`` added.
+
+``cabal-version: 1.20``
+----------------------
+
+* Add support for new :pkg-field:`license-files` field for declaring
+  multiple license documents.
+
+* New CPP Macro ``MIN_TOOL_VERSION_$buildtool``.
+
+* New :pkg-field:`license` types ``BSD2`` and ``MPL-2.0`` added.
+
+``cabal-version: 1.18``
+----------------------
+
+* Add support for new :pkg-field:`extra-doc-files` field for
+  specifying extra file assets referenced by the Haddock
+  documentation.
+
+* New :pkg-field:`license` type ``AGPL`` and ``AGPL-3`` added.
+
+* Add support for specifying a C/C++/obj-C source file in
+  :pkg-field:`executable:main-is` field.
+
+* Add ``getSysconfDir`` operation to ``Paths_`` API.
+
+``cabal-version: 1.16``
+----------------------
+
+.. todo::
+
+   this needs to be researched; there were only few changes between
+   1.12 and 1.18;
+
+``cabal-version: 1.12``
+----------------------
+
+* Change syntax of :pkg-field:`cabal-version` to support the new recommended
+  ``cabal-version: x.y`` style
+
+
+
+.. include:: references.inc
diff --git a/cabal/Cabal/doc/index.rst b/cabal/Cabal/doc/index.rst
--- a/cabal/Cabal/doc/index.rst
+++ b/cabal/Cabal/doc/index.rst
@@ -12,3 +12,4 @@
    bugs-and-stability
    nix-local-build-overview
    nix-integration
+   file-format-changelog
diff --git a/cabal/Cabal/doc/installing-packages.rst b/cabal/Cabal/doc/installing-packages.rst
--- a/cabal/Cabal/doc/installing-packages.rst
+++ b/cabal/Cabal/doc/installing-packages.rst
@@ -470,6 +470,13 @@
 :option:`--with-compiler` option is passed in a :option:`--with-hc-pkg` option
 and all options specified with :option:`--configure-option` are passed on.
 
+.. note::
+   `GNU autoconf places restrictions on paths, including the directory
+   that the package is built from.
+   <https://www.gnu.org/software/autoconf/manual/autoconf.html#File-System-Conventions>`_
+   The errors produced when this happens can be obscure; Cabal attempts to
+   detect and warn in this situation, but it is not perfect.
+
 In Cabal 2.0, support for a single positional argument was added to
 ``setup configure`` This makes Cabal configure a the specific component
 to be configured. Specified names can be qualified with ``lib:`` or
diff --git a/cabal/Cabal/doc/nix-local-build-overview.rst b/cabal/Cabal/doc/nix-local-build-overview.rst
--- a/cabal/Cabal/doc/nix-local-build-overview.rst
+++ b/cabal/Cabal/doc/nix-local-build-overview.rst
@@ -2,8 +2,17 @@
 ======================
 
 Nix-style local builds are a new build system implementation inspired by Nix.
-The Nix-style local build system is commonly called "new-build" for short after the ``cabal new-*`` family of commands that control it.
-However those names are only temporary until Nix-style local builds becomes the default.
+The Nix-style local build system is commonly called "new-build" for short
+after the ``cabal new-*`` family of commands that control it. However, those
+names are only temporary until Nix-style local builds become the default.
+This is expected to happen soon. For those who do not wish to use the new
+functionality, the classic project style will not be removed immediately,
+but these legacy commands will require the usage of the ``v1-`` prefix as of
+Cabal 3.0 and will be removed in a future release. For a future-proof
+way to use these commands in a script or tutorial that anticipates the
+possibility of another UI paradigm being devised in the future, there
+are also ``v2-`` prefixed versions that will reference the same functionality
+until such a point as it is completely removed from Cabal.
 
 Nix-style local builds combine the best of non-sandboxed and sandboxed Cabal:
 
diff --git a/cabal/Cabal/doc/nix-local-build.rst b/cabal/Cabal/doc/nix-local-build.rst
--- a/cabal/Cabal/doc/nix-local-build.rst
+++ b/cabal/Cabal/doc/nix-local-build.rst
@@ -45,8 +45,7 @@
 should not be checked in.)
 
 Then, to build every component of every package, from the top-level
-directory, run the command: (Warning: cabal-install-1.24 does NOT have
-this behavior; you will need to upgrade to HEAD.)
+directory, run the command: (using cabal-install-2.0 or greater.)
 
 ::
 
@@ -88,11 +87,6 @@
 How can I profile my library/application?
 -----------------------------------------
 
-First, make sure you have HEAD; 1.24 is affected by :issue:`3790`,
-which means that if any project which transitively depends on a
-package which has a Custom setup built against Cabal 1.22 or earlier
-will silently not work.
-
 Create or edit your ``cabal.project.local``, adding the following
 line::
 
@@ -157,7 +151,7 @@
 ``cabal new-build`` doesn't necessitate a rebuild of *every* transitive
 dependency in the global package store.
 
-In cabal-install HEAD, Nix-style local builds also take advantage of a
+In cabal-install 2.0 and above, Nix-style local builds also take advantage of a
 new Cabal library feature, `per-component
 builds <https://github.com/ezyang/ghc-proposals/blob/master/proposals/0000-componentized-cabal.rst>`__,
 where each component of a package is configured and built separately.
@@ -173,8 +167,8 @@
 there is no programmatic way to access the location of build products.
 The location of the build products is intended to be an internal
 implementation detail of new-build, but we also understand that many
-unimplemented features (e.g., ``new-install``) can only be reasonably
-worked around by accessing build products directly.
+unimplemented features can only be reasonably worked around by
+accessing build products directly.
 
 The location where build products can be found varies depending on the
 version of cabal-install:
@@ -184,7 +178,7 @@
    executable or test suite named ``pexe``, it would be located at
    ``dist-newstyle/build/p-0.1/build/pexe/pexe``.
 
--  In cabal-install HEAD, the dist directory for a package ``p-0.1``
+-  In cabal-install-2.0, the dist directory for a package ``p-0.1``
    defining a library built with GHC 8.0.1 on 64-bit Linux is
    ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1``. When
    per-component builds are enabled (any non-Custom package), a
@@ -195,7 +189,18 @@
    ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/c/pexe/build/pexe/pexe``
    (you can see why we want this to be an implementation detail!)
 
-The paths are a bit longer in HEAD but the benefit is that you can
+- In cabal-install-2.2 and above, the ``/c/`` part of the above path
+   is replaced with one of ``/l/``, ``/x/``, ``/f/``, ``/t/``, or
+   ``/b/``, depending on the type of component (sublibrary,
+   executable, foreign library, test suite, or benchmark
+   respectively). So the full path to an executable named ``pexe``
+   compiled with GHC 8.0.1 on a 64-bit Linux is now
+   ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/x/pexe/build/pexe/pexe``;
+   for a benchmark named ``pbench`` it now is
+   ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/b/pbench/build/pbench/pbench``;
+
+
+The paths are a bit longer in 2.0 and above but the benefit is that you can
 transparently have multiple builds with different versions of GHC. We
 plan to add the ability to create aliases for certain build
 configurations, and more convenient paths to access particularly useful
@@ -240,13 +245,29 @@
 ``improved-plan`` (binary)
     Like ``solver-plan``, but with all non-inplace packages improved
     into pre-existing copies from the store.
+``plan.json`` (JSON)
+    A JSON serialization of the computed install plan intended
+    for integrating ``cabal`` with external tooling.
+    The `cabal-plan <http://hackage.haskell.org/package/cabal-plan>`__
+    package provides a library for parsing ``plan.json`` files into a
+    Haskell data structure as well as an example tool showing possible
+    applications.
 
+    .. todo::
+
+        Document JSON schema (including version history of schema)
+
+
 Note that every package also has a local cache managed by the Cabal
 build system, e.g., in ``$distdir/cache``.
 
-There is another useful file in ``dist-newstyle/cache``, ``plan.json``,
-which is a JSON serialization of the computed install plan. (TODO: docs)
+There is another useful file in ``dist-newstyle/cache``,
+``plan.json``, which is a JSON serialization of the computed install
+plan and is intended for integrating with external tooling.
 
+
+
+
 Commands
 ========
 
@@ -358,23 +379,64 @@
 ``--enable-profiling`` will automatically make sure profiling libraries
 for all transitive dependencies are built and installed.)
 
+In addition ``cabal new-build`` accepts these flags:
+
+- ``--only-configure``: When given we will forgoe performing a full build and
+  abort after running the configure phase of each target package.
+
+
 cabal new-repl
 --------------
 
 ``cabal new-repl TARGET`` loads all of the modules of the target into
-GHCi as interpreted bytecode. It takes the same flags as
-``cabal new-build``.
+GHCi as interpreted bytecode. In addition to ``cabal new-build``'s flags,
+it takes an additional ``--repl-options`` flag.
 
+To avoid ``ghci`` specific flags from triggering unneeded global rebuilds these
+flags are now stripped from the internal configuration. As a result
+``--ghc-options`` will no longer (reliably) work to pass flags to ``ghci`` (or
+other repls). Instead, you should use the new ``--repl-options`` flag to
+specify these options to the invoked repl. (This flag also works on ``cabal
+repl`` and ``Setup repl`` on sufficiently new versions of Cabal.)
+
 Currently, it is not supported to pass multiple targets to ``new-repl``
 (``new-repl`` will just successively open a separate GHCi session for
 each target.)
 
+It also provides a way to experiment with libraries without needing to download
+them manually or to install them globally.
+
+This command opens a REPL with the current default target loaded, and a version
+of the ``vector`` package matching that specification exposed.
+
+:: 
+
+    $ cabal new-repl --build-depends "vector >= 0.12 && < 0.13"
+
+Both of these commands do the same thing as the above, but only exposes ``base``,
+``vector``, and the``vector`` package's transitive dependencies even if the user
+is in a project context.
+
+::
+
+    $ cabal new-repl --ignore-project --build-depends "vector >= 0.12 && < 0.13"
+    $ cabal new-repl --project='' --build-depends "vector >= 0.12 && < 0.13"
+
+This command would add ``vector``, but not (for example) ``primitive``, because
+it only includes the packages specified on the command line (and ``base``, which
+cannot be excluded for technical reasons).
+
+::
+
+    $ cabal new-repl --build-depends vector --no-transitive-deps
+
 cabal new-run
 -------------
 
 ``cabal new-run [TARGET [ARGS]]`` runs the executable specified by the
 target, which can be a component, a package or can be left blank, as
 long as it can uniquely identify an executable within the project.
+Tests and benchmarks are also treated as executables.
 
 See `the new-build section <#cabal-new-build>`__ for the target syntax.
 
@@ -389,6 +451,29 @@
 
     $ cabal new-run target -- -a -bcd --argument
 
+'new-run' also supports running script files that use a certain format. With
+a script that looks like:
+
+::
+
+    #!/usr/bin/env cabal
+    {- cabal:
+    build-depends: base ^>= 4.11
+                , shelly ^>= 1.8.1
+    -}
+
+    main :: IO ()
+    main = do
+        ...
+
+It can either be executed like any other script, using ``cabal`` as an
+interpreter, or through this command:
+
+::
+
+    $ cabal new-run script.hs
+    $ cabal new-run script.hs -- --arg1 # args are passed like this
+
 cabal new-freeze
 ----------------
 
@@ -436,9 +521,13 @@
 cabal new-haddock
 -----------------
 
-``cabal new-haddock [FLAGS] TARGET`` builds Haddock documentation for
+``cabal new-haddock [FLAGS] [TARGET]`` builds Haddock documentation for
 the specified packages within the project.
 
+If a target is not a library :cfg-field:`haddock-benchmarks`,
+:cfg-field:`haddock-executables`, :cfg-field:`haddock-internal`,
+:cfg-field:`haddock-tests` will be implied as necessary.
+
 cabal new-exec
 ---------------
 
@@ -446,15 +535,116 @@
 using the project's environment. That is, passing the right flags to compiler
 invocations and bringing the project's executables into scope.
 
-Unsupported commands
---------------------
+cabal new-install
+-----------------
 
-The following commands are not currently supported:
+``cabal new-install [FLAGS] PACKAGES`` builds the specified packages and 
+symlinks their executables in ``symlink-bindir`` (usually ``~/.cabal/bin``).
 
-``cabal new-install`` (:issue:`3737` and :issue:`3332`)
-    Workaround: no good workaround at the moment. (But note that you no
-    longer need to install libraries before building!)
+For example this command will build the latest ``cabal-install`` and symlink
+its ``cabal`` executable:
 
+::
+
+    $ cabal new-install cabal-install
+
+In addition, it's possible to use ``cabal new-install`` to install components
+of a local project. For example, with an up-to-date Git clone of the Cabal
+repository, this command will build cabal-install HEAD and symlink the
+``cabal`` executable:
+
+::
+
+    $ cabal new-install exe:cabal
+
+It is also possible to "install" libraries using the ``--lib`` flag. For 
+example, this command will build the latest Cabal library and install it:
+
+::
+
+    $ cabal new-install --lib Cabal
+
+This works by managing GHC environments. By default, it is writing to the
+global environment in ``~/.ghc/$ARCH-$OS-$GHCVER/environments/default``.
+``new-install`` provides the ``--package-env`` flag to control which of
+these environments is modified.
+
+This command will modify the environment file in the current directory:
+
+::
+
+    $ cabal new-install --lib Cabal --package-env .
+
+This command will modify the enviroment file in the ``~/foo`` directory:
+
+::
+
+    $ cabal new-install --lib Cabal --package-env foo/
+
+Do note that the results of the previous two commands will be overwritten by
+the use of other new-style commands, so it is not reccomended to use them inside
+a project directory.
+
+This command will modify the environment in the "local.env" file in the
+current directory:
+
+::
+
+    $ cabal new-install --lib Cabal --package-env local.env
+
+This command will modify the ``myenv`` named global environment:
+
+::
+
+    $ cabal new-install --lib Cabal --package-env myenv
+
+If you wish to create a named environment file in the current directory where
+the name does not contain an extension, you must reference it as ``./myenv``.
+
+You can learn more about how to use these environments in `this section of the
+GHC manual <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/packages.html#package-environments>`_.
+
+cabal new-clean
+---------------
+
+``cabal new-clean [FLAGS]`` cleans up the temporary files and build artifacts
+stored in the ``dist-newstyle`` folder.
+
+By default, it removes the entire folder, but it can also spare the configuration
+and caches if the ``--save-config`` option is given, in which case it only removes
+the build artefacts (``.hi``, ``.o`` along with any other temporary files generated
+by the compiler, along with the build output).
+
+cabal new-sdist
+---------------
+
+``cabal new-sdist [FLAGS] [TARGETS]`` takes the crucial files needed to build ``TARGETS``
+and puts them into an archive format ready for upload to Hackage. These archives are stable
+and two archives of the same format built from the same source will hash to the same value.
+
+``cabal new-sdist`` takes the following flags:
+
+- ``-l``, ``--list-only``: Rather than creating an archive, lists files that would be included.
+  Output is to ``stdout`` by default. The file paths are relative to the project's root
+  directory.
+
+- ``--targz``: Output an archive in ``.tar.gz`` format.
+
+- ``--zip``: Output an archive in ``.zip`` format.
+
+- ``-o``, ``--output-dir``: Sets the output dir, if a non-default one is desired. The default is
+  ``dist-newstyle/sdist/``. ``--output-dir -`` will send output to ``stdout``
+  unless multiple archives are being created.
+
+- ``-z``, ``--null``: Only used with ``--list-only``. Separates filenames with a NUL
+  byte instead of newlines.
+
+``new-sdist`` is inherently incompatible with sdist hooks, not due to implementation but due
+to fundamental core invariants (same source code should result in the same tarball, byte for
+byte) that must be satisfied for it to function correctly in the larger new-build ecosystem.
+``autogen-modules`` is able to replace uses of the hooks to add generated modules, along with
+the custom publishing of Haddock documentation to Hackage.
+
 Configuring builds with cabal.project
 =====================================
 
@@ -508,16 +698,16 @@
 
     2. They can specify a glob-style wildcards, which must match one or
        more (a) directories containing a (single) Cabal file, (b) Cabal
-       files (extension ``.cabal``), or (c) [STRIKEOUT:tarballs which
-       contain Cabal packages (extension ``.tar.gz``)] (not implemented
-       yet). For example, to match all Cabal files in all
+       files (extension ``.cabal``), or (c) tarballs which contain Cabal
+       packages (extension ``.tar.gz``).
+       For example, to match all Cabal files in all
        subdirectories, as well as the Cabal projects in the parent
        directories ``foo`` and ``bar``, use
        ``packages: */*.cabal ../{foo,bar}/``
 
-    3. [STRIKEOUT:They can specify an ``http``, ``https`` or ``file``
+    3. They can specify an ``http``, ``https`` or ``file``
        URL, representing the path to a remote tarball to be downloaded
-       and built.] (not implemented yet)
+       and built.
 
     There is no command line variant of this field; see :issue:`3585`.
 
@@ -702,7 +892,7 @@
 
     Valid constraints take the same form as for the `constraint
     command line option
-    <installing-packages.html#cmdoption-setup-configure--constraint>`__.
+    <installing-packages.html#cmdoption-setup-configure-constraint>`__.
 
 .. cfg-field:: preferences: preference (comma separated)
                --preference="pkg >= 2.0"
@@ -861,7 +1051,7 @@
 Package configuration options
 -----------------------------
 
-Package options affect the building of specific packages. There are two
+Package options affect the building of specific packages. There are three
 ways a package option can be specified:
 
 -  They can be specified at the top-level, in which case they apply only
@@ -871,6 +1061,11 @@
    apply to the build of the package, whether or not it is local or
    external.
 
+-  They can be specified inside an ``package *`` stanza, in which case they
+   apply to all packages, local ones from the project and also external
+   dependencies.
+
+
 For example, the following options specify that :cfg-field:`optimization`
 should be turned off for all local packages, and that ``bytestring`` (possibly
 an external dependency) should be built with ``-fno-state-hack``::
@@ -1508,9 +1703,6 @@
 Haddock options
 ^^^^^^^^^^^^^^^
 
-Documentation building support is fairly sparse at the moment. Let us
-know if it's a priority for you!
-
 .. cfg-field:: documentation: boolean
                --enable-documentation
                --disable-documentation
@@ -1523,6 +1715,11 @@
     The command line variant of this flag is ``--enable-documentation``
     and ``--disable-documentation``.
 
+    `documentation: true` does not imply :cfg-field:`haddock-benchmarks`,
+    :cfg-field:`haddock-executables`, :cfg-field:`haddock-internal` or
+    :cfg-field:`haddock-tests`. These need to be enabled separately if
+    desired.
+
 .. cfg-field:: doc-index-file: templated path
                --doc-index-file=TEMPLATE
     :synopsis: Path to haddock templates.
@@ -1676,6 +1873,21 @@
 
 Advanced global configuration options
 -------------------------------------
+
+.. cfg-field:: write-ghc-environment-files: always, never, or ghc-8.4.4+
+               --write-ghc-enviroment-files=policy
+    :synopsis: Whether a ``.ghc.enviroment`` should be created after a successful build.
+
+    :default: ``ghc-8.4.4+``
+
+    Whether a `GHC package environment file <https://downloads.haskell.org/~ghc/master/users-guide/packages.html#package-environments>`_
+    should be created after a successful build.
+
+    Defaults to creating them only when compiling with GHC 8.4.4 and
+    older (GHC 8.4.4 `is the first version <https://ghc.haskell.org/trac/ghc/ticket/13753>`_ that supports the
+    ``-package-env -`` option that allows ignoring the package
+    environment files).
+
 
 .. cfg-field:: http-transport: curl, wget, powershell, or plain-http
                --http-transport=transport
diff --git a/cabal/Cabal/doc/references.inc b/cabal/Cabal/doc/references.inc
--- a/cabal/Cabal/doc/references.inc
+++ b/cabal/Cabal/doc/references.inc
@@ -20,3 +20,5 @@
 .. _HsColour: http://www.cs.york.ac.uk/fp/darcs/hscolour/
 
 .. _cpphs: http://projects.haskell.org/cpphs/
+
+.. _ABNF: https://tools.ietf.org/html/rfc5234
diff --git a/cabal/Cabal/misc/travis-diff-files.sh b/cabal/Cabal/misc/travis-diff-files.sh
--- a/cabal/Cabal/misc/travis-diff-files.sh
+++ b/cabal/Cabal/misc/travis-diff-files.sh
@@ -1,3 +1,5 @@
 #!/bin/sh
+set -eax
+
 git status > /dev/null # See 09a71929e433f36b27fd6a4938469d3bbbd5e191
 git diff-files -p --exit-code
diff --git a/cabal/Makefile b/cabal/Makefile
--- a/cabal/Makefile
+++ b/cabal/Makefile
@@ -1,23 +1,63 @@
-.PHONY : all lexer lib exe doctest gen-extra-source-files
+.PHONY : all lexer sdpx lib exe doctest
+.PHONY : gen-extra-source-files gen-extra-source-files-lib gen-extra-source-files-cli
+.PHONY : cabal-install-dev cabal-install-prod
 
 LEXER_HS:=Cabal/Distribution/Parsec/Lexer.hs
+SPDX_LICENSE_HS:=Cabal/Distribution/SPDX/LicenseId.hs
+SPDX_EXCEPTION_HS:=Cabal/Distribution/SPDX/LicenseExceptionId.hs
 
 all : exe lib
 
 lexer : $(LEXER_HS)
 
+spdx : $(SPDX_LICENSE_HS) $(SPDX_EXCEPTION_HS)
+
 $(LEXER_HS) : boot/Lexer.x
 	alex --latin1 --ghc -o $@ $^
+	cat -s $@ > Lexer.tmp
+	mv Lexer.tmp $@
 
+$(SPDX_LICENSE_HS) : boot/SPDX.LicenseId.template.hs cabal-dev-scripts/src/GenUtils.hs cabal-dev-scripts/src/GenSPDX.hs license-list-data/licenses-3.0.json license-list-data/licenses-3.2.json
+	cabal new-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-spdx -- boot/SPDX.LicenseId.template.hs license-list-data/licenses-3.0.json license-list-data/licenses-3.2.json $(SPDX_LICENSE_HS)
+
+$(SPDX_EXCEPTION_HS) : boot/SPDX.LicenseExceptionId.template.hs cabal-dev-scripts/src/GenUtils.hs cabal-dev-scripts/src/GenSPDXExc.hs license-list-data/exceptions-3.0.json license-list-data/exceptions-3.2.json
+	cabal new-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-spdx-exc -- boot/SPDX.LicenseExceptionId.template.hs license-list-data/exceptions-3.0.json license-list-data/exceptions-3.2.json $(SPDX_EXCEPTION_HS)
+
+cabal-install-prod : cabal-install/cabal-install.cabal.pp
+	runghc cabal-dev-scripts/src/Preprocessor.hs -o cabal-install/cabal-install.cabal cabal-install/cabal-install.cabal.pp
+	git update-index --no-assume-unchanged cabal-install/cabal-install.cabal
+
+cabal-install-dev : cabal-install/cabal-install.cabal.pp
+	runghc cabal-dev-scripts/src/Preprocessor.hs -o cabal-install/cabal-install.cabal -f CABAL_FLAG_LIB cabal-install/cabal-install.cabal.pp
+	@echo "tell git to ignore changes to cabal-install.cabal:"
+	@echo "git update-index --assume-unchanged cabal-install/cabal-install.cabal"
+
+cabal-install-monolithic : cabal-install/cabal-install.cabal.pp
+	runghc cabal-dev-scripts/src/Preprocessor.hs -o cabal-install/cabal-install.cabal -f CABAL_FLAG_LIB -f CABAL_FLAG_MONOLITHIC cabal-install/cabal-install.cabal.pp
+	@echo "tell git to ignore changes to cabal-install.cabal:"
+	@echo "git update-index --assume-unchanged cabal-install/cabal-install.cabal"
+
 lib : $(LEXER_HS)
 	cabal new-build --enable-tests Cabal
 
 exe : $(LEXER_HS)
-	cabal new-build --enable-tests cabal
+	cabal new-build --enable-tests cabal-install
 
 doctest :
 	doctest --fast Cabal/Distribution Cabal/Language
 
-gen-extra-source-files:
-	cabal new-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-extra-source-files -- Cabal/Cabal.cabal
-	cabal new-run --builddir=dist-newstyle=meta --project-file=cabal.project.meta gen-extra-source-files -- cabal-install/cabal-install.cabal
+gen-extra-source-files : gen-extra-source-files-lib gen-extra-source-files-cli
+
+gen-extra-source-files-lib :
+	cabal new-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-extra-source-files -- $$(pwd)/Cabal/Cabal.cabal
+
+# We need to generate cabal-install-dev so the test modules are in .cabal file!
+gen-extra-source-files-cli :
+	$(MAKE) cabal-install-dev
+	cabal new-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-extra-source-files -- $$(pwd)/cabal-install/cabal-install.cabal.pp $$(pwd)/cabal-install/cabal-install.cabal
+	$(MAKE) cabal-install-prod
+
+cabal-install-test:
+	cabal new-build -j3 all --disable-tests --disable-benchmarks
+	rm -rf .ghc.environment.*
+	cd cabal-testsuite && `cabal-plan list-bin cabal-tests` --with-cabal=`cabal-plan list-bin cabal` --hide-successes -j3 ${TEST}
diff --git a/cabal/README.md b/cabal/README.md
--- a/cabal/README.md
+++ b/cabal/README.md
@@ -1,4 +1,4 @@
-# Cabal [![Hackage version](https://img.shields.io/hackage/v/Cabal.svg?label=Hackage)](https://hackage.haskell.org/package/Cabal) [![Stackage version](https://www.stackage.org/package/Cabal/badge/lts?label=Stackage)](https://www.stackage.org/package/Cabal) [![Build Status](https://secure.travis-ci.org/haskell/cabal.svg?branch=master)](http://travis-ci.org/haskell/cabal) [![Windows build status](https://ci.appveyor.com/api/projects/status/yotutrf4i4wn5d9y/branch/master?svg=true)](https://ci.appveyor.com/project/23Skidoo/cabal) [![Documentation Status](http://readthedocs.org/projects/cabal/badge/?version=latest)](http://cabal.readthedocs.io/en/latest/?badge=latest)
+# Cabal [![Hackage version](https://img.shields.io/hackage/v/Cabal.svg?label=Hackage)](https://hackage.haskell.org/package/Cabal) [![Stackage version](https://www.stackage.org/package/Cabal/badge/lts?label=Stackage)](https://www.stackage.org/package/Cabal) [![Build Status](https://secure.travis-ci.org/haskell/cabal.svg?branch=master)](http://travis-ci.org/haskell/cabal) [![Windows build status](https://ci.appveyor.com/api/projects/status/github/haskell/cabal?branch=master&svg=true)](https://ci.appveyor.com/project/23Skidoo/cabal) [![Documentation Status](http://readthedocs.org/projects/cabal/badge/?version=latest)](http://cabal.readthedocs.io/en/latest/?badge=latest)
 
 This Cabal Git repository contains the following packages:
 
@@ -87,11 +87,11 @@
 
 In more detail, suppose you have checkouts of Cabal at `~/cabal-prod`
 and `~/cabal-dev`, and you have a release copy of cabal installed at
-`/opt/cabal/1.24/bin/cabal`.  First, build your production tree:
+`/opt/cabal/2.4/bin/cabal`.  First, build your production tree:
 
 ~~~~
 cd ~/cabal-prod
-/opt/cabal/1.24/bin/cabal new-build cabal
+/opt/cabal/2.4/bin/cabal new-build cabal
 ~~~~
 
 This will produce a cabal binary (see also: [Where are my build products?](http://cabal.readthedocs.io/en/latest/nix-local-build.html#where-are-my-build-products)
diff --git a/cabal/appveyor.yml b/cabal/appveyor.yml
--- a/cabal/appveyor.yml
+++ b/cabal/appveyor.yml
@@ -1,59 +1,37 @@
 install:
   # Using '-y' and 'refreshenv' as a workaround to:
   # https://github.com/haskell/cabal/issues/3687
-  - choco install -y ghc --version 8.0.2
+  - choco source add -n mistuke -s https://www.myget.org/F/mistuke/api/v2
+  - choco install -y ghc --version 8.0.2 --ignore-dependencies
+  - choco install -y cabal-head -pre
   - refreshenv
   # See http://help.appveyor.com/discussions/problems/6312-curl-command-not-found#comment_42195491
   # NB: Do this after refreshenv, otherwise it will be clobbered!
-  - set PATH=%APPDATA%\cabal\bin;C:\Program Files\Git\mingw64\bin;%PATH%
-  # TODO: remove --insecure, this is to workaround haskell.org
-  # failing to send intermediate cert; see https://github.com/haskell/cabal/pull/4172
-  - curl -o cabal.zip --insecure --progress-bar https://www.haskell.org/cabal/release/cabal-install-2.0.0.0/cabal-install-2.0.0.0-x86_64-unknown-mingw32.zip
-  - 7z x -bd cabal.zip
+  - set PATH=%APPDATA%\cabal\bin;C:\Program Files\Git\cmd;C:\Program Files\Git\mingw64\bin;C:\msys64\usr\bin;%PATH%
   - cabal --version
-  - cabal update
-  # Install parsec, text and mtl, also alex and happy
-  - echo "" | appveyor-retry cabal install parsec-3.1.11 text-1.2.2.2 mtl-2.2.1 alex-3.1.7 happy-1.19.5
+  - cabal %CABOPTS% update
+  - cabal %CABOPTS% install happy alex
 
-build_script:
-  - cd Cabal
-  - ghc --make -threaded -i -i. Setup.hs -Wall -Werror -XRank2Types -XFlexibleContexts
+environment:
+  global:
+    CABOPTS:  "--store-dir=C:\\SR"
 
-  # 'echo "" |' works around an AppVeyor issue:
-  # https://github.com/commercialhaskell/stack/issues/1097#issuecomment-145747849
-  - echo "" | ..\appveyor-retry ..\cabal install --only-dependencies --enable-tests
+cache:
+  - "C:\\sr"
 
-  - Setup configure --user --ghc-option=-Werror --enable-tests
-  - Setup build
-  - Setup test --show-details=streaming --test-option=--hide-successes
-  - Setup install
-  # hackage-repo-tool doesn't build on Windows:
-  # https://github.com/well-typed/hackage-security/issues/175
-  # - echo "" | ..\cabal install hackage-repo-tool --allow-newer=Cabal,time --constraint="Cabal == 2.1.0.0"
-  - cd ..\cabal-testsuite
-  - ghc --make -threaded -i Setup.hs -package Cabal-2.1.0.0
-  - echo "" | ..\appveyor-retry ..\cabal install --only-dependencies --enable-tests
-  - Setup configure --user --ghc-option=-Werror --enable-tests
-  - Setup build
-  # Must install the test suite, so that our GHCi invocation picks it up
-  - Setup install
-  # Copy the setup script into the spot cabal-tests expects it
-  - mkdir dist\setup
-  - cp Setup.exe dist\setup
-  - dist\build\cabal-tests\cabal-tests.exe -j3
-  # - Setup test --show-details=streaming --test-option=--hide-successes
-  - cd ..\cabal-install
-  - ghc --make -threaded -i -i. Setup.hs -Wall -Werror
-  - echo "" | ..\appveyor-retry ..\cabal install --only-dependencies --enable-tests -flib
-  - ..\cabal configure --user --ghc-option=-Werror --enable-tests -flib
-  - ..\cabal build
-  # update package index again, this time for the cabal under test
-  - dist\build\cabal\cabal.exe update
-  # run cabal-testsuite first as it has better logging
-  - cd ..\cabal-testsuite
-  - dist\build\cabal-tests\cabal-tests.exe -j3 --skip-setup-tests --with-cabal=..\cabal-install\dist\build\cabal\cabal.exe
-  - cd ..\cabal-install
-  - ..\cabal test unit-tests --show-details=streaming --test-option=--pattern=!FileMonitor --test-option=--hide-successes
-  - ..\cabal test integration-tests2 --show-details=streaming --test-option=--hide-successes
-  - ..\cabal test solver-quickcheck --show-details=streaming --test-option=--hide-successes --test-option=--quickcheck-tests=1000
-  - ..\cabal test memory-usage-tests --show-details=streaming
+build_script:
+  - runghc cabal-dev-scripts/src/Preprocessor.hs -o cabal-install/cabal-install.cabal -f CABAL_FLAG_LIB cabal-install/cabal-install.cabal.pp
+  - cabal %CABOPTS% new-configure --enable-tests
+  - appveyor-retry cabal %CABOPTS% new-build lib:Cabal --only-dependencies
+  - cabal %CABOPTS% new-build lib:Cabal
+  - appveyor-retry cabal %CABOPTS% new-build Cabal:tests --only-dependencies
+  - cabal %CABOPTS% new-test Cabal
+  - appveyor-retry cabal %CABOPTS% new-build exe:cabal exe:cabal-tests --only-dependencies
+  - cabal %CABOPTS% new-build exe:cabal
+  - cabal %CABOPTS% new-run cabal-tests -- -j3 --with-cabal=dist-newstyle\build\x86_64-windows\ghc-8.0.2\cabal-install-2.4.1.0\x\cabal\build\cabal\cabal.exe
+  - appveyor-retry cabal %CABOPTS% new-build cabal-install:tests --only-dependencies
+  - cd cabal-install
+  - cabal %CABOPTS% new-run cabal-install:memory-usage-tests
+  - cabal %CABOPTS% new-run cabal-install:solver-quickcheck
+  - cabal %CABOPTS% new-run cabal-install:integration-tests2
+  - cabal %CABOPTS% new-run cabal-install:unit-tests -- --pattern "! (/FileMonitor/ || /VCS/ || /Get/)"
diff --git a/cabal/boot/Lexer.x b/cabal/boot/Lexer.x
--- a/cabal/boot/Lexer.x
+++ b/cabal/boot/Lexer.x
@@ -73,6 +73,7 @@
 @bom          = \xef \xbb \xbf
 @nbsp         = \xc2 \xa0
 @nbspspacetab = ($spacetab | @nbsp)
+@nbspspace    = ($space | @nbsp)
 @nl           = \n | \r\n | \r
 @name         = $namecore+
 @string       = \" ( $instr | \\ $instresc )* \"
@@ -83,7 +84,7 @@
 
 <0> {
   @bom?  { \_ len _ -> do
-              when (len /= 0) $ addWarning LexWarningBOM "Byte-order mark found at the beginning of the file"
+              when (len /= 0) $ addWarning LexWarningBOM
               setStartCode bol_section
               lexToken
          }
@@ -97,8 +98,7 @@
 }
 
 <bol_section> {
-  @nbspspacetab*  --TODO prevent or record leading tabs
-                   { \pos len inp -> checkWhitespace len inp >>
+  @nbspspacetab*   { \pos len inp -> checkLeadingWhitespace len inp >>
                                      if B.length inp == len
                                        then return (L pos EOF)
                                        else setStartCode in_section
@@ -123,8 +123,7 @@
 }
 
 <bol_field_layout> {
-  @nbspspacetab* --TODO prevent or record leading tabs
-                { \pos len inp -> checkWhitespace len inp >>= \len' ->
+  @nbspspacetab* { \pos len inp -> checkLeadingWhitespace len inp >>= \len' ->
                                   if B.length inp == len
                                     then return (L pos EOF)
                                     else setStartCode in_field_layout
@@ -132,7 +131,7 @@
 }
 
 <in_field_layout> {
-  $spacetab+; --TODO prevent or record leading tabs
+  $spacetab+;
   $field_layout' $field_layout*  { toki TokFieldLine }
   @nl             { \_ _ _ -> adjustPos retPos >> setStartCode bol_field_layout >> lexToken }
 }
@@ -142,7 +141,7 @@
 }
 
 <in_field_braces> {
-  $spacetab+; --TODO prevent or record leading tabs
+  $spacetab+;
   $field_braces' $field_braces*    { toki TokFieldLine }
   \{                { tok  OpenBrace  }
   \}                { tok  CloseBrace }
@@ -173,10 +172,17 @@
 tok :: Token -> Position -> Int -> ByteString -> Lex LToken
 tok  t pos _len _input = return $! L pos t
 
+checkLeadingWhitespace :: Int -> ByteString -> Lex Int
+checkLeadingWhitespace len bs
+    | B.any (== 9) (B.take len bs) = do
+        addWarning LexWarningTab
+        checkWhitespace len bs
+    | otherwise = checkWhitespace len bs
+
 checkWhitespace :: Int -> ByteString -> Lex Int
 checkWhitespace len bs
     | B.any (== 194) (B.take len bs) = do
-        addWarning LexWarningNBSP "Non-breaking space found"
+        addWarning LexWarningNBSP
         return $ len - B.count 194 (B.take len bs)
     | otherwise = return len
 
diff --git a/cabal/boot/SPDX.LicenseExceptionId.template.hs b/cabal/boot/SPDX.LicenseExceptionId.template.hs
new file mode 100644
--- /dev/null
+++ b/cabal/boot/SPDX.LicenseExceptionId.template.hs
@@ -0,0 +1,91 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+module Distribution.SPDX.LicenseExceptionId (
+    LicenseExceptionId (..),
+    licenseExceptionId,
+    licenseExceptionName,
+    mkLicenseExceptionId,
+    licenseExceptionIdList,
+    ) where
+
+import Distribution.Compat.Prelude
+import Prelude ()
+
+import Distribution.Pretty
+import Distribution.Parsec.Class
+import Distribution.Utils.Generic (isAsciiAlphaNum)
+import Distribution.SPDX.LicenseListVersion
+
+import qualified Data.Map.Strict as Map
+import qualified Distribution.Compat.CharParsing as P
+import qualified Text.PrettyPrint as Disp
+
+-------------------------------------------------------------------------------
+-- LicenseExceptionId
+-------------------------------------------------------------------------------
+
+-- | SPDX License identifier
+data LicenseExceptionId
+{{{ licenseIds }}}
+  deriving (Eq, Ord, Enum, Bounded, Show, Read, Typeable, Data, Generic)
+
+instance Binary LicenseExceptionId
+
+instance Pretty LicenseExceptionId where
+    pretty = Disp.text . licenseExceptionId
+
+instance Parsec LicenseExceptionId where
+    parsec = do
+        n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'
+        v <- askCabalSpecVersion
+        maybe (fail $ "Unknown SPDX license exception identifier: " ++ n) return $
+            mkLicenseExceptionId (cabalSpecVersionToSPDXListVersion v) n
+
+instance NFData LicenseExceptionId where
+    rnf l = l `seq` ()
+
+-------------------------------------------------------------------------------
+-- License Data
+-------------------------------------------------------------------------------
+
+-- | License SPDX identifier, e.g. @"BSD-3-Clause"@.
+licenseExceptionId :: LicenseExceptionId -> String
+{{#licenses}}
+licenseExceptionId {{licenseCon}} = {{{licenseId}}}
+{{/licenses}}
+
+-- | License name, e.g. @"GNU General Public License v2.0 only"@
+licenseExceptionName :: LicenseExceptionId -> String
+{{#licenses}}
+licenseExceptionName {{licenseCon}} = {{{licenseName}}}
+{{/licenses}}
+
+-------------------------------------------------------------------------------
+-- Creation
+-------------------------------------------------------------------------------
+
+licenseExceptionIdList :: LicenseListVersion -> [LicenseExceptionId]
+licenseExceptionIdList LicenseListVersion_3_0 =
+{{{licenseList_3_0}}}
+    ++ bulkOfLicenses
+licenseExceptionIdList LicenseListVersion_3_2 =
+{{{licenseList_3_2}}}
+    ++ bulkOfLicenses
+
+-- | Create a 'LicenseExceptionId' from a 'String'.
+mkLicenseExceptionId :: LicenseListVersion -> String -> Maybe LicenseExceptionId
+mkLicenseExceptionId LicenseListVersion_3_0 s = Map.lookup s stringLookup_3_0
+mkLicenseExceptionId LicenseListVersion_3_2 s = Map.lookup s stringLookup_3_2
+
+stringLookup_3_0 :: Map String LicenseExceptionId
+stringLookup_3_0 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $
+    licenseExceptionIdList LicenseListVersion_3_0
+
+stringLookup_3_2 :: Map String LicenseExceptionId
+stringLookup_3_2 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $
+    licenseExceptionIdList LicenseListVersion_3_2
+
+--  | License exceptions in all SPDX License lists
+bulkOfLicenses :: [LicenseExceptionId]
+bulkOfLicenses =
+{{{licenseList_all}}}
diff --git a/cabal/boot/SPDX.LicenseId.template.hs b/cabal/boot/SPDX.LicenseId.template.hs
new file mode 100644
--- /dev/null
+++ b/cabal/boot/SPDX.LicenseId.template.hs
@@ -0,0 +1,149 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+module Distribution.SPDX.LicenseId (
+    LicenseId (..),
+    licenseId,
+    licenseName,
+    licenseIsOsiApproved,
+    mkLicenseId,
+    licenseIdList,
+    -- * Helpers
+    licenseIdMigrationMessage,
+    ) where
+
+import Distribution.Compat.Prelude
+import Prelude ()
+
+import Distribution.Pretty
+import Distribution.Parsec.Class
+import Distribution.Utils.Generic (isAsciiAlphaNum)
+import Distribution.SPDX.LicenseListVersion
+
+import qualified Data.Map.Strict as Map
+import qualified Distribution.Compat.CharParsing as P
+import qualified Text.PrettyPrint as Disp
+
+-------------------------------------------------------------------------------
+-- LicenseId
+-------------------------------------------------------------------------------
+
+-- | SPDX License identifier
+data LicenseId
+{{{ licenseIds }}}
+  deriving (Eq, Ord, Enum, Bounded, Show, Read, Typeable, Data, Generic)
+
+instance Binary LicenseId
+
+instance Pretty LicenseId where
+    pretty = Disp.text . licenseId
+
+-- |
+-- >>> eitherParsec "BSD-3-Clause" :: Either String LicenseId
+-- Right BSD_3_Clause
+--
+-- >>> eitherParsec "BSD3" :: Either String LicenseId
+-- Left "...Unknown SPDX license identifier: 'BSD3' Do you mean BSD-3-Clause?"
+--
+instance Parsec LicenseId where
+    parsec = do
+        n <- some $ P.satisfy $ \c -> isAsciiAlphaNum c || c == '-' || c == '.'
+        v <- askCabalSpecVersion
+        maybe (fail $ "Unknown SPDX license identifier: '" ++  n ++ "' " ++ licenseIdMigrationMessage n) return $
+            mkLicenseId (cabalSpecVersionToSPDXListVersion v) n
+
+instance NFData LicenseId where
+    rnf l = l `seq` ()
+
+-- | Help message for migrating from non-SPDX license identifiers.
+--
+-- Old 'License' is almost SPDX, except for 'BSD2', 'BSD3'. This function
+-- suggests SPDX variant:
+--
+-- >>> licenseIdMigrationMessage "BSD3"
+-- "Do you mean BSD-3-Clause?"
+--
+-- Also 'OtherLicense', 'AllRightsReserved', and 'PublicDomain' aren't
+-- valid SPDX identifiers
+--
+-- >>> traverse_ (print . licenseIdMigrationMessage) [ "OtherLicense", "AllRightsReserved", "PublicDomain" ]
+-- "SPDX license list contains plenty of licenses. See https://spdx.org/licenses/. Also they can be combined into complex expressions with AND and OR."
+-- "You can use NONE as a value of license field."
+-- "Public Domain is a complex matter. See https://wiki.spdx.org/view/Legal_Team/Decisions/Dealing_with_Public_Domain_within_SPDX_Files. Consider using a proper license."
+--
+-- SPDX License list version 3.0 introduced "-only" and "-or-later" variants for GNU family of licenses.
+-- See <https://spdx.org/news/news/2018/01/license-list-30-released>
+-- >>> licenseIdMigrationMessage "GPL-2.0"
+-- "SPDX license list 3.0 deprecated suffixless variants of GNU family of licenses. Use GPL-2.0-only or GPL-2.0-or-later."
+--
+-- For other common licenses their old license format coincides with the SPDX identifiers:
+--
+-- >>> traverse eitherParsec ["GPL-2.0-only", "GPL-3.0-only", "LGPL-2.1-only", "MIT", "ISC", "MPL-2.0", "Apache-2.0"] :: Either String [LicenseId]
+-- Right [GPL_2_0_only,GPL_3_0_only,LGPL_2_1_only,MIT,ISC,MPL_2_0,Apache_2_0]
+--
+licenseIdMigrationMessage :: String -> String
+licenseIdMigrationMessage = go where
+    go l | gnuVariant l    = "SPDX license list 3.0 deprecated suffixless variants of GNU family of licenses. Use " ++ l ++ "-only or " ++ l ++ "-or-later."
+    go "BSD3"              = "Do you mean BSD-3-Clause?"
+    go "BSD2"              = "Do you mean BSD-2-Clause?"
+    go "AllRightsReserved" = "You can use NONE as a value of license field."
+    go "OtherLicense"      = "SPDX license list contains plenty of licenses. See https://spdx.org/licenses/. Also they can be combined into complex expressions with AND and OR."
+    go "PublicDomain"      = "Public Domain is a complex matter. See https://wiki.spdx.org/view/Legal_Team/Decisions/Dealing_with_Public_Domain_within_SPDX_Files. Consider using a proper license."
+
+    -- otherwise, we don't know
+    go _ = ""
+
+    gnuVariant = flip elem ["GPL-2.0", "GPL-3.0", "LGPL-2.1", "LGPL-3.0", "AGPL-3.0" ]
+
+-------------------------------------------------------------------------------
+-- License Data
+-------------------------------------------------------------------------------
+
+-- | License SPDX identifier, e.g. @"BSD-3-Clause"@.
+licenseId :: LicenseId -> String
+{{#licenses}}
+licenseId {{licenseCon}} = {{{licenseId}}}
+{{/licenses}}
+
+-- | License name, e.g. @"GNU General Public License v2.0 only"@
+licenseName :: LicenseId -> String
+{{#licenses}}
+licenseName {{licenseCon}} = {{{licenseName}}}
+{{/licenses}}
+
+-- | Whether the license is approved by Open Source Initiative (OSI).
+--
+-- See <https://opensource.org/licenses/alphabetical>.
+licenseIsOsiApproved :: LicenseId -> Bool
+{{#licenses}}
+licenseIsOsiApproved {{licenseCon}} = {{#isOsiApproved}}True{{/isOsiApproved}}{{^isOsiApproved}}False{{/isOsiApproved}}
+{{/licenses}}
+
+-------------------------------------------------------------------------------
+-- Creation
+-------------------------------------------------------------------------------
+
+licenseIdList :: LicenseListVersion -> [LicenseId]
+licenseIdList LicenseListVersion_3_0 =
+{{{licenseList_3_0}}}
+    ++ bulkOfLicenses
+licenseIdList LicenseListVersion_3_2 =
+{{{licenseList_3_2}}}
+    ++ bulkOfLicenses
+
+-- | Create a 'LicenseId' from a 'String'.
+mkLicenseId :: LicenseListVersion -> String -> Maybe LicenseId
+mkLicenseId LicenseListVersion_3_0 s = Map.lookup s stringLookup_3_0
+mkLicenseId LicenseListVersion_3_2 s = Map.lookup s stringLookup_3_2
+
+stringLookup_3_0 :: Map String LicenseId
+stringLookup_3_0 = Map.fromList $ map (\i -> (licenseId i, i)) $
+    licenseIdList LicenseListVersion_3_0
+
+stringLookup_3_2 :: Map String LicenseId
+stringLookup_3_2 = Map.fromList $ map (\i -> (licenseId i, i)) $
+    licenseIdList LicenseListVersion_3_2
+
+--  | Licenses in all SPDX License lists
+bulkOfLicenses :: [LicenseId]
+bulkOfLicenses =
+{{{licenseList_all}}}
diff --git a/cabal/cabal-dev-scripts/cabal-dev-scripts.cabal b/cabal/cabal-dev-scripts/cabal-dev-scripts.cabal
--- a/cabal/cabal-dev-scripts/cabal-dev-scripts.cabal
+++ b/cabal/cabal-dev-scripts/cabal-dev-scripts.cabal
@@ -1,7 +1,7 @@
 name:                cabal-dev-scripts
 version:             0
 synopsis:            Dev scripts for cabal development
-description:         
+description:
   This package provides a tools for Cabal development
 homepage:            http://www.haskell.org/cabal/
 license:             BSD3
@@ -16,8 +16,43 @@
   main-is:             GenExtraSourceFiles.hs
   hs-source-dirs:      src
   build-depends:
-    base                 >=4.10    && <4.11,
-    Cabal                >=2.0     && <2.2,
+    base                 >=4.11    && <4.12,
+    Cabal                >=2.2     && <2.5,
+    bytestring,
     directory,
     filepath,
     process
+
+executable gen-spdx
+  default-language:    Haskell2010
+  main-is:             GenSPDX.hs
+  other-modules:       GenUtils
+  hs-source-dirs:      src
+  ghc-options:         -Wall
+  build-depends:
+    base                 >=4.11    && <4.12,
+    aeson                >=1.4.0.0 && <1.5,
+    bytestring,
+    containers,
+    Diff                 >=0.3.4   && <0.4,
+    lens                 >=4.17    && <4.18,
+    microstache          >=1.0.1.1 && <1.1,
+    optparse-applicative >=0.13    && <0.15,
+    text
+
+executable gen-spdx-exc
+  default-language:    Haskell2010
+  main-is:             GenSPDXExc.hs
+  other-modules:       GenUtils
+  hs-source-dirs:      src
+  ghc-options:         -Wall
+  build-depends:
+    base                 >=4.11    && <4.12,
+    aeson                >=1.4.0.0 && <1.5,
+    bytestring,
+    containers,
+    Diff                 >=0.3.4   && <0.4,
+    lens                 >=4.17    && <4.18,
+    microstache          >=1.0.1.1 && <1.1,
+    optparse-applicative >=0.13    && <0.15,
+    text
diff --git a/cabal/cabal-dev-scripts/src/GenExtraSourceFiles.hs b/cabal/cabal-dev-scripts/src/GenExtraSourceFiles.hs
--- a/cabal/cabal-dev-scripts/src/GenExtraSourceFiles.hs
+++ b/cabal/cabal-dev-scripts/src/GenExtraSourceFiles.hs
@@ -1,31 +1,40 @@
+{-# LANGUAGE OverloadedStrings #-}
+
 import qualified Distribution.ModuleName               as ModuleName
 import           Distribution.PackageDescription
-import           Distribution.PackageDescription.Parse
-                 (ParseResult (..), parseGenericPackageDescription)
+import           Distribution.PackageDescription.Parsec
+                 (parseGenericPackageDescription, runParseResult)
 import           Distribution.Verbosity                (silent)
 
+import Control.Monad      (liftM, filterM)
 import Data.List          (isPrefixOf, isSuffixOf, sort)
-import System.Directory   (canonicalizePath, setCurrentDirectory)
+import System.Directory   (canonicalizePath, doesFileExist, setCurrentDirectory)
 import System.Environment (getArgs, getProgName)
-import System.FilePath    (takeDirectory, takeExtension, takeFileName)
+import System.FilePath    ((</>), takeDirectory, takeExtension, takeFileName)
 import System.Process     (readProcess)
 
-import qualified System.IO as IO
 
-main' :: FilePath -> IO ()
-main' fp' = do
+import qualified Data.ByteString       as BS
+import qualified Data.ByteString.Char8 as BS8
+import qualified System.IO             as IO
+
+main' :: FilePath -> FilePath -> IO ()
+main' templateFp fp' = do
     fp <- canonicalizePath fp'
     setCurrentDirectory (takeDirectory fp)
+    print $ takeDirectory fp
 
     -- Read cabal file, so we can determine test modules
-    contents <- strictReadFile fp
-    cabal <- case parseGenericPackageDescription contents of
-        ParseOk _ x      -> pure x
-        ParseFailed errs -> fail (show errs)
+    contents <- BS.readFile fp
+    cabal <-
+      case snd . runParseResult . parseGenericPackageDescription $ contents of
+        Right x            -> pure x
+        Left (_mver, errs) -> fail (show errs)
 
     -- We skip some files
-    let testModuleFiles = getOtherModulesFiles cabal
+    testModuleFiles    <- getOtherModulesFiles cabal
     let skipPredicates' = skipPredicates ++ map (==) testModuleFiles
+    print testModuleFiles
 
     -- Read all files git knows about under "tests"
     files0 <- lines <$> readProcess "git" ["ls-files", "tests"] ""
@@ -34,47 +43,59 @@
     let files1 = filter (\f -> takeExtension f `elem` whitelistedExtensionss ||
                                takeFileName f `elem` whitelistedFiles)
                         files0
-    let files2 = filter (\f -> not $ any ($ dropTestsDir f) skipPredicates') files1
+    let files2 = filter (\f -> not $ any ($ f) skipPredicates') files1
     let files3 = sort files2
     let files = files3
 
     -- Read current file
-    let inputLines  = lines contents
-        linesBefore = takeWhile (/= topLine) inputLines
-        linesAfter  = dropWhile (/= bottomLine) inputLines
+    templateContents <- BS.readFile templateFp
+    let topLine'    = BS8.pack topLine
+        bottomLine' = BS8.pack bottomLine
+        inputLines  = BS8.lines templateContents
+        linesBefore = takeWhile (/= topLine')    inputLines
+        linesAfter  = dropWhile (/= bottomLine') inputLines
 
     -- Output
-    let outputLines = linesBefore ++ [topLine] ++ map ("  " ++) files ++ linesAfter
-    writeFile fp (unlines outputLines)
+    let outputLines = linesBefore ++ [topLine']
+                      ++ map ((<>) "  " . BS8.pack) files ++ linesAfter
+    BS.writeFile templateFp (BS8.unlines outputLines)
 
 
 topLine, bottomLine :: String
 topLine = "  -- BEGIN gen-extra-source-files"
 bottomLine = "  -- END gen-extra-source-files"
 
-dropTestsDir :: FilePath -> FilePath
-dropTestsDir fp
-    | pfx `isPrefixOf` fp = drop (length pfx) fp
-    | otherwise           = fp
-  where
-    pfx = "tests/"
-
 whitelistedFiles :: [FilePath]
-whitelistedFiles = [ "ghc", "ghc-pkg", "ghc-7.10", "ghc-pkg-7.10", "ghc-pkg-ghc-7.10" ]
+whitelistedFiles = [ "ghc", "ghc-pkg", "ghc-7.10"
+                   , "ghc-pkg-7.10", "ghc-pkg-ghc-7.10" ]
 
 whitelistedExtensionss :: [String]
 whitelistedExtensionss = map ('.' : )
-    [ "hs", "lhs", "c", "h", "sh", "cabal", "hsc", "err", "out", "in", "project" ]
+    [ "hs", "lhs", "c", "h", "sh", "cabal", "hsc"
+    , "err", "out", "in", "project", "format", "errors", "expr"
+    , "check"
+    ]
 
-getOtherModulesFiles :: GenericPackageDescription -> [FilePath]
-getOtherModulesFiles gpd = mainModules ++ map fromModuleName otherModules'
+getOtherModulesFiles :: GenericPackageDescription -> IO [FilePath]
+getOtherModulesFiles gpd = do
+  mainModules   <- liftM concat . mapM findMainModules  $ testSuites
+  otherModules' <- liftM concat . mapM findOtherModules $ testSuites
+
+  return $ mainModules ++ otherModules'
   where
-    testSuites        :: [TestSuite]
-    testSuites        = map (foldMap id . snd) (condTestSuites gpd)
+    testSuites :: [TestSuite]
+    testSuites = map (foldMap id . snd) (condTestSuites gpd)
 
-    mainModules       = concatMap (mainModule   . testInterface) testSuites
-    otherModules'     = concatMap (otherModules . testBuildInfo) testSuites
+    findMainModules, findOtherModules :: TestSuite -> IO [FilePath]
+    findMainModules  ts = findModules (mainModule . testInterface $ ts) ts
+    findOtherModules ts =
+      findModules (map fromModuleName . otherModules . testBuildInfo $ ts) ts
 
+    findModules :: [FilePath] -> TestSuite -> IO [FilePath]
+    findModules filenames ts = filterM doesFileExist
+                               [ d </> f | d <- locations, f <- filenames ]
+      where locations = hsSourceDirs . testBuildInfo $ ts
+
     fromModuleName mn = ModuleName.toFilePath mn ++ ".hs"
 
     mainModule (TestSuiteLibV09 _ mn) = [fromModuleName mn]
@@ -90,18 +111,11 @@
 main = do
     args <- getArgs
     case args of
-        [fp] -> main' fp
-        _    -> do
+        [fp]     -> main' fp fp
+        [fp,fp'] -> main' fp fp'
+        _        -> do
             progName <- getProgName
             putStrLn "Error too few arguments!"
-            putStrLn $ "Usage: " ++ progName ++ " FILE"
-            putStrLn "  where FILE is Cabal.cabal, cabal-testsuite.cabal or cabal-install.cabal"
-
-strictReadFile :: FilePath -> IO String
-strictReadFile fp = do
-    handle <- IO.openFile fp IO.ReadMode
-    contents <- get handle
-    IO.hClose handle
-    return contents
-  where
-    get h = IO.hGetContents h >>= \s -> length s `seq` return s
+            putStrLn $ "Usage: " ++ progName ++ " <FILE | FILE CABAL>"
+            putStrLn $ "  where FILE is Cabal.cabal, cabal-testsuite.cabal, "
+              ++ "or cabal-install.cabal"
diff --git a/cabal/cabal-dev-scripts/src/GenSPDX.hs b/cabal/cabal-dev-scripts/src/GenSPDX.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-dev-scripts/src/GenSPDX.hs
@@ -0,0 +1,124 @@
+{-# LANGUAGE OverloadedStrings   #-}
+module Main (main) where
+
+import Control.Lens   hiding ((.=))
+import Data.Aeson     (FromJSON (..), Value, eitherDecode, object, withObject, (.:), (.=))
+import Data.Foldable  (for_)
+import Data.Semigroup ((<>))
+import Data.Text      (Text)
+
+import qualified Data.ByteString.Lazy as LBS
+import qualified Data.Set             as Set
+import qualified Data.Text            as T
+import qualified Data.Text.Lazy       as TL
+import qualified Data.Text.Lazy.IO    as TL
+import qualified Options.Applicative  as O
+import qualified Text.Microstache     as M
+
+import GenUtils
+
+data Opts = Opts FilePath FilePath FilePath FilePath
+
+main :: IO ()
+main = generate =<< O.execParser opts where
+    opts = O.info (O.helper <*> parser) $ mconcat
+        [ O.fullDesc
+        , O.progDesc "Generate SPDX LicenseId module"
+        ]
+
+    parser :: O.Parser Opts
+    parser = Opts <$> template <*> licenses "3.0" <*> licenses "3.2" <*> output
+
+    template = O.strArgument $ mconcat
+        [ O.metavar "SPDX.LicenseId.template.hs"
+        , O.help    "Module template file"
+        ]
+
+    licenses ver = O.strArgument $ mconcat
+        [ O.metavar $ "licenses-" ++ ver ++ ".json"
+        , O.help    "Licenses JSON. https://github.com/spdx/license-list-data"
+        ]
+
+    output = O.strArgument $ mconcat
+        [ O.metavar "Output.hs"
+        , O.help    "Output file"
+        ]
+
+generate :: Opts -> IO ()
+generate (Opts tmplFile fn3_0 fn3_2 out) = do
+    LicenseList ls3_0 <- either fail pure . eitherDecode =<< LBS.readFile fn3_0
+    LicenseList ls3_2 <- either fail pure . eitherDecode =<< LBS.readFile fn3_2
+    template <- M.compileMustacheFile tmplFile
+    let (ws, rendered) = generate' ls3_0 ls3_2 template
+    for_ ws $ putStrLn . M.displayMustacheWarning
+    TL.writeFile out (header <> "\n" <> rendered)
+    putStrLn $ "Generated file " ++ out
+
+generate'
+    :: [License]  -- SPDX 3.0
+    -> [License]  -- SPDX 3.2
+    -> M.Template
+    -> ([M.MustacheWarning], TL.Text)
+generate' ls_3_0 ls_3_2 template = M.renderMustacheW template $ object
+    [ "licenseIds" .= licenseIds
+    , "licenses"   .= licenseValues
+    , "licenseList_all" .= mkLicenseList (== allVers)
+    , "licenseList_3_0" .= mkLicenseList
+        (\vers -> vers /= allVers && Set.member SPDXLicenseListVersion_3_0 vers)
+    , "licenseList_3_2" .= mkLicenseList
+        (\vers -> vers /= allVers && Set.member SPDXLicenseListVersion_3_2 vers)
+    ]
+  where
+    constructorNames :: [(Text, License, Set.Set SPDXLicenseListVersion)]
+    constructorNames
+        = map (\(l, tags) -> (toConstructorName $ licenseId l, l, tags))
+        $ combine licenseId $ \ver -> case ver of
+            SPDXLicenseListVersion_3_2 -> filterDeprecated ls_3_2
+            SPDXLicenseListVersion_3_0 -> filterDeprecated ls_3_0
+
+    filterDeprecated = filter (not . licenseDeprecated)
+
+    licenseValues :: [Value]
+    licenseValues = flip map constructorNames $ \(c, l, _) -> object
+        [ "licenseCon"      .= c
+        , "licenseId"       .= textShow (licenseId l)
+        , "licenseName"     .= textShow (licenseName l)
+        , "isOsiApproved"   .= licenseOsiApproved l
+        ]
+
+    licenseIds :: Text
+    licenseIds = T.intercalate "\n" $ flip imap constructorNames $ \i (c, l, vers) ->
+        let pfx = if i == 0 then "    = " else "    | "
+            versInfo
+                | vers == allVers = ""
+                | otherwise       = foldMap (\v -> ", " <> prettyVer v) vers
+        in pfx <> c <> " -- ^ @" <> licenseId l <> "@, " <> licenseName l <> versInfo
+
+    mkLicenseList :: (Set.Set SPDXLicenseListVersion -> Bool) -> Text
+    mkLicenseList p = mkList [ n | (n, _, vers) <- constructorNames, p vers ]
+
+-------------------------------------------------------------------------------
+-- Licenses
+-------------------------------------------------------------------------------
+
+data License = License
+    { licenseId          :: !Text
+    , licenseName        :: !Text
+    , licenseOsiApproved :: !Bool
+    , licenseDeprecated  :: !Bool
+    }
+  deriving (Show)
+
+instance FromJSON License where
+    parseJSON = withObject "License" $ \obj -> License
+        <$> obj .: "licenseId"
+        <*> obj .: "name"
+        <*> obj .: "isOsiApproved"
+        <*> obj .: "isDeprecatedLicenseId"
+
+newtype LicenseList = LicenseList [License]
+  deriving (Show)
+
+instance FromJSON LicenseList where
+    parseJSON = withObject "License list" $ \obj -> LicenseList
+        <$> obj .: "licenses"
diff --git a/cabal/cabal-dev-scripts/src/GenSPDXExc.hs b/cabal/cabal-dev-scripts/src/GenSPDXExc.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-dev-scripts/src/GenSPDXExc.hs
@@ -0,0 +1,125 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Main (main) where
+
+import Control.Lens   hiding ((.=))
+import Data.Aeson     (FromJSON (..), Value, eitherDecode, object, withObject, (.:), (.=))
+import Data.Foldable  (for_)
+import Data.Semigroup ((<>))
+import Data.Text      (Text)
+
+import qualified Data.ByteString.Lazy as LBS
+import qualified Data.Text            as T
+import qualified Data.Text.Lazy       as TL
+import qualified Data.Text.Lazy.IO    as TL
+import qualified Data.Set             as Set
+import qualified Options.Applicative  as O
+import qualified Text.Microstache     as M
+
+import GenUtils
+
+data Opts = Opts FilePath FilePath FilePath FilePath
+
+main :: IO ()
+main = generate =<< O.execParser opts where
+    opts = O.info (O.helper <*> parser) $ mconcat
+        [ O.fullDesc
+        , O.progDesc "Generate SPDX LicenseExceptionId module"
+        ]
+
+    parser :: O.Parser Opts
+    parser = Opts <$> template <*> licenses "3.0" <*> licenses "3.2" <*> output
+
+    template = O.strArgument $ mconcat
+        [ O.metavar "SPDX.LicenseExceptionId.template.hs"
+        , O.help    "Module template file"
+        ]
+
+    licenses ver = O.strArgument $ mconcat
+        [ O.metavar $ "exceptions" ++  ver ++ ".json"
+        , O.help    "Exceptions JSON. https://github.com/spdx/license-list-data"
+        ]
+
+    output = O.strArgument $ mconcat
+        [ O.metavar "Output.hs"
+        , O.help    "Output file"
+        ]
+
+generate :: Opts -> IO ()
+generate (Opts tmplFile fn3_0 fn3_2 out) = do
+    LicenseList ls3_0 <- either fail pure . eitherDecode =<< LBS.readFile fn3_0
+    LicenseList ls3_2 <- either fail pure . eitherDecode =<< LBS.readFile fn3_2
+    template <- M.compileMustacheFile tmplFile
+    let (ws, rendered) = generate' ls3_0 ls3_2 template
+    for_ ws $ putStrLn . M.displayMustacheWarning
+    TL.writeFile out (header <> "\n" <> rendered)
+    putStrLn $ "Generated file " ++ out
+
+generate'
+    :: [License]  -- SPDX 3.0
+    -> [License]  -- SPDX 3.2
+    -> M.Template
+    -> ([M.MustacheWarning], TL.Text)
+generate' ls_3_0 ls_3_2 template = M.renderMustacheW template $ object
+    [ "licenseIds" .= licenseIds
+    , "licenses"   .= licenseValues
+    , "licenseList_all" .= mkLicenseList (== allVers)
+    , "licenseList_3_0" .= mkLicenseList
+        (\vers -> vers /= allVers && Set.member SPDXLicenseListVersion_3_0 vers)
+    , "licenseList_3_2" .= mkLicenseList
+        (\vers -> vers /= allVers && Set.member SPDXLicenseListVersion_3_2 vers)
+    ]
+  where
+    constructorNames :: [(Text, License, Set.Set SPDXLicenseListVersion)]
+    constructorNames
+        = map (\(l, tags) -> (toConstructorName $ licenseId l, l, tags))
+        $ combine licenseId $ \ver -> case ver of
+            SPDXLicenseListVersion_3_2 -> filterDeprecated ls_3_2
+            SPDXLicenseListVersion_3_0 -> filterDeprecated ls_3_0
+
+    filterDeprecated = filter (not . licenseDeprecated)
+
+    licenseValues :: [Value]
+    licenseValues = flip map constructorNames $ \(c, l, _) -> object
+        [ "licenseCon"    .= c
+        , "licenseId"     .= textShow (licenseId l)
+        , "licenseName"   .= textShow (licenseName l)
+        ]
+
+    licenseIds :: Text
+    licenseIds = T.intercalate "\n" $ flip imap constructorNames $ \i (c, l, vers) ->
+        let pfx = if i == 0 then "    = " else "    | "
+            versInfo
+                | vers == allVers = ""
+                | otherwise       = foldMap (\v -> ", " <> prettyVer v) vers
+        in pfx <> c <> " -- ^ @" <> licenseId l <> "@, " <> licenseName l <> versInfo
+
+    mkLicenseList :: (Set.Set SPDXLicenseListVersion -> Bool) -> Text
+    mkLicenseList p = mkList [ n | (n, _, vers) <- constructorNames, p vers ]
+
+-------------------------------------------------------------------------------
+-- Licenses
+-------------------------------------------------------------------------------
+
+-- TODO: move to common module, confusing naming. This is LicenseException!
+data License = License
+    { licenseId          :: !Text
+    , licenseName        :: !Text
+    , licenseDeprecated  :: !Bool
+    }
+  deriving (Show)
+
+instance FromJSON License where
+    parseJSON = withObject "License" $ \obj -> License
+        <$> obj .: "licenseExceptionId"
+        <*> fmap (T.map fixSpace) (obj .: "name")
+        <*> obj .: "isDeprecatedLicenseId"
+      where
+        fixSpace '\n' = ' '
+        fixSpace c =   c
+
+newtype LicenseList = LicenseList [License]
+  deriving (Show)
+
+instance FromJSON LicenseList where
+    parseJSON = withObject "Exceptions list" $ \obj -> LicenseList
+        <$> obj .: "exceptions"
diff --git a/cabal/cabal-dev-scripts/src/GenUtils.hs b/cabal/cabal-dev-scripts/src/GenUtils.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-dev-scripts/src/GenUtils.hs
@@ -0,0 +1,104 @@
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module GenUtils where
+
+import Control.Lens
+import Data.Char    (toUpper)
+import Data.Maybe   (fromMaybe)
+import Data.Text    (Text)
+
+import qualified Data.Algorithm.Diff as Diff
+import qualified Data.Map            as Map
+import qualified Data.Set            as Set
+import qualified Data.Text           as T
+import qualified Data.Text.Lazy      as TL
+
+-------------------------------------------------------------------------------
+-- License List version
+-------------------------------------------------------------------------------
+
+-- | SPDX license list version
+data SPDXLicenseListVersion
+    = SPDXLicenseListVersion_3_0
+    | SPDXLicenseListVersion_3_2
+  deriving (Eq, Ord, Show, Enum, Bounded)
+
+allVers :: Set.Set SPDXLicenseListVersion
+allVers =  Set.fromList [minBound .. maxBound]
+
+prettyVer :: SPDXLicenseListVersion -> Text
+prettyVer SPDXLicenseListVersion_3_2 = "SPDX License List 3.2"
+prettyVer SPDXLicenseListVersion_3_0 = "SPDX License List 3.0"
+
+-------------------------------------------------------------------------------
+-- Commmons
+-------------------------------------------------------------------------------
+
+header :: TL.Text
+header = "-- This file is generated. See Makefile's spdx rule"
+
+-------------------------------------------------------------------------------
+-- Tools
+-------------------------------------------------------------------------------
+
+combine
+    :: forall a b tag. (Ord b, Ord tag, Enum tag, Bounded tag)
+    => (a -> b)
+    -> (tag -> [a])
+    -> [(a, Set.Set tag)]
+combine f t
+    = map addTags
+    $ foldr process [] [ minBound .. maxBound ]
+  where
+    unDiff :: Diff.Diff a -> a
+    unDiff (Diff.First a)  = a
+    unDiff (Diff.Second a) = a
+    unDiff (Diff.Both _ a) = a -- important we prefer latter versions!
+
+    addTags :: a -> (a, Set.Set tag)
+    addTags a = (a, fromMaybe Set.empty (Map.lookup (f a) tags))
+
+    process :: tag -> [a] -> [a]
+    process tag as = map unDiff $ Diff.getDiffBy (\x y -> f x == f y) (t tag) as
+
+    tags :: Map.Map b (Set.Set tag)
+    tags = Map.fromListWith Set.union
+        [ (f a, Set.singleton tag)
+        | tag <- [ minBound .. maxBound ]
+        , a <- t tag
+        ]
+
+ordNubOn :: Ord b => (a -> b) -> [a] -> [a]
+ordNubOn f = go Set.empty where
+    go _    [] = []
+    go past (a:as)
+        | b `Set.member` past = go past as
+        | otherwise           = a :  go (Set.insert b past) as
+      where
+        b = f a
+
+textShow :: Text -> Text
+textShow = T.pack . show
+
+toConstructorName :: Text -> Text
+toConstructorName t = t
+    & each %~ f
+    & ix 0 %~ toUpper
+    & special
+  where
+    f '.' = '_'
+    f '-' = '_'
+    f '+' = '\''
+    f c   = c
+
+    special :: Text -> Text
+    special "0BSD"          = "NullBSD"
+    special "389_exception" = "DS389_exception"
+    special u               = u
+
+mkList :: [Text] -> Text
+mkList []     = "    []"
+mkList (x:xs) =
+    "    [ " <> x <> "\n"
+    <> foldMap (\x' -> "    , " <> x' <> "\n") xs
+    <> "    ]"
diff --git a/cabal/cabal-dev-scripts/src/Preprocessor.hs b/cabal/cabal-dev-scripts/src/Preprocessor.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-dev-scripts/src/Preprocessor.hs
@@ -0,0 +1,222 @@
+{-# LANGUAGE DeriveFunctor #-}
+module Main (main) where
+
+import Control.Applicative
+import Control.Monad       (ap, unless)
+import Data.Char           (isSpace)
+import System.Environment  (getArgs)
+import System.IO           (hPutStrLn, stderr)
+
+import qualified Data.Map              as Map
+import qualified System.Console.GetOpt as O
+
+-------------------------------------------------------------------------------
+-- Types
+-------------------------------------------------------------------------------
+
+type Flag = String
+type Var  = String
+
+data Token
+    = Raw String
+    | Var Int Var
+    | If Flag
+    | Else
+    | Endif
+    | Def Var
+    | Enddef
+    | Comment
+    | Error String
+  deriving Show
+
+data Tree
+    = TRaw String
+    | TVar Int Var
+    | TDef Var Forest
+    | TIf Flag Forest Forest
+  deriving Show
+
+type Forest = [Tree]
+
+-------------------------------------------------------------------------------
+-- Lex
+-------------------------------------------------------------------------------
+
+tokens :: String -> [Token]
+tokens = map classify . lines where
+    classify :: String -> Token
+    classify s0 = case s1 of
+        []        -> Raw ""
+        ('#' : _) -> Comment
+        ('$' : s) -> Var (length ws) s
+        ('%' : s)
+            | Just s' <- "if"     `isPrefixOf'` s -> If $ dropWhile isSpace s'
+            | Just _  <- "else"   `isPrefixOf'` s -> Else
+            | Just _  <- "endif"  `isPrefixOf'` s -> Endif
+            | Just s' <- "def"    `isPrefixOf'` s -> Def $ dropWhile isSpace s'
+            | Just _  <- "enddef" `isPrefixOf'` s -> Enddef
+            | otherwise                           -> Error $ "Unknown command: " ++ s
+        _ -> Raw s0
+      where
+        (ws, s1) = span isSpace s0
+
+-- | 'isPrefixOf' returning the rest of the string
+isPrefixOf' :: String -> String -> Maybe String
+isPrefixOf' []     ys                 = Just ys
+isPrefixOf' (_:_)  []                 = Nothing
+isPrefixOf' (x:xs) (y:ys) | x == y    = isPrefixOf' xs ys
+                          | otherwise = Nothing
+
+-------------------------------------------------------------------------------
+-- Parse
+-------------------------------------------------------------------------------
+
+newtype P a = P { unP :: [Token] -> Either String ([Token], a) }
+  deriving Functor
+
+instance Applicative P where
+    pure x = P $ \toks -> Right (toks, x)
+    (<*>)  = ap
+
+instance Alternative P where
+    empty = P $ \_ -> Left "empty"
+    x <|> y = P $ \toks -> case unP x toks of
+        Right res -> Right res
+        Left  _   -> unP y toks
+
+instance Monad P where
+    return = pure
+    m >>= k = P $ \toks0 -> do
+        (toks1, x) <- unP m toks0
+        unP (k x) toks1
+
+runP :: P a -> [Token] -> Either String a
+runP (P p) = fmap snd . p
+
+forest :: [Token] -> Either String Forest
+forest = runP (forestP <* eof) where
+    forestP = many tree
+    tree    = rawP <|> varP <|> ifP <|> defP
+
+    ifP :: P Tree
+    ifP = do
+        f <- if_
+        c <- forestP
+        a <- else_ *> forestP <|> pure []
+        endif_
+        return (TIf f c a)
+
+    defP :: P Tree
+    defP = do
+        v <- def_
+        t <- forestP
+        enddef_
+        return (TDef v t)
+
+    rawP :: P Tree
+    rawP = token "Raw " $ \tok -> case tok of
+        Raw s -> Just (TRaw s)
+        _     -> Nothing
+
+    varP :: P Tree
+    varP = token "Var" $ \toks -> case toks of
+        Var n v -> Just (TVar n v)
+        _       -> Nothing
+
+    if_ :: P Flag
+    if_ = token "If" $ \toks -> case toks of
+        If f -> Just f
+        _    -> Nothing
+
+    def_ :: P Var
+    def_ = token "Def" $ \toks -> case toks of
+        Def v -> Just v
+        _     -> Nothing
+
+    else_ :: P ()
+    else_ = token "Else" $ \toks -> case toks of
+        Else -> Just ()
+        _    -> Nothing
+
+    enddef_ :: P ()
+    enddef_ = token "Enddef" $ \toks -> case toks of
+        Enddef -> Just ()
+        _      -> Nothing
+
+    endif_ :: P ()
+    endif_ = token "Endif" $ \toks -> case toks of
+        Endif -> Just ()
+        _     -> Nothing
+
+    token :: String -> (Token -> Maybe a) -> P a
+    token name f = P $ \toks -> case toks of
+        (tok : toks') | Just x <- f tok -> Right (toks', x)
+        _                               -> Left $ "Expected " ++ name
+
+    eof :: P ()
+    eof = P $ \toks ->
+        if null toks
+        then Right (toks, ())
+        else Left $ "expected end-of-input, got: " ++ show (take 1 toks)
+
+
+-------------------------------------------------------------------------------
+-- Process
+-------------------------------------------------------------------------------
+
+process :: [Flag] -> String -> String
+process flags
+    = either error (unlines . go Map.empty)
+    . forest
+    . filter (not . isComment)
+    . tokens
+  where
+    isComment Comment = True
+    isComment _       = False
+
+    go :: Map.Map Var Forest -> Forest -> [String]
+    go _    []                = []
+    go vars (TRaw s : toks)   = s : go vars toks
+    go vars (TVar _ v : toks) = case Map.lookup v vars of
+        Nothing -> go vars toks
+        Just f  -> go vars (f ++ toks)
+    go vars (TIf f c a : toks)
+        | f `elem` flags      = go vars (c ++ toks)
+        | otherwise           = go vars (a ++ toks)
+    go vars (TDef n f : toks) = go (Map.insert n f vars) toks
+
+-------------------------------------------------------------------------------
+-- Main
+-------------------------------------------------------------------------------
+
+data Opts = Opts
+    { optsFlags  :: [Flag]
+    , optsOutput :: Maybe FilePath
+    }
+
+emptyOpts :: Opts
+emptyOpts = Opts [] Nothing
+
+optDescrs :: [O.OptDescr (Opts -> Opts)]
+optDescrs =
+    [ O.Option "o" []
+        (O.ReqArg (\arg opts -> opts { optsOutput = Just arg }) "OUTPUT")
+        "Output"
+    , O.Option "f" []
+        (O.ReqArg (\arg opts -> opts { optsFlags = arg : optsFlags opts }) "FLAG")
+        "Flag"
+    ]
+
+main :: IO ()
+main = do
+    (optEndos, args, errs) <- O.getOpt O.RequireOrder optDescrs <$> getArgs
+    let opts = foldr ($) emptyOpts optEndos :: Opts
+    unless (null errs) $ do
+        mapM_ (hPutStrLn stderr) errs
+        fail "errors"
+    case args of
+        [fp] -> do
+            contents <- readFile fp
+            let output = process (optsFlags opts) contents
+            maybe putStr writeFile (optsOutput opts) output
+        _ -> fail "Expecting exactly one argument"
diff --git a/cabal/cabal-install/Distribution/Client/Check.hs b/cabal/cabal-install/Distribution/Client/Check.hs
--- a/cabal/cabal-install/Distribution/Client/Check.hs
+++ b/cabal/cabal-install/Distribution/Client/Check.hs
@@ -16,21 +16,44 @@
     check
   ) where
 
-import Control.Monad ( when, unless )
+import Distribution.Client.Compat.Prelude
+import Prelude ()
 
-import Distribution.PackageDescription.Parsec ( readGenericPackageDescription )
+import Distribution.PackageDescription               (GenericPackageDescription)
 import Distribution.PackageDescription.Check
-import Distribution.PackageDescription.Configuration
-         ( flattenPackageDescription )
-import Distribution.Verbosity
-         ( Verbosity )
-import Distribution.Simple.Utils
-         ( defaultPackageDesc, wrapText )
+import Distribution.PackageDescription.Configuration (flattenPackageDescription)
+import Distribution.PackageDescription.Parsec
+       (parseGenericPackageDescription, runParseResult)
+import Distribution.Parsec.Common                    (PWarning (..), showPError, showPWarning)
+import Distribution.Simple.Utils                     (defaultPackageDesc, die', notice, warn)
+import Distribution.Verbosity                        (Verbosity)
 
+import qualified Data.ByteString  as BS
+import qualified System.Directory as Dir
+
+readGenericPackageDescriptionCheck :: Verbosity -> FilePath -> IO ([PWarning], GenericPackageDescription)
+readGenericPackageDescriptionCheck verbosity fpath = do
+    exists <- Dir.doesFileExist fpath
+    unless exists $
+      die' verbosity $
+        "Error Parsing: file \"" ++ fpath ++ "\" doesn't exist. Cannot continue."
+    bs <- BS.readFile fpath
+    let (warnings, result) = runParseResult (parseGenericPackageDescription bs)
+    case result of
+        Left (_, errors) -> do
+            traverse_ (warn verbosity . showPError fpath) errors
+            die' verbosity $ "Failed parsing \"" ++ fpath ++ "\"."
+        Right x  -> return (warnings, x)
+
+-- | Note: must be called with the CWD set to the directory containing
+-- the '.cabal' file.
 check :: Verbosity -> IO Bool
 check verbosity = do
     pdfile <- defaultPackageDesc verbosity
-    ppd <- readGenericPackageDescription verbosity pdfile
+    (ws, ppd) <- readGenericPackageDescriptionCheck verbosity pdfile
+    -- convert parse warnings into PackageChecks
+    -- Note: we /could/ pick different levels, based on warning type.
+    let ws' = [ PackageDistSuspicious (showPWarning pdfile w) | w <- ws ]
     -- flatten the generic package description into a regular package
     -- description
     -- TODO: this may give more warnings than it should give;
@@ -45,8 +68,8 @@
     --      Hovever, this is the same way hackage does it, so we will yield
     --      the exact same errors as it will.
     let pkg_desc = flattenPackageDescription ppd
-    ioChecks <- checkPackageFiles pkg_desc "."
-    let packageChecks = ioChecks ++ checkPackage ppd (Just pkg_desc)
+    ioChecks <- checkPackageFiles verbosity pkg_desc "."
+    let packageChecks = ioChecks ++ checkPackage ppd (Just pkg_desc) ++ ws'
         buildImpossible = [ x | x@PackageBuildImpossible {} <- packageChecks ]
         buildWarning    = [ x | x@PackageBuildWarning {}    <- packageChecks ]
         distSuspicious  = [ x | x@PackageDistSuspicious {}  <- packageChecks ]
@@ -54,19 +77,19 @@
         distInexusable  = [ x | x@PackageDistInexcusable {} <- packageChecks ]
 
     unless (null buildImpossible) $ do
-        putStrLn "The package will not build sanely due to these errors:"
+        warn verbosity "The package will not build sanely due to these errors:"
         printCheckMessages buildImpossible
 
     unless (null buildWarning) $ do
-        putStrLn "The following warnings are likely to affect your build negatively:"
+        warn verbosity "The following warnings are likely to affect your build negatively:"
         printCheckMessages buildWarning
 
     unless (null distSuspicious) $ do
-        putStrLn "These warnings may cause trouble when distributing the package:"
+        warn verbosity "These warnings may cause trouble when distributing the package:"
         printCheckMessages distSuspicious
 
     unless (null distInexusable) $ do
-        putStrLn "The following errors will cause portability problems on other environments:"
+        warn verbosity "The following errors will cause portability problems on other environments:"
         printCheckMessages distInexusable
 
     let isDistError (PackageDistSuspicious     {}) = False
@@ -77,13 +100,12 @@
         errors = filter isDistError packageChecks
 
     unless (null errors) $
-        putStrLn "Hackage would reject this package."
+        warn verbosity "Hackage would reject this package."
 
     when (null packageChecks) $
-        putStrLn "No errors or warnings could be found in the package."
+        notice verbosity "No errors or warnings could be found in the package."
 
     return (not . any isCheckError $ packageChecks)
 
   where
-    printCheckMessages = mapM_ (putStrLn . format . explanation)
-    format = wrapText . ("* "++)
+    printCheckMessages = traverse_ (warn verbosity . explanation)
diff --git a/cabal/cabal-install/Distribution/Client/CmdBench.hs b/cabal/cabal-install/Distribution/Client/CmdBench.hs
--- a/cabal/cabal-install/Distribution/Client/CmdBench.hs
+++ b/cabal/cabal-install/Distribution/Client/CmdBench.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE ViewPatterns   #-}
 
 -- | cabal-install CLI command: bench
 --
@@ -18,8 +17,7 @@
 import Distribution.Client.CmdErrorMessages
 
 import Distribution.Client.Setup
-         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags
-         , applyFlagDefaults )
+         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags )
 import qualified Distribution.Client.Setup as Client
 import Distribution.Simple.Setup
          ( HaddockFlags, fromFlagOrDefault )
@@ -77,13 +75,13 @@
 --
 benchAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
             -> [String] -> GlobalFlags -> IO ()
-benchAction (applyFlagDefaults -> (configFlags, configExFlags, installFlags, haddockFlags))
+benchAction (configFlags, configExFlags, installFlags, haddockFlags)
             targetStrings globalFlags = do
 
     baseCtx <- establishProjectBaseContext verbosity cliConfig
 
     targetSelectors <- either (reportTargetSelectorProblems verbosity) return
-                   =<< readTargetSelectors (localPackages baseCtx) targetStrings
+                   =<< readTargetSelectors (localPackages baseCtx) (Just BenchKind) targetStrings
 
     buildCtx <-
       runProjectPreBuildPhase verbosity baseCtx $ \elaboratedPlan -> do
@@ -102,6 +100,7 @@
                          selectComponentTarget
                          TargetProblemCommon
                          elaboratedPlan
+                         Nothing
                          targetSelectors
 
             let elaboratedPlan' = pruneInstallPlanToTargets
@@ -127,7 +126,7 @@
 -- For the @bench@ command we select all buildable benchmarks,
 -- or fail if there are no benchmarks or no buildable benchmarks.
 --
-selectPackageTargets :: TargetSelector PackageId
+selectPackageTargets :: TargetSelector
                      -> [AvailableTarget k] -> Either TargetProblem [k]
 selectPackageTargets targetSelector targets
 
@@ -162,17 +161,20 @@
 -- For the @bench@ command we just need to check it is a benchmark, in addition
 -- to the basic checks on being buildable etc.
 --
-selectComponentTarget :: PackageId -> ComponentName -> SubComponentTarget
+selectComponentTarget :: SubComponentTarget
                       -> AvailableTarget k -> Either TargetProblem k
-selectComponentTarget pkgid cname subtarget@WholeComponent t
+selectComponentTarget subtarget@WholeComponent t
   | CBenchName _ <- availableTargetComponentName t
   = either (Left . TargetProblemCommon) return $
-           selectComponentTargetBasic pkgid cname subtarget t
+           selectComponentTargetBasic subtarget t
   | otherwise
-  = Left (TargetProblemComponentNotBenchmark pkgid cname)
+  = Left (TargetProblemComponentNotBenchmark (availableTargetPackageId t)
+                                             (availableTargetComponentName t))
 
-selectComponentTarget pkgid cname subtarget _
-  = Left (TargetProblemIsSubComponent pkgid cname subtarget)
+selectComponentTarget subtarget t
+  = Left (TargetProblemIsSubComponent (availableTargetPackageId t)
+                                      (availableTargetComponentName t)
+                                       subtarget)
 
 -- | The various error conditions that can occur when matching a
 -- 'TargetSelector' against 'AvailableTarget's for the @bench@ command.
@@ -181,13 +183,13 @@
      TargetProblemCommon        TargetProblemCommon
 
      -- | The 'TargetSelector' matches benchmarks but none are buildable
-   | TargetProblemNoneEnabled  (TargetSelector PackageId) [AvailableTarget ()]
+   | TargetProblemNoneEnabled  TargetSelector [AvailableTarget ()]
 
      -- | There are no targets at all
-   | TargetProblemNoTargets    (TargetSelector PackageId)
+   | TargetProblemNoTargets    TargetSelector
 
      -- | The 'TargetSelector' matches targets but no benchmarks
-   | TargetProblemNoBenchmarks (TargetSelector PackageId)
+   | TargetProblemNoBenchmarks TargetSelector
 
      -- | The 'TargetSelector' refers to a component that is not a benchmark
    | TargetProblemComponentNotBenchmark PackageId ComponentName
diff --git a/cabal/cabal-install/Distribution/Client/CmdBuild.hs b/cabal/cabal-install/Distribution/Client/CmdBuild.hs
--- a/cabal/cabal-install/Distribution/Client/CmdBuild.hs
+++ b/cabal/cabal-install/Distribution/Client/CmdBuild.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE ViewPatterns #-}
-
 -- | cabal-install CLI command: build
 --
 module Distribution.Client.CmdBuild (
@@ -16,14 +14,15 @@
 import Distribution.Client.ProjectOrchestration
 import Distribution.Client.CmdErrorMessages
 
+import Distribution.Compat.Semigroup ((<>))
 import Distribution.Client.Setup
          ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags
-         , applyFlagDefaults )
+         , liftOptions, yesNoOpt )
 import qualified Distribution.Client.Setup as Client
 import Distribution.Simple.Setup
-         ( HaddockFlags, fromFlagOrDefault )
+         ( HaddockFlags, Flag(..), toFlag, fromFlag, fromFlagOrDefault )
 import Distribution.Simple.Command
-         ( CommandUI(..), usageAlternatives )
+         ( CommandUI(..), usageAlternatives, option )
 import Distribution.Verbosity
          ( Verbosity, normal )
 import Distribution.Simple.Utils
@@ -32,8 +31,8 @@
 import qualified Data.Map as Map
 
 
-buildCommand :: CommandUI (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
-buildCommand = Client.installCommand {
+buildCommand :: CommandUI (BuildFlags, (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags))
+buildCommand = CommandUI {
   commandName         = "new-build",
   commandSynopsis     = "Compile targets within the project.",
   commandUsage        = usageAlternatives "new-build" [ "[TARGETS] [FLAGS]" ],
@@ -62,10 +61,33 @@
      ++ "  " ++ pname ++ " new-build cname --enable-profiling\n"
      ++ "    Build the component in profiling mode (including dependencies as needed)\n\n"
 
-     ++ cmdCommonHelpTextNewBuildBeta
-   }
+     ++ cmdCommonHelpTextNewBuildBeta,
+  commandDefaultFlags =
+      (defaultBuildFlags, commandDefaultFlags Client.installCommand),
+  commandOptions = \ showOrParseArgs ->
+      liftOptions snd setSnd
+          (commandOptions Client.installCommand showOrParseArgs) ++
+      liftOptions fst setFst
+          [ option [] ["only-configure"]
+              "Instead of performing a full build just run the configure step"
+              buildOnlyConfigure (\v flags -> flags { buildOnlyConfigure = v })
+              (yesNoOpt showOrParseArgs)
+          ]
+  }
 
+  where
+    setFst a (_,b) = (a,b)
+    setSnd b (a,_) = (a,b)
 
+data BuildFlags = BuildFlags
+    { buildOnlyConfigure  :: Flag Bool
+    }
+
+defaultBuildFlags :: BuildFlags
+defaultBuildFlags = BuildFlags
+    { buildOnlyConfigure = toFlag False
+    }
+
 -- | The @build@ command does a lot. It brings the install plan up to date,
 -- selects that part of the plan needed by the given or implicit targets and
 -- then executes the plan.
@@ -73,15 +95,22 @@
 -- For more details on how this works, see the module
 -- "Distribution.Client.ProjectOrchestration"
 --
-buildAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
+buildAction :: (BuildFlags, (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags))
             -> [String] -> GlobalFlags -> IO ()
-buildAction (applyFlagDefaults -> (configFlags, configExFlags, installFlags, haddockFlags))
+buildAction (buildFlags,
+             (configFlags, configExFlags, installFlags, haddockFlags))
             targetStrings globalFlags = do
+    -- TODO: This flags defaults business is ugly
+    let onlyConfigure = fromFlag (buildOnlyConfigure defaultBuildFlags
+                                 <> buildOnlyConfigure buildFlags)
+        targetAction
+            | onlyConfigure = TargetActionConfigure
+            | otherwise = TargetActionBuild
 
     baseCtx <- establishProjectBaseContext verbosity cliConfig
 
     targetSelectors <- either (reportTargetSelectorProblems verbosity) return
-                   =<< readTargetSelectors (localPackages baseCtx) targetStrings
+                   =<< readTargetSelectors (localPackages baseCtx) Nothing targetStrings
 
     buildCtx <-
       runProjectPreBuildPhase verbosity baseCtx $ \elaboratedPlan -> do
@@ -94,10 +123,11 @@
                          selectComponentTarget
                          TargetProblemCommon
                          elaboratedPlan
+                         Nothing
                          targetSelectors
 
             let elaboratedPlan' = pruneInstallPlanToTargets
-                                    TargetActionBuild
+                                    targetAction
                                     targets
                                     elaboratedPlan
             elaboratedPlan'' <-
@@ -126,7 +156,7 @@
 -- For the @build@ command select all components except non-buildable and disabled
 -- tests\/benchmarks, fail if there are no such components
 --
-selectPackageTargets :: TargetSelector PackageId
+selectPackageTargets :: TargetSelector
                      -> [AvailableTarget k] -> Either TargetProblem [k]
 selectPackageTargets targetSelector targets
 
@@ -159,11 +189,11 @@
 --
 -- For the @build@ command we just need the basic checks on being buildable etc.
 --
-selectComponentTarget :: PackageId -> ComponentName -> SubComponentTarget
+selectComponentTarget :: SubComponentTarget
                       -> AvailableTarget k -> Either TargetProblem k
-selectComponentTarget pkgid cname subtarget =
+selectComponentTarget subtarget =
     either (Left . TargetProblemCommon) Right
-  . selectComponentTargetBasic pkgid cname subtarget
+  . selectComponentTargetBasic subtarget
 
 
 -- | The various error conditions that can occur when matching a
@@ -173,10 +203,10 @@
      TargetProblemCommon       TargetProblemCommon
 
      -- | The 'TargetSelector' matches targets but none are buildable
-   | TargetProblemNoneEnabled (TargetSelector PackageId) [AvailableTarget ()]
+   | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]
 
      -- | There are no targets at all
-   | TargetProblemNoTargets   (TargetSelector PackageId)
+   | TargetProblemNoTargets   TargetSelector
   deriving (Eq, Show)
 
 reportTargetProblems :: Verbosity -> [TargetProblem] -> IO a
@@ -194,4 +224,3 @@
 reportCannotPruneDependencies :: Verbosity -> CannotPruneDependencies -> IO a
 reportCannotPruneDependencies verbosity =
     die' verbosity . renderCannotPruneDependencies
-
diff --git a/cabal/cabal-install/Distribution/Client/CmdClean.hs b/cabal/cabal-install/Distribution/Client/CmdClean.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/Distribution/Client/CmdClean.hs
@@ -0,0 +1,115 @@
+{-# LANGUAGE RecordWildCards #-}
+module Distribution.Client.CmdClean (cleanCommand, cleanAction) where
+
+import Prelude ()
+import Distribution.Client.Compat.Prelude
+
+import Distribution.Client.DistDirLayout
+    ( DistDirLayout(..), defaultDistDirLayout )
+import Distribution.Client.ProjectConfig
+    ( findProjectRoot )
+import Distribution.Client.Setup
+    ( GlobalFlags )
+import Distribution.ReadE ( succeedReadE )
+import Distribution.Simple.Setup
+    ( Flag(..), toFlag, fromFlagOrDefault, flagToList, flagToMaybe
+    , optionDistPref, optionVerbosity, falseArg
+    )
+import Distribution.Simple.Command
+    ( CommandUI(..), option, reqArg )
+import Distribution.Simple.Utils
+    ( info, die', wrapText, handleDoesNotExist )
+import Distribution.Verbosity
+    ( Verbosity, normal )
+
+import Control.Monad
+    ( mapM_ )
+import Control.Exception
+    ( throwIO )
+import System.Directory
+    ( removeDirectoryRecursive, removeFile
+    , doesDirectoryExist, getDirectoryContents )
+import System.FilePath
+    ( (</>) )
+
+data CleanFlags = CleanFlags
+    { cleanSaveConfig  :: Flag Bool
+    , cleanVerbosity   :: Flag Verbosity
+    , cleanDistDir     :: Flag FilePath
+    , cleanProjectFile :: Flag FilePath
+    } deriving (Eq)
+
+defaultCleanFlags :: CleanFlags
+defaultCleanFlags = CleanFlags
+    { cleanSaveConfig  = toFlag False
+    , cleanVerbosity   = toFlag normal
+    , cleanDistDir     = NoFlag
+    , cleanProjectFile = mempty
+    }
+
+cleanCommand :: CommandUI CleanFlags
+cleanCommand = CommandUI
+    { commandName         = "new-clean"
+    , commandSynopsis     = "Clean the package store and remove temporary files."
+    , commandUsage        = \pname ->
+        "Usage: " ++ pname ++ " new-clean [FLAGS]\n"
+    , commandDescription  = Just $ \_ -> wrapText $
+        "Removes all temporary files created during the building process "
+     ++ "(.hi, .o, preprocessed sources, etc.) and also empties out the "
+     ++ "local caches (by default).\n\n"
+    , commandNotes        = Nothing
+    , commandDefaultFlags = defaultCleanFlags
+    , commandOptions      = \showOrParseArgs ->
+        [ optionVerbosity
+            cleanVerbosity (\v flags -> flags { cleanVerbosity = v })
+        , optionDistPref
+            cleanDistDir (\dd flags -> flags { cleanDistDir = dd })
+            showOrParseArgs
+        , option [] ["project-file"]
+            ("Set the name of the cabal.project file"
+             ++ " to search for in parent directories")
+            cleanProjectFile (\pf flags -> flags {cleanProjectFile = pf})
+            (reqArg "FILE" (succeedReadE Flag) flagToList)
+        , option ['s'] ["save-config"]
+            "Save configuration, only remove build artifacts"
+            cleanSaveConfig (\sc flags -> flags { cleanSaveConfig = sc })
+            falseArg
+        ]
+  }
+
+cleanAction :: CleanFlags -> [String] -> GlobalFlags -> IO ()
+cleanAction CleanFlags{..} extraArgs _ = do
+    let verbosity      = fromFlagOrDefault normal cleanVerbosity
+        saveConfig     = fromFlagOrDefault False  cleanSaveConfig
+        mdistDirectory = flagToMaybe cleanDistDir
+        mprojectFile   = flagToMaybe cleanProjectFile
+
+    unless (null extraArgs) $
+        die' verbosity $ "'clean' doesn't take any extra arguments: "
+                         ++ unwords extraArgs
+
+    projectRoot <- either throwIO return =<< findProjectRoot Nothing mprojectFile
+
+    let distLayout = defaultDistDirLayout projectRoot mdistDirectory
+
+    if saveConfig
+        then do
+            let buildRoot = distBuildRootDirectory distLayout
+
+            buildRootExists <- doesDirectoryExist buildRoot
+
+            when buildRootExists $ do
+                info verbosity ("Deleting build root (" ++ buildRoot ++ ")")
+                handleDoesNotExist () $ removeDirectoryRecursive buildRoot
+        else do
+            let distRoot = distDirectory distLayout
+
+            info verbosity ("Deleting dist-newstyle (" ++ distRoot ++ ")")
+            handleDoesNotExist () $ removeDirectoryRecursive distRoot
+
+    removeEnvFiles (distProjectRootDirectory distLayout)
+
+removeEnvFiles :: FilePath -> IO ()
+removeEnvFiles dir =
+  (mapM_ (removeFile . (dir </>)) . filter ((".ghc.environment" ==) . take 16))
+  =<< getDirectoryContents dir
diff --git a/cabal/cabal-install/Distribution/Client/CmdConfigure.hs b/cabal/cabal-install/Distribution/Client/CmdConfigure.hs
--- a/cabal/cabal-install/Distribution/Client/CmdConfigure.hs
+++ b/cabal/cabal-install/Distribution/Client/CmdConfigure.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE ViewPatterns #-}
 -- | cabal-install CLI command: configure
 --
 module Distribution.Client.CmdConfigure (
@@ -15,8 +14,7 @@
          ( writeProjectLocalExtraConfig )
 
 import Distribution.Client.Setup
-         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags
-         , applyFlagDefaults )
+         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags )
 import Distribution.Simple.Setup
          ( HaddockFlags, fromFlagOrDefault )
 import Distribution.Verbosity
@@ -82,7 +80,7 @@
 --
 configureAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
                 -> [String] -> GlobalFlags -> IO ()
-configureAction (applyFlagDefaults -> (configFlags, configExFlags, installFlags, haddockFlags))
+configureAction (configFlags, configExFlags, installFlags, haddockFlags)
                 _extraArgs globalFlags = do
     --TODO: deal with _extraArgs, since flags with wrong syntax end up there
 
diff --git a/cabal/cabal-install/Distribution/Client/CmdErrorMessages.hs b/cabal/cabal-install/Distribution/Client/CmdErrorMessages.hs
--- a/cabal/cabal-install/Distribution/Client/CmdErrorMessages.hs
+++ b/cabal/cabal-install/Distribution/Client/CmdErrorMessages.hs
@@ -12,7 +12,7 @@
          ( ComponentKindFilter, componentKind, showTargetSelector )
 
 import Distribution.Package
-         ( packageId, packageName )
+         ( packageId, PackageName, packageName )
 import Distribution.Types.ComponentName
          ( showComponentName )
 import Distribution.Solver.Types.OptionalStanza
@@ -84,14 +84,23 @@
 -- Renderering for a few project and package types
 --
 
-renderTargetSelector :: TargetSelector PackageId -> String
-renderTargetSelector (TargetPackage _ pkgid Nothing) =
-    "the package " ++ display pkgid
+renderTargetSelector :: TargetSelector -> String
+renderTargetSelector (TargetPackage _ pkgids Nothing) =
+    "the " ++ plural (listPlural pkgids) "package" "packages" ++ " "
+ ++ renderListCommaAnd (map display pkgids)
 
-renderTargetSelector (TargetPackage _ pkgid (Just kfilter)) =
+renderTargetSelector (TargetPackage _ pkgids (Just kfilter)) =
     "the " ++ renderComponentKind Plural kfilter
- ++ " in the package " ++ display pkgid
+ ++ " in the " ++ plural (listPlural pkgids) "package" "packages" ++ " "
+ ++ renderListCommaAnd (map display pkgids)
 
+renderTargetSelector (TargetPackageNamed pkgname Nothing) =
+    "the package " ++ display pkgname
+
+renderTargetSelector (TargetPackageNamed pkgname (Just kfilter)) =
+    "the " ++ renderComponentKind Plural kfilter
+ ++ " in the package " ++ display pkgname
+
 renderTargetSelector (TargetAllPackages Nothing) =
     "all the packages in the project"
 
@@ -99,20 +108,24 @@
     "all the " ++ renderComponentKind Plural kfilter
  ++ " in the project"
 
-renderTargetSelector (TargetComponent pkgid CLibName WholeComponent) =
-    "the library in the package " ++ display pkgid
-
-renderTargetSelector (TargetComponent _pkgid cname WholeComponent) =
-    "the " ++ showComponentName cname
+renderTargetSelector (TargetComponent pkgid cname subtarget) =
+    renderSubComponentTarget subtarget ++ "the "
+ ++ renderComponentName (packageName pkgid) cname
 
-renderTargetSelector (TargetComponent _pkgid cname (FileTarget filename)) =
-    "the file " ++ filename ++ " in the " ++ showComponentName cname
+renderTargetSelector (TargetComponentUnknown pkgname (Left ucname) subtarget) =
+    renderSubComponentTarget subtarget ++ "the component " ++ display ucname
+ ++ " in the package " ++ display pkgname
 
-renderTargetSelector (TargetComponent _pkgid cname (ModuleTarget modname)) =
-    "the module " ++ display modname ++ " in the " ++ showComponentName cname
+renderTargetSelector (TargetComponentUnknown pkgname (Right cname) subtarget) =
+    renderSubComponentTarget subtarget ++ "the "
+ ++ renderComponentName pkgname cname
 
-renderTargetSelector (TargetPackageName pkgname) =
-    "the package " ++ display pkgname
+renderSubComponentTarget :: SubComponentTarget -> String
+renderSubComponentTarget WholeComponent         = ""
+renderSubComponentTarget (FileTarget filename)  =
+  "the file " ++ filename ++ "in "
+renderSubComponentTarget (ModuleTarget modname) =
+  "the module" ++ display modname ++ "in "
 
 
 renderOptionalStanza :: Plural -> OptionalStanza -> String
@@ -129,25 +142,36 @@
 
 -- | Does the 'TargetSelector' potentially refer to one package or many?
 --
-targetSelectorPluralPkgs :: TargetSelector a -> Plural
+targetSelectorPluralPkgs :: TargetSelector -> Plural
 targetSelectorPluralPkgs (TargetAllPackages _)     = Plural
-targetSelectorPluralPkgs (TargetPackage _ _ _)     = Singular
-targetSelectorPluralPkgs (TargetComponent _ _ _)   = Singular
-targetSelectorPluralPkgs (TargetPackageName _)     = Singular
+targetSelectorPluralPkgs (TargetPackage _ pids _)  = listPlural pids
+targetSelectorPluralPkgs (TargetPackageNamed _ _)  = Singular
+targetSelectorPluralPkgs  TargetComponent{}        = Singular
+targetSelectorPluralPkgs  TargetComponentUnknown{} = Singular
 
--- | Does the 'TargetSelector' refer to 
-targetSelectorRefersToPkgs :: TargetSelector a -> Bool
-targetSelectorRefersToPkgs (TargetAllPackages  mkfilter) = isNothing mkfilter
-targetSelectorRefersToPkgs (TargetPackage  _ _ mkfilter) = isNothing mkfilter
-targetSelectorRefersToPkgs (TargetComponent _ _ _)       = False
-targetSelectorRefersToPkgs (TargetPackageName _)         = True
+-- | Does the 'TargetSelector' refer to packages or to components?
+targetSelectorRefersToPkgs :: TargetSelector -> Bool
+targetSelectorRefersToPkgs (TargetAllPackages    mkfilter) = isNothing mkfilter
+targetSelectorRefersToPkgs (TargetPackage    _ _ mkfilter) = isNothing mkfilter
+targetSelectorRefersToPkgs (TargetPackageNamed _ mkfilter) = isNothing mkfilter
+targetSelectorRefersToPkgs  TargetComponent{}              = False
+targetSelectorRefersToPkgs  TargetComponentUnknown{}       = False
 
-targetSelectorFilter :: TargetSelector a -> Maybe ComponentKindFilter
-targetSelectorFilter (TargetPackage  _ _ mkfilter) = mkfilter
-targetSelectorFilter (TargetAllPackages  mkfilter) = mkfilter
-targetSelectorFilter (TargetComponent _ _ _)       = Nothing
-targetSelectorFilter (TargetPackageName _)         = Nothing
+targetSelectorFilter :: TargetSelector -> Maybe ComponentKindFilter
+targetSelectorFilter (TargetPackage    _ _ mkfilter) = mkfilter
+targetSelectorFilter (TargetPackageNamed _ mkfilter) = mkfilter
+targetSelectorFilter (TargetAllPackages    mkfilter) = mkfilter
+targetSelectorFilter  TargetComponent{}              = Nothing
+targetSelectorFilter  TargetComponentUnknown{}       = Nothing
 
+renderComponentName :: PackageName -> ComponentName -> String
+renderComponentName pkgname CLibName     = "library " ++ display pkgname
+renderComponentName _ (CSubLibName name) = "library " ++ display name
+renderComponentName _ (CFLibName   name) = "foreign library " ++ display name
+renderComponentName _ (CExeName    name) = "executable " ++ display name
+renderComponentName _ (CTestName   name) = "test suite " ++ display name
+renderComponentName _ (CBenchName  name) = "benchmark " ++ display name
+
 renderComponentKind :: Plural -> ComponentKind -> String
 renderComponentKind Singular ckind = case ckind of
   LibKind   -> "library"  -- internal/sub libs?
@@ -173,6 +197,12 @@
  ++ "in this project (either directly or indirectly). If you want to add it "
  ++ "to the project then edit the cabal.project file."
 
+renderTargetProblemCommon verb (TargetAvailableInIndex pkgname) =
+    "Cannot " ++ verb ++ " the package " ++ display pkgname ++ ", it is not "
+ ++ "in this project (either directly or indirectly), but it is in the current "
+ ++ "package index. If you want to add it to the project then edit the "
+ ++ "cabal.project file."
+
 renderTargetProblemCommon verb (TargetComponentNotProjectLocal pkgid cname _) =
     "Cannot " ++ verb ++ " the " ++ showComponentName cname ++ " because the "
  ++ "package " ++ display pkgid ++ " is not local to the project, and cabal "
@@ -207,7 +237,7 @@
     "Cannot " ++ verb ++ " the " ++ showComponentName cname ++ " because the "
  ++ "solver did not find a plan that included the " ++ compkinds
  ++ " for " ++ display pkgid ++ ". It is probably worth trying again with "
- ++ compkinds ++ "explicitly enabled in the configuration in the "
+ ++ compkinds ++ " explicitly enabled in the configuration in the "
  ++ "cabal.project{.local} file. This will ask the solver to find a plan with "
  ++ "the " ++ compkinds ++ " available. It will either fail with an "
  ++ "explanation or find a different plan that uses different versions of some "
@@ -216,6 +246,18 @@
    where
      compkinds = renderComponentKind Plural (componentKind cname)
 
+renderTargetProblemCommon verb (TargetProblemUnknownComponent pkgname ecname) =
+    "Cannot " ++ verb ++ " the "
+ ++ (case ecname of
+      Left ucname -> "component " ++ display ucname
+      Right cname -> renderComponentName pkgname cname)
+ ++ " from the package " ++ display pkgname
+ ++ ", because the package does not contain a "
+ ++ (case ecname of
+      Left  _     -> "component"
+      Right cname -> renderComponentKind Singular (componentKind cname))
+ ++ " with that name."
+
 renderTargetProblemCommon verb (TargetProblemNoSuchPackage pkgid) =
     "Internal error when trying to " ++ verb ++ " the package "
   ++ display pkgid ++ ". The package is not in the set of available targets "
@@ -238,7 +280,7 @@
 -- This renders an error message for those cases.
 --
 renderTargetProblemNoneEnabled :: String
-                               -> TargetSelector PackageId
+                               -> TargetSelector
                                -> [AvailableTarget ()]
                                -> String
 renderTargetProblemNoneEnabled verb targetSelector targets =
@@ -300,7 +342,7 @@
 -- | Several commands have a @TargetProblemNoTargets@ problem constructor.
 -- This renders an error message for those cases.
 --
-renderTargetProblemNoTargets :: String -> TargetSelector PackageId -> String
+renderTargetProblemNoTargets :: String -> TargetSelector -> String
 renderTargetProblemNoTargets verb targetSelector =
     "Cannot " ++ verb ++ " " ++ renderTargetSelector targetSelector
  ++ " because " ++ reason targetSelector ++ ". "
@@ -314,6 +356,10 @@
         "it does not contain any components at all"
     reason (TargetPackage _ _ (Just kfilter)) =
         "it does not contain any " ++ renderComponentKind Plural kfilter
+    reason (TargetPackageNamed _ Nothing) =
+        "it does not contain any components at all"
+    reason (TargetPackageNamed _ (Just kfilter)) =
+        "it does not contain any " ++ renderComponentKind Plural kfilter
     reason (TargetAllPackages Nothing) =
         "none of them contain any components at all"
     reason (TargetAllPackages (Just kfilter)) =
@@ -321,8 +367,8 @@
      ++ renderComponentKind Plural kfilter
     reason ts@TargetComponent{} =
         error $ "renderTargetProblemNoTargets: " ++ show ts
-    reason (TargetPackageName _) =
-        "it does not contain any components at all"
+    reason ts@TargetComponentUnknown{} =
+        error $ "renderTargetProblemNoTargets: " ++ show ts
 
 -----------------------------------------------------------
 -- Renderering error messages for CannotPruneDependencies
diff --git a/cabal/cabal-install/Distribution/Client/CmdExec.hs b/cabal/cabal-install/Distribution/Client/CmdExec.hs
--- a/cabal/cabal-install/Distribution/Client/CmdExec.hs
+++ b/cabal/cabal-install/Distribution/Client/CmdExec.hs
@@ -27,6 +27,7 @@
   , GlobalFlags
   , InstallFlags
   )
+import qualified Distribution.Client.Setup as Client
 import Distribution.Client.ProjectOrchestration
   ( ProjectBuildContext(..)
   , runProjectPreBuildPhase
@@ -86,8 +87,6 @@
   , normal
   )
 
-import qualified Distribution.Client.CmdBuild as CmdBuild
-
 import Prelude ()
 import Distribution.Client.Compat.Prelude
 
@@ -116,8 +115,8 @@
     ++ " to choose an appropriate version of ghc and to include any"
     ++ " ghc-specific flags requested."
   , commandNotes = Nothing
-  , commandOptions = commandOptions CmdBuild.buildCommand
-  , commandDefaultFlags = commandDefaultFlags CmdBuild.buildCommand
+  , commandOptions = commandOptions Client.installCommand
+  , commandDefaultFlags = commandDefaultFlags Client.installCommand
   }
 
 execAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
diff --git a/cabal/cabal-install/Distribution/Client/CmdFreeze.hs b/cabal/cabal-install/Distribution/Client/CmdFreeze.hs
--- a/cabal/cabal-install/Distribution/Client/CmdFreeze.hs
+++ b/cabal/cabal-install/Distribution/Client/CmdFreeze.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE CPP, NamedFieldPuns, RecordWildCards, ViewPatterns #-}
+{-# LANGUAGE NamedFieldPuns, RecordWildCards #-}
 
 -- | cabal-install CLI command: freeze
 --
@@ -31,8 +31,7 @@
 import Distribution.PackageDescription
          ( FlagAssignment, nullFlagAssignment )
 import Distribution.Client.Setup
-         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags
-         , applyFlagDefaults )
+         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags )
 import Distribution.Simple.Setup
          ( HaddockFlags, fromFlagOrDefault )
 import Distribution.Simple.Utils
@@ -102,7 +101,7 @@
 --
 freezeAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
              -> [String] -> GlobalFlags -> IO ()
-freezeAction (applyFlagDefaults -> (configFlags, configExFlags, installFlags, haddockFlags))
+freezeAction (configFlags, configExFlags, installFlags, haddockFlags)
              extraArgs globalFlags = do
 
     unless (null extraArgs) $
@@ -210,7 +209,6 @@
       :: Map PackageName [(UserConstraint, ConstraintSource)]
       -> Map PackageName [(UserConstraint, ConstraintSource)]
     deleteLocalPackagesVersionConstraints =
-#if MIN_VERSION_containers(0,5,0)
       Map.mergeWithKey
         (\_pkgname () constraints ->
             case filter (not . isVersionConstraint . fst) constraints of
@@ -218,15 +216,6 @@
               constraints' -> Just constraints')
         (const Map.empty) id
         localPackages
-#else
-      Map.mapMaybeWithKey
-        (\pkgname constraints ->
-            if pkgname `Map.member` localPackages
-              then case filter (not . isVersionConstraint . fst) constraints of
-                     []           -> Nothing
-                     constraints' -> Just constraints'
-              else Just constraints)
-#endif
 
     isVersionConstraint (UserConstraint _ (PackagePropertyVersion _)) = True
     isVersionConstraint _                                             = False
diff --git a/cabal/cabal-install/Distribution/Client/CmdHaddock.hs b/cabal/cabal-install/Distribution/Client/CmdHaddock.hs
--- a/cabal/cabal-install/Distribution/Client/CmdHaddock.hs
+++ b/cabal/cabal-install/Distribution/Client/CmdHaddock.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE ViewPatterns   #-}
 
 -- | cabal-install CLI command: haddock
 --
@@ -18,11 +17,10 @@
 import Distribution.Client.CmdErrorMessages
 
 import Distribution.Client.Setup
-         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags
-         , applyFlagDefaults )
+         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags )
 import qualified Distribution.Client.Setup as Client
 import Distribution.Simple.Setup
-         ( HaddockFlags(..), fromFlagOrDefault, fromFlag )
+         ( HaddockFlags(..), fromFlagOrDefault )
 import Distribution.Simple.Command
          ( CommandUI(..), usageAlternatives )
 import Distribution.Verbosity
@@ -73,13 +71,13 @@
 --
 haddockAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
                  -> [String] -> GlobalFlags -> IO ()
-haddockAction (applyFlagDefaults -> (configFlags, configExFlags, installFlags, haddockFlags))
+haddockAction (configFlags, configExFlags, installFlags, haddockFlags)
                 targetStrings globalFlags = do
 
     baseCtx <- establishProjectBaseContext verbosity cliConfig
 
     targetSelectors <- either (reportTargetSelectorProblems verbosity) return
-                   =<< readTargetSelectors (localPackages baseCtx) targetStrings
+                   =<< readTargetSelectors (localPackages baseCtx) Nothing targetStrings
 
     buildCtx <-
       runProjectPreBuildPhase verbosity baseCtx $ \elaboratedPlan -> do
@@ -96,6 +94,7 @@
                          selectComponentTarget
                          TargetProblemCommon
                          elaboratedPlan
+                         Nothing
                          targetSelectors
 
             let elaboratedPlan' = pruneInstallPlanToTargets
@@ -122,7 +121,7 @@
 -- depending on the @--executables@ flag we also select all the buildable exes.
 -- We do similarly for test-suites, benchmarks and foreign libs.
 --
-selectPackageTargets  :: HaddockFlags -> TargetSelector PackageId
+selectPackageTargets  :: HaddockFlags -> TargetSelector
                       -> [AvailableTarget k] -> Either TargetProblem [k]
 selectPackageTargets haddockFlags targetSelector targets
 
@@ -153,23 +152,30 @@
     isRequested (TargetAllPackages (Just _)) _ = True
     isRequested _ LibKind    = True
 --  isRequested _ SubLibKind = True --TODO: what about sublibs?
-    isRequested _ FLibKind   = fromFlag (haddockForeignLibs haddockFlags)
-    isRequested _ ExeKind    = fromFlag (haddockExecutables haddockFlags)
-    isRequested _ TestKind   = fromFlag (haddockTestSuites  haddockFlags)
-    isRequested _ BenchKind  = fromFlag (haddockBenchmarks  haddockFlags)
 
+    -- TODO/HACK, we encode some defaults here as new-haddock's logic;
+    -- make sure this matches the defaults applied in
+    -- "Distribution.Client.ProjectPlanning"; this may need more work
+    -- to be done properly
+    --
+    -- See also https://github.com/haskell/cabal/pull/4886
+    isRequested _ FLibKind   = fromFlagOrDefault False (haddockForeignLibs haddockFlags)
+    isRequested _ ExeKind    = fromFlagOrDefault False (haddockExecutables haddockFlags)
+    isRequested _ TestKind   = fromFlagOrDefault False (haddockTestSuites  haddockFlags)
+    isRequested _ BenchKind  = fromFlagOrDefault False (haddockBenchmarks  haddockFlags)
 
+
 -- | For a 'TargetComponent' 'TargetSelector', check if the component can be
 -- selected.
 --
 -- For the @haddock@ command we just need the basic checks on being buildable
 -- etc.
 --
-selectComponentTarget :: PackageId -> ComponentName -> SubComponentTarget
+selectComponentTarget :: SubComponentTarget
                       -> AvailableTarget k -> Either TargetProblem k
-selectComponentTarget pkgid cname subtarget =
+selectComponentTarget subtarget =
     either (Left . TargetProblemCommon) Right
-  . selectComponentTargetBasic pkgid cname subtarget
+  . selectComponentTargetBasic subtarget
 
 
 -- | The various error conditions that can occur when matching a
@@ -179,10 +185,10 @@
      TargetProblemCommon       TargetProblemCommon
 
      -- | The 'TargetSelector' matches targets but none are buildable
-   | TargetProblemNoneEnabled (TargetSelector PackageId) [AvailableTarget ()]
+   | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]
 
      -- | There are no targets at all
-   | TargetProblemNoTargets   (TargetSelector PackageId)
+   | TargetProblemNoTargets   TargetSelector
   deriving (Eq, Show)
 
 reportTargetProblems :: Verbosity -> [TargetProblem] -> IO a
diff --git a/cabal/cabal-install/Distribution/Client/CmdInstall.hs b/cabal/cabal-install/Distribution/Client/CmdInstall.hs
--- a/cabal/cabal-install/Distribution/Client/CmdInstall.hs
+++ b/cabal/cabal-install/Distribution/Client/CmdInstall.hs
@@ -1,4 +1,7 @@
+{-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE ViewPatterns #-}
 
 -- | cabal-install CLI command: build
@@ -11,7 +14,8 @@
     -- * Internals exposed for testing
     TargetProblem(..),
     selectPackageTargets,
-    selectComponentTarget
+    selectComponentTarget,
+    establishDummyProjectBaseContext
   ) where
 
 import Prelude ()
@@ -19,87 +23,216 @@
 
 import Distribution.Client.ProjectOrchestration
 import Distribution.Client.CmdErrorMessages
+import Distribution.Client.CmdSdist
 
 import Distribution.Client.Setup
-         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags
-         , applyFlagDefaults )
-import qualified Distribution.Client.Setup as Client
+         ( GlobalFlags(..), ConfigFlags(..), ConfigExFlags, InstallFlags(..)
+         , configureExOptions, installOptions, liftOptions )
+import Distribution.Solver.Types.ConstraintSource
+         ( ConstraintSource(..) )
 import Distribution.Client.Types
-         ( PackageSpecifier(NamedPackage), UnresolvedSourcePackage )
-import Distribution.Client.ProjectPlanning.Types
-         ( pkgConfigCompiler )
+         ( PackageSpecifier(..), PackageLocation(..), UnresolvedSourcePackage
+         , SourcePackageDb(..) )
+import qualified Distribution.Client.InstallPlan as InstallPlan
+import Distribution.Package
+         ( Package(..), PackageName, mkPackageName, unPackageName )
+import Distribution.Types.PackageId
+         ( PackageIdentifier(..) )
 import Distribution.Client.ProjectConfig.Types
-         ( ProjectConfig, ProjectConfigBuildOnly(..)
-         , projectConfigLogsDir, projectConfigStoreDir, projectConfigShared
-         , projectConfigBuildOnly, projectConfigDistDir
-         , projectConfigConfigFile )
+         ( ProjectConfig(..), ProjectConfigShared(..)
+         , ProjectConfigBuildOnly(..), PackageConfig(..)
+         , getMapLast, getMapMappend, projectConfigLogsDir
+         , projectConfigStoreDir, projectConfigBuildOnly
+         , projectConfigDistDir, projectConfigConfigFile )
+import Distribution.Simple.Program.Db
+         ( userSpecifyPaths, userSpecifyArgss, defaultProgramDb
+         , modifyProgramSearchPath )
+import Distribution.Simple.Program.Find
+         ( ProgramSearchPathEntry(..) )
 import Distribution.Client.Config
-         ( defaultCabalDir )
+         ( getCabalDir )
+import qualified Distribution.Simple.PackageIndex as PI
+import Distribution.Solver.Types.PackageIndex
+         ( lookupPackageName, searchByName )
+import Distribution.Types.InstalledPackageInfo
+         ( InstalledPackageInfo(..) )
+import Distribution.Types.Version
+         ( nullVersion )
+import Distribution.Types.VersionRange
+         ( thisVersion )
+import Distribution.Solver.Types.PackageConstraint
+         ( PackageProperty(..) )
+import Distribution.Client.IndexUtils
+         ( getSourcePackages, getInstalledPackages )
 import Distribution.Client.ProjectConfig
-         ( readGlobalConfig, resolveBuildTimeSettings )
+         ( readGlobalConfig, projectConfigWithBuilderRepoContext
+         , resolveBuildTimeSettings, withProjectOrGlobalConfig )
 import Distribution.Client.DistDirLayout
-         ( defaultDistDirLayout, distDirectory, mkCabalDirLayout
-         , ProjectRoot(ProjectRootImplicit), distProjectCacheDirectory
-         , storePackageDirectory, cabalStoreDirLayout )
+         ( defaultDistDirLayout, DistDirLayout(..), mkCabalDirLayout
+         , ProjectRoot(ProjectRootImplicit)
+         , storePackageDirectory, cabalStoreDirLayout
+         , CabalDirLayout(..), StoreDirLayout(..) )
 import Distribution.Client.RebuildMonad
          ( runRebuild )
 import Distribution.Client.InstallSymlink
-         ( symlinkBinary )
+         ( OverwritePolicy(..), symlinkBinary )
 import Distribution.Simple.Setup
-         ( Flag(Flag), HaddockFlags, fromFlagOrDefault, flagToMaybe )
+         ( Flag(..), HaddockFlags, fromFlagOrDefault, flagToMaybe, toFlag
+         , trueArg, configureOptions, haddockOptions, flagToList )
+import Distribution.Solver.Types.SourcePackage
+         ( SourcePackage(..) )
+import Distribution.ReadE
+         ( ReadE(..), succeedReadE )
 import Distribution.Simple.Command
-         ( CommandUI(..), usageAlternatives )
+         ( CommandUI(..), ShowOrParseArgs(..), OptionField(..)
+         , option, usageAlternatives, reqArg )
+import Distribution.Simple.Configure
+         ( configCompilerEx )
 import Distribution.Simple.Compiler
-         ( compilerId )
-import Distribution.Types.PackageName
-         ( mkPackageName )
+         ( Compiler(..), CompilerId(..), CompilerFlavor(..) )
+import Distribution.Simple.GHC
+         ( ghcPlatformAndVersionString
+         , GhcImplInfo(..), getImplInfo
+         , GhcEnvironmentFileEntry(..)
+         , renderGhcEnvironmentFile, readGhcEnvironmentFile, ParseErrorExc )
 import Distribution.Types.UnitId
          ( UnitId )
 import Distribution.Types.UnqualComponentName
          ( UnqualComponentName, unUnqualComponentName )
 import Distribution.Verbosity
-         ( Verbosity, normal )
+         ( Verbosity, normal, lessVerbose )
 import Distribution.Simple.Utils
-         ( wrapText, die', withTempDirectory, createDirectoryIfMissingVerbose )
+         ( wrapText, die', notice, warn
+         , withTempDirectory, createDirectoryIfMissingVerbose
+         , ordNub )
+import Distribution.Utils.Generic
+         ( writeFileAtomic )
+import Distribution.Text
+         ( simpleParse )
+import Distribution.Pretty
+         ( prettyShow )
 
+import Control.Exception
+         ( catch )
+import Control.Monad
+         ( mapM, mapM_ )
+import qualified Data.ByteString.Lazy.Char8 as BS
+import Data.Either
+         ( partitionEithers, isLeft )
+import Data.Ord
+         ( comparing, Down(..) )
 import qualified Data.Map as Map
-import System.Directory ( getTemporaryDirectory, makeAbsolute )
-import System.FilePath ( (</>) )
+import Distribution.Utils.NubList
+         ( fromNubList )
+import System.Directory
+         ( getHomeDirectory, doesFileExist, createDirectoryIfMissing
+         , getTemporaryDirectory, makeAbsolute, doesDirectoryExist )
+import System.FilePath
+         ( (</>), takeDirectory, takeBaseName )
 
-import qualified Distribution.Client.CmdBuild as CmdBuild
+data NewInstallFlags = NewInstallFlags
+  { ninstInstallLibs :: Flag Bool
+  , ninstEnvironmentPath :: Flag FilePath
+  , ninstOverwritePolicy :: Flag OverwritePolicy
+  }
 
-installCommand :: CommandUI (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
+defaultNewInstallFlags :: NewInstallFlags
+defaultNewInstallFlags = NewInstallFlags
+  { ninstInstallLibs = toFlag False
+  , ninstEnvironmentPath = mempty
+  , ninstOverwritePolicy = toFlag NeverOverwrite
+  }
+
+newInstallOptions :: ShowOrParseArgs -> [OptionField NewInstallFlags]
+newInstallOptions _ =
+  [ option [] ["lib"]
+    "Install libraries rather than executables from the target package."
+    ninstInstallLibs (\v flags -> flags { ninstInstallLibs = v })
+    trueArg
+  , option [] ["package-env", "env"]
+    "Set the environment file that may be modified."
+    ninstEnvironmentPath (\pf flags -> flags { ninstEnvironmentPath = pf })
+    (reqArg "ENV" (succeedReadE Flag) flagToList)
+  , option [] ["overwrite-policy"]
+    "How to handle already existing symlinks."
+    ninstOverwritePolicy (\v flags -> flags { ninstOverwritePolicy = v })
+    $ reqArg
+        "always|never"
+        readOverwritePolicyFlag
+        showOverwritePolicyFlag
+  ]
+  where
+    readOverwritePolicyFlag = ReadE $ \case
+      "always" -> Right $ Flag AlwaysOverwrite
+      "never"  -> Right $ Flag NeverOverwrite
+      policy   -> Left  $ "'" <> policy <> "' isn't a valid overwrite policy"
+    showOverwritePolicyFlag (Flag AlwaysOverwrite) = ["always"]
+    showOverwritePolicyFlag (Flag NeverOverwrite)  = ["never"]
+    showOverwritePolicyFlag NoFlag                 = []
+
+installCommand :: CommandUI ( ConfigFlags, ConfigExFlags, InstallFlags
+                            , HaddockFlags, NewInstallFlags
+                            )
 installCommand = CommandUI
   { commandName         = "new-install"
   , commandSynopsis     = "Install packages."
-  , commandUsage        = usageAlternatives "new-install" [ "[TARGETS] [FLAGS]" ]
+  , commandUsage        = usageAlternatives
+                          "new-install" [ "[TARGETS] [FLAGS]" ]
   , commandDescription  = Just $ \_ -> wrapText $
-         "Installs one or more packages. This is done by installing them "
-      ++ "in the store and symlinking the executables in the directory "
-      ++ "specified by the --symlink-bindir flag (`~/.cabal/bin/` by default). "
-      ++ "If you want the installed executables to be available globally, "
-      ++ "make sure that the PATH environment variable contains that directory. "
-      ++ "\n\n"
-      ++ "If TARGET is a library, it will be added to the global environment. "
-      ++ "When doing this, cabal will try to build a plan that includes all "
-      ++ "the previously installed libraries. This is currently not implemented."
+    "Installs one or more packages. This is done by installing them "
+    ++ "in the store and symlinking the executables in the directory "
+    ++ "specified by the --symlink-bindir flag (`~/.cabal/bin/` by default). "
+    ++ "If you want the installed executables to be available globally, "
+    ++ "make sure that the PATH environment variable contains that directory. "
+    ++ "\n\n"
+    ++ "If TARGET is a library, it will be added to the global environment. "
+    ++ "When doing this, cabal will try to build a plan that includes all "
+    ++ "the previously installed libraries. This is currently not implemented."
   , commandNotes        = Just $ \pname ->
-         "Examples:\n"
+      "Examples:\n"
       ++ "  " ++ pname ++ " new-install\n"
       ++ "    Install the package in the current directory\n"
       ++ "  " ++ pname ++ " new-install pkgname\n"
-      ++ "    Install the package named pkgname (fetching it from hackage if necessary)\n"
+      ++ "    Install the package named pkgname"
+      ++ " (fetching it from hackage if necessary)\n"
       ++ "  " ++ pname ++ " new-install ./pkgfoo\n"
       ++ "    Install the package in the ./pkgfoo directory\n"
 
       ++ cmdCommonHelpTextNewBuildBeta
-  , commandOptions = commandOptions CmdBuild.buildCommand
-  , commandDefaultFlags = commandDefaultFlags CmdBuild.buildCommand
+  , commandOptions      = \showOrParseArgs ->
+        liftOptions get1 set1
+        -- Note: [Hidden Flags]
+        -- hide "constraint", "dependency", and
+        -- "exact-configuration" from the configure options.
+        (filter ((`notElem` ["constraint", "dependency"
+                            , "exact-configuration"])
+                 . optionName) $ configureOptions showOrParseArgs)
+     ++ liftOptions get2 set2 (configureExOptions showOrParseArgs ConstraintSourceCommandlineFlag)
+     ++ liftOptions get3 set3
+        -- hide "target-package-db" flag from the
+        -- install options.
+        (filter ((`notElem` ["target-package-db"])
+                 . optionName) $
+                               installOptions showOrParseArgs)
+       ++ liftOptions get4 set4
+          -- hide "verbose" and "builddir" flags from the
+          -- haddock options.
+          (filter ((`notElem` ["v", "verbose", "builddir"])
+                  . optionName) $
+                                haddockOptions showOrParseArgs)
+     ++ liftOptions get5 set5 (newInstallOptions showOrParseArgs)
+  , commandDefaultFlags = (mempty, mempty, mempty, mempty, defaultNewInstallFlags)
   }
+  where
+    get1 (a,_,_,_,_) = a; set1 a (_,b,c,d,e) = (a,b,c,d,e)
+    get2 (_,b,_,_,_) = b; set2 b (a,_,c,d,e) = (a,b,c,d,e)
+    get3 (_,_,c,_,_) = c; set3 c (a,b,_,d,e) = (a,b,c,d,e)
+    get4 (_,_,_,d,_) = d; set4 d (a,b,c,_,e) = (a,b,c,d,e)
+    get5 (_,_,_,_,e) = e; set5 e (a,b,c,d,_) = (a,b,c,d,e)
 
 
 -- | The @install@ command actually serves four different needs. It installs:
--- * Nonlocal exes:
+-- * exes:
 --   For example a program from hackage. The behavior is similar to the old
 --   install command, except that now conflicts between separate runs of the
 --   command are impossible thanks to the store.
@@ -107,16 +240,17 @@
 --   symlinked uin the directory specified by --symlink-bindir.
 --   To do this we need a dummy projectBaseContext containing the targets as
 --   estra packages and using a temporary dist directory.
--- * Nonlocal libraries (TODO see #4558)
--- * Local exes         (TODO see #4558)
--- * Local libraries    (TODO see #4558)
+-- * libraries
+--   Libraries install through a similar process, but using GHC environment
+--   files instead of symlinks. This means that 'new-install'ing libraries
+--   only works on GHC >= 8.0.
 --
 -- For more details on how this works, see the module
 -- "Distribution.Client.ProjectOrchestration"
 --
-installAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
+installAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags, NewInstallFlags)
             -> [String] -> GlobalFlags -> IO ()
-installAction (applyFlagDefaults -> (configFlags, configExFlags, installFlags, haddockFlags))
+installAction (configFlags, configExFlags, installFlags, haddockFlags, newInstallFlags)
             targetStrings globalFlags = do
   -- We never try to build tests/benchmarks for remote packages.
   -- So we set them as disabled by default and error if they are explicitly
@@ -128,25 +262,275 @@
     die' verbosity $ "--enable-benchmarks was specified, but benchmarks can't "
                   ++ "be enabled in a remote package"
 
-  -- We need a place to put a temporary dist directory
+  let
+    withProject = do
+      let verbosity' = lessVerbose verbosity
+
+      -- First, we need to learn about what's available to be installed.
+      localBaseCtx <- establishProjectBaseContext verbosity' cliConfig
+      let localDistDirLayout = distDirLayout localBaseCtx
+      pkgDb <- projectConfigWithBuilderRepoContext verbosity' (buildSettings localBaseCtx) (getSourcePackages verbosity)
+
+      let
+        (targetStrings', packageIds) = partitionEithers . flip fmap targetStrings $
+          \str -> case simpleParse str of
+            Just (pkgId :: PackageId)
+              | pkgVersion pkgId /= nullVersion -> Right pkgId
+            _ -> Left str
+        packageSpecifiers = flip fmap packageIds $ \case
+          PackageIdentifier{..}
+            | pkgVersion == nullVersion -> NamedPackage pkgName []
+            | otherwise ->
+              NamedPackage pkgName [PackagePropertyVersion (thisVersion pkgVersion)]
+        packageTargets = flip TargetPackageNamed Nothing . pkgName <$> packageIds
+
+      if null targetStrings'
+        then return (packageSpecifiers, packageTargets, projectConfig localBaseCtx)
+        else do
+          targetSelectors <- either (reportTargetSelectorProblems verbosity) return
+                        =<< readTargetSelectors (localPackages localBaseCtx) Nothing targetStrings'
+
+          (specs, selectors) <- withInstallPlan verbosity' localBaseCtx $ \elaboratedPlan _ -> do
+            -- Split into known targets and hackage packages.
+            (targets, hackageNames) <- case
+              resolveTargets
+                selectPackageTargets
+                selectComponentTarget
+                TargetProblemCommon
+                elaboratedPlan
+                (Just pkgDb)
+                targetSelectors of
+              Right targets -> do
+                -- Everything is a local dependency.
+                return (targets, [])
+              Left errs -> do
+                -- Not everything is local.
+                let
+                  (errs', hackageNames) = partitionEithers . flip fmap errs $ \case
+                    TargetProblemCommon (TargetAvailableInIndex name) -> Right name
+                    err -> Left err
+
+                -- report incorrect case for known package.
+                for_ errs' $ \case
+                  TargetProblemCommon (TargetNotInProject hn) ->
+                    case searchByName (packageIndex pkgDb) (unPackageName hn) of
+                      [] -> return ()
+                      xs -> die' verbosity . concat $
+                        [ "Unknown package \"", unPackageName hn, "\". "
+                        , "Did you mean any of the following?\n"
+                        , unlines (("- " ++) . unPackageName . fst <$> xs)
+                        ]
+                  _ -> return ()
+    
+                when (not . null $ errs') $ reportTargetProblems verbosity errs'
+
+                let
+                  targetSelectors' = flip filter targetSelectors $ \case
+                    TargetComponentUnknown name _ _
+                      | name `elem` hackageNames -> False
+                    TargetPackageNamed name _
+                      | name `elem` hackageNames -> False
+                    _ -> True
+
+                -- This can't fail, because all of the errors are removed (or we've given up).
+                targets <- either (reportTargetProblems verbosity) return $ resolveTargets
+                    selectPackageTargets
+                    selectComponentTarget
+                    TargetProblemCommon
+                    elaboratedPlan
+                    Nothing
+                    targetSelectors'
+
+                return (targets, hackageNames)
+
+            let
+              planMap = InstallPlan.toMap elaboratedPlan
+              targetIds = Map.keys targets
+
+              sdistize (SpecificSourcePackage spkg@SourcePackage{..}) = SpecificSourcePackage spkg'
+                where
+                  sdistPath = distSdistFile localDistDirLayout packageInfoId TargzFormat
+                  spkg' = spkg { packageSource = LocalTarballPackage sdistPath }
+              sdistize named = named
+
+              local = sdistize <$> localPackages localBaseCtx
+
+              gatherTargets :: UnitId -> TargetSelector
+              gatherTargets targetId = TargetPackageNamed pkgName Nothing
+                where
+                  Just targetUnit = Map.lookup targetId planMap
+                  PackageIdentifier{..} = packageId targetUnit
+
+              targets' = fmap gatherTargets targetIds
+
+              hackagePkgs :: [PackageSpecifier UnresolvedSourcePackage]
+              hackagePkgs = flip NamedPackage [] <$> hackageNames
+              hackageTargets :: [TargetSelector]
+              hackageTargets = flip TargetPackageNamed Nothing <$> hackageNames
+
+            createDirectoryIfMissing True (distSdistDirectory localDistDirLayout)
+
+            unless (Map.null targets) $
+              mapM_
+                (\(SpecificSourcePackage pkg) -> packageToSdist verbosity
+                  (distProjectRootDirectory localDistDirLayout) (Archive TargzFormat)
+                  (distSdistFile localDistDirLayout (packageId pkg) TargzFormat) pkg
+                ) (localPackages localBaseCtx)
+
+            if null targets
+              then return (hackagePkgs, hackageTargets)
+              else return (local ++ hackagePkgs, targets' ++ hackageTargets)
+
+          return (specs ++ packageSpecifiers, selectors ++ packageTargets, projectConfig localBaseCtx)
+
+    withoutProject globalConfig = do
+      let
+        parsePkg pkgName
+          | Just (pkg :: PackageId) <- simpleParse pkgName = return pkg
+          | otherwise = die' verbosity ("Invalid package ID: " ++ pkgName)
+      packageIds <- mapM parsePkg targetStrings
+      
+      cabalDir <- getCabalDir
+      let 
+        projectConfig = globalConfig <> cliConfig
+
+        ProjectConfigBuildOnly {
+          projectConfigLogsDir
+        } = projectConfigBuildOnly projectConfig
+
+        ProjectConfigShared {
+          projectConfigStoreDir
+        } = projectConfigShared projectConfig
+
+        mlogsDir = flagToMaybe projectConfigLogsDir
+        mstoreDir = flagToMaybe projectConfigStoreDir
+        cabalDirLayout = mkCabalDirLayout cabalDir mstoreDir mlogsDir
+
+        buildSettings = resolveBuildTimeSettings
+                          verbosity cabalDirLayout
+                          projectConfig
+
+      SourcePackageDb { packageIndex } <- projectConfigWithBuilderRepoContext
+                                            verbosity buildSettings 
+                                            (getSourcePackages verbosity)
+
+      for_ targetStrings $ \case
+            name
+              | null (lookupPackageName packageIndex (mkPackageName name))
+              , xs@(_:_) <- searchByName packageIndex name ->
+                die' verbosity . concat $
+                            [ "Unknown package \"", name, "\". "
+                            , "Did you mean any of the following?\n"
+                            , unlines (("- " ++) . unPackageName . fst <$> xs)
+                            ]
+            _ -> return ()
+
+      let
+        packageSpecifiers = flip fmap packageIds $ \case
+          PackageIdentifier{..}
+            | pkgVersion == nullVersion -> NamedPackage pkgName []
+            | otherwise ->
+              NamedPackage pkgName [PackagePropertyVersion (thisVersion pkgVersion)]
+        packageTargets = flip TargetPackageNamed Nothing . pkgName <$> packageIds
+      return (packageSpecifiers, packageTargets, projectConfig)
+
+  (specs, selectors, config) <- withProjectOrGlobalConfig verbosity globalConfigFlag
+                                  withProject withoutProject
+
+  home <- getHomeDirectory
+  let
+    ProjectConfig {
+      projectConfigShared = ProjectConfigShared {
+        projectConfigHcFlavor,
+        projectConfigHcPath,
+        projectConfigHcPkg
+      },
+      projectConfigLocalPackages = PackageConfig {
+        packageConfigProgramPaths,
+        packageConfigProgramArgs,
+        packageConfigProgramPathExtra
+      }
+    } = config
+
+    hcFlavor = flagToMaybe projectConfigHcFlavor
+    hcPath   = flagToMaybe projectConfigHcPath
+    hcPkg    = flagToMaybe projectConfigHcPkg
+
+    progDb =
+        userSpecifyPaths (Map.toList (getMapLast packageConfigProgramPaths))
+      . userSpecifyArgss (Map.toList (getMapMappend packageConfigProgramArgs))
+      . modifyProgramSearchPath
+          (++ [ ProgramSearchPathDir dir
+              | dir <- fromNubList packageConfigProgramPathExtra ])
+      $ defaultProgramDb
+
+  (compiler@Compiler { compilerId =
+    compilerId@(CompilerId compilerFlavor compilerVersion) }, platform, progDb') <-
+      configCompilerEx hcFlavor hcPath hcPkg progDb verbosity
+
+  let
+    globalEnv name =
+      home </> ".ghc" </> ghcPlatformAndVersionString platform compilerVersion
+           </> "environments" </> name
+    localEnv dir =
+      dir </> ".ghc.environment." ++ ghcPlatformAndVersionString platform compilerVersion
+
+    GhcImplInfo{ supportsPkgEnvFiles } = getImplInfo compiler
+    -- Why? We know what the first part will be, we only care about the packages.
+    filterEnvEntries = filter $ \case
+      GhcEnvFilePackageId _ -> True
+      _ -> False
+
+  envFile <- case flagToMaybe (ninstEnvironmentPath newInstallFlags) of
+    Just spec
+      -- Is spec a bare word without any "pathy" content, then it refers to
+      -- a named global environment.
+      | takeBaseName spec == spec -> return (globalEnv spec)
+      | otherwise -> do
+        spec' <- makeAbsolute spec
+        isDir <- doesDirectoryExist spec'
+        if isDir
+          -- If spec is a directory, then make an ambient environment inside
+          -- that directory.
+          then return (localEnv spec')
+          -- Otherwise, treat it like a literal file path.
+          else return spec'
+    Nothing -> return (globalEnv "default")
+
+  envFileExists <- doesFileExist envFile
+  envEntries <- filterEnvEntries <$> if
+    (compilerFlavor == GHC || compilerFlavor == GHCJS)
+      && supportsPkgEnvFiles && envFileExists
+    then catch (readGhcEnvironmentFile envFile) $ \(_ :: ParseErrorExc) ->
+      warn verbosity ("The environment file " ++ envFile ++
+        " is unparsable. Libraries cannot be installed.") >> return []
+    else return []
+
+  cabalDir  <- getCabalDir
+  mstoreDir <- sequenceA $ makeAbsolute <$> flagToMaybe (globalStoreDir globalFlags)
+  let
+    mlogsDir    = flagToMaybe (globalLogsDir globalFlags)
+    cabalLayout = mkCabalDirLayout cabalDir mstoreDir mlogsDir
+    packageDbs  = storePackageDBStack (cabalStoreDirLayout cabalLayout) compilerId
+
+  installedIndex <- getInstalledPackages verbosity compiler packageDbs progDb'
+
+  let (envSpecs, envEntries') = environmentFileToSpecifiers installedIndex envEntries
+
+  -- Second, we need to use a fake project to let Cabal build the
+  -- installables correctly. For that, we need a place to put a
+  -- temporary dist directory.
   globalTmp <- getTemporaryDirectory
   withTempDirectory
     verbosity
     globalTmp
     "cabal-install."
     $ \tmpDir -> do
-
-    let packageNames = mkPackageName <$> targetStrings
-        packageSpecifiers =
-          (\pname -> NamedPackage pname []) <$> packageNames
-
     baseCtx <- establishDummyProjectBaseContext
                  verbosity
-                 cliConfig
+                 config
                  tmpDir
-                 packageSpecifiers
-
-    let targetSelectors = TargetPackageName <$> packageNames
+                 (envSpecs ++ specs)
 
     buildCtx <-
       runProjectPreBuildPhase verbosity baseCtx $ \elaboratedPlan -> do
@@ -158,7 +542,8 @@
                          selectComponentTarget
                          TargetProblemCommon
                          elaboratedPlan
-                         targetSelectors
+                         Nothing
+                         selectors
 
             let elaboratedPlan' = pruneInstallPlanToTargets
                                     TargetActionBuild
@@ -176,27 +561,114 @@
     printPlan verbosity baseCtx buildCtx
 
     buildOutcomes <- runProjectBuildPhase verbosity baseCtx buildCtx
+    -- Temporary fix for #5641
+    when (any isLeft buildOutcomes) $
+      warn verbosity $ "Some package(s) failed to build. "
+                    <> "Try rerunning with -j1 if you can't see the error."
+    runProjectPostBuildPhase verbosity baseCtx buildCtx buildOutcomes
 
-    let compiler = pkgConfigCompiler $ elaboratedShared buildCtx
-    let mkPkgBinDir = (</> "bin") .
-                      storePackageDirectory
-                         (cabalStoreDirLayout $ cabalDirLayout baseCtx)
-                         (compilerId compiler)
+    let
+      dryRun = buildSettingDryRun $ buildSettings baseCtx
+      mkPkgBinDir = (</> "bin") .
+                    storePackageDirectory
+                       (cabalStoreDirLayout $ cabalDirLayout baseCtx)
+                       compilerId
+      installLibs = fromFlagOrDefault False (ninstInstallLibs newInstallFlags)
 
-    -- If there are exes, symlink them
-    let defaultSymlinkBindir = error "TODO: how do I get the default ~/.cabal (or ~/.local) directory? (use --symlink-bindir explicitly for now)" </> "bin"
-    symlinkBindir <- makeAbsolute $ fromFlagOrDefault defaultSymlinkBindir (Client.installSymlinkBinDir installFlags)
-    traverse_ (symlinkBuiltPackage mkPkgBinDir symlinkBindir)
-          $ Map.toList $ targetsMap buildCtx
-    runProjectPostBuildPhase verbosity baseCtx buildCtx buildOutcomes
+    when (not installLibs && not dryRun) $ do
+      -- If there are exes, symlink them
+      let symlinkBindirUnknown =
+            "symlink-bindir is not defined. Set it in your cabal config file "
+            ++ "or use --symlink-bindir=<path>"
+      symlinkBindir <- fromFlagOrDefault (die' verbosity symlinkBindirUnknown)
+                    $ fmap makeAbsolute
+                    $ projectConfigSymlinkBinDir
+                    $ projectConfigBuildOnly
+                    $ projectConfig $ baseCtx
+      createDirectoryIfMissingVerbose verbosity False symlinkBindir
+      warnIfNoExes verbosity buildCtx
+      let
+        doSymlink = symlinkBuiltPackage
+                      verbosity
+                      overwritePolicy
+                      mkPkgBinDir symlinkBindir
+        in traverse_ doSymlink $ Map.toList $ targetsMap buildCtx
+
+    when (installLibs && not dryRun) $
+      if supportsPkgEnvFiles
+        then do
+          -- Why do we get it again? If we updated a globalPackage then we need
+          -- the new version.
+          installedIndex' <- getInstalledPackages verbosity compiler packageDbs progDb'
+          let
+            getLatest = fmap (head . snd) . take 1 . sortBy (comparing (Down . fst))
+                      . PI.lookupPackageName installedIndex'
+            globalLatest = concat (getLatest <$> globalPackages)
+
+            baseEntries =
+              GhcEnvFileClearPackageDbStack : fmap GhcEnvFilePackageDb packageDbs
+            globalEntries = GhcEnvFilePackageId . installedUnitId <$> globalLatest
+            pkgEntries = ordNub $
+                  globalEntries
+              ++ envEntries'
+              ++ entriesForLibraryComponents (targetsMap buildCtx)
+            contents' = renderGhcEnvironmentFile (baseEntries ++ pkgEntries)
+          createDirectoryIfMissing True (takeDirectory envFile)
+          writeFileAtomic envFile (BS.pack contents')
+        else
+          warn verbosity $
+              "The current compiler doesn't support safely installing libraries, "
+            ++ "so only executables will be available. (Library installation is "
+            ++ "supported on GHC 8.0+ only)"
   where
     configFlags' = disableTestsBenchsByDefault configFlags
     verbosity = fromFlagOrDefault normal (configVerbosity configFlags')
     cliConfig = commandLineFlagsToProjectConfig
                   globalFlags configFlags' configExFlags
                   installFlags haddockFlags
+    globalConfigFlag = projectConfigConfigFile (projectConfigShared cliConfig)
+    overwritePolicy = fromFlagOrDefault NeverOverwrite
+                        $ ninstOverwritePolicy newInstallFlags
 
+warnIfNoExes :: Verbosity -> ProjectBuildContext -> IO ()
+warnIfNoExes verbosity buildCtx =
+  when noExes $
+    warn verbosity $ "You asked to install executables, "
+                  <> "but there are no executables in "
+                  <> plural (listPlural selectors) "target" "targets" <> ": "
+                  <> intercalate ", " (showTargetSelector <$> selectors) <> ". "
+                  <> "Perhaps you want to use --lib "
+                  <> "to install libraries instead."
+  where
+    targets = concat $ Map.elems $ targetsMap buildCtx
+    components = fst <$> targets
+    selectors = concatMap snd targets
+    noExes = null $ catMaybes $ exeMaybe <$> components
+    exeMaybe (ComponentTarget (CExeName exe) _) = Just exe
+    exeMaybe _ = Nothing
 
+globalPackages :: [PackageName]
+globalPackages = mkPackageName <$>
+  [ "ghc", "hoopl", "bytestring", "unix", "base", "time", "hpc", "filepath"
+  , "process", "array", "integer-gmp", "containers", "ghc-boot", "binary"
+  , "ghc-prim", "ghci", "rts", "terminfo", "transformers", "deepseq"
+  , "ghc-boot-th", "pretty", "template-haskell", "directory", "text"
+  , "bin-package-db"
+  ]
+
+environmentFileToSpecifiers :: PI.InstalledPackageIndex -> [GhcEnvironmentFileEntry]
+                            -> ([PackageSpecifier a], [GhcEnvironmentFileEntry])
+environmentFileToSpecifiers ipi = foldMap $ \case
+    (GhcEnvFilePackageId unitId)
+        | Just InstalledPackageInfo{ sourcePackageId = PackageIdentifier{..}, installedUnitId }
+          <- PI.lookupUnitId ipi unitId
+        , let pkgSpec = NamedPackage pkgName [PackagePropertyVersion (thisVersion pkgVersion)]
+        -> if pkgName `elem` globalPackages
+          then ([pkgSpec], [])
+          else ([pkgSpec], [GhcEnvFilePackageId installedUnitId])
+    _ -> ([], [])
+
+
 -- | Disables tests and benchmarks if they weren't explicitly enabled.
 disableTestsBenchsByDefault :: ConfigFlags -> ConfigFlags
 disableTestsBenchsByDefault configFlags =
@@ -204,42 +676,81 @@
               , configBenchmarks = Flag False <> configBenchmarks configFlags }
 
 -- | Symlink every exe from a package from the store to a given location
-symlinkBuiltPackage :: (UnitId -> FilePath) -- ^ A function to get an UnitId's
+symlinkBuiltPackage :: Verbosity
+                    -> OverwritePolicy -- ^ Whether to overwrite existing files
+                    -> (UnitId -> FilePath) -- ^ A function to get an UnitId's
                                             -- store directory
                     -> FilePath -- ^ Where to put the symlink
                     -> ( UnitId
-                        , [(ComponentTarget, [TargetSelector PackageId])] )
+                        , [(ComponentTarget, [TargetSelector])] )
                      -> IO ()
-symlinkBuiltPackage mkSourceBinDir destDir (pkg, components) =
-  traverse_ (symlinkBuiltExe (mkSourceBinDir pkg) destDir) exes
+symlinkBuiltPackage verbosity overwritePolicy
+                    mkSourceBinDir destDir
+                    (pkg, components) =
+  traverse_ symlinkAndWarn exes
   where
     exes = catMaybes $ (exeMaybe . fst) <$> components
     exeMaybe (ComponentTarget (CExeName exe) _) = Just exe
     exeMaybe _ = Nothing
+    symlinkAndWarn exe = do
+      success <- symlinkBuiltExe
+                   verbosity overwritePolicy
+                   (mkSourceBinDir pkg) destDir exe
+      let errorMessage = case overwritePolicy of
+                  NeverOverwrite ->
+                    "Path '" <> (destDir </> prettyShow exe) <> "' already exists. "
+                    <> "Use --overwrite-policy=always to overwrite."
+                  -- This shouldn't even be possible, but we keep it in case
+                  -- symlinking logic changes
+                  AlwaysOverwrite -> "Symlinking '" <> prettyShow exe <> "' failed."
+      unless success $ die' verbosity errorMessage
 
 -- | Symlink a specific exe.
-symlinkBuiltExe :: FilePath -> FilePath -> UnqualComponentName -> IO Bool
-symlinkBuiltExe sourceDir destDir exe =
+symlinkBuiltExe :: Verbosity -> OverwritePolicy
+                -> FilePath -> FilePath
+                -> UnqualComponentName
+                -> IO Bool
+symlinkBuiltExe verbosity overwritePolicy sourceDir destDir exe = do
+  notice verbosity $ "Symlinking '" <> prettyShow exe <> "'"
   symlinkBinary
+    overwritePolicy
     destDir
     sourceDir
     exe
     $ unUnqualComponentName exe
 
+-- | Create 'GhcEnvironmentFileEntry's for packages with exposed libraries.
+entriesForLibraryComponents :: TargetsMap -> [GhcEnvironmentFileEntry]
+entriesForLibraryComponents = Map.foldrWithKey' (\k v -> mappend (go k v)) []
+  where
+    hasLib :: (ComponentTarget, [TargetSelector]) -> Bool
+    hasLib (ComponentTarget CLibName _,        _) = True
+    hasLib (ComponentTarget (CSubLibName _) _, _) = True
+    hasLib _                                      = False
+
+    go :: UnitId -> [(ComponentTarget, [TargetSelector])] -> [GhcEnvironmentFileEntry]
+    go unitId targets
+      | any hasLib targets = [GhcEnvFilePackageId unitId]
+      | otherwise          = []
+
 -- | Create a dummy project context, without a .cabal or a .cabal.project file
 -- (a place where to put a temporary dist directory is still needed)
-establishDummyProjectBaseContext :: Verbosity
-                                 -> ProjectConfig
-                                 -> FilePath -- ^ Where to put the dist directory
-                                 -> [PackageSpecifier UnresolvedSourcePackage] -- ^ The packages to be included in the project
-                                 -> IO ProjectBaseContext
+establishDummyProjectBaseContext
+  :: Verbosity
+  -> ProjectConfig
+  -> FilePath
+     -- ^ Where to put the dist directory
+  -> [PackageSpecifier UnresolvedSourcePackage]
+     -- ^ The packages to be included in the project
+  -> IO ProjectBaseContext
 establishDummyProjectBaseContext verbosity cliConfig tmpDir localPackages = do
 
-    cabalDir <- defaultCabalDir
+    cabalDir <- getCabalDir
 
     -- Create the dist directories
     createDirectoryIfMissingVerbose verbosity True $ distDirectory distDirLayout
-    createDirectoryIfMissingVerbose verbosity True $ distProjectCacheDirectory distDirLayout
+    createDirectoryIfMissingVerbose verbosity True $
+      distProjectCacheDirectory distDirLayout
 
     globalConfig <- runRebuild ""
                   $ readGlobalConfig verbosity
@@ -248,10 +759,13 @@
     let projectConfig = globalConfig <> cliConfig
 
     let ProjectConfigBuildOnly {
-          projectConfigLogsDir,
-          projectConfigStoreDir
+          projectConfigLogsDir
         } = projectConfigBuildOnly projectConfig
 
+        ProjectConfigShared {
+          projectConfigStoreDir
+        } = projectConfigShared projectConfig
+
         mlogsDir = flagToMaybe projectConfigLogsDir
         mstoreDir = flagToMaybe projectConfigStoreDir
         cabalDirLayout = mkCabalDirLayout cabalDir mstoreDir mlogsDir
@@ -279,10 +793,11 @@
 -- It selects the 'AvailableTarget's that the 'TargetSelector' refers to,
 -- or otherwise classifies the problem.
 --
--- For the @build@ command select all components except non-buildable and disabled
--- tests\/benchmarks, fail if there are no such components
+-- For the @build@ command select all components except non-buildable
+-- and disabled tests\/benchmarks, fail if there are no such
+-- components
 --
-selectPackageTargets :: TargetSelector PackageId
+selectPackageTargets :: TargetSelector
                      -> [AvailableTarget k] -> Either TargetProblem [k]
 selectPackageTargets targetSelector targets
 
@@ -315,11 +830,11 @@
 --
 -- For the @build@ command we just need the basic checks on being buildable etc.
 --
-selectComponentTarget :: PackageId -> ComponentName -> SubComponentTarget
+selectComponentTarget :: SubComponentTarget
                       -> AvailableTarget k -> Either TargetProblem k
-selectComponentTarget pkgid cname subtarget =
+selectComponentTarget subtarget =
     either (Left . TargetProblemCommon) Right
-  . selectComponentTargetBasic pkgid cname subtarget
+  . selectComponentTargetBasic subtarget
 
 
 -- | The various error conditions that can occur when matching a
@@ -329,10 +844,10 @@
      TargetProblemCommon       TargetProblemCommon
 
      -- | The 'TargetSelector' matches targets but none are buildable
-   | TargetProblemNoneEnabled (TargetSelector PackageId) [AvailableTarget ()]
+   | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]
 
      -- | There are no targets at all
-   | TargetProblemNoTargets   (TargetSelector PackageId)
+   | TargetProblemNoTargets   TargetSelector
   deriving (Eq, Show)
 
 reportTargetProblems :: Verbosity -> [TargetProblem] -> IO a
@@ -350,4 +865,3 @@
 reportCannotPruneDependencies :: Verbosity -> CannotPruneDependencies -> IO a
 reportCannotPruneDependencies verbosity =
     die' verbosity . renderCannotPruneDependencies
-
diff --git a/cabal/cabal-install/Distribution/Client/CmdLegacy.hs b/cabal/cabal-install/Distribution/Client/CmdLegacy.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/Distribution/Client/CmdLegacy.hs
@@ -0,0 +1,173 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ViewPatterns #-}
+module Distribution.Client.CmdLegacy ( legacyCmd, legacyWrapperCmd, newCmd ) where
+
+import Prelude ()
+import Distribution.Client.Compat.Prelude
+
+import Distribution.Client.Sandbox
+    ( loadConfigOrSandboxConfig, findSavedDistPref )
+import qualified Distribution.Client.Setup as Client
+import Distribution.Client.SetupWrapper
+    ( SetupScriptOptions(..), setupWrapper, defaultSetupScriptOptions )
+import qualified Distribution.Simple.Setup as Setup
+import Distribution.Simple.Command
+import Distribution.Simple.Utils
+    ( warn, wrapText )
+import Distribution.Verbosity 
+    ( Verbosity, normal )
+
+import Control.Exception
+    ( SomeException(..), try )
+import qualified Data.Text as T
+
+-- Tweaked versions of code from Main.
+regularCmd :: (HasVerbosity flags) => CommandUI flags -> (flags -> [String] -> globals -> IO action) -> Bool -> CommandSpec (globals -> IO action)
+regularCmd ui action shouldWarn =
+        CommandSpec ui ((flip commandAddAction) (\flags extra globals -> showWarning flags >> action flags extra globals)) NormalCommand
+    where
+        showWarning flags = if shouldWarn 
+            then warn (verbosity flags) (deprecationNote (commandName ui) ++ "\n")
+            else return ()
+
+wrapperCmd :: Monoid flags => CommandUI flags -> (flags -> Setup.Flag Verbosity) -> (flags -> Setup.Flag String) -> Bool -> CommandSpec (Client.GlobalFlags -> IO ())
+wrapperCmd ui verbosity' distPref shouldWarn =
+  CommandSpec ui (\ui' -> wrapperAction ui' verbosity' distPref shouldWarn) NormalCommand
+
+wrapperAction :: Monoid flags => CommandUI flags  -> (flags -> Setup.Flag Verbosity) -> (flags -> Setup.Flag String) -> Bool -> Command (Client.GlobalFlags -> IO ())
+wrapperAction command verbosityFlag distPrefFlag shouldWarn =
+  commandAddAction command
+    { commandDefaultFlags = mempty } $ \flags extraArgs globalFlags -> do
+    let verbosity' = Setup.fromFlagOrDefault normal (verbosityFlag flags)
+
+    if shouldWarn
+        then warn verbosity' (deprecationNote (commandName command) ++ "\n")
+        else return ()
+
+    load <- try (loadConfigOrSandboxConfig verbosity' globalFlags)
+    let config = either (\(SomeException _) -> mempty) snd load
+    distPref <- findSavedDistPref config (distPrefFlag flags)
+    let setupScriptOptions = defaultSetupScriptOptions { useDistPref = distPref }
+
+    let command' = command { commandName = T.unpack . T.replace "v1-" "" . T.pack . commandName $ command }
+
+    setupWrapper verbosity' setupScriptOptions Nothing
+                 command' (const flags) (const extraArgs)
+
+--
+
+class HasVerbosity a where 
+    verbosity :: a -> Verbosity
+
+instance HasVerbosity (Setup.Flag Verbosity) where
+    verbosity = Setup.fromFlagOrDefault normal
+
+instance (HasVerbosity a) => HasVerbosity (a, b) where
+    verbosity (a, _) = verbosity a
+
+instance (HasVerbosity b) => HasVerbosity (a, b, c) where
+    verbosity (_ , b, _) = verbosity b
+
+instance (HasVerbosity a) => HasVerbosity (a, b, c, d) where
+    verbosity (a, _, _, _) = verbosity a
+
+instance HasVerbosity Setup.BuildFlags where
+    verbosity = verbosity . Setup.buildVerbosity
+
+instance HasVerbosity Setup.ConfigFlags where
+    verbosity = verbosity . Setup.configVerbosity
+
+instance HasVerbosity Setup.ReplFlags where
+    verbosity = verbosity . Setup.replVerbosity
+
+instance HasVerbosity Client.FreezeFlags where
+    verbosity = verbosity . Client.freezeVerbosity
+
+instance HasVerbosity Setup.HaddockFlags where
+    verbosity = verbosity . Setup.haddockVerbosity
+
+instance HasVerbosity Client.ExecFlags where
+    verbosity = verbosity . Client.execVerbosity
+
+instance HasVerbosity Client.UpdateFlags where
+    verbosity = verbosity . Client.updateVerbosity
+
+instance HasVerbosity Setup.CleanFlags where
+    verbosity = verbosity . Setup.cleanVerbosity
+
+instance HasVerbosity Client.SDistFlags where
+    verbosity = verbosity . Client.sDistVerbosity
+
+instance HasVerbosity Client.SandboxFlags where
+    verbosity = verbosity . Client.sandboxVerbosity
+
+instance HasVerbosity Setup.DoctestFlags where
+    verbosity = verbosity . Setup.doctestVerbosity
+
+--
+
+deprecationNote :: String -> String
+deprecationNote cmd = wrapText $
+    "The " ++ cmd ++ " command is a part of the legacy v1 style of cabal usage.\n\n" ++
+
+    "Please switch to using either the new project style and the new-" ++ cmd ++ 
+    " command or the legacy v1-" ++ cmd ++ " alias as new-style projects will" ++
+    " become the default in the next version of cabal-install. Please file a" ++
+    " bug if you cannot replicate a working v1- use case with the new-style commands.\n\n" ++
+
+    "For more information, see: https://wiki.haskell.org/Cabal/NewBuild\n"
+
+legacyNote :: String -> String
+legacyNote cmd = wrapText $
+    "The v1-" ++ cmd ++ " command is a part of the legacy v1 style of cabal usage.\n\n" ++
+
+    "It is a legacy feature and will be removed in a future release of cabal-install." ++
+    " Please file a bug if you cannot replicate a working v1- use case with the new-style" ++
+    " commands.\n\n" ++
+
+    "For more information, see: https://wiki.haskell.org/Cabal/NewBuild\n"
+
+toLegacyCmd :: (Bool -> CommandSpec (globals -> IO action)) -> [CommandSpec (globals -> IO action)]
+toLegacyCmd mkSpec = [toDeprecated (mkSpec True), toLegacy (mkSpec False)]
+    where
+        legacyMsg = T.unpack . T.replace "v1-" "" . T.pack
+
+        toLegacy (CommandSpec origUi@CommandUI{..} action type') = CommandSpec legUi action type'
+            where
+                legUi = origUi
+                    { commandName = "v1-" ++ commandName
+                    , commandNotes = Just $ \pname -> case commandNotes of
+                        Just notes -> notes pname ++ "\n" ++ legacyNote commandName
+                        Nothing -> legacyNote commandName
+                    }
+
+        toDeprecated (CommandSpec origUi@CommandUI{..} action type') = CommandSpec depUi action type'
+            where
+                depUi = origUi
+                    { commandName = legacyMsg commandName
+                    , commandUsage = legacyMsg . commandUsage
+                    , commandDescription = (legacyMsg .) <$> commandDescription
+                    , commandNotes = Just $ \pname -> case commandNotes of
+                        Just notes -> legacyMsg (notes pname) ++ "\n" ++ deprecationNote commandName
+                        Nothing -> deprecationNote commandName
+                    }
+
+legacyCmd :: (HasVerbosity flags) => CommandUI flags -> (flags -> [String] -> globals -> IO action) -> [CommandSpec (globals -> IO action)]
+legacyCmd ui action = toLegacyCmd (regularCmd ui action)
+
+legacyWrapperCmd :: Monoid flags => CommandUI flags -> (flags -> Setup.Flag Verbosity) -> (flags -> Setup.Flag String) -> [CommandSpec (Client.GlobalFlags -> IO ())]
+legacyWrapperCmd ui verbosity' distPref = toLegacyCmd (wrapperCmd ui verbosity' distPref)
+
+newCmd :: CommandUI flags -> (flags -> [String] -> globals -> IO action) -> [CommandSpec (globals -> IO action)]
+newCmd origUi@CommandUI{..} action = [cmd v2Ui, cmd origUi]
+    where
+        cmd ui = CommandSpec ui (flip commandAddAction action) NormalCommand
+        v2Msg = T.unpack . T.replace "new-" "v2-" . T.pack
+        v2Ui = origUi 
+            { commandName = v2Msg commandName
+            , commandUsage = v2Msg . commandUsage
+            , commandDescription = (v2Msg .) <$> commandDescription
+            , commandNotes = (v2Msg .) <$> commandDescription
+            }
diff --git a/cabal/cabal-install/Distribution/Client/CmdRepl.hs b/cabal/cabal-install/Distribution/Client/CmdRepl.hs
--- a/cabal/cabal-install/Distribution/Client/CmdRepl.hs
+++ b/cabal/cabal-install/Distribution/Client/CmdRepl.hs
@@ -1,5 +1,8 @@
+{-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE ViewPatterns   #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
 
 -- | cabal-install CLI command: repl
 --
@@ -14,34 +17,128 @@
     selectComponentTarget
   ) where
 
-import Distribution.Client.ProjectOrchestration
-import Distribution.Client.CmdErrorMessages
+import Prelude ()
+import Distribution.Client.Compat.Prelude
 
+import Distribution.Compat.Lens
+import qualified Distribution.Types.Lens as L
+
+import Distribution.Client.CmdErrorMessages
+import Distribution.Client.CmdInstall
+         ( establishDummyProjectBaseContext )
+import qualified Distribution.Client.InstallPlan as InstallPlan
+import Distribution.Client.ProjectBuilding
+         ( rebuildTargetsDryRun, improveInstallPlanWithUpToDatePackages )
+import Distribution.Client.ProjectConfig
+         ( ProjectConfig(..), withProjectOrGlobalConfig
+         , projectConfigConfigFile, readGlobalConfig )
+import Distribution.Client.ProjectOrchestration
+import Distribution.Client.ProjectPlanning 
+       ( ElaboratedSharedConfig(..), ElaboratedInstallPlan )
+import Distribution.Client.ProjectPlanning.Types
+       ( elabOrderExeDependencies )
+import Distribution.Client.RebuildMonad
+         ( runRebuild )
 import Distribution.Client.Setup
-         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags
-         , applyFlagDefaults )
+         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags )
 import qualified Distribution.Client.Setup as Client
+import Distribution.Client.Types
+         ( PackageLocation(..), PackageSpecifier(..), UnresolvedSourcePackage )
 import Distribution.Simple.Setup
-         ( HaddockFlags, fromFlagOrDefault )
+         ( HaddockFlags, fromFlagOrDefault, replOptions
+         , Flag(..), toFlag, trueArg, falseArg )
 import Distribution.Simple.Command
-         ( CommandUI(..), usageAlternatives )
+         ( CommandUI(..), liftOption, usageAlternatives, option
+         , ShowOrParseArgs, OptionField, reqArg )
 import Distribution.Package
-         ( packageName )
+         ( Package(..), packageName, UnitId, installedUnitId )
+import Distribution.PackageDescription.PrettyPrint
+import Distribution.Parsec.Class
+         ( Parsec(..) )
+import Distribution.Pretty
+         ( prettyShow )
+import Distribution.ReadE
+         ( ReadE, parsecToReadE )
+import qualified Distribution.SPDX.License as SPDX
+import Distribution.Solver.Types.SourcePackage
+         ( SourcePackage(..) )
+import Distribution.Types.BuildInfo
+         ( BuildInfo(..), emptyBuildInfo )
 import Distribution.Types.ComponentName
          ( componentNameString )
+import Distribution.Types.CondTree
+         ( CondTree(..), traverseCondTreeC )
+import Distribution.Types.Dependency
+         ( Dependency(..) )
+import Distribution.Types.GenericPackageDescription
+         ( emptyGenericPackageDescription )
+import Distribution.Types.PackageDescription
+         ( PackageDescription(..), emptyPackageDescription )
+import Distribution.Types.Library
+         ( Library(..), emptyLibrary )
+import Distribution.Types.PackageId
+         ( PackageIdentifier(..) )
+import Distribution.Types.Version
+         ( mkVersion, version0 )
+import Distribution.Types.VersionRange
+         ( anyVersion )
 import Distribution.Text
          ( display )
 import Distribution.Verbosity
-         ( Verbosity, normal )
+         ( Verbosity, normal, lessVerbose )
 import Distribution.Simple.Utils
-         ( wrapText, die', ordNub )
+         ( wrapText, die', debugNoWrap, ordNub, createTempDirectory, handleDoesNotExist )
+import Language.Haskell.Extension
+         ( Language(..) )
 
+import Data.List
+         ( (\\) )
 import qualified Data.Map as Map
 import qualified Data.Set as Set
-import Control.Monad (when)
+import System.Directory
+         ( getTemporaryDirectory, removeDirectoryRecursive )
+import System.FilePath
+         ( (</>) )
 
+type ReplFlags = [String]
 
-replCommand :: CommandUI (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
+data EnvFlags = EnvFlags 
+  { envPackages :: [Dependency]
+  , envIncludeTransitive :: Flag Bool
+  , envIgnoreProject :: Flag Bool
+  }
+
+defaultEnvFlags :: EnvFlags
+defaultEnvFlags = EnvFlags
+  { envPackages = []
+  , envIncludeTransitive = toFlag True
+  , envIgnoreProject = toFlag False
+  }
+
+envOptions :: ShowOrParseArgs -> [OptionField EnvFlags]
+envOptions _ =
+  [ option ['b'] ["build-depends"]
+    "Include an additional package in the environment presented to GHCi."
+    envPackages (\p flags -> flags { envPackages = p ++ envPackages flags })
+    (reqArg "DEPENDENCY" dependencyReadE (fmap prettyShow :: [Dependency] -> [String]))
+  , option [] ["no-transitive-deps"]
+    "Don't automatically include transitive dependencies of requested packages."
+    envIncludeTransitive (\p flags -> flags { envIncludeTransitive = p })
+    falseArg
+  , option ['z'] ["ignore-project"]
+    "Only include explicitly specified packages (and 'base')."
+    envIgnoreProject (\p flags -> flags { envIgnoreProject = p })
+    trueArg
+  ]
+  where
+    dependencyReadE :: ReadE [Dependency]
+    dependencyReadE =
+      fmap pure $
+        parsecToReadE
+          ("couldn't parse dependency: " ++)
+          parsec
+
+replCommand :: CommandUI (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags, ReplFlags, EnvFlags)
 replCommand = Client.installCommand {
   commandName         = "new-repl",
   commandSynopsis     = "Open an interactive session for the given component.",
@@ -71,11 +168,36 @@
      ++ "    for the component named 'cname'\n"
      ++ "  " ++ pname ++ " new-repl pkgname:cname\n"
      ++ "    for the component 'cname' in the package 'pkgname'\n\n"
+     ++ "  " ++ pname ++ " new-repl --build-depends lens\n"
+     ++ "    add the latest version of the library 'lens' to the default component "
+        ++ "(or no componentif there is no project present)\n"
+     ++ "  " ++ pname ++ " new-repl --build-depends \"lens >= 4.15 && < 4.18\"\n"
+     ++ "    add a version (constrained between 4.15 and 4.18) of the library 'lens' "
+        ++ "to the default component (or no component if there is no project present)\n"
 
-     ++ cmdCommonHelpTextNewBuildBeta
+     ++ cmdCommonHelpTextNewBuildBeta,
+  commandDefaultFlags = (configFlags,configExFlags,installFlags,haddockFlags,[],defaultEnvFlags),
+  commandOptions = \showOrParseArgs ->
+        map liftOriginal (commandOptions Client.installCommand showOrParseArgs)
+        ++ map liftReplOpts (replOptions showOrParseArgs)
+        ++ map liftEnvOpts  (envOptions  showOrParseArgs)
    }
+  where
+    (configFlags,configExFlags,installFlags,haddockFlags) = commandDefaultFlags Client.installCommand
 
+    liftOriginal = liftOption projectOriginal updateOriginal
+    liftReplOpts = liftOption projectReplOpts updateReplOpts
+    liftEnvOpts  = liftOption projectEnvOpts  updateEnvOpts
 
+    projectOriginal          (a,b,c,d,_,_) = (a,b,c,d)
+    updateOriginal (a,b,c,d) (_,_,_,_,e,f) = (a,b,c,d,e,f)
+
+    projectReplOpts  (_,_,_,_,e,_) = e
+    updateReplOpts e (a,b,c,d,_,f) = (a,b,c,d,e,f)
+
+    projectEnvOpts  (_,_,_,_,_,f) = f
+    updateEnvOpts f (a,b,c,d,e,_) = (a,b,c,d,e,f)
+
 -- | The @repl@ command is very much like @build@. It brings the install plan
 -- up to date, selects that part of the plan needed by the given or implicit
 -- repl target and then executes the plan.
@@ -87,57 +209,221 @@
 -- For more details on how this works, see the module
 -- "Distribution.Client.ProjectOrchestration"
 --
-replAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
+replAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags, ReplFlags, EnvFlags)
            -> [String] -> GlobalFlags -> IO ()
-replAction (applyFlagDefaults -> (configFlags, configExFlags, installFlags, haddockFlags))
+replAction (configFlags, configExFlags, installFlags, haddockFlags, replFlags, envFlags)
            targetStrings globalFlags = do
-
-    baseCtx <- establishProjectBaseContext verbosity cliConfig
+    let
+      ignoreProject = fromFlagOrDefault False (envIgnoreProject envFlags)
+      with           = withProject    cliConfig             verbosity targetStrings
+      without config = withoutProject (config <> cliConfig) verbosity targetStrings
+    
+    (baseCtx, targetSelectors, finalizer) <- if ignoreProject
+      then do
+        globalConfig <- runRebuild "" $ readGlobalConfig verbosity globalConfigFlag
+        without globalConfig
+      else withProjectOrGlobalConfig verbosity globalConfigFlag with without
 
-    targetSelectors <- either (reportTargetSelectorProblems verbosity) return
-                   =<< readTargetSelectors (localPackages baseCtx) targetStrings
+    when (buildSettingOnlyDeps (buildSettings baseCtx)) $
+      die' verbosity $ "The repl command does not support '--only-dependencies'. "
+          ++ "You may wish to use 'build --only-dependencies' and then "
+          ++ "use 'repl'."
 
-    buildCtx <-
-      runProjectPreBuildPhase verbosity baseCtx $ \elaboratedPlan -> do
+    (originalComponent, baseCtx') <- if null (envPackages envFlags)
+      then return (Nothing, baseCtx)
+      else
+        -- Unfortunately, the best way to do this is to let the normal solver
+        -- help us resolve the targets, but that isn't ideal for performance,
+        -- especially in the no-project case.
+        withInstallPlan (lessVerbose verbosity) baseCtx $ \elaboratedPlan _ -> do
+          targets <- validatedTargets elaboratedPlan targetSelectors
+          
+          let
+            (unitId, _) = head $ Map.toList targets
+            originalDeps = installedUnitId <$> InstallPlan.directDeps elaboratedPlan unitId
+            oci = OriginalComponentInfo unitId originalDeps
+            Just pkgId = packageId <$> InstallPlan.lookup elaboratedPlan unitId 
+            baseCtx' = addDepsToProjectTarget (envPackages envFlags) pkgId baseCtx
 
-            when (buildSettingOnlyDeps (buildSettings baseCtx)) $
-              die' verbosity $ "The repl command does not support '--only-dependencies'. "
-                 ++ "You may wish to use 'build --only-dependencies' and then "
-                 ++ "use 'repl'."
+          return (Just oci, baseCtx')
+          
+    -- Now, we run the solver again with the added packages. While the graph 
+    -- won't actually reflect the addition of transitive dependencies,
+    -- they're going to be available already and will be offered to the REPL
+    -- and that's good enough.
+    --
+    -- In addition, to avoid a *third* trip through the solver, we are 
+    -- replicating the second half of 'runProjectPreBuildPhase' by hand
+    -- here.
+    (buildCtx, replFlags') <- withInstallPlan verbosity baseCtx' $ 
+      \elaboratedPlan elaboratedShared' -> do
+        let ProjectBaseContext{..} = baseCtx'
+          
+        -- Recalculate with updated project.
+        targets <- validatedTargets elaboratedPlan targetSelectors
 
-            -- Interpret the targets on the command line as repl targets
-            -- (as opposed to say build or haddock targets).
-            targets <- either (reportTargetProblems verbosity) return
-                     $ resolveTargets
-                         selectPackageTargets
-                         selectComponentTarget
-                         TargetProblemCommon
-                         elaboratedPlan
-                         targetSelectors
+        let 
+          elaboratedPlan' = pruneInstallPlanToTargets
+                              TargetActionRepl
+                              targets
+                              elaboratedPlan
+          includeTransitive = fromFlagOrDefault True (envIncludeTransitive envFlags)
+          replFlags' = case originalComponent of 
+            Just oci -> generateReplFlags includeTransitive elaboratedPlan' oci
+            Nothing  -> []
+        
+        pkgsBuildStatus <- rebuildTargetsDryRun distDirLayout elaboratedShared'
+                                          elaboratedPlan'
 
-            -- Reject multiple targets, or at least targets in different
-            -- components. It is ok to have two module/file targets in the
-            -- same component, but not two that live in different components.
-            when (Set.size (distinctTargetComponents targets) > 1) $
-              reportTargetProblems verbosity
-                [TargetProblemMultipleTargets targets]
+        let elaboratedPlan'' = improveInstallPlanWithUpToDatePackages
+                                pkgsBuildStatus elaboratedPlan'
+        debugNoWrap verbosity (InstallPlan.showInstallPlan elaboratedPlan'')
 
-            let elaboratedPlan' = pruneInstallPlanToTargets
-                                    TargetActionRepl
-                                    targets
-                                    elaboratedPlan
-            return (elaboratedPlan', targets)
+        let 
+          buildCtx = ProjectBuildContext 
+            { elaboratedPlanOriginal = elaboratedPlan
+            , elaboratedPlanToExecute = elaboratedPlan''
+            , elaboratedShared = elaboratedShared'
+            , pkgsBuildStatus
+            , targetsMap = targets
+            }
+        return (buildCtx, replFlags')
 
-    printPlan verbosity baseCtx buildCtx
+    let buildCtx' = buildCtx
+          { elaboratedShared = (elaboratedShared buildCtx)
+                { pkgConfigReplOptions = replFlags ++ replFlags' }
+          }
+    printPlan verbosity baseCtx' buildCtx'
 
-    buildOutcomes <- runProjectBuildPhase verbosity baseCtx buildCtx
-    runProjectPostBuildPhase verbosity baseCtx buildCtx buildOutcomes
+    buildOutcomes <- runProjectBuildPhase verbosity baseCtx' buildCtx'
+    runProjectPostBuildPhase verbosity baseCtx' buildCtx' buildOutcomes
+    finalizer
   where
     verbosity = fromFlagOrDefault normal (configVerbosity configFlags)
     cliConfig = commandLineFlagsToProjectConfig
                   globalFlags configFlags configExFlags
                   installFlags haddockFlags
+    globalConfigFlag = projectConfigConfigFile (projectConfigShared cliConfig)
+    
+    validatedTargets elaboratedPlan targetSelectors = do
+      -- Interpret the targets on the command line as repl targets
+      -- (as opposed to say build or haddock targets).
+      targets <- either (reportTargetProblems verbosity) return
+          $ resolveTargets
+              selectPackageTargets
+              selectComponentTarget
+              TargetProblemCommon
+              elaboratedPlan
+              Nothing
+              targetSelectors
 
+      -- Reject multiple targets, or at least targets in different
+      -- components. It is ok to have two module/file targets in the
+      -- same component, but not two that live in different components.
+      when (Set.size (distinctTargetComponents targets) > 1) $
+        reportTargetProblems verbosity
+          [TargetProblemMultipleTargets targets]
+
+      return targets
+
+data OriginalComponentInfo = OriginalComponentInfo
+  { ociUnitId :: UnitId
+  , ociOriginalDeps :: [UnitId]
+  }
+  deriving (Show)
+
+withProject :: ProjectConfig -> Verbosity -> [String] -> IO (ProjectBaseContext, [TargetSelector], IO ())
+withProject cliConfig verbosity targetStrings = do
+  baseCtx <- establishProjectBaseContext verbosity cliConfig
+
+  targetSelectors <- either (reportTargetSelectorProblems verbosity) return
+                 =<< readTargetSelectors (localPackages baseCtx) (Just LibKind) targetStrings
+
+  return (baseCtx, targetSelectors, return ())
+
+withoutProject :: ProjectConfig -> Verbosity -> [String]  -> IO (ProjectBaseContext, [TargetSelector], IO ())
+withoutProject config verbosity extraArgs = do
+  unless (null extraArgs) $
+    die' verbosity $ "'repl' doesn't take any extra arguments when outside a project: " ++ unwords extraArgs
+
+  globalTmp <- getTemporaryDirectory
+  tempDir <- createTempDirectory globalTmp "cabal-repl."
+
+  -- We need to create a dummy package that lives in our dummy project.
+  let
+    sourcePackage = SourcePackage
+      { packageInfoId        = pkgId
+      , packageDescription   = genericPackageDescription
+      , packageSource        = LocalUnpackedPackage tempDir
+      , packageDescrOverride = Nothing
+      }
+    genericPackageDescription = emptyGenericPackageDescription 
+      & L.packageDescription .~ packageDescription
+      & L.condLibrary        .~ Just (CondNode library [baseDep] [])
+    packageDescription = emptyPackageDescription
+      { package = pkgId
+      , specVersionRaw = Left (mkVersion [2, 2])
+      , licenseRaw = Left SPDX.NONE
+      }
+    library = emptyLibrary { libBuildInfo = buildInfo }
+    buildInfo = emptyBuildInfo
+      { targetBuildDepends = [baseDep]
+      , defaultLanguage = Just Haskell2010
+      }
+    baseDep = Dependency "base" anyVersion
+    pkgId = PackageIdentifier "fake-package" version0
+
+  writeGenericPackageDescription (tempDir </> "fake-package.cabal") genericPackageDescription
+  
+  baseCtx <- 
+    establishDummyProjectBaseContext
+      verbosity
+      config
+      tempDir
+      [SpecificSourcePackage sourcePackage]
+
+  let
+    targetSelectors = [TargetPackage TargetExplicitNamed [pkgId] Nothing]
+    finalizer = handleDoesNotExist () (removeDirectoryRecursive tempDir)
+
+  return (baseCtx, targetSelectors, finalizer)
+
+addDepsToProjectTarget :: [Dependency]
+                       -> PackageId
+                       -> ProjectBaseContext
+                       -> ProjectBaseContext
+addDepsToProjectTarget deps pkgId ctx = 
+    (\p -> ctx { localPackages = p }) . fmap addDeps . localPackages $ ctx
+  where
+    addDeps :: PackageSpecifier UnresolvedSourcePackage
+            -> PackageSpecifier UnresolvedSourcePackage
+    addDeps (SpecificSourcePackage pkg)
+      | packageId pkg /= pkgId = SpecificSourcePackage pkg
+      | SourcePackage{..} <- pkg =
+        SpecificSourcePackage $ pkg { packageDescription = 
+          packageDescription & (\f -> L.allCondTrees $ traverseCondTreeC f)
+                            %~ (deps ++)
+        }
+    addDeps spec = spec
+
+generateReplFlags :: Bool -> ElaboratedInstallPlan -> OriginalComponentInfo -> ReplFlags
+generateReplFlags includeTransitive elaboratedPlan OriginalComponentInfo{..} = flags
+  where
+    exeDeps :: [UnitId]
+    exeDeps = 
+      foldMap 
+        (InstallPlan.foldPlanPackage (const []) elabOrderExeDependencies)
+        (InstallPlan.dependencyClosure elaboratedPlan [ociUnitId])
+
+    deps, deps', trans, trans' :: [UnitId]
+    flags :: ReplFlags
+    deps   = installedUnitId <$> InstallPlan.directDeps elaboratedPlan ociUnitId
+    deps'  = deps \\ ociOriginalDeps
+    trans  = installedUnitId <$> InstallPlan.dependencyClosure elaboratedPlan deps'
+    trans' = trans \\ ociOriginalDeps
+    flags  = fmap (("-package-id " ++) . prettyShow) . (\\ exeDeps)
+      $ if includeTransitive then trans' else deps'
+
 -- | This defines what a 'TargetSelector' means for the @repl@ command.
 -- It selects the 'AvailableTarget's that the 'TargetSelector' refers to,
 -- or otherwise classifies the problem.
@@ -153,7 +439,7 @@
 -- Fail if there are no buildable lib\/exe components, or if there are
 -- multiple libs or exes.
 --
-selectPackageTargets  :: TargetSelector PackageId
+selectPackageTargets  :: TargetSelector
                       -> [AvailableTarget k] -> Either TargetProblem [k]
 selectPackageTargets targetSelector targets
 
@@ -215,11 +501,11 @@
 --
 -- For the @repl@ command we just need the basic checks on being buildable etc.
 --
-selectComponentTarget :: PackageId -> ComponentName -> SubComponentTarget
+selectComponentTarget :: SubComponentTarget
                       -> AvailableTarget k -> Either TargetProblem k
-selectComponentTarget pkgid cname subtarget =
+selectComponentTarget subtarget =
     either (Left . TargetProblemCommon) Right
-  . selectComponentTargetBasic pkgid cname subtarget
+  . selectComponentTargetBasic subtarget
 
 
 -- | The various error conditions that can occur when matching a
@@ -229,13 +515,13 @@
      TargetProblemCommon       TargetProblemCommon
 
      -- | The 'TargetSelector' matches targets but none are buildable
-   | TargetProblemNoneEnabled (TargetSelector PackageId) [AvailableTarget ()]
+   | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]
 
      -- | There are no targets at all
-   | TargetProblemNoTargets   (TargetSelector PackageId)
+   | TargetProblemNoTargets   TargetSelector
 
      -- | A single 'TargetSelector' matches multiple targets
-   | TargetProblemMatchesMultiple (TargetSelector PackageId) [AvailableTarget ()]
+   | TargetProblemMatchesMultiple TargetSelector [AvailableTarget ()]
 
      -- | Multiple 'TargetSelector's match multiple targets
    | TargetProblemMultipleTargets TargetsMap
diff --git a/cabal/cabal-install/Distribution/Client/CmdRun.hs b/cabal/cabal-install/Distribution/Client/CmdRun.hs
--- a/cabal/cabal-install/Distribution/Client/CmdRun.hs
+++ b/cabal/cabal-install/Distribution/Client/CmdRun.hs
@@ -1,5 +1,7 @@
+{-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE ViewPatterns   #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
 
 -- | cabal-install CLI command: run
 --
@@ -7,6 +9,7 @@
     -- * The @run@ CLI and action
     runCommand,
     runAction,
+    handleShebang,
 
     -- * Internals exposed for testing
     TargetProblem(..),
@@ -21,46 +24,90 @@
 import Distribution.Client.CmdErrorMessages
 
 import Distribution.Client.Setup
-         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags
-         , applyFlagDefaults )
+         ( GlobalFlags(..), ConfigFlags(..), ConfigExFlags, InstallFlags )
+import Distribution.Client.GlobalFlags
+         ( defaultGlobalFlags )
 import qualified Distribution.Client.Setup as Client
 import Distribution.Simple.Setup
          ( HaddockFlags, fromFlagOrDefault )
 import Distribution.Simple.Command
          ( CommandUI(..), usageAlternatives )
 import Distribution.Types.ComponentName
-         ( componentNameString )
+         ( showComponentName )
 import Distribution.Text
          ( display )
 import Distribution.Verbosity
          ( Verbosity, normal )
 import Distribution.Simple.Utils
-         ( wrapText, die', ordNub, info )
+         ( wrapText, die', ordNub, info
+         , createTempDirectory, handleDoesNotExist )
+import Distribution.Client.CmdInstall
+         ( establishDummyProjectBaseContext )
+import Distribution.Client.ProjectConfig
+         ( ProjectConfig(..), ProjectConfigShared(..)
+         , withProjectOrGlobalConfig )
 import Distribution.Client.ProjectPlanning
-         ( ElaboratedConfiguredPackage(..), BuildStyle(..)
+         ( ElaboratedConfiguredPackage(..)
          , ElaboratedInstallPlan, binDirectoryFor )
+import Distribution.Client.ProjectPlanning.Types
+         ( dataDirsEnvironmentForPlan )
+import Distribution.Client.TargetSelector
+         ( TargetSelectorProblem(..), TargetString(..) )
 import Distribution.Client.InstallPlan
          ( toList, foldPlanPackage )
 import Distribution.Types.UnqualComponentName
          ( UnqualComponentName, unUnqualComponentName )
-import Distribution.Types.PackageDescription
-         ( PackageDescription(dataDir) )
 import Distribution.Simple.Program.Run
          ( runProgramInvocation, ProgramInvocation(..),
            emptyProgramInvocation )
-import Distribution.Simple.Build.PathsModule
-         ( pkgPathEnvVar )
 import Distribution.Types.UnitId
          ( UnitId )
+
+import Distribution.CabalSpecVersion
+         ( cabalSpecLatest )
 import Distribution.Client.Types
-         ( PackageLocation(..) )
+         ( PackageLocation(..), PackageSpecifier(..) )
+import Distribution.FieldGrammar
+         ( takeFields, parseFieldGrammar )
+import Distribution.PackageDescription.FieldGrammar
+         ( executableFieldGrammar )
+import Distribution.PackageDescription.PrettyPrint
+         ( writeGenericPackageDescription )
+import Distribution.Parsec.Common
+         ( Position(..) )
+import Distribution.Parsec.ParseResult
+         ( ParseResult, parseString, parseFatalFailure )
+import Distribution.Parsec.Parser
+         ( readFields )
+import qualified Distribution.SPDX.License as SPDX
+import Distribution.Solver.Types.SourcePackage as SP
+         ( SourcePackage(..) )
+import Distribution.Types.BuildInfo
+         ( BuildInfo(..) )
+import Distribution.Types.CondTree
+         ( CondTree(..) )
+import Distribution.Types.Executable
+         ( Executable(..) )
+import Distribution.Types.GenericPackageDescription as GPD
+         ( GenericPackageDescription(..), emptyGenericPackageDescription )
+import Distribution.Types.PackageDescription
+         ( PackageDescription(..), emptyPackageDescription )
+import Distribution.Types.PackageId
+         ( PackageIdentifier(..) )
+import Distribution.Types.Version
+         ( mkVersion, version0 )
+import Language.Haskell.Extension
+         ( Language(..) )
 
+import qualified Data.ByteString.Char8 as BS
 import qualified Data.Map as Map
 import qualified Data.Set as Set
+import qualified Text.Parsec as P
+import System.Directory
+         ( getTemporaryDirectory, removeDirectoryRecursive, doesFileExist )
 import System.FilePath
          ( (</>) )
 
-
 runCommand :: CommandUI (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
 runCommand = Client.installCommand {
   commandName         = "new-run",
@@ -68,12 +115,13 @@
   commandUsage        = usageAlternatives "new-run"
                           [ "[TARGET] [FLAGS] [-- EXECUTABLE_FLAGS]" ],
   commandDescription  = Just $ \pname -> wrapText $
-        "Runs the specified executable, first ensuring it is up to date.\n\n"
+        "Runs the specified executable-like component (an executable, a test, "
+     ++ "or a benchmark), first ensuring it is up to date.\n\n"
 
-     ++ "Any executable in any package in the project can be specified. "
-     ++ "A package can be specified if contains just one executable. "
-     ++ "The default is to use the package in the current directory if it "
-     ++ "contains just one executable.\n\n"
+     ++ "Any executable-like component in any package in the project can be "
+     ++ "specified. A package can be specified if contains just one "
+     ++ "executable-like. The default is to use the package in the current "
+     ++ "directory if it contains just one executable-like.\n\n"
 
      ++ "Extra arguments can be passed to the program, but use '--' to "
      ++ "separate arguments for the program from arguments for " ++ pname
@@ -87,40 +135,63 @@
   commandNotes        = Just $ \pname ->
         "Examples:\n"
      ++ "  " ++ pname ++ " new-run\n"
-     ++ "    Run the executable in the package in the current directory\n"
+     ++ "    Run the executable-like in the package in the current directory\n"
      ++ "  " ++ pname ++ " new-run foo-tool\n"
-     ++ "    Run the named executable (in any package in the project)\n"
+     ++ "    Run the named executable-like (in any package in the project)\n"
      ++ "  " ++ pname ++ " new-run pkgfoo:foo-tool\n"
-     ++ "    Run the executable 'foo-tool' in the package 'pkgfoo'\n"
+     ++ "    Run the executable-like 'foo-tool' in the package 'pkgfoo'\n"
      ++ "  " ++ pname ++ " new-run foo -O2 -- dothing --fooflag\n"
      ++ "    Build with '-O2' and run the program, passing it extra arguments.\n\n"
 
      ++ cmdCommonHelpTextNewBuildBeta
-   }
-
-
--- | The @build@ command does a lot. It brings the install plan up to date,
--- selects that part of the plan needed by the given or implicit targets and
--- then executes the plan.
+  }
+ 
+-- | The @run@ command runs a specified executable-like component, building it
+-- first if necessary. The component can be either an executable, a test,
+-- or a benchmark. This is particularly useful for passing arguments to
+-- exes/tests/benchs by simply appending them after a @--@.
 --
 -- For more details on how this works, see the module
 -- "Distribution.Client.ProjectOrchestration"
 --
 runAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
           -> [String] -> GlobalFlags -> IO ()
-runAction (applyFlagDefaults -> (configFlags, configExFlags, installFlags, haddockFlags))
+runAction (configFlags, configExFlags, installFlags, haddockFlags)
             targetStrings globalFlags = do
-
-    baseCtx <- establishProjectBaseContext verbosity cliConfig
+    globalTmp <- getTemporaryDirectory
+    tempDir <- createTempDirectory globalTmp "cabal-repl."
+  
+    let
+      with = 
+        establishProjectBaseContext verbosity cliConfig
+      without config = 
+        establishDummyProjectBaseContext verbosity (config <> cliConfig) tempDir []
 
-    targetSelectors <- either (reportTargetSelectorProblems verbosity) return
-                   =<< readTargetSelectors (localPackages baseCtx)
-                         (take 1 targetStrings) -- Drop the exe's args.
+    baseCtx <- withProjectOrGlobalConfig verbosity globalConfigFlag with without
 
+    let
+      scriptOrError script err = do
+        exists <- doesFileExist script
+        if exists
+          then BS.readFile script >>= handleScriptCase verbosity baseCtx tempDir
+          else reportTargetSelectorProblems verbosity err
+        
+    (baseCtx', targetSelectors) <-
+      readTargetSelectors (localPackages baseCtx) (Just ExeKind) (take 1 targetStrings)
+        >>= \case
+          Left err@(TargetSelectorNoTargetsInProject:_)
+            | (script:_) <- targetStrings -> scriptOrError script err
+          Left err@(TargetSelectorNoSuch t _:_)
+            | TargetString1 script <- t   -> scriptOrError script err
+          Left err@(TargetSelectorExpected t _ _:_)
+            | TargetString1 script <- t   -> scriptOrError script err
+          Left err   -> reportTargetSelectorProblems verbosity err
+          Right sels -> return (baseCtx, sels)
+    
     buildCtx <-
-      runProjectPreBuildPhase verbosity baseCtx $ \elaboratedPlan -> do
+      runProjectPreBuildPhase verbosity baseCtx' $ \elaboratedPlan -> do
 
-            when (buildSettingOnlyDeps (buildSettings baseCtx)) $
+            when (buildSettingOnlyDeps (buildSettings baseCtx')) $
               die' verbosity $
                   "The run command does not support '--only-dependencies'. "
                ++ "You may wish to use 'build --only-dependencies' and then "
@@ -134,6 +205,7 @@
                          selectComponentTarget
                          TargetProblemCommon
                          elaboratedPlan
+                         Nothing
                          targetSelectors
 
             -- Reject multiple targets, or at least targets in different
@@ -162,10 +234,10 @@
                        ++ "phase has been reached. This is a bug.")
         $ targetsMap buildCtx
 
-    printPlan verbosity baseCtx buildCtx
+    printPlan verbosity baseCtx' buildCtx
 
-    buildOutcomes <- runProjectBuildPhase verbosity baseCtx buildCtx
-    runProjectPostBuildPhase verbosity baseCtx buildCtx buildOutcomes
+    buildOutcomes <- runProjectBuildPhase verbosity baseCtx' buildCtx
+    runProjectPostBuildPhase verbosity baseCtx' buildCtx buildOutcomes
 
 
     let elaboratedPlan = elaboratedPlanToExecute buildCtx
@@ -214,51 +286,107 @@
       emptyProgramInvocation {
         progInvokePath  = exePath,
         progInvokeArgs  = args,
-        progInvokeEnv   = dataDirsEnvironmentForPlan elaboratedPlan
+        progInvokeEnv   = dataDirsEnvironmentForPlan
+                            (distDirLayout baseCtx)
+                            elaboratedPlan
       }
+    
+    handleDoesNotExist () (removeDirectoryRecursive tempDir)
   where
     verbosity = fromFlagOrDefault normal (configVerbosity configFlags)
     cliConfig = commandLineFlagsToProjectConfig
                   globalFlags configFlags configExFlags
                   installFlags haddockFlags
+    globalConfigFlag = projectConfigConfigFile (projectConfigShared cliConfig)
 
+handleShebang :: String -> IO ()
+handleShebang script =
+  runAction (commandDefaultFlags runCommand) [script] defaultGlobalFlags
 
--- | Construct the environment needed for the data files to work.
--- This consists of a separate @*_datadir@ variable for each
--- inplace package in the plan.
-dataDirsEnvironmentForPlan :: ElaboratedInstallPlan
-                           -> [(String, Maybe FilePath)]
-dataDirsEnvironmentForPlan = catMaybes
-                           . fmap (foldPlanPackage
-                               (const Nothing)
-                               dataDirEnvVarForPackage)
-                           . toList
+parseScriptBlock :: BS.ByteString -> ParseResult Executable
+parseScriptBlock str =
+    case readFields str of
+        Right fs -> do
+            let (fields, _) = takeFields fs
+            parseFieldGrammar cabalSpecLatest fields (executableFieldGrammar "script")
+        Left perr -> parseFatalFailure pos (show perr) where
+            ppos = P.errorPos perr
+            pos  = Position (P.sourceLine ppos) (P.sourceColumn ppos)
 
--- | Construct an environment variable that points
--- the package's datadir to its correct location.
--- This might be:
--- * 'Just' the package's source directory plus the data subdirectory
---   for inplace packages.
--- * 'Nothing' for packages installed in the store (the path was
---   already included in the package at install/build time).
--- * The other cases are not handled yet. See below.
-dataDirEnvVarForPackage :: ElaboratedConfiguredPackage
-                        -> Maybe (String, Maybe FilePath)
-dataDirEnvVarForPackage pkg =
-  case (elabBuildStyle pkg, elabPkgSourceLocation pkg)
-  of (BuildAndInstall, _) -> Nothing
-     (BuildInplaceOnly, LocalUnpackedPackage path) -> Just
-       (pkgPathEnvVar (elabPkgDescription pkg) "datadir",
-        Just $ path </> dataDir (elabPkgDescription pkg))
-     -- TODO: handle the other cases for PackageLocation.
-     -- We will only need this when we add support for
-     -- remote/local tarballs.
-     (BuildInplaceOnly, _) -> Nothing
+readScriptBlock :: Verbosity -> BS.ByteString -> IO Executable
+readScriptBlock verbosity = parseString parseScriptBlock verbosity "script block"
 
+readScriptBlockFromScript :: Verbosity -> BS.ByteString -> IO (Executable, BS.ByteString)
+readScriptBlockFromScript verbosity str = 
+    (\x -> (x, noShebang)) <$> readScriptBlock verbosity str'
+  where
+    start = "{- cabal:"
+    end   = "-}"
+
+    str' = BS.unlines
+          . takeWhile (/= end)
+          . drop 1 . dropWhile (/= start)
+          $ lines'
+    
+    noShebang = BS.unlines 
+              . filter ((/= "#!") . BS.take 2)
+              $ lines'
+
+    lines' = BS.lines str
+
+handleScriptCase :: Verbosity
+                 -> ProjectBaseContext
+                 -> FilePath
+                 -> BS.ByteString
+                 -> IO (ProjectBaseContext, [TargetSelector])
+handleScriptCase verbosity baseCtx tempDir scriptContents = do
+  (executable, contents') <- readScriptBlockFromScript verbosity scriptContents
+  
+  -- We need to create a dummy package that lives in our dummy project.
+  let
+    sourcePackage = SourcePackage
+      { packageInfoId        = pkgId
+      , SP.packageDescription   = genericPackageDescription
+      , packageSource        = LocalUnpackedPackage tempDir
+      , packageDescrOverride = Nothing
+      }
+    genericPackageDescription = emptyGenericPackageDescription 
+      { GPD.packageDescription = packageDescription
+      , condExecutables    = [("script", CondNode executable' targetBuildDepends [])]
+      }
+    executable' = executable
+      { modulePath = "Main.hs"
+      , buildInfo = binfo 
+        { defaultLanguage = 
+          case defaultLanguage of
+            just@(Just _) -> just
+            Nothing       -> Just Haskell2010
+        }
+      }
+    binfo@BuildInfo{..} = buildInfo executable
+    packageDescription = emptyPackageDescription
+      { package = pkgId
+      , specVersionRaw = Left (mkVersion [2, 2])
+      , licenseRaw = Left SPDX.NONE
+      }
+    pkgId = PackageIdentifier "fake-package" version0
+
+  writeGenericPackageDescription (tempDir </> "fake-package.cabal") genericPackageDescription
+  BS.writeFile (tempDir </> "Main.hs") contents'
+
+  let
+    baseCtx' = baseCtx 
+      { localPackages = localPackages baseCtx ++ [SpecificSourcePackage sourcePackage] }
+    targetSelectors = [TargetPackage TargetExplicitNamed [pkgId] Nothing]
+
+  return (baseCtx', targetSelectors)
+
 singleExeOrElse :: IO (UnitId, UnqualComponentName) -> TargetsMap -> IO (UnitId, UnqualComponentName)
 singleExeOrElse action targetsMap =
   case Set.toList . distinctTargetComponents $ targetsMap
   of [(unitId, CExeName component)] -> return (unitId, component)
+     [(unitId, CTestName component)] -> return (unitId, component)
+     [(unitId, CBenchName component)] -> return (unitId, component)
      _   -> action
 
 -- | Filter the 'ElaboratedInstallPlan' keeping only the
@@ -283,7 +411,7 @@
 -- For the @run@ command we select the exe if there is only one and it's
 -- buildable. Fail if there are no or multiple buildable exe components.
 --
-selectPackageTargets :: TargetSelector PackageId
+selectPackageTargets :: TargetSelector
                      -> [AvailableTarget k] -> Either TargetProblem [k]
 selectPackageTargets targetSelector targets
 
@@ -307,33 +435,40 @@
   | otherwise
   = Left (TargetProblemNoTargets targetSelector)
   where
+    -- Targets that can be executed
+    targetsExecutableLike =
+      concatMap (\kind -> filterTargetsKind kind targets)
+                [ExeKind, TestKind, BenchKind]
     (targetsExesBuildable,
-     targetsExesBuildable') = selectBuildableTargets'
-                            . filterTargetsKind ExeKind
-                            $ targets
+     targetsExesBuildable') = selectBuildableTargets' targetsExecutableLike
 
-    targetsExes             = forgetTargetsDetail
-                            . filterTargetsKind ExeKind
-                            $ targets
+    targetsExes             = forgetTargetsDetail targetsExecutableLike
 
 
 -- | For a 'TargetComponent' 'TargetSelector', check if the component can be
 -- selected.
 --
--- For the @run@ command we just need to check it is a executable, in addition
+-- For the @run@ command we just need to check it is a executable-like
+-- (an executable, a test, or a benchmark), in addition
 -- to the basic checks on being buildable etc.
 --
-selectComponentTarget :: PackageId -> ComponentName -> SubComponentTarget
+selectComponentTarget :: SubComponentTarget
                       -> AvailableTarget k -> Either TargetProblem  k
-selectComponentTarget pkgid cname subtarget@WholeComponent t
-  | CExeName _ <- availableTargetComponentName t
-  = either (Left . TargetProblemCommon) return $
-           selectComponentTargetBasic pkgid cname subtarget t
-  | otherwise
-  = Left (TargetProblemComponentNotExe pkgid cname)
+selectComponentTarget subtarget@WholeComponent t
+  = case availableTargetComponentName t
+    of CExeName _ -> component
+       CTestName _ -> component
+       CBenchName _ -> component
+       _ -> Left (TargetProblemComponentNotExe pkgid cname)
+    where pkgid = availableTargetPackageId t
+          cname = availableTargetComponentName t
+          component = either (Left . TargetProblemCommon) return $
+                        selectComponentTargetBasic subtarget t
 
-selectComponentTarget pkgid cname subtarget _
-  = Left (TargetProblemIsSubComponent pkgid cname subtarget)
+selectComponentTarget subtarget t
+  = Left (TargetProblemIsSubComponent (availableTargetPackageId t)
+                                      (availableTargetComponentName t)
+                                       subtarget)
 
 -- | The various error conditions that can occur when matching a
 -- 'TargetSelector' against 'AvailableTarget's for the @run@ command.
@@ -341,16 +476,16 @@
 data TargetProblem =
      TargetProblemCommon       TargetProblemCommon
      -- | The 'TargetSelector' matches targets but none are buildable
-   | TargetProblemNoneEnabled (TargetSelector PackageId) [AvailableTarget ()]
+   | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]
 
      -- | There are no targets at all
-   | TargetProblemNoTargets   (TargetSelector PackageId)
+   | TargetProblemNoTargets   TargetSelector
 
      -- | The 'TargetSelector' matches targets but no executables
-   | TargetProblemNoExes      (TargetSelector PackageId)
+   | TargetProblemNoExes      TargetSelector
 
      -- | A single 'TargetSelector' matches multiple targets
-   | TargetProblemMatchesMultiple (TargetSelector PackageId) [AvailableTarget ()]
+   | TargetProblemMatchesMultiple TargetSelector [AvailableTarget ()]
 
      -- | Multiple 'TargetSelector's match multiple targets
    | TargetProblemMultipleTargets TargetsMap
@@ -392,12 +527,13 @@
 renderTargetProblem (TargetProblemMatchesMultiple targetSelector targets) =
     "The run command is for running a single executable at once. The target '"
  ++ showTargetSelector targetSelector ++ "' refers to "
- ++ renderTargetSelector targetSelector ++ " which includes the executables "
- ++ renderListCommaAnd
-      [ display name
-      | cname@CExeName{} <- map availableTargetComponentName targets
-      , let Just name = componentNameString cname
-      ]
+ ++ renderTargetSelector targetSelector ++ " which includes "
+ ++ renderListCommaAnd ( ("the "++) <$>
+                         showComponentName <$>
+                         availableTargetComponentName <$>
+                         foldMap
+                           (\kind -> filterTargetsKind kind targets)
+                           [ExeKind, TestKind, BenchKind] )
  ++ "."
 
 renderTargetProblem (TargetProblemMultipleTargets selectorMap) =
diff --git a/cabal/cabal-install/Distribution/Client/CmdSdist.hs b/cabal/cabal-install/Distribution/Client/CmdSdist.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/Distribution/Client/CmdSdist.hs
@@ -0,0 +1,362 @@
+{-# LANGUAGE MultiWayIf #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE ViewPatterns #-}
+module Distribution.Client.CmdSdist 
+    ( sdistCommand, sdistAction, packageToSdist
+    , SdistFlags(..), defaultSdistFlags
+    , OutputFormat(..), ArchiveFormat(..) ) where
+
+import Distribution.Client.CmdErrorMessages
+    ( Plural(..), renderComponentKind )
+import Distribution.Client.ProjectOrchestration
+    ( ProjectBaseContext(..), establishProjectBaseContext )
+import Distribution.Client.TargetSelector
+    ( TargetSelector(..), ComponentKind
+    , readTargetSelectors, reportTargetSelectorProblems )
+import Distribution.Client.RebuildMonad
+    ( runRebuild )
+import Distribution.Client.Setup
+    ( ArchiveFormat(..), GlobalFlags(..) )
+import Distribution.Solver.Types.SourcePackage
+    ( SourcePackage(..) )
+import Distribution.Client.Types
+    ( PackageSpecifier(..), PackageLocation(..), UnresolvedSourcePackage )
+import Distribution.Client.DistDirLayout
+    ( DistDirLayout(..), defaultDistDirLayout )
+import Distribution.Client.ProjectConfig
+    ( findProjectRoot, readProjectConfig )
+
+import Distribution.Compat.Semigroup
+    ((<>))
+
+import Distribution.Package
+    ( Package(packageId) )
+import Distribution.PackageDescription.Configuration
+    ( flattenPackageDescription )
+import Distribution.Pretty
+    ( prettyShow )
+import Distribution.ReadE
+    ( succeedReadE )
+import Distribution.Simple.Command
+    ( CommandUI(..), option, choiceOpt, reqArg )
+import Distribution.Simple.PreProcess
+    ( knownSuffixHandlers )
+import Distribution.Simple.Setup
+    ( Flag(..), toFlag, fromFlagOrDefault, flagToList, flagToMaybe
+    , optionVerbosity, optionDistPref, trueArg
+    )
+import Distribution.Simple.SrcDist
+    ( listPackageSources )
+import Distribution.Simple.Utils
+    ( die', notice, withOutputMarker )
+import Distribution.Types.ComponentName
+    ( ComponentName, showComponentName )
+import Distribution.Types.PackageName
+    ( PackageName, unPackageName )
+import Distribution.Verbosity
+    ( Verbosity, normal )
+
+import qualified Codec.Archive.Tar       as Tar
+import qualified Codec.Archive.Tar.Entry as Tar
+import qualified Codec.Archive.Zip       as Zip
+import qualified Codec.Compression.GZip  as GZip
+import Control.Exception
+    ( throwIO )
+import Control.Monad
+    ( when, forM, forM_ )
+import Control.Monad.Trans
+    ( liftIO )
+import Control.Monad.State.Lazy
+    ( StateT, modify, gets, evalStateT )
+import Control.Monad.Writer.Lazy
+    ( WriterT, tell, execWriterT )
+import Data.Bits
+    ( shiftL )
+import qualified Data.ByteString.Char8      as BS
+import qualified Data.ByteString.Lazy.Char8 as BSL
+import Data.Either
+    ( partitionEithers )
+import Data.List
+    ( find, sortOn, nub, intercalate )
+import qualified Data.Set as Set
+import System.Directory
+    ( getCurrentDirectory, setCurrentDirectory
+    , createDirectoryIfMissing, makeAbsolute )
+import System.FilePath
+    ( (</>), (<.>), makeRelative, normalise, takeDirectory )
+
+sdistCommand :: CommandUI SdistFlags
+sdistCommand = CommandUI
+    { commandName = "new-sdist"
+    , commandSynopsis = "Generate a source distribution file (.tar.gz)."
+    , commandUsage = \pname ->
+        "Usage: " ++ pname ++ " new-sdist [FLAGS] [PACKAGES]\n"
+    , commandDescription  = Just $ \_ ->
+        "Generates tarballs of project packages suitable for upload to Hackage."
+    , commandNotes = Nothing
+    , commandDefaultFlags = defaultSdistFlags
+    , commandOptions = \showOrParseArgs ->
+        [ optionVerbosity
+            sdistVerbosity (\v flags -> flags { sdistVerbosity = v })
+        , optionDistPref
+            sdistDistDir (\dd flags -> flags { sdistDistDir = dd })
+            showOrParseArgs
+        , option [] ["project-file"]
+            "Set the name of the cabal.project file to search for in parent directories"
+            sdistProjectFile (\pf flags -> flags { sdistProjectFile = pf })
+            (reqArg "FILE" (succeedReadE Flag) flagToList)
+        , option ['l'] ["list-only"]
+            "Just list the sources, do not make a tarball"
+            sdistListSources (\v flags -> flags { sdistListSources = v })
+            trueArg
+        , option ['z'] ["null-sep"]
+            "Separate the source files with NUL bytes rather than newlines."
+            sdistNulSeparated (\v flags -> flags { sdistNulSeparated = v })
+            trueArg
+        , option [] ["archive-format"] 
+            "Choose what type of archive to create. No effect if given with '--list-only'"
+                sdistArchiveFormat (\v flags -> flags { sdistArchiveFormat = v })
+            (choiceOpt
+                [ (Flag TargzFormat, ([], ["targz"]),
+                        "Produce a '.tar.gz' format archive (default and required for uploading to hackage)")
+                , (Flag ZipFormat,   ([], ["zip"]),
+                        "Produce a '.zip' format archive")
+                ]
+            )
+        , option ['o'] ["output-dir", "outputdir"]
+            "Choose the output directory of this command. '-' sends all output to stdout"
+            sdistOutputPath (\o flags -> flags { sdistOutputPath = o })
+            (reqArg "PATH" (succeedReadE Flag) flagToList)
+        ]
+    }
+
+data SdistFlags = SdistFlags
+    { sdistVerbosity     :: Flag Verbosity
+    , sdistDistDir       :: Flag FilePath
+    , sdistProjectFile   :: Flag FilePath
+    , sdistListSources   :: Flag Bool
+    , sdistNulSeparated  :: Flag Bool
+    , sdistArchiveFormat :: Flag ArchiveFormat
+    , sdistOutputPath    :: Flag FilePath
+    }
+
+defaultSdistFlags :: SdistFlags
+defaultSdistFlags = SdistFlags
+    { sdistVerbosity     = toFlag normal
+    , sdistDistDir       = mempty
+    , sdistProjectFile   = mempty
+    , sdistListSources   = toFlag False
+    , sdistNulSeparated  = toFlag False
+    , sdistArchiveFormat = toFlag TargzFormat
+    , sdistOutputPath    = mempty
+    }
+
+--
+
+sdistAction :: SdistFlags -> [String] -> GlobalFlags -> IO ()
+sdistAction SdistFlags{..} targetStrings globalFlags = do
+    let verbosity = fromFlagOrDefault normal sdistVerbosity
+        mDistDirectory = flagToMaybe sdistDistDir
+        mProjectFile = flagToMaybe sdistProjectFile
+        globalConfig = globalConfigFile globalFlags
+        listSources = fromFlagOrDefault False sdistListSources
+        nulSeparated = fromFlagOrDefault False sdistNulSeparated
+        archiveFormat = fromFlagOrDefault TargzFormat sdistArchiveFormat
+        mOutputPath = flagToMaybe sdistOutputPath
+  
+    projectRoot <- either throwIO return =<< findProjectRoot Nothing mProjectFile
+    let distLayout = defaultDistDirLayout projectRoot mDistDirectory
+    dir <- getCurrentDirectory
+    projectConfig <- runRebuild dir $ readProjectConfig verbosity globalConfig distLayout
+    baseCtx <- establishProjectBaseContext verbosity projectConfig
+    let localPkgs = localPackages baseCtx
+
+    targetSelectors <- either (reportTargetSelectorProblems verbosity) return
+        =<< readTargetSelectors localPkgs Nothing targetStrings
+    
+    mOutputPath' <- case mOutputPath of
+        Just "-"  -> return (Just "-")
+        Just path -> Just <$> makeAbsolute path
+        Nothing   -> return Nothing
+    
+    let 
+        format =
+            if | listSources, nulSeparated -> SourceList '\0'
+               | listSources               -> SourceList '\n'
+               | otherwise                 -> Archive archiveFormat
+
+        ext = case format of
+                SourceList _        -> "list"
+                Archive TargzFormat -> "tar.gz"
+                Archive ZipFormat   -> "zip"
+    
+        outputPath pkg = case mOutputPath' of
+            Just path
+                | path == "-" -> "-"
+                | otherwise   -> path </> prettyShow (packageId pkg) <.> ext
+            Nothing
+                | listSources -> "-"
+                | otherwise   -> distSdistFile distLayout (packageId pkg) archiveFormat
+
+    createDirectoryIfMissing True (distSdistDirectory distLayout)
+    
+    case reifyTargetSelectors localPkgs targetSelectors of
+        Left errs -> die' verbosity . unlines . fmap renderTargetProblem $ errs
+        Right pkgs 
+            | length pkgs > 1, not listSources, Just "-" <- mOutputPath' -> 
+                die' verbosity "Can't write multiple tarballs to standard output!"
+            | otherwise ->
+                mapM_ (\pkg -> packageToSdist verbosity (distProjectRootDirectory distLayout) format (outputPath pkg) pkg) pkgs
+
+data IsExec = Exec | NoExec
+            deriving (Show, Eq)
+
+data OutputFormat = SourceList Char
+                  | Archive ArchiveFormat
+                  deriving (Show, Eq)
+
+packageToSdist :: Verbosity -> FilePath -> OutputFormat -> FilePath -> UnresolvedSourcePackage -> IO ()
+packageToSdist verbosity projectRootDir format outputFile pkg = do
+    let death = die' verbosity ("The impossible happened: a local package isn't local" <> (show pkg))
+    dir0 <- case packageSource pkg of
+             LocalUnpackedPackage path             -> pure (Right path)
+             RemoteSourceRepoPackage _ (Just path) -> pure (Right path)
+             RemoteSourceRepoPackage {}            -> death
+             LocalTarballPackage tgz               -> pure (Left tgz)
+             RemoteTarballPackage _ (Just tgz)     -> pure (Left tgz)
+             RemoteTarballPackage {}               -> death
+             RepoTarballPackage {}                 -> death
+
+    let write = if outputFile == "-"
+          then putStr . withOutputMarker verbosity . BSL.unpack
+          else BSL.writeFile outputFile
+
+    case dir0 of
+      Left tgz -> do
+        case format of
+          Archive TargzFormat -> do
+            write =<< BSL.readFile tgz
+            when (outputFile /= "-") $
+                notice verbosity $ "Wrote tarball sdist to " ++ outputFile ++ "\n"
+          _ -> die' verbosity ("cannot convert tarball package to " ++ show format)
+
+      Right dir -> do
+        oldPwd <- getCurrentDirectory
+        setCurrentDirectory dir
+
+        let norm flag = fmap ((flag, ) . normalise)
+        (norm NoExec -> nonexec, norm Exec -> exec) <-
+           listPackageSources verbosity (flattenPackageDescription $ packageDescription pkg) knownSuffixHandlers
+
+        let files =  nub . sortOn snd $ nonexec ++ exec
+
+        case format of
+            SourceList nulSep -> do
+                let prefix = makeRelative projectRootDir dir
+                write (BSL.pack . (++ [nulSep]) . intercalate [nulSep] . fmap ((prefix </>) . snd) $ files)
+                when (outputFile /= "-") $
+                    notice verbosity $ "Wrote source list to " ++ outputFile ++ "\n"
+            Archive TargzFormat -> do
+                let entriesM :: StateT (Set.Set FilePath) (WriterT [Tar.Entry] IO) ()
+                    entriesM = do
+                        let prefix = prettyShow (packageId pkg)
+                        modify (Set.insert prefix)
+                        case Tar.toTarPath True prefix of
+                            Left err -> liftIO $ die' verbosity ("Error packing sdist: " ++ err)
+                            Right path -> tell [Tar.directoryEntry path]
+
+                        forM_ files $ \(perm, file) -> do
+                            let fileDir = takeDirectory (prefix </> file)
+                                perm' = case perm of
+                                    Exec -> Tar.executableFilePermissions
+                                    NoExec -> Tar.ordinaryFilePermissions
+                            needsEntry <- gets (Set.notMember fileDir)
+
+                            when needsEntry $ do
+                                modify (Set.insert fileDir)
+                                case Tar.toTarPath True fileDir of
+                                    Left err -> liftIO $ die' verbosity ("Error packing sdist: " ++ err)
+                                    Right path -> tell [Tar.directoryEntry path]
+
+                            contents <- liftIO . fmap BSL.fromStrict . BS.readFile $ file
+                            case Tar.toTarPath False (prefix </> file) of
+                                Left err -> liftIO $ die' verbosity ("Error packing sdist: " ++ err)
+                                Right path -> tell [(Tar.fileEntry path contents) { Tar.entryPermissions = perm' }]
+
+                entries <- execWriterT (evalStateT entriesM mempty)
+                let -- Pretend our GZip file is made on Unix.
+                    normalize bs = BSL.concat [first, "\x03", rest']
+                        where
+                            (first, rest) = BSL.splitAt 9 bs
+                            rest' = BSL.tail rest
+                    -- The Unix epoch, which is the default value, is
+                    -- unsuitable because it causes unpacking problems on
+                    -- Windows; we need a post-1980 date. One gigasecond
+                    -- after the epoch is during 2001-09-09, so that does
+                    -- nicely. See #5596.
+                    setModTime entry = entry { Tar.entryTime = 1000000000 }
+                write . normalize . GZip.compress . Tar.write $ fmap setModTime entries
+                when (outputFile /= "-") $
+                    notice verbosity $ "Wrote tarball sdist to " ++ outputFile ++ "\n"
+            Archive ZipFormat -> do
+                let prefix = prettyShow (packageId pkg)
+                entries <- forM files $ \(perm, file) -> do
+                    let perm' = case perm of
+                            -- -rwxr-xr-x
+                            Exec   -> 0o010755 `shiftL` 16
+                            -- -rw-r--r--
+                            NoExec -> 0o010644 `shiftL` 16
+                    contents <- BSL.readFile file
+                    return $ (Zip.toEntry (prefix </> file) 0 contents) { Zip.eExternalFileAttributes = perm' }
+                let archive = foldr Zip.addEntryToArchive Zip.emptyArchive entries
+                write (Zip.fromArchive archive)
+                when (outputFile /= "-") $
+                    notice verbosity $ "Wrote zip sdist to " ++ outputFile ++ "\n"
+        setCurrentDirectory oldPwd
+
+--
+
+reifyTargetSelectors :: [PackageSpecifier UnresolvedSourcePackage] -> [TargetSelector] -> Either [TargetProblem] [UnresolvedSourcePackage]
+reifyTargetSelectors pkgs sels = 
+    case partitionEithers (foldMap go sels) of
+        ([], sels') -> Right sels'
+        (errs, _)   -> Left errs
+    where
+        flatten (SpecificSourcePackage pkg@SourcePackage{}) = pkg
+        flatten _ = error "The impossible happened: how do we not know about a local package?"
+        pkgs' = fmap flatten pkgs
+
+        getPkg pid = case find ((== pid) . packageId) pkgs' of
+            Just pkg -> Right pkg
+            Nothing -> error "The impossible happened: we have a reference to a local package that isn't in localPackages."
+        
+        go :: TargetSelector -> [Either TargetProblem UnresolvedSourcePackage]
+        go (TargetPackage _ pids Nothing) = fmap getPkg pids
+        go (TargetAllPackages Nothing) = Right <$> pkgs'
+
+        go (TargetPackage _ _ (Just kind)) = [Left (AllComponentsOnly kind)]
+        go (TargetAllPackages (Just kind)) = [Left (AllComponentsOnly kind)]
+
+        go (TargetPackageNamed pname _) = [Left (NonlocalPackageNotAllowed pname)]
+        go (TargetComponentUnknown pname _ _) = [Left (NonlocalPackageNotAllowed pname)]
+
+        go (TargetComponent _ cname _) = [Left (ComponentsNotAllowed cname)]
+
+data TargetProblem = AllComponentsOnly ComponentKind
+                   | NonlocalPackageNotAllowed PackageName
+                   | ComponentsNotAllowed ComponentName
+
+renderTargetProblem :: TargetProblem -> String
+renderTargetProblem (AllComponentsOnly kind) =
+    "It is not possible to package only the " ++ renderComponentKind Plural kind ++ " from a package "
+    ++ "for distribution. Only entire packages may be packaged for distribution."
+renderTargetProblem (ComponentsNotAllowed cname) =
+    "The component " ++ showComponentName cname ++ " cannot be packaged for distribution on its own. "
+    ++ "Only entire packages may be packaged for distribution."
+renderTargetProblem (NonlocalPackageNotAllowed pname) =
+    "The package " ++ unPackageName pname ++ " cannot be packaged for distribution, because it is not "
+    ++ "local to this project."
+
diff --git a/cabal/cabal-install/Distribution/Client/CmdTest.hs b/cabal/cabal-install/Distribution/Client/CmdTest.hs
--- a/cabal/cabal-install/Distribution/Client/CmdTest.hs
+++ b/cabal/cabal-install/Distribution/Client/CmdTest.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE ViewPatterns   #-}
 
 -- | cabal-install CLI command: test
 --
@@ -18,8 +17,7 @@
 import Distribution.Client.CmdErrorMessages
 
 import Distribution.Client.Setup
-         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags
-         , applyFlagDefaults )
+         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags )
 import qualified Distribution.Client.Setup as Client
 import Distribution.Simple.Setup
          ( HaddockFlags, fromFlagOrDefault )
@@ -52,7 +50,10 @@
      ++ "Dependencies are built or rebuilt as necessary. Additional "
      ++ "configuration flags can be specified on the command line and these "
      ++ "extend the project configuration from the 'cabal.project', "
-     ++ "'cabal.project.local' and other files.",
+     ++ "'cabal.project.local' and other files.\n\n"
+
+     ++ "To pass command-line arguments to a test suite, see the "
+     ++ "new-run command.",
   commandNotes        = Just $ \pname ->
         "Examples:\n"
      ++ "  " ++ pname ++ " new-test\n"
@@ -80,13 +81,13 @@
 --
 testAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
            -> [String] -> GlobalFlags -> IO ()
-testAction (applyFlagDefaults -> (configFlags, configExFlags, installFlags, haddockFlags))
+testAction (configFlags, configExFlags, installFlags, haddockFlags)
            targetStrings globalFlags = do
 
     baseCtx <- establishProjectBaseContext verbosity cliConfig
 
     targetSelectors <- either (reportTargetSelectorProblems verbosity) return
-                   =<< readTargetSelectors (localPackages baseCtx) targetStrings
+                   =<< readTargetSelectors (localPackages baseCtx) (Just TestKind) targetStrings
 
     buildCtx <-
       runProjectPreBuildPhase verbosity baseCtx $ \elaboratedPlan -> do
@@ -105,6 +106,7 @@
                          selectComponentTarget
                          TargetProblemCommon
                          elaboratedPlan
+                         Nothing
                          targetSelectors
 
             let elaboratedPlan' = pruneInstallPlanToTargets
@@ -130,7 +132,7 @@
 -- For the @test@ command we select all buildable test-suites,
 -- or fail if there are no test-suites or no buildable test-suites.
 --
-selectPackageTargets  :: TargetSelector PackageId
+selectPackageTargets  :: TargetSelector
                       -> [AvailableTarget k] -> Either TargetProblem [k]
 selectPackageTargets targetSelector targets
 
@@ -165,17 +167,20 @@
 -- For the @test@ command we just need to check it is a test-suite, in addition
 -- to the basic checks on being buildable etc.
 --
-selectComponentTarget :: PackageId -> ComponentName -> SubComponentTarget
+selectComponentTarget :: SubComponentTarget
                       -> AvailableTarget k -> Either TargetProblem k
-selectComponentTarget pkgid cname subtarget@WholeComponent t
+selectComponentTarget subtarget@WholeComponent t
   | CTestName _ <- availableTargetComponentName t
   = either (Left . TargetProblemCommon) return $
-           selectComponentTargetBasic pkgid cname subtarget t
+           selectComponentTargetBasic subtarget t
   | otherwise
-  = Left (TargetProblemComponentNotTest pkgid cname)
+  = Left (TargetProblemComponentNotTest (availableTargetPackageId t)
+                                        (availableTargetComponentName t))
 
-selectComponentTarget pkgid cname subtarget _
-  = Left (TargetProblemIsSubComponent pkgid cname subtarget)
+selectComponentTarget subtarget t
+  = Left (TargetProblemIsSubComponent (availableTargetPackageId t)
+                                      (availableTargetComponentName t)
+                                       subtarget)
 
 -- | The various error conditions that can occur when matching a
 -- 'TargetSelector' against 'AvailableTarget's for the @test@ command.
@@ -184,13 +189,13 @@
      TargetProblemCommon       TargetProblemCommon
 
      -- | The 'TargetSelector' matches targets but none are buildable
-   | TargetProblemNoneEnabled (TargetSelector PackageId) [AvailableTarget ()]
+   | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]
 
      -- | There are no targets at all
-   | TargetProblemNoTargets   (TargetSelector PackageId)
+   | TargetProblemNoTargets   TargetSelector
 
      -- | The 'TargetSelector' matches targets but no test-suites
-   | TargetProblemNoTests     (TargetSelector PackageId)
+   | TargetProblemNoTests     TargetSelector
 
      -- | The 'TargetSelector' refers to a component that is not a test-suite
    | TargetProblemComponentNotTest PackageId ComponentName
diff --git a/cabal/cabal-install/Distribution/Client/CmdUpdate.hs b/cabal/cabal-install/Distribution/Client/CmdUpdate.hs
--- a/cabal/cabal-install/Distribution/Client/CmdUpdate.hs
+++ b/cabal/cabal-install/Distribution/Client/CmdUpdate.hs
@@ -1,4 +1,5 @@
-{-# LANGUAGE CPP, NamedFieldPuns, RecordWildCards, ViewPatterns, TupleSections #-}
+{-# LANGUAGE CPP, LambdaCase, NamedFieldPuns, RecordWildCards, ViewPatterns,
+             TupleSections #-}
 
 -- | cabal-install CLI command: update
 --
@@ -7,10 +8,17 @@
     updateAction,
   ) where
 
+import Prelude ()
+import Distribution.Client.Compat.Prelude    
+
+import Distribution.Client.Compat.Directory
+         ( setModificationTime )
 import Distribution.Client.ProjectOrchestration
 import Distribution.Client.ProjectConfig
          ( ProjectConfig(..)
-         , projectConfigWithSolverRepoContext )
+         , ProjectConfigShared(projectConfigConfigFile)
+         , projectConfigWithSolverRepoContext
+         , withProjectOrGlobalConfig )
 import Distribution.Client.Types
          ( Repo(..), RemoteRepo(..), isRepoRemote )
 import Distribution.Client.HttpUtils
@@ -20,29 +28,30 @@
 import Distribution.Client.JobControl
          ( newParallelJobControl, spawnJob, collectJob )
 import Distribution.Client.Setup
-         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags, UpdateFlags
-         , applyFlagDefaults, defaultUpdateFlags, RepoContext(..) )
+         ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags
+         , UpdateFlags, defaultUpdateFlags
+         , RepoContext(..) )
 import Distribution.Simple.Setup
          ( HaddockFlags, fromFlagOrDefault )
 import Distribution.Simple.Utils
-         ( die', notice, wrapText, writeFileAtomic, noticeNoWrap, intercalate )
+         ( die', notice, wrapText, writeFileAtomic, noticeNoWrap )
 import Distribution.Verbosity
          ( Verbosity, normal, lessVerbose )
 import Distribution.Client.IndexUtils.Timestamp
 import Distribution.Client.IndexUtils
          ( updateRepoIndexCache, Index(..), writeIndexTimestamp
-         , currentIndexTimestamp )
+         , currentIndexTimestamp, indexBaseName )
 import Distribution.Text
          ( Text(..), display, simpleParse )
 
 import Data.Maybe (fromJust)
 import qualified Distribution.Compat.ReadP  as ReadP
-import qualified Text.PrettyPrint          as Disp
+import qualified Text.PrettyPrint           as Disp
 
-import Control.Monad (unless, when)
+import Control.Monad (mapM, mapM_)
 import qualified Data.ByteString.Lazy       as BS
 import Distribution.Client.GZipUtils (maybeDecompress)
-import System.FilePath (dropExtension)
+import System.FilePath ((<.>), dropExtension)
 import Data.Time (getCurrentTime)
 import Distribution.Simple.Command
          ( CommandUI(..), usageAlternatives )
@@ -50,7 +59,8 @@
 
 import qualified Hackage.Security.Client as Sec
 
-updateCommand :: CommandUI (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
+updateCommand :: CommandUI ( ConfigFlags, ConfigExFlags
+                           , InstallFlags, HaddockFlags )
 updateCommand = Client.installCommand {
   commandName         = "new-update",
   commandSynopsis     = "Updates list of known packages.",
@@ -102,21 +112,22 @@
 
 updateAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
              -> [String] -> GlobalFlags -> IO ()
-updateAction (applyFlagDefaults -> (configFlags, configExFlags, installFlags, haddockFlags))
+updateAction (configFlags, configExFlags, installFlags, haddockFlags)
              extraArgs globalFlags = do
-
-  ProjectBaseContext {
-    projectConfig
-  } <- establishProjectBaseContext verbosity cliConfig
+  projectConfig <- withProjectOrGlobalConfig verbosity globalConfigFlag
+    (projectConfig <$> establishProjectBaseContext verbosity cliConfig)
+    (\globalConfig -> return $ globalConfig <> cliConfig)
 
-  projectConfigWithSolverRepoContext verbosity (projectConfigShared projectConfig) (projectConfigBuildOnly projectConfig)
+  projectConfigWithSolverRepoContext verbosity
+    (projectConfigShared projectConfig) (projectConfigBuildOnly projectConfig)
     $ \repoCtxt -> do
     let repos       = filter isRepoRemote $ repoContextRepos repoCtxt
         repoName    = remoteRepoName . repoRemote
         parseArg :: String -> IO UpdateRequest
         parseArg s = case simpleParse s of
           Just r -> return r
-          Nothing -> die' verbosity $ "'new-update' unable to parse repo: \"" ++ s ++ "\""
+          Nothing -> die' verbosity $
+                     "'new-update' unable to parse repo: \"" ++ s ++ "\""
     updateRepoRequests <- mapM parseArg extraArgs
 
     unless (null updateRepoRequests) $ do
@@ -124,17 +135,20 @@
           unknownRepos = [r | (UpdateRequest r _) <- updateRepoRequests
                             , not (r `elem` remoteRepoNames)]
       unless (null unknownRepos) $
-        die' verbosity $ "'new-update' repo(s): \"" ++ intercalate "\", \"" unknownRepos
-                      ++ "\" can not be found in known remote repo(s): " ++ intercalate ", " remoteRepoNames
+        die' verbosity $ "'new-update' repo(s): \""
+                         ++ intercalate "\", \"" unknownRepos
+                         ++ "\" can not be found in known remote repo(s): "
+                         ++ intercalate ", " remoteRepoNames
 
     let reposToUpdate :: [(Repo, IndexState)]
         reposToUpdate = case updateRepoRequests of
-          -- if we are not given any speicifc repository. Update all repositories to
-          -- HEAD.
+          -- If we are not given any specific repository, update all
+          -- repositories to HEAD.
           [] -> map (,IndexStateHead) repos
           updateRequests -> let repoMap = [(repoName r, r) | r <- repos]
                                 lookup' k = fromJust (lookup k repoMap)
-                            in [(lookup' name, state) | (UpdateRequest name state) <- updateRequests]
+                            in [ (lookup' name, state)
+                               | (UpdateRequest name state) <- updateRequests ]
 
     case reposToUpdate of
       [] -> return ()
@@ -146,7 +160,8 @@
               : map (("- " ++) . repoName . fst) reposToUpdate
 
     jobCtrl <- newParallelJobControl (length reposToUpdate)
-    mapM_ (spawnJob jobCtrl . updateRepo verbosity defaultUpdateFlags repoCtxt) reposToUpdate
+    mapM_ (spawnJob jobCtrl . updateRepo verbosity defaultUpdateFlags repoCtxt)
+      reposToUpdate
     mapM_ (\_ -> collectJob jobCtrl) reposToUpdate
 
   where
@@ -154,16 +169,21 @@
     cliConfig = commandLineFlagsToProjectConfig
                   globalFlags configFlags configExFlags
                   installFlags haddockFlags
+    globalConfigFlag = projectConfigConfigFile (projectConfigShared cliConfig)
 
-updateRepo :: Verbosity -> UpdateFlags -> RepoContext -> (Repo, IndexState) -> IO ()
+updateRepo :: Verbosity -> UpdateFlags -> RepoContext -> (Repo, IndexState)
+           -> IO ()
 updateRepo verbosity _updateFlags repoCtxt (repo, indexState) = do
   transport <- repoContextGetTransport repoCtxt
   case repo of
     RepoLocal{..} -> return ()
     RepoRemote{..} -> do
-      downloadResult <- downloadIndex transport verbosity repoRemote repoLocalDir
+      downloadResult <- downloadIndex transport verbosity
+                        repoRemote repoLocalDir
       case downloadResult of
-        FileAlreadyInCache -> return ()
+        FileAlreadyInCache ->
+          setModificationTime (indexBaseName repo <.> "tar")
+          =<< getCurrentTime
         FileDownloaded indexPath -> do
           writeFileAtomic (dropExtension indexPath) . maybeDecompress
                                                   =<< BS.readFile indexPath
@@ -183,7 +203,8 @@
       -- (If all access to the cache goes through hackage-security this can go)
       case updated of
         Sec.NoUpdates  ->
-          return ()
+          setModificationTime (indexBaseName repo <.> "tar")
+          =<< getCurrentTime
         Sec.HasUpdates ->
           updateRepoIndexCache verbosity index
       -- TODO: This will print multiple times if there are multiple
@@ -192,5 +213,5 @@
       when (current_ts /= nullTimestamp) $
         noticeNoWrap verbosity $
           "To revert to previous state run:\n" ++
-          "    cabal new-update '" ++ remoteRepoName (repoRemote repo) ++ "," ++ display current_ts ++ "'\n"
- 
+          "    cabal new-update '" ++ remoteRepoName (repoRemote repo)
+          ++ "," ++ display current_ts ++ "'\n"
diff --git a/cabal/cabal-install/Distribution/Client/Compat/Directory.hs b/cabal/cabal-install/Distribution/Client/Compat/Directory.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/Distribution/Client/Compat/Directory.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE CPP #-}
+module Distribution.Client.Compat.Directory (setModificationTime) where
+
+#if MIN_VERSION_directory(1,2,3)
+import System.Directory (setModificationTime)
+#else
+
+import Data.Time.Clock (UTCTime)
+
+setModificationTime :: FilePath -> UTCTime -> IO ()
+setModificationTime _fp _t = return ()
+
+#endif
diff --git a/cabal/cabal-install/Distribution/Client/Compat/ExecutablePath.hs b/cabal/cabal-install/Distribution/Client/Compat/ExecutablePath.hs
--- a/cabal/cabal-install/Distribution/Client/Compat/ExecutablePath.hs
+++ b/cabal/cabal-install/Distribution/Client/Compat/ExecutablePath.hs
@@ -35,25 +35,6 @@
 import System.Posix.Internals
 #endif
 
--- GHC 7.0.* compatibility. 'System.Posix.Internals' in base-4.3.* doesn't
--- provide 'peekFilePath' and 'peekFilePathLen'.
-#if !MIN_VERSION_base(4,4,0)
-#ifdef mingw32_HOST_OS
-
-peekFilePath :: CWString -> IO FilePath
-peekFilePath = peekCWString
-
-#else
-
-peekFilePath :: CString -> IO FilePath
-peekFilePath = peekCString
-
-peekFilePathLen :: CStringLen -> IO FilePath
-peekFilePathLen = peekCStringLen
-
-#endif
-#endif
-
 -- The exported function is defined outside any if-guard to make sure
 -- every OS implements it with the same type.
 
diff --git a/cabal/cabal-install/Distribution/Client/Compat/Prelude.hs b/cabal/cabal-install/Distribution/Client/Compat/Prelude.hs
--- a/cabal/cabal-install/Distribution/Client/Compat/Prelude.hs
+++ b/cabal/cabal-install/Distribution/Client/Compat/Prelude.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE CPP #-}
-
 -- to suppress WARNING in "Distribution.Compat.Prelude.Internal"
 {-# OPTIONS_GHC -fno-warn-deprecations #-}
 
@@ -20,16 +18,5 @@
 
 import Prelude (IO)
 import Distribution.Compat.Prelude.Internal hiding (IO)
-
-#if MIN_VERSION_base(4,6,0)
 import Text.Read
          ( readMaybe )
-#endif
-
-#if !MIN_VERSION_base(4,6,0)
--- | An implementation of readMaybe, for compatibility with older base versions.
-readMaybe :: Read a => String -> Maybe a
-readMaybe s = case reads s of
-                [(x,"")] -> Just x
-                _        -> Nothing
-#endif
diff --git a/cabal/cabal-install/Distribution/Client/Compat/Process.hs b/cabal/cabal-install/Distribution/Client/Compat/Process.hs
--- a/cabal/cabal-install/Distribution/Client/Compat/Process.hs
+++ b/cabal/cabal-install/Distribution/Client/Compat/Process.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE CPP #-}
-
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Distribution.Client.Compat.Process
@@ -17,10 +15,6 @@
 module Distribution.Client.Compat.Process (
   readProcessWithExitCode
 ) where
-
-#if !MIN_VERSION_base(4,6,0)
-import           Prelude           hiding (catch)
-#endif
 
 import           Control.Exception (catch, throw)
 import           System.Exit       (ExitCode (ExitFailure))
diff --git a/cabal/cabal-install/Distribution/Client/Config.hs b/cabal/cabal-install/Distribution/Client/Config.hs
--- a/cabal/cabal-install/Distribution/Client/Config.hs
+++ b/cabal/cabal-install/Distribution/Client/Config.hs
@@ -24,7 +24,7 @@
     showConfigWithComments,
     parseConfig,
 
-    defaultCabalDir,
+    getCabalDir,
     defaultConfigFile,
     defaultCacheDir,
     defaultCompiler,
@@ -126,7 +126,7 @@
 import System.IO.Error
          ( isDoesNotExistError )
 import Distribution.Compat.Environment
-         ( getEnvironment )
+         ( getEnvironment, lookupEnv )
 import Distribution.Compat.Exception
          ( catchIO )
 import qualified Paths_cabal_install
@@ -236,7 +236,8 @@
         globalIgnoreExpiry      = combine globalIgnoreExpiry,
         globalHttpTransport     = combine globalHttpTransport,
         globalNix               = combine globalNix,
-        globalStoreDir          = combine globalStoreDir
+        globalStoreDir          = combine globalStoreDir,
+        globalProgPathExtra     = lastNonEmptyNL globalProgPathExtra
         }
         where
           combine        = combine'        savedGlobalFlags
@@ -246,6 +247,7 @@
         installDocumentation         = combine installDocumentation,
         installHaddockIndex          = combine installHaddockIndex,
         installDryRun                = combine installDryRun,
+        installDest                  = combine installDest,
         installMaxBackjumps          = combine installMaxBackjumps,
         installReorderGoals          = combine installReorderGoals,
         installCountConflicts        = combine installCountConflicts,
@@ -359,7 +361,9 @@
         configPreferences   = lastNonEmpty configPreferences,
         configSolver        = combine configSolver,
         configAllowNewer    = combineMonoid savedConfigureExFlags configAllowNewer,
-        configAllowOlder    = combineMonoid savedConfigureExFlags configAllowOlder
+        configAllowOlder    = combineMonoid savedConfigureExFlags configAllowOlder,
+        configWriteGhcEnvironmentFilesPolicy
+                            = combine configWriteGhcEnvironmentFilesPolicy
         }
         where
           combine      = combine' savedConfigureExFlags
@@ -407,12 +411,15 @@
         haddockForeignLibs   = combine haddockForeignLibs,
         haddockInternal      = combine haddockInternal,
         haddockCss           = combine haddockCss,
-        haddockHscolour      = combine haddockHscolour,
+        haddockLinkedSource  = combine haddockLinkedSource,
+        haddockQuickJump     = combine haddockQuickJump,
         haddockHscolourCss   = combine haddockHscolourCss,
         haddockContents      = combine haddockContents,
         haddockDistPref      = combine haddockDistPref,
         haddockKeepTempFiles = combine haddockKeepTempFiles,
-        haddockVerbosity     = combine haddockVerbosity
+        haddockVerbosity     = combine haddockVerbosity,
+        haddockCabalFilePath = combine haddockCabalFilePath,
+        haddockArgs          = lastNonEmpty haddockArgs
         }
         where
           combine      = combine'        savedHaddockFlags
@@ -430,7 +437,7 @@
 --
 baseSavedConfig :: IO SavedConfig
 baseSavedConfig = do
-  userPrefix <- defaultCabalDir
+  userPrefix <- getCabalDir
   cacheDir   <- defaultCacheDir
   logsDir    <- defaultLogsDir
   worldFile  <- defaultWorldFile
@@ -462,6 +469,7 @@
   logsDir    <- defaultLogsDir
   worldFile  <- defaultWorldFile
   extraPath  <- defaultExtraPath
+  symlinkPath <- defaultSymlinkPath
   return mempty {
     savedGlobalFlags     = mempty {
       globalCacheDir     = toFlag cacheDir,
@@ -474,41 +482,52 @@
     savedInstallFlags    = mempty {
       installSummaryFile = toNubList [toPathTemplate (logsDir </> "build.log")],
       installBuildReports= toFlag AnonymousReports,
-      installNumJobs     = toFlag Nothing
+      installNumJobs     = toFlag Nothing,
+      installSymlinkBinDir = toFlag symlinkPath
     }
   }
 
---TODO: misleading, there's no way to override this default
---      either make it possible or rename to simply getCabalDir.
 defaultCabalDir :: IO FilePath
 defaultCabalDir = getAppUserDataDirectory "cabal"
 
+getCabalDir :: IO FilePath
+getCabalDir = do
+  mDir <- lookupEnv "CABAL_DIR"
+  case mDir of
+    Nothing -> defaultCabalDir
+    Just dir -> return dir
+
 defaultConfigFile :: IO FilePath
 defaultConfigFile = do
-  dir <- defaultCabalDir
+  dir <- getCabalDir
   return $ dir </> "config"
 
 defaultCacheDir :: IO FilePath
 defaultCacheDir = do
-  dir <- defaultCabalDir
+  dir <- getCabalDir
   return $ dir </> "packages"
 
 defaultLogsDir :: IO FilePath
 defaultLogsDir = do
-  dir <- defaultCabalDir
+  dir <- getCabalDir
   return $ dir </> "logs"
 
 -- | Default position of the world file
 defaultWorldFile :: IO FilePath
 defaultWorldFile = do
-  dir <- defaultCabalDir
+  dir <- getCabalDir
   return $ dir </> "world"
 
 defaultExtraPath :: IO [FilePath]
 defaultExtraPath = do
-  dir <- defaultCabalDir
+  dir <- getCabalDir
   return [dir </> "bin"]
 
+defaultSymlinkPath :: IO FilePath
+defaultSymlinkPath = do
+  dir <- getCabalDir
+  return (dir </> "bin")
+
 defaultCompiler :: CompilerFlavor
 defaultCompiler = fromMaybe GHC defaultCompilerFlavor
 
@@ -621,7 +640,7 @@
     Nothing -> do
       notice verbosity $ "Config file path source is " ++ sourceMsg source ++ "."
       notice verbosity $ "Config file " ++ configFile ++ " not found."
-      createDefaultConfigFile verbosity configFile
+      createDefaultConfigFile verbosity [] configFile
     Just (ParseOk ws conf) -> do
       unless (null ws) $ warn verbosity $
         unlines (map (showPWarning configFile) ws)
@@ -670,12 +689,13 @@
         then return Nothing
         else ioError ioe
 
-createDefaultConfigFile :: Verbosity -> FilePath -> IO SavedConfig
-createDefaultConfigFile verbosity filePath = do
+createDefaultConfigFile :: Verbosity -> [String] -> FilePath -> IO SavedConfig
+createDefaultConfigFile verbosity extraLines filePath  = do
   commentConf <- commentSavedConfig
   initialConf <- initialSavedConfig
+  extraConf   <- parseExtraLines verbosity extraLines
   notice verbosity $ "Writing default configuration to " ++ filePath
-  writeConfigFile filePath commentConf initialConf
+  writeConfigFile filePath commentConf (initialConf `mappend` extraConf)
   return initialConf
 
 writeConfigFile :: FilePath -> SavedConfig -> SavedConfig -> IO ()
@@ -975,7 +995,9 @@
 
   return config {
     savedGlobalFlags       = (savedGlobalFlags config) {
-       globalRemoteRepos   = toNubList remoteRepoSections
+       globalRemoteRepos   = toNubList remoteRepoSections,
+       -- the global extra prog path comes from the configure flag prog path
+       globalProgPathExtra = configProgramPathExtra (savedConfigureFlags config)
        },
     savedConfigureFlags    = (savedConfigureFlags config) {
        configProgramPaths  = paths,
@@ -1154,16 +1176,30 @@
   map viewAsFieldDescr $
   programDbOptions defaultProgramDb ParseArgs id (++)
 
+parseExtraLines :: Verbosity -> [String] -> IO SavedConfig
+parseExtraLines verbosity extraLines =
+                case parseConfig (ConstraintSourceMainConfig "additional lines")
+                     mempty (unlines extraLines) of
+                  ParseFailed err ->
+                    let (line, msg) = locatedErrorMsg err
+                    in die' verbosity $
+                         "Error parsing additional config lines\n"
+                         ++ maybe "" (\n -> ':' : show n) line ++ ":\n" ++ msg
+                  ParseOk [] r -> return r
+                  ParseOk ws _ -> die' verbosity $
+                         unlines (map (showPWarning "Error parsing additional config lines") ws)
+
 -- | Get the differences (as a pseudo code diff) between the user's
 -- '~/.cabal/config' and the one that cabal would generate if it didn't exist.
-userConfigDiff :: GlobalFlags -> IO [String]
-userConfigDiff globalFlags = do
+userConfigDiff :: Verbosity -> GlobalFlags -> [String] -> IO [String]
+userConfigDiff verbosity globalFlags extraLines = do
   userConfig <- loadRawConfig normal (globalConfigFile globalFlags)
+  extraConfig <- parseExtraLines verbosity extraLines
   testConfig <- initialSavedConfig
   return $ reverse . foldl' createDiff [] . M.toList
                 $ M.unionWith combine
                     (M.fromList . map justFst $ filterShow testConfig)
-                    (M.fromList . map justSnd $ filterShow userConfig)
+                    (M.fromList . map justSnd $ filterShow (userConfig `mappend` extraConfig))
   where
     justFst (a, b) = (a, (Just b, Nothing))
     justSnd (a, b) = (a, (Nothing, Just b))
@@ -1201,9 +1237,10 @@
 
 
 -- | Update the user's ~/.cabal/config' keeping the user's customizations.
-userConfigUpdate :: Verbosity -> GlobalFlags -> IO ()
-userConfigUpdate verbosity globalFlags = do
+userConfigUpdate :: Verbosity -> GlobalFlags -> [String] -> IO ()
+userConfigUpdate verbosity globalFlags extraLines = do
   userConfig  <- loadRawConfig normal (globalConfigFile globalFlags)
+  extraConfig <- parseExtraLines verbosity extraLines
   newConfig   <- initialSavedConfig
   commentConf <- commentSavedConfig
   cabalFile <- getConfigFilePath $ globalConfigFile globalFlags
@@ -1211,4 +1248,4 @@
   notice verbosity $ "Renaming " ++ cabalFile ++ " to " ++ backup ++ "."
   renameFile cabalFile backup
   notice verbosity $ "Writing merged config to " ++ cabalFile ++ "."
-  writeConfigFile cabalFile commentConf (newConfig `mappend` userConfig)
+  writeConfigFile cabalFile commentConf (newConfig `mappend` userConfig `mappend` extraConfig)
diff --git a/cabal/cabal-install/Distribution/Client/Configure.hs b/cabal/cabal-install/Distribution/Client/Configure.hs
--- a/cabal/cabal-install/Distribution/Client/Configure.hs
+++ b/cabal/cabal-install/Distribution/Client/Configure.hs
@@ -134,7 +134,7 @@
         ++ message
         ++ "\nTrying configure anyway."
       setupWrapper verbosity (setupScriptOptions installedPkgIndex Nothing)
-        Nothing configureCommand (const configFlags) extraArgs
+        Nothing configureCommand (const configFlags) (const extraArgs)
 
     Right installPlan0 ->
      let installPlan = InstallPlan.configureInstallPlan configFlags installPlan0
@@ -204,6 +204,7 @@
     , useLoggingHandle         = Nothing
     , useWorkingDir            = Nothing
     , useExtraPathEnv          = []
+    , useExtraEnvOverrides     = []
     , setupCacheLock           = lock
     , useWin32CleanHack        = False
     , forceExternalSetupMethod = forceExternal
@@ -386,7 +387,7 @@
                  extraArgs =
 
   setupWrapper verbosity
-    scriptOptions (Just pkg) configureCommand configureFlags extraArgs
+    scriptOptions (Just pkg) configureCommand configureFlags (const extraArgs)
 
   where
     gpkg = packageDescription spkg
diff --git a/cabal/cabal-install/Distribution/Client/Dependency.hs b/cabal/cabal-install/Distribution/Client/Dependency.hs
--- a/cabal/cabal-install/Distribution/Client/Dependency.hs
+++ b/cabal/cabal-install/Distribution/Client/Dependency.hs
@@ -61,10 +61,11 @@
     removeUpperBounds,
     addDefaultSetupDependencies,
     addSetupCabalMinVersionConstraint,
+    addSetupCabalMaxVersionConstraint,
   ) where
 
 import Distribution.Solver.Modular
-         ( modularResolver, SolverConfig(..) )
+         ( modularResolver, SolverConfig(..), PruneAfterFirstSuccess(..) )
 import Distribution.Simple.PackageIndex (InstalledPackageIndex)
 import qualified Distribution.Simple.PackageIndex as InstalledPackageIndex
 import Distribution.Client.SolverInstallPlan (SolverInstallPlan)
@@ -96,7 +97,7 @@
 import Distribution.System
          ( Platform )
 import Distribution.Client.Utils
-         ( duplicates, duplicatesBy, mergeBy, MergeResult(..) )
+         ( duplicatesBy, mergeBy, MergeResult(..) )
 import Distribution.Simple.Utils
          ( comparing )
 import Distribution.Simple.Setup
@@ -525,16 +526,18 @@
               PD.setupBuildInfo =
                 case PD.setupBuildInfo pkgdesc of
                   Just sbi -> Just sbi
-                  Nothing  -> case defaultSetupDeps srcpkg of
+                  Nothing -> case defaultSetupDeps srcpkg of
                     Nothing -> Nothing
-                    Just deps -> Just PD.SetupBuildInfo {
-                      PD.defaultSetupDepends = True,
-                      PD.setupDepends        = deps
-                    }
+                    Just deps | isCustom -> Just PD.SetupBuildInfo {
+                                                PD.defaultSetupDepends = True,
+                                                PD.setupDepends        = deps
+                                            }
+                              | otherwise -> Nothing
             }
           }
         }
       where
+        isCustom = PD.buildType pkgdesc == PD.Custom
         gpkgdesc = packageDescription srcpkg
         pkgdesc  = PD.packageDescription gpkgdesc
 
@@ -553,7 +556,22 @@
   where
     cabalPkgname = mkPackageName "Cabal"
 
+-- | Variant of 'addSetupCabalMinVersionConstraint' which sets an
+-- upper bound on @setup.Cabal@ labeled with 'ConstraintSetupCabalMaxVersion'.
+--
+addSetupCabalMaxVersionConstraint :: Version
+                                  -> DepResolverParams -> DepResolverParams
+addSetupCabalMaxVersionConstraint maxVersion =
+    addConstraints
+      [ LabeledPackageConstraint
+          (PackageConstraint (ScopeAnySetupQualifier cabalPkgname)
+                             (PackagePropertyVersion $ earlierVersion maxVersion))
+          ConstraintSetupCabalMaxVersion
+      ]
+  where
+    cabalPkgname = mkPackageName "Cabal"
 
+
 upgradeDependencies :: DepResolverParams -> DepResolverParams
 upgradeDependencies = setPreferenceDefault PreferAllLatest
 
@@ -619,7 +637,7 @@
         where
           gpkgdesc = packageDescription srcpkg
           pkgdesc  = PD.packageDescription gpkgdesc
-          bt       = fromMaybe PD.Custom (PD.buildType pkgdesc)
+          bt       = PD.buildType pkgdesc
           affected = bt == PD.Custom && hasBuildableFalse gpkgdesc
 
       -- Does this package contain any components with non-empty 'build-depends'
@@ -717,7 +735,7 @@
   $ runSolver solver (SolverConfig reordGoals cntConflicts
                       indGoals noReinstalls
                       shadowing strFlags allowBootLibs maxBkjumps enableBj
-                      solveExes order verbosity)
+                      solveExes order verbosity (PruneAfterFirstSuccess False))
                      platform comp installedPkgIndex sourcePkgIndex
                      pkgConfigDB preferences constraints targets
   where
@@ -889,8 +907,8 @@
                           -> SolverPackage UnresolvedPkgLoc -> [PackageProblem]
 configuredPackageProblems platform cinfo
   (SolverPackage pkg specifiedFlags stanzas specifiedDeps' _specifiedExeDeps') =
-     -- FIXME/TODO: FlagAssignment ought to be duplicate-free as internal invariant
-     [ DuplicateFlag flag | ((flag,_):_) <- duplicates (PD.unFlagAssignment specifiedFlags) ]
+     [ DuplicateFlag flag
+     | flag <- PD.findDuplicateFlagAssignments specifiedFlags ]
   ++ [ MissingFlag flag | OnlyInLeft  flag <- mergedFlags ]
   ++ [ ExtraFlag   flag | OnlyInRight flag <- mergedFlags ]
   ++ [ DuplicateDeps pkgs
@@ -928,24 +946,24 @@
         (sortNubOn dependencyName required)
         (sortNubOn packageName    specified)
 
+    compSpec = enableStanzas stanzas
     -- TODO: It would be nicer to use ComponentDeps here so we can be more
-    -- precise in our checks. That's a bit tricky though, as this currently
-    -- relies on the 'buildDepends' field of 'PackageDescription'. (OTOH, that
-    -- field is deprecated and should be removed anyway.)  As long as we _do_
-    -- use a flat list here, we have to allow for duplicates when we fold
-    -- specifiedDeps; once we have proper ComponentDeps here we should get rid
-    -- of the `nubOn` in `mergeDeps`.
+    -- precise in our checks. In fact, this no longer relies on buildDepends and
+    -- thus should be easier to fix. As long as we _do_ use a flat list here, we
+    -- have to allow for duplicates when we fold specifiedDeps; once we have
+    -- proper ComponentDeps here we should get rid of the `nubOn` in
+    -- `mergeDeps`.
     requiredDeps :: [Dependency]
     requiredDeps =
       --TODO: use something lower level than finalizePD
       case finalizePD specifiedFlags
-         (enableStanzas stanzas)
+         compSpec
          (const True)
          platform cinfo
          []
          (packageDescription pkg) of
         Right (resolvedPkg, _) ->
-             externalBuildDepends resolvedPkg
+             externalBuildDepends resolvedPkg compSpec
           ++ maybe [] PD.setupDepends (PD.setupBuildInfo resolvedPkg)
         Left  _ ->
           error "configuredPackageInvalidDeps internal error"
diff --git a/cabal/cabal-install/Distribution/Client/DistDirLayout.hs b/cabal/cabal-install/Distribution/Client/DistDirLayout.hs
--- a/cabal/cabal-install/Distribution/Client/DistDirLayout.hs
+++ b/cabal/cabal-install/Distribution/Client/DistDirLayout.hs
@@ -2,7 +2,7 @@
 
 -- |
 --
--- The layout of the .\/dist\/ directory where cabal keeps all of it's state
+-- The layout of the .\/dist\/ directory where cabal keeps all of its state
 -- and build artifacts.
 --
 module Distribution.Client.DistDirLayout (
@@ -27,10 +27,14 @@
 
 import Distribution.Package
          ( PackageId, ComponentId, UnitId )
+import Distribution.Client.Setup
+         ( ArchiveFormat(..) )
 import Distribution.Compiler
 import Distribution.Simple.Compiler
          ( PackageDB(..), PackageDBStack, OptimisationLevel(..) )
 import Distribution.Text
+import Distribution.Pretty
+         ( prettyShow )
 import Distribution.Types.ComponentName
 import Distribution.System
 
@@ -85,10 +89,14 @@
        distBuildDirectory           :: DistDirParams -> FilePath,
        distBuildRootDirectory       :: FilePath,
 
+       -- | The directory under dist where we download tarballs and source
+       -- control repos to.
+       --
+       distDownloadSrcDirectory     :: FilePath,
+
        -- | The directory under dist where we put the unpacked sources of
        -- packages, in those cases where it makes sense to keep the build
-       -- artifacts to reduce rebuild times. These can be tarballs or could be
-       -- scm repos.
+       -- artifacts to reduce rebuild times.
        --
        distUnpackedSrcDirectory     :: PackageId -> FilePath,
        distUnpackedSrcRootDirectory :: FilePath,
@@ -105,6 +113,10 @@
        distPackageCacheFile         :: DistDirParams -> String -> FilePath,
        distPackageCacheDirectory    :: DistDirParams -> FilePath,
 
+       -- | The location that sdists are placed by default.
+       distSdistFile                :: PackageId -> ArchiveFormat -> FilePath,
+       distSdistDirectory           :: FilePath,
+
        distTempDirectory            :: FilePath,
        distBinDirectory             :: FilePath,
 
@@ -205,6 +217,8 @@
     distUnpackedSrcRootDirectory   = distDirectory </> "src"
     distUnpackedSrcDirectory pkgid = distUnpackedSrcRootDirectory
                                       </> display pkgid
+    -- we shouldn't get name clashes so this should be fine:
+    distDownloadSrcDirectory       = distUnpackedSrcRootDirectory
 
     distProjectCacheDirectory = distDirectory </> "cache"
     distProjectCacheFile name = distProjectCacheDirectory </> name
@@ -212,6 +226,14 @@
     distPackageCacheDirectory params = distBuildDirectory params </> "cache"
     distPackageCacheFile params name = distPackageCacheDirectory params </> name
 
+    distSdistFile pid format = distSdistDirectory </> prettyShow pid <.> ext
+        where
+          ext = case format of
+            TargzFormat -> "tar.gz"
+            ZipFormat -> "zip"
+    
+    distSdistDirectory = distDirectory </> "sdist"
+
     distTempDirectory = distDirectory </> "tmp"
 
     distBinDirectory = distDirectory </> "bin"
@@ -251,7 +273,7 @@
     mkCabalDirLayout cabalDir Nothing Nothing
 
 mkCabalDirLayout :: FilePath -- ^ Cabal directory
-                 -> Maybe FilePath -- ^ Store directory
+                 -> Maybe FilePath -- ^ Store directory. Must be absolute
                  -> Maybe FilePath -- ^ Log directory
                  -> CabalDirLayout
 mkCabalDirLayout cabalDir mstoreDir mlogDir =
diff --git a/cabal/cabal-install/Distribution/Client/Fetch.hs b/cabal/cabal-install/Distribution/Client/Fetch.hs
--- a/cabal/cabal-install/Distribution/Client/Fetch.hs
+++ b/cabal/cabal-install/Distribution/Client/Fetch.hs
@@ -1,5 +1,4 @@
------------------------------------------------------------------------------
--- |
+------------------------------------------------------------------------------- |
 -- Module      :  Distribution.Client.Fetch
 -- Copyright   :  (c) David Himmelstrup 2005
 --                    Duncan Coutts 2011
@@ -25,6 +24,9 @@
 import Distribution.Client.Setup
          ( GlobalFlags(..), FetchFlags(..), RepoContext(..) )
 
+import Distribution.Solver.Types.ConstraintSource
+import Distribution.Solver.Types.LabeledPackageConstraint
+import Distribution.Solver.Types.OptionalStanza
 import Distribution.Solver.Types.PkgConfigDb ( PkgConfigDb, readPkgConfigDb )
 import Distribution.Solver.Types.SolverPackage
 import Distribution.Solver.Types.SourcePackage
@@ -37,7 +39,7 @@
 import Distribution.Simple.Program
          ( ProgramDb )
 import Distribution.Simple.Setup
-         ( fromFlag )
+         ( fromFlag, fromFlagOrDefault )
 import Distribution.Simple.Utils
          ( die', notice, debug )
 import Distribution.System
@@ -168,6 +170,13 @@
 
       . setSolverVerbosity verbosity
 
+      . addConstraints
+          [ let pc = PackageConstraint
+                     (scopeToplevel $ pkgSpecifierTarget pkgSpecifier)
+                     (PackagePropertyStanzas stanzas)
+            in LabeledPackageConstraint pc ConstraintSourceConfigFlagOrTarget
+          | pkgSpecifier <- pkgSpecifiers ]
+
         -- Reinstall the targets given on the command line so that the dep
         -- resolver will decide that they need fetching, even if they're
         -- already installed. Since we want to get the source packages of
@@ -179,6 +188,11 @@
     includeDependencies = fromFlag (fetchDeps fetchFlags)
     logMsg message rest = debug verbosity message >> rest
 
+    stanzas           = [ TestStanzas | testsEnabled ]
+                     ++ [ BenchStanzas | benchmarksEnabled ]
+    testsEnabled      = fromFlagOrDefault False $ fetchTests fetchFlags
+    benchmarksEnabled = fromFlagOrDefault False $ fetchBenchmarks fetchFlags
+
     reorderGoals     = fromFlag (fetchReorderGoals     fetchFlags)
     countConflicts   = fromFlag (fetchCountConflicts   fetchFlags)
     independentGoals = fromFlag (fetchIndependentGoals fetchFlags)
@@ -203,6 +217,10 @@
     RemoteTarballPackage _uri _ ->
       die' verbosity $ "The 'fetch' command does not yet support remote tarballs. "
          ++ "In the meantime you can use the 'unpack' commands."
+
+    RemoteSourceRepoPackage _repo _ ->
+      die' verbosity $ "The 'fetch' command does not yet support remote "
+         ++ "source repositores."
 
     RepoTarballPackage repo pkgid _ -> do
       _ <- fetchRepoTarball verbosity repoCtxt repo pkgid
diff --git a/cabal/cabal-install/Distribution/Client/FetchUtils.hs b/cabal/cabal-install/Distribution/Client/FetchUtils.hs
--- a/cabal/cabal-install/Distribution/Client/FetchUtils.hs
+++ b/cabal/cabal-install/Distribution/Client/FetchUtils.hs
@@ -40,13 +40,15 @@
 import Distribution.Package
          ( PackageId, packageName, packageVersion )
 import Distribution.Simple.Utils
-         ( notice, info, debug, setupMessage )
+         ( notice, info, debug, die' )
 import Distribution.Text
          ( display )
 import Distribution.Verbosity
          ( Verbosity, verboseUnmarkOutput )
 import Distribution.Client.GlobalFlags
          ( RepoContext(..) )
+import Distribution.Client.Utils
+         ( ProgressPhase(..), progressMessage )
 
 import Data.Maybe
 import Data.Map (Map)
@@ -81,6 +83,8 @@
     LocalTarballPackage  _file      -> return True
     RemoteTarballPackage _uri local -> return (isJust local)
     RepoTarballPackage repo pkgid _ -> doesFileExist (packageFile repo pkgid)
+    RemoteSourceRepoPackage _ local -> return (isJust local)
+    
 
 -- | Checks if the package has already been fetched (or does not need
 -- fetching) and if so returns evidence in the form of a 'PackageLocation'
@@ -97,13 +101,15 @@
       return (Just $ RemoteTarballPackage uri file)
     RepoTarballPackage repo pkgid (Just file) ->
       return (Just $ RepoTarballPackage repo pkgid file)
+    RemoteSourceRepoPackage repo (Just dir) ->
+      return (Just $ RemoteSourceRepoPackage repo dir)
 
-    RemoteTarballPackage _uri Nothing -> return Nothing
+    RemoteTarballPackage     _uri Nothing -> return Nothing
+    RemoteSourceRepoPackage _repo Nothing -> return Nothing
     RepoTarballPackage repo pkgid Nothing ->
       fmap (fmap (RepoTarballPackage repo pkgid))
            (checkRepoTarballFetched repo pkgid)
 
-
 -- | Like 'checkFetched' but for the specific case of a 'RepoTarballPackage'.
 --
 checkRepoTarballFetched :: Repo -> PackageId -> IO (Maybe FilePath)
@@ -130,6 +136,8 @@
       return (RemoteTarballPackage uri file)
     RepoTarballPackage repo pkgid (Just file) ->
       return (RepoTarballPackage repo pkgid file)
+    RemoteSourceRepoPackage repo (Just dir) ->
+      return (RemoteSourceRepoPackage repo dir)
 
     RemoteTarballPackage uri Nothing -> do
       path <- downloadTarballPackage uri
@@ -137,6 +145,8 @@
     RepoTarballPackage repo pkgid Nothing -> do
       local <- fetchRepoTarball verbosity repoCtxt repo pkgid
       return (RepoTarballPackage repo pkgid local)
+    RemoteSourceRepoPackage _repo Nothing ->
+      die' verbosity "fetchPackage: source repos not supported"
   where
     downloadTarballPackage uri = do
       transport <- repoContextGetTransport repoCtxt
@@ -157,8 +167,12 @@
   if fetched
     then do info verbosity $ display pkgid ++ " has already been downloaded."
             return (packageFile repo pkgid)
-    else do setupMessage verbosity "Downloading" pkgid
-            downloadRepoPackage
+    else do progressMessage verbosity ProgressDownloading (display pkgid)
+            res <- downloadRepoPackage
+            progressMessage verbosity ProgressDownloaded (display pkgid)
+            return res
+
+
   where
     downloadRepoPackage = case repo of
       RepoLocal{..} -> return (packageFile repo pkgid)
diff --git a/cabal/cabal-install/Distribution/Client/FileMonitor.hs b/cabal/cabal-install/Distribution/Client/FileMonitor.hs
--- a/cabal/cabal-install/Distribution/Client/FileMonitor.hs
+++ b/cabal/cabal-install/Distribution/Client/FileMonitor.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE CPP, DeriveGeneric, DeriveFunctor, GeneralizedNewtypeDeriving,
+{-# LANGUAGE DeriveGeneric, DeriveFunctor, GeneralizedNewtypeDeriving,
              NamedFieldPuns, BangPatterns #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
@@ -39,11 +39,7 @@
 import Prelude ()
 import Distribution.Client.Compat.Prelude
 
-#if MIN_VERSION_containers(0,5,0)
 import qualified Data.Map.Strict as Map
-#else
-import qualified Data.Map        as Map
-#endif
 import qualified Data.ByteString.Lazy as BS
 import qualified Distribution.Compat.Binary as Binary
 import qualified Data.Hashable as Hashable
diff --git a/cabal/cabal-install/Distribution/Client/GenBounds.hs b/cabal/cabal-install/Distribution/Client/GenBounds.hs
--- a/cabal/cabal-install/Distribution/Client/GenBounds.hs
+++ b/cabal/cabal-install/Distribution/Client/GenBounds.hs
@@ -29,7 +29,7 @@
 import Distribution.Package
          ( Package(..), unPackageName, packageName, packageVersion )
 import Distribution.PackageDescription
-         ( buildDepends )
+         ( enabledBuildDepends )
 import Distribution.PackageDescription.Configuration
          ( finalizePD )
 import Distribution.PackageDescription.Parsec
@@ -122,7 +122,7 @@
       Left _ -> putStrLn "finalizePD failed"
       Right (pd,_) -> do
         let needBounds = filter (not . hasUpperBound . depVersion) $
-                         buildDepends pd
+                         enabledBuildDepends pd defaultComponentRequestedSpec
 
         if (null needBounds)
           then putStrLn
diff --git a/cabal/cabal-install/Distribution/Client/Get.hs b/cabal/cabal-install/Distribution/Client/Get.hs
--- a/cabal/cabal-install/Distribution/Client/Get.hs
+++ b/cabal/cabal-install/Distribution/Client/Get.hs
@@ -14,7 +14,12 @@
 -----------------------------------------------------------------------------
 
 module Distribution.Client.Get (
-    get
+    get,
+
+    -- * Cloning 'SourceRepo's
+    -- | Mainly exported for testing purposes
+    clonePackagesFromSourceRepo,
+    ClonePackageException(..),
   ) where
 
 import Prelude ()
@@ -25,39 +30,33 @@
 import Distribution.Simple.Setup
          ( Flag(..), fromFlag, fromFlagOrDefault, flagToMaybe )
 import Distribution.Simple.Utils
-         ( notice, die', info, rawSystemExitCode, writeFileAtomic )
+         ( notice, die', info, writeFileAtomic )
 import Distribution.Verbosity
          ( Verbosity )
-import Distribution.Text(display)
+import Distribution.Text (display)
 import qualified Distribution.PackageDescription as PD
+import Distribution.Simple.Program
+         ( programName )
 
 import Distribution.Client.Setup
          ( GlobalFlags(..), GetFlags(..), RepoContext(..) )
 import Distribution.Client.Types
 import Distribution.Client.Targets
 import Distribution.Client.Dependency
+import Distribution.Client.VCS
 import Distribution.Client.FetchUtils
 import qualified Distribution.Client.Tar as Tar (extractTarGzFile)
 import Distribution.Client.IndexUtils as IndexUtils
         ( getSourcePackagesAtIndexState )
-import Distribution.Client.Compat.Process
-        ( readProcessWithExitCode )
-import Distribution.Compat.Exception
-        ( catchIO )
-
 import Distribution.Solver.Types.SourcePackage
 
 import Control.Exception
-         ( finally )
+         ( Exception(..), catch, throwIO )
 import Control.Monad
-         ( forM_, mapM_ )
-import qualified Data.Map
-import Data.Ord
-         ( comparing )
+         ( mapM, forM_, mapM_ )
+import qualified Data.Map as Map
 import System.Directory
-         ( createDirectoryIfMissing, doesDirectoryExist, doesFileExist
-         , getCurrentDirectory, setCurrentDirectory
-         )
+         ( createDirectoryIfMissing, doesDirectoryExist, doesFileExist )
 import System.Exit
          ( ExitCode(..) )
 import System.FilePath
@@ -75,11 +74,11 @@
     notice verbosity "No packages requested. Nothing to do."
 
 get verbosity repoCtxt globalFlags getFlags userTargets = do
-  let useFork = case (getSourceRepository getFlags) of
-        NoFlag -> False
-        _      -> True
+  let useSourceRepo = case getSourceRepository getFlags of
+                        NoFlag -> False
+                        _      -> True
 
-  unless useFork $
+  unless useSourceRepo $
     mapM_ (checkTarget verbosity) userTargets
 
   let idxState = flagToMaybe $ getIndexState getFlags
@@ -98,8 +97,8 @@
   unless (null prefix) $
     createDirectoryIfMissing True prefix
 
-  if useFork
-    then fork pkgs
+  if useSourceRepo
+    then clone  pkgs
     else unpack pkgs
 
   where
@@ -109,11 +108,15 @@
 
     prefix = fromFlagOrDefault "" (getDestDir getFlags)
 
-    fork :: [UnresolvedSourcePackage] -> IO ()
-    fork pkgs = do
-      let kind = fromFlag . getSourceRepository $ getFlags
-      branchers <- findUsableBranchers
-      mapM_ (forkPackage verbosity branchers prefix kind) pkgs
+    clone :: [UnresolvedSourcePackage] -> IO ()
+    clone = clonePackagesFromSourceRepo verbosity prefix kind
+          . map (\pkg -> (packageId pkg, packageSourceRepos pkg))
+      where
+        kind = fromFlag . getSourceRepository $ getFlags
+        packageSourceRepos :: SourcePackage loc -> [SourceRepo]
+        packageSourceRepos = PD.sourceRepos
+                           . PD.packageDescription
+                           . packageDescription
 
     unpack :: [UnresolvedSourcePackage] -> IO ()
     unpack pkgs = do
@@ -132,6 +135,10 @@
           RepoTarballPackage _repo _pkgid tarballPath ->
             unpackPackage verbosity prefix pkgid descOverride tarballPath
 
+          RemoteSourceRepoPackage _repo _ ->
+            die' verbosity $ "The 'get' command does no yet support targets "
+                          ++ "that are remote source repositories."
+
           LocalUnpackedPackage _ ->
             error "Distribution.Client.Get.unpack: the impossible happened."
       where
@@ -178,174 +185,115 @@
 
 
 -- ------------------------------------------------------------
--- * Forking the source repository
+-- * Cloning packages from their declared source repositories
 -- ------------------------------------------------------------
 
-data BranchCmd = BranchCmd (Verbosity -> FilePath -> IO ExitCode)
 
-data Brancher = Brancher
-    { brancherBinary :: String
-    , brancherBuildCmd :: PD.SourceRepo -> Maybe BranchCmd
-    }
+data ClonePackageException =
+       ClonePackageNoSourceRepos       PackageId
+     | ClonePackageNoSourceReposOfKind PackageId (Maybe RepoKind)
+     | ClonePackageNoRepoType          PackageId SourceRepo
+     | ClonePackageUnsupportedRepoType PackageId SourceRepo RepoType
+     | ClonePackageNoRepoLocation      PackageId SourceRepo
+     | ClonePackageDestinationExists   PackageId FilePath Bool
+     | ClonePackageFailedWithExitCode  PackageId SourceRepo String ExitCode
+  deriving (Show, Eq)
 
--- | The set of all supported branch drivers.
-allBranchers :: [(PD.RepoType, Brancher)]
-allBranchers =
-    [ (PD.Bazaar, branchBzr)
-    , (PD.Darcs, branchDarcs)
-    , (PD.Git, branchGit)
-    , (PD.Mercurial, branchHg)
-    , (PD.SVN, branchSvn)
-    ]
+instance Exception ClonePackageException where
+  displayException (ClonePackageNoSourceRepos pkgid) =
+       "Cannot fetch a source repository for package " ++ display pkgid
+    ++ ". The package does not specify any source repositories."
 
--- | Find which usable branch drivers (selected from 'allBranchers') are
--- available and usable on the local machine.
---
--- Each driver's main command is run with @--help@, and if the child process
--- exits successfully, that brancher is considered usable.
-findUsableBranchers :: IO (Data.Map.Map PD.RepoType Brancher)
-findUsableBranchers = do
-    let usable (_, brancher) = flip catchIO (const (return False)) $ do
-         let cmd = brancherBinary brancher
-         (exitCode, _, _) <- readProcessWithExitCode cmd ["--help"] ""
-         return (exitCode == ExitSuccess)
-    pairs <- filterM usable allBranchers
-    return (Data.Map.fromList pairs)
+  displayException (ClonePackageNoSourceReposOfKind pkgid repoKind) =
+       "Cannot fetch a source repository for package " ++ display pkgid
+    ++ ". The package does not specify a source repository of the requested "
+    ++ "kind" ++ maybe "." (\k -> " (kind " ++ display k ++ ").") repoKind
 
--- | Fork a single package from a remote source repository to the local
--- file system.
-forkPackage :: Verbosity
-            -> Data.Map.Map PD.RepoType Brancher
-               -- ^ Branchers supported by the local machine.
-            -> FilePath
-               -- ^ The directory in which new branches or repositories will
-               -- be created.
-            -> (Maybe PD.RepoKind)
-               -- ^ Which repo to choose.
-            -> SourcePackage loc
-               -- ^ The package to fork.
-            -> IO ()
-forkPackage verbosity branchers prefix kind src = do
-    let desc    = PD.packageDescription (packageDescription src)
-        pkgid   = display (packageId src)
-        pkgname = display (packageName src)
-        destdir = prefix </> pkgname
+  displayException (ClonePackageNoRepoType pkgid _repo) =
+       "Cannot fetch the source repository for package " ++ display pkgid
+    ++ ". The package's description specifies a source repository but does "
+    ++ "not specify the repository 'type' field (e.g. git, darcs or hg)."
 
-    destDirExists <- doesDirectoryExist destdir
-    when destDirExists $ do
-        die' verbosity ("The directory " ++ show destdir ++ " already exists, not forking.")
+  displayException (ClonePackageUnsupportedRepoType pkgid _ repoType) =
+       "Cannot fetch the source repository for package " ++ display pkgid
+    ++ ". The repository type '" ++ display repoType
+    ++ "' is not yet supported."
 
-    destFileExists  <- doesFileExist destdir
-    when destFileExists $ do
-        die' verbosity ("A file " ++ show destdir ++ " is in the way, not forking.")
+  displayException (ClonePackageNoRepoLocation pkgid _repo) =
+       "Cannot fetch the source repository for package " ++ display pkgid
+    ++ ". The package's description specifies a source repository but does "
+    ++ "not specify the repository 'location' field (i.e. the URL)."
 
-    let repos = PD.sourceRepos desc
-    case findBranchCmd branchers repos kind of
-        Just (BranchCmd io) -> do
-            exitCode <- io verbosity destdir
-            case exitCode of
-                ExitSuccess -> return ()
-                ExitFailure _ -> die' verbosity ("Couldn't fork package " ++ pkgid)
-        Nothing -> case repos of
-            [] -> die' verbosity ("Package " ++ pkgid
-                       ++ " does not have any source repositories.")
-            _ -> die' verbosity ("Package " ++ pkgid
-                      ++ " does not have any usable source repositories.")
+  displayException (ClonePackageDestinationExists pkgid dest isdir) =
+       "Not fetching the source repository for package " ++ display pkgid ++ ". "
+    ++ if isdir then "The destination directory " ++ dest ++ " already exists."
+                else "A file " ++ dest ++ " is in the way."
 
--- | Given a set of possible branchers, and a set of possible source
--- repositories, find a repository that is both 1) likely to be specific to
--- this source version and 2) is supported by the local machine.
-findBranchCmd :: Data.Map.Map PD.RepoType Brancher -> [PD.SourceRepo]
-                 -> (Maybe PD.RepoKind) -> Maybe BranchCmd
-findBranchCmd branchers allRepos maybeKind = cmd where
-    -- Sort repositories by kind, from This to Head to Unknown. Repositories
-    -- with equivalent kinds are selected based on the order they appear in
-    -- the Cabal description file.
-    repos' = sortBy (comparing thisFirst) allRepos
-    thisFirst r = case PD.repoKind r of
-        PD.RepoThis -> 0 :: Int
-        PD.RepoHead -> case PD.repoTag r of
-            -- If the type is 'head' but the author specified a tag, they
-            -- probably meant to create a 'this' repository but screwed up.
-            Just _ -> 0
-            Nothing -> 1
-        PD.RepoKindUnknown _ -> 2
+  displayException (ClonePackageFailedWithExitCode
+                      pkgid repo vcsprogname exitcode) =
+       "Failed to fetch the source repository for package " ++ display pkgid
+    ++ maybe "" (", repository location " ++) (PD.repoLocation repo) ++ " ("
+    ++ vcsprogname ++ " failed with " ++ show exitcode ++ ")."
 
-    -- If the user has specified the repo kind, filter out the repositories
-    -- she's not interested in.
-    repos = maybe repos' (\k -> filter ((==) k . PD.repoKind) repos') maybeKind
 
-    repoBranchCmd repo = do
-        t <- PD.repoType repo
-        brancher <- Data.Map.lookup t branchers
-        brancherBuildCmd brancher repo
+-- | Given a bunch of package ids and their corresponding available
+-- 'SourceRepo's, pick a single 'SourceRepo' for each one and clone into
+-- new subdirs of the given directory.
+--
+clonePackagesFromSourceRepo :: Verbosity
+                            -> FilePath            -- ^ destination dir prefix
+                            -> Maybe RepoKind      -- ^ preferred 'RepoKind'
+                            -> [(PackageId, [SourceRepo])]
+                                                   -- ^ the packages and their
+                                                   -- available 'SourceRepo's
+                            -> IO ()
+clonePackagesFromSourceRepo verbosity destDirPrefix
+                            preferredRepoKind pkgrepos = do
 
-    cmd = listToMaybe (mapMaybe repoBranchCmd repos)
+    -- Do a bunch of checks and collect the required info
+    pkgrepos' <- mapM preCloneChecks pkgrepos
 
--- | Branch driver for Bazaar.
-branchBzr :: Brancher
-branchBzr = Brancher "bzr" $ \repo -> do
-    src <- PD.repoLocation repo
-    let args dst = case PD.repoTag repo of
-         Just tag -> ["branch", src, dst, "-r", "tag:" ++ tag]
-         Nothing -> ["branch", src, dst]
-    return $ BranchCmd $ \verbosity dst -> do
-        notice verbosity ("bzr: branch " ++ show src)
-        rawSystemExitCode verbosity "bzr" (args dst)
+    -- Configure the VCS drivers for all the repository types we may need
+    vcss <- configureVCSs verbosity $
+              Map.fromList [ (vcsRepoType vcs, vcs)
+                           | (_, _, vcs, _) <- pkgrepos' ]
 
--- | Branch driver for Darcs.
-branchDarcs :: Brancher
-branchDarcs = Brancher "darcs" $ \repo -> do
-    src <- PD.repoLocation repo
-    let args dst = case PD.repoTag repo of
-         Just tag -> ["get", src, dst, "-t", tag]
-         Nothing -> ["get", src, dst]
-    return $ BranchCmd $ \verbosity dst -> do
-        notice verbosity ("darcs: get " ++ show src)
-        rawSystemExitCode verbosity "darcs" (args dst)
+    -- Now execute all the required commands for each repo
+    sequence_
+      [ cloneSourceRepo verbosity vcs' repo destDir
+          `catch` \exitcode ->
+           throwIO (ClonePackageFailedWithExitCode
+                      pkgid repo (programName (vcsProgram vcs)) exitcode)
+      | (pkgid, repo, vcs, destDir) <- pkgrepos'
+      , let Just vcs' = Map.lookup (vcsRepoType vcs) vcss
+      ]
 
--- | Branch driver for Git.
-branchGit :: Brancher
-branchGit = Brancher "git" $ \repo -> do
-    src <- PD.repoLocation repo
-    let postClone verbosity dst = case PD.repoTag repo of
-         Just t -> do
-             cwd <- getCurrentDirectory
-             setCurrentDirectory dst
-             finally
-                 (rawSystemExitCode verbosity "git" ["checkout", t])
-                 (setCurrentDirectory cwd)
-         Nothing -> return ExitSuccess
-    return $ BranchCmd $ \verbosity dst -> do
-        notice verbosity ("git: clone " ++ show src)
-        code <- rawSystemExitCode verbosity "git" (["clone", src, dst] ++
-                    case PD.repoBranch repo of
-                        Nothing -> []
-                        Just b -> ["--branch", b])
-        case code of
-            ExitFailure _ -> return code
-            ExitSuccess -> postClone verbosity  dst
+  where
+    preCloneChecks :: (PackageId, [SourceRepo])
+                   -> IO (PackageId, SourceRepo, VCS Program, FilePath)
+    preCloneChecks (pkgid, repos) = do
+      repo <- case selectPackageSourceRepo preferredRepoKind repos of
+        Just repo            -> return repo
+        Nothing | null repos -> throwIO (ClonePackageNoSourceRepos pkgid)
+        Nothing              -> throwIO (ClonePackageNoSourceReposOfKind
+                                           pkgid preferredRepoKind)
 
--- | Branch driver for Mercurial.
-branchHg :: Brancher
-branchHg = Brancher "hg" $ \repo -> do
-    src <- PD.repoLocation repo
-    let branchArgs = case PD.repoBranch repo of
-         Just b -> ["--branch", b]
-         Nothing -> []
-    let tagArgs = case PD.repoTag repo of
-         Just t -> ["--rev", t]
-         Nothing -> []
-    let args dst = ["clone", src, dst] ++ branchArgs ++ tagArgs
-    return $ BranchCmd $ \verbosity dst -> do
-        notice verbosity ("hg: clone " ++ show src)
-        rawSystemExitCode verbosity "hg" (args dst)
+      vcs <- case validateSourceRepo repo of
+        Right (_, _, _, vcs) -> return vcs
+        Left SourceRepoRepoTypeUnspecified ->
+          throwIO (ClonePackageNoRepoType pkgid repo)
 
--- | Branch driver for Subversion.
-branchSvn :: Brancher
-branchSvn = Brancher "svn" $ \repo -> do
-    src <- PD.repoLocation repo
-    let args dst = ["checkout", src, dst]
-    return $ BranchCmd $ \verbosity dst -> do
-        notice verbosity ("svn: checkout " ++ show src)
-        rawSystemExitCode verbosity "svn" (args dst)
+        Left (SourceRepoRepoTypeUnsupported repoType) ->
+          throwIO (ClonePackageUnsupportedRepoType pkgid repo repoType)
+
+        Left SourceRepoLocationUnspecified ->
+          throwIO (ClonePackageNoRepoLocation pkgid repo)
+
+      let destDir = destDirPrefix </> display (packageName pkgid)
+      destDirExists  <- doesDirectoryExist destDir
+      destFileExists <- doesFileExist      destDir
+      when (destDirExists || destFileExists) $
+        throwIO (ClonePackageDestinationExists pkgid destDir destDirExists)
+
+      return (pkgid, repo, vcs, destDir)
+
diff --git a/cabal/cabal-install/Distribution/Client/GlobalFlags.hs b/cabal/cabal-install/Distribution/Client/GlobalFlags.hs
--- a/cabal/cabal-install/Distribution/Client/GlobalFlags.hs
+++ b/cabal/cabal-install/Distribution/Client/GlobalFlags.hs
@@ -69,7 +69,8 @@
     globalIgnoreExpiry      :: Flag Bool,    -- ^ Ignore security expiry dates
     globalHttpTransport     :: Flag String,
     globalNix               :: Flag Bool,  -- ^ Integrate with Nix
-    globalStoreDir          :: Flag FilePath
+    globalStoreDir          :: Flag FilePath,
+    globalProgPathExtra     :: NubList FilePath -- ^ Extra program path used for packagedb lookups in a global context (i.e. for http transports)
   } deriving Generic
 
 defaultGlobalFlags :: GlobalFlags
@@ -89,7 +90,8 @@
     globalIgnoreExpiry      = Flag False,
     globalHttpTransport     = mempty,
     globalNix               = Flag False,
-    globalStoreDir          = mempty
+    globalStoreDir          = mempty,
+    globalProgPathExtra     = mempty
   }
 
 instance Monoid GlobalFlags where
@@ -139,18 +141,20 @@
 withRepoContext verbosity globalFlags =
     withRepoContext'
       verbosity
-      (fromNubList (globalRemoteRepos   globalFlags))
-      (fromNubList (globalLocalRepos    globalFlags))
-      (fromFlag    (globalCacheDir      globalFlags))
-      (flagToMaybe (globalHttpTransport globalFlags))
-      (flagToMaybe (globalIgnoreExpiry  globalFlags))
+      (fromNubList (globalRemoteRepos    globalFlags))
+      (fromNubList (globalLocalRepos     globalFlags))
+      (fromFlag    (globalCacheDir       globalFlags))
+      (flagToMaybe (globalHttpTransport  globalFlags))
+      (flagToMaybe (globalIgnoreExpiry   globalFlags))
+      (fromNubList (globalProgPathExtra globalFlags))
 
 withRepoContext' :: Verbosity -> [RemoteRepo] -> [FilePath]
                  -> FilePath  -> Maybe String -> Maybe Bool
+                 -> [FilePath]
                  -> (RepoContext -> IO a)
                  -> IO a
 withRepoContext' verbosity remoteRepos localRepos
-                 sharedCacheDir httpTransport ignoreExpiry = \callback -> do
+                 sharedCacheDir httpTransport ignoreExpiry extraPaths = \callback -> do
     transportRef <- newMVar Nothing
     let httpLib = Sec.HTTP.transportAdapter
                     verbosity
@@ -178,7 +182,7 @@
       modifyMVar transportRef $ \mTransport -> do
         transport <- case mTransport of
           Just tr -> return tr
-          Nothing -> configureTransport verbosity httpTransport
+          Nothing -> configureTransport verbosity extraPaths httpTransport
         return (Just transport, transport)
 
     withSecureRepo :: Map Repo SecureRepo
diff --git a/cabal/cabal-install/Distribution/Client/Haddock.hs b/cabal/cabal-install/Distribution/Client/Haddock.hs
--- a/cabal/cabal-install/Distribution/Client/Haddock.hs
+++ b/cabal/cabal-install/Distribution/Client/Haddock.hs
@@ -40,7 +40,7 @@
                        -> IO ()
 regenerateHaddockIndex verbosity pkgs progdb index = do
       (paths, warns) <- haddockPackagePaths pkgs' Nothing
-      let paths' = [ (interface, html) | (interface, Just html) <- paths]
+      let paths' = [ (interface, html) | (interface, Just html, _) <- paths]
       forM_ warns (debug verbosity)
 
       (confHaddock, _, _) <-
diff --git a/cabal/cabal-install/Distribution/Client/HttpUtils.hs b/cabal/cabal-install/Distribution/Client/HttpUtils.hs
--- a/cabal/cabal-install/Distribution/Client/HttpUtils.hs
+++ b/cabal/cabal-install/Distribution/Client/HttpUtils.hs
@@ -60,11 +60,13 @@
 import Distribution.Simple.Program
          ( Program, simpleProgram, ConfiguredProgram, programPath
          , ProgramInvocation(..), programInvocation
+         , ProgramSearchPathEntry(..)
          , getProgramInvocationOutput )
 import Distribution.Simple.Program.Db
          ( ProgramDb, emptyProgramDb, addKnownPrograms
          , configureAllKnownPrograms
-         , requireProgram, lookupProgram )
+         , requireProgram, lookupProgram
+         , modifyProgramSearchPath )
 import Distribution.Simple.Program.Run
          ( getProgramInvocationOutputAndErrors )
 import Numeric (showHex)
@@ -264,18 +266,19 @@
       , \_ -> Just plainHttpTransport )
     ]
 
-configureTransport :: Verbosity -> Maybe String -> IO HttpTransport
+configureTransport :: Verbosity -> [FilePath] -> Maybe String -> IO HttpTransport
 
-configureTransport verbosity (Just name) =
+configureTransport verbosity extraPath (Just name) =
     -- the user secifically selected a transport by name so we'll try and
     -- configure that one
 
     case find (\(name',_,_,_) -> name' == name) supportedTransports of
       Just (_, mprog, _tls, mkTrans) -> do
 
+        let baseProgDb = modifyProgramSearchPath (\p -> map ProgramSearchPathDir extraPath ++ p) emptyProgramDb
         progdb <- case mprog of
           Nothing   -> return emptyProgramDb
-          Just prog -> snd <$> requireProgram verbosity prog emptyProgramDb
+          Just prog -> snd <$> requireProgram verbosity prog baseProgDb
                        --      ^^ if it fails, it'll fail here
 
         let Just transport = mkTrans progdb
@@ -286,16 +289,17 @@
                     ++ intercalate ", "
                          [ name' | (name', _, _, _ ) <- supportedTransports ]
 
-configureTransport verbosity Nothing = do
+configureTransport verbosity extraPath Nothing = do
     -- the user hasn't selected a transport, so we'll pick the first one we
     -- can configure successfully, provided that it supports tls
 
     -- for all the transports except plain-http we need to try and find
     -- their external executable
+    let baseProgDb = modifyProgramSearchPath (\p -> map ProgramSearchPathDir extraPath ++ p) emptyProgramDb
     progdb <- configureAllKnownPrograms  verbosity $
                 addKnownPrograms
                   [ prog | (_, Just prog, _, _) <- supportedTransports ]
-                  emptyProgramDb
+                  baseProgDb
 
     let availableTransports =
           [ (name, transport)
@@ -541,16 +545,37 @@
     gethttp verbosity uri etag destPath reqHeaders = do
       resp <- runPowershellScript verbosity $
         webclientScript
-          (setupHeaders ((useragentHeader : etagHeader) ++ reqHeaders))
-          [ "$wc.DownloadFile(" ++ escape (show uri)
-              ++ "," ++ escape destPath ++ ");"
-          , "Write-Host \"200\";"
-          , "Write-Host $wc.ResponseHeaders.Item(\"ETag\");"
+          (escape (show uri))
+          (("$targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList " ++ (escape destPath) ++ ", Create")
+          :(setupHeaders ((useragentHeader : etagHeader) ++ reqHeaders)))
+          [ "$response = $request.GetResponse()"
+          , "$responseStream = $response.GetResponseStream()"
+          , "$buffer = new-object byte[] 10KB"
+          , "$count = $responseStream.Read($buffer, 0, $buffer.length)"
+          , "while ($count -gt 0)"
+          , "{"
+          , "    $targetStream.Write($buffer, 0, $count)"
+          , "    $count = $responseStream.Read($buffer, 0, $buffer.length)"
+          , "}"
+          , "Write-Host ($response.StatusCode -as [int]);"
+          , "Write-Host $response.GetResponseHeader(\"ETag\").Trim('\"')"
           ]
+          [ "$targetStream.Flush()"
+          , "$targetStream.Close()"
+          , "$targetStream.Dispose()"
+          , "$responseStream.Dispose()"
+          ]
       parseResponse resp
       where
-        parseResponse x = case readMaybe . unlines . take 1 . lines $ trim x of
-          Just i  -> return (i, Nothing) -- TODO extract real etag
+        parseResponse :: String -> IO (HttpCode, Maybe ETag)
+        parseResponse x =
+          case lines $ trim x of
+            (code:etagv:_) -> fmap (\c -> (c, Just etagv)) $ parseCode code x
+            (code:      _) -> fmap (\c -> (c, Nothing  )) $ parseCode code x
+            _              -> statusParseFail verbosity uri x
+        parseCode :: String -> String -> IO HttpCode
+        parseCode code x = case readMaybe code of
+          Just i  -> return i
           Nothing -> statusParseFail verbosity uri x
         etagHeader = [ Header HdrIfNoneMatch t | t <- maybeToList etag ]
 
@@ -567,15 +592,19 @@
         let contentHeader = Header HdrContentType
               ("multipart/form-data; boundary=" ++ boundary)
         resp <- runPowershellScript verbosity $ webclientScript
+          (escape (show uri))
           (setupHeaders (contentHeader : extraHeaders) ++ setupAuth auth)
           (uploadFileAction "POST" uri fullPath)
+          uploadFileCleanup
         parseUploadResponse verbosity uri resp
 
     puthttpfile verbosity uri path auth headers = do
       fullPath <- canonicalizePath path
       resp <- runPowershellScript verbosity $ webclientScript
+        (escape (show uri))
         (setupHeaders (extraHeaders ++ headers) ++ setupAuth auth)
         (uploadFileAction "PUT" uri fullPath)
+        uploadFileCleanup
       parseUploadResponse verbosity uri resp
 
     runPowershellScript verbosity script = do
@@ -587,6 +616,7 @@
             , "-NoProfile", "-NonInteractive"
             , "-Command", "-"
             ]
+      debug verbosity script
       getProgramInvocationOutput verbosity (programInvocation prog args)
         { progInvokeInput = Just (script ++ "\nExit(0);")
         }
@@ -597,31 +627,74 @@
     extraHeaders = [Header HdrAccept "text/plain", useragentHeader]
 
     setupHeaders headers =
-      [ "$wc.Headers.Add(" ++ escape (show name) ++ "," ++ escape value ++ ");"
+      [ "$request." ++ addHeader name value
       | Header name value <- headers
       ]
+      where
+        addHeader header value
+          = case header of
+              HdrAccept           -> "Accept = "           ++ escape value
+              HdrUserAgent        -> "UserAgent = "        ++ escape value
+              HdrConnection       -> "Connection = "       ++ escape value
+              HdrContentLength    -> "ContentLength = "    ++ escape value
+              HdrContentType      -> "ContentType = "      ++ escape value
+              HdrDate             -> "Date = "             ++ escape value
+              HdrExpect           -> "Expect = "           ++ escape value
+              HdrHost             -> "Host = "             ++ escape value
+              HdrIfModifiedSince  -> "IfModifiedSince = "  ++ escape value
+              HdrReferer          -> "Referer = "          ++ escape value
+              HdrTransferEncoding -> "TransferEncoding = " ++ escape value
+              HdrRange            -> let (start, _:end) =
+                                          if "bytes=" `isPrefixOf` value
+                                             then break (== '-') value'
+                                             else error $ "Could not decode range: " ++ value
+                                         value' = drop 6 value
+                                     in "AddRange(\"bytes\", " ++ escape start ++ ", " ++ escape end ++ ");"
+              name                -> "Headers.Add(" ++ escape (show name) ++ "," ++ escape value ++ ");"
 
     setupAuth auth =
-      [ "$wc.Credentials = new-object System.Net.NetworkCredential("
+      [ "$request.Credentials = new-object System.Net.NetworkCredential("
           ++ escape uname ++ "," ++ escape passwd ++ ",\"\");"
       | (uname,passwd) <- maybeToList auth
       ]
 
-    uploadFileAction method uri fullPath =
-      [ "$fileBytes = [System.IO.File]::ReadAllBytes(" ++ escape fullPath ++ ");"
-      , "$bodyBytes = $wc.UploadData(" ++ escape (show uri) ++ ","
-        ++ show method ++ ", $fileBytes);"
-      , "Write-Host \"200\";"
-      , "Write-Host (-join [System.Text.Encoding]::UTF8.GetChars($bodyBytes));"
+    uploadFileAction method _uri fullPath =
+      [ "$request.Method = " ++ show method
+      , "$requestStream = $request.GetRequestStream()"
+      , "$fileStream = [System.IO.File]::OpenRead(" ++ escape fullPath ++ ")"
+      , "$bufSize=10000"
+      , "$chunk = New-Object byte[] $bufSize"
+      , "while( $bytesRead = $fileStream.Read($chunk,0,$bufsize) )"
+      , "{"
+      , "  $requestStream.write($chunk, 0, $bytesRead)"
+      , "  $requestStream.Flush()"
+      , "}"
+      , ""
+      , "$responseStream = $request.getresponse()"
+      , "$responseReader = new-object System.IO.StreamReader $responseStream.GetResponseStream()"
+      , "$code = $response.StatusCode -as [int]"
+      , "if ($code -eq 0) {"
+      , "  $code = 200;"
+      , "}"
+      , "Write-Host $code"
+      , "Write-Host $responseReader.ReadToEnd()"
       ]
 
+    uploadFileCleanup =
+      [ "$fileStream.Close()"
+      , "$requestStream.Close()"
+      , "$responseStream.Close()"
+      ]
+
     parseUploadResponse verbosity uri resp = case lines (trim resp) of
       (codeStr : message)
         | Just code <- readMaybe codeStr -> return (code, unlines message)
       _ -> statusParseFail verbosity uri resp
 
-    webclientScript setup action = unlines
-      [ "$wc = new-object system.net.webclient;"
+    webclientScript uri setup action cleanup = unlines
+      [ "[Net.ServicePointManager]::SecurityProtocol = \"tls12, tls11, tls\""
+      , "$uri = New-Object \"System.Uri\" " ++ uri
+      , "$request = [System.Net.HttpWebRequest]::Create($uri)"
       , unlines setup
       , "Try {"
       , unlines (map ("  " ++) action)
@@ -639,6 +712,8 @@
       , "  }"
       , "} Catch {"
       , "  Write-Host $_.Exception.Message;"
+      , "} finally {"
+      , unlines (map ("  " ++) cleanup)
       , "}"
       ]
 
diff --git a/cabal/cabal-install/Distribution/Client/IndexUtils.hs b/cabal/cabal-install/Distribution/Client/IndexUtils.hs
--- a/cabal/cabal-install/Distribution/Client/IndexUtils.hs
+++ b/cabal/cabal-install/Distribution/Client/IndexUtils.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE GADTs #-}
 
 -----------------------------------------------------------------------------
@@ -19,6 +20,7 @@
 module Distribution.Client.IndexUtils (
   getIndexFileAge,
   getInstalledPackages,
+  indexBaseName,
   Configure.getInstalledPackagesMonitorFiles,
   getSourcePackages,
   getSourcePackagesMonitorFiles,
@@ -55,7 +57,8 @@
 import Distribution.Types.Dependency
 import Distribution.Simple.PackageIndex (InstalledPackageIndex)
 import Distribution.PackageDescription
-         ( GenericPackageDescription )
+         ( GenericPackageDescription(..)
+         , PackageDescription(..), emptyPackageDescription )
 import Distribution.Simple.Compiler
          ( Compiler, PackageDBStack )
 import Distribution.Simple.Program
@@ -63,7 +66,7 @@
 import qualified Distribution.Simple.Configure as Configure
          ( getInstalledPackages, getInstalledPackagesMonitorFiles )
 import Distribution.Version
-         ( mkVersion, intersectVersionRanges )
+         ( Version, mkVersion, intersectVersionRanges )
 import Distribution.Text
          ( display, simpleParse )
 import Distribution.Simple.Utils
@@ -72,7 +75,7 @@
          ( RepoContext(..) )
 
 import Distribution.PackageDescription.Parsec
-         ( parseGenericPackageDescriptionMaybe )
+         ( parseGenericPackageDescription, parseGenericPackageDescriptionMaybe )
 import qualified Distribution.PackageDescription.Parsec as PackageDesc.Parse
 
 import           Distribution.Solver.Types.PackageIndex (PackageIndex)
@@ -280,12 +283,12 @@
     packagePreferences = prefs'
   }
 
-readCacheStrict :: Verbosity -> Index -> (PackageEntry -> pkg) -> IO ([pkg], [Dependency])
+readCacheStrict :: NFData pkg => Verbosity -> Index -> (PackageEntry -> pkg) -> IO ([pkg], [Dependency])
 readCacheStrict verbosity index mkPkg = do
     updateRepoIndexCache verbosity index
     cache <- readIndexCache verbosity index
     withFile (indexFile index) ReadMode $ \indexHnd ->
-      packageListFromCache verbosity mkPkg indexHnd cache ReadPackageIndexStrict
+      evaluate . force =<< packageListFromCache verbosity mkPkg indexHnd cache
 
 -- | Read a repository index from disk, from the local file specified by
 -- the 'Repo'.
@@ -638,9 +641,6 @@
     toCache (Pkg (BuildTreeRef refType _ _ _ blockNo)) = CacheBuildTreeRef refType blockNo
     toCache (Dep d) = CachePreference d 0 nullTimestamp
 
-data ReadPackageIndexMode = ReadPackageIndexStrict
-                          | ReadPackageIndexLazyIO
-
 readPackageIndexCacheFile :: Package pkg
                           => Verbosity
                           -> (PackageEntry -> pkg)
@@ -651,7 +651,7 @@
     cache0    <- readIndexCache verbosity index
     indexHnd <- openFile (indexFile index) ReadMode
     let (cache,isi) = filterCache idxState cache0
-    (pkgs,deps) <- packageIndexFromCache verbosity mkPkg indexHnd cache ReadPackageIndexLazyIO
+    (pkgs,deps) <- packageIndexFromCache verbosity mkPkg indexHnd cache
     pure (pkgs,deps,isi)
 
 
@@ -660,10 +660,9 @@
                      -> (PackageEntry -> pkg)
                       -> Handle
                       -> Cache
-                      -> ReadPackageIndexMode
                       -> IO (PackageIndex pkg, [Dependency])
-packageIndexFromCache verbosity mkPkg hnd cache mode = do
-     (pkgs, prefs) <- packageListFromCache verbosity mkPkg hnd cache mode
+packageIndexFromCache verbosity mkPkg hnd cache = do
+     (pkgs, prefs) <- packageListFromCache verbosity mkPkg hnd cache
      pkgIndex <- evaluate $ PackageIndex.fromList pkgs
      return (pkgIndex, prefs)
 
@@ -680,9 +679,8 @@
                      -> (PackageEntry -> pkg)
                      -> Handle
                      -> Cache
-                     -> ReadPackageIndexMode
                      -> IO ([pkg], [Dependency])
-packageListFromCache verbosity mkPkg hnd Cache{..} mode = accum mempty [] mempty cacheEntries
+packageListFromCache verbosity mkPkg hnd Cache{..} = accum mempty [] mempty cacheEntries
   where
     accum !srcpkgs btrs !prefs [] = return (Map.elems srcpkgs ++ btrs, Map.elems prefs)
 
@@ -693,11 +691,9 @@
       -- Most of the time we only need the package id.
       ~(pkg, pkgtxt) <- unsafeInterleaveIO $ do
         pkgtxt <- getEntryContent blockno
-        pkg    <- readPackageDescription pkgtxt
+        pkg    <- readPackageDescription pkgid pkgtxt
         return (pkg, pkgtxt)
-      case mode of
-        ReadPackageIndexLazyIO -> pure ()
-        ReadPackageIndexStrict -> evaluate pkg *> evaluate pkgtxt *> pure ()
+
       let srcpkg = mkPkg (NormalPackage pkgid pkg pkgtxt blockno)
       accum (Map.insert pkgid srcpkg srcpkgs) btrs prefs entries
 
@@ -725,16 +721,37 @@
           -> return content
         _ -> interror "unexpected tar entry type"
 
-    readPackageDescription :: ByteString -> IO GenericPackageDescription
-    readPackageDescription content =
-      case parseGenericPackageDescriptionMaybe (BS.toStrict content) of
-        Just gpd -> return gpd
-        Nothing  -> interror "failed to parse .cabal file"
+    readPackageDescription :: PackageIdentifier -> ByteString -> IO GenericPackageDescription
+    readPackageDescription pkgid content =
+      case snd $ PackageDesc.Parse.runParseResult $ parseGenericPackageDescription $ BS.toStrict content of
+        Right gpd                                           -> return gpd
+        Left (Just specVer, _) | specVer >= mkVersion [2,2] -> return (dummyPackageDescription specVer)
+        Left _                                              -> interror "failed to parse .cabal file"
+      where
+        dummyPackageDescription :: Version -> GenericPackageDescription
+        dummyPackageDescription specVer = GenericPackageDescription
+            { packageDescription = emptyPackageDescription
+                                   { specVersionRaw = Left specVer
+                                   , package        = pkgid
+                                   , synopsis       = dummySynopsis
+                                   }
+            , genPackageFlags  = []
+            , condLibrary      = Nothing
+            , condSubLibraries = []
+            , condForeignLibs  = []
+            , condExecutables  = []
+            , condTestSuites   = []
+            , condBenchmarks   = []
+            }
 
+        dummySynopsis = "<could not be parsed due to unsupported CABAL spec-version>"
+
     interror :: String -> IO a
     interror msg = die' verbosity $ "internal error when reading package index: " ++ msg
                       ++ "The package index or index cache is probably "
                       ++ "corrupt. Running 'hackport update' might fix it."
+
+
 
 ------------------------------------------------------------------------
 -- Index cache data structure
diff --git a/cabal/cabal-install/Distribution/Client/Init.hs b/cabal/cabal-install/Distribution/Client/Init.hs
--- a/cabal/cabal-install/Distribution/Client/Init.hs
+++ b/cabal/cabal-install/Distribution/Client/Init.hs
@@ -17,7 +17,6 @@
 
     -- * Commands
     initCabal
-  , pvpize
   , incVersion
 
   ) where
@@ -48,7 +47,7 @@
 import Text.PrettyPrint hiding (mode, cat)
 
 import Distribution.Version
-  ( Version, mkVersion, alterVersion
+  ( Version, mkVersion, alterVersion, versionNumbers, majorBoundVersion
   , orLaterVersion, earlierVersion, intersectVersionRanges, VersionRange )
 import Distribution.Verbosity
   ( Verbosity )
@@ -70,12 +69,15 @@
     scanForModules, neededBuildPrograms )
 
 import Distribution.License
-  ( License(..), knownLicenses )
+  ( License(..), knownLicenses, licenseToSPDX )
+import qualified Distribution.SPDX as SPDX
 
 import Distribution.ReadE
   ( runReadE, readP_to_E )
 import Distribution.Simple.Setup
   ( Flag(..), flagToMaybe )
+import Distribution.Simple.Utils
+  ( dropWhileEndLE )
 import Distribution.Simple.Configure
   ( getInstalledPackages )
 import Distribution.Simple.Compiler
@@ -86,6 +88,10 @@
   ( InstalledPackageIndex, moduleNameIndex )
 import Distribution.Text
   ( display, Text(..) )
+import Distribution.Pretty
+  ( prettyShow )
+import Distribution.Parsec.Class
+  ( eitherParsec )
 
 import Distribution.Solver.Types.PackageIndex
   ( elemByPackageName )
@@ -132,7 +138,8 @@
 --   user.
 extendFlags :: InstalledPackageIndex -> SourcePackageDb -> InitFlags -> IO InitFlags
 extendFlags pkgIx sourcePkgDb =
-      getPackageName sourcePkgDb
+      getCabalVersion
+  >=> getPackageName sourcePkgDb
   >=> getVersion
   >=> getLicense
   >=> getAuthorInfo
@@ -160,6 +167,30 @@
 maybeToFlag :: Maybe a -> Flag a
 maybeToFlag = maybe NoFlag Flag
 
+defaultCabalVersion :: Version
+defaultCabalVersion = mkVersion [1,10]
+
+displayCabalVersion :: Version -> String
+displayCabalVersion v = case versionNumbers v of
+  [1,10] -> "1.10   (legacy)"
+  [2,0]  -> "2.0    (+ support for Backpack, internal sub-libs, '^>=' operator)"
+  [2,2]  -> "2.2    (+ support for 'common', 'elif', redundant commas, SPDX)"
+  [2,4]  -> "2.4    (+ support for '**' globbing)"
+  _      -> display v
+
+-- | Ask which version of the cabal spec to use.
+getCabalVersion :: InitFlags -> IO InitFlags
+getCabalVersion flags = do
+  cabVer <-     return (flagToMaybe $ cabalVersion flags)
+            ?>> maybePrompt flags (either (const defaultCabalVersion) id `fmap`
+                                  promptList "Please choose version of the Cabal specification to use"
+                                  [mkVersion [1,10], mkVersion [2,0], mkVersion [2,2], mkVersion [2,4]]
+                                  (Just defaultCabalVersion) displayCabalVersion False)
+            ?>> return (Just defaultCabalVersion)
+
+  return $  flags { cabalVersion = maybeToFlag cabVer }
+
+
 -- | Get the package name: use the package directory (supplied, or the current
 --   directory by default) as a guess. It looks at the SourcePackageDb to avoid
 --   using an existing package name.
@@ -207,16 +238,26 @@
   lic <-     return (flagToMaybe $ license flags)
          ?>> fmap (fmap (either UnknownLicense id))
                   (maybePrompt flags
-                    (promptList "Please choose a license" listedLicenses (Just BSD3) display True))
+                    (promptList "Please choose a license" listedLicenses
+                     (Just BSD3) displayLicense True))
 
-  if isLicenseInvalid lic
-    then putStrLn promptInvalidOtherLicenseMsg >> getLicense flags
-    else return $ flags { license = maybeToFlag lic }
+  case checkLicenseInvalid lic of
+    Just msg -> putStrLn msg >> getLicense flags
+    Nothing  -> return $ flags { license = maybeToFlag lic }
 
   where
-    isLicenseInvalid (Just (UnknownLicense t)) = any (not . isAlphaNum) t
-    isLicenseInvalid _ = False
+    displayLicense l | needSpdx  = prettyShow (licenseToSPDX l)
+                     | otherwise = display l
 
+    checkLicenseInvalid (Just (UnknownLicense t))
+      | needSpdx  = case eitherParsec t :: Either String SPDX.License of
+                      Right _ -> Nothing
+                      Left _  -> Just "\nThe license must be a valid SPDX expression."
+      | otherwise = if any (not . isAlphaNum) t
+                    then Just promptInvalidOtherLicenseMsg
+                    else Nothing
+    checkLicenseInvalid _ = Nothing
+
     promptInvalidOtherLicenseMsg = "\nThe license must be alphanumeric. " ++
                                    "If your license name has many words, " ++
                                    "the convention is to use camel case (e.g. PublicDomain). " ++
@@ -226,6 +267,8 @@
       knownLicenses \\ [GPL Nothing, LGPL Nothing, AGPL Nothing
                        , Apache Nothing, OtherLicense]
 
+    needSpdx = maybe False (>= mkVersion [2,2]) $ flagToMaybe (cabalVersion flags)
+
 -- | The author's name and email. Prompt, or try to guess from an existing
 --   darcs repo.
 getAuthorInfo :: InitFlags -> IO InitFlags
@@ -286,7 +329,7 @@
   return $ flags { extraSrc = extraSrcFiles }
 
 defaultChangeLog :: FilePath
-defaultChangeLog = "ChangeLog.md"
+defaultChangeLog = "CHANGELOG.md"
 
 -- | Try to guess things to include in the extra-source-files field.
 --   For now, we just look for things in the root directory named
@@ -478,24 +521,31 @@
   where
     pkgGroups = groupBy ((==) `on` P.pkgName) (map P.packageId ps)
 
+    desugar = maybe True (< mkVersion [2]) $ flagToMaybe (cabalVersion flags)
+
     -- Given a list of available versions of the same package, pick a dependency.
     toDep :: [P.PackageIdentifier] -> IO P.Dependency
 
     -- If only one version, easy.  We change e.g. 0.4.2  into  0.4.*
-    toDep [pid] = return $ P.Dependency (P.pkgName pid) (pvpize . P.pkgVersion $ pid)
+    toDep [pid] = return $ P.Dependency (P.pkgName pid) (pvpize desugar . P.pkgVersion $ pid)
 
     -- Otherwise, choose the latest version and issue a warning.
     toDep pids  = do
       message flags ("\nWarning: multiple versions of " ++ display (P.pkgName . head $ pids) ++ " provide " ++ display m ++ ", choosing the latest.")
       return $ P.Dependency (P.pkgName . head $ pids)
-                            (pvpize . maximum . map P.pkgVersion $ pids)
+                            (pvpize desugar . maximum . map P.pkgVersion $ pids)
 
 -- | Given a version, return an API-compatible (according to PVP) version range.
 --
--- Example: @0.4.1@ produces the version range @>= 0.4 && < 0.5@ (which is the
+-- If the boolean argument denotes whether to use a desugared
+-- representation (if 'True') or the new-style @^>=@-form (if
+-- 'False').
+--
+-- Example: @pvpize True (mkVersion [0,4,1])@ produces the version range @>= 0.4 && < 0.5@ (which is the
 -- same as @0.4.*@).
-pvpize :: Version -> VersionRange
-pvpize v = orLaterVersion v'
+pvpize :: Bool -> Version -> VersionRange
+pvpize False  v = majorBoundVersion v
+pvpize True   v = orLaterVersion v'
            `intersectVersionRanges`
            earlierVersion (incVersion 1 v')
   where v' = alterVersion (take 2) v
@@ -799,12 +849,19 @@
 --   structure onto a low-level AST structure and use the existing
 --   pretty-printing code to generate the file.
 generateCabalFile :: String -> InitFlags -> String
-generateCabalFile fileName c =
+generateCabalFile fileName c = trimTrailingWS $
   (++ "\n") .
   renderStyle style { lineLength = 79, ribbonsPerLine = 1.1 } $
+  -- Starting with 2.2 the `cabal-version` field needs to be the first line of the PD
+  (if specVer < mkVersion [1,12]
+   then field "cabal-version" (Flag $ orLaterVersion specVer) -- legacy
+   else field "cabal-version" (Flag $ specVer))
+              Nothing -- NB: the first line must be the 'cabal-version' declaration
+              False
+  $$
   (if minimal c /= Flag True
-    then showComment (Just $ "Initial " ++ fileName ++ " generated by cabal "
-                          ++ "init.  For further documentation, see "
+    then showComment (Just $ "Initial package description '" ++ fileName ++ "' generated "
+                          ++ "by 'cabal init'.  For further documentation, see "
                           ++ "http://haskell.org/cabal/users-guide/")
          $$ text ""
     else empty)
@@ -814,7 +871,7 @@
                 True
 
        , field  "version"       (version       c)
-                (Just $ "The package version.  See the Haskell package versioning policy (PVP) for standards guiding when and how versions should be incremented.\nhttps://wiki.haskell.org/Package_versioning_policy\n"
+                (Just $ "The package version.  See the Haskell package versioning policy (PVP) for standards guiding when and how versions should be incremented.\nhttps://pvp.haskell.org\n"
                 ++ "PVP summary:      +-+------- breaking API changes\n"
                 ++ "                  | | +----- non-breaking API additions\n"
                 ++ "                  | | | +--- code changes with no API change")
@@ -834,9 +891,9 @@
 
        , fieldS "bug-reports"   NoFlag
                 (Just "A URL where users can report bugs.")
-                False
+                True
 
-       , field  "license"       (license      c)
+       , fieldS  "license"      licenseStr
                 (Just "The license under which the package is released.")
                 True
 
@@ -864,18 +921,14 @@
                 Nothing
                 True
 
-       , fieldS "build-type"    (Flag "Simple")
+       , fieldS "build-type"    (if specVer >= mkVersion [2,2] then NoFlag else Flag "Simple")
                 Nothing
-                True
+                False
 
        , fieldS "extra-source-files" (listFieldS (extraSrc c))
                 (Just "Extra files to be distributed with the package, such as examples or a README.")
                 True
 
-       , field  "cabal-version" (Flag $ orLaterVersion (mkVersion [1,10]))
-                (Just "Constraint on the version of Cabal needed to build this package.")
-                False
-
        , case packageType c of
            Flag Executable -> executableStanza
            Flag Library    -> libraryStanza
@@ -883,6 +936,14 @@
            _               -> empty
        ]
  where
+   specVer = fromMaybe defaultCabalVersion $ flagToMaybe (cabalVersion c)
+
+   licenseStr | specVer < mkVersion [2,2] = prettyShow `fmap` license c
+              | otherwise                 = go `fmap` license c
+     where
+       go (UnknownLicense s) = s
+       go l                  = prettyShow (licenseToSPDX l)
+
    generateBuildInfo :: BuildType -> InitFlags -> Doc
    generateBuildInfo buildType c' = vcat
      [ fieldS "other-modules" (listField (otherModules c'))
@@ -958,6 +1019,9 @@
    breakLine  cs = case break (==' ') cs of (w,cs') -> w : breakLine' cs'
    breakLine' [] = []
    breakLine' cs = case span (==' ') cs of (w,cs') -> w : breakLine cs'
+
+   trimTrailingWS :: String -> String
+   trimTrailingWS = unlines . map (dropWhileEndLE isSpace) . lines
 
    executableStanza :: Doc
    executableStanza = text "\nexecutable" <+>
diff --git a/cabal/cabal-install/Distribution/Client/Init/Types.hs b/cabal/cabal-install/Distribution/Client/Init/Types.hs
--- a/cabal/cabal-install/Distribution/Client/Init/Types.hs
+++ b/cabal/cabal-install/Distribution/Client/Init/Types.hs
@@ -47,7 +47,7 @@
 
               , packageName  :: Flag P.PackageName
               , version      :: Flag Version
-              , cabalVersion :: Flag VersionRange
+              , cabalVersion :: Flag Version
               , license      :: Flag License
               , author       :: Flag String
               , email        :: Flag String
@@ -68,6 +68,8 @@
               , dependencies :: Maybe [P.Dependency]
               , sourceDirs   :: Maybe [String]
               , buildTools   :: Maybe [String]
+
+              , initHcPath    :: Flag FilePath
 
               , initVerbosity :: Flag Verbosity
               , overwrite     :: Flag Bool
diff --git a/cabal/cabal-install/Distribution/Client/Install.hs b/cabal/cabal-install/Distribution/Client/Install.hs
--- a/cabal/cabal-install/Distribution/Client/Install.hs
+++ b/cabal/cabal-install/Distribution/Client/Install.hs
@@ -80,7 +80,7 @@
          , ConfigFlags(..), configureCommand, filterConfigureFlags
          , ConfigExFlags(..), InstallFlags(..) )
 import Distribution.Client.Config
-         ( defaultCabalDir, defaultUserInstall )
+         ( getCabalDir, defaultUserInstall )
 import Distribution.Client.Sandbox.Timestamp
          ( withUpdateTimestamps )
 import Distribution.Client.Sandbox.Types
@@ -96,7 +96,7 @@
 import qualified Distribution.Client.BuildReports.Storage as BuildReports
          ( storeAnonymous, storeLocal, fromInstallPlan, fromPlanningFailure )
 import qualified Distribution.Client.InstallSymlink as InstallSymlink
-         ( symlinkBinaries )
+         ( OverwritePolicy(..), symlinkBinaries )
 import qualified Distribution.Client.Win32SelfUpgrade as Win32SelfUpgrade
 import qualified Distribution.Client.World as World
 import qualified Distribution.InstalledPackageInfo as Installed
@@ -160,9 +160,9 @@
          , withTempDirectory )
 import Distribution.Client.Utils
          ( determineNumJobs, logDirChange, mergeBy, MergeResult(..)
-         , tryCanonicalizePath )
+         , tryCanonicalizePath, ProgressPhase(..), progressMessage )
 import Distribution.System
-         ( Platform, OS(Windows), buildOS )
+         ( Platform, OS(Windows), buildOS, buildPlatform )
 import Distribution.Text
          ( display )
 import Distribution.Verbosity as Verbosity
@@ -337,7 +337,7 @@
 
     unless (dryRun || nothingToInstall) $ do
       buildOutcomes <- performInstallations verbosity
-                         args installedPkgIndex installPlan
+                       args installedPkgIndex installPlan
       postInstallActions verbosity args userTargets installPlan buildOutcomes
   where
     installPlan = InstallPlan.configureInstallPlan configFlags installPlan0
@@ -821,6 +821,9 @@
   ,globalFlags, configFlags, _, installFlags, _)
   targets installPlan buildOutcomes = do
 
+  updateSandboxTimestampsFile verbosity useSandbox mSandboxPkgInfo
+                              comp platform installPlan buildOutcomes
+
   unless oneShot $
     World.insert verbosity worldFile
       --FIXME: does not handle flags
@@ -846,9 +849,6 @@
 
   printBuildFailures verbosity buildOutcomes
 
-  updateSandboxTimestampsFile verbosity useSandbox mSandboxPkgInfo
-                              comp platform installPlan buildOutcomes
-
   where
     reportingLevel = fromFlag (installBuildReports installFlags)
     logsDir        = fromFlag (globalLogsDir globalFlags)
@@ -858,7 +858,7 @@
 storeDetailedBuildReports :: Verbosity -> FilePath
                           -> [(BuildReports.BuildReport, Maybe Repo)] -> IO ()
 storeDetailedBuildReports verbosity logsDir reports = sequence_
-  [ do dotCabal <- defaultCabalDir
+  [ do dotCabal <- getCabalDir
        let logFileName = display (BuildReports.package report) <.> "log"
            logFile     = logsDir </> logFileName
            reportsDir  = dotCabal </> "reports" </> remoteRepoName remoteRepo
@@ -962,6 +962,7 @@
 symlinkBinaries verbosity platform comp configFlags installFlags
                 plan buildOutcomes = do
   failed <- InstallSymlink.symlinkBinaries platform comp
+                                           InstallSymlink.NeverOverwrite
                                            configFlags installFlags
                                            plan buildOutcomes
   case failed of
@@ -1197,7 +1198,7 @@
     -- otherwise.
     printBuildResult :: PackageId -> UnitId -> BuildOutcome -> IO ()
     printBuildResult pkgid uid buildOutcome = case buildOutcome of
-        (Right _) -> notice verbosity $ "Installed " ++ display pkgid
+        (Right _) -> progressMessage verbosity ProgressCompleted (display pkgid)
         (Left _)  -> do
           notice verbosity $ "Failed to install " ++ display pkgid
           when (verbosity >= normal) $
@@ -1285,6 +1286,9 @@
     LocalUnpackedPackage dir ->
       installPkg (Just dir)
 
+    RemoteSourceRepoPackage _repo dir ->
+      installPkg (Just dir)
+
     LocalTarballPackage tarballPath ->
       installLocalTarballPackage verbosity
         pkgid tarballPath distPref installPkg
@@ -1297,7 +1301,6 @@
       installLocalTarballPackage verbosity
         pkgid tarballPath distPref installPkg
 
-
 installLocalTarballPackage
   :: Verbosity
   -> PackageIdentifier -> FilePath -> FilePath
@@ -1396,14 +1399,12 @@
   logDirChange (maybe (const (return ())) appendFile mLogPath) workingDir $ do
     -- Configure phase
     onFailure ConfigureFailed $ do
-      when (numJobs > 1) $ notice verbosity $
-        "Configuring " ++ display pkgid ++ "..."
+      noticeProgress ProgressStarting
       setup configureCommand configureFlags mLogPath
 
     -- Build phase
       onFailure BuildFailed $ do
-        when (numJobs > 1) $ notice verbosity $
-          "Building " ++ display pkgid ++ "..."
+        noticeProgress ProgressBuilding
         setup buildCommand' buildFlags mLogPath
 
     -- Doc generation phase
@@ -1450,6 +1451,12 @@
     uid              = installedUnitId rpkg
     cinfo            = compilerInfo comp
     buildCommand'    = buildCommand progdb
+    dispname         = display pkgid
+    isParallelBuild  = numJobs >= 2
+
+    noticeProgress phase = when isParallelBuild $
+        progressMessage verbosity phase dispname
+
     buildFlags   _   = emptyBuildFlags {
       buildDistPref  = configDistPref configFlags,
       buildVerbosity = toFlag verbosity'
@@ -1551,7 +1558,7 @@
           scriptOptions { useLoggingHandle = logFileHandle
                         , useWorkingDir    = workingDir }
           (Just pkg)
-          cmd flags [])
+          cmd flags (const []))
 
 
 -- helper
@@ -1593,7 +1600,7 @@
     (CompilerId compFlavor _) = compilerInfoId cinfo
 
     exeInstallPaths defaultDirs =
-      [ InstallDirs.bindir absoluteDirs </> exeName <.> exeExtension
+      [ InstallDirs.bindir absoluteDirs </> exeName <.> exeExtension buildPlatform
       | exe <- PackageDescription.executables pkg
       , PackageDescription.buildable (PackageDescription.buildInfo exe)
       , let exeName = prefix ++ display (PackageDescription.exeName exe) ++ suffix
diff --git a/cabal/cabal-install/Distribution/Client/InstallPlan.hs b/cabal/cabal-install/Distribution/Client/InstallPlan.hs
--- a/cabal/cabal-install/Distribution/Client/InstallPlan.hs
+++ b/cabal/cabal-install/Distribution/Client/InstallPlan.hs
@@ -62,6 +62,7 @@
   showInstallPlan,
 
   -- * Graph-like operations
+  dependencyClosure,
   reverseTopologicalOrder,
   reverseDependencyClosure,
   ) where
@@ -402,6 +403,15 @@
                         -> [GenericPlanPackage ipkg srcpkg]
 reverseTopologicalOrder plan = Graph.revTopSort (planGraph plan)
 
+
+-- | Return the packages in the plan that are direct or indirect dependencies of
+-- the given packages.
+--
+dependencyClosure :: GenericInstallPlan ipkg srcpkg
+                  -> [UnitId]
+                  -> [GenericPlanPackage ipkg srcpkg]
+dependencyClosure plan = fromMaybe []
+                       . Graph.closure (planGraph plan)
 
 -- | Return the packages in the plan that depend directly or indirectly on the
 -- given packages.
diff --git a/cabal/cabal-install/Distribution/Client/InstallSymlink.hs b/cabal/cabal-install/Distribution/Client/InstallSymlink.hs
--- a/cabal/cabal-install/Distribution/Client/InstallSymlink.hs
+++ b/cabal/cabal-install/Distribution/Client/InstallSymlink.hs
@@ -12,6 +12,7 @@
 -- Managing installing binaries with symlinks.
 -----------------------------------------------------------------------------
 module Distribution.Client.InstallSymlink (
+    OverwritePolicy(..),
     symlinkBinaries,
     symlinkBinary,
   ) where
@@ -27,16 +28,22 @@
 import Distribution.Simple.Compiler
 import Distribution.System
 
+data OverwritePolicy = NeverOverwrite | AlwaysOverwrite
+  deriving (Show, Eq)
+
 symlinkBinaries :: Platform -> Compiler
+                -> OverwritePolicy
                 -> ConfigFlags
                 -> InstallFlags
                 -> InstallPlan
                 -> BuildOutcomes
                 -> IO [(PackageIdentifier, UnqualComponentName, FilePath)]
-symlinkBinaries _ _ _ _ _ _ = return []
+symlinkBinaries _ _ _ _ _ _ _ = return []
 
-symlinkBinary :: FilePath -> FilePath -> UnqualComponentName -> String -> IO Bool
-symlinkBinary _ _ _ _ = fail "Symlinking feature not available on Windows"
+symlinkBinary :: OverwritePolicy
+              -> FilePath -> FilePath -> UnqualComponentName -> String
+              -> IO Bool
+symlinkBinary _ _ _ _ _ = fail "Symlinking feature not available on Windows"
 
 #else
 
@@ -87,6 +94,9 @@
 import Data.Maybe
          ( catMaybes )
 
+data OverwritePolicy = NeverOverwrite | AlwaysOverwrite
+  deriving (Show, Eq)
+
 -- | We would like by default to install binaries into some location that is on
 -- the user's PATH. For per-user installations on Unix systems that basically
 -- means the @~/bin/@ directory. On the majority of platforms the @~/bin/@
@@ -108,12 +118,15 @@
 -- with symlinks so is not available to Windows users.
 --
 symlinkBinaries :: Platform -> Compiler
+                -> OverwritePolicy
                 -> ConfigFlags
                 -> InstallFlags
                 -> InstallPlan
                 -> BuildOutcomes
                 -> IO [(PackageIdentifier, UnqualComponentName, FilePath)]
-symlinkBinaries platform comp configFlags installFlags plan buildOutcomes =
+symlinkBinaries platform comp overwritePolicy
+                configFlags installFlags
+                plan buildOutcomes =
   case flagToMaybe (installSymlinkBinDir installFlags) of
     Nothing            -> return []
     Just symlinkBinDir
@@ -125,6 +138,7 @@
       fmap catMaybes $ sequence
         [ do privateBinDir <- pkgBinDir pkg ipid
              ok <- symlinkBinary
+                     overwritePolicy
                      publicBinDir  privateBinDir
                      publicExeName privateExeName
              if ok
@@ -187,7 +201,8 @@
     (CompilerId compilerFlavor _) = compilerInfoId cinfo
 
 symlinkBinary ::
-  FilePath               -- ^ The canonical path of the public bin dir eg
+  OverwritePolicy        -- ^ Whether to force overwrite an existing file
+  -> FilePath            -- ^ The canonical path of the public bin dir eg
                          --   @/home/user/bin@
   -> FilePath            -- ^ The canonical path of the private bin dir eg
                          --   @/home/user/.cabal/bin@
@@ -199,13 +214,16 @@
                          --   there was another file there already that we did
                          --   not own. Other errors like permission errors just
                          --   propagate as exceptions.
-symlinkBinary publicBindir privateBindir publicName privateName = do
+symlinkBinary overwritePolicy publicBindir privateBindir publicName privateName = do
   ok <- targetOkToOverwrite (publicBindir </> publicName')
                             (privateBindir </> privateName)
   case ok of
-    NotOurFile    ->                     return False
-    NotExists     ->           mkLink >> return True
-    OkToOverwrite -> rmLink >> mkLink >> return True
+    NotExists         ->           mkLink >> return True
+    OkToOverwrite     -> rmLink >> mkLink >> return True
+    NotOurFile ->
+      case overwritePolicy of
+        NeverOverwrite  ->                     return False
+        AlwaysOverwrite -> rmLink >> mkLink >> return True
   where
     publicName' = display publicName
     relativeBindir = makeRelative publicBindir privateBindir
diff --git a/cabal/cabal-install/Distribution/Client/List.hs b/cabal/cabal-install/Distribution/Client/List.hs
--- a/cabal/cabal-install/Distribution/Client/List.hs
+++ b/cabal/cabal-install/Distribution/Client/List.hs
@@ -26,6 +26,7 @@
          ( Flag(..), unFlagName )
 import Distribution.PackageDescription.Configuration
          ( flattenPackageDescription )
+import Distribution.Pretty (pretty)
 
 import Distribution.Simple.Compiler
         ( Compiler, PackageDBStack )
@@ -42,6 +43,8 @@
 import Distribution.Text
          ( Text(disp), display )
 
+import qualified Distribution.SPDX as SPDX
+
 import           Distribution.Solver.Types.PackageConstraint
 import qualified Distribution.Solver.Types.PackageIndex as PackageIndex
 import           Distribution.Solver.Types.SourcePackage
@@ -280,7 +283,7 @@
     synopsis          :: String,
     description       :: String,
     category          :: String,
-    license           :: License,
+    license           :: Either SPDX.License License,
     author            :: String,
     maintainer        :: String,
     dependencies      :: [ExtDependency],
@@ -316,7 +319,7 @@
          versions             -> dispTopVersions 4
                                    (preferredVersions pkginfo) versions
      , maybeShow (homepage pkginfo) "Homepage:" text
-     , text "License: " <+> text (display (license pkginfo))
+     , text "License: " <+> either pretty pretty (license pkginfo)
      ])
      $+$ text ""
   where
@@ -344,7 +347,7 @@
    , entry "Bug reports"   bugReports   orNotSpecified text
    , entry "Description"   description  hideIfNull     reflowParagraphs
    , entry "Category"      category     hideIfNull     text
-   , entry "License"       license      alwaysShow     disp
+   , entry "License"       license      alwaysShow     (either pretty pretty)
    , entry "Author"        author       hideIfNull     reflowLines
    , entry "Maintainer"    maintainer   hideIfNull     reflowLines
    , entry "Source repo"   sourceRepo   orNotSpecified text
@@ -435,7 +438,7 @@
     sourceVersions    = map packageVersion sourcePkgs,
     preferredVersions = versionPref,
 
-    license      = combine Source.license       source
+    license      = combine Source.licenseRaw    source
                            Installed.license    installed,
     maintainer   = combine Source.maintainer    source
                            Installed.maintainer installed,
@@ -467,7 +470,7 @@
                            source,
     dependencies =
       combine (map (SourceDependency . simplifyDependency)
-               . Source.buildDepends) source
+               . Source.allBuildDepends) source
       (map InstalledDependency . Installed.depends) installed,
     haddockHtml  = fromMaybe "" . join
                  . fmap (listToMaybe . Installed.haddockHTMLs)
diff --git a/cabal/cabal-install/Distribution/Client/Outdated.hs b/cabal/cabal-install/Distribution/Client/Outdated.hs
--- a/cabal/cabal-install/Distribution/Client/Outdated.hs
+++ b/cabal/cabal-install/Distribution/Client/Outdated.hs
@@ -27,12 +27,12 @@
 import Distribution.Solver.Types.PackageIndex
 import Distribution.Client.Sandbox.PackageEnvironment
 
-import Distribution.Package                          (PackageName
-                                                     ,packageVersion)
-import Distribution.PackageDescription               (buildDepends)
+import Distribution.Package                          (PackageName, packageVersion)
+import Distribution.PackageDescription               (allBuildDepends)
 import Distribution.PackageDescription.Configuration (finalizePD)
 import Distribution.Simple.Compiler                  (Compiler, compilerInfo)
-import Distribution.Simple.Setup                     (fromFlagOrDefault)
+import Distribution.Simple.Setup
+       (fromFlagOrDefault, flagToMaybe)
 import Distribution.Simple.Utils
        (die', notice, debug, tryFindPackageDesc)
 import Distribution.System                           (Platform)
@@ -61,6 +61,8 @@
   let freezeFile    = fromFlagOrDefault False (outdatedFreezeFile outdatedFlags)
       newFreezeFile = fromFlagOrDefault False
                       (outdatedNewFreezeFile outdatedFlags)
+      mprojectFile  = flagToMaybe
+                      (outdatedProjectFile outdatedFlags)
       simpleOutput  = fromFlagOrDefault False
                       (outdatedSimpleOutput outdatedFlags)
       quiet         = fromFlagOrDefault False (outdatedQuiet outdatedFlags)
@@ -76,13 +78,17 @@
                           in \pkgname -> pkgname `S.member` minorSet
       verbosity     = if quiet then silent else verbosity0
 
+  when (not newFreezeFile && isJust mprojectFile) $
+    die' verbosity $
+      "--project-file must only be used with --new-freeze-file."
+
   sourcePkgDb <- IndexUtils.getSourcePackages verbosity repoContext
   let pkgIndex = packageIndex sourcePkgDb
   deps <- if freezeFile
           then depsFromFreezeFile verbosity
           else if newFreezeFile
-               then depsFromNewFreezeFile verbosity
-               else depsFromPkgDesc       verbosity comp platform
+               then depsFromNewFreezeFile verbosity mprojectFile
+               else depsFromPkgDesc verbosity comp platform
   debug verbosity $ "Dependencies loaded: "
     ++ (intercalate ", " $ map display deps)
   let outdatedDeps = listOutdated deps pkgIndex
@@ -124,11 +130,10 @@
   return deps
 
 -- | Read the list of dependencies from the new-style freeze file.
-depsFromNewFreezeFile :: Verbosity -> IO [Dependency]
-depsFromNewFreezeFile verbosity = do
+depsFromNewFreezeFile :: Verbosity -> Maybe FilePath -> IO [Dependency]
+depsFromNewFreezeFile verbosity mprojectFile = do
   projectRoot <- either throwIO return =<<
-                 findProjectRoot Nothing
-                 {- TODO: Support '--project-file': -} Nothing
+                 findProjectRoot Nothing mprojectFile
   let distDirLayout = defaultDistDirLayout projectRoot
                       {- TODO: Support dist dir override -} Nothing
   projectConfig  <- runRebuild (distProjectRootDirectory distDirLayout) $
@@ -136,8 +141,8 @@
   let ucnstrs = map fst . projectConfigConstraints . projectConfigShared
                 $ projectConfig
       deps    = userConstraintsToDependencies ucnstrs
-  debug verbosity
-    "Reading the list of dependencies from the new-style freeze file"
+  debug verbosity $
+    "Reading the list of dependencies from the new-style freeze file " ++ distProjectFile distDirLayout "freeze"
   return deps
 
 -- | Read the list of dependencies from the package description.
@@ -152,7 +157,7 @@
   case epd of
     Left _        -> die' verbosity "finalizePD failed"
     Right (pd, _) -> do
-      let bd = buildDepends pd
+      let bd = allBuildDepends pd
       debug verbosity
         "Reading the list of dependencies from the package description"
       return bd
diff --git a/cabal/cabal-install/Distribution/Client/PackageHash.hs b/cabal/cabal-install/Distribution/Client/PackageHash.hs
--- a/cabal/cabal-install/Distribution/Client/PackageHash.hs
+++ b/cabal/cabal-install/Distribution/Client/PackageHash.hs
@@ -1,5 +1,5 @@
-{-# LANGUAGE RecordWildCards, NamedFieldPuns, GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE RecordWildCards, NamedFieldPuns #-}
+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
 
 -- | Functions to calculate nix-style hashes for package ids.
 --
@@ -135,22 +135,22 @@
                     | otherwise     = take (n-1) s ++ "_"
 
 -- | On macOS we shorten the name very aggressively.  The mach-o linker on
--- macOS has a limited load command size, to which the name of the lirbary
--- as well as it's relative path (\@rpath) entry count.  To circumvent this,
+-- macOS has a limited load command size, to which the name of the library
+-- as well as its relative path (\@rpath) entry count.  To circumvent this,
 -- on macOS the libraries are not stored as
 --  @store/<libraryname>/libHS<libraryname>.dylib@
--- where libraryname contains the librarys name, version and abi hash, but in
+-- where libraryname contains the libraries name, version and abi hash, but in
 --  @store/lib/libHS<very short libraryname>.dylib@
 -- where the very short library name drops all vowels from the package name,
 -- and truncates the hash to 4 bytes.
 --
--- We therefore only need one \@rpath entry to @store/lib@ instead of one
+-- We therefore we only need one \@rpath entry to @store/lib@ instead of one
 -- \@rpath entry for each library. And the reduced library name saves some
 -- additional space.
 --
 -- This however has two major drawbacks:
--- 1) Packages can easier collide due to the shortened hash.
--- 2) The lirbaries are *not* prefix relocateable anymore as they all end up
+-- 1) Packages can collide more easily due to the shortened hash.
+-- 2) The libraries are *not* prefix relocatable anymore as they all end up
 --    in the same @store/lib@ folder.
 --
 -- The ultimate solution would have to include generating proxy dynamic
@@ -211,11 +211,25 @@
        pkgHashExtraFrameworkDirs  :: [FilePath],
        pkgHashExtraIncludeDirs    :: [FilePath],
        pkgHashProgPrefix          :: Maybe PathTemplate,
-       pkgHashProgSuffix          :: Maybe PathTemplate
+       pkgHashProgSuffix          :: Maybe PathTemplate,
 
+       -- Haddock options
+       pkgHashDocumentation       :: Bool,
+       pkgHashHaddockHoogle       :: Bool,
+       pkgHashHaddockHtml         :: Bool,
+       pkgHashHaddockHtmlLocation :: Maybe String,
+       pkgHashHaddockForeignLibs  :: Bool,
+       pkgHashHaddockExecutables  :: Bool,
+       pkgHashHaddockTestSuites   :: Bool,
+       pkgHashHaddockBenchmarks   :: Bool,
+       pkgHashHaddockInternal     :: Bool,
+       pkgHashHaddockCss          :: Maybe FilePath,
+       pkgHashHaddockLinkedSource :: Bool,
+       pkgHashHaddockQuickJump    :: Bool,
+       pkgHashHaddockContents     :: Maybe PathTemplate
+
 --     TODO: [required eventually] pkgHashToolsVersions     ?
 --     TODO: [required eventually] pkgHashToolsExtraOptions ?
---     TODO: [research required] and what about docs?
      }
   deriving Show
 
@@ -248,7 +262,7 @@
     -- the default value for that feature. So if we avoid adding entries with
     -- the default value then most of the time adding new features will not
     -- change the hashes of existing packages and so fewer packages will need
-    -- to be rebuilt. 
+    -- to be rebuilt.
 
     --TODO: [nice to have] ultimately we probably want to put this config info
     -- into the ghc-pkg db. At that point this should probably be changed to
@@ -276,8 +290,8 @@
       , opt   "ghci-lib"    False display pkgHashGHCiLib
       , opt   "prof-lib"    False display pkgHashProfLib
       , opt   "prof-exe"    False display pkgHashProfExe
-      , opt   "prof-lib-detail" ProfDetailDefault showProfDetailLevel pkgHashProfLibDetail 
-      , opt   "prof-exe-detail" ProfDetailDefault showProfDetailLevel pkgHashProfExeDetail 
+      , opt   "prof-lib-detail" ProfDetailDefault showProfDetailLevel pkgHashProfLibDetail
+      , opt   "prof-exe-detail" ProfDetailDefault showProfDetailLevel pkgHashProfExeDetail
       , opt   "hpc"          False display pkgHashCoverage
       , opt   "optimisation" NormalOptimisation (show . fromEnum) pkgHashOptimization
       , opt   "split-objs"   False display pkgHashSplitObjs
@@ -290,6 +304,21 @@
       , opt   "extra-include-dirs" [] unwords pkgHashExtraIncludeDirs
       , opt   "prog-prefix" Nothing (maybe "" fromPathTemplate) pkgHashProgPrefix
       , opt   "prog-suffix" Nothing (maybe "" fromPathTemplate) pkgHashProgSuffix
+
+      , opt   "documentation"  False display pkgHashDocumentation
+      , opt   "haddock-hoogle" False display pkgHashHaddockHoogle
+      , opt   "haddock-html"   False display pkgHashHaddockHtml
+      , opt   "haddock-html-location" Nothing (fromMaybe "") pkgHashHaddockHtmlLocation
+      , opt   "haddock-foreign-libraries" False display pkgHashHaddockForeignLibs
+      , opt   "haddock-executables" False display pkgHashHaddockExecutables
+      , opt   "haddock-tests" False display pkgHashHaddockTestSuites
+      , opt   "haddock-benchmarks" False display pkgHashHaddockBenchmarks
+      , opt   "haddock-internal" False display pkgHashHaddockInternal
+      , opt   "haddock-css" Nothing (fromMaybe "") pkgHashHaddockCss
+      , opt   "haddock-hyperlink-source" False display pkgHashHaddockLinkedSource
+      , opt   "haddock-quickjump" False display pkgHashHaddockQuickJump
+      , opt   "haddock-contents-location" Nothing (maybe "" fromPathTemplate) pkgHashHaddockContents
+
       ] ++ Map.foldrWithKey (\prog args acc -> opt (prog ++ "-options") [] unwords args : acc) [] pkgHashProgramArgs
   where
     entry key     format value = Just (key ++ ": " ++ format value)
@@ -315,7 +344,7 @@
 -- package ids.
 
 newtype HashValue = HashValue BS.ByteString
-  deriving (Eq, Show, Typeable)
+  deriving (Eq, Generic, Show, Typeable)
 
 instance Binary HashValue where
   put (HashValue digest) = put digest
@@ -354,4 +383,3 @@
       (hash, trailing) | not (BS.null hash) && BS.null trailing
         -> HashValue hash
       _ -> error "hashFromTUF: cannot decode base16 hash"
-
diff --git a/cabal/cabal-install/Distribution/Client/PackageUtils.hs b/cabal/cabal-install/Distribution/Client/PackageUtils.hs
--- a/cabal/cabal-install/Distribution/Client/PackageUtils.hs
+++ b/cabal/cabal-install/Distribution/Client/PackageUtils.hs
@@ -16,18 +16,20 @@
 
 import Distribution.Package
          ( packageVersion, packageName )
+import Distribution.Types.ComponentRequestedSpec
+         ( ComponentRequestedSpec )
 import Distribution.Types.Dependency
 import Distribution.Types.UnqualComponentName
 import Distribution.PackageDescription
-         ( PackageDescription(..), libName )
+         ( PackageDescription(..), libName, enabledBuildDepends )
 import Distribution.Version
          ( withinRange, isAnyVersion )
 
 -- | The list of dependencies that refer to external packages
 -- rather than internal package components.
 --
-externalBuildDepends :: PackageDescription -> [Dependency]
-externalBuildDepends pkg = filter (not . internal) (buildDepends pkg)
+externalBuildDepends :: PackageDescription -> ComponentRequestedSpec -> [Dependency]
+externalBuildDepends pkg spec = filter (not . internal) (enabledBuildDepends pkg spec)
   where
     -- True if this dependency is an internal one (depends on a library
     -- defined in the same package).
diff --git a/cabal/cabal-install/Distribution/Client/ProjectBuilding.hs b/cabal/cabal-install/Distribution/Client/ProjectBuilding.hs
--- a/cabal/cabal-install/Distribution/Client/ProjectBuilding.hs
+++ b/cabal/cabal-install/Distribution/Client/ProjectBuilding.hs
@@ -60,11 +60,15 @@
 import           Distribution.Client.FetchUtils
 import           Distribution.Client.GlobalFlags (RepoContext)
 import qualified Distribution.Client.Tar as Tar
-import           Distribution.Client.Setup (filterConfigureFlags)
+import           Distribution.Client.Setup
+                   ( filterConfigureFlags, filterHaddockArgs
+                   , filterHaddockFlags )
 import           Distribution.Client.SourceFiles
 import           Distribution.Client.SrcDist (allPackageSourceFiles)
-import           Distribution.Client.Utils (removeExistingFile)
+import           Distribution.Client.Utils
+                   ( ProgressPhase(..), progressMessage, removeExistingFile )
 
+import           Distribution.Compat.Lens
 import           Distribution.Package hiding (InstalledPackageId, installedPackageId)
 import qualified Distribution.PackageDescription as PD
 import           Distribution.InstalledPackageInfo (InstalledPackageInfo)
@@ -72,15 +76,16 @@
 import           Distribution.Simple.BuildPaths (haddockDirName)
 import qualified Distribution.Simple.InstallDirs as InstallDirs
 import           Distribution.Types.BuildType
+import           Distribution.Types.PackageDescription.Lens (componentModules)
 import           Distribution.Simple.Program
 import qualified Distribution.Simple.Setup as Cabal
 import           Distribution.Simple.Command (CommandUI)
 import qualified Distribution.Simple.Register as Cabal
-import           Distribution.Simple.LocalBuildInfo (ComponentName)
+import           Distribution.Simple.LocalBuildInfo (ComponentName(..))
 import           Distribution.Simple.Compiler
                    ( Compiler, compilerId, PackageDB(..) )
 
-import           Distribution.Simple.Utils hiding (matchFileGlob)
+import           Distribution.Simple.Utils
 import           Distribution.Version
 import           Distribution.Verbosity
 import           Distribution.Text
@@ -96,6 +101,7 @@
 
 import           Control.Monad
 import           Control.Exception
+import           Data.Function (on)
 import           Data.Maybe
 
 import           System.FilePath
@@ -203,6 +209,11 @@
           -- artifacts under the shared dist directory.
           dryRunLocalPkg pkg depsBuildStatus srcdir
 
+        Just (RemoteSourceRepoPackage _repo srcdir) ->
+          -- At this point, source repos are essentially the same as local
+          -- dirs, since we've already download them.
+          dryRunLocalPkg pkg depsBuildStatus srcdir
+
         -- The three tarball cases are handled the same as each other,
         -- though depending on the build style.
         Just (LocalTarballPackage    tarball) ->
@@ -249,7 +260,7 @@
             return (BuildStatusUpToDate buildResult)
       where
         packageFileMonitor =
-          newPackageFileMonitor distDirLayout (elabDistDirParams shared pkg)
+          newPackageFileMonitor shared distDirLayout (elabDistDirParams shared pkg)
 
 
 -- | A specialised traversal over the packages in an install plan.
@@ -328,11 +339,20 @@
 --
 type BuildResultMisc = (DocsResult, TestsResult)
 
-newPackageFileMonitor :: DistDirLayout -> DistDirParams -> PackageFileMonitor
-newPackageFileMonitor DistDirLayout{distPackageCacheFile} dparams =
+newPackageFileMonitor :: ElaboratedSharedConfig
+                      -> DistDirLayout
+                      -> DistDirParams
+                      -> PackageFileMonitor
+newPackageFileMonitor shared
+                      DistDirLayout{distPackageCacheFile}
+                      dparams =
     PackageFileMonitor {
       pkgFileMonitorConfig =
-        newFileMonitor (distPackageCacheFile dparams "config"),
+        FileMonitor {
+          fileMonitorCacheFile = distPackageCacheFile dparams "config",
+          fileMonitorKeyValid = (==) `on` normaliseConfiguredPackage shared,
+          fileMonitorCheckIfOnlyValueChanged = False
+        },
 
       pkgFileMonitorBuild =
         FileMonitor {
@@ -366,11 +386,12 @@
     --
     elab_config =
         elab {
-            elabBuildTargets  = [],
-            elabTestTargets   = [],
+            elabBuildTargets   = [],
+            elabTestTargets    = [],
             elabBenchTargets   = [],
-            elabReplTarget    = Nothing,
-            elabBuildHaddocks = False
+            elabReplTarget     = Nothing,
+            elabHaddockTargets = [],
+            elabBuildHaddocks  = False
         }
 
     -- The second part is the value used to guard the build step. So this is
@@ -689,7 +710,7 @@
           verbosity distDirLayout storeDirLayout
           buildSettings registerLock cacheLock
           sharedPackageConfig
-          rpkg
+          plan rpkg
           srcdir builddir'
       where
         builddir' = makeRelative srcdir builddir
@@ -884,11 +905,12 @@
                                -> StoreDirLayout
                                -> BuildTimeSettings -> Lock -> Lock
                                -> ElaboratedSharedConfig
+                               -> ElaboratedInstallPlan
                                -> ElaboratedReadyPackage
                                -> FilePath -> FilePath
                                -> IO BuildResult
 buildAndInstallUnpackedPackage verbosity
-                               DistDirLayout{distTempDirectory}
+                               distDirLayout@DistDirLayout{distTempDirectory}
                                storeDirLayout@StoreDirLayout {
                                  storePackageDBStack
                                }
@@ -902,7 +924,7 @@
                                  pkgConfigCompiler      = compiler,
                                  pkgConfigCompilerProgs = progdb
                                }
-                               rpkg@(ReadyPackage pkg)
+                               plan rpkg@(ReadyPackage pkg)
                                srcdir builddir = do
 
     createDirectoryIfMissingVerbose verbosity True builddir
@@ -918,34 +940,36 @@
     --TODO: [required feature] docs and tests
     --TODO: [required feature] sudo re-exec
 
-    let dispname = case elabPkgOrComp pkg of
-            ElabPackage _ -> display pkgid
-                ++ " (all, legacy fallback)"
-            ElabComponent comp -> display pkgid
-                ++ " (" ++ maybe "custom" display (compComponentName comp) ++ ")"
-
     -- Configure phase
-    when isParallelBuild $
-      notice verbosity $ "Configuring " ++ dispname ++ "..."
+    noticeProgress ProgressStarting
+
     annotateFailure mlogFile ConfigureFailed $
       setup' configureCommand configureFlags configureArgs
 
     -- Build phase
-    when isParallelBuild $
-      notice verbosity $ "Building " ++ dispname ++ "..."
+    noticeProgress ProgressBuilding
+
     annotateFailure mlogFile BuildFailed $
       setup buildCommand buildFlags
 
+    -- Haddock phase
+    whenHaddock $ do
+      noticeProgress ProgressHaddock
+      annotateFailureNoLog HaddocksFailed $
+        setup haddockCommand haddockFlags
+
     -- Install phase
+    noticeProgress ProgressInstalling
     annotateFailure mlogFile InstallFailed $ do
 
       let copyPkgFiles tmpDir = do
-            setup Cabal.copyCommand (copyFlags tmpDir)
+            let tmpDirNormalised = normalise tmpDir
+            setup Cabal.copyCommand (copyFlags tmpDirNormalised)
             -- Note that the copy command has put the files into
             -- @$tmpDir/$prefix@ so we need to return this dir so
             -- the store knows which dir will be the final store entry.
-            let prefix   = dropDrive (InstallDirs.prefix (elabInstallDirs pkg))
-                entryDir = tmpDir </> prefix
+            let prefix   = normalise $ dropDrive (InstallDirs.prefix (elabInstallDirs pkg))
+                entryDir = tmpDirNormalised </> prefix
             LBS.writeFile
               (entryDir </> "cabal-hash.txt")
               (renderPackageHashInputs (packageHashInputs pkgshared pkg))
@@ -954,7 +978,9 @@
             -- While this breaks the prefix-relocatable property of the lirbaries
             -- it is necessary on macOS to stay under the load command limit of the
             -- macOS mach-o linker. See also @PackageHash.hashedInstalledPackageIdVeryShort@.
-            otherFiles <- filter (not . isPrefixOf entryDir) <$> listFilesRecursive tmpDir 
+            -- We also normalise paths to ensure that there are no different representations
+            -- for the same path. Like / and \\ on windows under msys.
+            otherFiles <- filter (not . isPrefixOf entryDir) <$> listFilesRecursive tmpDirNormalised
             -- here's where we could keep track of the installed files ourselves
             -- if we wanted to by making a manifest of the files in the tmp dir
             return (entryDir, otherFiles)
@@ -1009,6 +1035,8 @@
     let docsResult  = DocsNotTried
         testsResult = TestsNotTried
 
+    noticeProgress ProgressCompleted
+
     return BuildResult {
        buildResultDocs    = docsResult,
        buildResultTests   = testsResult,
@@ -1020,17 +1048,34 @@
     uid    = installedUnitId rpkg
     compid = compilerId compiler
 
+    dispname = case elabPkgOrComp pkg of
+        ElabPackage _ -> display pkgid
+            ++ " (all, legacy fallback)"
+        ElabComponent comp -> display pkgid
+            ++ " (" ++ maybe "custom" display (compComponentName comp) ++ ")"
+
+    noticeProgress phase = when isParallelBuild $
+        progressMessage verbosity phase dispname
+
     isParallelBuild = buildSettingNumJobs >= 2
 
+    whenHaddock action
+      | hasValidHaddockTargets pkg = action
+      | otherwise                  = return ()
+
     configureCommand = Cabal.configureCommand defaultProgramDb
     configureFlags v = flip filterConfigureFlags v $
                        setupHsConfigureFlags rpkg pkgshared
                                              verbosity builddir
-    configureArgs    = setupHsConfigureArgs pkg
+    configureArgs _  = setupHsConfigureArgs pkg
 
     buildCommand     = Cabal.buildCommand defaultProgramDb
     buildFlags   _   = setupHsBuildFlags pkg pkgshared verbosity builddir
 
+    haddockCommand   = Cabal.haddockCommand
+    haddockFlags _   = setupHsHaddockFlags pkg pkgshared
+                                           verbosity builddir
+
     generateInstalledPackageInfo :: IO InstalledPackageInfo
     generateInstalledPackageInfo =
       withTempInstalledPackageInfoFile
@@ -1044,18 +1089,21 @@
     copyFlags destdir _ = setupHsCopyFlags pkg pkgshared verbosity
                                            builddir destdir
 
-    scriptOptions = setupHsScriptOptions rpkg pkgshared srcdir builddir
+    scriptOptions = setupHsScriptOptions rpkg plan pkgshared
+                                         distDirLayout srcdir builddir
                                          isParallelBuild cacheLock
 
     setup :: CommandUI flags -> (Version -> flags) -> IO ()
-    setup cmd flags = setup' cmd flags []
+    setup cmd flags = setup' cmd flags (const [])
 
-    setup' :: CommandUI flags -> (Version -> flags) -> [String] -> IO ()
+    setup' :: CommandUI flags -> (Version -> flags) -> (Version -> [String]) -> IO ()
     setup' cmd flags args =
       withLogging $ \mLogFileHandle ->
         setupWrapper
           verbosity
-          scriptOptions { useLoggingHandle = mLogFileHandle }
+          scriptOptions
+            { useLoggingHandle     = mLogFileHandle
+            , useExtraEnvOverrides = dataDirsEnvironmentForPlan distDirLayout plan }
           (Just (elabPkgDescription pkg))
           cmd flags args
 
@@ -1079,6 +1127,27 @@
         Just logFile -> withFile logFile AppendMode (action . Just)
 
 
+hasValidHaddockTargets :: ElaboratedConfiguredPackage -> Bool
+hasValidHaddockTargets ElaboratedConfiguredPackage{..}
+  | not elabBuildHaddocks = False
+  | otherwise             = any componentHasHaddocks components
+  where
+    components = elabBuildTargets ++ elabTestTargets ++ elabBenchTargets
+              ++ maybeToList elabReplTarget ++ elabHaddockTargets
+
+    componentHasHaddocks :: ComponentTarget -> Bool
+    componentHasHaddocks (ComponentTarget name _) =
+      case name of
+        CLibName      -> hasHaddocks
+        CSubLibName _ -> elabHaddockInternal    && hasHaddocks
+        CFLibName   _ -> elabHaddockForeignLibs && hasHaddocks
+        CExeName    _ -> elabHaddockExecutables && hasHaddocks
+        CTestName   _ -> elabHaddockTestSuites  && hasHaddocks
+        CBenchName  _ -> elabHaddockBenchmarks  && hasHaddocks
+      where
+        hasHaddocks = not (null (elabPkgDescription ^. componentModules name))
+
+
 buildInplaceUnpackedPackage :: Verbosity
                             -> DistDirLayout
                             -> BuildTimeSettings -> Lock -> Lock
@@ -1139,7 +1208,7 @@
               ifNullThen m m' = do xs <- m
                                    if null xs then m' else return xs
           monitors <- case PD.buildType (elabPkgDescription pkg) of
-            Just Simple -> listSimple
+            Simple -> listSimple
             -- If a Custom setup was used, AND the Cabal is recent
             -- enough to have sdist --list-sources, use that to
             -- determine the files that we need to track.  This can
@@ -1202,7 +1271,7 @@
         -- Haddock phase
         whenHaddock $
           annotateFailureNoLog HaddocksFailed $ do
-            setup haddockCommand haddockFlags []
+            setup haddockCommand haddockFlags haddockArgs
             let haddockTarget = elabHaddockForHackage pkg
             when (haddockTarget == Cabal.ForHackage) $ do
               let dest = distDirectory </> name <.> "tar.gz"
@@ -1223,7 +1292,7 @@
 
     isParallelBuild = buildSettingNumJobs >= 2
 
-    packageFileMonitor = newPackageFileMonitor distDirLayout dparams
+    packageFileMonitor = newPackageFileMonitor pkgshared distDirLayout dparams
 
     whenReConfigure action = case buildStatus of
       BuildStatusConfigure _ -> action
@@ -1249,8 +1318,8 @@
       | otherwise                     = action
 
     whenHaddock action
-      | elabBuildHaddocks pkg = action
-      | otherwise            = return ()
+      | hasValidHaddockTargets pkg = action
+      | otherwise                  = return ()
 
     whenReRegister  action
       = case buildStatus of
@@ -1264,45 +1333,48 @@
     configureFlags v = flip filterConfigureFlags v $
                        setupHsConfigureFlags rpkg pkgshared
                                              verbosity builddir
-    configureArgs    = setupHsConfigureArgs pkg
+    configureArgs _  = setupHsConfigureArgs pkg
 
     buildCommand     = Cabal.buildCommand defaultProgramDb
     buildFlags   _   = setupHsBuildFlags pkg pkgshared
                                          verbosity builddir
-    buildArgs        = setupHsBuildArgs  pkg
+    buildArgs     _  = setupHsBuildArgs  pkg
 
     testCommand      = Cabal.testCommand -- defaultProgramDb
     testFlags    _   = setupHsTestFlags pkg pkgshared
                                          verbosity builddir
-    testArgs         = setupHsTestArgs  pkg
+    testArgs      _  = setupHsTestArgs  pkg
 
     benchCommand     = Cabal.benchmarkCommand
     benchFlags    _  = setupHsBenchFlags pkg pkgshared
                                           verbosity builddir
-    benchArgs        = setupHsBenchArgs  pkg
+    benchArgs     _  = setupHsBenchArgs  pkg
 
     replCommand      = Cabal.replCommand defaultProgramDb
     replFlags _      = setupHsReplFlags pkg pkgshared
                                         verbosity builddir
-    replArgs         = setupHsReplArgs  pkg
+    replArgs _       = setupHsReplArgs  pkg
 
     haddockCommand   = Cabal.haddockCommand
-    haddockFlags _   = setupHsHaddockFlags pkg pkgshared
+    haddockFlags v   = flip filterHaddockFlags v $
+                       setupHsHaddockFlags pkg pkgshared
                                            verbosity builddir
+    haddockArgs    v = flip filterHaddockArgs v $
+                       setupHsHaddockArgs pkg
 
-    scriptOptions    = setupHsScriptOptions rpkg pkgshared
-                                            srcdir builddir
+    scriptOptions    = setupHsScriptOptions rpkg plan pkgshared
+                                            distDirLayout srcdir builddir
                                             isParallelBuild cacheLock
 
     setupInteractive :: CommandUI flags
-                     -> (Version -> flags) -> [String] -> IO ()
+                     -> (Version -> flags) -> (Version -> [String]) -> IO ()
     setupInteractive cmd flags args =
       setupWrapper verbosity
                    scriptOptions { isInteractive = True }
                    (Just (elabPkgDescription pkg))
                    cmd flags args
 
-    setup :: CommandUI flags -> (Version -> flags) -> [String] -> IO ()
+    setup :: CommandUI flags -> (Version -> flags) -> (Version -> [String]) -> IO ()
     setup cmd flags args =
       setupWrapper verbosity
                    scriptOptions
@@ -1317,7 +1389,7 @@
                                 pkg pkgshared
                                 verbosity builddir
                                 pkgConfDest
-        setup Cabal.registerCommand registerFlags []
+        setup Cabal.registerCommand registerFlags (const [])
 
 withTempInstalledPackageInfoFile :: Verbosity -> FilePath
                                   -> (FilePath -> IO ())
@@ -1377,4 +1449,3 @@
   where
     handler :: Exception e => e -> IO a
     handler = throwIO . BuildFailure mlogFile . annotate . toException
-
diff --git a/cabal/cabal-install/Distribution/Client/ProjectBuilding/Types.hs b/cabal/cabal-install/Distribution/Client/ProjectBuilding/Types.hs
--- a/cabal/cabal-install/Distribution/Client/ProjectBuilding/Types.hs
+++ b/cabal/cabal-install/Distribution/Client/ProjectBuilding/Types.hs
@@ -204,4 +204,3 @@
                         | BenchFailed     SomeException
                         | InstallFailed   SomeException
   deriving Show
-
diff --git a/cabal/cabal-install/Distribution/Client/ProjectConfig.hs b/cabal/cabal-install/Distribution/Client/ProjectConfig.hs
--- a/cabal/cabal-install/Distribution/Client/ProjectConfig.hs
+++ b/cabal/cabal-install/Distribution/Client/ProjectConfig.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE CPP, RecordWildCards, NamedFieldPuns, DeriveDataTypeable #-}
+{-# LANGUAGE CPP, RecordWildCards, NamedFieldPuns, DeriveDataTypeable, LambdaCase #-}
 
 -- | Handling project configuration.
 --
@@ -22,6 +22,7 @@
     readProjectConfig,
     readGlobalConfig,
     readProjectLocalFreezeConfig,
+    withProjectOrGlobalConfig,
     writeProjectLocalExtraConfig,
     writeProjectLocalFreezeConfig,
     writeProjectConfigFile,
@@ -33,7 +34,7 @@
     BadPackageLocation(..),
     BadPackageLocationMatch(..),
     findProjectPackages,
-    readSourcePackage,
+    fetchAndReadSourcePackages,
 
     -- * Resolving configuration
     lookupLocalPackageConfig,
@@ -57,6 +58,9 @@
 import Distribution.Client.RebuildMonad
 import Distribution.Client.Glob
          ( isTrivialFilePathGlob )
+import Distribution.Client.VCS
+         ( validateSourceRepos, SourceRepoProblem(..)
+         , VCS(..), knownVCSs, configureVCS, syncSourceRepos )
 
 import Distribution.Client.Types
 import Distribution.Client.DistDirLayout
@@ -67,6 +71,9 @@
          ( ReportLevel(..) )
 import Distribution.Client.Config
          ( loadConfig, getConfigFilePath )
+import Distribution.Client.HttpUtils
+         ( HttpTransport, configureTransport, transportCheckHttps
+         , downloadURI )
 
 import Distribution.Solver.Types.SourcePackage
 import Distribution.Solver.Types.Settings
@@ -78,10 +85,16 @@
 import Distribution.Types.Dependency
 import Distribution.System
          ( Platform )
-import Distribution.PackageDescription
-         ( SourceRepo(..) )
+import Distribution.Types.GenericPackageDescription
+         ( GenericPackageDescription )
 import Distribution.PackageDescription.Parsec
-         ( readGenericPackageDescription )
+         ( parseGenericPackageDescription )
+import Distribution.Parsec.ParseResult
+         ( runParseResult )
+import Distribution.Parsec.Common as NewParser
+         ( PError, PWarning, showPWarning )
+import Distribution.Types.SourceRepo
+         ( SourceRepo(..), RepoType(..), )
 import Distribution.Simple.Compiler
          ( Compiler, compilerInfo )
 import Distribution.Simple.Program
@@ -95,27 +108,42 @@
          ( PathTemplate, fromPathTemplate
          , toPathTemplate, substPathTemplate, initialPathTemplateEnv )
 import Distribution.Simple.Utils
-         ( die', warn )
+         ( die', warn, notice, info, createDirectoryIfMissingVerbose )
 import Distribution.Client.Utils
          ( determineNumJobs )
 import Distribution.Utils.NubList
          ( fromNubList )
 import Distribution.Verbosity
          ( Verbosity, modifyVerbosity, verbose )
+import Distribution.Version
+         ( Version )
 import Distribution.Text
-import Distribution.ParseUtils
+import Distribution.ParseUtils as OldParser
          ( ParseResult(..), locatedErrorMsg, showPWarning )
 
+import qualified Codec.Archive.Tar       as Tar
+import qualified Codec.Archive.Tar.Entry as Tar
+import qualified Distribution.Client.Tar as Tar
+import qualified Distribution.Client.GZipUtils as GZipUtils
+
 import Control.Monad
 import Control.Monad.Trans (liftIO)
 import Control.Exception
 import Data.Either
+import qualified Data.ByteString      as BS
+import qualified Data.ByteString.Lazy as LBS
 import qualified Data.Map as Map
 import Data.Set (Set)
 import qualified Data.Set as Set
+import qualified Data.Hashable as Hashable
+import Numeric (showHex)
+
 import System.FilePath hiding (combine)
+import System.IO
+         ( withBinaryFile, IOMode(ReadMode) )
 import System.Directory
-import Network.URI (URI(..), URIAuth(..), parseAbsoluteURI)
+import Network.URI
+         ( URI(..), URIAuth(..), parseAbsoluteURI, uriToString )
 
 
 ----------------------------------------
@@ -152,6 +180,7 @@
       buildSettingCacheDir
       buildSettingHttpTransport
       (Just buildSettingIgnoreExpiry)
+      buildSettingProgPathExtra
 
 
 -- | Use a 'RepoContext', but only for the solver. The solver does not use the
@@ -174,6 +203,7 @@
                          projectConfigCacheDir)
       (flagToMaybe projectConfigHttpTransport)
       (flagToMaybe projectConfigIgnoreExpiry)
+      (fromNubList projectConfigProgPathExtra)
 
 
 -- | Resolve the project configuration, with all its optional fields, into
@@ -249,7 +279,8 @@
                          ProjectConfig {
                            projectConfigShared = ProjectConfigShared {
                              projectConfigRemoteRepos,
-                             projectConfigLocalRepos
+                             projectConfigLocalRepos,
+                             projectConfigProgPathExtra
                            },
                            projectConfigBuildOnly
                          } =
@@ -274,6 +305,7 @@
     buildSettingIgnoreExpiry  = fromFlag    projectConfigIgnoreExpiry
     buildSettingReportPlanningFailure
                               = fromFlag projectConfigReportPlanningFailure
+    buildSettingProgPathExtra = fromNubList projectConfigProgPathExtra
 
     ProjectConfigBuildOnly{..} = defaults
                               <> projectConfigBuildOnly
@@ -407,45 +439,63 @@
 renderBadProjectRoot (BadProjectRootExplicitFile projectFile) =
     "The given project file '" ++ projectFile ++ "' does not exist."
 
+withProjectOrGlobalConfig :: Verbosity 
+                          -> Flag FilePath
+                          -> IO a
+                          -> (ProjectConfig -> IO a)
+                          -> IO a
+withProjectOrGlobalConfig verbosity globalConfigFlag with without = do
+  globalConfig <- runRebuild "" $ readGlobalConfig verbosity globalConfigFlag
 
+  let
+    res' = catch with
+      $ \case
+        (BadPackageLocations prov locs) 
+          | prov == Set.singleton Implicit
+          , let 
+            isGlobErr (BadLocGlobEmptyMatch _) = True
+            isGlobErr _ = False
+          , any isGlobErr locs ->
+            without globalConfig
+        err -> throwIO err
+
+  catch res'
+    $ \case
+      (BadProjectRootExplicitFile "") -> without globalConfig
+      err -> throwIO err
+
 -- | Read all the config relevant for a project. This includes the project
 -- file if any, plus other global config.
 --
-readProjectConfig :: Verbosity -> Flag FilePath -> DistDirLayout -> Rebuild ProjectConfig
+readProjectConfig :: Verbosity
+                  -> Flag FilePath
+                  -> DistDirLayout
+                  -> Rebuild ProjectConfig
 readProjectConfig verbosity configFileFlag distDirLayout = do
-    global <- readGlobalConfig             verbosity configFileFlag
-    local  <- readProjectLocalConfig       verbosity distDirLayout
-    freeze <- readProjectLocalFreezeConfig verbosity distDirLayout
-    extra  <- readProjectLocalExtraConfig  verbosity distDirLayout
+    global <- readGlobalConfig                verbosity configFileFlag
+    local  <- readProjectLocalConfigOrDefault verbosity distDirLayout
+    freeze <- readProjectLocalFreezeConfig    verbosity distDirLayout
+    extra  <- readProjectLocalExtraConfig     verbosity distDirLayout
     return (global <> local <> freeze <> extra)
 
 
 -- | Reads an explicit @cabal.project@ file in the given project root dir,
 -- or returns the default project config for an implicitly defined project.
 --
-readProjectLocalConfig :: Verbosity -> DistDirLayout -> Rebuild ProjectConfig
-readProjectLocalConfig verbosity DistDirLayout{distProjectFile} = do
+readProjectLocalConfigOrDefault :: Verbosity
+                                -> DistDirLayout
+                                -> Rebuild ProjectConfig
+readProjectLocalConfigOrDefault verbosity distDirLayout = do
   usesExplicitProjectRoot <- liftIO $ doesFileExist projectFile
   if usesExplicitProjectRoot
     then do
-      monitorFiles [monitorFileHashed projectFile]
-      addProjectFileProvenance <$> liftIO readProjectFile
+      readProjectFile verbosity distDirLayout "" "project file"
     else do
       monitorFiles [monitorNonExistentFile projectFile]
       return defaultImplicitProjectConfig
 
   where
-    projectFile = distProjectFile ""
-    readProjectFile =
-          reportParseResult verbosity "project file" projectFile
-        . parseProjectConfig
-      =<< readFile projectFile
-
-    addProjectFileProvenance config =
-      config {
-        projectConfigProvenance =
-          Set.insert (Explicit projectFile) (projectConfigProvenance config)
-      }
+    projectFile = distProjectFile distDirLayout ""
 
     defaultImplicitProjectConfig :: ProjectConfig
     defaultImplicitProjectConfig =
@@ -466,7 +516,7 @@
 readProjectLocalExtraConfig :: Verbosity -> DistDirLayout
                             -> Rebuild ProjectConfig
 readProjectLocalExtraConfig verbosity distDirLayout =
-    readProjectExtensionFile verbosity distDirLayout "local"
+    readProjectFile verbosity distDirLayout "local"
                              "project local configuration file"
 
 -- | Reads a @cabal.project.freeze@ file in the given project root dir,
@@ -476,19 +526,22 @@
 readProjectLocalFreezeConfig :: Verbosity -> DistDirLayout
                              -> Rebuild ProjectConfig
 readProjectLocalFreezeConfig verbosity distDirLayout =
-    readProjectExtensionFile verbosity distDirLayout "freeze"
+    readProjectFile verbosity distDirLayout "freeze"
                              "project freeze file"
 
 -- | Reads a named config file in the given project root dir, or returns empty.
 --
-readProjectExtensionFile :: Verbosity -> DistDirLayout -> String -> FilePath
-                         -> Rebuild ProjectConfig
-readProjectExtensionFile verbosity DistDirLayout{distProjectFile}
+readProjectFile :: Verbosity
+                -> DistDirLayout
+                -> String
+                -> String
+                -> Rebuild ProjectConfig
+readProjectFile verbosity DistDirLayout{distProjectFile}
                          extensionName extensionDescription = do
     exists <- liftIO $ doesFileExist extensionFile
     if exists
       then do monitorFiles [monitorFileHashed extensionFile]
-              liftIO readExtensionFile
+              addProjectFileProvenance <$> liftIO readExtensionFile
       else do monitorFiles [monitorNonExistentFile extensionFile]
               return mempty
   where
@@ -499,7 +552,13 @@
         . parseProjectConfig
       =<< readFile extensionFile
 
+    addProjectFileProvenance config =
+      config {
+        projectConfigProvenance =
+          Set.insert (Explicit extensionFile) (projectConfigProvenance config)
+      }
 
+
 -- | Parse the 'ProjectConfig' format.
 --
 -- For the moment this is implemented in terms of parsers for legacy
@@ -554,7 +613,7 @@
 reportParseResult :: Verbosity -> String -> FilePath -> ParseResult a -> IO a
 reportParseResult verbosity _filetype filename (ParseOk warnings x) = do
     unless (null warnings) $
-      let msg = unlines (map (showPWarning filename) warnings)
+      let msg = unlines (map (OldParser.showPWarning filename) warnings)
        in warn verbosity msg
     return x
 reportParseResult verbosity filetype filename (ParseFailed err) =
@@ -564,7 +623,7 @@
 
 
 ---------------------------------------------
--- Reading packages in the project
+-- Finding packages in the project
 --
 
 -- | The location of a package as part of a project. Local file paths are
@@ -881,35 +940,411 @@
     Just x  -> return (Just x)
 
 
--- | Read the @.cabal@ file of the given package.
+-------------------------------------------------
+-- Fetching and reading packages in the project
 --
+
+-- | Read the @.cabal@ files for a set of packages. For remote tarballs and
+-- VCS source repos this also fetches them if needed.
+--
 -- Note here is where we convert from project-root relative paths to absolute
 -- paths.
 --
-readSourcePackage :: Verbosity -> ProjectPackageLocation
-                  -> Rebuild (PackageSpecifier UnresolvedSourcePackage)
-readSourcePackage verbosity (ProjectPackageLocalCabalFile cabalFile) =
-    readSourcePackage verbosity (ProjectPackageLocalDirectory dir cabalFile)
+fetchAndReadSourcePackages
+  :: Verbosity
+  -> DistDirLayout
+  -> ProjectConfigShared
+  -> ProjectConfigBuildOnly
+  -> [ProjectPackageLocation]
+  -> Rebuild [PackageSpecifier (SourcePackage UnresolvedPkgLoc)]
+fetchAndReadSourcePackages verbosity distDirLayout
+                           projectConfigShared
+                           projectConfigBuildOnly
+                           pkgLocations = do
+
+    pkgsLocalDirectory <-
+      sequence
+        [ readSourcePackageLocalDirectory verbosity dir cabalFile
+        | location <- pkgLocations
+        , (dir, cabalFile) <- projectPackageLocal location ]
+
+    pkgsLocalTarball <-
+      sequence
+        [ readSourcePackageLocalTarball verbosity path
+        | ProjectPackageLocalTarball path <- pkgLocations ]
+
+    pkgsRemoteTarball <- do
+      getTransport <- delayInitSharedResource $
+                      configureTransport verbosity progPathExtra
+                                         preferredHttpTransport
+      sequence
+        [ fetchAndReadSourcePackageRemoteTarball verbosity distDirLayout
+                                                 getTransport uri
+        | ProjectPackageRemoteTarball uri <- pkgLocations ]
+
+    pkgsRemoteRepo <-
+      syncAndReadSourcePackagesRemoteRepos
+        verbosity distDirLayout
+        projectConfigShared
+        [ repo | ProjectPackageRemoteRepo repo <- pkgLocations ]
+
+    let pkgsNamed =
+          [ NamedPackage pkgname [PackagePropertyVersion verrange]
+          | ProjectPackageNamed (Dependency pkgname verrange) <- pkgLocations ]
+
+    return $ concat
+      [ pkgsLocalDirectory
+      , pkgsLocalTarball
+      , pkgsRemoteTarball
+      , pkgsRemoteRepo
+      , pkgsNamed
+      ]
   where
-    dir = takeDirectory cabalFile
+    projectPackageLocal (ProjectPackageLocalDirectory dir file) = [(dir, file)]
+    projectPackageLocal (ProjectPackageLocalCabalFile     file) = [(dir, file)]
+                                                where dir = takeDirectory file
+    projectPackageLocal _ = []
 
-readSourcePackage verbosity (ProjectPackageLocalDirectory dir cabalFile) = do
+    progPathExtra = fromNubList (projectConfigProgPathExtra projectConfigShared)
+    preferredHttpTransport =
+      flagToMaybe (projectConfigHttpTransport projectConfigBuildOnly)
+
+-- | A helper for 'fetchAndReadSourcePackages' to handle the case of
+-- 'ProjectPackageLocalDirectory' and 'ProjectPackageLocalCabalFile'.
+-- We simply read the @.cabal@ file.
+--
+readSourcePackageLocalDirectory
+  :: Verbosity
+  -> FilePath  -- ^ The package directory
+  -> FilePath  -- ^ The package @.cabal@ file
+  -> Rebuild (PackageSpecifier (SourcePackage UnresolvedPkgLoc))
+readSourcePackageLocalDirectory verbosity dir cabalFile = do
     monitorFiles [monitorFileHashed cabalFile]
     root <- askRoot
-    pkgdesc <- liftIO $ readGenericPackageDescription verbosity (root </> cabalFile)
-    return $ SpecificSourcePackage SourcePackage {
-      packageInfoId        = packageId pkgdesc,
-      packageDescription   = pkgdesc,
-      packageSource        = LocalUnpackedPackage (root </> dir),
+    let location = LocalUnpackedPackage (root </> dir)
+    liftIO $ fmap (mkSpecificSourcePackage location)
+           . readSourcePackageCabalFile verbosity cabalFile
+         =<< BS.readFile (root </> cabalFile)
+
+
+-- | A helper for 'fetchAndReadSourcePackages' to handle the case of
+-- 'ProjectPackageLocalTarball'. We scan through the @.tar.gz@ file to find
+-- the @.cabal@ file and read that.
+--
+readSourcePackageLocalTarball
+  :: Verbosity
+  -> FilePath
+  -> Rebuild (PackageSpecifier (SourcePackage UnresolvedPkgLoc))
+readSourcePackageLocalTarball verbosity tarballFile = do
+    monitorFiles [monitorFile tarballFile]
+    root <- askRoot
+    let location = LocalTarballPackage (root </> tarballFile)
+    liftIO $ fmap (mkSpecificSourcePackage location)
+           . uncurry (readSourcePackageCabalFile verbosity)
+         =<< extractTarballPackageCabalFile (root </> tarballFile)
+
+
+-- | A helper for 'fetchAndReadSourcePackages' to handle the case of
+-- 'ProjectPackageRemoteTarball'. We download the tarball to the dist src dir
+-- and after that handle it like the local tarball case.
+--
+fetchAndReadSourcePackageRemoteTarball
+  :: Verbosity
+  -> DistDirLayout
+  -> Rebuild HttpTransport
+  -> URI
+  -> Rebuild (PackageSpecifier (SourcePackage UnresolvedPkgLoc))
+fetchAndReadSourcePackageRemoteTarball verbosity
+                                       DistDirLayout {
+                                         distDownloadSrcDirectory
+                                       }
+                                       getTransport
+                                       tarballUri =
+    -- The tarball download is expensive so we use another layer of file
+    -- monitor to avoid it whenever possible.
+    rerunIfChanged verbosity monitor tarballUri $ do
+
+      -- Download
+      transport <- getTransport
+      liftIO $ do
+        transportCheckHttps verbosity transport tarballUri
+        notice verbosity ("Downloading " ++ show tarballUri)
+        createDirectoryIfMissingVerbose verbosity True
+                                        distDownloadSrcDirectory
+        _ <- downloadURI transport verbosity tarballUri tarballFile
+        return ()
+
+      -- Read
+      monitorFiles [monitorFile tarballFile]
+      let location = RemoteTarballPackage tarballUri tarballFile
+      liftIO $ fmap (mkSpecificSourcePackage location)
+             . uncurry (readSourcePackageCabalFile verbosity)
+           =<< extractTarballPackageCabalFile tarballFile
+  where
+    tarballStem = distDownloadSrcDirectory
+              </> localFileNameForRemoteTarball tarballUri
+    tarballFile = tarballStem <.> "tar.gz"
+
+    monitor :: FileMonitor URI (PackageSpecifier (SourcePackage UnresolvedPkgLoc))
+    monitor = newFileMonitor (tarballStem <.> "cache")
+
+
+-- | A helper for 'fetchAndReadSourcePackages' to handle all the cases of
+-- 'ProjectPackageRemoteRepo'.
+--
+syncAndReadSourcePackagesRemoteRepos
+  :: Verbosity
+  -> DistDirLayout
+  -> ProjectConfigShared
+  -> [SourceRepo]
+  -> Rebuild [PackageSpecifier (SourcePackage UnresolvedPkgLoc)]
+syncAndReadSourcePackagesRemoteRepos verbosity
+                                     DistDirLayout{distDownloadSrcDirectory}
+                                     ProjectConfigShared {
+                                       projectConfigProgPathExtra
+                                     }
+                                    repos = do
+
+    repos' <- either reportSourceRepoProblems return $
+              validateSourceRepos repos
+
+    -- All 'SourceRepo's grouped by referring to the "same" remote repo
+    -- instance. So same location but can differ in commit/tag/branch/subdir.
+    let reposByLocation :: Map (RepoType, String)
+                               [(SourceRepo, RepoType)]
+        reposByLocation = Map.fromListWith (++)
+                            [ ((rtype, rloc), [(repo, vcsRepoType vcs)])
+                            | (repo, rloc, rtype, vcs) <- repos' ]
+
+    --TODO: pass progPathExtra on to 'configureVCS'
+    let _progPathExtra = fromNubList projectConfigProgPathExtra
+    getConfiguredVCS <- delayInitSharedResources $ \repoType ->
+                          let Just vcs = Map.lookup repoType knownVCSs in
+                          configureVCS verbosity {-progPathExtra-} vcs
+
+    concat <$> sequence
+      [ rerunIfChanged verbosity monitor repoGroup' $ do
+          vcs' <- getConfiguredVCS repoType
+          syncRepoGroupAndReadSourcePackages vcs' pathStem repoGroup'
+      | repoGroup@((primaryRepo, repoType):_) <- Map.elems reposByLocation
+      , let repoGroup' = map fst repoGroup
+            pathStem = distDownloadSrcDirectory
+                   </> localFileNameForRemoteRepo primaryRepo
+            monitor :: FileMonitor
+                         [SourceRepo]
+                         [PackageSpecifier (SourcePackage UnresolvedPkgLoc)]
+            monitor  = newFileMonitor (pathStem <.> "cache")
+      ]
+  where
+    syncRepoGroupAndReadSourcePackages
+      :: VCS ConfiguredProgram
+      -> FilePath
+      -> [SourceRepo]
+      -> Rebuild [PackageSpecifier (SourcePackage UnresolvedPkgLoc)]
+    syncRepoGroupAndReadSourcePackages vcs pathStem repoGroup = do
+        liftIO $ createDirectoryIfMissingVerbose verbosity False
+                                                 distDownloadSrcDirectory
+
+        -- For syncing we don't care about different 'SourceRepo' values that
+        -- are just different subdirs in the same repo.
+        syncSourceRepos verbosity vcs
+          [ (repo, repoPath)
+          | (repo, _, repoPath) <- repoGroupWithPaths ]
+
+        -- But for reading we go through each 'SourceRepo' including its subdir
+        -- value and have to know which path each one ended up in.
+        sequence
+          [ readPackageFromSourceRepo repoWithSubdir repoPath
+          | (_, reposWithSubdir, repoPath) <- repoGroupWithPaths
+          , repoWithSubdir <- reposWithSubdir ]
+      where
+        -- So to do both things above, we pair them up here.
+        repoGroupWithPaths =
+          zipWith (\(x, y) z -> (x,y,z))
+                  (Map.toList
+                    (Map.fromListWith (++)
+                      [ (repo { repoSubdir = Nothing }, [repo])
+                      | repo <- repoGroup ]))
+                  repoPaths
+
+        -- The repos in a group are given distinct names by simple enumeration
+        -- foo, foo-2, foo-3 etc
+        repoPaths = pathStem
+                  : [ pathStem ++ "-" ++ show (i :: Int) | i <- [2..] ]
+
+    readPackageFromSourceRepo repo repoPath = do
+        let packageDir = maybe repoPath (repoPath </>) (repoSubdir repo)
+        entries <- liftIO $ getDirectoryContents packageDir
+        --TODO: wrap exceptions
+        case filter (\e -> takeExtension e == ".cabal") entries of
+          []       -> liftIO $ throwIO NoCabalFileFound
+          (_:_:_)  -> liftIO $ throwIO MultipleCabalFilesFound
+          [cabalFileName] -> do
+            monitorFiles [monitorFileHashed cabalFilePath]
+            liftIO $ fmap (mkSpecificSourcePackage location)
+                   . readSourcePackageCabalFile verbosity cabalFilePath
+                 =<< BS.readFile cabalFilePath
+            where
+              cabalFilePath = packageDir </> cabalFileName
+              location      = RemoteSourceRepoPackage repo packageDir
+
+
+    reportSourceRepoProblems :: [(SourceRepo, SourceRepoProblem)] -> Rebuild a
+    reportSourceRepoProblems = liftIO . die' verbosity . renderSourceRepoProblems
+
+    renderSourceRepoProblems :: [(SourceRepo, SourceRepoProblem)] -> String
+    renderSourceRepoProblems = unlines . map show -- "TODO: the repo problems"
+
+
+-- | Utility used by all the helpers of 'fetchAndReadSourcePackages' to make an
+-- appropriate @'PackageSpecifier' ('SourcePackage' (..))@ for a given package
+-- from a given location.
+--
+mkSpecificSourcePackage :: PackageLocation FilePath
+                        -> GenericPackageDescription
+                        -> PackageSpecifier
+                             (SourcePackage (PackageLocation (Maybe FilePath)))
+mkSpecificSourcePackage location pkg =
+    SpecificSourcePackage SourcePackage {
+      packageInfoId        = packageId pkg,
+      packageDescription   = pkg,
+      --TODO: it is silly that we still have to use a Maybe FilePath here
+      packageSource        = fmap Just location,
       packageDescrOverride = Nothing
     }
 
-readSourcePackage _ (ProjectPackageNamed (Dependency pkgname verrange)) =
-    return $ NamedPackage pkgname [PackagePropertyVersion verrange]
 
-readSourcePackage _verbosity _ =
-    fail $ "TODO: add support for fetching and reading local tarballs, remote "
-        ++ "tarballs, remote repos and passing named packages through"
+-- | Errors reported upon failing to parse a @.cabal@ file.
+--
+data CabalFileParseError =
+     CabalFileParseError
+       FilePath
+       [PError]
+       (Maybe Version) -- We might discover the spec version the package needs
+       [PWarning]
+  deriving (Show, Typeable)
+
+instance Exception CabalFileParseError
+
+
+-- | Wrapper for the @.cabal@ file parser. It reports warnings on higher
+-- verbosity levels and throws 'CabalFileParseError' on failure.
+--
+readSourcePackageCabalFile :: Verbosity
+                           -> FilePath
+                           -> BS.ByteString
+                           -> IO GenericPackageDescription
+readSourcePackageCabalFile verbosity pkgfilename content =
+    case runParseResult (parseGenericPackageDescription content) of
+      (warnings, Right pkg) -> do
+        unless (null warnings) $
+          info verbosity (formatWarnings warnings)
+        return pkg
+
+      (warnings, Left (mspecVersion, errors)) ->
+        throwIO $ CabalFileParseError pkgfilename errors mspecVersion warnings
+  where
+    formatWarnings warnings =
+        "The package description file " ++ pkgfilename
+     ++ " has warnings: "
+     ++ unlines (map (NewParser.showPWarning pkgfilename) warnings)
+
+
+-- | When looking for a package's @.cabal@ file we can find none, or several,
+-- both of which are failures.
+--
+data CabalFileSearchFailure =
+     NoCabalFileFound
+   | MultipleCabalFilesFound
+  deriving (Show, Typeable)
+
+instance Exception CabalFileSearchFailure
+
+
+-- | Find the @.cabal@ file within a tarball file and return it by value.
+--
+-- Can fail with a 'Tar.FormatError' or 'CabalFileSearchFailure' exception.
+--
+extractTarballPackageCabalFile :: FilePath -> IO (FilePath, BS.ByteString)
+extractTarballPackageCabalFile tarballFile =
+    withBinaryFile tarballFile ReadMode $ \hnd -> do
+      content <- LBS.hGetContents hnd
+      case extractTarballPackageCabalFilePure content of
+        Left (Left  e) -> throwIO e
+        Left (Right e) -> throwIO e
+        Right (fileName, fileContent) ->
+          (,) fileName <$> evaluate (LBS.toStrict fileContent)
+
+
+-- | Scan through a tar file stream and collect the @.cabal@ file, or fail.
+--
+extractTarballPackageCabalFilePure :: LBS.ByteString
+                                   -> Either (Either Tar.FormatError
+                                                     CabalFileSearchFailure)
+                                             (FilePath, LBS.ByteString)
+extractTarballPackageCabalFilePure =
+      check
+    . accumEntryMap
+    . Tar.filterEntries isCabalFile
+    . Tar.read
+    . GZipUtils.maybeDecompress
+  where
+    accumEntryMap = Tar.foldlEntries
+                      (\m e -> Map.insert (Tar.entryTarPath e) e m)
+                      Map.empty
+
+    check (Left (e, _m)) = Left (Left e)
+    check (Right m) = case Map.elems m of
+        []     -> Left (Right NoCabalFileFound)
+        [file] -> case Tar.entryContent file of
+          Tar.NormalFile content _ -> Right (Tar.entryPath file, content)
+          _                        -> Left (Right NoCabalFileFound)
+        _files -> Left (Right MultipleCabalFilesFound)
+
+    isCabalFile e = case splitPath (Tar.entryPath e) of
+      [     _dir, file] -> takeExtension file == ".cabal"
+      [".", _dir, file] -> takeExtension file == ".cabal"
+      _                 -> False
+
+
+-- | The name to use for a local file for a remote tarball 'SourceRepo'.
+-- This is deterministic based on the remote tarball URI, and is intended
+-- to produce non-clashing file names for different tarballs.
+--
+localFileNameForRemoteTarball :: URI -> FilePath
+localFileNameForRemoteTarball uri =
+    mangleName uri
+ ++ "-" ++  showHex locationHash ""
+  where
+    mangleName = truncateString 10 . dropExtension . dropExtension
+               . takeFileName . dropTrailingPathSeparator . uriPath
+
+    locationHash :: Word
+    locationHash = fromIntegral (Hashable.hash (uriToString id uri ""))
+
+
+-- | The name to use for a local file or dir for a remote 'SourceRepo'.
+-- This is deterministic based on the source repo identity details, and
+-- intended to produce non-clashing file names for different repos.
+--
+localFileNameForRemoteRepo :: SourceRepo -> FilePath
+localFileNameForRemoteRepo SourceRepo{repoType, repoLocation, repoModule} =
+    maybe "" ((++ "-") . mangleName) repoLocation
+ ++ showHex locationHash ""
+  where
+    mangleName = truncateString 10 . dropExtension
+               . takeFileName . dropTrailingPathSeparator
+
+    -- just the parts that make up the "identity" of the repo
+    locationHash :: Word
+    locationHash =
+      fromIntegral (Hashable.hash (show repoType, repoLocation, repoModule))
+
+
+-- | Truncate a string, with a visual indication that it is truncated.
+truncateString :: Int -> String -> String
+truncateString n s | length s <= n = s
+                   | otherwise     = take (n-1) s ++ "_"
 
 
 -- TODO: add something like this, here or in the project planning
diff --git a/cabal/cabal-install/Distribution/Client/ProjectConfig/Legacy.hs b/cabal/cabal-install/Distribution/Client/ProjectConfig/Legacy.hs
--- a/cabal/cabal-install/Distribution/Client/ProjectConfig/Legacy.hs
+++ b/cabal/cabal-install/Distribution/Client/ProjectConfig/Legacy.hs
@@ -37,10 +37,11 @@
 import Distribution.PackageDescription
          ( SourceRepo(..), RepoKind(..)
          , dispFlagAssignment, parseFlagAssignment )
-import Distribution.PackageDescription.Parse
+import Distribution.Client.SourceRepoParse
          ( sourceRepoFieldDescrs )
 import Distribution.Simple.Compiler
          ( OptimisationLevel(..), DebugInfoLevel(..) )
+import Distribution.Simple.InstallDirs ( CopyDest (NoCopyDest) )
 import Distribution.Simple.Setup
          ( Flag(Flag), toFlag, fromFlagOrDefault
          , ConfigFlags(..), configureOptions
@@ -81,7 +82,6 @@
          , OptionField, option, reqArg' )
 
 import qualified Data.Map as Map
-
 ------------------------------------------------------------------
 -- Representing the project config file in terms of legacy types
 --
@@ -102,6 +102,7 @@
        legacyPackagesNamed     :: [Dependency],
 
        legacySharedConfig      :: LegacySharedConfig,
+       legacyAllConfig         :: LegacyPackageConfig,
        legacyLocalConfig       :: LegacyPackageConfig,
        legacySpecificConfig    :: MapMappend PackageName LegacyPackageConfig
      } deriving Generic
@@ -165,10 +166,35 @@
       projectConfigShared        = convertLegacyAllPackageFlags
                                      globalFlags configFlags
                                      configExFlags installFlags,
-      projectConfigLocalPackages = convertLegacyPerPackageFlags
-                                     configFlags installFlags haddockFlags
+      projectConfigLocalPackages = localConfig,
+      projectConfigAllPackages   = allConfig
     }
-
+  where (localConfig, allConfig) = splitConfig
+                                 (convertLegacyPerPackageFlags
+                                    configFlags installFlags haddockFlags)
+        -- split the package config (from command line arguments) into
+        -- those applied to all packages and those to local only.
+        --
+        -- for now we will just copy over the ProgramPaths/Args/Extra into
+        -- the AllPackages.  The LocalPackages do not inherit them from
+        -- AllPackages, and as such need to retain them.
+        --
+        -- The general decision rule for what to put into allConfig
+        -- into localConfig is the following:
+        --
+        -- - anything that is host/toolchain/env specific should be applied
+        --   to all packages, as packagesets have to be host/toolchain/env
+        --   consistent.
+        -- - anything else should be in the local config and could potentially
+        --   be lifted into all-packages vial the `package *` cabal.project
+        --   section.
+        --
+        splitConfig :: PackageConfig -> (PackageConfig, PackageConfig)
+        splitConfig pc = (pc
+                         , mempty { packageConfigProgramPaths = packageConfigProgramPaths pc
+                                  , packageConfigProgramArgs  = packageConfigProgramArgs  pc
+                                  , packageConfigProgramPathExtra = packageConfigProgramPathExtra pc
+                                  , packageConfigDocumentation = packageConfigDocumentation pc })
 
 -- | Convert from the types currently used for the user-wide @~/.cabal/config@
 -- file into the 'ProjectConfig' type.
@@ -192,9 +218,9 @@
       savedHaddockFlags      = haddockFlags
     } =
     mempty {
-      projectConfigShared        = configAllPackages,
-      projectConfigLocalPackages = configLocalPackages,
-      projectConfigBuildOnly     = configBuildOnly
+      projectConfigBuildOnly   = configBuildOnly,
+      projectConfigShared      = configShared,
+      projectConfigAllPackages = configAllPackages
     }
   where
     --TODO: [code cleanup] eliminate use of default*Flags here and specify the
@@ -203,9 +229,9 @@
     installFlags'  = defaultInstallFlags  <> installFlags
     haddockFlags'  = defaultHaddockFlags  <> haddockFlags
 
-    configLocalPackages = convertLegacyPerPackageFlags
+    configAllPackages   = convertLegacyPerPackageFlags
                             configFlags installFlags' haddockFlags'
-    configAllPackages   = convertLegacyAllPackageFlags
+    configShared        = convertLegacyAllPackageFlags
                             globalFlags configFlags
                             configExFlags' installFlags'
     configBuildOnly     = convertLegacyBuildOnlyFlags
@@ -226,6 +252,7 @@
     legacyPackagesNamed,
     legacySharedConfig = LegacySharedConfig globalFlags configShFlags
                                             configExFlags installSharedFlags,
+    legacyAllConfig,
     legacyLocalConfig  = LegacyPackageConfig configFlags installPerPkgFlags
                                              haddockFlags,
     legacySpecificConfig
@@ -238,15 +265,18 @@
       projectPackagesNamed         = legacyPackagesNamed,
 
       projectConfigBuildOnly       = configBuildOnly,
-      projectConfigShared          = configAllPackages,
+      projectConfigShared          = configPackagesShared,
       projectConfigProvenance      = mempty,
+      projectConfigAllPackages     = configAllPackages,
       projectConfigLocalPackages   = configLocalPackages,
       projectConfigSpecificPackage = fmap perPackage legacySpecificConfig
     }
   where
+    configAllPackages   = convertLegacyPerPackageFlags g i h
+                            where LegacyPackageConfig g i h = legacyAllConfig
     configLocalPackages = convertLegacyPerPackageFlags
                             configFlags installPerPkgFlags haddockFlags
-    configAllPackages   = convertLegacyAllPackageFlags
+    configPackagesShared= convertLegacyAllPackageFlags
                             globalFlags (configFlags <> configShFlags)
                             configExFlags installSharedFlags
     configBuildOnly     = convertLegacyBuildOnlyFlags
@@ -273,7 +303,9 @@
       globalConfigFile        = projectConfigConfigFile,
       globalSandboxConfigFile = _, -- ??
       globalRemoteRepos       = projectConfigRemoteRepos,
-      globalLocalRepos        = projectConfigLocalRepos
+      globalLocalRepos        = projectConfigLocalRepos,
+      globalProgPathExtra     = projectConfigProgPathExtra,
+      globalStoreDir          = projectConfigStoreDir
     } = globalFlags
 
     ConfigFlags {
@@ -281,6 +313,7 @@
       configHcFlavor            = projectConfigHcFlavor,
       configHcPath              = projectConfigHcPath,
       configHcPkg               = projectConfigHcPkg
+    --configProgramPathExtra    = projectConfigProgPathExtra DELETE ME
     --configInstallDirs         = projectConfigInstallDirs,
     --configUserInstall         = projectConfigUserInstall,
     --configPackageDBs          = projectConfigPackageDBs,
@@ -292,7 +325,9 @@
       configPreferences         = projectConfigPreferences,
       configSolver              = projectConfigSolver,
       configAllowOlder          = projectConfigAllowOlder,
-      configAllowNewer          = projectConfigAllowNewer
+      configAllowNewer          = projectConfigAllowNewer,
+      configWriteGhcEnvironmentFilesPolicy
+                                = projectConfigWriteGhcEnvironmentFilesPolicy
     } = configExFlags
 
     InstallFlags {
@@ -357,7 +392,7 @@
       configRelocatable         = packageConfigRelocatable
     } = configFlags
     packageConfigProgramPaths   = MapLast    (Map.fromList configProgramPaths)
-    packageConfigProgramArgs    = MapMappend (Map.fromList configProgramArgs)
+    packageConfigProgramArgs    = MapMappend (Map.fromListWith (++) configProgramArgs)
 
     packageConfigCoverage       = coverage <> libcoverage
     --TODO: defer this merging to the resolve phase
@@ -378,7 +413,8 @@
       haddockBenchmarks         = packageConfigHaddockBenchmarks,
       haddockInternal           = packageConfigHaddockInternal,
       haddockCss                = packageConfigHaddockCss,
-      haddockHscolour           = packageConfigHaddockHscolour,
+      haddockLinkedSource       = packageConfigHaddockLinkedSource,
+      haddockQuickJump          = packageConfigHaddockQuickJump,
       haddockHscolourCss        = packageConfigHaddockHscolourCss,
       haddockContents           = packageConfigHaddockContents
     } = haddockFlags
@@ -400,8 +436,7 @@
       globalLogsDir           = projectConfigLogsDir,
       globalWorldFile         = _,
       globalHttpTransport     = projectConfigHttpTransport,
-      globalIgnoreExpiry      = projectConfigIgnoreExpiry,
-      globalStoreDir          = projectConfigStoreDir
+      globalIgnoreExpiry      = projectConfigIgnoreExpiry
     } = globalFlags
 
     ConfigFlags {
@@ -436,6 +471,7 @@
       projectPackagesOptional,
       projectPackagesRepo,
       projectPackagesNamed,
+      projectConfigAllPackages,
       projectConfigLocalPackages,
       projectConfigSpecificPackage
     } =
@@ -445,6 +481,8 @@
       legacyPackagesRepo     = projectPackagesRepo,
       legacyPackagesNamed    = projectPackagesNamed,
       legacySharedConfig     = convertToLegacySharedConfig projectConfig,
+      legacyAllConfig        = convertToLegacyPerPackageConfig
+                                 projectConfigAllPackages,
       legacyLocalConfig      = convertToLegacyAllPackageConfig projectConfig
                             <> convertToLegacyPerPackageConfig
                                  projectConfigLocalPackages,
@@ -456,7 +494,10 @@
 convertToLegacySharedConfig
     ProjectConfig {
       projectConfigBuildOnly     = ProjectConfigBuildOnly {..},
-      projectConfigShared        = ProjectConfigShared {..}
+      projectConfigShared        = ProjectConfigShared {..},
+      projectConfigAllPackages   = PackageConfig {
+        packageConfigDocumentation
+      }
     } =
 
     LegacySharedConfig {
@@ -482,7 +523,8 @@
       globalIgnoreExpiry      = projectConfigIgnoreExpiry,
       globalHttpTransport     = projectConfigHttpTransport,
       globalNix               = mempty,
-      globalStoreDir          = projectConfigStoreDir
+      globalStoreDir          = projectConfigStoreDir,
+      globalProgPathExtra     = projectConfigProgPathExtra
     }
 
     configFlags = mempty {
@@ -496,13 +538,15 @@
       configPreferences   = projectConfigPreferences,
       configSolver        = projectConfigSolver,
       configAllowOlder    = projectConfigAllowOlder,
-      configAllowNewer    = projectConfigAllowNewer
-
+      configAllowNewer    = projectConfigAllowNewer,
+      configWriteGhcEnvironmentFilesPolicy
+                          = projectConfigWriteGhcEnvironmentFilesPolicy
     }
 
     installFlags = InstallFlags {
-      installDocumentation     = mempty,
+      installDocumentation     = packageConfigDocumentation,
       installHaddockIndex      = projectConfigHaddockIndex,
+      installDest              = Flag NoCopyDest,
       installDryRun            = projectConfigDryRun,
       installReinstall         = mempty, --projectConfigReinstall,
       installAvoidReinstalls   = mempty, --projectConfigAvoidReinstalls,
@@ -688,12 +732,15 @@
       haddockBenchmarks    = packageConfigHaddockBenchmarks,
       haddockInternal      = packageConfigHaddockInternal,
       haddockCss           = packageConfigHaddockCss,
-      haddockHscolour      = packageConfigHaddockHscolour,
+      haddockLinkedSource  = packageConfigHaddockLinkedSource,
+      haddockQuickJump     = packageConfigHaddockQuickJump,
       haddockHscolourCss   = packageConfigHaddockHscolourCss,
       haddockContents      = packageConfigHaddockContents,
       haddockDistPref      = mempty,
       haddockKeepTempFiles = mempty,
-      haddockVerbosity     = mempty
+      haddockVerbosity     = mempty,
+      haddockCabalFilePath = mempty,
+      haddockArgs          = mempty
     }
 
 
@@ -806,7 +853,11 @@
       [ newLineListField "local-repo"
           showTokenQ parseTokenQ
           (fromNubList . globalLocalRepos)
-          (\v conf -> conf { globalLocalRepos = toNubList v })
+          (\v conf -> conf { globalLocalRepos = toNubList v }),
+         newLineListField "extra-prog-path-shared-only"
+          showTokenQ parseTokenQ
+          (fromNubList . globalProgPathExtra)
+          (\v conf -> conf { globalProgPathExtra = toNubList v })
       ]
   . filterFields
       [ "remote-repo-cache"
@@ -845,7 +896,7 @@
         (\v conf -> conf { configAllowNewer = fmap AllowNewer v })
       ]
   . filterFields
-      [ "cabal-lib-version", "solver"
+      [ "cabal-lib-version", "solver", "write-ghc-environment-files"
         -- not "constraint" or "preference", we use our own plural ones above
       ]
   . commandOptionsToFields
@@ -958,7 +1009,7 @@
       [ "hoogle", "html", "html-location"
       , "foreign-libraries"
       , "executables", "tests", "benchmarks", "all", "internal", "css"
-      , "hyperlink-source", "hscolour-css"
+      , "hyperlink-source", "quickjump", "hscolour-css"
       , "contents-location", "keep-temp-files"
       ]
   . commandOptionsToFields
@@ -1074,45 +1125,61 @@
                            }
     }
 
+-- | The definitions of all the fields that can appear in the @package pkgfoo@
+-- and @package *@ sections of the @cabal.project@-format files.
+--
+packageSpecificOptionsFieldDescrs :: [FieldDescr LegacyPackageConfig]
+packageSpecificOptionsFieldDescrs =
+    legacyPackageConfigFieldDescrs
+ ++ programOptionsFieldDescrs
+      (configProgramArgs . legacyConfigureFlags)
+      (\args pkgconf -> pkgconf {
+          legacyConfigureFlags = (legacyConfigureFlags pkgconf) {
+            configProgramArgs  = args
+          }
+        }
+      )
+ ++ liftFields
+      legacyConfigureFlags
+      (\flags pkgconf -> pkgconf {
+          legacyConfigureFlags = flags
+        }
+      )
+      programLocationsFieldDescrs
+
+-- | The definition of the @package pkgfoo@ sections of the @cabal.project@-format
+-- files. This section is per-package name. The special package @*@ applies to all
+-- packages used anywhere by the project, locally or as dependencies.
+--
 packageSpecificOptionsSectionDescr :: SectionDescr LegacyProjectConfig
 packageSpecificOptionsSectionDescr =
     SectionDescr {
       sectionName        = "package",
-      sectionFields      = legacyPackageConfigFieldDescrs
-                        ++ programOptionsFieldDescrs
-                             (configProgramArgs . legacyConfigureFlags)
-                             (\args pkgconf -> pkgconf {
-                                 legacyConfigureFlags = (legacyConfigureFlags pkgconf) {
-                                   configProgramArgs  = args
-                                 }
-                               }
-                             )
-                        ++ liftFields
-                             legacyConfigureFlags
-                             (\flags pkgconf -> pkgconf {
-                                 legacyConfigureFlags = flags
-                               }
-                             )
-                             programLocationsFieldDescrs,
+      sectionFields      = packageSpecificOptionsFieldDescrs,
       sectionSubsections = [],
       sectionGet         = \projconf ->
                              [ (display pkgname, pkgconf)
                              | (pkgname, pkgconf) <-
                                  Map.toList . getMapMappend
-                               . legacySpecificConfig $ projconf ],
+                               . legacySpecificConfig $ projconf ]
+                          ++ [ ("*", legacyAllConfig projconf) ],
       sectionSet         =
-        \lineno pkgnamestr pkgconf projconf -> do
-          pkgname <- case simpleParse pkgnamestr of
-            Just pkgname -> return pkgname
-            Nothing      -> syntaxError lineno $
-                                "a 'package' section requires a package name "
-                             ++ "as an argument"
-          return projconf {
-            legacySpecificConfig =
-              MapMappend $
-              Map.insertWith mappend pkgname pkgconf
-                             (getMapMappend $ legacySpecificConfig projconf)
-          },
+        \lineno pkgnamestr pkgconf projconf -> case pkgnamestr of
+          "*" -> return projconf {
+                   legacyAllConfig = legacyAllConfig projconf <> pkgconf
+                 }
+          _   -> do
+            pkgname <- case simpleParse pkgnamestr of
+              Just pkgname -> return pkgname
+              Nothing      -> syntaxError lineno $
+                                  "a 'package' section requires a package name "
+                               ++ "as an argument"
+            return projconf {
+              legacySpecificConfig =
+                MapMappend $
+                Map.insertWith mappend pkgname pkgconf
+                               (getMapMappend $ legacySpecificConfig projconf)
+            },
       sectionEmpty       = mempty
     }
 
diff --git a/cabal/cabal-install/Distribution/Client/ProjectConfig/Types.hs b/cabal/cabal-install/Distribution/Client/ProjectConfig/Types.hs
--- a/cabal/cabal-install/Distribution/Client/ProjectConfig/Types.hs
+++ b/cabal/cabal-install/Distribution/Client/ProjectConfig/Types.hs
@@ -21,7 +21,8 @@
   ) where
 
 import Distribution.Client.Types
-         ( RemoteRepo, AllowNewer(..), AllowOlder(..) )
+         ( RemoteRepo, AllowNewer(..), AllowOlder(..)
+         , WriteGhcEnvironmentFilesPolicy )
 import Distribution.Client.Dependency.Types
          ( PreSolver )
 import Distribution.Client.Targets
@@ -113,6 +114,10 @@
        projectConfigShared          :: ProjectConfigShared,
        projectConfigProvenance      :: Set ProjectConfigProvenance,
 
+       -- | Configuration to be applied to *all* packages,
+       -- whether named in `cabal.project` or not.
+       projectConfigAllPackages     :: PackageConfig,
+
        -- | Configuration to be applied to *local* packages; i.e.,
        -- any packages which are explicitly named in `cabal.project`.
        projectConfigLocalPackages   :: PackageConfig,
@@ -143,8 +148,7 @@
        projectConfigHttpTransport         :: Flag String,
        projectConfigIgnoreExpiry          :: Flag Bool,
        projectConfigCacheDir              :: Flag FilePath,
-       projectConfigLogsDir               :: Flag FilePath,
-       projectConfigStoreDir              :: Flag FilePath
+       projectConfigLogsDir               :: Flag FilePath
      }
   deriving (Eq, Show, Generic)
 
@@ -174,6 +178,7 @@
        projectConfigRemoteRepos       :: NubList RemoteRepo,     -- ^ Available Hackage servers.
        projectConfigLocalRepos        :: NubList FilePath,
        projectConfigIndexState        :: Flag IndexState,
+       projectConfigStoreDir          :: Flag FilePath,
 
        -- solver configuration
        projectConfigConstraints       :: [(UserConstraint, ConstraintSource)],
@@ -182,14 +187,18 @@
        projectConfigSolver            :: Flag PreSolver,
        projectConfigAllowOlder        :: Maybe AllowOlder,
        projectConfigAllowNewer        :: Maybe AllowNewer,
+       projectConfigWriteGhcEnvironmentFilesPolicy
+                                      :: Flag WriteGhcEnvironmentFilesPolicy,
        projectConfigMaxBackjumps      :: Flag Int,
        projectConfigReorderGoals      :: Flag ReorderGoals,
        projectConfigCountConflicts    :: Flag CountConflicts,
        projectConfigStrongFlags       :: Flag StrongFlags,
        projectConfigAllowBootLibInstalls :: Flag AllowBootLibInstalls,
        projectConfigPerComponent      :: Flag Bool,
-       projectConfigIndependentGoals  :: Flag IndependentGoals
+       projectConfigIndependentGoals  :: Flag IndependentGoals,
 
+       projectConfigProgPathExtra     :: NubList FilePath
+
        -- More things that only make sense for manual mode, not --local mode
        -- too much control!
      --projectConfigShadowPkgs        :: Flag Bool,
@@ -263,7 +272,8 @@
        packageConfigHaddockBenchmarks   :: Flag Bool, --TODO: [required eventually] use this
        packageConfigHaddockInternal     :: Flag Bool, --TODO: [required eventually] use this
        packageConfigHaddockCss          :: Flag FilePath, --TODO: [required eventually] use this
-       packageConfigHaddockHscolour     :: Flag Bool, --TODO: [required eventually] use this
+       packageConfigHaddockLinkedSource :: Flag Bool, --TODO: [required eventually] use this
+       packageConfigHaddockQuickJump    :: Flag Bool, --TODO: [required eventually] use this
        packageConfigHaddockHscolourCss  :: Flag FilePath, --TODO: [required eventually] use this
        packageConfigHaddockContents     :: Flag PathTemplate, --TODO: [required eventually] use this
        packageConfigHaddockForHackage   :: Flag HaddockTarget
@@ -410,6 +420,6 @@
        buildSettingLocalRepos            :: [FilePath],
        buildSettingCacheDir              :: FilePath,
        buildSettingHttpTransport         :: Maybe String,
-       buildSettingIgnoreExpiry          :: Bool
+       buildSettingIgnoreExpiry          :: Bool,
+       buildSettingProgPathExtra         :: [FilePath]
      }
-
diff --git a/cabal/cabal-install/Distribution/Client/ProjectOrchestration.hs b/cabal/cabal-install/Distribution/Client/ProjectOrchestration.hs
--- a/cabal/cabal-install/Distribution/Client/ProjectOrchestration.hs
+++ b/cabal/cabal-install/Distribution/Client/ProjectOrchestration.hs
@@ -47,6 +47,7 @@
     commandLineFlagsToProjectConfig,
 
     -- * Pre-build phase: decide what to do.
+    withInstallPlan,
     runProjectPreBuildPhase,
     ProjectBuildContext(..),
 
@@ -56,6 +57,7 @@
     resolveTargets,
     TargetsMap,
     TargetSelector(..),
+    TargetImplicitCwd(..),
     PackageId,
     AvailableTarget(..),
     AvailableTargetStatus(..),
@@ -94,6 +96,11 @@
     cmdCommonHelpTextNewBuildBeta,
   ) where
 
+import Prelude ()
+import Distribution.Client.Compat.Prelude
+import Distribution.Compat.Directory
+         ( makeAbsolute )
+
 import           Distribution.Client.ProjectConfig
 import           Distribution.Client.ProjectPlanning
                    hiding ( pruneInstallPlanToTargets )
@@ -105,15 +112,25 @@
 
 import           Distribution.Client.Types
                    ( GenericReadyPackage(..), UnresolvedSourcePackage
-                   , PackageSpecifier(..) )
+                   , PackageSpecifier(..)
+                   , SourcePackageDb(..)
+                   , WriteGhcEnvironmentFilesPolicy(..) )
+import           Distribution.Solver.Types.PackageIndex
+                   ( lookupPackageName )
 import qualified Distribution.Client.InstallPlan as InstallPlan
 import           Distribution.Client.TargetSelector
-                   ( TargetSelector(..)
+                   ( TargetSelector(..), TargetImplicitCwd(..)
                    , ComponentKind(..), componentKind
                    , readTargetSelectors, reportTargetSelectorProblems )
 import           Distribution.Client.DistDirLayout
-import           Distribution.Client.Config (defaultCabalDir)
+import           Distribution.Client.Config (getCabalDir)
 import           Distribution.Client.Setup hiding (packageName)
+import           Distribution.Compiler
+                   ( CompilerFlavor(GHC) )
+import           Distribution.Types.ComponentName
+                   ( componentNameString )
+import           Distribution.Types.UnqualComponentName
+                   ( UnqualComponentName, packageNameToUnqualComponentName )
 
 import           Distribution.Solver.Types.OptionalStanza
 
@@ -124,26 +141,26 @@
                    , diffFlagAssignment )
 import           Distribution.Simple.LocalBuildInfo
                    ( ComponentName(..), pkgComponents )
+import           Distribution.Simple.Flag
+                   ( fromFlagOrDefault )
 import qualified Distribution.Simple.Setup as Setup
 import           Distribution.Simple.Command (commandShowOptions)
+import           Distribution.Simple.Configure (computeEffectiveProfiling)
 
 import           Distribution.Simple.Utils
-                   ( die'
-                   , notice, noticeNoWrap, debugNoWrap )
+                   ( die', warn, notice, noticeNoWrap, debugNoWrap )
 import           Distribution.Verbosity
+import           Distribution.Version
+                   ( mkVersion )
 import           Distribution.Text
 import           Distribution.Simple.Compiler
-                   ( showCompilerId
+                   ( compilerCompatVersion, showCompilerId
                    , OptimisationLevel(..))
 
 import qualified Data.Monoid as Mon
 import qualified Data.Set as Set
 import qualified Data.Map as Map
-import           Data.Map (Map)
-import           Data.List
-import           Data.Maybe
 import           Data.Either
-import           Control.Monad (void)
 import           Control.Exception (Exception(..), throwIO, assert)
 import           System.Exit (ExitCode(..), exitFailure)
 #ifdef MIN_VERSION_unix
@@ -167,7 +184,7 @@
                             -> IO ProjectBaseContext
 establishProjectBaseContext verbosity cliConfig = do
 
-    cabalDir <- defaultCabalDir
+    cabalDir <- getCabalDir
     projectRoot <- either throwIO return =<<
                    findProjectRoot Nothing mprojectFile
 
@@ -180,13 +197,16 @@
                            cliConfig
 
     let ProjectConfigBuildOnly {
-          projectConfigLogsDir,
-          projectConfigStoreDir
+          projectConfigLogsDir
         } = projectConfigBuildOnly projectConfig
 
+        ProjectConfigShared {
+          projectConfigStoreDir
+        } = projectConfigShared projectConfig
+
         mlogsDir = Setup.flagToMaybe projectConfigLogsDir
-        mstoreDir = Setup.flagToMaybe projectConfigStoreDir
-        cabalDirLayout = mkCabalDirLayout cabalDir mstoreDir mlogsDir
+    mstoreDir <- sequenceA $ makeAbsolute <$> Setup.flagToMaybe projectConfigStoreDir
+    let cabalDirLayout = mkCabalDirLayout cabalDir mstoreDir mlogsDir
 
         buildSettings = resolveBuildTimeSettings
                           verbosity cabalDirLayout
@@ -239,6 +259,31 @@
 
 -- | Pre-build phase: decide what to do.
 --
+withInstallPlan
+    :: Verbosity
+    -> ProjectBaseContext
+    -> (ElaboratedInstallPlan -> ElaboratedSharedConfig -> IO a)
+    -> IO a
+withInstallPlan
+    verbosity
+    ProjectBaseContext {
+      distDirLayout,
+      cabalDirLayout,
+      projectConfig,
+      localPackages
+    }
+    action = do
+    -- Take the project configuration and make a plan for how to build
+    -- everything in the project. This is independent of any specific targets
+    -- the user has asked for.
+    --
+    (elaboratedPlan, _, elaboratedShared) <-
+      rebuildInstallPlan verbosity
+                         distDirLayout cabalDirLayout
+                         projectConfig
+                         localPackages
+    action elaboratedPlan elaboratedShared
+
 runProjectPreBuildPhase
     :: Verbosity
     -> ProjectBaseContext
@@ -253,7 +298,6 @@
       localPackages
     }
     selectPlanSubset = do
-
     -- Take the project configuration and make a plan for how to build
     -- everything in the project. This is independent of any specific targets
     -- the user has asked for.
@@ -353,12 +397,28 @@
                          pkgsBuildStatus
                          buildOutcomes
 
-    void $ writePlanGhcEnvironment (distProjectRootDirectory
-                                      distDirLayout)
-                                   elaboratedPlanOriginal
-                                   elaboratedShared
-                                   postBuildStatus
+    -- Write the .ghc.environment file (if allowed by the env file write policy).
+    let writeGhcEnvFilesPolicy =
+          projectConfigWriteGhcEnvironmentFilesPolicy . projectConfigShared
+          $ projectConfig
 
+        shouldWriteGhcEnvironment =
+          case fromFlagOrDefault WriteGhcEnvironmentFilesOnlyForGhc844AndNewer
+               writeGhcEnvFilesPolicy
+          of
+            AlwaysWriteGhcEnvironmentFiles                -> True
+            NeverWriteGhcEnvironmentFiles                 -> False
+            WriteGhcEnvironmentFilesOnlyForGhc844AndNewer ->
+              let compiler         = pkgConfigCompiler elaboratedShared
+                  ghcCompatVersion = compilerCompatVersion GHC compiler
+              in maybe False (>= mkVersion [8,4,4]) ghcCompatVersion
+
+    when shouldWriteGhcEnvironment $
+      void $ writePlanGhcEnvironment (distProjectRootDirectory distDirLayout)
+                                     elaboratedPlanOriginal
+                                     elaboratedShared
+                                     postBuildStatus
+
     -- Finally if there were any build failures then report them and throw
     -- an exception to terminate the program
     dieOnBuildFailures verbosity elaboratedPlanToExecute buildOutcomes
@@ -393,7 +453,7 @@
 -- possible to for different selectors to match the same target. This extra
 -- information is primarily to help make helpful error messages.
 --
-type TargetsMap = Map UnitId [(ComponentTarget, [TargetSelector PackageId])]
+type TargetsMap = Map UnitId [(ComponentTarget, [TargetSelector])]
 
 -- | Given a set of 'TargetSelector's, resolve which 'UnitId's and
 -- 'ComponentTarget's they ought to refer to.
@@ -428,105 +488,187 @@
 -- a basis for their own @selectComponentTarget@ implementation.
 --
 resolveTargets :: forall err.
-                  (forall k. TargetSelector PackageId
+                  (forall k. TargetSelector
                           -> [AvailableTarget k]
                           -> Either err [k])
-               -> (forall k. PackageId -> ComponentName -> SubComponentTarget
+               -> (forall k. SubComponentTarget
                           -> AvailableTarget k
                           -> Either err  k )
                -> (TargetProblemCommon -> err)
                -> ElaboratedInstallPlan
-               -> [TargetSelector PackageId]
+               -> Maybe (SourcePackageDb)
+               -> [TargetSelector]
                -> Either [err] TargetsMap
 resolveTargets selectPackageTargets selectComponentTarget liftProblem
-               installPlan targetSelectors =
-    --TODO: [required eventually]
-    -- we cannot resolve names of packages other than those that are
-    -- directly in the current plan. We ought to keep a set of the known
-    -- hackage packages so we can resolve names to those. Though we don't
-    -- really need that until we can do something sensible with packages
-    -- outside of the project.
+               installPlan mPkgDb =
+      fmap mkTargetsMap
+    . checkErrors
+    . map (\ts -> (,) ts <$> checkTarget ts)
+  where
+    mkTargetsMap :: [(TargetSelector, [(UnitId, ComponentTarget)])]
+                 -> TargetsMap
+    mkTargetsMap targets =
+        Map.map nubComponentTargets
+      $ Map.fromListWith (++)
+          [ (uid, [(ct, ts)])
+          | (ts, cts) <- targets
+          , (uid, ct) <- cts ]
 
-    case partitionEithers
-           [ fmap ((,) targetSelector) (checkTarget targetSelector)
-           | targetSelector <- targetSelectors ] of
-      ([], targets) -> Right
-                     . Map.map nubComponentTargets
-                     $ Map.fromListWith (++)
-                         [ (uid, [(ct, ts)])
-                         | (ts, cts) <- targets
-                         , (uid, ct) <- cts ]
+    AvailableTargetIndexes{..} = availableTargetIndexes installPlan
 
-      (problems, _) -> Left problems
-  where
-    -- TODO [required eventually] currently all build targets refer to packages
-    -- inside the project. Ultimately this has to be generalised to allow
-    -- referring to other packages and targets.
-    checkTarget :: TargetSelector PackageId
-                -> Either err [(UnitId, ComponentTarget)]
+    checkTarget :: TargetSelector -> Either err [(UnitId, ComponentTarget)]
 
     -- We can ask to build any whole package, project-local or a dependency
-    checkTarget bt@(TargetPackage _ pkgid mkfilter)
+    checkTarget bt@(TargetPackage _ [pkgid] mkfilter)
       | Just ats <- fmap (maybe id filterTargetsKind mkfilter)
-                  $ Map.lookup pkgid availableTargetsByPackage
-      = case selectPackageTargets bt ats of
-          Left  e  -> Left e
-          Right ts -> Right [ (unitid, ComponentTarget cname WholeComponent)
-                            | (unitid, cname) <- ts ]
+                  $ Map.lookup pkgid availableTargetsByPackageId
+      = fmap (componentTargets WholeComponent)
+      $ selectPackageTargets bt ats
 
       | otherwise
       = Left (liftProblem (TargetProblemNoSuchPackage pkgid))
 
+    checkTarget (TargetPackage _ _ _)
+      = error "TODO: add support for multiple packages in a directory"
+      -- For the moment this error cannot happen here, because it gets
+      -- detected when the package config is being constructed. This case
+      -- will need handling properly when we do add support.
+      --
+      -- TODO: how should this use case play together with the
+      -- '--cabal-file' option of 'configure' which allows using multiple
+      -- .cabal files for a single package?
+
     checkTarget bt@(TargetAllPackages mkfilter) =
-      let ats = maybe id filterTargetsKind mkfilter
-              $ filter availableTargetLocalToProject
-              $ concat (Map.elems availableTargetsByPackage)
-       in case selectPackageTargets bt ats of
-            Left  e  -> Left e
-            Right ts -> Right [ (unitid, ComponentTarget cname WholeComponent)
-                              | (unitid, cname) <- ts ]
+        fmap (componentTargets WholeComponent)
+      . selectPackageTargets bt
+      . maybe id filterTargetsKind mkfilter
+      . filter availableTargetLocalToProject
+      $ concat (Map.elems availableTargetsByPackageId)
 
     checkTarget (TargetComponent pkgid cname subtarget)
-      | Just ats <- Map.lookup (pkgid, cname) availableTargetsByComponent
-      = case partitionEithers
-               (map (selectComponentTarget pkgid cname subtarget) ats) of
-          (e:_,_) -> Left e
-          ([],ts) -> Right [ (unitid, ctarget)
-                           | let ctarget = ComponentTarget cname subtarget
-                           , (unitid, _) <- ts ]
+      | Just ats <- Map.lookup (pkgid, cname)
+                               availableTargetsByPackageIdAndComponentName
+      = fmap (componentTargets subtarget)
+      $ selectComponentTargets subtarget ats
 
-      | Map.member pkgid availableTargetsByPackage
+      | Map.member pkgid availableTargetsByPackageId
       = Left (liftProblem (TargetProblemNoSuchComponent pkgid cname))
 
       | otherwise
       = Left (liftProblem (TargetProblemNoSuchPackage pkgid))
 
-    checkTarget bt@(TargetPackageName pkgname)
-      | Just ats <- Map.lookup pkgname availableTargetsByPackageName
-      = case selectPackageTargets bt ats of
-          Left  e  -> Left e
-          Right ts -> Right [ (unitid, ComponentTarget cname WholeComponent)
-                            | (unitid, cname) <- ts ]
+    checkTarget (TargetComponentUnknown pkgname ecname subtarget)
+      | Just ats <- case ecname of
+          Left ucname ->
+            Map.lookup (pkgname, ucname)
+                       availableTargetsByPackageNameAndUnqualComponentName
+          Right cname ->
+            Map.lookup (pkgname, cname)
+                       availableTargetsByPackageNameAndComponentName
+      = fmap (componentTargets subtarget)
+      $ selectComponentTargets subtarget ats
 
+      | Map.member pkgname availableTargetsByPackageName
+      = Left (liftProblem (TargetProblemUnknownComponent pkgname ecname))
+
       | otherwise
       = Left (liftProblem (TargetNotInProject pkgname))
-    --TODO: check if the package is in the plan, even if it's not local
-    --TODO: check if the package is in hackage and return different
-    -- error cases here so the commands can handle things appropriately
 
-    availableTargetsByPackage     :: Map PackageId                  [AvailableTarget (UnitId, ComponentName)]
-    availableTargetsByPackageName :: Map PackageName                [AvailableTarget (UnitId, ComponentName)]
-    availableTargetsByComponent   :: Map (PackageId, ComponentName) [AvailableTarget (UnitId, ComponentName)]
+    checkTarget bt@(TargetPackageNamed pkgname mkfilter)
+      | Just ats <- fmap (maybe id filterTargetsKind mkfilter)
+                  $ Map.lookup pkgname availableTargetsByPackageName
+      = fmap (componentTargets WholeComponent)
+      . selectPackageTargets bt
+      $ ats
 
-    availableTargetsByComponent   = availableTargets installPlan
-    availableTargetsByPackage     = Map.mapKeysWith
-                                      (++) (\(pkgid, _cname) -> pkgid)
-                                      availableTargetsByComponent
-                        `Map.union` availableTargetsEmptyPackages
-    availableTargetsByPackageName = Map.mapKeysWith
-                                    (++) packageName
-                                    availableTargetsByPackage
+      | Just SourcePackageDb{ packageIndex } <- mPkgDb
+      , let pkg = lookupPackageName packageIndex pkgname
+      , not (null pkg)
+      = Left (liftProblem (TargetAvailableInIndex pkgname))
 
+      | otherwise
+      = Left (liftProblem (TargetNotInProject pkgname))
+
+    componentTargets :: SubComponentTarget
+                     -> [(b, ComponentName)]
+                     -> [(b, ComponentTarget)]
+    componentTargets subtarget =
+      map (fmap (\cname -> ComponentTarget cname subtarget))
+
+    selectComponentTargets :: SubComponentTarget
+                           -> [AvailableTarget k]
+                           -> Either err [k]
+    selectComponentTargets subtarget =
+        either (Left . head) Right
+      . checkErrors
+      . map (selectComponentTarget subtarget)
+
+    checkErrors :: [Either e a] -> Either [e] [a]
+    checkErrors = (\(es, xs) -> if null es then Right xs else Left es)
+                . partitionEithers
+
+
+data AvailableTargetIndexes = AvailableTargetIndexes {
+       availableTargetsByPackageIdAndComponentName
+         :: AvailableTargetsMap (PackageId, ComponentName),
+
+       availableTargetsByPackageId
+         :: AvailableTargetsMap PackageId,
+
+       availableTargetsByPackageName
+         :: AvailableTargetsMap PackageName,
+
+       availableTargetsByPackageNameAndComponentName
+         :: AvailableTargetsMap (PackageName, ComponentName),
+
+       availableTargetsByPackageNameAndUnqualComponentName
+         :: AvailableTargetsMap (PackageName, UnqualComponentName)
+     }
+type AvailableTargetsMap k = Map k [AvailableTarget (UnitId, ComponentName)]
+
+-- We define a bunch of indexes to help 'resolveTargets' with resolving
+-- 'TargetSelector's to specific 'UnitId's.
+--
+-- They are all derived from the 'availableTargets' index.
+-- The 'availableTargetsByPackageIdAndComponentName' is just that main index,
+-- while the others are derived by re-grouping on the index key.
+--
+-- They are all constructed lazily because they are not necessarily all used.
+--
+availableTargetIndexes :: ElaboratedInstallPlan -> AvailableTargetIndexes
+availableTargetIndexes installPlan = AvailableTargetIndexes{..}
+  where
+    availableTargetsByPackageIdAndComponentName =
+      availableTargets installPlan
+
+    availableTargetsByPackageId =
+                  Map.mapKeysWith
+                    (++) (\(pkgid, _cname) -> pkgid)
+                    availableTargetsByPackageIdAndComponentName
+      `Map.union` availableTargetsEmptyPackages
+
+    availableTargetsByPackageName =
+      Map.mapKeysWith
+        (++) packageName
+        availableTargetsByPackageId
+
+    availableTargetsByPackageNameAndComponentName =
+      Map.mapKeysWith
+        (++) (\(pkgid, cname) -> (packageName pkgid, cname))
+        availableTargetsByPackageIdAndComponentName
+
+    availableTargetsByPackageNameAndUnqualComponentName =
+      Map.mapKeysWith
+        (++) (\(pkgid, cname) -> let pname  = packageName pkgid
+                                     cname' = unqualComponentName pname cname
+                                  in (pname, cname'))
+        availableTargetsByPackageIdAndComponentName
+     where
+       unqualComponentName :: PackageName -> ComponentName -> UnqualComponentName
+       unqualComponentName pkgname =
+           fromMaybe (packageNameToUnqualComponentName pkgname)
+         . componentNameString
+
     -- Add in all the empty packages. These do not appear in the
     -- availableTargetsByComponent map, since that only contains components
     -- so packages with no components are invisible from that perspective.
@@ -589,12 +731,15 @@
 -- buildable and isn't a test suite or benchmark that is disabled. This
 -- can also be used to do these basic checks as part of a custom impl that
 --
-selectComponentTargetBasic :: PackageId
-                           -> ComponentName
-                           -> SubComponentTarget
+selectComponentTargetBasic :: SubComponentTarget
                            -> AvailableTarget k
                            -> Either TargetProblemCommon k
-selectComponentTargetBasic pkgid cname subtarget AvailableTarget {..} =
+selectComponentTargetBasic subtarget
+                           AvailableTarget {
+                             availableTargetPackageId     = pkgid,
+                             availableTargetComponentName = cname,
+                             availableTargetStatus
+                           } =
     case availableTargetStatus of
       TargetDisabledByUser ->
         Left (TargetOptionalStanzaDisabledByUser pkgid cname subtarget)
@@ -613,10 +758,13 @@
 
 data TargetProblemCommon
    = TargetNotInProject                   PackageName
+   | TargetAvailableInIndex               PackageName
    | TargetComponentNotProjectLocal       PackageId ComponentName SubComponentTarget
    | TargetComponentNotBuildable          PackageId ComponentName SubComponentTarget
    | TargetOptionalStanzaDisabledByUser   PackageId ComponentName SubComponentTarget
    | TargetOptionalStanzaDisabledBySolver PackageId ComponentName SubComponentTarget
+   | TargetProblemUnknownComponent        PackageName
+                                          (Either UnqualComponentName ComponentName)
 
     -- The target matching stuff only returns packages local to the project,
     -- so these lookups should never fail, but if 'resolveTargets' is called
@@ -750,12 +898,7 @@
             nubFlag :: Eq a => a -> Setup.Flag a -> Setup.Flag a
             nubFlag x (Setup.Flag x') | x == x' = Setup.NoFlag
             nubFlag _ f = f
-            -- TODO: Closely logic from 'configureProfiling'.
-            tryExeProfiling = Setup.fromFlagOrDefault False
-                                (configProf fullConfigureFlags)
-            tryLibProfiling = Setup.fromFlagOrDefault False
-                                (Mon.mappend (configProf    fullConfigureFlags)
-                                             (configProfExe fullConfigureFlags))
+            (tryLibProfiling, tryExeProfiling) = computeEffectiveProfiling fullConfigureFlags
             partialConfigureFlags
               = Mon.mempty {
                 configProf    =
@@ -825,7 +968,7 @@
 
        -- For all failures, print either a short summary (if we showed the
        -- build log) or all details
-       die' verbosity $ unlines
+       dieIfNotHaddockFailure verbosity $ unlines
          [ case failureClassification of
              ShowBuildSummaryAndLog reason _
                | verbosity > normal
@@ -853,6 +996,15 @@
       , InstallPlan.Configured pkg <-
            maybeToList (InstallPlan.lookup plan pkgid)
       ]
+
+    dieIfNotHaddockFailure
+      | all isHaddockFailure failuresClassification = warn
+      | otherwise                                   = die'
+      where
+        isHaddockFailure (_, ShowBuildSummaryOnly   (HaddocksFailed _)  ) = True
+        isHaddockFailure (_, ShowBuildSummaryAndLog (HaddocksFailed _) _) = True
+        isHaddockFailure _                                                = False
+
 
     classifyBuildFailure :: BuildFailure -> BuildFailurePresentation
     classifyBuildFailure BuildFailure {
diff --git a/cabal/cabal-install/Distribution/Client/ProjectPlanOutput.hs b/cabal/cabal-install/Distribution/Client/ProjectPlanOutput.hs
--- a/cabal/cabal-install/Distribution/Client/ProjectPlanOutput.hs
+++ b/cabal/cabal-install/Distribution/Client/ProjectPlanOutput.hs
@@ -18,8 +18,8 @@
 import           Distribution.Client.ProjectPlanning.Types
 import           Distribution.Client.ProjectBuilding.Types
 import           Distribution.Client.DistDirLayout
-import           Distribution.Client.Types (confInstId)
-import           Distribution.Client.PackageHash (showHashValue)
+import           Distribution.Client.Types (Repo(..), RemoteRepo(..), PackageLocation(..), confInstId)
+import           Distribution.Client.PackageHash (showHashValue, hashValue)
 
 import qualified Distribution.Client.InstallPlan as InstallPlan
 import qualified Distribution.Client.Utils.Json as J
@@ -139,7 +139,10 @@
         , "flags"      J..= J.object [ PD.unFlagName fn J..= v
                                      | (fn,v) <- PD.unFlagAssignment (elabFlagAssignment elab) ]
         , "style"      J..= J.String (style2str (elabLocalToProject elab) (elabBuildStyle elab))
+        , "pkg-src"    J..= packageLocationToJ (elabPkgSourceLocation elab)
         ] ++
+        [ "pkg-cabal-sha256" J..= J.String (showHashValue hash)
+        | Just hash <- [ fmap hashValue (elabPkgDescriptionOverride elab) ] ] ++
         [ "pkg-src-sha256" J..= J.String (showHashValue hash)
         | Just hash <- [elabPkgSourceHash elab] ] ++
         (case elabBuildStyle elab of
@@ -154,7 +157,8 @@
             let components = J.object $
                   [ comp2str c J..= (J.object $
                     [ "depends"     J..= map (jdisplay . confInstId) ldeps
-                    , "exe-depends" J..= map (jdisplay . confInstId) edeps ] ++
+                    , "exe-depends" J..= map (jdisplay . confInstId) edeps
+                    ] ++
                     bin_file c)
                   | (c,(ldeps,edeps))
                       <- ComponentDeps.toList $
@@ -168,6 +172,57 @@
             ] ++
             bin_file (compSolverName comp)
      where
+      packageLocationToJ :: PackageLocation (Maybe FilePath) -> J.Value
+      packageLocationToJ pkgloc =
+        case pkgloc of
+          LocalUnpackedPackage local ->
+            J.object [ "type" J..= J.String "local"
+                     , "path" J..= J.String local
+                     ]
+          LocalTarballPackage local ->
+            J.object [ "type" J..= J.String "local-tar"
+                     , "path" J..= J.String local
+                     ]
+          RemoteTarballPackage uri _ ->
+            J.object [ "type" J..= J.String "remote-tar"
+                     , "uri"  J..= J.String (show uri)
+                     ]
+          RepoTarballPackage repo _ _ ->
+            J.object [ "type" J..= J.String "repo-tar"
+                     , "repo" J..= repoToJ repo
+                     ]
+          RemoteSourceRepoPackage srcRepo _ ->
+            J.object [ "type" J..= J.String "source-repo"
+                     , "source-repo" J..= sourceRepoToJ srcRepo
+                     ]
+
+      repoToJ :: Repo -> J.Value
+      repoToJ repo =
+        case repo of
+          RepoLocal{..} ->
+            J.object [ "type" J..= J.String "local-repo"
+                     , "path" J..= J.String repoLocalDir
+                     ]
+          RepoRemote{..} ->
+            J.object [ "type" J..= J.String "remote-repo"
+                     , "uri"  J..= J.String (show (remoteRepoURI repoRemote))
+                     ]
+          RepoSecure{..} ->
+            J.object [ "type" J..= J.String "secure-repo"
+                     , "uri"  J..= J.String (show (remoteRepoURI repoRemote))
+                     ]
+
+      sourceRepoToJ :: PD.SourceRepo -> J.Value
+      sourceRepoToJ PD.SourceRepo{..} =
+        J.object $ filter ((/= J.Null) . snd) $
+          [ "type"     J..= fmap jdisplay repoType
+          , "location" J..= fmap J.String repoLocation
+          , "module"   J..= fmap J.String repoModule
+          , "branch"   J..= fmap J.String repoBranch
+          , "tag"      J..= fmap J.String repoTag
+          , "subdir"   J..= fmap J.String repoSubdir
+          ]
+
       dist_dir = distBuildDirectory distDirLayout
                     (elabDistDirParams elaboratedSharedConfig elab)
 
@@ -510,7 +565,7 @@
       Graph.revClosure packagesLibDepGraph
         ( Map.keys
         . Map.filter (uncurry buildAttempted)
-        $ Map.intersectionWith (,) pkgBuildStatus buildOutcomes 
+        $ Map.intersectionWith (,) pkgBuildStatus buildOutcomes
         )
 
     -- The plan graph but only counting dependency-on-library edges
@@ -881,4 +936,3 @@
       UserPackageDB          -> UserPackageDB
       SpecificPackageDB path -> SpecificPackageDB relpath
         where relpath = makeRelative relroot path
-
diff --git a/cabal/cabal-install/Distribution/Client/ProjectPlanning.hs b/cabal/cabal-install/Distribution/Client/ProjectPlanning.hs
--- a/cabal/cabal-install/Distribution/Client/ProjectPlanning.hs
+++ b/cabal/cabal-install/Distribution/Client/ProjectPlanning.hs
@@ -56,6 +56,7 @@
     setupHsCopyFlags,
     setupHsRegisterFlags,
     setupHsHaddockFlags,
+    setupHsHaddockArgs,
 
     packageHashInputs,
 
@@ -80,11 +81,13 @@
 import           Distribution.Client.Dependency
 import           Distribution.Client.Dependency.Types
 import qualified Distribution.Client.IndexUtils as IndexUtils
+import           Distribution.Client.Init (incVersion)
 import           Distribution.Client.Targets (userToPackageConstraint)
 import           Distribution.Client.DistDirLayout
 import           Distribution.Client.SetupWrapper
 import           Distribution.Client.JobControl
 import           Distribution.Client.FetchUtils
+import           Distribution.Client.Config
 import qualified Hackage.Security.Client as Sec
 import           Distribution.Client.Setup hiding (packageName, cabalVersion)
 import           Distribution.Utils.NubList
@@ -141,7 +144,7 @@
 import           Distribution.Backpack
 import           Distribution.Types.ComponentInclude
 
-import           Distribution.Simple.Utils hiding (matchFileGlob)
+import           Distribution.Simple.Utils
 import           Distribution.Version
 import           Distribution.Verbosity
 import           Distribution.Text
@@ -293,41 +296,57 @@
 rebuildProjectConfig :: Verbosity
                      -> DistDirLayout
                      -> ProjectConfig
-                     -> IO (ProjectConfig,
-                            [PackageSpecifier UnresolvedSourcePackage])
+                     -> IO ( ProjectConfig
+                           , [PackageSpecifier UnresolvedSourcePackage] )
 rebuildProjectConfig verbosity
                      distDirLayout@DistDirLayout {
                        distProjectRootDirectory,
                        distDirectory,
                        distProjectCacheFile,
-                       distProjectCacheDirectory
+                       distProjectCacheDirectory,
+                       distProjectFile
                      }
                      cliConfig = do
 
+    fileMonitorProjectConfigKey <- do
+      configPath <- getConfigFilePath projectConfigConfigFile
+      return (configPath, distProjectFile "")
+
     (projectConfig, localPackages) <-
-      runRebuild distProjectRootDirectory $
-      rerunIfChanged verbosity fileMonitorProjectConfig () $ do
+      runRebuild distProjectRootDirectory
+      $ rerunIfChanged verbosity
+                       fileMonitorProjectConfig
+                       fileMonitorProjectConfigKey
+      $ do
+          liftIO $ info verbosity "Project settings changed, reconfiguring..."
+          projectConfig <- phaseReadProjectConfig
+          localPackages <- phaseReadLocalPackages projectConfig
+          return (projectConfig, localPackages)
 
-        projectConfig <- phaseReadProjectConfig
-        localPackages <- phaseReadLocalPackages projectConfig
-        return (projectConfig, localPackages)
+    info verbosity
+      $ unlines
+      $ ("this build was affected by the following (project) config files:" :)
+      $ [ "- " ++ path
+        | Explicit path <- Set.toList $ projectConfigProvenance projectConfig
+        ]
 
     return (projectConfig <> cliConfig, localPackages)
 
   where
-    ProjectConfigShared {
-      projectConfigConfigFile
-    } = projectConfigShared cliConfig
 
-    fileMonitorProjectConfig = newFileMonitor (distProjectCacheFile "config")
+    ProjectConfigShared { projectConfigConfigFile } =
+      projectConfigShared cliConfig
 
+    fileMonitorProjectConfig =
+      newFileMonitor (distProjectCacheFile "config") :: FileMonitor
+          (FilePath, FilePath)
+          (ProjectConfig, [PackageSpecifier UnresolvedSourcePackage])
+
     -- Read the cabal.project (or implicit config) and combine it with
     -- arguments from the command line
     --
     phaseReadProjectConfig :: Rebuild ProjectConfig
     phaseReadProjectConfig = do
-      liftIO $ do
-        info verbosity "Project settings changed, reconfiguring..."
       readProjectConfig verbosity projectConfigConfigFile distDirLayout
 
     -- Look for all the cabal packages in the project
@@ -335,8 +354,11 @@
     --
     phaseReadLocalPackages :: ProjectConfig
                            -> Rebuild [PackageSpecifier UnresolvedSourcePackage]
-    phaseReadLocalPackages projectConfig = do
-      localCabalFiles <- findProjectPackages distDirLayout projectConfig
+    phaseReadLocalPackages projectConfig@ProjectConfig {
+                               projectConfigShared,
+                               projectConfigBuildOnly
+                             } = do
+      pkgLocations <- findProjectPackages distDirLayout projectConfig
 
       -- Create folder only if findProjectPackages did not throw a
       -- BadPackageLocations exception.
@@ -344,7 +366,10 @@
         createDirectoryIfMissingVerbose verbosity True distDirectory
         createDirectoryIfMissingVerbose verbosity True distProjectCacheDirectory
 
-      mapM (readSourcePackage verbosity) localCabalFiles
+      fetchAndReadSourcePackages verbosity distDirLayout
+                                 projectConfigShared
+                                 projectConfigBuildOnly
+                                 pkgLocations
 
 
 -- | Return an up-to-date elaborated install plan.
@@ -585,11 +610,12 @@
                        -> (Compiler, Platform, ProgramDb)
                        -> PkgConfigDb
                        -> SolverInstallPlan
-                       -> [PackageSpecifier (SourcePackage loc)]
+                       -> [PackageSpecifier (SourcePackage (PackageLocation loc))]
                        -> Rebuild ( ElaboratedInstallPlan
                                   , ElaboratedSharedConfig )
     phaseElaboratePlan ProjectConfig {
                          projectConfigShared,
+                         projectConfigAllPackages,
                          projectConfigLocalPackages,
                          projectConfigSpecificPackage,
                          projectConfigBuildOnly
@@ -617,6 +643,7 @@
                 sourcePackageHashes
                 defaultInstallDirs
                 projectConfigShared
+                projectConfigAllPackages
                 projectConfigLocalPackages
                 (getMapMappend projectConfigSpecificPackage)
         let instantiatedPlan = instantiateInstallPlan elaboratedPlan
@@ -947,18 +974,8 @@
                                    . PD.packageDescription
                                    . packageDescription)
 
-      . addSetupCabalMinVersionConstraint (mkVersion [1,20])
-          -- While we can talk to older Cabal versions (we need to be able to
-          -- do so for custom Setup scripts that require older Cabal lib
-          -- versions), we have problems talking to some older versions that
-          -- don't support certain features.
-          --
-          -- For example, Cabal-1.16 and older do not know about build targets.
-          -- Even worse, 1.18 and older only supported the --constraint flag
-          -- with source package ids, not --dependency with installed package
-          -- ids. That is bad because we cannot reliably select the right
-          -- dependencies in the presence of multiple instances (i.e. the
-          -- store). See issue #3932. So we require Cabal 1.20 as a minimum.
+      . addSetupCabalMinVersionConstraint setupMinCabalVersionConstraint
+      . addSetupCabalMaxVersionConstraint setupMaxCabalVersionConstraint
 
       . addPreferences
           -- preferences from the config file or command line
@@ -1027,7 +1044,73 @@
         installedPkgIndex sourcePkgDb
         localPackages
 
+    -- While we can talk to older Cabal versions (we need to be able to
+    -- do so for custom Setup scripts that require older Cabal lib
+    -- versions), we have problems talking to some older versions that
+    -- don't support certain features.
+    --
+    -- For example, Cabal-1.16 and older do not know about build targets.
+    -- Even worse, 1.18 and older only supported the --constraint flag
+    -- with source package ids, not --dependency with installed package
+    -- ids. That is bad because we cannot reliably select the right
+    -- dependencies in the presence of multiple instances (i.e. the
+    -- store). See issue #3932. So we require Cabal 1.20 as a minimum.
+    --
+    -- Moreover, lib:Cabal generally only supports the interface of
+    -- current and past compilers; in fact recent lib:Cabal versions
+    -- will warn when they encounter a too new or unknown GHC compiler
+    -- version (c.f. #415). To avoid running into unsupported
+    -- configurations we encode the compatiblity matrix as lower
+    -- bounds on lib:Cabal here (effectively corresponding to the
+    -- respective major Cabal version bundled with the respective GHC
+    -- release).
+    --
+    -- GHC 8.4   needs  Cabal >= 2.4
+    -- GHC 8.4   needs  Cabal >= 2.2
+    -- GHC 8.2   needs  Cabal >= 2.0
+    -- GHC 8.0   needs  Cabal >= 1.24
+    -- GHC 7.10  needs  Cabal >= 1.22
+    --
+    -- (NB: we don't need to consider older GHCs as Cabal >= 1.20 is
+    -- the absolute lower bound)
+    --
+    -- TODO: long-term, this compatibility matrix should be
+    --       stored as a field inside 'Distribution.Compiler.Compiler'
+    setupMinCabalVersionConstraint
+      | isGHC, compVer >= mkVersion [8,6,1] = mkVersion [2,4]
+        -- GHC 8.6alpha2 (GHC 8.6.0.20180714) still shipped with a
+        -- devel snapshot of Cabal-2.3.0.0; the rule below can be
+        -- dropped at some point
+      | isGHC, compVer >= mkVersion [8,6]  = mkVersion [2,3]
+      | isGHC, compVer >= mkVersion [8,4]  = mkVersion [2,2]
+      | isGHC, compVer >= mkVersion [8,2]  = mkVersion [2,0]
+      | isGHC, compVer >= mkVersion [8,0]  = mkVersion [1,24]
+      | isGHC, compVer >= mkVersion [7,10] = mkVersion [1,22]
+      | otherwise                          = mkVersion [1,20]
+      where
+        isGHC    = compFlav `elem` [GHC,GHCJS]
+        compFlav = compilerFlavor comp
+        compVer  = compilerVersion comp
 
+    -- As we can't predict the future, we also place a global upper
+    -- bound on the lib:Cabal version we know how to interact with:
+    --
+    -- The upper bound is computed by incrementing the current major
+    -- version twice in order to allow for the current version, as
+    -- well as the next adjacent major version (one of which will not
+    -- be released, as only "even major" versions of Cabal are
+    -- released to Hackage or bundled with proper GHC releases).
+    --
+    -- For instance, if the current version of cabal-install is an odd
+    -- development version, e.g.  Cabal-2.1.0.0, then we impose an
+    -- upper bound `setup.Cabal < 2.3`; if `cabal-install` is on a
+    -- stable/release even version, e.g. Cabal-2.2.1.0, the upper
+    -- bound is `setup.Cabal < 2.4`. This gives us enough flexibility
+    -- when dealing with development snapshots of Cabal and cabal-install.
+    --
+    setupMaxCabalVersionConstraint =
+      alterVersion (take 2) $ incVersion 1 $ incVersion 1 cabalVersion
+
 ------------------------------------------------------------------------------
 -- * Install plan post-processing
 ------------------------------------------------------------------------------
@@ -1103,9 +1186,7 @@
 --      (due to setup dependencies); we can't just look up the package name
 --      from the package description.
 --
--- However, we do have the following INVARIANT: a component never directly
--- depends on multiple versions of the same package.  Thus, we can
--- adopt the following strategy:
+-- We can adopt the following strategy:
 --
 --      * When a package is transformed into components, record
 --        a mapping from SolverId to ALL of the components
@@ -1118,12 +1199,12 @@
 -- By the way, we can tell that SolverInstallPlan is not the "right" type
 -- because a SolverId cannot adequately represent all possible dependency
 -- solver states: we may need to record foo-0.1 multiple times in
--- the solver install plan with different dependencies.  The solver probably
--- doesn't handle this correctly... but it should.  The right way to solve
--- this is to come up with something very much like a 'ConfiguredId', in that
--- it incorporates the version choices of its dependencies, but less
--- fine grained.  Fortunately, this doesn't seem to have affected anyone,
--- but it is good to watch out about.
+-- the solver install plan with different dependencies.  This imprecision in the
+-- type currently doesn't cause any problems because the dependency solver
+-- continues to enforce the single instance restriction regardless of compiler
+-- version.  The right way to solve this is to come up with something very much
+-- like a 'ConfiguredId', in that it incorporates the version choices of its
+-- dependencies, but less fine grained.
 
 
 -- | Produce an elaborated install plan using the policy for local builds with
@@ -1137,11 +1218,12 @@
   -> DistDirLayout
   -> StoreDirLayout
   -> SolverInstallPlan
-  -> [PackageSpecifier (SourcePackage loc)]
+  -> [PackageSpecifier (SourcePackage (PackageLocation loc))]
   -> Map PackageId PackageSourceHash
   -> InstallDirs.InstallDirTemplates
   -> ProjectConfigShared
   -> PackageConfig
+  -> PackageConfig
   -> Map PackageName PackageConfig
   -> LogProgress (ElaboratedInstallPlan, ElaboratedSharedConfig)
 elaborateInstallPlan verbosity platform compiler compilerprogdb pkgConfigDB
@@ -1151,6 +1233,7 @@
                      sourcePackageHashes
                      defaultInstallDirs
                      sharedPackageConfig
+                     allPackagesConfig
                      localPackagesConfig
                      perPackageConfig = do
     x <- elaboratedInstallPlan
@@ -1160,7 +1243,8 @@
       ElaboratedSharedConfig {
         pkgConfigPlatform      = platform,
         pkgConfigCompiler      = compiler,
-        pkgConfigCompilerProgs = compilerprogdb
+        pkgConfigCompilerProgs = compilerprogdb,
+        pkgConfigReplOptions   = []
       }
 
     preexistingInstantiatedPkgs =
@@ -1206,7 +1290,7 @@
             if null not_per_component_reasons
                 then return comps
                 else do checkPerPackageOk comps not_per_component_reasons
-                        return [elaborateSolverToPackage mapDep spkg g $
+                        return [elaborateSolverToPackage spkg g $
                                 comps ++ maybeToList setupComponent]
            Left cns ->
             dieProgress $
@@ -1215,19 +1299,24 @@
       where
         -- You are eligible to per-component build if this list is empty
         why_not_per_component g
-            = cuz_custom ++ cuz_spec ++ cuz_length ++ cuz_flag
+            = cuz_buildtype ++ cuz_spec ++ cuz_length ++ cuz_flag ++ cuz_coverage
           where
             cuz reason = [text reason]
-            -- At this point in time, only non-Custom setup scripts
+            -- We have to disable per-component for now with
+            -- Configure-type scripts in order to prevent parallel
+            -- invocation of the same `./configure` script.
+            -- See https://github.com/haskell/cabal/issues/4548
+            --
+            -- Moreoever, at this point in time, only non-Custom setup scripts
             -- are supported.  Implementing per-component builds with
             -- Custom would require us to create a new 'ElabSetup'
             -- type, and teach all of the code paths how to handle it.
             -- Once you've implemented this, swap it for the code below.
-            cuz_custom =
+            cuz_buildtype =
                 case PD.buildType (elabPkgDescription elab0) of
-                    Nothing        -> cuz "build-type is not specified"
-                    Just PD.Custom -> cuz "build-type is Custom"
-                    Just _         -> []
+                    PD.Configure -> cuz "build-type is Configure"
+                    PD.Custom -> cuz "build-type is Custom"
+                    _         -> []
             -- cabal-format versions prior to 1.8 have different build-depends semantics
             -- for now it's easier to just fallback to legacy-mode when specVersion < 1.8
             -- see, https://github.com/haskell/cabal/issues/4121
@@ -1247,6 +1336,12 @@
                 | fromFlagOrDefault True (projectConfigPerComponent sharedPackageConfig)
                 = []
                 | otherwise = cuz "you passed --disable-per-component"
+            -- Enabling program coverage introduces odd runtime dependencies
+            -- between components.
+            cuz_coverage
+                | fromFlagOrDefault False (packageConfigCoverage localPackagesConfig)
+                = cuz "program coverage is enabled"
+                | otherwise = []
 
         -- | Sometimes a package may make use of features which are only
         -- supported in per-package mode.  If this is the case, we should
@@ -1261,7 +1356,7 @@
                         fsep (punctuate comma reasons)
             -- TODO: Maybe exclude Backpack too
 
-        elab0 = elaborateSolverToCommon mapDep spkg
+        elab0 = elaborateSolverToCommon spkg
         pkgid = elabPkgSourceId    elab0
         pd    = elabPkgDescription elab0
 
@@ -1271,7 +1366,7 @@
         -- have to add dependencies on this from all other components
         setupComponent :: Maybe ElaboratedConfiguredPackage
         setupComponent
-            | fromMaybe PD.Custom (PD.buildType (elabPkgDescription elab0)) == PD.Custom
+            | PD.buildType (elabPkgDescription elab0) == PD.Custom
             = Just elab0 {
                 elabModuleShape = emptyModuleShape,
                 elabUnitId = notImpl "elabUnitId",
@@ -1315,10 +1410,14 @@
                           quotes (text (componentNameStanza cname))) $ do
 
             -- 1. Configure the component, but with a place holder ComponentId.
-            cc0 <- toConfiguredComponent pd
+            cc0 <- toConfiguredComponent
+                    pd
                     (error "Distribution.Client.ProjectPlanning.cc_cid: filled in later")
-                    (Map.unionWith Map.union external_cc_map cc_map) comp
+                    (Map.unionWith Map.union external_lib_cc_map cc_map)
+                    (Map.unionWith Map.union external_exe_cc_map cc_map)
+                    comp
 
+
             -- 2. Read out the dependencies from the ConfiguredComponent cc0
             let compLibDependencies =
                     -- Nub because includes can show up multiple times
@@ -1330,7 +1429,8 @@
                 compExeDependencyPaths =
                     [ (annotatedIdToConfiguredId aid', path)
                     | aid' <- cc_exe_deps cc0
-                    , Just path <- [Map.lookup (ann_id aid') exe_map1]]
+                    , Just paths <- [Map.lookup (ann_id aid') exe_map1]
+                    , path <- paths ]
                 elab_comp = ElaboratedComponent {..}
 
             -- 3. Construct a preliminary ElaboratedConfiguredPackage,
@@ -1402,20 +1502,31 @@
             -- 'elab'.
             external_lib_dep_sids = CD.select (== compSolverName) deps0
             external_exe_dep_sids = CD.select (== compSolverName) exe_deps0
-            -- TODO: The fact that lib SolverIds and exe SolverIds are
-            -- jammed together here means that we're losing information!
-            external_dep_sids = external_lib_dep_sids ++ external_exe_dep_sids
-            external_dep_pkgs = concatMap mapDep external_dep_sids
 
+            external_lib_dep_pkgs = concatMap mapDep external_lib_dep_sids
+
+            -- Combine library and build-tool dependencies, for backwards
+            -- compatibility (See issue #5412 and the documentation for
+            -- InstallPlan.fromSolverInstallPlan), but prefer the versions
+            -- specified as build-tools.
+            external_exe_dep_pkgs =
+                concatMap mapDep $
+                ordNubBy (pkgName . packageId) $
+                external_exe_dep_sids ++ external_lib_dep_sids
+
             external_exe_map = Map.fromList $
-                [ (getComponentId pkg, path)
-                | pkg <- external_dep_pkgs
-                , Just path <- [planPackageExePath pkg] ]
-            exe_map1 = Map.union external_exe_map exe_map
+                [ (getComponentId pkg, paths)
+                | pkg <- external_exe_dep_pkgs
+                , let paths = planPackageExePaths pkg ]
+            exe_map1 = Map.union external_exe_map $ fmap (\x -> [x]) exe_map
 
-            external_cc_map = Map.fromListWith Map.union
-                            $ map mkCCMapping external_dep_pkgs
-            external_lc_map = Map.fromList (map mkShapeMapping external_dep_pkgs)
+            external_lib_cc_map = Map.fromListWith Map.union
+                                $ map mkCCMapping external_lib_dep_pkgs
+            external_exe_cc_map = Map.fromListWith Map.union
+                                $ map mkCCMapping external_exe_dep_pkgs
+            external_lc_map =
+                Map.fromList $ map mkShapeMapping $
+                external_lib_dep_pkgs ++ concatMap mapDep external_exe_dep_sids
 
             compPkgConfigDependencies =
                 [ (pn, fromMaybe (error $ "compPkgConfigDependencies: impossible! "
@@ -1467,32 +1578,41 @@
                          -> SolverId -> [ElaboratedPlanPackage]
     elaborateLibSolverId mapDep = filter (matchPlanPkg (== CLibName)) . mapDep
 
-    -- | Given an 'ElaboratedPlanPackage', return the path to where the
-    -- executable that this package represents would be installed.
-    planPackageExePath :: ElaboratedPlanPackage -> Maybe FilePath
-    planPackageExePath =
+    -- | Given an 'ElaboratedPlanPackage', return the paths to where the
+    -- executables that this package represents would be installed.
+    -- The only case where multiple paths can be returned is the inplace
+    -- monolithic package one, since there can be multiple exes and each one
+    -- has its own directory.
+    planPackageExePaths :: ElaboratedPlanPackage -> [FilePath]
+    planPackageExePaths =
         -- Pre-existing executables are assumed to be in PATH
         -- already.  In fact, this should be impossible.
-        InstallPlan.foldPlanPackage (const Nothing) $ \elab -> Just $
-            binDirectoryFor
-                distDirLayout
-                elaboratedSharedConfig
-                elab $
-                    case elabPkgOrComp elab of
-                        ElabPackage _ -> ""
-                        ElabComponent comp ->
-                            case fmap Cabal.componentNameString
-                                      (compComponentName comp) of
-                                Just (Just n) -> display n
-                                _ -> ""
+        InstallPlan.foldPlanPackage (const []) $ \elab ->
+            let
+              executables :: [FilePath]
+              executables =
+                case elabPkgOrComp elab of
+                    -- Monolithic mode: all exes of the package
+                    ElabPackage _ -> unUnqualComponentName . PD.exeName
+                                 <$> PD.executables (elabPkgDescription elab)
+                    -- Per-component mode: just the selected exe
+                    ElabComponent comp ->
+                        case fmap Cabal.componentNameString
+                                  (compComponentName comp) of
+                            Just (Just n) -> [display n]
+                            _ -> [""]
+            in
+              binDirectoryFor
+                 distDirLayout
+                 elaboratedSharedConfig
+                 elab
+                 <$> executables
 
-    elaborateSolverToPackage :: (SolverId -> [ElaboratedPlanPackage])
-                             -> SolverPackage UnresolvedPkgLoc
+    elaborateSolverToPackage :: SolverPackage UnresolvedPkgLoc
                              -> ComponentsGraph
                              -> [ElaboratedConfiguredPackage]
                              -> ElaboratedConfiguredPackage
     elaborateSolverToPackage
-        mapDep
         pkg@(SolverPackage (SourcePackage pkgid _gdesc _srcloc _descOverride)
                            _flags _stanzas _deps0 _exe_deps0)
         compGraph comps =
@@ -1501,7 +1621,7 @@
         -- of the other fields of the elaboratedPackage.
         elab
       where
-        elab0@ElaboratedConfiguredPackage{..} = elaborateSolverToCommon mapDep pkg
+        elab0@ElaboratedConfiguredPackage{..} = elaborateSolverToCommon pkg
         elab = elab0 {
                 elabUnitId = newSimpleUnitId pkgInstalledId,
                 elabComponentId = pkgInstalledId,
@@ -1564,8 +1684,14 @@
                             } <- comps
                           ]
 
-        -- Filled in later
-        pkgStanzasEnabled  = Set.empty
+        -- NB: This is not the final setting of 'pkgStanzasEnabled'.
+        -- See [Sticky enabled testsuites]; we may enable some extra
+        -- stanzas opportunistically when it is cheap to do so.
+        --
+        -- However, we start off by enabling everything that was
+        -- requested, so that we can maintain an invariant that
+        -- pkgStanzasEnabled is a superset of elabStanzasRequested
+        pkgStanzasEnabled  = Map.keysSet (Map.filter (id :: Bool -> Bool) elabStanzasRequested)
 
         install_dirs
           | shouldBuildInplaceOnly pkg
@@ -1592,10 +1718,9 @@
               (compilerId compiler)
               pkgInstalledId
 
-    elaborateSolverToCommon :: (SolverId -> [ElaboratedPlanPackage])
-                            -> SolverPackage UnresolvedPkgLoc
+    elaborateSolverToCommon :: SolverPackage UnresolvedPkgLoc
                             -> ElaboratedConfiguredPackage
-    elaborateSolverToCommon mapDep
+    elaborateSolverToCommon
         pkg@(SolverPackage (SourcePackage pkgid gdesc srcloc descOverride)
                            flags stanzas deps0 _exe_deps0) =
         elaboratedPackage
@@ -1650,12 +1775,16 @@
         -- but this function doesn't know what is installed (since
         -- we haven't improved the plan yet), so we do it in another pass.
         -- Check the comments of those functions for more details.
+        elabConfigureTargets = []
         elabBuildTargets    = []
         elabTestTargets     = []
         elabBenchTargets    = []
         elabReplTarget      = Nothing
-        elabBuildHaddocks   = False
+        elabHaddockTargets  = []
 
+        elabBuildHaddocks   =
+          perPkgOptionFlag pkgid False packageConfigDocumentation
+
         elabPkgSourceLocation = srcloc
         elabPkgSourceHash   = Map.lookup pkgid sourcePackageHashes
         elabLocalToProject  = isLocalToProject pkg
@@ -1665,10 +1794,9 @@
         elabRegisterPackageDBStack = buildAndRegisterDbs
 
         elabSetupScriptStyle       = packageSetupScriptStyle elabPkgDescription
-        -- Computing the deps here is a little awful
-        deps = fmap (concatMap (elaborateLibSolverId mapDep)) deps0
-        elabSetupScriptCliVersion  = packageSetupScriptSpecVersion
-                                      elabSetupScriptStyle elabPkgDescription deps
+        elabSetupScriptCliVersion  =
+          packageSetupScriptSpecVersion
+          elabSetupScriptStyle elabPkgDescription libDepGraph deps0
         elabSetupPackageDBStack    = buildAndRegisterDbs
 
         buildAndRegisterDbs
@@ -1734,7 +1862,8 @@
         elabHaddockBenchmarks   = perPkgOptionFlag pkgid False packageConfigHaddockBenchmarks
         elabHaddockInternal     = perPkgOptionFlag pkgid False packageConfigHaddockInternal
         elabHaddockCss          = perPkgOptionMaybe pkgid packageConfigHaddockCss
-        elabHaddockHscolour     = perPkgOptionFlag pkgid False packageConfigHaddockHscolour
+        elabHaddockLinkedSource = perPkgOptionFlag pkgid False packageConfigHaddockLinkedSource
+        elabHaddockQuickJump    = perPkgOptionFlag pkgid False packageConfigHaddockQuickJump
         elabHaddockHscolourCss  = perPkgOptionMaybe pkgid packageConfigHaddockHscolourCss
         elabHaddockContents     = perPkgOptionMaybe pkgid packageConfigHaddockContents
 
@@ -1759,14 +1888,17 @@
 
     lookupPerPkgOption :: (Package pkg, Monoid m)
                        => pkg -> (PackageConfig -> m) -> m
-    lookupPerPkgOption pkg f
-      -- the project config specifies values that apply to packages local to
-      -- but by default non-local packages get all default config values
-      -- the project, and can specify per-package values for any package,
-      | isLocalToProject pkg = local `mappend` perpkg
-      | otherwise            =                 perpkg
+    lookupPerPkgOption pkg f =
+        -- This is where we merge the options from the project config that
+        -- apply to all packages, all project local packages, and to specific
+        -- named packages
+        global `mappend` local `mappend` perpkg
       where
-        local  = f localPackagesConfig
+        global = f allPackagesConfig
+        local  | isLocalToProject pkg
+               = f localPackagesConfig
+               | otherwise
+               = mempty
         perpkg = maybe mempty f (Map.lookup (packageName pkg) perPackageConfig)
 
     inplacePackageDbs = storePackageDbs
@@ -1800,12 +1932,14 @@
         --TODO: localPackages is a misnomer, it's all project packages
         -- here is where we decide which ones will be local!
       where
-        shouldBeLocal :: PackageSpecifier (SourcePackage loc) -> Maybe PackageId
+        shouldBeLocal :: PackageSpecifier (SourcePackage (PackageLocation loc)) -> Maybe PackageId
         shouldBeLocal NamedPackage{}              = Nothing
-        shouldBeLocal (SpecificSourcePackage pkg) = Just (packageId pkg)
-        -- TODO: It's not actually obvious for all of the
-        -- 'ProjectPackageLocation's that they should all be local. We might
-        -- need to provide the user with a choice.
+        shouldBeLocal (SpecificSourcePackage pkg)
+          | LocalTarballPackage _ <- packageSource pkg = Nothing
+          | otherwise = Just (packageId pkg)
+        -- TODO: Is it only LocalTarballPackages we can know about without
+        -- them being "local" in the sense meant here?
+        --
         -- Also, review use of SourcePackage's loc vs ProjectPackageLocation
 
     pkgsUseSharedLibrary :: Set PackageId
@@ -2282,7 +2416,7 @@
     componentAvailableTargetStatus
       :: Component -> AvailableTargetStatus (UnitId, ComponentName)
     componentAvailableTargetStatus component =
-        case componentOptionalStanza (componentName component) of
+        case componentOptionalStanza $ CD.componentNameToComponent cname of
           -- it is not an optional stanza, so a library, exe or foreign lib
           Nothing
             | not buildable  -> TargetNotBuildable
@@ -2361,6 +2495,7 @@
     isJust (elabReplTarget elab)
  || (not . null) (elabTestTargets elab)
  || (not . null) (elabBenchTargets elab)
+ || (not . null) (elabHaddockTargets elab)
  || (not . null) [ () | ComponentTarget _ subtarget <- elabBuildTargets elab
                       , subtarget /= WholeComponent ]
 
@@ -2383,7 +2518,8 @@
 -- | How 'pruneInstallPlanToTargets' should interpret the per-package
 -- 'ComponentTarget's: as build, repl or haddock targets.
 --
-data TargetAction = TargetActionBuild
+data TargetAction = TargetActionConfigure
+                  | TargetActionBuild
                   | TargetActionRepl
                   | TargetActionTest
                   | TargetActionBench
@@ -2394,6 +2530,10 @@
 -- to specify which optional stanzas to enable, and which targets within each
 -- package to build.
 --
+-- NB: Pruning happens after improvement, which is important because we
+-- will prune differently depending on what is already installed (to
+-- implement "sticky" test suite enabling behavior).
+--
 pruneInstallPlanToTargets :: TargetAction
                           -> Map UnitId [ComponentTarget]
                           -> ElaboratedInstallPlan -> ElaboratedInstallPlan
@@ -2452,14 +2592,26 @@
       case (Map.lookup (installedUnitId elab) perPkgTargetsMap,
             targetAction) of
         (Nothing, _)                      -> elab
+        (Just tgts,  TargetActionConfigure) -> elab { elabConfigureTargets = tgts }
         (Just tgts,  TargetActionBuild)   -> elab { elabBuildTargets = tgts }
         (Just tgts,  TargetActionTest)    -> elab { elabTestTargets  = tgts }
         (Just tgts,  TargetActionBench)   -> elab { elabBenchTargets  = tgts }
-        (Just [tgt], TargetActionRepl)    -> elab { elabReplTarget = Just tgt }
-        (Just _,     TargetActionHaddock) -> elab { elabBuildHaddocks = True }
+        (Just [tgt], TargetActionRepl)    -> elab { elabReplTarget = Just tgt
+                                                  , elabBuildHaddocks = False }
+        (Just tgts,  TargetActionHaddock) ->
+          foldr setElabHaddockTargets (elab { elabHaddockTargets = tgts
+                                            , elabBuildHaddocks = True }) tgts
         (Just _,     TargetActionRepl)    ->
           error "pruneInstallPlanToTargets: multiple repl targets"
 
+    setElabHaddockTargets tgt elab
+      | isTestComponentTarget tgt       = elab { elabHaddockTestSuites  = True }
+      | isBenchComponentTarget tgt      = elab { elabHaddockBenchmarks  = True }
+      | isForeignLibComponentTarget tgt = elab { elabHaddockForeignLibs = True }
+      | isExeComponentTarget tgt        = elab { elabHaddockExecutables = True }
+      | isSubLibComponentTarget tgt     = elab { elabHaddockInternal    = True }
+      | otherwise                       = elab
+
 -- | Assuming we have previously set the root build targets (i.e. the user
 -- targets but not rev deps yet), the first pruning pass does two things:
 --
@@ -2480,20 +2632,24 @@
     roots = mapMaybe find_root pkgs'
 
     prune elab = PrunedPackage elab' (pruneOptionalDependencies elab')
-      where elab' = pruneOptionalStanzas elab
+      where elab' =
+                setDocumentation
+              $ addOptionalStanzas elab
 
     find_root (InstallPlan.Configured (PrunedPackage elab _)) =
-        if not (null (elabBuildTargets elab)
-                    && null (elabTestTargets elab)
-                    && null (elabBenchTargets elab)
-                    && isNothing (elabReplTarget elab)
-                    && not (elabBuildHaddocks elab))
+        if not $ and [ null (elabConfigureTargets elab)
+                     , null (elabBuildTargets elab)
+                     , null (elabTestTargets elab)
+                     , null (elabBenchTargets elab)
+                     , isNothing (elabReplTarget elab)
+                     , null (elabHaddockTargets elab)
+                     ]
             then Just (installedUnitId elab)
             else Nothing
     find_root _ = Nothing
 
-    -- Decide whether or not to enable testsuites and benchmarks
-    --
+    -- Note [Sticky enabled testsuites]
+    -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     -- The testsuite and benchmark targets are somewhat special in that we need
     -- to configure the packages with them enabled, and we need to do that even
     -- if we only want to build one of several testsuites.
@@ -2507,19 +2663,52 @@
     -- would involve unnecessarily reconfiguring the package with testsuites
     -- disabled. Technically this introduces a little bit of stateful
     -- behaviour to make this "sticky", but it should be benign.
-    --
-    pruneOptionalStanzas :: ElaboratedConfiguredPackage -> ElaboratedConfiguredPackage
-    pruneOptionalStanzas elab@ElaboratedConfiguredPackage{ elabPkgOrComp = ElabPackage pkg } =
+
+    -- Decide whether or not to enable testsuites and benchmarks.
+    -- See [Sticky enabled testsuites]
+    addOptionalStanzas :: ElaboratedConfiguredPackage -> ElaboratedConfiguredPackage
+    addOptionalStanzas elab@ElaboratedConfiguredPackage{ elabPkgOrComp = ElabPackage pkg } =
         elab {
             elabPkgOrComp = ElabPackage (pkg { pkgStanzasEnabled = stanzas })
         }
       where
         stanzas :: Set OptionalStanza
-        stanzas = optionalStanzasRequiredByTargets  elab
-               <> optionalStanzasRequestedByDefault elab
+               -- By default, we enabled all stanzas requested by the user,
+               -- as per elabStanzasRequested, done in
+               -- 'elaborateSolverToPackage'
+        stanzas = pkgStanzasEnabled pkg
+               -- optionalStanzasRequiredByTargets has to be done at
+               -- prune-time because it depends on 'elabTestTargets'
+               -- et al, which is done by 'setRootTargets' at the
+               -- beginning of pruning.
+               <> optionalStanzasRequiredByTargets elab
+               -- optionalStanzasWithDepsAvailable has to be done at
+               -- prune-time because it depends on what packages are
+               -- installed, which is not known until after improvement
+               -- (pruning is done after improvement)
                <> optionalStanzasWithDepsAvailable availablePkgs elab pkg
-    pruneOptionalStanzas elab = elab
+    addOptionalStanzas elab = elab
 
+    setDocumentation :: ElaboratedConfiguredPackage -> ElaboratedConfiguredPackage
+    setDocumentation elab@ElaboratedConfiguredPackage { elabPkgOrComp = ElabComponent comp } =
+      elab {
+        elabBuildHaddocks =
+            elabBuildHaddocks elab && documentationEnabled (compSolverName comp) elab
+      }
+
+      where
+        documentationEnabled c =
+          case c of
+            CD.ComponentLib      -> const True
+            CD.ComponentSubLib _ -> elabHaddockInternal
+            CD.ComponentFLib _   -> elabHaddockForeignLibs
+            CD.ComponentExe _    -> elabHaddockExecutables
+            CD.ComponentTest _   -> elabHaddockTestSuites
+            CD.ComponentBench _  -> elabHaddockBenchmarks
+            CD.ComponentSetup    -> const False
+
+    setDocumentation elab = elab
+
     -- Calculate package dependencies but cut out those needed only by
     -- optional stanzas that we've determined we will not enable.
     -- These pruned deps are not persisted in this pass since they're based on
@@ -2546,16 +2735,12 @@
                                   ++ elabTestTargets pkg
                                   ++ elabBenchTargets pkg
                                   ++ maybeToList (elabReplTarget pkg)
-        , stanza <- maybeToList (componentOptionalStanza cname)
+                                  ++ elabHaddockTargets pkg
+        , stanza <- maybeToList $
+                    componentOptionalStanza $
+                    CD.componentNameToComponent cname
         ]
 
-    optionalStanzasRequestedByDefault :: ElaboratedConfiguredPackage
-                                      -> Set OptionalStanza
-    optionalStanzasRequestedByDefault =
-        Map.keysSet
-      . Map.filter (id :: Bool -> Bool)
-      . elabStanzasRequested
-
     availablePkgs =
       Set.fromList
         [ installedUnitId pkg
@@ -2683,11 +2868,6 @@
 mapConfiguredPackage _ (InstallPlan.PreExisting pkg) =
   InstallPlan.PreExisting pkg
 
-componentOptionalStanza :: Cabal.ComponentName -> Maybe OptionalStanza
-componentOptionalStanza (Cabal.CTestName  _) = Just TestStanzas
-componentOptionalStanza (Cabal.CBenchName _) = Just BenchStanzas
-componentOptionalStanza _                    = Nothing
-
 ------------------------------------
 -- Support for --only-dependencies
 --
@@ -2795,7 +2975,7 @@
   | otherwise
   = SetupNonCustomInternalLib
   where
-    buildType = fromMaybe PD.Custom (PD.buildType pkg)
+    buildType = PD.buildType pkg
 
 
 -- | Part of our Setup.hs handling policy is implemented by getting the solver
@@ -2875,31 +3055,34 @@
 -- of what the solver picked for us, based on the explicit setup deps or the
 -- ones added implicitly by 'defaultSetupDeps'.
 --
-packageSetupScriptSpecVersion :: Package pkg
-                              => SetupScriptStyle
+packageSetupScriptSpecVersion :: SetupScriptStyle
                               -> PD.PackageDescription
-                              -> ComponentDeps [pkg]
+                              -> Graph.Graph NonSetupLibDepSolverPlanPackage
+                              -> ComponentDeps [SolverId]
                               -> Version
 
 -- We're going to be using the internal Cabal library, so the spec version of
 -- that is simply the version of the Cabal library that cabal-install has been
 -- built with.
-packageSetupScriptSpecVersion SetupNonCustomInternalLib _ _ =
+packageSetupScriptSpecVersion SetupNonCustomInternalLib _ _ _ =
     cabalVersion
 
 -- If we happen to be building the Cabal lib itself then because that
 -- bootstraps itself then we use the version of the lib we're building.
-packageSetupScriptSpecVersion SetupCustomImplicitDeps pkg _
+packageSetupScriptSpecVersion SetupCustomImplicitDeps pkg _ _
   | packageName pkg == cabalPkgname
   = packageVersion pkg
 
 -- In all other cases we have a look at what version of the Cabal lib the
 -- solver picked. Or if it didn't depend on Cabal at all (which is very rare)
 -- then we look at the .cabal file to see what spec version it declares.
-packageSetupScriptSpecVersion _ pkg deps =
-    case find ((cabalPkgname ==) . packageName) (CD.setupDeps deps) of
+packageSetupScriptSpecVersion _ pkg libDepGraph deps =
+    case find ((cabalPkgname ==) . packageName) setupLibDeps of
       Just dep -> packageVersion dep
       Nothing  -> PD.specVersion pkg
+  where
+    setupLibDeps = map packageId $ fromMaybe [] $
+                   Graph.closure libDepGraph (CD.setupDeps deps)
 
 
 cabalPkgname, basePkgname :: PackageName
@@ -2931,7 +3114,9 @@
 -- in the store and local dbs.
 
 setupHsScriptOptions :: ElaboratedReadyPackage
+                     -> ElaboratedInstallPlan
                      -> ElaboratedSharedConfig
+                     -> DistDirLayout
                      -> FilePath
                      -> FilePath
                      -> Bool
@@ -2940,7 +3125,7 @@
 -- TODO: Fix this so custom is a separate component.  Custom can ALWAYS
 -- be a separate component!!!
 setupHsScriptOptions (ReadyPackage elab@ElaboratedConfiguredPackage{..})
-                     ElaboratedSharedConfig{..} srcdir builddir
+                     plan ElaboratedSharedConfig{..} distdir srcdir builddir
                      isParallelBuild cacheLock =
     SetupScriptOptions {
       useCabalVersion          = thisVersion elabSetupScriptCliVersion,
@@ -2959,6 +3144,7 @@
       useLoggingHandle         = Nothing, -- this gets set later
       useWorkingDir            = Just srcdir,
       useExtraPathEnv          = elabExeDependencyPaths elab,
+      useExtraEnvOverrides     = dataDirsEnvironmentForPlan distdir plan,
       useWin32CleanHack        = False,   --TODO: [required eventually]
       forceExternalSetupMethod = isParallelBuild,
       setupCacheLock           = Just cacheLock,
@@ -3070,7 +3256,7 @@
     configVanillaLib          = toFlag elabVanillaLib
     configSharedLib           = toFlag elabSharedLib
     configStaticLib           = toFlag elabStaticLib
-    
+
     configDynExe              = toFlag elabDynExe
     configGHCiLib             = toFlag elabGHCiLib
     configProfExe             = mempty
@@ -3164,7 +3350,8 @@
       buildVerbosity    = toFlag verbosity,
       buildDistPref     = toFlag builddir,
       buildNumJobs      = mempty, --TODO: [nice to have] sometimes want to use toFlag (Just numBuildJobs),
-      buildArgs         = mempty  -- unused, passed via args not flags
+      buildArgs         = mempty, -- unused, passed via args not flags
+      buildCabalFilePath= mempty
     }
 
 
@@ -3221,13 +3408,14 @@
                  -> Verbosity
                  -> FilePath
                  -> Cabal.ReplFlags
-setupHsReplFlags _ _ verbosity builddir =
+setupHsReplFlags _ sharedConfig verbosity builddir =
     Cabal.ReplFlags {
       replProgramPaths = mempty, --unused, set at configure time
       replProgramArgs  = mempty, --unused, set at configure time
       replVerbosity    = toFlag verbosity,
       replDistPref     = toFlag builddir,
-      replReload       = mempty  --only used as callback from repl
+      replReload       = mempty, --only used as callback from repl
+      replReplOptions  = pkgConfigReplOptions sharedConfig       --runtime override for repl flags
     }
 
 
@@ -3248,7 +3436,8 @@
       copyArgs      = [], -- TODO: could use this to only copy what we enabled
       copyDest      = toFlag (InstallDirs.CopyTo destdir),
       copyDistPref  = toFlag builddir,
-      copyVerbosity = toFlag verbosity
+      copyVerbosity = toFlag verbosity,
+      copyCabalFilePath = mempty
     }
 
 setupHsRegisterFlags :: ElaboratedConfiguredPackage
@@ -3269,7 +3458,8 @@
       regPrintId     = mempty,  -- never use
       regDistPref    = toFlag builddir,
       regArgs        = [],
-      regVerbosity   = toFlag verbosity
+      regVerbosity   = toFlag verbosity,
+      regCabalFilePath = mempty
     }
 
 setupHsHaddockFlags :: ElaboratedConfiguredPackage
@@ -3277,8 +3467,6 @@
                     -> Verbosity
                     -> FilePath
                     -> Cabal.HaddockFlags
--- TODO: reconsider whether or not Executables/TestSuites/...
--- needed for component
 setupHsHaddockFlags (ElaboratedConfiguredPackage{..}) _ verbosity builddir =
     Cabal.HaddockFlags {
       haddockProgramPaths  = mempty, --unused, set at configure time
@@ -3293,14 +3481,22 @@
       haddockBenchmarks    = toFlag elabHaddockBenchmarks,
       haddockInternal      = toFlag elabHaddockInternal,
       haddockCss           = maybe mempty toFlag elabHaddockCss,
-      haddockHscolour      = toFlag elabHaddockHscolour,
+      haddockLinkedSource  = toFlag elabHaddockLinkedSource,
+      haddockQuickJump     = toFlag elabHaddockQuickJump,
       haddockHscolourCss   = maybe mempty toFlag elabHaddockHscolourCss,
       haddockContents      = maybe mempty toFlag elabHaddockContents,
       haddockDistPref      = toFlag builddir,
       haddockKeepTempFiles = mempty, --TODO: from build settings
-      haddockVerbosity     = toFlag verbosity
+      haddockVerbosity     = toFlag verbosity,
+      haddockCabalFilePath = mempty,
+      haddockArgs          = mempty
     }
 
+setupHsHaddockArgs :: ElaboratedConfiguredPackage -> [String]
+-- TODO: Does the issue #3335 affects test as well
+setupHsHaddockArgs elab =
+  map (showComponentTarget (packageId elab)) (elabHaddockTargets elab)
+
 {-
 setupHsTestFlags :: ElaboratedConfiguredPackage
                  -> ElaboratedSharedConfig
@@ -3403,10 +3599,7 @@
 packageHashConfigInputs :: ElaboratedSharedConfig
                         -> ElaboratedConfiguredPackage
                         -> PackageHashConfigInputs
-packageHashConfigInputs
-    ElaboratedSharedConfig{..}
-    ElaboratedConfiguredPackage{..} =
-
+packageHashConfigInputs shared@ElaboratedSharedConfig{..} pkg =
     PackageHashConfigInputs {
       pkgHashCompilerId          = compilerId pkgConfigCompiler,
       pkgHashPlatform            = pkgConfigPlatform,
@@ -3432,9 +3625,24 @@
       pkgHashExtraFrameworkDirs  = elabExtraFrameworkDirs,
       pkgHashExtraIncludeDirs    = elabExtraIncludeDirs,
       pkgHashProgPrefix          = elabProgPrefix,
-      pkgHashProgSuffix          = elabProgSuffix
-    }
+      pkgHashProgSuffix          = elabProgSuffix,
 
+      pkgHashDocumentation       = elabBuildHaddocks,
+      pkgHashHaddockHoogle       = elabHaddockHoogle,
+      pkgHashHaddockHtml         = elabHaddockHtml,
+      pkgHashHaddockHtmlLocation = elabHaddockHtmlLocation,
+      pkgHashHaddockForeignLibs  = elabHaddockForeignLibs,
+      pkgHashHaddockExecutables  = elabHaddockExecutables,
+      pkgHashHaddockTestSuites   = elabHaddockTestSuites,
+      pkgHashHaddockBenchmarks   = elabHaddockBenchmarks,
+      pkgHashHaddockInternal     = elabHaddockInternal,
+      pkgHashHaddockCss          = elabHaddockCss,
+      pkgHashHaddockLinkedSource = elabHaddockLinkedSource,
+      pkgHashHaddockQuickJump    = elabHaddockQuickJump,
+      pkgHashHaddockContents     = elabHaddockContents
+    }
+  where
+    ElaboratedConfiguredPackage{..} = normaliseConfiguredPackage shared pkg
 
 -- | Given the 'InstalledPackageIndex' for a nix-style package store, and an
 -- 'ElaboratedInstallPlan', replace configured source packages by installed
@@ -3489,4 +3697,3 @@
 inplaceBinRoot layout config package
   =  distBuildDirectory layout (elabDistDirParams config package)
  </> "build"
-
diff --git a/cabal/cabal-install/Distribution/Client/ProjectPlanning/Types.hs b/cabal/cabal-install/Distribution/Client/ProjectPlanning/Types.hs
--- a/cabal/cabal-install/Distribution/Client/ProjectPlanning/Types.hs
+++ b/cabal/cabal-install/Distribution/Client/ProjectPlanning/Types.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE TypeFamilies #-}
 
 -- | Types used while planning how to build everything in a project.
@@ -11,6 +12,7 @@
 
     -- * Elaborated install plan types
     ElaboratedInstallPlan,
+    normaliseConfiguredPackage,
     ElaboratedConfiguredPackage(..),
 
     elabDistDirParams,
@@ -23,6 +25,7 @@
     elabPkgConfigDependencies,
     elabInplaceDependencyBuildCacheFiles,
     elabRequiresRegistration,
+    dataDirsEnvironmentForPlan,
 
     elabPlanPackageName,
     elabConfiguredName,
@@ -45,8 +48,14 @@
     showBenchComponentTarget,
     SubComponentTarget(..),
 
+    isSubLibComponentTarget,
+    isForeignLibComponentTarget,
+    isExeComponentTarget,
     isTestComponentTarget,
+    isBenchComponentTarget,
 
+    componentOptionalStanza,
+
     -- * Setup script
     SetupScriptStyle(..),
   ) where
@@ -69,14 +78,16 @@
 import           Distribution.Verbosity
 import           Distribution.Text
 import           Distribution.Types.ComponentRequestedSpec
+import           Distribution.Types.PackageDescription (PackageDescription(..))
 import           Distribution.Package
                    hiding (InstalledPackageId, installedPackageId)
 import           Distribution.System
 import qualified Distribution.PackageDescription as Cabal
 import           Distribution.InstalledPackageInfo (InstalledPackageInfo)
 import           Distribution.Simple.Compiler
+import           Distribution.Simple.Build.PathsModule (pkgPathEnvVar)
 import qualified Distribution.Simple.BuildTarget as Cabal
-import           Distribution.Simple.Program.Db
+import           Distribution.Simple.Program
 import           Distribution.ModuleName (ModuleName)
 import           Distribution.Simple.LocalBuildInfo (ComponentName(..))
 import qualified Distribution.Simple.InstallDirs as InstallDirs
@@ -91,6 +102,8 @@
 import           Distribution.Simple.Utils (ordNub)
 
 import           Data.Map (Map)
+import qualified Data.Map as Map
+import           Data.Maybe (catMaybes)
 import           Data.Set (Set)
 import qualified Data.ByteString.Lazy as LBS
 import           Distribution.Compat.Binary
@@ -98,7 +111,7 @@
 import qualified Data.Monoid as Mon
 import           Data.Typeable
 import           Control.Monad
-
+import           System.FilePath ((</>))
 
 
 -- | The combination of an elaborated install plan plus a
@@ -137,7 +150,8 @@
        -- | The programs that the compiler configured (e.g. for GHC, the progs
        -- ghc & ghc-pkg). Once constructed, only the 'configuredPrograms' are
        -- used.
-       pkgConfigCompilerProgs :: ProgramDb
+       pkgConfigCompilerProgs :: ProgramDb,
+       pkgConfigReplOptions :: [String]
      }
   deriving (Show, Generic, Typeable)
   --TODO: [code cleanup] no Eq instance
@@ -268,7 +282,8 @@
        elabHaddockBenchmarks     :: Bool,
        elabHaddockInternal       :: Bool,
        elabHaddockCss            :: Maybe FilePath,
-       elabHaddockHscolour       :: Bool,
+       elabHaddockLinkedSource   :: Bool,
+       elabHaddockQuickJump      :: Bool,
        elabHaddockHscolourCss    :: Maybe FilePath,
        elabHaddockContents       :: Maybe PathTemplate,
 
@@ -285,10 +300,13 @@
        elabSetupScriptCliVersion :: Version,
 
        -- Build time related:
+       elabConfigureTargets      :: [ComponentTarget],
        elabBuildTargets          :: [ComponentTarget],
        elabTestTargets           :: [ComponentTarget],
        elabBenchTargets          :: [ComponentTarget],
        elabReplTarget            :: Maybe ComponentTarget,
+       elabHaddockTargets        :: [ComponentTarget],
+
        elabBuildHaddocks         :: Bool,
 
        --pkgSourceDir ? -- currently passed in later because they can use temp locations
@@ -299,6 +317,29 @@
    }
   deriving (Eq, Show, Generic, Typeable)
 
+normaliseConfiguredPackage :: ElaboratedSharedConfig
+                           -> ElaboratedConfiguredPackage
+                           -> ElaboratedConfiguredPackage
+normaliseConfiguredPackage ElaboratedSharedConfig{pkgConfigCompilerProgs} pkg =
+    pkg { elabProgramArgs = Map.mapMaybeWithKey lookupFilter (elabProgramArgs pkg) }
+  where
+    knownProgramDb = addKnownPrograms builtinPrograms pkgConfigCompilerProgs
+
+    pkgDesc :: PackageDescription
+    pkgDesc = elabPkgDescription pkg
+
+    removeEmpty :: [String] -> Maybe [String]
+    removeEmpty [] = Nothing
+    removeEmpty xs = Just xs
+
+    lookupFilter :: String -> [String] -> Maybe [String]
+    lookupFilter n args = removeEmpty $ case lookupKnownProgram n knownProgramDb of
+        Just p -> programNormaliseArgs p (getVersion p) pkgDesc args
+        Nothing -> args
+
+    getVersion :: Program -> Maybe Version
+    getVersion p = lookupProgram p knownProgramDb >>= programVersion
+
 -- | The package/component contains/is a library and so must be registered
 elabRequiresRegistration :: ElaboratedConfiguredPackage -> Bool
 elabRequiresRegistration elab =
@@ -317,7 +358,24 @@
             -- register in all cases, but some Custom Setups will fall
             -- over if you try to do that, ESPECIALLY if there actually is
             -- a library but they hadn't built it.
-            build_target || any (depends_on_lib pkg) (elabBuildTargets elab)
+            --
+            -- However, as the case of `cpphs-1.20.8` has shown in
+            -- #5379, in cases when a monolithic package gets
+            -- installed due to its executable components
+            -- (i.e. exe:cpphs) into the store we *have* to register
+            -- if there's a buildable public library (i.e. lib:cpphs)
+            -- that was built and installed into the same store folder
+            -- as otherwise this will cause build failures once a
+            -- target actually depends on lib:cpphs.
+            build_target || (elabBuildStyle elab == BuildAndInstall &&
+                             Cabal.hasPublicLib (elabPkgDescription elab))
+            -- the next sub-condition below is currently redundant
+            -- (see discussion in #5604 for more details), but it's
+            -- being kept intentionally here as a safeguard because if
+            -- internal libraries ever start working with
+            -- non-per-component builds this condition won't be
+            -- redundant anymore.
+                         || any (depends_on_lib pkg) (elabBuildTargets elab)
   where
     depends_on_lib pkg (ComponentTarget cn _) =
         not (null (CD.select (== CD.componentNameToComponent cn)
@@ -337,6 +395,47 @@
     is_lib (CSubLibName _) = True
     is_lib _ = False
 
+-- | Construct the environment needed for the data files to work.
+-- This consists of a separate @*_datadir@ variable for each
+-- inplace package in the plan.
+dataDirsEnvironmentForPlan :: DistDirLayout
+                           -> ElaboratedInstallPlan
+                           -> [(String, Maybe FilePath)]
+dataDirsEnvironmentForPlan distDirLayout = catMaybes
+                           . fmap (InstallPlan.foldPlanPackage
+                               (const Nothing)
+                               (dataDirEnvVarForPackage distDirLayout))
+                           . InstallPlan.toList
+
+-- | Construct an environment variable that points
+-- the package's datadir to its correct location.
+-- This might be:
+-- * 'Just' the package's source directory plus the data subdirectory
+--   for inplace packages.
+-- * 'Nothing' for packages installed in the store (the path was
+--   already included in the package at install/build time).
+dataDirEnvVarForPackage :: DistDirLayout
+                        -> ElaboratedConfiguredPackage
+                        -> Maybe (String, Maybe FilePath)
+dataDirEnvVarForPackage distDirLayout pkg =
+  case elabBuildStyle pkg
+  of BuildAndInstall -> Nothing
+     BuildInplaceOnly -> Just
+       ( pkgPathEnvVar (elabPkgDescription pkg) "datadir"
+       , Just $ srcPath (elabPkgSourceLocation pkg)
+            </> dataDir (elabPkgDescription pkg))
+  where
+    srcPath (LocalUnpackedPackage path) = path
+    srcPath (LocalTarballPackage _path) = unpackedPath
+    srcPath (RemoteTarballPackage _uri _localTar) = unpackedPath
+    srcPath (RepoTarballPackage _repo _packageId _localTar) = unpackedPath
+    srcPath (RemoteSourceRepoPackage _sourceRepo (Just localCheckout)) = localCheckout
+    -- TODO: see https://github.com/haskell/cabal/wiki/Potential-Refactors#unresolvedpkgloc
+    srcPath (RemoteSourceRepoPackage _sourceRepo Nothing) = error
+      "calling dataDirEnvVarForPackage on a not-downloaded repo is an error"
+    unpackedPath =
+      distUnpackedSrcDirectory distDirLayout $ elabPkgSourceId pkg
+
 instance Package ElaboratedConfiguredPackage where
   packageId = elabPkgSourceId
 
@@ -667,6 +766,27 @@
 showBenchComponentTarget _ (ComponentTarget (CBenchName n) _) = Just $ display n
 showBenchComponentTarget _ _ = Nothing
 
+isBenchComponentTarget :: ComponentTarget -> Bool
+isBenchComponentTarget (ComponentTarget (CBenchName _) _) = True
+isBenchComponentTarget _                                  = False
+
+isForeignLibComponentTarget :: ComponentTarget -> Bool
+isForeignLibComponentTarget (ComponentTarget (CFLibName _) _) = True
+isForeignLibComponentTarget _                                 = False
+
+isExeComponentTarget :: ComponentTarget -> Bool
+isExeComponentTarget (ComponentTarget (CExeName _) _ ) = True
+isExeComponentTarget _                                 = False
+
+isSubLibComponentTarget :: ComponentTarget -> Bool
+isSubLibComponentTarget (ComponentTarget (CSubLibName _) _) = True
+isSubLibComponentTarget _                                   = False
+
+componentOptionalStanza :: CD.Component -> Maybe OptionalStanza
+componentOptionalStanza (CD.ComponentTest _)  = Just TestStanzas
+componentOptionalStanza (CD.ComponentBench _) = Just BenchStanzas
+componentOptionalStanza _                     = Nothing
+
 ---------------------------
 -- Setup.hs script policy
 --
@@ -695,4 +815,3 @@
   deriving (Eq, Show, Generic, Typeable)
 
 instance Binary SetupScriptStyle
-
diff --git a/cabal/cabal-install/Distribution/Client/RebuildMonad.hs b/cabal/cabal-install/Distribution/Client/RebuildMonad.hs
--- a/cabal/cabal-install/Distribution/Client/RebuildMonad.hs
+++ b/cabal/cabal-install/Distribution/Client/RebuildMonad.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving, ScopedTypeVariables, BangPatterns #-}
 
 -- | An abstraction for re-running actions if values or files have changed.
 --
@@ -41,6 +41,8 @@
     rerunIfChanged,
 
     -- * Utils
+    delayInitSharedResource,
+    delayInitSharedResources,
     matchFileGlob,
     getDirectoryContentsMonitored,
     createDirectoryMonitored,
@@ -63,8 +65,10 @@
 import Distribution.Simple.Utils (debug)
 import Distribution.Verbosity    (Verbosity)
 
+import qualified Data.Map.Strict as Map
 import Control.Monad.State as State
 import Control.Monad.Reader as Reader
+import Control.Concurrent.MVar (MVar, newMVar, modifyMVar)
 import System.FilePath
 import System.Directory
 
@@ -144,6 +148,76 @@
     showReason (MonitoredValueChanged _)   = "monitor value changed"
     showReason  MonitorFirstRun            = "first run"
     showReason  MonitorCorruptCache        = "invalid cache file"
+
+
+-- | When using 'rerunIfChanged' for each element of a list of actions, it is
+-- sometimes the case that each action needs to make use of some resource. e.g.
+--
+-- > sequence
+-- >   [ rerunIfChanged verbosity monitor key $ do
+-- >       resource <- mkResource
+-- >       ... -- use the resource
+-- >   | ... ]
+--
+-- For efficiency one would like to share the resource between the actions
+-- but the straightforward way of doing this means initialising it every time
+-- even when no actions need re-running.
+--
+-- > resource <- mkResource
+-- > sequence
+-- >   [ rerunIfChanged verbosity monitor key $ do
+-- >       ... -- use the resource
+-- >   | ... ]
+--
+-- This utility allows one to get the best of both worlds:
+--
+-- > getResource <- delayInitSharedResource mkResource
+-- > sequence
+-- >   [ rerunIfChanged verbosity monitor key $ do
+-- >       resource <- getResource
+-- >       ... -- use the resource
+-- >   | ... ]
+--
+delayInitSharedResource :: forall a. IO a -> Rebuild (Rebuild a)
+delayInitSharedResource action = do
+    var <- liftIO (newMVar Nothing)
+    return (liftIO (getOrInitResource var))
+  where
+    getOrInitResource :: MVar (Maybe a) -> IO a
+    getOrInitResource var =
+      modifyMVar var $ \mx ->
+        case mx of
+          Just x  -> return (Just x, x)
+          Nothing -> do
+            x <- action
+            return (Just x, x)
+
+
+-- | Much like 'delayInitSharedResource' but for a keyed set of resources.
+--
+-- > getResource <- delayInitSharedResource mkResource
+-- > sequence
+-- >   [ rerunIfChanged verbosity monitor key $ do
+-- >       resource <- getResource key
+-- >       ... -- use the resource
+-- >   | ... ]
+--
+delayInitSharedResources :: forall k v. Ord k
+                         => (k -> IO v)
+                         -> Rebuild (k -> Rebuild v)
+delayInitSharedResources action = do
+    var <- liftIO (newMVar Map.empty)
+    return (liftIO . getOrInitResource var)
+  where
+    getOrInitResource :: MVar (Map k v) -> k -> IO v
+    getOrInitResource var k =
+      modifyMVar var $ \m ->
+        case Map.lookup k m of
+          Just x  -> return (m, x)
+          Nothing -> do
+            x <- action k
+            let !m' = Map.insert k x m
+            return (m', x)
 
 
 -- | Utility to match a file glob against the file system, starting from a
diff --git a/cabal/cabal-install/Distribution/Client/Run.hs b/cabal/cabal-install/Distribution/Client/Run.hs
--- a/cabal/cabal-install/Distribution/Client/Run.hs
+++ b/cabal/cabal-install/Distribution/Client/Run.hs
@@ -125,7 +125,7 @@
         return (cmd, cmdArgs ++ [script'])
       _     -> do
          p <- tryCanonicalizePath $
-            buildPref </> exeName' </> (exeName' <.> exeExtension)
+            buildPref </> exeName' </> (exeName' <.> exeExtension (hostPlatform lbi))
          return (p, [])
 
   env  <- (dataDirEnvVar:) <$> getEnvironment
diff --git a/cabal/cabal-install/Distribution/Client/Sandbox/Index.hs b/cabal/cabal-install/Distribution/Client/Sandbox/Index.hs
--- a/cabal/cabal-install/Distribution/Client/Sandbox/Index.hs
+++ b/cabal/cabal-install/Distribution/Client/Sandbox/Index.hs
@@ -39,6 +39,7 @@
 import Distribution.Verbosity    ( Verbosity )
 
 import qualified Data.ByteString.Lazy as BS
+import Control.DeepSeq           ( NFData(rnf) )
 import Control.Exception         ( evaluate, throw, Exception )
 import Control.Monad             ( liftM, unless )
 import Control.Monad.Writer.Lazy (WriterT(..), runWriterT, tell)
@@ -56,6 +57,9 @@
   buildTreeRefType :: !BuildTreeRefType,
   buildTreePath     :: !FilePath
   }
+
+instance NFData BuildTreeRef where
+  rnf (BuildTreeRef _ fp) = rnf fp
 
 defaultIndexFileName :: FilePath
 defaultIndexFileName = "00-index.tar"
diff --git a/cabal/cabal-install/Distribution/Client/Setup.hs b/cabal/cabal-install/Distribution/Client/Setup.hs
--- a/cabal/cabal-install/Distribution/Client/Setup.hs
+++ b/cabal/cabal-install/Distribution/Client/Setup.hs
@@ -1,7 +1,8 @@
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE RecordWildCards     #-}
+{-# LANGUAGE RankNTypes          #-}
+{-# LANGUAGE DeriveGeneric       #-}
+{-# LANGUAGE LambdaCase          #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Distribution.Client.Setup
@@ -24,6 +25,7 @@
     , replCommand, testCommand, benchmarkCommand
                         , configureExOptions, reconfigureCommand
     , installCommand, InstallFlags(..), installOptions, defaultInstallFlags
+    , filterHaddockArgs, filterHaddockFlags
     , defaultSolver, defaultMaxBackjumps
     , listCommand, ListFlags(..)
     , updateCommand, UpdateFlags(..), defaultUpdateFlags
@@ -48,9 +50,15 @@
     , execCommand, ExecFlags(..), defaultExecFlags
     , userConfigCommand, UserConfigFlags(..)
     , manpageCommand
+    , haddockCommand
+    , cleanCommand
+    , doctestCommand
+    , copyCommand
+    , registerCommand
 
-    , applyFlagDefaults
     , parsePackageArgs
+    , liftOptions
+    , yesNoOpt
     --TODO: stop exporting these:
     , showRepo
     , parseRepo
@@ -63,6 +71,7 @@
 import Distribution.Client.Types
          ( Username(..), Password(..), RemoteRepo(..)
          , AllowNewer(..), AllowOlder(..), RelaxDeps(..)
+         , WriteGhcEnvironmentFilesPolicy(..)
          )
 import Distribution.Client.BuildReports.Types
          ( ReportLevel(..) )
@@ -91,6 +100,8 @@
          ( ConfigFlags(..), BuildFlags(..), ReplFlags
          , TestFlags(..), BenchmarkFlags(..)
          , SDistFlags(..), HaddockFlags(..)
+         , CleanFlags(..), DoctestFlags(..)
+         , CopyFlags(..), RegisterFlags(..)
          , readPackageDbList, showPackageDbList
          , Flag(..), toFlag, flagToMaybe, flagToList, maybeToFlag
          , BooleanFlag(..), optionVerbosity
@@ -131,15 +142,6 @@
 import Network.URI
          ( parseAbsoluteURI, uriToString )
 
-applyFlagDefaults :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
-                  -> (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags)
-applyFlagDefaults (configFlags, configExFlags, installFlags, haddockFlags) =
-  ( commandDefaultFlags configureCommand <> configFlags
-  , defaultConfigExFlags <> configExFlags
-  , defaultInstallFlags <> installFlags
-  , Cabal.defaultHaddockFlags <> haddockFlags
-  )
-
 globalCommand :: [Command action] -> CommandUI GlobalFlags
 globalCommand commands = CommandUI {
     commandName         = "",
@@ -199,6 +201,44 @@
           , "new-test"
           , "new-bench"
           , "new-haddock"
+          , "new-exec"
+          , "new-update"
+          , "new-install"
+          , "new-clean"
+          , "new-sdist"
+          -- v1 commands, stateful style
+          , "v1-build"
+          , "v1-configure"
+          , "v1-repl"
+          , "v1-freeze"
+          , "v1-run"
+          , "v1-test"
+          , "v1-bench"
+          , "v1-haddock"
+          , "v1-exec"
+          , "v1-update"
+          , "v1-install"
+          , "v1-clean"
+          , "v1-sdist"
+          , "v1-doctest"
+          , "v1-copy"
+          , "v1-register"
+          , "v1-reconfigure"
+          , "v1-sandbox"
+          -- v2 commands, nix-style
+          , "v2-build"
+          , "v2-configure"
+          , "v2-repl"
+          , "v2-freeze"
+          , "v2-run"
+          , "v2-test"
+          , "v2-bench"
+          , "v2-haddock"
+          , "v2-exec"
+          , "v2-update"
+          , "v2-install"
+          , "v2-clean"
+          , "v2-sdist"
           ]
         maxlen    = maximum $ [length name | (name, _) <- cmdDescs]
         align str = str ++ replicate (maxlen - length str) ' '
@@ -266,6 +306,46 @@
         , addCmd "new-bench"
         , addCmd "new-freeze"
         , addCmd "new-haddock"
+        , addCmd "new-exec"
+        , addCmd "new-update"
+        , addCmd "new-install"
+        , addCmd "new-clean"
+        , addCmd "new-sdist"
+        , par
+        , startGroup "new-style projects (forwards-compatible aliases)"
+        , addCmd "v2-build"
+        , addCmd "v2-configure"
+        , addCmd "v2-repl"
+        , addCmd "v2-run"
+        , addCmd "v2-test"
+        , addCmd "v2-bench"
+        , addCmd "v2-freeze"
+        , addCmd "v2-haddock"
+        , addCmd "v2-exec"
+        , addCmd "v2-update"
+        , addCmd "v2-install"
+        , addCmd "v2-clean"
+        , addCmd "v2-sdist"
+        , par
+        , startGroup "legacy command aliases"
+        , addCmd "v1-build"
+        , addCmd "v1-configure"
+        , addCmd "v1-repl"
+        , addCmd "v1-run"
+        , addCmd "v1-test"
+        , addCmd "v1-bench"
+        , addCmd "v1-freeze"
+        , addCmd "v1-haddock"
+        , addCmd "v1-exec"
+        , addCmd "v1-update"
+        , addCmd "v1-install"
+        , addCmd "v1-clean"
+        , addCmd "v1-sdist"
+        , addCmd "v1-doctest"
+        , addCmd "v1-copy"
+        , addCmd "v1-register"
+        , addCmd "v1-reconfigure"
+        , addCmd "v1-sandbox"
         ] ++ if null otherCmds then [] else par
                                            :startGroup "other"
                                            :[addCmd n | n <- otherCmds])
@@ -359,7 +439,7 @@
          globalLocalRepos (\v flags -> flags { globalLocalRepos = v })
          (reqArg' "DIR" (\x -> toNubList [x]) fromNubList)
 
-      ,option [] ["logs-dir"]
+      ,option [] ["logs-dir", "logsdir"]
          "The location to put log files"
          globalLogsDir (\v flags -> flags { globalLogsDir = v })
          (reqArgFlag "DIR")
@@ -369,7 +449,7 @@
          globalWorldFile (\v flags -> flags { globalWorldFile = v })
          (reqArgFlag "FILE")
 
-      ,option [] ["store-dir"]
+      ,option [] ["store-dir", "storedir"]
          "The location of the nix-local-build store"
          globalStoreDir (\v flags -> flags { globalStoreDir = v })
          (reqArgFlag "DIR")
@@ -381,16 +461,24 @@
 
 configureCommand :: CommandUI ConfigFlags
 configureCommand = c
-  { commandDefaultFlags = mempty
-  , commandNotes = Just $ \pname -> (case commandNotes c of
-         Nothing -> ""
-         Just n  -> n pname ++ "\n")
-       ++ "Examples:\n"
-       ++ "  " ++ pname ++ " configure\n"
-       ++ "    Configure with defaults;\n"
-       ++ "  " ++ pname ++ " configure --enable-tests -fcustomflag\n"
-       ++ "    Configure building package including tests,\n"
-       ++ "    with some package-specific flag.\n"
+  { commandName         = "configure"
+  , commandDefaultFlags = mempty
+  , commandDescription  = Just $ \_ -> wrapText $
+         "Configure how the package is built by setting "
+      ++ "package (and other) flags.\n"
+      ++ "\n"
+      ++ "The configuration affects several other commands, "
+      ++ "including v1-build, v1-test, v1-bench, v1-run, v1-repl.\n"
+  , commandUsage        = \pname ->
+    "Usage: " ++ pname ++ " v1-configure [FLAGS]\n"
+  , commandNotes = Just $ \pname ->
+    (Cabal.programFlagsDescription defaultProgramDb ++ "\n")
+      ++ "Examples:\n"
+      ++ "  " ++ pname ++ " v1-configure\n"
+      ++ "    Configure with defaults;\n"
+      ++ "  " ++ pname ++ " v1-configure --enable-tests -fcustomflag\n"
+      ++ "    Configure building package including tests,\n"
+      ++ "    with some package-specific flag.\n"
   }
  where
   c = Cabal.configureCommand defaultProgramDb
@@ -525,12 +613,14 @@
 -- | cabal configure takes some extra flags beyond runghc Setup configure
 --
 data ConfigExFlags = ConfigExFlags {
-    configCabalVersion :: Flag Version,
-    configExConstraints:: [(UserConstraint, ConstraintSource)],
-    configPreferences  :: [Dependency],
-    configSolver       :: Flag PreSolver,
-    configAllowNewer   :: Maybe AllowNewer,
-    configAllowOlder   :: Maybe AllowOlder
+    configCabalVersion  :: Flag Version,
+    configExConstraints :: [(UserConstraint, ConstraintSource)],
+    configPreferences   :: [Dependency],
+    configSolver        :: Flag PreSolver,
+    configAllowNewer    :: Maybe AllowNewer,
+    configAllowOlder    :: Maybe AllowOlder,
+    configWriteGhcEnvironmentFilesPolicy
+      :: Flag WriteGhcEnvironmentFilesPolicy
   }
   deriving (Eq, Generic)
 
@@ -595,9 +685,34 @@
      (readP_to_E ("Cannot parse the list of packages: " ++) relaxDepsParser)
      (Just RelaxDepsAll) relaxDepsPrinter)
 
+  , option [] ["write-ghc-environment-files"]
+    ("Whether to create a .ghc.environment file after a successful build"
+      ++ " (v2-build only)")
+    configWriteGhcEnvironmentFilesPolicy
+    (\v flags -> flags { configWriteGhcEnvironmentFilesPolicy = v})
+    (reqArg "always|never|ghc8.4.4+"
+     writeGhcEnvironmentFilesPolicyParser
+     writeGhcEnvironmentFilesPolicyPrinter)
   ]
 
 
+writeGhcEnvironmentFilesPolicyParser :: ReadE (Flag WriteGhcEnvironmentFilesPolicy)
+writeGhcEnvironmentFilesPolicyParser = ReadE $ \case
+  "always"    -> Right $ Flag AlwaysWriteGhcEnvironmentFiles
+  "never"     -> Right $ Flag NeverWriteGhcEnvironmentFiles
+  "ghc8.4.4+" -> Right $ Flag WriteGhcEnvironmentFilesOnlyForGhc844AndNewer
+  policy      -> Left  $ "Cannot parse the GHC environment file write policy '"
+                 <> policy <> "'"
+
+writeGhcEnvironmentFilesPolicyPrinter
+  :: Flag WriteGhcEnvironmentFilesPolicy -> [String]
+writeGhcEnvironmentFilesPolicyPrinter = \case
+  (Flag AlwaysWriteGhcEnvironmentFiles)                -> ["always"]
+  (Flag NeverWriteGhcEnvironmentFiles)                 -> ["never"]
+  (Flag WriteGhcEnvironmentFilesOnlyForGhc844AndNewer) -> ["ghc8.4.4+"]
+  NoFlag                                               -> []
+
+
 relaxDepsParser :: Parse.ReadP r (Maybe RelaxDeps)
 relaxDepsParser =
   (Just . RelaxDepsSome) `fmap` Parse.sepBy1 parse (Parse.char ',')
@@ -623,17 +738,17 @@
     , commandDescription  = Just $ \pname -> wrapText $
          "Run `configure` with the most recently used flags, or append FLAGS "
          ++ "to the most recently used configuration. "
-         ++ "Accepts the same flags as `" ++ pname ++ " configure'. "
+         ++ "Accepts the same flags as `" ++ pname ++ " v1-configure'. "
          ++ "If the package has never been configured, the default flags are "
          ++ "used."
     , commandNotes        = Just $ \pname ->
         "Examples:\n"
-        ++ "  " ++ pname ++ " reconfigure\n"
+        ++ "  " ++ pname ++ " v1-reconfigure\n"
         ++ "    Configure with the most recently used flags.\n"
-        ++ "  " ++ pname ++ " reconfigure -w PATH\n"
+        ++ "  " ++ pname ++ " v1-reconfigure -w PATH\n"
         ++ "    Reconfigure with the most recently used flags,\n"
         ++ "    but use the compiler at PATH.\n\n"
-    , commandUsage        = usageAlternatives "reconfigure" [ "[FLAGS]" ]
+    , commandUsage        = usageAlternatives "v1-reconfigure" [ "[FLAGS]" ]
     , commandDefaultFlags = mempty
     }
 
@@ -660,12 +775,26 @@
 
 buildCommand :: CommandUI (BuildFlags, BuildExFlags)
 buildCommand = parent {
+    commandName = "build",
+    commandDescription  = Just $ \_ -> wrapText $
+      "Components encompass executables, tests, and benchmarks.\n"
+        ++ "\n"
+        ++ "Affected by configuration options, see `v1-configure`.\n",
     commandDefaultFlags = (commandDefaultFlags parent, mempty),
+    commandUsage        = usageAlternatives "v1-build" $
+      [ "[FLAGS]", "COMPONENTS [FLAGS]" ],
     commandOptions      =
       \showOrParseArgs -> liftOptions fst setFst
                           (commandOptions parent showOrParseArgs)
                           ++
                           liftOptions snd setSnd (buildExOptions showOrParseArgs)
+    , commandNotes        = Just $ \pname ->
+      "Examples:\n"
+        ++ "  " ++ pname ++ " v1-build           "
+        ++ "    All the components in the package\n"
+        ++ "  " ++ pname ++ " v1-build foo       "
+        ++ "    A component (i.e. lib, exe, test suite)\n\n"
+        ++ Cabal.programFlagsDescription defaultProgramDb
   }
   where
     setFst a (_,b) = (a,b)
@@ -686,12 +815,40 @@
 
 replCommand :: CommandUI (ReplFlags, BuildExFlags)
 replCommand = parent {
+    commandName = "repl",
+    commandDescription  = Just $ \pname -> wrapText $
+         "If the current directory contains no package, ignores COMPONENT "
+      ++ "parameters and opens an interactive interpreter session; if a "
+      ++ "sandbox is present, its package database will be used.\n"
+      ++ "\n"
+      ++ "Otherwise, (re)configures with the given or default flags, and "
+      ++ "loads the interpreter with the relevant modules. For executables, "
+      ++ "tests and benchmarks, loads the main module (and its "
+      ++ "dependencies); for libraries all exposed/other modules.\n"
+      ++ "\n"
+      ++ "The default component is the library itself, or the executable "
+      ++ "if that is the only component.\n"
+      ++ "\n"
+      ++ "Support for loading specific modules is planned but not "
+      ++ "implemented yet. For certain scenarios, `" ++ pname
+      ++ " v1-exec -- ghci :l Foo` may be used instead. Note that `v1-exec` will "
+      ++ "not (re)configure and you will have to specify the location of "
+      ++ "other modules, if required.\n",
+    commandUsage =  \pname -> "Usage: " ++ pname ++ " v1-repl [COMPONENT] [FLAGS]\n",
     commandDefaultFlags = (commandDefaultFlags parent, mempty),
     commandOptions      =
       \showOrParseArgs -> liftOptions fst setFst
                           (commandOptions parent showOrParseArgs)
                           ++
-                          liftOptions snd setSnd (buildExOptions showOrParseArgs)
+                          liftOptions snd setSnd (buildExOptions showOrParseArgs),
+    commandNotes        = Just $ \pname ->
+      "Examples:\n"
+    ++ "  " ++ pname ++ " v1-repl           "
+    ++ "    The first component in the package\n"
+    ++ "  " ++ pname ++ " v1-repl foo       "
+    ++ "    A named component (i.e. lib, exe, test suite)\n"
+    ++ "  " ++ pname ++ " v1-repl --ghc-options=\"-lstdc++\""
+    ++ "  Specifying flags for interpreter\n"
   }
   where
     setFst a (_,b) = (a,b)
@@ -705,6 +862,19 @@
 
 testCommand :: CommandUI (TestFlags, BuildFlags, BuildExFlags)
 testCommand = parent {
+  commandName = "test",
+  commandDescription  = Just $ \pname -> wrapText $
+         "If necessary (re)configures with `--enable-tests` flag and builds"
+      ++ " the test suite.\n"
+      ++ "\n"
+      ++ "Remember that the tests' dependencies must be installed if there"
+      ++ " are additional ones; e.g. with `" ++ pname
+      ++ " v1-install --only-dependencies --enable-tests`.\n"
+      ++ "\n"
+      ++ "By defining UserHooks in a custom Setup.hs, the package can"
+      ++ " define actions to be executed before and after running tests.\n",
+  commandUsage = usageAlternatives "v1-test"
+      [ "[FLAGS]", "TESTCOMPONENTS [FLAGS]" ],
   commandDefaultFlags = (commandDefaultFlags parent,
                          Cabal.defaultBuildFlags, mempty),
   commandOptions      =
@@ -730,6 +900,20 @@
 
 benchmarkCommand :: CommandUI (BenchmarkFlags, BuildFlags, BuildExFlags)
 benchmarkCommand = parent {
+  commandName = "bench",
+  commandUsage = usageAlternatives "v1-bench"
+      [ "[FLAGS]", "BENCHCOMPONENTS [FLAGS]" ],
+  commandDescription  = Just $ \pname -> wrapText $
+         "If necessary (re)configures with `--enable-benchmarks` flag and"
+      ++ " builds the benchmarks.\n"
+      ++ "\n"
+      ++ "Remember that the benchmarks' dependencies must be installed if"
+      ++ " there are additional ones; e.g. with `" ++ pname
+      ++ " v1-install --only-dependencies --enable-benchmarks`.\n"
+      ++ "\n"
+      ++ "By defining UserHooks in a custom Setup.hs, the package can"
+      ++ " define actions to be executed before and after running"
+      ++ " benchmarks.\n",
   commandDefaultFlags = (commandDefaultFlags parent,
                          Cabal.defaultBuildFlags, mempty),
   commandOptions      =
@@ -765,6 +949,8 @@
       fetchShadowPkgs       :: Flag ShadowPkgs,
       fetchStrongFlags      :: Flag StrongFlags,
       fetchAllowBootLibInstalls :: Flag AllowBootLibInstalls,
+      fetchTests            :: Flag Bool,
+      fetchBenchmarks       :: Flag Bool,
       fetchVerbosity :: Flag Verbosity
     }
 
@@ -781,6 +967,8 @@
     fetchShadowPkgs       = Flag (ShadowPkgs False),
     fetchStrongFlags      = Flag (StrongFlags False),
     fetchAllowBootLibInstalls = Flag (AllowBootLibInstalls False),
+    fetchTests            = toFlag False,
+    fetchBenchmarks       = toFlag False,
     fetchVerbosity = toFlag normal
    }
 
@@ -818,6 +1006,16 @@
            fetchDryRun (\v flags -> flags { fetchDryRun = v })
            trueArg
 
+      , option "" ["tests"]
+         "dependency checking and compilation for test suites listed in the package description file."
+         fetchTests (\v flags -> flags { fetchTests = v })
+         (boolOpt [] [])
+
+      , option "" ["benchmarks"]
+         "dependency checking and compilation for benchmarks listed in the package description file."
+         fetchBenchmarks (\v flags -> flags { fetchBenchmarks = v })
+         (boolOpt [] [])
+
        ] ++
 
        optionSolver      fetchSolver           (\v flags -> flags { fetchSolver           = v }) :
@@ -963,6 +1161,7 @@
   outdatedVerbosity     :: Flag Verbosity,
   outdatedFreezeFile    :: Flag Bool,
   outdatedNewFreezeFile :: Flag Bool,
+  outdatedProjectFile   :: Flag FilePath,
   outdatedSimpleOutput  :: Flag Bool,
   outdatedExitCode      :: Flag Bool,
   outdatedQuiet         :: Flag Bool,
@@ -975,6 +1174,7 @@
   outdatedVerbosity     = toFlag normal,
   outdatedFreezeFile    = mempty,
   outdatedNewFreezeFile = mempty,
+  outdatedProjectFile   = mempty,
   outdatedSimpleOutput  = mempty,
   outdatedExitCode      = mempty,
   outdatedQuiet         = mempty,
@@ -996,16 +1196,21 @@
     optionVerbosity outdatedVerbosity
       (\v flags -> flags { outdatedVerbosity = v })
 
-    ,option [] ["freeze-file"]
+    ,option [] ["freeze-file", "v1-freeze-file"]
      "Act on the freeze file"
      outdatedFreezeFile (\v flags -> flags { outdatedFreezeFile = v })
      trueArg
 
-    ,option [] ["new-freeze-file"]
-     "Act on the new-style freeze file"
+    ,option [] ["new-freeze-file", "v2-freeze-file"]
+     "Act on the new-style freeze file (default: cabal.project.freeze)"
      outdatedNewFreezeFile (\v flags -> flags { outdatedNewFreezeFile = v })
      trueArg
 
+    ,option [] ["project-file"]
+     "Act on the new-style freeze file named PROJECTFILE.freeze rather than the default cabal.project.freeze"
+     outdatedProjectFile (\v flags -> flags { outdatedProjectFile = v })
+     (reqArgFlag "PROJECTFILE")
+
     ,option [] ["simple-output"]
      "Only print names of outdated dependencies, one per line"
      outdatedSimpleOutput (\v flags -> flags { outdatedSimpleOutput = v })
@@ -1076,7 +1281,7 @@
       relevantConfigValuesText ["remote-repo"
                                ,"remote-repo-cache"
                                ,"local-repo"],
-    commandUsage        = usageFlags "update",
+    commandUsage        = usageFlags "v1-update",
     commandDefaultFlags = defaultUpdateFlags,
     commandOptions      = \_ -> [
         optionVerbosity updateVerbosity (\v flags -> flags { updateVerbosity = v }),
@@ -1108,16 +1313,11 @@
     commandOptions      = commandOptions installCommand
   }
 
-{-
-cleanCommand  :: CommandUI ()
-cleanCommand = makeCommand name shortDesc longDesc emptyFlags options
-  where
-    name       = "clean"
-    shortDesc  = "Removes downloaded files"
-    longDesc   = Nothing
-    emptyFlags = ()
-    options _  = []
--}
+cleanCommand :: CommandUI CleanFlags
+cleanCommand = Cabal.cleanCommand
+  { commandUsage = \pname ->
+    "Usage: " ++ pname ++ " v1-clean [FLAGS]\n"
+  }
 
 checkCommand  :: CommandUI (Flag Verbosity)
 checkCommand = CommandUI {
@@ -1130,9 +1330,9 @@
       ++ "If no errors and warnings are reported, Hackage will accept this "
       ++ "package.\n",
     commandNotes        = Nothing,
-    commandUsage        = \pname -> "Usage: " ++ pname ++ " check\n",
+    commandUsage        = usageFlags "check",
     commandDefaultFlags = toFlag normal,
-    commandOptions      = \_ -> []
+    commandOptions      = \_ -> [optionVerbosity id const]
   }
 
 formatCommand  :: CommandUI (Flag Verbosity)
@@ -1178,15 +1378,15 @@
       ++ "specified, but the package contains just one executable, that one "
       ++ "is built and executed.\n"
       ++ "\n"
-      ++ "Use `" ++ pname ++ " test --show-details=streaming` to run a "
+      ++ "Use `" ++ pname ++ " v1-test --show-details=streaming` to run a "
       ++ "test-suite and get its full output.\n",
     commandNotes        = Just $ \pname ->
           "Examples:\n"
-       ++ "  " ++ pname ++ " run\n"
+       ++ "  " ++ pname ++ " v1-run\n"
        ++ "    Run the only executable in the current package;\n"
-       ++ "  " ++ pname ++ " run foo -- --fooflag\n"
+       ++ "  " ++ pname ++ " v1-run foo -- --fooflag\n"
        ++ "    Works similar to `./foo --fooflag`.\n",
-    commandUsage        = usageAlternatives "run"
+    commandUsage        = usageAlternatives "v1-run"
         ["[FLAGS] [EXECUTABLE] [-- EXECUTABLE_FLAGS]"],
     commandDefaultFlags = mempty,
     commandOptions      =
@@ -1472,6 +1672,7 @@
 data InstallFlags = InstallFlags {
     installDocumentation    :: Flag Bool,
     installHaddockIndex     :: Flag PathTemplate,
+    installDest             :: Flag Cabal.CopyDest,
     installDryRun           :: Flag Bool,
     installMaxBackjumps     :: Flag Int,
     installReorderGoals     :: Flag ReorderGoals,
@@ -1516,6 +1717,7 @@
 defaultInstallFlags = InstallFlags {
     installDocumentation   = Flag False,
     installHaddockIndex    = Flag docIndexFile,
+    installDest            = Flag Cabal.NoCopyDest,
     installDryRun          = Flag False,
     installMaxBackjumps    = Flag defaultMaxBackjumps,
     installReorderGoals    = Flag (ReorderGoals False),
@@ -1562,7 +1764,7 @@
 installCommand = CommandUI {
   commandName         = "install",
   commandSynopsis     = "Install packages.",
-  commandUsage        = usageAlternatives "install" [ "[FLAGS]"
+  commandUsage        = usageAlternatives "v1-install" [ "[FLAGS]"
                                                     , "[FLAGS] PACKAGES"
                                                     ],
   commandDescription  = Just $ \_ -> wrapText $
@@ -1575,12 +1777,12 @@
      ++ " dependencies) (there must be exactly one .cabal file in the current"
      ++ " directory).\n"
      ++ "\n"
-     ++ "When using a sandbox, the flags for `install` only affect the"
+     ++ "When using a sandbox, the flags for `v1-install` only affect the"
      ++ " current command and have no effect on future commands. (To achieve"
-     ++ " that, `configure` must be used.)\n"
-     ++ " In contrast, without a sandbox, the flags to `install` are saved and"
-     ++ " affect future commands such as `build` and `repl`. See the help for"
-     ++ " `configure` for a list of commands being affected.\n"
+     ++ " that, `v1-configure` must be used.)\n"
+     ++ " In contrast, without a sandbox, the flags to `v1-install` are saved and"
+     ++ " affect future commands such as `v1-build` and `v1-repl`. See the help for"
+     ++ " `v1-configure` for a list of commands being affected.\n"
      ++ "\n"
      ++ "Installed executables will by default (and without a sandbox)"
      ++ " be put into `~/.cabal/bin/`."
@@ -1599,27 +1801,35 @@
              Nothing   -> ""
         )
      ++ "Examples:\n"
-     ++ "  " ++ pname ++ " install                 "
+     ++ "  " ++ pname ++ " v1-install                 "
      ++ "    Package in the current directory\n"
-     ++ "  " ++ pname ++ " install foo             "
+     ++ "  " ++ pname ++ " v1-install foo             "
      ++ "    Package from the hackage server\n"
-     ++ "  " ++ pname ++ " install foo-1.0         "
+     ++ "  " ++ pname ++ " v1-install foo-1.0         "
      ++ "    Specific version of a package\n"
-     ++ "  " ++ pname ++ " install 'foo < 2'       "
+     ++ "  " ++ pname ++ " v1-install 'foo < 2'       "
      ++ "    Constrained package version\n"
-     ++ "  " ++ pname ++ " install haddock --bindir=$HOME/hask-bin/ --datadir=$HOME/hask-data/\n"
+     ++ "  " ++ pname ++ " v1-install haddock --bindir=$HOME/hask-bin/ --datadir=$HOME/hask-data/\n"
      ++ "  " ++ (map (const ' ') pname)
                       ++ "                         "
      ++ "    Change installation destination\n",
   commandDefaultFlags = (mempty, mempty, mempty, mempty),
   commandOptions      = \showOrParseArgs ->
        liftOptions get1 set1
+       -- Note: [Hidden Flags]
+       -- hide "constraint", "dependency", and
+       -- "exact-configuration" from the configure options.
        (filter ((`notElem` ["constraint", "dependency"
                            , "exact-configuration"])
                 . optionName) $
                               configureOptions   showOrParseArgs)
     ++ liftOptions get2 set2 (configureExOptions showOrParseArgs ConstraintSourceCommandlineFlag)
-    ++ liftOptions get3 set3 (installOptions     showOrParseArgs)
+    ++ liftOptions get3 set3
+       -- hide "target-package-db" flag from the
+       -- install options.
+       (filter ((`notElem` ["target-package-db"])
+                . optionName) $
+                              installOptions     showOrParseArgs)
     ++ liftOptions get4 set4 (haddockOptions     showOrParseArgs)
   }
   where
@@ -1628,6 +1838,36 @@
     get3 (_,_,c,_) = c; set3 c (a,b,_,d) = (a,b,c,d)
     get4 (_,_,_,d) = d; set4 d (a,b,c,_) = (a,b,c,d)
 
+haddockCommand :: CommandUI HaddockFlags
+haddockCommand = Cabal.haddockCommand
+  { commandUsage = usageAlternatives "v1-haddock" $
+      [ "[FLAGS]", "COMPONENTS [FLAGS]" ]
+  }
+
+filterHaddockArgs :: [String] -> Version -> [String]
+filterHaddockArgs args cabalLibVersion
+  | cabalLibVersion >= mkVersion [2,3,0] = args_latest
+  | cabalLibVersion < mkVersion [2,3,0] = args_2_3_0
+  | otherwise = args_latest
+  where
+    args_latest = args
+
+    -- Cabal < 2.3 doesn't know about per-component haddock
+    args_2_3_0 = []
+
+filterHaddockFlags :: HaddockFlags -> Version -> HaddockFlags
+filterHaddockFlags flags cabalLibVersion
+  | cabalLibVersion >= mkVersion [2,3,0] = flags_latest
+  | cabalLibVersion < mkVersion [2,3,0] = flags_2_3_0
+  | otherwise = flags_latest
+  where
+    flags_latest = flags
+
+    flags_2_3_0 = flags_latest {
+      -- Cabal < 2.3 doesn't know about per-component haddock
+      haddockArgs = []
+      }
+
 haddockOptions :: ShowOrParseArgs -> [OptionField HaddockFlags]
 haddockOptions showOrParseArgs
   = [ opt { optionName = "haddock-" ++ name,
@@ -1637,7 +1877,7 @@
     , let name = optionName opt
     , name `elem` ["hoogle", "html", "html-location"
                   ,"executables", "tests", "benchmarks", "all", "internal", "css"
-                  ,"hyperlink-source", "hscolour-css"
+                  ,"hyperlink-source", "quickjump", "hscolour-css"
                   ,"contents-location", "for-hackage"]
     ]
   where
@@ -1664,6 +1904,12 @@
           "Do not install anything, only print what would be installed."
           installDryRun (\v flags -> flags { installDryRun = v })
           trueArg
+
+      , option "" ["target-package-db"]
+         "package database to install into. Required when using ${pkgroot} prefix."
+         installDest (\v flags -> flags { installDest = v })
+         (reqArg "DATABASE" (succeedReadE (Flag . Cabal.CopyToDb))
+                            (\f -> case f of Flag (Cabal.CopyToDb p) -> [p]; _ -> []))
       ] ++
 
       optionSolverFlags showOrParseArgs
@@ -1936,7 +2182,7 @@
         IT.overwrite (\v flags -> flags { IT.overwrite = v })
         trueArg
 
-      , option [] ["package-dir"]
+      , option [] ["package-dir", "packagedir"]
         "Root directory of the package (default = current directory)."
         IT.packageDir (\v flags -> flags { IT.packageDir = v })
         (reqArgFlag "DIRECTORY")
@@ -1956,9 +2202,9 @@
                           (flagToList . fmap display))
 
       , option [] ["cabal-version"]
-        "Required version of the Cabal library."
+        "Version of the Cabal specification."
         IT.cabalVersion (\v flags -> flags { IT.cabalVersion = v })
-        (reqArg "VERSION_RANGE" (readP_to_E ("Cannot parse Cabal version range: "++)
+        (reqArg "VERSION_RANGE" (readP_to_E ("Cannot parse Cabal specification version: "++)
                                             (toFlag `fmap` parse))
                                 (flagToList . fmap display))
 
@@ -2055,7 +2301,7 @@
                                       ((Just . (:[])) `fmap` parse))
                           (maybe [] (fmap display)))
 
-      , option [] ["source-dir"]
+      , option [] ["source-dir", "sourcedir"]
         "Directory containing package source."
         IT.sourceDirs (\v flags -> flags { IT.sourceDirs = v })
         (reqArg' "DIR" (Just . (:[]))
@@ -2067,6 +2313,14 @@
         (reqArg' "TOOL" (Just . (:[]))
                         (fromMaybe []))
 
+        -- NB: this is a bit of a transitional hack and will likely be
+        -- removed again if `cabal init` is migrated to the v2-* command
+        -- framework
+      , option "w" ["with-compiler"]
+        "give the path to a particular compiler"
+        IT.initHcPath (\v flags -> flags { IT.initHcPath = v })
+        (reqArgFlag "PATH")
+
       , optionVerbosity IT.initVerbosity (\v flags -> flags { IT.initVerbosity = v })
       ]
   }
@@ -2092,6 +2346,8 @@
 
 sdistCommand :: CommandUI (SDistFlags, SDistExFlags)
 sdistCommand = Cabal.sdistCommand {
+    commandUsage        = \pname ->
+        "Usage: " ++ pname ++ " v1-sdist [FLAGS]\n",
     commandDefaultFlags = (commandDefaultFlags Cabal.sdistCommand, defaultSDistExFlags),
     commandOptions      = \showOrParseArgs ->
          liftOptions fst setFst (commandOptions Cabal.sdistCommand showOrParseArgs)
@@ -2119,6 +2375,30 @@
 instance Semigroup SDistExFlags where
   (<>) = gmappend
 
+--
+
+doctestCommand :: CommandUI DoctestFlags
+doctestCommand = Cabal.doctestCommand
+  { commandUsage = \pname ->  "Usage: " ++ pname ++ " v1-doctest [FLAGS]\n" }
+
+copyCommand :: CommandUI CopyFlags
+copyCommand = Cabal.copyCommand
+ { commandNotes = Just $ \pname ->
+    "Examples:\n"
+     ++ "  " ++ pname ++ " v1-copy           "
+     ++ "    All the components in the package\n"
+     ++ "  " ++ pname ++ " v1-copy foo       "
+     ++ "    A component (i.e. lib, exe, test suite)"
+  , commandUsage = usageAlternatives "v1-copy" $
+    [ "[FLAGS]"
+    , "COMPONENTS [FLAGS]"
+    ]
+ }
+
+registerCommand :: CommandUI RegisterFlags
+registerCommand = Cabal.registerCommand
+ { commandUsage = \pname ->  "Usage: " ++ pname ++ " v1-register [FLAGS]\n" }
+
 -- ------------------------------------------------------------
 -- * Win32SelfUpgrade flags
 -- ------------------------------------------------------------
@@ -2224,11 +2504,11 @@
       ++ " packages are installed in the same database (i.e. the user's"
       ++ " database in the home directory)."
     , paragraph $ "A sandbox in the current directory (created by"
-      ++ " `sandbox init`) will be used instead of the user's database for"
-      ++ " commands such as `install` and `build`. Note that (a directly"
+      ++ " `v1-sandbox init`) will be used instead of the user's database for"
+      ++ " commands such as `v1-install` and `v1-build`. Note that (a directly"
       ++ " invoked) GHC will not automatically be aware of sandboxes;"
       ++ " only if called via appropriate " ++ pname
-      ++ " commands, e.g. `repl`, `build`, `exec`."
+      ++ " commands, e.g. `v1-repl`, `v1-build`, `v1-exec`."
     , paragraph $ "Currently, " ++ pname ++ " will not search for a sandbox"
       ++ " in folders above the current one, so cabal will not see the sandbox"
       ++ " if you are in a subfolder of a sandbox."
@@ -2254,16 +2534,16 @@
     , indentParagraph $ "Remove an add-source dependency; however, this will"
       ++ " not delete the package(s) that have been installed in the sandbox"
       ++ " from this dependency. You can either unregister the package(s) via"
-      ++ " `" ++ pname ++ " sandbox hc-pkg unregister` or re-create the"
-      ++ " sandbox (`sandbox delete; sandbox init`)."
+      ++ " `" ++ pname ++ " v1-sandbox hc-pkg unregister` or re-create the"
+      ++ " sandbox (`v1-sandbox delete; v1-sandbox init`)."
     , headLine "list-sources:"
     , indentParagraph $ "List the directories of local packages made"
-      ++ " available via `" ++ pname ++ " add-source`."
+      ++ " available via `" ++ pname ++ " v1-sandbox add-source`."
     , headLine "hc-pkg:"
     , indentParagraph $ "Similar to `ghc-pkg`, but for the sandbox package"
       ++ " database. Can be used to list specific/all packages that are"
       ++ " installed in the sandbox. For subcommands, see the help for"
-      ++ " ghc-pkg. Affected by the compiler version specified by `configure`."
+      ++ " ghc-pkg. Affected by the compiler version specified by `v1-configure`."
     ],
   commandNotes        = Just $ \pname ->
        relevantConfigValuesText ["require-sandbox"
@@ -2271,18 +2551,18 @@
     ++ "\n"
     ++ "Examples:\n"
     ++ "  Set up a sandbox with one local dependency, located at ../foo:\n"
-    ++ "    " ++ pname ++ " sandbox init\n"
-    ++ "    " ++ pname ++ " sandbox add-source ../foo\n"
-    ++ "    " ++ pname ++ " install --only-dependencies\n"
+    ++ "    " ++ pname ++ " v1-sandbox init\n"
+    ++ "    " ++ pname ++ " v1-sandbox add-source ../foo\n"
+    ++ "    " ++ pname ++ " v1-install --only-dependencies\n"
     ++ "  Reset the sandbox:\n"
-    ++ "    " ++ pname ++ " sandbox delete\n"
-    ++ "    " ++ pname ++ " sandbox init\n"
-    ++ "    " ++ pname ++ " install --only-dependencies\n"
+    ++ "    " ++ pname ++ " v1-sandbox delete\n"
+    ++ "    " ++ pname ++ " v1-sandbox init\n"
+    ++ "    " ++ pname ++ " v1-install --only-dependencies\n"
     ++ "  List the packages in the sandbox:\n"
-    ++ "    " ++ pname ++ " sandbox hc-pkg list\n"
+    ++ "    " ++ pname ++ " v1-sandbox hc-pkg list\n"
     ++ "  Unregister the `broken` package from the sandbox:\n"
-    ++ "    " ++ pname ++ " sandbox hc-pkg -- --force unregister broken\n",
-  commandUsage        = usageAlternatives "sandbox"
+    ++ "    " ++ pname ++ " v1-sandbox hc-pkg -- --force unregister broken\n",
+  commandUsage        = usageAlternatives "v1-sandbox"
     [ "init          [FLAGS]"
     , "delete        [FLAGS]"
     , "add-source    [FLAGS] PATHS"
@@ -2338,7 +2618,7 @@
        -- TODO: this is too GHC-focused for my liking..
        "A directly invoked GHC will not automatically be aware of any"
     ++ " sandboxes: the GHC_PACKAGE_PATH environment variable controls what"
-    ++ " GHC uses. `" ++ pname ++ " exec` can be used to modify this variable:"
+    ++ " GHC uses. `" ++ pname ++ " v1-exec` can be used to modify this variable:"
     ++ " COMMAND will be executed in a modified environment and thereby uses"
     ++ " the sandbox package database.\n"
     ++ "\n"
@@ -2346,26 +2626,26 @@
     ++ "\n"
     ++ "Note that other " ++ pname ++ " commands change the environment"
     ++ " variable appropriately already, so there is no need to wrap those"
-    ++ " in `" ++ pname ++ " exec`. But with `" ++ pname ++ " exec`, the user"
+    ++ " in `" ++ pname ++ " v1-exec`. But with `" ++ pname ++ " v1-exec`, the user"
     ++ " has more control and can, for example, execute custom scripts which"
     ++ " indirectly execute GHC.\n"
     ++ "\n"
-    ++ "Note that `" ++ pname ++ " repl` is different from `" ++ pname
-    ++ " exec -- ghci` as the latter will not forward any additional flags"
+    ++ "Note that `" ++ pname ++ " v1-repl` is different from `" ++ pname
+    ++ " v1-exec -- ghci` as the latter will not forward any additional flags"
     ++ " being defined in the local package to ghci.\n"
     ++ "\n"
     ++ "See `" ++ pname ++ " sandbox`.\n",
   commandNotes        = Just $ \pname ->
        "Examples:\n"
-    ++ "  " ++ pname ++ " exec -- ghci -Wall\n"
+    ++ "  " ++ pname ++ " v1-exec -- ghci -Wall\n"
     ++ "    Start a repl session with sandbox packages and all warnings;\n"
-    ++ "  " ++ pname ++ " exec gitit -- -f gitit.cnf\n"
+    ++ "  " ++ pname ++ " v1-exec gitit -- -f gitit.cnf\n"
     ++ "    Give gitit access to the sandbox packages, and pass it a flag;\n"
-    ++ "  " ++ pname ++ " exec runghc Foo.hs\n"
+    ++ "  " ++ pname ++ " v1-exec runghc Foo.hs\n"
     ++ "    Execute runghc on Foo.hs with runghc configured to use the\n"
     ++ "    sandbox package database (if a sandbox is being used).\n",
   commandUsage        = \pname ->
-       "Usage: " ++ pname ++ " exec [FLAGS] [--] COMMAND [--] [ARGS]\n",
+       "Usage: " ++ pname ++ " v1-exec [FLAGS] [--] COMMAND [--] [ARGS]\n",
 
   commandDefaultFlags = defaultExecFlags,
   commandOptions      = \showOrParseArgs ->
@@ -2389,14 +2669,16 @@
 -- ------------------------------------------------------------
 
 data UserConfigFlags = UserConfigFlags {
-  userConfigVerbosity :: Flag Verbosity,
-  userConfigForce     :: Flag Bool
-} deriving Generic
+  userConfigVerbosity   :: Flag Verbosity,
+  userConfigForce       :: Flag Bool,
+  userConfigAppendLines :: Flag [String]
+  } deriving Generic
 
 instance Monoid UserConfigFlags where
   mempty = UserConfigFlags {
-    userConfigVerbosity = toFlag normal,
-    userConfigForce     = toFlag False
+    userConfigVerbosity   = toFlag normal,
+    userConfigForce       = toFlag False,
+    userConfigAppendLines = toFlag []
     }
   mappend = (<>)
 
@@ -2432,6 +2714,12 @@
      "Overwrite the config file if it already exists."
      userConfigForce (\v flags -> flags { userConfigForce = v })
      trueArg
+ , option ['a'] ["augment"]
+     "Additional setting to augment the config file (replacing a previous setting if it existed)."
+     userConfigAppendLines (\v flags -> flags
+                               {userConfigAppendLines =
+                                   Flag $ concat (flagToList (userConfigAppendLines flags) ++ flagToList v)})
+     (reqArg' "CONFIGLINE" (Flag . (:[])) (fromMaybe [] . flagToMaybe))
    ]
   }
 
diff --git a/cabal/cabal-install/Distribution/Client/SetupWrapper.hs b/cabal/cabal-install/Distribution/Client/SetupWrapper.hs
--- a/cabal/cabal-install/Distribution/Client/SetupWrapper.hs
+++ b/cabal/cabal-install/Distribution/Client/SetupWrapper.hs
@@ -33,13 +33,14 @@
          , withinRange )
 import qualified Distribution.Backpack as Backpack
 import Distribution.Package
-         ( newSimpleUnitId, unsafeMkDefUnitId, ComponentId, PackageId, mkPackageName
+         ( newSimpleUnitId, unsafeMkDefUnitId, ComponentId
+         , PackageId, mkPackageName
          , PackageIdentifier(..), packageVersion, packageName )
 import Distribution.Types.Dependency
 import Distribution.PackageDescription
          ( GenericPackageDescription(packageDescription)
-         , PackageDescription(..), specVersion
-         , BuildType(..), knownBuildTypes, defaultRenaming )
+         , PackageDescription(..), specVersion, buildType
+         , BuildType(..), defaultRenaming )
 import Distribution.PackageDescription.Parsec
          ( readGenericPackageDescription )
 import Distribution.Simple.Configure
@@ -57,7 +58,8 @@
          , getProgramSearchPath, getDbProgramOutput, runDbProgram, ghcProgram
          , ghcjsProgram )
 import Distribution.Simple.Program.Find
-         ( programSearchPathAsPATHVar, ProgramSearchPathEntry(ProgramSearchPathDir) )
+         ( programSearchPathAsPATHVar
+         , ProgramSearchPathEntry(ProgramSearchPathDir) )
 import Distribution.Simple.Program.Run
          ( getEffectiveEnvironment )
 import qualified Distribution.Simple.Program.Strip as Strip
@@ -73,7 +75,7 @@
 import qualified Distribution.InstalledPackageInfo as IPI
 import Distribution.Client.Types
 import Distribution.Client.Config
-         ( defaultCabalDir )
+         ( getCabalDir )
 import Distribution.Client.IndexUtils
          ( getInstalledPackages )
 import Distribution.Client.JobControl
@@ -81,12 +83,13 @@
 import Distribution.Simple.Setup
          ( Flag(..) )
 import Distribution.Simple.Utils
-         ( die', debug, info, infoNoWrap, cabalVersion, tryFindPackageDesc, comparing
+         ( die', debug, info, infoNoWrap
+         , cabalVersion, tryFindPackageDesc, comparing
          , createDirectoryIfMissingVerbose, installExecutableFile
-         , copyFileVerbose, rewriteFile )
+         , copyFileVerbose, rewriteFileEx )
 import Distribution.Client.Utils
          ( inDir, tryCanonicalizePath, withExtraPathEnv
-         , existsAndIsMoreRecentThan, moreRecentFile, withEnv
+         , existsAndIsMoreRecentThan, moreRecentFile, withEnv, withEnvOverrides
 #ifdef mingw32_HOST_OS
          , canonicalizePathNoThrow
 #endif
@@ -185,6 +188,11 @@
     useWorkingDir            :: Maybe FilePath,
     -- | Extra things to add to PATH when invoking the setup script.
     useExtraPathEnv          :: [FilePath],
+    -- | Extra environment variables paired with overrides, where
+    --
+    -- * @'Just' v@ means \"set the environment variable's value to @v@\".
+    -- * 'Nothing' means \"unset the environment variable\".
+    useExtraEnvOverrides     :: [(String, Maybe FilePath)],
     forceExternalSetupMethod :: Bool,
 
     -- | List of dependencies to use when building Setup.hs.
@@ -259,6 +267,7 @@
     useLoggingHandle         = Nothing,
     useWorkingDir            = Nothing,
     useExtraPathEnv          = [],
+    useExtraEnvOverrides     = [],
     useWin32CleanHack        = False,
     forceExternalSetupMethod = False,
     setupCacheLock           = Nothing,
@@ -293,8 +302,7 @@
                                           (useCabalVersion options)
                                           (orLaterVersion (specVersion pkg))
                     }
-      buildType'  = fromMaybe Custom (buildType pkg)
-  checkBuildType buildType'
+      buildType'  = buildType pkg
   (version, method, options'') <-
     getSetupMethod verbosity options' pkg buildType'
   return Setup { setupMethod = method
@@ -308,12 +316,6 @@
          >>= readGenericPackageDescription verbosity
          >>= return . packageDescription
 
-    checkBuildType (UnknownBuildType name) =
-      die' verbosity $ "The build-type '" ++ name ++ "' is not known. Use one of: "
-         ++ intercalate ", " (map display knownBuildTypes) ++ "."
-    checkBuildType _ = return ()
-
-
 -- | Decide if we're going to be able to do a direct internal call to the
 -- entry point in the Cabal library or if we're going to have to compile
 -- and execute an external Setup.hs script.
@@ -390,7 +392,7 @@
 runSetupCommand :: Verbosity -> Setup
                 -> CommandUI flags  -- ^ command definition
                 -> flags  -- ^ command flags
-                -> [String]  -- ^ extra command-line arguments
+                -> [String] -- ^ extra command-line arguments
                 -> IO ()
 runSetupCommand verbosity setup cmd flags extraArgs = do
   let args = commandName cmd : commandShowOptions cmd flags ++ extraArgs
@@ -404,11 +406,13 @@
              -> CommandUI flags
              -> (Version -> flags)
                 -- ^ produce command flags given the Cabal library version
-             -> [String]
+             -> (Version -> [String])
              -> IO ()
 setupWrapper verbosity options mpkg cmd flags extraArgs = do
   setup <- getSetup verbosity options mpkg
-  runSetupCommand verbosity setup cmd (flags $ setupVersion setup) extraArgs
+  runSetupCommand verbosity setup
+                  cmd (flags $ setupVersion setup)
+                      (extraArgs $ setupVersion setup)
 
 -- ------------------------------------------------------------
 -- * Internal SetupMethod
@@ -421,7 +425,8 @@
   inDir (useWorkingDir options) $ do
     withEnv "HASKELL_DIST_DIR" (useDistPref options) $
       withExtraPathEnv (useExtraPathEnv options) $
-        buildTypeAction bt args
+        withEnvOverrides (useExtraEnvOverrides options) $
+          buildTypeAction bt args
 
 buildTypeAction :: BuildType -> ([String] -> IO ())
 buildTypeAction Simple    = Simple.defaultMainArgs
@@ -429,7 +434,6 @@
                               Simple.autoconfUserHooks
 buildTypeAction Make      = Make.defaultMainArgs
 buildTypeAction Custom               = error "buildTypeAction Custom"
-buildTypeAction (UnknownBuildType _) = error "buildTypeAction UnknownBuildType"
 
 
 -- | @runProcess'@ is a version of @runProcess@ where we have
@@ -452,9 +456,7 @@
                      , Process.std_in  = mbToStd mb_stdin
                      , Process.std_out = mbToStd mb_stdout
                      , Process.std_err = mbToStd mb_stderr
-#if MIN_VERSION_process(1,2,0)
                      , Process.delegate_ctlc = _delegate
-#endif
                      }
   return ph
   where
@@ -482,8 +484,10 @@
   searchpath <- programSearchPathAsPATHVar
                 (map ProgramSearchPathDir (useExtraPathEnv options) ++
                  getProgramSearchPath (useProgramDb options))
-  env       <- getEffectiveEnvironment [("PATH", Just searchpath)
-                                        ,("HASKELL_DIST_DIR", Just (useDistPref options))]
+  env       <- getEffectiveEnvironment $
+                 [ ("PATH", Just searchpath)
+                 , ("HASKELL_DIST_DIR", Just (useDistPref options))
+                 ] ++ useExtraEnvOverrides options
   process <- runProcess' path args
              (useWorkingDir options) env Nothing
              (useLoggingHandle options) (useLoggingHandle options)
@@ -515,9 +519,12 @@
       searchpath <- programSearchPathAsPATHVar
                     (map ProgramSearchPathDir (useExtraPathEnv options) ++
                       getProgramSearchPath (useProgramDb options))
-      env        <- getEffectiveEnvironment [("PATH", Just searchpath)
-                                            ,("HASKELL_DIST_DIR", Just (useDistPref options))]
+      env        <- getEffectiveEnvironment $
+                      [ ("PATH", Just searchpath)
+                      , ("HASKELL_DIST_DIR", Just (useDistPref options))
+                      ] ++ useExtraEnvOverrides options
 
+      debug verbosity $ "Setup arguments: "++unwords args
       process <- runProcess' path' args
                   (useWorkingDir options) env Nothing
                   (useLoggingHandle options) (useLoggingHandle options)
@@ -535,7 +542,7 @@
                   doInvoke
 
     moveOutOfTheWay tmpDir path' = do
-      let newPath = tmpDir </> "setup" <.> exeExtension
+      let newPath = tmpDir </> "setup" <.> exeExtension buildPlatform
       Win32.moveFile path' newPath
       return newPath
 
@@ -587,7 +594,7 @@
   setupDir         = workingDir options </> useDistPref options </> "setup"
   setupVersionFile = setupDir   </> "setup" <.> "version"
   setupHs          = setupDir   </> "setup" <.> "hs"
-  setupProgFile    = setupDir   </> "setup" <.> exeExtension
+  setupProgFile    = setupDir   </> "setup" <.> exeExtension buildPlatform
   platform         = fromMaybe buildPlatform (usePlatform options)
 
   useCachedSetupExecutable = (bt == Simple || bt == Configure || bt == Make)
@@ -632,8 +639,8 @@
             case savedVer of
               Just version | version `withinRange` useCabalVersion options
                 -> do updateSetupScript version bt
-                      -- Does the previously compiled setup executable still exist
-                      -- and is it up-to date?
+                      -- Does the previously compiled setup executable
+                      -- still exist and is it up-to date?
                       useExisting <- canUseExistingSetup version
                       if useExisting
                         then return (version, Nothing, options)
@@ -662,7 +669,8 @@
                              ,SetupScriptOptions)
       installedVersion = do
         (comp,    progdb,  options')  <- configureCompiler options
-        (version, mipkgid, options'') <- installedCabalVersion options' comp progdb
+        (version, mipkgid, options'') <- installedCabalVersion options'
+                                         comp progdb
         updateSetupScript version bt
         writeSetupVersionFile version
         return (version, mipkgid, options'')
@@ -691,7 +699,7 @@
       customSetupLhs  = workingDir options </> "Setup.lhs"
 
   updateSetupScript cabalLibVersion _ =
-    rewriteFile verbosity setupHs (buildTypeScript cabalLibVersion)
+    rewriteFileEx verbosity setupHs (buildTypeScript cabalLibVersion)
 
   buildTypeScript :: Version -> String
   buildTypeScript cabalLibVersion = case bt of
@@ -701,8 +709,7 @@
                    then "autoconfUserHooks\n"
                    else "defaultUserHooks\n"
     Make      -> "import Distribution.Make; main = defaultMain\n"
-    Custom             -> error "buildTypeScript Custom"
-    UnknownBuildType _ -> error "buildTypeScript UnknownBuildType"
+    Custom    -> error "buildTypeScript Custom"
 
   installedCabalVersion :: SetupScriptOptions -> Compiler -> ProgramDb
                         -> IO (Version, Maybe InstalledPackageId
@@ -712,7 +719,8 @@
     return (packageVersion pkg, Nothing, options')
   installedCabalVersion options' compiler progdb = do
     index <- maybeGetInstalledPackages options' compiler progdb
-    let cabalDep   = Dependency (mkPackageName "Cabal") (useCabalVersion options')
+    let cabalDep   = Dependency (mkPackageName "Cabal")
+                                (useCabalVersion options')
         options''  = options' { usePackageIndex = Just index }
     case PackageIndex.lookupDependency index cabalDep of
       []   -> die' verbosity $ "The package '" ++ display (packageName pkg)
@@ -774,14 +782,14 @@
   cachedSetupDirAndProg :: SetupScriptOptions -> Version
                         -> IO (FilePath, FilePath)
   cachedSetupDirAndProg options' cabalLibVersion = do
-    cabalDir <- defaultCabalDir
+    cabalDir <- getCabalDir
     let setupCacheDir       = cabalDir </> "setup-exe-cache"
         cachedSetupProgFile = setupCacheDir
                               </> ("setup-" ++ buildTypeString ++ "-"
                                    ++ cabalVersionString ++ "-"
                                    ++ platformString ++ "-"
                                    ++ compilerVersionString)
-                              <.> exeExtension
+                              <.> exeExtension buildPlatform
     return (setupCacheDir, cachedSetupProgFile)
       where
         buildTypeString       = show bt
@@ -822,7 +830,7 @@
               cachedSetupProgFile
     return cachedSetupProgFile
       where
-        criticalSection'      = maybe id criticalSection $ setupCacheLock options'
+        criticalSection' = maybe id criticalSection $ setupCacheLock options'
 
   -- | If the Setup.hs is out of date wrt the executable then recompile it.
   -- Currently this is GHC/GHCJS only. It should really be generalised.
@@ -859,16 +867,19 @@
           selectedDeps | useDependenciesExclusive options'
                                    = useDependencies options'
                        | otherwise = useDependencies options' ++
-                                     if any (isCabalPkgId . snd) (useDependencies options')
+                                     if any (isCabalPkgId . snd)
+                                        (useDependencies options')
                                      then []
                                      else cabalDep
           addRenaming (ipid, _) =
             -- Assert 'DefUnitId' invariant
-            (Backpack.DefiniteUnitId (unsafeMkDefUnitId (newSimpleUnitId ipid)), defaultRenaming)
+            (Backpack.DefiniteUnitId (unsafeMkDefUnitId (newSimpleUnitId ipid))
+            ,defaultRenaming)
           cppMacrosFile = setupDir </> "setup_macros.h"
           ghcOptions = mempty {
               -- Respect -v0, but don't crank up verbosity on GHC if
-              -- Cabal verbosity is requested. For that, use --ghc-option=-v instead!
+              -- Cabal verbosity is requested. For that, use
+              -- --ghc-option=-v instead!
               ghcOptVerbosity       = Flag (min verbosity normal)
             , ghcOptMode            = Flag GhcModeMake
             , ghcOptInputFiles      = toNubListR [setupHs]
@@ -885,16 +896,17 @@
             , ghcOptPackages        = toNubListR $ map addRenaming selectedDeps
             , ghcOptCppIncludes     = toNubListR [ cppMacrosFile
                                                  | useVersionMacros options' ]
-            , ghcOptExtra           = toNubListR extraOpts
+            , ghcOptExtra           = extraOpts
             }
       let ghcCmdLine = renderGhcOptions compiler platform ghcOptions
       when (useVersionMacros options') $
-        rewriteFile verbosity cppMacrosFile
+        rewriteFileEx verbosity cppMacrosFile
             (generatePackageVersionMacros (map snd selectedDeps))
       case useLoggingHandle options of
         Nothing          -> runDbProgram verbosity program progdb ghcCmdLine
 
-        -- If build logging is enabled, redirect compiler output to the log file.
+        -- If build logging is enabled, redirect compiler output to
+        -- the log file.
         (Just logHandle) -> do output <- getDbProgramOutput verbosity program
                                          progdb ghcCmdLine
                                hPutStr logHandle output
diff --git a/cabal/cabal-install/Distribution/Client/SourceRepoParse.hs b/cabal/cabal-install/Distribution/Client/SourceRepoParse.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/Distribution/Client/SourceRepoParse.hs
@@ -0,0 +1,22 @@
+module Distribution.Client.SourceRepoParse where
+
+import Distribution.Client.Compat.Prelude
+import Prelude ()
+
+import Distribution.FieldGrammar.FieldDescrs        (fieldDescrsToList)
+import Distribution.PackageDescription.FieldGrammar (sourceRepoFieldGrammar)
+import Distribution.Parsec.Class                    (explicitEitherParsec)
+import Distribution.ParseUtils                      (FieldDescr (..), syntaxError)
+import Distribution.Types.SourceRepo                (SourceRepo, RepoKind (..))
+
+sourceRepoFieldDescrs :: [FieldDescr SourceRepo]
+sourceRepoFieldDescrs =
+    map toDescr . fieldDescrsToList $ sourceRepoFieldGrammar (RepoKindUnknown "unused")
+  where
+    toDescr (name, pretty, parse) = FieldDescr
+        { fieldName = name
+        , fieldGet  = pretty
+        , fieldSet  = \lineNo str x ->
+              either (syntaxError lineNo) return
+              $ explicitEitherParsec (parse x) str
+        }
diff --git a/cabal/cabal-install/Distribution/Client/SrcDist.hs b/cabal/cabal-install/Distribution/Client/SrcDist.hs
--- a/cabal/cabal-install/Distribution/Client/SrcDist.hs
+++ b/cabal/cabal-install/Distribution/Client/SrcDist.hs
@@ -69,7 +69,7 @@
     -- Run 'setup sdist --output-directory=tmpDir' (or
     -- '--list-source'/'--output-directory=someOtherDir') in case we were passed
     -- those options.
-    setupWrapper verbosity setupOpts (Just pkg) sdistCommand (const flags') []
+    setupWrapper verbosity setupOpts (Just pkg) sdistCommand (const flags') (const [])
 
     -- Unless we were given --list-sources or --output-directory ourselves,
     -- create an archive.
@@ -176,7 +176,7 @@
 
       doListSources :: IO [FilePath]
       doListSources = do
-        setupWrapper verbosity setupOpts (Just pkg) sdistCommand (const flags) []
+        setupWrapper verbosity setupOpts (Just pkg) sdistCommand (const flags) (const [])
         fmap lines . readFile $ file
 
       onFailedListSources :: IOException -> IO ()
diff --git a/cabal/cabal-install/Distribution/Client/TargetSelector.hs b/cabal/cabal-install/Distribution/Client/TargetSelector.hs
--- a/cabal/cabal-install/Distribution/Client/TargetSelector.hs
+++ b/cabal/cabal-install/Distribution/Client/TargetSelector.hs
@@ -1,4 +1,5 @@
-{-# LANGUAGE CPP, DeriveGeneric, DeriveFunctor, RecordWildCards #-}
+{-# LANGUAGE CPP, DeriveGeneric, DeriveFunctor,
+             RecordWildCards, NamedFieldPuns #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Distribution.Client.TargetSelector
@@ -26,7 +27,7 @@
     TargetSelectorProblem(..),
     reportTargetSelectorProblems,
     showTargetSelector,
-    TargetString,
+    TargetString(..),
     showTargetString,
     parseTargetString,
     -- ** non-IO
@@ -35,12 +36,14 @@
     defaultDirActions,
   ) where
 
+import Prelude ()
+import Distribution.Client.Compat.Prelude
+
 import Distribution.Package
-         ( Package(..), PackageId, PackageIdentifier(..)
-         , PackageName, packageName, mkPackageName )
-import Distribution.Version
-         ( mkVersion )
-import Distribution.Types.UnqualComponentName ( unUnqualComponentName )
+         ( Package(..), PackageId, PackageName, packageName )
+import Distribution.Types.UnqualComponentName
+         ( UnqualComponentName, mkUnqualComponentName, unUnqualComponentName
+         , packageNameToUnqualComponentName )
 import Distribution.Client.Types
          ( PackageLocation(..), PackageSpecifier(..) )
 
@@ -63,7 +66,7 @@
 import Distribution.Types.ForeignLib
 
 import Distribution.Text
-         ( display, simpleParse )
+         ( Text, display, simpleParse )
 import Distribution.Simple.Utils
          ( die', lowercase, ordNub )
 import Distribution.Client.Utils
@@ -74,36 +77,20 @@
 import Data.Function
          ( on )
 import Data.List
-         ( nubBy, stripPrefix, partition, intercalate, sortBy, groupBy )
-import Data.Maybe
-         ( maybeToList )
+         ( stripPrefix, partition, groupBy )
 import Data.Ord
          ( comparing )
-import Distribution.Compat.Binary (Binary)
-import GHC.Generics (Generic)
-#if MIN_VERSION_containers(0,5,0)
 import qualified Data.Map.Lazy   as Map.Lazy
 import qualified Data.Map.Strict as Map
-import Data.Map.Strict (Map)
-#else
-import qualified Data.Map as Map.Lazy
-import qualified Data.Map as Map
-import Data.Map (Map)
-#endif
 import qualified Data.Set as Set
 import Control.Arrow ((&&&))
-import Control.Monad
-#if __GLASGOW_HASKELL__ < 710
-import Control.Applicative (Applicative(..), (<$>))
-#endif
-import Control.Applicative (Alternative(..))
+import Control.Monad 
+  hiding ( mfilter )
 import qualified Distribution.Compat.ReadP as Parse
 import Distribution.Compat.ReadP
          ( (+++), (<++) )
 import Distribution.ParseUtils
          ( readPToMaybe )
-import Data.Char
-         ( isSpace, isAlphaNum )
 import System.FilePath as FilePath
          ( takeExtension, dropExtension
          , splitDirectories, joinPath, splitPath )
@@ -140,27 +127,39 @@
 -- > [ [lib:|exe:] component name ]
 -- > [ module name | source file ]
 --
-data TargetSelector pkg =
+data TargetSelector =
 
-     -- | A package as a whole: the default components for the package or all
-     -- components of a particular kind.
+     -- | One (or more) packages as a whole, or all the components of a
+     -- particular kind within the package(s).
      --
-     TargetPackage TargetImplicitCwd pkg (Maybe ComponentKindFilter)
+     -- These are always packages that are local to the project. In the case
+     -- that there is more than one, they all share the same directory location.
+     --
+     TargetPackage TargetImplicitCwd [PackageId] (Maybe ComponentKindFilter)
 
+     -- | A package specified by name. This may refer to @extra-packages@ from
+     -- the @cabal.project@ file, or a dependency of a known project package or
+     -- could refer to a package from a hackage archive. It needs further
+     -- context to resolve to a specific package.
+     --
+   | TargetPackageNamed PackageName (Maybe ComponentKindFilter)
+
      -- | All packages, or all components of a particular kind in all packages.
      --
    | TargetAllPackages (Maybe ComponentKindFilter)
 
-     -- | A specific component in a package.
+     -- | A specific component in a package within the project.
      --
-   | TargetComponent pkg ComponentName SubComponentTarget
+   | TargetComponent PackageId ComponentName SubComponentTarget
 
-     -- | A named package, but not a known local package. It could for example
-     -- resolve to a dependency of a local package or to a package from
-     -- hackage. Either way, it requires further processing to resolve.
+     -- | A component in a package, but where it cannot be verified that the
+     -- package has such a component, or because the package is itself not
+     -- known.
      --
-   | TargetPackageName PackageName
-  deriving (Eq, Ord, Functor, Show, Generic)
+   | TargetComponentUnknown PackageName
+                            (Either UnqualComponentName ComponentName)
+                            SubComponentTarget
+  deriving (Eq, Ord, Show, Generic)
 
 -- | Does this 'TargetPackage' selector arise from syntax referring to a
 -- package in the current directory (e.g. @tests@ or no giving no explicit
@@ -203,40 +202,32 @@
 -- the available packages (and their locations).
 --
 readTargetSelectors :: [PackageSpecifier (SourcePackage (PackageLocation a))]
+                    -> Maybe ComponentKindFilter
+                    -- ^ This parameter is used when there are ambiguous selectors.
+                    --   If it is 'Just', then we attempt to resolve ambiguitiy
+                    --   by applying it, since otherwise there is no way to allow
+                    --   contextually valid yet syntactically ambiguous selectors.
+                    --   (#4676, #5461)
                     -> [String]
-                    -> IO (Either [TargetSelectorProblem]
-                                  [TargetSelector PackageId])
+                    -> IO (Either [TargetSelectorProblem] [TargetSelector])
 readTargetSelectors = readTargetSelectorsWith defaultDirActions
 
 readTargetSelectorsWith :: (Applicative m, Monad m) => DirActions m
                         -> [PackageSpecifier (SourcePackage (PackageLocation a))]
+                        -> Maybe ComponentKindFilter
                         -> [String]
-                        -> m (Either [TargetSelectorProblem]
-                                     [TargetSelector PackageId])
-readTargetSelectorsWith dirActions@DirActions{..} pkgs targetStrs =
+                        -> m (Either [TargetSelectorProblem] [TargetSelector])
+readTargetSelectorsWith dirActions@DirActions{..} pkgs mfilter targetStrs =
     case parseTargetStrings targetStrs of
-      ([], utargets) -> do
-        utargets' <- mapM (getTargetStringFileStatus dirActions) utargets
-        pkgs'     <- sequence [ selectPackageInfo dirActions pkg
-                              | SpecificSourcePackage pkg <- pkgs ]
-        cwd       <- getCurrentDirectory
-        let (cwdPkg, otherPkgs) = selectCwdPackage cwd pkgs'
-        case resolveTargetSelectors cwdPkg otherPkgs utargets' of
-          ([], btargets) -> return (Right (map (fmap packageId) btargets))
+      ([], usertargets) -> do
+        usertargets' <- mapM (getTargetStringFileStatus dirActions) usertargets
+        knowntargets <- getKnownTargets dirActions pkgs
+        case resolveTargetSelectors knowntargets usertargets' mfilter of
+          ([], btargets) -> return (Right btargets)
           (problems, _)  -> return (Left problems)
       (strs, _)          -> return (Left (map TargetSelectorUnrecognised strs))
-  where
-    selectCwdPackage :: FilePath
-                     -> [PackageInfo]
-                     -> ([PackageInfo], [PackageInfo])
-    selectCwdPackage cwd pkgs' =
-        let (cwdpkg, others) = partition isPkgDirCwd pkgs'
-         in (cwdpkg, others)
-      where
-        isPkgDirCwd PackageInfo { pinfoDirectory = Just (dir,_) }
-          | dir == cwd = True
-        isPkgDirCwd _  = False
 
+
 data DirActions m = DirActions {
        doesFileExist       :: FilePath -> m Bool,
        doesDirectoryExist  :: FilePath -> m Bool,
@@ -358,25 +349,29 @@
     components (TargetString5 s1 s2 s3 s4 s5)       = [s1,s2,s3,s4,s5]
     components (TargetString7 s1 s2 s3 s4 s5 s6 s7) = [s1,s2,s3,s4,s5,s6,s7]
 
-showTargetSelector :: Package p => TargetSelector p -> String
+showTargetSelector :: TargetSelector -> String
 showTargetSelector ts =
   case [ t | ql <- [QL1 .. QLFull]
            , t  <- renderTargetSelector ql ts ]
   of (t':_) -> showTargetString (forgetFileStatus t')
      [] -> ""
 
-showTargetSelectorKind :: TargetSelector a -> String
+showTargetSelectorKind :: TargetSelector -> String
 showTargetSelectorKind bt = case bt of
   TargetPackage TargetExplicitNamed _ Nothing  -> "package"
   TargetPackage TargetExplicitNamed _ (Just _) -> "package:filter"
   TargetPackage TargetImplicitCwd   _ Nothing  -> "cwd-package"
   TargetPackage TargetImplicitCwd   _ (Just _) -> "cwd-package:filter"
-  TargetAllPackages Nothing                    -> "all-packages"
-  TargetAllPackages (Just _)                   -> "all-packages:filter"
-  TargetComponent _ _ WholeComponent           -> "component"
-  TargetComponent _ _ ModuleTarget{}           -> "module"
-  TargetComponent _ _ FileTarget{}             -> "file"
-  TargetPackageName{}                          -> "package name"
+  TargetPackageNamed                _ Nothing  -> "named-package"
+  TargetPackageNamed                _ (Just _) -> "named-package:filter"
+  TargetAllPackages Nothing                    -> "package *"
+  TargetAllPackages (Just _)                   -> "package *:filter"
+  TargetComponent        _ _ WholeComponent    -> "component"
+  TargetComponent        _ _ ModuleTarget{}    -> "module"
+  TargetComponent        _ _ FileTarget{}      -> "file"
+  TargetComponentUnknown _ _ WholeComponent    -> "unknown-component"
+  TargetComponentUnknown _ _ ModuleTarget{}    -> "unknown-module"
+  TargetComponentUnknown _ _ FileTarget{}      -> "unknown-file"
 
 
 -- ------------------------------------------------------------
@@ -446,68 +441,64 @@
 -- | Given a bunch of user-specified targets, try to resolve what it is they
 -- refer to.
 --
-resolveTargetSelectors :: [PackageInfo]     -- any pkg in the cur dir
-                       -> [PackageInfo]     -- all the other local packages
+resolveTargetSelectors :: KnownTargets
                        -> [TargetStringFileStatus]
+                       -> Maybe ComponentKindFilter
                        -> ([TargetSelectorProblem],
-                           [TargetSelector PackageInfo])
-
+                           [TargetSelector])
 -- default local dir target if there's no given target:
-resolveTargetSelectors [] [] [] =
+resolveTargetSelectors (KnownTargets{knownPackagesAll = []}) [] _ =
     ([TargetSelectorNoTargetsInProject], [])
 
-resolveTargetSelectors [] _opinfo [] =
+resolveTargetSelectors (KnownTargets{knownPackagesPrimary = []}) [] _ =
     ([TargetSelectorNoTargetsInCwd], [])
 
-resolveTargetSelectors ppinfo _opinfo [] =
-    ([], [TargetPackage TargetImplicitCwd (head ppinfo) Nothing])
-    --TODO: in future allow multiple packages in the same dir
+resolveTargetSelectors (KnownTargets{knownPackagesPrimary}) [] _ =
+    ([], [TargetPackage TargetImplicitCwd pkgids Nothing])
+  where
+    pkgids = [ pinfoId | KnownPackage{pinfoId} <- knownPackagesPrimary ]
 
-resolveTargetSelectors ppinfo opinfo targetStrs =
+resolveTargetSelectors knowntargets targetStrs mfilter =
     partitionEithers
-  . map (resolveTargetSelector ppinfo opinfo)
+  . map (resolveTargetSelector knowntargets mfilter)
   $ targetStrs
 
-resolveTargetSelector :: [PackageInfo] -> [PackageInfo]
+resolveTargetSelector :: KnownTargets
+                      -> Maybe ComponentKindFilter
                       -> TargetStringFileStatus
-                      -> Either TargetSelectorProblem
-                                (TargetSelector PackageInfo)
-resolveTargetSelector ppinfo opinfo targetStrStatus =
+                      -> Either TargetSelectorProblem TargetSelector
+resolveTargetSelector knowntargets@KnownTargets{..} mfilter targetStrStatus =
     case findMatch (matcher targetStrStatus) of
 
       Unambiguous _
         | projectIsEmpty -> Left TargetSelectorNoTargetsInProject
 
-      Unambiguous (TargetPackage TargetImplicitCwd _ mkfilter)
-        | null ppinfo -> Left (TargetSelectorNoCurrentPackage targetStr)
-        | otherwise   -> Right (TargetPackage TargetImplicitCwd
-                                              (head ppinfo) mkfilter)
-                       --TODO: in future allow multiple packages in the same dir
+      Unambiguous (TargetPackage TargetImplicitCwd [] _)
+                         -> Left (TargetSelectorNoCurrentPackage targetStr)
 
       Unambiguous target -> Right target
 
       None errs
-        | TargetStringFileStatus1 str _ <- targetStrStatus
-        , validPackageName str -> Right (TargetPackageName (mkPackageName str))
         | projectIsEmpty       -> Left TargetSelectorNoTargetsInProject
         | otherwise            -> Left (classifyMatchErrors errs)
 
+      Ambiguous _          targets
+        | Just kfilter <- mfilter
+        , [target] <- applyKindFilter kfilter targets -> Right target
+
       Ambiguous exactMatch targets ->
         case disambiguateTargetSelectors
                matcher targetStrStatus exactMatch
                targets of
-          Right targets'   -> Left (TargetSelectorAmbiguous targetStr
-                                       (map (fmap (fmap packageId)) targets'))
-          Left ((m, ms):_) -> Left (MatchingInternalError targetStr
-                                       (fmap packageId m)
-                                       (map (fmap (map (fmap packageId))) ms))
+          Right targets'   -> Left (TargetSelectorAmbiguous targetStr targets')
+          Left ((m, ms):_) -> Left (MatchingInternalError targetStr m ms)
           Left []          -> internalError "resolveTargetSelector"
   where
-    matcher = matchTargetSelector ppinfo opinfo
+    matcher = matchTargetSelector knowntargets
 
     targetStr = forgetFileStatus targetStrStatus
 
-    projectIsEmpty = null ppinfo && null opinfo
+    projectIsEmpty = null knownPackagesAll
 
     classifyMatchErrors errs
       | not (null expected)
@@ -554,6 +545,21 @@
                      = innerErr (Just (kind,thing)) m
         innerErr c m = (c,m)
 
+    applyKindFilter :: ComponentKindFilter -> [TargetSelector] -> [TargetSelector]
+    applyKindFilter kfilter = filter go
+      where
+        go (TargetPackage      _ _ (Just filter')) = kfilter == filter'
+        go (TargetPackageNamed _   (Just filter')) = kfilter == filter'
+        go (TargetAllPackages      (Just filter')) = kfilter == filter'
+        go (TargetComponent _ cname _)
+          | CLibName      <- cname                 = kfilter == LibKind
+          | CSubLibName _ <- cname                 = kfilter == LibKind
+          | CFLibName   _ <- cname                 = kfilter == FLibKind
+          | CExeName    _ <- cname                 = kfilter == ExeKind
+          | CTestName   _ <- cname                 = kfilter == TestKind
+          | CBenchName  _ <- cname                 = kfilter == BenchKind
+        go _                                       = True
+
 -- | The various ways that trying to resolve a 'TargetString' to a
 -- 'TargetSelector' can fail.
 --
@@ -564,10 +570,10 @@
                            [(Maybe (String, String), String, String, [String])]
      -- ^ [([in thing], no such thing,  actually got, alternatives)]
    | TargetSelectorAmbiguous  TargetString
-                              [(TargetString, TargetSelector PackageId)]
+                              [(TargetString, TargetSelector)]
 
-   | MatchingInternalError TargetString (TargetSelector PackageId)
-                           [(TargetString, [TargetSelector PackageId])]
+   | MatchingInternalError TargetString TargetSelector
+                           [(TargetString, [TargetSelector])]
    | TargetSelectorUnrecognised String
      -- ^ Syntax error when trying to parse a target string.
    | TargetSelectorNoCurrentPackage TargetString
@@ -579,12 +585,11 @@
   deriving (Eq, Enum, Show)
 
 disambiguateTargetSelectors
-  :: (TargetStringFileStatus -> Match (TargetSelector PackageInfo))
-  -> TargetStringFileStatus -> Bool
-  -> [TargetSelector PackageInfo]
-  -> Either [(TargetSelector PackageInfo,
-              [(TargetString, [TargetSelector PackageInfo])])]
-            [(TargetString, TargetSelector PackageInfo)]
+  :: (TargetStringFileStatus -> Match TargetSelector)
+  -> TargetStringFileStatus -> MatchClass
+  -> [TargetSelector]
+  -> Either [(TargetSelector, [(TargetString, [TargetSelector])])]
+            [(TargetString, TargetSelector)]
 disambiguateTargetSelectors matcher matchInput exactMatch matchResults =
     case partitionEithers results of
       (errs@(_:_), _) -> Left errs
@@ -593,8 +598,7 @@
     -- So, here's the strategy. We take the original match results, and make a
     -- table of all their renderings at all qualification levels.
     -- Note there can be multiple renderings at each qualification level.
-    matchResultsRenderings :: [(TargetSelector PackageInfo,
-                                [TargetStringFileStatus])]
+    matchResultsRenderings :: [(TargetSelector, [TargetStringFileStatus])]
     matchResultsRenderings =
       [ (matchResult, matchRenderings)
       | matchResult <- matchResults
@@ -609,12 +613,12 @@
     -- for all of those renderings. So by looking up in this table we can see
     -- if we've got an unambiguous match.
 
-    memoisedMatches :: Map TargetStringFileStatus
-                           (Match (TargetSelector PackageInfo))
+    memoisedMatches :: Map TargetStringFileStatus (Match TargetSelector)
     memoisedMatches =
         -- avoid recomputing the main one if it was an exact match
-        (if exactMatch then Map.insert matchInput (ExactMatch 0 matchResults)
-                       else id)
+        (if exactMatch == Exact
+           then Map.insert matchInput (Match Exact 0 matchResults)
+           else id)
       $ Map.Lazy.fromList
           [ (rendering, matcher rendering)
           | rendering <- concatMap snd matchResultsRenderings ]
@@ -623,9 +627,8 @@
     -- possible renderings (in order of qualification level, though remember
     -- there can be multiple renderings per level), and find the first one
     -- that has an unambiguous match.
-    results :: [Either (TargetSelector PackageInfo,
-                        [(TargetString, [TargetSelector PackageInfo])])
-                       (TargetString, TargetSelector PackageInfo)]
+    results :: [Either (TargetSelector, [(TargetString, [TargetSelector])])
+                       (TargetString, TargetSelector)]
     results =
       [ case findUnambiguous originalMatch matchRenderings of
           Just unambiguousRendering ->
@@ -637,23 +640,25 @@
             Left  ( originalMatch
                   , [ (forgetFileStatus rendering, matches)
                     | rendering <- matchRenderings
-                    , let (ExactMatch _ matches) =
+                    , let Match m _ matches =
                             memoisedMatches Map.! rendering
+                    , m /= Inexact
                     ] )
 
       | (originalMatch, matchRenderings) <- matchResultsRenderings ]
 
-    findUnambiguous :: TargetSelector PackageInfo
+    findUnambiguous :: TargetSelector
                     -> [TargetStringFileStatus]
                     -> Maybe TargetStringFileStatus
     findUnambiguous _ []     = Nothing
     findUnambiguous t (r:rs) =
       case memoisedMatches Map.! r of
-        ExactMatch _ [t'] | fmap packageName t == fmap packageName t'
-                         -> Just r
-        ExactMatch _  _  -> findUnambiguous t rs
-        InexactMatch _ _ -> internalError "InexactMatch"
-        NoMatch      _ _ -> internalError "NoMatch"
+        Match Exact _ [t'] | t == t'
+                          -> Just r
+        Match Exact   _ _ -> findUnambiguous t rs
+        Match Unknown _ _ -> findUnambiguous t rs
+        Match Inexact _ _ -> internalError "Match Inexact"
+        NoMatch       _ _ -> internalError "NoMatch"
 
 internalError :: String -> a
 internalError msg =
@@ -793,8 +798,8 @@
             | AmbiguousAlternatives Syntax Syntax
             | ShadowingAlternatives Syntax Syntax
 
-type Matcher  = TargetStringFileStatus -> Match (TargetSelector PackageInfo)
-type Renderer = TargetSelector PackageId -> [TargetStringFileStatus]
+type Matcher  = TargetStringFileStatus -> Match TargetSelector
+type Renderer = TargetSelector -> [TargetStringFileStatus]
 
 foldSyntax :: (a -> a -> a) -> (a -> a -> a)
            -> (QualLevel -> Matcher -> Renderer -> a)
@@ -810,29 +815,30 @@
 -- Top level renderer and matcher
 --
 
-renderTargetSelector :: Package p => QualLevel -> TargetSelector p
+renderTargetSelector :: QualLevel -> TargetSelector
                      -> [TargetStringFileStatus]
 renderTargetSelector ql ts =
     foldSyntax
       (++) (++)
-      (\ql' _ render -> guard (ql == ql') >> render (fmap packageId ts))
+      (\ql' _ render -> guard (ql == ql') >> render ts)
       syntax
   where
-    syntax = syntaxForms [] [] -- don't need pinfo for rendering
+    syntax = syntaxForms emptyKnownTargets
+                         -- don't need known targets for rendering
 
-matchTargetSelector :: [PackageInfo] -> [PackageInfo]
+matchTargetSelector :: KnownTargets
                     -> TargetStringFileStatus
-                    -> Match (TargetSelector PackageInfo)
-matchTargetSelector ppinfo opinfo = \utarget ->
-    nubMatchesBy ((==) `on` (fmap packageName)) $
+                    -> Match TargetSelector
+matchTargetSelector knowntargets = \usertarget ->
+    nubMatchesBy (==) $
 
-    let ql = targetQualLevel utarget in
+    let ql = targetQualLevel usertarget in
     foldSyntax
       (<|>) (<//>)
-      (\ql' match _ -> guard (ql == ql') >> match utarget)
+      (\ql' match _ -> guard (ql == ql') >> match usertarget)
       syntax
   where
-    syntax = syntaxForms ppinfo opinfo
+    syntax = syntaxForms knowntargets
 
     targetQualLevel TargetStringFileStatus1{} = QL1
     targetQualLevel TargetStringFileStatus2{} = QL2
@@ -848,8 +854,14 @@
 
 -- | All the forms of syntax for 'TargetSelector'.
 --
-syntaxForms :: [PackageInfo] -> [PackageInfo] -> Syntax
-syntaxForms ppinfo opinfo =
+syntaxForms :: KnownTargets -> Syntax
+syntaxForms KnownTargets {
+              knownPackagesAll       = pinfo,
+              knownPackagesPrimary   = ppinfo,
+              knownComponentsAll     = cinfo,
+              knownComponentsPrimary = pcinfo,
+              knownComponentsOther   = ocinfo
+            } =
     -- The various forms of syntax here are ambiguous in many cases.
     -- Our policy is by default we expose that ambiguity and report
     -- ambiguous matches. In certain cases we override the ambiguity
@@ -865,7 +877,7 @@
       [ shadowingAlternatives
           [ ambiguousAlternatives
               [ syntaxForm1All
-              , syntaxForm1Filter
+              , syntaxForm1Filter        ppinfo
               , shadowingAlternatives
                   [ syntaxForm1Component pcinfo
                   , syntaxForm1Package   pinfo
@@ -907,7 +919,7 @@
 
         -- fully-qualified forms for all and cwd with filter
       , syntaxForm3MetaAllFilter
-      , syntaxForm3MetaCwdFilter
+      , syntaxForm3MetaCwdFilter ppinfo
 
         -- fully-qualified form for package and package with filter
       , syntaxForm3MetaNamespacePackage       pinfo
@@ -921,10 +933,6 @@
   where
     ambiguousAlternatives = foldr1 AmbiguousAlternatives
     shadowingAlternatives = foldr1 ShadowingAlternatives
-    pinfo  = ppinfo ++ opinfo
-    cinfo  = concatMap pinfoComponents pinfo
-    pcinfo = concatMap pinfoComponents ppinfo
-    ocinfo = concatMap pinfoComponents opinfo
 
 
 -- | Syntax: "all" to select all packages in the project
@@ -945,56 +953,50 @@
 --
 -- > cabal build tests
 --
-syntaxForm1Filter :: Syntax
-syntaxForm1Filter =
+syntaxForm1Filter :: [KnownPackage] -> Syntax
+syntaxForm1Filter ps =
   syntaxForm1 render $ \str1 _fstatus1 -> do
     kfilter <- matchComponentKindFilter str1
-    return (TargetPackage TargetImplicitCwd dummyPackageInfo (Just kfilter))
+    return (TargetPackage TargetImplicitCwd pids (Just kfilter))
   where
+    pids = [ pinfoId | KnownPackage{pinfoId} <- ps ]
     render (TargetPackage TargetImplicitCwd _ (Just kfilter)) =
       [TargetStringFileStatus1 (dispF kfilter) noFileStatus]
     render _ = []
 
--- Only used for TargetPackage TargetImplicitCwd
-dummyPackageInfo :: PackageInfo
-dummyPackageInfo =
-    PackageInfo {
-      pinfoId          = PackageIdentifier
-                           (mkPackageName "dummyPackageInfo")
-                           (mkVersion []),
-      pinfoDirectory   = unused,
-      pinfoPackageFile = unused,
-      pinfoComponents  = unused
-    }
-  where
-    unused = error "dummyPackageInfo"
 
 -- | Syntax: package (name, dir or file)
 --
 -- > cabal build foo
 -- > cabal build ../bar ../bar/bar.cabal
 --
-syntaxForm1Package :: [PackageInfo] -> Syntax
+syntaxForm1Package :: [KnownPackage] -> Syntax
 syntaxForm1Package pinfo =
   syntaxForm1 render $ \str1 fstatus1 -> do
     guardPackage            str1 fstatus1
     p <- matchPackage pinfo str1 fstatus1
-    return (TargetPackage TargetExplicitNamed p Nothing)
+    case p of
+      KnownPackage{pinfoId} ->
+        return (TargetPackage TargetExplicitNamed [pinfoId] Nothing)
+      KnownPackageName pn ->
+        return (TargetPackageNamed pn Nothing)
   where
-    render (TargetPackage TargetExplicitNamed p Nothing) =
+    render (TargetPackage TargetExplicitNamed [p] Nothing) =
       [TargetStringFileStatus1 (dispP p) noFileStatus]
+    render (TargetPackageNamed pn Nothing) =
+      [TargetStringFileStatus1 (dispPN pn) noFileStatus]
     render _ = []
 
 -- | Syntax: component
 --
 -- > cabal build foo
 --
-syntaxForm1Component :: [ComponentInfo] -> Syntax
+syntaxForm1Component :: [KnownComponent] -> Syntax
 syntaxForm1Component cs =
   syntaxForm1 render $ \str1 _fstatus1 -> do
     guardComponentName str1
     c <- matchComponentName cs str1
-    return (TargetComponent (cinfoPackage c) (cinfoName c) WholeComponent)
+    return (TargetComponent (cinfoPackageId c) (cinfoName c) WholeComponent)
   where
     render (TargetComponent p c WholeComponent) =
       [TargetStringFileStatus1 (dispC p c) noFileStatus]
@@ -1004,13 +1006,13 @@
 --
 -- > cabal build Data.Foo
 --
-syntaxForm1Module :: [ComponentInfo] -> Syntax
+syntaxForm1Module :: [KnownComponent] -> Syntax
 syntaxForm1Module cs =
   syntaxForm1 render $  \str1 _fstatus1 -> do
     guardModuleName str1
     let ms = [ (m,c) | c <- cs, m <- cinfoModules c ]
     (m,c) <- matchModuleNameAnd ms str1
-    return (TargetComponent (cinfoPackage c) (cinfoName c) (ModuleTarget m))
+    return (TargetComponent (cinfoPackageId c) (cinfoName c) (ModuleTarget m))
   where
     render (TargetComponent _p _c (ModuleTarget m)) =
       [TargetStringFileStatus1 (dispM m) noFileStatus]
@@ -1020,7 +1022,7 @@
 --
 -- > cabal build Data/Foo.hs bar/Main.hsc
 --
-syntaxForm1File :: [PackageInfo] -> Syntax
+syntaxForm1File :: [KnownPackage] -> Syntax
 syntaxForm1File ps =
     -- Note there's a bit of an inconsistency here vs the other syntax forms
     -- for files. For the single-part syntax the target has to point to a file
@@ -1028,10 +1030,12 @@
     -- all the other forms we don't require that.
   syntaxForm1 render $ \str1 fstatus1 ->
     expecting "file" str1 $ do
-    (pkgfile, p) <- matchPackageDirectoryPrefix ps fstatus1
-    orNoThingIn "package" (display (packageName p)) $ do
-      (filepath, c) <- matchComponentFile (pinfoComponents p) pkgfile
-      return (TargetComponent p (cinfoName c) (FileTarget filepath))
+    (pkgfile, ~KnownPackage{pinfoId, pinfoComponents})
+      -- always returns the KnownPackage case
+      <- matchPackageDirectoryPrefix ps fstatus1
+    orNoThingIn "package" (display (packageName pinfoId)) $ do
+      (filepath, c) <- matchComponentFile pinfoComponents pkgfile
+      return (TargetComponent pinfoId (cinfoName c) (FileTarget filepath))
   where
     render (TargetComponent _p _c (FileTarget f)) =
       [TargetStringFileStatus1 f noFileStatus]
@@ -1073,32 +1077,44 @@
 --
 -- > cabal build foo:tests
 --
-syntaxForm2PackageFilter :: [PackageInfo] -> Syntax
+syntaxForm2PackageFilter :: [KnownPackage] -> Syntax
 syntaxForm2PackageFilter ps =
   syntaxForm2 render $ \str1 fstatus1 str2 -> do
     guardPackage         str1 fstatus1
     p <- matchPackage ps str1 fstatus1
     kfilter <- matchComponentKindFilter str2
-    return (TargetPackage TargetExplicitNamed p (Just kfilter))
+    case p of
+      KnownPackage{pinfoId} ->
+        return (TargetPackage TargetExplicitNamed [pinfoId] (Just kfilter))
+      KnownPackageName pn ->
+        return (TargetPackageNamed pn (Just kfilter))
   where
-    render (TargetPackage TargetExplicitNamed p (Just kfilter)) =
+    render (TargetPackage TargetExplicitNamed [p] (Just kfilter)) =
       [TargetStringFileStatus2 (dispP p) noFileStatus (dispF kfilter)]
+    render (TargetPackageNamed pn (Just kfilter)) =
+      [TargetStringFileStatus2 (dispPN pn) noFileStatus (dispF kfilter)]
     render _ = []
 
 -- | Syntax: pkg : package name
 --
 -- > cabal build pkg:foo
 --
-syntaxForm2NamespacePackage :: [PackageInfo] -> Syntax
+syntaxForm2NamespacePackage :: [KnownPackage] -> Syntax
 syntaxForm2NamespacePackage pinfo =
   syntaxForm2 render $ \str1 _fstatus1 str2 -> do
     guardNamespacePackage   str1
     guardPackageName        str2
     p <- matchPackage pinfo str2 noFileStatus
-    return (TargetPackage TargetExplicitNamed p Nothing)
+    case p of
+      KnownPackage{pinfoId} ->
+        return (TargetPackage TargetExplicitNamed [pinfoId] Nothing)
+      KnownPackageName pn ->
+        return (TargetPackageNamed pn Nothing)
   where
-    render (TargetPackage TargetExplicitNamed p Nothing) =
+    render (TargetPackage TargetExplicitNamed [p] Nothing) =
       [TargetStringFileStatus2 "pkg" noFileStatus (dispP p)]
+    render (TargetPackageNamed pn Nothing) =
+      [TargetStringFileStatus2 "pkg" noFileStatus (dispPN pn)]
     render _ = []
 
 -- | Syntax: package : component
@@ -1107,36 +1123,43 @@
 -- > cabal build ./foo:foo
 -- > cabal build ./foo.cabal:foo
 --
-syntaxForm2PackageComponent :: [PackageInfo] -> Syntax
+syntaxForm2PackageComponent :: [KnownPackage] -> Syntax
 syntaxForm2PackageComponent ps =
   syntaxForm2 render $ \str1 fstatus1 str2 -> do
     guardPackage         str1 fstatus1
     guardComponentName   str2
     p <- matchPackage ps str1 fstatus1
-    orNoThingIn "package" (display (packageName p)) $ do
-      c <- matchComponentName (pinfoComponents p) str2
-      return (TargetComponent p (cinfoName c) WholeComponent)
-    --TODO: the error here ought to say there's no component by that name in
-    -- this package, and name the package
+    case p of
+      KnownPackage{pinfoId, pinfoComponents} ->
+        orNoThingIn "package" (display (packageName pinfoId)) $ do
+          c <- matchComponentName pinfoComponents str2
+          return (TargetComponent pinfoId (cinfoName c) WholeComponent)
+        --TODO: the error here ought to say there's no component by that name in
+        -- this package, and name the package
+      KnownPackageName pn ->
+        let cn = mkUnqualComponentName str2 in
+        return (TargetComponentUnknown pn (Left cn) WholeComponent)
   where
     render (TargetComponent p c WholeComponent) =
       [TargetStringFileStatus2 (dispP p) noFileStatus (dispC p c)]
+    render (TargetComponentUnknown pn (Left cn) WholeComponent) =
+      [TargetStringFileStatus2 (dispPN pn) noFileStatus (display cn)]
     render _ = []
 
 -- | Syntax: namespace : component
 --
 -- > cabal build lib:foo exe:foo
 --
-syntaxForm2KindComponent :: [ComponentInfo] -> Syntax
+syntaxForm2KindComponent :: [KnownComponent] -> Syntax
 syntaxForm2KindComponent cs =
   syntaxForm2 render $ \str1 _fstatus1 str2 -> do
     ckind <- matchComponentKind str1
     guardComponentName str2
     c <- matchComponentKindAndName cs ckind str2
-    return (TargetComponent (cinfoPackage c) (cinfoName c) WholeComponent)
+    return (TargetComponent (cinfoPackageId c) (cinfoName c) WholeComponent)
   where
     render (TargetComponent p c WholeComponent) =
-      [TargetStringFileStatus2 (dispK c) noFileStatus (dispC p c)]
+      [TargetStringFileStatus2 (dispCK c) noFileStatus (dispC p c)]
     render _ = []
 
 -- | Syntax: package : module
@@ -1145,16 +1168,22 @@
 -- > cabal build ./foo:Data.Foo
 -- > cabal build ./foo.cabal:Data.Foo
 --
-syntaxForm2PackageModule :: [PackageInfo] -> Syntax
+syntaxForm2PackageModule :: [KnownPackage] -> Syntax
 syntaxForm2PackageModule ps =
   syntaxForm2 render $ \str1 fstatus1 str2 -> do
     guardPackage         str1 fstatus1
     guardModuleName      str2
     p <- matchPackage ps str1 fstatus1
-    orNoThingIn "package" (display (packageName p)) $ do
-      let ms = [ (m,c) | c <- pinfoComponents p, m <- cinfoModules c ]
-      (m,c) <- matchModuleNameAnd ms str2
-      return (TargetComponent p (cinfoName c) (ModuleTarget m))
+    case p of
+      KnownPackage{pinfoId, pinfoComponents} ->
+        orNoThingIn "package" (display (packageName pinfoId)) $ do
+          let ms = [ (m,c) | c <- pinfoComponents, m <- cinfoModules c ]
+          (m,c) <- matchModuleNameAnd ms str2
+          return (TargetComponent pinfoId (cinfoName c) (ModuleTarget m))
+      KnownPackageName pn -> do
+        m <- matchModuleNameUnknown str2
+        -- We assume the primary library component of the package:
+        return (TargetComponentUnknown pn (Right CLibName) (ModuleTarget m))
   where
     render (TargetComponent p _c (ModuleTarget m)) =
       [TargetStringFileStatus2 (dispP p) noFileStatus (dispM m)]
@@ -1164,7 +1193,7 @@
 --
 -- > cabal build foo:Data.Foo
 --
-syntaxForm2ComponentModule :: [ComponentInfo] -> Syntax
+syntaxForm2ComponentModule :: [KnownComponent] -> Syntax
 syntaxForm2ComponentModule cs =
   syntaxForm2 render $ \str1 _fstatus1 str2 -> do
     guardComponentName str1
@@ -1173,7 +1202,7 @@
     orNoThingIn "component" (cinfoStrName c) $ do
       let ms = cinfoModules c
       m <- matchModuleName ms str2
-      return (TargetComponent (cinfoPackage c) (cinfoName c)
+      return (TargetComponent (cinfoPackageId c) (cinfoName c)
                               (ModuleTarget m))
   where
     render (TargetComponent p c (ModuleTarget m)) =
@@ -1186,14 +1215,20 @@
 -- > cabal build ./foo:Data/Foo.hs
 -- > cabal build ./foo.cabal:Data/Foo.hs
 --
-syntaxForm2PackageFile :: [PackageInfo] -> Syntax
+syntaxForm2PackageFile :: [KnownPackage] -> Syntax
 syntaxForm2PackageFile ps =
   syntaxForm2 render $ \str1 fstatus1 str2 -> do
     guardPackage         str1 fstatus1
     p <- matchPackage ps str1 fstatus1
-    orNoThingIn "package" (display (packageName p)) $ do
-      (filepath, c) <- matchComponentFile (pinfoComponents p) str2
-      return (TargetComponent p (cinfoName c) (FileTarget filepath))
+    case p of
+      KnownPackage{pinfoId, pinfoComponents} ->
+        orNoThingIn "package" (display (packageName pinfoId)) $ do
+          (filepath, c) <- matchComponentFile pinfoComponents str2
+          return (TargetComponent pinfoId (cinfoName c) (FileTarget filepath))
+      KnownPackageName pn ->
+        let filepath = str2 in
+        -- We assume the primary library component of the package:
+        return (TargetComponentUnknown pn (Right CLibName) (FileTarget filepath))
   where
     render (TargetComponent p _c (FileTarget f)) =
       [TargetStringFileStatus2 (dispP p) noFileStatus f]
@@ -1203,14 +1238,14 @@
 --
 -- > cabal build foo:Data/Foo.hs
 --
-syntaxForm2ComponentFile :: [ComponentInfo] -> Syntax
+syntaxForm2ComponentFile :: [KnownComponent] -> Syntax
 syntaxForm2ComponentFile cs =
   syntaxForm2 render $ \str1 _fstatus1 str2 -> do
     guardComponentName str1
     c <- matchComponentName cs str1
     orNoThingIn "component" (cinfoStrName c) $ do
       (filepath, _) <- matchComponentFile [c] str2
-      return (TargetComponent (cinfoPackage c) (cinfoName c)
+      return (TargetComponent (cinfoPackageId c) (cinfoName c)
                               (FileTarget filepath))
   where
     render (TargetComponent p c (FileTarget f)) =
@@ -1235,14 +1270,15 @@
       [TargetStringFileStatus3 "" noFileStatus "all" (dispF kfilter)]
     render _ = []
 
-syntaxForm3MetaCwdFilter :: Syntax
-syntaxForm3MetaCwdFilter =
+syntaxForm3MetaCwdFilter :: [KnownPackage] -> Syntax
+syntaxForm3MetaCwdFilter ps =
   syntaxForm3 render $ \str1 _fstatus1 str2 str3 -> do
     guardNamespaceMeta str1
     guardNamespaceCwd str2
     kfilter <- matchComponentKindFilter str3
-    return (TargetPackage TargetImplicitCwd dummyPackageInfo (Just kfilter))
+    return (TargetPackage TargetImplicitCwd pids (Just kfilter))
   where
+    pids = [ pinfoId | KnownPackage{pinfoId} <- ps ]
     render (TargetPackage TargetImplicitCwd _ (Just kfilter)) =
       [TargetStringFileStatus3 "" noFileStatus "cwd" (dispF kfilter)]
     render _ = []
@@ -1251,17 +1287,23 @@
 --
 -- > cabal build :pkg:foo
 --
-syntaxForm3MetaNamespacePackage :: [PackageInfo] -> Syntax
+syntaxForm3MetaNamespacePackage :: [KnownPackage] -> Syntax
 syntaxForm3MetaNamespacePackage pinfo =
   syntaxForm3 render $ \str1 _fstatus1 str2 str3 -> do
     guardNamespaceMeta      str1
     guardNamespacePackage   str2
     guardPackageName        str3
     p <- matchPackage pinfo str3 noFileStatus
-    return (TargetPackage TargetExplicitNamed p Nothing)
+    case p of
+      KnownPackage{pinfoId} ->
+        return (TargetPackage TargetExplicitNamed [pinfoId] Nothing)
+      KnownPackageName pn ->
+        return (TargetPackageNamed pn Nothing)
   where
-    render (TargetPackage TargetExplicitNamed p Nothing) =
+    render (TargetPackage TargetExplicitNamed [p] Nothing) =
       [TargetStringFileStatus3 "" noFileStatus "pkg" (dispP p)]
+    render (TargetPackageNamed pn Nothing) =
+      [TargetStringFileStatus3 "" noFileStatus "pkg" (dispPN pn)]
     render _ = []
 
 -- | Syntax: package : namespace : component
@@ -1270,19 +1312,26 @@
 -- > cabal build foo/:lib:foo
 -- > cabal build foo.cabal:lib:foo
 --
-syntaxForm3PackageKindComponent :: [PackageInfo] -> Syntax
+syntaxForm3PackageKindComponent :: [KnownPackage] -> Syntax
 syntaxForm3PackageKindComponent ps =
   syntaxForm3 render $ \str1 fstatus1 str2 str3 -> do
     guardPackage         str1 fstatus1
     ckind <- matchComponentKind str2
     guardComponentName   str3
     p <- matchPackage ps str1 fstatus1
-    orNoThingIn "package" (display (packageName p)) $ do
-      c <- matchComponentKindAndName (pinfoComponents p) ckind str3
-      return (TargetComponent p (cinfoName c) WholeComponent)
+    case p of
+      KnownPackage{pinfoId, pinfoComponents} ->
+        orNoThingIn "package" (display (packageName pinfoId)) $ do
+          c <- matchComponentKindAndName pinfoComponents ckind str3
+          return (TargetComponent pinfoId (cinfoName c) WholeComponent)
+      KnownPackageName pn ->
+        let cn = mkComponentName pn ckind (mkUnqualComponentName str3) in
+        return (TargetComponentUnknown pn (Right cn) WholeComponent)
   where
     render (TargetComponent p c WholeComponent) =
-      [TargetStringFileStatus3 (dispP p) noFileStatus (dispK c) (dispC p c)]
+      [TargetStringFileStatus3 (dispP p) noFileStatus (dispCK c) (dispC p c)]
+    render (TargetComponentUnknown pn (Right c) WholeComponent) =
+      [TargetStringFileStatus3 (dispPN pn) noFileStatus (dispCK c) (dispC' pn c)]
     render _ = []
 
 -- | Syntax: package : component : module
@@ -1291,29 +1340,37 @@
 -- > cabal build foo/:foo:Data.Foo
 -- > cabal build foo.cabal:foo:Data.Foo
 --
-syntaxForm3PackageComponentModule :: [PackageInfo] -> Syntax
+syntaxForm3PackageComponentModule :: [KnownPackage] -> Syntax
 syntaxForm3PackageComponentModule ps =
   syntaxForm3 render $ \str1 fstatus1 str2 str3 -> do
     guardPackage str1 fstatus1
     guardComponentName str2
     guardModuleName    str3
     p <- matchPackage ps str1 fstatus1
-    orNoThingIn "package" (display (packageName p)) $ do
-      c <- matchComponentName (pinfoComponents p) str2
-      orNoThingIn "component" (cinfoStrName c) $ do
-        let ms = cinfoModules c
-        m <- matchModuleName ms str3
-        return (TargetComponent p (cinfoName c) (ModuleTarget m))
+    case p of
+      KnownPackage{pinfoId, pinfoComponents} ->
+        orNoThingIn "package" (display (packageName pinfoId)) $ do
+          c <- matchComponentName pinfoComponents str2
+          orNoThingIn "component" (cinfoStrName c) $ do
+            let ms = cinfoModules c
+            m <- matchModuleName ms str3
+            return (TargetComponent pinfoId (cinfoName c) (ModuleTarget m))
+      KnownPackageName pn -> do
+        let cn = mkUnqualComponentName  str2
+        m     <- matchModuleNameUnknown str3
+        return (TargetComponentUnknown pn (Left cn) (ModuleTarget m))
   where
     render (TargetComponent p c (ModuleTarget m)) =
       [TargetStringFileStatus3 (dispP p) noFileStatus (dispC p c) (dispM m)]
+    render (TargetComponentUnknown pn (Left c) (ModuleTarget m)) =
+      [TargetStringFileStatus3 (dispPN pn) noFileStatus (dispCN c) (dispM m)]
     render _ = []
 
 -- | Syntax: namespace : component : module
 --
 -- > cabal build lib:foo:Data.Foo
 --
-syntaxForm3KindComponentModule :: [ComponentInfo] -> Syntax
+syntaxForm3KindComponentModule :: [KnownComponent] -> Syntax
 syntaxForm3KindComponentModule cs =
   syntaxForm3 render $ \str1 _fstatus1 str2 str3 -> do
     ckind <- matchComponentKind str1
@@ -1323,11 +1380,11 @@
     orNoThingIn "component" (cinfoStrName c) $ do
       let ms = cinfoModules c
       m <- matchModuleName ms str3
-      return (TargetComponent (cinfoPackage c) (cinfoName c)
+      return (TargetComponent (cinfoPackageId c) (cinfoName c)
                               (ModuleTarget m))
   where
     render (TargetComponent p c (ModuleTarget m)) =
-      [TargetStringFileStatus3 (dispK c) noFileStatus (dispC p c) (dispM m)]
+      [TargetStringFileStatus3 (dispCK c) noFileStatus (dispC p c) (dispM m)]
     render _ = []
 
 -- | Syntax: package : component : filename
@@ -1336,27 +1393,35 @@
 -- > cabal build foo/:foo:Data/Foo.hs
 -- > cabal build foo.cabal:foo:Data/Foo.hs
 --
-syntaxForm3PackageComponentFile :: [PackageInfo] -> Syntax
+syntaxForm3PackageComponentFile :: [KnownPackage] -> Syntax
 syntaxForm3PackageComponentFile ps =
   syntaxForm3 render $ \str1 fstatus1 str2 str3 -> do
     guardPackage         str1 fstatus1
     guardComponentName   str2
     p <- matchPackage ps str1 fstatus1
-    orNoThingIn "package" (display (packageName p)) $ do
-      c <- matchComponentName (pinfoComponents p) str2
-      orNoThingIn "component" (cinfoStrName c) $ do
-        (filepath, _) <- matchComponentFile [c] str3
-        return (TargetComponent p (cinfoName c) (FileTarget filepath))
+    case p of
+      KnownPackage{pinfoId, pinfoComponents} ->
+        orNoThingIn "package" (display (packageName pinfoId)) $ do
+          c <- matchComponentName pinfoComponents str2
+          orNoThingIn "component" (cinfoStrName c) $ do
+            (filepath, _) <- matchComponentFile [c] str3
+            return (TargetComponent pinfoId (cinfoName c) (FileTarget filepath))
+      KnownPackageName pn ->
+        let cn = mkUnqualComponentName str2
+            filepath = str3 in
+        return (TargetComponentUnknown pn (Left cn) (FileTarget filepath))
   where
     render (TargetComponent p c (FileTarget f)) =
       [TargetStringFileStatus3 (dispP p) noFileStatus (dispC p c) f]
+    render (TargetComponentUnknown pn (Left c) (FileTarget f)) =
+      [TargetStringFileStatus3 (dispPN pn) noFileStatus (dispCN c) f]
     render _ = []
 
 -- | Syntax: namespace : component : filename
 --
 -- > cabal build lib:foo:Data/Foo.hs
 --
-syntaxForm3KindComponentFile :: [ComponentInfo] -> Syntax
+syntaxForm3KindComponentFile :: [KnownComponent] -> Syntax
 syntaxForm3KindComponentFile cs =
   syntaxForm3 render $ \str1 _fstatus1 str2 str3 -> do
     ckind <- matchComponentKind str1
@@ -1364,29 +1429,35 @@
     c <- matchComponentKindAndName cs ckind str2
     orNoThingIn "component" (cinfoStrName c) $ do
       (filepath, _) <- matchComponentFile [c] str3
-      return (TargetComponent (cinfoPackage c) (cinfoName c)
+      return (TargetComponent (cinfoPackageId c) (cinfoName c)
                               (FileTarget filepath))
   where
     render (TargetComponent p c (FileTarget f)) =
-      [TargetStringFileStatus3 (dispK c) noFileStatus (dispC p c) f]
+      [TargetStringFileStatus3 (dispCK c) noFileStatus (dispC p c) f]
     render _ = []
 
-syntaxForm3NamespacePackageFilter :: [PackageInfo] -> Syntax
+syntaxForm3NamespacePackageFilter :: [KnownPackage] -> Syntax
 syntaxForm3NamespacePackageFilter ps =
   syntaxForm3 render $ \str1 _fstatus1 str2 str3 -> do
     guardNamespacePackage str1
     guardPackageName      str2
     p <- matchPackage  ps str2 noFileStatus
     kfilter <- matchComponentKindFilter str3
-    return (TargetPackage TargetExplicitNamed p (Just kfilter))
+    case p of
+      KnownPackage{pinfoId} ->
+        return (TargetPackage TargetExplicitNamed [pinfoId] (Just kfilter))
+      KnownPackageName pn ->
+        return (TargetPackageNamed pn (Just kfilter))
   where
-    render (TargetPackage TargetExplicitNamed p (Just kfilter)) =
+    render (TargetPackage TargetExplicitNamed [p] (Just kfilter)) =
       [TargetStringFileStatus3 "pkg" noFileStatus (dispP p) (dispF kfilter)]
+    render (TargetPackageNamed pn (Just kfilter)) =
+      [TargetStringFileStatus3 "pkg" noFileStatus (dispPN pn) (dispF kfilter)]
     render _ = []
 
 --
 
-syntaxForm4MetaNamespacePackageFilter :: [PackageInfo] -> Syntax
+syntaxForm4MetaNamespacePackageFilter :: [KnownPackage] -> Syntax
 syntaxForm4MetaNamespacePackageFilter ps =
   syntaxForm4 render $ \str1 str2 str3 str4 -> do
     guardNamespaceMeta    str1
@@ -1394,17 +1465,23 @@
     guardPackageName      str3
     p <- matchPackage  ps str3 noFileStatus
     kfilter <- matchComponentKindFilter str4
-    return (TargetPackage TargetExplicitNamed p (Just kfilter))
+    case p of
+      KnownPackage{pinfoId} ->
+        return (TargetPackage TargetExplicitNamed [pinfoId] (Just kfilter))
+      KnownPackageName pn ->
+        return (TargetPackageNamed pn (Just kfilter))
   where
-    render (TargetPackage TargetExplicitNamed p (Just kfilter)) =
+    render (TargetPackage TargetExplicitNamed [p] (Just kfilter)) =
       [TargetStringFileStatus4 "" "pkg" (dispP p) (dispF kfilter)]
+    render (TargetPackageNamed pn (Just kfilter)) =
+      [TargetStringFileStatus4 "" "pkg" (dispPN pn) (dispF kfilter)]
     render _ = []
 
 -- | Syntax: :pkg : package : namespace : component
 --
 -- > cabal build :pkg:foo:lib:foo
 --
-syntaxForm5MetaNamespacePackageKindComponent :: [PackageInfo] -> Syntax
+syntaxForm5MetaNamespacePackageKindComponent :: [KnownPackage] -> Syntax
 syntaxForm5MetaNamespacePackageKindComponent ps =
   syntaxForm5 render $ \str1 str2 str3 str4 str5 -> do
     guardNamespaceMeta    str1
@@ -1413,12 +1490,19 @@
     ckind <- matchComponentKind str4
     guardComponentName    str5
     p <- matchPackage  ps str3 noFileStatus
-    orNoThingIn "package" (display (packageName p)) $ do
-      c <- matchComponentKindAndName (pinfoComponents p) ckind str5
-      return (TargetComponent p (cinfoName c) WholeComponent)
+    case p of
+      KnownPackage{pinfoId, pinfoComponents} ->
+        orNoThingIn "package" (display (packageName pinfoId)) $ do
+          c <- matchComponentKindAndName pinfoComponents ckind str5
+          return (TargetComponent pinfoId (cinfoName c) WholeComponent)
+      KnownPackageName pn ->
+        let cn = mkComponentName pn ckind (mkUnqualComponentName str5) in
+        return (TargetComponentUnknown pn (Right cn) WholeComponent)
   where
     render (TargetComponent p c WholeComponent) =
-      [TargetStringFileStatus5 "" "pkg" (dispP p) (dispK c) (dispC p c)]
+      [TargetStringFileStatus5 "" "pkg" (dispP p) (dispCK c) (dispC p c)]
+    render (TargetComponentUnknown pn (Right c) WholeComponent) =
+      [TargetStringFileStatus5 "" "pkg" (dispPN pn) (dispCK c) (dispC' pn c)]
     render _ = []
 
 -- | Syntax: :pkg : package : namespace : component : module : module
@@ -1426,7 +1510,7 @@
 -- > cabal build :pkg:foo:lib:foo:module:Data.Foo
 --
 syntaxForm7MetaNamespacePackageKindComponentNamespaceModule
-  :: [PackageInfo] -> Syntax
+  :: [KnownPackage] -> Syntax
 syntaxForm7MetaNamespacePackageKindComponentNamespaceModule ps =
   syntaxForm7 render $ \str1 str2 str3 str4 str5 str6 str7 -> do
     guardNamespaceMeta    str1
@@ -1436,17 +1520,27 @@
     guardComponentName    str5
     guardNamespaceModule  str6
     p <- matchPackage  ps str3 noFileStatus
-    orNoThingIn "package" (display (packageName p)) $ do
-      c <- matchComponentKindAndName (pinfoComponents p) ckind str5
-      orNoThingIn "component" (cinfoStrName c) $ do
-        let ms = cinfoModules c
-        m <- matchModuleName ms str7
-        return (TargetComponent p (cinfoName c) (ModuleTarget m))
+    case p of
+      KnownPackage{pinfoId, pinfoComponents} ->
+        orNoThingIn "package" (display (packageName pinfoId)) $ do
+          c <- matchComponentKindAndName pinfoComponents ckind str5
+          orNoThingIn "component" (cinfoStrName c) $ do
+            let ms = cinfoModules c
+            m <- matchModuleName ms str7
+            return (TargetComponent pinfoId (cinfoName c) (ModuleTarget m))
+      KnownPackageName pn -> do
+        let cn = mkComponentName pn ckind (mkUnqualComponentName str2)
+        m <- matchModuleNameUnknown str7
+        return (TargetComponentUnknown pn (Right cn) (ModuleTarget m))
   where
     render (TargetComponent p c (ModuleTarget m)) =
       [TargetStringFileStatus7 "" "pkg" (dispP p)
-                               (dispK c) (dispC p c)
+                               (dispCK c) (dispC p c)
                                "module" (dispM m)]
+    render (TargetComponentUnknown pn (Right c) (ModuleTarget m)) =
+      [TargetStringFileStatus7 "" "pkg" (dispPN pn)
+                               (dispCK c) (dispC' pn c)
+                               "module" (dispM m)]
     render _ = []
 
 -- | Syntax: :pkg : package : namespace : component : file : filename
@@ -1454,7 +1548,7 @@
 -- > cabal build :pkg:foo:lib:foo:file:Data/Foo.hs
 --
 syntaxForm7MetaNamespacePackageKindComponentNamespaceFile
-  :: [PackageInfo] -> Syntax
+  :: [KnownPackage] -> Syntax
 syntaxForm7MetaNamespacePackageKindComponentNamespaceFile ps =
   syntaxForm7 render $ \str1 str2 str3 str4 str5 str6 str7 -> do
     guardNamespaceMeta    str1
@@ -1464,16 +1558,26 @@
     guardComponentName    str5
     guardNamespaceFile    str6
     p <- matchPackage  ps str3 noFileStatus
-    orNoThingIn "package" (display (packageName p)) $ do
-      c <- matchComponentKindAndName (pinfoComponents p) ckind str5
-      orNoThingIn "component" (cinfoStrName c) $ do
-        (filepath,_) <- matchComponentFile [c] str7
-        return (TargetComponent p (cinfoName c) (FileTarget filepath))
+    case p of
+      KnownPackage{pinfoId, pinfoComponents} ->
+        orNoThingIn "package" (display (packageName pinfoId)) $ do
+          c <- matchComponentKindAndName pinfoComponents ckind str5
+          orNoThingIn "component" (cinfoStrName c) $ do
+            (filepath,_) <- matchComponentFile [c] str7
+            return (TargetComponent pinfoId (cinfoName c) (FileTarget filepath))
+      KnownPackageName pn ->
+        let cn       = mkComponentName pn ckind (mkUnqualComponentName str5)
+            filepath = str7 in
+        return (TargetComponentUnknown pn (Right cn) (FileTarget filepath))
   where
     render (TargetComponent p c (FileTarget f)) =
       [TargetStringFileStatus7 "" "pkg" (dispP p)
-                               (dispK c) (dispC p c)
+                               (dispCK c) (dispC p c)
                                "file" f]
+    render (TargetComponentUnknown pn (Right c) (FileTarget f)) =
+      [TargetStringFileStatus7 "" "pkg" (dispPN pn)
+                               (dispCK c) (dispC' pn c)
+                               "file" f]
     render _ = []
 
 
@@ -1481,17 +1585,17 @@
 -- Syntax utils
 --
 
-type Match1 = String -> FileStatus -> Match (TargetSelector PackageInfo)
+type Match1 = String -> FileStatus -> Match TargetSelector
 type Match2 = String -> FileStatus -> String
-              -> Match (TargetSelector PackageInfo)
+              -> Match TargetSelector
 type Match3 = String -> FileStatus -> String -> String
-              -> Match (TargetSelector PackageInfo)
+              -> Match TargetSelector
 type Match4 = String -> String -> String -> String
-              -> Match (TargetSelector PackageInfo)
+              -> Match TargetSelector
 type Match5 = String -> String -> String -> String -> String
-              -> Match (TargetSelector PackageInfo)
+              -> Match TargetSelector
 type Match7 = String -> String -> String -> String -> String -> String -> String
-              -> Match (TargetSelector PackageInfo)
+              -> Match TargetSelector
 
 syntaxForm1 :: Renderer -> Match1 -> Syntax
 syntaxForm2 :: Renderer -> Match2 -> Syntax
@@ -1542,12 +1646,24 @@
 dispP :: Package p => p -> String
 dispP = display . packageName
 
-dispC :: Package p => p -> ComponentName -> String
-dispC = componentStringName
+dispPN :: PackageName -> String
+dispPN = display
 
-dispK :: ComponentName -> String
-dispK = showComponentKindShort . componentKind
+dispC :: PackageId -> ComponentName -> String
+dispC = componentStringName . packageName
 
+dispC' :: PackageName -> ComponentName -> String
+dispC' = componentStringName
+
+dispCN :: UnqualComponentName -> String
+dispCN = display
+
+dispK :: ComponentKind -> String
+dispK = showComponentKindShort
+
+dispCK :: ComponentName -> String
+dispCK = dispK . componentKind
+
 dispF :: ComponentKind -> String
 dispF = showComponentKindFilterShort
 
@@ -1559,38 +1675,88 @@
 -- Package and component info
 --
 
-data PackageInfo = PackageInfo {
+data KnownTargets = KnownTargets {
+       knownPackagesAll       :: [KnownPackage],
+       knownPackagesPrimary   :: [KnownPackage],
+       knownPackagesOther     :: [KnownPackage],
+       knownComponentsAll     :: [KnownComponent],
+       knownComponentsPrimary :: [KnownComponent],
+       knownComponentsOther   :: [KnownComponent]
+     }
+  deriving Show
+
+data KnownPackage =
+     KnownPackage {
        pinfoId          :: PackageId,
        pinfoDirectory   :: Maybe (FilePath, FilePath),
        pinfoPackageFile :: Maybe (FilePath, FilePath),
-       pinfoComponents  :: [ComponentInfo]
+       pinfoComponents  :: [KnownComponent]
      }
-  -- not instance of Show due to recursive construction
+   | KnownPackageName {
+       pinfoName        :: PackageName
+     }
+  deriving Show
 
-data ComponentInfo = ComponentInfo {
-       cinfoName    :: ComponentName,
-       cinfoStrName :: ComponentStringName,
-       cinfoPackage :: PackageInfo,
-       cinfoSrcDirs :: [FilePath],
-       cinfoModules :: [ModuleName],
-       cinfoHsFiles :: [FilePath],   -- other hs files (like main.hs)
-       cinfoCFiles  :: [FilePath],
-       cinfoJsFiles :: [FilePath]
+data KnownComponent = KnownComponent {
+       cinfoName      :: ComponentName,
+       cinfoStrName   :: ComponentStringName,
+       cinfoPackageId :: PackageId,
+       cinfoSrcDirs   :: [FilePath],
+       cinfoModules   :: [ModuleName],
+       cinfoHsFiles   :: [FilePath],   -- other hs files (like main.hs)
+       cinfoCFiles    :: [FilePath],
+       cinfoJsFiles   :: [FilePath]
      }
-  -- not instance of Show due to recursive construction
+  deriving Show
 
 type ComponentStringName = String
 
-instance Package PackageInfo where
-  packageId = pinfoId
+knownPackageName :: KnownPackage -> PackageName
+knownPackageName KnownPackage{pinfoId}       = packageName pinfoId
+knownPackageName KnownPackageName{pinfoName} = pinfoName
 
-selectPackageInfo :: (Applicative m, Monad m) => DirActions m
-                  -> SourcePackage (PackageLocation a) -> m PackageInfo
-selectPackageInfo dirActions@DirActions{..}
-                  SourcePackage {
+emptyKnownTargets :: KnownTargets
+emptyKnownTargets = KnownTargets [] [] [] [] [] []
+
+getKnownTargets :: (Applicative m, Monad m)
+                => DirActions m
+                -> [PackageSpecifier (SourcePackage (PackageLocation a))]
+                -> m KnownTargets
+getKnownTargets dirActions@DirActions{..} pkgs = do
+    pinfo <- mapM (collectKnownPackageInfo dirActions) pkgs
+    cwd   <- getCurrentDirectory
+    let (ppinfo, opinfo) = selectPrimaryPackage cwd pinfo
+    return KnownTargets {
+      knownPackagesAll       = pinfo,
+      knownPackagesPrimary   = ppinfo,
+      knownPackagesOther     = opinfo,
+      knownComponentsAll     = allComponentsIn pinfo,
+      knownComponentsPrimary = allComponentsIn ppinfo,
+      knownComponentsOther   = allComponentsIn opinfo
+    }
+  where
+    selectPrimaryPackage :: FilePath
+                         -> [KnownPackage]
+                         -> ([KnownPackage], [KnownPackage])
+    selectPrimaryPackage cwd = partition isPkgDirCwd
+      where
+        isPkgDirCwd KnownPackage { pinfoDirectory = Just (dir,_) }
+          | dir == cwd = True
+        isPkgDirCwd _  = False
+    allComponentsIn ps =
+      [ c | KnownPackage{pinfoComponents} <- ps, c <- pinfoComponents ]
+
+
+collectKnownPackageInfo :: (Applicative m, Monad m) => DirActions m
+                        -> PackageSpecifier (SourcePackage (PackageLocation a))
+                        -> m KnownPackage
+collectKnownPackageInfo _ (NamedPackage pkgname _props) =
+    return (KnownPackageName pkgname)
+collectKnownPackageInfo dirActions@DirActions{..}
+                  (SpecificSourcePackage SourcePackage {
                     packageDescription = pkg,
                     packageSource      = loc
-                  } = do
+                  }) = do
     (pkgdir, pkgfile) <-
       case loc of
         --TODO: local tarballs, remote tarballs etc
@@ -1606,37 +1772,34 @@
                  )
         _ -> return (Nothing, Nothing)
     let pinfo =
-          PackageInfo {
+          KnownPackage {
             pinfoId          = packageId pkg,
             pinfoDirectory   = pkgdir,
             pinfoPackageFile = pkgfile,
-            pinfoComponents  = selectComponentInfo pinfo
+            pinfoComponents  = collectKnownComponentInfo
                                  (flattenPackageDescription pkg)
           }
     return pinfo
 
 
-selectComponentInfo :: PackageInfo -> PackageDescription -> [ComponentInfo]
-selectComponentInfo pinfo pkg =
-    [ ComponentInfo {
-        cinfoName    = componentName c,
-        cinfoStrName = componentStringName pkg (componentName c),
-        cinfoPackage = pinfo,
-        cinfoSrcDirs = ordNub (hsSourceDirs bi),
---                       [ pkgroot </> srcdir
---                       | (pkgroot,_) <- maybeToList (pinfoDirectory pinfo)
---                       , srcdir <- hsSourceDirs bi ],
-        cinfoModules = ordNub (componentModules c),
-        cinfoHsFiles = ordNub (componentHsFiles c),
-        cinfoCFiles  = ordNub (cSources bi),
-        cinfoJsFiles = ordNub (jsSources bi)
+collectKnownComponentInfo :: PackageDescription -> [KnownComponent]
+collectKnownComponentInfo pkg =
+    [ KnownComponent {
+        cinfoName      = componentName c,
+        cinfoStrName   = componentStringName (packageName pkg) (componentName c),
+        cinfoPackageId = packageId pkg,
+        cinfoSrcDirs   = ordNub (hsSourceDirs bi),
+        cinfoModules   = ordNub (componentModules c),
+        cinfoHsFiles   = ordNub (componentHsFiles c),
+        cinfoCFiles    = ordNub (cSources bi),
+        cinfoJsFiles   = ordNub (jsSources bi)
       }
     | c <- pkgComponents pkg
     , let bi = componentBuildInfo c ]
 
 
-componentStringName :: Package pkg => pkg -> ComponentName -> ComponentStringName
-componentStringName pkg CLibName          = display (packageName pkg)
+componentStringName :: PackageName -> ComponentName -> ComponentStringName
+componentStringName pkgname CLibName    = display pkgname
 componentStringName _ (CSubLibName name) = unUnqualComponentName name
 componentStringName _ (CFLibName name)  = unUnqualComponentName name
 componentStringName _ (CExeName   name) = unUnqualComponentName name
@@ -1686,7 +1849,7 @@
 guardNamespaceFile = guardToken ["file"] "'file' namespace"
 
 guardToken :: [String] -> String -> String -> Match ()
-guardToken tokens msg s 
+guardToken tokens msg s
   | caseFold s `elem` tokens = increaseConfidence
   | otherwise                = matchErrorExpected msg s
 
@@ -1703,7 +1866,7 @@
 componentKind (CTestName  _) = TestKind
 componentKind (CBenchName _) = BenchKind
 
-cinfoKind :: ComponentInfo -> ComponentKind
+cinfoKind :: KnownComponent -> ComponentKind
 cinfoKind = componentKind . cinfoName
 
 matchComponentKind :: String -> Match ComponentKind
@@ -1796,25 +1959,32 @@
 guardPackageFile str _ = matchErrorExpected "package .cabal file" str
 
 
-matchPackage :: [PackageInfo] -> String -> FileStatus -> Match PackageInfo
+matchPackage :: [KnownPackage] -> String -> FileStatus -> Match KnownPackage
 matchPackage pinfo = \str fstatus ->
     orNoThingIn "project" "" $
           matchPackageName pinfo str
-    <//> (matchPackageDir  pinfo str fstatus
+    <//> (matchPackageNameUnknown str
+     <|>  matchPackageDir  pinfo str fstatus
      <|>  matchPackageFile pinfo str fstatus)
 
 
-matchPackageName :: [PackageInfo] -> String -> Match PackageInfo
+matchPackageName :: [KnownPackage] -> String -> Match KnownPackage
 matchPackageName ps = \str -> do
     guard (validPackageName str)
     orNoSuchThing "package" str
-                  (map (display . packageName) ps) $
+                  (map (display . knownPackageName) ps) $
       increaseConfidenceFor $
-        matchInexactly caseFold (display . packageName) ps str
+        matchInexactly caseFold (display . knownPackageName) ps str
 
 
-matchPackageDir :: [PackageInfo]
-                -> String -> FileStatus -> Match PackageInfo
+matchPackageNameUnknown :: String -> Match KnownPackage
+matchPackageNameUnknown str = do
+    pn <- matchParse str
+    unknownMatch (KnownPackageName pn)
+
+
+matchPackageDir :: [KnownPackage]
+                -> String -> FileStatus -> Match KnownPackage
 matchPackageDir ps = \str fstatus ->
     case fstatus of
       FileStatusExistsDir canondir ->
@@ -1824,10 +1994,10 @@
       _ -> mzero
   where
     dirs = [ ((dabs,drel),p)
-           | p@PackageInfo{ pinfoDirectory = Just (dabs,drel) } <- ps ]
+           | p@KnownPackage{ pinfoDirectory = Just (dabs,drel) } <- ps ]
 
 
-matchPackageFile :: [PackageInfo] -> String -> FileStatus -> Match PackageInfo
+matchPackageFile :: [KnownPackage] -> String -> FileStatus -> Match KnownPackage
 matchPackageFile ps = \str fstatus -> do
     case fstatus of
       FileStatusExistsFile canonfile ->
@@ -1837,7 +2007,7 @@
       _ -> mzero
   where
     files = [ ((fabs,frel),p)
-            | p@PackageInfo{ pinfoPackageFile = Just (fabs,frel) } <- ps ]
+            | p@KnownPackage{ pinfoPackageFile = Just (fabs,frel) } <- ps ]
 
 --TODO: test outcome when dir exists but doesn't match any known one
 
@@ -1860,15 +2030,15 @@
                         || c == '_' || c == '-' || c == '\''
 
 
-matchComponentName :: [ComponentInfo] -> String -> Match ComponentInfo
+matchComponentName :: [KnownComponent] -> String -> Match KnownComponent
 matchComponentName cs str =
     orNoSuchThing "component" str (map cinfoStrName cs)
   $ increaseConfidenceFor
   $ matchInexactly caseFold cinfoStrName cs str
 
 
-matchComponentKindAndName :: [ComponentInfo] -> ComponentKind -> String
-                          -> Match ComponentInfo
+matchComponentKindAndName :: [KnownComponent] -> ComponentKind -> String
+                          -> Match KnownComponent
 matchComponentKindAndName cs ckind str =
     orNoSuchThing (showComponentKind ckind ++ " component") str
                   (map render cs)
@@ -1910,31 +2080,38 @@
   $ matchInexactly caseFold (display . fst) ms str
 
 
+matchModuleNameUnknown :: String -> Match ModuleName
+matchModuleNameUnknown str =
+    expecting "module" str
+  $ increaseConfidenceFor
+  $ matchParse str
+
+
 ------------------------------
 -- Matching file targets
 --
 
-matchPackageDirectoryPrefix :: [PackageInfo] -> FileStatus
-                            -> Match (FilePath, PackageInfo)
+matchPackageDirectoryPrefix :: [KnownPackage] -> FileStatus
+                            -> Match (FilePath, KnownPackage)
 matchPackageDirectoryPrefix ps (FileStatusExistsFile filepath) =
     increaseConfidenceFor $
       matchDirectoryPrefix pkgdirs filepath
   where
     pkgdirs = [ (dir, p)
-              | p@PackageInfo { pinfoDirectory = Just (dir,_) } <- ps ]
+              | p@KnownPackage { pinfoDirectory = Just (dir,_) } <- ps ]
 matchPackageDirectoryPrefix _ _ = mzero
 
 
-matchComponentFile :: [ComponentInfo] -> String
-                   -> Match (FilePath, ComponentInfo)
+matchComponentFile :: [KnownComponent] -> String
+                   -> Match (FilePath, KnownComponent)
 matchComponentFile cs str =
     orNoSuchThing "file" str [] $
         matchComponentModuleFile cs str
     <|> matchComponentOtherFile  cs str
 
 
-matchComponentOtherFile :: [ComponentInfo] -> String
-                        -> Match (FilePath, ComponentInfo)
+matchComponentOtherFile :: [KnownComponent] -> String
+                        -> Match (FilePath, KnownComponent)
 matchComponentOtherFile cs =
     matchFile
       [ (file, c)
@@ -1945,8 +2122,8 @@
       ]
 
 
-matchComponentModuleFile :: [ComponentInfo] -> String
-                         -> Match (FilePath, ComponentInfo)
+matchComponentModuleFile :: [KnownComponent] -> String
+                         -> Match (FilePath, KnownComponent)
 matchComponentModuleFile cs str = do
     matchFile
       [ (normalise (d </> toFilePath m), c)
@@ -1988,11 +2165,22 @@
 -- ways to combine matchers ('matchPlus', 'matchPlusShadowing') and finally we
 -- can run a matcher against an input using 'findMatch'.
 --
-data Match a = NoMatch      Confidence [MatchError]
-             | ExactMatch   Confidence [a]
-             | InexactMatch Confidence [a]
+data Match a = NoMatch           !Confidence [MatchError]
+             | Match !MatchClass !Confidence [a]
   deriving Show
 
+-- | The kind of match, inexact or exact. We keep track of this so we can
+-- prefer exact over inexact matches. The 'Ord' here is important: we try
+-- to maximise this, so 'Exact' is the top value and 'Inexact' the bottom.
+--
+data MatchClass = Unknown -- ^ Matches an unknown thing e.g. parses as a package
+                          --   name without it being a specific known package
+                | Inexact -- ^ Matches a known thing inexactly
+                          --   e.g. matches a known package case insensitively
+                | Exact   -- ^ Exactly matches a known thing,
+                          --   e.g. matches a known package case sensitively
+  deriving (Show, Eq, Ord)
+
 type Confidence = Int
 
 data MatchError = MatchErrorExpected String String            -- thing got
@@ -2002,12 +2190,11 @@
 
 
 instance Functor Match where
-    fmap _ (NoMatch      d ms) = NoMatch      d ms
-    fmap f (ExactMatch   d xs) = ExactMatch   d (fmap f xs)
-    fmap f (InexactMatch d xs) = InexactMatch d (fmap f xs)
+    fmap _ (NoMatch d ms) = NoMatch d ms
+    fmap f (Match m d xs) = Match m d (fmap f xs)
 
 instance Applicative Match where
-    pure a = ExactMatch 0 [a]
+    pure a = Match Exact 0 [a]
     (<*>)  = ap
 
 instance Alternative Match where
@@ -2015,13 +2202,20 @@
     (<|>) = matchPlus
 
 instance Monad Match where
-    return                  = pure
-    NoMatch      d ms >>= _ = NoMatch d ms
-    ExactMatch   d xs >>= f = addDepth d
-                            $ msum (map f xs)
-    InexactMatch d xs >>= f = addDepth d . forceInexact
-                            $ msum (map f xs)
+    return             = pure
+    NoMatch d ms >>= _ = NoMatch d ms
+    Match m d xs >>= f =
+      -- To understand this, it needs to be read in context with the
+      -- implementation of 'matchPlus' below
+      case msum (map f xs) of
+        Match m' d' xs' -> Match (min m m') (d + d') xs'
+        -- The minimum match class is the one we keep. The match depth is
+        -- tracked but not used in the Match case.
 
+        NoMatch  d' ms  -> NoMatch          (d + d') ms
+        -- Here is where we transfer the depth we were keeping track of in
+        -- the Match case over to the NoMatch case where it finally gets used.
+
 instance MonadPlus Match where
     mzero = empty
     mplus = matchPlus
@@ -2031,15 +2225,6 @@
 
 infixl 3 <//>
 
-addDepth :: Confidence -> Match a -> Match a
-addDepth d' (NoMatch      d msgs) = NoMatch      (d'+d) msgs
-addDepth d' (ExactMatch   d xs)   = ExactMatch   (d'+d) xs
-addDepth d' (InexactMatch d xs)   = InexactMatch (d'+d) xs
-
-forceInexact :: Match a -> Match a
-forceInexact (ExactMatch d ys) = InexactMatch d ys
-forceInexact m                 = m
-
 -- | Combine two matchers. Exact matches are used over inexact matches
 -- but if we have multiple exact, or inexact then the we collect all the
 -- ambiguous matches.
@@ -2047,20 +2232,16 @@
 -- This operator is associative, has unit 'mzero' and is also commutative.
 --
 matchPlus :: Match a -> Match a -> Match a
-matchPlus   (ExactMatch   d1 xs)   (ExactMatch   d2 xs') =
-  ExactMatch (max d1 d2) (xs ++ xs')
-matchPlus a@(ExactMatch   _  _ )   (InexactMatch _  _  ) = a
-matchPlus a@(ExactMatch   _  _ )   (NoMatch      _  _  ) = a
-matchPlus   (InexactMatch _  _ ) b@(ExactMatch   _  _  ) = b
-matchPlus   (InexactMatch d1 xs)   (InexactMatch d2 xs') =
-  InexactMatch (max d1 d2) (xs ++ xs')
-matchPlus a@(InexactMatch _  _ )   (NoMatch      _  _  ) = a
-matchPlus   (NoMatch      _  _ ) b@(ExactMatch   _  _  ) = b
-matchPlus   (NoMatch      _  _ ) b@(InexactMatch _  _  ) = b
-matchPlus a@(NoMatch      d1 ms) b@(NoMatch      d2 ms')
-                                             | d1 >  d2  = a
-                                             | d1 <  d2  = b
-                                             | otherwise = NoMatch d1 (ms ++ ms')
+matchPlus a@(Match _ _ _ )   (NoMatch _ _) = a
+matchPlus   (NoMatch _ _ ) b@(Match _ _ _) = b
+matchPlus a@(NoMatch d_a ms_a) b@(NoMatch d_b ms_b)
+  | d_a > d_b = a  -- We only really make use of the depth in the NoMatch case.
+  | d_a < d_b = b
+  | otherwise = NoMatch d_a (ms_a ++ ms_b)
+matchPlus a@(Match m_a d_a xs_a) b@(Match m_b d_b xs_b)
+  | m_a > m_b = a  -- exact over inexact
+  | m_a < m_b = b  -- exact over inexact
+  | otherwise = Match m_a (max d_a d_b) (xs_a ++ xs_b)
 
 -- | Combine two matchers. This is similar to 'matchPlus' with the
 -- difference that an exact match from the left matcher shadows any exact
@@ -2069,7 +2250,7 @@
 -- This operator is associative, has unit 'mzero' and is not commutative.
 --
 matchPlusShadowing :: Match a -> Match a -> Match a
-matchPlusShadowing a@(ExactMatch _ _)  _ = a
+matchPlusShadowing a@(Match Exact _ _) _ = a
 matchPlusShadowing a                   b = matchPlus a b
 
 
@@ -2097,26 +2278,28 @@
 orNoThingIn _ _ m = m
 
 increaseConfidence :: Match ()
-increaseConfidence = ExactMatch 1 [()]
+increaseConfidence = Match Exact 1 [()]
 
 increaseConfidenceFor :: Match a -> Match a
 increaseConfidenceFor m = m >>= \r -> increaseConfidence >> return r
 
 nubMatchesBy :: (a -> a -> Bool) -> Match a -> Match a
-nubMatchesBy _  (NoMatch      d msgs) = NoMatch      d msgs
-nubMatchesBy eq (ExactMatch   d xs)   = ExactMatch   d (nubBy eq xs)
-nubMatchesBy eq (InexactMatch d xs)   = InexactMatch d (nubBy eq xs)
+nubMatchesBy _  (NoMatch d msgs) = NoMatch d msgs
+nubMatchesBy eq (Match m d xs)   = Match m d (nubBy eq xs)
 
 -- | Lift a list of matches to an exact match.
 --
 exactMatches, inexactMatches :: [a] -> Match a
 
 exactMatches [] = mzero
-exactMatches xs = ExactMatch 0 xs
+exactMatches xs = Match Exact 0 xs
 
 inexactMatches [] = mzero
-inexactMatches xs = InexactMatch 0 xs
+inexactMatches xs = Match Inexact 0 xs
 
+unknownMatch :: a -> Match a
+unknownMatch x = Match Unknown 0 [x]
+
 tryEach :: [a] -> Match a
 tryEach = exactMatches
 
@@ -2131,15 +2314,18 @@
 --
 findMatch :: Match a -> MaybeAmbiguous a
 findMatch match = case match of
-  NoMatch    _ msgs  -> None msgs
-  ExactMatch   _ [x] -> Unambiguous x
-  InexactMatch _ [x] -> Unambiguous x
-  ExactMatch   _  [] -> error "findMatch: impossible: ExactMatch []"
-  InexactMatch _  [] -> error "findMatch: impossible: InexactMatch []"
-  ExactMatch   _  xs -> Ambiguous True  xs
-  InexactMatch _  xs -> Ambiguous False xs
+  NoMatch _ msgs -> None msgs
+  Match _ _  [x] -> Unambiguous x
+  Match m d   [] -> error $ "findMatch: impossible: " ++ show match'
+                      where match' = Match m d [] :: Match ()
+                    -- TODO: Maybe use Data.List.NonEmpty inside
+                    -- Match so that this case would be correct
+                    -- by construction?
+  Match m _   xs -> Ambiguous m xs
 
-data MaybeAmbiguous a = None [MatchError] | Unambiguous a | Ambiguous Bool [a]
+data MaybeAmbiguous a = None [MatchError]
+                      | Unambiguous a
+                      | Ambiguous MatchClass [a]
   deriving Show
 
 
@@ -2181,7 +2367,10 @@
     -- the map of canonicalised keys to groups of inexact matches
     m' = Map.mapKeysWith (++) cannonicalise m
 
+matchParse :: Text a => String -> Match a
+matchParse = maybe mzero return . simpleParse
 
+
 ------------------------------
 -- Utils
 --
@@ -2189,22 +2378,41 @@
 caseFold :: String -> String
 caseFold = lowercase
 
+-- | Make a 'ComponentName' given an 'UnqualComponentName' and knowing the
+-- 'ComponentKind'. We also need the 'PackageName' to distinguish the package's
+-- primary library from named private libraries.
+--
+mkComponentName :: PackageName
+                -> ComponentKind
+                -> UnqualComponentName
+                -> ComponentName
+mkComponentName pkgname ckind ucname =
+  case ckind of
+    LibKind
+      | packageNameToUnqualComponentName pkgname == ucname
+                  -> CLibName
+      | otherwise -> CSubLibName ucname
+    FLibKind      -> CFLibName   ucname
+    ExeKind       -> CExeName    ucname
+    TestKind      -> CTestName   ucname
+    BenchKind     -> CBenchName  ucname
 
+
 ------------------------------
 -- Example inputs
 --
 
 {-
-ex1pinfo :: [PackageInfo]
+ex1pinfo :: [KnownPackage]
 ex1pinfo =
   [ addComponent (CExeName (mkUnqualComponentName "foo-exe")) [] ["Data.Foo"] $
-    PackageInfo {
+    KnownPackage {
       pinfoId          = PackageIdentifier (mkPackageName "foo") (mkVersion [1]),
       pinfoDirectory   = Just ("/the/foo", "foo"),
       pinfoPackageFile = Just ("/the/foo/foo.cabal", "foo/foo.cabal"),
       pinfoComponents  = []
     }
-  , PackageInfo {
+  , KnownPackage {
       pinfoId          = PackageIdentifier (mkPackageName "bar") (mkVersion [1]),
       pinfoDirectory   = Just ("/the/bar", "bar"),
       pinfoPackageFile = Just ("/the/bar/bar.cabal", "bar/bar.cabal"),
@@ -2215,7 +2423,7 @@
     addComponent n ds ms p =
       p {
         pinfoComponents =
-            ComponentInfo n (componentStringName (pinfoId p) n)
+            KnownComponent n (componentStringName (pinfoId p) n)
                           p ds (map mkMn ms)
                           [] [] []
           : pinfoComponents p
@@ -2239,13 +2447,13 @@
 -}
 
 {-
-ex_cs :: [ComponentInfo]
+ex_cs :: [KnownComponent]
 ex_cs =
   [ (mkC (CExeName "foo") ["src1", "src1/src2"] ["Foo", "Src2.Bar", "Bar"])
   , (mkC (CExeName "tst") ["src1", "test"]      ["Foo"])
   ]
     where
-    mkC n ds ms = ComponentInfo n (componentStringName n) ds (map mkMn ms)
+    mkC n ds ms = KnownComponent n (componentStringName n) ds (map mkMn ms)
     mkMn :: String -> ModuleName
     mkMn  = fromJust . simpleParse
     pkgid :: PackageIdentifier
diff --git a/cabal/cabal-install/Distribution/Client/Targets.hs b/cabal/cabal-install/Distribution/Client/Targets.hs
--- a/cabal/cabal-install/Distribution/Client/Targets.hs
+++ b/cabal/cabal-install/Distribution/Client/Targets.hs
@@ -455,6 +455,14 @@
         error "TODO: readPackageTarget RepoTarballPackage"
         -- For repo tarballs this info should be obtained from the index.
 
+      RemoteSourceRepoPackage _srcRepo _ ->
+        error "TODO: readPackageTarget RemoteSourceRepoPackage"
+        -- This can't happen, because it would have errored out already
+        -- in fetchPackage, via fetchPackageTarget before it gets to this
+        -- function.
+        --
+        -- When that is corrected, this will also need to be fixed.
+
     readTarballPackageTarget location tarballFile tarballOriginalLoc = do
       (filename, content) <- extractTarballPackageCabalFile
                                tarballFile tarballOriginalLoc
diff --git a/cabal/cabal-install/Distribution/Client/Types.hs b/cabal/cabal-install/Distribution/Client/Types.hs
--- a/cabal/cabal-install/Distribution/Client/Types.hs
+++ b/cabal/cabal-install/Distribution/Client/Types.hs
@@ -46,6 +46,8 @@
          ( PackageName, mkPackageName )
 import Distribution.Types.ComponentName
          ( ComponentName(..) )
+import Distribution.Types.SourceRepo
+         ( SourceRepo )
 
 import Distribution.Solver.Types.PackageIndex
          ( PackageIndex )
@@ -147,11 +149,11 @@
 
 -- | A ConfiguredId is a package ID for a configured package.
 --
--- Once we configure a source package we know it's UnitId. It is still
+-- Once we configure a source package we know its UnitId. It is still
 -- however useful in lots of places to also know the source ID for the package.
 -- We therefore bundle the two.
 --
--- An already installed package of course is also "configured" (all it's
+-- An already installed package of course is also "configured" (all its
 -- configuration parameters and dependencies have been specified).
 data ConfiguredId = ConfiguredId {
     confSrcId  :: PackageId
@@ -234,7 +236,7 @@
      -- | A fully specified source package.
      --
    | SpecificSourcePackage pkg
-  deriving (Eq, Show, Generic)
+  deriving (Eq, Show, Functor, Generic)
 
 instance Binary pkg => Binary (PackageSpecifier pkg)
 
@@ -282,9 +284,8 @@
     -- locally cached copy. ie a package available from hackage
   | RepoTarballPackage Repo PackageId local
 
---TODO:
---  * add support for darcs and other SCM style remote repos with a local cache
---  | ScmPackage
+    -- | A package available from a version control system source repository
+  | RemoteSourceRepoPackage SourceRepo local
   deriving (Show, Functor, Eq, Ord, Generic, Typeable)
 
 instance Binary local => Binary (PackageLocation local)
@@ -588,3 +589,19 @@
 instance Monoid AllowOlder where
   mempty  = AllowOlder mempty
   mappend = (<>)
+
+-- ------------------------------------------------------------
+-- * --write-ghc-environment-file
+-- ------------------------------------------------------------
+
+-- | Whether 'v2-build' should write a .ghc.environment file after
+-- success. Possible values: 'always', 'never', 'ghc8.4.4+' (the
+-- default; GHC 8.4.4 is the earliest version that supports
+-- '-package-env -').
+data WriteGhcEnvironmentFilesPolicy
+  = AlwaysWriteGhcEnvironmentFiles
+  | NeverWriteGhcEnvironmentFiles
+  | WriteGhcEnvironmentFilesOnlyForGhc844AndNewer
+  deriving (Eq, Enum, Bounded, Generic, Show)
+
+instance Binary WriteGhcEnvironmentFilesPolicy
diff --git a/cabal/cabal-install/Distribution/Client/Update.hs b/cabal/cabal-install/Distribution/Client/Update.hs
--- a/cabal/cabal-install/Distribution/Client/Update.hs
+++ b/cabal/cabal-install/Distribution/Client/Update.hs
@@ -17,6 +17,8 @@
 
 import Distribution.Simple.Setup
          ( fromFlag )
+import Distribution.Client.Compat.Directory
+         ( setModificationTime )
 import Distribution.Client.Types
          ( Repo(..), RemoteRepo(..), maybeRepoRemote )
 import Distribution.Client.HttpUtils
@@ -26,7 +28,7 @@
 import Distribution.Client.IndexUtils.Timestamp
 import Distribution.Client.IndexUtils
          ( updateRepoIndexCache, Index(..), writeIndexTimestamp
-         , currentIndexTimestamp )
+         , currentIndexTimestamp, indexBaseName )
 import Distribution.Client.JobControl
          ( newParallelJobControl, spawnJob, collectJob )
 import Distribution.Client.Setup
@@ -40,7 +42,7 @@
 
 import qualified Data.ByteString.Lazy       as BS
 import Distribution.Client.GZipUtils (maybeDecompress)
-import System.FilePath (dropExtension)
+import System.FilePath ((<.>), dropExtension)
 import Data.Maybe (mapMaybe)
 import Data.Time (getCurrentTime)
 import Control.Monad
@@ -75,7 +77,8 @@
     RepoRemote{..} -> do
       downloadResult <- downloadIndex transport verbosity repoRemote repoLocalDir
       case downloadResult of
-        FileAlreadyInCache -> return ()
+        FileAlreadyInCache ->
+          setModificationTime (indexBaseName repo <.> "tar") =<< getCurrentTime
         FileDownloaded indexPath -> do
           writeFileAtomic (dropExtension indexPath) . maybeDecompress
                                                   =<< BS.readFile indexPath
@@ -95,7 +98,7 @@
       -- (If all access to the cache goes through hackage-security this can go)
       case updated of
         Sec.NoUpdates  ->
-          return ()
+          setModificationTime (indexBaseName repo <.> "tar") =<< getCurrentTime
         Sec.HasUpdates ->
           updateRepoIndexCache verbosity index
       -- TODO: This will print multiple times if there are multiple
diff --git a/cabal/cabal-install/Distribution/Client/Upload.hs b/cabal/cabal-install/Distribution/Client/Upload.hs
--- a/cabal/cabal-install/Distribution/Client/Upload.hs
+++ b/cabal/cabal-install/Distribution/Client/Upload.hs
@@ -172,7 +172,7 @@
       repos       = repoContextRepos repoCtxt
       remoteRepos = mapMaybe maybeRepoRemote repos
   forM_ remoteRepos $ \remoteRepo ->
-      do dotCabal <- defaultCabalDir
+      do dotCabal <- getCabalDir
          let srcDir = dotCabal </> "reports" </> remoteRepoName remoteRepo
          -- We don't want to bomb out just because we haven't built any packages
          -- from this repo yet.
diff --git a/cabal/cabal-install/Distribution/Client/Utils.hs b/cabal/cabal-install/Distribution/Client/Utils.hs
--- a/cabal/cabal-install/Distribution/Client/Utils.hs
+++ b/cabal/cabal-install/Distribution/Client/Utils.hs
@@ -3,8 +3,8 @@
 module Distribution.Client.Utils ( MergeResult(..)
                                  , mergeBy, duplicates, duplicatesBy
                                  , readMaybe
-                                 , inDir, withEnv, logDirChange
-                                 , withExtraPathEnv
+                                 , inDir, withEnv, withEnvOverrides
+                                 , logDirChange, withExtraPathEnv
                                  , determineNumJobs, numberOfProcessors
                                  , removeExistingFile
                                  , withTempFileName
@@ -17,7 +17,9 @@
                                  , moreRecentFile, existsAndIsMoreRecentThan
                                  , tryFindAddSourcePackageDesc
                                  , tryFindPackageDesc
-                                 , relaxEncodingErrors)
+                                 , relaxEncodingErrors
+                                 , ProgressPhase (..)
+                                 , progressMessage)
        where
 
 import Prelude ()
@@ -28,11 +30,13 @@
 import Distribution.Compat.Time ( getModTime )
 import Distribution.Simple.Setup       ( Flag(..) )
 import Distribution.Verbosity
-import Distribution.Simple.Utils       ( die', findPackageDesc )
+import Distribution.Simple.Utils       ( die', findPackageDesc, noticeNoWrap )
 import qualified Data.ByteString.Lazy as BS
 import Data.Bits
          ( (.|.), shiftL, shiftR )
 import System.FilePath
+import Control.Monad
+         ( mapM, mapM_, zipWithM_ )
 import Data.List
          ( groupBy )
 import Foreign.C.Types ( CInt(..) )
@@ -43,18 +47,14 @@
          , removeFile, setCurrentDirectory )
 import System.IO
          ( Handle, hClose, openTempFile
-#if MIN_VERSION_base(4,4,0)
          , hGetEncoding, hSetEncoding
-#endif
          )
 import System.IO.Unsafe ( unsafePerformIO )
 
-#if MIN_VERSION_base(4,4,0)
 import GHC.IO.Encoding
          ( recover, TextEncoding(TextEncoding) )
 import GHC.IO.Encoding.Failure
          ( recoverEncode, CodingFailureMode(TransliterateCodingFailure) )
-#endif
 
 #if defined(mingw32_HOST_OS) || MIN_VERSION_directory(1,2,3)
 import qualified System.Directory as Dir
@@ -133,6 +133,27 @@
     Nothing -> unsetEnv k
     Just old -> setEnv k old)
 
+-- | Executes the action with a list of environment variables and
+-- corresponding overrides, where
+--
+-- * @'Just' v@ means \"set the environment variable's value to @v@\".
+-- * 'Nothing' means \"unset the environment variable\".
+--
+-- Warning: This operation is NOT thread-safe, because current
+-- environment is a process-global concept.
+withEnvOverrides :: [(String, Maybe FilePath)] -> IO a -> IO a
+withEnvOverrides overrides m = do
+  mb_olds <- mapM lookupEnv envVars
+  mapM_ (uncurry update) overrides
+  m `Exception.finally` zipWithM_ update envVars mb_olds
+   where
+    envVars :: [String]
+    envVars = map fst overrides
+
+    update :: String -> Maybe FilePath -> IO ()
+    update var Nothing    = unsetEnv var
+    update var (Just val) = setEnv var val
+
 -- | Executes the action, increasing the PATH environment
 -- in some way
 --
@@ -288,14 +309,12 @@
 -- set. It's a no-op for versions of `base` less than 4.4.
 relaxEncodingErrors :: Handle -> IO ()
 relaxEncodingErrors handle = do
-#if MIN_VERSION_base(4,4,0)
   maybeEncoding <- hGetEncoding handle
   case maybeEncoding of
     Just (TextEncoding name decoder encoder) | not ("UTF" `isPrefixOf` name) ->
       let relax x = x { recover = recoverEncode TransliterateCodingFailure }
       in hSetEncoding handle (TextEncoding name decoder (fmap relax encoder))
     _ ->
-#endif
       return ()
 
 -- |Like 'tryFindPackageDesc', but with error specific to add-source deps.
@@ -313,3 +332,27 @@
     case errOrCabalFile of
         Right file -> return file
         Left _ -> die' verbosity err
+
+-- | Phase of building a dependency. Represents current status of package
+-- dependency processing. See #4040 for details.
+data ProgressPhase
+    = ProgressDownloading
+    | ProgressDownloaded
+    | ProgressStarting
+    | ProgressBuilding
+    | ProgressHaddock
+    | ProgressInstalling
+    | ProgressCompleted
+
+progressMessage :: Verbosity -> ProgressPhase -> String -> IO ()
+progressMessage verbosity phase subject = do
+    noticeNoWrap verbosity $ phaseStr ++ subject ++ "\n"
+  where
+    phaseStr = case phase of
+        ProgressDownloading -> "Downloading  "
+        ProgressDownloaded  -> "Downloaded   "
+        ProgressStarting    -> "Starting     "
+        ProgressBuilding    -> "Building     "
+        ProgressHaddock     -> "Haddock      "
+        ProgressInstalling  -> "Installing   "
+        ProgressCompleted   -> "Completed    "
diff --git a/cabal/cabal-install/Distribution/Client/VCS.hs b/cabal/cabal-install/Distribution/Client/VCS.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/Distribution/Client/VCS.hs
@@ -0,0 +1,518 @@
+{-# LANGUAGE NamedFieldPuns, RecordWildCards #-}
+module Distribution.Client.VCS (
+    -- * VCS driver type
+    VCS,
+    vcsRepoType,
+    vcsProgram,
+    -- ** Type re-exports
+    SourceRepo,
+    RepoType,
+    RepoKind,
+    Program,
+    ConfiguredProgram,
+
+    -- * Selecting amongst source repos
+    selectPackageSourceRepo,
+
+    -- * Validating 'SourceRepo's and configuring VCS drivers
+    validateSourceRepo,
+    validateSourceRepos,
+    SourceRepoProblem(..),
+    configureVCS,
+    configureVCSs,
+
+    -- * Running the VCS driver
+    cloneSourceRepo,
+    syncSourceRepos,
+
+    -- * The individual VCS drivers
+    knownVCSs,
+    vcsBzr,
+    vcsDarcs,
+    vcsGit,
+    vcsHg,
+    vcsSvn,
+  ) where
+
+import Prelude ()
+import Distribution.Client.Compat.Prelude
+
+import Distribution.Types.SourceRepo
+         ( SourceRepo(..), RepoType(..), RepoKind(..) )
+import Distribution.Client.RebuildMonad
+         ( Rebuild, monitorFiles, MonitorFilePath, monitorDirectoryExistence )
+import Distribution.Verbosity as Verbosity
+         ( Verbosity, normal )
+import Distribution.Simple.Program
+         ( Program(programFindVersion)
+         , ConfiguredProgram(programVersion)
+         , simpleProgram, findProgramVersion
+         , ProgramInvocation(..), programInvocation, runProgramInvocation
+         , emptyProgramDb, requireProgram )
+import Distribution.Version
+         ( mkVersion )
+
+import Control.Monad
+         ( mapM_ )
+import Control.Monad.Trans
+         ( liftIO )
+import qualified Data.Char as Char
+import qualified Data.Map  as Map
+import Data.Ord
+         ( comparing )
+import Data.Either
+         ( partitionEithers )
+import System.FilePath
+         ( takeDirectory )
+import System.Directory
+         ( doesDirectoryExist )
+
+
+-- | A driver for a version control system, e.g. git, darcs etc.
+--
+data VCS program = VCS {
+       -- | The type of repository this driver is for.
+       vcsRepoType  :: RepoType,
+
+       -- | The vcs program itself.
+       -- This is used at type 'Program' and 'ConfiguredProgram'.
+       vcsProgram   :: program,
+
+       -- | The program invocation(s) to get\/clone a repository into a fresh
+       -- local directory.
+       vcsCloneRepo :: Verbosity
+                    -> ConfiguredProgram
+                    -> SourceRepo
+                    -> FilePath   -- Source URI
+                    -> FilePath   -- Destination directory
+                    -> [ProgramInvocation],
+
+       -- | The program invocation(s) to synchronise a whole set of /related/
+       -- repositories with corresponding local directories. Also returns the
+       -- files that the command depends on, for change monitoring.
+       vcsSyncRepos :: Verbosity
+                    -> ConfiguredProgram
+                    -> [(SourceRepo, FilePath)]
+                    -> IO [MonitorFilePath]
+     }
+
+
+-- ------------------------------------------------------------
+-- * Selecting repos and drivers
+-- ------------------------------------------------------------
+
+-- | Pick the 'SourceRepo' to use to get the package sources from.
+--
+-- Note that this does /not/ depend on what 'VCS' drivers we are able to
+-- successfully configure. It is based only on the 'SourceRepo's declared
+-- in the package, and optionally on a preferred 'RepoKind'.
+--
+selectPackageSourceRepo :: Maybe RepoKind
+                        -> [SourceRepo]
+                        -> Maybe SourceRepo
+selectPackageSourceRepo preferredRepoKind =
+    listToMaybe
+    -- Sort repositories by kind, from This to Head to Unknown. Repositories
+    -- with equivalent kinds are selected based on the order they appear in
+    -- the Cabal description file.
+  . sortBy (comparing thisFirst)
+    -- If the user has specified the repo kind, filter out the repositories
+    -- they're not interested in.
+  . filter (\repo -> maybe True (repoKind repo ==) preferredRepoKind)
+  where
+    thisFirst :: SourceRepo -> Int
+    thisFirst r = case repoKind r of
+        RepoThis -> 0
+        RepoHead -> case repoTag r of
+            -- If the type is 'head' but the author specified a tag, they
+            -- probably meant to create a 'this' repository but screwed up.
+            Just _  -> 0
+            Nothing -> 1
+        RepoKindUnknown _ -> 2
+
+data SourceRepoProblem = SourceRepoRepoTypeUnspecified
+                       | SourceRepoRepoTypeUnsupported RepoType
+                       | SourceRepoLocationUnspecified
+  deriving Show
+
+-- | Validates that the 'SourceRepo' specifies a location URI and a repository
+-- type that is supported by a VCS driver.
+--
+-- | It also returns the 'VCS' driver we should use to work with it.
+--
+validateSourceRepo :: SourceRepo
+                   -> Either SourceRepoProblem
+                             (SourceRepo, String, RepoType, VCS Program)
+validateSourceRepo = \repo -> do
+    rtype <- repoType repo               ?! SourceRepoRepoTypeUnspecified
+    vcs   <- Map.lookup rtype knownVCSs  ?! SourceRepoRepoTypeUnsupported rtype
+    uri   <- repoLocation repo           ?! SourceRepoLocationUnspecified
+    return (repo, uri, rtype, vcs)
+  where
+    a ?! e = maybe (Left e) Right a
+
+
+-- | As 'validateSourceRepo' but for a bunch of 'SourceRepo's, and return
+-- things in a convenient form to pass to 'configureVCSs', or to report
+-- problems.
+--
+validateSourceRepos :: [SourceRepo]
+                    -> Either [(SourceRepo, SourceRepoProblem)]
+                              [(SourceRepo, String, RepoType, VCS Program)]
+validateSourceRepos rs =
+    case partitionEithers (map validateSourceRepo' rs) of
+      (problems@(_:_), _) -> Left problems
+      ([], vcss)          -> Right vcss
+  where
+    validateSourceRepo' r = either (Left . (,) r) Right
+                                   (validateSourceRepo r)
+
+
+configureVCS :: Verbosity
+             -> VCS Program
+             -> IO (VCS ConfiguredProgram)
+configureVCS verbosity vcs@VCS{vcsProgram = prog} =
+    asVcsConfigured <$> requireProgram verbosity prog emptyProgramDb
+  where
+    asVcsConfigured (prog', _) = vcs { vcsProgram = prog' }
+
+configureVCSs :: Verbosity
+              -> Map RepoType (VCS Program)
+              -> IO (Map RepoType (VCS ConfiguredProgram))
+configureVCSs verbosity = traverse (configureVCS verbosity)
+
+
+-- ------------------------------------------------------------
+-- * Running the driver
+-- ------------------------------------------------------------
+
+-- | Clone a single source repo into a fresh directory, using a configured VCS.
+--
+-- This is for making a new copy, not synchronising an existing copy. It will
+-- fail if the destination directory already exists.
+--
+-- Make sure to validate the 'SourceRepo' using 'validateSourceRepo' first.
+--
+cloneSourceRepo :: Verbosity
+                -> VCS ConfiguredProgram
+                -> SourceRepo -- ^ Must have 'repoLocation' filled.
+                -> FilePath   -- ^ Destination directory
+                -> IO ()
+cloneSourceRepo _ _ repo@SourceRepo{ repoLocation = Nothing } _ =
+    error $ "cloneSourceRepo: precondition violation, missing repoLocation: \""
+         ++ show repo ++ "\". Validate using validateSourceRepo first."
+
+cloneSourceRepo verbosity vcs
+                repo@SourceRepo{ repoLocation = Just srcuri } destdir =
+    mapM_ (runProgramInvocation verbosity) invocations
+  where
+    invocations = vcsCloneRepo vcs verbosity
+                               (vcsProgram vcs) repo
+                               srcuri destdir
+
+
+-- | Syncronise a set of 'SourceRepo's referring to the same repository with
+-- corresponding local directories. The local directories may or may not
+-- already exist.
+--
+-- The 'SourceRepo' values used in a single invocation of 'syncSourceRepos',
+-- or used across a series of invocations with any local directory must refer
+-- to the /same/ repository. That means it must be the same location but they
+-- can differ in the branch, or tag or subdir.
+--
+-- The reason to allow multiple related 'SourceRepo's is to allow for the
+-- network or storage to be shared between different checkouts of the repo.
+-- For example if a single repo contains multiple packages in different subdirs
+-- and in some project it may make sense to use a different state of the repo
+-- for one subdir compared to another.
+--
+syncSourceRepos :: Verbosity
+                -> VCS ConfiguredProgram
+                -> [(SourceRepo, FilePath)]
+                -> Rebuild ()
+syncSourceRepos verbosity vcs repos = do
+    files <- liftIO $ vcsSyncRepos vcs verbosity (vcsProgram vcs) repos
+    monitorFiles files
+
+
+-- ------------------------------------------------------------
+-- * The various VCS drivers
+-- ------------------------------------------------------------
+
+-- | The set of all supported VCS drivers, organised by 'RepoType'.
+--
+knownVCSs :: Map RepoType (VCS Program)
+knownVCSs = Map.fromList [ (vcsRepoType vcs, vcs) | vcs <- vcss ]
+  where
+    vcss = [ vcsBzr, vcsDarcs, vcsGit, vcsHg, vcsSvn ]
+
+
+-- | VCS driver for Bazaar.
+--
+vcsBzr :: VCS Program
+vcsBzr =
+    VCS {
+      vcsRepoType = Bazaar,
+      vcsProgram  = bzrProgram,
+      vcsCloneRepo,
+      vcsSyncRepos
+    }
+  where
+    vcsCloneRepo :: Verbosity
+                 -> ConfiguredProgram
+                 -> SourceRepo
+                 -> FilePath
+                 -> FilePath
+                 -> [ProgramInvocation]
+    vcsCloneRepo verbosity prog repo srcuri destdir =
+        [ programInvocation prog
+            ([branchCmd, srcuri, destdir] ++ tagArgs ++ verboseArg) ]
+      where
+        -- The @get@ command was deprecated in version 2.4 in favour of
+        -- the alias @branch@
+        branchCmd | programVersion prog >= Just (mkVersion [2,4])
+                              = "branch"
+                  | otherwise = "get"
+
+        tagArgs = case repoTag repo of
+          Nothing  -> []
+          Just tag -> ["-r", "tag:" ++ tag]
+        verboseArg = [ "--quiet" | verbosity < Verbosity.normal ]
+
+    vcsSyncRepos :: Verbosity -> ConfiguredProgram
+                 -> [(SourceRepo, FilePath)] -> IO [MonitorFilePath]
+    vcsSyncRepos _v _p _rs = fail "sync repo not yet supported for bzr"
+
+bzrProgram :: Program
+bzrProgram = (simpleProgram "bzr") {
+    programFindVersion = findProgramVersion "--version" $ \str ->
+      case words str of
+        -- "Bazaar (bzr) 2.6.0\n  ... lots of extra stuff"
+        (_:_:ver:_) -> ver
+        _ -> ""
+  }
+
+
+-- | VCS driver for Darcs.
+--
+vcsDarcs :: VCS Program
+vcsDarcs =
+    VCS {
+      vcsRepoType = Darcs,
+      vcsProgram  = darcsProgram,
+      vcsCloneRepo,
+      vcsSyncRepos
+    }
+  where
+    vcsCloneRepo :: Verbosity
+                 -> ConfiguredProgram
+                 -> SourceRepo
+                 -> FilePath
+                 -> FilePath
+                 -> [ProgramInvocation]
+    vcsCloneRepo verbosity prog repo srcuri destdir =
+        [ programInvocation prog cloneArgs ]
+      where
+        cloneArgs  = [cloneCmd, srcuri, destdir] ++ tagArgs ++ verboseArg
+        -- At some point the @clone@ command was introduced as an alias for
+        -- @get@, and @clone@ seems to be the recommended one now.
+        cloneCmd   | programVersion prog >= Just (mkVersion [2,8])
+                               = "clone"
+                   | otherwise = "get"
+        tagArgs    = case repoTag repo of
+          Nothing  -> []
+          Just tag -> ["-t", tag]
+        verboseArg = [ "--quiet" | verbosity < Verbosity.normal ]
+
+    vcsSyncRepos :: Verbosity -> ConfiguredProgram
+                 -> [(SourceRepo, FilePath)] -> IO [MonitorFilePath]
+    vcsSyncRepos _v _p _rs = fail "sync repo not yet supported for darcs"
+
+darcsProgram :: Program
+darcsProgram = (simpleProgram "darcs") {
+    programFindVersion = findProgramVersion "--version" $ \str ->
+      case words str of
+        -- "2.8.5 (release)"
+        (ver:_) -> ver
+        _ -> ""
+  }
+
+
+-- | VCS driver for Git.
+--
+vcsGit :: VCS Program
+vcsGit =
+    VCS {
+      vcsRepoType = Git,
+      vcsProgram  = gitProgram,
+      vcsCloneRepo,
+      vcsSyncRepos
+    }
+  where
+    vcsCloneRepo :: Verbosity
+                 -> ConfiguredProgram
+                 -> SourceRepo
+                 -> FilePath
+                 -> FilePath
+                 -> [ProgramInvocation]
+    vcsCloneRepo verbosity prog repo srcuri destdir =
+        [ programInvocation prog cloneArgs ]
+        -- And if there's a tag, we have to do that in a second step:
+     ++ [ (programInvocation prog (checkoutArgs tag)) {
+            progInvokeCwd = Just destdir
+          }
+        | tag <- maybeToList (repoTag repo) ]
+      where
+        cloneArgs  = ["clone", srcuri, destdir]
+                     ++ branchArgs ++ verboseArg
+        branchArgs = case repoBranch repo of
+          Just b  -> ["--branch", b]
+          Nothing -> []
+        checkoutArgs tag = "checkout" : verboseArg ++ [tag, "--"]
+        verboseArg = [ "--quiet" | verbosity < Verbosity.normal ]
+
+    vcsSyncRepos :: Verbosity
+                 -> ConfiguredProgram
+                 -> [(SourceRepo, FilePath)]
+                 -> IO [MonitorFilePath]
+    vcsSyncRepos _ _ [] = return []
+    vcsSyncRepos verbosity gitProg
+                 ((primaryRepo, primaryLocalDir) : secondaryRepos) = do
+
+      vcsSyncRepo verbosity gitProg primaryRepo primaryLocalDir Nothing
+      sequence_
+        [ vcsSyncRepo verbosity gitProg repo localDir (Just primaryLocalDir)
+        | (repo, localDir) <- secondaryRepos ]
+      return [ monitorDirectoryExistence dir 
+             | dir <- (primaryLocalDir : map snd secondaryRepos) ]
+
+    vcsSyncRepo verbosity gitProg SourceRepo{..} localDir peer = do
+        exists <- doesDirectoryExist localDir
+        if exists
+          then git localDir                 ["fetch"]
+          else git (takeDirectory localDir) cloneArgs
+        git localDir checkoutArgs
+      where
+        git :: FilePath -> [String] -> IO ()
+        git cwd args = runProgramInvocation verbosity $
+                         (programInvocation gitProg args) {
+                           progInvokeCwd = Just cwd
+                         }
+
+        cloneArgs      = ["clone", "--no-checkout", loc, localDir]
+                      ++ case peer of
+                           Nothing           -> []
+                           Just peerLocalDir -> ["--reference", peerLocalDir]
+                      ++ verboseArg
+                         where Just loc = repoLocation
+        checkoutArgs   = "checkout" : verboseArg ++ ["--detach", "--force"
+                         , checkoutTarget, "--" ]
+        checkoutTarget = fromMaybe "HEAD" (repoBranch `mplus` repoTag)
+        verboseArg     = [ "--quiet" | verbosity < Verbosity.normal ]
+
+gitProgram :: Program
+gitProgram = (simpleProgram "git") {
+    programFindVersion = findProgramVersion "--version" $ \str ->
+      case words str of
+        -- "git version 2.5.5"
+        (_:_:ver:_) | all isTypical ver -> ver
+
+        -- or annoyingly "git version 2.17.1.windows.2" yes, really
+        (_:_:ver:_) -> intercalate "."
+                     . takeWhile (all isNum)
+                     . split
+                     $ ver
+        _ -> ""
+  }
+  where
+    isNum     c = c >= '0' && c <= '9'
+    isTypical c = isNum c || c == '.'
+    split    cs = case break (=='.') cs of
+                    (chunk,[])     -> chunk : []
+                    (chunk,_:rest) -> chunk : split rest
+
+-- | VCS driver for Mercurial.
+--
+vcsHg :: VCS Program
+vcsHg =
+    VCS {
+      vcsRepoType = Mercurial,
+      vcsProgram  = hgProgram,
+      vcsCloneRepo,
+      vcsSyncRepos
+    }
+  where
+    vcsCloneRepo :: Verbosity
+                 -> ConfiguredProgram
+                 -> SourceRepo
+                 -> FilePath
+                 -> FilePath
+                 -> [ProgramInvocation]
+    vcsCloneRepo verbosity prog repo srcuri destdir =
+        [ programInvocation prog cloneArgs ]
+      where
+        cloneArgs  = ["clone", srcuri, destdir]
+                     ++ branchArgs ++ tagArgs ++ verboseArg
+        branchArgs = case repoBranch repo of
+          Just b  -> ["--branch", b]
+          Nothing -> []
+        tagArgs = case repoTag repo of
+          Just t  -> ["--rev", t]
+          Nothing -> []
+        verboseArg = [ "--quiet" | verbosity < Verbosity.normal ]
+
+    vcsSyncRepos :: Verbosity
+                 -> ConfiguredProgram
+                 -> [(SourceRepo, FilePath)]
+                 -> IO [MonitorFilePath]
+    vcsSyncRepos _v _p _rs = fail "sync repo not yet supported for hg"
+
+hgProgram :: Program
+hgProgram = (simpleProgram "hg") {
+    programFindVersion = findProgramVersion "--version" $ \str ->
+      case words str of
+        -- Mercurial Distributed SCM (version 3.5.2)\n ... long message
+        (_:_:_:_:ver:_) -> takeWhile (\c -> Char.isDigit c || c == '.') ver
+        _ -> ""
+  }
+
+
+-- | VCS driver for Subversion.
+--
+vcsSvn :: VCS Program
+vcsSvn =
+    VCS {
+      vcsRepoType = SVN,
+      vcsProgram  = svnProgram,
+      vcsCloneRepo,
+      vcsSyncRepos
+    }
+  where
+    vcsCloneRepo :: Verbosity
+                 -> ConfiguredProgram
+                 -> SourceRepo
+                 -> FilePath
+                 -> FilePath
+                 -> [ProgramInvocation]
+    vcsCloneRepo verbosity prog _repo srcuri destdir =
+        [ programInvocation prog checkoutArgs ]
+      where
+        checkoutArgs = ["checkout", srcuri, destdir] ++ verboseArg
+        verboseArg   = [ "--quiet" | verbosity < Verbosity.normal ]
+        --TODO: branch or tag?
+
+    vcsSyncRepos :: Verbosity
+                 -> ConfiguredProgram
+                 -> [(SourceRepo, FilePath)]
+                 -> IO [MonitorFilePath]
+    vcsSyncRepos _v _p _rs = fail "sync repo not yet supported for svn"
+
+svnProgram :: Program
+svnProgram = (simpleProgram "svn") {
+    programFindVersion = findProgramVersion "--version" $ \str ->
+      case words str of
+        -- svn, version 1.9.4 (r1740329)\n ... long message
+        (_:_:ver:_) -> ver
+        _ -> ""
+  }
+
diff --git a/cabal/cabal-install/Distribution/Client/Win32SelfUpgrade.hs b/cabal/cabal-install/Distribution/Client/Win32SelfUpgrade.hs
--- a/cabal/cabal-install/Distribution/Client/Win32SelfUpgrade.hs
+++ b/cabal/cabal-install/Distribution/Client/Win32SelfUpgrade.hs
@@ -17,7 +17,7 @@
 -- | Windows inherited a design choice from DOS that while initially innocuous
 -- has rather unfortunate consequences. It maintains the invariant that every
 -- open file has a corresponding name on disk. One positive consequence of this
--- is that an executable can always find it's own executable file. The downside
+-- is that an executable can always find its own executable file. The downside
 -- is that a program cannot be deleted or upgraded while it is running without
 -- hideous workarounds. This module implements one such hideous workaround.
 --
diff --git a/cabal/cabal-install/Distribution/Solver/Modular.hs b/cabal/cabal-install/Distribution/Solver/Modular.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular.hs
@@ -1,5 +1,5 @@
 module Distribution.Solver.Modular
-         ( modularResolver, SolverConfig(..)) where
+         ( modularResolver, SolverConfig(..), PruneAfterFirstSuccess(..)) where
 
 -- Here, we try to map between the external cabal-install solver
 -- interface and the internal interface that the solver actually
@@ -9,41 +9,57 @@
 -- and finally, we have to convert back the resulting install
 -- plan.
 
-import Data.Map as M
-         ( fromListWith )
+import Prelude ()
+import Distribution.Solver.Compat.Prelude
+
+import qualified Data.Map as M
+import Data.Set (Set)
+import Data.Ord
 import Distribution.Compat.Graph
          ( IsNode(..) )
+import Distribution.Compiler
+         ( CompilerInfo )
 import Distribution.Solver.Modular.Assignment
-         ( toCPs )
+         ( Assignment, toCPs )
 import Distribution.Solver.Modular.ConfiguredConversion
          ( convCP )
+import qualified Distribution.Solver.Modular.ConflictSet as CS
+import Distribution.Solver.Modular.Dependency
+import Distribution.Solver.Modular.Flag
+import Distribution.Solver.Modular.Index
 import Distribution.Solver.Modular.IndexConversion
          ( convPIs )
 import Distribution.Solver.Modular.Log
-         ( logToProgress )
+         ( SolverFailure(..), logToProgress )
 import Distribution.Solver.Modular.Package
          ( PN )
 import Distribution.Solver.Modular.Solver
-         ( SolverConfig(..), solve )
+         ( SolverConfig(..), PruneAfterFirstSuccess(..), solve )
+import Distribution.Solver.Types.DependencyResolver
 import Distribution.Solver.Types.LabeledPackageConstraint
 import Distribution.Solver.Types.PackageConstraint
-import Distribution.Solver.Types.DependencyResolver
+import Distribution.Solver.Types.PackagePath
+import Distribution.Solver.Types.PackagePreferences
+import Distribution.Solver.Types.PkgConfigDb
+         ( PkgConfigDb )
+import Distribution.Solver.Types.Progress
+import Distribution.Solver.Types.Variable
 import Distribution.System
          ( Platform(..) )
 import Distribution.Simple.Utils
          ( ordNubBy )
+import Distribution.Verbosity
 
 
 -- | Ties the two worlds together: classic cabal-install vs. the modular
 -- solver. Performs the necessary translations before and after.
 modularResolver :: SolverConfig -> DependencyResolver loc
 modularResolver sc (Platform arch os) cinfo iidx sidx pkgConfigDB pprefs pcs pns =
-  fmap (uncurry postprocess)                           $ -- convert install plan
-  logToProgress (solverVerbosity sc) (maxBackjumps sc) $ -- convert log format into progress format
-  solve sc cinfo idx pkgConfigDB pprefs gcs pns
+  fmap (uncurry postprocess) $ -- convert install plan
+  solve' sc cinfo idx pkgConfigDB pprefs gcs pns
     where
       -- Indices have to be converted into solver-specific uniform index.
-      idx    = convPIs os arch cinfo (shadowPkgs sc) (strongFlags sc) (solveExecutables sc) iidx sidx
+      idx    = convPIs os arch cinfo gcs (shadowPkgs sc) (strongFlags sc) (solveExecutables sc) iidx sidx
       -- Constraints have to be converted into a finite map indexed by PN.
       gcs    = M.fromListWith (++) (map pair pcs)
         where
@@ -58,3 +74,102 @@
       -- Helper function to extract the PN from a constraint.
       pcName :: PackageConstraint -> PN
       pcName (PackageConstraint scope _) = scopeToPackageName scope
+
+-- | Run 'D.S.Modular.Solver.solve' and then produce a summarized log to display
+-- in the error case.
+--
+-- When there is no solution, we produce the error message by rerunning the
+-- solver but making it prefer the goals from the final conflict set from the
+-- first run. We also set the backjump limit to 0, so that the log stops at the
+-- first backjump and is relatively short. Preferring goals from the final
+-- conflict set increases the probability that the log to the first backjump
+-- contains package, flag, and stanza choices that are relevant to the final
+-- failure. The solver shouldn't need to choose any packages that aren't in the
+-- final conflict set. (For every variable in the final conflict set, the final
+-- conflict set should also contain the variable that introduced that variable.
+-- The solver can then follow that chain of variables in reverse order from the
+-- user target to the conflict.) However, it is possible that the conflict set
+-- contains unnecessary variables.
+--
+-- Producing an error message when the solver reaches the backjump limit is more
+-- complicated. There is no final conflict set, so we create one for the minimal
+-- subtree containing the path that the solver took to the first backjump. This
+-- conflict set helps explain why the solver reached the backjump limit, because
+-- the first backjump contributes to reaching the backjump limit. Additionally,
+-- the solver is much more likely to be able to finish traversing this subtree
+-- before the backjump limit, since its size is linear (not exponential) in the
+-- number of goal choices. We create it by pruning all children after the first
+-- successful child under each node in the original tree, so that there is at
+-- most one valid choice at each level. Then we use the final conflict set from
+-- that run to generate an error message, as in the case where the solver found
+-- that there was no solution.
+--
+-- Using the full log from a rerun of the solver ensures that the log is
+-- complete, i.e., it shows the whole chain of dependencies from the user
+-- targets to the conflicting packages.
+solve' :: SolverConfig
+       -> CompilerInfo
+       -> Index
+       -> PkgConfigDb
+       -> (PN -> PackagePreferences)
+       -> Map PN [LabeledPackageConstraint]
+       -> Set PN
+       -> Progress String String (Assignment, RevDepMap)
+solve' sc cinfo idx pkgConfigDB pprefs gcs pns =
+    foldProgress Step (uncurry createErrorMsg) Done (runSolver printFullLog sc)
+  where
+    runSolver :: Bool -> SolverConfig
+              -> Progress String (SolverFailure, String) (Assignment, RevDepMap)
+    runSolver keepLog sc' =
+        logToProgress keepLog (solverVerbosity sc') (maxBackjumps sc') $
+        solve sc' cinfo idx pkgConfigDB pprefs gcs pns
+
+    createErrorMsg :: SolverFailure -> String
+                   -> Progress String String (Assignment, RevDepMap)
+    createErrorMsg (ExhaustiveSearch cs _) msg =
+        Fail $ rerunSolverForErrorMsg cs ++ msg
+    createErrorMsg BackjumpLimitReached    msg =
+        Step ("Backjump limit reached. Rerunning dependency solver to generate "
+              ++ "a final conflict set for the search tree containing the "
+              ++ "first backjump.") $
+        foldProgress Step (f . fst) Done $
+        runSolver printFullLog
+                  sc { pruneAfterFirstSuccess = PruneAfterFirstSuccess True }
+      where
+        f :: SolverFailure -> Progress String String (Assignment, RevDepMap)
+        f (ExhaustiveSearch cs _) = Fail $ rerunSolverForErrorMsg cs ++ msg
+        f BackjumpLimitReached    =
+            -- This case is possible when the number of goals involved in
+            -- conflicts is greater than the backjump limit.
+            Fail $ msg ++ "Failed to generate a summarized dependency solver "
+                       ++ "log due to low backjump limit."
+
+    rerunSolverForErrorMsg :: ConflictSet -> String
+    rerunSolverForErrorMsg cs =
+      let sc' = sc {
+                    goalOrder = Just goalOrder'
+                  , maxBackjumps = Just 0
+                  }
+
+          -- Preferring goals from the conflict set takes precedence over the
+          -- original goal order.
+          goalOrder' = preferGoalsFromConflictSet cs <> fromMaybe mempty (goalOrder sc)
+
+      in unlines ("Could not resolve dependencies:" : messages (runSolver True sc'))
+
+    printFullLog = solverVerbosity sc >= verbose
+
+    messages :: Progress step fail done -> [step]
+    messages = foldProgress (:) (const []) (const [])
+
+-- | Goal ordering that chooses goals contained in the conflict set before
+-- other goals.
+preferGoalsFromConflictSet :: ConflictSet
+                           -> Variable QPN -> Variable QPN -> Ordering
+preferGoalsFromConflictSet cs =
+    comparing $ \v -> not $ CS.member (toVar v) cs
+  where
+    toVar :: Variable QPN -> Var QPN
+    toVar (PackageVar qpn)    = P qpn
+    toVar (FlagVar    qpn fn) = F (FN qpn fn)
+    toVar (StanzaVar  qpn sn) = S (SN qpn sn)
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/Builder.hs b/cabal/cabal-install/Distribution/Solver/Modular/Builder.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/Builder.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/Builder.hs
@@ -21,6 +21,7 @@
 
 import Data.List as L
 import Data.Map as M
+import Data.Set as S
 import Prelude hiding (sequence, mapM)
 
 import Distribution.Solver.Modular.Dependency
@@ -31,6 +32,7 @@
 import Distribution.Solver.Modular.Tree
 import qualified Distribution.Solver.Modular.WeightedPSQ as W
 
+import Distribution.Solver.Types.ComponentDeps
 import Distribution.Solver.Types.PackagePath
 import Distribution.Solver.Types.Settings
 
@@ -70,9 +72,16 @@
       -- the later addition will have better dependency information.
     go g o ((Stanza sn@(SN qpn _) t)           : ngs) =
         go g (StanzaGoal sn t (flagGR qpn) : o) ngs
-    go g o ((Simple (LDep dr (Dep _ qpn _)) c) : ngs)
-      | qpn == qpn'       = go                            g               o  ngs
-          -- we ignore self-dependencies at this point; TODO: more care may be needed
+    go g o ((Simple (LDep dr (Dep (PkgComponent qpn _) _)) c) : ngs)
+      | qpn == qpn'       =
+            -- We currently only add a self-dependency to the graph if it is
+            -- between a package and its setup script. The edge creates a cycle
+            -- and causes the solver to backtrack and choose a different
+            -- instance for the setup script. We may need to track other
+            -- self-dependencies once we implement component-based solving.
+          case c of
+            ComponentSetup -> go (M.adjust (addIfAbsent (ComponentSetup, qpn')) qpn g) o ngs
+            _              -> go                                                    g  o ngs
       | qpn `M.member` g  = go (M.adjust (addIfAbsent (c, qpn')) qpn g)   o  ngs
       | otherwise         = go (M.insert qpn [(c, qpn')]  g) (PkgGoal qpn (DependencyGoal dr) : o) ngs
           -- code above is correct; insert/adjust have different arg order
@@ -86,7 +95,7 @@
     -- GoalReason for a flag or stanza. Each flag/stanza is introduced only by
     -- its containing package.
     flagGR :: qpn -> GoalReason qpn
-    flagGR qpn = DependencyGoal (DependencyReason qpn [] [])
+    flagGR qpn = DependencyGoal (DependencyReason qpn M.empty S.empty)
 
 -- | Given the current scope, qualify all the package names in the given set of
 -- dependencies and then extend the set of open goals accordingly.
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/ConflictSet.hs b/cabal/cabal-install/Distribution/Solver/Modular/ConflictSet.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/ConflictSet.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/ConflictSet.hs
@@ -51,7 +51,7 @@
 -- kept abstract.
 data ConflictSet = CS {
     -- | The set of variables involved on the conflict
-    conflictSetToSet :: Set (Var QPN)
+    conflictSetToSet :: !(Set (Var QPN))
 
 #ifdef DEBUG_CONFLICT_SETS
     -- | The origin of the conflict set
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/Dependency.hs b/cabal/cabal-install/Distribution/Solver/Modular/Dependency.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/Dependency.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/Dependency.hs
@@ -16,6 +16,8 @@
   , FlaggedDep(..)
   , LDep(..)
   , Dep(..)
+  , PkgComponent(..)
+  , ExposedComponent(..)
   , DependencyReason(..)
   , showDependencyReason
   , flattenFlaggedDeps
@@ -35,7 +37,9 @@
   ) where
 
 import Prelude ()
-import Distribution.Client.Compat.Prelude hiding (pi)
+import qualified Data.Map as M
+import qualified Data.Set as S
+import Distribution.Solver.Compat.Prelude hiding (pi)
 
 import Language.Haskell.Extension (Extension(..), Language(..))
 
@@ -110,17 +114,27 @@
 -- | A dependency (constraint) associates a package name with a constrained
 -- instance. It can also represent other types of dependencies, such as
 -- dependencies on language extensions.
-data Dep qpn = Dep (Maybe UnqualComponentName) qpn CI  -- ^ dependency on a package (possibly for executable)
-             | Ext  Extension                          -- ^ dependency on a language extension
-             | Lang Language                           -- ^ dependency on a language version
-             | Pkg  PkgconfigName VR                   -- ^ dependency on a pkg-config package
+data Dep qpn = Dep (PkgComponent qpn) CI  -- ^ dependency on a package component
+             | Ext Extension              -- ^ dependency on a language extension
+             | Lang Language              -- ^ dependency on a language version
+             | Pkg PkgconfigName VR       -- ^ dependency on a pkg-config package
   deriving Functor
 
+-- | An exposed component within a package. This type is used to represent
+-- build-depends and build-tool-depends dependencies.
+data PkgComponent qpn = PkgComponent qpn ExposedComponent
+  deriving (Eq, Ord, Functor, Show)
+
+-- | A component that can be depended upon by another package, i.e., a library
+-- or an executable.
+data ExposedComponent = ExposedLib | ExposedExe UnqualComponentName
+  deriving (Eq, Ord, Show)
+
 -- | The reason that a dependency is active. It identifies the package and any
 -- flag and stanza choices that introduced the dependency. It contains
 -- everything needed for creating ConflictSets or describing conflicts in solver
 -- log messages.
-data DependencyReason qpn = DependencyReason qpn [(Flag, FlagValue)] [Stanza]
+data DependencyReason qpn = DependencyReason qpn (Map Flag FlagValue) (S.Set Stanza)
   deriving (Functor, Eq, Show)
 
 -- | Print the reason that a dependency was introduced.
@@ -128,7 +142,8 @@
 showDependencyReason (DependencyReason qpn flags stanzas) =
     intercalate " " $
         showQPN qpn
-      : map (uncurry showFlagValue) flags ++ map (\s -> showSBool s True) stanzas
+      : map (uncurry showFlagValue) (M.toList flags)
+     ++ map (\s -> showSBool s True) (S.toList stanzas)
 
 -- | Options for goal qualification (used in 'qualifyDeps')
 --
@@ -166,7 +181,7 @@
     -- Suppose package B has a setup dependency on package A.
     -- This will be recorded as something like
     --
-    -- > LDep (DependencyReason "B") (Dep Nothing "A" (Constrained AnyVersion))
+    -- > LDep (DependencyReason "B") (Dep (PkgComponent "A" ExposedLib) (Constrained AnyVersion))
     --
     -- Observe that when we qualify this dependency, we need to turn that
     -- @"A"@ into @"B-setup.A"@, but we should not apply that same qualifier
@@ -178,11 +193,12 @@
     goD (Ext  ext)    _    = Ext  ext
     goD (Lang lang)   _    = Lang lang
     goD (Pkg pkn vr)  _    = Pkg pkn vr
-    goD (Dep mExe dep ci) comp
-      | isJust mExe = Dep mExe (Q (PackagePath ns (QualExe   pn dep)) dep) ci
-      | qBase  dep  = Dep mExe (Q (PackagePath ns (QualBase  pn    )) dep) ci
-      | qSetup comp = Dep mExe (Q (PackagePath ns (QualSetup pn    )) dep) ci
-      | otherwise   = Dep mExe (Q (PackagePath ns inheritedQ        ) dep) ci
+    goD (Dep dep@(PkgComponent qpn (ExposedExe _)) ci) _ =
+        Dep (Q (PackagePath ns (QualExe pn qpn)) <$> dep) ci
+    goD (Dep dep@(PkgComponent qpn ExposedLib) ci) comp
+      | qBase qpn   = Dep (Q (PackagePath ns (QualBase  pn)) <$> dep) ci
+      | qSetup comp = Dep (Q (PackagePath ns (QualSetup pn)) <$> dep) ci
+      | otherwise   = Dep (Q (PackagePath ns inheritedQ    ) <$> dep) ci
 
     -- If P has a setup dependency on Q, and Q has a regular dependency on R, then
     -- we say that the 'Setup' qualifier is inherited: P has an (indirect) setup
@@ -270,13 +286,13 @@
 -- It drops the flag and stanza values, which are only needed for log messages.
 dependencyReasonToCS :: DependencyReason QPN -> ConflictSet
 dependencyReasonToCS (DependencyReason qpn flags stanzas) =
-    CS.fromList $ P qpn : flagVars ++ map stanzaToVar stanzas
+    CS.fromList $ P qpn : flagVars ++ map stanzaToVar (S.toList stanzas)
   where
     -- Filter out any flags that introduced the dependency with both values.
     -- They don't need to be included in the conflict set, because changing the
     -- flag value can't remove the dependency.
     flagVars :: [Var QPN]
-    flagVars = [F (FN qpn fn) | (fn, fv) <- flags, fv /= FlagBoth]
+    flagVars = [F (FN qpn fn) | (fn, fv) <- M.toList flags, fv /= FlagBoth]
 
     stanzaToVar :: Stanza -> Var QPN
     stanzaToVar = S . SN qpn
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/Explore.hs b/cabal/cabal-install/Distribution/Solver/Modular/Explore.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/Explore.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/Explore.hs
@@ -5,9 +5,11 @@
     , backjumpAndExplore
     ) where
 
+import qualified Distribution.Solver.Types.Progress as P
+
 import Data.Foldable as F
 import Data.List as L (foldl')
-import Data.Map as M
+import Data.Map.Strict as M
 
 import Distribution.Solver.Modular.Assignment
 import Distribution.Solver.Modular.Dependency
@@ -43,34 +45,61 @@
 -- with the (virtual) option not to choose anything for the current
 -- variable. See also the comments for 'avoidSet'.
 --
-backjump :: EnableBackjumping -> Var QPN
-         -> ConflictSet -> W.WeightedPSQ w k (ConflictMap -> ConflictSetLog a)
-         -> ConflictMap -> ConflictSetLog a
-backjump (EnableBackjumping enableBj) var lastCS xs =
+backjump :: Maybe Int -> EnableBackjumping -> Var QPN
+         -> ConflictSet -> W.WeightedPSQ w k (ExploreState -> ConflictSetLog a)
+         -> ExploreState -> ConflictSetLog a
+backjump mbj (EnableBackjumping enableBj) var lastCS xs =
     F.foldr combine avoidGoal xs CS.empty
   where
-    combine :: forall a . (ConflictMap -> ConflictSetLog a)
-            -> (ConflictSet -> ConflictMap -> ConflictSetLog a)
-            ->  ConflictSet -> ConflictMap -> ConflictSetLog a
-    combine x f csAcc cm = retry (x cm) next
+    combine :: forall a . (ExploreState -> ConflictSetLog a)
+            -> (ConflictSet -> ExploreState -> ConflictSetLog a)
+            ->  ConflictSet -> ExploreState -> ConflictSetLog a
+    combine x f csAcc es = retry (x es) next
       where
-        next :: (ConflictSet, ConflictMap) -> ConflictSetLog a
-        next (cs, cm')
-          | enableBj && not (var `CS.member` cs) = logBackjump cs cm'
-          | otherwise                            = f (csAcc `CS.union` cs) cm'
+        next :: IntermediateFailure -> ConflictSetLog a
+        next BackjumpLimit = fromProgress (P.Fail BackjumpLimit)
+        next (NoSolution !cs es')
+          | enableBj && not (var `CS.member` cs) = skipLoggingBackjump cs es'
+          | otherwise                            = f (csAcc `CS.union` cs) es'
 
     -- This function represents the option to not choose a value for this goal.
-    avoidGoal :: ConflictSet -> ConflictMap -> ConflictSetLog a
-    avoidGoal cs !cm = logBackjump (cs `CS.union` lastCS) (updateCM lastCS cm)
-                                -- 'lastCS' instead of 'cs' here ---^
-                                -- since we do not want to double-count the
-                                -- additionally accumulated conflicts.
+    avoidGoal :: ConflictSet -> ExploreState -> ConflictSetLog a
+    avoidGoal cs !es =
+        logBackjump (cs `CS.union` lastCS) $
 
-    logBackjump :: ConflictSet -> ConflictMap -> ConflictSetLog a
-    logBackjump cs cm = failWith (Failure cs Backjump) (cs, cm)
+        -- Use 'lastCS' below instead of 'cs' since we do not want to
+        -- double-count the additionally accumulated conflicts.
+        es { esConflictMap = updateCM lastCS (esConflictMap es) }
 
-type ConflictSetLog = RetryLog Message (ConflictSet, ConflictMap)
+    logBackjump :: ConflictSet -> ExploreState -> ConflictSetLog a
+    logBackjump cs es =
+        failWith (Failure cs Backjump) $
+            if reachedBjLimit (esBackjumps es)
+            then BackjumpLimit
+            else NoSolution cs es { esBackjumps = esBackjumps es + 1 }
+      where
+        reachedBjLimit = case mbj of
+                           Nothing    -> const False
+                           Just limit -> (== limit)
 
+    -- The solver does not count or log backjumps at levels where the conflict
+    -- set does not contain the current variable. Otherwise, there would be many
+    -- consecutive log messages about backjumping with the same conflict set.
+    skipLoggingBackjump :: ConflictSet -> ExploreState -> ConflictSetLog a
+    skipLoggingBackjump cs es = fromProgress $ P.Fail (NoSolution cs es)
+
+-- | The state that is read and written while exploring the search tree.
+data ExploreState = ES {
+    esConflictMap :: !ConflictMap
+  , esBackjumps   :: !Int
+  }
+
+data IntermediateFailure =
+    NoSolution ConflictSet ExploreState
+  | BackjumpLimit
+
+type ConflictSetLog = RetryLog Message IntermediateFailure
+
 getBestGoal :: ConflictMap -> P.PSQ (Goal QPN) a -> (Goal QPN, a)
 getBestGoal cm =
   P.maximumBy
@@ -86,10 +115,7 @@
 
 updateCM :: ConflictSet -> ConflictMap -> ConflictMap
 updateCM cs cm =
-  L.foldl' (\ cmc k -> M.alter inc k cmc) cm (CS.toList cs)
-  where
-    inc Nothing  = Just 1
-    inc (Just n) = Just $! n + 1
+  L.foldl' (\ cmc k -> M.insertWith (+) k 1 cmc) cm (CS.toList cs)
 
 -- | Record complete assignments on 'Done' nodes.
 assign :: Tree d c -> Tree Assignment c
@@ -109,39 +135,46 @@
 
 -- | A tree traversal that simultaneously propagates conflict sets up
 -- the tree from the leaves and creates a log.
-exploreLog :: EnableBackjumping -> CountConflicts -> Tree Assignment QGoalReason
+exploreLog :: Maybe Int -> EnableBackjumping -> CountConflicts
+           -> Tree Assignment QGoalReason
            -> ConflictSetLog (Assignment, RevDepMap)
-exploreLog enableBj (CountConflicts countConflicts) t = cata go t M.empty
+exploreLog mbj enableBj (CountConflicts countConflicts) t = cata go t initES
   where
     getBestGoal' :: P.PSQ (Goal QPN) a -> ConflictMap -> (Goal QPN, a)
     getBestGoal'
       | countConflicts = \ ts cm -> getBestGoal cm ts
       | otherwise      = \ ts _  -> getFirstGoal ts
 
-    go :: TreeF Assignment QGoalReason (ConflictMap -> ConflictSetLog (Assignment, RevDepMap))
-                                    -> (ConflictMap -> ConflictSetLog (Assignment, RevDepMap))
-    go (FailF c fr)                            = \ !cm -> failWith (Failure c fr)
-                                                                 (c, updateCM c cm)
+    go :: TreeF Assignment QGoalReason (ExploreState -> ConflictSetLog (Assignment, RevDepMap))
+                                    -> (ExploreState -> ConflictSetLog (Assignment, RevDepMap))
+    go (FailF c fr)                            = \ !es ->
+        let es' = es { esConflictMap = updateCM c (esConflictMap es) }
+        in failWith (Failure c fr) (NoSolution c es')
     go (DoneF rdm a)                           = \ _   -> succeedWith Success (a, rdm)
     go (PChoiceF qpn _ gr       ts)            =
-      backjump enableBj (P qpn) (avoidSet (P qpn) gr) $ -- try children in order,
-        W.mapWithKey                                -- when descending ...
-          (\ k r cm -> tryWith (TryP qpn k) (r cm))
+      backjump mbj enableBj (P qpn) (avoidSet (P qpn) gr) $ -- try children in order,
+        W.mapWithKey                                        -- when descending ...
+          (\ k r es -> tryWith (TryP qpn k) (r es))
           ts
     go (FChoiceF qfn _ gr _ _ _ ts)            =
-      backjump enableBj (F qfn) (avoidSet (F qfn) gr) $ -- try children in order,
-        W.mapWithKey                                -- when descending ...
-          (\ k r cm -> tryWith (TryF qfn k) (r cm))
+      backjump mbj enableBj (F qfn) (avoidSet (F qfn) gr) $ -- try children in order,
+        W.mapWithKey                                        -- when descending ...
+          (\ k r es -> tryWith (TryF qfn k) (r es))
           ts
     go (SChoiceF qsn _ gr _     ts)            =
-      backjump enableBj (S qsn) (avoidSet (S qsn) gr) $ -- try children in order,
-        W.mapWithKey                                -- when descending ...
-          (\ k r cm -> tryWith (TryS qsn k) (r cm))
+      backjump mbj enableBj (S qsn) (avoidSet (S qsn) gr) $ -- try children in order,
+        W.mapWithKey                                        -- when descending ...
+          (\ k r es -> tryWith (TryS qsn k) (r es))
           ts
-    go (GoalChoiceF _           ts)            = \ cm ->
-      let (k, v) = getBestGoal' ts cm
-      in continueWith (Next k) (v cm)
+    go (GoalChoiceF _           ts)            = \ es ->
+      let (k, v) = getBestGoal' ts (esConflictMap es)
+      in continueWith (Next k) (v es)
 
+    initES = ES {
+        esConflictMap = M.empty
+      , esBackjumps = 0
+      }
+
 -- | Build a conflict set corresponding to the (virtual) option not to
 -- choose a solution for a goal at all.
 --
@@ -171,8 +204,17 @@
   CS.union (CS.singleton var) (goalReasonToCS gr)
 
 -- | Interface.
-backjumpAndExplore :: EnableBackjumping
+--
+-- Takes as an argument a limit on allowed backjumps. If the limit is 'Nothing',
+-- then infinitely many backjumps are allowed. If the limit is 'Just 0',
+-- backtracking is completely disabled.
+backjumpAndExplore :: Maybe Int
+                   -> EnableBackjumping
                    -> CountConflicts
-                   -> Tree d QGoalReason -> Log Message (Assignment, RevDepMap)
-backjumpAndExplore enableBj countConflicts =
-    toProgress . exploreLog enableBj countConflicts . assign
+                   -> Tree d QGoalReason
+                   -> RetryLog Message SolverFailure (Assignment, RevDepMap)
+backjumpAndExplore mbj enableBj countConflicts =
+    mapFailure convertFailure . exploreLog mbj enableBj countConflicts . assign
+  where
+    convertFailure (NoSolution cs es) = ExhaustiveSearch cs (esConflictMap es)
+    convertFailure BackjumpLimit      = BackjumpLimitReached
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/Index.hs b/cabal/cabal-install/Distribution/Solver/Modular/Index.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/Index.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/Index.hs
@@ -1,6 +1,7 @@
 module Distribution.Solver.Modular.Index
     ( Index
     , PInfo(..)
+    , IsBuildable(..)
     , defaultQualifyOptions
     , mkIndex
     ) where
@@ -13,7 +14,6 @@
 import Distribution.Solver.Modular.Flag
 import Distribution.Solver.Modular.Package
 import Distribution.Solver.Modular.Tree
-import Distribution.Types.UnqualComponentName
 
 -- | An index contains information about package instances. This is a nested
 -- dictionary. Package names are mapped to instances, which in turn is mapped
@@ -21,13 +21,18 @@
 type Index = Map PN (Map I PInfo)
 
 -- | Info associated with a package instance.
--- Currently, dependencies, executable names, flags and failure reasons.
+-- Currently, dependencies, component names, flags and failure reasons.
+-- The component map records whether any components are unbuildable in the
+-- current environment (compiler, os, arch, and global flag constraints).
 -- Packages that have a failure reason recorded for them are disabled
 -- globally, for reasons external to the solver. We currently use this
 -- for shadowing which essentially is a GHC limitation, and for
 -- installed packages that are broken.
-data PInfo = PInfo (FlaggedDeps PN) [UnqualComponentName] FlagInfo (Maybe FailReason)
+data PInfo = PInfo (FlaggedDeps PN) (Map ExposedComponent IsBuildable) FlagInfo (Maybe FailReason)
 
+-- | Whether a component is made unbuildable by a "buildable: False" field.
+newtype IsBuildable = IsBuildable Bool
+
 mkIndex :: [(PN, I, PInfo)] -> Index
 mkIndex xs = M.map M.fromList (groupMap (L.map (\ (pn, i, pi) -> (pn, (i, pi))) xs))
 
@@ -40,9 +45,9 @@
                               | -- Find all versions of base ..
                                 Just is <- [M.lookup base idx]
                                 -- .. which are installed ..
-                              , (I _ver (Inst _), PInfo deps _exes _flagNfo _fr) <- M.toList is
+                              , (I _ver (Inst _), PInfo deps _comps _flagNfo _fr) <- M.toList is
                                 -- .. and flatten all their dependencies ..
-                              , (LDep _ (Dep _is_exe dep _ci), _comp) <- flattenFlaggedDeps deps
+                              , (LDep _ (Dep (PkgComponent dep _) _ci), _comp) <- flattenFlaggedDeps deps
                               ]
     , qoSetupIndependent = True
     }
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/IndexConversion.hs b/cabal/cabal-install/Distribution/Solver/Modular/IndexConversion.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/IndexConversion.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/IndexConversion.hs
@@ -3,7 +3,8 @@
     ) where
 
 import Data.List as L
-import Data.Map as M
+import Data.Map.Strict (Map)
+import qualified Data.Map.Strict as M
 import Data.Maybe
 import Data.Monoid as Mon
 import Data.Set as S
@@ -29,7 +30,9 @@
 import           Distribution.Solver.Types.ComponentDeps
                    ( Component(..), componentNameToComponent )
 import           Distribution.Solver.Types.Flag
+import           Distribution.Solver.Types.LabeledPackageConstraint
 import           Distribution.Solver.Types.OptionalStanza
+import           Distribution.Solver.Types.PackageConstraint
 import qualified Distribution.Solver.Types.PackageIndex as CI
 import           Distribution.Solver.Types.Settings
 import           Distribution.Solver.Types.SourcePackage
@@ -52,10 +55,13 @@
 -- resolving these situations. However, the right thing to do is to
 -- fix the problem there, so for now, shadowing is only activated if
 -- explicitly requested.
-convPIs :: OS -> Arch -> CompilerInfo -> ShadowPkgs -> StrongFlags -> SolveExecutables ->
-           SI.InstalledPackageIndex -> CI.PackageIndex (SourcePackage loc) -> Index
-convPIs os arch comp sip strfl solveExes iidx sidx =
-  mkIndex (convIPI' sip iidx ++ convSPI' os arch comp strfl solveExes sidx)
+convPIs :: OS -> Arch -> CompilerInfo -> Map PN [LabeledPackageConstraint]
+        -> ShadowPkgs -> StrongFlags -> SolveExecutables
+        -> SI.InstalledPackageIndex -> CI.PackageIndex (SourcePackage loc)
+        -> Index
+convPIs os arch comp constraints sip strfl solveExes iidx sidx =
+  mkIndex $
+  convIPI' sip iidx ++ convSPI' os arch comp constraints strfl solveExes sidx
 
 -- | Convert a Cabal installed package index to the simpler,
 -- more uniform index format of the solver.
@@ -71,7 +77,8 @@
   where
 
     -- shadowing is recorded in the package info
-    shadow (pn, i, PInfo fdeps exes fds _) | sip = (pn, i, PInfo fdeps exes fds (Just Shadowed))
+    shadow (pn, i, PInfo fdeps comps fds _)
+      | sip = (pn, i, PInfo fdeps comps fds (Just Shadowed))
     shadow x                                     = x
 
 -- | Extract/recover the the package ID from an installed package info, and convert it to a solver's I.
@@ -84,9 +91,11 @@
 -- | Convert a single installed package into the solver-specific format.
 convIP :: SI.InstalledPackageIndex -> InstalledPackageInfo -> (PN, I, PInfo)
 convIP idx ipi =
-  case mapM (convIPId (DependencyReason pn [] []) comp idx) (IPI.depends ipi) of
-        Nothing  -> (pn, i, PInfo [] [] M.empty (Just Broken))
-        Just fds -> (pn, i, PInfo fds [] M.empty Nothing)
+  case mapM (convIPId (DependencyReason pn M.empty S.empty) comp idx) (IPI.depends ipi) of
+        Nothing  -> (pn, i, PInfo [] M.empty M.empty (Just Broken))
+        Just fds -> ( pn
+                    , i
+                    , PInfo fds (M.singleton ExposedLib (IsBuildable True)) M.empty Nothing)
  where
   (pn, i) = convId ipi
   -- 'sourceLibName' is unreliable, but for now we only really use this for
@@ -132,30 +141,35 @@
   case SI.lookupUnitId idx ipid of
     Nothing  -> Nothing
     Just ipi -> let (pn, i) = convId ipi
-                in  Just (D.Simple (LDep dr (Dep Nothing pn (Fixed i))) comp)
+                in  Just (D.Simple (LDep dr (Dep (PkgComponent pn ExposedLib) (Fixed i))) comp)
                 -- NB: something we pick up from the
                 -- InstalledPackageIndex is NEVER an executable
 
 -- | Convert a cabal-install source package index to the simpler,
 -- more uniform index format of the solver.
-convSPI' :: OS -> Arch -> CompilerInfo -> StrongFlags -> SolveExecutables ->
-            CI.PackageIndex (SourcePackage loc) -> [(PN, I, PInfo)]
-convSPI' os arch cinfo strfl solveExes = L.map (convSP os arch cinfo strfl solveExes) . CI.allPackages
+convSPI' :: OS -> Arch -> CompilerInfo -> Map PN [LabeledPackageConstraint]
+         -> StrongFlags -> SolveExecutables
+         -> CI.PackageIndex (SourcePackage loc) -> [(PN, I, PInfo)]
+convSPI' os arch cinfo constraints strfl solveExes =
+    L.map (convSP os arch cinfo constraints strfl solveExes) . CI.allPackages
 
 -- | Convert a single source package into the solver-specific format.
-convSP :: OS -> Arch -> CompilerInfo -> StrongFlags -> SolveExecutables -> SourcePackage loc -> (PN, I, PInfo)
-convSP os arch cinfo strfl solveExes (SourcePackage (PackageIdentifier pn pv) gpd _ _pl) =
+convSP :: OS -> Arch -> CompilerInfo -> Map PN [LabeledPackageConstraint]
+       -> StrongFlags -> SolveExecutables -> SourcePackage loc -> (PN, I, PInfo)
+convSP os arch cinfo constraints strfl solveExes (SourcePackage (PackageIdentifier pn pv) gpd _ _pl) =
   let i = I pv InRepo
-  in  (pn, i, convGPD os arch cinfo strfl solveExes pn gpd)
+      pkgConstraints = fromMaybe [] $ M.lookup pn constraints
+  in  (pn, i, convGPD os arch cinfo pkgConstraints strfl solveExes pn gpd)
 
 -- We do not use 'flattenPackageDescription' or 'finalizePD'
 -- from 'Distribution.PackageDescription.Configuration' here, because we
 -- want to keep the condition tree, but simplify much of the test.
 
 -- | Convert a generic package description to a solver-specific 'PInfo'.
-convGPD :: OS -> Arch -> CompilerInfo -> StrongFlags -> SolveExecutables ->
-           PN -> GenericPackageDescription -> PInfo
-convGPD os arch cinfo strfl solveExes pn
+convGPD :: OS -> Arch -> CompilerInfo -> [LabeledPackageConstraint]
+        -> StrongFlags -> SolveExecutables -> PN -> GenericPackageDescription
+        -> PInfo
+convGPD os arch cinfo constraints strfl solveExes pn
         (GenericPackageDescription pkg flags mlib sub_libs flibs exes tests benchs) =
   let
     fds  = flagInfo strfl flags
@@ -172,10 +186,10 @@
     conv :: Mon.Monoid a => Component -> (a -> BuildInfo) -> DependencyReason PN ->
             CondTree ConfVar [Dependency] a -> FlaggedDeps PN
     conv comp getInfo dr =
-        convCondTree dr pkg os arch cinfo pn fds comp getInfo ipns solveExes .
+        convCondTree M.empty dr pkg os arch cinfo pn fds comp getInfo ipns solveExes .
         PDC.addBuildableCondition getInfo
 
-    initDR = DependencyReason pn [] []
+    initDR = DependencyReason pn M.empty S.empty
 
     flagged_deps
         = concatMap (\ds ->       conv ComponentLib         libBuildInfo        initDR ds) (maybeToList mlib)
@@ -191,7 +205,7 @@
        ++ maybe []  (convSetupBuildInfo pn) (setupBuildInfo pkg)
 
     addStanza :: Stanza -> DependencyReason pn -> DependencyReason pn
-    addStanza s (DependencyReason pn' fs ss) = DependencyReason pn' fs (s : ss)
+    addStanza s (DependencyReason pn' fs ss) = DependencyReason pn' fs (S.insert s ss)
 
     -- | We infer the maximally supported spec-version from @lib:Cabal@'s version
     --
@@ -221,9 +235,82 @@
     -- forced to, emit a meaningful solver error message).
     fr | reqSpecVer > maxSpecVer = Just (UnsupportedSpecVer reqSpecVer)
        | otherwise               = Nothing
-  in
-    PInfo flagged_deps (L.map fst exes) fds fr
 
+    components :: Map ExposedComponent IsBuildable
+    components = M.fromList $ libComps ++ exeComps
+      where
+        libComps = [ (ExposedLib, IsBuildable $ isBuildable libBuildInfo lib)
+                   | lib <- maybeToList mlib ]
+        exeComps = [ (ExposedExe name, IsBuildable $ isBuildable buildInfo exe)
+                   | (name, exe) <- exes ]
+        isBuildable = isBuildableComponent os arch cinfo constraints
+
+  in PInfo flagged_deps components fds fr
+
+-- | Returns true if the component is buildable in the given environment.
+-- This function can give false-positives. For example, it only considers flags
+-- that are set by unqualified flag constraints, and it doesn't check whether
+-- the intra-package dependencies of a component are buildable. It is also
+-- possible for the solver to later assign a value to an automatic flag that
+-- makes the component unbuildable.
+isBuildableComponent :: OS
+                     -> Arch
+                     -> CompilerInfo
+                     -> [LabeledPackageConstraint]
+                     -> (a -> BuildInfo)
+                     -> CondTree ConfVar [Dependency] a
+                     -> Bool
+isBuildableComponent os arch cinfo constraints getInfo tree =
+    case simplifyCondition $ extractCondition (buildable . getInfo) tree of
+      Lit False -> False
+      _         -> True
+  where
+    flagAssignment :: [(FlagName, Bool)]
+    flagAssignment =
+        mconcat [ unFlagAssignment fa
+                | PackageConstraint (ScopeAnyQualifier _) (PackagePropertyFlags fa)
+                    <- L.map unlabelPackageConstraint constraints]
+
+    -- Simplify the condition, using the current environment. Most of this
+    -- function was copied from convBranch and
+    -- Distribution.Types.Condition.simplifyCondition.
+    simplifyCondition :: Condition ConfVar -> Condition ConfVar
+    simplifyCondition (Var (OS os')) = Lit (os == os')
+    simplifyCondition (Var (Arch arch')) = Lit (arch == arch')
+    simplifyCondition (Var (Impl cf cvr))
+        | matchImpl (compilerInfoId cinfo) ||
+              -- fixme: Nothing should be treated as unknown, rather than empty
+              --        list. This code should eventually be changed to either
+              --        support partial resolution of compiler flags or to
+              --        complain about incompletely configured compilers.
+          any matchImpl (fromMaybe [] $ compilerInfoCompat cinfo) = Lit True
+        | otherwise = Lit False
+      where
+        matchImpl (CompilerId cf' cv) = cf == cf' && checkVR cvr cv
+    simplifyCondition (Var (Flag f))
+        | Just b <- L.lookup f flagAssignment = Lit b
+    simplifyCondition (Var v) = Var v
+    simplifyCondition (Lit b) = Lit b
+    simplifyCondition (CNot c) =
+        case simplifyCondition c of
+          Lit True -> Lit False
+          Lit False -> Lit True
+          c' -> CNot c'
+    simplifyCondition (COr c d) =
+        case (simplifyCondition c, simplifyCondition d) of
+          (Lit False, d') -> d'
+          (Lit True, _)   -> Lit True
+          (c', Lit False) -> c'
+          (_, Lit True)   -> Lit True
+          (c', d')        -> COr c' d'
+    simplifyCondition (CAnd c d) =
+        case (simplifyCondition c, simplifyCondition d) of
+          (Lit False, _) -> Lit False
+          (Lit True, d') -> d'
+          (_, Lit False) -> Lit False
+          (c', Lit True) -> c'
+          (c', d')       -> CAnd c' d'
+
 -- | Create a flagged dependency tree from a list @fds@ of flagged
 -- dependencies, using @f@ to form the tree node (@f@ will be
 -- something like @Stanza sn@).
@@ -245,29 +332,35 @@
 -- dependencies.
 type IPNs = Set PN
 
--- | Convenience function to delete a 'FlaggedDep' if it's
+-- | Convenience function to delete a 'Dependency' if it's
 -- for a 'PN' that isn't actually real.
-filterIPNs :: IPNs -> Dependency -> FlaggedDep PN -> FlaggedDeps PN
-filterIPNs ipns (Dependency pn _) fd
-    | S.notMember pn ipns = [fd]
-    | otherwise           = []
+filterIPNs :: IPNs -> Dependency -> Maybe Dependency
+filterIPNs ipns d@(Dependency pn _)
+    | S.notMember pn ipns = Just d
+    | otherwise           = Nothing
 
 -- | Convert condition trees to flagged dependencies.  Mutually
 -- recursive with 'convBranch'.  See 'convBranch' for an explanation
 -- of all arguments preceeding the input 'CondTree'.
-convCondTree :: DependencyReason PN -> PackageDescription -> OS -> Arch -> CompilerInfo -> PN -> FlagInfo ->
+convCondTree :: Map FlagName Bool -> DependencyReason PN -> PackageDescription -> OS -> Arch -> CompilerInfo -> PN -> FlagInfo ->
                 Component ->
                 (a -> BuildInfo) ->
                 IPNs ->
                 SolveExecutables ->
                 CondTree ConfVar [Dependency] a -> FlaggedDeps PN
-convCondTree dr pkg os arch cinfo pn fds comp getInfo ipns solveExes@(SolveExecutables solveExes') (CondNode info ds branches) =
-                 concatMap
-                    (\d -> filterIPNs ipns d (D.Simple (convLibDep dr d) comp))             ds  -- unconditional package dependencies
+convCondTree flags dr pkg os arch cinfo pn fds comp getInfo ipns solveExes@(SolveExecutables solveExes') (CondNode info ds branches) =
+             -- Merge all library and build-tool dependencies at every level in
+             -- the tree of flagged dependencies. Otherwise 'extractCommon'
+             -- could create duplicate dependencies, and the number of
+             -- duplicates could grow exponentially from the leaves to the root
+             -- of the tree.
+             mergeSimpleDeps $
+                 L.map (\d -> D.Simple (convLibDep dr d) comp)
+                       (mapMaybe (filterIPNs ipns) ds)                                -- unconditional package dependencies
               ++ L.map (\e -> D.Simple (LDep dr (Ext  e)) comp) (PD.allExtensions bi) -- unconditional extension dependencies
               ++ L.map (\l -> D.Simple (LDep dr (Lang l)) comp) (PD.allLanguages  bi) -- unconditional language dependencies
               ++ L.map (\(PkgconfigDependency pkn vr) -> D.Simple (LDep dr (Pkg pkn vr)) comp) (PD.pkgconfigDepends bi) -- unconditional pkg-config dependencies
-              ++ concatMap (convBranch dr pkg os arch cinfo pn fds comp getInfo ipns solveExes) branches
+              ++ concatMap (convBranch flags dr pkg os arch cinfo pn fds comp getInfo ipns solveExes) branches
               -- build-tools dependencies
               -- NB: Only include these dependencies if SolveExecutables
               -- is True.  It might be false in the legacy solver
@@ -281,6 +374,58 @@
   where
     bi = getInfo info
 
+data SimpleFlaggedDepKey qpn =
+    SimpleFlaggedDepKey (PkgComponent qpn) Component
+  deriving (Eq, Ord)
+
+data SimpleFlaggedDepValue qpn = SimpleFlaggedDepValue (DependencyReason qpn) VR
+
+-- | Merge 'Simple' dependencies that apply to the same library or build-tool.
+-- This function should be able to merge any two dependencies that can be merged
+-- by extractCommon, in order to prevent the exponential growth of dependencies.
+--
+-- Note that this function can merge dependencies that have different
+-- DependencyReasons, which can make the DependencyReasons less precise. This
+-- loss of precision only affects performance and log messages, not correctness.
+-- However, when 'mergeSimpleDeps' is only called on dependencies at a single
+-- location in the dependency tree, the only difference between
+-- DependencyReasons should be flags that have value FlagBoth. Adding extra
+-- flags with value FlagBoth should not affect performance, since they are not
+-- added to the conflict set. The only downside is the possibility of the log
+-- incorrectly saying that the flag contributed to excluding a specific version
+-- of a dependency. For example, if +/-flagA introduces pkg >=2 and +/-flagB
+-- introduces pkg <5, the merged dependency would mean that
+-- +/-flagA and +/-flagB introduce pkg >=2 && <5, which would incorrectly imply
+-- that +/-flagA excludes pkg-6.
+mergeSimpleDeps :: Ord qpn => FlaggedDeps qpn -> FlaggedDeps qpn
+mergeSimpleDeps deps = L.map (uncurry toFlaggedDep) (M.toList merged) ++ unmerged
+  where
+    (merged, unmerged) = L.foldl' f (M.empty, []) deps
+      where
+        f :: Ord qpn
+          => (Map (SimpleFlaggedDepKey qpn) (SimpleFlaggedDepValue qpn), FlaggedDeps qpn)
+          -> FlaggedDep qpn
+          -> (Map (SimpleFlaggedDepKey qpn) (SimpleFlaggedDepValue qpn), FlaggedDeps qpn)
+        f (merged', unmerged') (D.Simple (LDep dr (Dep dep (Constrained vr))) comp) =
+            ( M.insertWith mergeValues
+                           (SimpleFlaggedDepKey dep comp)
+                           (SimpleFlaggedDepValue dr vr)
+                           merged'
+            , unmerged')
+        f (merged', unmerged') unmergeableDep = (merged', unmergeableDep : unmerged')
+
+        mergeValues :: SimpleFlaggedDepValue qpn
+                    -> SimpleFlaggedDepValue qpn
+                    -> SimpleFlaggedDepValue qpn
+        mergeValues (SimpleFlaggedDepValue dr1 vr1) (SimpleFlaggedDepValue dr2 vr2) =
+            SimpleFlaggedDepValue (unionDRs dr1 dr2) (vr1 .&&. vr2)
+
+    toFlaggedDep :: SimpleFlaggedDepKey qpn
+                 -> SimpleFlaggedDepValue qpn
+                 -> FlaggedDep qpn
+    toFlaggedDep (SimpleFlaggedDepKey dep comp) (SimpleFlaggedDepValue dr vr) =
+        D.Simple (LDep dr (Dep dep (Constrained vr))) comp
+
 -- | Branch interpreter.  Mutually recursive with 'convCondTree'.
 --
 -- Here, we try to simplify one of Cabal's condition tree branches into the
@@ -292,61 +437,81 @@
 --
 -- This function takes a number of arguments:
 --
---      1. Some pre dependency-solving known information ('OS', 'Arch',
+--      1. A map of flag values that have already been chosen. It allows
+--         convBranch to avoid creating nested FlaggedDeps that are
+--         controlled by the same flag and avoid creating DependencyReasons with
+--         conflicting values for the same flag.
+--
+--      2. The DependencyReason calculated at this point in the tree of
+--         conditionals. The flag values in the DependencyReason are similar to
+--         the values in the map above, except for the use of FlagBoth.
+--
+--      3. Some pre dependency-solving known information ('OS', 'Arch',
 --         'CompilerInfo') for @os()@, @arch()@ and @impl()@ variables,
 --
---      2. The package name @'PN'@ which this condition tree
+--      4. The package name @'PN'@ which this condition tree
 --         came from, so that we can correctly associate @flag()@
 --         variables with the correct package name qualifier,
 --
---      3. The flag defaults 'FlagInfo' so that we can populate
+--      5. The flag defaults 'FlagInfo' so that we can populate
 --         'Flagged' dependencies with 'FInfo',
 --
---      4. The name of the component 'Component' so we can record where
+--      6. The name of the component 'Component' so we can record where
 --         the fine-grained information about where the component came
 --         from (see 'convCondTree'), and
 --
---      5. A selector to extract the 'BuildInfo' from the leaves of
+--      7. A selector to extract the 'BuildInfo' from the leaves of
 --         the 'CondTree' (which actually contains the needed
 --         dependency information.)
 --
---      6. The set of package names which should be considered internal
+--      8. The set of package names which should be considered internal
 --         dependencies, and thus not handled as dependencies.
-convBranch :: DependencyReason PN -> PackageDescription -> OS -> Arch -> CompilerInfo ->
-              PN -> FlagInfo ->
-              Component ->
-              (a -> BuildInfo) ->
-              IPNs ->
-              SolveExecutables ->
-              CondBranch ConfVar [Dependency] a ->
-              FlaggedDeps PN
-convBranch dr pkg os arch cinfo pn fds comp getInfo ipns solveExes (CondBranch c' t' mf') =
+convBranch :: Map FlagName Bool
+           -> DependencyReason PN
+           -> PackageDescription
+           -> OS
+           -> Arch
+           -> CompilerInfo
+           -> PN
+           -> FlagInfo
+           -> Component
+           -> (a -> BuildInfo)
+           -> IPNs
+           -> SolveExecutables
+           -> CondBranch ConfVar [Dependency] a
+           -> FlaggedDeps PN
+convBranch flags dr pkg os arch cinfo pn fds comp getInfo ipns solveExes (CondBranch c' t' mf') =
     go c'
-       (\dr' ->           convCondTree dr' pkg os arch cinfo pn fds comp getInfo ipns solveExes  t')
-       (\dr' -> maybe [] (convCondTree dr' pkg os arch cinfo pn fds comp getInfo ipns solveExes) mf')
-       dr
+       (\flags' dr' ->           convCondTree flags' dr' pkg os arch cinfo pn fds comp getInfo ipns solveExes  t')
+       (\flags' dr' -> maybe [] (convCondTree flags' dr' pkg os arch cinfo pn fds comp getInfo ipns solveExes) mf')
+       flags dr
   where
     go :: Condition ConfVar
-       -> (DependencyReason PN -> FlaggedDeps PN)
-       -> (DependencyReason PN -> FlaggedDeps PN)
-       ->  DependencyReason PN -> FlaggedDeps PN
+       -> (Map FlagName Bool -> DependencyReason PN -> FlaggedDeps PN)
+       -> (Map FlagName Bool -> DependencyReason PN -> FlaggedDeps PN)
+       ->  Map FlagName Bool -> DependencyReason PN -> FlaggedDeps PN
     go (Lit True)  t _ = t
     go (Lit False) _ f = f
     go (CNot c)    t f = go c f t
     go (CAnd c d)  t f = go c (go d t f) f
     go (COr  c d)  t f = go c t (go d t f)
-    go (Var (Flag fn)) t f = \dr' ->
-         -- Add each flag to the DependencyReason for all dependencies below,
-         -- including any extracted dependencies. Extracted dependencies are
-         -- introduced by both flag values (FlagBoth). Note that we don't
-         -- actually need to add the flag to the extracted dependencies for
-         -- correct backjumping; the information only improves log messages by
-         -- giving the user the full reason for each dependency.
-         let addFlagVal v = addFlag fn v dr'
-         in extractCommon (t (addFlagVal FlagBoth))
-                          (f (addFlagVal FlagBoth))
-             ++ [ Flagged (FN pn fn) (fds ! fn) (t (addFlagVal FlagTrue))
-                                                (f (addFlagVal FlagFalse)) ]
+    go (Var (Flag fn)) t f = \flags' ->
+        case M.lookup fn flags' of
+          Just True  -> t flags'
+          Just False -> f flags'
+          Nothing    -> \dr' ->
+            -- Add each flag to the DependencyReason for all dependencies below,
+            -- including any extracted dependencies. Extracted dependencies are
+            -- introduced by both flag values (FlagBoth). Note that we don't
+            -- actually need to add the flag to the extracted dependencies for
+            -- correct backjumping; the information only improves log messages
+            -- by giving the user the full reason for each dependency.
+            let addFlagValue v = addFlagToDependencyReason fn v dr'
+                addFlag v = M.insert fn v flags'
+            in extractCommon (t (addFlag True)  (addFlagValue FlagBoth))
+                             (f (addFlag False) (addFlagValue FlagBoth))
+                ++ [ Flagged (FN pn fn) (fds M.! fn) (t (addFlag True)  (addFlagValue FlagTrue))
+                                                     (f (addFlag False) (addFlagValue FlagFalse)) ]
     go (Var (OS os')) t f
       | os == os'      = t
       | otherwise      = f
@@ -364,9 +529,9 @@
       where
         matchImpl (CompilerId cf' cv) = cf == cf' && checkVR cvr cv
 
-    addFlag :: FlagName -> FlagValue -> DependencyReason pn -> DependencyReason pn
-    addFlag fn v (DependencyReason pn' flags stanzas) =
-        DependencyReason pn' ((fn, v) : flags) stanzas
+    addFlagToDependencyReason :: FlagName -> FlagValue -> DependencyReason pn -> DependencyReason pn
+    addFlagToDependencyReason fn v (DependencyReason pn' fs ss) =
+        DependencyReason pn' (M.insert fn v fs) ss
 
     -- If both branches contain the same package as a simple dep, we lift it to
     -- the next higher-level, but with the union of version ranges. This
@@ -381,29 +546,30 @@
     -- WARNING: This is quadratic!
     extractCommon :: Eq pn => FlaggedDeps pn -> FlaggedDeps pn -> FlaggedDeps pn
     extractCommon ps ps' =
-        [ D.Simple (LDep (mergeDRs vs1 vs2) (Dep is_exe1 pn1 (Constrained $ vr1 .||. vr2))) comp
-        | D.Simple (LDep vs1                (Dep is_exe1 pn1 (Constrained vr1))) _ <- ps
-        , D.Simple (LDep vs2                (Dep is_exe2 pn2 (Constrained vr2))) _ <- ps'
-        , pn1 == pn2
-        , is_exe1 == is_exe2
-        ]
-      where
-        -- Merge the DependencyReasons, because the extracted dependency can be
+        -- Union the DependencyReasons, because the extracted dependency can be
         -- avoided by removing the dependency from either side of the
         -- conditional.
-        mergeDRs :: DependencyReason pn -> DependencyReason pn -> DependencyReason pn
-        mergeDRs (DependencyReason pn' fs1 ss1) (DependencyReason _ fs2 ss2) =
-            DependencyReason pn' (nub $ fs1 ++ fs2) (nub $ ss1 ++ ss2)
+        [ D.Simple (LDep (unionDRs vs1 vs2) (Dep dep1 (Constrained $ vr1 .||. vr2))) comp
+        | D.Simple (LDep vs1                (Dep dep1 (Constrained vr1))) _ <- ps
+        , D.Simple (LDep vs2                (Dep dep2 (Constrained vr2))) _ <- ps'
+        , dep1 == dep2
+        ]
 
+-- | Merge DependencyReasons by unioning their variables.
+unionDRs :: DependencyReason pn -> DependencyReason pn -> DependencyReason pn
+unionDRs (DependencyReason pn' fs1 ss1) (DependencyReason _ fs2 ss2) =
+    DependencyReason pn' (M.union fs1 fs2) (S.union ss1 ss2)
+
 -- | Convert a Cabal dependency on a library to a solver-specific dependency.
 convLibDep :: DependencyReason PN -> Dependency -> LDep PN
-convLibDep dr (Dependency pn vr) = LDep dr $ Dep Nothing pn (Constrained vr)
+convLibDep dr (Dependency pn vr) = LDep dr $ Dep (PkgComponent pn ExposedLib) (Constrained vr)
 
 -- | Convert a Cabal dependency on an executable (build-tools) to a solver-specific dependency.
 convExeDep :: DependencyReason PN -> ExeDependency -> LDep PN
-convExeDep dr (ExeDependency pn exe vr) = LDep dr $ Dep (Just exe) pn (Constrained vr)
+convExeDep dr (ExeDependency pn exe vr) = LDep dr $ Dep (PkgComponent pn (ExposedExe exe)) (Constrained vr)
 
 -- | Convert setup dependencies
 convSetupBuildInfo :: PN -> SetupBuildInfo -> FlaggedDeps PN
 convSetupBuildInfo pn nfo =
-    L.map (\d -> D.Simple (convLibDep (DependencyReason pn [] []) d) ComponentSetup) (PD.setupDepends nfo)
+    L.map (\d -> D.Simple (convLibDep (DependencyReason pn M.empty S.empty) d) ComponentSetup)
+          (PD.setupDepends nfo)
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/Linking.hs b/cabal/cabal-install/Distribution/Solver/Modular/Linking.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/Linking.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/Linking.hs
@@ -245,7 +245,7 @@
 
     go1 :: FlaggedDep QPN -> FlaggedDep QPN -> UpdateState ()
     go1 dep rdep = case (dep, rdep) of
-      (Simple (LDep dr1 (Dep _ qpn _)) _, ~(Simple (LDep dr2 (Dep _ qpn' _)) _)) -> do
+      (Simple (LDep dr1 (Dep (PkgComponent qpn _) _)) _, ~(Simple (LDep dr2 (Dep (PkgComponent qpn' _) _)) _)) -> do
         vs <- get
         let lg   = M.findWithDefault (lgSingleton qpn  Nothing) qpn  $ vsLinks vs
             lg'  = M.findWithDefault (lgSingleton qpn' Nothing) qpn' $ vsLinks vs
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/Log.hs b/cabal/cabal-install/Distribution/Solver/Modular/Log.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/Log.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/Log.hs
@@ -1,92 +1,56 @@
 module Distribution.Solver.Modular.Log
-    ( Log
-    , logToProgress
+    ( logToProgress
+    , SolverFailure(..)
     ) where
 
 import Prelude ()
 import Distribution.Solver.Compat.Prelude
 
-import Data.List as L
-
 import Distribution.Solver.Types.Progress
 
 import Distribution.Solver.Modular.Dependency
 import Distribution.Solver.Modular.Message
-import Distribution.Solver.Modular.Tree (FailReason(..))
 import qualified Distribution.Solver.Modular.ConflictSet as CS
+import Distribution.Solver.Modular.RetryLog
 import Distribution.Verbosity
 
--- | The 'Log' datatype.
---
--- Represents the progress of a computation lazily.
---
--- Parameterized over the type of actual messages and the final result.
-type Log m a = Progress m (ConflictSet, ConflictMap) a
-
-messages :: Progress step fail done -> [step]
-messages = foldProgress (:) (const []) (const [])
-
-data Exhaustiveness = Exhaustive | BackjumpLimitReached
+-- | Information about a dependency solver failure.
+data SolverFailure =
+    ExhaustiveSearch ConflictSet ConflictMap
+  | BackjumpLimitReached
 
--- | Postprocesses a log file. Takes as an argument a limit on allowed backjumps.
--- If the limit is 'Nothing', then infinitely many backjumps are allowed. If the
--- limit is 'Just 0', backtracking is completely disabled.
-logToProgress :: Verbosity -> Maybe Int -> Log Message a -> Progress String String a
-logToProgress verbosity mbj l =
-    let es = proc (Just 0) l -- catch first error (always)
-        ms = proc mbj l
-    in go es es -- trace for first error
-          (showMessages (const True) True ms) -- run with backjump limit applied
+-- | Postprocesses a log file. When the dependency solver fails to find a
+-- solution, the log ends with a SolverFailure and a message describing the
+-- failure. This function discards all log messages and avoids calling
+-- 'showMessages' if the log isn't needed (specified by 'keepLog'), for
+-- efficiency.
+logToProgress :: Bool
+              -> Verbosity
+              -> Maybe Int
+              -> RetryLog Message SolverFailure a
+              -> Progress String (SolverFailure, String) a
+logToProgress keepLog verbosity mbj lg =
+    if keepLog
+    then showMessages progress
+    else foldProgress (const id) Fail Done progress
   where
-    -- Proc takes the allowed number of backjumps and a 'Progress' and explores the
-    -- messages until the maximum number of backjumps has been reached. It filters out
-    -- and ignores repeated backjumps. If proc reaches the backjump limit, it truncates
-    -- the 'Progress' and ends it with the last conflict set. Otherwise, it leaves the
-    -- original result.
-    proc :: Maybe Int -> Log Message b -> Progress Message (Exhaustiveness, ConflictSet, ConflictMap) b
-    proc _        (Done x)                          = Done x
-    proc _        (Fail (cs, cm))                   = Fail (Exhaustive, cs, cm)
-    proc mbj'     (Step x@(Failure cs Backjump) xs@(Step Leave (Step (Failure cs' Backjump) _)))
-      | cs == cs'                                   = Step x (proc mbj'           xs) -- repeated backjumps count as one
-    proc (Just 0) (Step   (Failure cs Backjump)  _) = Fail (BackjumpLimitReached, cs, mempty) -- No final conflict map available
-    proc (Just n) (Step x@(Failure _  Backjump) xs) = Step x (proc (Just (n - 1)) xs)
-    proc mbj'     (Step x                       xs) = Step x (proc mbj'           xs)
+    progress =
+        -- Convert the RetryLog to a Progress (with toProgress) as late as
+        -- possible, to take advantage of efficient updates at failures.
+        toProgress $
+        mapFailure (\failure -> (failure, finalErrorMsg failure)) lg
 
-    -- The first two arguments are both supposed to be the log up to the first error.
-    -- That's the error that will always be printed in case we do not find a solution.
-    -- We pass this log twice, because we evaluate it in parallel with the full log,
-    -- but we also want to retain the reference to its beginning for when we print it.
-    -- This trick prevents a space leak!
-    --
-    -- The third argument is the full log, ending with either the solution or the
-    -- exhaustiveness and final conflict set.
-    go :: Progress Message (Exhaustiveness, ConflictSet, ConflictMap) b
-       -> Progress Message (Exhaustiveness, ConflictSet, ConflictMap) b
-       -> Progress String  (Exhaustiveness, ConflictSet, ConflictMap) b
-       -> Progress String String b
-    go ms (Step _ ns)        (Step x xs)           = Step x (go ms ns xs)
-    go ms r                  (Step x xs)           = Step x (go ms r  xs)
-    go ms (Step _ ns)        r                     = go ms ns r
-    go ms (Fail (_, cs', _)) (Fail (exh, cs, cm))  = Fail $
-        "Could not resolve dependencies:\n" ++
-        unlines (messages $ showMessages (L.foldr (\ v _ -> v `CS.member` cs') True) False ms) ++
-        case exh of
-            Exhaustive ->
-                "After searching the rest of the dependency tree exhaustively, "
-                ++ "these were the goals I've had most trouble fulfilling: "
-                ++ showCS cm cs
-              where
-                showCS = if verbosity > normal
-                         then CS.showCSWithFrequency
-                         else CS.showCSSortedByFrequency
-            BackjumpLimitReached ->
-                "Backjump limit reached (" ++ currlimit mbj ++
-                "change with --max-backjumps or try to run with --reorder-goals).\n"
-              where currlimit (Just n) = "currently " ++ show n ++ ", "
-                    currlimit Nothing  = ""
-    go _  _                  (Done s)              = Done s
-    go _  (Done _)           (Fail _)              = Fail $
-        -- Should not happen: Second argument is the log up to first error,
-        -- third one is the entire log. Therefore it should never happen that
-        -- the second log finishes with 'Done' and the third log with 'Fail'.
-        "Could not resolve dependencies; something strange happened."
+    finalErrorMsg :: SolverFailure -> String
+    finalErrorMsg (ExhaustiveSearch cs cm) =
+        "After searching the rest of the dependency tree exhaustively, "
+        ++ "these were the goals I've had most trouble fulfilling: "
+        ++ showCS cm cs
+      where
+        showCS = if verbosity > normal
+                 then CS.showCSWithFrequency
+                 else CS.showCSSortedByFrequency
+    finalErrorMsg BackjumpLimitReached =
+        "Backjump limit reached (" ++ currlimit mbj ++
+        "change with --max-backjumps or try to run with --reorder-goals).\n"
+      where currlimit (Just n) = "currently " ++ show n ++ ", "
+            currlimit Nothing  = ""
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/Message.hs b/cabal/cabal-install/Distribution/Solver/Modular/Message.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/Message.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/Message.hs
@@ -33,59 +33,40 @@
 
 -- | Transforms the structured message type to actual messages (strings).
 --
--- Takes an additional relevance predicate. The predicate gets a stack of goal
--- variables and can decide whether messages regarding these goals are relevant.
--- You can plug in 'const True' if you're interested in a full trace. If you
--- want a slice of the trace concerning a particular conflict set, then plug in
--- a predicate returning 'True' on the empty stack and if the head is in the
--- conflict set.
---
--- The second argument indicates if the level numbers should be shown. This is
--- recommended for any trace that involves backtracking, because only the level
--- numbers will allow to keep track of backjumps.
-showMessages :: ([Var QPN] -> Bool) -> Bool -> Progress Message a b -> Progress String a b
-showMessages p sl = go [] 0
+-- The log contains level numbers, which are useful for any trace that involves
+-- backtracking, because only the level numbers will allow to keep track of
+-- backjumps.
+showMessages :: Progress Message a b -> Progress String a b
+showMessages = go 0
   where
-    -- The stack 'v' represents variables that are currently assigned by the
-    -- solver.  'go' pushes a variable for a recursive call when it encounters
-    -- 'TryP', 'TryF', or 'TryS' and pops a variable when it encounters 'Leave'.
-    -- When 'go' processes a package goal, or a package goal followed by a
-    -- 'Failure', it calls 'atLevel' with the goal variable at the head of the
-    -- stack so that the predicate can also select messages relating to package
-    -- goal choices.
-    go :: [Var QPN] -> Int -> Progress Message a b -> Progress String a b
-    go !_ !_ (Done x)                           = Done x
-    go !_ !_ (Fail x)                           = Fail x
+    -- 'go' increments the level for a recursive call when it encounters
+    -- 'TryP', 'TryF', or 'TryS' and decrements the level when it encounters 'Leave'.
+    go :: Int -> Progress Message a b -> Progress String a b
+    go !_ (Done x)                           = Done x
+    go !_ (Fail x)                           = Fail x
     -- complex patterns
-    go !v !l (Step (TryP qpn i) (Step Enter (Step (Failure c fr) (Step Leave ms)))) =
-        goPReject v l qpn [i] c fr ms
-    go !v !l (Step (TryF qfn b) (Step Enter (Step (Failure c fr) (Step Leave ms)))) =
-        (atLevel (F qfn : v) l $ "rejecting: " ++ showQFNBool qfn b ++ showFR c fr) (go v l ms)
-    go !v !l (Step (TryS qsn b) (Step Enter (Step (Failure c fr) (Step Leave ms)))) =
-        (atLevel (S qsn : v) l $ "rejecting: " ++ showQSNBool qsn b ++ showFR c fr) (go v l ms)
-    go !v !l (Step (Next (Goal (P qpn) gr)) (Step (TryP qpn' i) ms@(Step Enter (Step (Next _) _)))) =
-        (atLevel (P qpn : v) l $ "trying: " ++ showQPNPOpt qpn' i ++ showGR gr) (go (P qpn : v) l ms)
-    go !v !l (Step (Next (Goal (P qpn) gr)) ms@(Fail _)) =
-        (atLevel (P qpn : v) l $ "unknown package: " ++ showQPN qpn ++ showGR gr) $ go v l ms
-        -- the previous case potentially arises in the error output, because we remove the backjump itself
-        -- if we cut the log after the first error
-    go !v !l (Step (Next (Goal (P qpn) gr)) ms@(Step (Failure _c Backjump) _)) =
-        (atLevel (P qpn : v) l $ "unknown package: " ++ showQPN qpn ++ showGR gr) $ go v l ms
-    go !v !l (Step (Next (Goal (P qpn) gr)) (Step (Failure c fr) ms)) =
-        let v' = P qpn : v
-        in (atLevel v' l $ showPackageGoal qpn gr) $ (atLevel v' l $ showFailure c fr) (go v l ms)
-    go !v !l (Step (Failure c Backjump) ms@(Step Leave (Step (Failure c' Backjump) _)))
-        | c == c' = go v l ms
+    go !l (Step (TryP qpn i) (Step Enter (Step (Failure c fr) (Step Leave ms)))) =
+        goPReject l qpn [i] c fr ms
+    go !l (Step (TryF qfn b) (Step Enter (Step (Failure c fr) (Step Leave ms)))) =
+        (atLevel l $ "rejecting: " ++ showQFNBool qfn b ++ showFR c fr) (go l ms)
+    go !l (Step (TryS qsn b) (Step Enter (Step (Failure c fr) (Step Leave ms)))) =
+        (atLevel l $ "rejecting: " ++ showQSNBool qsn b ++ showFR c fr) (go l ms)
+    go !l (Step (Next (Goal (P _  ) gr)) (Step (TryP qpn' i) ms@(Step Enter (Step (Next _) _)))) =
+        (atLevel l $ "trying: " ++ showQPNPOpt qpn' i ++ showGR gr) (go l ms)
+    go !l (Step (Next (Goal (P qpn) gr)) ms@(Step (Failure _c Backjump) _)) =
+        (atLevel l $ "unknown package: " ++ showQPN qpn ++ showGR gr) $ go l ms
+    go !l (Step (Next (Goal (P qpn) gr)) (Step (Failure c fr) ms)) =
+        (atLevel l $ showPackageGoal qpn gr) $ (atLevel l $ showFailure c fr) (go l ms)
     -- standard display
-    go !v !l (Step Enter                    ms) = go v          (l+1) ms
-    go !v !l (Step Leave                    ms) = go (drop 1 v) (l-1) ms
-    go !v !l (Step (TryP qpn i)             ms) = (atLevel (P qpn : v) l $ "trying: " ++ showQPNPOpt qpn i) (go (P qpn : v) l ms)
-    go !v !l (Step (TryF qfn b)             ms) = (atLevel (F qfn : v) l $ "trying: " ++ showQFNBool qfn b) (go (F qfn : v) l ms)
-    go !v !l (Step (TryS qsn b)             ms) = (atLevel (S qsn : v) l $ "trying: " ++ showQSNBool qsn b) (go (S qsn : v) l ms)
-    go !v !l (Step (Next (Goal (P qpn) gr)) ms) = (atLevel (P qpn : v) l $ showPackageGoal qpn gr) (go v l ms)
-    go !v !l (Step (Next _)                 ms) = go v l ms -- ignore flag goals in the log
-    go !v !l (Step (Success)                ms) = (atLevel v l $ "done") (go v l ms)
-    go !v !l (Step (Failure c fr)           ms) = (atLevel v l $ showFailure c fr) (go v l ms)
+    go !l (Step Enter                    ms) = go (l+1) ms
+    go !l (Step Leave                    ms) = go (l-1) ms
+    go !l (Step (TryP qpn i)             ms) = (atLevel l $ "trying: " ++ showQPNPOpt qpn i) (go l ms)
+    go !l (Step (TryF qfn b)             ms) = (atLevel l $ "trying: " ++ showQFNBool qfn b) (go l ms)
+    go !l (Step (TryS qsn b)             ms) = (atLevel l $ "trying: " ++ showQSNBool qsn b) (go l ms)
+    go !l (Step (Next (Goal (P qpn) gr)) ms) = (atLevel l $ showPackageGoal qpn gr) (go l ms)
+    go !l (Step (Next _)                 ms) = go l     ms -- ignore flag goals in the log
+    go !l (Step (Success)                ms) = (atLevel l $ "done") (go l ms)
+    go !l (Step (Failure c fr)           ms) = (atLevel l $ showFailure c fr) (go l ms)
 
     showPackageGoal :: QPN -> QGoalReason -> String
     showPackageGoal qpn gr = "next goal: " ++ showQPN qpn ++ showGR gr
@@ -94,26 +75,23 @@
     showFailure c fr = "fail" ++ showFR c fr
 
     -- special handler for many subsequent package rejections
-    goPReject :: [Var QPN]
-              -> Int
+    goPReject :: Int
               -> QPN
               -> [POption]
               -> ConflictSet
               -> FailReason
               -> Progress Message a b
               -> Progress String a b
-    goPReject v l qpn is c fr (Step (TryP qpn' i) (Step Enter (Step (Failure _ fr') (Step Leave ms))))
-      | qpn == qpn' && fr == fr' = goPReject v l qpn (i : is) c fr ms
-    goPReject v l qpn is c fr ms =
-        (atLevel (P qpn : v) l $ "rejecting: " ++ L.intercalate ", " (map (showQPNPOpt qpn) (reverse is)) ++ showFR c fr) (go v l ms)
+    goPReject l qpn is c fr (Step (TryP qpn' i) (Step Enter (Step (Failure _ fr') (Step Leave ms))))
+      | qpn == qpn' && fr == fr' = goPReject l qpn (i : is) c fr ms
+    goPReject l qpn is c fr ms =
+        (atLevel l $ "rejecting: " ++ L.intercalate ", " (map (showQPNPOpt qpn) (reverse is)) ++ showFR c fr) (go l ms)
 
-    -- write a message, but only if it's relevant; we can also enable or disable the display of the current level
-    atLevel :: [Var QPN] -> Int -> String -> Progress String a b -> Progress String a b
-    atLevel v l x xs
-      | sl && p v = let s = show l
-                    in  Step ("[" ++ replicate (3 - length s) '_' ++ s ++ "] " ++ x) xs
-      | p v       = Step x xs
-      | otherwise = xs
+    -- write a message with the current level number
+    atLevel :: Int -> String -> Progress String a b -> Progress String a b
+    atLevel l x xs =
+      let s = show l
+      in  Step ("[" ++ replicate (3 - length s) '_' ++ s ++ "] " ++ x) xs
 
 showQPNPOpt :: QPN -> POption -> String
 showQPNPOpt qpn@(Q _pp pn) (POption i linkedTo) =
@@ -131,8 +109,10 @@
 showFR _ (MissingPkgconfigPackage pn vr)  = " (conflict: pkg-config package " ++ display pn ++ display vr ++ ", not found in the pkg-config database)"
 showFR _ (NewPackageDoesNotMatchExistingConstraint d) = " (conflict: " ++ showConflictingDep d ++ ")"
 showFR _ (ConflictingConstraints d1 d2)   = " (conflict: " ++ L.intercalate ", " (L.map showConflictingDep [d1, d2]) ++ ")"
-showFR _ (NewPackageIsMissingRequiredExe exe dr) = " (does not contain executable " ++ unUnqualComponentName exe ++ ", which is required by " ++ showDependencyReason dr ++ ")"
-showFR _ (PackageRequiresMissingExe qpn exe) = " (requires executable " ++ unUnqualComponentName exe ++ " from " ++ showQPN qpn ++ ", but the executable does not exist)"
+showFR _ (NewPackageIsMissingRequiredComponent comp dr) = " (does not contain " ++ showExposedComponent comp ++ ", which is required by " ++ showDependencyReason dr ++ ")"
+showFR _ (NewPackageHasUnbuildableRequiredComponent comp dr) = " (" ++ showExposedComponent comp ++ " is not buildable in the current environment, but it is required by " ++ showDependencyReason dr ++ ")"
+showFR _ (PackageRequiresMissingComponent qpn comp) = " (requires " ++ showExposedComponent comp ++ " from " ++ showQPN qpn ++ ", but the component does not exist)"
+showFR _ (PackageRequiresUnbuildableComponent qpn comp) = " (requires " ++ showExposedComponent comp ++ " from " ++ showQPN qpn ++ ", but the component is not buildable in the current environment)"
 showFR _ CannotInstall                    = " (only already installed instances can be used)"
 showFR _ CannotReinstall                  = " (avoiding to reinstall a package with same version but new dependencies)"
 showFR _ Shadowed                         = " (shadowed by another installed package with same version)"
@@ -154,17 +134,21 @@
 showFR _ (MalformedStanzaChoice qsn)      = " (INTERNAL ERROR: MALFORMED STANZA CHOICE: " ++ showQSN qsn ++ ")"
 showFR _ EmptyGoalChoice                  = " (INTERNAL ERROR: EMPTY GOAL CHOICE)"
 
+showExposedComponent :: ExposedComponent -> String
+showExposedComponent ExposedLib = "library"
+showExposedComponent (ExposedExe name) = "executable '" ++ unUnqualComponentName name ++ "'"
+
 constraintSource :: ConstraintSource -> String
 constraintSource src = "constraint from " ++ showConstraintSource src
 
 showConflictingDep :: ConflictingDep -> String
-showConflictingDep (ConflictingDep dr mExe qpn ci) =
+showConflictingDep (ConflictingDep dr (PkgComponent qpn comp) ci) =
   let DependencyReason qpn' _ _ = dr
-      exeStr = case mExe of
-                 Just exe -> " (exe " ++ unUnqualComponentName exe ++ ")"
-                 Nothing  -> ""
+      componentStr = case comp of
+                       ExposedExe exe -> " (exe " ++ unUnqualComponentName exe ++ ")"
+                       ExposedLib     -> ""
   in case ci of
        Fixed i        -> (if qpn /= qpn' then showDependencyReason dr ++ " => " else "") ++
-                         showQPN qpn ++ exeStr ++ "==" ++ showI i
+                         showQPN qpn ++ componentStr ++ "==" ++ showI i
        Constrained vr -> showDependencyReason dr ++ " => " ++ showQPN qpn ++
-                         exeStr ++ showVR vr
+                         componentStr ++ showVR vr
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/Preference.hs b/cabal/cabal-install/Distribution/Solver/Modular/Preference.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/Preference.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/Preference.hs
@@ -14,6 +14,7 @@
     , preferReallyEasyGoalChoices
     , requireInstalled
     , sortGoals
+    , pruneAfterFirstSuccess
     ) where
 
 import Prelude ()
@@ -350,6 +351,17 @@
     varToVariable (P qpn)                    = PackageVar qpn
     varToVariable (F (FN qpn fn))     = FlagVar qpn fn
     varToVariable (S (SN qpn stanza)) = StanzaVar qpn stanza
+
+-- | Reduce the branching degree of the search tree by removing all choices
+-- after the first successful choice at each level. The returned tree is the
+-- minimal subtree containing the path to the first backjump.
+pruneAfterFirstSuccess :: Tree d c -> Tree d c
+pruneAfterFirstSuccess = trav go
+  where
+    go (PChoiceF qpn rdm gr       ts) = PChoiceF qpn rdm gr       (W.takeUntil active ts)
+    go (FChoiceF qfn rdm gr w m d ts) = FChoiceF qfn rdm gr w m d (W.takeUntil active ts)
+    go (SChoiceF qsn rdm gr w     ts) = SChoiceF qsn rdm gr w     (W.takeUntil active ts)
+    go x                              = x
 
 -- | Always choose the first goal in the list next, abandoning all
 -- other choices.
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/Solver.hs b/cabal/cabal-install/Distribution/Solver/Modular/Solver.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/Solver.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/Solver.hs
@@ -6,6 +6,7 @@
 module Distribution.Solver.Modular.Solver
     ( SolverConfig(..)
     , solve
+    , PruneAfterFirstSuccess(..)
     ) where
 
 import Data.Map as M
@@ -35,6 +36,7 @@
 import Distribution.Solver.Modular.Validate
 import Distribution.Solver.Modular.Linking
 import Distribution.Solver.Modular.PSQ (PSQ)
+import Distribution.Solver.Modular.RetryLog
 import Distribution.Solver.Modular.Tree
 import qualified Distribution.Solver.Modular.PSQ as PSQ
 
@@ -53,20 +55,25 @@
 
 -- | Various options for the modular solver.
 data SolverConfig = SolverConfig {
-  reorderGoals          :: ReorderGoals,
-  countConflicts        :: CountConflicts,
-  independentGoals      :: IndependentGoals,
-  avoidReinstalls       :: AvoidReinstalls,
-  shadowPkgs            :: ShadowPkgs,
-  strongFlags           :: StrongFlags,
-  allowBootLibInstalls  :: AllowBootLibInstalls,
-  maxBackjumps          :: Maybe Int,
-  enableBackjumping     :: EnableBackjumping,
-  solveExecutables      :: SolveExecutables,
-  goalOrder             :: Maybe (Variable QPN -> Variable QPN -> Ordering),
-  solverVerbosity       :: Verbosity
+  reorderGoals           :: ReorderGoals,
+  countConflicts         :: CountConflicts,
+  independentGoals       :: IndependentGoals,
+  avoidReinstalls        :: AvoidReinstalls,
+  shadowPkgs             :: ShadowPkgs,
+  strongFlags            :: StrongFlags,
+  allowBootLibInstalls   :: AllowBootLibInstalls,
+  maxBackjumps           :: Maybe Int,
+  enableBackjumping      :: EnableBackjumping,
+  solveExecutables       :: SolveExecutables,
+  goalOrder              :: Maybe (Variable QPN -> Variable QPN -> Ordering),
+  solverVerbosity        :: Verbosity,
+  pruneAfterFirstSuccess :: PruneAfterFirstSuccess
 }
 
+-- | Whether to remove all choices after the first successful choice at each
+-- level in the search tree.
+newtype PruneAfterFirstSuccess = PruneAfterFirstSuccess Bool
+
 -- | Run all solver phases.
 --
 -- In principle, we have a valid tree after 'validationPhase', which
@@ -83,7 +90,7 @@
       -> (PN -> PackagePreferences)           -- ^ preferences
       -> Map PN [LabeledPackageConstraint]    -- ^ global constraints
       -> Set PN                               -- ^ global goals
-      -> Log Message (Assignment, RevDepMap)
+      -> RetryLog Message SolverFailure (Assignment, RevDepMap)
 solve sc cinfo idx pkgConfigDB userPrefs userConstraints userGoals =
   explorePhase     $
   detectCycles     $
@@ -93,19 +100,24 @@
   prunePhase       $
   buildPhase
   where
-    explorePhase     = backjumpAndExplore (enableBackjumping sc) (countConflicts sc)
+    explorePhase     = backjumpAndExplore (maxBackjumps sc)
+                                          (enableBackjumping sc)
+                                          (countConflicts sc)
     detectCycles     = traceTree "cycles.json" id . detectCyclesPhase
     heuristicsPhase  =
       let heuristicsTree = traceTree "heuristics.json" id
-      in case goalOrder sc of
-           Nothing -> goalChoiceHeuristics .
-                      heuristicsTree .
-                      P.deferSetupChoices .
-                      P.deferWeakFlagChoices .
-                      P.preferBaseGoalChoice
-           Just order -> P.firstGoal .
-                         heuristicsTree .
-                         P.sortGoals order
+          sortGoals = case goalOrder sc of
+                        Nothing -> goalChoiceHeuristics .
+                                   heuristicsTree .
+                                   P.deferSetupChoices .
+                                   P.deferWeakFlagChoices .
+                                   P.preferBaseGoalChoice
+                        Just order -> P.firstGoal .
+                                   heuristicsTree .
+                                   P.sortGoals order
+          PruneAfterFirstSuccess prune = pruneAfterFirstSuccess sc
+      in sortGoals .
+         (if prune then P.pruneAfterFirstSuccess else id)
     preferencesPhase = P.preferLinked .
                        P.preferPackagePreferences userPrefs
     validationPhase  = traceTree "validated.json" id .
@@ -232,4 +244,4 @@
        DependencyGoal $
        DependencyReason
            (Q (PackagePath DefaultNamespace QualToplevel) (mkPackageName "$"))
-           [] []
+           M.empty S.empty
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/Tree.hs b/cabal/cabal-install/Distribution/Solver/Modular/Tree.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/Tree.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/Tree.hs
@@ -13,6 +13,7 @@
     , para
     , trav
     , zeroOrOneChoices
+    , active
     ) where
 
 import Control.Monad hiding (mapM, sequence)
@@ -30,7 +31,6 @@
 import Distribution.Solver.Types.ConstraintSource
 import Distribution.Solver.Types.Flag
 import Distribution.Solver.Types.PackagePath
-import Distribution.Types.UnqualComponentName
 import Language.Haskell.Extension (Extension, Language)
 
 type Weight = Double
@@ -100,8 +100,10 @@
                 | MissingPkgconfigPackage PkgconfigName VR
                 | NewPackageDoesNotMatchExistingConstraint ConflictingDep
                 | ConflictingConstraints ConflictingDep ConflictingDep
-                | NewPackageIsMissingRequiredExe UnqualComponentName (DependencyReason QPN)
-                | PackageRequiresMissingExe QPN UnqualComponentName
+                | NewPackageIsMissingRequiredComponent ExposedComponent (DependencyReason QPN)
+                | NewPackageHasUnbuildableRequiredComponent ExposedComponent (DependencyReason QPN)
+                | PackageRequiresMissingComponent QPN ExposedComponent
+                | PackageRequiresUnbuildableComponent QPN ExposedComponent
                 | CannotInstall
                 | CannotReinstall
                 | Shadowed
@@ -122,7 +124,7 @@
   deriving (Eq, Show)
 
 -- | Information about a dependency involved in a conflict, for error messages.
-data ConflictingDep = ConflictingDep (DependencyReason QPN) (Maybe UnqualComponentName) QPN CI
+data ConflictingDep = ConflictingDep (DependencyReason QPN) (PkgComponent QPN) CI
   deriving (Eq, Show)
 
 -- | Functor for the tree type. 'a' is the type of nodes' children. 'd' and 'c'
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/Validate.hs b/cabal/cabal-install/Distribution/Solver/Modular/Validate.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/Validate.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/Validate.hs
@@ -22,7 +22,7 @@
 
 import Language.Haskell.Extension (Extension, Language)
 
-import Distribution.Compat.Map.Strict as M
+import Data.Map.Strict as M
 import Distribution.Compiler (CompilerInfo(..))
 
 import Distribution.Solver.Modular.Assignment
@@ -37,7 +37,6 @@
 
 import Distribution.Solver.Types.PackagePath
 import Distribution.Solver.Types.PkgConfigDb (PkgConfigDb, pkgConfigPkgIsPresent)
-import Distribution.Types.UnqualComponentName
 
 #ifdef DEBUG_CONFLICT_SETS
 import GHC.Stack (CallStack)
@@ -95,28 +94,28 @@
 
 -- | The state needed during validation.
 data ValidateState = VS {
-  supportedExt  :: Extension -> Bool,
-  supportedLang :: Language  -> Bool,
-  presentPkgs   :: PkgconfigName -> VR  -> Bool,
-  index :: Index,
+  supportedExt        :: Extension -> Bool,
+  supportedLang       :: Language  -> Bool,
+  presentPkgs         :: PkgconfigName -> VR  -> Bool,
+  index               :: Index,
 
   -- Saved, scoped, dependencies. Every time 'validate' makes a package choice,
   -- it qualifies the package's dependencies and saves them in this map. Then
   -- the qualified dependencies are available for subsequent flag and stanza
   -- choices for the same package.
-  saved :: Map QPN (FlaggedDeps QPN),
+  saved               :: Map QPN (FlaggedDeps QPN),
 
-  pa    :: PreAssignment,
+  pa                  :: PreAssignment,
 
-  -- Map from package name to the executables that are provided by the chosen
-  -- instance of that package.
-  availableExes  :: Map QPN [UnqualComponentName],
+  -- Map from package name to the components that are provided by the chosen
+  -- instance of that package, and whether those components are buildable.
+  availableComponents :: Map QPN (Map ExposedComponent IsBuildable),
 
-  -- Map from package name to the executables that are required from that
+  -- Map from package name to the components that are required from that
   -- package.
-  requiredExes   :: Map QPN ExeDeps,
+  requiredComponents  :: Map QPN ComponentDependencyReasons,
 
-  qualifyOptions :: QualifyOptions
+  qualifyOptions      :: QualifyOptions
 }
 
 newtype Validate a = Validate (Reader ValidateState a)
@@ -133,12 +132,12 @@
 -- are associated with MergedPkgDeps.
 type PPreAssignment = Map QPN MergedPkgDep
 
--- | A dependency on a package, including its DependencyReason.
-data PkgDep = PkgDep (DependencyReason QPN) (Maybe UnqualComponentName) QPN CI
+-- | A dependency on a component, including its DependencyReason.
+data PkgDep = PkgDep (DependencyReason QPN) (PkgComponent QPN) CI
 
--- | Map from executable name to one of the reasons that the executable is
+-- | Map from component name to one of the reasons that the component is
 -- required.
-type ExeDeps = Map UnqualComponentName (DependencyReason QPN)
+type ComponentDependencyReasons = Map ExposedComponent (DependencyReason QPN)
 
 -- | MergedPkgDep records constraints about the instances that can still be
 -- chosen, and in the extreme case fixes a concrete instance. Otherwise, it is a
@@ -146,15 +145,15 @@
 -- them. It also records whether a package is a build-tool dependency, for each
 -- reason that it was introduced.
 --
--- It is important to store the executable name with the version constraint, for
+-- It is important to store the component name with the version constraint, for
 -- error messages, because whether something is a build-tool dependency affects
 -- its qualifier, which affects which constraint is applied.
 data MergedPkgDep =
-    MergedDepFixed (Maybe UnqualComponentName) (DependencyReason QPN) I
+    MergedDepFixed ExposedComponent (DependencyReason QPN) I
   | MergedDepConstrained [VROrigin]
 
 -- | Version ranges paired with origins.
-type VROrigin = (VR, Maybe UnqualComponentName, DependencyReason QPN)
+type VROrigin = (VR, ExposedComponent, DependencyReason QPN)
 
 -- | The information needed to create a 'Fail' node.
 type Conflict = (ConflictSet, FailReason)
@@ -204,11 +203,11 @@
       pkgPresent     <- asks presentPkgs -- obtain the present pkg-config pkgs
       idx            <- asks index -- obtain the index
       svd            <- asks saved -- obtain saved dependencies
-      aExes          <- asks availableExes
-      rExes          <- asks requiredExes
+      aComps         <- asks availableComponents
+      rComps         <- asks requiredComponents
       qo             <- asks qualifyOptions
       -- obtain dependencies and index-dictated exclusions introduced by the choice
-      let (PInfo deps exes _ mfr) = idx ! pn ! i
+      let (PInfo deps comps _ mfr) = idx ! pn ! i
       -- qualify the deps in the current scope
       let qdeps = qualifyDeps qo qpn deps
       -- the new active constraints are given by the instance we have chosen,
@@ -223,21 +222,21 @@
         Just fr -> -- The index marks this as an invalid choice. We can stop.
                    return (Fail (varToConflictSet (P qpn)) fr)
         Nothing ->
-          let newDeps :: Either Conflict (PPreAssignment, Map QPN ExeDeps)
+          let newDeps :: Either Conflict (PPreAssignment, Map QPN ComponentDependencyReasons)
               newDeps = do
                 nppa <- mnppa
-                rExes' <- extendRequiredExes aExes rExes newactives
-                checkExesInNewPackage rExes qpn exes
-                return (nppa, rExes')
+                rComps' <- extendRequiredComponents aComps rComps newactives
+                checkComponentsInNewPackage (M.findWithDefault M.empty qpn rComps) qpn comps
+                return (nppa, rComps')
           in case newDeps of
-               Left (c, fr)         -> -- We have an inconsistency. We can stop.
-                                       return (Fail c fr)
-               Right (nppa, rExes') -> -- We have an updated partial assignment for the recursive validation.
-                                       local (\ s -> s { pa = PA nppa pfa psa
-                                                       , saved = nsvd
-                                                       , availableExes = M.insert qpn exes aExes
-                                                       , requiredExes = rExes'
-                                                       }) r
+               Left (c, fr)          -> -- We have an inconsistency. We can stop.
+                                        return (Fail c fr)
+               Right (nppa, rComps') -> -- We have an updated partial assignment for the recursive validation.
+                                        local (\ s -> s { pa = PA nppa pfa psa
+                                                        , saved = nsvd
+                                                        , availableComponents = M.insert qpn comps aComps
+                                                        , requiredComponents = rComps'
+                                                        }) r
 
     -- What to do for flag nodes ...
     goF :: QFN -> Bool -> Validate (Tree d c) -> Validate (Tree d c)
@@ -247,8 +246,8 @@
       langSupported  <- asks supportedLang -- obtain the supported languages
       pkgPresent     <- asks presentPkgs   -- obtain the present pkg-config pkgs
       svd            <- asks saved         -- obtain saved dependencies
-      aExes          <- asks availableExes
-      rExes          <- asks requiredExes
+      aComps         <- asks availableComponents
+      rComps         <- asks requiredComponents
       -- Note that there should be saved dependencies for the package in question,
       -- because while building, we do not choose flags before we see the packages
       -- that define them.
@@ -261,13 +260,13 @@
       -- We now try to get the new active dependencies we might learn about because
       -- we have chosen a new flag.
       let newactives = extractNewDeps (F qfn) b npfa psa qdeps
-          mNewRequiredExes = extendRequiredExes aExes rExes newactives
+          mNewRequiredComps = extendRequiredComponents aComps rComps newactives
       -- As in the package case, we try to extend the partial assignment.
       let mnppa = extend extSupported langSupported pkgPresent newactives ppa
-      case liftM2 (,) mnppa mNewRequiredExes of
+      case liftM2 (,) mnppa mNewRequiredComps of
         Left (c, fr)         -> return (Fail c fr) -- inconsistency found
-        Right (nppa, rExes') ->
-            local (\ s -> s { pa = PA nppa npfa psa, requiredExes = rExes' }) r
+        Right (nppa, rComps') ->
+            local (\ s -> s { pa = PA nppa npfa psa, requiredComponents = rComps' }) r
 
     -- What to do for stanza nodes (similar to flag nodes) ...
     goS :: QSN -> Bool -> Validate (Tree d c) -> Validate (Tree d c)
@@ -277,8 +276,8 @@
       langSupported  <- asks supportedLang -- obtain the supported languages
       pkgPresent     <- asks presentPkgs -- obtain the present pkg-config pkgs
       svd            <- asks saved         -- obtain saved dependencies
-      aExes          <- asks availableExes
-      rExes          <- asks requiredExes
+      aComps         <- asks availableComponents
+      rComps         <- asks requiredComponents
       -- Note that there should be saved dependencies for the package in question,
       -- because while building, we do not choose flags before we see the packages
       -- that define them.
@@ -291,26 +290,40 @@
       -- We now try to get the new active dependencies we might learn about because
       -- we have chosen a new flag.
       let newactives = extractNewDeps (S qsn) b pfa npsa qdeps
-          mNewRequiredExes = extendRequiredExes aExes rExes newactives
+          mNewRequiredComps = extendRequiredComponents aComps rComps newactives
       -- As in the package case, we try to extend the partial assignment.
       let mnppa = extend extSupported langSupported pkgPresent newactives ppa
-      case liftM2 (,) mnppa mNewRequiredExes of
+      case liftM2 (,) mnppa mNewRequiredComps of
         Left (c, fr)         -> return (Fail c fr) -- inconsistency found
-        Right (nppa, rExes') ->
-            local (\ s -> s { pa = PA nppa pfa npsa, requiredExes = rExes' }) r
+        Right (nppa, rComps') ->
+            local (\ s -> s { pa = PA nppa pfa npsa, requiredComponents = rComps' }) r
 
--- | Check that a newly chosen package instance contains all executables that
--- are required from that package so far.
-checkExesInNewPackage :: Map QPN ExeDeps
-                      -> QPN
-                      -> [UnqualComponentName]
-                      -> Either Conflict ()
-checkExesInNewPackage required qpn providedExes =
-    case M.toList $ deleteKeys providedExes (M.findWithDefault M.empty qpn required) of
-      (missingExe, dr) : _ -> let cs = CS.insert (P qpn) $ dependencyReasonToCS dr
-                              in Left (cs, NewPackageIsMissingRequiredExe missingExe dr)
-      []                   -> Right ()
+-- | Check that a newly chosen package instance contains all components that
+-- are required from that package so far. The components must also be buildable.
+checkComponentsInNewPackage :: ComponentDependencyReasons
+                            -> QPN
+                            -> Map ExposedComponent IsBuildable
+                            -> Either Conflict ()
+checkComponentsInNewPackage required qpn providedComps =
+    case M.toList $ deleteKeys (M.keys providedComps) required of
+      (missingComp, dr) : _ ->
+          Left $ mkConflict missingComp dr NewPackageIsMissingRequiredComponent
+      []                    ->
+          case M.toList $ deleteKeys buildableProvidedComps required of
+            (unbuildableComp, dr) : _ ->
+                Left $ mkConflict unbuildableComp dr NewPackageHasUnbuildableRequiredComponent
+            []                        -> Right ()
   where
+    mkConflict :: ExposedComponent
+               -> DependencyReason QPN
+               -> (ExposedComponent -> DependencyReason QPN -> FailReason)
+               -> Conflict
+    mkConflict comp dr mkFailure =
+        (CS.insert (P qpn) (dependencyReasonToCS dr), mkFailure comp dr)
+
+    buildableProvidedComps :: [ExposedComponent]
+    buildableProvidedComps = [comp | (comp, IsBuildable True) <- M.toList providedComps]
+
     deleteKeys :: Ord k => [k] -> Map k v -> Map k v
     deleteKeys ks m = L.foldr M.delete m ks
 
@@ -386,18 +399,23 @@
     extendSingle a (LDep dr (Pkg pn vr))  =
       if pkgPresent pn vr then Right a
                           else Left (dependencyReasonToCS dr, MissingPkgconfigPackage pn vr)
-    extendSingle a (LDep dr (Dep mExe qpn ci)) =
+    extendSingle a (LDep dr (Dep dep@(PkgComponent qpn _) ci)) =
       let mergedDep = M.findWithDefault (MergedDepConstrained []) qpn a
-      in  case (\ x -> M.insert qpn x a) <$> merge mergedDep (PkgDep dr mExe qpn ci) of
+      in  case (\ x -> M.insert qpn x a) <$> merge mergedDep (PkgDep dr dep ci) of
             Left (c, (d, d')) -> Left (c, ConflictingConstraints d d')
             Right x           -> Right x
 
 -- | Extend a package preassignment with a package choice. For example, when
 -- the solver chooses foo-2.0, it tries to add the constraint foo==2.0.
+--
+-- TODO: The new constraint is implemented as a dependency from foo to foo's
+-- library. That isn't correct, because foo might only be needed as a build
+-- tool dependency. The implemention may need to change when we support
+-- component-based dependency solving.
 extendWithPackageChoice :: PI QPN -> PPreAssignment -> Either Conflict PPreAssignment
 extendWithPackageChoice (PI qpn i) ppa =
   let mergedDep = M.findWithDefault (MergedDepConstrained []) qpn ppa
-      newChoice = PkgDep (DependencyReason qpn [] []) Nothing qpn (Fixed i)
+      newChoice = PkgDep (DependencyReason qpn M.empty S.empty) (PkgComponent qpn ExposedLib) (Fixed i)
   in  case (\ x -> M.insert qpn x ppa) <$> merge mergedDep newChoice of
         Left (c, (d, _d')) -> -- Don't include the package choice in the
                               -- FailReason, because it is redundant.
@@ -426,76 +444,93 @@
   (?loc :: CallStack) =>
 #endif
   MergedPkgDep -> PkgDep -> Either (ConflictSet, (ConflictingDep, ConflictingDep)) MergedPkgDep
-merge (MergedDepFixed mExe1 vs1 i1) (PkgDep vs2 mExe2 p ci@(Fixed i2))
-  | i1 == i2  = Right $ MergedDepFixed mExe1 vs1 i1
+merge (MergedDepFixed comp1 vs1 i1) (PkgDep vs2 (PkgComponent p comp2) ci@(Fixed i2))
+  | i1 == i2  = Right $ MergedDepFixed comp1 vs1 i1
   | otherwise =
       Left ( (CS.union `on` dependencyReasonToCS) vs1 vs2
-           , ( ConflictingDep vs1 mExe1 p (Fixed i1)
-             , ConflictingDep vs2 mExe2 p ci ) )
+           , ( ConflictingDep vs1 (PkgComponent p comp1) (Fixed i1)
+             , ConflictingDep vs2 (PkgComponent p comp2) ci ) )
 
-merge (MergedDepFixed mExe1 vs1 i@(I v _)) (PkgDep vs2 mExe2 p ci@(Constrained vr))
-  | checkVR vr v = Right $ MergedDepFixed mExe1 vs1 i
+merge (MergedDepFixed comp1 vs1 i@(I v _)) (PkgDep vs2 (PkgComponent p comp2) ci@(Constrained vr))
+  | checkVR vr v = Right $ MergedDepFixed comp1 vs1 i
   | otherwise    =
       Left ( (CS.union `on` dependencyReasonToCS) vs1 vs2
-           , ( ConflictingDep vs1 mExe1 p (Fixed i)
-             , ConflictingDep vs2 mExe2 p ci ) )
+           , ( ConflictingDep vs1 (PkgComponent p comp1) (Fixed i)
+             , ConflictingDep vs2 (PkgComponent p comp2) ci ) )
 
-merge (MergedDepConstrained vrOrigins) (PkgDep vs2 mExe2 p ci@(Fixed i@(I v _))) =
+merge (MergedDepConstrained vrOrigins) (PkgDep vs2 (PkgComponent p comp2) ci@(Fixed i@(I v _))) =
     go vrOrigins -- I tried "reverse vrOrigins" here, but it seems to slow things down ...
   where
     go :: [VROrigin] -> Either (ConflictSet, (ConflictingDep, ConflictingDep)) MergedPkgDep
-    go [] = Right (MergedDepFixed mExe2 vs2 i)
-    go ((vr, mExe1, vs1) : vros)
+    go [] = Right (MergedDepFixed comp2 vs2 i)
+    go ((vr, comp1, vs1) : vros)
        | checkVR vr v = go vros
        | otherwise    =
            Left ( (CS.union `on` dependencyReasonToCS) vs1 vs2
-                , ( ConflictingDep vs1 mExe1 p (Constrained vr)
-                  , ConflictingDep vs2 mExe2 p ci ) )
+                , ( ConflictingDep vs1 (PkgComponent p comp1) (Constrained vr)
+                  , ConflictingDep vs2 (PkgComponent p comp2) ci ) )
 
-merge (MergedDepConstrained vrOrigins) (PkgDep vs2 mExe2 _ (Constrained vr)) =
+merge (MergedDepConstrained vrOrigins) (PkgDep vs2 (PkgComponent _ comp2) (Constrained vr)) =
     Right (MergedDepConstrained $
 
     -- TODO: This line appends the new version range, to preserve the order used
     -- before a refactoring. Consider prepending the version range, if there is
     -- no negative performance impact.
-    vrOrigins ++ [(vr, mExe2, vs2)])
+    vrOrigins ++ [(vr, comp2, vs2)])
 
 -- | Takes a list of new dependencies and uses it to try to update the map of
--- known executable dependencies. It returns a failure when a new dependency
--- requires an executable that is missing from one of the previously chosen
+-- known component dependencies. It returns a failure when a new dependency
+-- requires a component that is missing or unbuildable in a previously chosen
 -- packages.
-extendRequiredExes :: Map QPN [UnqualComponentName]
-                   -> Map QPN ExeDeps
-                   -> [LDep QPN]
-                   -> Either Conflict (Map QPN ExeDeps)
-extendRequiredExes available = foldM extendSingle
+extendRequiredComponents :: Map QPN (Map ExposedComponent IsBuildable)
+                         -> Map QPN ComponentDependencyReasons
+                         -> [LDep QPN]
+                         -> Either Conflict (Map QPN ComponentDependencyReasons)
+extendRequiredComponents available = foldM extendSingle
   where
-    extendSingle :: Map QPN ExeDeps -> LDep QPN -> Either Conflict (Map QPN ExeDeps)
-    extendSingle required (LDep dr (Dep (Just exe) qpn _)) =
-      let exeDeps = M.findWithDefault M.empty qpn required
-      in -- Only check for the existence of the exe if its package has already
-         -- been chosen.
+    extendSingle :: Map QPN ComponentDependencyReasons
+                 -> LDep QPN
+                 -> Either Conflict (Map QPN ComponentDependencyReasons)
+    extendSingle required (LDep dr (Dep (PkgComponent qpn comp) _)) =
+      let compDeps = M.findWithDefault M.empty qpn required
+      in -- Only check for the existence of the component if its package has
+         -- already been chosen.
          case M.lookup qpn available of
-           Just exes
-             | L.notElem exe exes -> let cs = CS.insert (P qpn) (dependencyReasonToCS dr)
-                                     in Left (cs, PackageRequiresMissingExe qpn exe)
-           _                      -> Right $ M.insertWith M.union qpn (M.insert exe dr exeDeps) required
-    extendSingle required _                                = Right required
+           Just comps
+             | M.notMember comp comps                ->
+                 Left $ mkConflict qpn comp dr PackageRequiresMissingComponent
+             | L.notElem comp (buildableComps comps) ->
+                 Left $ mkConflict qpn comp dr PackageRequiresUnbuildableComponent
+           _                                         ->
+                 Right $ M.insertWith M.union qpn (M.insert comp dr compDeps) required
+    extendSingle required _                                         = Right required
 
+    mkConflict :: QPN
+               -> ExposedComponent
+               -> DependencyReason QPN
+               -> (QPN -> ExposedComponent -> FailReason)
+               -> Conflict
+    mkConflict qpn comp dr mkFailure =
+      (CS.insert (P qpn) (dependencyReasonToCS dr), mkFailure qpn comp)
+
+    buildableComps :: Map comp IsBuildable -> [comp]
+    buildableComps comps = [comp | (comp, IsBuildable True) <- M.toList comps]
+
+
 -- | Interface.
 validateTree :: CompilerInfo -> Index -> PkgConfigDb -> Tree d c -> Tree d c
 validateTree cinfo idx pkgConfigDb t = runValidate (validate t) VS {
-    supportedExt   = maybe (const True) -- if compiler has no list of extensions, we assume everything is supported
-                           (\ es -> let s = S.fromList es in \ x -> S.member x s)
-                           (compilerInfoExtensions cinfo)
-  , supportedLang  = maybe (const True)
-                           (flip L.elem) -- use list lookup because language list is small and no Ord instance
-                           (compilerInfoLanguages  cinfo)
-  , presentPkgs    = pkgConfigPkgIsPresent pkgConfigDb
-  , index          = idx
-  , saved          = M.empty
-  , pa             = PA M.empty M.empty M.empty
-  , availableExes  = M.empty
-  , requiredExes   = M.empty
-  , qualifyOptions = defaultQualifyOptions idx
+    supportedExt        = maybe (const True) -- if compiler has no list of extensions, we assume everything is supported
+                                (\ es -> let s = S.fromList es in \ x -> S.member x s)
+                                (compilerInfoExtensions cinfo)
+  , supportedLang       = maybe (const True)
+                                (flip L.elem) -- use list lookup because language list is small and no Ord instance
+                                (compilerInfoLanguages  cinfo)
+  , presentPkgs         = pkgConfigPkgIsPresent pkgConfigDb
+  , index               = idx
+  , saved               = M.empty
+  , pa                  = PA M.empty M.empty M.empty
+  , availableComponents = M.empty
+  , requiredComponents  = M.empty
+  , qualifyOptions      = defaultQualifyOptions idx
   }
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/Version.hs b/cabal/cabal-install/Distribution/Solver/Modular/Version.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/Version.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/Version.hs
@@ -38,11 +38,11 @@
 
 -- | Intersect two version ranges.
 (.&&.) :: VR -> VR -> VR
-(.&&.) = CV.intersectVersionRanges
+v1 .&&. v2 = simplifyVR $ CV.intersectVersionRanges v1 v2
 
 -- | Union of two version ranges.
 (.||.) :: VR -> VR -> VR
-(.||.) = CV.unionVersionRanges
+v1 .||. v2 = simplifyVR $ CV.unionVersionRanges v1 v2
 
 -- | Simplify a version range.
 simplifyVR :: VR -> VR
diff --git a/cabal/cabal-install/Distribution/Solver/Modular/WeightedPSQ.hs b/cabal/cabal-install/Distribution/Solver/Modular/WeightedPSQ.hs
--- a/cabal/cabal-install/Distribution/Solver/Modular/WeightedPSQ.hs
+++ b/cabal/cabal-install/Distribution/Solver/Modular/WeightedPSQ.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 module Distribution.Solver.Modular.WeightedPSQ (
     WeightedPSQ
   , fromList
@@ -11,6 +12,7 @@
   , mapWithKey
   , mapWeightsWithKey
   , union
+  , takeUntil
   ) where
 
 import qualified Data.Foldable as F
@@ -75,6 +77,15 @@
 -- second when they have the same weight.
 union :: Ord w => WeightedPSQ w k v -> WeightedPSQ w k v -> WeightedPSQ w k v
 union (WeightedPSQ xs) (WeightedPSQ ys) = fromList (xs ++ ys)
+
+-- | /O(N)/. Return the prefix of values ending with the first element that
+-- satisfies p, or all elements if none satisfy p.
+takeUntil :: forall w k v. (v -> Bool) -> WeightedPSQ w k v -> WeightedPSQ w k v
+takeUntil p (WeightedPSQ xs) = WeightedPSQ (go xs)
+  where
+    go :: [(w, k, v)] -> [(w, k, v)]
+    go []       = []
+    go (y : ys) = y : if p (triple_3 y) then [] else go ys
 
 triple_1 :: (x, y, z) -> x
 triple_1 (x, _, _) = x
diff --git a/cabal/cabal-install/Distribution/Solver/Types/ConstraintSource.hs b/cabal/cabal-install/Distribution/Solver/Types/ConstraintSource.hs
--- a/cabal/cabal-install/Distribution/Solver/Types/ConstraintSource.hs
+++ b/cabal/cabal-install/Distribution/Solver/Types/ConstraintSource.hs
@@ -49,6 +49,10 @@
   -- | An internal constraint due to compatibility issues with the Setup.hs
   -- command line interface requires a minimum lower bound on Cabal
   | ConstraintSetupCabalMinVersion
+
+  -- | An internal constraint due to compatibility issues with the Setup.hs
+  -- command line interface requires a maximum upper bound on Cabal
+  | ConstraintSetupCabalMaxVersion
   deriving (Eq, Show, Generic)
 
 instance Binary ConstraintSource
@@ -74,3 +78,5 @@
 showConstraintSource ConstraintSourceUnknown = "unknown source"
 showConstraintSource ConstraintSetupCabalMinVersion =
     "minimum version of Cabal used by Setup.hs"
+showConstraintSource ConstraintSetupCabalMaxVersion =
+    "maximum version of Cabal used by Setup.hs"
diff --git a/cabal/cabal-install/Distribution/Solver/Types/SolverPackage.hs b/cabal/cabal-install/Distribution/Solver/Types/SolverPackage.hs
--- a/cabal/cabal-install/Distribution/Solver/Types/SolverPackage.hs
+++ b/cabal/cabal-install/Distribution/Solver/Types/SolverPackage.hs
@@ -20,8 +20,8 @@
 -- but for symmetry we have the parameter.  (Maybe it can be removed.)
 --
 data SolverPackage loc = SolverPackage {
-        solverPkgSource :: SourcePackage loc,
-        solverPkgFlags :: FlagAssignment,
+        solverPkgSource  :: SourcePackage loc,
+        solverPkgFlags   :: FlagAssignment,
         solverPkgStanzas :: [OptionalStanza],
         solverPkgLibDeps :: ComponentDeps [SolverId],
         solverPkgExeDeps :: ComponentDeps [SolverId]
diff --git a/cabal/cabal-install/Distribution/Solver/Types/Variable.hs b/cabal/cabal-install/Distribution/Solver/Types/Variable.hs
--- a/cabal/cabal-install/Distribution/Solver/Types/Variable.hs
+++ b/cabal/cabal-install/Distribution/Solver/Types/Variable.hs
@@ -5,8 +5,7 @@
 import Distribution.PackageDescription (FlagName)
 
 -- | Variables used by the dependency solver. This type is similar to the
--- internal 'Var' type, except that flags and stanzas are associated with
--- package names instead of package instances.
+-- internal 'Var' type.
 data Variable qpn =
     PackageVar qpn
   | FlagVar qpn FlagName
diff --git a/cabal/cabal-install/bootstrap.sh b/cabal/cabal-install/bootstrap.sh
--- a/cabal/cabal-install/bootstrap.sh
+++ b/cabal/cabal-install/bootstrap.sh
@@ -1,4 +1,5 @@
 #!/bin/sh
+set -e
 
 # A script to bootstrap cabal-install.
 
@@ -208,53 +209,38 @@
 
 # Versions of the packages to install.
 # The version regex says what existing installed versions are ok.
-PARSEC_VER="3.1.9";    PARSEC_VER_REGEXP="[3]\.[01]\."
-                       # >= 3.0 && < 3.2
-DEEPSEQ_VER="1.4.2.0"; DEEPSEQ_VER_REGEXP="1\.[1-9]\."
+PARSEC_VER="3.1.13.0"; PARSEC_VER_REGEXP="[3]\.[1]\."
+                       # >= 3.1 && < 3.2
+DEEPSEQ_VER="1.4.3.0"; DEEPSEQ_VER_REGEXP="1\.[1-9]\."
                        # >= 1.1 && < 2
-
-case "$GHC_VER" in
-    7.4*|7.6*)
-        # GHC 7.4 or 7.6
-        BINARY_VER="0.8.2.1"
-        BINARY_VER_REGEXP="[0]\.[78]\.[0-2]\." # >= 0.7 && < 0.8.3
-        ;;
-    *)
-        # GHC >= 7.8
-        BINARY_VER="0.8.3.0"
-        BINARY_VER_REGEXP="[0]\.[78]\." # >= 0.7 && < 0.9
-        ;;
-esac
-
-
-TEXT_VER="1.2.2.2";    TEXT_VER_REGEXP="((1\.[012]\.)|(0\.([2-9]|(1[0-1]))\.))"
-                       # >= 0.2 && < 1.3
-NETWORK_VER="2.6.3.2"; NETWORK_VER_REGEXP="2\.[0-6]\."
+BINARY_VER="0.8.5.1";  BINARY_VER_REGEXP="[0]\.[78]\."
+                       # >= 0.7 && < 0.9
+TEXT_VER="1.2.3.0";    TEXT_VER_REGEXP="[1]\.[2]\."
+                       # >= 1.2 && < 1.3
+NETWORK_URI_VER="2.6.1.0"; NETWORK_URI_VER_REGEXP="2\.6\.(0\.[2-9]|[1-9])"
+                       # >= 2.6.0.2 && < 2.7
+NETWORK_VER="2.7.0.0"; NETWORK_VER_REGEXP="2\.[0-7]\."
                        # >= 2.0 && < 2.7
-NETWORK_URI_VER="2.6.1.0"; NETWORK_URI_VER_REGEXP="2\.6\."
-                       # >= 2.6 && < 2.7
-CABAL_VER="2.1.0.0";   CABAL_VER_REGEXP="2\.1\.[0-9]"
-                       # >= 2.1 && < 2.2
+CABAL_VER="2.4.1.0";   CABAL_VER_REGEXP="2\.4\.[1-9]"
+                       # >= 2.4.1.0 && < 2.5
 TRANS_VER="0.5.5.0";   TRANS_VER_REGEXP="0\.[45]\."
                        # >= 0.2.* && < 0.6
-MTL_VER="2.2.1";       MTL_VER_REGEXP="[2]\."
+MTL_VER="2.2.2";       MTL_VER_REGEXP="[2]\."
                        #  >= 2.0 && < 3
-HTTP_VER="4000.3.8";   HTTP_VER_REGEXP="4000\.(2\.([5-9]|1[0-9]|2[0-9])|3\.?)"
+HTTP_VER="4000.3.12";  HTTP_VER_REGEXP="4000\.(2\.([5-9]|1[0-9]|2[0-9])|3\.?)"
                        # >= 4000.2.5 < 4000.4
-ZLIB_VER="0.6.1.2";    ZLIB_VER_REGEXP="(0\.5\.([3-9]|1[0-9])|0\.6)"
+ZLIB_VER="0.6.2";      ZLIB_VER_REGEXP="(0\.5\.([3-9]|1[0-9])|0\.6)"
                        # >= 0.5.3 && <= 0.7
-TIME_VER="1.8.0.3"     TIME_VER_REGEXP="1\.[1-8]\.?"
-                       # >= 1.1 && < 1.9
+TIME_VER="1.9.1"       TIME_VER_REGEXP="1\.[1-9]\.?"
+                       # >= 1.1 && < 1.10
 RANDOM_VER="1.1"       RANDOM_VER_REGEXP="1\.[01]\.?"
                        # >= 1 && < 1.2
-STM_VER="2.4.4.1";     STM_VER_REGEXP="2\."
+STM_VER="2.4.5.0";     STM_VER_REGEXP="2\."
                        # == 2.*
-ASYNC_VER="2.1.1.1";   ASYNC_VER_REGEXP="2\."
+HASHABLE_VER="1.2.7.0"; HASHABLE_VER_REGEXP="1\."
+                       # 1.*
+ASYNC_VER="2.2.1";     ASYNC_VER_REGEXP="2\."
                        # 2.*
-OLD_TIME_VER="1.1.0.3"; OLD_TIME_VER_REGEXP="1\.[01]\.?"
-                       # >=1.0.0.0 && <1.2
-OLD_LOCALE_VER="1.0.0.7"; OLD_LOCALE_VER_REGEXP="1\.0\.?"
-                       # >=1.0.0.0 && <1.1
 BASE16_BYTESTRING_VER="0.1.1.6"; BASE16_BYTESTRING_VER_REGEXP="0\.1"
                        # 0.1.*
 BASE64_BYTESTRING_VER="1.0.0.1"; BASE64_BYTESTRING_VER_REGEXP="1\."
@@ -263,7 +249,7 @@
                        # 0.11.*
 RESOLV_VER="0.1.1.1";  RESOLV_VER_REGEXP="0\.1\.[1-9]"
                        # >= 0.1.1 && < 0.2
-MINTTY_VER="0.1.1";    MINTTY_VER_REGEXP="0\.1\.?"
+MINTTY_VER="0.1.2";    MINTTY_VER_REGEXP="0\.1\.?"
                        # 0.1.*
 ECHO_VER="0.1.3";      ECHO_VER_REGEXP="0\.1\.[3-9]"
                        # >= 0.1.3 && < 0.2
@@ -271,19 +257,20 @@
                        # 0.2.2.*
 ED25519_VER="0.0.5.0"; ED25519_VER_REGEXP="0\.0\.?"
                        # 0.0.*
-HACKAGE_SECURITY_VER="0.5.2.2"; HACKAGE_SECURITY_VER_REGEXP="0\.5\.(2\.[2-9]|[3-9])"
+HACKAGE_SECURITY_VER="0.5.3.0"; HACKAGE_SECURITY_VER_REGEXP="0\.5\.((2\.[2-9]|[3-9])|3)"
                        # >= 0.5.2 && < 0.6
-BYTESTRING_BUILDER_VER="0.10.8.1.0"; BYTESTRING_BUILDER_VER_REGEXP="0\.10\.?"
-TAR_VER="0.5.0.3";     TAR_VER_REGEXP="0\.5\.([1-9]|1[0-9]|0\.[3-9]|0\.1[0-9])\.?"
+TAR_VER="0.5.1.0";     TAR_VER_REGEXP="0\.5\.([1-9]|1[0-9]|0\.[3-9]|0\.1[0-9])\.?"
                        # >= 0.5.0.3  && < 0.6
-HASHABLE_VER="1.2.6.1"; HASHABLE_VER_REGEXP="1\."
-                       # 1.*
+DIGEST_VER="0.0.1.2"; DIGEST_REGEXP="0\.0\.(1\.[2-9]|[2-9]\.?)"
+                       # >= 0.0.1.2 && < 0.1
+ZIP_ARCHIVE_VER="0.3.3"; ZIP_ARCHIVE_REGEXP="0\.3\.[3-9]"
+                       # >= 0.3.3 && < 0.4
 
 HACKAGE_URL="https://hackage.haskell.org/package"
 
-# Haddock fails for network-2.5.0.0, and for hackage-security for
-# GHC <8, c.f. https://github.com/well-typed/hackage-security/issues/149
-NO_DOCS_PACKAGES_VER_REGEXP="network-uri-2\.5\.[0-9]+\.[0-9]+|hackage-security-0\.5\.[0-9]+\.[0-9]+"
+# Haddock fails for hackage-security for GHC <8,
+# c.f. https://github.com/well-typed/hackage-security/issues/149
+NO_DOCS_PACKAGES_VER_REGEXP="hackage-security-0\.5\.[0-9]+\.[0-9]+"
 
 # Cache the list of packages:
 echo "Checking installed packages for ghc-${GHC_VER}..."
@@ -329,11 +316,8 @@
   URL_PKGDESC=${HACKAGE_URL}/${PKG}-${VER}/${PKG}.cabal
   if which ${CURL} > /dev/null
   then
-    # TODO: switch back to resuming curl command once
-    #       https://github.com/haskell/hackage-server/issues/111 is resolved
-    #${CURL} -L --fail -C - -O ${URL_PKG} || die "Failed to download ${PKG}."
-    ${CURL} -L --fail -O ${URL_PKG} || die "Failed to download ${PKG}."
-    ${CURL} -L --fail -O ${URL_PKGDESC} \
+    ${CURL} -L --fail -C - -O ${URL_PKG} || die "Failed to download ${PKG}."
+    ${CURL} -L --fail -C - -O ${URL_PKGDESC} \
         || die "Failed to download '${PKG}.cabal'."
   elif which ${WGET} > /dev/null
   then
@@ -370,7 +354,12 @@
   [ -x Setup ] && ./Setup clean
   [ -f Setup ] && rm Setup
 
-  ${GHC} --make ${JOBS} Setup -o Setup -XRank2Types -XFlexibleContexts ||
+  PKG_DBS=$(printf '%s\n' "${SCOPE_OF_INSTALLATION}" \
+             | sed -e 's/--package-db/-package-db/' \
+                   -e 's/--global/-global-package-db/' \
+                   -e 's/--user/-user-package-db/')
+
+  ${GHC} --make ${JOBS} ${PKG_DBS} Setup -o Setup -XRank2Types -XFlexibleContexts ||
     die "Compiling the Setup script failed."
 
   [ -x Setup ] || die "The Setup script does not exist or cannot be run"
@@ -438,38 +427,6 @@
     fi
 }
 
-# Replicate the flag selection logic for network-uri in the .cabal file.
-do_network_uri_pkg () {
-  # Refresh installed package list.
-  ${GHC_PKG} list --global ${SCOPE_OF_INSTALLATION} > ghc-pkg-stage2.list \
-    || die "running '${GHC_PKG} list' failed"
-
-  NETWORK_URI_DUMMY_VER="2.5.0.0"; NETWORK_URI_DUMMY_VER_REGEXP="2\.5\." # < 2.6
-  if egrep " network-2\.[6-9]\." ghc-pkg-stage2.list > /dev/null 2>&1
-  then
-    # Use network >= 2.6 && network-uri >= 2.6
-    info_pkg "network-uri" ${NETWORK_URI_VER} ${NETWORK_URI_VER_REGEXP}
-    do_pkg   "network-uri" ${NETWORK_URI_VER} ${NETWORK_URI_VER_REGEXP}
-  else
-    # Use network < 2.6 && network-uri < 2.6
-    info_pkg "network-uri" ${NETWORK_URI_DUMMY_VER} \
-        ${NETWORK_URI_DUMMY_VER_REGEXP}
-    do_pkg   "network-uri" ${NETWORK_URI_DUMMY_VER} \
-        ${NETWORK_URI_DUMMY_VER_REGEXP}
-  fi
-}
-
-# Conditionally install bytestring-builder if bytestring is < 0.10.2.
-do_bytestring_builder_pkg () {
-  if egrep "bytestring-0\.(9|10\.[0,1])\.?" ghc-pkg-stage2.list > /dev/null 2>&1
-  then
-      info_pkg "bytestring-builder" ${BYTESTRING_BUILDER_VER} \
-               ${BYTESTRING_BUILDER_VER_REGEXP}
-      do_pkg   "bytestring-builder" ${BYTESTRING_BUILDER_VER} \
-               ${BYTESTRING_BUILDER_VER_REGEXP}
-  fi
-}
-
 # Actually do something!
 
 info_pkg "deepseq"      ${DEEPSEQ_VER} ${DEEPSEQ_VER_REGEXP}
@@ -479,13 +436,13 @@
 info_pkg "mtl"          ${MTL_VER}     ${MTL_VER_REGEXP}
 info_pkg "text"         ${TEXT_VER}    ${TEXT_VER_REGEXP}
 info_pkg "parsec"       ${PARSEC_VER}  ${PARSEC_VER_REGEXP}
+info_pkg "network-uri"  ${NETWORK_URI_VER} ${NETWORK_URI_VER_REGEXP}
 info_pkg "network"      ${NETWORK_VER} ${NETWORK_VER_REGEXP}
-info_pkg "old-locale"   ${OLD_LOCALE_VER} ${OLD_LOCALE_VER_REGEXP}
-info_pkg "old-time"     ${OLD_TIME_VER}   ${OLD_TIME_VER_REGEXP}
 info_pkg "HTTP"         ${HTTP_VER}    ${HTTP_VER_REGEXP}
 info_pkg "zlib"         ${ZLIB_VER}    ${ZLIB_VER_REGEXP}
 info_pkg "random"       ${RANDOM_VER}  ${RANDOM_VER_REGEXP}
 info_pkg "stm"          ${STM_VER}     ${STM_VER_REGEXP}
+info_pkg "hashable"     ${HASHABLE_VER}  ${HASHABLE_VER_REGEXP}
 info_pkg "async"        ${ASYNC_VER}   ${ASYNC_VER_REGEXP}
 info_pkg "base16-bytestring" ${BASE16_BYTESTRING_VER} \
     ${BASE16_BYTESTRING_VER_REGEXP}
@@ -499,7 +456,8 @@
 info_pkg "edit-distance" ${EDIT_DISTANCE_VER} ${EDIT_DISTANCE_VER_REGEXP}
 info_pkg "ed25519"           ${ED25519_VER}          ${ED25519_VER_REGEXP}
 info_pkg "tar"               ${TAR_VER}              ${TAR_VER_REGEXP}
-info_pkg "hashable"          ${HASHABLE_VER}         ${HASHABLE_VER_REGEXP}
+info_pkg "digest"            ${DIGEST_VER}           ${DIGEST_REGEXP}
+info_pkg "zip-archive"       ${ZIP_ARCHIVE_VER}      ${ZIP_ARCHIVE_REGEXP}
 info_pkg "hackage-security"  ${HACKAGE_SECURITY_VER} \
     ${HACKAGE_SECURITY_VER_REGEXP}
 
@@ -516,17 +474,13 @@
 # Install the Cabal library from the local Git clone if possible.
 do_Cabal_pkg
 
+do_pkg   "network-uri"  ${NETWORK_URI_VER} ${NETWORK_URI_VER_REGEXP}
 do_pkg   "network"      ${NETWORK_VER} ${NETWORK_VER_REGEXP}
-
-# We conditionally install network-uri, depending on the network version.
-do_network_uri_pkg
-
-do_pkg   "old-locale"   ${OLD_LOCALE_VER} ${OLD_LOCALE_VER_REGEXP}
-do_pkg   "old-time"     ${OLD_TIME_VER}   ${OLD_TIME_VER_REGEXP}
 do_pkg   "HTTP"         ${HTTP_VER}       ${HTTP_VER_REGEXP}
 do_pkg   "zlib"         ${ZLIB_VER}       ${ZLIB_VER_REGEXP}
 do_pkg   "random"       ${RANDOM_VER}     ${RANDOM_VER_REGEXP}
 do_pkg   "stm"          ${STM_VER}        ${STM_VER_REGEXP}
+do_pkg   "hashable"     ${HASHABLE_VER}   ${HASHABLE_VER_REGEXP}
 do_pkg   "async"        ${ASYNC_VER}      ${ASYNC_VER_REGEXP}
 do_pkg   "base16-bytestring" ${BASE16_BYTESTRING_VER} \
     ${BASE16_BYTESTRING_VER_REGEXP}
@@ -539,13 +493,9 @@
 do_pkg "echo"          ${ECHO_VER}          ${ECHO_VER_REGEXP}
 do_pkg "edit-distance" ${EDIT_DISTANCE_VER} ${EDIT_DISTANCE_VER_REGEXP}
 do_pkg   "ed25519"           ${ED25519_VER}          ${ED25519_VER_REGEXP}
-
-# We conditionally install bytestring-builder, depending on the bytestring
-# version.
-do_bytestring_builder_pkg
-
 do_pkg   "tar"               ${TAR_VER}              ${TAR_VER_REGEXP}
-do_pkg   "hashable"          ${HASHABLE_VER}         ${HASHABLE_VER_REGEXP}
+do_pkg   "digest"            ${DIGEST_VER}           ${DIGEST_REGEXP}
+do_pkg   "zip-archive"       ${ZIP_ARCHIVE_VER}      ${ZIP_ARCHIVE_REGEXP}
 do_pkg   "hackage-security"  ${HACKAGE_SECURITY_VER} \
     ${HACKAGE_SECURITY_VER_REGEXP}
 
diff --git a/cabal/cabal-install/cabal-install.cabal b/cabal/cabal-install/cabal-install.cabal
--- a/cabal/cabal-install/cabal-install.cabal
+++ b/cabal/cabal-install/cabal-install.cabal
@@ -1,28 +1,29 @@
+Cabal-Version:      >= 1.10
+-- NOTE: This file is autogenerated from 'cabal-install.cabal.pp'.
+-- DO NOT EDIT MANUALLY.
+-- To update this file, edit 'cabal-install.cabal.pp' and run
+-- 'make cabal-install-prod' in the project's root folder.
 Name:               cabal-install
-Version:            2.1.0.0
+Version:            2.4.1.0
 Synopsis:           The command-line interface for Cabal and Hackage.
 Description:
     The \'cabal\' command-line program simplifies the process of managing
     Haskell software by automating the fetching, configuration, compilation
     and installation of Haskell libraries and programs.
-    .
-    This package only provides an executable and cannot be used as a
-    library (ignore the module listing below.)
 homepage:           http://www.haskell.org/cabal/
 bug-reports:        https://github.com/haskell/cabal/issues
 License:            BSD3
 License-File:       LICENSE
 Author:             Cabal Development Team (see AUTHORS file)
 Maintainer:         Cabal Development Team <cabal-devel@haskell.org>
-Copyright:          2003-2017, Cabal Development Team
+Copyright:          2003-2018, Cabal Development Team
 Category:           Distribution
 Build-type:         Custom
-Cabal-Version:      >= 1.10
 Extra-Source-Files:
   README.md bash-completion/cabal bootstrap.sh changelog
   tests/README.md
 
-  -- Generated with '../Cabal/misc/gen-extra-source-files.sh'
+  -- Generated with 'make gen-extra-source-files'
   -- Do NOT edit this section manually; instead, run the script.
   -- BEGIN gen-extra-source-files
   tests/IntegrationTests2/build/keep-going/cabal.project
@@ -30,6 +31,9 @@
   tests/IntegrationTests2/build/keep-going/p/p.cabal
   tests/IntegrationTests2/build/keep-going/q/Q.hs
   tests/IntegrationTests2/build/keep-going/q/q.cabal
+  tests/IntegrationTests2/build/local-tarball/cabal.project
+  tests/IntegrationTests2/build/local-tarball/q/Q.hs
+  tests/IntegrationTests2/build/local-tarball/q/q.cabal
   tests/IntegrationTests2/build/setup-custom1/A.hs
   tests/IntegrationTests2/build/setup-custom1/Setup.hs
   tests/IntegrationTests2/build/setup-custom1/a.cabal
@@ -65,6 +69,7 @@
   tests/IntegrationTests2/targets/exes-disabled/cabal.project
   tests/IntegrationTests2/targets/exes-disabled/p/p.cabal
   tests/IntegrationTests2/targets/exes-disabled/q/q.cabal
+  tests/IntegrationTests2/targets/lib-only/p.cabal
   tests/IntegrationTests2/targets/libs-disabled/cabal.project
   tests/IntegrationTests2/targets/libs-disabled/p/p.cabal
   tests/IntegrationTests2/targets/libs-disabled/q/q.cabal
@@ -88,23 +93,15 @@
   tests/IntegrationTests2/targets/variety/p.cabal
   -- END gen-extra-source-files
 
+  -- Additional manual extra-source-files:
+  tests/IntegrationTests2/build/local-tarball/p-0.1.tar.gz
+
+
 source-repository head
   type:     git
   location: https://github.com/haskell/cabal/
   subdir:   cabal-install
 
-Flag old-bytestring
-  description:  Use bytestring < 0.10.2 and bytestring-builder
-  default: False
-
-Flag old-directory
-  description:  Use directory < 1.2 and old-time
-  default:      False
-
-Flag network-uri
-  description:  Get Network.URI from the network-uri package
-  default:      True
-
 Flag native-dns
   description:  Enable use of the [resolv](https://hackage.haskell.org/package/resolv) & [windns](https://hackage.haskell.org/package/windns) packages for performing DNS lookups
   default:      True
@@ -125,32 +122,30 @@
   default:      False
   manual:       True
 
-flag lib
-  description:  Build cabal-install as a library. Please only use this if you are a cabal-install developer.
-  Default:      False
-  manual:       True
-
--- Build everything (including the test binaries) as a single static binary
--- instead of 5 discrete binaries.
--- This is useful for CI where we build our binaries on one machine, and then
--- ship them to another machine for testing.  Since the test binaries are
--- statically linked (making deployment easier), if we build five executables,
--- that means we need to ship ALL 5 binaries (with 5 versions of all the
--- statically linked libraries) to the test machines. This reduces that to one
--- binary and one set of linked libraries.
-flag monolithic
-  description:  Build cabal-install also with all of its test and support code.  Used by our continuous integration.
-  default:      False
-  manual:       True
+custom-setup
+   setup-depends:
+       Cabal     >= 2.2,
+       base,
+       process   >= 1.1.0.1  && < 1.7,
+       filepath  >= 1.3      && < 1.5
 
-library
+executable cabal
+    main-is:        Main.hs
+    hs-source-dirs: main
+    default-language: Haskell2010
     ghc-options:    -Wall -fwarn-tabs
     if impl(ghc >= 8.0)
         ghc-options: -Wcompat
                      -Wnoncanonical-monad-instances
                      -Wnoncanonical-monadfail-instances
 
-    exposed-modules:
+    ghc-options: -rtsopts -threaded
+
+    -- On AIX, some legacy BSD operations such as flock(2) are provided by libbsd.a
+    if os(aix)
+        extra-libraries: bsd
+    hs-source-dirs: .
+    other-modules:
         Distribution.Client.BuildReports.Anonymous
         Distribution.Client.BuildReports.Storage
         Distribution.Client.BuildReports.Types
@@ -158,6 +153,7 @@
         Distribution.Client.Check
         Distribution.Client.CmdBench
         Distribution.Client.CmdBuild
+        Distribution.Client.CmdClean
         Distribution.Client.CmdConfigure
         Distribution.Client.CmdUpdate
         Distribution.Client.CmdErrorMessages
@@ -168,6 +164,9 @@
         Distribution.Client.CmdRepl
         Distribution.Client.CmdRun
         Distribution.Client.CmdTest
+        Distribution.Client.CmdLegacy
+        Distribution.Client.CmdSdist
+        Distribution.Client.Compat.Directory
         Distribution.Client.Compat.ExecutablePath
         Distribution.Client.Compat.FileLock
         Distribution.Client.Compat.FilePerms
@@ -232,6 +231,7 @@
         Distribution.Client.SetupWrapper
         Distribution.Client.SolverInstallPlan
         Distribution.Client.SourceFiles
+        Distribution.Client.SourceRepoParse
         Distribution.Client.SrcDist
         Distribution.Client.Store
         Distribution.Client.Tar
@@ -243,6 +243,7 @@
         Distribution.Client.Utils
         Distribution.Client.Utils.Assertion
         Distribution.Client.Utils.Json
+        Distribution.Client.VCS
         Distribution.Client.Win32SelfUpgrade
         Distribution.Client.World
         Distribution.Solver.Compat.Prelude
@@ -295,52 +296,37 @@
         Distribution.Solver.Types.Variable
         Paths_cabal_install
 
-    -- NOTE: when updating build-depends, don't forget to update version regexps
-    -- in bootstrap.sh.
     build-depends:
-        async      >= 2.0      && < 3,
+        async      >= 2.0      && < 2.3,
         array      >= 0.4      && < 0.6,
-        base       >= 4.5      && < 5,
+        base       >= 4.8      && < 4.13,
         base16-bytestring >= 0.1.1 && < 0.2,
-        binary     >= 0.5      && < 0.9,
-        bytestring >= 0.9      && < 1,
-        Cabal      >= 2.1      && < 2.2,
-        containers >= 0.4      && < 0.6,
+        binary     >= 0.7.3    && < 0.9,
+        bytestring >= 0.10.6.0 && < 0.11,
+        Cabal      >= 2.4.1.0  && < 2.5,
+        containers >= 0.5.6.2  && < 0.7,
         cryptohash-sha256 >= 0.11 && < 0.12,
-        deepseq    >= 1.3      && < 1.5,
+        deepseq    >= 1.4.1.1  && < 1.5,
+        directory  >= 1.2.2.0  && < 1.4,
         echo       >= 0.1.3    && < 0.2,
         edit-distance >= 0.2.2 && < 0.3,
-        filepath   >= 1.3      && < 1.5,
-        hashable   >= 1.0      && < 2,
+        filepath   >= 1.4.0.0  && < 1.5,
+        hashable   >= 1.0      && < 1.3,
         HTTP       >= 4000.1.5 && < 4000.4,
-        mtl        >= 2.0      && < 3,
+        mtl        >= 2.0      && < 2.3,
+        network-uri >= 2.6.0.2 && < 2.7,
+        network    >= 2.6      && < 2.9,
         pretty     >= 1.1      && < 1.2,
+        process    >= 1.2.3.0  && < 1.7,
         random     >= 1        && < 1.2,
-        stm        >= 2.0      && < 3,
+        stm        >= 2.0      && < 2.6,
         tar        >= 0.5.0.3  && < 0.6,
-        time       >= 1.4      && < 1.9,
+        time       >= 1.5.0.1  && < 1.10,
         zlib       >= 0.5.3    && < 0.7,
-        hackage-security >= 0.5.2.2 && < 0.6
-
-    if flag(old-bytestring)
-      build-depends: bytestring <  0.10.2, bytestring-builder >= 0.10 && < 1
-    else
-      build-depends: bytestring >= 0.10.2
-
-    if flag(old-directory)
-      build-depends: directory >= 1.1 && < 1.2, old-time >= 1 && < 1.2,
-                     process   >= 1.0.1.1  && < 1.1.0.2
-    else
-      build-depends: directory >= 1.2 && < 1.4,
-                     process   >= 1.1.0.2  && < 1.7
-
-    -- NOTE: you MUST include the network dependency even when network-uri
-    -- is pulled in, otherwise the constraint solver doesn't have enough
-    -- information
-    if flag(network-uri)
-      build-depends: network-uri >= 2.6 && < 2.7, network >= 2.6 && < 2.7
-    else
-      build-depends: network     >= 2.4 && < 2.6
+        hackage-security >= 0.5.2.2 && < 0.6,
+        text       >= 1.2.3    && < 1.3,
+        zip-archive >= 0.3.2.5 && < 0.4,
+        parsec     >= 3.1.13.0 && < 3.2
 
     if flag(native-dns)
       if os(windows)
@@ -348,10 +334,6 @@
       else
         build-depends: resolv      >= 0.1.1 && < 0.2
 
-    -- Needed for GHC.Generics before GHC 7.6
-    if impl(ghc < 7.6)
-      build-depends: ghc-prim >= 0.2 && < 0.3
-
     if os(windows)
       build-depends: Win32 >= 2 && < 3
     else
@@ -367,465 +349,3 @@
     if flag(debug-tracetree)
       cpp-options: -DDEBUG_TRACETREE
       build-depends: tracetree >= 0.1 && < 0.2
-
-    if !flag(lib)
-      buildable: False
-
-    default-language: Haskell2010
-
-executable cabal
-    main-is:        Main.hs
-    hs-source-dirs: main
-
-    ghc-options:    -Wall -fwarn-tabs -rtsopts
-    if impl(ghc >= 8.0)
-        ghc-options: -Wcompat
-                     -Wnoncanonical-monad-instances
-                     -Wnoncanonical-monadfail-instances
-
-    other-modules: Paths_cabal_install
-
-    if flag(lib)
-        build-depends:
-            cabal-install,
-            Cabal      >= 2.1      && < 2.2,
-            base,
-            directory,
-            filepath
-    else
-        hs-source-dirs: .
-        build-depends:
-            async      >= 2.0      && < 3,
-            array      >= 0.4      && < 0.6,
-            base       >= 4.5      && < 5,
-            base16-bytestring >= 0.1.1 && < 0.2,
-            binary     >= 0.5      && < 0.9,
-            bytestring >= 0.9      && < 1,
-            Cabal      >= 2.1      && < 2.2,
-            containers >= 0.4      && < 0.6,
-            cryptohash-sha256 >= 0.11 && < 0.12,
-            deepseq    >= 1.3      && < 1.5,
-            echo       >= 0.1.3    && < 0.2,
-            edit-distance >= 0.2.2 && < 0.3,
-            filepath   >= 1.3      && < 1.5,
-            hashable   >= 1.0      && < 2,
-            HTTP       >= 4000.1.5 && < 4000.4,
-            mtl        >= 2.0      && < 3,
-            pretty     >= 1.1      && < 1.2,
-            random     >= 1        && < 1.2,
-            stm        >= 2.0      && < 3,
-            tar        >= 0.5.0.3  && < 0.6,
-            time       >= 1.4      && < 1.9,
-            zlib       >= 0.5.3    && < 0.7,
-            hackage-security >= 0.5.2.2 && < 0.6
-
-        other-modules:
-            Distribution.Client.BuildReports.Anonymous
-            Distribution.Client.BuildReports.Storage
-            Distribution.Client.BuildReports.Types
-            Distribution.Client.BuildReports.Upload
-            Distribution.Client.Check
-            Distribution.Client.CmdBench
-            Distribution.Client.CmdBuild
-            Distribution.Client.CmdConfigure
-            Distribution.Client.CmdUpdate
-            Distribution.Client.CmdErrorMessages
-            Distribution.Client.CmdExec
-            Distribution.Client.CmdFreeze
-            Distribution.Client.CmdHaddock
-            Distribution.Client.CmdInstall
-            Distribution.Client.CmdRepl
-            Distribution.Client.CmdRun
-            Distribution.Client.CmdTest
-            Distribution.Client.Compat.ExecutablePath
-            Distribution.Client.Compat.FileLock
-            Distribution.Client.Compat.FilePerms
-            Distribution.Client.Compat.Prelude
-            Distribution.Client.Compat.Process
-            Distribution.Client.Compat.Semaphore
-            Distribution.Client.Config
-            Distribution.Client.Configure
-            Distribution.Client.Dependency
-            Distribution.Client.Dependency.Types
-            Distribution.Client.DistDirLayout
-            Distribution.Client.Exec
-            Distribution.Client.Fetch
-            Distribution.Client.FetchUtils
-            Distribution.Client.FileMonitor
-            Distribution.Client.Freeze
-            Distribution.Client.GZipUtils
-            Distribution.Client.GenBounds
-            Distribution.Client.Get
-            Distribution.Client.Glob
-            Distribution.Client.GlobalFlags
-            Distribution.Client.Haddock
-            Distribution.Client.HttpUtils
-            Distribution.Client.IndexUtils
-            Distribution.Client.IndexUtils.Timestamp
-            Distribution.Client.Init
-            Distribution.Client.Init.Heuristics
-            Distribution.Client.Init.Licenses
-            Distribution.Client.Init.Types
-            Distribution.Client.Install
-            Distribution.Client.InstallPlan
-            Distribution.Client.InstallSymlink
-            Distribution.Client.JobControl
-            Distribution.Client.List
-            Distribution.Client.Manpage
-            Distribution.Client.Nix
-            Distribution.Client.Outdated
-            Distribution.Client.PackageHash
-            Distribution.Client.PackageUtils
-            Distribution.Client.ParseUtils
-            Distribution.Client.ProjectBuilding
-            Distribution.Client.ProjectBuilding.Types
-            Distribution.Client.ProjectConfig
-            Distribution.Client.ProjectConfig.Legacy
-            Distribution.Client.ProjectConfig.Types
-            Distribution.Client.ProjectOrchestration
-            Distribution.Client.ProjectPlanOutput
-            Distribution.Client.ProjectPlanning
-            Distribution.Client.ProjectPlanning.Types
-            Distribution.Client.RebuildMonad
-            Distribution.Client.Reconfigure
-            Distribution.Client.Run
-            Distribution.Client.Sandbox
-            Distribution.Client.Sandbox.Index
-            Distribution.Client.Sandbox.PackageEnvironment
-            Distribution.Client.Sandbox.Timestamp
-            Distribution.Client.Sandbox.Types
-            Distribution.Client.SavedFlags
-            Distribution.Client.Security.DNS
-            Distribution.Client.Security.HTTP
-            Distribution.Client.Setup
-            Distribution.Client.SetupWrapper
-            Distribution.Client.SolverInstallPlan
-            Distribution.Client.SourceFiles
-            Distribution.Client.SrcDist
-            Distribution.Client.Store
-            Distribution.Client.Tar
-            Distribution.Client.TargetSelector
-            Distribution.Client.Targets
-            Distribution.Client.Types
-            Distribution.Client.Update
-            Distribution.Client.Upload
-            Distribution.Client.Utils
-            Distribution.Client.Utils.Assertion
-            Distribution.Client.Utils.Json
-            Distribution.Client.Win32SelfUpgrade
-            Distribution.Client.World
-            Distribution.Solver.Compat.Prelude
-            Distribution.Solver.Modular
-            Distribution.Solver.Modular.Assignment
-            Distribution.Solver.Modular.Builder
-            Distribution.Solver.Modular.Configured
-            Distribution.Solver.Modular.ConfiguredConversion
-            Distribution.Solver.Modular.ConflictSet
-            Distribution.Solver.Modular.Cycles
-            Distribution.Solver.Modular.Dependency
-            Distribution.Solver.Modular.Explore
-            Distribution.Solver.Modular.Flag
-            Distribution.Solver.Modular.Index
-            Distribution.Solver.Modular.IndexConversion
-            Distribution.Solver.Modular.LabeledGraph
-            Distribution.Solver.Modular.Linking
-            Distribution.Solver.Modular.Log
-            Distribution.Solver.Modular.Message
-            Distribution.Solver.Modular.PSQ
-            Distribution.Solver.Modular.Package
-            Distribution.Solver.Modular.Preference
-            Distribution.Solver.Modular.RetryLog
-            Distribution.Solver.Modular.Solver
-            Distribution.Solver.Modular.Tree
-            Distribution.Solver.Modular.Validate
-            Distribution.Solver.Modular.Var
-            Distribution.Solver.Modular.Version
-            Distribution.Solver.Modular.WeightedPSQ
-            Distribution.Solver.Types.ComponentDeps
-            Distribution.Solver.Types.ConstraintSource
-            Distribution.Solver.Types.DependencyResolver
-            Distribution.Solver.Types.Flag
-            Distribution.Solver.Types.InstSolverPackage
-            Distribution.Solver.Types.InstalledPreference
-            Distribution.Solver.Types.LabeledPackageConstraint
-            Distribution.Solver.Types.OptionalStanza
-            Distribution.Solver.Types.PackageConstraint
-            Distribution.Solver.Types.PackageFixedDeps
-            Distribution.Solver.Types.PackageIndex
-            Distribution.Solver.Types.PackagePath
-            Distribution.Solver.Types.PackagePreferences
-            Distribution.Solver.Types.PkgConfigDb
-            Distribution.Solver.Types.Progress
-            Distribution.Solver.Types.ResolverPackage
-            Distribution.Solver.Types.Settings
-            Distribution.Solver.Types.SolverId
-            Distribution.Solver.Types.SolverPackage
-            Distribution.Solver.Types.SourcePackage
-            Distribution.Solver.Types.Variable
-
-        if flag(old-bytestring)
-          build-depends: bytestring <  0.10.2, bytestring-builder >= 0.10 && < 1
-        else
-          build-depends: bytestring >= 0.10.2
-
-        if flag(old-directory)
-          build-depends: directory >= 1.1 && < 1.2, old-time >= 1 && < 1.2,
-                         process   >= 1.0.1.1  && < 1.1.0.2
-        else
-          build-depends: directory >= 1.2 && < 1.4,
-                         process   >= 1.1.0.2  && < 1.7
-
-        -- NOTE: you MUST include the network dependency even when network-uri
-        -- is pulled in, otherwise the constraint solver doesn't have enough
-        -- information
-        if flag(network-uri)
-          build-depends: network-uri >= 2.6 && < 2.7, network >= 2.6 && < 2.7
-        else
-          build-depends: network     >= 2.4 && < 2.6
-
-        if flag(native-dns)
-          if os(windows)
-            build-depends: windns      >= 0.1.0 && < 0.2
-          else
-            build-depends: resolv      >= 0.1.1 && < 0.2
-
-        -- Needed for GHC.Generics before GHC 7.6
-        if impl(ghc < 7.6)
-          build-depends: ghc-prim >= 0.2 && < 0.3
-
-        if os(windows)
-          build-depends: Win32 >= 2 && < 3
-        else
-          build-depends: unix >= 2.5 && < 2.8
-
-        if flag(debug-expensive-assertions)
-          cpp-options: -DDEBUG_EXPENSIVE_ASSERTIONS
-
-        if flag(debug-conflict-sets)
-          cpp-options: -DDEBUG_CONFLICT_SETS
-          build-depends: base >= 4.8
-
-        if flag(debug-tracetree)
-          cpp-options: -DDEBUG_TRACETREE
-          build-depends: tracetree >= 0.1 && < 0.2
-
-    if flag(monolithic)
-      hs-source-dirs: tests
-      other-modules:
-        UnitTests
-        MemoryUsageTests
-        SolverQuickCheck
-        IntegrationTests2
-
-        UnitTests.Distribution.Client.ArbitraryInstances
-        UnitTests.Distribution.Client.FileMonitor
-        UnitTests.Distribution.Client.GZipUtils
-        UnitTests.Distribution.Client.Glob
-        UnitTests.Distribution.Client.IndexUtils.Timestamp
-        UnitTests.Distribution.Client.InstallPlan
-        UnitTests.Distribution.Client.JobControl
-        UnitTests.Distribution.Client.ProjectConfig
-        UnitTests.Distribution.Client.Sandbox
-        UnitTests.Distribution.Client.Sandbox.Timestamp
-        UnitTests.Distribution.Client.Store
-        UnitTests.Distribution.Client.Tar
-        UnitTests.Distribution.Client.Targets
-        UnitTests.Distribution.Client.UserConfig
-        UnitTests.Distribution.Solver.Modular.Builder
-        UnitTests.Distribution.Solver.Modular.DSL
-        UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils
-        UnitTests.Distribution.Solver.Modular.MemoryUsage
-        UnitTests.Distribution.Solver.Modular.QuickCheck
-        UnitTests.Distribution.Solver.Modular.RetryLog
-        UnitTests.Distribution.Solver.Modular.Solver
-        UnitTests.Distribution.Solver.Modular.WeightedPSQ
-        UnitTests.Options
-
-      cpp-options: -DMONOLITHIC
-      build-depends:
-        Cabal      >= 2.1 && < 2.2,
-        QuickCheck >= 2.8.2,
-        array,
-        async,
-        bytestring,
-        containers,
-        deepseq,
-        directory,
-        edit-distance,
-        filepath,
-        hashable,
-        mtl,
-        network,
-        network-uri,
-        pretty-show,
-        random,
-        tagged,
-        tar,
-        tasty >= 0.12,
-        tasty-hunit >= 0.10,
-        tasty-quickcheck,
-        time,
-        zlib
-
-    if !(arch(arm) && impl(ghc < 7.6))
-      ghc-options: -threaded
-
-    -- On AIX, some legacy BSD operations such as flock(2) are provided by libbsd.a
-    if os(aix)
-      extra-libraries: bsd
-
-    default-language: Haskell2010
-
--- Small, fast running tests.
-Test-Suite unit-tests
-  type: exitcode-stdio-1.0
-  main-is: UnitTests.hs
-  hs-source-dirs: tests
-  ghc-options: -Wall -fwarn-tabs -main-is UnitTests
-  other-modules:
-    UnitTests.Distribution.Client.ArbitraryInstances
-    UnitTests.Distribution.Client.Targets
-    UnitTests.Distribution.Client.FileMonitor
-    UnitTests.Distribution.Client.Glob
-    UnitTests.Distribution.Client.GZipUtils
-    UnitTests.Distribution.Client.Sandbox
-    UnitTests.Distribution.Client.Sandbox.Timestamp
-    UnitTests.Distribution.Client.Store
-    UnitTests.Distribution.Client.Tar
-    UnitTests.Distribution.Client.UserConfig
-    UnitTests.Distribution.Client.ProjectConfig
-    UnitTests.Distribution.Client.JobControl
-    UnitTests.Distribution.Client.IndexUtils.Timestamp
-    UnitTests.Distribution.Client.InstallPlan
-    UnitTests.Distribution.Solver.Modular.Builder
-    UnitTests.Distribution.Solver.Modular.RetryLog
-    UnitTests.Distribution.Solver.Modular.Solver
-    UnitTests.Distribution.Solver.Modular.DSL
-    UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils
-    UnitTests.Distribution.Solver.Modular.WeightedPSQ
-    UnitTests.Options
-  build-depends:
-        array,
-        base,
-        async,
-        bytestring,
-        cabal-install,
-        Cabal,
-        containers,
-        deepseq,
-        mtl,
-        random,
-        directory,
-        filepath,
-        tar,
-        time,
-        zlib,
-        network-uri,
-        network,
-        tasty >= 0.12,
-        tasty-hunit >= 0.10,
-        tasty-quickcheck,
-        tagged,
-        QuickCheck >= 2.8.2
-
-  if !(arch(arm) && impl(ghc < 7.6))
-    ghc-options: -threaded
-
-  if !flag(lib)
-    buildable: False
-
-  default-language: Haskell2010
-
--- Tests to run with a limited stack and heap size
-Test-Suite memory-usage-tests
-  type: exitcode-stdio-1.0
-  main-is: MemoryUsageTests.hs
-  hs-source-dirs: tests
-  ghc-options: -Wall -fwarn-tabs "-with-rtsopts=-M4M -K1K" -main-is MemoryUsageTests
-  other-modules:
-    UnitTests.Distribution.Solver.Modular.DSL
-    UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils
-    UnitTests.Distribution.Solver.Modular.MemoryUsage
-    UnitTests.Options
-  build-depends:
-        base,
-        async,
-        Cabal,
-        cabal-install,
-        containers,
-        deepseq,
-        tagged,
-        tasty >= 0.12,
-        tasty-hunit >= 0.10
-
-  if !(arch(arm) && impl(ghc < 7.6))
-    ghc-options: -threaded
-
-  if !flag(lib)
-    buildable: False
-
-  default-language: Haskell2010
-
--- Slow solver tests
-Test-Suite solver-quickcheck
-  type: exitcode-stdio-1.0
-  main-is: SolverQuickCheck.hs
-  hs-source-dirs: tests
-  ghc-options: -Wall -fwarn-tabs -main-is SolverQuickCheck
-  other-modules:
-    UnitTests.Distribution.Solver.Modular.DSL
-    UnitTests.Distribution.Solver.Modular.QuickCheck
-  build-depends:
-        base,
-        async,
-        Cabal,
-        cabal-install,
-        containers,
-        deepseq >= 1.2,
-        hashable,
-        tasty >= 0.12,
-        tasty-quickcheck,
-        QuickCheck >= 2.8.2,
-        pretty-show
-
-  if !(arch(arm) && impl(ghc < 7.6))
-    ghc-options: -threaded
-
-  if !flag(lib)
-    buildable: False
-
-  default-language: Haskell2010
-
--- Integration tests that use the cabal-install code directly
--- but still build whole projects
-test-suite integration-tests2
-  type: exitcode-stdio-1.0
-  main-is: IntegrationTests2.hs
-  hs-source-dirs: tests
-  ghc-options: -Wall -fwarn-tabs -main-is IntegrationTests2
-  other-modules:
-  build-depends:
-        base,
-        Cabal,
-        cabal-install,
-        containers,
-        deepseq,
-        directory,
-        edit-distance,
-        filepath,
-        tasty >= 0.12,
-        tasty-hunit >= 0.10,
-        tagged
-
-  if !flag(lib)
-    buildable: False
-
-  if !(arch(arm) && impl(ghc < 7.6))
-    ghc-options: -threaded
-  default-language: Haskell2010
-
-custom-setup
-  setup-depends: Cabal >= 2.1,
-                 base,
-                 process   >= 1.1.0.1  && < 1.7,
-                 filepath   >= 1.3      && < 1.5
diff --git a/cabal/cabal-install/cabal-install.cabal.pp b/cabal/cabal-install/cabal-install.cabal.pp
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/cabal-install.cabal.pp
@@ -0,0 +1,642 @@
+# lib enabled means that we have internal library: cabal-lib-client
+%if CABAL_FLAG_LIB
+Cabal-Version:      2.0
+%else
+Cabal-Version:      >= 1.10
+%endif
+    $variable
+-- NOTE: This file is autogenerated from 'cabal-install.cabal.pp'.
+-- DO NOT EDIT MANUALLY.
+-- To update this file, edit 'cabal-install.cabal.pp' and run
+-- 'make cabal-install-prod' in the project's root folder.
+Name:               cabal-install
+Version:            2.4.1.0
+#
+# NOTE: when updating build-depends, don't forget to update version regexps in bootstrap.sh.
+#
+%def CABAL_BUILDDEPENDS
+    build-depends:
+        async      >= 2.0      && < 2.3,
+        array      >= 0.4      && < 0.6,
+        base       >= 4.8      && < 4.13,
+        base16-bytestring >= 0.1.1 && < 0.2,
+        binary     >= 0.7.3    && < 0.9,
+        bytestring >= 0.10.6.0 && < 0.11,
+        Cabal      >= 2.4.1.0  && < 2.5,
+        containers >= 0.5.6.2  && < 0.7,
+        cryptohash-sha256 >= 0.11 && < 0.12,
+        deepseq    >= 1.4.1.1  && < 1.5,
+        directory  >= 1.2.2.0  && < 1.4,
+        echo       >= 0.1.3    && < 0.2,
+        edit-distance >= 0.2.2 && < 0.3,
+        filepath   >= 1.4.0.0  && < 1.5,
+        hashable   >= 1.0      && < 1.3,
+        HTTP       >= 4000.1.5 && < 4000.4,
+        mtl        >= 2.0      && < 2.3,
+        network-uri >= 2.6.0.2 && < 2.7,
+        network    >= 2.6      && < 2.9,
+        pretty     >= 1.1      && < 1.2,
+        process    >= 1.2.3.0  && < 1.7,
+        random     >= 1        && < 1.2,
+        stm        >= 2.0      && < 2.6,
+        tar        >= 0.5.0.3  && < 0.6,
+        time       >= 1.5.0.1  && < 1.10,
+        zlib       >= 0.5.3    && < 0.7,
+        hackage-security >= 0.5.2.2 && < 0.6,
+        text       >= 1.2.3    && < 1.3,
+        zip-archive >= 0.3.2.5 && < 0.4,
+        parsec     >= 3.1.13.0 && < 3.2
+
+    if flag(native-dns)
+      if os(windows)
+        build-depends: windns      >= 0.1.0 && < 0.2
+      else
+        build-depends: resolv      >= 0.1.1 && < 0.2
+
+    if os(windows)
+      build-depends: Win32 >= 2 && < 3
+    else
+      build-depends: unix >= 2.5 && < 2.8
+%enddef
+%def CABAL_COMPONENTCOMMON
+    default-language: Haskell2010
+    ghc-options:    -Wall -fwarn-tabs
+    if impl(ghc >= 8.0)
+        ghc-options: -Wcompat
+                     -Wnoncanonical-monad-instances
+                     -Wnoncanonical-monadfail-instances
+%enddef
+%def CABAL_BUILDINFO
+%if CABAL_FLAG_LIB
+    exposed-modules:
+%else
+    other-modules:
+%endif
+        Distribution.Client.BuildReports.Anonymous
+        Distribution.Client.BuildReports.Storage
+        Distribution.Client.BuildReports.Types
+        Distribution.Client.BuildReports.Upload
+        Distribution.Client.Check
+        Distribution.Client.CmdBench
+        Distribution.Client.CmdBuild
+        Distribution.Client.CmdClean
+        Distribution.Client.CmdConfigure
+        Distribution.Client.CmdUpdate
+        Distribution.Client.CmdErrorMessages
+        Distribution.Client.CmdExec
+        Distribution.Client.CmdFreeze
+        Distribution.Client.CmdHaddock
+        Distribution.Client.CmdInstall
+        Distribution.Client.CmdRepl
+        Distribution.Client.CmdRun
+        Distribution.Client.CmdTest
+        Distribution.Client.CmdLegacy
+        Distribution.Client.CmdSdist
+        Distribution.Client.Compat.Directory
+        Distribution.Client.Compat.ExecutablePath
+        Distribution.Client.Compat.FileLock
+        Distribution.Client.Compat.FilePerms
+        Distribution.Client.Compat.Prelude
+        Distribution.Client.Compat.Process
+        Distribution.Client.Compat.Semaphore
+        Distribution.Client.Config
+        Distribution.Client.Configure
+        Distribution.Client.Dependency
+        Distribution.Client.Dependency.Types
+        Distribution.Client.DistDirLayout
+        Distribution.Client.Exec
+        Distribution.Client.Fetch
+        Distribution.Client.FetchUtils
+        Distribution.Client.FileMonitor
+        Distribution.Client.Freeze
+        Distribution.Client.GZipUtils
+        Distribution.Client.GenBounds
+        Distribution.Client.Get
+        Distribution.Client.Glob
+        Distribution.Client.GlobalFlags
+        Distribution.Client.Haddock
+        Distribution.Client.HttpUtils
+        Distribution.Client.IndexUtils
+        Distribution.Client.IndexUtils.Timestamp
+        Distribution.Client.Init
+        Distribution.Client.Init.Heuristics
+        Distribution.Client.Init.Licenses
+        Distribution.Client.Init.Types
+        Distribution.Client.Install
+        Distribution.Client.InstallPlan
+        Distribution.Client.InstallSymlink
+        Distribution.Client.JobControl
+        Distribution.Client.List
+        Distribution.Client.Manpage
+        Distribution.Client.Nix
+        Distribution.Client.Outdated
+        Distribution.Client.PackageHash
+        Distribution.Client.PackageUtils
+        Distribution.Client.ParseUtils
+        Distribution.Client.ProjectBuilding
+        Distribution.Client.ProjectBuilding.Types
+        Distribution.Client.ProjectConfig
+        Distribution.Client.ProjectConfig.Legacy
+        Distribution.Client.ProjectConfig.Types
+        Distribution.Client.ProjectOrchestration
+        Distribution.Client.ProjectPlanOutput
+        Distribution.Client.ProjectPlanning
+        Distribution.Client.ProjectPlanning.Types
+        Distribution.Client.RebuildMonad
+        Distribution.Client.Reconfigure
+        Distribution.Client.Run
+        Distribution.Client.Sandbox
+        Distribution.Client.Sandbox.Index
+        Distribution.Client.Sandbox.PackageEnvironment
+        Distribution.Client.Sandbox.Timestamp
+        Distribution.Client.Sandbox.Types
+        Distribution.Client.SavedFlags
+        Distribution.Client.Security.DNS
+        Distribution.Client.Security.HTTP
+        Distribution.Client.Setup
+        Distribution.Client.SetupWrapper
+        Distribution.Client.SolverInstallPlan
+        Distribution.Client.SourceFiles
+        Distribution.Client.SourceRepoParse
+        Distribution.Client.SrcDist
+        Distribution.Client.Store
+        Distribution.Client.Tar
+        Distribution.Client.TargetSelector
+        Distribution.Client.Targets
+        Distribution.Client.Types
+        Distribution.Client.Update
+        Distribution.Client.Upload
+        Distribution.Client.Utils
+        Distribution.Client.Utils.Assertion
+        Distribution.Client.Utils.Json
+        Distribution.Client.VCS
+        Distribution.Client.Win32SelfUpgrade
+        Distribution.Client.World
+        Distribution.Solver.Compat.Prelude
+        Distribution.Solver.Modular
+        Distribution.Solver.Modular.Assignment
+        Distribution.Solver.Modular.Builder
+        Distribution.Solver.Modular.Configured
+        Distribution.Solver.Modular.ConfiguredConversion
+        Distribution.Solver.Modular.ConflictSet
+        Distribution.Solver.Modular.Cycles
+        Distribution.Solver.Modular.Dependency
+        Distribution.Solver.Modular.Explore
+        Distribution.Solver.Modular.Flag
+        Distribution.Solver.Modular.Index
+        Distribution.Solver.Modular.IndexConversion
+        Distribution.Solver.Modular.LabeledGraph
+        Distribution.Solver.Modular.Linking
+        Distribution.Solver.Modular.Log
+        Distribution.Solver.Modular.Message
+        Distribution.Solver.Modular.PSQ
+        Distribution.Solver.Modular.Package
+        Distribution.Solver.Modular.Preference
+        Distribution.Solver.Modular.RetryLog
+        Distribution.Solver.Modular.Solver
+        Distribution.Solver.Modular.Tree
+        Distribution.Solver.Modular.Validate
+        Distribution.Solver.Modular.Var
+        Distribution.Solver.Modular.Version
+        Distribution.Solver.Modular.WeightedPSQ
+        Distribution.Solver.Types.ComponentDeps
+        Distribution.Solver.Types.ConstraintSource
+        Distribution.Solver.Types.DependencyResolver
+        Distribution.Solver.Types.Flag
+        Distribution.Solver.Types.InstSolverPackage
+        Distribution.Solver.Types.InstalledPreference
+        Distribution.Solver.Types.LabeledPackageConstraint
+        Distribution.Solver.Types.OptionalStanza
+        Distribution.Solver.Types.PackageConstraint
+        Distribution.Solver.Types.PackageFixedDeps
+        Distribution.Solver.Types.PackageIndex
+        Distribution.Solver.Types.PackagePath
+        Distribution.Solver.Types.PackagePreferences
+        Distribution.Solver.Types.PkgConfigDb
+        Distribution.Solver.Types.Progress
+        Distribution.Solver.Types.ResolverPackage
+        Distribution.Solver.Types.Settings
+        Distribution.Solver.Types.SolverId
+        Distribution.Solver.Types.SolverPackage
+        Distribution.Solver.Types.SourcePackage
+        Distribution.Solver.Types.Variable
+        Paths_cabal_install
+
+%if CABAL_FLAG_LIB
+    autogen-modules:
+        Paths_cabal_install
+%endif
+    $CABAL_BUILDDEPENDS
+
+    if flag(debug-expensive-assertions)
+      cpp-options: -DDEBUG_EXPENSIVE_ASSERTIONS
+
+    if flag(debug-conflict-sets)
+      cpp-options: -DDEBUG_CONFLICT_SETS
+      build-depends: base >= 4.8
+
+    if flag(debug-tracetree)
+      cpp-options: -DDEBUG_TRACETREE
+      build-depends: tracetree >= 0.1 && < 0.2
+%enddef
+#
+# Package Description
+#
+Synopsis:           The command-line interface for Cabal and Hackage.
+Description:
+    The \'cabal\' command-line program simplifies the process of managing
+    Haskell software by automating the fetching, configuration, compilation
+    and installation of Haskell libraries and programs.
+homepage:           http://www.haskell.org/cabal/
+bug-reports:        https://github.com/haskell/cabal/issues
+License:            BSD3
+License-File:       LICENSE
+Author:             Cabal Development Team (see AUTHORS file)
+Maintainer:         Cabal Development Team <cabal-devel@haskell.org>
+Copyright:          2003-2018, Cabal Development Team
+Category:           Distribution
+%if CABAL_FLAG_LIB
+Build-type:         Simple
+%else
+Build-type:         Custom
+%endif
+Extra-Source-Files:
+  README.md bash-completion/cabal bootstrap.sh changelog
+  tests/README.md
+
+  -- Generated with 'make gen-extra-source-files'
+  -- Do NOT edit this section manually; instead, run the script.
+  -- BEGIN gen-extra-source-files
+  tests/IntegrationTests2/build/keep-going/cabal.project
+  tests/IntegrationTests2/build/keep-going/p/P.hs
+  tests/IntegrationTests2/build/keep-going/p/p.cabal
+  tests/IntegrationTests2/build/keep-going/q/Q.hs
+  tests/IntegrationTests2/build/keep-going/q/q.cabal
+  tests/IntegrationTests2/build/local-tarball/cabal.project
+  tests/IntegrationTests2/build/local-tarball/q/Q.hs
+  tests/IntegrationTests2/build/local-tarball/q/q.cabal
+  tests/IntegrationTests2/build/setup-custom1/A.hs
+  tests/IntegrationTests2/build/setup-custom1/Setup.hs
+  tests/IntegrationTests2/build/setup-custom1/a.cabal
+  tests/IntegrationTests2/build/setup-custom2/A.hs
+  tests/IntegrationTests2/build/setup-custom2/Setup.hs
+  tests/IntegrationTests2/build/setup-custom2/a.cabal
+  tests/IntegrationTests2/build/setup-simple/A.hs
+  tests/IntegrationTests2/build/setup-simple/Setup.hs
+  tests/IntegrationTests2/build/setup-simple/a.cabal
+  tests/IntegrationTests2/exception/bad-config/cabal.project
+  tests/IntegrationTests2/exception/build/Main.hs
+  tests/IntegrationTests2/exception/build/a.cabal
+  tests/IntegrationTests2/exception/configure/a.cabal
+  tests/IntegrationTests2/exception/no-pkg/empty.in
+  tests/IntegrationTests2/exception/no-pkg2/cabal.project
+  tests/IntegrationTests2/regression/3324/cabal.project
+  tests/IntegrationTests2/regression/3324/p/P.hs
+  tests/IntegrationTests2/regression/3324/p/p.cabal
+  tests/IntegrationTests2/regression/3324/q/Q.hs
+  tests/IntegrationTests2/regression/3324/q/q.cabal
+  tests/IntegrationTests2/targets/all-disabled/cabal.project
+  tests/IntegrationTests2/targets/all-disabled/p.cabal
+  tests/IntegrationTests2/targets/benchmarks-disabled/cabal.project
+  tests/IntegrationTests2/targets/benchmarks-disabled/p.cabal
+  tests/IntegrationTests2/targets/benchmarks-disabled/q/q.cabal
+  tests/IntegrationTests2/targets/complex/cabal.project
+  tests/IntegrationTests2/targets/complex/q/Q.hs
+  tests/IntegrationTests2/targets/complex/q/q.cabal
+  tests/IntegrationTests2/targets/empty-pkg/cabal.project
+  tests/IntegrationTests2/targets/empty-pkg/p.cabal
+  tests/IntegrationTests2/targets/empty/cabal.project
+  tests/IntegrationTests2/targets/empty/foo.hs
+  tests/IntegrationTests2/targets/exes-disabled/cabal.project
+  tests/IntegrationTests2/targets/exes-disabled/p/p.cabal
+  tests/IntegrationTests2/targets/exes-disabled/q/q.cabal
+  tests/IntegrationTests2/targets/lib-only/p.cabal
+  tests/IntegrationTests2/targets/libs-disabled/cabal.project
+  tests/IntegrationTests2/targets/libs-disabled/p/p.cabal
+  tests/IntegrationTests2/targets/libs-disabled/q/q.cabal
+  tests/IntegrationTests2/targets/multiple-exes/cabal.project
+  tests/IntegrationTests2/targets/multiple-exes/p.cabal
+  tests/IntegrationTests2/targets/multiple-libs/cabal.project
+  tests/IntegrationTests2/targets/multiple-libs/p/p.cabal
+  tests/IntegrationTests2/targets/multiple-libs/q/q.cabal
+  tests/IntegrationTests2/targets/multiple-tests/cabal.project
+  tests/IntegrationTests2/targets/multiple-tests/p.cabal
+  tests/IntegrationTests2/targets/simple/P.hs
+  tests/IntegrationTests2/targets/simple/cabal.project
+  tests/IntegrationTests2/targets/simple/p.cabal
+  tests/IntegrationTests2/targets/simple/q/QQ.hs
+  tests/IntegrationTests2/targets/simple/q/q.cabal
+  tests/IntegrationTests2/targets/test-only/p.cabal
+  tests/IntegrationTests2/targets/tests-disabled/cabal.project
+  tests/IntegrationTests2/targets/tests-disabled/p.cabal
+  tests/IntegrationTests2/targets/tests-disabled/q/q.cabal
+  tests/IntegrationTests2/targets/variety/cabal.project
+  tests/IntegrationTests2/targets/variety/p.cabal
+  -- END gen-extra-source-files
+
+  -- Additional manual extra-source-files:
+  tests/IntegrationTests2/build/local-tarball/p-0.1.tar.gz
+
+
+source-repository head
+  type:     git
+  location: https://github.com/haskell/cabal/
+  subdir:   cabal-install
+
+Flag native-dns
+  description:  Enable use of the [resolv](https://hackage.haskell.org/package/resolv) & [windns](https://hackage.haskell.org/package/windns) packages for performing DNS lookups
+  default:      True
+  manual:       True
+
+Flag debug-expensive-assertions
+  description:  Enable expensive assertions for testing or debugging
+  default:      False
+  manual:       True
+
+Flag debug-conflict-sets
+  description:  Add additional information to ConflictSets
+  default:      False
+  manual:       True
+
+Flag debug-tracetree
+  description:  Compile in support for tracetree (used to debug the solver)
+  default:      False
+  manual:       True
+
+%if CABAL_FLAG_LIB
+%else
+custom-setup
+   setup-depends:
+       Cabal     >= 2.2,
+       base,
+       process   >= 1.1.0.1  && < 1.7,
+       filepath  >= 1.3      && < 1.5
+
+%endif
+#
+# Libraries, if CABAL_FLAG_LIB
+#
+%if CABAL_FLAG_LIB
+library cabal-lib-client
+    $CABAL_COMPONENTCOMMON
+    hs-source-dirs: .
+    $CABAL_BUILDINFO
+
+library cabal-install-solver-dsl
+    $CABAL_COMPONENTCOMMON
+    hs-source-dirs: solver-dsl
+    exposed-modules:
+        UnitTests.Distribution.Solver.Modular.DSL
+    build-depends:
+        base,
+        Cabal,
+        containers,
+        -- TODO: depend on cabal-install-solver only
+        cabal-lib-client
+%endif
+#
+# Executable
+#
+executable cabal
+    main-is:        Main.hs
+    hs-source-dirs: main
+    $CABAL_COMPONENTCOMMON
+
+    ghc-options: -rtsopts -threaded
+
+    -- On AIX, some legacy BSD operations such as flock(2) are provided by libbsd.a
+    if os(aix)
+        extra-libraries: bsd
+%if CABAL_FLAG_LIB
+    build-depends:
+        cabal-lib-client,
+        Cabal,
+        base,
+        directory,
+        filepath
+
+    other-modules: Paths_cabal_install
+%else
+    hs-source-dirs: .
+    $CABAL_BUILDINFO
+%endif
+#
+# MONOLITHIC exe additions
+#
+%if CABAL_FLAG_LIB
+%if CABAL_FLAG_MONOLITHIC
+    -- Monolithic: tests fused into executable
+    hs-source-dirs: tests
+    other-modules:
+        UnitTests
+        MemoryUsageTests
+        SolverQuickCheck
+        IntegrationTests2
+
+        UnitTests.Distribution.Client.ArbitraryInstances
+        UnitTests.Distribution.Client.FileMonitor
+        UnitTests.Distribution.Client.Get
+        UnitTests.Distribution.Client.GZipUtils
+        UnitTests.Distribution.Client.Glob
+        UnitTests.Distribution.Client.IndexUtils.Timestamp
+        UnitTests.Distribution.Client.InstallPlan
+        UnitTests.Distribution.Client.JobControl
+        UnitTests.Distribution.Client.ProjectConfig
+        UnitTests.Distribution.Client.Sandbox
+        UnitTests.Distribution.Client.Sandbox.Timestamp
+        UnitTests.Distribution.Client.Store
+        UnitTests.Distribution.Client.Tar
+        UnitTests.Distribution.Client.Targets
+        UnitTests.Distribution.Client.UserConfig
+        UnitTests.Distribution.Client.VCS
+        UnitTests.Distribution.Solver.Modular.Builder
+        UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils
+        UnitTests.Distribution.Solver.Modular.MemoryUsage
+        UnitTests.Distribution.Solver.Modular.QuickCheck
+        UnitTests.Distribution.Solver.Modular.QuickCheck.Utils
+        UnitTests.Distribution.Solver.Modular.RetryLog
+        UnitTests.Distribution.Solver.Modular.Solver
+        UnitTests.Distribution.Solver.Modular.WeightedPSQ
+        UnitTests.Options
+        UnitTests.TempTestDir
+
+    cpp-options: -DMONOLITHIC
+    build-depends:
+        Cabal      == 2.4.*,
+        cabal-install-solver-dsl,
+        QuickCheck >= 2.8.2,
+        array,
+        async,
+        bytestring,
+        containers,
+        deepseq,
+        directory,
+        edit-distance,
+        filepath,
+        hashable,
+        mtl,
+        network,
+        network-uri,
+        pretty-show >= 1.6.15,
+        random,
+        tagged,
+        tar,
+        tasty >= 1.1.0.3 && < 1.2,
+        tasty-hunit >= 0.10,
+        tasty-quickcheck,
+        time,
+        zlib
+%endif
+%endif
+#
+# Test-suites
+# disable if we don't configure with an (internal) libs
+#
+%if CABAL_FLAG_LIB
+#
+# Small, fast running tests.
+#
+Test-Suite unit-tests
+  type: exitcode-stdio-1.0
+  main-is: UnitTests.hs
+  hs-source-dirs: tests
+  ghc-options: -Wall -fwarn-tabs -main-is UnitTests
+  other-modules:
+    UnitTests.Distribution.Client.ArbitraryInstances
+    UnitTests.Distribution.Client.Targets
+    UnitTests.Distribution.Client.FileMonitor
+    UnitTests.Distribution.Client.Get
+    UnitTests.Distribution.Client.Glob
+    UnitTests.Distribution.Client.GZipUtils
+    UnitTests.Distribution.Client.Sandbox
+    UnitTests.Distribution.Client.Sandbox.Timestamp
+    UnitTests.Distribution.Client.Store
+    UnitTests.Distribution.Client.Tar
+    UnitTests.Distribution.Client.UserConfig
+    UnitTests.Distribution.Client.ProjectConfig
+    UnitTests.Distribution.Client.JobControl
+    UnitTests.Distribution.Client.IndexUtils.Timestamp
+    UnitTests.Distribution.Client.InstallPlan
+    UnitTests.Distribution.Client.VCS
+    UnitTests.Distribution.Solver.Modular.Builder
+    UnitTests.Distribution.Solver.Modular.RetryLog
+    UnitTests.Distribution.Solver.Modular.Solver
+    UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils
+    UnitTests.Distribution.Solver.Modular.WeightedPSQ
+    UnitTests.Options
+    UnitTests.TempTestDir
+  build-depends:
+        array,
+        base,
+        async,
+        bytestring,
+        cabal-lib-client,
+        cabal-install-solver-dsl,
+        Cabal,
+        containers,
+        deepseq,
+        mtl,
+        random,
+        directory,
+        filepath,
+        tar,
+        time,
+        zlib,
+        network-uri,
+        network,
+        tasty >= 1.1.0.3 && < 1.2,
+        tasty-hunit >= 0.10,
+        tasty-quickcheck,
+        tagged,
+        QuickCheck >= 2.8.2
+
+  ghc-options: -threaded
+
+  default-language: Haskell2010
+
+#
+# Tests to run with a limited stack and heap size
+#
+Test-Suite memory-usage-tests
+  type: exitcode-stdio-1.0
+  main-is: MemoryUsageTests.hs
+  hs-source-dirs: tests
+  ghc-options: -Wall -fwarn-tabs "-with-rtsopts=-M4M -K1K" -main-is MemoryUsageTests
+  other-modules:
+    UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils
+    UnitTests.Distribution.Solver.Modular.MemoryUsage
+    UnitTests.Options
+  build-depends:
+        base,
+        async,
+        Cabal,
+        cabal-lib-client,
+        cabal-install-solver-dsl,
+        containers,
+        deepseq,
+        tagged,
+        tasty >= 1.1.0.3 && < 1.2,
+        tasty-hunit >= 0.10
+
+  ghc-options: -threaded
+
+  default-language: Haskell2010
+
+#
+# Slow solver tests
+#
+Test-Suite solver-quickcheck
+  type: exitcode-stdio-1.0
+  main-is: SolverQuickCheck.hs
+  hs-source-dirs: tests
+  ghc-options: -Wall -fwarn-tabs -main-is SolverQuickCheck
+  other-modules:
+    UnitTests.Distribution.Solver.Modular.QuickCheck
+    UnitTests.Distribution.Solver.Modular.QuickCheck.Utils
+  build-depends:
+        base,
+        async,
+        Cabal,
+        cabal-lib-client,
+        cabal-install-solver-dsl,
+        containers,
+        deepseq >= 1.2,
+        hashable,
+        random,
+        tagged,
+        tasty >= 1.1.0.3 && <1.2,
+        tasty-quickcheck,
+        QuickCheck >= 2.8.2,
+        pretty-show >= 1.6.15
+
+  ghc-options: -threaded
+
+  default-language: Haskell2010
+
+#
+# Integration tests that use the cabal-install code directly
+# but still build whole projects
+#
+test-suite integration-tests2
+  type: exitcode-stdio-1.0
+  main-is: IntegrationTests2.hs
+  hs-source-dirs: tests
+  ghc-options: -Wall -fwarn-tabs -main-is IntegrationTests2
+  other-modules:
+  build-depends:
+        base,
+        Cabal,
+        cabal-lib-client,
+        containers,
+        deepseq,
+        directory,
+        edit-distance,
+        filepath,
+        tasty >= 1.1.0.3 && < 1.2,
+        tasty-hunit >= 0.10,
+        tagged
+
+  ghc-options: -threaded
+  default-language: Haskell2010
+
+%endif
diff --git a/cabal/cabal-install/changelog b/cabal/cabal-install/changelog
--- a/cabal/cabal-install/changelog
+++ b/cabal/cabal-install/changelog
@@ -1,43 +1,155 @@
 -*-change-log-*-
 
-2.2.0.0 (current development version)
+2.4.1.0 Mikhail Glushenkov <mikhail.glushenkov@gmail.com> November 2018
+	* Add message to alert user to potential package casing errors. (#5635)
+	* new-clean no longer deletes dist-newstyle/src with `-s`. (#5699)
+	* 'new-install' now warns when failing to symlink an exe (#5602)
+	* Extend 'cabal init' support for 'cabal-version' selection (#5567)
+	* 'new-sdist' now generates tarballs with file modification
+	  times from a date in 2001. Using the Unix epoch caused
+	  problems on Windows. (#5596)
+	* Register monolithic packages installed into the store due to a
+	  build-tool dependency if they also happen to contain a buildable
+	  public lib. (#5379,#5604)
+        * Fixed a Windows bug where cabal-install tried to copy files
+          after moving them (#5631).
+        * 'cabal v2-repl' now works for indefinite (in the Backpack sense) components. (#5619)
+	* Set data dir environment variable for tarballs and remote repos (#5469)
+	* Fix monolithic inplace build tool PATH (#5633)
+	* 'cabal init' now supports '-w'/'--with-compiler' flag (#4936, #5654)
+	* Fix ambiguous --builddir on new-install (#5652)
+	* Allow relative --storedir (#5662)
+	* Respect --dry on new-install (#5671)
+	* Warn when new-installing zero exes (#5666)
+	* Add 'pkg-cabal-sha256' field to plan.json (#5695)
+	* New v2-build flag: '--only-configure'. (#5578)
+	* Fixed a 'new-install' failure that manifested when it
+	  encountered remote source dependencies in a project. (#5643)
+	* New 'v2-[build,configure' flag: '--write-ghc-environment-files'
+	  to control the generation of .ghc.environment files. (#5711)
+
+2.4.0.0 Mikhail Glushenkov <mikhail.glushenkov@gmail.com> September 2018
+	* Bugfix: "cabal new-build --ghc-option '--bogus' --ghc-option '-O1'"
+	  no longer ignores all arguments except the last one (#5512).
+	* Add the following option aliases for '-dir'-suffixed options:
+	  'storedir', 'logsdir', 'packagedir', 'sourcedir', 'outputdir' (#5484).
+	* 'new-run' now allows the user to run scripts that use a special block
+	  to define their requirements (as in the executable stanza) in place
+	  of a target. This also allows the use of 'cabal' as an interpreter
+	  in a shebang line.
+	* Add aliases for the "new-" commands that won't change when they
+	  lose their prefix or are eventually replaced by a third UI
+	  paradigm in the future. (#5429)
+	* 'outdated' now accepts '--project-file FILE', which will look for bounds
+	  from the new-style freeze file named FILE.freeze. This is only
+	  available when `--new-freeze-file` has been passed.
+	* 'new-repl' now accepts a '--build-depends' flag which accepts the
+	  same syntax as is used in .cabal files to add additional dependencies
+	  to the environment when developing in the REPL. It is now usable outside
+	  of projects. (#5425, #5454)
+	* 'new-build' now treats Haddock errors non-fatally. In addition,
+	  it attempts to avoid trying to generate Haddocks when there is
+	  nothing to generate them from. (#5232, #5459)
+	* 'new-run', 'new-test', and 'new-bench' now will attempt to resolve
+	  ambiguous selectors by filtering out selectors that would be invalid.
+	  (#4679, #5461)
+	* 'new-install' now supports installing libraries and local
+	  components. (#5399)
+	* Drop support for GHC 7.4, since it is out of our support window
+	  (and has been for over a year!).
+	* 'new-update' now works outside of projects. (#5096)
+	* Extend `plan.json` with `pkg-src` provenance information. (#5487)
+	* Add 'new-sdist' command (#5389). Creates stable archives based on
+	  cabal projects in '.zip' and '.tar.gz' formats.
+	* Add '--repl-options' flag to 'cabal repl' and 'cabal new-repl'
+	  commands. Passes its arguments to the invoked repl, bypassing the
+	  new-build's cached configurations. This assures they don't trigger
+	  useless rebuilds and are always applied within the repl. (#4247, #5287)
+	* Add 'v1-' prefixes for the commands that will be replaced in the
+	  new-build universe, in preparation for it becoming the default.
+	  (#5358)
+	* 'outdated' accepts '--v1-freeze-file' and '--v2-freeze-file'
+	  in the same spirit.
+	* Completed the 'new-clean' command (#5357). The functionality is
+	  equivalent to old-style clean, but for nix-style builds.
+	* Ensure that each package selected for a build-depends dependency
+	  contains a library (#5304).
+	* Support packages from local tarballs in the cabal.project file.
+	* Default changelog generated by 'cabal init' is now named
+	  'CHANGELOG.md' (#5441).
+	* Align output of 'new-build' command phases (#4040).
+	* Add suport for specifying remote VCS dependencies via new
+	  'source-repository-package' stanzas in 'cabal.project' files
+	  (#5351).
+
+2.2.0.0 Mikhail Glushenkov <mikhail.glushenkov@gmail.com> March 2018
+	* '--with-PROG' and '--PROG-options' are applied to all packages
+	and not local packages only (#5019).
 	* Completed the 'new-update' command (#4809), which respects nix-style
 	cabal.project(.local) files and allows to update from
 	multiple repositories when using overlays.
-	* New config file field: 'cxx-options' to specify which options to be
-	passed to the compiler when compiling C++ sources specified by the
-	'cxx-sources' field. (#3700)
-	* New config file field: 'cxx-sources' to specify C++ files to be
-	compiled separately from C source files. Useful in conjunction with the
-	'cxx-options' flag to pass different compiler options to C and C++
-	source files. (#3700)
-	* 'cabal configure' now supports '--enable-static' which can be
-	used to build static libaries with GHC via GHC's `-staticlib` flag.
-	* Don't automatically/silently case-correct mispelled package-names
-	on CLI (#4778)
-	* 'cabal update' now supports '--index-state' which can be used to
-	roll back the index to an earlier state.
-	* 'cabal new-configure' now backs up the old 'cabal.project.local'
-	file if it exists (#4460).
 	* Completed the 'new-run' command (#4477). The functionality is the
 	same of the old 'run' command but using nix-style builds.
 	Additionally, it can run executables across packages in a project.
+	Tests and benchmarks are also treated as executables, providing a
+	quick way to pass them arguments.
 	* Completed the 'new-bench' command (#3638). Same as above.
 	* Completed the 'new-exec' command (#3638). Same as above.
 	* Added a preliminary 'new-install' command (#4558, nonlocal exes
-	part) which allows to quickly install executables from hackage.
+	part) which allows to quickly install executables from Hackage.
+	* Set symlink-bindir (used by new-install) to .cabal/bin by default on
+	.cabal/config initialization (#5188).
+	* 'cabal update' now supports '--index-state' which can be used to
+	roll back the index to an earlier state.
 	* '--allow-{newer,older}' syntax has been enhanced. Dependency
 	relaxation can be now limited to a specific release of a package,
 	plus there's a new syntax for relaxing only caret-style (i.e. '^>=')
 	dependencies (#4575, #4669).
+	* New config file field: 'cxx-options' to specify which options to be
+	passed to the compiler when compiling C++ sources specified by the
+	'cxx-sources' field. (#3700)
+	* New config file field: 'cxx-sources' to specify C++ files to be
+	compiled separately from C source files. Useful in conjunction with the
+	'cxx-options' flag to pass different compiler options to C and C++
+	source files. (#3700)
+	* Use [lfxtb] letters to differentiate component kind instead of
+	opaque "c" in dist-dir layout.
+	* 'cabal configure' now supports '--enable-static', which can be
+	used to build static libaries with GHC via GHC's `-staticlib`
+	flag.
+	* 'cabal user-config now supports '--augment' which can append
+	additional lines to a new or updated cabal config file.
+	* Added support for '--enable-tests' and '--enable-benchmarks' to
+	'cabal fetch' (#4948).
+	* Misspelled package-names on CLI will no longer be silently
+	case-corrected (#4778).
+	* 'cabal new-configure' now backs up the old 'cabal.project.local'
+	file if it exists (#4460).
 	* On macOS, `new-build` will now place dynamic libraries into
 	`store/lib` and aggressively shorten their names in an effort to
 	stay within the load command size limits of macOSs mach-o linker.
-	* Use [lfxtb] letters to differentiate component kind instead of
-	opaque "c" in dist-dir layout.
 	* 'new-build' now checks for the existence of executables for
 	build-tools and build-tool-depends dependencies in the solver
 	(#4884).
+	* Fixed a spurious warning telling the user to run 'cabal update'
+	when it wasn't necessary (#4444).
+	* Packages installed in sandboxes via 'add-source' now have
+	their timestamps updated correctly and so will not be reinstalled
+	unncecessarily if the main install command fails (#1375).
+	* Add Windows device path support for copyFile, renameFile. Allows cabal
+	new-build to use temporary store path of up to 32k length
+	(#3972, #4914, #4515).
+	* When a flag value is specified multiple times on the command
+	line, the last one is now preferred, so e.g. '-f+dev -f-dev' is
+	now equivalent to '-f-dev' (#4452).
+	* Removed support for building cabal-install with GHC < 7.10 (#4870).
+	* New 'package *' section in 'cabal.project' files that applies
+	options to all packages, not just those local to the project.
+	* Paths_ autogen modules now compile when `RebindableSyntax` or
+	`OverloadedStrings` is used in `default-extensions`.
+	[stack#3789](https://github.com/commercialhaskell/stack/issues/3789)
+	* `getDataDir` and other `Paths_autogen` functions now work correctly
+	when compiling a custom `Setup.hs` script using `new-build` (#5164).
 
 2.0.0.1 Mikhail Glushenkov <mikhail.glushenkov@gmail.com> December 2017
 	* Support for GHC's numeric -g debug levels (#4673).
@@ -194,7 +306,8 @@
 
 1.22.7.0 Ryan Thomas <ryan@ryant.org> December 2015
 	* Remove GZipUtils tests
-	* maybeDecompress: bail on all errors at the beginning of the stream with zlib < 0.6
+	* maybeDecompress: bail on all errors at the beginning of the
+	stream with zlib < 0.6
 	* Correct maybeDecompress
 
 1.22.6.0 Ryan Thomas <ryan@ryant.org> June 2015
@@ -206,10 +319,12 @@
 1.22.4.0 Ryan Thomas <ryan@ryant.org> May 2015
 	* Force cabal upload to always use digest auth and never basic auth.
 	* Add dependency-graph information to `printPlan` output
-	* bootstrap.sh: fixes linker matching to avoid cases where tested linker names appear unexpectedly in compiler output (fixes #2542)
+	* bootstrap.sh: fixes linker matching to avoid cases where tested
+	linker names appear unexpectedly in compiler output (fixes #2542)
 
 1.22.3.0 Ryan Thomas <ryan@ryant.org> April 2015
-	* Fix bash completion for sandbox subcommands - Fixes #2513 (Mikhail Glushenkov)
+	* Fix bash completion for sandbox subcommands - Fixes #2513
+	(Mikhail Glushenkov)
 	* filterConfigureFlags: filter more flags (Mikhail Glushenkov)
 
 1.22.2.0 Ryan Thomas <ryan@ryant.org> March 2015
diff --git a/cabal/cabal-install/main/Main.hs b/cabal/cabal-install/main/Main.hs
--- a/cabal/cabal-install/main/Main.hs
+++ b/cabal/cabal-install/main/Main.hs
@@ -38,7 +38,7 @@
          , UploadFlags(..), uploadCommand
          , ReportFlags(..), reportCommand
          , runCommand
-         , InitFlags(initVerbosity), initCommand
+         , InitFlags(initVerbosity, initHcPath), initCommand
          , SDistFlags(..), SDistExFlags(..), sdistCommand
          , Win32SelfUpgradeFlags(..), win32SelfUpgradeCommand
          , ActAsSetupFlags(..), actAsSetupCommand
@@ -47,16 +47,21 @@
          , UserConfigFlags(..), userConfigCommand
          , reportCommand
          , manpageCommand
+         , haddockCommand
+         , cleanCommand
+         , doctestCommand
+         , copyCommand
+         , registerCommand
          )
 import Distribution.Simple.Setup
          ( HaddockTarget(..)
-         , DoctestFlags(..), doctestCommand
-         , HaddockFlags(..), haddockCommand, defaultHaddockFlags
+         , DoctestFlags(..)
+         , HaddockFlags(..), defaultHaddockFlags
          , HscolourFlags(..), hscolourCommand
          , ReplFlags(..)
-         , CopyFlags(..), copyCommand
-         , RegisterFlags(..), registerCommand
-         , CleanFlags(..), cleanCommand
+         , CopyFlags(..)
+         , RegisterFlags(..)
+         , CleanFlags(..)
          , TestFlags(..), BenchmarkFlags(..)
          , Flag(..), fromFlag, fromFlagOrDefault, flagToMaybe, toFlag
          , configAbsolutePaths
@@ -87,6 +92,9 @@
 import qualified Distribution.Client.CmdTest      as CmdTest
 import qualified Distribution.Client.CmdBench     as CmdBench
 import qualified Distribution.Client.CmdExec      as CmdExec
+import qualified Distribution.Client.CmdClean     as CmdClean
+import qualified Distribution.Client.CmdSdist     as CmdSdist
+import           Distribution.Client.CmdLegacy
 
 import Distribution.Client.Install            (install)
 import Distribution.Client.Configure          (configure, writeConfigFlags)
@@ -232,24 +240,32 @@
   getArgs >>= mainWorker
 
 mainWorker :: [String] -> IO ()
-mainWorker args = topHandler $
-  case commandsRun (globalCommand commands) commands args of
-    CommandHelp   help                 -> printGlobalHelp help
-    CommandList   opts                 -> printOptionsList opts
-    CommandErrors errs                 -> printErrors errs
-    CommandReadyToGo (globalFlags, commandParse)  ->
-      case commandParse of
-        _ | fromFlagOrDefault False (globalVersion globalFlags)
-            -> printVersion
-          | fromFlagOrDefault False (globalNumericVersion globalFlags)
-            -> printNumericVersion
-        CommandHelp     help           -> printCommandHelp help
-        CommandList     opts           -> printOptionsList opts
-        CommandErrors   errs           -> printErrors errs
-        CommandReadyToGo action        -> do
-          globalFlags' <- updateSandboxConfigFileFlag globalFlags
-          action globalFlags'
+mainWorker args = do
+  validScript <- 
+    if null args
+      then return False
+      else doesFileExist (last args)
 
+  topHandler $
+    case commandsRun (globalCommand commands) commands args of
+      CommandHelp   help                 -> printGlobalHelp help
+      CommandList   opts                 -> printOptionsList opts
+      CommandErrors errs                 -> printErrors errs
+      CommandReadyToGo (globalFlags, commandParse)  ->
+        case commandParse of
+          _ | fromFlagOrDefault False (globalVersion globalFlags)
+              -> printVersion
+            | fromFlagOrDefault False (globalNumericVersion globalFlags)
+              -> printNumericVersion
+          CommandHelp     help           -> printCommandHelp help
+          CommandList     opts           -> printOptionsList opts
+          CommandErrors   errs           
+            | validScript                -> CmdRun.handleShebang (last args)
+            | otherwise                  -> printErrors errs
+          CommandReadyToGo action        -> do
+            globalFlags' <- updateSandboxConfigFileFlag globalFlags
+            action globalFlags'
+
   where
     printCommandHelp help = do
       pname <- getProgName
@@ -275,37 +291,19 @@
 
     commands = map commandFromSpec commandSpecs
     commandSpecs =
-      [ regularCmd installCommand installAction
-      , regularCmd updateCommand updateAction
-      , regularCmd listCommand listAction
+      [ regularCmd listCommand listAction
       , regularCmd infoCommand infoAction
       , regularCmd fetchCommand fetchAction
-      , regularCmd freezeCommand freezeAction
       , regularCmd getCommand getAction
       , hiddenCmd  unpackCommand unpackAction
       , regularCmd checkCommand checkAction
-      , regularCmd sdistCommand sdistAction
       , regularCmd uploadCommand uploadAction
       , regularCmd reportCommand reportAction
-      , regularCmd runCommand runAction
       , regularCmd initCommand initAction
-      , regularCmd configureExCommand configureAction
-      , regularCmd reconfigureCommand reconfigureAction
-      , regularCmd buildCommand buildAction
-      , regularCmd replCommand replAction
-      , regularCmd sandboxCommand sandboxAction
-      , regularCmd doctestCommand doctestAction
-      , regularCmd haddockCommand haddockAction
-      , regularCmd execCommand execAction
       , regularCmd userConfigCommand userConfigAction
-      , regularCmd cleanCommand cleanAction
       , regularCmd genBoundsCommand genBoundsAction
       , regularCmd outdatedCommand outdatedAction
-      , wrapperCmd copyCommand copyVerbosity copyDistPref
       , wrapperCmd hscolourCommand hscolourVerbosity hscolourDistPref
-      , wrapperCmd registerCommand regVerbosity regDistPref
-      , regularCmd testCommand testAction
-      , regularCmd benchmarkCommand benchmarkAction
       , hiddenCmd  uninstallCommand uninstallAction
       , hiddenCmd  formatCommand formatAction
       , hiddenCmd  upgradeCommand upgradeAction
@@ -313,21 +311,45 @@
       , hiddenCmd  actAsSetupCommand actAsSetupAction
       , hiddenCmd  manpageCommand (manpageAction commandSpecs)
 
-      , regularCmd  CmdConfigure.configureCommand CmdConfigure.configureAction
-      , regularCmd  CmdUpdate.updateCommand       CmdUpdate.updateAction
-      , regularCmd  CmdBuild.buildCommand         CmdBuild.buildAction
-      , regularCmd  CmdRepl.replCommand           CmdRepl.replAction
-      , regularCmd  CmdFreeze.freezeCommand       CmdFreeze.freezeAction
-      , regularCmd  CmdHaddock.haddockCommand     CmdHaddock.haddockAction
-      , regularCmd  CmdInstall.installCommand     CmdInstall.installAction
-      , regularCmd  CmdRun.runCommand             CmdRun.runAction
-      , regularCmd  CmdTest.testCommand           CmdTest.testAction
-      , regularCmd  CmdBench.benchCommand         CmdBench.benchAction
-      , regularCmd  CmdExec.execCommand           CmdExec.execAction
+      ] ++ concat
+      [ newCmd  CmdConfigure.configureCommand CmdConfigure.configureAction
+      , newCmd  CmdUpdate.updateCommand       CmdUpdate.updateAction
+      , newCmd  CmdBuild.buildCommand         CmdBuild.buildAction
+      , newCmd  CmdRepl.replCommand           CmdRepl.replAction
+      , newCmd  CmdFreeze.freezeCommand       CmdFreeze.freezeAction
+      , newCmd  CmdHaddock.haddockCommand     CmdHaddock.haddockAction
+      , newCmd  CmdInstall.installCommand     CmdInstall.installAction
+      , newCmd  CmdRun.runCommand             CmdRun.runAction
+      , newCmd  CmdTest.testCommand           CmdTest.testAction
+      , newCmd  CmdBench.benchCommand         CmdBench.benchAction
+      , newCmd  CmdExec.execCommand           CmdExec.execAction
+      , newCmd  CmdClean.cleanCommand         CmdClean.cleanAction 
+      , newCmd  CmdSdist.sdistCommand         CmdSdist.sdistAction
+      
+      , legacyCmd configureExCommand configureAction
+      , legacyCmd updateCommand updateAction
+      , legacyCmd buildCommand buildAction
+      , legacyCmd replCommand replAction
+      , legacyCmd freezeCommand freezeAction
+      , legacyCmd haddockCommand haddockAction
+      , legacyCmd installCommand installAction
+      , legacyCmd runCommand runAction
+      , legacyCmd testCommand testAction
+      , legacyCmd benchmarkCommand benchmarkAction
+      , legacyCmd execCommand execAction
+      , legacyCmd cleanCommand cleanAction
+      , legacyCmd sdistCommand sdistAction
+      , legacyCmd doctestCommand doctestAction
+      , legacyWrapperCmd copyCommand copyVerbosity copyDistPref
+      , legacyWrapperCmd registerCommand regVerbosity regDistPref
+      , legacyCmd reconfigureCommand reconfigureAction
+      , legacyCmd sandboxCommand sandboxAction
       ]
 
 type Action = GlobalFlags -> IO ()
 
+-- Duplicated in Distribution.Client.CmdLegacy. Any changes must be
+-- reflected there, as well.
 regularCmd :: CommandUI flags -> (flags -> [String] -> action)
            -> CommandSpec action
 regularCmd ui action =
@@ -358,7 +380,7 @@
     distPref <- findSavedDistPref config (distPrefFlag flags)
     let setupScriptOptions = defaultSetupScriptOptions { useDistPref = distPref }
     setupWrapper verbosity setupScriptOptions Nothing
-                 command (const flags) extraArgs
+                 command (const flags) (const extraArgs)
 
 configureAction :: (ConfigFlags, ConfigExFlags)
                 -> [String] -> Action
@@ -455,7 +477,7 @@
 build :: Verbosity -> SavedConfig -> FilePath -> BuildFlags -> [String] -> IO ()
 build verbosity config distPref buildFlags extraArgs =
   setupWrapper verbosity setupOptions Nothing
-               (Cabal.buildCommand progDb) mkBuildFlags extraArgs
+               (Cabal.buildCommand progDb) mkBuildFlags (const extraArgs)
   where
     progDb       = defaultProgramDb
     setupOptions = defaultSetupScriptOptions { useDistPref = distPref }
@@ -521,7 +543,7 @@
       nixShell verbosity distPref globalFlags config $ do
         maybeWithSandboxDirOnSearchPath useSandbox $
           setupWrapper verbosity setupOptions Nothing
-          (Cabal.replCommand progDb) (const replFlags') extraArgs
+          (Cabal.replCommand progDb) (const replFlags') (const extraArgs)
 
     -- No .cabal file in the current directory: just start the REPL (possibly
     -- using the sandbox package DB).
@@ -549,7 +571,7 @@
       nixShellIfSandboxed verb dist globalFlags config useSandbox $
         setupWrapper
         verb setupOpts Nothing
-        installCommand (const mempty) []
+        installCommand (const mempty) (const [])
 
 installAction
   (configFlags, configExFlags, installFlags, haddockFlags)
@@ -679,7 +701,7 @@
 
     maybeWithSandboxDirOnSearchPath useSandbox $
       setupWrapper verbosity setupOptions Nothing
-      Cabal.testCommand (const testFlags') extraArgs'
+      Cabal.testCommand (const testFlags') (const extraArgs')
 
 data ComponentNames = ComponentNamesUnknown
                     | ComponentNames [LBI.ComponentName]
@@ -762,7 +784,7 @@
 
     maybeWithSandboxDirOnSearchPath useSandbox $
       setupWrapper verbosity setupOptions Nothing
-      Cabal.benchmarkCommand (const benchmarkFlags') extraArgs'
+      Cabal.benchmarkCommand (const benchmarkFlags') (const extraArgs')
 
 haddockAction :: HaddockFlags -> [String] -> Action
 haddockAction haddockFlags extraArgs globalFlags = do
@@ -780,7 +802,7 @@
         setupScriptOptions = defaultSetupScriptOptions
                              { useDistPref = distPref }
     setupWrapper verbosity setupScriptOptions Nothing
-      haddockCommand (const haddockFlags') extraArgs
+      haddockCommand (const haddockFlags') (const extraArgs)
     when (haddockForHackage haddockFlags == Flag ForHackage) $ do
       pkg <- fmap LBI.localPkgDescr (getPersistBuildConfig distPref)
       let dest = distPref </> name <.> "tar.gz"
@@ -794,7 +816,7 @@
   let verbosity = fromFlag (doctestVerbosity doctestFlags)
 
   setupWrapper verbosity defaultSetupScriptOptions Nothing
-    doctestCommand (const doctestFlags) extraArgs
+    doctestCommand (const doctestFlags) (const extraArgs)
 
 cleanAction :: CleanFlags -> [String] -> Action
 cleanAction cleanFlags extraArgs globalFlags = do
@@ -807,7 +829,7 @@
                            }
       cleanFlags' = cleanFlags { cleanDistPref = toFlag distPref }
   setupWrapper verbosity setupScriptOptions Nothing
-               cleanCommand (const cleanFlags') extraArgs
+               cleanCommand (const cleanFlags') (const extraArgs)
   where
     verbosity = fromFlagOrDefault normal (cleanVerbosity cleanFlags)
 
@@ -1121,7 +1143,9 @@
     die' verbosity $ "'init' doesn't take any extra arguments: " ++ unwords extraArgs
   (_useSandbox, config) <- loadConfigOrSandboxConfig verbosity
                            (globalFlags { globalRequireSandbox = Flag False })
-  let configFlags  = savedConfigureFlags config
+  let configFlags  = savedConfigureFlags config `mappend`
+                     -- override with `--with-compiler` from CLI if available
+                     mempty { configHcPath = initHcPath initFlags }
   let globalFlags' = savedGlobalFlags    config `mappend` globalFlags
   (comp, _, progdb) <- configCompilerAux' configFlags
   withRepoContext verbosity globalFlags' $ \repoContext ->
@@ -1179,17 +1203,18 @@
 
 userConfigAction :: UserConfigFlags -> [String] -> Action
 userConfigAction ucflags extraArgs globalFlags = do
-  let verbosity = fromFlag (userConfigVerbosity ucflags)
-      force     = fromFlag (userConfigForce ucflags)
+  let verbosity  = fromFlag (userConfigVerbosity ucflags)
+      force      = fromFlag (userConfigForce ucflags)
+      extraLines = fromFlag (userConfigAppendLines ucflags)
   case extraArgs of
     ("init":_) -> do
       path       <- configFile
       fileExists <- doesFileExist path
       if (not fileExists || (fileExists && force))
-      then void $ createDefaultConfigFile verbosity path
+      then void $ createDefaultConfigFile verbosity extraLines path
       else die' verbosity $ path ++ " already exists."
-    ("diff":_) -> mapM_ putStrLn =<< userConfigDiff globalFlags
-    ("update":_) -> userConfigUpdate verbosity globalFlags
+    ("diff":_) -> mapM_ putStrLn =<< userConfigDiff verbosity globalFlags extraLines
+    ("update":_) -> userConfigUpdate verbosity globalFlags extraLines
     -- Error handling.
     [] -> die' verbosity $ "Please specify a subcommand (see 'help user-config')"
     _  -> die' verbosity $ "Unknown 'user-config' subcommand: " ++ unwords extraArgs
@@ -1214,8 +1239,7 @@
     Configure -> Simple.defaultMainWithHooksArgs
                   Simple.autoconfUserHooks args
     Make      -> Make.defaultMainArgs args
-    Custom               -> error "actAsSetupAction Custom"
-    (UnknownBuildType _) -> error "actAsSetupAction UnknownBuildType"
+    Custom    -> error "actAsSetupAction Custom"
 
 manpageAction :: [CommandSpec action] -> Flag Verbosity -> [String] -> Action
 manpageAction commands flagVerbosity extraArgs _ = do
diff --git a/cabal/cabal-install/solver-dsl/UnitTests/Distribution/Solver/Modular/DSL.hs b/cabal/cabal-install/solver-dsl/UnitTests/Distribution/Solver/Modular/DSL.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/solver-dsl/UnitTests/Distribution/Solver/Modular/DSL.hs
@@ -0,0 +1,729 @@
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+-- | DSL for testing the modular solver
+module UnitTests.Distribution.Solver.Modular.DSL (
+    ExampleDependency(..)
+  , Dependencies(..)
+  , ExTest(..)
+  , ExExe(..)
+  , ExConstraint(..)
+  , ExPreference(..)
+  , ExampleDb
+  , ExampleVersionRange
+  , ExamplePkgVersion
+  , ExamplePkgName
+  , ExampleFlagName
+  , ExFlag(..)
+  , ExampleAvailable(..)
+  , ExampleInstalled(..)
+  , ExampleQualifier(..)
+  , ExampleVar(..)
+  , EnableAllTests(..)
+  , exAv
+  , exAvNoLibrary
+  , exInst
+  , exFlagged
+  , exResolve
+  , extractInstallPlan
+  , declareFlags
+  , withSetupDeps
+  , withTest
+  , withTests
+  , withExe
+  , withExes
+  , runProgress
+  , mkSimpleVersion
+  , mkVersionRange
+  ) where
+
+import Prelude ()
+import Distribution.Solver.Compat.Prelude
+
+-- base
+import Control.Arrow (second)
+import Data.Either (partitionEithers)
+import qualified Data.Map as Map
+
+-- Cabal
+import qualified Distribution.Compiler                  as C
+import qualified Distribution.InstalledPackageInfo      as IPI
+import           Distribution.License (License(..))
+import qualified Distribution.ModuleName                as Module
+import qualified Distribution.Package                   as C
+  hiding (HasUnitId(..))
+import qualified Distribution.Types.ExeDependency       as C
+import qualified Distribution.Types.ForeignLib          as C
+import qualified Distribution.Types.LegacyExeDependency as C
+import qualified Distribution.Types.PkgconfigDependency as C
+import qualified Distribution.Types.UnqualComponentName as C
+import qualified Distribution.Types.CondTree            as C
+import qualified Distribution.PackageDescription        as C
+import qualified Distribution.PackageDescription.Check  as C
+import qualified Distribution.Simple.PackageIndex       as C.PackageIndex
+import           Distribution.Simple.Setup (BooleanFlag(..))
+import qualified Distribution.System                    as C
+import           Distribution.Text (display)
+import qualified Distribution.Verbosity                 as C
+import qualified Distribution.Version                   as C
+import Language.Haskell.Extension (Extension(..), Language(..))
+
+-- cabal-install
+import Distribution.Client.Dependency
+import Distribution.Client.Dependency.Types
+import Distribution.Client.Types
+import qualified Distribution.Client.SolverInstallPlan as CI.SolverInstallPlan
+
+import           Distribution.Solver.Types.ComponentDeps (ComponentDeps)
+import qualified Distribution.Solver.Types.ComponentDeps as CD
+import           Distribution.Solver.Types.ConstraintSource
+import           Distribution.Solver.Types.Flag
+import           Distribution.Solver.Types.LabeledPackageConstraint
+import           Distribution.Solver.Types.OptionalStanza
+import qualified Distribution.Solver.Types.PackageIndex      as CI.PackageIndex
+import           Distribution.Solver.Types.PackageConstraint
+import qualified Distribution.Solver.Types.PackagePath as P
+import qualified Distribution.Solver.Types.PkgConfigDb as PC
+import           Distribution.Solver.Types.Settings
+import           Distribution.Solver.Types.SolverPackage
+import           Distribution.Solver.Types.SourcePackage
+import           Distribution.Solver.Types.Variable
+
+{-------------------------------------------------------------------------------
+  Example package database DSL
+
+  In order to be able to set simple examples up quickly, we define a very
+  simple version of the package database here explicitly designed for use in
+  tests.
+
+  The design of `ExampleDb` takes the perspective of the solver, not the
+  perspective of the package DB. This makes it easier to set up tests for
+  various parts of the solver, but makes the mapping somewhat awkward,  because
+  it means we first map from "solver perspective" `ExampleDb` to the package
+  database format, and then the modular solver internally in `IndexConversion`
+  maps this back to the solver specific data structures.
+
+  IMPLEMENTATION NOTES
+  --------------------
+
+  TODO: Perhaps these should be made comments of the corresponding data type
+  definitions. For now these are just my own conclusions and may be wrong.
+
+  * The difference between `GenericPackageDescription` and `PackageDescription`
+    is that `PackageDescription` describes a particular _configuration_ of a
+    package (for instance, see documentation for `checkPackage`). A
+    `GenericPackageDescription` can be turned into a `PackageDescription` in
+    two ways:
+
+      a. `finalizePD` does the proper translation, by taking
+         into account the platform, available dependencies, etc. and picks a
+         flag assignment (or gives an error if no flag assignment can be found)
+      b. `flattenPackageDescription` ignores flag assignment and just joins all
+         components together.
+
+    The slightly odd thing is that a `GenericPackageDescription` contains a
+    `PackageDescription` as a field; both of the above functions do the same
+    thing: they take the embedded `PackageDescription` as a basis for the result
+    value, but override `library`, `executables`, `testSuites`, `benchmarks`
+    and `buildDepends`.
+  * The `condTreeComponents` fields of a `CondTree` is a list of triples
+    `(condition, then-branch, else-branch)`, where the `else-branch` is
+    optional.
+-------------------------------------------------------------------------------}
+
+type ExamplePkgName    = String
+type ExamplePkgVersion = Int
+type ExamplePkgHash    = String  -- for example "installed" packages
+type ExampleFlagName   = String
+type ExampleTestName   = String
+type ExampleExeName    = String
+type ExampleVersionRange = C.VersionRange
+
+data Dependencies = NotBuildable | Buildable [ExampleDependency]
+  deriving Show
+
+data ExampleDependency =
+    -- | Simple dependency on any version
+    ExAny ExamplePkgName
+
+    -- | Simple dependency on a fixed version
+  | ExFix ExamplePkgName ExamplePkgVersion
+
+    -- | Simple dependency on a range of versions, with an inclusive lower bound
+    -- and an exclusive upper bound.
+  | ExRange ExamplePkgName ExamplePkgVersion ExamplePkgVersion
+
+    -- | Build-tool-depends dependency
+  | ExBuildToolAny ExamplePkgName ExampleExeName
+
+    -- | Build-tool-depends dependency on a fixed version
+  | ExBuildToolFix ExamplePkgName ExampleExeName ExamplePkgVersion
+
+    -- | Legacy build-tools dependency
+  | ExLegacyBuildToolAny ExamplePkgName
+
+    -- | Legacy build-tools dependency on a fixed version
+  | ExLegacyBuildToolFix ExamplePkgName ExamplePkgVersion
+
+    -- | Dependencies indexed by a flag
+  | ExFlagged ExampleFlagName Dependencies Dependencies
+
+    -- | Dependency on a language extension
+  | ExExt Extension
+
+    -- | Dependency on a language version
+  | ExLang Language
+
+    -- | Dependency on a pkg-config package
+  | ExPkg (ExamplePkgName, ExamplePkgVersion)
+  deriving Show
+
+-- | Simplified version of D.Types.GenericPackageDescription.Flag for use in
+-- example source packages.
+data ExFlag = ExFlag {
+    exFlagName    :: ExampleFlagName
+  , exFlagDefault :: Bool
+  , exFlagType    :: FlagType
+  } deriving Show
+
+data ExTest = ExTest ExampleTestName [ExampleDependency]
+
+data ExExe = ExExe ExampleExeName [ExampleDependency]
+
+exFlagged :: ExampleFlagName -> [ExampleDependency] -> [ExampleDependency]
+          -> ExampleDependency
+exFlagged n t e = ExFlagged n (Buildable t) (Buildable e)
+
+data ExConstraint =
+    ExVersionConstraint ConstraintScope ExampleVersionRange
+  | ExFlagConstraint ConstraintScope ExampleFlagName Bool
+  | ExStanzaConstraint ConstraintScope [OptionalStanza]
+  deriving Show
+
+data ExPreference =
+    ExPkgPref ExamplePkgName ExampleVersionRange
+  | ExStanzaPref ExamplePkgName [OptionalStanza]
+  deriving Show
+
+data ExampleAvailable = ExAv {
+    exAvName    :: ExamplePkgName
+  , exAvVersion :: ExamplePkgVersion
+  , exAvDeps    :: ComponentDeps [ExampleDependency]
+
+  -- Setting flags here is only necessary to override the default values of
+  -- the fields in C.Flag.
+  , exAvFlags   :: [ExFlag]
+  } deriving Show
+
+data ExampleVar =
+    P ExampleQualifier ExamplePkgName
+  | F ExampleQualifier ExamplePkgName ExampleFlagName
+  | S ExampleQualifier ExamplePkgName OptionalStanza
+
+data ExampleQualifier =
+    QualNone
+  | QualIndep ExamplePkgName
+  | QualSetup ExamplePkgName
+
+    -- The two package names are the build target and the package containing the
+    -- setup script.
+  | QualIndepSetup ExamplePkgName ExamplePkgName
+
+    -- The two package names are the package depending on the exe and the
+    -- package containing the exe.
+  | QualExe ExamplePkgName ExamplePkgName
+
+-- | Whether to enable tests in all packages in a test case.
+newtype EnableAllTests = EnableAllTests Bool
+  deriving BooleanFlag
+
+-- | Constructs an 'ExampleAvailable' package for the 'ExampleDb',
+-- given:
+--
+--      1. The name 'ExamplePkgName' of the available package,
+--      2. The version 'ExamplePkgVersion' available
+--      3. The list of dependency constraints ('ExampleDependency')
+--         for this package's library component.  'ExampleDependency'
+--         provides a number of pre-canned dependency types to look at.
+--
+exAv :: ExamplePkgName -> ExamplePkgVersion -> [ExampleDependency]
+     -> ExampleAvailable
+exAv n v ds = (exAvNoLibrary n v) { exAvDeps = CD.fromLibraryDeps ds }
+
+-- | Constructs an 'ExampleAvailable' package without a default library
+-- component.
+exAvNoLibrary :: ExamplePkgName -> ExamplePkgVersion -> ExampleAvailable
+exAvNoLibrary n v = ExAv { exAvName = n
+                         , exAvVersion = v
+                         , exAvDeps = CD.empty
+                         , exAvFlags = [] }
+
+-- | Override the default settings (e.g., manual vs. automatic) for a subset of
+-- a package's flags.
+declareFlags :: [ExFlag] -> ExampleAvailable -> ExampleAvailable
+declareFlags flags ex = ex {
+      exAvFlags = flags
+    }
+
+withSetupDeps :: ExampleAvailable -> [ExampleDependency] -> ExampleAvailable
+withSetupDeps ex setupDeps = ex {
+      exAvDeps = exAvDeps ex <> CD.fromSetupDeps setupDeps
+    }
+
+withTest :: ExampleAvailable -> ExTest -> ExampleAvailable
+withTest ex test = withTests ex [test]
+
+withTests :: ExampleAvailable -> [ExTest] -> ExampleAvailable
+withTests ex tests =
+  let testCDs = CD.fromList [(CD.ComponentTest $ C.mkUnqualComponentName name, deps)
+                            | ExTest name deps <- tests]
+  in ex { exAvDeps = exAvDeps ex <> testCDs }
+
+withExe :: ExampleAvailable -> ExExe -> ExampleAvailable
+withExe ex exe = withExes ex [exe]
+
+withExes :: ExampleAvailable -> [ExExe] -> ExampleAvailable
+withExes ex exes =
+  let exeCDs = CD.fromList [(CD.ComponentExe $ C.mkUnqualComponentName name, deps)
+                           | ExExe name deps <- exes]
+  in ex { exAvDeps = exAvDeps ex <> exeCDs }
+
+-- | An installed package in 'ExampleDb'; construct me with 'exInst'.
+data ExampleInstalled = ExInst {
+    exInstName         :: ExamplePkgName
+  , exInstVersion      :: ExamplePkgVersion
+  , exInstHash         :: ExamplePkgHash
+  , exInstBuildAgainst :: [ExamplePkgHash]
+  } deriving Show
+
+-- | Constructs an example installed package given:
+--
+--      1. The name of the package 'ExamplePkgName', i.e., 'String'
+--      2. The version of the package 'ExamplePkgVersion', i.e., 'Int'
+--      3. The IPID for the package 'ExamplePkgHash', i.e., 'String'
+--         (just some unique identifier for the package.)
+--      4. The 'ExampleInstalled' packages which this package was
+--         compiled against.)
+--
+exInst :: ExamplePkgName -> ExamplePkgVersion -> ExamplePkgHash
+       -> [ExampleInstalled] -> ExampleInstalled
+exInst pn v hash deps = ExInst pn v hash (map exInstHash deps)
+
+-- | An example package database is a list of installed packages
+-- 'ExampleInstalled' and available packages 'ExampleAvailable'.
+-- Generally, you want to use 'exInst' and 'exAv' to construct
+-- these packages.
+type ExampleDb = [Either ExampleInstalled ExampleAvailable]
+
+type DependencyTree a = C.CondTree C.ConfVar [C.Dependency] a
+
+type DependencyComponent a = C.CondBranch C.ConfVar [C.Dependency] a
+
+exDbPkgs :: ExampleDb -> [ExamplePkgName]
+exDbPkgs = map (either exInstName exAvName)
+
+exAvSrcPkg :: ExampleAvailable -> UnresolvedSourcePackage
+exAvSrcPkg ex =
+    let pkgId = exAvPkgId ex
+
+        flags :: [C.Flag]
+        flags =
+          let declaredFlags :: Map ExampleFlagName C.Flag
+              declaredFlags =
+                  Map.fromListWith
+                      (\f1 f2 -> error $ "duplicate flag declarations: " ++ show [f1, f2])
+                      [(exFlagName flag, mkFlag flag) | flag <- exAvFlags ex]
+
+              usedFlags :: Map ExampleFlagName C.Flag
+              usedFlags = Map.fromList [(fn, mkDefaultFlag fn) | fn <- names]
+                where
+                  names = concatMap extractFlags $ CD.flatDeps (exAvDeps ex)
+          in -- 'declaredFlags' overrides 'usedFlags' to give flags non-default settings:
+             Map.elems $ declaredFlags `Map.union` usedFlags
+
+        subLibraries = [(name, deps) | (CD.ComponentSubLib name, deps) <- CD.toList (exAvDeps ex)]
+        foreignLibraries = [(name, deps) | (CD.ComponentFLib name, deps) <- CD.toList (exAvDeps ex)]
+        testSuites = [(name, deps) | (CD.ComponentTest name, deps) <- CD.toList (exAvDeps ex)]
+        benchmarks = [(name, deps) | (CD.ComponentBench name, deps) <- CD.toList (exAvDeps ex)]
+        executables = [(name, deps) | (CD.ComponentExe name, deps) <- CD.toList (exAvDeps ex)]
+        setup = case CD.setupDeps (exAvDeps ex) of
+                  []   -> Nothing
+                  deps -> Just C.SetupBuildInfo {
+                            C.setupDepends = mkSetupDeps deps,
+                            C.defaultSetupDepends = False
+                          }
+        package = SourcePackage {
+            packageInfoId        = pkgId
+          , packageSource        = LocalTarballPackage "<<path>>"
+          , packageDescrOverride = Nothing
+          , packageDescription   = C.GenericPackageDescription {
+                C.packageDescription = C.emptyPackageDescription {
+                    C.package        = pkgId
+                  , C.setupBuildInfo = setup
+                  , C.licenseRaw = Right BSD3
+                  , C.buildTypeRaw = if isNothing setup
+                                     then Just C.Simple
+                                     else Just C.Custom
+                  , C.category = "category"
+                  , C.maintainer = "maintainer"
+                  , C.description = "description"
+                  , C.synopsis = "synopsis"
+                  , C.licenseFiles = ["LICENSE"]
+                    -- Version 2.0 is required for internal libraries.
+                  , C.specVersionRaw = Left $ C.mkVersion [2,0]
+                  }
+              , C.genPackageFlags = flags
+              , C.condLibrary =
+                  let mkLib bi = mempty { C.libBuildInfo = bi }
+                      -- Avoid using the Monoid instance for [a] when getting
+                      -- the library dependencies, to allow for the possibility
+                      -- that the package doesn't have a library:
+                      libDeps = lookup CD.ComponentLib (CD.toList (exAvDeps ex))
+                  in mkCondTree defaultLib mkLib . mkBuildInfoTree . Buildable <$> libDeps
+              , C.condSubLibraries =
+                  let mkTree = mkCondTree defaultLib mkLib . mkBuildInfoTree . Buildable
+                      mkLib bi = mempty { C.libBuildInfo = bi }
+                  in map (second mkTree) subLibraries
+              , C.condForeignLibs =
+                  let mkTree = mkCondTree mempty mkLib . mkBuildInfoTree . Buildable
+                      mkLib bi = mempty { C.foreignLibBuildInfo = bi }
+                  in map (second mkTree) foreignLibraries
+              , C.condExecutables =
+                  let mkTree = mkCondTree defaultExe mkExe . mkBuildInfoTree . Buildable
+                      mkExe bi = mempty { C.buildInfo = bi }
+                  in map (second mkTree) executables
+              , C.condTestSuites =
+                  let mkTree = mkCondTree defaultTest mkTest . mkBuildInfoTree . Buildable
+                      mkTest bi = mempty { C.testBuildInfo = bi }
+                  in map (second mkTree) testSuites
+              , C.condBenchmarks  =
+                  let mkTree = mkCondTree defaultBenchmark mkBench . mkBuildInfoTree . Buildable
+                      mkBench bi = mempty { C.benchmarkBuildInfo = bi }
+                  in map (second mkTree) benchmarks
+              }
+            }
+        pkgCheckErrors =
+          -- We ignore these warnings because some unit tests test that the
+          -- solver allows unknown extensions/languages when the compiler
+          -- supports them.
+          let ignore = ["Unknown extensions:", "Unknown languages:"]
+          in [ err | err <- C.checkPackage (packageDescription package) Nothing
+             , not $ any (`isPrefixOf` C.explanation err) ignore ]
+    in if null pkgCheckErrors
+       then package
+       else error $ "invalid GenericPackageDescription for package "
+                 ++ display pkgId ++ ": " ++ show pkgCheckErrors
+  where
+    defaultTopLevelBuildInfo :: C.BuildInfo
+    defaultTopLevelBuildInfo = mempty { C.defaultLanguage = Just Haskell98 }
+
+    defaultLib :: C.Library
+    defaultLib = mempty { C.exposedModules = [Module.fromString "Module"] }
+
+    defaultExe :: C.Executable
+    defaultExe = mempty { C.modulePath = "Main.hs" }
+
+    defaultTest :: C.TestSuite
+    defaultTest = mempty {
+        C.testInterface = C.TestSuiteExeV10 (C.mkVersion [1,0]) "Test.hs"
+      }
+
+    defaultBenchmark :: C.Benchmark
+    defaultBenchmark = mempty {
+        C.benchmarkInterface = C.BenchmarkExeV10 (C.mkVersion [1,0]) "Benchmark.hs"
+      }
+
+    -- Split the set of dependencies into the set of dependencies of the library,
+    -- the dependencies of the test suites and extensions.
+    splitTopLevel :: [ExampleDependency]
+                  -> ( [ExampleDependency]
+                     , [Extension]
+                     , Maybe Language
+                     , [(ExamplePkgName, ExamplePkgVersion)] -- pkg-config
+                     , [(ExamplePkgName, ExampleExeName, C.VersionRange)] -- build tools
+                     , [(ExamplePkgName, C.VersionRange)] -- legacy build tools
+                     )
+    splitTopLevel [] =
+        ([], [], Nothing, [], [], [])
+    splitTopLevel (ExBuildToolAny p e:deps) =
+      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
+      in (other, exts, lang, pcpkgs, (p, e, C.anyVersion):exes, legacyExes)
+    splitTopLevel (ExBuildToolFix p e v:deps) =
+      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
+      in (other, exts, lang, pcpkgs, (p, e, C.thisVersion (mkSimpleVersion v)):exes, legacyExes)
+    splitTopLevel (ExLegacyBuildToolAny p:deps) =
+      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
+      in (other, exts, lang, pcpkgs, exes, (p, C.anyVersion):legacyExes)
+    splitTopLevel (ExLegacyBuildToolFix p v:deps) =
+      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
+      in (other, exts, lang, pcpkgs, exes, (p, C.thisVersion (mkSimpleVersion v)):legacyExes)
+    splitTopLevel (ExExt ext:deps) =
+      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
+      in (other, ext:exts, lang, pcpkgs, exes, legacyExes)
+    splitTopLevel (ExLang lang:deps) =
+        case splitTopLevel deps of
+            (other, exts, Nothing, pcpkgs, exes, legacyExes) -> (other, exts, Just lang, pcpkgs, exes, legacyExes)
+            _ -> error "Only 1 Language dependency is supported"
+    splitTopLevel (ExPkg pkg:deps) =
+      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
+      in (other, exts, lang, pkg:pcpkgs, exes, legacyExes)
+    splitTopLevel (dep:deps) =
+      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
+      in (dep:other, exts, lang, pcpkgs, exes, legacyExes)
+
+    -- Extract the total set of flags used
+    extractFlags :: ExampleDependency -> [ExampleFlagName]
+    extractFlags (ExAny _)            = []
+    extractFlags (ExFix _ _)          = []
+    extractFlags (ExRange _ _ _)      = []
+    extractFlags (ExBuildToolAny _ _)   = []
+    extractFlags (ExBuildToolFix _ _ _) = []
+    extractFlags (ExLegacyBuildToolAny _)   = []
+    extractFlags (ExLegacyBuildToolFix _ _) = []
+    extractFlags (ExFlagged f a b)    =
+        f : concatMap extractFlags (deps a ++ deps b)
+      where
+        deps :: Dependencies -> [ExampleDependency]
+        deps NotBuildable = []
+        deps (Buildable ds) = ds
+    extractFlags (ExExt _)      = []
+    extractFlags (ExLang _)     = []
+    extractFlags (ExPkg _)      = []
+
+    -- Convert a tree of BuildInfos into a tree of a specific component type.
+    -- 'defaultTopLevel' contains the default values for the component, and
+    -- 'mkComponent' creates a component from a 'BuildInfo'.
+    mkCondTree :: forall a. Semigroup a =>
+                  a -> (C.BuildInfo -> a)
+               -> DependencyTree C.BuildInfo
+               -> DependencyTree a
+    mkCondTree defaultTopLevel mkComponent (C.CondNode topData topConstraints topComps) =
+        C.CondNode {
+            C.condTreeData =
+                defaultTopLevel <> mkComponent (defaultTopLevelBuildInfo <> topData)
+          , C.condTreeConstraints = topConstraints
+          , C.condTreeComponents = goComponents topComps
+          }
+      where
+        go :: DependencyTree C.BuildInfo -> DependencyTree a
+        go (C.CondNode ctData constraints comps) =
+            C.CondNode (mkComponent ctData) constraints (goComponents comps)
+
+        goComponents :: [DependencyComponent C.BuildInfo]
+                     -> [DependencyComponent a]
+        goComponents comps = [C.CondBranch cond (go t) (go <$> me) | C.CondBranch cond t me <- comps]
+
+    mkBuildInfoTree :: Dependencies -> DependencyTree C.BuildInfo
+    mkBuildInfoTree NotBuildable =
+      C.CondNode {
+             C.condTreeData        = mempty { C.buildable = False }
+           , C.condTreeConstraints = []
+           , C.condTreeComponents  = []
+           }
+    mkBuildInfoTree (Buildable deps) =
+      let (libraryDeps, exts, mlang, pcpkgs, buildTools, legacyBuildTools) = splitTopLevel deps
+          (directDeps, flaggedDeps) = splitDeps libraryDeps
+          bi = mempty {
+                  C.otherExtensions = exts
+                , C.defaultLanguage = mlang
+                , C.buildToolDepends = [ C.ExeDependency (C.mkPackageName p) (C.mkUnqualComponentName e) vr
+                                       | (p, e, vr) <- buildTools]
+                , C.buildTools = [ C.LegacyExeDependency n vr
+                                 | (n,vr) <- legacyBuildTools]
+                , C.pkgconfigDepends = [ C.PkgconfigDependency n' v'
+                                       | (n,v) <- pcpkgs
+                                       , let n' = C.mkPkgconfigName n
+                                       , let v' = C.thisVersion (mkSimpleVersion v) ]
+              }
+      in C.CondNode {
+             C.condTreeData        = bi -- Necessary for language extensions
+           -- TODO: Arguably, build-tools dependencies should also
+           -- effect constraints on conditional tree. But no way to
+           -- distinguish between them
+           , C.condTreeConstraints = map mkDirect directDeps
+           , C.condTreeComponents  = map mkFlagged flaggedDeps
+           }
+
+    mkDirect :: (ExamplePkgName, C.VersionRange) -> C.Dependency
+    mkDirect (dep, vr) = C.Dependency (C.mkPackageName dep) vr
+
+    mkFlagged :: (ExampleFlagName, Dependencies, Dependencies)
+              -> DependencyComponent C.BuildInfo
+    mkFlagged (f, a, b) =
+        C.CondBranch (C.Var (C.Flag (C.mkFlagName f)))
+                     (mkBuildInfoTree a)
+                     (Just (mkBuildInfoTree b))
+
+    -- Split a set of dependencies into direct dependencies and flagged
+    -- dependencies. A direct dependency is a tuple of the name of package and
+    -- its version range meant to be converted to a 'C.Dependency' with
+    -- 'mkDirect' for example. A flagged dependency is the set of dependencies
+    -- guarded by a flag.
+    splitDeps :: [ExampleDependency]
+              -> ( [(ExamplePkgName, C.VersionRange)]
+                 , [(ExampleFlagName, Dependencies, Dependencies)]
+                 )
+    splitDeps [] =
+      ([], [])
+    splitDeps (ExAny p:deps) =
+      let (directDeps, flaggedDeps) = splitDeps deps
+      in ((p, C.anyVersion):directDeps, flaggedDeps)
+    splitDeps (ExFix p v:deps) =
+      let (directDeps, flaggedDeps) = splitDeps deps
+      in ((p, C.thisVersion $ mkSimpleVersion v):directDeps, flaggedDeps)
+    splitDeps (ExRange p v1 v2:deps) =
+      let (directDeps, flaggedDeps) = splitDeps deps
+      in ((p, mkVersionRange v1 v2):directDeps, flaggedDeps)
+    splitDeps (ExFlagged f a b:deps) =
+      let (directDeps, flaggedDeps) = splitDeps deps
+      in (directDeps, (f, a, b):flaggedDeps)
+    splitDeps (dep:_) = error $ "Unexpected dependency: " ++ show dep
+
+    -- custom-setup only supports simple dependencies
+    mkSetupDeps :: [ExampleDependency] -> [C.Dependency]
+    mkSetupDeps deps =
+      let (directDeps, []) = splitDeps deps in map mkDirect directDeps
+
+mkSimpleVersion :: ExamplePkgVersion -> C.Version
+mkSimpleVersion n = C.mkVersion [n, 0, 0]
+
+mkVersionRange :: ExamplePkgVersion -> ExamplePkgVersion -> C.VersionRange
+mkVersionRange v1 v2 =
+    C.intersectVersionRanges (C.orLaterVersion $ mkSimpleVersion v1)
+                             (C.earlierVersion $ mkSimpleVersion v2)
+
+mkFlag :: ExFlag -> C.Flag
+mkFlag flag = C.MkFlag {
+    C.flagName        = C.mkFlagName $ exFlagName flag
+  , C.flagDescription = ""
+  , C.flagDefault     = exFlagDefault flag
+  , C.flagManual      =
+      case exFlagType flag of
+        Manual    -> True
+        Automatic -> False
+  }
+
+mkDefaultFlag :: ExampleFlagName -> C.Flag
+mkDefaultFlag flag = C.MkFlag {
+    C.flagName        = C.mkFlagName flag
+  , C.flagDescription = ""
+  , C.flagDefault     = True
+  , C.flagManual      = False
+  }
+
+exAvPkgId :: ExampleAvailable -> C.PackageIdentifier
+exAvPkgId ex = C.PackageIdentifier {
+      pkgName    = C.mkPackageName (exAvName ex)
+    , pkgVersion = C.mkVersion [exAvVersion ex, 0, 0]
+    }
+
+exInstInfo :: ExampleInstalled -> IPI.InstalledPackageInfo
+exInstInfo ex = IPI.emptyInstalledPackageInfo {
+      IPI.installedUnitId    = C.mkUnitId (exInstHash ex)
+    , IPI.sourcePackageId    = exInstPkgId ex
+    , IPI.depends            = map C.mkUnitId (exInstBuildAgainst ex)
+    }
+
+exInstPkgId :: ExampleInstalled -> C.PackageIdentifier
+exInstPkgId ex = C.PackageIdentifier {
+      pkgName    = C.mkPackageName (exInstName ex)
+    , pkgVersion = C.mkVersion [exInstVersion ex, 0, 0]
+    }
+
+exAvIdx :: [ExampleAvailable] -> CI.PackageIndex.PackageIndex UnresolvedSourcePackage
+exAvIdx = CI.PackageIndex.fromList . map exAvSrcPkg
+
+exInstIdx :: [ExampleInstalled] -> C.PackageIndex.InstalledPackageIndex
+exInstIdx = C.PackageIndex.fromList . map exInstInfo
+
+exResolve :: ExampleDb
+          -- List of extensions supported by the compiler, or Nothing if unknown.
+          -> Maybe [Extension]
+          -- List of languages supported by the compiler, or Nothing if unknown.
+          -> Maybe [Language]
+          -> PC.PkgConfigDb
+          -> [ExamplePkgName]
+          -> Maybe Int
+          -> CountConflicts
+          -> IndependentGoals
+          -> ReorderGoals
+          -> AllowBootLibInstalls
+          -> EnableBackjumping
+          -> SolveExecutables
+          -> Maybe (Variable P.QPN -> Variable P.QPN -> Ordering)
+          -> [ExConstraint]
+          -> [ExPreference]
+          -> C.Verbosity
+          -> EnableAllTests
+          -> Progress String String CI.SolverInstallPlan.SolverInstallPlan
+exResolve db exts langs pkgConfigDb targets mbj countConflicts indepGoals
+          reorder allowBootLibInstalls enableBj solveExes goalOrder constraints
+          prefs verbosity enableAllTests
+    = resolveDependencies C.buildPlatform compiler pkgConfigDb Modular params
+  where
+    defaultCompiler = C.unknownCompilerInfo C.buildCompilerId C.NoAbiTag
+    compiler = defaultCompiler { C.compilerInfoExtensions = exts
+                               , C.compilerInfoLanguages  = langs
+                               }
+    (inst, avai) = partitionEithers db
+    instIdx      = exInstIdx inst
+    avaiIdx      = SourcePackageDb {
+                       packageIndex       = exAvIdx avai
+                     , packagePreferences = Map.empty
+                     }
+    enableTests
+        | asBool enableAllTests = fmap (\p -> PackageConstraint
+                                              (scopeToplevel (C.mkPackageName p))
+                                              (PackagePropertyStanzas [TestStanzas]))
+                                       (exDbPkgs db)
+        | otherwise             = []
+    targets'     = fmap (\p -> NamedPackage (C.mkPackageName p) []) targets
+    params       =   addConstraints (fmap toConstraint constraints)
+                   $ addConstraints (fmap toLpc enableTests)
+                   $ addPreferences (fmap toPref prefs)
+                   $ setCountConflicts countConflicts
+                   $ setIndependentGoals indepGoals
+                   $ setReorderGoals reorder
+                   $ setMaxBackjumps mbj
+                   $ setAllowBootLibInstalls allowBootLibInstalls
+                   $ setEnableBackjumping enableBj
+                   $ setSolveExecutables solveExes
+                   $ setGoalOrder goalOrder
+                   $ setSolverVerbosity verbosity
+                   $ standardInstallPolicy instIdx avaiIdx targets'
+    toLpc     pc = LabeledPackageConstraint pc ConstraintSourceUnknown
+
+    toConstraint (ExVersionConstraint scope v) =
+        toLpc $ PackageConstraint scope (PackagePropertyVersion v)
+    toConstraint (ExFlagConstraint scope fn b) =
+        toLpc $ PackageConstraint scope (PackagePropertyFlags (C.mkFlagAssignment [(C.mkFlagName fn, b)]))
+    toConstraint (ExStanzaConstraint scope stanzas) =
+        toLpc $ PackageConstraint scope (PackagePropertyStanzas stanzas)
+
+    toPref (ExPkgPref n v)          = PackageVersionPreference (C.mkPackageName n) v
+    toPref (ExStanzaPref n stanzas) = PackageStanzasPreference (C.mkPackageName n) stanzas
+
+extractInstallPlan :: CI.SolverInstallPlan.SolverInstallPlan
+                   -> [(ExamplePkgName, ExamplePkgVersion)]
+extractInstallPlan = catMaybes . map confPkg . CI.SolverInstallPlan.toList
+  where
+    confPkg :: CI.SolverInstallPlan.SolverPlanPackage -> Maybe (String, Int)
+    confPkg (CI.SolverInstallPlan.Configured pkg) = Just $ srcPkg pkg
+    confPkg _                               = Nothing
+
+    srcPkg :: SolverPackage UnresolvedPkgLoc -> (String, Int)
+    srcPkg cpkg =
+      let C.PackageIdentifier pn ver = packageInfoId (solverPkgSource cpkg)
+      in (C.unPackageName pn, head (C.versionNumbers ver))
+
+{-------------------------------------------------------------------------------
+  Auxiliary
+-------------------------------------------------------------------------------}
+
+-- | Run Progress computation
+runProgress :: Progress step e a -> ([step], Either e a)
+runProgress = go
+  where
+    go (Step s p) = let (ss, result) = go p in (s:ss, result)
+    go (Fail e)   = ([], Left e)
+    go (Done a)   = ([], Right a)
diff --git a/cabal/cabal-install/tests/IntegrationTests2.hs b/cabal/cabal-install/tests/IntegrationTests2.hs
--- a/cabal/cabal-install/tests/IntegrationTests2.hs
+++ b/cabal/cabal-install/tests/IntegrationTests2.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE OverloadedStrings #-}
@@ -9,7 +10,7 @@
 
 import Distribution.Client.DistDirLayout
 import Distribution.Client.ProjectConfig
-import Distribution.Client.Config (defaultCabalDir)
+import Distribution.Client.Config (getCabalDir)
 import Distribution.Client.TargetSelector hiding (DirActions(..))
 import qualified Distribution.Client.TargetSelector as TS (DirActions(..))
 import Distribution.Client.ProjectPlanning
@@ -48,7 +49,9 @@
 import Distribution.Verbosity
 import Distribution.Text
 
-import Data.Monoid
+#if !MIN_VERSION_base(4,8,0)
+import Data.Monoid (mempty, mappend)
+#endif
 import Data.List (sort)
 import Data.String (IsString(..))
 import qualified Data.Map as Map
@@ -114,6 +117,7 @@
   , testGroup "Successful builds" $
     [ testCaseSteps "Setup script styles" (testSetupScriptStyles config)
     , testCase      "keep-going"          (testBuildKeepGoing config)
+    , testCase      "local tarball"       (testBuildLocalTarball config)
     ]
 
   , testGroup "Regression tests" $
@@ -146,10 +150,11 @@
     (_, _, _, localPackages, _) <- configureProject testdir config
     let readTargetSelectors' = readTargetSelectorsWith (dirActions testdir)
                                                        localPackages
+                                                       Nothing
 
     reportSubCase "cwd"
     do Right ts <- readTargetSelectors' []
-       ts @?= [TargetPackage TargetImplicitCwd "p-0.1" Nothing]
+       ts @?= [TargetPackage TargetImplicitCwd ["p-0.1"] Nothing]
 
     reportSubCase "all"
     do Right ts <- readTargetSelectors'
@@ -164,7 +169,7 @@
                      , "tests", ":cwd:tests"
                      , "benchmarks", ":cwd:benchmarks"]
        zipWithM_ (@?=) ts
-         [ TargetPackage TargetImplicitCwd "p-0.1" (Just kind)
+         [ TargetPackage TargetImplicitCwd ["p-0.1"] (Just kind)
          | kind <- concatMap (replicate 2) [LibKind .. ]
          ]
 
@@ -200,10 +205,10 @@
                      , "q:tests", "q/:tests", ":pkg:q:tests"
                      , "q:benchmarks", "q/:benchmarks", ":pkg:q:benchmarks"]
        zipWithM_ (@?=) ts $
-         [ TargetPackage TargetExplicitNamed "p-0.1" (Just kind)
+         [ TargetPackage TargetExplicitNamed ["p-0.1"] (Just kind)
          | kind <- concatMap (replicate 3) [LibKind .. ]
          ] ++
-         [ TargetPackage TargetExplicitNamed "q-0.1" (Just kind)
+         [ TargetPackage TargetExplicitNamed ["q-0.1"] (Just kind)
          | kind <- concatMap (replicate 3) [LibKind .. ]
          ]
 
@@ -253,7 +258,7 @@
                   , "foo:", "foo::bar"
                   , "foo: ", "foo: :bar"
                   , "a:b:c:d:e:f", "a:b:c:d:e:f:g:h" ]
-    Left errs <- readTargetSelectors localPackages targets
+    Left errs <- readTargetSelectors localPackages Nothing targets
     zipWithM_ (@?=) errs (map TargetSelectorUnrecognised targets)
     cleanProject testdir
   where
@@ -289,19 +294,19 @@
     reportSubCase "ambiguous: cwd-pkg filter vs pkg"
     assertAmbiguous "libs"
       [ mkTargetPackage "libs"
-      , TargetPackage TargetImplicitCwd "dummyPackageInfo" (Just LibKind) ]
+      , TargetPackage TargetImplicitCwd ["libs"] (Just LibKind) ]
       [mkpkg "libs" []]
 
     reportSubCase "ambiguous: filter vs cwd component"
     assertAmbiguous "exes"
       [ mkTargetComponent "other" (CExeName "exes")
-      , TargetPackage TargetImplicitCwd "dummyPackageInfo" (Just ExeKind) ]
+      , TargetPackage TargetImplicitCwd ["other"] (Just ExeKind) ]
       [mkpkg "other" [mkexe "exes"]]
 
     -- but filters are not ambiguous with non-cwd components, modules or files
     reportSubCase "unambiguous: filter vs non-cwd comp, mod, file"
     assertUnambiguous "Libs"
-      (TargetPackage TargetImplicitCwd "bar" (Just LibKind))
+      (TargetPackage TargetImplicitCwd ["bar"] (Just LibKind))
       [ mkpkgAt "foo" [mkexe "Libs"] "foo"
       , mkpkg   "bar" [ mkexe "bar" `withModules` ["Libs"]
                       , mkexe "baz" `withCFiles` ["Libs"] ]
@@ -367,13 +372,14 @@
       ]
   where
     assertAmbiguous :: String
-                    -> [TargetSelector PackageId]
+                    -> [TargetSelector]
                     -> [SourcePackage (PackageLocation a)]
                     -> Assertion
     assertAmbiguous str tss pkgs = do
       res <- readTargetSelectorsWith
                fakeDirActions
                (map SpecificSourcePackage pkgs)
+               Nothing
                [str]
       case res of
         Left [TargetSelectorAmbiguous _ tss'] ->
@@ -382,13 +388,14 @@
                           ++ "got " ++ show res
 
     assertUnambiguous :: String
-                      -> TargetSelector PackageId
+                      -> TargetSelector
                       -> [SourcePackage (PackageLocation a)]
                       -> Assertion
     assertUnambiguous str ts pkgs = do
       res <- readTargetSelectorsWith
                fakeDirActions
                (map SpecificSourcePackage pkgs)
+               Nothing
                [str]
       case res of
         Right [ts'] -> ts' @?= ts
@@ -439,23 +446,23 @@
       exe { buildInfo = (buildInfo exe) { cSources = files } }
 
 
-mkTargetPackage :: PackageId -> TargetSelector PackageId
+mkTargetPackage :: PackageId -> TargetSelector
 mkTargetPackage pkgid =
-    TargetPackage TargetExplicitNamed pkgid Nothing
+    TargetPackage TargetExplicitNamed [pkgid] Nothing
 
-mkTargetComponent :: PackageId -> ComponentName -> TargetSelector PackageId
+mkTargetComponent :: PackageId -> ComponentName -> TargetSelector
 mkTargetComponent pkgid cname =
     TargetComponent pkgid cname WholeComponent
 
-mkTargetModule :: PackageId -> ComponentName -> ModuleName -> TargetSelector PackageId
+mkTargetModule :: PackageId -> ComponentName -> ModuleName -> TargetSelector
 mkTargetModule pkgid cname mname =
     TargetComponent pkgid cname (ModuleTarget mname)
 
-mkTargetFile :: PackageId -> ComponentName -> String -> TargetSelector PackageId
+mkTargetFile :: PackageId -> ComponentName -> String -> TargetSelector
 mkTargetFile pkgid cname fname =
     TargetComponent pkgid cname (FileTarget fname)
 
-mkTargetAllPackages :: TargetSelector PackageId
+mkTargetAllPackages :: TargetSelector
 mkTargetAllPackages = TargetAllPackages Nothing
 
 instance IsString PackageIdentifier where
@@ -468,6 +475,7 @@
     (_, _, _, localPackages, _) <- configureProject testdir config
     let readTargetSelectors' = readTargetSelectorsWith (dirActions testdir)
                                                        localPackages
+                                                       Nothing
         targets = [ "libs",  ":cwd:libs"
                   , "flibs", ":cwd:flibs"
                   , "exes",  ":cwd:exes"
@@ -488,7 +496,7 @@
 testTargetSelectorNoTargets :: Assertion
 testTargetSelectorNoTargets = do
     (_, _, _, localPackages, _) <- configureProject testdir config
-    Left errs <- readTargetSelectors localPackages []
+    Left errs <- readTargetSelectors localPackages Nothing []
     errs @?= [TargetSelectorNoTargetsInCwd]
     cleanProject testdir
   where
@@ -499,7 +507,7 @@
 testTargetSelectorProjectEmpty :: Assertion
 testTargetSelectorProjectEmpty = do
     (_, _, _, localPackages, _) <- configureProject testdir config
-    Left errs <- readTargetSelectors localPackages []
+    Left errs <- readTargetSelectors localPackages Nothing []
     errs @?= [TargetSelectorNoTargetsInProject]
     cleanProject testdir
   where
@@ -516,8 +524,8 @@
                      [ (packageName p, packageId p)
                      | p <- InstallPlan.toList elaboratedPlan ]
 
-        cases :: [( TargetSelector PackageId -> CmdBuild.TargetProblem
-                  , TargetSelector PackageId
+        cases :: [( TargetSelector -> CmdBuild.TargetProblem
+                  , TargetSelector
                   )]
         cases =
           [ -- Cannot resolve packages outside of the project
@@ -673,8 +681,8 @@
          CmdBuild.selectPackageTargets
          CmdBuild.selectComponentTarget
          CmdBuild.TargetProblemCommon
-         [ TargetPackage TargetExplicitNamed "p-0.1" (Just TestKind)
-         , TargetPackage TargetExplicitNamed "p-0.1" (Just BenchKind)
+         [ TargetPackage TargetExplicitNamed ["p-0.1"] (Just TestKind)
+         , TargetPackage TargetExplicitNamed ["p-0.1"] (Just BenchKind)
          ]
          [ ("p-0.1-inplace-a-benchmark", CBenchName "a-benchmark")
          , ("p-0.1-inplace-a-testsuite", CTestName  "a-testsuite")
@@ -726,7 +734,7 @@
                , AvailableTarget "p-0.1" (CTestName "p1")
                    (TargetBuildable () TargetNotRequestedByDefault) True
                ]
-        , TargetPackage TargetExplicitNamed "p-0.1" (Just TestKind) )
+        , TargetPackage TargetExplicitNamed ["p-0.1"] (Just TestKind) )
       ]
 
     reportSubCase "multiple targets"
@@ -796,7 +804,7 @@
          CmdRepl.selectPackageTargets
          CmdRepl.selectComponentTarget
          CmdRepl.TargetProblemCommon
-         [ TargetPackage TargetExplicitNamed "p-0.1" Nothing ]
+         [ TargetPackage TargetExplicitNamed ["p-0.1"] Nothing ]
          [ ("p-0.1-inplace", CLibName) ]
        -- When we select the package with an explicit filter then we get those
        -- components even though we did not explicitly enable tests/benchmarks
@@ -805,14 +813,14 @@
          CmdRepl.selectPackageTargets
          CmdRepl.selectComponentTarget
          CmdRepl.TargetProblemCommon
-         [ TargetPackage TargetExplicitNamed "p-0.1" (Just TestKind) ]
+         [ TargetPackage TargetExplicitNamed ["p-0.1"] (Just TestKind) ]
          [ ("p-0.1-inplace-a-testsuite", CTestName  "a-testsuite") ]
        assertProjectDistinctTargets
          elaboratedPlan
          CmdRepl.selectPackageTargets
          CmdRepl.selectComponentTarget
          CmdRepl.TargetProblemCommon
-         [ TargetPackage TargetExplicitNamed "p-0.1" (Just BenchKind) ]
+         [ TargetPackage TargetExplicitNamed ["p-0.1"] (Just BenchKind) ]
          [ ("p-0.1-inplace-a-benchmark", CBenchName "a-benchmark") ]
 
 
@@ -869,45 +877,16 @@
       [ ( CmdRun.TargetProblemNoTargets, mkTargetPackage "p-0.1" )
       ]
 
-    reportSubCase "test-only"
+    reportSubCase "lib-only"
     assertProjectTargetProblems
-      "targets/test-only" config
+      "targets/lib-only" config
       CmdRun.selectPackageTargets
       CmdRun.selectComponentTarget
       CmdRun.TargetProblemCommon
       [ ( CmdRun.TargetProblemNoExes, mkTargetPackage "p-0.1" )
       ]
 
-    reportSubCase "variety"
-    assertProjectTargetProblems
-      "targets/variety" config
-      CmdRun.selectPackageTargets
-      CmdRun.selectComponentTarget
-      CmdRun.TargetProblemCommon $
-      [ ( const (CmdRun.TargetProblemComponentNotExe "p-0.1" cname)
-        , mkTargetComponent "p-0.1" cname )
-      | cname <- [ CLibName, CFLibName "libp",
-                   CTestName "a-testsuite", CBenchName "a-benchmark" ]
-      ] ++
-      [ ( const (CmdRun.TargetProblemIsSubComponent
-                          "p-0.1" cname (ModuleTarget modname))
-        , mkTargetModule "p-0.1" cname modname )
-      | (cname, modname) <- [ (CTestName  "a-testsuite", "TestModule")
-                            , (CBenchName "a-benchmark", "BenchModule")
-                            , (CExeName   "an-exe",      "ExeModule")
-                            , (CLibName,                 "P")
-                            ]
-      ] ++
-      [ ( const (CmdRun.TargetProblemIsSubComponent
-                          "p-0.1" cname (FileTarget fname))
-        , mkTargetFile "p-0.1" cname fname)
-      | (cname, fname) <- [ (CTestName  "a-testsuite", "Test.hs")
-                          , (CBenchName "a-benchmark", "Bench.hs")
-                          , (CExeName   "an-exe",      "Main.hs")
-                          ]
-      ]
 
-
 testTargetProblemsTest :: ProjectConfig -> (String -> IO ()) -> Assertion
 testTargetProblemsTest config reportSubCase = do
 
@@ -1195,10 +1174,10 @@
           (CmdHaddock.selectPackageTargets haddockFlags)
           CmdHaddock.selectComponentTarget
           CmdHaddock.TargetProblemCommon
-          [ TargetPackage TargetExplicitNamed "p-0.1" (Just FLibKind)
-          , TargetPackage TargetExplicitNamed "p-0.1" (Just ExeKind)
-          , TargetPackage TargetExplicitNamed "p-0.1" (Just TestKind)
-          , TargetPackage TargetExplicitNamed "p-0.1" (Just BenchKind)
+          [ TargetPackage TargetExplicitNamed ["p-0.1"] (Just FLibKind)
+          , TargetPackage TargetExplicitNamed ["p-0.1"] (Just ExeKind)
+          , TargetPackage TargetExplicitNamed ["p-0.1"] (Just TestKind)
+          , TargetPackage TargetExplicitNamed ["p-0.1"] (Just BenchKind)
           ]
           [ ("p-0.1-inplace-a-benchmark", CBenchName "a-benchmark")
           , ("p-0.1-inplace-a-testsuite", CTestName  "a-testsuite")
@@ -1217,10 +1196,10 @@
 assertProjectDistinctTargets
   :: forall err. (Eq err, Show err) =>
      ElaboratedInstallPlan
-  -> (forall k. TargetSelector PackageId -> [AvailableTarget k] -> Either err [k])
-  -> (forall k. PackageId -> ComponentName -> SubComponentTarget ->  AvailableTarget k  -> Either err  k )
+  -> (forall k. TargetSelector -> [AvailableTarget k] -> Either err [k])
+  -> (forall k. SubComponentTarget ->  AvailableTarget k  -> Either err  k )
   -> (TargetProblemCommon -> err)
-  -> [TargetSelector PackageId]
+  -> [TargetSelector]
   -> [(UnitId, ComponentName)]
   -> Assertion
 assertProjectDistinctTargets elaboratedPlan
@@ -1241,20 +1220,21 @@
                 selectComponentTarget
                 liftProblem
                 elaboratedPlan
+                Nothing
                 targetSelectors
 
 
 assertProjectTargetProblems
   :: forall err. (Eq err, Show err) =>
      FilePath -> ProjectConfig
-  -> (forall k. TargetSelector PackageId
+  -> (forall k. TargetSelector
              -> [AvailableTarget k]
              -> Either err [k])
-  -> (forall k. PackageId -> ComponentName -> SubComponentTarget
+  -> (forall k. SubComponentTarget
              -> AvailableTarget k
              -> Either err k )
   -> (TargetProblemCommon -> err)
-  -> [(TargetSelector PackageId -> err, TargetSelector PackageId)]
+  -> [(TargetSelector -> err, TargetSelector)]
   -> Assertion
 assertProjectTargetProblems testdir config
                             selectPackageTargets
@@ -1273,10 +1253,10 @@
 assertTargetProblems
   :: forall err. (Eq err, Show err) =>
      ElaboratedInstallPlan
-  -> (forall k. TargetSelector PackageId -> [AvailableTarget k] -> Either err [k])
-  -> (forall k. PackageId -> ComponentName -> SubComponentTarget ->  AvailableTarget k  -> Either err  k )
+  -> (forall k. TargetSelector -> [AvailableTarget k] -> Either err [k])
+  -> (forall k. SubComponentTarget ->  AvailableTarget k  -> Either err  k )
   -> (TargetProblemCommon -> err)
-  -> [(TargetSelector PackageId -> err, TargetSelector PackageId)]
+  -> [(TargetSelector -> err, TargetSelector)]
   -> Assertion
 assertTargetProblems elaboratedPlan
                      selectPackageTargets
@@ -1286,7 +1266,8 @@
   where
     assertTargetProblem expected targetSelector =
       let res = resolveTargets selectPackageTargets selectComponentTarget
-                               liftProblem elaboratedPlan [targetSelector] in
+                               liftProblem elaboratedPlan Nothing
+                               [targetSelector] in
       case res of
         Left [problem] ->
           problem @?= expected targetSelector
@@ -1376,14 +1357,16 @@
     marker1 @?= "ok"
     removeFile (basedir </> testdir1 </> "marker")
 
-    reportSubCase (show SetupCustomImplicitDeps)
-    (plan2, res2) <- executePlan =<< planProject testdir2 config
-    (pkg2,  _)    <- expectPackageInstalled plan2 res2 pkgidA
-    elabSetupScriptStyle pkg2 @?= SetupCustomImplicitDeps
-    hasDefaultSetupDeps pkg2 @?= Just True
-    marker2 <- readFile (basedir </> testdir2 </> "marker")
-    marker2 @?= "ok"
-    removeFile (basedir </> testdir2 </> "marker")
+    -- implicit deps implies 'Cabal < 2' which conflicts w/ GHC 8.2 or later
+    when (compilerVersion (pkgConfigCompiler sharedConfig) < mkVersion [8,2]) $ do
+      reportSubCase (show SetupCustomImplicitDeps)
+      (plan2, res2) <- executePlan =<< planProject testdir2 config
+      (pkg2,  _)    <- expectPackageInstalled plan2 res2 pkgidA
+      elabSetupScriptStyle pkg2 @?= SetupCustomImplicitDeps
+      hasDefaultSetupDeps pkg2 @?= Just True
+      marker2 <- readFile (basedir </> testdir2 </> "marker")
+      marker2 @?= "ok"
+      removeFile (basedir </> testdir2 </> "marker")
 
     reportSubCase (show SetupNonCustomInternalLib)
     (plan3, res3) <- executePlan =<< planProject testdir3 config
@@ -1415,14 +1398,14 @@
 testBuildKeepGoing config = do
     -- P is expected to fail, Q does not depend on P but without
     -- parallel build and without keep-going then we don't build Q yet.
-    (plan1, res1) <- executePlan =<< planProject testdir (config  <> keepGoing False)
+    (plan1, res1) <- executePlan =<< planProject testdir (config `mappend` keepGoing False)
     (_, failure1) <- expectPackageFailed plan1 res1 "p-0.1"
     expectBuildFailed failure1
     _ <- expectPackageConfigured plan1 res1 "q-0.1"
 
     -- With keep-going then we should go on to sucessfully build Q
     (plan2, res2) <- executePlan
-                 =<< planProject testdir (config <> keepGoing True)
+                 =<< planProject testdir (config `mappend` keepGoing True)
     (_, failure2) <- expectPackageFailed plan2 res2 "p-0.1"
     expectBuildFailed failure2
     _ <- expectPackageInstalled plan2 res2 "q-0.1"
@@ -1436,6 +1419,18 @@
         }
       }
 
+-- | Test we can successfully build packages from local tarball files.
+--
+testBuildLocalTarball :: ProjectConfig -> Assertion
+testBuildLocalTarball config = do
+    -- P is a tarball package, Q is a local dir package that depends on it.
+    (plan, res) <- executePlan =<< planProject testdir config
+    _ <- expectPackageInstalled plan res "p-0.1"
+    _ <- expectPackageInstalled plan res "q-0.1"
+    return ()
+  where
+    testdir = "build/local-tarball"
+
 -- | See <https://github.com/haskell/cabal/issues/3324>
 --
 testRegressionIssue3324 :: ProjectConfig -> Assertion
@@ -1490,7 +1485,7 @@
 
 configureProject :: FilePath -> ProjectConfig -> IO ProjDetails
 configureProject testdir cliConfig = do
-    cabalDir <- defaultCabalDir
+    cabalDir <- getCabalDir
     let cabalDirLayout = defaultCabalDirLayout cabalDir
 
     projectRootDir <- canonicalizePath (basedir </> testdir)
diff --git a/cabal/cabal-install/tests/IntegrationTests2/build/local-tarball/cabal.project b/cabal/cabal-install/tests/IntegrationTests2/build/local-tarball/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/tests/IntegrationTests2/build/local-tarball/cabal.project
@@ -0,0 +1,2 @@
+packages: p-0.1.tar.gz
+          q/
diff --git a/cabal/cabal-install/tests/IntegrationTests2/build/local-tarball/p-0.1.tar.gz b/cabal/cabal-install/tests/IntegrationTests2/build/local-tarball/p-0.1.tar.gz
new file mode 100644
Binary files /dev/null and b/cabal/cabal-install/tests/IntegrationTests2/build/local-tarball/p-0.1.tar.gz differ
diff --git a/cabal/cabal-install/tests/IntegrationTests2/build/local-tarball/q/Q.hs b/cabal/cabal-install/tests/IntegrationTests2/build/local-tarball/q/Q.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/tests/IntegrationTests2/build/local-tarball/q/Q.hs
@@ -0,0 +1,5 @@
+module Q where
+
+import P
+
+q = p ++ " world"
diff --git a/cabal/cabal-install/tests/IntegrationTests2/build/local-tarball/q/q.cabal b/cabal/cabal-install/tests/IntegrationTests2/build/local-tarball/q/q.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/tests/IntegrationTests2/build/local-tarball/q/q.cabal
@@ -0,0 +1,8 @@
+name: q
+version: 0.1
+build-type: Simple
+cabal-version: >= 1.2
+
+library
+  exposed-modules: Q
+  build-depends: base, p
diff --git a/cabal/cabal-install/tests/IntegrationTests2/targets/lib-only/p.cabal b/cabal/cabal-install/tests/IntegrationTests2/targets/lib-only/p.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/tests/IntegrationTests2/targets/lib-only/p.cabal
@@ -0,0 +1,8 @@
+name: p
+version: 0.1
+build-type: Simple
+cabal-version: >= 1.2
+
+library
+  exposed-modules: P
+  build-depends: base
diff --git a/cabal/cabal-install/tests/UnitTests.hs b/cabal/cabal-install/tests/UnitTests.hs
--- a/cabal/cabal-install/tests/UnitTests.hs
+++ b/cabal/cabal-install/tests/UnitTests.hs
@@ -26,6 +26,8 @@
 import qualified UnitTests.Distribution.Client.JobControl
 import qualified UnitTests.Distribution.Client.IndexUtils.Timestamp
 import qualified UnitTests.Distribution.Client.InstallPlan
+import qualified UnitTests.Distribution.Client.VCS
+import qualified UnitTests.Distribution.Client.Get
 
 import UnitTests.Options
 
@@ -72,6 +74,10 @@
        UnitTests.Distribution.Client.IndexUtils.Timestamp.tests
   , testGroup "UnitTests.Distribution.Client.InstallPlan"
        UnitTests.Distribution.Client.InstallPlan.tests
+  , testGroup "UnitTests.Distribution.Client.VCS" $
+       UnitTests.Distribution.Client.VCS.tests mtimeChange
+  , testGroup "UnitTests.Distribution.Client.Get"
+       UnitTests.Distribution.Client.Get.tests
   ]
 
 main :: IO ()
diff --git a/cabal/cabal-install/tests/UnitTests/Distribution/Client/ArbitraryInstances.hs b/cabal/cabal-install/tests/UnitTests/Distribution/Client/ArbitraryInstances.hs
--- a/cabal/cabal-install/tests/UnitTests/Distribution/Client/ArbitraryInstances.hs
+++ b/cabal/cabal-install/tests/UnitTests/Distribution/Client/ArbitraryInstances.hs
@@ -31,6 +31,7 @@
 
 import Distribution.Utils.NubList
 
+import Distribution.Client.Types
 import Distribution.Client.IndexUtils.Timestamp
 
 import Test.QuickCheck
@@ -178,3 +179,6 @@
     arbitrary = frequency [ (1, pure IndexStateHead)
                           , (50, IndexStateTime <$> arbitrary)
                           ]
+
+instance Arbitrary WriteGhcEnvironmentFilesPolicy where
+    arbitrary = arbitraryBoundedEnum
diff --git a/cabal/cabal-install/tests/UnitTests/Distribution/Client/Get.hs b/cabal/cabal-install/tests/UnitTests/Distribution/Client/Get.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/tests/UnitTests/Distribution/Client/Get.hs
@@ -0,0 +1,234 @@
+{-# LANGUAGE ScopedTypeVariables, FlexibleContexts #-}
+module UnitTests.Distribution.Client.Get (tests) where
+
+import Distribution.Client.Get
+
+import Distribution.Types.PackageId
+import Distribution.Types.PackageName
+import Distribution.Types.SourceRepo
+import Distribution.Verbosity as Verbosity
+import Distribution.Version
+
+import Control.Monad
+import Control.Exception
+import Data.Typeable
+import System.FilePath
+import System.Directory
+import System.Exit
+import System.IO.Error
+
+import Test.Tasty
+import Test.Tasty.HUnit
+import UnitTests.Options (RunNetworkTests (..))
+import UnitTests.TempTestDir (withTestDir)
+
+
+tests :: [TestTree]
+tests =
+  [ testGroup "forkPackages"
+    [ testCase "no repos"                    testNoRepos
+    , testCase "no repos of requested kind"  testNoReposOfKind
+    , testCase "no repo type specified"      testNoRepoType
+    , testCase "unsupported repo type"       testUnsupportedRepoType
+    , testCase "no repo location specified"  testNoRepoLocation
+    , testCase "correct repo kind selection" testSelectRepoKind
+    , testCase "repo destination exists"     testRepoDestinationExists
+    , testCase "git fetch failure"           testGitFetchFailed
+    ]
+  , askOption $ \(RunNetworkTests doRunNetTests) ->
+    testGroup "forkPackages, network tests" $
+    includeTestsIf doRunNetTests $
+    [ testCase "git clone"                   testNetworkGitClone 
+    ]
+  ]
+  where
+    includeTestsIf True xs = xs
+    includeTestsIf False _ = []
+
+
+
+verbosity :: Verbosity
+verbosity = Verbosity.silent -- for debugging try verbose
+
+pkgidfoo :: PackageId
+pkgidfoo = PackageIdentifier (mkPackageName "foo") (mkVersion [1,0])
+
+
+-- ------------------------------------------------------------
+-- * Unit tests
+-- ------------------------------------------------------------
+
+testNoRepos :: Assertion
+testNoRepos = do
+    e <- assertException $
+           clonePackagesFromSourceRepo verbosity "." Nothing pkgrepos
+    e @?= ClonePackageNoSourceRepos pkgidfoo
+  where
+    pkgrepos = [(pkgidfoo, [])]
+
+
+testNoReposOfKind :: Assertion
+testNoReposOfKind = do
+    e <- assertException $
+           clonePackagesFromSourceRepo verbosity "." repokind pkgrepos
+    e @?= ClonePackageNoSourceReposOfKind pkgidfoo repokind
+  where
+    pkgrepos = [(pkgidfoo, [repo])]
+    repo     = emptySourceRepo RepoHead
+    repokind = Just RepoThis
+
+
+testNoRepoType :: Assertion
+testNoRepoType = do
+    e <- assertException $
+           clonePackagesFromSourceRepo verbosity "." Nothing pkgrepos
+    e @?= ClonePackageNoRepoType pkgidfoo repo
+  where
+    pkgrepos = [(pkgidfoo, [repo])]
+    repo     = emptySourceRepo RepoHead
+
+
+testUnsupportedRepoType :: Assertion
+testUnsupportedRepoType = do
+    e <- assertException $
+           clonePackagesFromSourceRepo verbosity "." Nothing pkgrepos
+    e @?= ClonePackageUnsupportedRepoType pkgidfoo repo repotype
+  where
+    pkgrepos = [(pkgidfoo, [repo])]
+    repo     = (emptySourceRepo RepoHead) {
+                 repoType = Just repotype
+               }
+    repotype = OtherRepoType "baz"
+
+
+testNoRepoLocation :: Assertion
+testNoRepoLocation = do
+    e <- assertException $
+           clonePackagesFromSourceRepo verbosity "." Nothing pkgrepos
+    e @?= ClonePackageNoRepoLocation pkgidfoo repo
+  where
+    pkgrepos = [(pkgidfoo, [repo])]
+    repo     = (emptySourceRepo RepoHead) {
+                 repoType = Just repotype
+               }
+    repotype = Darcs
+
+
+testSelectRepoKind :: Assertion
+testSelectRepoKind =
+    sequence_
+      [ do e <- test requestedRepoType pkgrepos
+           e @?= ClonePackageNoRepoType pkgidfoo expectedRepo
+
+           e' <- test requestedRepoType (reverse pkgrepos)
+           e' @?= ClonePackageNoRepoType pkgidfoo expectedRepo
+      | let test rt rs = assertException $
+                           clonePackagesFromSourceRepo verbosity "." rt rs
+      , (requestedRepoType, expectedRepo) <- cases
+      ]
+  where
+    pkgrepos = [(pkgidfoo, [repo1, repo2, repo3])]
+    repo1    = emptySourceRepo RepoThis
+    repo2    = emptySourceRepo RepoHead
+    repo3    = emptySourceRepo (RepoKindUnknown "bar")
+    cases    = [ (Nothing,       repo1)
+               , (Just RepoThis, repo1)
+               , (Just RepoHead, repo2)
+               , (Just (RepoKindUnknown "bar"), repo3)
+               ]
+
+
+testRepoDestinationExists :: Assertion
+testRepoDestinationExists =
+    withTestDir verbosity "repos" $ \tmpdir -> do
+      let pkgdir = tmpdir </> "foo"
+      createDirectory pkgdir
+      e1 <- assertException $
+              clonePackagesFromSourceRepo verbosity tmpdir Nothing pkgrepos
+      e1 @?= ClonePackageDestinationExists pkgidfoo pkgdir True {- isdir -}
+
+      removeDirectory pkgdir
+
+      writeFile pkgdir ""
+      e2 <- assertException $
+              clonePackagesFromSourceRepo verbosity tmpdir Nothing pkgrepos
+      e2 @?= ClonePackageDestinationExists pkgidfoo pkgdir False {- isfile -}
+  where
+    pkgrepos = [(pkgidfoo, [repo])]
+    repo     = (emptySourceRepo RepoHead) {
+                 repoType     = Just Darcs,
+                 repoLocation = Just ""
+               }
+
+
+testGitFetchFailed :: Assertion
+testGitFetchFailed =
+    withTestDir verbosity "repos" $ \tmpdir -> do
+      let srcdir   = tmpdir </> "src"
+          repo     = (emptySourceRepo RepoHead) {
+                       repoType     = Just Git,
+                       repoLocation = Just srcdir
+                     }
+          pkgrepos = [(pkgidfoo, [repo])]
+      e1 <- assertException $
+              clonePackagesFromSourceRepo verbosity tmpdir Nothing pkgrepos
+      e1 @?= ClonePackageFailedWithExitCode pkgidfoo repo "git" (ExitFailure 128)
+
+
+testNetworkGitClone :: Assertion
+testNetworkGitClone =
+    withTestDir verbosity "repos" $ \tmpdir -> do
+      let repo1 = (emptySourceRepo RepoHead) {
+                    repoType     = Just Git,
+                    repoLocation = Just "https://github.com/haskell/zlib.git"
+                  }
+      clonePackagesFromSourceRepo verbosity tmpdir Nothing
+                                  [(mkpkgid "zlib1", [repo1])]
+      assertFileContains (tmpdir </> "zlib1/zlib.cabal") ["name:", "zlib"]
+
+      let repo2 = (emptySourceRepo RepoHead) {
+                    repoType     = Just Git,
+                    repoLocation = Just (tmpdir </> "zlib1")
+                  }
+      clonePackagesFromSourceRepo verbosity tmpdir Nothing
+                                  [(mkpkgid "zlib2", [repo2])]
+      assertFileContains (tmpdir </> "zlib2/zlib.cabal") ["name:", "zlib"]
+
+      let repo3 = (emptySourceRepo RepoHead) {
+                    repoType     = Just Git,
+                    repoLocation = Just (tmpdir </> "zlib1"),
+                    repoTag      = Just "0.5.0.0"
+                  }
+      clonePackagesFromSourceRepo verbosity tmpdir Nothing
+                                  [(mkpkgid "zlib3", [repo3])]
+      assertFileContains (tmpdir </> "zlib3/zlib.cabal") ["version:", "0.5.0.0"]
+  where
+    mkpkgid nm = PackageIdentifier (mkPackageName nm) (mkVersion [])
+
+
+-- ------------------------------------------------------------
+-- * HUnit utils
+-- ------------------------------------------------------------
+
+assertException :: forall e a. (Exception e, HasCallStack) => IO a -> IO e
+assertException action = do
+    r <- try action
+    case r of
+      Left e  -> return e
+      Right _ -> assertFailure $ "expected exception of type "
+                              ++ show (typeOf (undefined :: e)) 
+
+
+-- | Expect that one line in a file matches exactly the given words (i.e. at
+-- least insensitive to whitespace)
+--
+assertFileContains :: HasCallStack => FilePath -> [String] -> Assertion
+assertFileContains file expected = do
+    c <- readFile file `catch` \e ->
+           if isDoesNotExistError e
+              then assertFailure $ "expected a file to exist: " ++ file
+              else throwIO e
+    unless (expected `elem` map words (lines c)) $
+      assertFailure $ "expected the file " ++ file ++ " to contain "
+                   ++ show (take 100 expected)
+
diff --git a/cabal/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs b/cabal/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs
--- a/cabal/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs
+++ b/cabal/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs
@@ -204,7 +204,7 @@
 hackProjectConfigShared config =
     config {
       projectConfigProjectFile = mempty, -- not present within project files
-      projectConfigConfigFile  = mempty, -- dito
+      projectConfigConfigFile  = mempty, -- ditto
       projectConfigConstraints =
       --TODO: [required eventually] parse ambiguity in constraint
       -- "pkgname -any" as either any version or disabled flag "any".
@@ -284,6 +284,7 @@
         <*> arbitrary
         <*> arbitrary
         <*> arbitrary
+        <*> arbitrary
         <*> (MapMappend . fmap getNonMEmpty . Map.fromList
                <$> shortListOf 3 arbitrary)
         -- package entries with no content are equivalent to
@@ -297,7 +298,8 @@
                          , projectConfigShared = x5
                          , projectConfigProvenance = x6
                          , projectConfigLocalPackages = x7
-                         , projectConfigSpecificPackage = x8 } =
+                         , projectConfigSpecificPackage = x8
+                         , projectConfigAllPackages = x9 } =
       [ ProjectConfig { projectPackages = x0'
                       , projectPackagesOptional = x1'
                       , projectPackagesRepo = x2'
@@ -307,10 +309,11 @@
                       , projectConfigProvenance = x6'
                       , projectConfigLocalPackages = x7'
                       , projectConfigSpecificPackage = (MapMappend
-                                                         (fmap getNonMEmpty x8')) }
-      | ((x0', x1', x2', x3'), (x4', x5', x6', x7', x8'))
+                                                         (fmap getNonMEmpty x8'))
+                      , projectConfigAllPackages = x9' }
+      | ((x0', x1', x2', x3'), (x4', x5', x6', x7', x8', x9'))
           <- shrink ((x0, x1, x2, x3),
-                      (x4, x5, x6, x7, fmap NonMEmpty (getMapMappend x8)))
+                      (x4, x5, x6, x7, fmap NonMEmpty (getMapMappend x8), x9))
       ]
 
 newtype PackageLocationString
@@ -359,7 +362,6 @@
         <*> arbitrary
         <*> (fmap getShortToken <$> arbitrary)
         <*> (fmap getShortToken <$> arbitrary)
-        <*> (fmap getShortToken <$> arbitrary)
       where
         arbitraryNumJobs = fmap (fmap getPositive) <$> arbitrary
 
@@ -379,8 +381,7 @@
                                   , projectConfigHttpTransport = x13
                                   , projectConfigIgnoreExpiry = x14
                                   , projectConfigCacheDir = x15
-                                  , projectConfigLogsDir = x16
-                                  , projectConfigStoreDir = x17 } =
+                                  , projectConfigLogsDir = x16 } =
       [ ProjectConfigBuildOnly { projectConfigVerbosity = x00'
                                , projectConfigDryRun = x01'
                                , projectConfigOnlyDeps = x02'
@@ -397,8 +398,7 @@
                                , projectConfigHttpTransport = x13
                                , projectConfigIgnoreExpiry = x14'
                                , projectConfigCacheDir = x15
-                               , projectConfigLogsDir = x16
-                               , projectConfigStoreDir = x17}
+                               , projectConfigLogsDir = x16 }
       | ((x00', x01', x02', x03', x04'),
          (x05', x06', x07', x08', x09'),
          (x10', x11', x12',       x14'))
@@ -424,6 +424,7 @@
         <*> arbitrary
         <*> (toNubList <$> listOf arbitraryShortToken)
         <*> arbitrary
+        <*> arbitraryFlag arbitraryShortToken
         <*> arbitraryConstraints
         <*> shortListOf 2 arbitrary
         <*> arbitrary <*> arbitrary
@@ -433,6 +434,8 @@
         <*> arbitrary
         <*> arbitrary
         <*> arbitrary
+        <*> arbitrary
+        <*> (toNubList <$> listOf arbitraryShortToken)
       where
         arbitraryConstraints :: Gen [(UserConstraint, ConstraintSource)]
         arbitraryConstraints =
@@ -453,14 +456,17 @@
                                , projectConfigSolver = x12
                                , projectConfigAllowOlder = x13
                                , projectConfigAllowNewer = x14
-                               , projectConfigMaxBackjumps = x15
-                               , projectConfigReorderGoals = x16
-                               , projectConfigCountConflicts = x17
-                               , projectConfigStrongFlags = x18
-                               , projectConfigAllowBootLibInstalls = x19
-                               , projectConfigPerComponent = x20
-                               , projectConfigIndependentGoals = x21
-                               , projectConfigConfigFile = x22 } =
+                               , projectConfigWriteGhcEnvironmentFilesPolicy = x15
+                               , projectConfigMaxBackjumps = x16
+                               , projectConfigReorderGoals = x17
+                               , projectConfigCountConflicts = x18
+                               , projectConfigStrongFlags = x19
+                               , projectConfigAllowBootLibInstalls = x20
+                               , projectConfigPerComponent = x21
+                               , projectConfigIndependentGoals = x22
+                               , projectConfigConfigFile = x23
+                               , projectConfigProgPathExtra = x24
+                               , projectConfigStoreDir = x25 } =
       [ ProjectConfigShared { projectConfigDistDir = x00'
                             , projectConfigProjectFile = x01'
                             , projectConfigHcFlavor = x02'
@@ -476,25 +482,28 @@
                             , projectConfigSolver = x12'
                             , projectConfigAllowOlder = x13'
                             , projectConfigAllowNewer = x14'
-                            , projectConfigMaxBackjumps = x15'
-                            , projectConfigReorderGoals = x16'
-                            , projectConfigCountConflicts = x17'
-                            , projectConfigStrongFlags = x18'
-                            , projectConfigAllowBootLibInstalls = x19'
-                            , projectConfigPerComponent = x20'
-                            , projectConfigIndependentGoals = x21'
-                            , projectConfigConfigFile = x22' }
+                            , projectConfigWriteGhcEnvironmentFilesPolicy = x15'
+                            , projectConfigMaxBackjumps = x16'
+                            , projectConfigReorderGoals = x17'
+                            , projectConfigCountConflicts = x18'
+                            , projectConfigStrongFlags = x19'
+                            , projectConfigAllowBootLibInstalls = x20'
+                            , projectConfigPerComponent = x21'
+                            , projectConfigIndependentGoals = x22'
+                            , projectConfigConfigFile = x23'
+                            , projectConfigProgPathExtra = x24'
+                            , projectConfigStoreDir = x25' }
       | ((x00', x01', x02', x03', x04'),
          (x05', x06', x07', x08', x09'),
-         (x10', x11', x12', x13', x14'),
-         (x15', x16', x17', x18', x19'),
-          x20', x21', x22')
+         (x10', x11', x12', x13', x14', x15'),
+         (x16', x17', x18', x19', x20'),
+          x21', x22', x23', x24', x25')
           <- shrink
                ((x00, x01, x02, fmap NonEmpty x03, fmap NonEmpty x04),
                 (x05, x06, x07, x08, preShrink_Constraints x09),
-                (x10, x11, x12, x13, x14),
-                (x15, x16, x17, x18, x19),
-                 x20, x21, x22)
+                (x10, x11, x12, x13, x14, x15),
+                (x16, x17, x18, x19, x20),
+                 x21, x22, x23, x24, x25)
       ]
       where
         preShrink_Constraints  = map fst
@@ -545,6 +554,7 @@
         <*> arbitrary
         <*> arbitraryFlag arbitraryShortToken
         <*> arbitrary
+        <*> arbitrary
         <*> arbitraryFlag arbitraryShortToken
         <*> arbitrary
         <*> arbitrary
@@ -595,7 +605,8 @@
                          , packageConfigHaddockBenchmarks = x35
                          , packageConfigHaddockInternal = x36
                          , packageConfigHaddockCss = x37
-                         , packageConfigHaddockHscolour = x38
+                         , packageConfigHaddockLinkedSource = x38
+                         , packageConfigHaddockQuickJump = x43
                          , packageConfigHaddockHscolourCss = x39
                          , packageConfigHaddockContents = x40
                          , packageConfigHaddockForHackage = x41 } =
@@ -640,7 +651,8 @@
                       , packageConfigHaddockBenchmarks = x35'
                       , packageConfigHaddockInternal = x36'
                       , packageConfigHaddockCss = fmap getNonEmpty x37'
-                      , packageConfigHaddockHscolour = x38'
+                      , packageConfigHaddockLinkedSource = x38'
+                      , packageConfigHaddockQuickJump = x43'
                       , packageConfigHaddockHscolourCss = fmap getNonEmpty x39'
                       , packageConfigHaddockContents = x40'
                       , packageConfigHaddockForHackage = x41' }
@@ -651,7 +663,7 @@
          ((x20', x20_1', x21', x22', x23', x24'),
           (x25', x26', x27', x28', x29'),
           (x30', x31', x32', (x33', x33_1'), x34'),
-          (x35', x36', x37', x38', x39'),
+          (x35', x36', x37', x38', x43', x39'),
           (x40', x41')))
           <- shrink
              (((preShrink_Paths x00, preShrink_Args x01, x02, x03, x04),
@@ -664,7 +676,7 @@
                ((x20, x20_1, x21, x22, x23, x24),
                  (x25, x26, x27, x28, x29),
                  (x30, x31, x32, (x33, x33_1), x34),
-                 (x35, x36, fmap NonEmpty x37, x38, fmap NonEmpty x39),
+                 (x35, x36, fmap NonEmpty x37, x38, x43, fmap NonEmpty x39),
                  (x40, x41)))
       ]
       where
@@ -720,11 +732,6 @@
 
 instance Arbitrary CompilerFlavor where
     arbitrary = elements knownCompilerFlavors
-      where
-        --TODO: [code cleanup] export knownCompilerFlavors from D.Compiler
-        -- it's already defined there, just need it exported.
-        knownCompilerFlavors =
-          [GHC, GHCJS, NHC, YHC, Hugs, HBC, Helium, JHC, LHC, UHC]
 
 instance Arbitrary a => Arbitrary (InstallDirs a) where
     arbitrary =
diff --git a/cabal/cabal-install/tests/UnitTests/Distribution/Client/Targets.hs b/cabal/cabal-install/tests/UnitTests/Distribution/Client/Targets.hs
--- a/cabal/cabal-install/tests/UnitTests/Distribution/Client/Targets.hs
+++ b/cabal/cabal-install/tests/UnitTests/Distribution/Client/Targets.hs
@@ -31,10 +31,10 @@
 tests =
   [ makeGroup "readUserConstraint" (uncurry readUserConstraintTest)
       exampleConstraints
-    
+
   , makeGroup "parseUserConstraint" (uncurry parseUserConstraintTest)
       exampleConstraints
-  
+
   , makeGroup "readUserConstraints" (uncurry readUserConstraintsTest)
       [-- First example only.
        (head exampleStrs, take 1 exampleUcs),
@@ -49,7 +49,7 @@
   [ ("template-haskell installed",
      UserConstraint (UserQualified UserQualToplevel (pn "template-haskell"))
                     PackagePropertyInstalled)
-    
+
   , ("bytestring -any",
      UserConstraint (UserQualified UserQualToplevel (pn "bytestring"))
                     (PackagePropertyVersion anyVersion))
@@ -65,14 +65,14 @@
   , ("process:setup.bytestring ==5.2",
      UserConstraint (UserQualified (UserQualSetup (pn "process")) (pn "bytestring"))
                     (PackagePropertyVersion (thisVersion (mkVersion [5, 2]))))
-    
+
   , ("network:setup.containers +foo -bar baz",
      UserConstraint (UserQualified (UserQualSetup (pn "network")) (pn "containers"))
                     (PackagePropertyFlags (mkFlagAssignment
                                           [(fn "foo", True),
                                            (fn "bar", False),
                                            (fn "baz", True)])))
-    
+
   -- -- TODO: Re-enable UserQualExe tests once we decide on a syntax.
   --
   -- , ("foo:happy:exe.template-haskell test",
diff --git a/cabal/cabal-install/tests/UnitTests/Distribution/Client/UserConfig.hs b/cabal/cabal-install/tests/UnitTests/Distribution/Client/UserConfig.hs
--- a/cabal/cabal-install/tests/UnitTests/Distribution/Client/UserConfig.hs
+++ b/cabal/cabal-install/tests/UnitTests/Distribution/Client/UserConfig.hs
@@ -37,7 +37,7 @@
     -- Create a new default config file in our test directory.
     _ <- loadConfig silent (Flag configFile)
     -- Now we read it in and compare it against the default.
-    diff <- userConfigDiff $ globalFlags configFile
+    diff <- userConfigDiff silent (globalFlags configFile) []
     assertBool (unlines $ "Following diff should be empty:" : diff) $ null diff
 
 
@@ -46,7 +46,7 @@
     -- Create a new default config file in our test directory.
     _ <- loadConfig silent (Flag configFile)
     appendFile configFile "verbose: 0\n"
-    diff <- userConfigDiff $ globalFlags configFile
+    diff <- userConfigDiff silent (globalFlags configFile) []
     assertBool (unlines $ "Should detect a difference:" : diff) $
         diff == [ "+ verbose: 0" ]
 
@@ -56,7 +56,7 @@
     -- Write a trivial cabal file.
     writeFile configFile "tests: True\n"
     -- Update the config file.
-    userConfigUpdate silent $ globalFlags configFile
+    userConfigUpdate silent (globalFlags configFile) []
     -- Load it again.
     updated <- loadConfig silent (Flag configFile)
     assertBool ("Field 'tests' should be True") $
@@ -68,7 +68,7 @@
     -- Create a new default config file in our test directory.
     _ <- loadConfig silent (Flag configFile)
     -- Update it twice.
-    replicateM_ 2 . userConfigUpdate silent $ globalFlags configFile
+    replicateM_ 2 $ userConfigUpdate silent (globalFlags configFile) []
     -- Load it again.
     updated <- loadConfig silent (Flag configFile)
 
@@ -85,7 +85,7 @@
     sysTmpDir <- getTemporaryDirectory
     withTempDirectory silent sysTmpDir "cabal-test" $ \tmpDir -> do
         let configFile  = tmpDir </> "tmp.config"
-        _ <- createDefaultConfigFile silent configFile
+        _ <- createDefaultConfigFile silent [] configFile
         exists <- doesFileExist configFile
         assertBool ("Config file should be written to " ++ configFile) exists
 
diff --git a/cabal/cabal-install/tests/UnitTests/Distribution/Client/VCS.hs b/cabal/cabal-install/tests/UnitTests/Distribution/Client/VCS.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/tests/UnitTests/Distribution/Client/VCS.hs
@@ -0,0 +1,694 @@
+{-# LANGUAGE RecordWildCards, NamedFieldPuns #-}
+module UnitTests.Distribution.Client.VCS (tests) where
+
+import Distribution.Client.VCS
+import Distribution.Client.RebuildMonad
+         ( execRebuild )
+import Distribution.Simple.Program
+import Distribution.Verbosity as Verbosity
+import Distribution.Types.SourceRepo
+
+import Data.List
+import Data.Tuple
+import qualified Data.Map as Map
+import Data.Map (Map)
+import qualified Data.Set as Set
+import Data.Set (Set)
+import Data.Char (isSpace)
+
+import Control.Monad
+import qualified Control.Monad.State as State
+import Control.Monad.State (StateT, liftIO, execStateT)
+import Control.Exception
+import Control.Concurrent (threadDelay)
+
+import System.IO
+import System.FilePath
+import System.Directory
+import System.Random
+
+import Test.Tasty
+import Test.Tasty.QuickCheck
+import UnitTests.Distribution.Client.ArbitraryInstances
+import UnitTests.TempTestDir (withTestDir, removeDirectoryRecursiveHack)
+
+
+-- | These tests take the following approach: we generate a pure representation
+-- of a repository plus a corresponding real repository, and then run various
+-- test operations and compare the actual working state with the expected
+-- working state.
+--
+-- The first test simply checks that the test infrastructure works. It
+-- constructs a repository on disk and then checks out every tag or commmit
+-- and checks that the working state is the same as the pure representation.
+--
+-- The second test works in a similar way but tests 'syncSourceRepos'. It
+-- uses an arbitrary source repo and a set of (initially empty) destination
+-- directories. It picks a number of tags or commits from the source repo and
+-- synchronises the destination directories to those target states, and then
+-- checks that the working state is as expected (given the pure representation).
+--
+tests :: MTimeChange -> [TestTree]
+tests mtimeChange =
+  [ testGroup "check VCS test framework" $
+    [ testProperty "git"    prop_framework_git
+    ] ++
+    [ testProperty "darcs" (prop_framework_darcs mtimeChange)
+    | enableDarcsTests
+    ]
+  , testGroup "cloneSourceRepo" $
+    [ testProperty "git"    prop_cloneRepo_git
+    ] ++
+    [ testProperty "darcs" (prop_cloneRepo_darcs mtimeChange)
+    | enableDarcsTests
+    ]
+  , testGroup "syncSourceRepos" $
+    [ testProperty "git"    prop_syncRepos_git
+    ] ++
+    [ testProperty "darcs" (prop_syncRepos_darcs mtimeChange)
+    | enableDarcsTests
+    ]
+  ]
+  where
+    -- for the moment they're not yet working
+    enableDarcsTests = False
+
+
+prop_framework_git :: BranchingRepoRecipe -> Property
+prop_framework_git =
+    ioProperty
+  . prop_framework vcsGit vcsTestDriverGit
+  . WithBranchingSupport
+
+prop_framework_darcs :: MTimeChange -> NonBranchingRepoRecipe -> Property
+prop_framework_darcs mtimeChange =
+    ioProperty
+  . prop_framework vcsDarcs (vcsTestDriverDarcs mtimeChange)
+  . WithoutBranchingSupport
+
+prop_cloneRepo_git :: BranchingRepoRecipe -> Property
+prop_cloneRepo_git =
+    ioProperty
+  . prop_cloneRepo vcsGit vcsTestDriverGit
+  . WithBranchingSupport
+
+prop_cloneRepo_darcs :: MTimeChange
+                     -> NonBranchingRepoRecipe -> Property
+prop_cloneRepo_darcs mtimeChange =
+    ioProperty
+  . prop_cloneRepo vcsDarcs (vcsTestDriverDarcs mtimeChange)
+  . WithoutBranchingSupport
+
+prop_syncRepos_git :: RepoDirSet -> SyncTargetIterations -> PrngSeed
+                   -> BranchingRepoRecipe -> Property
+prop_syncRepos_git destRepoDirs syncTargetSetIterations seed =
+    ioProperty
+  . prop_syncRepos vcsGit vcsTestDriverGit
+                   destRepoDirs syncTargetSetIterations seed
+  . WithBranchingSupport
+
+prop_syncRepos_darcs :: MTimeChange
+                     -> RepoDirSet -> SyncTargetIterations -> PrngSeed
+                     -> NonBranchingRepoRecipe -> Property
+prop_syncRepos_darcs  mtimeChange destRepoDirs syncTargetSetIterations seed =
+    ioProperty
+  . prop_syncRepos vcsDarcs (vcsTestDriverDarcs mtimeChange)
+                   destRepoDirs syncTargetSetIterations seed
+  . WithoutBranchingSupport
+
+
+-- ------------------------------------------------------------
+-- * General test setup
+-- ------------------------------------------------------------
+
+testSetup :: VCS Program
+          -> (Verbosity -> VCS ConfiguredProgram
+                        -> FilePath -> VCSTestDriver)
+          -> RepoRecipe
+          -> (VCSTestDriver -> FilePath -> RepoState -> IO a)
+          -> IO a
+testSetup vcs mkVCSTestDriver repoRecipe theTest = do
+    -- test setup
+    vcs' <- configureVCS verbosity vcs
+    withTestDir verbosity "vcstest" $ \tmpdir -> do
+      let srcRepoPath = tmpdir </> "src"
+          vcsDriver   = mkVCSTestDriver verbosity vcs' srcRepoPath
+      repoState <- createRepo vcsDriver repoRecipe
+
+      -- actual test
+      result <- theTest vcsDriver tmpdir repoState
+
+      return result
+  where
+    verbosity = silent
+
+-- ------------------------------------------------------------
+-- * Test 1: VCS infrastructure
+-- ------------------------------------------------------------
+
+-- | This test simply checks that the test infrastructure works. It constructs
+-- a repository on disk and then checks out every tag or commit and checks that
+-- the working state is the same as the pure representation.
+--
+prop_framework :: VCS Program
+               -> (Verbosity -> VCS ConfiguredProgram
+                             -> FilePath -> VCSTestDriver)
+               -> RepoRecipe
+               -> IO ()
+prop_framework vcs mkVCSTestDriver repoRecipe =
+    testSetup vcs mkVCSTestDriver repoRecipe $ \vcsDriver tmpdir repoState ->
+      mapM_ (checkAtTag vcsDriver tmpdir) (Map.toList (allTags repoState))
+  where
+    -- Check for any given tag/commit in the 'RepoState' that the working state
+    -- matches the actual working state from the repository at that tag/commit.
+    checkAtTag VCSTestDriver {..} tmpdir (tagname, expectedState) =
+      case vcsCheckoutTag of
+        -- We handle two cases: inplace checkouts for VCSs that support it
+        -- (e.g. git) and separate dir otherwise (e.g. darcs)
+        Left checkoutInplace -> do
+          checkoutInplace tagname
+          checkExpectedWorkingState vcsIgnoreFiles vcsRepoRoot expectedState
+
+        Right checkoutCloneTo -> do
+          checkoutCloneTo tagname destRepoPath
+          checkExpectedWorkingState vcsIgnoreFiles destRepoPath expectedState
+          removeDirectoryRecursiveHack silent destRepoPath
+        where
+          destRepoPath = tmpdir </> "dest"
+
+
+-- ------------------------------------------------------------
+-- * Test 2: 'cloneSourceRepo'
+-- ------------------------------------------------------------
+
+prop_cloneRepo :: VCS Program
+               -> (Verbosity -> VCS ConfiguredProgram
+                             -> FilePath -> VCSTestDriver)
+               -> RepoRecipe
+               -> IO ()
+prop_cloneRepo vcs mkVCSTestDriver repoRecipe =
+    testSetup vcs mkVCSTestDriver repoRecipe $ \vcsDriver tmpdir repoState ->
+      mapM_ (checkAtTag vcsDriver tmpdir) (Map.toList (allTags repoState))
+  where
+    checkAtTag VCSTestDriver{..} tmpdir (tagname, expectedState) = do
+        cloneSourceRepo verbosity vcsVCS repo destRepoPath
+        checkExpectedWorkingState vcsIgnoreFiles destRepoPath expectedState
+        removeDirectoryRecursiveHack verbosity destRepoPath
+      where
+        destRepoPath = tmpdir </> "dest"
+        repo = (emptySourceRepo RepoThis) {
+                 repoType     = Just (vcsRepoType vcsVCS),
+                 repoLocation = Just vcsRepoRoot,
+                 repoTag      = Just tagname
+               }
+    verbosity = silent
+
+
+-- ------------------------------------------------------------
+-- * Test 3: 'syncSourceRepos'
+-- ------------------------------------------------------------
+
+newtype RepoDirSet           = RepoDirSet Int           deriving Show
+newtype SyncTargetIterations = SyncTargetIterations Int deriving Show
+newtype PrngSeed             = PrngSeed Int             deriving Show
+
+prop_syncRepos :: VCS Program
+               -> (Verbosity -> VCS ConfiguredProgram
+                             -> FilePath -> VCSTestDriver)
+               -> RepoDirSet
+               -> SyncTargetIterations
+               -> PrngSeed
+               -> RepoRecipe
+               -> IO ()
+prop_syncRepos vcs mkVCSTestDriver
+               repoDirs syncTargetSetIterations seed repoRecipe =
+    testSetup vcs mkVCSTestDriver repoRecipe $ \vcsDriver tmpdir repoState ->
+      let srcRepoPath   = vcsRepoRoot vcsDriver
+          destRepoPaths = map (tmpdir </>) (getRepoDirs repoDirs)
+       in checkSyncRepos verbosity vcsDriver repoState
+                         srcRepoPath destRepoPaths
+                         syncTargetSetIterations seed
+  where
+    verbosity = silent
+
+    getRepoDirs :: RepoDirSet -> [FilePath]
+    getRepoDirs (RepoDirSet n) =
+        [ "dest" ++ show i | i <- [1..n] ]
+
+
+-- | The purpose of this test is to check that irrespective of the local cached
+-- repo dir we can sync it to an arbitrary target state. So we do that by
+-- syncing each target dir to a sequence of target states without cleaning it
+-- in between.
+--
+-- One slight complication is that 'syncSourceRepos' takes a whole list of
+-- target dirs to sync in one go (to allow for sharing). So we must actually
+-- generate and sync to a sequence of list of target repo states.
+--
+-- So, given a source repo dir, the corresponding 'RepoState' and a number of
+-- target repo dirs, pick a sequence of (lists of) sync targets from the
+-- 'RepoState' and syncronise the target dirs with those targets, checking for
+-- each one that the actual working state matches the expected repo state.
+--
+checkSyncRepos
+  :: Verbosity
+  -> VCSTestDriver
+  -> RepoState
+  -> FilePath
+  -> [FilePath]
+  -> SyncTargetIterations
+  -> PrngSeed
+  -> IO ()
+checkSyncRepos verbosity VCSTestDriver { vcsVCS = vcs, vcsIgnoreFiles }
+               repoState srcRepoPath destRepoPath
+               (SyncTargetIterations syncTargetSetIterations) (PrngSeed seed) =
+    mapM_ checkSyncTargetSet syncTargetSets
+  where
+    checkSyncTargetSet :: [(SourceRepo, FilePath, RepoWorkingState)] -> IO ()
+    checkSyncTargetSet syncTargets = do
+      _ <- execRebuild "root-unused" $
+           syncSourceRepos verbosity vcs
+                           [ (repo, repoPath)
+                           | (repo, repoPath, _) <- syncTargets ]
+      sequence_
+        [ checkExpectedWorkingState vcsIgnoreFiles repoPath workingState
+        | (_, repoPath, workingState) <- syncTargets ]
+
+    syncTargetSets = take syncTargetSetIterations
+                   $ pickSyncTargetSets (vcsRepoType vcs) repoState
+                                        srcRepoPath destRepoPath
+                                        (mkStdGen seed)
+
+pickSyncTargetSets :: RepoType -> RepoState
+                   -> FilePath -> [FilePath]
+                   -> StdGen
+                   -> [[(SourceRepo, FilePath, RepoWorkingState)]]
+pickSyncTargetSets repoType repoState srcRepoPath dstReposPath =
+    assert (Map.size (allTags repoState) > 0) $
+    unfoldr (Just . swap . pickSyncTargetSet)
+  where
+    pickSyncTargetSet :: Rand [(SourceRepo, FilePath, RepoWorkingState)]
+    pickSyncTargetSet = flip (mapAccumL (flip pickSyncTarget)) dstReposPath
+
+    pickSyncTarget :: FilePath -> Rand (SourceRepo, FilePath, RepoWorkingState)
+    pickSyncTarget destRepoPath prng =
+        (prng', (repo, destRepoPath, workingState))
+      where
+        repo                = (emptySourceRepo RepoThis) {
+                                repoType     = Just repoType,
+                                repoLocation = Just srcRepoPath,
+                                repoTag      = Just tag
+                              }
+        (tag, workingState) = Map.elemAt tagIdx (allTags repoState)
+        (tagIdx, prng')     = randomR (0, Map.size (allTags repoState) - 1) prng
+
+type Rand a = StdGen -> (StdGen, a)
+
+instance Arbitrary RepoDirSet where
+  arbitrary =
+    sized $ \n -> oneof $ [ RepoDirSet <$> pure 1 ]
+                       ++ [ RepoDirSet <$> choose (2,5) | n >= 3 ]
+  shrink (RepoDirSet n) =
+    [ RepoDirSet i | i <- shrink n, i > 0 ]
+
+instance Arbitrary SyncTargetIterations where
+  arbitrary =
+    sized $ \n -> SyncTargetIterations <$> elements [ 1 .. min 20 (n + 1) ]
+  shrink (SyncTargetIterations n) =
+    [ SyncTargetIterations i | i <- shrink n, i > 0 ]
+
+instance Arbitrary PrngSeed where
+  arbitrary = PrngSeed <$> arbitraryBoundedRandom
+
+
+-- ------------------------------------------------------------
+-- * Instructions for constructing repositories
+-- ------------------------------------------------------------
+
+-- These instructions for constructing a repository can be interpreted in two
+-- ways: to make a pure representation of repository state, and to execute
+-- VCS commands to make a repository on-disk.
+
+data FileUpdate    = FileUpdate FilePath String        deriving Show
+data Commit        = Commit [FileUpdate]               deriving Show
+data TaggedCommits = TaggedCommits TagName    [Commit] deriving Show
+data BranchCommits = BranchCommits BranchName [Commit] deriving Show
+
+type BranchName    = String
+type TagName       = String
+
+-- | Instructions to make a repository without branches, for VCSs that do not
+-- support branches (e.g. darcs).
+newtype NonBranchingRepoRecipe = NonBranchingRepoRecipe [TaggedCommits]
+ deriving Show
+
+-- | Instructions to make a repository with branches, for VCSs that do
+-- support branches (e.g. git).
+newtype BranchingRepoRecipe = BranchingRepoRecipe
+                                [Either TaggedCommits BranchCommits]
+ deriving Show
+
+data RepoRecipe = WithBranchingSupport       BranchingRepoRecipe
+                | WithoutBranchingSupport NonBranchingRepoRecipe
+
+-- ---------------------------------------------------------------------------
+-- Arbitrary instances for them
+
+instance Arbitrary FileUpdate where
+  arbitrary = FileUpdate <$> genFileName <*> genFileContent
+    where
+      genFileName    = (\c -> "file" </> [c]) <$> choose ('A', 'E')
+      genFileContent = vectorOf 10 (choose ('#', '~'))
+
+instance Arbitrary Commit where
+  arbitrary = Commit <$> shortListOf1 5 arbitrary
+  shrink (Commit writes) = Commit <$> filter (not . null) (shrink writes)
+
+instance Arbitrary TaggedCommits where
+  arbitrary = TaggedCommits <$> genTagName <*>  shortListOf1 5 arbitrary
+    where
+      genTagName = ("tag_" ++) <$> shortListOf1 5 (choose ('A', 'Z'))
+  shrink (TaggedCommits tag commits) =
+    TaggedCommits tag <$> filter (not . null) (shrink commits)
+
+instance Arbitrary BranchCommits where
+  arbitrary = BranchCommits <$> genBranchName <*> shortListOf1 5 arbitrary
+    where
+      genBranchName =
+        sized $ \n ->
+          (\c -> "branch_" ++ [c]) <$> elements (take (max 1 n) ['A'..'E'])
+
+  shrink (BranchCommits branch commits) =
+    BranchCommits branch <$> filter (not . null) (shrink commits)
+
+instance Arbitrary NonBranchingRepoRecipe where
+  arbitrary = NonBranchingRepoRecipe <$> shortListOf1 15 arbitrary
+  shrink (NonBranchingRepoRecipe xs) =
+    NonBranchingRepoRecipe <$> filter (not . null) (shrink xs)
+
+instance Arbitrary BranchingRepoRecipe where
+  arbitrary = BranchingRepoRecipe <$> shortListOf1 15 taggedOrBranch
+    where
+      taggedOrBranch = frequency [ (3, Left  <$> arbitrary)
+                                 , (1, Right <$> arbitrary)
+                                 ]
+  shrink (BranchingRepoRecipe xs) =
+    BranchingRepoRecipe <$> filter (not . null) (shrink xs)
+
+
+-- ------------------------------------------------------------
+-- * A pure model of repository state
+-- ------------------------------------------------------------
+
+-- | The full state of a repository. In particular it records the full working
+-- state for every tag.
+--
+-- This is also the interpreter state for executing a 'RepoRecipe'.
+--
+-- This allows us to compare expected working states with the actual files in
+-- the working directory of a repository. See 'checkExpectedWorkingState'.
+--
+data RepoState =
+     RepoState {
+       currentBranch  :: BranchName,
+       currentWorking :: RepoWorkingState,
+       allTags        :: Map TagOrCommitId RepoWorkingState,
+       allBranches    :: Map BranchName RepoWorkingState
+     }
+  deriving Show
+
+type RepoWorkingState = Map FilePath String
+type CommitId         = String
+type TagOrCommitId    = String
+
+
+------------------------------------------------------------------------------
+-- Functions used to interpret instructions for constructing repositories
+
+initialRepoState :: RepoState
+initialRepoState =
+    RepoState {
+      currentBranch  = "branch_master",
+      currentWorking = Map.empty,
+      allTags        = Map.empty,
+      allBranches    = Map.empty
+    }
+
+updateFile :: FilePath -> String -> RepoState -> RepoState
+updateFile filename content state@RepoState{currentWorking} =
+  state { currentWorking = Map.insert filename content currentWorking }
+
+addTagOrCommit :: TagOrCommitId -> RepoState -> RepoState
+addTagOrCommit commit state@RepoState{currentWorking, allTags} =
+  state { allTags = Map.insert commit currentWorking allTags }
+
+switchBranch :: BranchName -> RepoState -> RepoState
+switchBranch branch state@RepoState{currentWorking, currentBranch, allBranches} =
+  -- Use updated allBranches to cover case of switching to the same branch
+  let allBranches' = Map.insert currentBranch currentWorking allBranches in
+  state {
+    currentBranch  = branch,
+    currentWorking = case Map.lookup branch allBranches' of
+                       Just working -> working
+                       -- otherwise we're creating a new branch, which starts
+                       -- from our current branch state
+                       Nothing      -> currentWorking,
+    allBranches    = allBranches'
+  }
+
+
+-- ------------------------------------------------------------
+-- * Comparing on-disk with expected 'RepoWorkingState'
+-- ------------------------------------------------------------
+
+-- | Compare expected working states with the actual files in
+-- the working directory of a repository.
+--
+checkExpectedWorkingState :: Set FilePath
+                          -> FilePath -> RepoWorkingState -> IO ()
+checkExpectedWorkingState ignore repoPath expectedState = do
+    currentState <- getCurrentWorkingState ignore repoPath
+    unless (currentState == expectedState) $
+      throwIO (WorkingStateMismatch expectedState currentState)
+
+data WorkingStateMismatch =
+     WorkingStateMismatch RepoWorkingState -- expected
+                          RepoWorkingState -- actual
+  deriving Show
+
+instance Exception WorkingStateMismatch
+
+getCurrentWorkingState :: Set FilePath -> FilePath -> IO RepoWorkingState
+getCurrentWorkingState ignore repoRoot = do
+    entries <- getDirectoryContentsRecursive ignore repoRoot ""
+    Map.fromList <$> mapM getFileEntry
+                          [ file | (file, isDir) <- entries, not isDir ]
+  where
+   getFileEntry name =
+     withBinaryFile (repoRoot </> name) ReadMode $ \h -> do
+       str <- hGetContents h
+       _   <- evaluate (length str)
+       return (name, str)
+
+getDirectoryContentsRecursive :: Set FilePath -> FilePath -> FilePath
+                              -> IO [(FilePath, Bool)]
+getDirectoryContentsRecursive ignore dir0 dir = do
+    entries  <- getDirectoryContents (dir0 </> dir)
+    entries' <- sequence
+                  [ do isdir <- doesDirectoryExist (dir0 </> dir </> entry)
+                       return (dir </> entry, isdir)
+                  | entry <- entries
+                  , not (isPrefixOf "." entry)
+                  , (dir </> entry) `Set.notMember` ignore
+                  ]
+    let subdirs = [ d | (d, True)  <- entries' ]
+    subdirEntries <- mapM (getDirectoryContentsRecursive ignore dir0) subdirs
+    return (concat (entries' : subdirEntries))
+
+
+-- ------------------------------------------------------------
+-- * Executing instructions to make on-disk VCS repos
+-- ------------------------------------------------------------
+
+-- | Execute the instructions in a 'RepoRecipe' using the given 'VCSTestDriver'
+-- to make an on-disk repository.
+--
+-- This also returns a 'RepoState'. This is done as part of construction to
+-- support VCSs like git that have commit ids, so that those commit ids can be
+-- included in the 'RepoState's 'allTags' set.
+--
+createRepo :: VCSTestDriver -> RepoRecipe -> IO RepoState
+createRepo vcsDriver@VCSTestDriver{vcsRepoRoot, vcsInit} recipe = do
+    createDirectory vcsRepoRoot
+    createDirectory (vcsRepoRoot </> "file")
+    vcsInit
+    execStateT createRepoAction initialRepoState
+  where
+    createRepoAction :: StateT RepoState IO ()
+    createRepoAction = case recipe of
+      WithoutBranchingSupport r -> execNonBranchingRepoRecipe vcsDriver r
+      WithBranchingSupport    r -> execBranchingRepoRecipe    vcsDriver r
+
+type CreateRepoAction a = VCSTestDriver -> a -> StateT RepoState IO ()
+
+execNonBranchingRepoRecipe :: CreateRepoAction NonBranchingRepoRecipe
+execNonBranchingRepoRecipe vcsDriver (NonBranchingRepoRecipe taggedCommits) =
+    mapM_ (execTaggdCommits vcsDriver) taggedCommits
+
+execBranchingRepoRecipe :: CreateRepoAction BranchingRepoRecipe
+execBranchingRepoRecipe vcsDriver (BranchingRepoRecipe taggedCommits) =
+    mapM_ (either (execTaggdCommits  vcsDriver)
+                  (execBranchCommits vcsDriver))
+          taggedCommits
+
+execBranchCommits :: CreateRepoAction BranchCommits
+execBranchCommits vcsDriver@VCSTestDriver{vcsSwitchBranch}
+                  (BranchCommits branch commits) = do
+    mapM_ (execCommit vcsDriver) commits
+    -- add commits and then switch branch
+    State.modify (switchBranch branch)
+    state <- State.get -- repo state after the commits and branch switch
+    liftIO $ vcsSwitchBranch state branch
+
+    -- It may seem odd that we add commits on the existing branch and then
+    -- switch branch. In part this is because git cannot branch from an empty
+    -- repo state, it complains that the master branch doesn't exist yet.
+
+execTaggdCommits :: CreateRepoAction TaggedCommits
+execTaggdCommits vcsDriver@VCSTestDriver{vcsTagState}
+                 (TaggedCommits tagname commits) = do
+    mapM_ (execCommit vcsDriver) commits
+    -- add commits then tag
+    state <- State.get -- repo state after the commits
+    liftIO $ vcsTagState state tagname
+    State.modify (addTagOrCommit tagname)
+
+execCommit :: CreateRepoAction Commit
+execCommit vcsDriver@VCSTestDriver{..} (Commit fileUpdates) = do
+    mapM_ (execFileUpdate vcsDriver) fileUpdates
+    state <- State.get -- existing state, not updated
+    mcommit <- liftIO $ vcsCommitChanges state
+    State.modify (maybe id addTagOrCommit mcommit)
+
+execFileUpdate :: CreateRepoAction FileUpdate
+execFileUpdate VCSTestDriver{..} (FileUpdate filename content) = do
+    liftIO $ writeFile (vcsRepoRoot </> filename) content
+    state <- State.get -- existing state, not updated
+    liftIO $ vcsAddFile state filename
+    State.modify (updateFile filename content)
+
+
+-- ------------------------------------------------------------
+-- * VCSTestDriver for various VCSs
+-- ------------------------------------------------------------
+
+-- | Extends 'VCS' with extra methods to construct a repository. Used by
+-- 'createRepo'.
+--
+-- Several of the methods are allowed to rely on the current 'RepoState'
+-- because some VCSs need different commands for initial vs later actions
+-- (like adding a file to the tracked set, or creating a new branch).
+--
+-- The driver instance knows the particular repo directory.
+--
+data VCSTestDriver = VCSTestDriver {
+       vcsVCS           :: VCS ConfiguredProgram,
+       vcsRepoRoot      :: FilePath,
+       vcsIgnoreFiles   :: Set FilePath,
+       vcsInit          :: IO (),
+       vcsAddFile       :: RepoState -> FilePath -> IO (),
+       vcsCommitChanges :: RepoState -> IO (Maybe CommitId),
+       vcsTagState      :: RepoState -> TagName -> IO (),
+       vcsSwitchBranch  :: RepoState -> BranchName -> IO (),
+       vcsCheckoutTag   :: Either (TagName -> IO ())
+                                  (TagName -> FilePath -> IO ())
+     }
+
+
+vcsTestDriverGit :: Verbosity -> VCS ConfiguredProgram
+                 -> FilePath -> VCSTestDriver
+vcsTestDriverGit verbosity vcs repoRoot =
+    VCSTestDriver {
+      vcsVCS = vcs
+
+    , vcsRepoRoot = repoRoot
+
+    , vcsIgnoreFiles = Set.empty
+
+    , vcsInit =
+        git $ ["init"]  ++ verboseArg
+
+    , vcsAddFile = \_ filename ->
+        git ["add", filename]
+
+    , vcsCommitChanges = \_state -> do
+        git $ [ "-c", "user.name=A", "-c", "user.email=a@example.com"
+              , "commit", "--all", "--message=a patch"
+              , "--author=A <a@example.com>"
+              ] ++ verboseArg
+        commit <- git' ["log", "--format=%H", "-1"]
+        let commit' = takeWhile (not . isSpace) commit
+        return (Just commit')
+
+    , vcsTagState = \_ tagname ->
+        git ["tag", "--force", tagname]
+
+    , vcsSwitchBranch = \RepoState{allBranches} branchname -> do
+        unless (branchname `Map.member` allBranches) $
+          git ["branch", branchname]
+        git $ ["checkout", branchname] ++ verboseArg
+
+    , vcsCheckoutTag = Left $ \tagname ->
+        git $ ["checkout", "--detach", "--force", tagname] ++ verboseArg
+    }
+  where
+    gitInvocation args = (programInvocation (vcsProgram vcs) args) {
+                           progInvokeCwd = Just repoRoot
+                         }
+    git  = runProgramInvocation       verbosity . gitInvocation
+    git' = getProgramInvocationOutput verbosity . gitInvocation
+    verboseArg = [ "--quiet" | verbosity < Verbosity.normal ]
+
+
+type MTimeChange = Int
+
+vcsTestDriverDarcs :: MTimeChange -> Verbosity -> VCS ConfiguredProgram
+                   -> FilePath -> VCSTestDriver
+vcsTestDriverDarcs mtimeChange verbosity vcs repoRoot =
+    VCSTestDriver {
+      vcsVCS = vcs
+
+    , vcsRepoRoot = repoRoot
+
+    , vcsIgnoreFiles = Set.singleton "_darcs"
+
+    , vcsInit =
+        darcs ["initialize"]
+
+    , vcsAddFile = \state filename -> do
+        threadDelay mtimeChange
+        unless (filename `Map.member` currentWorking state) $
+          darcs ["add", filename]
+        -- Darcs's file change tracking relies on mtime changes,
+        -- so we have to be careful with doing stuff too quickly:
+
+    , vcsCommitChanges = \_state -> do
+        threadDelay mtimeChange
+        darcs ["record", "--all", "--author=author", "--name=a patch"]
+        return Nothing
+
+    , vcsTagState = \_ tagname ->
+        darcs ["tag", "--author=author", tagname]
+
+    , vcsSwitchBranch = \_ _ ->
+        fail "vcsSwitchBranch: darcs does not support branches within a repo"
+
+    , vcsCheckoutTag = Right $ \tagname dest ->
+        darcs ["clone", "--lazy", "--tag=^" ++ tagname ++ "$", ".", dest]
+    }
+  where
+    darcsInvocation args = (programInvocation (vcsProgram vcs) args) {
+                               progInvokeCwd = Just repoRoot
+                           }
+    darcs = runProgramInvocation verbosity . darcsInvocation
+
diff --git a/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL.hs b/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL.hs
deleted file mode 100644
--- a/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL.hs
+++ /dev/null
@@ -1,698 +0,0 @@
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE ScopedTypeVariables #-}
--- | DSL for testing the modular solver
-module UnitTests.Distribution.Solver.Modular.DSL (
-    ExampleDependency(..)
-  , Dependencies(..)
-  , ExTest(..)
-  , ExExe(..)
-  , ExConstraint(..)
-  , ExPreference(..)
-  , ExampleDb
-  , ExampleVersionRange
-  , ExamplePkgVersion
-  , ExamplePkgName
-  , ExampleFlagName
-  , ExFlag(..)
-  , ExampleAvailable(..)
-  , ExampleInstalled(..)
-  , ExampleQualifier(..)
-  , ExampleVar(..)
-  , EnableAllTests(..)
-  , exAv
-  , exInst
-  , exFlagged
-  , exResolve
-  , extractInstallPlan
-  , declareFlags
-  , withSetupDeps
-  , withTest
-  , withTests
-  , withExe
-  , withExes
-  , runProgress
-  , mkSimpleVersion
-  , mkVersionRange
-  ) where
-
-import Prelude ()
-import Distribution.Solver.Compat.Prelude
-
--- base
-import Data.Either (partitionEithers)
-import qualified Data.Map as Map
-
--- Cabal
-import qualified Distribution.Compiler                  as C
-import qualified Distribution.InstalledPackageInfo      as IPI
-import           Distribution.License (License(..))
-import qualified Distribution.ModuleName                as Module
-import qualified Distribution.Package                   as C
-  hiding (HasUnitId(..))
-import qualified Distribution.Types.ExeDependency as C
-import qualified Distribution.Types.LegacyExeDependency as C
-import qualified Distribution.Types.PkgconfigDependency as C
-import qualified Distribution.Types.UnqualComponentName as C
-import qualified Distribution.Types.CondTree            as C
-import qualified Distribution.PackageDescription        as C
-import qualified Distribution.PackageDescription.Check  as C
-import qualified Distribution.Simple.PackageIndex       as C.PackageIndex
-import           Distribution.Simple.Setup (BooleanFlag(..))
-import qualified Distribution.System                    as C
-import           Distribution.Text (display)
-import qualified Distribution.Version                   as C
-import Language.Haskell.Extension (Extension(..), Language(..))
-
--- cabal-install
-import Distribution.Client.Dependency
-import Distribution.Client.Dependency.Types
-import Distribution.Client.Types
-import qualified Distribution.Client.SolverInstallPlan as CI.SolverInstallPlan
-
-import           Distribution.Solver.Types.ComponentDeps (ComponentDeps)
-import qualified Distribution.Solver.Types.ComponentDeps as CD
-import           Distribution.Solver.Types.ConstraintSource
-import           Distribution.Solver.Types.Flag
-import           Distribution.Solver.Types.LabeledPackageConstraint
-import           Distribution.Solver.Types.OptionalStanza
-import qualified Distribution.Solver.Types.PackageIndex      as CI.PackageIndex
-import           Distribution.Solver.Types.PackageConstraint
-import qualified Distribution.Solver.Types.PackagePath as P
-import qualified Distribution.Solver.Types.PkgConfigDb as PC
-import           Distribution.Solver.Types.Settings
-import           Distribution.Solver.Types.SolverPackage
-import           Distribution.Solver.Types.SourcePackage
-import           Distribution.Solver.Types.Variable
-
-{-------------------------------------------------------------------------------
-  Example package database DSL
-
-  In order to be able to set simple examples up quickly, we define a very
-  simple version of the package database here explicitly designed for use in
-  tests.
-
-  The design of `ExampleDb` takes the perspective of the solver, not the
-  perspective of the package DB. This makes it easier to set up tests for
-  various parts of the solver, but makes the mapping somewhat awkward,  because
-  it means we first map from "solver perspective" `ExampleDb` to the package
-  database format, and then the modular solver internally in `IndexConversion`
-  maps this back to the solver specific data structures.
-
-  IMPLEMENTATION NOTES
-  --------------------
-
-  TODO: Perhaps these should be made comments of the corresponding data type
-  definitions. For now these are just my own conclusions and may be wrong.
-
-  * The difference between `GenericPackageDescription` and `PackageDescription`
-    is that `PackageDescription` describes a particular _configuration_ of a
-    package (for instance, see documentation for `checkPackage`). A
-    `GenericPackageDescription` can be turned into a `PackageDescription` in
-    two ways:
-
-      a. `finalizePD` does the proper translation, by taking
-         into account the platform, available dependencies, etc. and picks a
-         flag assignment (or gives an error if no flag assignment can be found)
-      b. `flattenPackageDescription` ignores flag assignment and just joins all
-         components together.
-
-    The slightly odd thing is that a `GenericPackageDescription` contains a
-    `PackageDescription` as a field; both of the above functions do the same
-    thing: they take the embedded `PackageDescription` as a basis for the result
-    value, but override `library`, `executables`, `testSuites`, `benchmarks`
-    and `buildDepends`.
-  * The `condTreeComponents` fields of a `CondTree` is a list of triples
-    `(condition, then-branch, else-branch)`, where the `else-branch` is
-    optional.
--------------------------------------------------------------------------------}
-
-type ExamplePkgName    = String
-type ExamplePkgVersion = Int
-type ExamplePkgHash    = String  -- for example "installed" packages
-type ExampleFlagName   = String
-type ExampleTestName   = String
-type ExampleExeName    = String
-type ExampleVersionRange = C.VersionRange
-
-data Dependencies = NotBuildable | Buildable [ExampleDependency]
-  deriving Show
-
-data ExampleDependency =
-    -- | Simple dependency on any version
-    ExAny ExamplePkgName
-
-    -- | Simple dependency on a fixed version
-  | ExFix ExamplePkgName ExamplePkgVersion
-
-    -- | Simple dependency on a range of versions, with an inclusive lower bound
-    -- and an exclusive upper bound.
-  | ExRange ExamplePkgName ExamplePkgVersion ExamplePkgVersion
-
-    -- | Build-tool-depends dependency
-  | ExBuildToolAny ExamplePkgName ExampleExeName
-
-    -- | Build-tool-depends dependency on a fixed version
-  | ExBuildToolFix ExamplePkgName ExampleExeName ExamplePkgVersion
-
-    -- | Legacy build-tools dependency
-  | ExLegacyBuildToolAny ExamplePkgName
-
-    -- | Legacy build-tools dependency on a fixed version
-  | ExLegacyBuildToolFix ExamplePkgName ExamplePkgVersion
-
-    -- | Dependencies indexed by a flag
-  | ExFlagged ExampleFlagName Dependencies Dependencies
-
-    -- | Dependency on a language extension
-  | ExExt Extension
-
-    -- | Dependency on a language version
-  | ExLang Language
-
-    -- | Dependency on a pkg-config package
-  | ExPkg (ExamplePkgName, ExamplePkgVersion)
-  deriving Show
-
--- | Simplified version of D.Types.GenericPackageDescription.Flag for use in
--- example source packages.
-data ExFlag = ExFlag {
-    exFlagName    :: ExampleFlagName
-  , exFlagDefault :: Bool
-  , exFlagType    :: FlagType
-  } deriving Show
-
-data ExTest = ExTest ExampleTestName [ExampleDependency]
-
-data ExExe = ExExe ExampleExeName [ExampleDependency]
-
-exFlagged :: ExampleFlagName -> [ExampleDependency] -> [ExampleDependency]
-          -> ExampleDependency
-exFlagged n t e = ExFlagged n (Buildable t) (Buildable e)
-
-data ExConstraint =
-    ExVersionConstraint ConstraintScope ExampleVersionRange
-  | ExFlagConstraint ConstraintScope ExampleFlagName Bool
-  | ExStanzaConstraint ConstraintScope [OptionalStanza]
-  deriving Show
-
-data ExPreference =
-    ExPkgPref ExamplePkgName ExampleVersionRange
-  | ExStanzaPref ExamplePkgName [OptionalStanza]
-  deriving Show
-
-data ExampleAvailable = ExAv {
-    exAvName    :: ExamplePkgName
-  , exAvVersion :: ExamplePkgVersion
-  , exAvDeps    :: ComponentDeps [ExampleDependency]
-
-  -- Setting flags here is only necessary to override the default values of
-  -- the fields in C.Flag.
-  , exAvFlags   :: [ExFlag]
-  } deriving Show
-
-data ExampleVar =
-    P ExampleQualifier ExamplePkgName
-  | F ExampleQualifier ExamplePkgName ExampleFlagName
-  | S ExampleQualifier ExamplePkgName OptionalStanza
-
-data ExampleQualifier =
-    QualNone
-  | QualIndep ExamplePkgName
-  | QualSetup ExamplePkgName
-
-    -- The two package names are the build target and the package containing the
-    -- setup script.
-  | QualIndepSetup ExamplePkgName ExamplePkgName
-
-    -- The two package names are the package depending on the exe and the
-    -- package containing the exe.
-  | QualExe ExamplePkgName ExamplePkgName
-
--- | Whether to enable tests in all packages in a test case.
-newtype EnableAllTests = EnableAllTests Bool
-  deriving BooleanFlag
-
--- | Constructs an 'ExampleAvailable' package for the 'ExampleDb',
--- given:
---
---      1. The name 'ExamplePkgName' of the available package,
---      2. The version 'ExamplePkgVersion' available
---      3. The list of dependency constraints 'ExampleDependency'
---         that this package has.  'ExampleDependency' provides
---         a number of pre-canned dependency types to look at.
---
-exAv :: ExamplePkgName -> ExamplePkgVersion -> [ExampleDependency]
-     -> ExampleAvailable
-exAv n v ds = ExAv { exAvName = n, exAvVersion = v
-                   , exAvDeps = CD.fromLibraryDeps ds, exAvFlags = [] }
-
--- | Override the default settings (e.g., manual vs. automatic) for a subset of
--- a package's flags.
-declareFlags :: [ExFlag] -> ExampleAvailable -> ExampleAvailable
-declareFlags flags ex = ex {
-      exAvFlags = flags
-    }
-
-withSetupDeps :: ExampleAvailable -> [ExampleDependency] -> ExampleAvailable
-withSetupDeps ex setupDeps = ex {
-      exAvDeps = exAvDeps ex <> CD.fromSetupDeps setupDeps
-    }
-
-withTest :: ExampleAvailable -> ExTest -> ExampleAvailable
-withTest ex test = withTests ex [test]
-
-withTests :: ExampleAvailable -> [ExTest] -> ExampleAvailable
-withTests ex tests =
-  let testCDs = CD.fromList [(CD.ComponentTest $ C.mkUnqualComponentName name, deps)
-                            | ExTest name deps <- tests]
-  in ex { exAvDeps = exAvDeps ex <> testCDs }
-
-withExe :: ExampleAvailable -> ExExe -> ExampleAvailable
-withExe ex exe = withExes ex [exe]
-
-withExes :: ExampleAvailable -> [ExExe] -> ExampleAvailable
-withExes ex exes =
-  let exeCDs = CD.fromList [(CD.ComponentExe $ C.mkUnqualComponentName name, deps)
-                           | ExExe name deps <- exes]
-  in ex { exAvDeps = exAvDeps ex <> exeCDs }
-
--- | An installed package in 'ExampleDb'; construct me with 'exInst'.
-data ExampleInstalled = ExInst {
-    exInstName         :: ExamplePkgName
-  , exInstVersion      :: ExamplePkgVersion
-  , exInstHash         :: ExamplePkgHash
-  , exInstBuildAgainst :: [ExamplePkgHash]
-  } deriving Show
-
--- | Constructs an example installed package given:
---
---      1. The name of the package 'ExamplePkgName', i.e., 'String'
---      2. The version of the package 'ExamplePkgVersion', i.e., 'Int'
---      3. The IPID for the package 'ExamplePkgHash', i.e., 'String'
---         (just some unique identifier for the package.)
---      4. The 'ExampleInstalled' packages which this package was
---         compiled against.)
---
-exInst :: ExamplePkgName -> ExamplePkgVersion -> ExamplePkgHash
-       -> [ExampleInstalled] -> ExampleInstalled
-exInst pn v hash deps = ExInst pn v hash (map exInstHash deps)
-
--- | An example package database is a list of installed packages
--- 'ExampleInstalled' and available packages 'ExampleAvailable'.
--- Generally, you want to use 'exInst' and 'exAv' to construct
--- these packages.
-type ExampleDb = [Either ExampleInstalled ExampleAvailable]
-
-type DependencyTree a = C.CondTree C.ConfVar [C.Dependency] a
-
-type DependencyComponent a = C.CondBranch C.ConfVar [C.Dependency] a
-
-exDbPkgs :: ExampleDb -> [ExamplePkgName]
-exDbPkgs = map (either exInstName exAvName)
-
-exAvSrcPkg :: ExampleAvailable -> UnresolvedSourcePackage
-exAvSrcPkg ex =
-    let pkgId = exAvPkgId ex
-
-        flags :: [C.Flag]
-        flags =
-          let declaredFlags :: Map ExampleFlagName C.Flag
-              declaredFlags =
-                  Map.fromListWith
-                      (\f1 f2 -> error $ "duplicate flag declarations: " ++ show [f1, f2])
-                      [(exFlagName flag, mkFlag flag) | flag <- exAvFlags ex]
-
-              usedFlags :: Map ExampleFlagName C.Flag
-              usedFlags = Map.fromList [(fn, mkDefaultFlag fn) | fn <- names]
-                where
-                  names = concatMap extractFlags $
-                          CD.libraryDeps (exAvDeps ex)
-                           ++ concatMap snd testSuites
-                           ++ concatMap snd executables
-          in -- 'declaredFlags' overrides 'usedFlags' to give flags non-default settings:
-             Map.elems $ declaredFlags `Map.union` usedFlags
-
-        testSuites = [(name, deps) | (CD.ComponentTest name, deps) <- CD.toList (exAvDeps ex)]
-        executables = [(name, deps) | (CD.ComponentExe name, deps) <- CD.toList (exAvDeps ex)]
-        setup = case CD.setupDeps (exAvDeps ex) of
-                  []   -> Nothing
-                  deps -> Just C.SetupBuildInfo {
-                            C.setupDepends = mkSetupDeps deps,
-                            C.defaultSetupDepends = False
-                          }
-        package = SourcePackage {
-            packageInfoId        = pkgId
-          , packageSource        = LocalTarballPackage "<<path>>"
-          , packageDescrOverride = Nothing
-          , packageDescription   = C.GenericPackageDescription {
-                C.packageDescription = C.emptyPackageDescription {
-                    C.package        = pkgId
-                  , C.setupBuildInfo = setup
-                  , C.license = BSD3
-                  , C.buildType = if isNothing setup
-                                  then Just C.Simple
-                                  else Just C.Custom
-                  , C.category = "category"
-                  , C.maintainer = "maintainer"
-                  , C.description = "description"
-                  , C.synopsis = "synopsis"
-                  , C.licenseFiles = ["LICENSE"]
-                  , C.specVersionRaw = Left $ C.mkVersion [1,12]
-                  }
-              , C.genPackageFlags = flags
-              , C.condLibrary =
-                  let mkLib bi = mempty { C.libBuildInfo = bi }
-                  in Just $ mkCondTree defaultLib mkLib $ mkBuildInfoTree $
-                     Buildable (CD.libraryDeps (exAvDeps ex))
-              , C.condSubLibraries = []
-              , C.condForeignLibs = []
-              , C.condExecutables =
-                  let mkTree = mkCondTree defaultExe mkExe . mkBuildInfoTree . Buildable
-                      mkExe bi = mempty { C.buildInfo = bi }
-                  in map (\(t, deps) -> (t, mkTree deps)) executables
-              , C.condTestSuites =
-                  let mkTree = mkCondTree defaultTest mkTest . mkBuildInfoTree . Buildable
-                      mkTest bi = mempty { C.testBuildInfo = bi }
-                  in map (\(t, deps) -> (t, mkTree deps)) testSuites
-              , C.condBenchmarks  = []
-              }
-            }
-        pkgCheckErrors =
-          -- We ignore these warnings because some unit tests test that the
-          -- solver allows unknown extensions/languages when the compiler
-          -- supports them.
-          let ignore = ["Unknown extensions:", "Unknown languages:"]
-          in [ err | err <- C.checkPackage (packageDescription package) Nothing
-             , not $ any (`isPrefixOf` C.explanation err) ignore ]
-    in if null pkgCheckErrors
-       then package
-       else error $ "invalid GenericPackageDescription for package "
-                 ++ display pkgId ++ ": " ++ show pkgCheckErrors
-  where
-    defaultTopLevelBuildInfo :: C.BuildInfo
-    defaultTopLevelBuildInfo = mempty { C.defaultLanguage = Just Haskell98 }
-
-    defaultLib :: C.Library
-    defaultLib = mempty { C.exposedModules = [Module.fromString "Module"] }
-
-    defaultExe :: C.Executable
-    defaultExe = mempty { C.modulePath = "Main.hs" }
-
-    defaultTest :: C.TestSuite
-    defaultTest = mempty {
-        C.testInterface = C.TestSuiteExeV10 (C.mkVersion [1,0]) "Test.hs"
-      }
-
-    -- Split the set of dependencies into the set of dependencies of the library,
-    -- the dependencies of the test suites and extensions.
-    splitTopLevel :: [ExampleDependency]
-                  -> ( [ExampleDependency]
-                     , [Extension]
-                     , Maybe Language
-                     , [(ExamplePkgName, ExamplePkgVersion)] -- pkg-config
-                     , [(ExamplePkgName, ExampleExeName, C.VersionRange)] -- build tools
-                     , [(ExamplePkgName, C.VersionRange)] -- legacy build tools
-                     )
-    splitTopLevel [] =
-        ([], [], Nothing, [], [], [])
-    splitTopLevel (ExBuildToolAny p e:deps) =
-      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
-      in (other, exts, lang, pcpkgs, (p, e, C.anyVersion):exes, legacyExes)
-    splitTopLevel (ExBuildToolFix p e v:deps) =
-      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
-      in (other, exts, lang, pcpkgs, (p, e, C.thisVersion (mkSimpleVersion v)):exes, legacyExes)
-    splitTopLevel (ExLegacyBuildToolAny p:deps) =
-      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
-      in (other, exts, lang, pcpkgs, exes, (p, C.anyVersion):legacyExes)
-    splitTopLevel (ExLegacyBuildToolFix p v:deps) =
-      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
-      in (other, exts, lang, pcpkgs, exes, (p, C.thisVersion (mkSimpleVersion v)):legacyExes)
-    splitTopLevel (ExExt ext:deps) =
-      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
-      in (other, ext:exts, lang, pcpkgs, exes, legacyExes)
-    splitTopLevel (ExLang lang:deps) =
-        case splitTopLevel deps of
-            (other, exts, Nothing, pcpkgs, exes, legacyExes) -> (other, exts, Just lang, pcpkgs, exes, legacyExes)
-            _ -> error "Only 1 Language dependency is supported"
-    splitTopLevel (ExPkg pkg:deps) =
-      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
-      in (other, exts, lang, pkg:pcpkgs, exes, legacyExes)
-    splitTopLevel (dep:deps) =
-      let (other, exts, lang, pcpkgs, exes, legacyExes) = splitTopLevel deps
-      in (dep:other, exts, lang, pcpkgs, exes, legacyExes)
-
-    -- Extract the total set of flags used
-    extractFlags :: ExampleDependency -> [ExampleFlagName]
-    extractFlags (ExAny _)            = []
-    extractFlags (ExFix _ _)          = []
-    extractFlags (ExRange _ _ _)      = []
-    extractFlags (ExBuildToolAny _ _)   = []
-    extractFlags (ExBuildToolFix _ _ _) = []
-    extractFlags (ExLegacyBuildToolAny _)   = []
-    extractFlags (ExLegacyBuildToolFix _ _) = []
-    extractFlags (ExFlagged f a b)    =
-        f : concatMap extractFlags (deps a ++ deps b)
-      where
-        deps :: Dependencies -> [ExampleDependency]
-        deps NotBuildable = []
-        deps (Buildable ds) = ds
-    extractFlags (ExExt _)      = []
-    extractFlags (ExLang _)     = []
-    extractFlags (ExPkg _)      = []
-
-    -- Convert a tree of BuildInfos into a tree of a specific component type.
-    -- 'defaultTopLevel' contains the default values for the component, and
-    -- 'mkComponent' creates a component from a 'BuildInfo'.
-    mkCondTree :: forall a. Semigroup a =>
-                  a -> (C.BuildInfo -> a)
-               -> DependencyTree C.BuildInfo
-               -> DependencyTree a
-    mkCondTree defaultTopLevel mkComponent (C.CondNode topData topConstraints topComps) =
-        C.CondNode {
-            C.condTreeData =
-                defaultTopLevel <> mkComponent (defaultTopLevelBuildInfo <> topData)
-          , C.condTreeConstraints = topConstraints
-          , C.condTreeComponents = goComponents topComps
-          }
-      where
-        go :: DependencyTree C.BuildInfo -> DependencyTree a
-        go (C.CondNode ctData constraints comps) =
-            C.CondNode (mkComponent ctData) constraints (goComponents comps)
-
-        goComponents :: [DependencyComponent C.BuildInfo]
-                     -> [DependencyComponent a]
-        goComponents comps = [C.CondBranch cond (go t) (go <$> me) | C.CondBranch cond t me <- comps]
-
-    mkBuildInfoTree :: Dependencies -> DependencyTree C.BuildInfo
-    mkBuildInfoTree NotBuildable =
-      C.CondNode {
-             C.condTreeData        = mempty { C.buildable = False }
-           , C.condTreeConstraints = []
-           , C.condTreeComponents  = []
-           }
-    mkBuildInfoTree (Buildable deps) =
-      let (libraryDeps, exts, mlang, pcpkgs, buildTools, legacyBuildTools) = splitTopLevel deps
-          (directDeps, flaggedDeps) = splitDeps libraryDeps
-          bi = mempty {
-                  C.otherExtensions = exts
-                , C.defaultLanguage = mlang
-                , C.buildToolDepends = [ C.ExeDependency (C.mkPackageName p) (C.mkUnqualComponentName e) vr
-                                       | (p, e, vr) <- buildTools]
-                , C.buildTools = [ C.LegacyExeDependency n vr
-                                 | (n,vr) <- legacyBuildTools]
-                , C.pkgconfigDepends = [ C.PkgconfigDependency n' v'
-                                       | (n,v) <- pcpkgs
-                                       , let n' = C.mkPkgconfigName n
-                                       , let v' = C.thisVersion (mkSimpleVersion v) ]
-              }
-      in C.CondNode {
-             C.condTreeData        = bi -- Necessary for language extensions
-           -- TODO: Arguably, build-tools dependencies should also
-           -- effect constraints on conditional tree. But no way to
-           -- distinguish between them
-           , C.condTreeConstraints = map mkDirect directDeps
-           , C.condTreeComponents  = map mkFlagged flaggedDeps
-           }
-
-    mkDirect :: (ExamplePkgName, C.VersionRange) -> C.Dependency
-    mkDirect (dep, vr) = C.Dependency (C.mkPackageName dep) vr
-
-    mkFlagged :: (ExampleFlagName, Dependencies, Dependencies)
-              -> DependencyComponent C.BuildInfo
-    mkFlagged (f, a, b) =
-        C.CondBranch (C.Var (C.Flag (C.mkFlagName f)))
-                     (mkBuildInfoTree a)
-                     (Just (mkBuildInfoTree b))
-
-    -- Split a set of dependencies into direct dependencies and flagged
-    -- dependencies. A direct dependency is a tuple of the name of package and
-    -- its version range meant to be converted to a 'C.Dependency' with
-    -- 'mkDirect' for example. A flagged dependency is the set of dependencies
-    -- guarded by a flag.
-    splitDeps :: [ExampleDependency]
-              -> ( [(ExamplePkgName, C.VersionRange)]
-                 , [(ExampleFlagName, Dependencies, Dependencies)]
-                 )
-    splitDeps [] =
-      ([], [])
-    splitDeps (ExAny p:deps) =
-      let (directDeps, flaggedDeps) = splitDeps deps
-      in ((p, C.anyVersion):directDeps, flaggedDeps)
-    splitDeps (ExFix p v:deps) =
-      let (directDeps, flaggedDeps) = splitDeps deps
-      in ((p, C.thisVersion $ mkSimpleVersion v):directDeps, flaggedDeps)
-    splitDeps (ExRange p v1 v2:deps) =
-      let (directDeps, flaggedDeps) = splitDeps deps
-      in ((p, mkVersionRange v1 v2):directDeps, flaggedDeps)
-    splitDeps (ExFlagged f a b:deps) =
-      let (directDeps, flaggedDeps) = splitDeps deps
-      in (directDeps, (f, a, b):flaggedDeps)
-    splitDeps (dep:_) = error $ "Unexpected dependency: " ++ show dep
-
-    -- custom-setup only supports simple dependencies
-    mkSetupDeps :: [ExampleDependency] -> [C.Dependency]
-    mkSetupDeps deps =
-      let (directDeps, []) = splitDeps deps in map mkDirect directDeps
-
-mkSimpleVersion :: ExamplePkgVersion -> C.Version
-mkSimpleVersion n = C.mkVersion [n, 0, 0]
-
-mkVersionRange :: ExamplePkgVersion -> ExamplePkgVersion -> C.VersionRange
-mkVersionRange v1 v2 =
-    C.intersectVersionRanges (C.orLaterVersion $ mkSimpleVersion v1)
-                             (C.earlierVersion $ mkSimpleVersion v2)
-
-mkFlag :: ExFlag -> C.Flag
-mkFlag flag = C.MkFlag {
-    C.flagName        = C.mkFlagName $ exFlagName flag
-  , C.flagDescription = ""
-  , C.flagDefault     = exFlagDefault flag
-  , C.flagManual      =
-      case exFlagType flag of
-        Manual    -> True
-        Automatic -> False
-  }
-
-mkDefaultFlag :: ExampleFlagName -> C.Flag
-mkDefaultFlag flag = C.MkFlag {
-    C.flagName        = C.mkFlagName flag
-  , C.flagDescription = ""
-  , C.flagDefault     = True
-  , C.flagManual      = False
-  }
-
-exAvPkgId :: ExampleAvailable -> C.PackageIdentifier
-exAvPkgId ex = C.PackageIdentifier {
-      pkgName    = C.mkPackageName (exAvName ex)
-    , pkgVersion = C.mkVersion [exAvVersion ex, 0, 0]
-    }
-
-exInstInfo :: ExampleInstalled -> IPI.InstalledPackageInfo
-exInstInfo ex = IPI.emptyInstalledPackageInfo {
-      IPI.installedUnitId    = C.mkUnitId (exInstHash ex)
-    , IPI.sourcePackageId    = exInstPkgId ex
-    , IPI.depends            = map C.mkUnitId (exInstBuildAgainst ex)
-    }
-
-exInstPkgId :: ExampleInstalled -> C.PackageIdentifier
-exInstPkgId ex = C.PackageIdentifier {
-      pkgName    = C.mkPackageName (exInstName ex)
-    , pkgVersion = C.mkVersion [exInstVersion ex, 0, 0]
-    }
-
-exAvIdx :: [ExampleAvailable] -> CI.PackageIndex.PackageIndex UnresolvedSourcePackage
-exAvIdx = CI.PackageIndex.fromList . map exAvSrcPkg
-
-exInstIdx :: [ExampleInstalled] -> C.PackageIndex.InstalledPackageIndex
-exInstIdx = C.PackageIndex.fromList . map exInstInfo
-
-exResolve :: ExampleDb
-          -- List of extensions supported by the compiler, or Nothing if unknown.
-          -> Maybe [Extension]
-          -- List of languages supported by the compiler, or Nothing if unknown.
-          -> Maybe [Language]
-          -> PC.PkgConfigDb
-          -> [ExamplePkgName]
-          -> Maybe Int
-          -> CountConflicts
-          -> IndependentGoals
-          -> ReorderGoals
-          -> AllowBootLibInstalls
-          -> EnableBackjumping
-          -> SolveExecutables
-          -> Maybe (Variable P.QPN -> Variable P.QPN -> Ordering)
-          -> [ExConstraint]
-          -> [ExPreference]
-          -> EnableAllTests
-          -> Progress String String CI.SolverInstallPlan.SolverInstallPlan
-exResolve db exts langs pkgConfigDb targets mbj countConflicts indepGoals
-          reorder allowBootLibInstalls enableBj solveExes goalOrder constraints
-          prefs enableAllTests
-    = resolveDependencies C.buildPlatform compiler pkgConfigDb Modular params
-  where
-    defaultCompiler = C.unknownCompilerInfo C.buildCompilerId C.NoAbiTag
-    compiler = defaultCompiler { C.compilerInfoExtensions = exts
-                               , C.compilerInfoLanguages  = langs
-                               }
-    (inst, avai) = partitionEithers db
-    instIdx      = exInstIdx inst
-    avaiIdx      = SourcePackageDb {
-                       packageIndex       = exAvIdx avai
-                     , packagePreferences = Map.empty
-                     }
-    enableTests
-        | asBool enableAllTests = fmap (\p -> PackageConstraint
-                                              (scopeToplevel (C.mkPackageName p))
-                                              (PackagePropertyStanzas [TestStanzas]))
-                                       (exDbPkgs db)
-        | otherwise             = []
-    targets'     = fmap (\p -> NamedPackage (C.mkPackageName p) []) targets
-    params       =   addConstraints (fmap toConstraint constraints)
-                   $ addConstraints (fmap toLpc enableTests)
-                   $ addPreferences (fmap toPref prefs)
-                   $ setCountConflicts countConflicts
-                   $ setIndependentGoals indepGoals
-                   $ setReorderGoals reorder
-                   $ setMaxBackjumps mbj
-                   $ setAllowBootLibInstalls allowBootLibInstalls
-                   $ setEnableBackjumping enableBj
-                   $ setSolveExecutables solveExes
-                   $ setGoalOrder goalOrder
-                   $ standardInstallPolicy instIdx avaiIdx targets'
-    toLpc     pc = LabeledPackageConstraint pc ConstraintSourceUnknown
-
-    toConstraint (ExVersionConstraint scope v) =
-        toLpc $ PackageConstraint scope (PackagePropertyVersion v)
-    toConstraint (ExFlagConstraint scope fn b) =
-        toLpc $ PackageConstraint scope (PackagePropertyFlags (C.mkFlagAssignment [(C.mkFlagName fn, b)]))
-    toConstraint (ExStanzaConstraint scope stanzas) =
-        toLpc $ PackageConstraint scope (PackagePropertyStanzas stanzas)
-
-    toPref (ExPkgPref n v)          = PackageVersionPreference (C.mkPackageName n) v
-    toPref (ExStanzaPref n stanzas) = PackageStanzasPreference (C.mkPackageName n) stanzas
-
-extractInstallPlan :: CI.SolverInstallPlan.SolverInstallPlan
-                   -> [(ExamplePkgName, ExamplePkgVersion)]
-extractInstallPlan = catMaybes . map confPkg . CI.SolverInstallPlan.toList
-  where
-    confPkg :: CI.SolverInstallPlan.SolverPlanPackage -> Maybe (String, Int)
-    confPkg (CI.SolverInstallPlan.Configured pkg) = Just $ srcPkg pkg
-    confPkg _                               = Nothing
-
-    srcPkg :: SolverPackage UnresolvedPkgLoc -> (String, Int)
-    srcPkg cpkg =
-      let C.PackageIdentifier pn ver = packageInfoId (solverPkgSource cpkg)
-      in (C.unPackageName pn, head (C.versionNumbers ver))
-
-{-------------------------------------------------------------------------------
-  Auxiliary
--------------------------------------------------------------------------------}
-
--- | Run Progress computation
-runProgress :: Progress step e a -> ([step], Either e a)
-runProgress = go
-  where
-    go (Step s p) = let (ss, result) = go p in (s:ss, result)
-    go (Fail e)   = ([], Left e)
-    go (Done a)   = ([], Right a)
diff --git a/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs b/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs
--- a/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs
+++ b/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs
@@ -3,6 +3,7 @@
 module UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils (
     SolverTest
   , SolverResult(..)
+  , maxBackjumps
   , independentGoals
   , allowBootLibInstalls
   , disableBackjumping
@@ -10,6 +11,7 @@
   , goalOrder
   , constraints
   , preferences
+  , setVerbose
   , enableAllTests
   , solverSuccess
   , solverFailure
@@ -36,6 +38,7 @@
 import qualified Distribution.PackageDescription as C
 import qualified Distribution.Types.PackageName as C
 import Language.Haskell.Extension (Extension(..), Language(..))
+import Distribution.Verbosity
 
 -- cabal-install
 import qualified Distribution.Solver.Types.PackagePath as P
@@ -46,6 +49,9 @@
 import UnitTests.Distribution.Solver.Modular.DSL
 import UnitTests.Options
 
+maxBackjumps :: Maybe Int -> SolverTest -> SolverTest
+maxBackjumps mbj test = test { testMaxBackjumps = mbj }
+
 -- | Combinator to turn on --independent-goals behavior, i.e. solve
 -- for the goals as if we were solving for each goal independently.
 independentGoals :: SolverTest -> SolverTest
@@ -72,6 +78,11 @@
 preferences :: [ExPreference] -> SolverTest -> SolverTest
 preferences prefs test = test { testSoftConstraints = prefs }
 
+-- | Increase the solver's verbosity. This is necessary for test cases that
+-- check the contents of the verbose log.
+setVerbose :: SolverTest -> SolverTest
+setVerbose test = test { testVerbosity = verbose }
+
 enableAllTests :: SolverTest -> SolverTest
 enableAllTests test = test { testEnableAllTests = EnableAllTests True }
 
@@ -83,6 +94,7 @@
     testLabel                :: String
   , testTargets              :: [String]
   , testResult               :: SolverResult
+  , testMaxBackjumps         :: Maybe Int
   , testIndepGoals           :: IndependentGoals
   , testAllowBootLibInstalls :: AllowBootLibInstalls
   , testEnableBackjumping    :: EnableBackjumping
@@ -90,6 +102,7 @@
   , testGoalOrder            :: Maybe [ExampleVar]
   , testConstraints          :: [ExConstraint]
   , testSoftConstraints      :: [ExPreference]
+  , testVerbosity            :: Verbosity
   , testDb                   :: ExampleDb
   , testSupportedExts        :: Maybe [Extension]
   , testSupportedLangs       :: Maybe [Language]
@@ -175,6 +188,7 @@
     testLabel                = label
   , testTargets              = targets
   , testResult               = result
+  , testMaxBackjumps         = Nothing
   , testIndepGoals           = IndependentGoals False
   , testAllowBootLibInstalls = AllowBootLibInstalls False
   , testEnableBackjumping    = EnableBackjumping True
@@ -182,6 +196,7 @@
   , testGoalOrder            = Nothing
   , testConstraints          = []
   , testSoftConstraints      = []
+  , testVerbosity            = normal
   , testDb                   = db
   , testSupportedExts        = exts
   , testSupportedLangs       = langs
@@ -194,11 +209,11 @@
     testCase testLabel $ do
       let progress = exResolve testDb testSupportedExts
                      testSupportedLangs testPkgConfigDb testTargets
-                     Nothing (CountConflicts True) testIndepGoals
+                     testMaxBackjumps (CountConflicts True) testIndepGoals
                      (ReorderGoals False) testAllowBootLibInstalls
                      testEnableBackjumping testSolveExecutables
                      (sortGoals <$> testGoalOrder) testConstraints
-                     testSoftConstraints testEnableAllTests
+                     testSoftConstraints testVerbosity testEnableAllTests
           printMsg msg = when showSolverLog $ putStrLn msg
           msgs = foldProgress (:) (const []) (const []) progress
       assertBool ("Unexpected solver log:\n" ++ unlines msgs) $
diff --git a/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/MemoryUsage.hs b/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/MemoryUsage.hs
--- a/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/MemoryUsage.hs
+++ b/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/MemoryUsage.hs
@@ -11,6 +11,8 @@
       runTest $ basicTest "basic space leak test"
     , runTest $ flagsTest "package with many flags"
     , runTest $ issue2899 "issue #2899"
+    , runTest $ duplicateDependencies "duplicate dependencies"
+    , runTest $ duplicateFlaggedDependencies "duplicate flagged dependencies"
     ]
 
 -- | This test solves for n packages that each have two versions. There is no
@@ -49,17 +51,14 @@
 
     pkgs :: ExampleDb
     pkgs = [Right $ exAv "pkg" 1 $
-                [exFlagged (flagName n) [ExAny "unknown1"] [ExAny "unknown2"]]
+                [exFlagged (numberedFlag n) [ExAny "unknown1"] [ExAny "unknown2"]]
 
                 -- The remaining flags have no effect:
-             ++ [exFlagged (flagName i) [] [] | i <- [1..n - 1]]
+             ++ [exFlagged (numberedFlag i) [] [] | i <- [1..n - 1]]
            ]
 
-    flagName :: Int -> ExampleFlagName
-    flagName x = "flag-" ++ show x
-
     orderedFlags :: [ExampleVar]
-    orderedFlags = [F QualNone "pkg" (flagName i) | i <- [1..n]]
+    orderedFlags = [F QualNone "pkg" (numberedFlag i) | i <- [1..n]]
 
 -- | Test for a space leak caused by sharing of search trees under packages with
 -- link choices (issue #2899).
@@ -95,3 +94,98 @@
 
     goals :: [ExampleVar]
     goals = [P QualNone "setup-dep", P (QualSetup "target") "setup-dep"]
+
+-- | Test for an issue related to lifting dependencies out of conditionals when
+-- converting a PackageDescription to the solver's internal representation.
+--
+-- Issue:
+-- For each conditional and each package B, the solver combined each dependency
+-- on B in the true branch with each dependency on B in the false branch. It
+-- added the combined dependencies to the build-depends outside of the
+-- conditional. Since dependencies could be lifted out of multiple levels of
+-- conditionals, the number of new dependencies could grow exponentially in the
+-- number of levels. For example, the following package generated 4 copies of B
+-- under flag-2=False, 8 copies under flag-1=False, and 16 copies at the top
+-- level:
+--
+-- if flag(flag-1)
+--   build-depends: B, B
+-- else
+--   if flag(flag-2)
+--     build-depends: B, B
+--   else
+--     if flag(flag-3)
+--       build-depends: B, B
+--     else
+--       build-depends: B, B
+--
+-- This issue caused the quickcheck tests to start frequently running out of
+-- memory after an optimization that pruned unreachable branches (See PR #4929).
+-- Each problematic test case contained at least one build-depends field with
+-- duplicate dependencies, which was then duplicated under multiple levels of
+-- conditionals by the solver's "buildable: False" transformation, when
+-- "buildable: False" was under multiple flags. Finally, the branch pruning
+-- feature put all build-depends fields in consecutive levels of the condition
+-- tree, causing the solver's representation of the package to follow the
+-- pattern in the example above.
+--
+-- Now the solver avoids this issue by combining all dependencies on the same
+-- package before lifting them out of conditionals.
+--
+-- This test case is an expanded version of the example above, with library and
+-- build-tool dependencies.
+duplicateDependencies :: String -> SolverTest
+duplicateDependencies name =
+    mkTest pkgs name ["A"] $ solverSuccess [("A", 1), ("B", 1)]
+  where
+    copies, depth :: Int
+    copies = 50
+    depth = 50
+
+    pkgs :: ExampleDb
+    pkgs = [
+        Right $ exAv "A" 1 (dependencyTree 1)
+      , Right $ exAv "B" 1 [] `withExe` ExExe "exe" []
+      ]
+
+    dependencyTree :: Int -> [ExampleDependency]
+    dependencyTree n
+        | n > depth = buildDepends
+        | otherwise = [exFlagged (numberedFlag n) buildDepends
+                                                  (dependencyTree (n + 1))]
+      where
+        buildDepends = replicate copies (ExFix "B" 1)
+                    ++ replicate copies (ExBuildToolFix "B" "exe" 1)
+
+-- | This test is similar to duplicateDependencies, except that every dependency
+-- on B is replaced by a conditional that contains B in both branches. It tests
+-- that the solver doesn't just combine dependencies within one build-depends or
+-- build-tool-depends field; it also needs to combine dependencies after they
+-- are lifted out of conditionals.
+duplicateFlaggedDependencies :: String -> SolverTest
+duplicateFlaggedDependencies name =
+    mkTest pkgs name ["A"] $ solverSuccess [("A", 1), ("B", 1)]
+  where
+    copies, depth :: Int
+    copies = 15
+    depth = 15
+
+    pkgs :: ExampleDb
+    pkgs = [
+        Right $ exAv "A" 1 (dependencyTree 1)
+      , Right $ exAv "B" 1 [] `withExe` ExExe "exe" []
+      ]
+
+    dependencyTree :: Int -> [ExampleDependency]
+    dependencyTree n
+        | n > depth = flaggedDeps
+        | otherwise = [exFlagged (numberedFlag n) flaggedDeps
+                                                  (dependencyTree (n + 1))]
+      where
+        flaggedDeps = zipWith ($) (replicate copies flaggedDep) [0 :: Int ..]
+        flaggedDep m = exFlagged (numberedFlag n ++ "-" ++ show m) buildDepends
+                                                                   buildDepends
+        buildDepends = [ExFix "B" 1, ExBuildToolFix "B" "exe" 1]
+
+numberedFlag :: Int -> ExampleFlagName
+numberedFlag n = "flag-" ++ show n
diff --git a/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs b/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs
--- a/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs
+++ b/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs
@@ -39,9 +39,12 @@
                    (pkgConfigDbFromList)
 import           Distribution.Solver.Types.Settings
 import           Distribution.Solver.Types.Variable
+import           Distribution.Verbosity
 import           Distribution.Version
 
 import UnitTests.Distribution.Solver.Modular.DSL
+import UnitTests.Distribution.Solver.Modular.QuickCheck.Utils
+    ( testPropertyWithSeed )
 
 tests :: [TestTree]
 tests = [
@@ -49,7 +52,7 @@
       -- existence of a solution. It runs the solver twice, and only sets those
       -- parameters on the second run. The test also applies parameters that
       -- can affect the existence of a solution to both runs.
-      testProperty "target and goal order do not affect solvability" $
+      testPropertyWithSeed "target and goal order do not affect solvability" $
           \test targetOrder mGoalOrder1 mGoalOrder2 indepGoals ->
             let r1 = solve' mGoalOrder1 test
                 r2 = solve' mGoalOrder2 test { testTargets = targets2 }
@@ -65,7 +68,7 @@
                noneReachedBackjumpLimit [r1, r2] ==>
                isRight (resultPlan r1) === isRight (resultPlan r2)
 
-    , testProperty
+    , testPropertyWithSeed
           "solvable without --independent-goals => solvable with --independent-goals" $
           \test reorderGoals ->
             let r1 = solve' (IndependentGoals False) test
@@ -76,7 +79,7 @@
                 noneReachedBackjumpLimit [r1, r2] ==>
                 isRight (resultPlan r1) `implies` isRight (resultPlan r2)
 
-    , testProperty "backjumping does not affect solvability" $
+    , testPropertyWithSeed "backjumping does not affect solvability" $
           \test reorderGoals indepGoals ->
             let r1 = solve' (EnableBackjumping True)  test
                 r2 = solve' (EnableBackjumping False) test
@@ -93,7 +96,7 @@
     -- different solutions and cause the test to fail.
     -- TODO: Find a faster way to randomly sort goals, and then use a random
     -- goal order in this test.
-    , testProperty
+    , testPropertyWithSeed
           "backjumping does not affect the result (with static goal order)" $
           \test reorderGoals indepGoals ->
             let r1 = solve' (EnableBackjumping True)  test
@@ -142,7 +145,7 @@
                   (Just defaultMaxBackjumps)
                   countConflicts indep reorder (AllowBootLibInstalls False)
                   enableBj (SolveExecutables True) (unVarOrdering <$> goalOrder)
-                  (testConstraints test) (testPreferences test)
+                  (testConstraints test) (testPreferences test) normal
                   (EnableAllTests False)
 
       failure :: String -> Failure
@@ -223,8 +226,12 @@
         pkgs = nub $ map fst pkgVersions
     Positive n <- arbitrary
     targets <- randomSubset n pkgs
-    constraints <- boundedListOf 1 $ arbitraryConstraint pkgVersions
-    prefs <- boundedListOf 3 $ arbitraryPreference pkgVersions
+    constraints <- case pkgVersions of
+                     [] -> return []
+                     _  -> boundedListOf 1 $ arbitraryConstraint pkgVersions
+    prefs <- case pkgVersions of
+               [] -> return []
+               _  -> boundedListOf 3 $ arbitraryPreference pkgVersions
     return (SolverTest db targets constraints prefs)
 
   shrink test =
@@ -260,7 +267,7 @@
 
 arbitraryExAv :: PN -> PV -> TestDb -> Gen ExampleAvailable
 arbitraryExAv pn v db =
-    (\cds -> ExAv (unPN pn) (unPV v) cds []) <$> arbitraryComponentDeps db
+    (\cds -> ExAv (unPN pn) (unPV v) cds []) <$> arbitraryComponentDeps pn db
 
 arbitraryExInst :: PN -> PV -> [ExampleInstalled] -> Gen ExampleInstalled
 arbitraryExInst pn v pkgs = do
@@ -269,15 +276,23 @@
   deps <- randomSubset numDeps pkgs
   return $ ExInst (unPN pn) (unPV v) pkgHash (map exInstHash deps)
 
-arbitraryComponentDeps :: TestDb -> Gen (ComponentDeps [ExampleDependency])
-arbitraryComponentDeps (TestDb []) = return $ CD.fromList []
-arbitraryComponentDeps db =
-    -- dedupComponentNames removes components with duplicate names, for example,
-    -- 'ComponentExe x' and 'ComponentTest x', and then CD.fromList combines
-    -- duplicate unnamed components.
-    CD.fromList . dedupComponentNames <$>
-    boundedListOf 5 (arbitraryComponentDep db)
+arbitraryComponentDeps :: PN -> TestDb -> Gen (ComponentDeps [ExampleDependency])
+arbitraryComponentDeps _  (TestDb []) = return $ CD.fromLibraryDeps []
+arbitraryComponentDeps pn db          = do
+  -- dedupComponentNames removes components with duplicate names, for example,
+  -- 'ComponentExe x' and 'ComponentTest x', and then CD.fromList combines
+  -- duplicate unnamed components.
+  cds <- CD.fromList . dedupComponentNames . filter (isValid . fst)
+           <$> boundedListOf 5 (arbitraryComponentDep db)
+  return $ if isCompleteComponentDeps cds
+           then cds
+           else -- Add a library if the ComponentDeps isn't complete.
+                CD.fromLibraryDeps [] <> cds
   where
+    isValid :: Component -> Bool
+    isValid (ComponentSubLib name) = name /= mkUnqualComponentName (unPN pn)
+    isValid _                      = True
+
     dedupComponentNames =
         nubBy ((\x y -> isJust x && isJust y && x == y) `on` componentName . fst)
 
@@ -290,6 +305,19 @@
     componentName (ComponentTest   n) = Just n
     componentName (ComponentBench  n) = Just n
 
+-- | Returns true if the ComponentDeps forms a complete package, i.e., it
+-- contains a library, exe, test, or benchmark.
+isCompleteComponentDeps :: ComponentDeps a -> Bool
+isCompleteComponentDeps = any (completesPkg . fst) . CD.toList
+  where
+    completesPkg ComponentLib        = True
+    completesPkg (ComponentExe    _) = True
+    completesPkg (ComponentTest   _) = True
+    completesPkg (ComponentBench  _) = True
+    completesPkg (ComponentSubLib _) = False
+    completesPkg (ComponentFLib   _) = False
+    completesPkg ComponentSetup      = False
+
 arbitraryComponentDep :: TestDb -> Gen (ComponentDep [ExampleDependency])
 arbitraryComponentDep db = do
   comp <- arbitrary
@@ -371,7 +399,12 @@
   shrink (IndependentGoals indep) = [IndependentGoals False | indep]
 
 instance Arbitrary UnqualComponentName where
-  arbitrary = mkUnqualComponentName <$> (:[]) <$> elements "ABC"
+  -- The "component-" prefix prevents component names and build-depends
+  -- dependency names from overlapping.
+  -- TODO: Remove the prefix once the QuickCheck tests support dependencies on
+  -- internal libraries.
+  arbitrary =
+      mkUnqualComponentName <$> (\c -> "component-" ++ [c]) <$> elements "ABC"
 
 instance Arbitrary Component where
   arbitrary = oneof [ return ComponentLib
@@ -400,7 +433,7 @@
 instance (Arbitrary a, Monoid a) => Arbitrary (ComponentDeps a) where
   arbitrary = error "arbitrary not implemented: ComponentDeps"
 
-  shrink = map CD.fromList . shrink . CD.toList
+  shrink = filter isCompleteComponentDeps . map CD.fromList . shrink . CD.toList
 
 instance Arbitrary ExampleDependency where
   arbitrary = error "arbitrary not implemented: ExampleDependency"
diff --git a/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck/Utils.hs b/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck/Utils.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck/Utils.hs
@@ -0,0 +1,33 @@
+module UnitTests.Distribution.Solver.Modular.QuickCheck.Utils (
+    testPropertyWithSeed
+  ) where
+
+import Data.Tagged (Tagged, retag)
+import System.Random (getStdRandom, random)
+
+import Test.Tasty (TestTree)
+import Test.Tasty.Options (OptionDescription, lookupOption, setOption)
+import Test.Tasty.Providers (IsTest (..), singleTest)
+import Test.Tasty.QuickCheck
+    ( QC (..), QuickCheckReplay (..), Testable, property )
+
+import Distribution.Simple.Utils
+import Distribution.Verbosity
+
+-- | Create a QuickCheck test that prints the seed before testing the property.
+-- The seed can be useful for debugging non-terminating test cases. This is
+-- related to https://github.com/feuerbach/tasty/issues/86.
+testPropertyWithSeed :: Testable a => String -> a -> TestTree
+testPropertyWithSeed name = singleTest name . QCWithSeed . QC . property
+
+newtype QCWithSeed = QCWithSeed QC
+
+instance IsTest QCWithSeed where
+  testOptions = retag (testOptions :: Tagged QC [OptionDescription])
+
+  run options (QCWithSeed test) progress = do
+    replay <- case lookupOption options of
+                 QuickCheckReplay (Just override) -> return override
+                 QuickCheckReplay Nothing         -> getStdRandom random
+    notice normal $ "Using --quickcheck-replay=" ++ show replay
+    run (setOption (QuickCheckReplay (Just replay)) options) test progress
diff --git a/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs b/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs
--- a/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs
+++ b/cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs
@@ -43,6 +43,7 @@
         , runTest $         mkTest db21 "unknownPackage1"   ["A"]      (solverSuccess [("A", 1), ("B", 1)])
         , runTest $         mkTest db22 "unknownPackage2"   ["A"]      (solverFailure (isInfixOf "unknown package: C"))
         , runTest $         mkTest db23 "unknownPackage3"   ["A"]      (solverFailure (isInfixOf "unknown package: B"))
+        , runTest $         mkTest []   "unknown target"    ["A"]      (solverFailure (isInfixOf "unknown package: A"))
         ]
     , testGroup "Flagged dependencies" [
           runTest $         mkTest db3 "forceFlagOn"  ["C"]      (solverSuccess [("A", 1), ("B", 1), ("C", 1)])
@@ -51,13 +52,19 @@
         , runTest $ indep $ mkTest db4 "linkFlags2"   ["C", "D"] anySolverFailure
         , runTest $ indep $ mkTest db18 "linkFlags3"  ["A", "B"] (solverSuccess [("A", 1), ("B", 1), ("C", 1), ("D", 1), ("D", 2), ("F", 1)])
         ]
+    , testGroup "Lifting dependencies out of conditionals" [
+          runTest $ commonDependencyLogMessage "common dependency log message"
+        , runTest $ twoLevelDeepCommonDependencyLogMessage "two level deep common dependency log message"
+        , runTest $ testBackjumpingWithCommonDependency "backjumping with common dependency"
+        ]
     , testGroup "Manual flags" [
           runTest $ mkTest dbManualFlags "Use default value for manual flag" ["pkg"] $
           solverSuccess [("pkg", 1), ("true-dep", 1)]
 
         , let checkFullLog =
                   any $ isInfixOf "rejecting: pkg:-flag (manual flag can only be changed explicitly)"
-          in runTest $ constraints [ExVersionConstraint (ScopeAnyQualifier "true-dep") V.noVersion] $
+          in runTest $ setVerbose $
+             constraints [ExVersionConstraint (ScopeAnyQualifier "true-dep") V.noVersion] $
              mkTest dbManualFlags "Don't toggle manual flag to avoid conflict" ["pkg"] $
              -- TODO: We should check the summarized log instead of the full log
              -- for the manual flags error message, but it currently only
@@ -104,7 +111,7 @@
                   all (\msg -> any (msg `isInfixOf`) lns)
                   [ "rejecting: B:-flag "         ++ failureReason
                   , "rejecting: A:setup.B:+flag " ++ failureReason ]
-          in runTest $ constraints cs $
+          in runTest $ constraints cs $ setVerbose $
              mkTest dbLinkedSetupDepWithManualFlag name ["A"] $
              SolverResult checkFullLog (Left $ const True)
         ]
@@ -154,6 +161,7 @@
         , runTest $ mkTest db15 "cycleThroughSetupDep3" ["C"]      (solverSuccess [("C", 2), ("D", 1)])
         , runTest $ mkTest db15 "cycleThroughSetupDep4" ["D"]      (solverSuccess [("D", 1)])
         , runTest $ mkTest db15 "cycleThroughSetupDep5" ["E"]      (solverSuccess [("C", 2), ("D", 1), ("E", 1)])
+        , runTest $ issue4161 "detect cycle between package and its setup script"
         , runTest $ testCyclicDependencyErrorMessages "cyclic dependency error messages"
         ]
     , testGroup "Extensions" [
@@ -255,6 +263,23 @@
         , runTest $         mkTest dbBJ7  "bj7"  ["A"]      (solverSuccess [("A", 1), ("B",  1), ("C", 1)])
         , runTest $ indep $ mkTest dbBJ8  "bj8"  ["A", "B"] (solverSuccess [("A", 1), ("B",  1), ("C", 1)])
         ]
+    , testGroup "library dependencies" [
+          let db = [Right $ exAvNoLibrary "A" 1 `withExe` ExExe "exe" []]
+          in runTest $ mkTest db "install build target without a library" ["A"] $
+             solverSuccess [("A", 1)]
+
+        , let db = [ Right $ exAv "A" 1 [ExAny "B"]
+                   , Right $ exAvNoLibrary "B" 1 `withExe` ExExe "exe" [] ]
+          in runTest $ mkTest db "reject build-depends dependency with no library" ["A"] $
+             solverFailure (isInfixOf "rejecting: B-1.0.0 (does not contain library, which is required by A)")
+
+        , let exe = ExExe "exe" []
+              db = [ Right $ exAv "A" 1 [ExAny "B"]
+                   , Right $ exAvNoLibrary "B" 2 `withExe` exe
+                   , Right $ exAv "B" 1 [] `withExe` exe ]
+          in runTest $ mkTest db "choose version of build-depends dependency that has a library" ["A"] $
+             solverSuccess [("A", 1), ("B", 1)]
+        ]
     -- build-tool-depends dependencies
     , testGroup "build-tool-depends" [
           runTest $ mkTest dbBuildTools "simple exe dependency" ["A"] (solverSuccess [("A", 1), ("bt-pkg", 2)])
@@ -268,7 +293,7 @@
           mkTest dbBuildTools "test suite exe dependency" ["C"] (solverSuccess [("C", 1), ("bt-pkg", 2)])
 
         , runTest $ mkTest dbBuildTools "unknown exe" ["D"] $
-          solverFailure (isInfixOf "does not contain executable unknown-exe, which is required by D")
+          solverFailure (isInfixOf "does not contain executable 'unknown-exe', which is required by D")
 
         , runTest $ disableSolveExecutables $
           mkTest dbBuildTools "don't check for build tool executables in legacy mode" ["D"] $ solverSuccess [("D", 1)]
@@ -277,18 +302,18 @@
           solverFailure (isInfixOf "unknown package: E:unknown-pkg:exe.unknown-pkg (dependency of E)")
 
         , runTest $ mkTest dbBuildTools "unknown flagged exe" ["F"] $
-          solverFailure (isInfixOf "does not contain executable unknown-exe, which is required by F +flagF")
+          solverFailure (isInfixOf "does not contain executable 'unknown-exe', which is required by F +flagF")
 
         , runTest $ enableAllTests $ mkTest dbBuildTools "unknown test suite exe" ["G"] $
-          solverFailure (isInfixOf "does not contain executable unknown-exe, which is required by G *test")
+          solverFailure (isInfixOf "does not contain executable 'unknown-exe', which is required by G *test")
 
         , runTest $ mkTest dbBuildTools "wrong exe for build tool package version" ["H"] $
           solverFailure $ isInfixOf $
               -- The solver reports the version conflict when a version conflict
               -- and an executable conflict apply to the same package version.
-              "rejecting: H:bt-pkg:exe.bt-pkg-4.0.0 (conflict: H => H:bt-pkg:exe.bt-pkg (exe exe1)==3.0.0)\n"
-           ++ "rejecting: H:bt-pkg:exe.bt-pkg-3.0.0 (does not contain executable exe1, which is required by H)\n"
-           ++ "rejecting: H:bt-pkg:exe.bt-pkg-2.0.0, H:bt-pkg:exe.bt-pkg-1.0.0 (conflict: H => H:bt-pkg:exe.bt-pkg (exe exe1)==3.0.0)"
+              "[__1] rejecting: H:bt-pkg:exe.bt-pkg-4.0.0 (conflict: H => H:bt-pkg:exe.bt-pkg (exe exe1)==3.0.0)\n"
+           ++ "[__1] rejecting: H:bt-pkg:exe.bt-pkg-3.0.0 (does not contain executable 'exe1', which is required by H)\n"
+           ++ "[__1] rejecting: H:bt-pkg:exe.bt-pkg-2.0.0, H:bt-pkg:exe.bt-pkg-1.0.0 (conflict: H => H:bt-pkg:exe.bt-pkg (exe exe1)==3.0.0)"
 
         , runTest $ chooseExeAfterBuildToolsPackage True "choose exe after choosing its package - success"
 
@@ -306,7 +331,7 @@
           mkTest dbLegacyBuildTools1 "bt1 - don't install build tool packages in legacy mode" ["A"] (solverSuccess [("A", 1)])
 
         , runTest $ mkTest dbLegacyBuildTools2 "bt2" ["A"] $
-          solverFailure (isInfixOf "does not contain executable alex, which is required by A")
+          solverFailure (isInfixOf "does not contain executable 'alex', which is required by A")
 
         , runTest $ disableSolveExecutables $
           mkTest dbLegacyBuildTools2 "bt2 - don't check for build tool executables in legacy mode" ["A"] (solverSuccess [("A", 1)])
@@ -323,6 +348,48 @@
     , testGroup "internal dependencies" [
           runTest $ mkTest dbIssue3775 "issue #3775" ["B"] (solverSuccess [("A", 2), ("B", 2), ("warp", 1)])
         ]
+      -- tests for partial fix for issue #5325
+    , testGroup "Components that are unbuildable in the current environment" $
+      let flagConstraint = ExFlagConstraint . ScopeAnyQualifier
+      in [
+          let db = [ Right $ exAv "A" 1 [ExFlagged "build-lib" (Buildable []) NotBuildable] ]
+          in runTest $ constraints [flagConstraint "A" "build-lib" False] $
+             mkTest db "install unbuildable library" ["A"] $
+             solverSuccess [("A", 1)]
+
+        , let db = [ Right $ exAvNoLibrary "A" 1
+                       `withExe` ExExe "exe" [ExFlagged "build-exe" (Buildable []) NotBuildable] ]
+          in runTest $ constraints [flagConstraint "A" "build-exe" False] $
+             mkTest db "install unbuildable exe" ["A"] $
+             solverSuccess [("A", 1)]
+
+        , let db = [ Right $ exAv "A" 1 [ExAny "B"]
+                   , Right $ exAv "B" 1 [ExFlagged "build-lib" (Buildable []) NotBuildable] ]
+          in runTest $ constraints [flagConstraint "B" "build-lib" False] $
+             mkTest db "reject library dependency with unbuildable library" ["A"] $
+             solverFailure $ isInfixOf $
+                   "rejecting: B-1.0.0 (library is not buildable in the "
+                ++ "current environment, but it is required by A)"
+
+        , let db = [ Right $ exAv "A" 1 [ExBuildToolAny "B" "bt"]
+                   , Right $ exAv "B" 1 [ExFlagged "build-lib" (Buildable []) NotBuildable]
+                       `withExe` ExExe "bt" [] ]
+          in runTest $ constraints [flagConstraint "B" "build-lib" False] $
+             mkTest db "allow build-tool dependency with unbuildable library" ["A"] $
+             solverSuccess [("A", 1), ("B", 1)]
+
+        , let db = [ Right $ exAv "A" 1 [ExBuildToolAny "B" "bt"]
+                   , Right $ exAv "B" 1 []
+                       `withExe` ExExe "bt" [ExFlagged "build-exe" (Buildable []) NotBuildable] ]
+          in runTest $ constraints [flagConstraint "B" "build-exe" False] $
+             mkTest db "reject build-tool dependency with unbuildable exe" ["A"] $
+             solverFailure $ isInfixOf $
+                   "rejecting: A:B:exe.B-1.0.0 (executable 'bt' is not "
+                ++ "buildable in the current environment, but it is required by A)"
+        , runTest $
+          chooseUnbuildableExeAfterBuildToolsPackage
+          "choose unbuildable exe after choosing its package"
+        ]
       -- Tests for the contents of the solver's log
     , testGroup "Solver log" [
           -- See issue #3203. The solver should only choose a version for A once.
@@ -332,7 +399,7 @@
                   p :: [String] -> Bool
                   p lg =    elem "targets: A" lg
                          && length (filter ("trying: A" `isInfixOf`) lg) == 1
-              in mkTest db "deduplicate targets" ["A", "A"] $
+              in setVerbose $ mkTest db "deduplicate targets" ["A", "A"] $
                  SolverResult p $ Right [("A", 1)]
         , runTest $
               let db = [Right $ exAv "A" 1 [ExAny "B"]]
@@ -340,6 +407,26 @@
                      ++ "these were the goals I've had most trouble fulfilling: A, B"
               in mkTest db "exhaustive search failure message" ["A"] $
                  solverFailure (isInfixOf msg)
+        , testSummarizedLog "show conflicts from final conflict set after exhaustive search" Nothing $
+                "Could not resolve dependencies:\n"
+             ++ "[__0] trying: A-1.0.0 (user goal)\n"
+             ++ "[__1] unknown package: D (dependency of A)\n"
+             ++ "[__1] fail (backjumping, conflict set: A, D)\n"
+             ++ "After searching the rest of the dependency tree exhaustively, "
+             ++ "these were the goals I've had most trouble fulfilling: A, D"
+        , testSummarizedLog "show first conflicts after inexhaustive search" (Just 3) $
+                "Could not resolve dependencies:\n"
+             ++ "[__0] trying: A-1.0.0 (user goal)\n"
+             ++ "[__1] trying: B-3.0.0 (dependency of A)\n"
+             ++ "[__2] next goal: C (dependency of B)\n"
+             ++ "[__2] rejecting: C-1.0.0 (conflict: B => C==3.0.0)\n"
+             ++ "[__2] fail (backjumping, conflict set: B, C)\n"
+             ++ "Backjump limit reached (currently 3, change with --max-backjumps "
+             ++ "or try to run with --reorder-goals).\n"
+        , testSummarizedLog "don't show summarized log when backjump limit is too low" (Just 1) $
+                "Backjump limit reached (currently 1, change with --max-backjumps "
+             ++ "or try to run with --reorder-goals).\n"
+             ++ "Failed to generate a summarized dependency solver log due to low backjump limit."
         ]
     ]
   where
@@ -778,6 +865,30 @@
   , Right $ exAv   "E" 1            [ExFix "C" 2]
   ]
 
+-- | Detect a cycle between a package and its setup script.
+--
+-- This type of cycle can easily occur when new-build adds default setup
+-- dependencies to packages without custom-setup stanzas. For example, cabal
+-- adds 'time' as a setup dependency for 'time'. The solver should detect the
+-- cycle when it attempts to link the setup and non-setup instances of the
+-- package and then choose a different version for the setup dependency.
+issue4161 :: String -> SolverTest
+issue4161 name =
+    setVerbose $ mkTest db name ["target"] $
+    SolverResult checkFullLog $ Right [("target", 1), ("time", 1), ("time", 2)]
+  where
+    db :: ExampleDb
+    db = [
+        Right $ exAv "target" 1 [ExFix "time" 2]
+      , Right $ exAv "time"   2 []               `withSetupDeps` [ExAny "time"]
+      , Right $ exAv "time"   1 []
+      ]
+
+    checkFullLog :: [String] -> Bool
+    checkFullLog = any $ isInfixOf $
+        "rejecting: time:setup.time~>time-2.0.0 (cyclic dependencies; "
+                ++ "conflict set: time:setup.time)"
+
 -- | Packages pkg-A, pkg-B, and pkg-C form a cycle. The solver should backtrack
 -- as soon as it chooses the last package in the cycle, to avoid searching parts
 -- of the tree that have no solution. Since there is no way to break the cycle,
@@ -911,6 +1022,61 @@
   , Right $ exAv "G" 1 []
   ]
 
+-- | When both values for flagA introduce package B, the solver should be able
+-- to choose B before choosing a value for flagA. It should try to choose a
+-- version for B that is in the union of the version ranges required by +flagA
+-- and -flagA.
+commonDependencyLogMessage :: String -> SolverTest
+commonDependencyLogMessage name =
+    mkTest db name ["A"] $ solverFailure $ isInfixOf $
+        "[__0] trying: A-1.0.0 (user goal)\n"
+     ++ "[__1] next goal: B (dependency of A +/-flagA)\n"
+     ++ "[__1] rejecting: B-2.0.0 (conflict: A +/-flagA => B==1.0.0 || ==3.0.0)"
+  where
+    db :: ExampleDb
+    db = [
+        Right $ exAv "A" 1 [exFlagged "flagA"
+                               [ExFix "B" 1]
+                               [ExFix "B" 3]]
+      , Right $ exAv "B" 2 []
+      ]
+
+-- | Test lifting dependencies out of multiple levels of conditionals.
+twoLevelDeepCommonDependencyLogMessage :: String -> SolverTest
+twoLevelDeepCommonDependencyLogMessage name =
+    mkTest db name ["A"] $ solverFailure $ isInfixOf $
+        "unknown package: B (dependency of A +/-flagA +/-flagB)"
+  where
+    db :: ExampleDb
+    db = [
+        Right $ exAv "A" 1 [exFlagged "flagA"
+                               [exFlagged "flagB"
+                                   [ExAny "B"]
+                                   [ExAny "B"]]
+                               [exFlagged "flagB"
+                                   [ExAny "B"]
+                                   [ExAny "B"]]]
+      ]
+
+-- | Test handling nested conditionals that are controlled by the same flag.
+-- The solver should treat flagA as introducing 'unknown' with value true, not
+-- both true and false. That means that when +flagA causes a conflict, the
+-- solver should try flipping flagA to false to resolve the conflict, rather
+-- than backjumping past flagA.
+testBackjumpingWithCommonDependency :: String -> SolverTest
+testBackjumpingWithCommonDependency name =
+    mkTest db name ["A"] $ solverSuccess [("A", 1), ("B", 1)]
+  where
+    db :: ExampleDb
+    db = [
+        Right $ exAv "A" 1 [exFlagged "flagA"
+                               [exFlagged "flagA"
+                                   [ExAny "unknown"]
+                                   [ExAny "unknown"]]
+                               [ExAny "B"]]
+      , Right $ exAv "B" 1 []
+      ]
+
 -- | Tricky test case with independent goals (issue #2842)
 --
 -- Suppose we are installing D, E, and F as independent goals:
@@ -1197,6 +1363,29 @@
   , Right $ exAv "C" 1 [ExAny "B"]
   ]
 
+-- | Test for the solver's summarized log. The final conflict set is {A, D},
+-- though the goal order forces the solver to find the (avoidable) conflict
+-- between B >= 2 and C first. When the solver reaches the backjump limit, it
+-- should only show the log to the first conflict. When the backjump limit is
+-- high enough to allow an exhaustive search, the solver should make use of the
+-- final conflict set to only show the conflict between A and D in the
+-- summarized log.
+testSummarizedLog :: String -> Maybe Int -> String -> TestTree
+testSummarizedLog testName mbj expectedMsg =
+    runTest $ maxBackjumps mbj $ goalOrder goals $ mkTest db testName ["A"] $
+    solverFailure (== expectedMsg)
+  where
+    db = [
+        Right $ exAv "A" 1 [ExAny "B", ExAny "D"]
+      , Right $ exAv "B" 3 [ExFix "C" 3]
+      , Right $ exAv "B" 2 [ExFix "C" 2]
+      , Right $ exAv "B" 1 [ExAny "C"]
+      , Right $ exAv "C" 1 []
+      ]
+
+    goals :: [ExampleVar]
+    goals = [P QualNone pkg | pkg <- ["A", "B", "C", "D"]]
+
 {-------------------------------------------------------------------------------
   Simple databases for the illustrations for the backjumping blog post
 -------------------------------------------------------------------------------}
@@ -1323,7 +1512,7 @@
 rejectInstalledBuildToolPackage name =
     mkTest db name ["A"] $ solverFailure $ isInfixOf $
     "rejecting: A:B:exe.B-1.0.0/installed-1 "
-     ++ "(does not contain executable exe, which is required by A)"
+     ++ "(does not contain executable 'exe', which is required by A)"
   where
     db :: ExampleDb
     db = [
@@ -1347,8 +1536,8 @@
       if shouldSucceed
       then solverSuccess [("A", 1), ("B", 1)]
       else solverFailure $ isInfixOf $
-           "rejecting: A:+flagA (requires executable exe2 from A:B:exe.B, "
-            ++ "but the executable does not exist)"
+           "rejecting: A:+flagA (requires executable 'exe2' from A:B:exe.B, "
+            ++ "but the component does not exist)"
   where
     db :: ExampleDb
     db = [
@@ -1364,7 +1553,7 @@
     goals = [
         P QualNone "A"
       , P (QualExe "A" "B") "B"
-      , F QualNone "A" "flag"
+      , F QualNone "A" "flagA"
       ]
 
 -- | Test that when one package depends on two executables from another package,
@@ -1374,8 +1563,8 @@
 requireConsistentBuildToolVersions :: String -> SolverTest
 requireConsistentBuildToolVersions name =
     mkTest db name ["A"] $ solverFailure $ isInfixOf $
-        "rejecting: A:B:exe.B-2.0.0 (conflict: A => A:B:exe.B (exe exe1)==1.0.0)\n"
-     ++ "rejecting: A:B:exe.B-1.0.0 (conflict: A => A:B:exe.B (exe exe2)==2.0.0)"
+        "[__1] rejecting: A:B:exe.B-2.0.0 (conflict: A => A:B:exe.B (exe exe1)==1.0.0)\n"
+     ++ "[__1] rejecting: A:B:exe.B-1.0.0 (conflict: A => A:B:exe.B (exe exe2)==2.0.0)"
   where
     db :: ExampleDb
     db = [
@@ -1386,6 +1575,36 @@
       ]
 
     exes = [ExExe "exe1" [], ExExe "exe2" []]
+
+-- | This test is similar to the failure case for
+-- chooseExeAfterBuildToolsPackage, except that the build tool is unbuildable
+-- instead of missing.
+chooseUnbuildableExeAfterBuildToolsPackage :: String -> SolverTest
+chooseUnbuildableExeAfterBuildToolsPackage name =
+    constraints [ExFlagConstraint (ScopeAnyQualifier "B") "build-bt2" False] $
+    goalOrder goals $
+    mkTest db name ["A"] $ solverFailure $ isInfixOf $
+         "rejecting: A:+use-bt2 (requires executable 'bt2' from A:B:exe.B, but "
+          ++ "the component is not buildable in the current environment)"
+  where
+    db :: ExampleDb
+    db = [
+        Right $ exAv "A" 1 [ ExBuildToolAny "B" "bt1"
+                           , exFlagged "use-bt2" [ExBuildToolAny "B" "bt2"]
+                                                 [ExAny "unknown"]]
+      , Right $ exAvNoLibrary "B" 1
+         `withExes`
+           [ ExExe "bt1" []
+           , ExExe "bt2" [ExFlagged "build-bt2" (Buildable []) NotBuildable]
+           ]
+      ]
+
+    goals :: [ExampleVar]
+    goals = [
+        P QualNone "A"
+      , P (QualExe "A" "B") "B"
+      , F QualNone "A" "use-bt2"
+      ]
 
 {-------------------------------------------------------------------------------
   Databases for legacy build-tools
diff --git a/cabal/cabal-install/tests/UnitTests/Options.hs b/cabal/cabal-install/tests/UnitTests/Options.hs
--- a/cabal/cabal-install/tests/UnitTests/Options.hs
+++ b/cabal/cabal-install/tests/UnitTests/Options.hs
@@ -2,6 +2,7 @@
 
 module UnitTests.Options ( OptionShowSolverLog(..)
                          , OptionMtimeChangeDelay(..)
+                         , RunNetworkTests(..)
                          , extraOptions )
        where
 
@@ -18,6 +19,7 @@
 extraOptions =
   [ Option (Proxy :: Proxy OptionShowSolverLog)
   , Option (Proxy :: Proxy OptionMtimeChangeDelay)
+  , Option (Proxy :: Proxy RunNetworkTests)
   ]
 
 newtype OptionShowSolverLog = OptionShowSolverLog Bool
@@ -25,7 +27,7 @@
 
 instance IsOption OptionShowSolverLog where
   defaultValue   = OptionShowSolverLog False
-  parseValue     = fmap OptionShowSolverLog . safeRead
+  parseValue     = fmap OptionShowSolverLog . safeReadBool
   optionName     = return "show-solver-log"
   optionHelp     = return "Show full log from the solver"
   optionCLParser = flagCLParser Nothing (OptionShowSolverLog True)
@@ -39,3 +41,12 @@
   optionName     = return "mtime-change-delay"
   optionHelp     = return $ "How long to wait before attempting to detect"
                    ++ "file modification, in microseconds"
+
+newtype RunNetworkTests = RunNetworkTests Bool
+  deriving Typeable
+
+instance IsOption RunNetworkTests where
+  defaultValue = RunNetworkTests True
+  parseValue   = fmap RunNetworkTests . safeReadBool
+  optionName   = return "run-network-tests"
+  optionHelp   = return "Run tests that need network access (default true)."
diff --git a/cabal/cabal-install/tests/UnitTests/TempTestDir.hs b/cabal/cabal-install/tests/UnitTests/TempTestDir.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-install/tests/UnitTests/TempTestDir.hs
@@ -0,0 +1,104 @@
+{-# LANGUAGE CPP #-}
+
+module UnitTests.TempTestDir (
+    withTestDir, removeDirectoryRecursiveHack
+  ) where
+
+import Distribution.Verbosity
+import Distribution.Compat.Internal.TempFile (createTempDirectory)
+import Distribution.Simple.Utils (warn)
+
+import Control.Monad (when)
+import Control.Exception (bracket, try, throwIO)
+import Control.Concurrent (threadDelay)
+
+import System.IO.Error
+import System.Directory
+#if !(MIN_VERSION_directory(1,2,7))
+import System.FilePath ((</>))
+#endif
+import qualified System.Info (os)
+
+
+-- | Much like 'withTemporaryDirectory' but with a number of hacks to make
+-- sure on windows that we can clean up the directory at the end.
+--
+withTestDir :: Verbosity -> String ->  (FilePath -> IO a) -> IO a
+withTestDir verbosity template action = do
+    systmpdir <- getTemporaryDirectory
+    bracket
+      (createTempDirectory systmpdir template)
+      (removeDirectoryRecursiveHack verbosity)
+      action
+
+
+-- | On Windows, file locks held by programs we run (in this case VCSs)
+-- are not always released prior to completing process termination!
+-- <https://msdn.microsoft.com/en-us/library/windows/desktop/aa365202.aspx>
+-- This means we run into stale locks when trying to delete the test
+-- directory. There is no sane way to wait on those locks being released,
+-- we just have to wait, try again and hope.
+--
+-- In addition, on Windows a file that is not writable also cannot be deleted,
+-- so we must try setting the permissions to readable before deleting files.
+-- Some VCS tools on Windows create files with read-only attributes.
+--
+removeDirectoryRecursiveHack :: Verbosity -> FilePath -> IO ()
+removeDirectoryRecursiveHack verbosity dir | isWindows = go 1
+  where
+    isWindows = System.Info.os == "mingw32"
+    limit     = 3
+
+    go :: Int -> IO ()
+    go n = do
+      res <- try $ removePathForcibly dir
+      case res of
+        Left e
+            -- wait a second and try again
+          | isPermissionError e  &&  n < limit -> do
+              threadDelay 1000000
+              go (n+1)
+
+            -- but if we hit the limt warn and fail.
+          | isPermissionError e -> do
+              warn verbosity $ "Windows file locking hack: hit the retry limit "
+                            ++ show limit ++ " while trying to remove " ++ dir
+              throwIO e
+
+            -- or it's a different error fail.
+          | otherwise -> throwIO e
+
+        Right () ->
+          when (n > 1) $
+            warn verbosity $ "Windows file locking hack: had to try "
+                          ++ show n ++ " times to remove " ++ dir
+
+removeDirectoryRecursiveHack _ dir = removeDirectoryRecursive dir
+
+
+#if !(MIN_VERSION_directory(1,2,7))
+-- A simplified version that ought to work for our use case here, and does
+-- not rely on directory internals.
+removePathForcibly :: FilePath -> IO ()
+removePathForcibly path = do
+    makeRemovable path `catchIOError` \ _ -> pure ()
+    isDir <- doesDirectoryExist path
+    if isDir
+       then do
+         entries <- getDirectoryContents path
+         sequence_
+           [ removePathForcibly (path </> entry)
+           | entry <- entries, entry /= ".", entry /= ".." ]
+         removeDirectory path
+       else
+         removeFile path
+  where
+    makeRemovable :: FilePath -> IO ()
+    makeRemovable p =
+      setPermissions p emptyPermissions {
+        readable   = True,
+        searchable = True,
+        writable   = True
+      }
+#endif
+
diff --git a/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/Setup.hs b/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/Setup.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/Setup.hs
@@ -0,0 +1,6 @@
+module Main (main) where
+
+import Distribution.Simple
+
+main :: IO ()
+main = defaultMainWithHooks autoconfUserHooks
diff --git a/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/cabal.out b/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/cabal.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/cabal.out
@@ -0,0 +1,82 @@
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo bar/configure', contains the character ' ' (space). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo	bar/configure', contains the character '	' (tab). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo
+bar/configure', contains the character '
+' (newline). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo"bar/configure', contains the character '"' (double quote). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo#bar/configure', contains the character '#' (hash). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo$bar/configure', contains the character '$' (dollar sign). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo&bar/configure', contains the character '&' (ampersand). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo'bar/configure', contains the character ''' (single quote). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo(bar/configure', contains the character '(' (left bracket). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo)bar/configure', contains the character ')' (right bracket). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo*bar/configure', contains the character '*' (star). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo;bar/configure', contains the character ';' (semicolon). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo<bar/configure', contains the character '<' (less-than sign). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo=bar/configure', contains the character '=' (equals sign). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo>bar/configure', contains the character '>' (greater-than sign). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo?bar/configure', contains the character '?' (question mark). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo[bar/configure', contains the character '[' (left square bracket). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo/bar/configure', contains the character '/' (backslash). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo`bar/configure', contains the character '`' (backtick). This may cause the script to fail with an obscure error, or for building the package to fail later.
+# cabal v1-configure
+Resolving dependencies...
+Configuring test-0...
+Warning: The path to the './configure' script, '/<ROOT>/cabal.dist/foo|bar/configure', contains the character '|' (pipe). This may cause the script to fail with an obscure error, or for building the package to fail later.
diff --git a/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/cabal.test.hs
@@ -0,0 +1,53 @@
+import Test.Cabal.Prelude
+import Data.Foldable (traverse_)
+main = cabalTest $ do
+  -- Test the forbidden characters except NUL. Reference:
+  -- https://www.gnu.org/software/autoconf/manual/autoconf.html#File-System-Conventions
+  -- Most of these are magic on Windows, so don't bother testing there.
+  --
+  -- Note: we bundle the configure script so no need to autoreconf
+  -- while building
+  skipIf =<< isWindows
+  traverse_ check
+    [ "foo bar"
+    , "foo\tbar"
+    , "foo\nbar"
+    , "foo\"bar"
+    , "foo#bar"
+    , "foo$bar"
+    , "foo&bar"
+    , "foo'bar"
+    , "foo(bar"
+    , "foo)bar"
+    , "foo*bar"
+    , "foo;bar"
+    , "foo<bar"
+    , "foo=bar"
+    , "foo>bar"
+    , "foo?bar"
+    , "foo[bar"
+    , "foo\\bar"
+    , "foo`bar"
+    , "foo|bar"
+    ]
+  where
+    -- 'cabal' from the prelude requires the command to succeed; we
+    -- don't mind if it fails, so long as we get the warning. This is
+    -- an inlined+specialised version of 'cabal' for v1-configure.
+    check dir = withSourceCopyDir dir $
+      defaultRecordMode RecordMarked $ do
+        recordHeader ["cabal", "v1-configure"]
+        env <- getTestEnv
+        let args =
+              [ "v1-configure"
+              , "-vverbose +markoutput +nowrap"
+              , "--builddir"
+              , testDistDir env
+              ]
+        configured_prog <- requireProgramM cabalProgram
+        r <- liftIO $ run (testVerbosity env)
+                      (Just (testCurrentDir env))
+                      (testEnvironment env)
+                      (programPath configured_prog)
+                      args
+        recordLog r
diff --git a/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/configure b/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/configure
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/configure
@@ -0,0 +1,2406 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for Test for autoconf brokenness 0.
+#
+# Report bugs to <none@example.com>.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org and none@example.com
+$0: about your system, including any error possibly output
+$0: before this message. Then install a modern shell, or
+$0: manually run the script under such a shell if you do
+$0: have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='Test for autoconf brokenness'
+PACKAGE_TARNAME='test'
+PACKAGE_VERSION='0'
+PACKAGE_STRING='Test for autoconf brokenness 0'
+PACKAGE_BUGREPORT='none@example.com'
+PACKAGE_URL=''
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir runstatedir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures Test for autoconf brokenness 0 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/test]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of Test for autoconf brokenness 0:";;
+   esac
+  cat <<\_ACEOF
+
+Report bugs to <none@example.com>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+Test for autoconf brokenness configure 0
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by Test for autoconf brokenness $as_me 0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+	g
+	s/^\n//
+	s/\n/ /g
+	p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by Test for autoconf brokenness $as_me 0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+
+Report bugs to <none@example.com>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+Test for autoconf brokenness config.status 0
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --he | --h |  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/configure.ac b/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/configure.ac
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/configure.ac
@@ -0,0 +1,3 @@
+AC_INIT([Test for autoconf brokenness], [0], [none@example.com], [test])
+
+AC_OUTPUT
diff --git a/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/test.cabal b/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/test.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/test.cabal
@@ -0,0 +1,8 @@
+cabal-version: 2.2
+name: test
+version: 0
+build-type: Configure
+
+executable foo
+  main-is: Main.hs
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/my.cabal b/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/my.cabal
--- a/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/my.cabal
+++ b/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/my.cabal
@@ -7,7 +7,7 @@
 synopsis: AutogenModules
 category: PackageTests
 build-type: Simple
-cabal-version: >= 1.25
+cabal-version: 1.25
 
 description:
     Check that Cabal recognizes the autogen-modules fields below.
diff --git a/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.cabal.out b/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.cabal.out
--- a/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.cabal.out
@@ -14,7 +14,7 @@
 On executable 'Exe' an 'autogen-module' is not on 'other-modules'
 On test suite 'Test' an 'autogen-module' is not on 'other-modules'
 On benchmark 'Bench' an 'autogen-module' is not on 'other-modules'
-Packages using 'cabal-version: >= 1.25' and the autogenerated module Paths_* must include it also on the 'autogen-modules' field besides 'exposed-modules' and 'other-modules'. This specifies that the module does not come with the package and is generated on setup. Modules built with a custom Setup.hs script also go here to ensure that commands like sdist don't fail.
+Packages using 'cabal-version: 2.0' and the autogenerated module Paths_* must include it also on the 'autogen-modules' field besides 'exposed-modules' and 'other-modules'. This specifies that the module does not come with the package and is generated on setup. Modules built with a custom Setup.hs script also go here to ensure that commands like sdist don't fail.
 The filename ./my.cabal does not match package name (expected: AutogenModules.cabal)
 Note: the public hackage server would reject this package.
 Warning: Cannot run preprocessors. Run 'configure' command first.
diff --git a/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.out b/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.out
--- a/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.out
+++ b/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.out
@@ -13,7 +13,7 @@
 On executable 'Exe' an 'autogen-module' is not on 'other-modules'
 On test suite 'Test' an 'autogen-module' is not on 'other-modules'
 On benchmark 'Bench' an 'autogen-module' is not on 'other-modules'
-Packages using 'cabal-version: >= 1.25' and the autogenerated module Paths_* must include it also on the 'autogen-modules' field besides 'exposed-modules' and 'other-modules'. This specifies that the module does not come with the package and is generated on setup. Modules built with a custom Setup.hs script also go here to ensure that commands like sdist don't fail.
+Packages using 'cabal-version: 2.0' and the autogenerated module Paths_* must include it also on the 'autogen-modules' field besides 'exposed-modules' and 'other-modules'. This specifies that the module does not come with the package and is generated on setup. Modules built with a custom Setup.hs script also go here to ensure that commands like sdist don't fail.
 The filename ./my.cabal does not match package name (expected: AutogenModules.cabal)
 Note: the public hackage server would reject this package.
 Warning: Cannot run preprocessors. Run 'configure' command first.
diff --git a/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.test.hs b/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.test.hs
--- a/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.test.hs
@@ -20,7 +20,7 @@
                    "On benchmark 'Bench' an 'autogen-module' is not on "
                 ++ "'other-modules'"
         let pathsAutogenMsg =
-                "Packages using 'cabal-version: >= 1.25' and the autogenerated"
+                "Packages using 'cabal-version: 2.0' and the autogenerated"
 
         -- Asserts for the desired check messages after configure.
         assertOutputContains libAutogenMsg   configureResult
diff --git a/cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/AutogenModules.cabal b/cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/AutogenModules.cabal
--- a/cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/AutogenModules.cabal
+++ b/cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/AutogenModules.cabal
@@ -7,7 +7,7 @@
 synopsis: AutogenModules
 category: PackageTests
 build-type: Simple
-cabal-version: >= 1.24
+cabal-version: 1.24
 
 description:
     Check that Cabal recognizes the autogen-modules fields below.
diff --git a/cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/setup.test.hs b/cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/setup.test.hs
--- a/cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/setup.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/setup.test.hs
@@ -51,7 +51,7 @@
                    "On benchmark 'Bench' an 'autogen-module' is not on "
                 ++ "'other-modules'"
         let pathsAutogenMsg =
-                "Packages using 'cabal-version: >= 1.25' and the autogenerated"
+                "Packages using 'cabal-version: 2.0' and the autogenerated"
 
         -- Asserts for the undesired check messages after configure.
         assertOutputDoesNotContain libAutogenMsg   configureResult
diff --git a/cabal/cabal-testsuite/PackageTests/Backpack/Includes1/setup.test.hs b/cabal/cabal-testsuite/PackageTests/Backpack/Includes1/setup.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Backpack/Includes1/setup.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Backpack/Includes1/setup.test.hs
@@ -5,4 +5,4 @@
     r <- fails $ setup' "build" []
     assertRegex "error should be in B.hs" "^B.hs:" r
     assertRegex "error should be \"Could not find module Data.Set\""
-                "(Could not find module|Failed to load interface).*Data.Set" r
+                "(Could not (load|find) module|Failed to load interface).*Data.Set" r
diff --git a/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/setup-external.cabal.out b/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/setup-external.cabal.out
--- a/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/setup-external.cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/Backpack/Includes2/setup-external.cabal.out
@@ -99,10 +99,10 @@
 Resolving dependencies...
 Warning: solver failed to find a solution:
 Could not resolve dependencies:
-trying: exe-0.1.0.0 (user goal)
-next goal: src (dependency of exe)
-rejecting: src-<VERSION>/installed-<HASH>... (conflict: src => mylib==0.1.0.0/installed-0.1..., src => mylib==0.1.0.0/installed-0.1...)
-fail (backjumping, conflict set: exe, src)
+[__0] trying: exe-0.1.0.0 (user goal)
+[__1] next goal: src (dependency of exe)
+[__1] rejecting: src-<VERSION>/installed-<HASH>... (conflict: src => mylib==0.1.0.0/installed-0.1..., src => mylib==0.1.0.0/installed-0.1...)
+[__1] fail (backjumping, conflict set: exe, src)
 After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: exe (2), src (2)
 Trying configure anyway.
 Configuring exe-0.1.0.0...
diff --git a/cabal/cabal-testsuite/PackageTests/Backpack/Includes3/Includes3.cabal b/cabal/cabal-testsuite/PackageTests/Backpack/Includes3/Includes3.cabal
--- a/cabal/cabal-testsuite/PackageTests/Backpack/Includes3/Includes3.cabal
+++ b/cabal/cabal-testsuite/PackageTests/Backpack/Includes3/Includes3.cabal
@@ -4,7 +4,7 @@
 author:              Edward Z. Yang
 maintainer:          ezyang@cs.stanford.edu
 build-type:          Simple
-cabal-version:       >=1.25
+cabal-version:       1.25
 
 library sigs
   build-depends:       base
diff --git a/cabal/cabal-testsuite/PackageTests/Backpack/Includes5/setup.test.hs b/cabal/cabal-testsuite/PackageTests/Backpack/Includes5/setup.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Backpack/Includes5/setup.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Backpack/Includes5/setup.test.hs
@@ -4,5 +4,8 @@
     setup "configure" []
     r <- fails $ setup' "build" []
     assertOutputContains "Foobar" r
-    assertOutputContains "Could not find" r
+    assertRegex
+      "error should be about not being able to find a module"
+      "Could not (find|load) module"
+      r
     return ()
diff --git a/cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps1/setup.test.hs b/cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps1/setup.test.hs
--- a/cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps1/setup.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps1/setup.test.hs
@@ -8,4 +8,4 @@
     assertRegex "error should be in MyLibrary.hs" "^MyLibrary.hs:" r
     assertRegex
       "error should be \"Could not find module `Text\\.PrettyPrint\""
-      "(Could not find module|Failed to load interface for).*Text\\.PrettyPrint" r
+      "(Could not (load|find) module|Failed to load interface for).*Text\\.PrettyPrint" r
diff --git a/cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps3/setup.test.hs b/cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps3/setup.test.hs
--- a/cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps3/setup.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps3/setup.test.hs
@@ -8,4 +8,4 @@
     assertRegex "error should be in lemon.hs" "^lemon.hs:" r
     assertRegex
       "error should be \"Could not find module `Text\\.PrettyPrint\""
-      "(Could not find module|Failed to load interface for).*Text\\.PrettyPrint" r
+      "(Could not (load|find) module|Failed to load interface for).*Text\\.PrettyPrint" r
diff --git a/cabal/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackage/use-local-version-of-package.out b/cabal/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackage/use-local-version-of-package.out
--- a/cabal/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackage/use-local-version-of-package.out
+++ b/cabal/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackage/use-local-version-of-package.out
@@ -1,4 +1,4 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
 # cabal new-build
 Resolving dependencies...
@@ -13,7 +13,8 @@
 # cabal new-build
 Resolving dependencies...
 cabal: Could not resolve dependencies:
-next goal: pkg (user goal)
-rejecting: pkg-2.0 (constraint from user target requires ==1.0)
-rejecting: pkg-1.0 (constraint from command line flag requires ==2.0)
+[__0] next goal: pkg (user goal)
+[__0] rejecting: pkg-2.0 (constraint from user target requires ==1.0)
+[__0] rejecting: pkg-1.0 (constraint from command line flag requires ==2.0)
+[__0] fail (backjumping, conflict set: pkg)
 After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: pkg (3)
diff --git a/cabal/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackageForSetup/use-local-package-as-setup-dep.out b/cabal/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackageForSetup/use-local-package-as-setup-dep.out
--- a/cabal/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackageForSetup/use-local-package-as-setup-dep.out
+++ b/cabal/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackageForSetup/use-local-package-as-setup-dep.out
@@ -1,13 +1,13 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
 # cabal new-build
 Resolving dependencies...
 cabal: Could not resolve dependencies:
-trying: pkg-1.0 (user goal)
-next goal: setup-dep (user goal)
-rejecting: setup-dep-2.0 (conflict: pkg => setup-dep==1.*)
-rejecting: setup-dep-1.0 (constraint from user target requires ==2.0)
-fail (backjumping, conflict set: pkg, setup-dep)
+[__0] trying: pkg-1.0 (user goal)
+[__1] next goal: setup-dep (user goal)
+[__1] rejecting: setup-dep-2.0 (conflict: pkg => setup-dep==1.*)
+[__1] rejecting: setup-dep-1.0 (constraint from user target requires ==2.0)
+[__1] fail (backjumping, conflict set: pkg, setup-dep)
 After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: setup-dep (3), pkg (2)
 # pkg my-exe
 Main.hs: setup-dep from repo
diff --git a/cabal/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackageForSetup/use-local-package-as-setup-dep.test.hs b/cabal/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackageForSetup/use-local-package-as-setup-dep.test.hs
--- a/cabal/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackageForSetup/use-local-package-as-setup-dep.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/BuildTargets/UseLocalPackageForSetup/use-local-package-as-setup-dep.test.hs
@@ -10,16 +10,17 @@
 -- qualifier as pkg, even though they are both build targets of the project.
 -- The solution must use --independent-goals to give pkg and setup-dep different
 -- qualifiers.
-main = cabalTest $ do
-  skipUnless =<< hasNewBuildCompatBootCabal
-  withRepo "repo" $ do
-    fails $ cabal "new-build" ["pkg:my-exe", "--dry-run"]
-    -- Disabled recording because whether or not we get
-    -- detailed information for the build of my-exe depends
-    -- on whether or not the Cabal library version is recent
-    -- enough
-    r1 <- recordMode DoNotRecord $ cabal' "new-build" ["pkg:my-exe", "--independent-goals"]
-    assertOutputContains "Setup.hs: setup-dep from project" r1
-    withPlan $ do
-      r2 <- runPlanExe' "pkg" "my-exe" []
-      assertOutputContains "Main.hs: setup-dep from repo" r2
+main = withShorterPathForNewBuildStore $ \storeDir ->
+  cabalTest $ do
+    skipUnless =<< hasNewBuildCompatBootCabal
+    withRepo "repo" $ do
+      fails $ cabalG ["--store-dir=" ++ storeDir] "new-build" ["pkg:my-exe", "--dry-run"]
+      -- Disabled recording because whether or not we get
+      -- detailed information for the build of my-exe depends
+      -- on whether or not the Cabal library version is recent
+      -- enough
+      r1 <- recordMode DoNotRecord $ cabalG' ["--store-dir=" ++ storeDir] "new-build" ["pkg:my-exe", "--independent-goals"]
+      assertOutputContains "Setup.hs: setup-dep from project" r1
+      withPlan $ do
+        r2 <- runPlanExe' "pkg" "my-exe" []
+        assertOutputContains "Main.hs: setup-dep from repo" r2
diff --git a/cabal/cabal-testsuite/PackageTests/COnlyMain/my.cabal b/cabal/cabal-testsuite/PackageTests/COnlyMain/my.cabal
--- a/cabal/cabal-testsuite/PackageTests/COnlyMain/my.cabal
+++ b/cabal/cabal-testsuite/PackageTests/COnlyMain/my.cabal
@@ -1,7 +1,7 @@
+cabal-version:  2.1
 name:           my
 version:        0.1
-license:        BSD3
-cabal-version:  >= 2.1
+license:        BSD-3-Clause
 build-type:     Simple
 
 executable foo
diff --git a/cabal/cabal-testsuite/PackageTests/Check/InvalidGlob/cabal.out b/cabal/cabal-testsuite/PackageTests/Check/InvalidGlob/cabal.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/InvalidGlob/cabal.out
@@ -0,0 +1,5 @@
+# cabal check
+Warning: The following errors will cause portability problems on other environments:
+Warning: No 'synopsis' or 'description' field.
+Warning: In the 'extra-doc-files' field: invalid file glob '***.html'. Wildcards '*' may only totally replace the file's base name, not only parts of it.
+Warning: Hackage would reject this package.
diff --git a/cabal/cabal-testsuite/PackageTests/Check/InvalidGlob/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/Check/InvalidGlob/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/InvalidGlob/cabal.test.hs
@@ -0,0 +1,3 @@
+import Test.Cabal.Prelude
+main = cabalTest $
+  fails $ cabal "check" []
diff --git a/cabal/cabal-testsuite/PackageTests/Check/InvalidGlob/pkg.cabal b/cabal/cabal-testsuite/PackageTests/Check/InvalidGlob/pkg.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/InvalidGlob/pkg.cabal
@@ -0,0 +1,13 @@
+cabal-version: 2.2
+name: pkg
+version: 0
+extra-doc-files:
+  ***.html
+category: example
+maintainer: none@example.com
+license: BSD-3-Clause
+
+library
+  exposed-modules: Foo
+  default-language: Haskell2010
+  
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/Foo.hs b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/Foo.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/Foo.hs
@@ -0,0 +1,1 @@
+foo = True
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/cabal.out b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/cabal.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/cabal.out
@@ -0,0 +1,6 @@
+# cabal check
+Warning: These warnings may cause trouble when distributing the package:
+Warning: In 'data-files': the pattern 'another-non-existent-directory/**/*.dat' attempts to match files in the directory 'another-non-existent-directory', but there is no directory by that name.
+Warning: In 'extra-doc-files': the pattern 'non-existent-directory/*.html' attempts to match files in the directory 'non-existent-directory', but there is no directory by that name.
+Warning: In 'extra-doc-files': the pattern 'present/present/missing/*.tex' attempts to match files in the directory 'present/present/missing', but there is no directory by that name.
+Warning: In 'extra-source-files': the pattern 'file-not-a-directory/*.js' attempts to match files in the directory 'file-not-a-directory', but there is no directory by that name.
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/cabal.test.hs
@@ -0,0 +1,3 @@
+import Test.Cabal.Prelude
+main = cabalTest $
+       cabal "check" []
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/data/hello.dat b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/data/hello.dat
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/data/hello.dat
@@ -0,0 +1,1 @@
+hello.dat
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/file-not-a-directory b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/file-not-a-directory
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/file-not-a-directory
@@ -0,0 +1,1 @@
+This is not a directory.
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/pkg.cabal b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/pkg.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/pkg.cabal
@@ -0,0 +1,21 @@
+cabal-version: 2.4
+name: pkg
+version: 0
+extra-doc-files:
+  non-existent-directory/*.html
+  present/present/missing/*.tex
+extra-source-files:
+  file-not-a-directory/*.js
+data-dir:
+  data
+data-files:
+  another-non-existent-directory/**/*.dat
+category: example
+maintainer: none@example.com
+synopsis: synopsis
+description: description
+license: BSD-3-Clause
+
+library
+  exposed-modules: Foo
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/present/present/hello b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/present/present/hello
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory/present/present/hello
@@ -0,0 +1,1 @@
+This file only exists so that Git will create its two parent directories.
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/Foo.hs b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/Foo.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/Foo.hs
@@ -0,0 +1,1 @@
+foo = True
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/cabal.out b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/cabal.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/cabal.out
@@ -0,0 +1,5 @@
+# cabal check
+Warning: These warnings may cause trouble when distributing the package:
+Warning: In 'data-files': the pattern 'non-existent-directory/*.dat' attempts to match files in the directory 'non-existent-directory', but there is no directory by that name.
+Warning: In 'extra-source-files': the pattern 'dir/*.html' does not match any files.
+Warning: In 'extra-source-files': the pattern 'dir/*.html' does not match the file 'dir/foo.en.html' because the extensions do not exactly match (e.g., foo.en.html does not exactly match *.html). To enable looser suffix-only matching, set 'cabal-version: 2.4' or higher.
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/cabal.test.hs
@@ -0,0 +1,2 @@
+import Test.Cabal.Prelude
+main = cabalTest $ cabal "check" []
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/dir/foo.en.html b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/dir/foo.en.html
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/dir/foo.en.html
@@ -0,0 +1,1 @@
+foo.en.html
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/pkg.cabal b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/pkg.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MissingGlobDirectory2/pkg.cabal
@@ -0,0 +1,16 @@
+cabal-version: 2.2
+name: pkg
+version: 0
+data-files:
+  non-existent-directory/*.dat
+extra-source-files:
+  dir/*.html
+category: example
+maintainer: none@example.com
+synopsis: synopsis
+description: description
+license: BSD-3-Clause
+
+library
+  exposed-modules: Foo
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/check.out b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/check.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/check.out
@@ -0,0 +1,5 @@
+# cabal check
+Warning: These warnings may cause trouble when distributing the package:
+Warning: In 'data-files': the pattern 'data/*.dat' does not match the file 'data/foo.bar.dat' because the extensions do not exactly match (e.g., foo.en.html does not exactly match *.html). To enable looser suffix-only matching, set 'cabal-version: 2.4' or higher.
+Warning: In 'extra-doc-files': the pattern 'doc/*.html' does not match the file 'doc/foo.en.html' because the extensions do not exactly match (e.g., foo.en.html does not exactly match *.html). To enable looser suffix-only matching, set 'cabal-version: 2.4' or higher.
+Warning: In 'extra-doc-files': the pattern 'doc/*.html' does not match the file 'doc/foo.fr.html' because the extensions do not exactly match (e.g., foo.en.html does not exactly match *.html). To enable looser suffix-only matching, set 'cabal-version: 2.4' or higher.
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/check.test.hs b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/check.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/check.test.hs
@@ -0,0 +1,4 @@
+import Test.Cabal.Prelude
+
+main = cabalTest $
+  cabal "check" []
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/data/foo.bar.dat b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/data/foo.bar.dat
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/data/foo.bar.dat
@@ -0,0 +1,1 @@
+foo.bar.dat
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/data/index.dat b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/data/index.dat
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/data/index.dat
@@ -0,0 +1,1 @@
+index.dat
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/.foo.html b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/.foo.html
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/.foo.html
@@ -0,0 +1,1 @@
+.foo.html
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/bar.html b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/bar.html
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/bar.html
@@ -0,0 +1,1 @@
+bar.html
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/foo.en.html b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/foo.en.html
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/foo.en.html
@@ -0,0 +1,1 @@
+foo.en.html
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/foo.fr.html b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/foo.fr.html
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/foo.fr.html
@@ -0,0 +1,1 @@
+foo.fr.html
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/index.html b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/index.html
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/doc/index.html
@@ -0,0 +1,1 @@
+index.html
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/src/foo.cobol b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/src/foo.cobol
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/src/foo.cobol
@@ -0,0 +1,1 @@
+foo.cobol
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/src/index.js b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/src/index.js
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/src/index.js
@@ -0,0 +1,1 @@
+index.js
diff --git a/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/test.cabal b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/test.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/MultiDotGlob2.2/test.cabal
@@ -0,0 +1,19 @@
+cabal-version: 2.2
+name: test
+version: 0
+license: BSD-3-Clause
+synopsis: foo
+description: foobar
+category: example
+maintainer: none@example.com
+extra-doc-files:
+  doc/*.html
+extra-source-files:
+  -- Include a glob that doesn't match anything, to make sure that the code in Check.hs won't call 'die' because of it.
+  src/*.js
+data-files:
+  data/*.dat
+
+executable foo
+  main-is: Main.hs
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/Check/NoGlobMatches/cabal.out b/cabal/cabal-testsuite/PackageTests/Check/NoGlobMatches/cabal.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/NoGlobMatches/cabal.out
@@ -0,0 +1,3 @@
+# cabal check
+Warning: These warnings may cause trouble when distributing the package:
+Warning: In 'extra-doc-files': the pattern '*.html' does not match any files.
diff --git a/cabal/cabal-testsuite/PackageTests/Check/NoGlobMatches/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/Check/NoGlobMatches/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/NoGlobMatches/cabal.test.hs
@@ -0,0 +1,2 @@
+import Test.Cabal.Prelude
+main = cabalTest $ cabal "check" []
diff --git a/cabal/cabal-testsuite/PackageTests/Check/NoGlobMatches/pkg.cabal b/cabal/cabal-testsuite/PackageTests/Check/NoGlobMatches/pkg.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Check/NoGlobMatches/pkg.cabal
@@ -0,0 +1,14 @@
+cabal-version: 2.2
+name: pkg
+version: 0
+extra-doc-files:
+  *.html
+category: example
+maintainer: none@example.com
+synopsis: synopsis
+description: description
+license: BSD-3-Clause
+
+library
+  exposed-modules: Foo
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/Configure/setup.test.hs b/cabal/cabal-testsuite/PackageTests/Configure/setup.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Configure/setup.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Configure/setup.test.hs
@@ -1,8 +1,10 @@
 import Test.Cabal.Prelude
+import Control.Monad.IO.Class
+import Data.Maybe
+import System.Directory
 -- Test for 'build-type: Configure' example from the setup manual.
--- Disabled on Windows since MingW doesn't ship with autoreconf by
--- default.
 main = setupAndCabalTest $ do
-    skipIf =<< isWindows
+    hasAutoreconf <- liftIO $ fmap isJust $ findExecutable "autoreconf"
+    skipUnless hasAutoreconf
     _ <- shell "autoreconf" ["-i"]
     setup_build []
diff --git a/cabal/cabal-testsuite/PackageTests/ConfigureComponent/Exe/setup.cabal.out b/cabal/cabal-testsuite/PackageTests/ConfigureComponent/Exe/setup.cabal.out
--- a/cabal/cabal-testsuite/PackageTests/ConfigureComponent/Exe/setup.cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/ConfigureComponent/Exe/setup.cabal.out
@@ -2,9 +2,9 @@
 Resolving dependencies...
 Warning: solver failed to find a solution:
 Could not resolve dependencies:
-trying: Exe-0.1.0.0 (user goal)
-unknown package: totally-impossible-dependency-to-fill (dependency of Exe)
-fail (backjumping, conflict set: Exe, totally-impossible-dependency-to-fill)
+[__0] trying: Exe-0.1.0.0 (user goal)
+[__1] unknown package: totally-impossible-dependency-to-fill (dependency of Exe)
+[__1] fail (backjumping, conflict set: Exe, totally-impossible-dependency-to-fill)
 After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: Exe (2), totally-impossible-dependency-to-fill (1)
 Trying configure anyway.
 Configuring executable 'goodexe' for Exe-0.1.0.0..
diff --git a/cabal/cabal-testsuite/PackageTests/CustomDep/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/CustomDep/cabal.test.hs
--- a/cabal/cabal-testsuite/PackageTests/CustomDep/cabal.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/CustomDep/cabal.test.hs
@@ -2,9 +2,11 @@
 main = cabalTest $ do
     -- NB: This variant seems to use the bootstrapped Cabal?
     skipUnless =<< hasCabalForGhc
+    -- implicit setup-depends conflict with GHC >= 8.2; c.f. #415
+    skipIf =<< (ghcVersionIs (>= mkVersion [8,2]))
     -- This test depends heavily on what packages are in the global
     -- database, don't record the output
     recordMode DoNotRecord $ do
         -- TODO: Hack, delete me
-        withEnvFilter (/= "HOME") $ do
+        withEnvFilter (`notElem` ["HOME", "CABAL_DIR"]) $ do
             cabal "new-build" ["all"]
diff --git a/cabal/cabal-testsuite/PackageTests/CustomDep/custom/custom.cabal b/cabal/cabal-testsuite/PackageTests/CustomDep/custom/custom.cabal
--- a/cabal/cabal-testsuite/PackageTests/CustomDep/custom/custom.cabal
+++ b/cabal/cabal-testsuite/PackageTests/CustomDep/custom/custom.cabal
@@ -10,3 +10,6 @@
   exposed-modules:     A
   build-depends:       base
   default-language:    Haskell2010
+
+custom-setup
+  setup-depends: base, Cabal
diff --git a/cabal/cabal-testsuite/PackageTests/CustomDep/sandbox.out b/cabal/cabal-testsuite/PackageTests/CustomDep/sandbox.out
--- a/cabal/cabal-testsuite/PackageTests/CustomDep/sandbox.out
+++ b/cabal/cabal-testsuite/PackageTests/CustomDep/sandbox.out
@@ -1,5 +1,5 @@
-# cabal sandbox init
+# cabal v1-sandbox init
 Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config
 Creating a new sandbox at <ROOT>/sandbox.dist/sandbox
-# cabal sandbox add-source
-# cabal sandbox add-source
+# cabal v1-sandbox add-source
+# cabal v1-sandbox add-source
diff --git a/cabal/cabal-testsuite/PackageTests/CustomDep/sandbox.test.hs b/cabal/cabal-testsuite/PackageTests/CustomDep/sandbox.test.hs
--- a/cabal/cabal-testsuite/PackageTests/CustomDep/sandbox.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/CustomDep/sandbox.test.hs
@@ -1,11 +1,17 @@
 import Test.Cabal.Prelude
 main = cabalTest $ do
     osx <- isOSX
+    win <- isWindows
     -- On Travis OSX, Cabal shipped with GHC 7.8 does not work
     -- with error "setup: /usr/bin/ar: permission denied"; see
     -- also https://github.com/haskell/cabal/issues/3938
     -- This is a hack to make the test not run in this case.
     when osx $ skipUnless =<< ghcVersionIs (>= mkVersion [7,10])
+    -- On Appveyor, for some reason this test fails sometimes
+    -- due to missing symbols in Cabal 1.24. The solution is to
+    -- use a newer version of GHC that bundles a newer version
+    -- of Cabal, but for now, we skip.
+    when win $ skipUnless =<< ghcVersionIs (>= mkVersion [8,2])
     withSandbox $ do
         cabal_sandbox "add-source" ["custom"]
         cabal_sandbox "add-source" ["client"]
@@ -13,4 +19,4 @@
         -- built against GHC's bundled Cabal.  This means that the
         -- output we see may vary between tests, so we don't record this.
         recordMode DoNotRecord $
-            cabal "install" ["client"]
+            cabal "v1-install" ["client"]
diff --git a/cabal/cabal-testsuite/PackageTests/CustomPlain/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/CustomPlain/cabal.test.hs
--- a/cabal/cabal-testsuite/PackageTests/CustomPlain/cabal.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/CustomPlain/cabal.test.hs
@@ -1,9 +1,11 @@
 import Test.Cabal.Prelude
 main = cabalTest $ do
+    -- implicit setup-depends conflict with GHC >= 8.2; c.f. #415
+    skipIf =<< (ghcVersionIs (>= mkVersion [8,2]))
     -- Regression test for #4393
     recordMode DoNotRecord $ do
         -- TODO: Hack; see also CustomDep/cabal.test.hs
-        withEnvFilter (/= "HOME") $ do
+        withEnvFilter (`notElem` ["HOME", "CABAL_DIR"]) $ do
             -- On -v2, we don't have vQuiet set, which suppressed
             -- the error
             cabal "new-build" ["-v1"]
diff --git a/cabal/cabal-testsuite/PackageTests/CustomPlain/plain.cabal b/cabal/cabal-testsuite/PackageTests/CustomPlain/plain.cabal
--- a/cabal/cabal-testsuite/PackageTests/CustomPlain/plain.cabal
+++ b/cabal/cabal-testsuite/PackageTests/CustomPlain/plain.cabal
@@ -3,7 +3,6 @@
 license:             BSD3
 author:              Edward Z. Yang
 maintainer:          ezyang@cs.stanford.edu
-build-type:          Custom
 cabal-version:       >=1.10
 
 library
diff --git a/cabal/cabal-testsuite/PackageTests/CustomPlain/setup.cabal.out b/cabal/cabal-testsuite/PackageTests/CustomPlain/setup.cabal.out
--- a/cabal/cabal-testsuite/PackageTests/CustomPlain/setup.cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/CustomPlain/setup.cabal.out
@@ -1,6 +1,7 @@
 # Setup configure
 Resolving dependencies...
 Configuring plain-0.1.0.0...
+Warning: No 'build-type' specified. If you do not need a custom Setup.hs or ./configure script then use 'build-type: Simple'.
 # Setup build
 Preprocessing library for plain-0.1.0.0..
 Building library for plain-0.1.0.0..
diff --git a/cabal/cabal-testsuite/PackageTests/CustomPlain/setup.out b/cabal/cabal-testsuite/PackageTests/CustomPlain/setup.out
--- a/cabal/cabal-testsuite/PackageTests/CustomPlain/setup.out
+++ b/cabal/cabal-testsuite/PackageTests/CustomPlain/setup.out
@@ -1,5 +1,6 @@
 # Setup configure
 Configuring plain-0.1.0.0...
+Warning: No 'build-type' specified. If you do not need a custom Setup.hs or ./configure script then use 'build-type: Simple'.
 # Setup build
 Preprocessing library for plain-0.1.0.0..
 Building library for plain-0.1.0.0..
diff --git a/cabal/cabal-testsuite/PackageTests/CustomWithoutCabalDefaultMain/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/CustomWithoutCabalDefaultMain/cabal.test.hs
--- a/cabal/cabal-testsuite/PackageTests/CustomWithoutCabalDefaultMain/cabal.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/CustomWithoutCabalDefaultMain/cabal.test.hs
@@ -5,7 +5,7 @@
     -- Compilation should fail because Setup.hs imports Distribution.Simple.
     r <- fails $ cabal' "new-build" ["custom-setup-without-cabal-defaultMain"]
     assertRegex "Should not have been able to import Cabal"
-                "(Could not find module|Failed to load interface for).*Distribution\\.Simple" r
+                "(Could not find module|Could not load module|Failed to load interface for).*Distribution\\.Simple" r
     {-
     -- TODO: With GHC 8.2, this no longer is displayed
     -- When using --with-ghc, this message is not necessarily output
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/T4049/sandbox.out b/cabal/cabal-testsuite/PackageTests/Exec/T4049/sandbox.out
--- a/cabal/cabal-testsuite/PackageTests/Exec/T4049/sandbox.out
+++ b/cabal/cabal-testsuite/PackageTests/Exec/T4049/sandbox.out
@@ -1,12 +1,12 @@
-# cabal sandbox init
+# cabal v1-sandbox init
 Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config
 Creating a new sandbox at <ROOT>/sandbox.dist/sandbox
-# cabal install
+# cabal v1-install
 Resolving dependencies...
 Configuring my-foreign-lib-0.1.0.0...
 Preprocessing foreign library 'myforeignlib' for my-foreign-lib-0.1.0.0..
 Building foreign library 'myforeignlib' for my-foreign-lib-0.1.0.0..
 Installing foreign library myforeignlib in <PATH>
-Installed my-foreign-lib-0.1.0.0
-# cabal exec
+Completed    my-foreign-lib-0.1.0.0
+# cabal v1-exec
 Hi from a foreign library! Foo has value 5678
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/T4049/sandbox.test.hs b/cabal/cabal-testsuite/PackageTests/Exec/T4049/sandbox.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Exec/T4049/sandbox.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Exec/T4049/sandbox.test.hs
@@ -2,7 +2,7 @@
 main = cabalTest $ do
     skipUnless =<< ghcVersionIs (>= mkVersion [7,8])
     withSandbox $ do
-        cabal "install" ["--enable-shared"]
+        cabal "v1-install" ["--enable-shared"]
         env <- getTestEnv
         is_windows <- isWindows
         let sandbox_dir = testSandboxDir env
@@ -17,4 +17,4 @@
             , "-l" ++ "myforeignlib"
             , "-L" ++ lib_dir ]
         recordMode RecordAll $
-            cabal "exec" ["-v0", work_dir </> "UseLib"]
+            cabal "v1-exec" ["-v0", work_dir </> "UseLib"]
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/legacy-autoconfigure.out b/cabal/cabal-testsuite/PackageTests/Exec/legacy-autoconfigure.out
--- a/cabal/cabal-testsuite/PackageTests/Exec/legacy-autoconfigure.out
+++ b/cabal/cabal-testsuite/PackageTests/Exec/legacy-autoconfigure.out
@@ -1,1 +1,1 @@
-# cabal exec
+# cabal v1-exec
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/legacy-autoconfigure.test.hs b/cabal/cabal-testsuite/PackageTests/Exec/legacy-autoconfigure.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Exec/legacy-autoconfigure.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Exec/legacy-autoconfigure.test.hs
@@ -1,4 +1,4 @@
 import Test.Cabal.Prelude
 main = cabalTest $ do
-    cabal' "exec" ["echo", "find_me_in_output"]
+    cabal' "v1-exec" ["echo", "find_me_in_output"]
         >>= assertOutputContains "find_me_in_output"
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/legacy-no-args.out b/cabal/cabal-testsuite/PackageTests/Exec/legacy-no-args.out
--- a/cabal/cabal-testsuite/PackageTests/Exec/legacy-no-args.out
+++ b/cabal/cabal-testsuite/PackageTests/Exec/legacy-no-args.out
@@ -1,2 +1,2 @@
-# cabal exec
+# cabal v1-exec
 cabal: Please specify an executable to run
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/legacy-no-args.test.hs b/cabal/cabal-testsuite/PackageTests/Exec/legacy-no-args.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Exec/legacy-no-args.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Exec/legacy-no-args.test.hs
@@ -1,2 +1,2 @@
 import Test.Cabal.Prelude
-main = cabalTest $ fails (cabal' "exec" []) >>= assertOutputContains "Please specify an executable to run"
+main = cabalTest $ fails (cabal' "v1-exec" []) >>= assertOutputContains "Please specify an executable to run"
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/legacy.out b/cabal/cabal-testsuite/PackageTests/Exec/legacy.out
--- a/cabal/cabal-testsuite/PackageTests/Exec/legacy.out
+++ b/cabal/cabal-testsuite/PackageTests/Exec/legacy.out
@@ -1,4 +1,4 @@
-# cabal configure
+# cabal v1-configure
 Resolving dependencies...
 Configuring my-0.1...
-# cabal exec
+# cabal v1-exec
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/legacy.test.hs b/cabal/cabal-testsuite/PackageTests/Exec/legacy.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Exec/legacy.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Exec/legacy.test.hs
@@ -1,5 +1,5 @@
 import Test.Cabal.Prelude
 main = cabalTest $ do
-    cabal "configure" []
-    cabal' "exec" ["echo", "find_me_in_output"]
+    cabal "v1-configure" []
+    cabal' "v1-exec" ["echo", "find_me_in_output"]
         >>= assertOutputContains "find_me_in_output"
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/sandbox-ghc-pkg.out b/cabal/cabal-testsuite/PackageTests/Exec/sandbox-ghc-pkg.out
--- a/cabal/cabal-testsuite/PackageTests/Exec/sandbox-ghc-pkg.out
+++ b/cabal/cabal-testsuite/PackageTests/Exec/sandbox-ghc-pkg.out
@@ -1,9 +1,9 @@
-# cabal sandbox init
+# cabal v1-sandbox init
 Writing a default package environment file to <ROOT>/sandbox-ghc-pkg.dist/cabal.sandbox.config
 Creating a new sandbox at <ROOT>/sandbox-ghc-pkg.dist/sandbox
-# cabal exec
+# cabal v1-exec
 cabal: The program 'my-executable' is required but it could not be found.
-# cabal install
+# cabal v1-install
 Resolving dependencies...
 Configuring my-0.1...
 Preprocessing executable 'my-executable' for my-0.1..
@@ -12,5 +12,5 @@
 Building library for my-0.1..
 Installing executable my-executable in <PATH>
 Installing library in <PATH>
-Installed my-0.1
-# cabal exec
+Completed    my-0.1
+# cabal v1-exec
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/sandbox-ghc-pkg.test.hs b/cabal/cabal-testsuite/PackageTests/Exec/sandbox-ghc-pkg.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Exec/sandbox-ghc-pkg.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Exec/sandbox-ghc-pkg.test.hs
@@ -3,10 +3,10 @@
 main = cabalTest $ do
     withPackageDb $ do
         withSandbox $ do
-            fails $ cabal "exec" ["my-executable"]
-            cabal "install" []
+            fails $ cabal "v1-exec" ["my-executable"]
+            cabal "v1-install" []
             -- The library should not be available outside the sandbox
             ghcPkg' "list" [] >>= assertOutputDoesNotContain "my-0.1"
             -- Execute ghc-pkg inside the sandbox; it should find my-0.1
-            cabal' "exec" ["ghc-pkg", "list"]
+            cabal' "v1-exec" ["ghc-pkg", "list"]
                 >>= assertOutputContains "my-0.1"
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/sandbox-hc-pkg.out b/cabal/cabal-testsuite/PackageTests/Exec/sandbox-hc-pkg.out
--- a/cabal/cabal-testsuite/PackageTests/Exec/sandbox-hc-pkg.out
+++ b/cabal/cabal-testsuite/PackageTests/Exec/sandbox-hc-pkg.out
@@ -1,9 +1,9 @@
-# cabal sandbox init
+# cabal v1-sandbox init
 Writing a default package environment file to <ROOT>/sandbox-hc-pkg.dist/cabal.sandbox.config
 Creating a new sandbox at <ROOT>/sandbox-hc-pkg.dist/sandbox
-# cabal exec
+# cabal v1-exec
 cabal: The program 'my-executable' is required but it could not be found.
-# cabal install
+# cabal v1-install
 Resolving dependencies...
 Configuring my-0.1...
 Preprocessing executable 'my-executable' for my-0.1..
@@ -12,5 +12,5 @@
 Building library for my-0.1..
 Installing executable my-executable in <PATH>
 Installing library in <PATH>
-Installed my-0.1
-# cabal exec
+Completed    my-0.1
+# cabal v1-exec
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/sandbox-hc-pkg.test.hs b/cabal/cabal-testsuite/PackageTests/Exec/sandbox-hc-pkg.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Exec/sandbox-hc-pkg.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Exec/sandbox-hc-pkg.test.hs
@@ -5,8 +5,8 @@
 main = cabalTest $ do
     withPackageDb $ do
         withSandbox $ do
-            fails $ cabal "exec" ["my-executable"]
-            cabal "install" []
+            fails $ cabal "v1-exec" ["my-executable"]
+            cabal "v1-install" []
             -- The library should not be available outside the sandbox
             ghcPkg' "list" [] >>= assertOutputDoesNotContain "my-0.1"
             -- When run inside 'cabal-exec' the 'sandbox hc-pkg list' sub-command
@@ -16,7 +16,7 @@
             -- turn it absolute
             rel_cabal_path <- programPathM cabalProgram
             cabal_path <- liftIO $ makeAbsolute rel_cabal_path
-            cabal' "exec" ["sh", "--", "-c"
+            cabal' "v1-exec" ["sh", "--", "-c"
                           , "cd subdir && " ++ show cabal_path ++
                             -- TODO: Ugh. Test abstractions leaking
                             -- through
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/sandbox-path.out b/cabal/cabal-testsuite/PackageTests/Exec/sandbox-path.out
--- a/cabal/cabal-testsuite/PackageTests/Exec/sandbox-path.out
+++ b/cabal/cabal-testsuite/PackageTests/Exec/sandbox-path.out
@@ -1,9 +1,9 @@
-# cabal sandbox init
+# cabal v1-sandbox init
 Writing a default package environment file to <ROOT>/sandbox-path.dist/cabal.sandbox.config
 Creating a new sandbox at <ROOT>/sandbox-path.dist/sandbox
-# cabal exec
+# cabal v1-exec
 cabal: The program 'my-executable' is required but it could not be found.
-# cabal install
+# cabal v1-install
 Resolving dependencies...
 Configuring my-0.1...
 Preprocessing executable 'my-executable' for my-0.1..
@@ -12,5 +12,5 @@
 Building library for my-0.1..
 Installing executable my-executable in <PATH>
 Installing library in <PATH>
-Installed my-0.1
-# cabal exec
+Completed    my-0.1
+# cabal v1-exec
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/sandbox-path.test.hs b/cabal/cabal-testsuite/PackageTests/Exec/sandbox-path.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Exec/sandbox-path.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Exec/sandbox-path.test.hs
@@ -1,8 +1,8 @@
 import Test.Cabal.Prelude
 main = cabalTest $ do
     withSandbox $ do
-        fails $ cabal "exec" ["my-executable"]
-        cabal "install" []
+        fails $ cabal "v1-exec" ["my-executable"]
+        cabal "v1-install" []
         -- Execute indirectly via bash to ensure that we go through $PATH
-        cabal' "exec" ["sh", "--", "-c", "my-executable"]
+        cabal' "v1-exec" ["sh", "--", "-c", "my-executable"]
             >>= assertOutputContains "This is my-executable"
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/sandbox.out b/cabal/cabal-testsuite/PackageTests/Exec/sandbox.out
--- a/cabal/cabal-testsuite/PackageTests/Exec/sandbox.out
+++ b/cabal/cabal-testsuite/PackageTests/Exec/sandbox.out
@@ -1,9 +1,9 @@
-# cabal sandbox init
+# cabal v1-sandbox init
 Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config
 Creating a new sandbox at <ROOT>/sandbox.dist/sandbox
-# cabal exec
+# cabal v1-exec
 cabal: The program 'my-executable' is required but it could not be found.
-# cabal install
+# cabal v1-install
 Resolving dependencies...
 Configuring my-0.1...
 Preprocessing executable 'my-executable' for my-0.1..
@@ -12,5 +12,5 @@
 Building library for my-0.1..
 Installing executable my-executable in <PATH>
 Installing library in <PATH>
-Installed my-0.1
-# cabal exec
+Completed    my-0.1
+# cabal v1-exec
diff --git a/cabal/cabal-testsuite/PackageTests/Exec/sandbox.test.hs b/cabal/cabal-testsuite/PackageTests/Exec/sandbox.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Exec/sandbox.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Exec/sandbox.test.hs
@@ -1,7 +1,7 @@
 import Test.Cabal.Prelude
 main = cabalTest $ do
     withSandbox $ do
-        fails $ cabal "exec" ["my-executable"]
-        cabal "install" []
-        cabal' "exec" ["my-executable"]
+        fails $ cabal "v1-exec" ["my-executable"]
+        cabal "v1-install" []
+        cabal' "v1-exec" ["my-executable"]
             >>= assertOutputContains "This is my-executable"
diff --git a/cabal/cabal-testsuite/PackageTests/ForeignLibs/my-foreign-lib.cabal b/cabal/cabal-testsuite/PackageTests/ForeignLibs/my-foreign-lib.cabal
--- a/cabal/cabal-testsuite/PackageTests/ForeignLibs/my-foreign-lib.cabal
+++ b/cabal/cabal-testsuite/PackageTests/ForeignLibs/my-foreign-lib.cabal
@@ -38,3 +38,14 @@
   hs-source-dirs:      src
   c-sources:           csrc/MyForeignLibWrapper.c
   default-language:    Haskell2010
+
+foreign-library includeslib
+  type:                native-shared
+  if os(windows)
+     options: standalone
+  other-modules:       MyForeignLib.Export
+  install-includes:    Export_stub.h
+  include-dirs:        includeslib-tmp/MyForeignLib
+  build-depends:       base, my-foreign-lib
+  hs-source-dirs:      src
+  default-language:    Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/ForeignLibs/src/MyForeignLib/Export.hs b/cabal/cabal-testsuite/PackageTests/ForeignLibs/src/MyForeignLib/Export.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/ForeignLibs/src/MyForeignLib/Export.hs
@@ -0,0 +1,8 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+module MyForeignLib.Export
+  ( foo ) where
+
+foo :: Int -> Int
+foo x = x + 1
+
+foreign export ccall foo :: Int -> Int
diff --git a/cabal/cabal-testsuite/PackageTests/Freeze/disable-benchmarks.out b/cabal/cabal-testsuite/PackageTests/Freeze/disable-benchmarks.out
--- a/cabal/cabal-testsuite/PackageTests/Freeze/disable-benchmarks.out
+++ b/cabal/cabal-testsuite/PackageTests/Freeze/disable-benchmarks.out
@@ -1,4 +1,4 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
-# cabal freeze
+# cabal v1-freeze
 Resolving dependencies...
diff --git a/cabal/cabal-testsuite/PackageTests/Freeze/disable-benchmarks.test.hs b/cabal/cabal-testsuite/PackageTests/Freeze/disable-benchmarks.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Freeze/disable-benchmarks.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Freeze/disable-benchmarks.test.hs
@@ -1,6 +1,6 @@
 import Test.Cabal.Prelude
 main = cabalTest $ do
     withRepo "repo" . withSourceCopy $ do
-        cabal "freeze" ["--disable-benchmarks"]
+        cabal "v1-freeze" ["--disable-benchmarks"]
         cwd <- fmap testCurrentDir getTestEnv
         assertFileDoesNotContain (cwd </> "cabal.config") "criterion"
diff --git a/cabal/cabal-testsuite/PackageTests/Freeze/disable-tests.out b/cabal/cabal-testsuite/PackageTests/Freeze/disable-tests.out
--- a/cabal/cabal-testsuite/PackageTests/Freeze/disable-tests.out
+++ b/cabal/cabal-testsuite/PackageTests/Freeze/disable-tests.out
@@ -1,4 +1,4 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
-# cabal freeze
+# cabal v1-freeze
 Resolving dependencies...
diff --git a/cabal/cabal-testsuite/PackageTests/Freeze/disable-tests.test.hs b/cabal/cabal-testsuite/PackageTests/Freeze/disable-tests.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Freeze/disable-tests.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Freeze/disable-tests.test.hs
@@ -1,6 +1,6 @@
 import Test.Cabal.Prelude
 main = cabalTest $ do
     withRepo "repo" . withSourceCopy $ do
-        cabal "freeze" ["--disable-tests"]
+        cabal "v1-freeze" ["--disable-tests"]
         cwd <- fmap testCurrentDir getTestEnv
         assertFileDoesNotContain (cwd </> "cabal.config") "test-framework"
diff --git a/cabal/cabal-testsuite/PackageTests/Freeze/dry-run.out b/cabal/cabal-testsuite/PackageTests/Freeze/dry-run.out
--- a/cabal/cabal-testsuite/PackageTests/Freeze/dry-run.out
+++ b/cabal/cabal-testsuite/PackageTests/Freeze/dry-run.out
@@ -1,2 +1,2 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
diff --git a/cabal/cabal-testsuite/PackageTests/Freeze/dry-run.test.hs b/cabal/cabal-testsuite/PackageTests/Freeze/dry-run.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Freeze/dry-run.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Freeze/dry-run.test.hs
@@ -1,6 +1,6 @@
 import Test.Cabal.Prelude
 main = cabalTest $ do
     withRepo "repo" . withSourceCopy $ do
-        recordMode DoNotRecord $ cabal "freeze" ["--dry-run"]
+        recordMode DoNotRecord $ cabal "v1-freeze" ["--dry-run"]
         cwd <- fmap testCurrentDir getTestEnv
         shouldNotExist (cwd </> "cabal.config")
diff --git a/cabal/cabal-testsuite/PackageTests/Freeze/enable-benchmarks.out b/cabal/cabal-testsuite/PackageTests/Freeze/enable-benchmarks.out
--- a/cabal/cabal-testsuite/PackageTests/Freeze/enable-benchmarks.out
+++ b/cabal/cabal-testsuite/PackageTests/Freeze/enable-benchmarks.out
@@ -1,4 +1,4 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
-# cabal freeze
+# cabal v1-freeze
 Resolving dependencies...
diff --git a/cabal/cabal-testsuite/PackageTests/Freeze/enable-benchmarks.test.hs b/cabal/cabal-testsuite/PackageTests/Freeze/enable-benchmarks.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Freeze/enable-benchmarks.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Freeze/enable-benchmarks.test.hs
@@ -1,7 +1,7 @@
 import Test.Cabal.Prelude
 main = cabalTest $ do
     withRepo "repo" . withSourceCopy $ do
-        cabal "freeze" ["--enable-benchmarks"]
+        cabal "v1-freeze" ["--enable-benchmarks"]
         cwd <- fmap testCurrentDir getTestEnv
         assertFileDoesContain (cwd </> "cabal.config") "criterion"
         assertFileDoesContain (cwd </> "cabal.config") "ghc-prim"
diff --git a/cabal/cabal-testsuite/PackageTests/Freeze/enable-tests.out b/cabal/cabal-testsuite/PackageTests/Freeze/enable-tests.out
--- a/cabal/cabal-testsuite/PackageTests/Freeze/enable-tests.out
+++ b/cabal/cabal-testsuite/PackageTests/Freeze/enable-tests.out
@@ -1,4 +1,4 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
-# cabal freeze
+# cabal v1-freeze
 Resolving dependencies...
diff --git a/cabal/cabal-testsuite/PackageTests/Freeze/enable-tests.test.hs b/cabal/cabal-testsuite/PackageTests/Freeze/enable-tests.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Freeze/enable-tests.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Freeze/enable-tests.test.hs
@@ -1,6 +1,6 @@
 import Test.Cabal.Prelude
 main = cabalTest $ do
     withRepo "repo" . withSourceCopy $ do
-        cabal "freeze" ["--enable-tests"]
+        cabal "v1-freeze" ["--enable-tests"]
         cwd <- fmap testCurrentDir getTestEnv
         assertFileDoesContain (cwd </> "cabal.config") "test-framework"
diff --git a/cabal/cabal-testsuite/PackageTests/Freeze/freeze.out b/cabal/cabal-testsuite/PackageTests/Freeze/freeze.out
--- a/cabal/cabal-testsuite/PackageTests/Freeze/freeze.out
+++ b/cabal/cabal-testsuite/PackageTests/Freeze/freeze.out
@@ -1,4 +1,4 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
-# cabal freeze
+# cabal v1-freeze
 Resolving dependencies...
diff --git a/cabal/cabal-testsuite/PackageTests/Freeze/freeze.test.hs b/cabal/cabal-testsuite/PackageTests/Freeze/freeze.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Freeze/freeze.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Freeze/freeze.test.hs
@@ -3,7 +3,7 @@
     withRepo "repo" . withSourceCopy $ do
         -- TODO: test this with a sandbox-installed package
         -- that is not depended upon
-        cabal "freeze" []
+        cabal "v1-freeze" []
         cwd <- fmap testCurrentDir getTestEnv
         assertFileDoesNotContain (cwd </> "cabal.config") "exceptions"
         assertFileDoesNotContain (cwd </> "cabal.config") "my"
diff --git a/cabal/cabal-testsuite/PackageTests/InternalLibraries/Executable/setup-static.test.hs b/cabal/cabal-testsuite/PackageTests/InternalLibraries/Executable/setup-static.test.hs
--- a/cabal/cabal-testsuite/PackageTests/InternalLibraries/Executable/setup-static.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/InternalLibraries/Executable/setup-static.test.hs
@@ -1,6 +1,7 @@
 import Test.Cabal.Prelude
 import Control.Monad.IO.Class
 import Control.Monad
+import Distribution.System (buildPlatform)
 import Distribution.Package
 import Distribution.Simple.Configure
 import Distribution.Simple.BuildPaths
@@ -41,11 +42,11 @@
               then
                 assertBool "dynamic library MUST be installed"
                     =<< liftIO (doesFileExist (dyndir </> mkSharedLibName
-                                               compiler_id uid))
+                                               buildPlatform compiler_id uid))
               else
                 assertBool "dynamic library should be installed"
                     =<< liftIO (doesFileExist (dyndir </> mkSharedLibName
-                                               compiler_id uid))
+                                               buildPlatform compiler_id uid))
             fails $ ghcPkg "describe" ["foo"]
             -- clean away the dist directory so that we catch accidental
             -- dependence on the inplace files
diff --git a/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox-shadow.out b/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox-shadow.out
--- a/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox-shadow.out
+++ b/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox-shadow.out
@@ -1,9 +1,9 @@
-# cabal sandbox init
+# cabal v1-sandbox init
 Writing a default package environment file to <ROOT>/sandbox-shadow.dist/cabal.sandbox.config
 Creating a new sandbox at <ROOT>/sandbox-shadow.dist/sandbox
-# cabal sandbox add-source
-# cabal sandbox add-source
-# cabal install
+# cabal v1-sandbox add-source
+# cabal v1-sandbox add-source
+# cabal v1-install
 Resolving dependencies...
 Configuring p-0.1.0.0...
 Preprocessing library 'q' for p-0.1.0.0..
@@ -15,4 +15,4 @@
 Installing internal library q in <PATH>
 Installing executable foo in <PATH>
 Installing library in <PATH>
-Installed p-0.1.0.0
+Completed    p-0.1.0.0
diff --git a/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox-shadow.test.hs b/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox-shadow.test.hs
--- a/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox-shadow.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox-shadow.test.hs
@@ -3,4 +3,4 @@
     withSandbox $ do
         cabal_sandbox "add-source" ["p"]
         cabal_sandbox "add-source" ["q"]
-        cabal "install" ["p"]
+        cabal "v1-install" ["p"]
diff --git a/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox.out b/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox.out
--- a/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox.out
+++ b/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox.out
@@ -1,8 +1,8 @@
-# cabal sandbox init
+# cabal v1-sandbox init
 Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config
 Creating a new sandbox at <ROOT>/sandbox.dist/sandbox
-# cabal sandbox add-source
-# cabal install
+# cabal v1-sandbox add-source
+# cabal v1-install
 Resolving dependencies...
 Configuring p-0.1.0.0...
 Preprocessing library 'q' for p-0.1.0.0..
@@ -14,4 +14,4 @@
 Installing internal library q in <PATH>
 Installing executable foo in <PATH>
 Installing library in <PATH>
-Installed p-0.1.0.0
+Completed    p-0.1.0.0
diff --git a/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox.test.hs b/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox.test.hs
--- a/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox.test.hs
@@ -2,4 +2,4 @@
 main = cabalTest $ do
     withSandbox $ do
         cabal_sandbox "add-source" ["p"]
-        cabal "install" ["p"]
+        cabal "v1-install" ["p"]
diff --git a/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsBad/setup.cabal.out b/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsBad/setup.cabal.out
--- a/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsBad/setup.cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsBad/setup.cabal.out
@@ -2,8 +2,9 @@
 Resolving dependencies...
 Warning: solver failed to find a solution:
 Could not resolve dependencies:
-next goal: build-depends-bad-version (user goal)
-rejecting: build-depends-bad-version-0.1.0.0 (conflict: build-depends-bad-version==0.1.0.0, build-depends-bad-version => build-depends-bad-version>=2)
+[__0] next goal: build-depends-bad-version (user goal)
+[__0] rejecting: build-depends-bad-version-0.1.0.0 (conflict: build-depends-bad-version==0.1.0.0, build-depends-bad-version => build-depends-bad-version>=2)
+[__0] fail (backjumping, conflict set: build-depends-bad-version)
 After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: build-depends-bad-version (2)
 Trying configure anyway.
 Configuring build-depends-bad-version-0.1.0.0...
diff --git a/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.cabal.out b/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.cabal.out
--- a/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.cabal.out
@@ -1,16 +1,3 @@
 # Setup configure
 Resolving dependencies...
 Configuring build-depends-extra-version-0.1.0.0...
-Warning: The package has an extraneous version range for a dependency on an internal library: build-depends-extra-version >=0.0.0.1. This version range includes the current package but isn't needed as the current package's library will always be used.
-# Setup sdist
-Distribution quality errors:
-The package has an extraneous version range for a dependency on an internal library: build-depends-extra-version >=0.0.0.1. This version range includes the current package but isn't needed as the current package's library will always be used.
-Distribution quality warnings:
-No 'maintainer' field.
-No 'description' field.
-A 'license-file' is not specified.
-Note: the public hackage server would reject this package.
-Building source dist for build-depends-extra-version-0.1.0.0...
-Preprocessing library for build-depends-extra-version-0.1.0.0..
-Preprocessing executable 'bar' for build-depends-extra-version-0.1.0.0..
-Source tarball created: setup.cabal.dist/work/dist/build-depends-extra-version-0.1.0.0.tar.gz
diff --git a/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.out b/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.out
--- a/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.out
+++ b/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.out
@@ -1,15 +1,2 @@
 # Setup configure
 Configuring build-depends-extra-version-0.1.0.0...
-Warning: The package has an extraneous version range for a dependency on an internal library: build-depends-extra-version >=0.0.0.1. This version range includes the current package but isn't needed as the current package's library will always be used.
-# Setup sdist
-Distribution quality errors:
-The package has an extraneous version range for a dependency on an internal library: build-depends-extra-version >=0.0.0.1. This version range includes the current package but isn't needed as the current package's library will always be used.
-Distribution quality warnings:
-No 'maintainer' field.
-No 'description' field.
-A 'license-file' is not specified.
-Note: the public hackage server would reject this package.
-Building source dist for build-depends-extra-version-0.1.0.0...
-Preprocessing library for build-depends-extra-version-0.1.0.0..
-Preprocessing executable 'bar' for build-depends-extra-version-0.1.0.0..
-Source tarball created: setup.dist/work/dist/build-depends-extra-version-0.1.0.0.tar.gz
diff --git a/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.test.hs b/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.test.hs
--- a/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.test.hs
@@ -2,5 +2,7 @@
 -- Test unneed version bound on internal build-tools deps
 main = setupAndCabalTest $ do
     setup' "configure" []
-    assertOutputContains "extraneous version range"
-        =<< setup' "sdist" []
+    -- Hack alert: had to squelch this warning because of #5119.
+--    assertOutputContains "extraneous version range"
+--        =<< setup' "sdist" []
+    return ()
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/Bar.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/Bar.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/Bar.hs
@@ -0,0 +1,1 @@
+main = print "Bar"
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/Baz.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/Baz.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/Baz.hs
@@ -0,0 +1,1 @@
+main = print "Baz"
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/Foo.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/Foo.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/Foo.hs
@@ -0,0 +1,1 @@
+main = print "Foo"
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/Lib.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/Lib.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/Lib.hs
@@ -0,0 +1,2 @@
+module Lib where
+lib = 1
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/OnlyConfigure.cabal b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/OnlyConfigure.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/OnlyConfigure.cabal
@@ -0,0 +1,26 @@
+name: OnlyConfigure
+version: 1.0
+build-type: Simple
+cabal-version: >= 1.10
+
+library
+    exposed-modules: Lib
+    build-depends: base
+    default-language: Haskell2010
+
+executable foo
+    main-is: Foo.hs
+    build-depends: base
+    default-language: Haskell2010
+
+test-suite bar
+    type: exitcode-stdio-1.0
+    main-is: Bar.hs
+    build-depends: base
+    default-language: Haskell2010
+
+benchmark baz
+    type: exitcode-stdio-1.0
+    main-is: Baz.hs
+    build-depends: base
+    default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/cabal.out b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/cabal.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/cabal.out
@@ -0,0 +1,30 @@
+# cabal v2-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - OnlyConfigure-1.0 (lib) (first run)
+ - OnlyConfigure-1.0 (exe:foo) (first run)
+Configuring library for OnlyConfigure-1.0..
+Configuring executable 'foo' for OnlyConfigure-1.0..
+# cabal v2-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - OnlyConfigure-1.0 (lib) (configuration changed)
+ - OnlyConfigure-1.0 (test:bar) (first run)
+ - OnlyConfigure-1.0 (exe:foo) (configuration changed)
+Configuring library for OnlyConfigure-1.0..
+Configuring test suite 'bar' for OnlyConfigure-1.0..
+Configuring executable 'foo' for OnlyConfigure-1.0..
+# cabal v2-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - OnlyConfigure-1.0 (lib) (configuration changed)
+ - OnlyConfigure-1.0 (test:bar) (configuration changed)
+ - OnlyConfigure-1.0 (bench:baz) (first run)
+ - OnlyConfigure-1.0 (exe:foo) (configuration changed)
+Configuring library for OnlyConfigure-1.0..
+Configuring test suite 'bar' for OnlyConfigure-1.0..
+Configuring benchmark 'baz' for OnlyConfigure-1.0..
+Configuring executable 'foo' for OnlyConfigure-1.0..
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/cabal.project b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/cabal.project
@@ -0,0 +1,1 @@
+packages: .
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdBuild/OnlyConfigure/cabal.test.hs
@@ -0,0 +1,24 @@
+import Test.Cabal.Prelude
+
+main = cabalTest $ do
+    res <- cabal' "v2-build" ["--only-configure"]
+    assertOutputContains       "Configuring library for" res
+    assertOutputContains       "Configuring executable 'foo' for" res
+    assertOutputDoesNotContain "Configuring test suite 'bar' for" res
+    assertOutputDoesNotContain "Configuring benchmark 'baz' for" res
+    assertOutputDoesNotContain "Building" res
+
+    res <- cabal' "v2-build" ["--only-configure", "--enable-tests"]
+    assertOutputContains       "Configuring library for" res
+    assertOutputContains       "Configuring executable 'foo' for" res
+    assertOutputContains       "Configuring test suite 'bar' for" res
+    assertOutputDoesNotContain "Configuring benchmark 'baz' for" res
+    assertOutputDoesNotContain "Building" res
+
+    res <- cabal' "v2-build"
+             [ "--only-configure", "--enable-tests", "--enable-benchmarks"]
+    assertOutputContains       "Configuring library for" res
+    assertOutputContains       "Configuring executable 'foo' for" res
+    assertOutputContains       "Configuring test suite 'bar' for" res
+    assertOutputContains       "Configuring benchmark 'baz' for" res
+    assertOutputDoesNotContain "Building" res
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.test.hs
--- a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.test.hs
@@ -1,17 +1,17 @@
 import Test.Cabal.Prelude
-import Control.Monad.Trans (liftIO)
 import System.Directory-- (getDirectoryContents, removeFile)
 main = cabalTest $ do
     cabal "new-build" ["inplace-dep"]
     env <- getTestEnv
     liftIO $ removeEnvFiles $ testSourceDir env -- we don't want existing env files to interfere
-    cabal "new-exec" ["ghc", "Main.hs"]
+    -- Drop the compiled executable into the temporary directory, to avoid cluttering the tree. If compilation succeeds, we've tested what we need to!
+    tmpdir <- fmap testTmpDir getTestEnv
+    let dest = tmpdir </> "a.out"
+    cabal "new-exec" ["ghc", "--", "Main.hs", "-o", dest]
     -- TODO external (store) deps, once new-install is working
 
+-- copy-pasted from D.C.CmdClean.
 removeEnvFiles :: FilePath -> IO ()
-removeEnvFiles dir = (mapM_ (removeFile . (dir </>))
-                   . filter
-                       ((".ghc.environment" ==)
-                       . take 16))
-                   =<< getDirectoryContents dir
-
+removeEnvFiles dir =
+  (mapM_ (removeFile . (dir </>)) . filter ((".ghc.environment" ==) . take 16))
+  =<< getDirectoryContents dir
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/ExeAndLib/cabal.out b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/ExeAndLib/cabal.out
--- a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/ExeAndLib/cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/ExeAndLib/cabal.out
@@ -7,4 +7,4 @@
 Preprocessing executable 'foo' for ExeAndLib-1.0..
 Building executable 'foo' for ExeAndLib-1.0..
 # cabal new-run
-cabal: The run command is for running executables, but the target 'ExeAndLib' refers to the library in the package ExeAndLib-1.0 from the package ExeAndLib-1.0.
+cabal: The run command is for running executables, but the target 'ExeAndLib' refers to the library ExeAndLib from the package ExeAndLib-1.0.
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/MultipleExes/cabal.out b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/MultipleExes/cabal.out
--- a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/MultipleExes/cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/MultipleExes/cabal.out
@@ -16,6 +16,6 @@
 # cabal new-run
 Up to date
 # cabal new-run
-cabal: The run command is for running a single executable at once. The target '' refers to the package MultipleExes-1.0 which includes the executables foo and bar.
+cabal: The run command is for running a single executable at once. The target '' refers to the package MultipleExes-1.0 which includes the executable 'foo' and the executable 'bar'.
 # cabal new-run
-cabal: The run command is for running a single executable at once. The target 'MultipleExes' refers to the package MultipleExes-1.0 which includes the executables foo and bar.
+cabal: The run command is for running a single executable at once. The target 'MultipleExes' refers to the package MultipleExes-1.0 which includes the executable 'foo' and the executable 'bar'.
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/MultiplePackages/cabal.out b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/MultiplePackages/cabal.out
--- a/cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/MultiplePackages/cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/MultiplePackages/cabal.out
@@ -25,7 +25,7 @@
 # cabal new-run
 cabal: No targets given and there is no package in the current directory. Use the target 'all' for all packages in the project or specify packages or components by name or location. See 'cabal build --help' for more details on target options.
 # cabal new-run
-cabal: The run command is for running a single executable at once. The target 'bar' refers to the package bar-1.0 which includes the executables foo-exe and bar-exe.
+cabal: The run command is for running a single executable at once. The target 'bar' refers to the package bar-1.0 which includes the executable 'foo-exe' and the executable 'bar-exe'.
 # cabal new-run
 cabal: Ambiguous target 'foo-exe'. It could be:
     bar:foo-exe (component)
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/LocalPackageWithCustomSetup/build-local-package-with-custom-setup.out b/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/LocalPackageWithCustomSetup/build-local-package-with-custom-setup.out
--- a/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/LocalPackageWithCustomSetup/build-local-package-with-custom-setup.out
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/LocalPackageWithCustomSetup/build-local-package-with-custom-setup.out
@@ -1,2 +1,2 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/LocalPackageWithCustomSetup/build-local-package-with-custom-setup.test.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/LocalPackageWithCustomSetup/build-local-package-with-custom-setup.test.hs
--- a/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/LocalPackageWithCustomSetup/build-local-package-with-custom-setup.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/LocalPackageWithCustomSetup/build-local-package-with-custom-setup.test.hs
@@ -2,10 +2,11 @@
 
 -- The one local package, pkg, has a setup dependency on setup-dep-2.0, which is
 -- in the repository.
-main = cabalTest $ do
-  skipUnless =<< hasNewBuildCompatBootCabal
-  withRepo "repo" $ do
-    r <- recordMode DoNotRecord $ cabal' "new-build" ["pkg"]
-    -- pkg's setup script should print out a message that it imported from
-    -- setup-dep:
-    assertOutputContains "pkg Setup.hs: setup-dep-2.0" r
+main = withShorterPathForNewBuildStore $ \storeDir ->
+  cabalTest $ do
+    skipUnless =<< hasNewBuildCompatBootCabal
+    withRepo "repo" $ do
+      r <- recordMode DoNotRecord $ cabalG' ["--store-dir=" ++ storeDir] "new-build" ["pkg"]
+      -- pkg's setup script should print out a message that it imported from
+      -- setup-dep:
+      assertOutputContains "pkg Setup.hs: setup-dep-2.0" r
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/RemotePackageWithCustomSetup/build-package-from-repo-with-custom-setup.out b/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/RemotePackageWithCustomSetup/build-package-from-repo-with-custom-setup.out
--- a/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/RemotePackageWithCustomSetup/build-package-from-repo-with-custom-setup.out
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/RemotePackageWithCustomSetup/build-package-from-repo-with-custom-setup.out
@@ -1,4 +1,4 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
 # pkg my-exe
 pkg Main.hs: remote-pkg-2.0
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/RemotePackageWithCustomSetup/build-package-from-repo-with-custom-setup.test.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/RemotePackageWithCustomSetup/build-package-from-repo-with-custom-setup.test.hs
--- a/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/RemotePackageWithCustomSetup/build-package-from-repo-with-custom-setup.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/CustomSetup/RemotePackageWithCustomSetup/build-package-from-repo-with-custom-setup.test.hs
@@ -2,14 +2,19 @@
 
 -- The one local package, pkg, has a dependency on remote-pkg-2.0, which has a
 -- setup dependency on remote-setup-dep-3.0.
-main = cabalTest $ do
-  skipUnless =<< hasNewBuildCompatBootCabal
-  withRepo "repo" $ do
-    r1 <- recordMode DoNotRecord $ cabal' "new-build" ["pkg:my-exe"]
-    -- remote-pkg's setup script should print out a message that it imported from
-    -- remote-setup-dep:
-    assertOutputContains "remote-pkg Setup.hs: remote-setup-dep-3.0" r1
-    withPlan $ do
-      r2 <- runPlanExe' "pkg" "my-exe" []
-      -- pkg's executable should print a message that it imported from remote-pkg:
-      assertOutputContains "pkg Main.hs: remote-pkg-2.0" r2
+main = withShorterPathForNewBuildStore $ \storeDir ->
+  cabalTest $ do
+
+    -- TODO: Debug this failure on Windows.
+    skipIf =<< isWindows
+
+    skipUnless =<< hasNewBuildCompatBootCabal
+    withRepo "repo" $ do
+      r1 <- recordMode DoNotRecord $ cabalG' ["--store-dir=" ++ storeDir] "new-build" ["pkg:my-exe"]
+      -- remote-pkg's setup script should print out a message that it imported from
+      -- remote-setup-dep:
+      assertOutputContains "remote-pkg Setup.hs: remote-setup-dep-3.0" r1
+      withPlan $ do
+        r2 <- runPlanExe' "pkg" "my-exe" []
+        -- pkg's executable should print a message that it imported from remote-pkg:
+        assertOutputContains "pkg Main.hs: remote-pkg-2.0" r2
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T3827/cabal.out b/cabal/cabal-testsuite/PackageTests/NewBuild/T3827/cabal.out
--- a/cabal/cabal-testsuite/PackageTests/NewBuild/T3827/cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T3827/cabal.out
@@ -2,7 +2,7 @@
 Resolving dependencies...
 Build profile: -w ghc-<GHCVER> -O1
 In order, the following will be built:
- - p-1.0 (lib) --enable-library-profiling (first run)
+ - p-1.0 (lib) (first run)
  - q-1.0 (exe:q) --enable-profiling (first run)
 Configuring library for p-1.0..
 Preprocessing library for p-1.0..
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T3978/cabal.out b/cabal/cabal-testsuite/PackageTests/NewBuild/T3978/cabal.out
--- a/cabal/cabal-testsuite/PackageTests/NewBuild/T3978/cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T3978/cabal.out
@@ -1,6 +1,8 @@
 # cabal new-build
 Resolving dependencies...
-Error:
-    Dependency on unbuildable library from p
-    In the stanza 'library'
-    In the inplace package 'q-1.0'
+cabal: Could not resolve dependencies:
+[__0] trying: p-1.0 (user goal)
+[__1] next goal: q (user goal)
+[__1] rejecting: q-1.0 (requires library from p, but the component is not buildable in the current environment)
+[__1] fail (backjumping, conflict set: p, q)
+After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: p (2), q (2)
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/CustomIssue.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/CustomIssue.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/CustomIssue.hs
@@ -0,0 +1,3 @@
+module CustomIssue where
+
+f x = x + 1
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/Setup.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/Setup.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/Setup.hs
@@ -0,0 +1,3 @@
+import SetupHelper (setupHelperDefaultMain)
+
+main = setupHelperDefaultMain
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/T4288.cabal b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/T4288.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/T4288.cabal
@@ -0,0 +1,16 @@
+name: T4288
+version: 1.0
+build-type: Custom
+
+-- cabal-version is lower than the version of Cabal that will be chosen for the
+-- setup script.
+cabal-version: >=1.10
+
+-- Setup script only has a transitive dependency on Cabal.
+custom-setup
+  setup-depends: base, setup-helper
+
+library
+  exposed-modules: CustomIssue
+  build-depends: base
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/cabal.project b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/cabal.project
@@ -0,0 +1,1 @@
+packages: . setup-helper/
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/cabal.test.hs
@@ -0,0 +1,17 @@
+import Test.Cabal.Prelude
+
+-- This test is similar to the simplified example in issue #4288. The package's
+-- setup script only depends on base and setup-helper. setup-helper exposes a
+-- function that is a wrapper for Cabal's defaultMain (similar to
+-- cabal-doctest). This test builds the package to check that the flags passed
+-- to the setup script are compatible with the version of Cabal that it depends
+-- on, even though Cabal is only a transitive dependency.
+main = cabalTest $ do
+  skipUnless =<< hasNewBuildCompatBootCabal
+  r <- recordMode DoNotRecord $ cabal' "new-build" ["T4288"]
+  assertOutputContains "This is setup-helper-1.0." r
+  assertOutputContains
+      ("In order, the following will be built: "
+       ++ " - setup-helper-1.0 (lib:setup-helper) (first run) "
+       ++ " - T4288-1.0 (lib:T4288) (first run)")
+      r
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/setup-helper/SetupHelper.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/setup-helper/SetupHelper.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/setup-helper/SetupHelper.hs
@@ -0,0 +1,5 @@
+module SetupHelper (setupHelperDefaultMain) where
+
+import Distribution.Simple
+
+setupHelperDefaultMain = putStrLn "This is setup-helper-1.0." >> defaultMain
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/setup-helper/setup-helper.cabal b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/setup-helper/setup-helper.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T4288/setup-helper/setup-helper.cabal
@@ -0,0 +1,9 @@
+name: setup-helper
+version: 1.0
+build-type: Simple
+cabal-version: >= 1.2
+
+library
+  exposed-modules: SetupHelper
+  build-depends: base, Cabal
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T4375/cabal.out b/cabal/cabal-testsuite/PackageTests/NewBuild/T4375/cabal.out
--- a/cabal/cabal-testsuite/PackageTests/NewBuild/T4375/cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T4375/cabal.out
@@ -1,4 +1,4 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
 # cabal new-build
 Resolving dependencies...
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T4375/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/T4375/cabal.test.hs
--- a/cabal/cabal-testsuite/PackageTests/NewBuild/T4375/cabal.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T4375/cabal.test.hs
@@ -1,5 +1,6 @@
 import Test.Cabal.Prelude
-main = cabalTest $ do
+main = withShorterPathForNewBuildStore $ \storeDir ->
+  cabalTest $ do
     -- Don't run this test unless the GHC is sufficiently recent
     -- to not ship boot old-time/old-locale
     skipUnless =<< ghcVersionIs (>= mkVersion [7,11])
@@ -8,4 +9,4 @@
     -- we had the full Hackage index, we'd try it.)
     skipUnless =<< ghcVersionIs (< mkVersion [8,1])
     withRepo "repo" $ do
-        cabal "new-build" ["a"]
+        cabalG ["--store-dir=" ++ storeDir] "new-build" ["a"]
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/cabal.project b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/cabal.project
@@ -0,0 +1,2 @@
+packages: ./setup-lib
+          ./uses-custom-setup
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/cabal.test.hs
@@ -0,0 +1,4 @@
+import Test.Cabal.Prelude
+main = cabalTest $ do
+    r1 <- recordMode DoNotRecord $ cabal' "new-build" ["all"]
+    assertOutputContains "Example data file" r1
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/setup-lib/SetupLib.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/setup-lib/SetupLib.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/setup-lib/SetupLib.hs
@@ -0,0 +1,9 @@
+module SetupLib (printExampleTxt) where
+
+import Paths_setup_lib
+
+printExampleTxt :: IO ()
+printExampleTxt = do
+  ex <- getDataFileName "example.txt"
+  exContents <- readFile ex
+  putStrLn exContents
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/setup-lib/example.txt b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/setup-lib/example.txt
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/setup-lib/example.txt
@@ -0,0 +1,1 @@
+Example data file
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/setup-lib/setup-lib.cabal b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/setup-lib/setup-lib.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/setup-lib/setup-lib.cabal
@@ -0,0 +1,11 @@
+name: setup-lib
+version: 1.0
+build-type: Simple
+cabal-version: >= 1.10
+data-files: example.txt
+
+library
+    exposed-modules: SetupLib
+    other-modules: Paths_setup_lib
+    build-depends: base
+    default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/uses-custom-setup/Setup.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/uses-custom-setup/Setup.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/uses-custom-setup/Setup.hs
@@ -0,0 +1,7 @@
+import Distribution.Simple (defaultMain)
+import SetupLib (printExampleTxt)
+
+main :: IO ()
+main = do
+  printExampleTxt
+  defaultMain
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/uses-custom-setup/UsesCustomSetup.hs b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/uses-custom-setup/UsesCustomSetup.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/uses-custom-setup/UsesCustomSetup.hs
@@ -0,0 +1,4 @@
+module UsesCustomSetup (foo) where
+
+foo :: Int
+foo = 42
diff --git a/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/uses-custom-setup/uses-custom-setup.cabal b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/uses-custom-setup/uses-custom-setup.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewBuild/T5164/uses-custom-setup/uses-custom-setup.cabal
@@ -0,0 +1,12 @@
+name: uses-custom-setup
+version: 1.0
+build-type: Custom
+cabal-version: >= 1.10
+
+custom-setup
+  setup-depends: base, Cabal, setup-lib
+
+library
+    exposed-modules: UsesCustomSetup
+    build-depends: base
+    default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/cabal.project b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/cabal.project
@@ -0,0 +1,1 @@
+packages: .
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/my-local-package.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/my-local-package.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/my-local-package.cabal
@@ -0,0 +1,9 @@
+name: my-local-package
+version: 1.0
+cabal-version: >= 1.20
+build-type: Simple
+
+library
+  build-depends: base, my-library-dep
+  build-tool-depends: my-build-tool-dep:my-build-tool >= 2
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/new_freeze.out b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/new_freeze.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/new_freeze.out
@@ -0,0 +1,21 @@
+# cabal v1-update
+Downloading the latest package list from test-local-repo
+# cabal new-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following would be built:
+ - my-build-tool-dep-1.0 (exe:my-build-tool) (requires download & build)
+ - my-build-tool-dep-3.0 (exe:my-build-tool) (requires download & build)
+ - my-library-dep-1.0 (lib) (requires download & build)
+ - my-local-package-1.0 (lib) (first run)
+# cabal new-freeze
+Resolving dependencies...
+Wrote freeze file: <ROOT>/new_freeze.dist/source/cabal.project.freeze
+# cabal new-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following would be built:
+ - my-build-tool-dep-1.0 (exe:my-build-tool) (requires download & build)
+ - my-build-tool-dep-2.0 (exe:my-build-tool) (requires download & build)
+ - my-library-dep-1.0 (lib) (requires download & build)
+ - my-local-package-1.0 (lib) (first run)
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/new_freeze.test.hs b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/new_freeze.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/new_freeze.test.hs
@@ -0,0 +1,44 @@
+import Test.Cabal.Prelude
+import Control.Monad.IO.Class
+import System.Directory
+
+-- Test that 'cabal new-freeze' works with multiple versions of a build tool
+-- dependency.
+--
+-- The repository contains versions 1.0, 2.0, and 3.0 of the build tool. There
+-- is one local package, which requires >= 2, and a library dependency of the
+-- local package, which requires < 2, so cabal should pick versions 1.0 and 3.0
+-- of the build tool when there are no constraints.
+main = cabalTest $ withSourceCopy $ do
+  withRepo "repo" $ do
+    cabal' "new-build" ["--dry-run"] >>= assertUsesLatestBuildTool
+
+    -- Force the project to use versions 1.0 and 2.0 of the build tool.
+    cabal "new-freeze" ["--constraint=any.my-build-tool-dep < 3"]
+
+    cwd <- fmap testCurrentDir getTestEnv
+    let freezeFile = cwd </> "cabal.project.freeze"
+
+    -- The freeze file should specify a version range that includes both
+    -- versions of the build tool from the install plan. (This constraint will
+    -- be replaced with two exe qualified constraints once #3502 is fully
+    -- implemented).
+    assertFileDoesContain freezeFile "any.my-build-tool-dep ==1.0 || ==2.0"
+
+    -- The library dependency should have a constraint on an exact version.
+    assertFileDoesContain freezeFile "any.my-library-dep ==1.0"
+
+    -- The local package should be unconstrained.
+    assertFileDoesNotContain freezeFile "my-local-package"
+
+    -- cabal should be able to find an install plan that fits the constraints
+    -- from the freeze file.
+    cabal' "new-build" ["--dry-run"] >>= assertDoesNotUseLatestBuildTool
+  where
+    assertUsesLatestBuildTool out = do
+      assertOutputContains "my-build-tool-dep-3.0 (exe:my-build-tool)" out
+      assertOutputDoesNotContain "my-build-tool-dep-2.0" out
+
+    assertDoesNotUseLatestBuildTool out = do
+      assertOutputContains "my-build-tool-dep-2.0 (exe:my-build-tool)" out
+      assertOutputDoesNotContain "my-build-tool-dep-3.0" out
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/repo/my-build-tool-dep-1.0/my-build-tool-dep.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/repo/my-build-tool-dep-1.0/my-build-tool-dep.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/repo/my-build-tool-dep-1.0/my-build-tool-dep.cabal
@@ -0,0 +1,9 @@
+name: my-build-tool-dep
+version: 1.0
+cabal-version: >= 1.20
+build-type: Simple
+
+executable my-build-tool
+  main-is: Main.hs
+  build-depends: base
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/repo/my-build-tool-dep-2.0/my-build-tool-dep.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/repo/my-build-tool-dep-2.0/my-build-tool-dep.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/repo/my-build-tool-dep-2.0/my-build-tool-dep.cabal
@@ -0,0 +1,9 @@
+name: my-build-tool-dep
+version: 2.0
+cabal-version: >= 1.20
+build-type: Simple
+
+executable my-build-tool
+  main-is: Main.hs
+  build-depends: base
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/repo/my-build-tool-dep-3.0/my-build-tool-dep.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/repo/my-build-tool-dep-3.0/my-build-tool-dep.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/repo/my-build-tool-dep-3.0/my-build-tool-dep.cabal
@@ -0,0 +1,9 @@
+name: my-build-tool-dep
+version: 3.0
+cabal-version: >= 1.20
+build-type: Simple
+
+executable my-build-tool
+  main-is: Main.hs
+  build-depends: base
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/repo/my-library-dep-1.0/my-library-dep.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/repo/my-library-dep-1.0/my-library-dep.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/BuildTools/repo/my-library-dep-1.0/my-library-dep.cabal
@@ -0,0 +1,9 @@
+name: my-library-dep
+version: 1.0
+cabal-version: >= 1.20
+build-type: Simple
+
+library
+  build-depends: base
+  build-tool-depends: my-build-tool-dep:my-build-tool < 2
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/cabal.project b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/cabal.project
@@ -0,0 +1,1 @@
+packages: .
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/my-local-package.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/my-local-package.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/my-local-package.cabal
@@ -0,0 +1,7 @@
+name: my-local-package
+version: 1.0
+cabal-version: 1.20
+build-type: Simple
+
+library
+  build-depends: my-library-dep
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/new_freeze.out b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/new_freeze.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/new_freeze.out
@@ -0,0 +1,19 @@
+# cabal v1-update
+Downloading the latest package list from test-local-repo
+# cabal new-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following would be built:
+ - true-dep-1.0 (lib) (requires download & build)
+ - my-library-dep-1.0 (lib) (requires download & build)
+ - my-local-package-1.0 (lib) (first run)
+# cabal new-freeze
+Resolving dependencies...
+Wrote freeze file: <ROOT>/new_freeze.dist/source/cabal.project.freeze
+# cabal new-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following would be built:
+ - false-dep-1.0 (lib) (requires download & build)
+ - my-library-dep-1.0 (lib) (requires download & build)
+ - my-local-package-1.0 (lib) (first run)
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/new_freeze.test.hs b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/new_freeze.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/new_freeze.test.hs
@@ -0,0 +1,35 @@
+import Test.Cabal.Prelude
+import Control.Monad.IO.Class
+import Data.Char
+import System.Directory
+
+-- Test that 'cabal new-freeze' freezes flag choices. my-local-package depends
+-- on my-library-dep. my-library-dep has a flag, my-flag, which defaults to
+-- true.
+main = cabalTest $ withSourceCopy $
+  withRepo "repo" $ do
+    cabal' "new-build" ["--dry-run"] >>= assertDependencyFlagChoice True
+
+    cabal "new-freeze" ["--constraint=my-library-dep -my-flag"]
+
+    cwd <- fmap testCurrentDir getTestEnv
+    let freezeFile = cwd </> "cabal.project.freeze"
+
+    -- The freeze file should constrain the version and the flag.
+    -- TODO: The flag constraint should be qualified. See
+    -- https://github.com/haskell/cabal/issues/5134.
+    assertFileDoesContain freezeFile "any.my-library-dep ==1.0"
+    assertFileDoesContain freezeFile "my-library-dep -my-flag"
+
+    -- cabal should be able to find an install plan that fits the constraints
+    -- from the freeze file.
+    cabal' "new-build" ["--dry-run"] >>= assertDependencyFlagChoice False
+  where
+    -- my-library-dep's flag controls whether it depends on true-dep or
+    -- false-dep, so this function uses the dependency to infer the flag choice.
+    assertDependencyFlagChoice True out = do
+        assertOutputContains "true-dep-1.0 (lib)" out
+        assertOutputDoesNotContain "false-dep" out
+    assertDependencyFlagChoice False out = do
+        assertOutputContains "false-dep-1.0 (lib)" out
+        assertOutputDoesNotContain "true-dep" out
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/repo/false-dep-1.0/false-dep.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/repo/false-dep-1.0/false-dep.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/repo/false-dep-1.0/false-dep.cabal
@@ -0,0 +1,6 @@
+name: false-dep
+version: 1.0
+cabal-version: 1.20
+build-type: Simple
+
+library
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/repo/my-library-dep-1.0/my-library-dep.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/repo/my-library-dep-1.0/my-library-dep.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/repo/my-library-dep-1.0/my-library-dep.cabal
@@ -0,0 +1,15 @@
+name: my-library-dep
+version: 1.0
+cabal-version: 1.20
+build-type: Simple
+
+flag my-flag
+  default: True
+  manual: False
+
+library
+  build-depends: base
+  if flag(my-flag)
+    build-depends: true-dep
+  else
+    build-depends: false-dep
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/repo/true-dep-1.0/true-dep.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/repo/true-dep-1.0/true-dep.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/Flags/repo/true-dep-1.0/true-dep.cabal
@@ -0,0 +1,6 @@
+name: true-dep
+version: 1.0
+cabal-version: 1.20
+build-type: Simple
+
+library
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/Main.hs b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/Main.hs
@@ -0,0 +1,3 @@
+import MyLibModule (message)
+
+main = putStrLn message
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/cabal.project b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/cabal.project
@@ -0,0 +1,1 @@
+packages: .
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/my-local-package.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/my-local-package.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/my-local-package.cabal
@@ -0,0 +1,10 @@
+name: my-local-package
+version: 1.0
+cabal-version: 1.20
+build-type: Simple
+
+executable my-exe
+  hs-source-dirs: .
+  main-is: Main.hs
+  build-depends: base, my-library-dep
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/new_freeze.out b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/new_freeze.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/new_freeze.out
@@ -0,0 +1,34 @@
+# cabal v1-update
+Downloading the latest package list from test-local-repo
+# cabal new-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following would be built:
+ - my-library-dep-2.0 (lib) (requires download & build)
+ - my-local-package-1.0 (exe:my-exe) (first run)
+# cabal new-freeze
+Resolving dependencies...
+Wrote freeze file: <ROOT>/new_freeze.dist/source/cabal.project.freeze
+# cabal new-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - my-library-dep-1.0 (lib) (requires download & build)
+ - my-local-package-1.0 (exe:my-exe) (first run)
+Configuring library for my-library-dep-1.0..
+Preprocessing library for my-library-dep-1.0..
+Building library for my-library-dep-1.0..
+Installing library in <PATH>
+Configuring executable 'my-exe' for my-local-package-1.0..
+Preprocessing executable 'my-exe' for my-local-package-1.0..
+Building executable 'my-exe' for my-local-package-1.0..
+# cabal new-freeze
+Wrote freeze file: <ROOT>/new_freeze.dist/source/cabal.project.freeze
+# cabal new-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following would be built:
+ - my-library-dep-2.0 (lib) (requires download & build)
+ - my-local-package-1.0 (exe:my-exe) (configuration changed)
+# cabal new-freeze
+Wrote freeze file: <ROOT>/new_freeze.dist/source/cabal.project.freeze
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/new_freeze.test.hs b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/new_freeze.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/new_freeze.test.hs
@@ -0,0 +1,53 @@
+import Test.Cabal.Prelude
+import Control.Monad.IO.Class
+import Data.Char
+import System.Directory
+
+-- Test for 'cabal new-freeze' with only a single library dependency.
+-- my-local-package depends on my-library-dep, which has versions 1.0 and 2.0.
+main = withShorterPathForNewBuildStore $ \storeDir ->
+  cabalTest $ withSourceCopy $
+    withRepo "repo" $ do
+      cwd <- fmap testCurrentDir getTestEnv
+      let freezeFile = cwd </> "cabal.project.freeze"
+
+      shouldNotExist freezeFile
+
+      -- new-build should choose the latest version for the dependency.
+      cabalG' ["--store-dir=" ++ storeDir] "new-build" ["--dry-run"] >>= assertUsesLatestDependency
+
+      -- Freeze a dependency on the older version.
+      cabalG ["--store-dir=" ++ storeDir] "new-freeze" ["--constraint=my-library-dep==1.0"]
+
+      -- The file should constrain the dependency, but not the local package.
+      shouldExist freezeFile
+      assertFileDoesContain freezeFile "any.my-library-dep ==1.0"
+      assertFileDoesNotContain freezeFile "my-local-package"
+
+      -- cabal should be able to build the package using the constraint from the
+      -- freeze file.
+      cabalG' ["--store-dir=" ++ storeDir] "new-build" [] >>= assertDoesNotUseLatestDependency
+
+      -- Re-running new-freeze should not change the constraints, because cabal
+      -- should use the existing freeze file when choosing the new install plan.
+      cabalG ["--store-dir=" ++ storeDir] "new-freeze" []
+      assertFileDoesContain freezeFile "any.my-library-dep ==1.0"
+
+      -- cabal should choose the latest version again after the freeze file is
+      -- removed.
+      liftIO $ removeFile freezeFile
+      cabalG' ["--store-dir=" ++ storeDir] "new-build" ["--dry-run"] >>= assertUsesLatestDependency
+
+      -- Re-running new-freeze with no constraints or freeze file should constrain
+      -- the dependency to the latest version.
+      cabalG ["--store-dir=" ++ storeDir] "new-freeze" []
+      assertFileDoesContain freezeFile "any.my-library-dep ==2.0"
+      assertFileDoesNotContain freezeFile "my-local-package"
+    where
+      assertUsesLatestDependency out = do
+        assertOutputContains "my-library-dep-2.0 (lib)" out
+        assertOutputDoesNotContain "my-library-dep-1.0" out
+
+      assertDoesNotUseLatestDependency out = do
+        assertOutputContains "my-library-dep-1.0 (lib)" out
+        assertOutputDoesNotContain "my-library-dep-2.0" out
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/repo/my-library-dep-1.0/MyLibModule.hs b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/repo/my-library-dep-1.0/MyLibModule.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/repo/my-library-dep-1.0/MyLibModule.hs
@@ -0,0 +1,3 @@
+module MyLibModule (message) where
+
+message = "Hello"
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/repo/my-library-dep-1.0/my-library-dep.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/repo/my-library-dep-1.0/my-library-dep.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/repo/my-library-dep-1.0/my-library-dep.cabal
@@ -0,0 +1,10 @@
+name: my-library-dep
+version: 1.0
+cabal-version: 1.20
+build-type: Simple
+
+library
+  hs-source-dirs: .
+  build-depends: base
+  default-language: Haskell2010
+  exposed-modules: MyLibModule
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/repo/my-library-dep-2.0/MyLibModule.hs b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/repo/my-library-dep-2.0/MyLibModule.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/repo/my-library-dep-2.0/MyLibModule.hs
@@ -0,0 +1,3 @@
+module MyLibModule (message) where
+
+message = "Hello"
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/repo/my-library-dep-2.0/my-library-dep.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/repo/my-library-dep-2.0/my-library-dep.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewFreeze/FreezeFile/repo/my-library-dep-2.0/my-library-dep.cabal
@@ -0,0 +1,10 @@
+name: my-library-dep
+version: 2.0
+cabal-version: 1.20
+build-type: Simple
+
+library
+  hs-source-dirs: .
+  build-depends: base
+  default-language: Haskell2010
+  exposed-modules: MyLibModule
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/cabal.project b/cabal/cabal-testsuite/PackageTests/NewFreeze/cabal.project
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/NewFreeze/cabal.project
+++ /dev/null
@@ -1,1 +0,0 @@
-packages: .
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/my-local-package.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/my-local-package.cabal
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/NewFreeze/my-local-package.cabal
+++ /dev/null
@@ -1,9 +0,0 @@
-name: my-local-package
-version: 1.0
-cabal-version: >= 1.20
-build-type: Simple
-
-library
-  build-depends: base, my-library-dep
-  build-tool-depends: my-build-tool-dep:my-build-tool >= 2
-  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/new_freeze.out b/cabal/cabal-testsuite/PackageTests/NewFreeze/new_freeze.out
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/NewFreeze/new_freeze.out
+++ /dev/null
@@ -1,29 +0,0 @@
-# cabal update
-Downloading the latest package list from test-local-repo
-# cabal new-build
-Resolving dependencies...
-Build profile: -w ghc-<GHCVER> -O1
-In order, the following would be built:
- - my-build-tool-dep-1.0 (exe:my-build-tool) (requires download & build)
- - my-build-tool-dep-3.0 (exe:my-build-tool) (requires download & build)
- - my-library-dep-1.0 (lib) (requires download & build)
- - my-local-package-1.0 (lib) (first run)
-# cabal new-freeze
-Resolving dependencies...
-Wrote freeze file: <ROOT>/new_freeze.dist/source/cabal.project.freeze
-# cabal new-build
-Resolving dependencies...
-Build profile: -w ghc-<GHCVER> -O1
-In order, the following would be built:
- - my-build-tool-dep-1.0 (exe:my-build-tool) (requires download & build)
- - my-build-tool-dep-2.0 (exe:my-build-tool) (requires download & build)
- - my-library-dep-1.0 (lib) (requires download & build)
- - my-local-package-1.0 (lib) (first run)
-# cabal new-build
-Resolving dependencies...
-Build profile: -w ghc-<GHCVER> -O1
-In order, the following would be built:
- - my-build-tool-dep-1.0 (exe:my-build-tool) (requires download & build)
- - my-build-tool-dep-3.0 (exe:my-build-tool) (requires download & build)
- - my-library-dep-1.0 (lib) (requires download & build)
- - my-local-package-1.0 (lib) (first run)
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/new_freeze.test.hs b/cabal/cabal-testsuite/PackageTests/NewFreeze/new_freeze.test.hs
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/NewFreeze/new_freeze.test.hs
+++ /dev/null
@@ -1,49 +0,0 @@
-import Test.Cabal.Prelude
-import Control.Monad.IO.Class
-import System.Directory
-
--- Test that 'cabal new-freeze' works with multiple versions of a build tool
--- dependency.
---
--- The repository contains versions 1.0, 2.0, and 3.0 of the build tool. There
--- is one local package, which requires >= 2, and a library dependency of the
--- local package, which requires < 2, so cabal should pick versions 1.0 and 3.0
--- of the build tool when there are no constraints.
-main = cabalTest $ withSourceCopy $ do
-  withRepo "repo" $ do
-    cabal' "new-build" ["--dry-run"] >>= assertUsesLatestBuildTool
-
-    -- Force the project to use versions 1.0 and 2.0 of the build tool.
-    cabal "new-freeze" ["--constraint=any.my-build-tool-dep < 3"]
-
-    cwd <- fmap testCurrentDir getTestEnv
-    let freezeFile = cwd </> "cabal.project.freeze"
-
-    -- The freeze file should specify a version range that includes both
-    -- versions of the build tool from the install plan. (This constraint will
-    -- be replaced with two exe qualified constraints once #3502 is fully
-    -- implemented).
-    assertFileDoesContain freezeFile "any.my-build-tool-dep ==1.0 || ==2.0"
-
-    -- The library dependency should have a constraint on an exact version.
-    assertFileDoesContain freezeFile "any.my-library-dep ==1.0"
-
-    -- The local package should be unconstrained.
-    assertFileDoesNotContain freezeFile "my-local-package"
-
-    -- cabal should be able to find an install plan that fits the constraints
-    -- from the freeze file.
-    cabal' "new-build" ["--dry-run"] >>= assertDoesNotUseLatestBuildTool
-
-    -- cabal should choose the latest version again after the freeze file is
-    -- removed.
-    liftIO $ removeFile freezeFile
-    cabal' "new-build" ["--dry-run"] >>= assertUsesLatestBuildTool
-  where
-    assertUsesLatestBuildTool out = do
-      assertOutputContains "my-build-tool-dep-3.0 (exe:my-build-tool)" out
-      assertOutputDoesNotContain "my-build-tool-dep-2.0" out
-
-    assertDoesNotUseLatestBuildTool out = do
-      assertOutputContains "my-build-tool-dep-2.0 (exe:my-build-tool)" out
-      assertOutputDoesNotContain "my-build-tool-dep-3.0" out
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/repo/my-build-tool-dep-1.0/my-build-tool-dep.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/repo/my-build-tool-dep-1.0/my-build-tool-dep.cabal
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/NewFreeze/repo/my-build-tool-dep-1.0/my-build-tool-dep.cabal
+++ /dev/null
@@ -1,9 +0,0 @@
-name: my-build-tool-dep
-version: 1.0
-cabal-version: >= 1.20
-build-type: Simple
-
-executable my-build-tool
-  main-is: Main.hs
-  build-depends: base
-  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/repo/my-build-tool-dep-2.0/my-build-tool-dep.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/repo/my-build-tool-dep-2.0/my-build-tool-dep.cabal
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/NewFreeze/repo/my-build-tool-dep-2.0/my-build-tool-dep.cabal
+++ /dev/null
@@ -1,9 +0,0 @@
-name: my-build-tool-dep
-version: 2.0
-cabal-version: >= 1.20
-build-type: Simple
-
-executable my-build-tool
-  main-is: Main.hs
-  build-depends: base
-  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/repo/my-build-tool-dep-3.0/my-build-tool-dep.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/repo/my-build-tool-dep-3.0/my-build-tool-dep.cabal
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/NewFreeze/repo/my-build-tool-dep-3.0/my-build-tool-dep.cabal
+++ /dev/null
@@ -1,9 +0,0 @@
-name: my-build-tool-dep
-version: 3.0
-cabal-version: >= 1.20
-build-type: Simple
-
-executable my-build-tool
-  main-is: Main.hs
-  build-depends: base
-  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewFreeze/repo/my-library-dep-1.0/my-library-dep.cabal b/cabal/cabal-testsuite/PackageTests/NewFreeze/repo/my-library-dep-1.0/my-library-dep.cabal
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/NewFreeze/repo/my-library-dep-1.0/my-library-dep.cabal
+++ /dev/null
@@ -1,9 +0,0 @@
-name: my-library-dep
-version: 1.0
-cabal-version: >= 1.20
-build-type: Simple
-
-library
-  build-depends: base
-  build-tool-depends: my-build-tool-dep:my-build-tool < 2
-  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/Main.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/Main.hs
@@ -0,0 +1,4 @@
+module Main (main) where
+
+main :: IO ()
+main = putStrLn "Hello, world!"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/cabal.project b/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/cabal.project
@@ -0,0 +1,1 @@
+packages: .
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic-0.tar.gz b/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic-0.tar.gz
new file mode 100644
Binary files /dev/null and b/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic-0.tar.gz differ
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic.cabal b/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic.cabal
@@ -0,0 +1,7 @@
+cabal-version: 2.2
+name: deterministic
+version: 0
+
+executable dummy
+  default-language: Haskell2010
+  main-is: Main.hs
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic.out b/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic.out
@@ -0,0 +1,2 @@
+# cabal new-sdist
+Wrote tarball sdist to <ROOT>/dist-newstyle/sdist/deterministic-0.tar.gz
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic.test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic.test.hs
@@ -0,0 +1,18 @@
+import Test.Cabal.Prelude
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Base16 as BS16
+import qualified Crypto.Hash.SHA256 as SHA256
+import System.FilePath
+    ( (</>) )
+
+main = cabalTest $ do
+    cabal "new-sdist" ["deterministic"]
+    env <- getTestEnv
+    let dir = testCurrentDir env
+        knownSdist = dir </> "deterministic-0.tar.gz"
+        mySdist = dir </> "dist-newstyle" </> "sdist" </> "deterministic-0.tar.gz"
+    
+    known <- liftIO (BS.readFile knownSdist)
+    unknown <- liftIO (BS.readFile mySdist)
+
+    assertEqual "hashes didn't match for sdist" (BS16.encode $ SHA256.hash known) (BS16.encode $ SHA256.hash unknown)
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/a/Main.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/a/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/a/Main.hs
@@ -0,0 +1,1 @@
+main = putStrLn "Main.hs"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/a/a.cabal b/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/a/a.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/a/a.cabal
@@ -0,0 +1,9 @@
+cabal-version: 2.2
+name: a
+version: 1
+extra-doc-files:
+  doc/*.html
+
+executable a
+  default-language: Haskell2010
+  main-is: Main.hs
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/a/doc/index.html b/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/a/doc/index.html
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/a/doc/index.html
@@ -0,0 +1,1 @@
+index.html
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/cabal.out b/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/cabal.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/cabal.out
@@ -0,0 +1,4 @@
+# cabal new-sdist
+a/Main.hs
+a/a.cabal
+a/doc/index.html
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/cabal.project b/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/cabal.project
@@ -0,0 +1,2 @@
+packages:
+  a/
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/Globbing/cabal.test.hs
@@ -0,0 +1,4 @@
+import Test.Cabal.Prelude
+main = cabalTest $ withSourceCopy $ do
+  cabal "new-sdist" ["a", "--list-only"]
+
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/Main.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/Main.hs
@@ -0,0 +1,4 @@
+module Main (main) where
+
+main :: IO ()
+main = putStrLn "Hello, World!"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/cabal.project b/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/cabal.project
@@ -0,0 +1,1 @@
+packages: .
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/many-data-files.cabal b/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/many-data-files.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/many-data-files.cabal
@@ -0,0 +1,9 @@
+cabal-version: 2.2
+name: many-data-files
+version: 0
+
+data-files: data/*.txt
+
+executable dummy
+    default-language: Haskell2010
+    main-is: Main.hs
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/many-data-files.out b/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/many-data-files.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/many-data-files.out
@@ -0,0 +1,2 @@
+# cabal new-sdist
+Wrote tarball sdist to <ROOT>/many-data-files.dist/source/dist-newstyle/sdist/many-data-files-0.tar.gz
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/many-data-files.test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/many-data-files.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/ManyDataFiles/many-data-files.test.hs
@@ -0,0 +1,17 @@
+import Test.Cabal.Prelude
+
+import Control.Applicative ((<$>))
+import System.Directory ( createDirectoryIfMissing )
+import qualified Data.ByteString.Char8 as BS
+
+main = cabalTest . withSourceCopy $ do
+    limit <- getOpenFilesLimit
+    cwd <- testCurrentDir <$> getTestEnv
+
+    case limit of
+        Just n -> do
+            liftIO $ createDirectoryIfMissing False (cwd </> "data")
+            forM_ [1 .. n + 100] $ \i -> 
+                liftIO $ BS.writeFile (cwd </> "data" </> ("data-file-" ++ show i) <.> "txt") (BS.pack "a data file\n")
+            cabal "new-sdist" ["many-data-files"]
+        Nothing -> skip
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/a/Main.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/a/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/a/Main.hs
@@ -0,0 +1,1 @@
+main = putStrLn "a"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/a/Test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/a/Test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/a/Test.hs
@@ -0,0 +1,1 @@
+main = putStrLn "a-test"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/a/a.cabal b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/a/a.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/a/a.cabal
@@ -0,0 +1,12 @@
+cabal-version: 2.2
+name: a
+version: 0.1
+
+executable a
+  default-language: Haskell2010
+  main-is: Main.hs
+
+test-suite a-tests
+  default-language: Haskell2010
+  main-is: Test.hs
+  type: exitcode-stdio-1.0
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all-output-dir.out b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all-output-dir.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all-output-dir.out
@@ -0,0 +1,3 @@
+# cabal new-sdist
+Wrote tarball sdist to <ROOT>/all-output-dir.dist/source/archives/a-0.1.tar.gz
+Wrote tarball sdist to <ROOT>/all-output-dir.dist/source/archives/b-0.1.tar.gz
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all-output-dir.test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all-output-dir.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all-output-dir.test.hs
@@ -0,0 +1,10 @@
+import Test.Cabal.Prelude
+import System.Directory
+main = cabalTest $ withSourceCopy $ do
+  cwd <- fmap testCurrentDir getTestEnv
+  liftIO $ createDirectoryIfMissing False $ cwd </> "archives"
+  cabal "new-sdist" ["all", "--output-dir", "archives"]
+  shouldNotExist $ cwd </> "dist-newstyle/sdist/a-0.1.tar.gz"
+  shouldNotExist $ cwd </> "dist-newstyle/sdist/b-0.1.tar.gz"
+  shouldExist $ cwd </> "archives/a-0.1.tar.gz"
+  shouldExist $ cwd </> "archives/b-0.1.tar.gz"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all-test-sute.out b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all-test-sute.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all-test-sute.out
@@ -0,0 +1,2 @@
+# cabal new-sdist
+cabal: It is not possible to package only the test suites from a package for distribution. Only entire packages may be packaged for distribution.
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all-test-sute.test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all-test-sute.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all-test-sute.test.hs
@@ -0,0 +1,6 @@
+import Test.Cabal.Prelude
+main = cabalTest $ withSourceCopy $ do
+  cwd <- fmap testCurrentDir getTestEnv
+  fails $ cabal "new-sdist" ["all:tests"]
+  shouldNotExist $ cwd </> "dist-newstyle/sdist/a-0.1.tar.gz"
+  shouldNotExist $ cwd </> "dist-newstyle/sdist/b-0.1.tar.gz"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all.out b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all.out
@@ -0,0 +1,3 @@
+# cabal new-sdist
+Wrote tarball sdist to <ROOT>/all.dist/source/dist-newstyle/sdist/a-0.1.tar.gz
+Wrote tarball sdist to <ROOT>/all.dist/source/dist-newstyle/sdist/b-0.1.tar.gz
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all.test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/all.test.hs
@@ -0,0 +1,6 @@
+import Test.Cabal.Prelude
+main = cabalTest $ withSourceCopy $ do
+  cwd <- fmap testCurrentDir getTestEnv
+  cabal "new-sdist" ["all"]
+  shouldExist $ cwd </> "dist-newstyle/sdist/a-0.1.tar.gz"
+  shouldExist $ cwd </> "dist-newstyle/sdist/b-0.1.tar.gz"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/b/Main.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/b/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/b/Main.hs
@@ -0,0 +1,1 @@
+main = putStrLn "b"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/b/b.cabal b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/b/b.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/b/b.cabal
@@ -0,0 +1,7 @@
+cabal-version: 2.2
+name: b
+version: 0.1
+
+executable b
+  default-language: Haskell2010
+  main-is: Main.hs
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/cabal.project b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/cabal.project
@@ -0,0 +1,3 @@
+packages:
+  a/
+  b/
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/list-sources-output-dir.out b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/list-sources-output-dir.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/list-sources-output-dir.out
@@ -0,0 +1,3 @@
+# cabal new-sdist
+Wrote source list to <ROOT>/list-sources-output-dir.dist/source/lists/a-0.1.list
+Wrote source list to <ROOT>/list-sources-output-dir.dist/source/lists/b-0.1.list
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/list-sources-output-dir.test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/list-sources-output-dir.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/list-sources-output-dir.test.hs
@@ -0,0 +1,9 @@
+import Test.Cabal.Prelude
+import System.Directory
+import System.FilePath
+main = cabalTest $ withSourceCopy $ do
+  cwd <- fmap testCurrentDir getTestEnv
+  liftIO $ createDirectoryIfMissing False $ cwd </> "lists"
+  cabal "new-sdist" ["all", "--list-only", "--output-dir", "lists"]
+  assertFindInFile (normalise "a/a.cabal") (cwd </> "lists/a-0.1.list")
+  assertFindInFile (normalise "b/b.cabal") (cwd </> "lists/b-0.1.list")
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-archive-to-stdout.out b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-archive-to-stdout.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-archive-to-stdout.out
@@ -0,0 +1,2 @@
+# cabal new-sdist
+cabal: Can't write multiple tarballs to standard output!
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-archive-to-stdout.test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-archive-to-stdout.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-archive-to-stdout.test.hs
@@ -0,0 +1,6 @@
+import Test.Cabal.Prelude
+main = cabalTest $ withSourceCopy $ do
+  cwd <- fmap testCurrentDir getTestEnv
+  fails $ cabal "new-sdist" ["a", "b", "--output-dir", "-"]
+  shouldNotExist $ cwd </> "dist-newstyle/sdist/a-0.1.tar.gz"
+  shouldNotExist $ cwd </> "dist-newstyle/sdist/b-0.1.tar.gz"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-list-sources.out b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-list-sources.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-list-sources.out
@@ -0,0 +1,6 @@
+# cabal new-sdist
+a/Main.hs
+a/Test.hs
+a/a.cabal
+b/Main.hs
+b/b.cabal
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-list-sources.test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-list-sources.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-list-sources.test.hs
@@ -0,0 +1,4 @@
+import Test.Cabal.Prelude
+import Data.List
+main = cabalTest $ withSourceCopy $
+  cabal "new-sdist" ["a", "b", "--list-only"]
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-target.out b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-target.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-target.out
@@ -0,0 +1,3 @@
+# cabal new-sdist
+Wrote tarball sdist to <ROOT>/multi-target.dist/source/dist-newstyle/sdist/a-0.1.tar.gz
+Wrote tarball sdist to <ROOT>/multi-target.dist/source/dist-newstyle/sdist/b-0.1.tar.gz
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-target.test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-target.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/multi-target.test.hs
@@ -0,0 +1,6 @@
+import Test.Cabal.Prelude
+main = cabalTest $ withSourceCopy $ do
+  cwd <- fmap testCurrentDir getTestEnv
+  cabal "new-sdist" ["a", "b"]
+  shouldExist $ cwd </> "dist-newstyle/sdist/a-0.1.tar.gz"
+  shouldExist $ cwd </> "dist-newstyle/sdist/b-0.1.tar.gz"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/target-remote-package.out b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/target-remote-package.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/target-remote-package.out
@@ -0,0 +1,2 @@
+# cabal new-sdist
+cabal: The package base cannot be packaged for distribution, because it is not local to this project.
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/target-remote-package.test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/target-remote-package.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/target-remote-package.test.hs
@@ -0,0 +1,5 @@
+import Test.Cabal.Prelude
+main = cabalTest $ withSourceCopy $ do
+  cwd <- fmap testCurrentDir getTestEnv
+  fails $ cabal "new-sdist" ["a", "base"]
+  shouldNotExist $ cwd </> "dist-newstyle/sdist/a-0.1.tar.gz"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/valid-and-test-suite.out b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/valid-and-test-suite.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/valid-and-test-suite.out
@@ -0,0 +1,2 @@
+# cabal new-sdist
+cabal: The component test suite 'a-tests' cannot be packaged for distribution on its own. Only entire packages may be packaged for distribution.
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/valid-and-test-suite.test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/valid-and-test-suite.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/MultiTarget/valid-and-test-suite.test.hs
@@ -0,0 +1,6 @@
+import Test.Cabal.Prelude
+main = cabalTest $ withSourceCopy $ do
+  cwd <- fmap testCurrentDir getTestEnv
+  fails $ cabal "new-sdist" ["a", "b", "a-tests"]
+  shouldNotExist $ cwd </> "dist-newstyle/sdist/a-0.1.tar.gz"
+  shouldNotExist $ cwd </> "dist-newstyle/sdist/b-0.1.tar.gz"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/Main.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/Main.hs
@@ -0,0 +1,1 @@
+main = putStrLn "Main.hs"
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/cabal.out b/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/cabal.out
new file mode 100644
Binary files /dev/null and b/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/cabal.out differ
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/cabal.project b/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/cabal.project
@@ -0,0 +1,2 @@
+packages:
+  ./
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/cabal.test.hs
@@ -0,0 +1,4 @@
+import Test.Cabal.Prelude
+import Data.List
+main = cabalTest $
+  cabal "new-sdist" ["--list-only", "--null"]
diff --git a/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/test.cabal b/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/test.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/NewSdist/NullTerminated/test.cabal
@@ -0,0 +1,7 @@
+cabal-version: 2.2
+name: test
+version: 0.1
+
+executable a
+  default-language: Haskell2010
+  main-is: Main.hs
diff --git a/cabal/cabal-testsuite/PackageTests/Outdated/outdated-project-file.out b/cabal/cabal-testsuite/PackageTests/Outdated/outdated-project-file.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Outdated/outdated-project-file.out
@@ -0,0 +1,10 @@
+# cabal v1-update
+Downloading the latest package list from test-local-repo
+# cabal outdated
+Outdated dependencies:
+base ==3.0.3.2 (latest: 4.0.0.0)
+# cabal outdated
+Outdated dependencies:
+base ==3.0.3.2 (latest: 4.0.0.0)
+# cabal outdated
+cabal: --project-file must only be used with --new-freeze-file.
diff --git a/cabal/cabal-testsuite/PackageTests/Outdated/outdated-project-file.test.hs b/cabal/cabal-testsuite/PackageTests/Outdated/outdated-project-file.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Outdated/outdated-project-file.test.hs
@@ -0,0 +1,13 @@
+import Test.Cabal.Prelude
+main = cabalTest $ withRepo "repo" $ do
+  res <- cabal' "outdated" ["--new-freeze-file", "--project-file", "variant.project"]
+  assertOutputContains "base" res
+  assertOutputDoesNotContain "template-haskell" res
+
+  -- Test last-one-wins behaviour.
+  res <- cabal' "outdated" ["--new-freeze-file", "--project-file", "cabal.project", "--project-file", "variant.project"]
+  assertOutputContains "base" res
+  assertOutputDoesNotContain "template-haskell" res
+
+  -- Test for erroring on --project-file without --new-freeze-file
+  fails $ cabal "outdated" ["--project-file", "variant.project"]
diff --git a/cabal/cabal-testsuite/PackageTests/Outdated/outdated.out b/cabal/cabal-testsuite/PackageTests/Outdated/outdated.out
--- a/cabal/cabal-testsuite/PackageTests/Outdated/outdated.out
+++ b/cabal/cabal-testsuite/PackageTests/Outdated/outdated.out
@@ -1,4 +1,4 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
 # cabal outdated
 Outdated dependencies:
diff --git a/cabal/cabal-testsuite/PackageTests/Outdated/outdated_freeze.out b/cabal/cabal-testsuite/PackageTests/Outdated/outdated_freeze.out
--- a/cabal/cabal-testsuite/PackageTests/Outdated/outdated_freeze.out
+++ b/cabal/cabal-testsuite/PackageTests/Outdated/outdated_freeze.out
@@ -1,4 +1,4 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
 # cabal outdated
 Outdated dependencies:
diff --git a/cabal/cabal-testsuite/PackageTests/Outdated/variant.project b/cabal/cabal-testsuite/PackageTests/Outdated/variant.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Outdated/variant.project
@@ -0,0 +1,1 @@
+packages: .
diff --git a/cabal/cabal-testsuite/PackageTests/Outdated/variant.project.freeze b/cabal/cabal-testsuite/PackageTests/Outdated/variant.project.freeze
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Outdated/variant.project.freeze
@@ -0,0 +1,1 @@
+constraints: base == 3.0.3.2
diff --git a/cabal/cabal-testsuite/PackageTests/PathsModule/Library/my.cabal b/cabal/cabal-testsuite/PackageTests/PathsModule/Library/my.cabal
--- a/cabal/cabal-testsuite/PackageTests/PathsModule/Library/my.cabal
+++ b/cabal/cabal-testsuite/PackageTests/PathsModule/Library/my.cabal
@@ -1,11 +1,11 @@
+Cabal-version: 2.1
 name: PathsModule
 version: 0.1
-license: BSD3
+license: BSD-3-Clause
 author: Johan Tibell
 stability: stable
 category: PackageTests
 build-type: Simple
-Cabal-version: >= 1.2
 
 description:
     Check that the generated paths module compiles.
@@ -13,3 +13,22 @@
 Library
     exposed-modules: Paths_PathsModule
     build-depends: base
+    default-language: Haskell2010
+    default-extensions:
+        -- This is a non-exhaustive list of extensions that can cause code to
+        -- not compile when it would if the extension was disabled. This ensures
+        -- that autogen modules are compatible with default extensions.
+        NoImplicitPrelude
+        CPP
+        TemplateHaskell
+        QuasiQuotes
+        Arrows
+        OverloadedStrings
+    if impl(ghc >= 6.12)
+       default-extensions: MonoLocalBinds
+    if impl(ghc >= 7.0.1)
+       default-extensions: RebindableSyntax
+    if impl(ghc >= 7.4.1)
+       default-extensions: NoTraditionalRecordSyntax
+    if impl(ghc >= 7.8.1)
+       default-extensions: OverloadedLists
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/pkg/Main.hs b/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/pkg/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/pkg/Main.hs
@@ -0,0 +1,1 @@
+main = putStrLn "Main.hs"
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/pkg/a.cabal b/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/pkg/a.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/pkg/a.cabal
@@ -0,0 +1,9 @@
+cabal-version: 2.2
+name: a
+version: 0
+extra-source-files:
+  doc/*.html
+
+executable foo
+  main-is: Main.hs
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/pkg/doc/hello.html b/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/pkg/doc/hello.html
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/pkg/doc/hello.html
@@ -0,0 +1,1 @@
+hello.html
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/setup.out b/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/setup.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/setup.out
@@ -0,0 +1,2 @@
+# Setup configure
+Configuring a-0...
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/setup.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/setup.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/HadrianT634/setup.test.hs
@@ -0,0 +1,4 @@
+import Test.Cabal.Prelude
+import Test.Cabal.Script
+main = setupTest $
+  void $ setup'' "pkg" "configure" ["--cabal-file", "pkg/a.cabal"]
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T3199/sandbox.out b/cabal/cabal-testsuite/PackageTests/Regression/T3199/sandbox.out
--- a/cabal/cabal-testsuite/PackageTests/Regression/T3199/sandbox.out
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T3199/sandbox.out
@@ -1,8 +1,8 @@
-# cabal sandbox init
+# cabal v1-sandbox init
 Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config
 Creating a new sandbox at <ROOT>/sandbox.dist/sandbox
-# cabal sandbox add-source
-# cabal install
+# cabal v1-sandbox add-source
+# cabal v1-install
 Resolving dependencies...
 In order, the following would be installed:
 Cabal-2.0.0.0 (new version)
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T3199/sandbox.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T3199/sandbox.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Regression/T3199/sandbox.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T3199/sandbox.test.hs
@@ -5,7 +5,7 @@
     skipUnless =<< ghcVersionIs (< mkVersion [8,0])
     withSandbox $ do
         cabal_sandbox "add-source" ["Cabal"]
-        cabal "install"
+        cabal "v1-install"
             -- Ignore the Cabal library that is under test
             ["--package-db=clear", "--package-db=global"
             ,"--only-dep", "--dry-run"]
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T3436/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T3436/cabal.test.hs
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/Regression/T3436/cabal.test.hs
+++ /dev/null
@@ -1,8 +0,0 @@
-import Test.Cabal.Prelude
-main = cabalTest $ do
-    -- NB: This test doesn't really test #3436, because Cabal-1.2
-    -- isn't in the system database and thus we can't see if the
-    -- depsolver incorrectly chooses it.  Worth fixing if we figure
-    -- out how to simulate the "global" database without root.
-    r <- fails $ cabal' "new-build" ["custom-setup"]
-    assertOutputContains "This is Cabal-2.0" r
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T3436/sandbox.out b/cabal/cabal-testsuite/PackageTests/Regression/T3436/sandbox.out
--- a/cabal/cabal-testsuite/PackageTests/Regression/T3436/sandbox.out
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T3436/sandbox.out
@@ -1,22 +1,22 @@
-# cabal sandbox init
+# cabal v1-sandbox init
 Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config
 Creating a new sandbox at <ROOT>/sandbox.dist/sandbox
-# cabal install
+# cabal v1-install
 Resolving dependencies...
 Configuring Cabal-1.2...
 Preprocessing library for Cabal-1.2..
 Building library for Cabal-1.2..
 Installing library in <PATH>
-Installed Cabal-1.2
-# cabal sandbox add-source
-# cabal install
+Completed    Cabal-1.2
+# cabal v1-sandbox add-source
+# cabal v1-install
 Resolving dependencies...
 Configuring Cabal-2.0...
 Preprocessing library for Cabal-2.0..
 Building library for Cabal-2.0..
 Installing library in <PATH>
-Installed Cabal-2.0
+Completed    Cabal-2.0
 Failed to install custom-setup-1.0
 cabal: Error: some packages failed to install:
-custom-setup-1.0-92JpsxIMpiQHysxYdDtEVq failed during the configure step. The exception was:
+custom-setup-1.0-KL06TzJxSBkDtcPp9Xd2v1 failed during the configure step. The exception was:
   ExitFailure 1
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T3436/sandbox.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T3436/sandbox.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Regression/T3436/sandbox.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T3436/sandbox.test.hs
@@ -11,11 +11,11 @@
 -- setup-depends).
 main = cabalTest $ do
     withSandbox $ do
-        cabal "install" ["./Cabal-1.2"]
+        cabal "v1-install" ["./Cabal-1.2"]
         cabal_sandbox "add-source" ["Cabal-2.0"]
 
         -- cabal should build custom-setup's setup script with Cabal-2.0, but
         -- then configure should fail because Setup just prints an error message
         -- imported from Cabal and exits.
-        r <- fails $ cabal' "install" ["custom-setup/"]
+        r <- fails $ cabal' "v1-install" ["custom-setup/"]
         assertOutputContains "This is Cabal-2.0" r
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T3932/cabal.out b/cabal/cabal-testsuite/PackageTests/Regression/T3932/cabal.out
--- a/cabal/cabal-testsuite/PackageTests/Regression/T3932/cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T3932/cabal.out
@@ -1,2 +1,2 @@
-# cabal update
+# cabal v1-update
 Downloading the latest package list from test-local-repo
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T3932/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T3932/cabal.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Regression/T3932/cabal.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T3932/cabal.test.hs
@@ -5,8 +5,11 @@
     -- extra constraint that setup Cabal must be 1.20.  If we don't
     -- have a choice like this available, the unsatisfied constraint
     -- won't be reported.
+    --
+    -- Due to #415, the lower bound may be even higher based on GHC
+    -- version
     withRepo "repo" $ do
         -- Don't record because output wobbles based on installed database.
         recordMode DoNotRecord $ do
             fails (cabal' "new-build" []) >>=
-                assertOutputContains "Setup.hs requires >=1.20"
+                assertOutputContains "Setup.hs requires >="
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4154/install-time-with-constraint.out b/cabal/cabal-testsuite/PackageTests/Regression/T4154/install-time-with-constraint.out
--- a/cabal/cabal-testsuite/PackageTests/Regression/T4154/install-time-with-constraint.out
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4154/install-time-with-constraint.out
@@ -1,8 +1,5 @@
-# cabal update
-Downloading the latest package list from test-local-repo
 # cabal new-build
 Resolving dependencies...
 Build profile: -w ghc-<GHCVER> -O1
 In order, the following would be built:
- - Cabal-99999 (lib) (requires download & build)
  - time-99999 (lib:time) (first run)
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4154/install-time-with-constraint.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T4154/install-time-with-constraint.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Regression/T4154/install-time-with-constraint.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4154/install-time-with-constraint.test.hs
@@ -2,14 +2,17 @@
 
 -- Test that unqualified command line constraints do not constrain setup
 -- dependencies. cabal should be able to install the local time-99999 by
--- building its setup script with the installed time, even though the installed
--- time doesn't fit the constraint.
-main = cabalTest $ withRepo "repo" $ do
+-- building its setup script with the installed Cabal, which depends on the
+-- installed time, even though the installed time doesn't fit the constraint.
+main = cabalTest $ do
   cabal "new-build" ["time", "--constraint=time==99999", "--dry-run"]
 
   -- Temporarily disabled recording here because output is not stable
   recordMode DoNotRecord $ do
-      -- Constraining all uses of 'time' results in a cyclic dependency
-      -- between 'Cabal' and the new 'time'.
-      r <- fails $ cabal' "new-build" ["time", "--constraint=any.time==99999", "--dry-run"]
-      assertOutputContains "cyclic dependencies; conflict set: time:setup.Cabal, time:setup.time" r
+    -- Constraining all uses of 'time' fails because the installed 'time'
+    -- doesn't fit the constraint.
+    r <- fails $ cabal' "new-build" ["time", "--constraint=any.time==99999", "--dry-run"]
+    assertRegex "Expected cabal to reject the setup dependency on the installed time"
+                ("rejecting: time:setup.time-[0-9.]*/installed-[^[:space:]]* "
+                  ++ "\\(constraint from command line flag requires ==99999\\)")
+                r
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4154/repo/Cabal-99999/Cabal.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T4154/repo/Cabal-99999/Cabal.cabal
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/Regression/T4154/repo/Cabal-99999/Cabal.cabal
+++ /dev/null
@@ -1,7 +0,0 @@
-name:            Cabal
-version:         99999
-cabal-version:   >=1.8
-build-type:      Simple
-
-library
-  build-depends: base, time
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4154/time.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T4154/time.cabal
--- a/cabal/cabal-testsuite/PackageTests/Regression/T4154/time.cabal
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4154/time.cabal
@@ -4,7 +4,7 @@
 build-type:      Custom
 
 custom-setup
-  setup-depends: base, Cabal == 99999
+  setup-depends: base, Cabal
 
 library
   build-depends: base
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4270/T4270.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T4270/T4270.cabal
--- a/cabal/cabal-testsuite/PackageTests/Regression/T4270/T4270.cabal
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4270/T4270.cabal
@@ -1,6 +1,5 @@
 name: T4270
 version: 0.1
-cabal-version: >= 1.2
 license: BSD3
 author: Benno Fünfstück
 stability: stable
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4449/A.hs b/cabal/cabal-testsuite/PackageTests/Regression/T4449/A.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4449/A.hs
@@ -0,0 +1,1 @@
+module A where
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4449/Setup.hs b/cabal/cabal-testsuite/PackageTests/Regression/T4449/Setup.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4449/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4449/setup.out b/cabal/cabal-testsuite/PackageTests/Regression/T4449/setup.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4449/setup.out
@@ -0,0 +1,6 @@
+# Setup configure
+Resolving dependencies...
+Configuring test-t4449-0.1.0.0...
+# Setup build
+Preprocessing library for test-t4449-0.1.0.0..
+Building library for test-t4449-0.1.0.0..
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4449/setup.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T4449/setup.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4449/setup.test.hs
@@ -0,0 +1,5 @@
+import Test.Cabal.Prelude
+main = cabalTest $ do
+    skipIf =<< (ghcVersionIs (< mkVersion [7,10]))
+    setup "configure" []
+    setup "build" []
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4449/test-t4449.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T4449/test-t4449.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4449/test-t4449.cabal
@@ -0,0 +1,13 @@
+name:                test-t4449
+version:             0.1.0.0
+license:             BSD3
+author:              Test
+maintainer:          test@example.com
+build-type:          Simple
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     A
+  build-depends:       base
+  default-language:    Haskell2010
+  ghc-options:         -trust base -trust containers
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4720/bug/Main.hs b/cabal/cabal-testsuite/PackageTests/Regression/T4720/bug/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4720/bug/Main.hs
@@ -0,0 +1,4 @@
+module Main where
+
+main :: IO ()
+main = return ()
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4720/bug/bug.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T4720/bug/bug.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4720/bug/bug.cabal
@@ -0,0 +1,12 @@
+cabal-version: 1.12
+
+name: bug
+version: 0
+build-type: Simple
+
+test-suite test
+  default-language: Haskell2010
+  main-is: Main.hs
+  type: exitcode-stdio-1.0
+  build-depends: base
+  c-sources: cbits/bug.c
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4720/bug/cbits/bug.c b/cabal/cabal-testsuite/PackageTests/Regression/T4720/bug/cbits/bug.c
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4720/bug/cbits/bug.c
@@ -0,0 +1,2 @@
+#include <stdlib.h>
+#include <bug-extra-inc.h>
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4720/bug/extra-inc/bug-extra-inc.h b/cabal/cabal-testsuite/PackageTests/Regression/T4720/bug/extra-inc/bug-extra-inc.h
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4720/bug/extra-inc/bug-extra-inc.h
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4720/cabal.out b/cabal/cabal-testsuite/PackageTests/Regression/T4720/cabal.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4720/cabal.out
@@ -0,0 +1,8 @@
+# cabal new-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - bug-0 (test:test) (first run)
+Configuring test suite 'test' for bug-0..
+Preprocessing test suite 'test' for bug-0..
+Building test suite 'test' for bug-0..
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4720/cabal.project b/cabal/cabal-testsuite/PackageTests/Regression/T4720/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4720/cabal.project
@@ -0,0 +1,4 @@
+packages: ./bug
+
+package bug
+  extra-include-dirs: ./extra-inc
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4720/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T4720/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4720/cabal.test.hs
@@ -0,0 +1,3 @@
+import Test.Cabal.Prelude
+main = cabalTest $ do
+    cabal "new-build" ["test"]
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4986/cabal.out b/cabal/cabal-testsuite/PackageTests/Regression/T4986/cabal.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4986/cabal.out
@@ -0,0 +1,6 @@
+# cabal new-configure
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following would be built:
+ - happy-999.999.999 (exe:happy) (first run)
+ - client-0.1.0.0 (exe:hello-world) (first run)
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4986/cabal.project b/cabal/cabal-testsuite/PackageTests/Regression/T4986/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4986/cabal.project
@@ -0,0 +1,1 @@
+packages: client, happy
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4986/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T4986/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4986/cabal.test.hs
@@ -0,0 +1,4 @@
+import Test.Cabal.Prelude
+main = cabalTest $
+    withSourceCopy $
+        cabal "new-configure" []
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4986/client/Hello.hs b/cabal/cabal-testsuite/PackageTests/Regression/T4986/client/Hello.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4986/client/Hello.hs
@@ -0,0 +1,1 @@
+main = return ()
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4986/client/client.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T4986/client/client.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4986/client/client.cabal
@@ -0,0 +1,14 @@
+name:                client
+version:             0.1.0.0
+synopsis:            Checks build-tools are put in PATH
+license:             BSD3
+category:            Testing
+build-type:          Simple
+cabal-version:       >=1.10
+
+executable             hello-world
+  main-is:             Hello.hs
+  build-depends:       base
+  build-tools:         happy
+  build-tool-depends:  happy:happy
+  default-language:    Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4986/happy/Main.hs b/cabal/cabal-testsuite/PackageTests/Regression/T4986/happy/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4986/happy/Main.hs
@@ -0,0 +1,1 @@
+main = return ()
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T4986/happy/happy.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T4986/happy/happy.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T4986/happy/happy.cabal
@@ -0,0 +1,12 @@
+name:                happy
+version:             999.999.999
+synopsis:            Checks double-dependency on build-tool works correctly
+license:             BSD3
+category:            Testing
+build-type:          Simple
+cabal-version:       >=1.10
+
+executable             happy
+  main-is:             Main.hs
+  build-depends:       base
+  default-language:    Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/T5309.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T5309/T5309.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/T5309.cabal
@@ -0,0 +1,149 @@
+cabal-version:      2.2
+category:           Example
+build-type:         Simple
+
+name:               T5309
+version:            1.0.0.0
+
+author:             Alex Washburn
+maintainer:         github@recursion.ninja
+copyright:          2018 Alex Washburn (recursion.ninja)
+                    
+synopsis:           A binding to a C++ hashtable for thread-safe memoization.
+
+description:        This package is designed to provide a "minimal working example"
+                    to test the cxx-sources and the cxx-options buildinfo flags.
+                    The code was pulled out PCG, https://github.com/amnh/pcg
+
+
+common ffi-build-info
+
+  -- We must provide the full relative path to every C file that the project depends on.
+  c-sources:        memoized-tcm/costMatrixWrapper.c
+                    memoized-tcm/dynamicCharacterOperations.c
+
+  cc-options:       --std=c11
+                     
+  cxx-sources:      memoized-tcm/costMatrix.cpp
+
+  cxx-options:      --std=c++11
+
+  default-language: Haskell2010
+
+  -- This library is required for the C++ standard template library.
+  extra-libraries:  stdc++
+
+  -- Here we list all directories that contain C header files that the FFI tools will need
+  -- to locate when preprocessing the C files. Without listing the directories containing
+  -- the C header files here, the FFI preprocession (hsc2hs, c2hs,etc.) will fail to locate
+  -- the requisite files.
+  -- Note also, that the parent directory of the nessicary C header files must be specified.
+  -- The preprocesser will not recursively look in subdirectories for C header files!
+  include-dirs:     memoized-tcm
+
+
+common language-spec
+
+  build-depends:    base       >=4.5.1
+--                  , lens
+       
+  default-language: Haskell2010
+
+  ghc-options:      -O2 -Wall
+
+                    
+common lib-build-info
+
+  hs-source-dirs:   lib
+
+  -- Modules exported by the library.
+  other-modules:    Bio.Character.Exportable.Class
+                    Data.TCM.Memoized
+                    Data.TCM.Memoized.FFI
+
+                    
+library
+
+  import:           ffi-build-info
+                  , language-spec
+
+  -- Modules exported by the library.
+  exposed-modules:  Bio.Character.Exportable.Class
+                    Data.TCM.Memoized
+                    Data.TCM.Memoized.FFI
+
+  hs-source-dirs:   lib
+                    
+
+executable exe-no-lib
+
+  import:           ffi-build-info
+                  , language-spec
+                  , lib-build-info
+
+  main-is:          Main.hs
+
+  hs-source-dirs:   app
+
+
+executable exe-with-lib
+
+  import:           language-spec
+
+  main-is:          Main.hs
+
+  build-depends:    T5309
+
+  hs-source-dirs:   app
+
+
+benchmark bench-no-lib
+
+  import:           ffi-build-info
+                  , language-spec
+                  , lib-build-info
+
+  main-is:          Main.hs
+
+  type:             exitcode-stdio-1.0
+                     
+  hs-source-dirs:   app
+
+ 
+benchmark bench-with-lib
+
+  import:           language-spec
+
+  main-is:          Main.hs
+
+  type:             exitcode-stdio-1.0
+
+  build-depends:    T5309
+
+  hs-source-dirs:   app
+
+ 
+test-suite test-no-lib
+
+  import:           ffi-build-info
+                  , language-spec
+                  , lib-build-info
+
+  main-is:          Main.hs
+
+  type:             exitcode-stdio-1.0
+                     
+  hs-source-dirs:   app
+
+
+test-suite test-with-lib
+
+  import:           language-spec
+
+  main-is:          Main.hs
+
+  type:             exitcode-stdio-1.0
+  
+  build-depends:    T5309
+                     
+  hs-source-dirs:   app
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/app/Main.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5309/app/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/app/Main.hs
@@ -0,0 +1,9 @@
+{-# LANGUAGE FlexibleContexts, TypeFamilies #-}
+
+module Main (main) where
+
+import Data.TCM.Memoized
+
+
+main :: IO ()
+main = generateMemoizedTransitionCostMatrix 5 (const (const 1)) `seq` return ()
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/cabal.out b/cabal/cabal-testsuite/PackageTests/Regression/T5309/cabal.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/cabal.out
@@ -0,0 +1,54 @@
+# cabal new-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - T5309-1.0.0.0 (lib) (first run)
+ - T5309-1.0.0.0 (exe:exe-no-lib) (first run)
+ - T5309-1.0.0.0 (exe:exe-with-lib) (first run)
+Configuring library for T5309-1.0.0.0..
+Preprocessing library for T5309-1.0.0.0..
+Building library for T5309-1.0.0.0..
+Configuring executable 'exe-no-lib' for T5309-1.0.0.0..
+Preprocessing executable 'exe-no-lib' for T5309-1.0.0.0..
+Building executable 'exe-no-lib' for T5309-1.0.0.0..
+Configuring executable 'exe-with-lib' for T5309-1.0.0.0..
+Preprocessing executable 'exe-with-lib' for T5309-1.0.0.0..
+Building executable 'exe-with-lib' for T5309-1.0.0.0..
+# cabal new-test
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - T5309-1.0.0.0 (test:test-no-lib) (first run)
+ - T5309-1.0.0.0 (test:test-with-lib) (first run)
+Configuring test suite 'test-no-lib' for T5309-1.0.0.0..
+Preprocessing test suite 'test-no-lib' for T5309-1.0.0.0..
+Building test suite 'test-no-lib' for T5309-1.0.0.0..
+Running 1 test suites...
+Test suite test-no-lib: RUNNING...
+Test suite test-no-lib: PASS
+Test suite logged to: <ROOT>/cabal.dist/work/./dist/build/<ARCH>/ghc-<GHCVER>/T5309-1.0.0.0/t/test-no-lib/test/T5309-1.0.0.0-test-no-lib.log
+1 of 1 test suites (1 of 1 test cases) passed.
+Configuring test suite 'test-with-lib' for T5309-1.0.0.0..
+Preprocessing test suite 'test-with-lib' for T5309-1.0.0.0..
+Building test suite 'test-with-lib' for T5309-1.0.0.0..
+Running 1 test suites...
+Test suite test-with-lib: RUNNING...
+Test suite test-with-lib: PASS
+Test suite logged to: <ROOT>/cabal.dist/work/./dist/build/<ARCH>/ghc-<GHCVER>/T5309-1.0.0.0/t/test-with-lib/test/T5309-1.0.0.0-test-with-lib.log
+1 of 1 test suites (1 of 1 test cases) passed.
+# cabal new-bench
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - T5309-1.0.0.0 (bench:bench-no-lib) (first run)
+ - T5309-1.0.0.0 (bench:bench-with-lib) (first run)
+Configuring benchmark 'bench-no-lib' for T5309-1.0.0.0..
+Preprocessing benchmark 'bench-no-lib' for T5309-1.0.0.0..
+Building benchmark 'bench-no-lib' for T5309-1.0.0.0..
+Running 1 benchmarks...
+Benchmark bench-no-lib: RUNNING...
+Benchmark bench-no-lib: FINISH
+Configuring benchmark 'bench-with-lib' for T5309-1.0.0.0..
+Preprocessing benchmark 'bench-with-lib' for T5309-1.0.0.0..
+Building benchmark 'bench-with-lib' for T5309-1.0.0.0..
+Running 1 benchmarks...
+Benchmark bench-with-lib: RUNNING...
+Benchmark bench-with-lib: FINISH
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/cabal.project b/cabal/cabal-testsuite/PackageTests/Regression/T5309/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/cabal.project
@@ -0,0 +1,2 @@
+packages:
+  ./
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5309/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/cabal.test.hs
@@ -0,0 +1,5 @@
+import Test.Cabal.Prelude
+main = cabalTest $ do
+        cabal "new-build" ["all"]
+        cabal "new-test"  ["all"]
+        cabal "new-bench" ["all"]
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/lib/Bio/Character/Exportable/Class.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5309/lib/Bio/Character/Exportable/Class.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/lib/Bio/Character/Exportable/Class.hs
@@ -0,0 +1,56 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Bio.Character.Exportable.Class
+-- Copyright   :  (c) 2015-2015 Ward Wheeler
+-- License     :  BSD-style
+--
+-- Maintainer  :  wheeler@amnh.org
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Class for needed operations of coded sequences and characters
+--
+--
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts, FlexibleInstances, FunctionalDependencies, MultiParamTypeClasses #-}
+
+module Bio.Character.Exportable.Class where
+
+
+import Foreign.C.Types 
+
+
+-- |
+-- Represents a sequence of fixed width characters packed into a bitwise form
+-- consumable by lower level functions.
+class Exportable c where
+
+    toExportableBuffer     :: c -> ExportableCharacterSequence
+    fromExportableBuffer   :: ExportableCharacterSequence -> c
+
+    toExportableElements   :: c -> Maybe ExportableCharacterElements
+    fromExportableElements :: ExportableCharacterElements -> c
+
+
+-- |
+-- A structure used for FFI calls.
+--
+-- 'bufferChunks' contains the bit-packed representation of the character sequence.
+data ExportableCharacterSequence
+   = ExportableCharacterSequence
+   { exportedElementCountSequence :: Int
+   , exportedElementWidthSequence :: Int
+   , exportedBufferChunks :: [CULong]
+   } deriving (Eq, Show)   
+
+
+-- |
+-- A structure used for FFI calls--
+-- 'characterElements' contains the integral value for each character element.
+data ExportableCharacterElements
+   = ExportableCharacterElements
+   { exportedElementCountElements :: Int
+   , exportedElementWidthElements :: Int 
+   , exportedCharacterElements :: [CUInt]
+   } deriving (Eq, Show)   
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/lib/Data/TCM/Memoized.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5309/lib/Data/TCM/Memoized.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/lib/Data/TCM/Memoized.hs
@@ -0,0 +1,45 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.TCM.Memoized
+-- Copyright   :  (c) 2015-2015 Ward Wheeler
+-- License     :  BSD-style
+--
+-- Maintainer  :  wheeler@amnh.org
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+
+module Data.TCM.Memoized
+  ( FFI.MemoizedCostMatrix
+  , generateMemoizedTransitionCostMatrix
+  , FFI.getMedianAndCost
+  ) where
+
+import qualified Data.TCM.Memoized.FFI as FFI
+
+
+-- |
+-- /O(n^2)/ where @n@ is the alphabet size.
+--
+-- Generate a memoized TCM by supplying the size of the symbol alphabet and the
+-- generating function for unambiguous symbol change cost to produce a memoized
+-- TCM. A memoized TCM computes all the costs and medians of unambiguous,
+-- singleton symbol set transitions strictly when this function is invoked. A
+-- memoized TCM calculates the cost and medians of ambiguous symbol sets in a
+-- lazy, memoized manner.
+--
+-- *Note:* The collection of ambiguous symbols set transitions is the powerset of
+-- the collection of unambiguous, singleton symbol sets. The lazy, memoization is
+-- a requisite for efficient computation on any non-trivial alphabet size.
+generateMemoizedTransitionCostMatrix
+  :: Word                   -- ^ Alphabet size
+  -> (Word -> Word -> Word) -- ^ Generating function
+  -> FFI.MemoizedCostMatrix
+generateMemoizedTransitionCostMatrix = FFI.getMemoizedCostMatrix
+
+{-
+-- Causes ambiguity with Data.TCM.(!)
+(!) :: Exportable s => FFI.MemoizedCostMatrix -> (s, s) -> (s, Word)
+(!) memo (x,y) = FFI.getMedianAndCost memo x y
+-}
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/lib/Data/TCM/Memoized/FFI.hsc b/cabal/cabal-testsuite/PackageTests/Regression/T5309/lib/Data/TCM/Memoized/FFI.hsc
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/lib/Data/TCM/Memoized/FFI.hsc
@@ -0,0 +1,280 @@
+-----------------------------------------------------------------------------
+-- |
+-- TODO: Document module.
+--
+-- Exports C types for dynamic characters and their constructors allong with
+-- an FFI binding for the memoizing TCM structure.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE BangPatterns, DeriveGeneric, FlexibleInstances, ForeignFunctionInterface, TypeSynonymInstances #-}
+
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+module Data.TCM.Memoized.FFI
+  ( CBufferUnit
+  , CDynamicChar(..)
+  , DCElement(..)
+  , ForeignVoid()
+  , MemoizedCostMatrix(costMatrix)
+  , getMemoizedCostMatrix
+  , getMedianAndCost
+  -- * Utility functions
+  , calculateBufferLength
+  , coerceEnum
+  , constructCharacterFromExportable
+  , constructElementFromExportable
+  , constructEmptyElement
+  ) where
+
+import Bio.Character.Exportable.Class
+import Data.Bits
+import Foreign         hiding (alignPtr)
+import Foreign.C.Types
+import GHC.Generics           (Generic)
+import System.IO.Unsafe
+
+-- import Debug.Trace
+
+#include "costMatrixWrapper.h"
+#include "dynamicCharacterOperations.h"
+
+
+-- |
+-- A convient type alias for improved clairity of use.
+type CBufferUnit  = CULong -- This will be compatible with uint64_t
+
+
+-- |
+-- Type of a dynamic character to pass back and forth across the FFI interface.
+data CDynamicChar
+   = CDynamicChar
+   { alphabetSizeChar :: CSize
+   , numElements      :: CSize
+   , dynCharLen       :: CSize
+   , dynChar          :: Ptr CBufferUnit
+   }
+
+
+-- |
+-- Represents a single element in a dynamic character in an exportable form.
+data DCElement = DCElement
+    { alphabetSizeElem :: CSize
+    , characterElement :: Ptr CBufferUnit
+    } deriving (Show)
+
+
+-- |
+-- A closed type wrapping a void pointer in C to the C++ memoized TCM.
+data ForeignVoid deriving (Generic)
+
+
+-- |
+-- A type-safe wrapper for the mutable, memoized TCm.
+newtype MemoizedCostMatrix
+      = MemoizedCostMatrix
+      { costMatrix :: StablePtr ForeignVoid
+      } deriving (Eq, Generic)
+
+
+{-
+-- | (✔)
+instance Show CDynamicChar where
+    show (CDynamicChar alphSize dcLen numElems dChar) =
+       mconcat
+         ["alphabetSize:  "
+         , show intAlphSize
+         , "\ndynCharLen: "
+         , show intLen
+         , "\nbuffer length: "
+         , show bufferLength
+         , "\ndynChar:    "
+         , show $ unsafePerformIO printedArr
+         ]
+        where
+            bufferLength = fromEnum numElems
+            intAlphSize  = fromEnum alphSize
+            intLen       = fromEnum dcLen
+            printedArr   = show <$> peekArray bufferLength dChar
+
+-}
+
+
+instance Storable CDynamicChar where
+
+    sizeOf    _ = (#size struct dynChar_t) -- #size is a built-in that works with arrays, as are #peek and #poke, below
+
+    alignment _ = alignment (undefined :: CBufferUnit)
+
+    peek ptr    = do -- to get values from the C app
+        alphLen <- (#peek struct dynChar_t, alphSize  ) ptr
+        nElems  <- (#peek struct dynChar_t, numElems  ) ptr
+        seqLen  <- (#peek struct dynChar_t, dynCharLen) ptr
+        seqVal  <- (#peek struct dynChar_t, dynChar   ) ptr
+        pure CDynamicChar
+             { alphabetSizeChar = alphLen
+             , numElements      = nElems
+             , dynCharLen       = seqLen
+             , dynChar          = seqVal
+             }
+
+    poke ptr (CDynamicChar alphLen nElems seqLen seqVal) = do -- to modify values in the C app
+        (#poke struct dynChar_t, alphSize  ) ptr alphLen
+        (#poke struct dynChar_t, numElems  ) ptr nElems
+        (#poke struct dynChar_t, dynCharLen) ptr seqLen
+        (#poke struct dynChar_t, dynChar   ) ptr seqVal
+
+
+-- | (✔)
+instance Storable DCElement where
+
+    sizeOf    _ = (#size struct dcElement_t)
+
+    alignment _ = alignment (undefined :: CBufferUnit)
+
+    peek ptr    = do
+        alphLen <- (#peek struct dcElement_t, alphSize) ptr
+        element <- (#peek struct dcElement_t, element ) ptr
+        pure DCElement
+            { alphabetSizeElem = alphLen
+            , characterElement = element
+            }
+
+    poke ptr (DCElement alphLen element) = do
+        (#poke struct dcElement_t, alphSize) ptr alphLen
+        (#poke struct dcElement_t, element ) ptr element
+
+
+
+-- TODO: For now we only allocate 2d matrices. 3d will come later.
+-- |
+-- Create and allocate cost matrix.
+-- The first argument, TCM, is only for non-ambiguous nucleotides, and it used to
+-- generate the entire cost matrix, which includes ambiguous elements. TCM is
+-- row-major, with each row being the left character element. It is therefore
+-- indexed not by powers of two, but by cardinal integer.
+foreign import ccall unsafe "costMatrixWrapper matrixInit"
+    initializeMemoizedCMfn_c :: CSize
+                             -> Ptr CInt
+                             -> IO (StablePtr ForeignVoid)
+
+
+foreign import ccall unsafe "costMatrix getCostAndMedian"
+    getCostAndMedianFn_c :: Ptr DCElement
+                         -> Ptr DCElement
+                         -> Ptr DCElement
+--                         -> CSize
+                         -> StablePtr ForeignVoid
+                         -> IO CInt
+
+
+-- |
+-- Set up and return a cost matrix.
+--
+-- The cost matrix is allocated strictly.
+getMemoizedCostMatrix :: Word
+                      -> (Word -> Word -> Word)
+                      -> MemoizedCostMatrix
+getMemoizedCostMatrix alphabetSize costFn = unsafePerformIO . withArray rowMajorList $ \allocedTCM -> do
+    !resultPtr <- initializeMemoizedCMfn_c (coerceEnum alphabetSize) allocedTCM
+    pure $ MemoizedCostMatrix resultPtr
+  where
+    rowMajorList = [ coerceEnum $ costFn i j | i <- range,  j <- range ]
+    range = [0 .. alphabetSize - 1]
+
+
+-- |
+-- /O(1)/ amortized.
+--
+-- Calculate the median symbol set and transition cost between the two input
+-- symbol sets.
+--
+-- *Note:* This operation is lazily evaluated and memoized for future calls.
+getMedianAndCost :: Exportable s => MemoizedCostMatrix -> s -> s -> (s, Word)
+getMedianAndCost memo lhs rhs = unsafePerformIO $ do
+    medianPtr     <- constructEmptyElement alphabetSize
+    lhs'          <- constructElementFromExportable lhs
+    rhs'          <- constructElementFromExportable rhs
+    !cost         <- getCostAndMedianFn_c lhs' rhs' medianPtr (costMatrix memo)
+    medianElement <- peek medianPtr
+    medianValue   <- fmap buildExportable . peekArray bufferLength $ characterElement medianElement
+    pure (medianValue, coerceEnum cost)
+  where
+    alphabetSize    = exportedElementWidthSequence $ toExportableBuffer lhs
+    buildExportable = fromExportableBuffer . ExportableCharacterSequence 1 alphabetSize
+    bufferLength    = calculateBufferLength alphabetSize 1
+
+
+-- |
+-- /O(1)/
+--
+-- Calculate the buffer length based on the element count and element bit width.
+calculateBufferLength :: Enum b
+                      => Int -- ^ Element count
+                      -> Int -- ^ Element bit width
+                      -> b
+calculateBufferLength count width = coerceEnum $ q + if r == 0 then 0 else 1
+   where
+    (q,r)  = (count * width) `divMod` finiteBitSize (undefined :: CULong)
+
+
+-- |
+-- Coerce one 'Enum' value to another through the type's corresponding 'Int'
+-- values.
+coerceEnum :: (Enum a, Enum b) => a -> b
+coerceEnum = toEnum . fromEnum
+
+
+-- |
+-- /O(n)/ where @n@ is the length of the dynamic character.
+--
+-- Malloc and populate a pointer to an exportable representation of the
+-- 'Exportable' value. The supplied value is assumed to be a dynamic character
+-- and the result is a pointer to a C representation of a dynamic character.
+constructCharacterFromExportable :: Exportable s => s -> IO (Ptr CDynamicChar)
+constructCharacterFromExportable exChar = do
+    valueBuffer <- newArray $ exportedBufferChunks exportableBuffer
+    charPointer <- malloc :: IO (Ptr CDynamicChar)
+    let charValue = CDynamicChar (coerceEnum width) (coerceEnum count) bufLen valueBuffer
+    !_ <- poke charPointer charValue
+    pure charPointer
+  where
+    count  = exportedElementCountSequence exportableBuffer
+    width  = exportedElementWidthSequence exportableBuffer
+    bufLen = calculateBufferLength count width
+    exportableBuffer = toExportableBuffer exChar
+
+
+-- |
+-- /O(1)/
+--
+-- Malloc and populate a pointer to an exportable representation of the
+-- 'Exportable' value. The supplied value is assumed to be a dynamic character
+-- element and the result is a pointer to a C representation of a dynamic
+-- character element.
+constructElementFromExportable :: Exportable s => s -> IO (Ptr DCElement)
+constructElementFromExportable exChar = do
+    valueBuffer    <- newArray $ exportedBufferChunks exportableBuffer
+    elementPointer <- malloc :: IO (Ptr DCElement)
+    let elementValue = DCElement (coerceEnum width) valueBuffer
+    !_ <- poke elementPointer elementValue
+    pure elementPointer
+  where
+    width  = exportedElementWidthSequence exportableBuffer
+    exportableBuffer = toExportableBuffer exChar
+
+
+-- |
+-- /O(1)/
+--
+-- Malloc and populate a pointer to a C representation of a dynamic character.
+-- The buffer of the resulting value is intentially zeroed out.
+constructEmptyElement :: Int -- ^ Bit width of a dynamic character element.
+                      -> IO (Ptr DCElement)
+constructEmptyElement alphabetSize = do
+    elementPointer <- malloc :: IO (Ptr DCElement)
+    valueBuffer    <- mallocArray bufferLength
+    let elementValue = DCElement (coerceEnum alphabetSize) valueBuffer
+    !_ <- poke elementPointer elementValue
+    pure elementPointer
+  where
+    bufferLength = calculateBufferLength alphabetSize 1
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrix.cpp b/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrix.cpp
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrix.cpp
@@ -0,0 +1,93 @@
+#include <inttypes.h>
+
+/*
+#include <climits>
+#include <cstdlib>
+#include <unordered_map>
+*/
+
+#include "costMatrix.h"
+#include "dynamicCharacterOperations.h"
+#include <cstring> //for memcpy;
+
+#define __STDC_FORMAT_MACROS
+
+// TODO: I'll need this for the Haskell side of things: https://hackage.haskell.org/package/base-4.9.0.0/docs/Foreign-StablePtr.html
+
+costMatrix_p construct_CostMatrix_C(size_t alphSize, int* tcm) {
+    return new CostMatrix(alphSize, tcm);
+}
+
+void destruct_CostMatrix_C(costMatrix_p untyped_self) {
+    delete static_cast<CostMatrix*> (untyped_self);
+}
+
+int call_getSetCost_C(costMatrix_p untyped_self, dcElement_t* left, dcElement_t* right, dcElement_t* retMedian) {
+
+    CostMatrix* thisMtx = static_cast<CostMatrix*> (untyped_self);
+    return thisMtx->getSetCostMedian(left, right, retMedian);
+}
+
+
+void freeCostMedian_t (costMedian_t* toFree) {
+    free(toFree->second);
+}
+
+CostMatrix::CostMatrix(size_t alphSize, int* inTcm) {
+    alphabetSize = alphSize;
+    size_t space = alphabetSize * alphabetSize * sizeof(int);
+    tcm = (int*) malloc(space);
+    memcpy(tcm, inTcm, space);
+    initializeMatrix();
+}
+
+CostMatrix::~CostMatrix() {
+    for ( auto& thing: myMatrix ) {
+        freeCostMedian_t(&thing.second);
+    }
+    myMatrix.clear();
+    hasher.clear();
+
+}
+
+int CostMatrix::getCostMedian(dcElement_t* left, dcElement_t* right, dcElement_t* retMedian) {
+    keys_t toLookup;
+    toLookup.first  = *left;
+    toLookup.second = *right;
+    mapIterator found;
+    int foundCost;
+
+    found = myMatrix.find(toLookup);
+
+    if ( found == myMatrix.end() ) {
+        return -1;
+    } else {
+        foundCost          = found->second.first;
+        retMedian->element = found->second.second;
+    }
+
+    return foundCost;
+}
+
+int CostMatrix::getSetCostMedian(dcElement_t* left, dcElement_t* right, dcElement_t* retMedian) {
+    keys_t* toLookup = (keys_t*) malloc( sizeof(keys_t) );
+    toLookup->first  = *left;
+    toLookup->second = *right;
+    mapIterator found;
+    int foundCost;
+
+    found = myMatrix.find(*toLookup);
+
+    if ( found == myMatrix.end() ) {
+      foundCost = 0;
+    } else {
+        foundCost = found->second.first;
+    }
+    return foundCost;
+}
+
+void CostMatrix::initializeMatrix () { ; }
+
+void CostMatrix::setValue(keys_t* key, costMedian_t* median) {
+    myMatrix.insert(std::make_pair(*key, *median));
+}
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrix.h b/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrix.h
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrix.h
@@ -0,0 +1,201 @@
+/** costMatrix object to provide for a memoizable cost lookup table. Table is indexed by two
+ *  dcElement values, and returns an int, for the cost. In addition, an additional dcElement
+ *  is passed in by reference, and the median value of the two input elements is placed there.
+ *  The getCost function is designed to interface directly with C.
+ *
+ *  The key lookup is an ordered pair, so when looking up transition a -> b, a must go in as
+ *  first in pair
+ *
+ *  WARNING: In the interest of speed this code does no "type checking" to make sure that the
+ *  two passed deElements are of the same type, i.e. that they have the same alphabet length.
+ *  Any such checks should be done exterior to this library.
+ */
+
+#ifndef _COSTMATRIX_H
+#define _COSTMATRIX_H
+
+#define DEBUG 0
+
+#include <climits>
+#include <cstdlib>
+#include <unordered_map>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "dynamicCharacterOperations.h"
+
+/** Next three fns defined here to use on C side. */
+costMatrix_p construct_CostMatrix_C (size_t alphSize, int* tcm);
+
+void destruct_CostMatrix_C (costMatrix_p mytype);
+
+int call_getSetCost_C (costMatrix_p untyped_self, dcElement_t* left, dcElement_t* right, dcElement_t* retMedian);
+
+#ifdef __cplusplus
+}
+#endif
+
+typedef std::pair<dcElement_t, dcElement_t>  keys_t;
+typedef std::pair<int,         packedChar*>  costMedian_t;
+typedef std::pair<keys_t,      costMedian_t> mapAccessPair_t;
+
+typedef void* costMatrix_p;
+
+/** Allocate room for a costMedian_t. Assumes alphabetSize is already initialized. */
+costMedian_t* allocCostMedian_t (size_t alphabetSize);
+
+/** dealloc costMedian_t. */
+void freeCostMedian_t (costMedian_t* toFree);
+
+/** Allocate room for a keys_t. */
+keys_t* allocKeys_t (size_t alphSize);
+
+/** dealloc keys_t. Calls various other free fns. */
+void freeKeys_t (const keys_t* toFree);
+
+/** Allocate space for Pair<keys_t, costMedian_t>, calling allocators for both types. */
+mapAccessPair_t* allocateMapAccessPair (size_t alphSize);
+
+/** Hashes two `dcElement`s, and returns an order-dependent hash value. In this case
+ *  "order dependent" means that the order of the arrays within the `dcElement`s matter,
+ *  and the order that the `dcElement`s are sent in also matters, as is necessary for a
+ *  non-symmetric tcm.
+ *
+ *  First loops through each `dcElement` and combines all of the element values (recall that a
+ *  `dcElement` has two fields, the second of which is the element, and is an array of `uint64_t`s)
+ *  using two different seeds, then combines the two resulting values.
+ */
+struct KeyHash {
+    /** Following hash_combine code modified from here (seems to be based on Boost):
+     *  http://stackoverflow.com/questions/2590677/how-do-i-combine-hash-values-in-c0x
+     */
+    std::size_t hash_combine (const dcElement_t lhs, const dcElement_t rhs) const {
+        std::size_t left_seed  = 3141592653; // PI used as arbitrarily random seed
+        std::size_t right_seed = 2718281828; // E  used as arbitrarily random seed
+
+        std::hash<uint64_t> hasher;
+        size_t elemArrCount = dcElemSize(lhs.alphSize);
+        for (size_t i = 0; i < elemArrCount; i++) {
+            left_seed  ^= hasher(lhs.element[i]) + 0x9e3779b9 + (left_seed  << 6) + (left_seed  >> 2);
+            right_seed ^= hasher(rhs.element[i]) + 0x9e3779b9 + (right_seed << 6) + (right_seed >> 2);
+        }
+        left_seed ^= hasher(right_seed) + 0x9e3779b9 + (left_seed << 6) + (left_seed >> 2);
+        return left_seed;
+    }
+
+    std::size_t operator()(const keys_t& k) const
+    {
+        return hash_combine (k.first, k.second);
+    }
+};
+
+struct KeyEqual {
+    // Return true if every `uint64_t` in lhs->element and rhs->element is equal, else false.
+    bool operator()(const keys_t& lhs, const keys_t& rhs) const
+    {
+      // Assert that all key components share the same alphSize value
+      if (   lhs.first.alphSize  != rhs.first.alphSize
+          || lhs.first.alphSize  != lhs.second.alphSize
+          || lhs.second.alphSize != rhs.second.alphSize) {
+          return false;
+      }
+
+      //Assert that the left key elements match the right key elements
+      size_t elemArrWidth = dcElemSize(lhs.first.alphSize);
+        for (size_t i = 0; i < elemArrWidth; i++) {
+            if (lhs.first.element[i] != rhs.first.element[i]) {
+                return false;
+            }
+            if (lhs.second.element[i] != rhs.second.element[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+};
+
+typedef std::unordered_map<keys_t, costMedian_t, KeyHash, KeyEqual>::const_iterator mapIterator;
+
+
+class CostMatrix
+{
+    public:
+//        CostMatrix();
+
+        CostMatrix(size_t alphSize, int* tcm);
+
+        ~CostMatrix();
+
+        /** Getter only for cost. Necessary for testing, to insure that particular
+         *  key pair has, in fact, already been inserted into lookup table.
+         */
+        int getCostMedian(dcElement_t* left, dcElement_t* right, dcElement_t* retMedian);
+
+        /** Acts as both a setter and getter, mutating myMap.
+         *
+         *  Receives two dcElements and computes the transformation cost as well as
+         *  the median for the two. Puts the median and alphabet size into retMedian,
+         *  which must therefore by necessity be allocated elsewhere.
+         *
+         *  This functin allocates _if necessary_. So freeing inputs after a call will not
+         *  cause invalid reads from the cost matrix.
+         */
+        int getSetCostMedian(dcElement_t* left, dcElement_t* right, dcElement_t* retMedian);
+
+    private:
+        std::unordered_map <keys_t, costMedian_t, KeyHash, KeyEqual> myMatrix;
+
+        std::unordered_map <keys_t, costMedian_t, KeyHash, KeyEqual> hasher;
+
+        size_t alphabetSize;
+
+        /** Stored unambiguous tcm, necessary to do first calls to findDistance() without having to rewrite findDistance()
+         *  and computeCostMedian()
+         */
+        int *tcm;
+
+        /** Takes in a `keys_t` and a `costMedian_t` and updates myMap to store the new values,
+         *  with @key as a key, and @median as the value.
+         */
+        void setValue(keys_t* key, costMedian_t* median);
+
+        /** Takes in a pair of keys_t (each of which is a single `dcElement`) and computes their lowest-cost median.
+         *  Uses a Sankoff-like algorithm, where all bases are considered, and the lowest cost bases are included in the
+         *  cost and median calculations. That means a base might appear in the median that is not present in either of
+         *  the two elements being compared.
+         */
+        costMedian_t* computeCostMedian(keys_t key);
+
+        /** Find distance between an ambiguous nucleotide and an unambiguous ambElem. Return that value and the median.
+         *  @param ambElem is ambiguous input.
+         *  @param nucleotide is unambiguous.
+         *  @param median is used to return the calculated median value.
+         *
+         *  This fn is necessary because there isn't yet a cost matrix set up, so it's not possible to
+         *  look up ambElems, therefore we must loop over possible values of the ambElem
+         *  and find the lowest cost median.
+         *
+         *  Nota bene: Requires symmetric, if not metric, matrix. TODO: Is this true? If so fix it?
+         */
+        int findDistance (keys_t* searchKey, dcElement_t* ambElem);
+
+        /** Takes in an initial TCM, which is actually just a row-major array, creates hash table of costs
+         *  where cost is least cost between two elements, and medians, where median is union of characters.
+         *
+         *  Nota bene:
+         *  Can only be called once this.alphabetSize has been set.
+         */
+        void initializeMatrix ();
+
+        // DEPRECATED!!!
+        /** Takes in a pair of keys_t (each of which is a single `dcElement`) and computes their lowest-cost median.
+         *  Contrast with computeCostMedian(). In this algorithm only bases which are present in at least one of
+         *  the two elements being compared are considered.
+         */
+        /* costMedian_t* computeCostMedianFitchy(keys_t keys); */
+
+};
+
+#endif // COSTMATRIX_H
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrixWrapper.c b/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrixWrapper.c
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrixWrapper.c
@@ -0,0 +1,28 @@
+#include <stdint.h>
+#include <stdio.h>
+
+#include "costMatrixWrapper.h"
+#include "dynamicCharacterOperations.h"
+
+costMatrix_p matrixInit(size_t alphSize, int *tcm) {
+   return (costMatrix_p) construct_CostMatrix_C(alphSize, tcm);
+}
+
+void matrixDestroy(costMatrix_p untyped_ptr) {
+    destruct_CostMatrix_C(untyped_ptr);
+}
+
+int getCostAndMedian(dcElement_t *elem1, dcElement_t *elem2, dcElement_t *retElem, costMatrix_p tcm) {
+    size_t alphSize = elem1->alphSize;
+    dcElement_t *elem1copy = (dcElement_t *) malloc(sizeof(dcElement_t));
+    elem1copy->alphSize    = alphSize;
+    dcElement_t *elem2copy = (dcElement_t *) malloc(sizeof(dcElement_t));
+    elem2copy->alphSize    = alphSize;
+
+    elem1copy->element = makePackedCharCopy( elem1->element, alphSize, 1 );
+    elem2copy->element = makePackedCharCopy( elem2->element, alphSize, 1 );
+
+    int cost = call_getSetCost_C(tcm, elem1copy, elem2copy, retElem);
+
+    return cost;
+}
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrixWrapper.h b/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrixWrapper.h
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrixWrapper.h
@@ -0,0 +1,24 @@
+#ifndef _COST_MATRIX_WRAPPER_H
+#define _COST_MATRIX_WRAPPER_H
+
+#include <stdint.h>
+
+#include "dynamicCharacterOperations.h"
+
+/** Initialize a matrix (fill in all values for non-ambiguous chracter transition costs) using a TCM sent in from an outside source. */
+costMatrix_p matrixInit(size_t alphSize, int *tcm);
+
+/** C wrapper for cpp destructor */
+void matrixDestroy(costMatrix_p untyped_ptr);
+
+/** Like getCost, but also returns a pointer to a median value. */
+int getCostAndMedian(dcElement_t *elem1, dcElement_t *elem2, dcElement_t *retElem, costMatrix_p tcm);
+
+/** Following three fns are C references to cpp functions found in costMatrix.cpp */
+costMatrix_p construct_CostMatrix_C(size_t alphSize, int *tcm);
+
+void destruct_CostMatrix_C(costMatrix_p mytype);
+
+int call_getSetCost_C(costMatrix_p untyped_self, dcElement_t *left, dcElement_t *right, dcElement_t *retMedian);
+
+#endif // _COST_MATRIX_WRAPPER_H
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/dynamicCharacterOperations.c b/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/dynamicCharacterOperations.c
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/dynamicCharacterOperations.c
@@ -0,0 +1,35 @@
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dynamicCharacterOperations.h"
+
+#define __STDC_FORMAT_MACROS
+
+size_t dynCharSize(size_t alphSize, size_t numElems) { return 1; }
+
+size_t dcElemSize(size_t alphSize) { return 1; }
+
+packedChar *allocatePackedChar( size_t alphSize, size_t numElems ) {
+    packedChar *outChar = (packedChar*) calloc( dynCharSize(alphSize, numElems), sizeof(packedChar) );
+    if (outChar == NULL) {
+        printf("Out of memory.\n");
+        fflush(stdout);
+        exit(1);
+    }
+    return outChar;
+}
+
+packedChar *makePackedCharCopy( packedChar *inChar, size_t alphSize, size_t numElems) {
+    packedChar *outChar = allocatePackedChar(alphSize, numElems);
+    size_t length = dynCharSize(alphSize, numElems);
+    for (size_t i = 0; i < length; i++) {
+        outChar[i] = inChar[i];
+    }
+    return outChar;
+}
+
+void freeDynChar( dynChar_t *p ) { free( p->dynChar ); }
+
+void freeDCElem( const dcElement_t *p ) { free( p->element ); }
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/dynamicCharacterOperations.h b/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/dynamicCharacterOperations.h
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/dynamicCharacterOperations.h
@@ -0,0 +1,36 @@
+#ifndef DYNAMIC_CHARACTER_OPERATIONS
+#define DYNAMIC_CHARACTER_OPERATIONS
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef uint64_t packedChar;
+typedef void *costMatrix_p;
+
+typedef struct dynChar_t {
+    size_t      alphSize;
+    size_t      numElems;     // how many dc elements are stored
+    size_t      dynCharLen;   // how many uint64_ts are necessary to store the elements
+    packedChar *dynChar;
+} dynChar_t;
+
+typedef struct dcElement_t {
+    size_t      alphSize;
+    packedChar *element;
+} dcElement_t;
+
+size_t dynCharSize(size_t alphSize, size_t numElems);
+
+size_t dcElemSize(size_t alphSize);
+
+void freeDynChar( dynChar_t *p );
+
+void freeDCElem( const dcElement_t *p );
+
+packedChar *allocatePackedChar( size_t alphSize, size_t numElems );
+
+packedChar *makePackedCharCopy( packedChar *inChar, size_t alphSize, size_t numElems );
+
+#endif /* DYNAMIC_CHARACTER_OPERATIONS */
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5318/Main.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5318/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5318/Main.hs
@@ -0,0 +1,1 @@
+main = putStrLn "hi"
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5318/empty-data-dir.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T5318/empty-data-dir.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5318/empty-data-dir.cabal
@@ -0,0 +1,10 @@
+cabal-version: 2.0
+name: empty-data-dir
+version: 0
+build-type: Simple
+data-files: foo.dat
+
+executable foo
+  default-language: Haskell2010
+  build-depends: base
+  main-is: Main.hs
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5318/foo.dat b/cabal/cabal-testsuite/PackageTests/Regression/T5318/foo.dat
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5318/foo.dat
@@ -0,0 +1,1 @@
+Hello!
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5318/install.out b/cabal/cabal-testsuite/PackageTests/Regression/T5318/install.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5318/install.out
@@ -0,0 +1,8 @@
+# cabal v1-install
+Resolving dependencies...
+Configuring empty-data-dir-0...
+Preprocessing executable 'foo' for empty-data-dir-0..
+Building executable 'foo' for empty-data-dir-0..
+Installing executable foo in <PATH>
+Warning: The directory <ROOT>/install.dist/home/.cabal/bin is not in the system search path.
+Completed    empty-data-dir-0
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5318/install.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5318/install.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5318/install.test.hs
@@ -0,0 +1,3 @@
+import Test.Cabal.Prelude
+main = cabalTest $
+  cabal "v1-install" []
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5318/sdist-list-sources.out b/cabal/cabal-testsuite/PackageTests/Regression/T5318/sdist-list-sources.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5318/sdist-list-sources.out
@@ -0,0 +1,3 @@
+# cabal v1-sdist
+List of package sources written to file '<TMPDIR>/sources'
+List of package sources written to file '<TMPDIR>/sources'
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5318/sdist-list-sources.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5318/sdist-list-sources.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5318/sdist-list-sources.test.hs
@@ -0,0 +1,7 @@
+import Test.Cabal.Prelude
+main = cabalTest $ do
+  tmpdir <- fmap testTmpDir getTestEnv
+  let fn = tmpdir </> "sources"
+  cabal "v1-sdist" ["--list-sources=" ++ fn]
+  -- --list-sources outputs with slashes on posix and backslashes on Windows. 'normalise' converts our needle to the necessary format.
+  assertFileDoesContain fn $ normalise "foo.dat"
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5386/Foo.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5386/Foo.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5386/Foo.hs
@@ -0,0 +1,4 @@
+{-# LANGUAGE CPP #-}
+module Foo where
+
+foo = FOO
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5386/Main.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5386/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5386/Main.hs
@@ -0,0 +1,1 @@
+main = return ()
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5386/Setup.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5386/Setup.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5386/Setup.hs
@@ -0,0 +1,6 @@
+module Main (main) where
+
+import Distribution.Simple
+
+main :: IO ()
+main = defaultMainWithHooks autoconfUserHooks
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5386/cabal.project b/cabal/cabal-testsuite/PackageTests/Regression/T5386/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5386/cabal.project
@@ -0,0 +1,2 @@
+packages:
+  ./
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5386/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5386/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5386/cabal.test.hs
@@ -0,0 +1,5 @@
+import Test.Cabal.Prelude
+-- See #4332, dep solving output is not deterministic
+main = cabalTest . recordMode DoNotRecord $ withSourceCopyDir "9" $
+  -- Note: we bundle the configure script so no need to autoreconf while building
+  cabal "new-build" ["all"]
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5386/configure b/cabal/cabal-testsuite/PackageTests/Regression/T5386/configure
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5386/configure
@@ -0,0 +1,2837 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for Test for autoconf brokenness 0.
+#
+# Report bugs to <none@example.com>.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org and none@example.com
+$0: about your system, including any error possibly output
+$0: before this message. Then install a modern shell, or
+$0: manually run the script under such a shell if you do
+$0: have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='Test for autoconf brokenness'
+PACKAGE_TARNAME='test'
+PACKAGE_VERSION='0'
+PACKAGE_STRING='Test for autoconf brokenness 0'
+PACKAGE_BUGREPORT='none@example.com'
+PACKAGE_URL=''
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir runstatedir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures Test for autoconf brokenness 0 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/test]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of Test for autoconf brokenness 0:";;
+   esac
+  cat <<\_ACEOF
+
+Report bugs to <none@example.com>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+Test for autoconf brokenness configure 0
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by Test for autoconf brokenness $as_me 0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_config_files="$ac_config_files test.buildinfo"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+	g
+	s/^\n//
+	s/\n/ /g
+	p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by Test for autoconf brokenness $as_me 0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <none@example.com>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+Test for autoconf brokenness config.status 0
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h |  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "test.buildinfo") CONFIG_FILES="$CONFIG_FILES test.buildinfo" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X "  :F $CONFIG_FILES      "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+  esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5386/configure.ac b/cabal/cabal-testsuite/PackageTests/Regression/T5386/configure.ac
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5386/configure.ac
@@ -0,0 +1,5 @@
+AC_INIT([Test for autoconf brokenness], [0], [none@example.com], [test])
+
+AC_CONFIG_FILES([test.buildinfo])
+
+AC_OUTPUT
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5386/test.buildinfo.in b/cabal/cabal-testsuite/PackageTests/Regression/T5386/test.buildinfo.in
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5386/test.buildinfo.in
@@ -0,0 +1,1 @@
+ghc-options: -DFOO=42
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5386/test.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T5386/test.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5386/test.cabal
@@ -0,0 +1,14 @@
+cabal-version: 2.2
+name: test
+version: 0
+build-type: Configure
+
+executable foo
+  main-is: Main.hs
+  build-depends: base
+  default-language: Haskell2010
+
+library
+  exposed-modules: Foo
+  build-depends: base
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5409/Main.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5409/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5409/Main.hs
@@ -0,0 +1,11 @@
+{-# OPTIONS_GHC -F -pgmF build-tool-exe #-}
+
+import BuildToolLibrary (buildToolLibraryVersion)
+
+main = do
+  putStrLn $ "build-tool library version: " ++ show buildToolLibraryVersion ++ ","
+  putStrLn $ "build-tool exe version: " ++ show buildToolExeVersion
+
+buildToolExeVersion :: Int
+buildToolExeVersion =
+    BUILD_TOOL_VERSION
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5409/cabal.project b/cabal/cabal-testsuite/PackageTests/Regression/T5409/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5409/cabal.project
@@ -0,0 +1,1 @@
+packages: *.cabal
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5409/pkg.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T5409/pkg.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5409/pkg.cabal
@@ -0,0 +1,10 @@
+cabal-version: 2.2
+name: pkg
+version: 1.0
+build-type: Simple
+
+executable my-exe
+  main-is: Main.hs
+  build-depends: base, build-tool-pkg == 1
+  build-tool-depends: build-tool-pkg:build-tool-exe == 2
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-1/build-tool-pkg.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-1/build-tool-pkg.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-1/build-tool-pkg.cabal
@@ -0,0 +1,15 @@
+name: build-tool-pkg
+version: 1
+build-type: Simple
+cabal-version: >= 1.20
+
+library
+  hs-source-dirs: src/
+  build-depends: base
+  exposed-modules: BuildToolLibrary
+  default-language: Haskell2010
+
+executable build-tool-exe
+  main-is: main/Main.hs
+  build-depends: base, build-tool-pkg
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-1/main/Main.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-1/main/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-1/main/Main.hs
@@ -0,0 +1,11 @@
+module Main where
+
+import BuildToolLibrary (buildToolLibraryVersion)
+import System.Environment
+
+main = do
+  (_:source:target:_) <- getArgs
+  writeFile target . unlines . map replaceVersion . lines =<< readFile source
+
+replaceVersion "    BUILD_TOOL_VERSION" = "    " ++ show buildToolLibraryVersion
+replaceVersion line                     = line
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-1/src/BuildToolLibrary.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-1/src/BuildToolLibrary.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-1/src/BuildToolLibrary.hs
@@ -0,0 +1,4 @@
+module BuildToolLibrary where
+
+buildToolLibraryVersion :: Int
+buildToolLibraryVersion = 1
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-2/build-tool-pkg.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-2/build-tool-pkg.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-2/build-tool-pkg.cabal
@@ -0,0 +1,15 @@
+name: build-tool-pkg
+version: 2
+build-type: Simple
+cabal-version: >= 1.20
+
+library
+  hs-source-dirs: src/
+  build-depends: base
+  exposed-modules: BuildToolLibrary
+  default-language: Haskell2010
+
+executable build-tool-exe
+  main-is: main/Main.hs
+  build-depends: base, build-tool-pkg
+  default-language: Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-2/main/Main.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-2/main/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-2/main/Main.hs
@@ -0,0 +1,11 @@
+module Main where
+
+import BuildToolLibrary (buildToolLibraryVersion)
+import System.Environment
+
+main = do
+  (_:source:target:_) <- getArgs
+  writeFile target . unlines . map replaceVersion . lines =<< readFile source
+
+replaceVersion "    BUILD_TOOL_VERSION" = "    " ++ show buildToolLibraryVersion
+replaceVersion line                     = line
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-2/src/BuildToolLibrary.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-2/src/BuildToolLibrary.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5409/repo/build-tool-pkg-2/src/BuildToolLibrary.hs
@@ -0,0 +1,4 @@
+module BuildToolLibrary where
+
+buildToolLibraryVersion :: Int
+buildToolLibraryVersion = 2
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5409/use-different-versions-of-dependency-for-library-and-build-tool.out b/cabal/cabal-testsuite/PackageTests/Regression/T5409/use-different-versions-of-dependency-for-library-and-build-tool.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5409/use-different-versions-of-dependency-for-library-and-build-tool.out
@@ -0,0 +1,5 @@
+# cabal v1-update
+Downloading the latest package list from test-local-repo
+# pkg my-exe
+build-tool library version: 1,
+build-tool exe version: 2
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5409/use-different-versions-of-dependency-for-library-and-build-tool.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5409/use-different-versions-of-dependency-for-library-and-build-tool.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5409/use-different-versions-of-dependency-for-library-and-build-tool.test.hs
@@ -0,0 +1,28 @@
+import Test.Cabal.Prelude
+
+-- The local package, pkg-1.0, depends on build-tool-pkg-1 as a library and
+-- build-tool-pkg-2 as a build-tool.  This test checks that cabal uses the
+-- correct version of build-tool-pkg for each purpose.  pkg imports a version
+-- number from the build-tool-pkg library and uses the build-tool-pkg executable
+-- as a preprocessor to insert the executable's version number into the source
+-- code.  Then the pkg executable prints out both versions.
+--
+-- Issue #5409 caused new-build to use the same instance of build-tool-pkg for
+-- the build-depends and build-tool-depends dependencies, even though it
+-- violated the version constraints.
+main = withShorterPathForNewBuildStore $ \storeDir ->
+  cabalTest $ do
+    skipUnless =<< hasNewBuildCompatBootCabal
+    withRepo "repo" $ do
+      r1 <- recordMode DoNotRecord $
+            cabalG' ["--store-dir=" ++ storeDir] "new-build" ["pkg:my-exe"]
+      let msg = "In order, the following will be built:"
+             ++ "  - build-tool-pkg-1 (lib) (requires download & build)"
+             ++ "  - build-tool-pkg-2 (lib) (requires download & build)"  -- dependency of build-tool-exe
+             ++ "  - build-tool-pkg-2 (exe:build-tool-exe) (requires download & build)"
+             ++ "  - pkg-1.0 (exe:my-exe) (first run)"
+      assertOutputContains msg r1
+      withPlan $ do
+        r2 <- runPlanExe' "pkg" "my-exe" []
+        assertOutputContains
+            "build-tool library version: 1, build-tool exe version: 2" r2
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5677/cabal.out b/cabal/cabal-testsuite/PackageTests/Regression/T5677/cabal.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5677/cabal.out
@@ -0,0 +1,28 @@
+# cabal new-build
+Resolving dependencies...
+Build profile: -w ghc-<GHCVER> -O1
+In order, the following will be built:
+ - impl-0 (lib) (first run)
+ - sig-0 (lib) (first run)
+ - prog-0 (lib) (first run)
+ - prog-0 (lib with Sig=impl-0-inplace:Sig) (first run)
+ - prog-0 (exe:prog) (first run)
+Configuring library for impl-0..
+Preprocessing library for impl-0..
+Building library for impl-0..
+Configuring library for sig-0..
+Preprocessing library for sig-0..
+Building library instantiated with Sig = <Sig>
+for sig-0..
+Configuring library for prog-0..
+Preprocessing library for prog-0..
+Building library instantiated with Sig = <Sig>
+for prog-0..
+Configuring library instantiated with Sig = impl-0-inplace:Sig
+for prog-0..
+Preprocessing library for prog-0..
+Building library instantiated with Sig = impl-0-inplace:Sig
+for prog-0..
+Configuring executable 'prog' for prog-0..
+Preprocessing executable 'prog' for prog-0..
+Building executable 'prog' for prog-0..
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5677/cabal.project b/cabal/cabal-testsuite/PackageTests/Regression/T5677/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5677/cabal.project
@@ -0,0 +1,4 @@
+packages:
+  sig/
+  impl/
+  prog/
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5677/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5677/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5677/cabal.test.hs
@@ -0,0 +1,6 @@
+import Test.Cabal.Prelude
+main = cabalTest $ do
+  -- -Wmissing-export-lists is new in 8.4.
+  skipUnless =<< ghcVersionIs (>= mkVersion [8,3])
+  cabal "new-build" ["all"]
+
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5677/impl/Sig.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5677/impl/Sig.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5677/impl/Sig.hs
@@ -0,0 +1,3 @@
+module Sig where
+
+foo = True
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5677/impl/impl.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T5677/impl/impl.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5677/impl/impl.cabal
@@ -0,0 +1,10 @@
+cabal-version: 2.2
+name: impl
+version: 0
+
+library
+  default-language: Haskell2010
+  build-depends:
+    base
+  exposed-modules:
+    Sig
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/prog.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/prog.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/prog.cabal
@@ -0,0 +1,19 @@
+cabal-version: 2.2
+name: prog
+version: 0
+
+library
+  default-language: Haskell2010
+  hs-source-dirs: src/
+  exposed-modules:
+    Prog
+  ghc-options: -Wmissing-export-lists -Werror
+  build-depends:
+    base, sig
+
+executable prog
+  default-language: Haskell2010
+  main-is: prog.hs
+  ghc-options: -Wmissing-export-lists -Werror
+  build-depends:
+    base, impl, prog
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/prog.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/prog.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/prog.hs
@@ -0,0 +1,5 @@
+module Main (main) where
+
+import qualified Prog
+
+main = Prog.main
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/src/Prog.hs b/cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/src/Prog.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/src/Prog.hs
@@ -0,0 +1,5 @@
+module Prog (main) where
+
+import Sig
+
+main = print foo
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5677/sig/Sig.hsig b/cabal/cabal-testsuite/PackageTests/Regression/T5677/sig/Sig.hsig
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5677/sig/Sig.hsig
@@ -0,0 +1,3 @@
+signature Sig where
+
+foo :: Bool
diff --git a/cabal/cabal-testsuite/PackageTests/Regression/T5677/sig/sig.cabal b/cabal/cabal-testsuite/PackageTests/Regression/T5677/sig/sig.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/Regression/T5677/sig/sig.cabal
@@ -0,0 +1,10 @@
+cabal-version: 2.2
+name: sig
+version: 0
+
+library
+  default-language: Haskell2010
+  build-depends:
+    base
+  signatures:
+    Sig
diff --git a/cabal/cabal-testsuite/PackageTests/SDist/ListSources/Main.hs b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/Main.hs
@@ -0,0 +1,1 @@
+main = return ()
diff --git a/cabal/cabal-testsuite/PackageTests/SDist/ListSources/data/blah/a.dat b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/data/blah/a.dat
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/data/blah/a.dat
@@ -0,0 +1,1 @@
+blah
diff --git a/cabal/cabal-testsuite/PackageTests/SDist/ListSources/extra-doc/blah/a.tex b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/extra-doc/blah/a.tex
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/extra-doc/blah/a.tex
@@ -0,0 +1,1 @@
+blah
diff --git a/cabal/cabal-testsuite/PackageTests/SDist/ListSources/extra-src/blah/a.html b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/extra-src/blah/a.html
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/extra-src/blah/a.html
@@ -0,0 +1,1 @@
+blah
diff --git a/cabal/cabal-testsuite/PackageTests/SDist/ListSources/list-sources.cabal b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/list-sources.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/list-sources.cabal
@@ -0,0 +1,11 @@
+cabal-version: 2.2
+name: list-sources
+version: 0
+data-dir: data
+data-files: blah/*.dat
+extra-source-files: extra-src/blah/*.html
+extra-doc-files: extra-doc/blah/*.tex
+
+executable dummy
+  default-language: Haskell2010
+  main-is: Main.hs
diff --git a/cabal/cabal-testsuite/PackageTests/SDist/ListSources/list-sources.out b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/list-sources.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/list-sources.out
@@ -0,0 +1,2 @@
+# Setup sdist
+List of package sources written to file '<TMPDIR>/sources'
diff --git a/cabal/cabal-testsuite/PackageTests/SDist/ListSources/list-sources.test.hs b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/list-sources.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SDist/ListSources/list-sources.test.hs
@@ -0,0 +1,10 @@
+import System.FilePath (normalise)
+import Test.Cabal.Prelude
+main = setupTest $ do
+  tmpdir <- fmap testTmpDir getTestEnv
+  let fn = tmpdir </> "sources"
+  setup "sdist" ["--list-sources=" ++ fn]
+  -- --list-sources outputs with slashes on posix and backslashes on Windows. 'normalise' converts our needle to the necessary format.
+  assertFileDoesContain fn $ normalise "data/blah/a.dat"
+  assertFileDoesContain fn $ normalise "extra-src/blah/a.html"
+  assertFileDoesContain fn $ normalise "extra-doc/blah/a.tex"
diff --git a/cabal/cabal-testsuite/PackageTests/SDist/T5195/Main.hs b/cabal/cabal-testsuite/PackageTests/SDist/T5195/Main.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SDist/T5195/Main.hs
@@ -0,0 +1,1 @@
+main = putStrLn "hi"
diff --git a/cabal/cabal-testsuite/PackageTests/SDist/T5195/actually-a-directory/some-file b/cabal/cabal-testsuite/PackageTests/SDist/T5195/actually-a-directory/some-file
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SDist/T5195/actually-a-directory/some-file
@@ -0,0 +1,1 @@
+Hello.
diff --git a/cabal/cabal-testsuite/PackageTests/SDist/T5195/cabal.out b/cabal/cabal-testsuite/PackageTests/SDist/T5195/cabal.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SDist/T5195/cabal.out
@@ -0,0 +1,2 @@
+# cabal v1-sdist
+cabal: filepath wildcard './actually-a-directory' does not match any files.
diff --git a/cabal/cabal-testsuite/PackageTests/SDist/T5195/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/SDist/T5195/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SDist/T5195/cabal.test.hs
@@ -0,0 +1,6 @@
+import Test.Cabal.Prelude
+main = cabalTest $ do
+  tmpdir <- fmap testTmpDir getTestEnv
+  let fn = tmpdir </> "sources"
+  res <- fails $ cabal' "v1-sdist" ["--list-sources=" ++ fn]
+  assertOutputContains "filepath wildcard './actually-a-directory' does not match any files" res
diff --git a/cabal/cabal-testsuite/PackageTests/SDist/T5195/t5195.cabal b/cabal/cabal-testsuite/PackageTests/SDist/T5195/t5195.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SDist/T5195/t5195.cabal
@@ -0,0 +1,10 @@
+cabal-version: 2.2
+name: t5195
+version: 0
+
+extra-source-files:
+  ./actually-a-directory
+
+executable foo
+  default-language: Haskell2010
+  main-is: Main.hs
diff --git a/cabal/cabal-testsuite/PackageTests/SPDX/M.hs b/cabal/cabal-testsuite/PackageTests/SPDX/M.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SPDX/M.hs
@@ -0,0 +1,1 @@
+module M where
diff --git a/cabal/cabal-testsuite/PackageTests/SPDX/Setup.hs b/cabal/cabal-testsuite/PackageTests/SPDX/Setup.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SPDX/Setup.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = fail "Setup called despite `build-type:Simple`"
diff --git a/cabal/cabal-testsuite/PackageTests/SPDX/cabal-old-build.cabal.out b/cabal/cabal-testsuite/PackageTests/SPDX/cabal-old-build.cabal.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SPDX/cabal-old-build.cabal.out
@@ -0,0 +1,10 @@
+# Setup configure
+Resolving dependencies...
+Configuring my-0...
+# Setup build
+Preprocessing library for my-0..
+Building library for my-0..
+# Setup copy
+Installing library in <PATH>
+# Setup register
+Registering library for my-0..
diff --git a/cabal/cabal-testsuite/PackageTests/SPDX/cabal-old-build.out b/cabal/cabal-testsuite/PackageTests/SPDX/cabal-old-build.out
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SPDX/cabal-old-build.out
@@ -0,0 +1,9 @@
+# Setup configure
+Configuring my-0...
+# Setup build
+Preprocessing library for my-0..
+Building library for my-0..
+# Setup copy
+Installing library in <PATH>
+# Setup register
+Registering library for my-0..
diff --git a/cabal/cabal-testsuite/PackageTests/SPDX/cabal-old-build.test.hs b/cabal/cabal-testsuite/PackageTests/SPDX/cabal-old-build.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SPDX/cabal-old-build.test.hs
@@ -0,0 +1,10 @@
+import Test.Cabal.Prelude
+main = setupAndCabalTest $ withPackageDb $ do
+    -- skip for GHC-8.4 and GHC-head until their Cabal modules are updated.
+    skipUnless =<< ghcVersionIs (< mkVersion [8,3])
+
+    setup_install []
+    recordMode DoNotRecord $ do
+        ghc84 <- ghcVersionIs (>= mkVersion [8,4])
+        let lic = if ghc84 then "BSD-3-Clause" else "BSD3"
+        ghcPkg' "field" ["my", "license"] >>= assertOutputContains lic
diff --git a/cabal/cabal-testsuite/PackageTests/SPDX/cabal.project b/cabal/cabal-testsuite/PackageTests/SPDX/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SPDX/cabal.project
@@ -0,0 +1,1 @@
+packages: .
diff --git a/cabal/cabal-testsuite/PackageTests/SPDX/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/SPDX/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SPDX/cabal.test.hs
@@ -0,0 +1,6 @@
+import Test.Cabal.Prelude
+main = cabalTest $ do
+    recordMode DoNotRecord $ do
+        -- TODO: Hack; see also CustomDep/cabal.test.hs
+        withEnvFilter (/= "HOME") $ do
+            cabal "new-build" ["all"]
diff --git a/cabal/cabal-testsuite/PackageTests/SPDX/my.cabal b/cabal/cabal-testsuite/PackageTests/SPDX/my.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SPDX/my.cabal
@@ -0,0 +1,10 @@
+cabal-version:       2.1
+name:                my
+version:             0
+build-type:          Simple
+license:             BSD-3-Clause
+
+library
+  exposed-modules:     M
+  build-depends:       base
+  default-language:    Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/cabal.out b/cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/cabal.out
--- a/cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/cabal.out
+++ b/cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/cabal.out
@@ -1,12 +1,12 @@
-# cabal sandbox init
+# cabal v1-sandbox init
 Writing a default package environment file to <ROOT>/cabal.dist/cabal.sandbox.config
 Creating a new sandbox at <ROOT>/cabal.dist/sandbox
-# cabal sandbox add-source
-# cabal sandbox add-source
-# cabal install
+# cabal v1-sandbox add-source
+# cabal v1-sandbox add-source
+# cabal v1-install
 Resolving dependencies...
 Configuring q-0.1.0.0...
 Preprocessing library for q-0.1.0.0..
 Building library for q-0.1.0.0..
 Installing library in <PATH>
-Installed q-0.1.0.0
+Completed    q-0.1.0.0
diff --git a/cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/cabal.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/cabal.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/cabal.test.hs
@@ -3,4 +3,4 @@
     withSandbox $ do
         cabal_sandbox "add-source" ["p"]
         cabal_sandbox "add-source" ["q"]
-        cabal "install" ["q"]
+        cabal "v1-install" ["q"]
diff --git a/cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/p/Main.hs b/cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/p/Main.hs
--- a/cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/p/Main.hs
+++ b/cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/p/Main.hs
@@ -1,4 +1,7 @@
 import Q (message)
 
 main :: IO ()
-main = putStrLn message
+main = do
+  putStrLn "-----BEGIN CABAL OUTPUT-----"
+  putStrLn message
+  putStrLn "-----END CABAL OUTPUT-----"
diff --git a/cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/sandbox.out b/cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/sandbox.out
--- a/cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/sandbox.out
+++ b/cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/sandbox.out
@@ -1,17 +1,15 @@
-# cabal sandbox init
+# cabal v1-sandbox init
 Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config
 Creating a new sandbox at <ROOT>/sandbox.dist/sandbox
-# cabal sandbox add-source
-# cabal install
+# cabal v1-sandbox add-source
+# cabal v1-install
 Resolving dependencies...
 Configuring q-1.0...
 Preprocessing library for q-1.0..
 Building library for q-1.0..
 Installing library in <PATH>
-Installed q-1.0
-# cabal run
+Completed    q-1.0
+# cabal v1-run
 message
-# cabal run
-In order, the following will be installed:
-q-1.0 (reinstall)
+# cabal v1-run
 message updated
diff --git a/cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/sandbox.test.hs b/cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/sandbox.test.hs
--- a/cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/sandbox.test.hs
+++ b/cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/sandbox.test.hs
@@ -2,8 +2,8 @@
 main = cabalTest $ do
     withSourceCopy . withDelay . withDirectory "p" . withSandbox $ do
         cabal_sandbox "add-source" ["../q"]
-        cabal "install" ["--only-dependencies"]
-        recordMode RecordAll $ cabal "run" ["p", "-v0"]
+        cabal "v1-install" ["--only-dependencies"]
+        recordMode RecordMarked $ cabal "v1-run" ["p", "-v0"]
         delay
         copySourceFileTo "../q/Q.hs.in2" "../q/Q.hs"
-        recordMode RecordAll $ cabal "run" ["p", "-v0"]
+        recordMode RecordMarked $ cabal "v1-run" ["p", "-v0"]
diff --git a/cabal/cabal-testsuite/PackageTests/Sandbox/Sources/sandbox.out b/cabal/cabal-testsuite/PackageTests/Sandbox/Sources/sandbox.out
--- a/cabal/cabal-testsuite/PackageTests/Sandbox/Sources/sandbox.out
+++ b/cabal/cabal-testsuite/PackageTests/Sandbox/Sources/sandbox.out
@@ -1,13 +1,13 @@
-# cabal sandbox init
+# cabal v1-sandbox init
 Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config
 Creating a new sandbox at <ROOT>/sandbox.dist/sandbox
-# cabal sandbox add-source
-# cabal sandbox delete-source
+# cabal v1-sandbox add-source
+# cabal v1-sandbox delete-source
 Warning: Sources not registered: "q"
 
 cabal: The sources with the above errors were skipped. ("q")
-# cabal sandbox add-source
-# cabal sandbox delete-source
+# cabal v1-sandbox add-source
+# cabal v1-sandbox delete-source
 Success deleting sources: "p" "q"
 
 Note: 'sandbox delete-source' only unregisters the source dependency, but does not remove the package from the sandbox package DB.
diff --git a/cabal/cabal-testsuite/PackageTests/SimpleDefault/M.hs b/cabal/cabal-testsuite/PackageTests/SimpleDefault/M.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SimpleDefault/M.hs
@@ -0,0 +1,1 @@
+module M where
diff --git a/cabal/cabal-testsuite/PackageTests/SimpleDefault/Setup.hs b/cabal/cabal-testsuite/PackageTests/SimpleDefault/Setup.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SimpleDefault/Setup.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = fail "Setup called despite `build-type:Simple`"
diff --git a/cabal/cabal-testsuite/PackageTests/SimpleDefault/cabal.project b/cabal/cabal-testsuite/PackageTests/SimpleDefault/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SimpleDefault/cabal.project
@@ -0,0 +1,1 @@
+packages: .
diff --git a/cabal/cabal-testsuite/PackageTests/SimpleDefault/cabal.test.hs b/cabal/cabal-testsuite/PackageTests/SimpleDefault/cabal.test.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SimpleDefault/cabal.test.hs
@@ -0,0 +1,6 @@
+import Test.Cabal.Prelude
+main = cabalTest $ do
+    recordMode DoNotRecord $ do
+        -- TODO: Hack; see also CustomDep/cabal.test.hs
+        withEnvFilter (/= "HOME") $ do
+            cabal "new-build" ["all"]
diff --git a/cabal/cabal-testsuite/PackageTests/SimpleDefault/my.cabal b/cabal/cabal-testsuite/PackageTests/SimpleDefault/my.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/SimpleDefault/my.cabal
@@ -0,0 +1,10 @@
+cabal-version:       2.1
+name:                my
+version:             0
+-- tests whether the default is `build-type: Simple`
+-- (for cabal-version >= 2.1)
+
+library
+  exposed-modules:     M
+  build-depends:       base
+  default-language:    Haskell2010
diff --git a/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/cabal-with-hpc.multitest.hs b/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/cabal-with-hpc.multitest.hs
new file mode 100644
--- /dev/null
+++ b/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/cabal-with-hpc.multitest.hs
@@ -0,0 +1,55 @@
+import qualified Control.Exception as E (IOException, catch)
+import Control.Monad (unless)
+import Control.Monad.IO.Class (liftIO)
+import Control.Monad.Trans.Reader (ask)
+import Data.Maybe (catMaybes)
+
+import qualified Distribution.Verbosity as Verbosity
+
+import Test.Cabal.Prelude
+
+main = cabalTest $ do
+    skipIf =<< isOSX -- TODO: re-enable this once the macOS Travis
+                     -- issues are resolved, see discussion in #4902.
+
+    hasShared   <- hasSharedLibraries
+    hasProfiled <- hasProfiledLibraries
+    hpcOk       <- correctHpcVersion
+
+    forM_ (choose4 [True, False]) $ \(libProf, exeProf, exeDyn, shared) ->
+      do
+        let
+          opts = catMaybes
+              [ enable libProf "library-profiling"
+              , enable exeProf "profiling"
+              , enable exeDyn "executable-dynamic"
+              , enable shared "shared"
+              ]
+            where
+              enable cond flag
+                | cond = Just $ "--enable-" ++ flag
+                | otherwise = Nothing
+          args = "test-Short" : "--enable-coverage" : opts
+        recordMode DoNotRecord $ do
+          let
+            skip =
+                not hpcOk
+                || (not hasShared && (exeDyn || shared))
+                || (not hasProfiled && (libProf || exeProf))
+          unless skip $ cabal "new-test" args
+  where
+    choose4 :: [a] -> [(a, a, a, a)]
+    choose4 xs = liftM4 (,,,) xs xs xs xs
+
+-- | Checks for a suitable HPC version for testing.
+correctHpcVersion :: TestM Bool
+correctHpcVersion = do
+    let verbosity = Verbosity.normal
+        verRange  = orLaterVersion (mkVersion [0,7])
+    progDB <- testProgramDb `fmap` ask
+    liftIO $ (requireProgramVersion verbosity hpcProgram verRange progDB
+              >> return True) `catchIO` (\_ -> return False)
+  where
+    -- Distribution.Compat.Exception is hidden.
+    catchIO :: IO a -> (E.IOException -> IO a) -> IO a
+    catchIO = E.catch
diff --git a/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.multitest.hs b/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.multitest.hs
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.multitest.hs
+++ /dev/null
@@ -1,98 +0,0 @@
-import qualified Control.Exception as E (IOException, catch)
-import Control.Monad
-import Control.Monad.IO.Class
-import Data.Maybe (catMaybes)
-import System.FilePath
-import Data.List
-
-import Distribution.Compiler (CompilerFlavor(..), CompilerId(..))
-import Distribution.Simple.Compiler (compilerId)
-import Distribution.Types.LocalBuildInfo (localPackage)
-import Distribution.Simple.LocalBuildInfo (compiler, localCompatPackageKey)
-import Distribution.Simple.Hpc
-import Distribution.Simple.Program.Builtin (hpcProgram)
-import Distribution.Simple.Program.Db
-    ( emptyProgramDb, configureProgram, requireProgramVersion )
-import Distribution.Text (display)
-import qualified Distribution.Verbosity as Verbosity
-import Distribution.Version (mkVersion, orLaterVersion)
-
-import Test.Cabal.Prelude
-
-main =
-  forM_ (choose4 [True, False]) $ \(libProf, exeProf, exeDyn, shared) ->
-   -- NB: inside so we cleanup each time.  This seems to
-   -- be important on Mac OS X, where leftover build products
-   -- can cause errors like this:
-   --
-   -- Test suite test-Short: RUNNING...
-   -- setup-with-hpc.dist/dist/build/test-Short/test-Short
-   -- dyld: Library not loaded:
-   -- @rpath/libHSmy-0.1-B1rF0UIcOou1OUvUhHrTHK-ghc7.8.4.dylib
-   --   Referenced from:
-   --   /Users/travis/build/haskell/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.dist/dist/build/test-Short/test-Short
-   --     Reason: image not found
-   --
-   -- This should get fixed eventually, but not today as I don't
-   -- have an actual Mac OS X box to debug on.
-   setupAndCabalTest . recordMode DoNotRecord $ do
-    let name | null suffixes = "Vanilla"
-             | otherwise = intercalate "-" suffixes
-          where
-            suffixes = catMaybes
-                      [ if libProf then Just "LibProf" else Nothing
-                      , if exeProf then Just "ExeProf" else Nothing
-                      , if exeDyn then Just "ExeDyn" else Nothing
-                      , if shared then Just "Shared" else Nothing
-                      ]
-        opts = catMaybes
-            [ enable libProf "library-profiling"
-            , enable exeProf "profiling"
-            , enable exeDyn "executable-dynamic"
-            , enable shared "shared"
-            ]
-          where
-            enable cond flag
-              | cond = Just $ "--enable-" ++ flag
-              | otherwise = Nothing
-    -- Ensure that both .tix file and markup are generated if coverage
-    -- is enabled.
-    shared_libs <- hasSharedLibraries
-    prof_libs <- hasProfiledLibraries
-    unless ((exeDyn || shared) && not shared_libs) $ do
-      unless ((libProf || exeProf) && not prof_libs) $ do
-        isCorrectVersion <- liftIO $ correctHpcVersion
-        when isCorrectVersion $ do
-            dist_dir <- fmap testDistDir getTestEnv
-            setup_build ("--enable-tests" : "--enable-coverage" : opts)
-            setup "test" ["test-Short", "--show-details=direct"]
-            lbi <- getLocalBuildInfoM
-            let way = guessWay lbi
-                CompilerId comp version = compilerId (compiler lbi)
-                subdir
-                  | comp == GHC && version >= mkVersion [7,10] =
-                      localCompatPackageKey lbi
-                  | otherwise = display (localPackage lbi)
-            mapM_ shouldExist
-                [ mixDir dist_dir way "my-0.1" </> subdir </> "Foo.mix"
-                , mixDir dist_dir way "test-Short" </> "Main.mix"
-                , tixFilePath dist_dir way "test-Short"
-                , htmlDir dist_dir way "test-Short" </> "hpc_index.html"
-                ]
-  where
-    choose4 :: [a] -> [(a, a, a, a)]
-    choose4 xs = liftM4 (,,,) xs xs xs xs
-
--- | Checks for a suitable HPC version for testing.
-correctHpcVersion :: IO Bool
-correctHpcVersion = do
-    let programDb' = emptyProgramDb
-    let verbosity = Verbosity.normal
-    let verRange  = orLaterVersion (mkVersion [0,7])
-    programDb <- configureProgram verbosity hpcProgram programDb'
-    (requireProgramVersion verbosity hpcProgram verRange programDb
-     >> return True) `catchIO` (\_ -> return False)
-  where
-    -- Distribution.Compat.Exception is hidden.
-    catchIO :: IO a -> (E.IOException -> IO a) -> IO a
-    catchIO = E.catch
diff --git a/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.out b/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.out
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-with-hpc.out
+++ /dev/null
diff --git a/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.out b/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.out
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.out
+++ /dev/null
@@ -1,18 +0,0 @@
-# Setup configure
-Configuring my-0.1...
-# Setup build
-Preprocessing library for my-0.1..
-Building library for my-0.1..
-Preprocessing test suite 'test-Foo' for my-0.1..
-Building test suite 'test-Foo' for my-0.1..
-Preprocessing test suite 'test-Short' for my-0.1..
-Building test suite 'test-Short' for my-0.1..
-# Setup test
-Running 2 test suites...
-Test suite test-Foo: RUNNING...
-Test suite test-Foo: PASS
-Test suite logged to: setup.dist/work/dist/test/my-0.1-test-Foo.log
-Test suite test-Short: RUNNING...
-Test suite test-Short: PASS
-Test suite logged to: setup.dist/work/dist/test/my-0.1-test-Short.log
-2 of 2 test suites (2 of 2 test cases) passed.
diff --git a/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.test.hs b/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.test.hs
deleted file mode 100644
--- a/cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup.test.hs
+++ /dev/null
@@ -1,7 +0,0 @@
-import Test.Cabal.Prelude
-
-main = setupAndCabalTest $ do
-    setup_build ["--enable-tests"]
-    -- This one runs both tests, including the very LONG Foo
-    -- test which prints a lot of output
-    setup "test" ["--show-details=direct"]
diff --git a/cabal/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/LibV09.cabal b/cabal/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/LibV09.cabal
--- a/cabal/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/LibV09.cabal
+++ b/cabal/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/LibV09.cabal
@@ -1,6 +1,5 @@
 name: LibV09
 version: 0.1
-cabal-version: >= 1.2
 license: BSD3
 author: Thomas Tuegel
 stability: stable
diff --git a/cabal/cabal-testsuite/Test/Cabal/CheckArMetadata.hs b/cabal/cabal-testsuite/Test/Cabal/CheckArMetadata.hs
--- a/cabal/cabal-testsuite/Test/Cabal/CheckArMetadata.hs
+++ b/cabal/cabal-testsuite/Test/Cabal/CheckArMetadata.hs
@@ -22,7 +22,6 @@
 
 import Distribution.Compiler              (CompilerFlavor(..), CompilerId(..))
 import Distribution.Package               (getHSLibraryName)
-import Distribution.Version               (mkVersion)
 import Distribution.Simple.Compiler       (compilerId)
 import Distribution.Simple.LocalBuildInfo (LocalBuildInfo, compiler, localUnitId)
 
diff --git a/cabal/cabal-testsuite/Test/Cabal/Monad.hs b/cabal/cabal-testsuite/Test/Cabal/Monad.hs
--- a/cabal/cabal-testsuite/Test/Cabal/Monad.hs
+++ b/cabal/cabal-testsuite/Test/Cabal/Monad.hs
@@ -31,12 +31,12 @@
     testPrefixDir,
     testDistDir,
     testPackageDbDir,
-    testHomeDir,
     testSandboxDir,
     testSandboxConfigFile,
     testRepoDir,
     testKeysDir,
     testSourceCopyDir,
+    testCabalDir,
     testUserCabalConfigFile,
     testActualFile,
     -- * Skipping tests
@@ -87,6 +87,7 @@
 import System.FilePath
 import System.IO
 import System.IO.Error (isDoesNotExistError)
+import System.IO.Temp (withSystemTempDirectory)
 import System.Process hiding (env)
 import Options.Applicative
 import Text.Regex
@@ -232,7 +233,7 @@
 
 -- | Run a test in the test monad according to program's arguments.
 runTestM :: String -> TestM a -> IO a
-runTestM mode m = do
+runTestM mode m = withSystemTempDirectory "cabal-testsuite" $ \tmp_dir -> do
     args <- execParser (info testArgParser mempty)
     let dist_dir = testArgDistDir args
         (script_dir0, script_filename) = splitFileName (testArgScriptPath args)
@@ -300,6 +301,7 @@
                 Just _  -> [GlobalPackageDB]
         env = TestEnv {
                     testSourceDir = script_dir,
+                    testTmpDir = tmp_dir,
                     testSubName = script_base,
                     testMode = mode,
                     testProgramDb = program_db,
@@ -316,7 +318,10 @@
                         -- Try to avoid Unicode output
                         [ ("LC_ALL", Just "C")
                         -- Hermetic builds (knot-tied)
-                        , ("HOME", Just (testHomeDir env))],
+                        , ("HOME", Just (testHomeDir env))
+                        -- Set CABAL_DIR in addition to HOME, since HOME has no
+                        -- effect on Windows.
+                        , ("CABAL_DIR", Just (testCabalDir env))],
                     testShouldFail = False,
                     testRelativeCurrentDir = ".",
                     testHavePackageDb = False,
@@ -328,7 +333,8 @@
                     testPlan = Nothing,
                     testRecordDefaultMode = DoNotRecord,
                     testRecordUserMode = Nothing,
-                    testRecordNormalizer = id
+                    testRecordNormalizer = id,
+                    testSourceCopyRelativeDir = "source"
                 }
     let go = do cleanup
                 r <- m
@@ -343,7 +349,7 @@
         -- the default configuration hardcodes Hackage, which we do
         -- NOT want to assume for these tests (no test should
         -- hit Hackage.)
-        liftIO $ createDirectoryIfMissing True (testHomeDir env </> ".cabal")
+        liftIO $ createDirectoryIfMissing True (testCabalDir env)
         ghc_path <- programPathM ghcProgram
         liftIO $ writeFile (testUserCabalConfigFile env)
                $ unlines [ "with-compiler: " ++ ghc_path ]
@@ -409,6 +415,7 @@
     -- string search-replace.  Make sure we do this before backslash
     -- normalization!
   . resub (posixRegexEscape (normalizerRoot nenv)) "<ROOT>/"
+  . resub (posixRegexEscape (normalizerTmpDir nenv)) "<TMPDIR>/"
   . appEndo (F.fold (map (Endo . packageIdRegex) (normalizerKnownPackages nenv)))
     -- Look for foo-0.1/installed-0d6...
     -- These installed packages will vary depending on GHC version
@@ -417,8 +424,10 @@
     -- Apply this before packageIdRegex, otherwise this regex doesn't match.
   . resub "([a-zA-Z]+(-[a-zA-Z])*)-[0-9]+(\\.[0-9]+)*/installed-[A-Za-z0-9.]+"
           "\\1-<VERSION>/installed-<HASH>..."
-  . -- Normalize architecture
-    resub (posixRegexEscape (display (normalizerPlatform nenv))) "<ARCH>"
+    -- Normalize architecture
+  . resub (posixRegexEscape (display (normalizerPlatform nenv))) "<ARCH>"
+    -- Some GHC versions are chattier than others
+  . resub "^ignoring \\(possibly broken\\) abi-depends field for packages" ""
     -- Normalize the current GHC version.  Apply this BEFORE packageIdRegex,
     -- which will pick up the install ghc library (which doesn't have the
     -- date glob).
@@ -435,6 +444,7 @@
 
 data NormalizerEnv = NormalizerEnv {
         normalizerRoot :: FilePath,
+        normalizerTmpDir :: FilePath,
         normalizerGhcVersion :: Version,
         normalizerKnownPackages :: [PackageId],
         normalizerPlatform :: Platform
@@ -451,6 +461,8 @@
     return NormalizerEnv {
         normalizerRoot
             = addTrailingPathSeparator (testSourceDir env),
+        normalizerTmpDir
+            = addTrailingPathSeparator (testTmpDir env),
         normalizerGhcVersion
             = compilerVersion (testCompiler env),
         normalizerKnownPackages
@@ -505,6 +517,8 @@
     -- | Path to the test directory, as specified by path to test
     -- script.
       testSourceDir     :: FilePath
+    -- | Somewhere to stow temporary files needed by the test.
+    , testTmpDir        :: FilePath
     -- | Test sub-name, used to qualify dist/database directory to avoid
     -- conflicts.
     , testSubName       :: String
@@ -565,6 +579,9 @@
     , testRecordUserMode :: Maybe RecordMode
     -- | Function to normalize recorded output
     , testRecordNormalizer :: String -> String
+    -- | Name of the subdirectory we copied the test's sources to,
+    -- relative to 'testSourceDir'
+    , testSourceCopyRelativeDir :: FilePath
     }
 
 testRecordMode :: TestEnv -> RecordMode
@@ -635,12 +652,15 @@
 
 -- | If 'withSourceCopy' is used, where the source files go.
 testSourceCopyDir :: TestEnv -> FilePath
-testSourceCopyDir env = testWorkDir env </> "source"
+testSourceCopyDir env = testWorkDir env </> testSourceCopyRelativeDir env
 
+-- | The user cabal directory
+testCabalDir :: TestEnv -> FilePath
+testCabalDir env = testHomeDir env </> ".cabal"
+
 -- | The user cabal config file
--- TODO: Not obviously working on Windows
 testUserCabalConfigFile :: TestEnv -> FilePath
-testUserCabalConfigFile env = testHomeDir env </> ".cabal" </> "config"
+testUserCabalConfigFile env = testCabalDir env </> "config"
 
 -- | The file where the expected output of the test lives
 testExpectFile :: TestEnv -> FilePath
diff --git a/cabal/cabal-testsuite/Test/Cabal/Prelude.hs b/cabal/cabal-testsuite/Test/Cabal/Prelude.hs
--- a/cabal/cabal-testsuite/Test/Cabal/Prelude.hs
+++ b/cabal/cabal-testsuite/Test/Cabal/Prelude.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE NondecreasingIndentation #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE CPP #-}
@@ -11,6 +12,7 @@
     module Test.Cabal.Run,
     module System.FilePath,
     module Control.Monad,
+    module Control.Monad.IO.Class,
     module Distribution.Version,
     module Distribution.Simple.Program,
 ) where
@@ -27,7 +29,7 @@
 import Distribution.Simple.Program
 import Distribution.System (OS(Windows,Linux,OSX), buildOS)
 import Distribution.Simple.Utils
-    ( withFileContents, tryFindPackageDesc )
+    ( withFileContents, withTempDirectory, tryFindPackageDesc )
 import Distribution.Simple.Configure
     ( getPersistBuildConfig )
 import Distribution.Version
@@ -36,6 +38,7 @@
 import Distribution.Types.LocalBuildInfo
 import Distribution.PackageDescription
 import Distribution.PackageDescription.Parsec
+import Distribution.Verbosity (normal)
 
 import Distribution.Compat.Stack
 
@@ -59,6 +62,7 @@
 #ifndef mingw32_HOST_OS
 import Control.Monad.Catch ( bracket_ )
 import System.Posix.Files  ( createSymbolicLink )
+import System.Posix.Resource
 #endif
 
 ------------------------------------------------------------------------
@@ -113,7 +117,17 @@
 setup cmd args = void (setup' cmd args)
 
 setup' :: String -> [String] -> TestM Result
-setup' cmd args = do
+setup' = setup'' "."
+
+setup''
+  :: FilePath
+  -- ^ Subdirectory to find the @.cabal@ file in.
+  -> String
+  -- ^ Command name
+  -> [String]
+  -- ^ Arguments
+  -> TestM Result
+setup'' prefix cmd args = do
     env <- getTestEnv
     when ((cmd == "register" || cmd == "copy") && not (testHavePackageDb env)) $
         error "Cannot register/copy without using 'withPackageDb'"
@@ -147,18 +161,43 @@
     defaultRecordMode RecordMarked $ do
     recordHeader ["Setup", cmd]
     if testCabalInstallAsSetup env
-        then runProgramM cabalProgram full_args
+        then 
+            -- `cabal` and `Setup` no longer have the same interface.
+            -- A bit of fettling is required to hide this fact.
+            let 
+                legacyCmds = 
+                    [ "build"
+                    , "configure"
+                    , "repl"
+                    , "freeze"
+                    , "run"
+                    , "test"
+                    , "bench"
+                    , "haddock"
+                    , "exec"
+                    , "update"
+                    , "install"
+                    , "clean"
+                    , "register"
+                    , "copy"
+                    , "sdist"
+                    , "reconfigure"
+                    , "doctest"
+                    ]
+                (a:as) = full_args
+                full_args' = if a `elem` legacyCmds then ("v1-" ++ a) : as else a:as
+            in runProgramM cabalProgram full_args'
         else do
-            pdfile <- liftIO $ tryFindPackageDesc (testCurrentDir env)
+            pdfile <- liftIO $ tryFindPackageDesc (testCurrentDir env </> prefix)
             pdesc <- liftIO $ readGenericPackageDescription (testVerbosity env) pdfile
-            if buildType (packageDescription pdesc) == Just Simple
+            if buildType (packageDescription pdesc) == Simple
                 then runM (testSetupPath env) full_args
                 -- Run the Custom script!
                 else do
                   r <- liftIO $ runghc (testScriptEnv env)
                                        (Just (testCurrentDir env))
                                        (testEnvironment env)
-                                       (testCurrentDir env </> "Setup.hs")
+                                       (testCurrentDir env </> prefix </> "Setup.hs")
                                        full_args
                   recordLog r
                   requireSuccess r
@@ -247,14 +286,15 @@
     env <- getTestEnv
     -- Freeze writes out cabal.config to source directory, this is not
     -- overwritable
-    when (cmd `elem` ["freeze"]) requireHasSourceCopy
+    when (cmd == "v1-freeze") requireHasSourceCopy
     let extra_args
           -- Sandboxes manage dist dir
           | testHaveSandbox env
           = install_args
-          | cmd `elem` ["update", "outdated", "user-config", "manpage", "freeze"]
+          | cmd `elem` ["v1-update", "outdated", "user-config", "manpage", "v1-freeze", "check"]
           = [ ]
           -- new-build commands are affected by testCabalProjectFile
+          | cmd == "new-sdist" = [ "--project-file", testCabalProjectFile env ]
           | "new-" `isPrefixOf` cmd
           = [ "--builddir", testDistDir env
             , "--project-file", testCabalProjectFile env
@@ -263,8 +303,8 @@
           = [ "--builddir", testDistDir env ] ++
             install_args
         install_args
-          | cmd == "install"
-         || cmd == "build" = [ "-j1" ]
+          | cmd == "v1-install"
+         || cmd == "v1-build" = [ "-j1" ]
           | otherwise = []
         extra_global_args
           | testHaveSandbox env
@@ -287,11 +327,11 @@
 cabal_sandbox' cmd args = do
     env <- getTestEnv
     let cabal_args = [ "--sandbox-config-file", testSandboxConfigFile env
-                     , "sandbox", cmd
+                     , "v1-sandbox", cmd
                      , marked_verbose ]
                   ++ args
     defaultRecordMode RecordMarked $ do
-    recordHeader ["cabal", "sandbox", cmd]
+    recordHeader ["cabal", "v1-sandbox", cmd]
     cabal_raw' cabal_args
 
 cabal_raw' :: [String] -> TestM Result
@@ -477,7 +517,10 @@
     -- TODO: Consider using the @tar@ library?
     let (src_parent, src_dir) = splitFileName src
     -- TODO: --format ustar, like createArchive?
-    tar ["-czf", dst, "-C", src_parent, src_dir]
+    -- --force-local is necessary for handling colons in Windows paths.
+    tar $ ["-czf", dst]
+       ++ ["--force-local" | buildOS == Windows]
+       ++ ["-C", src_parent, src_dir]
 
 infixr 4 `archiveTo`
 
@@ -509,10 +552,10 @@
     hackageRepoTool "bootstrap" ["--keys", testKeysDir env, "--repo", testRepoDir env]
     -- 5. Wire it up in .cabal/config
     -- TODO: libify this
-    let package_cache = testHomeDir env </> ".cabal" </> "packages"
+    let package_cache = testCabalDir env </> "packages"
     liftIO $ appendFile (testUserCabalConfigFile env)
            $ unlines [ "repository test-local-repo"
-                     , "  url: file:" ++ testRepoDir env
+                     , "  url: " ++ repoUri env
                      , "  secure: True"
                      -- TODO: Hypothetically, we could stick in the
                      -- correct key here
@@ -523,10 +566,22 @@
     -- fix that this can be removed)
     liftIO $ createDirectoryIfMissing True (package_cache </> "test-local-repo")
     -- 7. Update our local index
-    cabal "update" []
+    cabal "v1-update" []
     -- 8. Profit
     withReaderT (\env' -> env' { testHaveRepo = True }) m
     -- TODO: Arguably should undo everything when we're done...
+  where
+    -- Work around issue #5218 (incorrect conversions between Windows paths and
+    -- file URIs) by using a relative path on Windows.
+    repoUri env =
+      if buildOS == Windows
+      then let relPath = definitelyMakeRelative (testCurrentDir env)
+                                                (testRepoDir env)
+               convertSeparators = intercalate "/"
+                                 . map dropTrailingPathSeparator
+                                 . splitPath
+           in "file:" ++ convertSeparators relPath
+      else "file:" ++ testRepoDir env
 
 ------------------------------------------------------------------------
 -- * Subprocess run results
@@ -751,6 +806,19 @@
 isLinux :: TestM Bool
 isLinux = return (buildOS == Linux)
 
+getOpenFilesLimit :: TestM (Maybe Integer)
+#ifdef mingw32_HOST_OS
+-- No MS-specified limit, was determined experimentally on Windows 10 Pro x64,
+-- matches other online reports from other versions of Windows.
+getOpenFilesLimit = return (Just 2048)
+#else
+getOpenFilesLimit = liftIO $ do
+    ResourceLimits { softLimit } <- getResourceLimit ResourceOpenFiles
+    case softLimit of
+        ResourceLimit n -> return (Just n)
+        _ -> return Nothing
+#endif
+
 hasCabalForGhc :: TestM Bool
 hasCabalForGhc = do
     env <- getTestEnv
@@ -832,6 +900,8 @@
 -- This requires the test repository to be a Git checkout, because
 -- we use the Git metadata to figure out what files to copy into the
 -- hermetic copy.
+--
+-- Also see 'withSourceCopyDir'.
 withSourceCopy :: TestM a -> TestM a
 withSourceCopy m = do
     env <- getTestEnv
@@ -844,14 +914,31 @@
             liftIO $ copyFile (cwd </> f) (dest </> f)
     withReaderT (\nenv -> nenv { testHaveSourceCopy = True }) m
 
+-- | If a test needs to modify or write out source files, it's
+-- necessary to make a hermetic copy of the source files to operate
+-- on.  This function arranges for this to be done in a subdirectory
+-- with a given name, so that tests that are sensitive to the path
+-- that they're running in (e.g., autoconf tests) can run.
+--
+-- This requires the test repository to be a Git checkout, because
+-- we use the Git metadata to figure out what files to copy into the
+-- hermetic copy.
+--
+-- Also see 'withSourceCopy'.
+withSourceCopyDir :: FilePath -> TestM a -> TestM a
+withSourceCopyDir dir =
+  withReaderT (\nenv -> nenv { testSourceCopyRelativeDir = dir }) . withSourceCopy
+
 -- | Look up the 'InstalledPackageId' of a package name.
 getIPID :: String -> TestM String
 getIPID pn = do
     r <- ghcPkg' "field" ["--global", pn, "id"]
     -- Don't choke on warnings from ghc-pkg
     case mapMaybe (stripPrefix "id: ") (lines (resultOutput r)) of
-        [x] -> return (takeWhile (not . Char.isSpace) x)
-        _ -> error $ "could not determine id of " ++ pn
+        -- ~/.cabal/store may contain multiple versions of single package
+        -- we pick first one. It should work
+        (x:_) -> return (takeWhile (not . Char.isSpace) x)
+        _     -> error $ "could not determine id of " ++ pn
 
 -- | Delay a sufficient period of time to permit file timestamp
 -- to be updated.
@@ -925,3 +1012,14 @@
         ".test.hs"      -> True
         ".multitest.hs" -> True
         _               -> False
+
+-- | Work around issue #4515 (store paths exceeding the Windows path length
+-- limit) by creating a temporary directory for the new-build store. This
+-- function creates a directory immediately under the current drive on Windows.
+-- The directory must be passed to new- commands with --store-dir.
+withShorterPathForNewBuildStore :: (FilePath -> IO a) -> IO a
+withShorterPathForNewBuildStore test = do
+  tempDir <- if buildOS == Windows
+             then takeDrive `fmap` getCurrentDirectory
+             else getTemporaryDirectory
+  withTempDirectory normal tempDir "cabal-test-store" test
diff --git a/cabal/cabal-testsuite/cabal-testsuite.cabal b/cabal/cabal-testsuite/cabal-testsuite.cabal
--- a/cabal/cabal-testsuite/cabal-testsuite.cabal
+++ b/cabal/cabal-testsuite/cabal-testsuite.cabal
@@ -1,6 +1,6 @@
 name:          cabal-testsuite
-version:       2.1.0.0
-copyright:     2003-2017, Cabal Development Team (see AUTHORS file)
+version:       2.4.1.0
+copyright:     2003-2018, Cabal Development Team (see AUTHORS file)
 license:       BSD3
 license-file:  LICENSE
 author:        Cabal Development Team <cabal-devel@haskell.org>
@@ -33,20 +33,23 @@
     Test.Cabal.Monad
     Test.Cabal.CheckArMetadata
   build-depends:
-    aeson >= 1.1 && <1.3,
+    aeson ==1.4.*,
     attoparsec,
     async,
     base,
     bytestring,
     transformers,
-    optparse-applicative >=0.13 && <0.15,
+    optparse-applicative >=0.14 && <0.15,
     process,
     directory,
     filepath,
     regex-compat-tdfa,
     regex-tdfa,
+    temporary,
     text,
-    Cabal >= 2.1
+    cryptohash-sha256,
+    base16-bytestring,
+    Cabal >= 2.3
   ghc-options: -Wall -fwarn-tabs
   if !os(windows)
     build-depends: unix, exceptions
@@ -61,15 +64,16 @@
   build-depends:
     async,
     base,
-    Cabal >= 2.1,
+    Cabal == 2.4.1.0,
     clock,
     filepath,
     process,
     optparse-applicative,
     cabal-testsuite,
+    transformers,
     exceptions
   default-language: Haskell2010
 
 custom-setup
-  setup-depends: Cabal >= 1.25,
+  setup-depends: Cabal == 2.4.1.0,
                  base
diff --git a/cabal/cabal-testsuite/main/cabal-tests.hs b/cabal/cabal-testsuite/main/cabal-tests.hs
--- a/cabal/cabal-testsuite/main/cabal-tests.hs
+++ b/cabal/cabal-testsuite/main/cabal-tests.hs
@@ -1,6 +1,6 @@
-{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE NondecreasingIndentation #-}
-{-# LANGUAGE PatternGuards #-}
+{-# LANGUAGE PatternGuards            #-}
+{-# LANGUAGE ScopedTypeVariables      #-}
 
 import Test.Cabal.Workdir
 import Test.Cabal.Script
@@ -20,7 +20,7 @@
 import qualified Control.Exception as E
 import GHC.Conc (numCapabilities)
 import Data.List
-import Data.Monoid
+import Data.Monoid (mempty, (<>))
 import Text.Printf
 import qualified System.Clock as Clock
 import System.IO
diff --git a/cabal/cabal.project b/cabal/cabal.project
--- a/cabal/cabal.project
+++ b/cabal/cabal.project
@@ -1,6 +1,5 @@
-packages: Cabal/ cabal-testsuite/ cabal-install/ solver-benchmarks/
-constraints: unix >= 2.7.1.0,
-             cabal-install +lib +monolithic
+packages: Cabal/ cabal-testsuite/ cabal-install/ solver-benchmarks/ pretty-show-1.6.16/
+constraints: unix >= 2.7.1.0
 
 -- Uncomment to allow picking up extra local unpacked deps:
 --optional-packages: */
diff --git a/cabal/cabal.project.local.travis b/cabal/cabal.project.local.travis
new file mode 100644
--- /dev/null
+++ b/cabal/cabal.project.local.travis
@@ -0,0 +1,20 @@
+-- Force error messages to be better
+-- Parallel new-build error messages are non-existent.
+-- Turn off parallelization to get good errors.
+jobs: 1
+
+-- We vendor a copy of hackage-repo-tool so that we can
+-- build it reliably.  If we eventually get new-install
+-- in the bootstrap, this can go away.
+optional-packages: hackage-repo-tool-*/
+-- hackage-repo-tool has upper bound on time
+allow-newer: hackage-repo-tool:time
+
+-- The -fno-warn-orphans is a hack to make Cabal-1.24
+-- build properly (unfortunately the flags here get applied
+-- to the dependencies too!)
+package Cabal
+  ghc-options: -Werror -fno-warn-orphans
+
+package cabal-install
+  ghc-options: -Werror
diff --git a/cabal/cabal.project.meta b/cabal/cabal.project.meta
--- a/cabal/cabal.project.meta
+++ b/cabal/cabal.project.meta
@@ -1,1 +1,2 @@
 packages: cabal-dev-scripts
+optional-packages:
diff --git a/cabal/cabal.project.travis b/cabal/cabal.project.travis
deleted file mode 100644
--- a/cabal/cabal.project.travis
+++ /dev/null
@@ -1,22 +0,0 @@
--- Force error messages to be better
--- Parallel new-build error messages are non-existent.
--- Turn off parallelization to get good errors.
-jobs: 1
-
-constraints: cabal-install +monolithic
-
--- We vendor a copy of hackage-repo-tool so that we can
--- build it reliably.  If we eventually get new-install
--- in the bootstrap, this can go away.
-optional-packages: hackage-repo-tool-*/
--- hackage-repo-tool has upper bound on Cabal
-allow-newer: hackage-repo-tool:Cabal, hackage-repo-tool:time, hackage-repo-tool:directory
-
--- The -fno-warn-orphans is a hack to make Cabal-1.24
--- build properly (unfortunately the flags here get applied
--- to the dependencies too!)
-package Cabal
-  ghc-options: -Werror -fno-warn-orphans
-
-package cabal-install
-  ghc-options: -Werror
diff --git a/cabal/cabal.project.travis.libonly b/cabal/cabal.project.travis.libonly
new file mode 100644
--- /dev/null
+++ b/cabal/cabal.project.travis.libonly
@@ -0,0 +1,25 @@
+-- A copy of cabal.project, but with a trimmed down 'packages'
+-- field. Needed for LIB_ONLY configurations that can't build cabal-install,
+-- only lib:Cabal.
+
+packages: Cabal/ cabal-testsuite/
+constraints: unix >= 2.7.1.0
+
+-- Uncomment to allow picking up extra local unpacked deps:
+--optional-packages: */
+
+program-options
+  -- So us hackers get all the assertion failures early:
+  --
+  -- NOTE: currently commented out, see
+  -- https://github.com/haskell/cabal/issues/3911
+  --
+  -- ghc-options: -fno-ignore-asserts
+  --
+  -- as a workaround we specify it for each package individually:
+package Cabal
+  ghc-options: -fno-ignore-asserts
+package cabal-testsuite
+  ghc-options: -fno-ignore-asserts
+package cabal-install
+  ghc-options: -fno-ignore-asserts
diff --git a/cabal/cabal.project.validate b/cabal/cabal.project.validate
new file mode 100644
--- /dev/null
+++ b/cabal/cabal.project.validate
@@ -0,0 +1,8 @@
+packages: Cabal/ cabal-testsuite/ cabal-install/
+
+package Cabal
+  ghc-options: -Werror -fno-ignore-asserts
+package cabal-testsuite
+  ghc-options: -Werror -fno-ignore-asserts
+package cabal-install
+  ghc-options: -Werror -fno-ignore-asserts
diff --git a/cabal/license-list-data/exceptions-3.0.json b/cabal/license-list-data/exceptions-3.0.json
new file mode 100644
--- /dev/null
+++ b/cabal/license-list-data/exceptions-3.0.json
@@ -0,0 +1,306 @@
+{
+  "licenseListVersion": "3.0",
+  "releaseDate": "28 December 2017",
+  "exceptions": [
+    {
+      "reference": "./389-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/389-exception.json",
+      "referenceNumber": "1",
+      "name": "389 Directory Server Exception",
+      "seeAlso": [
+        "http://directory.fedoraproject.org/wiki/GPL_Exception_License_Text"
+      ],
+      "licenseExceptionId": "389-exception"
+    },
+    {
+      "reference": "./Autoconf-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Autoconf-exception-2.0.json",
+      "referenceNumber": "2",
+      "name": "Autoconf exception 2.0",
+      "seeAlso": [
+        "http://ac-archive.sourceforge.net/doc/copyright.html",
+        "http://ftp.gnu.org/gnu/autoconf/autoconf-2.59.tar.gz"
+      ],
+      "licenseExceptionId": "Autoconf-exception-2.0"
+    },
+    {
+      "reference": "./Autoconf-exception-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Autoconf-exception-3.0.json",
+      "referenceNumber": "3",
+      "name": "Autoconf exception 3.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/autoconf-exception-3.0.html"
+      ],
+      "licenseExceptionId": "Autoconf-exception-3.0"
+    },
+    {
+      "reference": "./Bison-exception-2.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Bison-exception-2.2.json",
+      "referenceNumber": "4",
+      "name": "Bison exception 2.2",
+      "seeAlso": [
+        "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141"
+      ],
+      "licenseExceptionId": "Bison-exception-2.2"
+    },
+    {
+      "reference": "./Bootloader-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Bootloader-exception.json",
+      "referenceNumber": "5",
+      "name": "Bootloader Distribution Exception",
+      "seeAlso": [
+        "https://github.com/pyinstaller/pyinstaller/blob/develop/COPYING.txt"
+      ],
+      "licenseExceptionId": "Bootloader-exception"
+    },
+    {
+      "reference": "./Classpath-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Classpath-exception-2.0.json",
+      "referenceNumber": "6",
+      "name": "Classpath exception 2.0",
+      "seeAlso": [
+        "http://www.gnu.org/software/classpath/license.html",
+        "https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception"
+      ],
+      "licenseExceptionId": "Classpath-exception-2.0"
+    },
+    {
+      "reference": "./CLISP-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CLISP-exception-2.0.json",
+      "referenceNumber": "7",
+      "name": "CLISP exception 2.0",
+      "seeAlso": [
+        "http://sourceforge.net/p/clisp/clisp/ci/default/tree/COPYRIGHT"
+      ],
+      "licenseExceptionId": "CLISP-exception-2.0"
+    },
+    {
+      "reference": "./DigiRule-FOSS-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/DigiRule-FOSS-exception.json",
+      "referenceNumber": "8",
+      "name": "DigiRule FOSS License Exception",
+      "seeAlso": [
+        "http://www.digirulesolutions.com/drupal/foss"
+      ],
+      "licenseExceptionId": "DigiRule-FOSS-exception"
+    },
+    {
+      "reference": "./eCos-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/eCos-exception-2.0.json",
+      "referenceNumber": "9",
+      "name": "eCos exception 2.0",
+      "seeAlso": [
+        "http://ecos.sourceware.org/license-overview.html"
+      ],
+      "licenseExceptionId": "eCos-exception-2.0"
+    },
+    {
+      "reference": "./Fawkes-Runtime-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Fawkes-Runtime-exception.json",
+      "referenceNumber": "10",
+      "name": "Fawkes Runtime Exception",
+      "seeAlso": [
+        "http://www.fawkesrobotics.org/about/license/"
+      ],
+      "licenseExceptionId": "Fawkes-Runtime-exception"
+    },
+    {
+      "reference": "./FLTK-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/FLTK-exception.json",
+      "referenceNumber": "11",
+      "name": "FLTK exception",
+      "seeAlso": [
+        "http://www.fltk.org/COPYING.php"
+      ],
+      "licenseExceptionId": "FLTK-exception"
+    },
+    {
+      "reference": "./Font-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Font-exception-2.0.json",
+      "referenceNumber": "12",
+      "name": "Font exception 2.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gpl-faq.html#FontException"
+      ],
+      "licenseExceptionId": "Font-exception-2.0"
+    },
+    {
+      "reference": "./freertos-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/freertos-exception-2.0.json",
+      "referenceNumber": "13",
+      "name": "FreeRTOS Exception 2.0",
+      "seeAlso": [
+        "http://www.freertos.org/a00114.html#exception"
+      ],
+      "licenseExceptionId": "freertos-exception-2.0"
+    },
+    {
+      "reference": "./GCC-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GCC-exception-2.0.json",
+      "referenceNumber": "14",
+      "name": "GCC Runtime Library exception 2.0",
+      "seeAlso": [
+        "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10"
+      ],
+      "licenseExceptionId": "GCC-exception-2.0"
+    },
+    {
+      "reference": "./GCC-exception-3.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GCC-exception-3.1.json",
+      "referenceNumber": "15",
+      "name": "GCC Runtime Library exception 3.1",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gcc-exception-3.1.html"
+      ],
+      "licenseExceptionId": "GCC-exception-3.1"
+    },
+    {
+      "reference": "./gnu-javamail-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/gnu-javamail-exception.json",
+      "referenceNumber": "16",
+      "name": "GNU JavaMail exception",
+      "seeAlso": [
+        "http://www.gnu.org/software/classpathx/javamail/javamail.html"
+      ],
+      "licenseExceptionId": "gnu-javamail-exception"
+    },
+    {
+      "reference": "./i2p-gpl-java-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/i2p-gpl-java-exception.json",
+      "referenceNumber": "17",
+      "name": "i2p GPL+Java Exception",
+      "seeAlso": [
+        "http://geti2p.net/en/get-involved/develop/licenses#java_exception"
+      ],
+      "licenseExceptionId": "i2p-gpl-java-exception"
+    },
+    {
+      "reference": "./Libtool-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Libtool-exception.json",
+      "referenceNumber": "18",
+      "name": "Libtool Exception",
+      "seeAlso": [
+        "http://git.savannah.gnu.org/cgit/libtool.git/tree/m4/libtool.m4"
+      ],
+      "licenseExceptionId": "Libtool-exception"
+    },
+    {
+      "reference": "./Linux-syscall-note.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Linux-syscall-note.json",
+      "referenceNumber": "19",
+      "name": "Linux Syscall Note",
+      "seeAlso": [
+        "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/COPYING"
+      ],
+      "licenseExceptionId": "Linux-syscall-note"
+    },
+    {
+      "reference": "./LZMA-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LZMA-exception.json",
+      "referenceNumber": "20",
+      "name": "LZMA exception",
+      "seeAlso": [
+        "http://nsis.sourceforge.net/Docs/AppendixI.html#I.6"
+      ],
+      "licenseExceptionId": "LZMA-exception"
+    },
+    {
+      "reference": "./mif-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/mif-exception.json",
+      "referenceNumber": "21",
+      "name": "Macros and Inline Functions Exception",
+      "seeAlso": [
+        "http://www.scs.stanford.edu/histar/src/lib/cppsup/exception",
+        "http://dev.bertos.org/doxygen/ https://www.threadingbuildingblocks.org/licensing"
+      ],
+      "licenseExceptionId": "mif-exception"
+    },
+    {
+      "reference": "./Nokia-Qt-exception-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Nokia-Qt-exception-1.1.json",
+      "referenceNumber": "22",
+      "name": "Nokia Qt LGPL exception 1.1",
+      "seeAlso": [
+        "https://www.keepassx.org/dev/projects/keepassx/repository/revisions/b8dfb9cc4d5133e0f09cd7533d15a4f1c19a40f2/entry/LICENSE.NOKIA-LGPL-EXCEPTION"
+      ],
+      "licenseExceptionId": "Nokia-Qt-exception-1.1"
+    },
+    {
+      "reference": "./OCCT-exception-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OCCT-exception-1.0.json",
+      "referenceNumber": "23",
+      "name": "Open CASCADE Exception 1.0",
+      "seeAlso": [
+        "http://www.opencascade.com/content/licensing"
+      ],
+      "licenseExceptionId": "OCCT-exception-1.0"
+    },
+    {
+      "reference": "./openvpn-openssl-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/openvpn-openssl-exception.json",
+      "referenceNumber": "24",
+      "name": "OpenVPN OpenSSL Exception",
+      "seeAlso": [
+        "http://openvpn.net/index.php/license.html"
+      ],
+      "licenseExceptionId": "openvpn-openssl-exception"
+    },
+    {
+      "reference": "./Qwt-exception-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Qwt-exception-1.0.json",
+      "referenceNumber": "25",
+      "name": "Qwt exception 1.0",
+      "seeAlso": [
+        "http://qwt.sourceforge.net/qwtlicense.html"
+      ],
+      "licenseExceptionId": "Qwt-exception-1.0"
+    },
+    {
+      "reference": "./u-boot-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/u-boot-exception-2.0.json",
+      "referenceNumber": "26",
+      "name": "U-Boot exception 2.0",
+      "seeAlso": [
+        "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003dLicenses/Exceptions"
+      ],
+      "licenseExceptionId": "u-boot-exception-2.0"
+    },
+    {
+      "reference": "./WxWindows-exception-3.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/WxWindows-exception-3.1.json",
+      "referenceNumber": "27",
+      "name": "WxWindows Library Exception 3.1",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/WXwindows"
+      ],
+      "licenseExceptionId": "WxWindows-exception-3.1"
+    }
+  ]
+}
diff --git a/cabal/license-list-data/exceptions-3.2.json b/cabal/license-list-data/exceptions-3.2.json
new file mode 100644
--- /dev/null
+++ b/cabal/license-list-data/exceptions-3.2.json
@@ -0,0 +1,363 @@
+{
+  "licenseListVersion": "3.2",
+  "releaseDate": "2018-07-10",
+  "exceptions": [
+    {
+      "reference": "./389-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/389-exception.json",
+      "referenceNumber": "1",
+      "name": "389 Directory Server Exception",
+      "seeAlso": [
+        "http://directory.fedoraproject.org/wiki/GPL_Exception_License_Text"
+      ],
+      "licenseExceptionId": "389-exception"
+    },
+    {
+      "reference": "./Autoconf-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Autoconf-exception-2.0.json",
+      "referenceNumber": "2",
+      "name": "Autoconf exception 2.0",
+      "seeAlso": [
+        "http://ac-archive.sourceforge.net/doc/copyright.html",
+        "http://ftp.gnu.org/gnu/autoconf/autoconf-2.59.tar.gz"
+      ],
+      "licenseExceptionId": "Autoconf-exception-2.0"
+    },
+    {
+      "reference": "./Autoconf-exception-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Autoconf-exception-3.0.json",
+      "referenceNumber": "3",
+      "name": "Autoconf exception 3.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/autoconf-exception-3.0.html"
+      ],
+      "licenseExceptionId": "Autoconf-exception-3.0"
+    },
+    {
+      "reference": "./Bison-exception-2.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Bison-exception-2.2.json",
+      "referenceNumber": "4",
+      "name": "Bison exception 2.2",
+      "seeAlso": [
+        "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141"
+      ],
+      "licenseExceptionId": "Bison-exception-2.2"
+    },
+    {
+      "reference": "./Bootloader-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Bootloader-exception.json",
+      "referenceNumber": "5",
+      "name": "Bootloader Distribution Exception",
+      "seeAlso": [
+        "https://github.com/pyinstaller/pyinstaller/blob/develop/COPYING.txt"
+      ],
+      "licenseExceptionId": "Bootloader-exception"
+    },
+    {
+      "reference": "./Classpath-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Classpath-exception-2.0.json",
+      "referenceNumber": "6",
+      "name": "Classpath exception 2.0",
+      "seeAlso": [
+        "http://www.gnu.org/software/classpath/license.html",
+        "https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception"
+      ],
+      "licenseExceptionId": "Classpath-exception-2.0"
+    },
+    {
+      "reference": "./CLISP-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CLISP-exception-2.0.json",
+      "referenceNumber": "7",
+      "name": "CLISP exception 2.0",
+      "seeAlso": [
+        "http://sourceforge.net/p/clisp/clisp/ci/default/tree/COPYRIGHT"
+      ],
+      "licenseExceptionId": "CLISP-exception-2.0"
+    },
+    {
+      "reference": "./DigiRule-FOSS-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/DigiRule-FOSS-exception.json",
+      "referenceNumber": "8",
+      "name": "DigiRule FOSS License Exception",
+      "seeAlso": [
+        "http://www.digirulesolutions.com/drupal/foss"
+      ],
+      "licenseExceptionId": "DigiRule-FOSS-exception"
+    },
+    {
+      "reference": "./eCos-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/eCos-exception-2.0.json",
+      "referenceNumber": "9",
+      "name": "eCos exception 2.0",
+      "seeAlso": [
+        "http://ecos.sourceware.org/license-overview.html"
+      ],
+      "licenseExceptionId": "eCos-exception-2.0"
+    },
+    {
+      "reference": "./Fawkes-Runtime-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Fawkes-Runtime-exception.json",
+      "referenceNumber": "10",
+      "name": "Fawkes Runtime Exception",
+      "seeAlso": [
+        "http://www.fawkesrobotics.org/about/license/"
+      ],
+      "licenseExceptionId": "Fawkes-Runtime-exception"
+    },
+    {
+      "reference": "./FLTK-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/FLTK-exception.json",
+      "referenceNumber": "11",
+      "name": "FLTK exception",
+      "seeAlso": [
+        "http://www.fltk.org/COPYING.php"
+      ],
+      "licenseExceptionId": "FLTK-exception"
+    },
+    {
+      "reference": "./Font-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Font-exception-2.0.json",
+      "referenceNumber": "12",
+      "name": "Font exception 2.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gpl-faq.html#FontException"
+      ],
+      "licenseExceptionId": "Font-exception-2.0"
+    },
+    {
+      "reference": "./freertos-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/freertos-exception-2.0.json",
+      "referenceNumber": "13",
+      "name": "FreeRTOS Exception 2.0",
+      "seeAlso": [
+        "http://www.freertos.org/a00114.html#exception"
+      ],
+      "licenseExceptionId": "freertos-exception-2.0"
+    },
+    {
+      "reference": "./GCC-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GCC-exception-2.0.json",
+      "referenceNumber": "14",
+      "name": "GCC Runtime Library exception 2.0",
+      "seeAlso": [
+        "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10"
+      ],
+      "licenseExceptionId": "GCC-exception-2.0"
+    },
+    {
+      "reference": "./GCC-exception-3.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GCC-exception-3.1.json",
+      "referenceNumber": "15",
+      "name": "GCC Runtime Library exception 3.1",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gcc-exception-3.1.html"
+      ],
+      "licenseExceptionId": "GCC-exception-3.1"
+    },
+    {
+      "reference": "./gnu-javamail-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/gnu-javamail-exception.json",
+      "referenceNumber": "16",
+      "name": "GNU JavaMail exception",
+      "seeAlso": [
+        "http://www.gnu.org/software/classpathx/javamail/javamail.html"
+      ],
+      "licenseExceptionId": "gnu-javamail-exception"
+    },
+    {
+      "reference": "./i2p-gpl-java-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/i2p-gpl-java-exception.json",
+      "referenceNumber": "17",
+      "name": "i2p GPL+Java Exception",
+      "seeAlso": [
+        "http://geti2p.net/en/get-involved/develop/licenses#java_exception"
+      ],
+      "licenseExceptionId": "i2p-gpl-java-exception"
+    },
+    {
+      "reference": "./Libtool-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Libtool-exception.json",
+      "referenceNumber": "18",
+      "name": "Libtool Exception",
+      "seeAlso": [
+        "http://git.savannah.gnu.org/cgit/libtool.git/tree/m4/libtool.m4"
+      ],
+      "licenseExceptionId": "Libtool-exception"
+    },
+    {
+      "reference": "./Linux-syscall-note.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Linux-syscall-note.json",
+      "referenceNumber": "19",
+      "name": "Linux Syscall Note",
+      "seeAlso": [
+        "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/COPYING"
+      ],
+      "licenseExceptionId": "Linux-syscall-note"
+    },
+    {
+      "reference": "./LLVM-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LLVM-exception.json",
+      "referenceNumber": "20",
+      "name": "LLVM Exception",
+      "seeAlso": [
+        "http://llvm.org/foundation/relicensing/LICENSE.txt"
+      ],
+      "licenseExceptionId": "LLVM-exception"
+    },
+    {
+      "reference": "./LZMA-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LZMA-exception.json",
+      "referenceNumber": "21",
+      "name": "LZMA exception",
+      "seeAlso": [
+        "http://nsis.sourceforge.net/Docs/AppendixI.html#I.6"
+      ],
+      "licenseExceptionId": "LZMA-exception"
+    },
+    {
+      "reference": "./mif-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/mif-exception.json",
+      "referenceNumber": "22",
+      "name": "Macros and Inline Functions Exception",
+      "seeAlso": [
+        "http://www.scs.stanford.edu/histar/src/lib/cppsup/exception",
+        "http://dev.bertos.org/doxygen/",
+        "https://www.threadingbuildingblocks.org/licensing"
+      ],
+      "licenseExceptionId": "mif-exception"
+    },
+    {
+      "reference": "./Nokia-Qt-exception-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Nokia-Qt-exception-1.1.json",
+      "referenceNumber": "23",
+      "name": "Nokia Qt LGPL exception 1.1",
+      "seeAlso": [
+        "https://www.keepassx.org/dev/projects/keepassx/repository/revisions/b8dfb9cc4d5133e0f09cd7533d15a4f1c19a40f2/entry/LICENSE.NOKIA-LGPL-EXCEPTION"
+      ],
+      "licenseExceptionId": "Nokia-Qt-exception-1.1"
+    },
+    {
+      "reference": "./OCCT-exception-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OCCT-exception-1.0.json",
+      "referenceNumber": "24",
+      "name": "Open CASCADE Exception 1.0",
+      "seeAlso": [
+        "http://www.opencascade.com/content/licensing"
+      ],
+      "licenseExceptionId": "OCCT-exception-1.0"
+    },
+    {
+      "reference": "./OpenJDK-assembly-exception-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OpenJDK-assembly-exception-1.0.json",
+      "referenceNumber": "25",
+      "name": "OpenJDK Assembly exception 1.0",
+      "seeAlso": [
+        "http://openjdk.java.net/legal/assembly-exception.html\n         "
+      ],
+      "licenseExceptionId": "OpenJDK-assembly-exception-1.0"
+    },
+    {
+      "reference": "./openvpn-openssl-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/openvpn-openssl-exception.json",
+      "referenceNumber": "26",
+      "name": "OpenVPN OpenSSL Exception",
+      "seeAlso": [
+        "http://openvpn.net/index.php/license.html"
+      ],
+      "licenseExceptionId": "openvpn-openssl-exception"
+    },
+    {
+      "reference": "./PS-or-PDF-font-exception-20170817.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/PS-or-PDF-font-exception-20170817.json",
+      "referenceNumber": "27",
+      "name": "PS/PDF font exception (2017-08-17)",
+      "seeAlso": [
+        "https://github.com/ArtifexSoftware/urw-base35-fonts/blob/master/LICENSE",
+        "https://github.com/ArtifexSoftware/urw-base35-fonts/blob/65962e27febc3883a17e651cdb23e783668c996f/LICENSE"
+      ],
+      "licenseExceptionId": "PS-or-PDF-font-exception-20170817"
+    },
+    {
+      "reference": "./Qt-GPL-exception-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Qt-GPL-exception-1.0.json",
+      "referenceNumber": "28",
+      "name": "Qt GPL exception 1.0",
+      "seeAlso": [
+        "http://code.qt.io/cgit/qt/qtbase.git/tree/LICENSE.GPL3-EXCEPT"
+      ],
+      "licenseExceptionId": "Qt-GPL-exception-1.0"
+    },
+    {
+      "reference": "./Qt-LGPL-exception-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Qt-LGPL-exception-1.1.json",
+      "referenceNumber": "29",
+      "name": "Qt LGPL exception 1.1",
+      "seeAlso": [
+        "http://code.qt.io/cgit/qt/qtbase.git/tree/LGPL_EXCEPTION.txt"
+      ],
+      "licenseExceptionId": "Qt-LGPL-exception-1.1"
+    },
+    {
+      "reference": "./Qwt-exception-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Qwt-exception-1.0.json",
+      "referenceNumber": "30",
+      "name": "Qwt exception 1.0",
+      "seeAlso": [
+        "http://qwt.sourceforge.net/qwtlicense.html"
+      ],
+      "licenseExceptionId": "Qwt-exception-1.0"
+    },
+    {
+      "reference": "./u-boot-exception-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/u-boot-exception-2.0.json",
+      "referenceNumber": "31",
+      "name": "U-Boot exception 2.0",
+      "seeAlso": [
+        "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003dLicenses/Exceptions"
+      ],
+      "licenseExceptionId": "u-boot-exception-2.0"
+    },
+    {
+      "reference": "./WxWindows-exception-3.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/WxWindows-exception-3.1.json",
+      "referenceNumber": "32",
+      "name": "WxWindows Library Exception 3.1",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/WXwindows"
+      ],
+      "licenseExceptionId": "WxWindows-exception-3.1"
+    }
+  ]
+}
diff --git a/cabal/license-list-data/licenses-3.0.json b/cabal/license-list-data/licenses-3.0.json
new file mode 100644
--- /dev/null
+++ b/cabal/license-list-data/licenses-3.0.json
@@ -0,0 +1,4653 @@
+{
+  "licenseListVersion": "3.0",
+  "licenses": [
+    {
+      "reference": "./0BSD.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/0BSD.json",
+      "referenceNumber": "1",
+      "name": "BSD Zero Clause License",
+      "licenseId": "0BSD",
+      "seeAlso": [
+        "http://landley.net/toybox/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AAL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/AAL.json",
+      "referenceNumber": "2",
+      "name": "Attribution Assurance License",
+      "licenseId": "AAL",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/attribution"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Abstyles.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Abstyles.json",
+      "referenceNumber": "3",
+      "name": "Abstyles License",
+      "licenseId": "Abstyles",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Abstyles"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Adobe-2006.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Adobe-2006.json",
+      "referenceNumber": "4",
+      "name": "Adobe Systems Incorporated Source Code License Agreement",
+      "licenseId": "Adobe-2006",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/AdobeLicense"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Adobe-Glyph.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Adobe-Glyph.json",
+      "referenceNumber": "5",
+      "name": "Adobe Glyph List License",
+      "licenseId": "Adobe-Glyph",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MIT#AdobeGlyph"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ADSL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ADSL.json",
+      "referenceNumber": "6",
+      "name": "Amazon Digital Services License",
+      "licenseId": "ADSL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/AmazonDigitalServicesLicense"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AFL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AFL-1.1.json",
+      "referenceNumber": "7",
+      "name": "Academic Free License v1.1",
+      "licenseId": "AFL-1.1",
+      "seeAlso": [
+        "http://opensource.linux-mirror.org/licenses/afl-1.1.txt",
+        "http://wayback.archive.org/web/20021004124254/http://www.opensource.org/licenses/academic.php"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./AFL-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AFL-1.2.json",
+      "referenceNumber": "8",
+      "name": "Academic Free License v1.2",
+      "licenseId": "AFL-1.2",
+      "seeAlso": [
+        "http://opensource.linux-mirror.org/licenses/afl-1.2.txt",
+        "http://wayback.archive.org/web/20021204204652/http://www.opensource.org/licenses/academic.php"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./AFL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AFL-2.0.json",
+      "referenceNumber": "9",
+      "name": "Academic Free License v2.0",
+      "licenseId": "AFL-2.0",
+      "seeAlso": [
+        "http://opensource.linux-mirror.org/licenses/afl-2.0.txt",
+        "http://wayback.archive.org/web/20060924134533/http://www.opensource.org/licenses/afl-2.0.txt"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./AFL-2.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AFL-2.1.json",
+      "referenceNumber": "10",
+      "name": "Academic Free License v2.1",
+      "licenseId": "AFL-2.1",
+      "seeAlso": [
+        "http://opensource.linux-mirror.org/licenses/afl-2.1.txt"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./AFL-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AFL-3.0.json",
+      "referenceNumber": "11",
+      "name": "Academic Free License v3.0",
+      "licenseId": "AFL-3.0",
+      "seeAlso": [
+        "http://www.rosenlaw.com/AFL3.0.htm",
+        "http://www.opensource.org/licenses/afl-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Afmparse.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Afmparse.json",
+      "referenceNumber": "12",
+      "name": "Afmparse License",
+      "licenseId": "Afmparse",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Afmparse"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AGPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AGPL-1.0.json",
+      "referenceNumber": "13",
+      "name": "Affero General Public License v1.0",
+      "licenseId": "AGPL-1.0",
+      "seeAlso": [
+        "http://www.affero.org/oagpl.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AGPL-3.0-only.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/AGPL-3.0-only.json",
+      "referenceNumber": "14",
+      "name": "GNU Affero General Public License v3.0 only",
+      "licenseId": "AGPL-3.0-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/agpl.txt",
+        "http://www.opensource.org/licenses/AGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./AGPL-3.0-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/AGPL-3.0-or-later.json",
+      "referenceNumber": "15",
+      "name": "GNU Affero General Public License v3.0 or later",
+      "licenseId": "AGPL-3.0-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/agpl.txt",
+        "http://www.opensource.org/licenses/AGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Aladdin.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/Aladdin.json",
+      "referenceNumber": "16",
+      "name": "Aladdin Free Public License",
+      "licenseId": "Aladdin",
+      "seeAlso": [
+        "http://pages.cs.wisc.edu/~ghost/doc/AFPL/6.01/Public.htm"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AMDPLPA.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/AMDPLPA.json",
+      "referenceNumber": "17",
+      "name": "AMD\u0027s plpa_map.c License",
+      "licenseId": "AMDPLPA",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/AMD_plpa_map_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AML.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/AML.json",
+      "referenceNumber": "18",
+      "name": "Apple MIT License",
+      "licenseId": "AML",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Apple_MIT_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AMPAS.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/AMPAS.json",
+      "referenceNumber": "19",
+      "name": "Academy of Motion Picture Arts and Sciences BSD",
+      "licenseId": "AMPAS",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/BSD#AMPASBSD"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ANTLR-PD.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ANTLR-PD.json",
+      "referenceNumber": "20",
+      "name": "ANTLR Software Rights Notice",
+      "licenseId": "ANTLR-PD",
+      "seeAlso": [
+        "http://www.antlr2.org/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Apache-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Apache-1.0.json",
+      "referenceNumber": "21",
+      "name": "Apache License 1.0",
+      "licenseId": "Apache-1.0",
+      "seeAlso": [
+        "http://www.apache.org/licenses/LICENSE-1.0"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Apache-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Apache-1.1.json",
+      "referenceNumber": "22",
+      "name": "Apache License 1.1",
+      "licenseId": "Apache-1.1",
+      "seeAlso": [
+        "http://apache.org/licenses/LICENSE-1.1",
+        "http://opensource.org/licenses/Apache-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Apache-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Apache-2.0.json",
+      "referenceNumber": "23",
+      "name": "Apache License 2.0",
+      "licenseId": "Apache-2.0",
+      "seeAlso": [
+        "http://www.apache.org/licenses/LICENSE-2.0",
+        "http://www.opensource.org/licenses/Apache-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./APAFML.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/APAFML.json",
+      "referenceNumber": "24",
+      "name": "Adobe Postscript AFM License",
+      "licenseId": "APAFML",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/AdobePostscriptAFM"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./APL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/APL-1.0.json",
+      "referenceNumber": "25",
+      "name": "Adaptive Public License 1.0",
+      "licenseId": "APL-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/APL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./APSL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/APSL-1.0.json",
+      "referenceNumber": "26",
+      "name": "Apple Public Source License 1.0",
+      "licenseId": "APSL-1.0",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Apple_Public_Source_License_1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./APSL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/APSL-1.1.json",
+      "referenceNumber": "27",
+      "name": "Apple Public Source License 1.1",
+      "licenseId": "APSL-1.1",
+      "seeAlso": [
+        "http://www.opensource.apple.com/source/IOSerialFamily/IOSerialFamily-7/APPLE_LICENSE"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./APSL-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/APSL-1.2.json",
+      "referenceNumber": "28",
+      "name": "Apple Public Source License 1.2",
+      "licenseId": "APSL-1.2",
+      "seeAlso": [
+        "http://www.samurajdata.se/opensource/mirror/licenses/apsl.php"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./APSL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/APSL-2.0.json",
+      "referenceNumber": "29",
+      "name": "Apple Public Source License 2.0",
+      "licenseId": "APSL-2.0",
+      "seeAlso": [
+        "http://www.opensource.apple.com/license/apsl/"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Artistic-1.0-cl8.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Artistic-1.0-cl8.json",
+      "referenceNumber": "30",
+      "name": "Artistic License 1.0 w/clause 8",
+      "licenseId": "Artistic-1.0-cl8",
+      "seeAlso": [
+        "http://opensource.org/licenses/Artistic-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Artistic-1.0-Perl.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Artistic-1.0-Perl.json",
+      "referenceNumber": "31",
+      "name": "Artistic License 1.0 (Perl)",
+      "licenseId": "Artistic-1.0-Perl",
+      "seeAlso": [
+        "http://dev.perl.org/licenses/artistic.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Artistic-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/Artistic-1.0.json",
+      "referenceNumber": "32",
+      "name": "Artistic License 1.0",
+      "licenseId": "Artistic-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/Artistic-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Artistic-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Artistic-2.0.json",
+      "referenceNumber": "33",
+      "name": "Artistic License 2.0",
+      "licenseId": "Artistic-2.0",
+      "seeAlso": [
+        "http://www.perlfoundation.org/artistic_license_2_0",
+        "http://www.opensource.org/licenses/artistic-license-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Bahyph.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Bahyph.json",
+      "referenceNumber": "34",
+      "name": "Bahyph License",
+      "licenseId": "Bahyph",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Bahyph"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Barr.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Barr.json",
+      "referenceNumber": "35",
+      "name": "Barr License",
+      "licenseId": "Barr",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Barr"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Beerware.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Beerware.json",
+      "referenceNumber": "36",
+      "name": "Beerware License",
+      "licenseId": "Beerware",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Beerware",
+        "https://people.freebsd.org/~phk/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BitTorrent-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BitTorrent-1.0.json",
+      "referenceNumber": "37",
+      "name": "BitTorrent Open Source License v1.0",
+      "licenseId": "BitTorrent-1.0",
+      "seeAlso": [
+        "http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/licenses/BitTorrent?r1\u003d1.1\u0026r2\u003d1.1.1.1\u0026diff_format\u003ds"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BitTorrent-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/BitTorrent-1.1.json",
+      "referenceNumber": "38",
+      "name": "BitTorrent Open Source License v1.1",
+      "licenseId": "BitTorrent-1.1",
+      "seeAlso": [
+        "http://directory.fsf.org/wiki/License:BitTorrentOSL1.1"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Borceux.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Borceux.json",
+      "referenceNumber": "39",
+      "name": "Borceux license",
+      "licenseId": "Borceux",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Borceux"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-1-Clause.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-1-Clause.json",
+      "referenceNumber": "40",
+      "name": "BSD 1-Clause License",
+      "licenseId": "BSD-1-Clause",
+      "seeAlso": [
+        "https://svnweb.freebsd.org/base/head/include/ifaddrs.h?revision\u003d326823"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-2-Clause-FreeBSD.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-FreeBSD.json",
+      "referenceNumber": "41",
+      "name": "BSD 2-Clause FreeBSD License",
+      "licenseId": "BSD-2-Clause-FreeBSD",
+      "seeAlso": [
+        "http://www.freebsd.org/copyright/freebsd-license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-2-Clause-NetBSD.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-NetBSD.json",
+      "referenceNumber": "42",
+      "name": "BSD 2-Clause NetBSD License",
+      "licenseId": "BSD-2-Clause-NetBSD",
+      "seeAlso": [
+        "http://www.netbsd.org/about/redistribution.html#default"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-2-Clause-Patent.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-Patent.json",
+      "referenceNumber": "43",
+      "name": "BSD-2-Clause Plus Patent License",
+      "licenseId": "BSD-2-Clause-Patent",
+      "seeAlso": [
+        "https://opensource.org/licenses/BSDplusPatent"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./BSD-2-Clause.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause.json",
+      "referenceNumber": "44",
+      "name": "BSD 2-Clause \"Simplified\" License",
+      "licenseId": "BSD-2-Clause",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/BSD-2-Clause"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./BSD-3-Clause-Attribution.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-Attribution.json",
+      "referenceNumber": "45",
+      "name": "BSD with attribution",
+      "licenseId": "BSD-3-Clause-Attribution",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/BSD_with_Attribution"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-3-Clause-Clear.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-Clear.json",
+      "referenceNumber": "46",
+      "name": "BSD 3-Clause Clear License",
+      "licenseId": "BSD-3-Clause-Clear",
+      "seeAlso": [
+        "http://labs.metacarta.com/license-explanation.html#license"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-3-Clause-LBNL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-LBNL.json",
+      "referenceNumber": "47",
+      "name": "Lawrence Berkeley National Labs BSD variant license",
+      "licenseId": "BSD-3-Clause-LBNL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/LBNLBSD"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-3-Clause-No-Nuclear-License-2014.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.json",
+      "referenceNumber": "48",
+      "name": "BSD 3-Clause No Nuclear License 2014",
+      "licenseId": "BSD-3-Clause-No-Nuclear-License-2014",
+      "seeAlso": [
+        "https://java.net/projects/javaeetutorial/pages/BerkeleyLicense"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-3-Clause-No-Nuclear-License.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.json",
+      "referenceNumber": "49",
+      "name": "BSD 3-Clause No Nuclear License",
+      "licenseId": "BSD-3-Clause-No-Nuclear-License",
+      "seeAlso": [
+        "http://download.oracle.com/otn-pub/java/licenses/bsd.txt?AuthParam\u003d1467140197_43d516ce1776bd08a58235a7785be1cc"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-3-Clause-No-Nuclear-Warranty.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.json",
+      "referenceNumber": "50",
+      "name": "BSD 3-Clause No Nuclear Warranty",
+      "licenseId": "BSD-3-Clause-No-Nuclear-Warranty",
+      "seeAlso": [
+        "https://jogamp.org/git/?p\u003dgluegen.git;a\u003dblob_plain;f\u003dLICENSE.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-3-Clause.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause.json",
+      "referenceNumber": "51",
+      "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+      "licenseId": "BSD-3-Clause",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/BSD-3-Clause"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./BSD-4-Clause-UC.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-4-Clause-UC.json",
+      "referenceNumber": "52",
+      "name": "BSD-4-Clause (University of California-Specific)",
+      "licenseId": "BSD-4-Clause-UC",
+      "seeAlso": [
+        "http://www.freebsd.org/copyright/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-4-Clause.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/BSD-4-Clause.json",
+      "referenceNumber": "53",
+      "name": "BSD 4-Clause \"Original\" or \"Old\" License",
+      "licenseId": "BSD-4-Clause",
+      "seeAlso": [
+        "http://directory.fsf.org/wiki/License:BSD_4Clause"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-Protection.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-Protection.json",
+      "referenceNumber": "54",
+      "name": "BSD Protection License",
+      "licenseId": "BSD-Protection",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/BSD_Protection_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-Source-Code.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-Source-Code.json",
+      "referenceNumber": "55",
+      "name": "BSD Source Code Attribution",
+      "licenseId": "BSD-Source-Code",
+      "seeAlso": [
+        "https://github.com/robbiehanson/CocoaHTTPServer/blob/master/LICENSE.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/BSL-1.0.json",
+      "referenceNumber": "56",
+      "name": "Boost Software License 1.0",
+      "licenseId": "BSL-1.0",
+      "seeAlso": [
+        "http://www.boost.org/LICENSE_1_0.txt",
+        "http://www.opensource.org/licenses/BSL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./bzip2-1.0.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/bzip2-1.0.5.json",
+      "referenceNumber": "57",
+      "name": "bzip2 and libbzip2 License v1.0.5",
+      "licenseId": "bzip2-1.0.5",
+      "seeAlso": [
+        "http://bzip.org/1.0.5/bzip2-manual-1.0.5.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./bzip2-1.0.6.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/bzip2-1.0.6.json",
+      "referenceNumber": "58",
+      "name": "bzip2 and libbzip2 License v1.0.6",
+      "licenseId": "bzip2-1.0.6",
+      "seeAlso": [
+        "https://github.com/asimonov-im/bzip2/blob/master/LICENSE"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Caldera.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Caldera.json",
+      "referenceNumber": "59",
+      "name": "Caldera License",
+      "licenseId": "Caldera",
+      "seeAlso": [
+        "http://www.lemis.com/grog/UNIX/ancient-source-all.pdf"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CATOSL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CATOSL-1.1.json",
+      "referenceNumber": "60",
+      "name": "Computer Associates Trusted Open Source License 1.1",
+      "licenseId": "CATOSL-1.1",
+      "seeAlso": [
+        "http://opensource.org/licenses/CATOSL-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./CC-BY-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-1.0.json",
+      "referenceNumber": "61",
+      "name": "Creative Commons Attribution 1.0",
+      "licenseId": "CC-BY-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-2.0.json",
+      "referenceNumber": "62",
+      "name": "Creative Commons Attribution 2.0",
+      "licenseId": "CC-BY-2.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by/2.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-2.5.json",
+      "referenceNumber": "63",
+      "name": "Creative Commons Attribution 2.5",
+      "licenseId": "CC-BY-2.5",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by/2.5/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-3.0.json",
+      "referenceNumber": "64",
+      "name": "Creative Commons Attribution 3.0",
+      "licenseId": "CC-BY-3.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by/3.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-4.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-4.0.json",
+      "referenceNumber": "65",
+      "name": "Creative Commons Attribution 4.0",
+      "licenseId": "CC-BY-4.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by/4.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-1.0.json",
+      "referenceNumber": "66",
+      "name": "Creative Commons Attribution Non Commercial 1.0",
+      "licenseId": "CC-BY-NC-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-2.0.json",
+      "referenceNumber": "67",
+      "name": "Creative Commons Attribution Non Commercial 2.0",
+      "licenseId": "CC-BY-NC-2.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc/2.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-2.5.json",
+      "referenceNumber": "68",
+      "name": "Creative Commons Attribution Non Commercial 2.5",
+      "licenseId": "CC-BY-NC-2.5",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc/2.5/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-3.0.json",
+      "referenceNumber": "69",
+      "name": "Creative Commons Attribution Non Commercial 3.0",
+      "licenseId": "CC-BY-NC-3.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc/3.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-4.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-4.0.json",
+      "referenceNumber": "70",
+      "name": "Creative Commons Attribution Non Commercial 4.0",
+      "licenseId": "CC-BY-NC-4.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc/4.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-ND-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-1.0.json",
+      "referenceNumber": "71",
+      "name": "Creative Commons Attribution Non Commercial No Derivatives 1.0",
+      "licenseId": "CC-BY-NC-ND-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nd-nc/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-ND-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-2.0.json",
+      "referenceNumber": "72",
+      "name": "Creative Commons Attribution Non Commercial No Derivatives 2.0",
+      "licenseId": "CC-BY-NC-ND-2.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-nd/2.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-ND-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-2.5.json",
+      "referenceNumber": "73",
+      "name": "Creative Commons Attribution Non Commercial No Derivatives 2.5",
+      "licenseId": "CC-BY-NC-ND-2.5",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-nd/2.5/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-ND-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-3.0.json",
+      "referenceNumber": "74",
+      "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0",
+      "licenseId": "CC-BY-NC-ND-3.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-nd/3.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-ND-4.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-4.0.json",
+      "referenceNumber": "75",
+      "name": "Creative Commons Attribution Non Commercial No Derivatives 4.0",
+      "licenseId": "CC-BY-NC-ND-4.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-nd/4.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-SA-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-1.0.json",
+      "referenceNumber": "76",
+      "name": "Creative Commons Attribution Non Commercial Share Alike 1.0",
+      "licenseId": "CC-BY-NC-SA-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-sa/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-SA-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-2.0.json",
+      "referenceNumber": "77",
+      "name": "Creative Commons Attribution Non Commercial Share Alike 2.0",
+      "licenseId": "CC-BY-NC-SA-2.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-sa/2.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-SA-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-2.5.json",
+      "referenceNumber": "78",
+      "name": "Creative Commons Attribution Non Commercial Share Alike 2.5",
+      "licenseId": "CC-BY-NC-SA-2.5",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-sa/2.5/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-SA-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-3.0.json",
+      "referenceNumber": "79",
+      "name": "Creative Commons Attribution Non Commercial Share Alike 3.0",
+      "licenseId": "CC-BY-NC-SA-3.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-SA-4.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-4.0.json",
+      "referenceNumber": "80",
+      "name": "Creative Commons Attribution Non Commercial Share Alike 4.0",
+      "licenseId": "CC-BY-NC-SA-4.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-sa/4.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-ND-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-1.0.json",
+      "referenceNumber": "81",
+      "name": "Creative Commons Attribution No Derivatives 1.0",
+      "licenseId": "CC-BY-ND-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nd/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-ND-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-2.0.json",
+      "referenceNumber": "82",
+      "name": "Creative Commons Attribution No Derivatives 2.0",
+      "licenseId": "CC-BY-ND-2.0",
+      "seeAlso": [
+        "https://creativecommons.org/licenses/by-nd/2.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-ND-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-2.5.json",
+      "referenceNumber": "83",
+      "name": "Creative Commons Attribution No Derivatives 2.5",
+      "licenseId": "CC-BY-ND-2.5",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nd/2.5/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-ND-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-3.0.json",
+      "referenceNumber": "84",
+      "name": "Creative Commons Attribution No Derivatives 3.0",
+      "licenseId": "CC-BY-ND-3.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nd/3.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-ND-4.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-4.0.json",
+      "referenceNumber": "85",
+      "name": "Creative Commons Attribution No Derivatives 4.0",
+      "licenseId": "CC-BY-ND-4.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nd/4.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-SA-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-1.0.json",
+      "referenceNumber": "86",
+      "name": "Creative Commons Attribution Share Alike 1.0",
+      "licenseId": "CC-BY-SA-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-sa/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-SA-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-2.0.json",
+      "referenceNumber": "87",
+      "name": "Creative Commons Attribution Share Alike 2.0",
+      "licenseId": "CC-BY-SA-2.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-sa/2.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-SA-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-2.5.json",
+      "referenceNumber": "88",
+      "name": "Creative Commons Attribution Share Alike 2.5",
+      "licenseId": "CC-BY-SA-2.5",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-sa/2.5/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-SA-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-3.0.json",
+      "referenceNumber": "89",
+      "name": "Creative Commons Attribution Share Alike 3.0",
+      "licenseId": "CC-BY-SA-3.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-sa/3.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-SA-4.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-4.0.json",
+      "referenceNumber": "90",
+      "name": "Creative Commons Attribution Share Alike 4.0",
+      "licenseId": "CC-BY-SA-4.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-sa/4.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC0-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CC0-1.0.json",
+      "referenceNumber": "91",
+      "name": "Creative Commons Zero v1.0 Universal",
+      "licenseId": "CC0-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/publicdomain/zero/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CDDL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CDDL-1.0.json",
+      "referenceNumber": "92",
+      "name": "Common Development and Distribution License 1.0",
+      "licenseId": "CDDL-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/cddl1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./CDDL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CDDL-1.1.json",
+      "referenceNumber": "93",
+      "name": "Common Development and Distribution License 1.1",
+      "licenseId": "CDDL-1.1",
+      "seeAlso": [
+        "http://glassfish.java.net/public/CDDL+GPL_1_1.html",
+        "https://javaee.github.io/glassfish/LICENSE"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CDLA-Permissive-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CDLA-Permissive-1.0.json",
+      "referenceNumber": "94",
+      "name": "Community Data License Agreement Permissive 1.0",
+      "licenseId": "CDLA-Permissive-1.0",
+      "seeAlso": [
+        "https://cdla.io/permissive-1-0"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CDLA-Sharing-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CDLA-Sharing-1.0.json",
+      "referenceNumber": "95",
+      "name": "Community Data License Agreement Sharing 1.0",
+      "licenseId": "CDLA-Sharing-1.0",
+      "seeAlso": [
+        "https://cdla.io/sharing-1-0"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CECILL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CECILL-1.0.json",
+      "referenceNumber": "96",
+      "name": "CeCILL Free Software License Agreement v1.0",
+      "licenseId": "CECILL-1.0",
+      "seeAlso": [
+        "http://www.cecill.info/licences/Licence_CeCILL_V1-fr.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CECILL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CECILL-1.1.json",
+      "referenceNumber": "97",
+      "name": "CeCILL Free Software License Agreement v1.1",
+      "licenseId": "CECILL-1.1",
+      "seeAlso": [
+        "http://www.cecill.info/licences/Licence_CeCILL_V1.1-US.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CECILL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CECILL-2.0.json",
+      "referenceNumber": "98",
+      "name": "CeCILL Free Software License Agreement v2.0",
+      "licenseId": "CECILL-2.0",
+      "seeAlso": [
+        "http://www.cecill.info/licences/Licence_CeCILL_V2-en.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CECILL-2.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CECILL-2.1.json",
+      "referenceNumber": "99",
+      "name": "CeCILL Free Software License Agreement v2.1",
+      "licenseId": "CECILL-2.1",
+      "seeAlso": [
+        "http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./CECILL-B.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CECILL-B.json",
+      "referenceNumber": "100",
+      "name": "CeCILL-B Free Software License Agreement",
+      "licenseId": "CECILL-B",
+      "seeAlso": [
+        "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CECILL-C.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CECILL-C.json",
+      "referenceNumber": "101",
+      "name": "CeCILL-C Free Software License Agreement",
+      "licenseId": "CECILL-C",
+      "seeAlso": [
+        "http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html\n    "
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ClArtistic.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/ClArtistic.json",
+      "referenceNumber": "102",
+      "name": "Clarified Artistic License",
+      "licenseId": "ClArtistic",
+      "seeAlso": [
+        "http://gianluca.dellavedova.org/2011/01/03/clarified-artistic-license/",
+        "http://www.ncftp.com/ncftp/doc/LICENSE.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CNRI-Jython.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CNRI-Jython.json",
+      "referenceNumber": "103",
+      "name": "CNRI Jython License",
+      "licenseId": "CNRI-Jython",
+      "seeAlso": [
+        "http://www.jython.org/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CNRI-Python-GPL-Compatible.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CNRI-Python-GPL-Compatible.json",
+      "referenceNumber": "104",
+      "name": "CNRI Python Open Source GPL Compatible License Agreement",
+      "licenseId": "CNRI-Python-GPL-Compatible",
+      "seeAlso": [
+        "http://www.python.org/download/releases/1.6.1/download_win/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CNRI-Python.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CNRI-Python.json",
+      "referenceNumber": "105",
+      "name": "CNRI Python License",
+      "licenseId": "CNRI-Python",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/CNRI-Python"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Condor-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Condor-1.1.json",
+      "referenceNumber": "106",
+      "name": "Condor Public License v1.1",
+      "licenseId": "Condor-1.1",
+      "seeAlso": [
+        "http://research.cs.wisc.edu/condor/license.html#condor",
+        "http://web.archive.org/web/20111123062036/http://research.cs.wisc.edu/condor/license.html#condor"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CPAL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CPAL-1.0.json",
+      "referenceNumber": "107",
+      "name": "Common Public Attribution License 1.0",
+      "licenseId": "CPAL-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/CPAL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./CPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CPL-1.0.json",
+      "referenceNumber": "108",
+      "name": "Common Public License 1.0",
+      "licenseId": "CPL-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/CPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./CPOL-1.02.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/CPOL-1.02.json",
+      "referenceNumber": "109",
+      "name": "Code Project Open License 1.02",
+      "licenseId": "CPOL-1.02",
+      "seeAlso": [
+        "http://www.codeproject.com/info/cpol10.aspx"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Crossword.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Crossword.json",
+      "referenceNumber": "110",
+      "name": "Crossword License",
+      "licenseId": "Crossword",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Crossword"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CrystalStacker.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CrystalStacker.json",
+      "referenceNumber": "111",
+      "name": "CrystalStacker License",
+      "licenseId": "CrystalStacker",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing:CrystalStacker?rd\u003dLicensing/CrystalStacker"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CUA-OPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CUA-OPL-1.0.json",
+      "referenceNumber": "112",
+      "name": "CUA Office Public License v1.0",
+      "licenseId": "CUA-OPL-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/CUA-OPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Cube.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Cube.json",
+      "referenceNumber": "113",
+      "name": "Cube License",
+      "licenseId": "Cube",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Cube"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./curl.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/curl.json",
+      "referenceNumber": "114",
+      "name": "curl License",
+      "licenseId": "curl",
+      "seeAlso": [
+        "https://github.com/bagder/curl/blob/master/COPYING"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./D-FSL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/D-FSL-1.0.json",
+      "referenceNumber": "115",
+      "name": "Deutsche Freie Software Lizenz",
+      "licenseId": "D-FSL-1.0",
+      "seeAlso": [
+        "http://www.dipp.nrw.de/d-fsl/lizenzen/",
+        "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/de/D-FSL-1_0_de.txt",
+        "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/en/D-FSL-1_0_en.txt",
+        "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl",
+        "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/deutsche-freie-software-lizenz",
+        "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/german-free-software-license",
+        "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_de.txt/at_download/file",
+        "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_en.txt/at_download/file"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./diffmark.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/diffmark.json",
+      "referenceNumber": "116",
+      "name": "diffmark license",
+      "licenseId": "diffmark",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/diffmark"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./DOC.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/DOC.json",
+      "referenceNumber": "117",
+      "name": "DOC License",
+      "licenseId": "DOC",
+      "seeAlso": [
+        "http://www.cs.wustl.edu/~schmidt/ACE-copying.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Dotseqn.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Dotseqn.json",
+      "referenceNumber": "118",
+      "name": "Dotseqn License",
+      "licenseId": "Dotseqn",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Dotseqn"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./DSDP.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/DSDP.json",
+      "referenceNumber": "119",
+      "name": "DSDP License",
+      "licenseId": "DSDP",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/DSDP"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./dvipdfm.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/dvipdfm.json",
+      "referenceNumber": "120",
+      "name": "dvipdfm License",
+      "licenseId": "dvipdfm",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/dvipdfm"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ECL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ECL-1.0.json",
+      "referenceNumber": "121",
+      "name": "Educational Community License v1.0",
+      "licenseId": "ECL-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/ECL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./ECL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/ECL-2.0.json",
+      "referenceNumber": "122",
+      "name": "Educational Community License v2.0",
+      "licenseId": "ECL-2.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/ECL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./EFL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/EFL-1.0.json",
+      "referenceNumber": "123",
+      "name": "Eiffel Forum License v1.0",
+      "licenseId": "EFL-1.0",
+      "seeAlso": [
+        "http://www.eiffel-nice.org/license/forum.txt",
+        "http://opensource.org/licenses/EFL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./EFL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/EFL-2.0.json",
+      "referenceNumber": "124",
+      "name": "Eiffel Forum License v2.0",
+      "licenseId": "EFL-2.0",
+      "seeAlso": [
+        "http://www.eiffel-nice.org/license/eiffel-forum-license-2.html",
+        "http://opensource.org/licenses/EFL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./eGenix.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/eGenix.json",
+      "referenceNumber": "125",
+      "name": "eGenix.com Public License 1.1.0",
+      "licenseId": "eGenix",
+      "seeAlso": [
+        "http://www.egenix.com/products/eGenix.com-Public-License-1.1.0.pdf",
+        "https://fedoraproject.org/wiki/Licensing/eGenix.com_Public_License_1.1.0"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Entessa.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Entessa.json",
+      "referenceNumber": "126",
+      "name": "Entessa Public License v1.0",
+      "licenseId": "Entessa",
+      "seeAlso": [
+        "http://opensource.org/licenses/Entessa"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./EPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/EPL-1.0.json",
+      "referenceNumber": "127",
+      "name": "Eclipse Public License 1.0",
+      "licenseId": "EPL-1.0",
+      "seeAlso": [
+        "http://www.eclipse.org/legal/epl-v10.html",
+        "http://www.opensource.org/licenses/EPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./EPL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/EPL-2.0.json",
+      "referenceNumber": "128",
+      "name": "Eclipse Public License 2.0",
+      "licenseId": "EPL-2.0",
+      "seeAlso": [
+        "https://www.eclipse.org/legal/epl-2.0",
+        "https://www.opensource.org/licenses/EPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./ErlPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ErlPL-1.1.json",
+      "referenceNumber": "129",
+      "name": "Erlang Public License v1.1",
+      "licenseId": "ErlPL-1.1",
+      "seeAlso": [
+        "http://www.erlang.org/EPLICENSE"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./EUDatagrid.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/EUDatagrid.json",
+      "referenceNumber": "130",
+      "name": "EU DataGrid Software License",
+      "licenseId": "EUDatagrid",
+      "seeAlso": [
+        "http://eu-datagrid.web.cern.ch/eu-datagrid/license.html",
+        "http://www.opensource.org/licenses/EUDatagrid"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./EUPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/EUPL-1.0.json",
+      "referenceNumber": "131",
+      "name": "European Union Public License 1.0",
+      "licenseId": "EUPL-1.0",
+      "seeAlso": [
+        "http://ec.europa.eu/idabc/en/document/7330.html",
+        "http://ec.europa.eu/idabc/servlets/Doc027f.pdf?id\u003d31096"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./EUPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/EUPL-1.1.json",
+      "referenceNumber": "132",
+      "name": "European Union Public License 1.1",
+      "licenseId": "EUPL-1.1",
+      "seeAlso": [
+        "https://joinup.ec.europa.eu/software/page/eupl/licence-eupl",
+        "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl1.1.-licence-en_0.pdf",
+        "http://www.opensource.org/licenses/EUPL-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./EUPL-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/EUPL-1.2.json",
+      "referenceNumber": "133",
+      "name": "European Union Public License 1.2",
+      "licenseId": "EUPL-1.2",
+      "seeAlso": [
+        "https://joinup.ec.europa.eu/page/eupl-text-11-12",
+        "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl_v1.2_en.pdf",
+        "https://joinup.ec.europa.eu/sites/default/files/inline-files/EUPL%20v1_2%20EN(1).txt",
+        "http://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri\u003dCELEX:32017D0863",
+        "http://www.opensource.org/licenses/EUPL-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Eurosym.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Eurosym.json",
+      "referenceNumber": "134",
+      "name": "Eurosym License",
+      "licenseId": "Eurosym",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Eurosym"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Fair.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Fair.json",
+      "referenceNumber": "135",
+      "name": "Fair License",
+      "licenseId": "Fair",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Fair",
+        "http://fairlicense.org/"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Frameworx-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Frameworx-1.0.json",
+      "referenceNumber": "136",
+      "name": "Frameworx Open License 1.0",
+      "licenseId": "Frameworx-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Frameworx-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./FreeImage.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/FreeImage.json",
+      "referenceNumber": "137",
+      "name": "FreeImage Public License v1.0",
+      "licenseId": "FreeImage",
+      "seeAlso": [
+        "http://freeimage.sourceforge.net/freeimage-license.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./FSFAP.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/FSFAP.json",
+      "referenceNumber": "138",
+      "name": "FSF All Permissive License",
+      "licenseId": "FSFAP",
+      "seeAlso": [
+        "http://www.gnu.org/prep/maintain/html_node/License-Notices-for-Other-Files.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./FSFUL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/FSFUL.json",
+      "referenceNumber": "139",
+      "name": "FSF Unlimited License",
+      "licenseId": "FSFUL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./FSFULLR.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/FSFULLR.json",
+      "referenceNumber": "140",
+      "name": "FSF Unlimited License (with License Retention)",
+      "licenseId": "FSFULLR",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License#License_Retention_Variant"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./FTL.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/FTL.json",
+      "referenceNumber": "141",
+      "name": "Freetype Project License",
+      "licenseId": "FTL",
+      "seeAlso": [
+        "http://freetype.fis.uniroma2.it/FTL.TXT",
+        "http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.1-only.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.1-only.json",
+      "referenceNumber": "142",
+      "name": "GNU Free Documentation License v1.1 only",
+      "licenseId": "GFDL-1.1-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/fdl-1.1.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.1-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.1-or-later.json",
+      "referenceNumber": "143",
+      "name": "GNU Free Documentation License v1.1 or later",
+      "licenseId": "GFDL-1.1-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/fdl-1.1.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.2-only.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.2-only.json",
+      "referenceNumber": "144",
+      "name": "GNU Free Documentation License v1.2 only",
+      "licenseId": "GFDL-1.2-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/fdl-1.2.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.2-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.2-or-later.json",
+      "referenceNumber": "145",
+      "name": "GNU Free Documentation License v1.2 or later",
+      "licenseId": "GFDL-1.2-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/fdl-1.2.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.3-only.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.3-only.json",
+      "referenceNumber": "146",
+      "name": "GNU Free Documentation License v1.3 only",
+      "licenseId": "GFDL-1.3-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/fdl-1.3.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.3-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.3-or-later.json",
+      "referenceNumber": "147",
+      "name": "GNU Free Documentation License v1.3 or later",
+      "licenseId": "GFDL-1.3-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/fdl-1.3.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Giftware.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Giftware.json",
+      "referenceNumber": "148",
+      "name": "Giftware License",
+      "licenseId": "Giftware",
+      "seeAlso": [
+        "http://liballeg.org/license.html#allegro-4-the-giftware-license"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GL2PS.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GL2PS.json",
+      "referenceNumber": "149",
+      "name": "GL2PS License",
+      "licenseId": "GL2PS",
+      "seeAlso": [
+        "http://www.geuz.org/gl2ps/COPYING.GL2PS"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Glide.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Glide.json",
+      "referenceNumber": "150",
+      "name": "3dfx Glide License",
+      "licenseId": "Glide",
+      "seeAlso": [
+        "http://www.users.on.net/~triforce/glidexp/COPYING.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Glulxe.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Glulxe.json",
+      "referenceNumber": "151",
+      "name": "Glulxe License",
+      "licenseId": "Glulxe",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Glulxe"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./gnuplot.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/gnuplot.json",
+      "referenceNumber": "152",
+      "name": "gnuplot License",
+      "licenseId": "gnuplot",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Gnuplot"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-1.0-only.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-1.0-only.json",
+      "referenceNumber": "153",
+      "name": "GNU General Public License v1.0 only",
+      "licenseId": "GPL-1.0-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-1.0-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-1.0-or-later.json",
+      "referenceNumber": "154",
+      "name": "GNU General Public License v1.0 or later",
+      "licenseId": "GPL-1.0-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0-only.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-only.json",
+      "referenceNumber": "155",
+      "name": "GNU General Public License v2.0 only",
+      "licenseId": "GPL-2.0-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-2.0-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-or-later.json",
+      "referenceNumber": "156",
+      "name": "GNU General Public License v2.0 or later",
+      "licenseId": "GPL-2.0-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-3.0-only.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-3.0-only.json",
+      "referenceNumber": "157",
+      "name": "GNU General Public License v3.0 only",
+      "licenseId": "GPL-3.0-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-3.0-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-3.0-or-later.json",
+      "referenceNumber": "158",
+      "name": "GNU General Public License v3.0 or later",
+      "licenseId": "GPL-3.0-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./gSOAP-1.3b.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/gSOAP-1.3b.json",
+      "referenceNumber": "159",
+      "name": "gSOAP Public License v1.3b",
+      "licenseId": "gSOAP-1.3b",
+      "seeAlso": [
+        "http://www.cs.fsu.edu/~engelen/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./HaskellReport.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/HaskellReport.json",
+      "referenceNumber": "160",
+      "name": "Haskell Language Report License",
+      "licenseId": "HaskellReport",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Haskell_Language_Report_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./HPND.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/HPND.json",
+      "referenceNumber": "161",
+      "name": "Historical Permission Notice and Disclaimer",
+      "licenseId": "HPND",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/HPND"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./IBM-pibs.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/IBM-pibs.json",
+      "referenceNumber": "162",
+      "name": "IBM PowerPC Initialization and Boot Software",
+      "licenseId": "IBM-pibs",
+      "seeAlso": [
+        "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003darch/powerpc/cpu/ppc4xx/miiphy.c;h\u003d297155fdafa064b955e53e9832de93bfb0cfb85b;hb\u003d9fab4bf4cc077c21e43941866f3f2c196f28670d"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ICU.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ICU.json",
+      "referenceNumber": "163",
+      "name": "ICU License",
+      "licenseId": "ICU",
+      "seeAlso": [
+        "http://source.icu-project.org/repos/icu/icu/trunk/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./IJG.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/IJG.json",
+      "referenceNumber": "164",
+      "name": "Independent JPEG Group License",
+      "licenseId": "IJG",
+      "seeAlso": [
+        "http://dev.w3.org/cvsweb/Amaya/libjpeg/Attic/README?rev\u003d1.2"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ImageMagick.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ImageMagick.json",
+      "referenceNumber": "165",
+      "name": "ImageMagick License",
+      "licenseId": "ImageMagick",
+      "seeAlso": [
+        "http://www.imagemagick.org/script/license.php"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./iMatix.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/iMatix.json",
+      "referenceNumber": "166",
+      "name": "iMatix Standard Function Library Agreement",
+      "licenseId": "iMatix",
+      "seeAlso": [
+        "http://legacy.imatix.com/html/sfl/sfl4.htm#license"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Imlib2.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Imlib2.json",
+      "referenceNumber": "167",
+      "name": "Imlib2 License",
+      "licenseId": "Imlib2",
+      "seeAlso": [
+        "https://git.enlightenment.org/legacy/imlib2.git/tree/COPYING"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Info-ZIP.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Info-ZIP.json",
+      "referenceNumber": "168",
+      "name": "Info-ZIP License",
+      "licenseId": "Info-ZIP",
+      "seeAlso": [
+        "http://www.info-zip.org/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Intel-ACPI.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Intel-ACPI.json",
+      "referenceNumber": "169",
+      "name": "Intel ACPI Software License Agreement",
+      "licenseId": "Intel-ACPI",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Intel_ACPI_Software_License_Agreement"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Intel.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Intel.json",
+      "referenceNumber": "170",
+      "name": "Intel Open Source License",
+      "licenseId": "Intel",
+      "seeAlso": [
+        "http://opensource.org/licenses/Intel"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Interbase-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Interbase-1.0.json",
+      "referenceNumber": "171",
+      "name": "Interbase Public License v1.0",
+      "licenseId": "Interbase-1.0",
+      "seeAlso": [
+        "https://web.archive.org/web/20060319014854/http://info.borland.com/devsupport/interbase/opensource/IPL.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./IPA.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/IPA.json",
+      "referenceNumber": "172",
+      "name": "IPA Font License",
+      "licenseId": "IPA",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/IPA"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./IPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/IPL-1.0.json",
+      "referenceNumber": "173",
+      "name": "IBM Public License v1.0",
+      "licenseId": "IPL-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/IPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./ISC.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/ISC.json",
+      "referenceNumber": "174",
+      "name": "ISC License",
+      "licenseId": "ISC",
+      "seeAlso": [
+        "https://www.isc.org/downloads/software-support-policy/isc-license/",
+        "http://www.opensource.org/licenses/ISC"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./JasPer-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/JasPer-2.0.json",
+      "referenceNumber": "175",
+      "name": "JasPer License",
+      "licenseId": "JasPer-2.0",
+      "seeAlso": [
+        "http://www.ece.uvic.ca/~mdadams/jasper/LICENSE"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./JSON.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/JSON.json",
+      "referenceNumber": "176",
+      "name": "JSON License",
+      "licenseId": "JSON",
+      "seeAlso": [
+        "http://www.json.org/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LAL-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LAL-1.2.json",
+      "referenceNumber": "177",
+      "name": "Licence Art Libre 1.2",
+      "licenseId": "LAL-1.2",
+      "seeAlso": [
+        "http://artlibre.org/licence/lal/licence-art-libre-12/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LAL-1.3.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LAL-1.3.json",
+      "referenceNumber": "178",
+      "name": "Licence Art Libre 1.3",
+      "licenseId": "LAL-1.3",
+      "seeAlso": [
+        "http://artlibre.org/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Latex2e.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Latex2e.json",
+      "referenceNumber": "179",
+      "name": "Latex2e License",
+      "licenseId": "Latex2e",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Latex2e"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Leptonica.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Leptonica.json",
+      "referenceNumber": "180",
+      "name": "Leptonica License",
+      "licenseId": "Leptonica",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Leptonica"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LGPL-2.0-only.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.0-only.json",
+      "referenceNumber": "181",
+      "name": "GNU Library General Public License v2 only",
+      "licenseId": "LGPL-2.0-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.0-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.0-or-later.json",
+      "referenceNumber": "182",
+      "name": "GNU Library General Public License v2 or later",
+      "licenseId": "LGPL-2.0-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.1-only.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.1-only.json",
+      "referenceNumber": "183",
+      "name": "GNU Lesser General Public License v2.1 only",
+      "licenseId": "LGPL-2.1-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-2.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.1-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.1-or-later.json",
+      "referenceNumber": "184",
+      "name": "GNU Lesser General Public License v2.1 or later",
+      "licenseId": "LGPL-2.1-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-2.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-3.0-only.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-3.0-only.json",
+      "referenceNumber": "185",
+      "name": "GNU Lesser General Public License v3.0 only",
+      "licenseId": "LGPL-3.0-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/lgpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-3.0-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-3.0-or-later.json",
+      "referenceNumber": "186",
+      "name": "GNU Lesser General Public License v3.0 or later",
+      "licenseId": "LGPL-3.0-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/lgpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPLLR.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPLLR.json",
+      "referenceNumber": "187",
+      "name": "Lesser General Public License For Linguistic Resources",
+      "licenseId": "LGPLLR",
+      "seeAlso": [
+        "http://www-igm.univ-mlv.fr/~unitex/lgpllr.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Libpng.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Libpng.json",
+      "referenceNumber": "188",
+      "name": "libpng License",
+      "licenseId": "Libpng",
+      "seeAlso": [
+        "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./libtiff.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/libtiff.json",
+      "referenceNumber": "189",
+      "name": "libtiff License",
+      "licenseId": "libtiff",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/libtiff"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LiLiQ-P-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LiLiQ-P-1.1.json",
+      "referenceNumber": "190",
+      "name": "Licence Libre du Québec – Permissive version 1.1",
+      "licenseId": "LiLiQ-P-1.1",
+      "seeAlso": [
+        "http://opensource.org/licenses/LiLiQ-P-1.1",
+        "https://forge.gouv.qc.ca/licence/fr/liliq-v1-1/"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LiLiQ-R-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LiLiQ-R-1.1.json",
+      "referenceNumber": "191",
+      "name": "Licence Libre du Québec – Réciprocité version 1.1",
+      "licenseId": "LiLiQ-R-1.1",
+      "seeAlso": [
+        "http://opensource.org/licenses/LiLiQ-R-1.1",
+        "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-liliq-r-v1-1/"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LiLiQ-Rplus-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LiLiQ-Rplus-1.1.json",
+      "referenceNumber": "192",
+      "name": "Licence Libre du Québec – Réciprocité forte version 1.1",
+      "licenseId": "LiLiQ-Rplus-1.1",
+      "seeAlso": [
+        "http://opensource.org/licenses/LiLiQ-Rplus-1.1",
+        "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-forte-liliq-r-v1-1/"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LPL-1.0.json",
+      "referenceNumber": "193",
+      "name": "Lucent Public License Version 1.0",
+      "licenseId": "LPL-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/LPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LPL-1.02.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LPL-1.02.json",
+      "referenceNumber": "194",
+      "name": "Lucent Public License v1.02",
+      "licenseId": "LPL-1.02",
+      "seeAlso": [
+        "http://plan9.bell-labs.com/plan9/license.html",
+        "http://www.opensource.org/licenses/LPL-1.02"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LPPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LPPL-1.0.json",
+      "referenceNumber": "195",
+      "name": "LaTeX Project Public License v1.0",
+      "licenseId": "LPPL-1.0",
+      "seeAlso": [
+        "http://www.latex-project.org/lppl/lppl-1-0.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LPPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LPPL-1.1.json",
+      "referenceNumber": "196",
+      "name": "LaTeX Project Public License v1.1",
+      "licenseId": "LPPL-1.1",
+      "seeAlso": [
+        "http://www.latex-project.org/lppl/lppl-1-1.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LPPL-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LPPL-1.2.json",
+      "referenceNumber": "197",
+      "name": "LaTeX Project Public License v1.2",
+      "licenseId": "LPPL-1.2",
+      "seeAlso": [
+        "http://www.latex-project.org/lppl/lppl-1-2.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LPPL-1.3a.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LPPL-1.3a.json",
+      "referenceNumber": "198",
+      "name": "LaTeX Project Public License v1.3a",
+      "licenseId": "LPPL-1.3a",
+      "seeAlso": [
+        "http://www.latex-project.org/lppl/lppl-1-3a.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LPPL-1.3c.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LPPL-1.3c.json",
+      "referenceNumber": "199",
+      "name": "LaTeX Project Public License v1.3c",
+      "licenseId": "LPPL-1.3c",
+      "seeAlso": [
+        "http://www.latex-project.org/lppl/lppl-1-3c.txt",
+        "http://www.opensource.org/licenses/LPPL-1.3c"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MakeIndex.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MakeIndex.json",
+      "referenceNumber": "200",
+      "name": "MakeIndex License",
+      "licenseId": "MakeIndex",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MakeIndex"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./MirOS.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MirOS.json",
+      "referenceNumber": "201",
+      "name": "MirOS License",
+      "licenseId": "MirOS",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/MirOS"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MIT-advertising.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MIT-advertising.json",
+      "referenceNumber": "202",
+      "name": "Enlightenment License (e16)",
+      "licenseId": "MIT-advertising",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MIT_With_Advertising"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./MIT-CMU.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MIT-CMU.json",
+      "referenceNumber": "203",
+      "name": "CMU License",
+      "licenseId": "MIT-CMU",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing:MIT?rd\u003dLicensing/MIT#CMU_Style"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./MIT-enna.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MIT-enna.json",
+      "referenceNumber": "204",
+      "name": "enna License",
+      "licenseId": "MIT-enna",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MIT#enna"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./MIT-feh.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MIT-feh.json",
+      "referenceNumber": "205",
+      "name": "feh License",
+      "licenseId": "MIT-feh",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MIT#feh"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./MIT.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/MIT.json",
+      "referenceNumber": "206",
+      "name": "MIT License",
+      "licenseId": "MIT",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/MIT"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MITNFA.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MITNFA.json",
+      "referenceNumber": "207",
+      "name": "MIT +no-false-attribs license",
+      "licenseId": "MITNFA",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MITNFA"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Motosoto.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Motosoto.json",
+      "referenceNumber": "208",
+      "name": "Motosoto License",
+      "licenseId": "Motosoto",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Motosoto"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./mpich2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/mpich2.json",
+      "referenceNumber": "209",
+      "name": "mpich2 License",
+      "licenseId": "mpich2",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MIT"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./MPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MPL-1.0.json",
+      "referenceNumber": "210",
+      "name": "Mozilla Public License 1.0",
+      "licenseId": "MPL-1.0",
+      "seeAlso": [
+        "http://www.mozilla.org/MPL/MPL-1.0.html",
+        "http://opensource.org/licenses/MPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/MPL-1.1.json",
+      "referenceNumber": "211",
+      "name": "Mozilla Public License 1.1",
+      "licenseId": "MPL-1.1",
+      "seeAlso": [
+        "http://www.mozilla.org/MPL/MPL-1.1.html",
+        "http://www.opensource.org/licenses/MPL-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MPL-2.0-no-copyleft-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MPL-2.0-no-copyleft-exception.json",
+      "referenceNumber": "212",
+      "name": "Mozilla Public License 2.0 (no copyleft exception)",
+      "licenseId": "MPL-2.0-no-copyleft-exception",
+      "seeAlso": [
+        "http://www.mozilla.org/MPL/2.0/",
+        "http://opensource.org/licenses/MPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MPL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/MPL-2.0.json",
+      "referenceNumber": "213",
+      "name": "Mozilla Public License 2.0",
+      "licenseId": "MPL-2.0",
+      "seeAlso": [
+        "http://www.mozilla.org/MPL/2.0/",
+        "http://opensource.org/licenses/MPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MS-PL.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/MS-PL.json",
+      "referenceNumber": "214",
+      "name": "Microsoft Public License",
+      "licenseId": "MS-PL",
+      "seeAlso": [
+        "http://www.microsoft.com/opensource/licenses.mspx",
+        "http://www.opensource.org/licenses/MS-PL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MS-RL.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/MS-RL.json",
+      "referenceNumber": "215",
+      "name": "Microsoft Reciprocal License",
+      "licenseId": "MS-RL",
+      "seeAlso": [
+        "http://www.microsoft.com/opensource/licenses.mspx",
+        "http://www.opensource.org/licenses/MS-RL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MTLL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MTLL.json",
+      "referenceNumber": "216",
+      "name": "Matrix Template Library License",
+      "licenseId": "MTLL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Matrix_Template_Library_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Multics.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Multics.json",
+      "referenceNumber": "217",
+      "name": "Multics License",
+      "licenseId": "Multics",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Multics"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Mup.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Mup.json",
+      "referenceNumber": "218",
+      "name": "Mup License",
+      "licenseId": "Mup",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Mup"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NASA-1.3.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/NASA-1.3.json",
+      "referenceNumber": "219",
+      "name": "NASA Open Source Agreement 1.3",
+      "licenseId": "NASA-1.3",
+      "seeAlso": [
+        "http://ti.arc.nasa.gov/opensource/nosa/",
+        "http://www.opensource.org/licenses/NASA-1.3"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Naumen.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Naumen.json",
+      "referenceNumber": "220",
+      "name": "Naumen Public License",
+      "licenseId": "Naumen",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Naumen"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./NBPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NBPL-1.0.json",
+      "referenceNumber": "221",
+      "name": "Net Boolean Public License v1",
+      "licenseId": "NBPL-1.0",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d37b4b3f6cc4bf34e1d3dec61e69914b9819d8894"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NCSA.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/NCSA.json",
+      "referenceNumber": "222",
+      "name": "University of Illinois/NCSA Open Source License",
+      "licenseId": "NCSA",
+      "seeAlso": [
+        "http://otm.illinois.edu/uiuc_openSource",
+        "http://www.opensource.org/licenses/NCSA"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Net-SNMP.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Net-SNMP.json",
+      "referenceNumber": "223",
+      "name": "Net-SNMP License",
+      "licenseId": "Net-SNMP",
+      "seeAlso": [
+        "http://net-snmp.sourceforge.net/about/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NetCDF.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NetCDF.json",
+      "referenceNumber": "224",
+      "name": "NetCDF license",
+      "licenseId": "NetCDF",
+      "seeAlso": [
+        "http://www.unidata.ucar.edu/software/netcdf/copyright.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Newsletr.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Newsletr.json",
+      "referenceNumber": "225",
+      "name": "Newsletr License",
+      "licenseId": "Newsletr",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Newsletr"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NGPL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NGPL.json",
+      "referenceNumber": "226",
+      "name": "Nethack General Public License",
+      "licenseId": "NGPL",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/NGPL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./NLOD-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NLOD-1.0.json",
+      "referenceNumber": "227",
+      "name": "Norwegian Licence for Open Government Data",
+      "licenseId": "NLOD-1.0",
+      "seeAlso": [
+        "http://data.norge.no/nlod/en/1.0"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NLPL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NLPL.json",
+      "referenceNumber": "228",
+      "name": "No Limit Public License",
+      "licenseId": "NLPL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/NLPL"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Nokia.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Nokia.json",
+      "referenceNumber": "229",
+      "name": "Nokia Open Source License",
+      "licenseId": "Nokia",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/nokia"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./NOSL.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/NOSL.json",
+      "referenceNumber": "230",
+      "name": "Netizen Open Source License",
+      "licenseId": "NOSL",
+      "seeAlso": [
+        "http://bits.netizen.com.au/licenses/NOSL/nosl.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Noweb.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Noweb.json",
+      "referenceNumber": "231",
+      "name": "Noweb License",
+      "licenseId": "Noweb",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Noweb"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/NPL-1.0.json",
+      "referenceNumber": "232",
+      "name": "Netscape Public License v1.0",
+      "licenseId": "NPL-1.0",
+      "seeAlso": [
+        "http://www.mozilla.org/MPL/NPL/1.0/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/NPL-1.1.json",
+      "referenceNumber": "233",
+      "name": "Netscape Public License v1.1",
+      "licenseId": "NPL-1.1",
+      "seeAlso": [
+        "http://www.mozilla.org/MPL/NPL/1.1/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NPOSL-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NPOSL-3.0.json",
+      "referenceNumber": "234",
+      "name": "Non-Profit Open Software License 3.0",
+      "licenseId": "NPOSL-3.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/NOSL3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./NRL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NRL.json",
+      "referenceNumber": "235",
+      "name": "NRL License",
+      "licenseId": "NRL",
+      "seeAlso": [
+        "http://web.mit.edu/network/isakmp/nrllicense.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NTP.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NTP.json",
+      "referenceNumber": "236",
+      "name": "NTP License",
+      "licenseId": "NTP",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/NTP"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OCCT-PL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OCCT-PL.json",
+      "referenceNumber": "237",
+      "name": "Open CASCADE Technology Public License",
+      "licenseId": "OCCT-PL",
+      "seeAlso": [
+        "http://www.opencascade.com/content/occt-public-license"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OCLC-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OCLC-2.0.json",
+      "referenceNumber": "238",
+      "name": "OCLC Research Public License 2.0",
+      "licenseId": "OCLC-2.0",
+      "seeAlso": [
+        "http://www.oclc.org/research/activities/software/license/v2final.htm",
+        "http://www.opensource.org/licenses/OCLC-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./ODbL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/ODbL-1.0.json",
+      "referenceNumber": "239",
+      "name": "ODC Open Database License v1.0",
+      "licenseId": "ODbL-1.0",
+      "seeAlso": [
+        "http://www.opendatacommons.org/licenses/odbl/1.0/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OFL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OFL-1.0.json",
+      "referenceNumber": "240",
+      "name": "SIL Open Font License 1.0",
+      "licenseId": "OFL-1.0",
+      "seeAlso": [
+        "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OFL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OFL-1.1.json",
+      "referenceNumber": "241",
+      "name": "SIL Open Font License 1.1",
+      "licenseId": "OFL-1.1",
+      "seeAlso": [
+        "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web",
+        "http://www.opensource.org/licenses/OFL-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OGTSL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OGTSL.json",
+      "referenceNumber": "242",
+      "name": "Open Group Test Suite License",
+      "licenseId": "OGTSL",
+      "seeAlso": [
+        "http://www.opengroup.org/testing/downloads/The_Open_Group_TSL.txt",
+        "http://www.opensource.org/licenses/OGTSL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OLDAP-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-1.1.json",
+      "referenceNumber": "243",
+      "name": "Open LDAP Public License v1.1",
+      "licenseId": "OLDAP-1.1",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d806557a5ad59804ef3a44d5abfbe91d706b0791f"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-1.2.json",
+      "referenceNumber": "244",
+      "name": "Open LDAP Public License v1.2",
+      "licenseId": "OLDAP-1.2",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d42b0383c50c299977b5893ee695cf4e486fb0dc7"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-1.3.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-1.3.json",
+      "referenceNumber": "245",
+      "name": "Open LDAP Public License v1.3",
+      "licenseId": "OLDAP-1.3",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003de5f8117f0ce088d0bd7a8e18ddf37eaa40eb09b1"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-1.4.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-1.4.json",
+      "referenceNumber": "246",
+      "name": "Open LDAP Public License v1.4",
+      "licenseId": "OLDAP-1.4",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dc9f95c2f3f2ffb5e0ae55fe7388af75547660941"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.0.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.0.1.json",
+      "referenceNumber": "247",
+      "name": "Open LDAP Public License v2.0.1",
+      "licenseId": "OLDAP-2.0.1",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db6d68acd14e51ca3aab4428bf26522aa74873f0e"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.0.json",
+      "referenceNumber": "248",
+      "name": "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
+      "licenseId": "OLDAP-2.0",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcbf50f4e1185a21abd4c0a54d3f4341fe28f36ea"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.1.json",
+      "referenceNumber": "249",
+      "name": "Open LDAP Public License v2.1",
+      "licenseId": "OLDAP-2.1",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db0d176738e96a0d3b9f85cb51e140a86f21be715"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.2.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.1.json",
+      "referenceNumber": "250",
+      "name": "Open LDAP Public License v2.2.1",
+      "licenseId": "OLDAP-2.2.1",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d4bc786f34b50aa301be6f5600f58a980070f481e"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.2.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.2.json",
+      "referenceNumber": "251",
+      "name": "Open LDAP Public License 2.2.2",
+      "licenseId": "OLDAP-2.2.2",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003ddf2cc1e21eb7c160695f5b7cffd6296c151ba188"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.json",
+      "referenceNumber": "252",
+      "name": "Open LDAP Public License v2.2",
+      "licenseId": "OLDAP-2.2",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d470b0c18ec67621c85881b2733057fecf4a1acc3"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.3.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.3.json",
+      "referenceNumber": "253",
+      "name": "Open LDAP Public License v2.3",
+      "licenseId": "OLDAP-2.3",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dd32cf54a32d581ab475d23c810b0a7fbaf8d63c3"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.4.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.4.json",
+      "referenceNumber": "254",
+      "name": "Open LDAP Public License v2.4",
+      "licenseId": "OLDAP-2.4",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcd1284c4a91a8a380d904eee68d1583f989ed386"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.5.json",
+      "referenceNumber": "255",
+      "name": "Open LDAP Public License v2.5",
+      "licenseId": "OLDAP-2.5",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d6852b9d90022e8593c98205413380536b1b5a7cf"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.6.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.6.json",
+      "referenceNumber": "256",
+      "name": "Open LDAP Public License v2.6",
+      "licenseId": "OLDAP-2.6",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d1cae062821881f41b73012ba816434897abf4205"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.7.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.7.json",
+      "referenceNumber": "257",
+      "name": "Open LDAP Public License v2.7",
+      "licenseId": "OLDAP-2.7",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d47c2415c1df81556eeb39be6cad458ef87c534a2"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.8.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.8.json",
+      "referenceNumber": "258",
+      "name": "Open LDAP Public License v2.8",
+      "licenseId": "OLDAP-2.8",
+      "seeAlso": [
+        "http://www.openldap.org/software/release/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OML.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OML.json",
+      "referenceNumber": "259",
+      "name": "Open Market License",
+      "licenseId": "OML",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Open_Market_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OpenSSL.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OpenSSL.json",
+      "referenceNumber": "260",
+      "name": "OpenSSL License",
+      "licenseId": "OpenSSL",
+      "seeAlso": [
+        "http://www.openssl.org/source/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/OPL-1.0.json",
+      "referenceNumber": "261",
+      "name": "Open Public License v1.0",
+      "licenseId": "OPL-1.0",
+      "seeAlso": [
+        "http://old.koalateam.com/jackaroo/OPL_1_0.TXT",
+        "https://fedoraproject.org/wiki/Licensing/Open_Public_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OSET-PL-2.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OSET-PL-2.1.json",
+      "referenceNumber": "262",
+      "name": "OSET Public License version 2.1",
+      "licenseId": "OSET-PL-2.1",
+      "seeAlso": [
+        "http://opensource.org/licenses/OPL-2.1",
+        "http://www.osetfoundation.org/public-license"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OSL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OSL-1.0.json",
+      "referenceNumber": "263",
+      "name": "Open Software License 1.0",
+      "licenseId": "OSL-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/OSL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OSL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OSL-1.1.json",
+      "referenceNumber": "264",
+      "name": "Open Software License 1.1",
+      "licenseId": "OSL-1.1",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/OSL1.1"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OSL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OSL-2.0.json",
+      "referenceNumber": "265",
+      "name": "Open Software License 2.0",
+      "licenseId": "OSL-2.0",
+      "seeAlso": [
+        "http://web.archive.org/web/20041020171434/http://www.rosenlaw.com/osl2.0.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OSL-2.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OSL-2.1.json",
+      "referenceNumber": "266",
+      "name": "Open Software License 2.1",
+      "licenseId": "OSL-2.1",
+      "seeAlso": [
+        "http://opensource.org/licenses/OSL-2.1",
+        "http://web.archive.org/web/20050212003940/http://www.rosenlaw.com/osl21.htm"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OSL-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OSL-3.0.json",
+      "referenceNumber": "267",
+      "name": "Open Software License 3.0",
+      "licenseId": "OSL-3.0",
+      "seeAlso": [
+        "http://www.rosenlaw.com/OSL3.0.htm",
+        "http://www.opensource.org/licenses/OSL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./PDDL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/PDDL-1.0.json",
+      "referenceNumber": "268",
+      "name": "ODC Public Domain Dedication \u0026 License 1.0",
+      "licenseId": "PDDL-1.0",
+      "seeAlso": [
+        "http://opendatacommons.org/licenses/pddl/1.0/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./PHP-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/PHP-3.0.json",
+      "referenceNumber": "269",
+      "name": "PHP License v3.0",
+      "licenseId": "PHP-3.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/PHP-3.0",
+        "http://www.php.net/license/3_0.txt"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./PHP-3.01.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/PHP-3.01.json",
+      "referenceNumber": "270",
+      "name": "PHP License v3.01",
+      "licenseId": "PHP-3.01",
+      "seeAlso": [
+        "http://www.php.net/license/3_01.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Plexus.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Plexus.json",
+      "referenceNumber": "271",
+      "name": "Plexus Classworlds License",
+      "licenseId": "Plexus",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Plexus_Classworlds_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./PostgreSQL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/PostgreSQL.json",
+      "referenceNumber": "272",
+      "name": "PostgreSQL License",
+      "licenseId": "PostgreSQL",
+      "seeAlso": [
+        "http://www.postgresql.org/about/licence",
+        "http://www.opensource.org/licenses/PostgreSQL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./psfrag.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/psfrag.json",
+      "referenceNumber": "273",
+      "name": "psfrag License",
+      "licenseId": "psfrag",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/psfrag"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./psutils.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/psutils.json",
+      "referenceNumber": "274",
+      "name": "psutils License",
+      "licenseId": "psutils",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/psutils"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Python-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Python-2.0.json",
+      "referenceNumber": "275",
+      "name": "Python License 2.0",
+      "licenseId": "Python-2.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Python-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Qhull.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Qhull.json",
+      "referenceNumber": "276",
+      "name": "Qhull License",
+      "licenseId": "Qhull",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Qhull"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./QPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/QPL-1.0.json",
+      "referenceNumber": "277",
+      "name": "Q Public License 1.0",
+      "licenseId": "QPL-1.0",
+      "seeAlso": [
+        "http://doc.qt.nokia.com/3.3/license.html",
+        "http://www.opensource.org/licenses/QPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Rdisc.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Rdisc.json",
+      "referenceNumber": "278",
+      "name": "Rdisc License",
+      "licenseId": "Rdisc",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Rdisc_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./RHeCos-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/RHeCos-1.1.json",
+      "referenceNumber": "279",
+      "name": "Red Hat eCos Public License v1.1",
+      "licenseId": "RHeCos-1.1",
+      "seeAlso": [
+        "http://ecos.sourceware.org/old-license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./RPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/RPL-1.1.json",
+      "referenceNumber": "280",
+      "name": "Reciprocal Public License 1.1",
+      "licenseId": "RPL-1.1",
+      "seeAlso": [
+        "http://opensource.org/licenses/RPL-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./RPL-1.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/RPL-1.5.json",
+      "referenceNumber": "281",
+      "name": "Reciprocal Public License 1.5",
+      "licenseId": "RPL-1.5",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/RPL-1.5"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./RPSL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/RPSL-1.0.json",
+      "referenceNumber": "282",
+      "name": "RealNetworks Public Source License v1.0",
+      "licenseId": "RPSL-1.0",
+      "seeAlso": [
+        "https://helixcommunity.org/content/rpsl",
+        "http://www.opensource.org/licenses/RPSL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./RSA-MD.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/RSA-MD.json",
+      "referenceNumber": "283",
+      "name": "RSA Message-Digest License ",
+      "licenseId": "RSA-MD",
+      "seeAlso": [
+        "http://www.faqs.org/rfcs/rfc1321.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./RSCPL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/RSCPL.json",
+      "referenceNumber": "284",
+      "name": "Ricoh Source Code Public License",
+      "licenseId": "RSCPL",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/RSCPL",
+        "http://wayback.archive.org/web/20060715140826/http://www.risource.org/RPL/RPL-1.0A.shtml"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Ruby.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Ruby.json",
+      "referenceNumber": "285",
+      "name": "Ruby License",
+      "licenseId": "Ruby",
+      "seeAlso": [
+        "http://www.ruby-lang.org/en/LICENSE.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SAX-PD.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SAX-PD.json",
+      "referenceNumber": "286",
+      "name": "Sax Public Domain Notice",
+      "licenseId": "SAX-PD",
+      "seeAlso": [
+        "http://www.saxproject.org/copying.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Saxpath.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Saxpath.json",
+      "referenceNumber": "287",
+      "name": "Saxpath License",
+      "licenseId": "Saxpath",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Saxpath_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SCEA.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SCEA.json",
+      "referenceNumber": "288",
+      "name": "SCEA Shared Source License",
+      "licenseId": "SCEA",
+      "seeAlso": [
+        "http://research.scea.com/scea_shared_source_license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Sendmail.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Sendmail.json",
+      "referenceNumber": "289",
+      "name": "Sendmail License",
+      "licenseId": "Sendmail",
+      "seeAlso": [
+        "http://www.sendmail.com/pdfs/open_source/sendmail_license.pdf",
+        "https://web.archive.org/web/20160322142305/https://www.sendmail.com/pdfs/open_source/sendmail_license.pdf"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SGI-B-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SGI-B-1.0.json",
+      "referenceNumber": "290",
+      "name": "SGI Free Software License B v1.0",
+      "licenseId": "SGI-B-1.0",
+      "seeAlso": [
+        "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.1.0.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SGI-B-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SGI-B-1.1.json",
+      "referenceNumber": "291",
+      "name": "SGI Free Software License B v1.1",
+      "licenseId": "SGI-B-1.1",
+      "seeAlso": [
+        "http://oss.sgi.com/projects/FreeB/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SGI-B-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/SGI-B-2.0.json",
+      "referenceNumber": "292",
+      "name": "SGI Free Software License B v2.0",
+      "licenseId": "SGI-B-2.0",
+      "seeAlso": [
+        "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.2.0.pdf"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SimPL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SimPL-2.0.json",
+      "referenceNumber": "293",
+      "name": "Simple Public License 2.0",
+      "licenseId": "SimPL-2.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/SimPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./SISSL-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SISSL-1.2.json",
+      "referenceNumber": "294",
+      "name": "Sun Industry Standards Source License v1.2",
+      "licenseId": "SISSL-1.2",
+      "seeAlso": [
+        "http://gridscheduler.sourceforge.net/Gridengine_SISSL_license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SISSL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SISSL.json",
+      "referenceNumber": "295",
+      "name": "Sun Industry Standards Source License v1.1",
+      "licenseId": "SISSL",
+      "seeAlso": [
+        "http://www.openoffice.org/licenses/sissl_license.html",
+        "http://opensource.org/licenses/SISSL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Sleepycat.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Sleepycat.json",
+      "referenceNumber": "296",
+      "name": "Sleepycat License",
+      "licenseId": "Sleepycat",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Sleepycat"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./SMLNJ.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/SMLNJ.json",
+      "referenceNumber": "297",
+      "name": "Standard ML of New Jersey License",
+      "licenseId": "SMLNJ",
+      "seeAlso": [
+        "https://www.smlnj.org/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SMPPL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SMPPL.json",
+      "referenceNumber": "298",
+      "name": "Secure Messaging Protocol Public License",
+      "licenseId": "SMPPL",
+      "seeAlso": [
+        "https://github.com/dcblake/SMP/blob/master/Documentation/License.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SNIA.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SNIA.json",
+      "referenceNumber": "299",
+      "name": "SNIA Public License 1.1",
+      "licenseId": "SNIA",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/SNIA_Public_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Spencer-86.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Spencer-86.json",
+      "referenceNumber": "300",
+      "name": "Spencer License 86",
+      "licenseId": "Spencer-86",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Spencer-94.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Spencer-94.json",
+      "referenceNumber": "301",
+      "name": "Spencer License 94",
+      "licenseId": "Spencer-94",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Spencer-99.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Spencer-99.json",
+      "referenceNumber": "302",
+      "name": "Spencer License 99",
+      "licenseId": "Spencer-99",
+      "seeAlso": [
+        "http://www.opensource.apple.com/source/tcl/tcl-5/tcl/generic/regfronts.c"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/SPL-1.0.json",
+      "referenceNumber": "303",
+      "name": "Sun Public License v1.0",
+      "licenseId": "SPL-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/SPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./SugarCRM-1.1.3.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SugarCRM-1.1.3.json",
+      "referenceNumber": "304",
+      "name": "SugarCRM Public License v1.1.3",
+      "licenseId": "SugarCRM-1.1.3",
+      "seeAlso": [
+        "http://www.sugarcrm.com/crm/SPL"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SWL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SWL.json",
+      "referenceNumber": "305",
+      "name": "Scheme Widget Library (SWL) Software License Agreement",
+      "licenseId": "SWL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/SWL"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./TCL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/TCL.json",
+      "referenceNumber": "306",
+      "name": "TCL/TK License",
+      "licenseId": "TCL",
+      "seeAlso": [
+        "http://www.tcl.tk/software/tcltk/license.html",
+        "https://fedoraproject.org/wiki/Licensing/TCL"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./TCP-wrappers.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/TCP-wrappers.json",
+      "referenceNumber": "307",
+      "name": "TCP Wrappers License",
+      "licenseId": "TCP-wrappers",
+      "seeAlso": [
+        "http://rc.quest.com/topics/openssh/license.php#tcpwrappers"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./TMate.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/TMate.json",
+      "referenceNumber": "308",
+      "name": "TMate Open Source License",
+      "licenseId": "TMate",
+      "seeAlso": [
+        "http://svnkit.com/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./TORQUE-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/TORQUE-1.1.json",
+      "referenceNumber": "309",
+      "name": "TORQUE v2.5+ Software License v1.1",
+      "licenseId": "TORQUE-1.1",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/TORQUEv1.1"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./TOSL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/TOSL.json",
+      "referenceNumber": "310",
+      "name": "Trusster Open Source License",
+      "licenseId": "TOSL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/TOSL"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Unicode-DFS-2015.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Unicode-DFS-2015.json",
+      "referenceNumber": "311",
+      "name": "Unicode License Agreement - Data Files and Software (2015)",
+      "licenseId": "Unicode-DFS-2015",
+      "seeAlso": [
+        "https://web.archive.org/web/20151224134844/http://unicode.org/copyright.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Unicode-DFS-2016.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Unicode-DFS-2016.json",
+      "referenceNumber": "312",
+      "name": "Unicode License Agreement - Data Files and Software (2016)",
+      "licenseId": "Unicode-DFS-2016",
+      "seeAlso": [
+        "http://www.unicode.org/copyright.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Unicode-TOU.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Unicode-TOU.json",
+      "referenceNumber": "313",
+      "name": "Unicode Terms of Use",
+      "licenseId": "Unicode-TOU",
+      "seeAlso": [
+        "http://www.unicode.org/copyright.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Unlicense.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Unlicense.json",
+      "referenceNumber": "314",
+      "name": "The Unlicense",
+      "licenseId": "Unlicense",
+      "seeAlso": [
+        "http://unlicense.org/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./UPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/UPL-1.0.json",
+      "referenceNumber": "315",
+      "name": "Universal Permissive License v1.0",
+      "licenseId": "UPL-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/UPL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Vim.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Vim.json",
+      "referenceNumber": "316",
+      "name": "Vim License",
+      "licenseId": "Vim",
+      "seeAlso": [
+        "http://vimdoc.sourceforge.net/htmldoc/uganda.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./VOSTROM.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/VOSTROM.json",
+      "referenceNumber": "317",
+      "name": "VOSTROM Public License for Open Source",
+      "licenseId": "VOSTROM",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/VOSTROM"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./VSL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/VSL-1.0.json",
+      "referenceNumber": "318",
+      "name": "Vovida Software License v1.0",
+      "licenseId": "VSL-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/VSL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./W3C-19980720.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/W3C-19980720.json",
+      "referenceNumber": "319",
+      "name": "W3C Software Notice and License (1998-07-20)",
+      "licenseId": "W3C-19980720",
+      "seeAlso": [
+        "http://www.w3.org/Consortium/Legal/copyright-software-19980720.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./W3C-20150513.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/W3C-20150513.json",
+      "referenceNumber": "320",
+      "name": "W3C Software Notice and Document License (2015-05-13)",
+      "licenseId": "W3C-20150513",
+      "seeAlso": [
+        "https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./W3C.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/W3C.json",
+      "referenceNumber": "321",
+      "name": "W3C Software Notice and License (2002-12-31)",
+      "licenseId": "W3C",
+      "seeAlso": [
+        "http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html",
+        "http://www.opensource.org/licenses/W3C"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Watcom-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/Watcom-1.0.json",
+      "referenceNumber": "322",
+      "name": "Sybase Open Watcom Public License 1.0",
+      "licenseId": "Watcom-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Watcom-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Wsuipa.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Wsuipa.json",
+      "referenceNumber": "323",
+      "name": "Wsuipa License",
+      "licenseId": "Wsuipa",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Wsuipa"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./WTFPL.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/WTFPL.json",
+      "referenceNumber": "324",
+      "name": "Do What The F*ck You Want To Public License",
+      "licenseId": "WTFPL",
+      "seeAlso": [
+        "http://sam.zoy.org/wtfpl/COPYING"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./X11.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/X11.json",
+      "referenceNumber": "325",
+      "name": "X11 License",
+      "licenseId": "X11",
+      "seeAlso": [
+        "http://www.xfree86.org/3.3.6/COPYRIGHT2.html#3"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Xerox.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Xerox.json",
+      "referenceNumber": "326",
+      "name": "Xerox License",
+      "licenseId": "Xerox",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Xerox"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./XFree86-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/XFree86-1.1.json",
+      "referenceNumber": "327",
+      "name": "XFree86 License 1.1",
+      "licenseId": "XFree86-1.1",
+      "seeAlso": [
+        "http://www.xfree86.org/current/LICENSE4.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./xinetd.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/xinetd.json",
+      "referenceNumber": "328",
+      "name": "xinetd License",
+      "licenseId": "xinetd",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Xinetd_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Xnet.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Xnet.json",
+      "referenceNumber": "329",
+      "name": "X.Net License",
+      "licenseId": "Xnet",
+      "seeAlso": [
+        "http://opensource.org/licenses/Xnet"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./xpp.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/xpp.json",
+      "referenceNumber": "330",
+      "name": "XPP License",
+      "licenseId": "xpp",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/xpp"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./XSkat.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/XSkat.json",
+      "referenceNumber": "331",
+      "name": "XSkat License",
+      "licenseId": "XSkat",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/XSkat_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./YPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/YPL-1.0.json",
+      "referenceNumber": "332",
+      "name": "Yahoo! Public License v1.0",
+      "licenseId": "YPL-1.0",
+      "seeAlso": [
+        "http://www.zimbra.com/license/yahoo_public_license_1.0.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./YPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/YPL-1.1.json",
+      "referenceNumber": "333",
+      "name": "Yahoo! Public License v1.1",
+      "licenseId": "YPL-1.1",
+      "seeAlso": [
+        "http://www.zimbra.com/license/yahoo_public_license_1.1.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Zed.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Zed.json",
+      "referenceNumber": "334",
+      "name": "Zed License",
+      "licenseId": "Zed",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Zed"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Zend-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Zend-2.0.json",
+      "referenceNumber": "335",
+      "name": "Zend License v2.0",
+      "licenseId": "Zend-2.0",
+      "seeAlso": [
+        "https://web.archive.org/web/20130517195954/http://www.zend.com/license/2_00.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Zimbra-1.3.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Zimbra-1.3.json",
+      "referenceNumber": "336",
+      "name": "Zimbra Public License v1.3",
+      "licenseId": "Zimbra-1.3",
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Zimbra-1.4.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Zimbra-1.4.json",
+      "referenceNumber": "337",
+      "name": "Zimbra Public License v1.4",
+      "licenseId": "Zimbra-1.4",
+      "seeAlso": [
+        "http://www.zimbra.com/legal/zimbra-public-license-1-4"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./zlib-acknowledgement.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/zlib-acknowledgement.json",
+      "referenceNumber": "338",
+      "name": "zlib/libpng License with Acknowledgement",
+      "licenseId": "zlib-acknowledgement",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/ZlibWithAcknowledgement"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Zlib.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Zlib.json",
+      "referenceNumber": "339",
+      "name": "zlib License",
+      "licenseId": "Zlib",
+      "seeAlso": [
+        "http://www.zlib.net/zlib_license.html",
+        "http://www.opensource.org/licenses/Zlib"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./ZPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ZPL-1.1.json",
+      "referenceNumber": "340",
+      "name": "Zope Public License 1.1",
+      "licenseId": "ZPL-1.1",
+      "seeAlso": [
+        "http://old.zope.org/Resources/License/ZPL-1.1"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ZPL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/ZPL-2.0.json",
+      "referenceNumber": "341",
+      "name": "Zope Public License 2.0",
+      "licenseId": "ZPL-2.0",
+      "seeAlso": [
+        "http://old.zope.org/Resources/License/ZPL-2.0",
+        "http://opensource.org/licenses/ZPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./ZPL-2.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/ZPL-2.1.json",
+      "referenceNumber": "342",
+      "name": "Zope Public License 2.1",
+      "licenseId": "ZPL-2.1",
+      "seeAlso": [
+        "http://old.zope.org/Resources/ZPL/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AGPL-3.0.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/AGPL-3.0.json",
+      "referenceNumber": "343",
+      "name": "GNU Affero General Public License v3.0",
+      "licenseId": "AGPL-3.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/agpl.txt",
+        "http://www.opensource.org/licenses/AGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./eCos-2.0.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/eCos-2.0.json",
+      "referenceNumber": "344",
+      "name": "eCos license version 2.0",
+      "licenseId": "eCos-2.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/ecos-license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.1.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.1.json",
+      "referenceNumber": "345",
+      "name": "GNU Free Documentation License v1.1",
+      "licenseId": "GFDL-1.1",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/fdl-1.1.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.2.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.2.json",
+      "referenceNumber": "346",
+      "name": "GNU Free Documentation License v1.2",
+      "licenseId": "GFDL-1.2",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/fdl-1.2.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.3.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.3.json",
+      "referenceNumber": "347",
+      "name": "GNU Free Documentation License v1.3",
+      "licenseId": "GFDL-1.3",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/fdl-1.3.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-1.0+.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-1.0+.json",
+      "referenceNumber": "348",
+      "name": "GNU General Public License v1.0 or later",
+      "licenseId": "GPL-1.0+",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-1.0.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-1.0.json",
+      "referenceNumber": "349",
+      "name": "GNU General Public License v1.0 only",
+      "licenseId": "GPL-1.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0+.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0+.json",
+      "referenceNumber": "350",
+      "name": "GNU General Public License v2.0 or later",
+      "licenseId": "GPL-2.0+",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-2.0-with-autoconf-exception.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-autoconf-exception.json",
+      "referenceNumber": "351",
+      "name": "GNU General Public License v2.0 w/Autoconf exception",
+      "licenseId": "GPL-2.0-with-autoconf-exception",
+      "seeAlso": [
+        "http://ac-archive.sourceforge.net/doc/copyright.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0-with-bison-exception.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-bison-exception.json",
+      "referenceNumber": "352",
+      "name": "GNU General Public License v2.0 w/Bison exception",
+      "licenseId": "GPL-2.0-with-bison-exception",
+      "seeAlso": [
+        "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0-with-classpath-exception.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-classpath-exception.json",
+      "referenceNumber": "353",
+      "name": "GNU General Public License v2.0 w/Classpath exception",
+      "licenseId": "GPL-2.0-with-classpath-exception",
+      "seeAlso": [
+        "http://www.gnu.org/software/classpath/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0-with-font-exception.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-font-exception.json",
+      "referenceNumber": "354",
+      "name": "GNU General Public License v2.0 w/Font exception",
+      "licenseId": "GPL-2.0-with-font-exception",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gpl-faq.html#FontException"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0-with-GCC-exception.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-GCC-exception.json",
+      "referenceNumber": "355",
+      "name": "GNU General Public License v2.0 w/GCC Runtime Library exception",
+      "licenseId": "GPL-2.0-with-GCC-exception",
+      "seeAlso": [
+        "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0.json",
+      "referenceNumber": "356",
+      "name": "GNU General Public License v2.0 only",
+      "licenseId": "GPL-2.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-3.0+.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-3.0+.json",
+      "referenceNumber": "357",
+      "name": "GNU General Public License v3.0 or later",
+      "licenseId": "GPL-3.0+",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-3.0-with-autoconf-exception.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-3.0-with-autoconf-exception.json",
+      "referenceNumber": "358",
+      "name": "GNU General Public License v3.0 w/Autoconf exception",
+      "licenseId": "GPL-3.0-with-autoconf-exception",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/autoconf-exception-3.0.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-3.0-with-GCC-exception.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-3.0-with-GCC-exception.json",
+      "referenceNumber": "359",
+      "name": "GNU General Public License v3.0 w/GCC Runtime Library exception",
+      "licenseId": "GPL-3.0-with-GCC-exception",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gcc-exception-3.1.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-3.0.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-3.0.json",
+      "referenceNumber": "360",
+      "name": "GNU General Public License v3.0 only",
+      "licenseId": "GPL-3.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.0+.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.0+.json",
+      "referenceNumber": "361",
+      "name": "GNU Library General Public License v2 or later",
+      "licenseId": "LGPL-2.0+",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.0.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.0.json",
+      "referenceNumber": "362",
+      "name": "GNU Library General Public License v2 only",
+      "licenseId": "LGPL-2.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.1+.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.1+.json",
+      "referenceNumber": "363",
+      "name": "GNU Library General Public License v2 or later",
+      "licenseId": "LGPL-2.1+",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-2.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.1.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.1.json",
+      "referenceNumber": "364",
+      "name": "GNU Lesser General Public License v2.1 only",
+      "licenseId": "LGPL-2.1",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-2.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-3.0+.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-3.0+.json",
+      "referenceNumber": "365",
+      "name": "GNU Lesser General Public License v3.0 or later",
+      "licenseId": "LGPL-3.0+",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/lgpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-3.0.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-3.0.json",
+      "referenceNumber": "366",
+      "name": "GNU Lesser General Public License v3.0 only",
+      "licenseId": "LGPL-3.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/lgpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Nunit.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/Nunit.json",
+      "referenceNumber": "367",
+      "name": "Nunit License",
+      "licenseId": "Nunit",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Nunit"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./StandardML-NJ.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/StandardML-NJ.json",
+      "referenceNumber": "368",
+      "name": "Standard ML of New Jersey License",
+      "licenseId": "StandardML-NJ",
+      "seeAlso": [
+        "http://www.smlnj.org//license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./wxWindows.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": false,
+      "detailsUrl": "http://spdx.org/licenses/wxWindows.json",
+      "referenceNumber": "369",
+      "name": "wxWindows Library License",
+      "licenseId": "wxWindows",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/WXwindows"
+      ],
+      "isOsiApproved": false
+    }
+  ],
+  "releaseDate": "28 December 2017"
+}
diff --git a/cabal/license-list-data/licenses-3.2.json b/cabal/license-list-data/licenses-3.2.json
new file mode 100644
--- /dev/null
+++ b/cabal/license-list-data/licenses-3.2.json
@@ -0,0 +1,4729 @@
+{
+  "licenseListVersion": "3.2",
+  "licenses": [
+    {
+      "reference": "./0BSD.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/0BSD.json",
+      "referenceNumber": "1",
+      "name": "BSD Zero Clause License",
+      "licenseId": "0BSD",
+      "seeAlso": [
+        "http://landley.net/toybox/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AAL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/AAL.json",
+      "referenceNumber": "2",
+      "name": "Attribution Assurance License",
+      "licenseId": "AAL",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/attribution"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Abstyles.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Abstyles.json",
+      "referenceNumber": "3",
+      "name": "Abstyles License",
+      "licenseId": "Abstyles",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Abstyles"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Adobe-2006.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Adobe-2006.json",
+      "referenceNumber": "4",
+      "name": "Adobe Systems Incorporated Source Code License Agreement",
+      "licenseId": "Adobe-2006",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/AdobeLicense"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Adobe-Glyph.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Adobe-Glyph.json",
+      "referenceNumber": "5",
+      "name": "Adobe Glyph List License",
+      "licenseId": "Adobe-Glyph",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MIT#AdobeGlyph"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ADSL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ADSL.json",
+      "referenceNumber": "6",
+      "name": "Amazon Digital Services License",
+      "licenseId": "ADSL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/AmazonDigitalServicesLicense"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AFL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AFL-1.1.json",
+      "referenceNumber": "7",
+      "name": "Academic Free License v1.1",
+      "licenseId": "AFL-1.1",
+      "seeAlso": [
+        "http://opensource.linux-mirror.org/licenses/afl-1.1.txt",
+        "http://wayback.archive.org/web/20021004124254/http://www.opensource.org/licenses/academic.php"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./AFL-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AFL-1.2.json",
+      "referenceNumber": "8",
+      "name": "Academic Free License v1.2",
+      "licenseId": "AFL-1.2",
+      "seeAlso": [
+        "http://opensource.linux-mirror.org/licenses/afl-1.2.txt",
+        "http://wayback.archive.org/web/20021204204652/http://www.opensource.org/licenses/academic.php"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./AFL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AFL-2.0.json",
+      "referenceNumber": "9",
+      "name": "Academic Free License v2.0",
+      "licenseId": "AFL-2.0",
+      "seeAlso": [
+        "http://wayback.archive.org/web/20060924134533/http://www.opensource.org/licenses/afl-2.0.txt"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./AFL-2.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AFL-2.1.json",
+      "referenceNumber": "10",
+      "name": "Academic Free License v2.1",
+      "licenseId": "AFL-2.1",
+      "seeAlso": [
+        "http://opensource.linux-mirror.org/licenses/afl-2.1.txt"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./AFL-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AFL-3.0.json",
+      "referenceNumber": "11",
+      "name": "Academic Free License v3.0",
+      "licenseId": "AFL-3.0",
+      "seeAlso": [
+        "http://www.rosenlaw.com/AFL3.0.htm",
+        "http://www.opensource.org/licenses/afl-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Afmparse.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Afmparse.json",
+      "referenceNumber": "12",
+      "name": "Afmparse License",
+      "licenseId": "Afmparse",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Afmparse"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AGPL-1.0-only.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/AGPL-1.0-only.json",
+      "referenceNumber": "13",
+      "name": "Affero General Public License v1.0 only",
+      "licenseId": "AGPL-1.0-only",
+      "seeAlso": [
+        "http://www.affero.org/oagpl.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AGPL-1.0-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/AGPL-1.0-or-later.json",
+      "referenceNumber": "14",
+      "name": "Affero General Public License v1.0 or later",
+      "licenseId": "AGPL-1.0-or-later",
+      "seeAlso": [
+        "http://www.affero.org/oagpl.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AGPL-3.0-only.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AGPL-3.0-only.json",
+      "referenceNumber": "15",
+      "name": "GNU Affero General Public License v3.0 only",
+      "licenseId": "AGPL-3.0-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/agpl.txt",
+        "http://www.opensource.org/licenses/AGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./AGPL-3.0-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AGPL-3.0-or-later.json",
+      "referenceNumber": "16",
+      "name": "GNU Affero General Public License v3.0 or later",
+      "licenseId": "AGPL-3.0-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/agpl.txt",
+        "http://www.opensource.org/licenses/AGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Aladdin.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Aladdin.json",
+      "referenceNumber": "17",
+      "name": "Aladdin Free Public License",
+      "licenseId": "Aladdin",
+      "seeAlso": [
+        "http://pages.cs.wisc.edu/~ghost/doc/AFPL/6.01/Public.htm"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AMDPLPA.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/AMDPLPA.json",
+      "referenceNumber": "18",
+      "name": "AMD\u0027s plpa_map.c License",
+      "licenseId": "AMDPLPA",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/AMD_plpa_map_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AML.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/AML.json",
+      "referenceNumber": "19",
+      "name": "Apple MIT License",
+      "licenseId": "AML",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Apple_MIT_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AMPAS.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/AMPAS.json",
+      "referenceNumber": "20",
+      "name": "Academy of Motion Picture Arts and Sciences BSD",
+      "licenseId": "AMPAS",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/BSD#AMPASBSD"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ANTLR-PD.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ANTLR-PD.json",
+      "referenceNumber": "21",
+      "name": "ANTLR Software Rights Notice",
+      "licenseId": "ANTLR-PD",
+      "seeAlso": [
+        "http://www.antlr2.org/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Apache-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Apache-1.0.json",
+      "referenceNumber": "22",
+      "name": "Apache License 1.0",
+      "licenseId": "Apache-1.0",
+      "seeAlso": [
+        "http://www.apache.org/licenses/LICENSE-1.0"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Apache-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Apache-1.1.json",
+      "referenceNumber": "23",
+      "name": "Apache License 1.1",
+      "licenseId": "Apache-1.1",
+      "seeAlso": [
+        "http://apache.org/licenses/LICENSE-1.1",
+        "http://opensource.org/licenses/Apache-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Apache-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Apache-2.0.json",
+      "referenceNumber": "24",
+      "name": "Apache License 2.0",
+      "licenseId": "Apache-2.0",
+      "seeAlso": [
+        "http://www.apache.org/licenses/LICENSE-2.0",
+        "http://www.opensource.org/licenses/Apache-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./APAFML.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/APAFML.json",
+      "referenceNumber": "25",
+      "name": "Adobe Postscript AFM License",
+      "licenseId": "APAFML",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/AdobePostscriptAFM"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./APL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/APL-1.0.json",
+      "referenceNumber": "26",
+      "name": "Adaptive Public License 1.0",
+      "licenseId": "APL-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/APL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./APSL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/APSL-1.0.json",
+      "referenceNumber": "27",
+      "name": "Apple Public Source License 1.0",
+      "licenseId": "APSL-1.0",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Apple_Public_Source_License_1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./APSL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/APSL-1.1.json",
+      "referenceNumber": "28",
+      "name": "Apple Public Source License 1.1",
+      "licenseId": "APSL-1.1",
+      "seeAlso": [
+        "http://www.opensource.apple.com/source/IOSerialFamily/IOSerialFamily-7/APPLE_LICENSE"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./APSL-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/APSL-1.2.json",
+      "referenceNumber": "29",
+      "name": "Apple Public Source License 1.2",
+      "licenseId": "APSL-1.2",
+      "seeAlso": [
+        "http://www.samurajdata.se/opensource/mirror/licenses/apsl.php"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./APSL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/APSL-2.0.json",
+      "referenceNumber": "30",
+      "name": "Apple Public Source License 2.0",
+      "licenseId": "APSL-2.0",
+      "seeAlso": [
+        "http://www.opensource.apple.com/license/apsl/"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Artistic-1.0-cl8.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Artistic-1.0-cl8.json",
+      "referenceNumber": "31",
+      "name": "Artistic License 1.0 w/clause 8",
+      "licenseId": "Artistic-1.0-cl8",
+      "seeAlso": [
+        "http://opensource.org/licenses/Artistic-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Artistic-1.0-Perl.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Artistic-1.0-Perl.json",
+      "referenceNumber": "32",
+      "name": "Artistic License 1.0 (Perl)",
+      "licenseId": "Artistic-1.0-Perl",
+      "seeAlso": [
+        "http://dev.perl.org/licenses/artistic.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Artistic-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Artistic-1.0.json",
+      "referenceNumber": "33",
+      "name": "Artistic License 1.0",
+      "licenseId": "Artistic-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/Artistic-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Artistic-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Artistic-2.0.json",
+      "referenceNumber": "34",
+      "name": "Artistic License 2.0",
+      "licenseId": "Artistic-2.0",
+      "seeAlso": [
+        "http://www.perlfoundation.org/artistic_license_2_0",
+        "http://www.opensource.org/licenses/artistic-license-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Bahyph.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Bahyph.json",
+      "referenceNumber": "35",
+      "name": "Bahyph License",
+      "licenseId": "Bahyph",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Bahyph"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Barr.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Barr.json",
+      "referenceNumber": "36",
+      "name": "Barr License",
+      "licenseId": "Barr",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Barr"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Beerware.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Beerware.json",
+      "referenceNumber": "37",
+      "name": "Beerware License",
+      "licenseId": "Beerware",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Beerware",
+        "https://people.freebsd.org/~phk/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BitTorrent-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BitTorrent-1.0.json",
+      "referenceNumber": "38",
+      "name": "BitTorrent Open Source License v1.0",
+      "licenseId": "BitTorrent-1.0",
+      "seeAlso": [
+        "http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/licenses/BitTorrent?r1\u003d1.1\u0026r2\u003d1.1.1.1\u0026diff_format\u003ds"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BitTorrent-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/BitTorrent-1.1.json",
+      "referenceNumber": "39",
+      "name": "BitTorrent Open Source License v1.1",
+      "licenseId": "BitTorrent-1.1",
+      "seeAlso": [
+        "http://directory.fsf.org/wiki/License:BitTorrentOSL1.1"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Borceux.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Borceux.json",
+      "referenceNumber": "40",
+      "name": "Borceux license",
+      "licenseId": "Borceux",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Borceux"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-1-Clause.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-1-Clause.json",
+      "referenceNumber": "41",
+      "name": "BSD 1-Clause License",
+      "licenseId": "BSD-1-Clause",
+      "seeAlso": [
+        "https://svnweb.freebsd.org/base/head/include/ifaddrs.h?revision\u003d326823"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-2-Clause-FreeBSD.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-FreeBSD.json",
+      "referenceNumber": "42",
+      "name": "BSD 2-Clause FreeBSD License",
+      "licenseId": "BSD-2-Clause-FreeBSD",
+      "seeAlso": [
+        "http://www.freebsd.org/copyright/freebsd-license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-2-Clause-NetBSD.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-NetBSD.json",
+      "referenceNumber": "43",
+      "name": "BSD 2-Clause NetBSD License",
+      "licenseId": "BSD-2-Clause-NetBSD",
+      "seeAlso": [
+        "http://www.netbsd.org/about/redistribution.html#default"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-2-Clause-Patent.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-Patent.json",
+      "referenceNumber": "44",
+      "name": "BSD-2-Clause Plus Patent License",
+      "licenseId": "BSD-2-Clause-Patent",
+      "seeAlso": [
+        "https://opensource.org/licenses/BSDplusPatent"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./BSD-2-Clause.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause.json",
+      "referenceNumber": "45",
+      "name": "BSD 2-Clause \"Simplified\" License",
+      "licenseId": "BSD-2-Clause",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/BSD-2-Clause"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./BSD-3-Clause-Attribution.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-Attribution.json",
+      "referenceNumber": "46",
+      "name": "BSD with attribution",
+      "licenseId": "BSD-3-Clause-Attribution",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/BSD_with_Attribution"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-3-Clause-Clear.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-Clear.json",
+      "referenceNumber": "47",
+      "name": "BSD 3-Clause Clear License",
+      "licenseId": "BSD-3-Clause-Clear",
+      "seeAlso": [
+        "http://labs.metacarta.com/license-explanation.html#license"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-3-Clause-LBNL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-LBNL.json",
+      "referenceNumber": "48",
+      "name": "Lawrence Berkeley National Labs BSD variant license",
+      "licenseId": "BSD-3-Clause-LBNL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/LBNLBSD"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-3-Clause-No-Nuclear-License-2014.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.json",
+      "referenceNumber": "49",
+      "name": "BSD 3-Clause No Nuclear License 2014",
+      "licenseId": "BSD-3-Clause-No-Nuclear-License-2014",
+      "seeAlso": [
+        "https://java.net/projects/javaeetutorial/pages/BerkeleyLicense"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-3-Clause-No-Nuclear-License.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.json",
+      "referenceNumber": "50",
+      "name": "BSD 3-Clause No Nuclear License",
+      "licenseId": "BSD-3-Clause-No-Nuclear-License",
+      "seeAlso": [
+        "http://download.oracle.com/otn-pub/java/licenses/bsd.txt?AuthParam\u003d1467140197_43d516ce1776bd08a58235a7785be1cc"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-3-Clause-No-Nuclear-Warranty.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.json",
+      "referenceNumber": "51",
+      "name": "BSD 3-Clause No Nuclear Warranty",
+      "licenseId": "BSD-3-Clause-No-Nuclear-Warranty",
+      "seeAlso": [
+        "https://jogamp.org/git/?p\u003dgluegen.git;a\u003dblob_plain;f\u003dLICENSE.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-3-Clause.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause.json",
+      "referenceNumber": "52",
+      "name": "BSD 3-Clause \"New\" or \"Revised\" License",
+      "licenseId": "BSD-3-Clause",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/BSD-3-Clause"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./BSD-4-Clause-UC.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-4-Clause-UC.json",
+      "referenceNumber": "53",
+      "name": "BSD-4-Clause (University of California-Specific)",
+      "licenseId": "BSD-4-Clause-UC",
+      "seeAlso": [
+        "http://www.freebsd.org/copyright/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-4-Clause.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/BSD-4-Clause.json",
+      "referenceNumber": "54",
+      "name": "BSD 4-Clause \"Original\" or \"Old\" License",
+      "licenseId": "BSD-4-Clause",
+      "seeAlso": [
+        "http://directory.fsf.org/wiki/License:BSD_4Clause"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-Protection.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-Protection.json",
+      "referenceNumber": "55",
+      "name": "BSD Protection License",
+      "licenseId": "BSD-Protection",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/BSD_Protection_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSD-Source-Code.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/BSD-Source-Code.json",
+      "referenceNumber": "56",
+      "name": "BSD Source Code Attribution",
+      "licenseId": "BSD-Source-Code",
+      "seeAlso": [
+        "https://github.com/robbiehanson/CocoaHTTPServer/blob/master/LICENSE.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./BSL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/BSL-1.0.json",
+      "referenceNumber": "57",
+      "name": "Boost Software License 1.0",
+      "licenseId": "BSL-1.0",
+      "seeAlso": [
+        "http://www.boost.org/LICENSE_1_0.txt",
+        "http://www.opensource.org/licenses/BSL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./bzip2-1.0.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/bzip2-1.0.5.json",
+      "referenceNumber": "58",
+      "name": "bzip2 and libbzip2 License v1.0.5",
+      "licenseId": "bzip2-1.0.5",
+      "seeAlso": [
+        "http://bzip.org/1.0.5/bzip2-manual-1.0.5.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./bzip2-1.0.6.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/bzip2-1.0.6.json",
+      "referenceNumber": "59",
+      "name": "bzip2 and libbzip2 License v1.0.6",
+      "licenseId": "bzip2-1.0.6",
+      "seeAlso": [
+        "https://github.com/asimonov-im/bzip2/blob/master/LICENSE"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Caldera.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Caldera.json",
+      "referenceNumber": "60",
+      "name": "Caldera License",
+      "licenseId": "Caldera",
+      "seeAlso": [
+        "http://www.lemis.com/grog/UNIX/ancient-source-all.pdf"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CATOSL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CATOSL-1.1.json",
+      "referenceNumber": "61",
+      "name": "Computer Associates Trusted Open Source License 1.1",
+      "licenseId": "CATOSL-1.1",
+      "seeAlso": [
+        "http://opensource.org/licenses/CATOSL-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./CC-BY-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-1.0.json",
+      "referenceNumber": "62",
+      "name": "Creative Commons Attribution 1.0 Generic",
+      "licenseId": "CC-BY-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-2.0.json",
+      "referenceNumber": "63",
+      "name": "Creative Commons Attribution 2.0 Generic",
+      "licenseId": "CC-BY-2.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by/2.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-2.5.json",
+      "referenceNumber": "64",
+      "name": "Creative Commons Attribution 2.5 Generic",
+      "licenseId": "CC-BY-2.5",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by/2.5/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-3.0.json",
+      "referenceNumber": "65",
+      "name": "Creative Commons Attribution 3.0 Unported",
+      "licenseId": "CC-BY-3.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by/3.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-4.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-4.0.json",
+      "referenceNumber": "66",
+      "name": "Creative Commons Attribution 4.0 International",
+      "licenseId": "CC-BY-4.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by/4.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-1.0.json",
+      "referenceNumber": "67",
+      "name": "Creative Commons Attribution Non Commercial 1.0 Generic",
+      "licenseId": "CC-BY-NC-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-2.0.json",
+      "referenceNumber": "68",
+      "name": "Creative Commons Attribution Non Commercial 2.0 Generic",
+      "licenseId": "CC-BY-NC-2.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc/2.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-2.5.json",
+      "referenceNumber": "69",
+      "name": "Creative Commons Attribution Non Commercial 2.5 Generic",
+      "licenseId": "CC-BY-NC-2.5",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc/2.5/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-3.0.json",
+      "referenceNumber": "70",
+      "name": "Creative Commons Attribution Non Commercial 3.0 Unported",
+      "licenseId": "CC-BY-NC-3.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc/3.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-4.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-4.0.json",
+      "referenceNumber": "71",
+      "name": "Creative Commons Attribution Non Commercial 4.0 International",
+      "licenseId": "CC-BY-NC-4.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc/4.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-ND-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-1.0.json",
+      "referenceNumber": "72",
+      "name": "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic",
+      "licenseId": "CC-BY-NC-ND-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nd-nc/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-ND-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-2.0.json",
+      "referenceNumber": "73",
+      "name": "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic",
+      "licenseId": "CC-BY-NC-ND-2.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-nd/2.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-ND-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-2.5.json",
+      "referenceNumber": "74",
+      "name": "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic",
+      "licenseId": "CC-BY-NC-ND-2.5",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-nd/2.5/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-ND-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-3.0.json",
+      "referenceNumber": "75",
+      "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported",
+      "licenseId": "CC-BY-NC-ND-3.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-nd/3.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-ND-4.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-4.0.json",
+      "referenceNumber": "76",
+      "name": "Creative Commons Attribution Non Commercial No Derivatives 4.0 International",
+      "licenseId": "CC-BY-NC-ND-4.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-nd/4.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-SA-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-1.0.json",
+      "referenceNumber": "77",
+      "name": "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic",
+      "licenseId": "CC-BY-NC-SA-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-sa/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-SA-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-2.0.json",
+      "referenceNumber": "78",
+      "name": "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic",
+      "licenseId": "CC-BY-NC-SA-2.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-sa/2.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-SA-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-2.5.json",
+      "referenceNumber": "79",
+      "name": "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic",
+      "licenseId": "CC-BY-NC-SA-2.5",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-sa/2.5/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-SA-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-3.0.json",
+      "referenceNumber": "80",
+      "name": "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported",
+      "licenseId": "CC-BY-NC-SA-3.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-NC-SA-4.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-4.0.json",
+      "referenceNumber": "81",
+      "name": "Creative Commons Attribution Non Commercial Share Alike 4.0 International",
+      "licenseId": "CC-BY-NC-SA-4.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nc-sa/4.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-ND-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-1.0.json",
+      "referenceNumber": "82",
+      "name": "Creative Commons Attribution No Derivatives 1.0 Generic",
+      "licenseId": "CC-BY-ND-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nd/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-ND-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-2.0.json",
+      "referenceNumber": "83",
+      "name": "Creative Commons Attribution No Derivatives 2.0 Generic",
+      "licenseId": "CC-BY-ND-2.0",
+      "seeAlso": [
+        "https://creativecommons.org/licenses/by-nd/2.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-ND-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-2.5.json",
+      "referenceNumber": "84",
+      "name": "Creative Commons Attribution No Derivatives 2.5 Generic",
+      "licenseId": "CC-BY-ND-2.5",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nd/2.5/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-ND-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-3.0.json",
+      "referenceNumber": "85",
+      "name": "Creative Commons Attribution No Derivatives 3.0 Unported",
+      "licenseId": "CC-BY-ND-3.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nd/3.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-ND-4.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-4.0.json",
+      "referenceNumber": "86",
+      "name": "Creative Commons Attribution No Derivatives 4.0 International",
+      "licenseId": "CC-BY-ND-4.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-nd/4.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-SA-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-1.0.json",
+      "referenceNumber": "87",
+      "name": "Creative Commons Attribution Share Alike 1.0 Generic",
+      "licenseId": "CC-BY-SA-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-sa/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-SA-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-2.0.json",
+      "referenceNumber": "88",
+      "name": "Creative Commons Attribution Share Alike 2.0 Generic",
+      "licenseId": "CC-BY-SA-2.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-sa/2.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-SA-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-2.5.json",
+      "referenceNumber": "89",
+      "name": "Creative Commons Attribution Share Alike 2.5 Generic",
+      "licenseId": "CC-BY-SA-2.5",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-sa/2.5/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-SA-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-3.0.json",
+      "referenceNumber": "90",
+      "name": "Creative Commons Attribution Share Alike 3.0 Unported",
+      "licenseId": "CC-BY-SA-3.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-sa/3.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC-BY-SA-4.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-4.0.json",
+      "referenceNumber": "91",
+      "name": "Creative Commons Attribution Share Alike 4.0 International",
+      "licenseId": "CC-BY-SA-4.0",
+      "seeAlso": [
+        "http://creativecommons.org/licenses/by-sa/4.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CC0-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CC0-1.0.json",
+      "referenceNumber": "92",
+      "name": "Creative Commons Zero v1.0 Universal",
+      "licenseId": "CC0-1.0",
+      "seeAlso": [
+        "http://creativecommons.org/publicdomain/zero/1.0/legalcode"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CDDL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CDDL-1.0.json",
+      "referenceNumber": "93",
+      "name": "Common Development and Distribution License 1.0",
+      "licenseId": "CDDL-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/cddl1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./CDDL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CDDL-1.1.json",
+      "referenceNumber": "94",
+      "name": "Common Development and Distribution License 1.1",
+      "licenseId": "CDDL-1.1",
+      "seeAlso": [
+        "http://glassfish.java.net/public/CDDL+GPL_1_1.html",
+        "https://javaee.github.io/glassfish/LICENSE"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CDLA-Permissive-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CDLA-Permissive-1.0.json",
+      "referenceNumber": "95",
+      "name": "Community Data License Agreement Permissive 1.0",
+      "licenseId": "CDLA-Permissive-1.0",
+      "seeAlso": [
+        "https://cdla.io/permissive-1-0"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CDLA-Sharing-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CDLA-Sharing-1.0.json",
+      "referenceNumber": "96",
+      "name": "Community Data License Agreement Sharing 1.0",
+      "licenseId": "CDLA-Sharing-1.0",
+      "seeAlso": [
+        "https://cdla.io/sharing-1-0"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CECILL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CECILL-1.0.json",
+      "referenceNumber": "97",
+      "name": "CeCILL Free Software License Agreement v1.0",
+      "licenseId": "CECILL-1.0",
+      "seeAlso": [
+        "http://www.cecill.info/licences/Licence_CeCILL_V1-fr.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CECILL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CECILL-1.1.json",
+      "referenceNumber": "98",
+      "name": "CeCILL Free Software License Agreement v1.1",
+      "licenseId": "CECILL-1.1",
+      "seeAlso": [
+        "http://www.cecill.info/licences/Licence_CeCILL_V1.1-US.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CECILL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CECILL-2.0.json",
+      "referenceNumber": "99",
+      "name": "CeCILL Free Software License Agreement v2.0",
+      "licenseId": "CECILL-2.0",
+      "seeAlso": [
+        "http://www.cecill.info/licences/Licence_CeCILL_V2-en.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CECILL-2.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CECILL-2.1.json",
+      "referenceNumber": "100",
+      "name": "CeCILL Free Software License Agreement v2.1",
+      "licenseId": "CECILL-2.1",
+      "seeAlso": [
+        "http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./CECILL-B.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CECILL-B.json",
+      "referenceNumber": "101",
+      "name": "CeCILL-B Free Software License Agreement",
+      "licenseId": "CECILL-B",
+      "seeAlso": [
+        "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CECILL-C.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CECILL-C.json",
+      "referenceNumber": "102",
+      "name": "CeCILL-C Free Software License Agreement",
+      "licenseId": "CECILL-C",
+      "seeAlso": [
+        "http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html\n    "
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ClArtistic.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/ClArtistic.json",
+      "referenceNumber": "103",
+      "name": "Clarified Artistic License",
+      "licenseId": "ClArtistic",
+      "seeAlso": [
+        "http://gianluca.dellavedova.org/2011/01/03/clarified-artistic-license/",
+        "http://www.ncftp.com/ncftp/doc/LICENSE.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CNRI-Jython.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CNRI-Jython.json",
+      "referenceNumber": "104",
+      "name": "CNRI Jython License",
+      "licenseId": "CNRI-Jython",
+      "seeAlso": [
+        "http://www.jython.org/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CNRI-Python-GPL-Compatible.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CNRI-Python-GPL-Compatible.json",
+      "referenceNumber": "105",
+      "name": "CNRI Python Open Source GPL Compatible License Agreement",
+      "licenseId": "CNRI-Python-GPL-Compatible",
+      "seeAlso": [
+        "http://www.python.org/download/releases/1.6.1/download_win/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CNRI-Python.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CNRI-Python.json",
+      "referenceNumber": "106",
+      "name": "CNRI Python License",
+      "licenseId": "CNRI-Python",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/CNRI-Python"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Condor-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Condor-1.1.json",
+      "referenceNumber": "107",
+      "name": "Condor Public License v1.1",
+      "licenseId": "Condor-1.1",
+      "seeAlso": [
+        "http://research.cs.wisc.edu/condor/license.html#condor",
+        "http://web.archive.org/web/20111123062036/http://research.cs.wisc.edu/condor/license.html#condor"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CPAL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CPAL-1.0.json",
+      "referenceNumber": "108",
+      "name": "Common Public Attribution License 1.0",
+      "licenseId": "CPAL-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/CPAL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./CPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/CPL-1.0.json",
+      "referenceNumber": "109",
+      "name": "Common Public License 1.0",
+      "licenseId": "CPL-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/CPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./CPOL-1.02.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CPOL-1.02.json",
+      "referenceNumber": "110",
+      "name": "Code Project Open License 1.02",
+      "licenseId": "CPOL-1.02",
+      "seeAlso": [
+        "http://www.codeproject.com/info/cpol10.aspx"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Crossword.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Crossword.json",
+      "referenceNumber": "111",
+      "name": "Crossword License",
+      "licenseId": "Crossword",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Crossword"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CrystalStacker.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CrystalStacker.json",
+      "referenceNumber": "112",
+      "name": "CrystalStacker License",
+      "licenseId": "CrystalStacker",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing:CrystalStacker?rd\u003dLicensing/CrystalStacker"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./CUA-OPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/CUA-OPL-1.0.json",
+      "referenceNumber": "113",
+      "name": "CUA Office Public License v1.0",
+      "licenseId": "CUA-OPL-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/CUA-OPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Cube.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Cube.json",
+      "referenceNumber": "114",
+      "name": "Cube License",
+      "licenseId": "Cube",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Cube"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./curl.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/curl.json",
+      "referenceNumber": "115",
+      "name": "curl License",
+      "licenseId": "curl",
+      "seeAlso": [
+        "https://github.com/bagder/curl/blob/master/COPYING"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./D-FSL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/D-FSL-1.0.json",
+      "referenceNumber": "116",
+      "name": "Deutsche Freie Software Lizenz",
+      "licenseId": "D-FSL-1.0",
+      "seeAlso": [
+        "http://www.dipp.nrw.de/d-fsl/lizenzen/",
+        "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/de/D-FSL-1_0_de.txt",
+        "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/en/D-FSL-1_0_en.txt",
+        "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl",
+        "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/deutsche-freie-software-lizenz",
+        "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/german-free-software-license",
+        "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_de.txt/at_download/file",
+        "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_en.txt/at_download/file"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./diffmark.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/diffmark.json",
+      "referenceNumber": "117",
+      "name": "diffmark license",
+      "licenseId": "diffmark",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/diffmark"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./DOC.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/DOC.json",
+      "referenceNumber": "118",
+      "name": "DOC License",
+      "licenseId": "DOC",
+      "seeAlso": [
+        "http://www.cs.wustl.edu/~schmidt/ACE-copying.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Dotseqn.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Dotseqn.json",
+      "referenceNumber": "119",
+      "name": "Dotseqn License",
+      "licenseId": "Dotseqn",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Dotseqn"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./DSDP.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/DSDP.json",
+      "referenceNumber": "120",
+      "name": "DSDP License",
+      "licenseId": "DSDP",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/DSDP"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./dvipdfm.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/dvipdfm.json",
+      "referenceNumber": "121",
+      "name": "dvipdfm License",
+      "licenseId": "dvipdfm",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/dvipdfm"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ECL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ECL-1.0.json",
+      "referenceNumber": "122",
+      "name": "Educational Community License v1.0",
+      "licenseId": "ECL-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/ECL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./ECL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/ECL-2.0.json",
+      "referenceNumber": "123",
+      "name": "Educational Community License v2.0",
+      "licenseId": "ECL-2.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/ECL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./EFL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/EFL-1.0.json",
+      "referenceNumber": "124",
+      "name": "Eiffel Forum License v1.0",
+      "licenseId": "EFL-1.0",
+      "seeAlso": [
+        "http://www.eiffel-nice.org/license/forum.txt",
+        "http://opensource.org/licenses/EFL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./EFL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/EFL-2.0.json",
+      "referenceNumber": "125",
+      "name": "Eiffel Forum License v2.0",
+      "licenseId": "EFL-2.0",
+      "seeAlso": [
+        "http://www.eiffel-nice.org/license/eiffel-forum-license-2.html",
+        "http://opensource.org/licenses/EFL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./eGenix.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/eGenix.json",
+      "referenceNumber": "126",
+      "name": "eGenix.com Public License 1.1.0",
+      "licenseId": "eGenix",
+      "seeAlso": [
+        "http://www.egenix.com/products/eGenix.com-Public-License-1.1.0.pdf",
+        "https://fedoraproject.org/wiki/Licensing/eGenix.com_Public_License_1.1.0"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Entessa.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Entessa.json",
+      "referenceNumber": "127",
+      "name": "Entessa Public License v1.0",
+      "licenseId": "Entessa",
+      "seeAlso": [
+        "http://opensource.org/licenses/Entessa"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./EPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/EPL-1.0.json",
+      "referenceNumber": "128",
+      "name": "Eclipse Public License 1.0",
+      "licenseId": "EPL-1.0",
+      "seeAlso": [
+        "http://www.eclipse.org/legal/epl-v10.html",
+        "http://www.opensource.org/licenses/EPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./EPL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/EPL-2.0.json",
+      "referenceNumber": "129",
+      "name": "Eclipse Public License 2.0",
+      "licenseId": "EPL-2.0",
+      "seeAlso": [
+        "https://www.eclipse.org/legal/epl-2.0",
+        "https://www.opensource.org/licenses/EPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./ErlPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ErlPL-1.1.json",
+      "referenceNumber": "130",
+      "name": "Erlang Public License v1.1",
+      "licenseId": "ErlPL-1.1",
+      "seeAlso": [
+        "http://www.erlang.org/EPLICENSE"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./EUDatagrid.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/EUDatagrid.json",
+      "referenceNumber": "131",
+      "name": "EU DataGrid Software License",
+      "licenseId": "EUDatagrid",
+      "seeAlso": [
+        "http://eu-datagrid.web.cern.ch/eu-datagrid/license.html",
+        "http://www.opensource.org/licenses/EUDatagrid"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./EUPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/EUPL-1.0.json",
+      "referenceNumber": "132",
+      "name": "European Union Public License 1.0",
+      "licenseId": "EUPL-1.0",
+      "seeAlso": [
+        "http://ec.europa.eu/idabc/en/document/7330.html",
+        "http://ec.europa.eu/idabc/servlets/Doc027f.pdf?id\u003d31096"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./EUPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/EUPL-1.1.json",
+      "referenceNumber": "133",
+      "name": "European Union Public License 1.1",
+      "licenseId": "EUPL-1.1",
+      "seeAlso": [
+        "https://joinup.ec.europa.eu/software/page/eupl/licence-eupl",
+        "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl1.1.-licence-en_0.pdf",
+        "http://www.opensource.org/licenses/EUPL-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./EUPL-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/EUPL-1.2.json",
+      "referenceNumber": "134",
+      "name": "European Union Public License 1.2",
+      "licenseId": "EUPL-1.2",
+      "seeAlso": [
+        "https://joinup.ec.europa.eu/page/eupl-text-11-12",
+        "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl_v1.2_en.pdf",
+        "https://joinup.ec.europa.eu/sites/default/files/inline-files/EUPL%20v1_2%20EN(1).txt",
+        "http://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri\u003dCELEX:32017D0863",
+        "http://www.opensource.org/licenses/EUPL-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Eurosym.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Eurosym.json",
+      "referenceNumber": "135",
+      "name": "Eurosym License",
+      "licenseId": "Eurosym",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Eurosym"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Fair.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Fair.json",
+      "referenceNumber": "136",
+      "name": "Fair License",
+      "licenseId": "Fair",
+      "seeAlso": [
+        "http://fairlicense.org/",
+        "http://www.opensource.org/licenses/Fair"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Frameworx-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Frameworx-1.0.json",
+      "referenceNumber": "137",
+      "name": "Frameworx Open License 1.0",
+      "licenseId": "Frameworx-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Frameworx-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./FreeImage.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/FreeImage.json",
+      "referenceNumber": "138",
+      "name": "FreeImage Public License v1.0",
+      "licenseId": "FreeImage",
+      "seeAlso": [
+        "http://freeimage.sourceforge.net/freeimage-license.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./FSFAP.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/FSFAP.json",
+      "referenceNumber": "139",
+      "name": "FSF All Permissive License",
+      "licenseId": "FSFAP",
+      "seeAlso": [
+        "http://www.gnu.org/prep/maintain/html_node/License-Notices-for-Other-Files.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./FSFUL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/FSFUL.json",
+      "referenceNumber": "140",
+      "name": "FSF Unlimited License",
+      "licenseId": "FSFUL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./FSFULLR.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/FSFULLR.json",
+      "referenceNumber": "141",
+      "name": "FSF Unlimited License (with License Retention)",
+      "licenseId": "FSFULLR",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License#License_Retention_Variant"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./FTL.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/FTL.json",
+      "referenceNumber": "142",
+      "name": "Freetype Project License",
+      "licenseId": "FTL",
+      "seeAlso": [
+        "http://freetype.fis.uniroma2.it/FTL.TXT",
+        "http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.1-only.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.1-only.json",
+      "referenceNumber": "143",
+      "name": "GNU Free Documentation License v1.1 only",
+      "licenseId": "GFDL-1.1-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/fdl-1.1.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.1-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.1-or-later.json",
+      "referenceNumber": "144",
+      "name": "GNU Free Documentation License v1.1 or later",
+      "licenseId": "GFDL-1.1-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/fdl-1.1.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.2-only.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.2-only.json",
+      "referenceNumber": "145",
+      "name": "GNU Free Documentation License v1.2 only",
+      "licenseId": "GFDL-1.2-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/fdl-1.2.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.2-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.2-or-later.json",
+      "referenceNumber": "146",
+      "name": "GNU Free Documentation License v1.2 or later",
+      "licenseId": "GFDL-1.2-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/fdl-1.2.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.3-only.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.3-only.json",
+      "referenceNumber": "147",
+      "name": "GNU Free Documentation License v1.3 only",
+      "licenseId": "GFDL-1.3-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/fdl-1.3.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.3-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.3-or-later.json",
+      "referenceNumber": "148",
+      "name": "GNU Free Documentation License v1.3 or later",
+      "licenseId": "GFDL-1.3-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/fdl-1.3.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Giftware.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Giftware.json",
+      "referenceNumber": "149",
+      "name": "Giftware License",
+      "licenseId": "Giftware",
+      "seeAlso": [
+        "http://liballeg.org/license.html#allegro-4-the-giftware-license"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GL2PS.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GL2PS.json",
+      "referenceNumber": "150",
+      "name": "GL2PS License",
+      "licenseId": "GL2PS",
+      "seeAlso": [
+        "http://www.geuz.org/gl2ps/COPYING.GL2PS"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Glide.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Glide.json",
+      "referenceNumber": "151",
+      "name": "3dfx Glide License",
+      "licenseId": "Glide",
+      "seeAlso": [
+        "http://www.users.on.net/~triforce/glidexp/COPYING.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Glulxe.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Glulxe.json",
+      "referenceNumber": "152",
+      "name": "Glulxe License",
+      "licenseId": "Glulxe",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Glulxe"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./gnuplot.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/gnuplot.json",
+      "referenceNumber": "153",
+      "name": "gnuplot License",
+      "licenseId": "gnuplot",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Gnuplot"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-1.0-only.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-1.0-only.json",
+      "referenceNumber": "154",
+      "name": "GNU General Public License v1.0 only",
+      "licenseId": "GPL-1.0-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-1.0-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/GPL-1.0-or-later.json",
+      "referenceNumber": "155",
+      "name": "GNU General Public License v1.0 or later",
+      "licenseId": "GPL-1.0-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0-only.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-only.json",
+      "referenceNumber": "156",
+      "name": "GNU General Public License v2.0 only",
+      "licenseId": "GPL-2.0-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-2.0-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-or-later.json",
+      "referenceNumber": "157",
+      "name": "GNU General Public License v2.0 or later",
+      "licenseId": "GPL-2.0-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-3.0-only.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-3.0-only.json",
+      "referenceNumber": "158",
+      "name": "GNU General Public License v3.0 only",
+      "licenseId": "GPL-3.0-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-3.0-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-3.0-or-later.json",
+      "referenceNumber": "159",
+      "name": "GNU General Public License v3.0 or later",
+      "licenseId": "GPL-3.0-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./gSOAP-1.3b.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/gSOAP-1.3b.json",
+      "referenceNumber": "160",
+      "name": "gSOAP Public License v1.3b",
+      "licenseId": "gSOAP-1.3b",
+      "seeAlso": [
+        "http://www.cs.fsu.edu/~engelen/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./HaskellReport.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/HaskellReport.json",
+      "referenceNumber": "161",
+      "name": "Haskell Language Report License",
+      "licenseId": "HaskellReport",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Haskell_Language_Report_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./HPND.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/HPND.json",
+      "referenceNumber": "162",
+      "name": "Historical Permission Notice and Disclaimer",
+      "licenseId": "HPND",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/HPND"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./IBM-pibs.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/IBM-pibs.json",
+      "referenceNumber": "163",
+      "name": "IBM PowerPC Initialization and Boot Software",
+      "licenseId": "IBM-pibs",
+      "seeAlso": [
+        "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003darch/powerpc/cpu/ppc4xx/miiphy.c;h\u003d297155fdafa064b955e53e9832de93bfb0cfb85b;hb\u003d9fab4bf4cc077c21e43941866f3f2c196f28670d"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ICU.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ICU.json",
+      "referenceNumber": "164",
+      "name": "ICU License",
+      "licenseId": "ICU",
+      "seeAlso": [
+        "http://source.icu-project.org/repos/icu/icu/trunk/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./IJG.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/IJG.json",
+      "referenceNumber": "165",
+      "name": "Independent JPEG Group License",
+      "licenseId": "IJG",
+      "seeAlso": [
+        "http://dev.w3.org/cvsweb/Amaya/libjpeg/Attic/README?rev\u003d1.2"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ImageMagick.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ImageMagick.json",
+      "referenceNumber": "166",
+      "name": "ImageMagick License",
+      "licenseId": "ImageMagick",
+      "seeAlso": [
+        "http://www.imagemagick.org/script/license.php"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./iMatix.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/iMatix.json",
+      "referenceNumber": "167",
+      "name": "iMatix Standard Function Library Agreement",
+      "licenseId": "iMatix",
+      "seeAlso": [
+        "http://legacy.imatix.com/html/sfl/sfl4.htm#license"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Imlib2.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Imlib2.json",
+      "referenceNumber": "168",
+      "name": "Imlib2 License",
+      "licenseId": "Imlib2",
+      "seeAlso": [
+        "http://trac.enlightenment.org/e/browser/trunk/imlib2/COPYING",
+        "https://git.enlightenment.org/legacy/imlib2.git/tree/COPYING"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Info-ZIP.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Info-ZIP.json",
+      "referenceNumber": "169",
+      "name": "Info-ZIP License",
+      "licenseId": "Info-ZIP",
+      "seeAlso": [
+        "http://www.info-zip.org/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Intel-ACPI.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Intel-ACPI.json",
+      "referenceNumber": "170",
+      "name": "Intel ACPI Software License Agreement",
+      "licenseId": "Intel-ACPI",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Intel_ACPI_Software_License_Agreement"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Intel.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Intel.json",
+      "referenceNumber": "171",
+      "name": "Intel Open Source License",
+      "licenseId": "Intel",
+      "seeAlso": [
+        "http://opensource.org/licenses/Intel"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Interbase-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Interbase-1.0.json",
+      "referenceNumber": "172",
+      "name": "Interbase Public License v1.0",
+      "licenseId": "Interbase-1.0",
+      "seeAlso": [
+        "https://web.archive.org/web/20060319014854/http://info.borland.com/devsupport/interbase/opensource/IPL.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./IPA.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/IPA.json",
+      "referenceNumber": "173",
+      "name": "IPA Font License",
+      "licenseId": "IPA",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/IPA"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./IPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/IPL-1.0.json",
+      "referenceNumber": "174",
+      "name": "IBM Public License v1.0",
+      "licenseId": "IPL-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/IPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./ISC.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/ISC.json",
+      "referenceNumber": "175",
+      "name": "ISC License",
+      "licenseId": "ISC",
+      "seeAlso": [
+        "https://www.isc.org/downloads/software-support-policy/isc-license/",
+        "http://www.opensource.org/licenses/ISC"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./JasPer-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/JasPer-2.0.json",
+      "referenceNumber": "176",
+      "name": "JasPer License",
+      "licenseId": "JasPer-2.0",
+      "seeAlso": [
+        "http://www.ece.uvic.ca/~mdadams/jasper/LICENSE"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./JSON.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/JSON.json",
+      "referenceNumber": "177",
+      "name": "JSON License",
+      "licenseId": "JSON",
+      "seeAlso": [
+        "http://www.json.org/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LAL-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LAL-1.2.json",
+      "referenceNumber": "178",
+      "name": "Licence Art Libre 1.2",
+      "licenseId": "LAL-1.2",
+      "seeAlso": [
+        "http://artlibre.org/licence/lal/licence-art-libre-12/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LAL-1.3.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LAL-1.3.json",
+      "referenceNumber": "179",
+      "name": "Licence Art Libre 1.3",
+      "licenseId": "LAL-1.3",
+      "seeAlso": [
+        "http://artlibre.org/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Latex2e.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Latex2e.json",
+      "referenceNumber": "180",
+      "name": "Latex2e License",
+      "licenseId": "Latex2e",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Latex2e"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Leptonica.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Leptonica.json",
+      "referenceNumber": "181",
+      "name": "Leptonica License",
+      "licenseId": "Leptonica",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Leptonica"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LGPL-2.0-only.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.0-only.json",
+      "referenceNumber": "182",
+      "name": "GNU Library General Public License v2 only",
+      "licenseId": "LGPL-2.0-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.0-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.0-or-later.json",
+      "referenceNumber": "183",
+      "name": "GNU Library General Public License v2 or later",
+      "licenseId": "LGPL-2.0-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.1-only.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.1-only.json",
+      "referenceNumber": "184",
+      "name": "GNU Lesser General Public License v2.1 only",
+      "licenseId": "LGPL-2.1-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-2.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.1-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.1-or-later.json",
+      "referenceNumber": "185",
+      "name": "GNU Lesser General Public License v2.1 or later",
+      "licenseId": "LGPL-2.1-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-2.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-3.0-only.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-3.0-only.json",
+      "referenceNumber": "186",
+      "name": "GNU Lesser General Public License v3.0 only",
+      "licenseId": "LGPL-3.0-only",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/lgpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-3.0-or-later.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-3.0-or-later.json",
+      "referenceNumber": "187",
+      "name": "GNU Lesser General Public License v3.0 or later",
+      "licenseId": "LGPL-3.0-or-later",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/lgpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPLLR.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LGPLLR.json",
+      "referenceNumber": "188",
+      "name": "Lesser General Public License For Linguistic Resources",
+      "licenseId": "LGPLLR",
+      "seeAlso": [
+        "http://www-igm.univ-mlv.fr/~unitex/lgpllr.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Libpng.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Libpng.json",
+      "referenceNumber": "189",
+      "name": "libpng License",
+      "licenseId": "Libpng",
+      "seeAlso": [
+        "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./libtiff.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/libtiff.json",
+      "referenceNumber": "190",
+      "name": "libtiff License",
+      "licenseId": "libtiff",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/libtiff"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LiLiQ-P-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LiLiQ-P-1.1.json",
+      "referenceNumber": "191",
+      "name": "Licence Libre du Québec – Permissive version 1.1",
+      "licenseId": "LiLiQ-P-1.1",
+      "seeAlso": [
+        "https://forge.gouv.qc.ca/licence/fr/liliq-v1-1/",
+        "http://opensource.org/licenses/LiLiQ-P-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LiLiQ-R-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LiLiQ-R-1.1.json",
+      "referenceNumber": "192",
+      "name": "Licence Libre du Québec – Réciprocité version 1.1",
+      "licenseId": "LiLiQ-R-1.1",
+      "seeAlso": [
+        "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-liliq-r-v1-1/",
+        "http://opensource.org/licenses/LiLiQ-R-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LiLiQ-Rplus-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LiLiQ-Rplus-1.1.json",
+      "referenceNumber": "193",
+      "name": "Licence Libre du Québec – Réciprocité forte version 1.1",
+      "licenseId": "LiLiQ-Rplus-1.1",
+      "seeAlso": [
+        "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-forte-liliq-r-v1-1/",
+        "http://opensource.org/licenses/LiLiQ-Rplus-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Linux-OpenIB.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Linux-OpenIB.json",
+      "referenceNumber": "194",
+      "name": "Linux Kernel Variant of OpenIB.org license",
+      "licenseId": "Linux-OpenIB",
+      "seeAlso": [
+        "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/infiniband/core/sa.h"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LPL-1.0.json",
+      "referenceNumber": "195",
+      "name": "Lucent Public License Version 1.0",
+      "licenseId": "LPL-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/LPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LPL-1.02.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LPL-1.02.json",
+      "referenceNumber": "196",
+      "name": "Lucent Public License v1.02",
+      "licenseId": "LPL-1.02",
+      "seeAlso": [
+        "http://plan9.bell-labs.com/plan9/license.html",
+        "http://www.opensource.org/licenses/LPL-1.02"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LPPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LPPL-1.0.json",
+      "referenceNumber": "197",
+      "name": "LaTeX Project Public License v1.0",
+      "licenseId": "LPPL-1.0",
+      "seeAlso": [
+        "http://www.latex-project.org/lppl/lppl-1-0.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LPPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LPPL-1.1.json",
+      "referenceNumber": "198",
+      "name": "LaTeX Project Public License v1.1",
+      "licenseId": "LPPL-1.1",
+      "seeAlso": [
+        "http://www.latex-project.org/lppl/lppl-1-1.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LPPL-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LPPL-1.2.json",
+      "referenceNumber": "199",
+      "name": "LaTeX Project Public License v1.2",
+      "licenseId": "LPPL-1.2",
+      "seeAlso": [
+        "http://www.latex-project.org/lppl/lppl-1-2.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LPPL-1.3a.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LPPL-1.3a.json",
+      "referenceNumber": "200",
+      "name": "LaTeX Project Public License v1.3a",
+      "licenseId": "LPPL-1.3a",
+      "seeAlso": [
+        "http://www.latex-project.org/lppl/lppl-1-3a.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./LPPL-1.3c.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/LPPL-1.3c.json",
+      "referenceNumber": "201",
+      "name": "LaTeX Project Public License v1.3c",
+      "licenseId": "LPPL-1.3c",
+      "seeAlso": [
+        "http://www.latex-project.org/lppl/lppl-1-3c.txt",
+        "http://www.opensource.org/licenses/LPPL-1.3c"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MakeIndex.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MakeIndex.json",
+      "referenceNumber": "202",
+      "name": "MakeIndex License",
+      "licenseId": "MakeIndex",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MakeIndex"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./MirOS.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MirOS.json",
+      "referenceNumber": "203",
+      "name": "MirOS License",
+      "licenseId": "MirOS",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/MirOS"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MIT-0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MIT-0.json",
+      "referenceNumber": "204",
+      "name": "MIT No Attribution",
+      "licenseId": "MIT-0",
+      "seeAlso": [
+        "https://github.com/aws/mit-0",
+        "https://romanrm.net/mit-zero",
+        "https://github.com/awsdocs/aws-cloud9-user-guide/blob/master/LICENSE-SAMPLECODE"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MIT-advertising.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MIT-advertising.json",
+      "referenceNumber": "205",
+      "name": "Enlightenment License (e16)",
+      "licenseId": "MIT-advertising",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MIT_With_Advertising"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./MIT-CMU.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MIT-CMU.json",
+      "referenceNumber": "206",
+      "name": "CMU License",
+      "licenseId": "MIT-CMU",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing:MIT?rd\u003dLicensing/MIT#CMU_Style"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./MIT-enna.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MIT-enna.json",
+      "referenceNumber": "207",
+      "name": "enna License",
+      "licenseId": "MIT-enna",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MIT#enna"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./MIT-feh.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MIT-feh.json",
+      "referenceNumber": "208",
+      "name": "feh License",
+      "licenseId": "MIT-feh",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MIT#feh"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./MIT.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/MIT.json",
+      "referenceNumber": "209",
+      "name": "MIT License",
+      "licenseId": "MIT",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/MIT"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MITNFA.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MITNFA.json",
+      "referenceNumber": "210",
+      "name": "MIT +no-false-attribs license",
+      "licenseId": "MITNFA",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MITNFA"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Motosoto.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Motosoto.json",
+      "referenceNumber": "211",
+      "name": "Motosoto License",
+      "licenseId": "Motosoto",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Motosoto"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./mpich2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/mpich2.json",
+      "referenceNumber": "212",
+      "name": "mpich2 License",
+      "licenseId": "mpich2",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/MIT"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./MPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MPL-1.0.json",
+      "referenceNumber": "213",
+      "name": "Mozilla Public License 1.0",
+      "licenseId": "MPL-1.0",
+      "seeAlso": [
+        "http://www.mozilla.org/MPL/MPL-1.0.html",
+        "http://opensource.org/licenses/MPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/MPL-1.1.json",
+      "referenceNumber": "214",
+      "name": "Mozilla Public License 1.1",
+      "licenseId": "MPL-1.1",
+      "seeAlso": [
+        "http://www.mozilla.org/MPL/MPL-1.1.html",
+        "http://www.opensource.org/licenses/MPL-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MPL-2.0-no-copyleft-exception.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MPL-2.0-no-copyleft-exception.json",
+      "referenceNumber": "215",
+      "name": "Mozilla Public License 2.0 (no copyleft exception)",
+      "licenseId": "MPL-2.0-no-copyleft-exception",
+      "seeAlso": [
+        "http://www.mozilla.org/MPL/2.0/",
+        "http://opensource.org/licenses/MPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MPL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/MPL-2.0.json",
+      "referenceNumber": "216",
+      "name": "Mozilla Public License 2.0",
+      "licenseId": "MPL-2.0",
+      "seeAlso": [
+        "http://www.mozilla.org/MPL/2.0/",
+        "http://opensource.org/licenses/MPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MS-PL.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/MS-PL.json",
+      "referenceNumber": "217",
+      "name": "Microsoft Public License",
+      "licenseId": "MS-PL",
+      "seeAlso": [
+        "http://www.microsoft.com/opensource/licenses.mspx",
+        "http://www.opensource.org/licenses/MS-PL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MS-RL.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/MS-RL.json",
+      "referenceNumber": "218",
+      "name": "Microsoft Reciprocal License",
+      "licenseId": "MS-RL",
+      "seeAlso": [
+        "http://www.microsoft.com/opensource/licenses.mspx",
+        "http://www.opensource.org/licenses/MS-RL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./MTLL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/MTLL.json",
+      "referenceNumber": "219",
+      "name": "Matrix Template Library License",
+      "licenseId": "MTLL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Matrix_Template_Library_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Multics.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Multics.json",
+      "referenceNumber": "220",
+      "name": "Multics License",
+      "licenseId": "Multics",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Multics"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Mup.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Mup.json",
+      "referenceNumber": "221",
+      "name": "Mup License",
+      "licenseId": "Mup",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Mup"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NASA-1.3.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NASA-1.3.json",
+      "referenceNumber": "222",
+      "name": "NASA Open Source Agreement 1.3",
+      "licenseId": "NASA-1.3",
+      "seeAlso": [
+        "http://ti.arc.nasa.gov/opensource/nosa/",
+        "http://www.opensource.org/licenses/NASA-1.3"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Naumen.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Naumen.json",
+      "referenceNumber": "223",
+      "name": "Naumen Public License",
+      "licenseId": "Naumen",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Naumen"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./NBPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NBPL-1.0.json",
+      "referenceNumber": "224",
+      "name": "Net Boolean Public License v1",
+      "licenseId": "NBPL-1.0",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d37b4b3f6cc4bf34e1d3dec61e69914b9819d8894"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NCSA.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/NCSA.json",
+      "referenceNumber": "225",
+      "name": "University of Illinois/NCSA Open Source License",
+      "licenseId": "NCSA",
+      "seeAlso": [
+        "http://otm.illinois.edu/uiuc_openSource",
+        "http://www.opensource.org/licenses/NCSA"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Net-SNMP.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Net-SNMP.json",
+      "referenceNumber": "226",
+      "name": "Net-SNMP License",
+      "licenseId": "Net-SNMP",
+      "seeAlso": [
+        "http://net-snmp.sourceforge.net/about/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NetCDF.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NetCDF.json",
+      "referenceNumber": "227",
+      "name": "NetCDF license",
+      "licenseId": "NetCDF",
+      "seeAlso": [
+        "http://www.unidata.ucar.edu/software/netcdf/copyright.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Newsletr.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Newsletr.json",
+      "referenceNumber": "228",
+      "name": "Newsletr License",
+      "licenseId": "Newsletr",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Newsletr"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NGPL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NGPL.json",
+      "referenceNumber": "229",
+      "name": "Nethack General Public License",
+      "licenseId": "NGPL",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/NGPL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./NLOD-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NLOD-1.0.json",
+      "referenceNumber": "230",
+      "name": "Norwegian Licence for Open Government Data",
+      "licenseId": "NLOD-1.0",
+      "seeAlso": [
+        "http://data.norge.no/nlod/en/1.0"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NLPL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NLPL.json",
+      "referenceNumber": "231",
+      "name": "No Limit Public License",
+      "licenseId": "NLPL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/NLPL"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Nokia.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Nokia.json",
+      "referenceNumber": "232",
+      "name": "Nokia Open Source License",
+      "licenseId": "Nokia",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/nokia"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./NOSL.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/NOSL.json",
+      "referenceNumber": "233",
+      "name": "Netizen Open Source License",
+      "licenseId": "NOSL",
+      "seeAlso": [
+        "http://bits.netizen.com.au/licenses/NOSL/nosl.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Noweb.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Noweb.json",
+      "referenceNumber": "234",
+      "name": "Noweb License",
+      "licenseId": "Noweb",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Noweb"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/NPL-1.0.json",
+      "referenceNumber": "235",
+      "name": "Netscape Public License v1.0",
+      "licenseId": "NPL-1.0",
+      "seeAlso": [
+        "http://www.mozilla.org/MPL/NPL/1.0/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/NPL-1.1.json",
+      "referenceNumber": "236",
+      "name": "Netscape Public License v1.1",
+      "licenseId": "NPL-1.1",
+      "seeAlso": [
+        "http://www.mozilla.org/MPL/NPL/1.1/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NPOSL-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NPOSL-3.0.json",
+      "referenceNumber": "237",
+      "name": "Non-Profit Open Software License 3.0",
+      "licenseId": "NPOSL-3.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/NOSL3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./NRL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NRL.json",
+      "referenceNumber": "238",
+      "name": "NRL License",
+      "licenseId": "NRL",
+      "seeAlso": [
+        "http://web.mit.edu/network/isakmp/nrllicense.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./NTP.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/NTP.json",
+      "referenceNumber": "239",
+      "name": "NTP License",
+      "licenseId": "NTP",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/NTP"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OCCT-PL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OCCT-PL.json",
+      "referenceNumber": "240",
+      "name": "Open CASCADE Technology Public License",
+      "licenseId": "OCCT-PL",
+      "seeAlso": [
+        "http://www.opencascade.com/content/occt-public-license"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OCLC-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OCLC-2.0.json",
+      "referenceNumber": "241",
+      "name": "OCLC Research Public License 2.0",
+      "licenseId": "OCLC-2.0",
+      "seeAlso": [
+        "http://www.oclc.org/research/activities/software/license/v2final.htm",
+        "http://www.opensource.org/licenses/OCLC-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./ODbL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/ODbL-1.0.json",
+      "referenceNumber": "242",
+      "name": "ODC Open Database License v1.0",
+      "licenseId": "ODbL-1.0",
+      "seeAlso": [
+        "http://www.opendatacommons.org/licenses/odbl/1.0/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ODC-By-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ODC-By-1.0.json",
+      "referenceNumber": "243",
+      "name": "Open Data Commons Attribution License v1.0",
+      "licenseId": "ODC-By-1.0",
+      "seeAlso": [
+        "https://opendatacommons.org/licenses/by/1.0/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OFL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OFL-1.0.json",
+      "referenceNumber": "244",
+      "name": "SIL Open Font License 1.0",
+      "licenseId": "OFL-1.0",
+      "seeAlso": [
+        "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OFL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OFL-1.1.json",
+      "referenceNumber": "245",
+      "name": "SIL Open Font License 1.1",
+      "licenseId": "OFL-1.1",
+      "seeAlso": [
+        "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web",
+        "http://www.opensource.org/licenses/OFL-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OGTSL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OGTSL.json",
+      "referenceNumber": "246",
+      "name": "Open Group Test Suite License",
+      "licenseId": "OGTSL",
+      "seeAlso": [
+        "http://www.opengroup.org/testing/downloads/The_Open_Group_TSL.txt",
+        "http://www.opensource.org/licenses/OGTSL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OLDAP-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-1.1.json",
+      "referenceNumber": "247",
+      "name": "Open LDAP Public License v1.1",
+      "licenseId": "OLDAP-1.1",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d806557a5ad59804ef3a44d5abfbe91d706b0791f"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-1.2.json",
+      "referenceNumber": "248",
+      "name": "Open LDAP Public License v1.2",
+      "licenseId": "OLDAP-1.2",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d42b0383c50c299977b5893ee695cf4e486fb0dc7"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-1.3.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-1.3.json",
+      "referenceNumber": "249",
+      "name": "Open LDAP Public License v1.3",
+      "licenseId": "OLDAP-1.3",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003de5f8117f0ce088d0bd7a8e18ddf37eaa40eb09b1"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-1.4.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-1.4.json",
+      "referenceNumber": "250",
+      "name": "Open LDAP Public License v1.4",
+      "licenseId": "OLDAP-1.4",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dc9f95c2f3f2ffb5e0ae55fe7388af75547660941"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.0.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.0.1.json",
+      "referenceNumber": "251",
+      "name": "Open LDAP Public License v2.0.1",
+      "licenseId": "OLDAP-2.0.1",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db6d68acd14e51ca3aab4428bf26522aa74873f0e"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.0.json",
+      "referenceNumber": "252",
+      "name": "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
+      "licenseId": "OLDAP-2.0",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcbf50f4e1185a21abd4c0a54d3f4341fe28f36ea"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.1.json",
+      "referenceNumber": "253",
+      "name": "Open LDAP Public License v2.1",
+      "licenseId": "OLDAP-2.1",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db0d176738e96a0d3b9f85cb51e140a86f21be715"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.2.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.1.json",
+      "referenceNumber": "254",
+      "name": "Open LDAP Public License v2.2.1",
+      "licenseId": "OLDAP-2.2.1",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d4bc786f34b50aa301be6f5600f58a980070f481e"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.2.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.2.json",
+      "referenceNumber": "255",
+      "name": "Open LDAP Public License 2.2.2",
+      "licenseId": "OLDAP-2.2.2",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003ddf2cc1e21eb7c160695f5b7cffd6296c151ba188"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.json",
+      "referenceNumber": "256",
+      "name": "Open LDAP Public License v2.2",
+      "licenseId": "OLDAP-2.2",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d470b0c18ec67621c85881b2733057fecf4a1acc3"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.3.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.3.json",
+      "referenceNumber": "257",
+      "name": "Open LDAP Public License v2.3",
+      "licenseId": "OLDAP-2.3",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dd32cf54a32d581ab475d23c810b0a7fbaf8d63c3"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.4.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.4.json",
+      "referenceNumber": "258",
+      "name": "Open LDAP Public License v2.4",
+      "licenseId": "OLDAP-2.4",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcd1284c4a91a8a380d904eee68d1583f989ed386"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.5.json",
+      "referenceNumber": "259",
+      "name": "Open LDAP Public License v2.5",
+      "licenseId": "OLDAP-2.5",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d6852b9d90022e8593c98205413380536b1b5a7cf"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.6.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.6.json",
+      "referenceNumber": "260",
+      "name": "Open LDAP Public License v2.6",
+      "licenseId": "OLDAP-2.6",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d1cae062821881f41b73012ba816434897abf4205"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.7.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.7.json",
+      "referenceNumber": "261",
+      "name": "Open LDAP Public License v2.7",
+      "licenseId": "OLDAP-2.7",
+      "seeAlso": [
+        "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d47c2415c1df81556eeb39be6cad458ef87c534a2"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OLDAP-2.8.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OLDAP-2.8.json",
+      "referenceNumber": "262",
+      "name": "Open LDAP Public License v2.8",
+      "licenseId": "OLDAP-2.8",
+      "seeAlso": [
+        "http://www.openldap.org/software/release/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OML.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OML.json",
+      "referenceNumber": "263",
+      "name": "Open Market License",
+      "licenseId": "OML",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Open_Market_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OpenSSL.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OpenSSL.json",
+      "referenceNumber": "264",
+      "name": "OpenSSL License",
+      "licenseId": "OpenSSL",
+      "seeAlso": [
+        "http://www.openssl.org/source/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OPL-1.0.json",
+      "referenceNumber": "265",
+      "name": "Open Public License v1.0",
+      "licenseId": "OPL-1.0",
+      "seeAlso": [
+        "http://old.koalateam.com/jackaroo/OPL_1_0.TXT",
+        "https://fedoraproject.org/wiki/Licensing/Open_Public_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OSET-PL-2.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/OSET-PL-2.1.json",
+      "referenceNumber": "266",
+      "name": "OSET Public License version 2.1",
+      "licenseId": "OSET-PL-2.1",
+      "seeAlso": [
+        "http://www.osetfoundation.org/public-license",
+        "http://opensource.org/licenses/OPL-2.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OSL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OSL-1.0.json",
+      "referenceNumber": "267",
+      "name": "Open Software License 1.0",
+      "licenseId": "OSL-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/OSL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OSL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OSL-1.1.json",
+      "referenceNumber": "268",
+      "name": "Open Software License 1.1",
+      "licenseId": "OSL-1.1",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/OSL1.1"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./OSL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OSL-2.0.json",
+      "referenceNumber": "269",
+      "name": "Open Software License 2.0",
+      "licenseId": "OSL-2.0",
+      "seeAlso": [
+        "http://web.archive.org/web/20041020171434/http://www.rosenlaw.com/osl2.0.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OSL-2.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OSL-2.1.json",
+      "referenceNumber": "270",
+      "name": "Open Software License 2.1",
+      "licenseId": "OSL-2.1",
+      "seeAlso": [
+        "http://web.archive.org/web/20050212003940/http://www.rosenlaw.com/osl21.htm",
+        "http://opensource.org/licenses/OSL-2.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./OSL-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/OSL-3.0.json",
+      "referenceNumber": "271",
+      "name": "Open Software License 3.0",
+      "licenseId": "OSL-3.0",
+      "seeAlso": [
+        "http://www.rosenlaw.com/OSL3.0.htm",
+        "http://www.opensource.org/licenses/OSL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./PDDL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/PDDL-1.0.json",
+      "referenceNumber": "272",
+      "name": "ODC Public Domain Dedication \u0026 License 1.0",
+      "licenseId": "PDDL-1.0",
+      "seeAlso": [
+        "http://opendatacommons.org/licenses/pddl/1.0/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./PHP-3.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/PHP-3.0.json",
+      "referenceNumber": "273",
+      "name": "PHP License v3.0",
+      "licenseId": "PHP-3.0",
+      "seeAlso": [
+        "http://www.php.net/license/3_0.txt",
+        "http://www.opensource.org/licenses/PHP-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./PHP-3.01.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/PHP-3.01.json",
+      "referenceNumber": "274",
+      "name": "PHP License v3.01",
+      "licenseId": "PHP-3.01",
+      "seeAlso": [
+        "http://www.php.net/license/3_01.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Plexus.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Plexus.json",
+      "referenceNumber": "275",
+      "name": "Plexus Classworlds License",
+      "licenseId": "Plexus",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Plexus_Classworlds_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./PostgreSQL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/PostgreSQL.json",
+      "referenceNumber": "276",
+      "name": "PostgreSQL License",
+      "licenseId": "PostgreSQL",
+      "seeAlso": [
+        "http://www.postgresql.org/about/licence",
+        "http://www.opensource.org/licenses/PostgreSQL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./psfrag.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/psfrag.json",
+      "referenceNumber": "277",
+      "name": "psfrag License",
+      "licenseId": "psfrag",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/psfrag"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./psutils.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/psutils.json",
+      "referenceNumber": "278",
+      "name": "psutils License",
+      "licenseId": "psutils",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/psutils"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Python-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Python-2.0.json",
+      "referenceNumber": "279",
+      "name": "Python License 2.0",
+      "licenseId": "Python-2.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Python-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Qhull.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Qhull.json",
+      "referenceNumber": "280",
+      "name": "Qhull License",
+      "licenseId": "Qhull",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Qhull"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./QPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/QPL-1.0.json",
+      "referenceNumber": "281",
+      "name": "Q Public License 1.0",
+      "licenseId": "QPL-1.0",
+      "seeAlso": [
+        "http://doc.qt.nokia.com/3.3/license.html",
+        "http://www.opensource.org/licenses/QPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Rdisc.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Rdisc.json",
+      "referenceNumber": "282",
+      "name": "Rdisc License",
+      "licenseId": "Rdisc",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Rdisc_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./RHeCos-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/RHeCos-1.1.json",
+      "referenceNumber": "283",
+      "name": "Red Hat eCos Public License v1.1",
+      "licenseId": "RHeCos-1.1",
+      "seeAlso": [
+        "http://ecos.sourceware.org/old-license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./RPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/RPL-1.1.json",
+      "referenceNumber": "284",
+      "name": "Reciprocal Public License 1.1",
+      "licenseId": "RPL-1.1",
+      "seeAlso": [
+        "http://opensource.org/licenses/RPL-1.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./RPL-1.5.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/RPL-1.5.json",
+      "referenceNumber": "285",
+      "name": "Reciprocal Public License 1.5",
+      "licenseId": "RPL-1.5",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/RPL-1.5"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./RPSL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/RPSL-1.0.json",
+      "referenceNumber": "286",
+      "name": "RealNetworks Public Source License v1.0",
+      "licenseId": "RPSL-1.0",
+      "seeAlso": [
+        "https://helixcommunity.org/content/rpsl",
+        "http://www.opensource.org/licenses/RPSL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./RSA-MD.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/RSA-MD.json",
+      "referenceNumber": "287",
+      "name": "RSA Message-Digest License ",
+      "licenseId": "RSA-MD",
+      "seeAlso": [
+        "http://www.faqs.org/rfcs/rfc1321.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./RSCPL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/RSCPL.json",
+      "referenceNumber": "288",
+      "name": "Ricoh Source Code Public License",
+      "licenseId": "RSCPL",
+      "seeAlso": [
+        "http://wayback.archive.org/web/20060715140826/http://www.risource.org/RPL/RPL-1.0A.shtml",
+        "http://www.opensource.org/licenses/RSCPL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Ruby.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Ruby.json",
+      "referenceNumber": "289",
+      "name": "Ruby License",
+      "licenseId": "Ruby",
+      "seeAlso": [
+        "http://www.ruby-lang.org/en/LICENSE.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SAX-PD.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SAX-PD.json",
+      "referenceNumber": "290",
+      "name": "Sax Public Domain Notice",
+      "licenseId": "SAX-PD",
+      "seeAlso": [
+        "http://www.saxproject.org/copying.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Saxpath.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Saxpath.json",
+      "referenceNumber": "291",
+      "name": "Saxpath License",
+      "licenseId": "Saxpath",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Saxpath_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SCEA.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SCEA.json",
+      "referenceNumber": "292",
+      "name": "SCEA Shared Source License",
+      "licenseId": "SCEA",
+      "seeAlso": [
+        "http://research.scea.com/scea_shared_source_license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Sendmail.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Sendmail.json",
+      "referenceNumber": "293",
+      "name": "Sendmail License",
+      "licenseId": "Sendmail",
+      "seeAlso": [
+        "http://www.sendmail.com/pdfs/open_source/sendmail_license.pdf",
+        "https://web.archive.org/web/20160322142305/https://www.sendmail.com/pdfs/open_source/sendmail_license.pdf"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SGI-B-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SGI-B-1.0.json",
+      "referenceNumber": "294",
+      "name": "SGI Free Software License B v1.0",
+      "licenseId": "SGI-B-1.0",
+      "seeAlso": [
+        "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.1.0.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SGI-B-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SGI-B-1.1.json",
+      "referenceNumber": "295",
+      "name": "SGI Free Software License B v1.1",
+      "licenseId": "SGI-B-1.1",
+      "seeAlso": [
+        "http://oss.sgi.com/projects/FreeB/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SGI-B-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/SGI-B-2.0.json",
+      "referenceNumber": "296",
+      "name": "SGI Free Software License B v2.0",
+      "licenseId": "SGI-B-2.0",
+      "seeAlso": [
+        "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.2.0.pdf"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SimPL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SimPL-2.0.json",
+      "referenceNumber": "297",
+      "name": "Simple Public License 2.0",
+      "licenseId": "SimPL-2.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/SimPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./SISSL-1.2.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SISSL-1.2.json",
+      "referenceNumber": "298",
+      "name": "Sun Industry Standards Source License v1.2",
+      "licenseId": "SISSL-1.2",
+      "seeAlso": [
+        "http://gridscheduler.sourceforge.net/Gridengine_SISSL_license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SISSL.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/SISSL.json",
+      "referenceNumber": "299",
+      "name": "Sun Industry Standards Source License v1.1",
+      "licenseId": "SISSL",
+      "seeAlso": [
+        "http://www.openoffice.org/licenses/sissl_license.html",
+        "http://opensource.org/licenses/SISSL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Sleepycat.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Sleepycat.json",
+      "referenceNumber": "300",
+      "name": "Sleepycat License",
+      "licenseId": "Sleepycat",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Sleepycat"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./SMLNJ.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/SMLNJ.json",
+      "referenceNumber": "301",
+      "name": "Standard ML of New Jersey License",
+      "licenseId": "SMLNJ",
+      "seeAlso": [
+        "https://www.smlnj.org/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SMPPL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SMPPL.json",
+      "referenceNumber": "302",
+      "name": "Secure Messaging Protocol Public License",
+      "licenseId": "SMPPL",
+      "seeAlso": [
+        "https://github.com/dcblake/SMP/blob/master/Documentation/License.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SNIA.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SNIA.json",
+      "referenceNumber": "303",
+      "name": "SNIA Public License 1.1",
+      "licenseId": "SNIA",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/SNIA_Public_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Spencer-86.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Spencer-86.json",
+      "referenceNumber": "304",
+      "name": "Spencer License 86",
+      "licenseId": "Spencer-86",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Spencer-94.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Spencer-94.json",
+      "referenceNumber": "305",
+      "name": "Spencer License 94",
+      "licenseId": "Spencer-94",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Spencer-99.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Spencer-99.json",
+      "referenceNumber": "306",
+      "name": "Spencer License 99",
+      "licenseId": "Spencer-99",
+      "seeAlso": [
+        "http://www.opensource.apple.com/source/tcl/tcl-5/tcl/generic/regfronts.c"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/SPL-1.0.json",
+      "referenceNumber": "307",
+      "name": "Sun Public License v1.0",
+      "licenseId": "SPL-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/SPL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./SugarCRM-1.1.3.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SugarCRM-1.1.3.json",
+      "referenceNumber": "308",
+      "name": "SugarCRM Public License v1.1.3",
+      "licenseId": "SugarCRM-1.1.3",
+      "seeAlso": [
+        "http://www.sugarcrm.com/crm/SPL"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./SWL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/SWL.json",
+      "referenceNumber": "309",
+      "name": "Scheme Widget Library (SWL) Software License Agreement",
+      "licenseId": "SWL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/SWL"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./TCL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/TCL.json",
+      "referenceNumber": "310",
+      "name": "TCL/TK License",
+      "licenseId": "TCL",
+      "seeAlso": [
+        "http://www.tcl.tk/software/tcltk/license.html",
+        "https://fedoraproject.org/wiki/Licensing/TCL"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./TCP-wrappers.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/TCP-wrappers.json",
+      "referenceNumber": "311",
+      "name": "TCP Wrappers License",
+      "licenseId": "TCP-wrappers",
+      "seeAlso": [
+        "http://rc.quest.com/topics/openssh/license.php#tcpwrappers"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./TMate.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/TMate.json",
+      "referenceNumber": "312",
+      "name": "TMate Open Source License",
+      "licenseId": "TMate",
+      "seeAlso": [
+        "http://svnkit.com/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./TORQUE-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/TORQUE-1.1.json",
+      "referenceNumber": "313",
+      "name": "TORQUE v2.5+ Software License v1.1",
+      "licenseId": "TORQUE-1.1",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/TORQUEv1.1"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./TOSL.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/TOSL.json",
+      "referenceNumber": "314",
+      "name": "Trusster Open Source License",
+      "licenseId": "TOSL",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/TOSL"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./TU-Berlin-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/TU-Berlin-1.0.json",
+      "referenceNumber": "315",
+      "name": "Technische Universitaet Berlin License 1.0",
+      "licenseId": "TU-Berlin-1.0",
+      "seeAlso": [
+        "https://github.com/swh/ladspa/blob/7bf6f3799fdba70fda297c2d8fd9f526803d9680/gsm/COPYRIGHT"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./TU-Berlin-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/TU-Berlin-2.0.json",
+      "referenceNumber": "316",
+      "name": "Technische Universitaet Berlin License 2.0",
+      "licenseId": "TU-Berlin-2.0",
+      "seeAlso": [
+        "https://github.com/CorsixTH/deps/blob/fd339a9f526d1d9c9f01ccf39e438a015da50035/licences/libgsm.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Unicode-DFS-2015.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Unicode-DFS-2015.json",
+      "referenceNumber": "317",
+      "name": "Unicode License Agreement - Data Files and Software (2015)",
+      "licenseId": "Unicode-DFS-2015",
+      "seeAlso": [
+        "https://web.archive.org/web/20151224134844/http://unicode.org/copyright.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Unicode-DFS-2016.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Unicode-DFS-2016.json",
+      "referenceNumber": "318",
+      "name": "Unicode License Agreement - Data Files and Software (2016)",
+      "licenseId": "Unicode-DFS-2016",
+      "seeAlso": [
+        "http://www.unicode.org/copyright.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Unicode-TOU.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Unicode-TOU.json",
+      "referenceNumber": "319",
+      "name": "Unicode Terms of Use",
+      "licenseId": "Unicode-TOU",
+      "seeAlso": [
+        "http://www.unicode.org/copyright.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Unlicense.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Unlicense.json",
+      "referenceNumber": "320",
+      "name": "The Unlicense",
+      "licenseId": "Unlicense",
+      "seeAlso": [
+        "http://unlicense.org/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./UPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/UPL-1.0.json",
+      "referenceNumber": "321",
+      "name": "Universal Permissive License v1.0",
+      "licenseId": "UPL-1.0",
+      "seeAlso": [
+        "http://opensource.org/licenses/UPL"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Vim.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Vim.json",
+      "referenceNumber": "322",
+      "name": "Vim License",
+      "licenseId": "Vim",
+      "seeAlso": [
+        "http://vimdoc.sourceforge.net/htmldoc/uganda.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./VOSTROM.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/VOSTROM.json",
+      "referenceNumber": "323",
+      "name": "VOSTROM Public License for Open Source",
+      "licenseId": "VOSTROM",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/VOSTROM"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./VSL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/VSL-1.0.json",
+      "referenceNumber": "324",
+      "name": "Vovida Software License v1.0",
+      "licenseId": "VSL-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/VSL-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./W3C-19980720.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/W3C-19980720.json",
+      "referenceNumber": "325",
+      "name": "W3C Software Notice and License (1998-07-20)",
+      "licenseId": "W3C-19980720",
+      "seeAlso": [
+        "http://www.w3.org/Consortium/Legal/copyright-software-19980720.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./W3C-20150513.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/W3C-20150513.json",
+      "referenceNumber": "326",
+      "name": "W3C Software Notice and Document License (2015-05-13)",
+      "licenseId": "W3C-20150513",
+      "seeAlso": [
+        "https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./W3C.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/W3C.json",
+      "referenceNumber": "327",
+      "name": "W3C Software Notice and License (2002-12-31)",
+      "licenseId": "W3C",
+      "seeAlso": [
+        "http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html",
+        "http://www.opensource.org/licenses/W3C"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Watcom-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Watcom-1.0.json",
+      "referenceNumber": "328",
+      "name": "Sybase Open Watcom Public License 1.0",
+      "licenseId": "Watcom-1.0",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/Watcom-1.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Wsuipa.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Wsuipa.json",
+      "referenceNumber": "329",
+      "name": "Wsuipa License",
+      "licenseId": "Wsuipa",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Wsuipa"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./WTFPL.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/WTFPL.json",
+      "referenceNumber": "330",
+      "name": "Do What The F*ck You Want To Public License",
+      "licenseId": "WTFPL",
+      "seeAlso": [
+        "http://sam.zoy.org/wtfpl/COPYING"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./X11.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/X11.json",
+      "referenceNumber": "331",
+      "name": "X11 License",
+      "licenseId": "X11",
+      "seeAlso": [
+        "http://www.xfree86.org/3.3.6/COPYRIGHT2.html#3"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Xerox.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Xerox.json",
+      "referenceNumber": "332",
+      "name": "Xerox License",
+      "licenseId": "Xerox",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Xerox"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./XFree86-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/XFree86-1.1.json",
+      "referenceNumber": "333",
+      "name": "XFree86 License 1.1",
+      "licenseId": "XFree86-1.1",
+      "seeAlso": [
+        "http://www.xfree86.org/current/LICENSE4.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./xinetd.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/xinetd.json",
+      "referenceNumber": "334",
+      "name": "xinetd License",
+      "licenseId": "xinetd",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Xinetd_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Xnet.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Xnet.json",
+      "referenceNumber": "335",
+      "name": "X.Net License",
+      "licenseId": "Xnet",
+      "seeAlso": [
+        "http://opensource.org/licenses/Xnet"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./xpp.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/xpp.json",
+      "referenceNumber": "336",
+      "name": "XPP License",
+      "licenseId": "xpp",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/xpp"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./XSkat.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/XSkat.json",
+      "referenceNumber": "337",
+      "name": "XSkat License",
+      "licenseId": "XSkat",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/XSkat_License"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./YPL-1.0.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/YPL-1.0.json",
+      "referenceNumber": "338",
+      "name": "Yahoo! Public License v1.0",
+      "licenseId": "YPL-1.0",
+      "seeAlso": [
+        "http://www.zimbra.com/license/yahoo_public_license_1.0.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./YPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/YPL-1.1.json",
+      "referenceNumber": "339",
+      "name": "Yahoo! Public License v1.1",
+      "licenseId": "YPL-1.1",
+      "seeAlso": [
+        "http://www.zimbra.com/license/yahoo_public_license_1.1.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Zed.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Zed.json",
+      "referenceNumber": "340",
+      "name": "Zed License",
+      "licenseId": "Zed",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Zed"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Zend-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Zend-2.0.json",
+      "referenceNumber": "341",
+      "name": "Zend License v2.0",
+      "licenseId": "Zend-2.0",
+      "seeAlso": [
+        "https://web.archive.org/web/20130517195954/http://www.zend.com/license/2_00.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Zimbra-1.3.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Zimbra-1.3.json",
+      "referenceNumber": "342",
+      "name": "Zimbra Public License v1.3",
+      "licenseId": "Zimbra-1.3",
+      "seeAlso": [
+        "http://web.archive.org/web/20100302225219/http://www.zimbra.com/license/zimbra-public-license-1-3.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Zimbra-1.4.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/Zimbra-1.4.json",
+      "referenceNumber": "343",
+      "name": "Zimbra Public License v1.4",
+      "licenseId": "Zimbra-1.4",
+      "seeAlso": [
+        "http://www.zimbra.com/legal/zimbra-public-license-1-4"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./zlib-acknowledgement.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/zlib-acknowledgement.json",
+      "referenceNumber": "344",
+      "name": "zlib/libpng License with Acknowledgement",
+      "licenseId": "zlib-acknowledgement",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/ZlibWithAcknowledgement"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./Zlib.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Zlib.json",
+      "referenceNumber": "345",
+      "name": "zlib License",
+      "licenseId": "Zlib",
+      "seeAlso": [
+        "http://www.zlib.net/zlib_license.html",
+        "http://www.opensource.org/licenses/Zlib"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./ZPL-1.1.html",
+      "isDeprecatedLicenseId": false,
+      "detailsUrl": "http://spdx.org/licenses/ZPL-1.1.json",
+      "referenceNumber": "346",
+      "name": "Zope Public License 1.1",
+      "licenseId": "ZPL-1.1",
+      "seeAlso": [
+        "http://old.zope.org/Resources/License/ZPL-1.1"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./ZPL-2.0.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/ZPL-2.0.json",
+      "referenceNumber": "347",
+      "name": "Zope Public License 2.0",
+      "licenseId": "ZPL-2.0",
+      "seeAlso": [
+        "http://old.zope.org/Resources/License/ZPL-2.0",
+        "http://opensource.org/licenses/ZPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./ZPL-2.1.html",
+      "isDeprecatedLicenseId": false,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/ZPL-2.1.json",
+      "referenceNumber": "348",
+      "name": "Zope Public License 2.1",
+      "licenseId": "ZPL-2.1",
+      "seeAlso": [
+        "http://old.zope.org/Resources/ZPL/"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AGPL-1.0.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AGPL-1.0.json",
+      "referenceNumber": "349",
+      "name": "Affero General Public License v1.0",
+      "licenseId": "AGPL-1.0",
+      "seeAlso": [
+        "http://www.affero.org/oagpl.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./AGPL-3.0.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/AGPL-3.0.json",
+      "referenceNumber": "350",
+      "name": "GNU Affero General Public License v3.0",
+      "licenseId": "AGPL-3.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/agpl.txt",
+        "http://www.opensource.org/licenses/AGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./eCos-2.0.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/eCos-2.0.json",
+      "referenceNumber": "351",
+      "name": "eCos license version 2.0",
+      "licenseId": "eCos-2.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/ecos-license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.1.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.1.json",
+      "referenceNumber": "352",
+      "name": "GNU Free Documentation License v1.1",
+      "licenseId": "GFDL-1.1",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/fdl-1.1.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.2.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.2.json",
+      "referenceNumber": "353",
+      "name": "GNU Free Documentation License v1.2",
+      "licenseId": "GFDL-1.2",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/fdl-1.2.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GFDL-1.3.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GFDL-1.3.json",
+      "referenceNumber": "354",
+      "name": "GNU Free Documentation License v1.3",
+      "licenseId": "GFDL-1.3",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/fdl-1.3.txt"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-1.0+.html",
+      "isDeprecatedLicenseId": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-1.0+.json",
+      "referenceNumber": "355",
+      "name": "GNU General Public License v1.0 or later",
+      "licenseId": "GPL-1.0+",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-1.0.html",
+      "isDeprecatedLicenseId": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-1.0.json",
+      "referenceNumber": "356",
+      "name": "GNU General Public License v1.0 only",
+      "licenseId": "GPL-1.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0+.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0+.json",
+      "referenceNumber": "357",
+      "name": "GNU General Public License v2.0 or later",
+      "licenseId": "GPL-2.0+",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-2.0-with-autoconf-exception.html",
+      "isDeprecatedLicenseId": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-autoconf-exception.json",
+      "referenceNumber": "358",
+      "name": "GNU General Public License v2.0 w/Autoconf exception",
+      "licenseId": "GPL-2.0-with-autoconf-exception",
+      "seeAlso": [
+        "http://ac-archive.sourceforge.net/doc/copyright.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0-with-bison-exception.html",
+      "isDeprecatedLicenseId": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-bison-exception.json",
+      "referenceNumber": "359",
+      "name": "GNU General Public License v2.0 w/Bison exception",
+      "licenseId": "GPL-2.0-with-bison-exception",
+      "seeAlso": [
+        "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0-with-classpath-exception.html",
+      "isDeprecatedLicenseId": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-classpath-exception.json",
+      "referenceNumber": "360",
+      "name": "GNU General Public License v2.0 w/Classpath exception",
+      "licenseId": "GPL-2.0-with-classpath-exception",
+      "seeAlso": [
+        "http://www.gnu.org/software/classpath/license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0-with-font-exception.html",
+      "isDeprecatedLicenseId": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-font-exception.json",
+      "referenceNumber": "361",
+      "name": "GNU General Public License v2.0 w/Font exception",
+      "licenseId": "GPL-2.0-with-font-exception",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gpl-faq.html#FontException"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0-with-GCC-exception.html",
+      "isDeprecatedLicenseId": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-GCC-exception.json",
+      "referenceNumber": "362",
+      "name": "GNU General Public License v2.0 w/GCC Runtime Library exception",
+      "licenseId": "GPL-2.0-with-GCC-exception",
+      "seeAlso": [
+        "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-2.0.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-2.0.json",
+      "referenceNumber": "363",
+      "name": "GNU General Public License v2.0 only",
+      "licenseId": "GPL-2.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-2.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-3.0+.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-3.0+.json",
+      "referenceNumber": "364",
+      "name": "GNU General Public License v3.0 or later",
+      "licenseId": "GPL-3.0+",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-3.0-with-autoconf-exception.html",
+      "isDeprecatedLicenseId": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-3.0-with-autoconf-exception.json",
+      "referenceNumber": "365",
+      "name": "GNU General Public License v3.0 w/Autoconf exception",
+      "licenseId": "GPL-3.0-with-autoconf-exception",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/autoconf-exception-3.0.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./GPL-3.0-with-GCC-exception.html",
+      "isDeprecatedLicenseId": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-3.0-with-GCC-exception.json",
+      "referenceNumber": "366",
+      "name": "GNU General Public License v3.0 w/GCC Runtime Library exception",
+      "licenseId": "GPL-3.0-with-GCC-exception",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gcc-exception-3.1.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./GPL-3.0.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/GPL-3.0.json",
+      "referenceNumber": "367",
+      "name": "GNU General Public License v3.0 only",
+      "licenseId": "GPL-3.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/gpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/GPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.0+.html",
+      "isDeprecatedLicenseId": true,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.0+.json",
+      "referenceNumber": "368",
+      "name": "GNU Library General Public License v2 or later",
+      "licenseId": "LGPL-2.0+",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.0.html",
+      "isDeprecatedLicenseId": true,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.0.json",
+      "referenceNumber": "369",
+      "name": "GNU Library General Public License v2 only",
+      "licenseId": "LGPL-2.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.1+.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.1+.json",
+      "referenceNumber": "370",
+      "name": "GNU Library General Public License v2.1 or later",
+      "licenseId": "LGPL-2.1+",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-2.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-2.1.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-2.1.json",
+      "referenceNumber": "371",
+      "name": "GNU Lesser General Public License v2.1 only",
+      "licenseId": "LGPL-2.1",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-2.1"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-3.0+.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-3.0+.json",
+      "referenceNumber": "372",
+      "name": "GNU Lesser General Public License v3.0 or later",
+      "licenseId": "LGPL-3.0+",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/lgpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./LGPL-3.0.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/LGPL-3.0.json",
+      "referenceNumber": "373",
+      "name": "GNU Lesser General Public License v3.0 only",
+      "licenseId": "LGPL-3.0",
+      "seeAlso": [
+        "http://www.gnu.org/licenses/lgpl-3.0-standalone.html",
+        "http://www.opensource.org/licenses/LGPL-3.0"
+      ],
+      "isOsiApproved": true
+    },
+    {
+      "reference": "./Nunit.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/Nunit.json",
+      "referenceNumber": "374",
+      "name": "Nunit License",
+      "licenseId": "Nunit",
+      "seeAlso": [
+        "https://fedoraproject.org/wiki/Licensing/Nunit"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./StandardML-NJ.html",
+      "isDeprecatedLicenseId": true,
+      "isFsfLibre": true,
+      "detailsUrl": "http://spdx.org/licenses/StandardML-NJ.json",
+      "referenceNumber": "375",
+      "name": "Standard ML of New Jersey License",
+      "licenseId": "StandardML-NJ",
+      "seeAlso": [
+        "http://www.smlnj.org//license.html"
+      ],
+      "isOsiApproved": false
+    },
+    {
+      "reference": "./wxWindows.html",
+      "isDeprecatedLicenseId": true,
+      "detailsUrl": "http://spdx.org/licenses/wxWindows.json",
+      "referenceNumber": "376",
+      "name": "wxWindows Library License",
+      "licenseId": "wxWindows",
+      "seeAlso": [
+        "http://www.opensource.org/licenses/WXwindows"
+      ],
+      "isOsiApproved": false
+    }
+  ],
+  "releaseDate": "2018-07-10"
+}
diff --git a/cabal/pretty-show-1.6.16/CHANGELOG b/cabal/pretty-show-1.6.16/CHANGELOG
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/CHANGELOG
@@ -0,0 +1,41 @@
+Changes in 1.6.16
+  * Fixes to accomodate GHC 8.4
+
+Changes in 1.6.13
+  * Parse things like <function> and <Function> as constructors
+
+Changes in 1.6.12
+  * Treat reserved operators as infix constructors (best effort kind of thing)
+
+Changes in 1.6.11
+  * Add `pPrint`, which is `putStrLn . ppShow`
+
+Changes in 1.6.10
+  * Increase the precedence of unary minus
+
+Changes in 1.6.9
+  * Relax parsing of atoms, so that we can support things like the show
+    instance of StdGen (e.g., [ 123 45, 786 10 ])
+
+Changes in 1.6.8.2:
+  * Correct license in srouce files.
+
+Changes in 1.6.8.1:
+  * Correct the 'License' field in the Cabal file to match the license (MIT)
+
+Changes in 1.6.8:
+  * Move source-repository pragma to top-level.
+
+Changes in 1.6.5:
+  * Rename CHANGES to CHANGELOG to work with hackage.
+
+Changes in 1.6.4:
+  * Drop dependency on happy >= 1.19
+
+Changes in 1.6.3:
+  * Add Safe Haskell annotations
+  * Add CHANGES file
+  * Add generated parser to package again.  We do this, because otherwise
+    the package fails to build on systems that do not have `happy`.
+    This is a bit questionable, but hopefully it won't be too much of
+    a problem.
diff --git a/cabal/pretty-show-1.6.16/LICENSE b/cabal/pretty-show-1.6.16/LICENSE
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2008 Iavor S. Diatchki
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/cabal/pretty-show-1.6.16/Setup.lhs b/cabal/pretty-show-1.6.16/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/Setup.lhs
@@ -0,0 +1,8 @@
+#! /usr/bin/env runhaskell
+
+> module Main (main) where
+>
+> import Distribution.Simple (defaultMain)
+>
+> main :: IO ()
+> main = defaultMain
diff --git a/cabal/pretty-show-1.6.16/Text/Show/Html.hs b/cabal/pretty-show-1.6.16/Text/Show/Html.hs
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/Text/Show/Html.hs
@@ -0,0 +1,211 @@
+{-# LANGUAGE Safe #-}
+module Text.Show.Html
+  ( HtmlOpts(..), defaultHtmlOpts
+  , valToHtml, valToHtmlPage, htmlPage
+  , Html(..)
+  ) where
+
+import Text.Show.Value
+import Prelude hiding (span)
+
+-- | Make an Html page representing the given value.
+valToHtmlPage :: HtmlOpts -> Value -> String
+valToHtmlPage opts = htmlPage opts . valToHtml opts
+
+-- | Options on how to generate Html (more to come).
+data HtmlOpts = HtmlOpts
+  { dataDir :: FilePath   -- ^ Path for extra files.  If empty, we look in
+                          -- directory `style`, relative to document.
+  , wideListWidth :: Int  -- ^ Max. number of columns in wide lists.
+  } deriving Show
+
+-- | Default options.
+defaultHtmlOpts :: HtmlOpts
+defaultHtmlOpts = HtmlOpts
+  { dataDir       = ""
+  , wideListWidth = 80
+  }
+
+-- | Convert a value into an Html fragment.
+valToHtml :: HtmlOpts -> Value -> Html
+valToHtml opts = loop
+  where
+  loop val =
+    case val of
+      Con con []  -> span "con" (text con)
+      Con con vs  -> tallRecord con (map conLab vs) (map loop         vs)
+      Rec con fs  -> tallRecord con (map fst fs)    (map (loop . snd) fs)
+      Tuple vs    -> wideTuple                      (map loop vs)
+
+      InfixCons v ms ->
+        table "infix tallRecord"
+          [ tr $ (th "label" 1 (text " ") :)
+               $ map td $ loop v : [ h | (op,u) <- ms
+                                   , h <- [ text op, loop u ]
+                                   ]
+          ]
+
+      List []     -> span "list" (text "[]")
+      List vs@(v : vs1) ->
+        case v of
+
+          Con c fs
+            | all (isCon c) vs1  -> recordList c (map conLab fs)
+                                     [ map loop xs | Con _ xs <- vs ]
+            | otherwise          -> tallList $ map (loop) vs
+
+          Rec c fs
+            | all (isRec c) vs1   -> recordList c (map fst fs)
+                                   [ map (loop . snd) xs | Rec _ xs <- vs ]
+            | otherwise           -> tallList $ map (loop) vs
+
+          Tuple fs -> tupleList (length fs)
+                            [ map (loop) xs | Tuple xs <- vs ]
+
+          List {}    -> tallList    $ map loop vs
+
+          Neg {}     -> wideList (wideListWidth opts) $ map loop vs
+          Ratio {}   -> wideList (wideListWidth opts) $ map loop vs
+          Integer {} -> wideList (wideListWidth opts) $ map loop vs
+          Float {}   -> wideList (wideListWidth opts) $ map loop vs
+          Char {}    -> wideList (wideListWidth opts) $ map loop vs
+          String {}  -> tallList                      $ map loop vs
+          InfixCons {} -> tallList                    $ map loop vs
+
+      Neg v       ->
+        case v of
+          Integer txt -> span "integer" $ text ('-' : txt)
+          Float txt   -> span "float"   $ text ('-' : txt)
+          _           -> neg (loop v)
+
+      Ratio v1 v2 -> ratio (loop v1) (loop v2)
+      Integer txt -> span "integer" (text txt)
+      Float txt   -> span "float"   (text txt)
+      Char txt    -> span "char"    (text txt)
+      String txt  -> span "string"  (text txt)
+
+  conLab _          = " "
+
+  isCon c (Con d _) = c == d
+  isCon _ _         = False
+
+  isRec c (Rec d _) = c == d
+  isRec _ _         = False
+
+
+neg :: Html -> Html
+neg e = table "negate" [ tr [td (text "-"), td e] ]
+
+ratio :: Html -> Html -> Html
+ratio e1 e2 = table "ratio" [ tr [ td' "numerator" e1 ], tr [td e2] ]
+
+wideTuple :: [Html] -> Html
+wideTuple els = table "wideTuple" [ tr $ map td els ]
+
+tallTuple :: [Html] -> Html
+tallTuple els = table "tallTuple" $ map (tr . return . td) els
+
+tallRecord :: Name -> [Name] -> [Html] -> Html
+tallRecord con labs els = table "tallRecord" $ topHs : zipWith row labs els
+  where
+  topHs   = tr [ th "con" 2 (text con) ]
+  row l e = tr [ th "label" 1 (text l),   td e ]
+
+recordList :: Name -> [Name] -> [[Html]] -> Html
+recordList con labs els = table "recordList" $ topHs : zipWith row [0..] els
+  where
+  topHs    = tr $ th "con" 1 (text con) : map (th "label" 1 . text) labs
+  row n es = tr $ th "ix" 1 (int n) : map td es
+
+tupleList :: Int -> [[Html]] -> Html
+tupleList n els = recordList " " (replicate n " ") els
+
+tallList :: [Html] -> Html
+tallList els = table "tallList" $ top : zipWith row [0..] els
+  where
+  top     = tr [ th "con" 2 (text " ")]
+  row n e = tr [ th "ix" 1 (int n), td e ]
+
+wideList :: Int -> [Html] -> Html
+wideList w els = table "wideList" $ topHs : zipWith row [0..] (chop els)
+  where
+  elNum = length els
+  pad   = elNum > w
+
+  chop [] = []
+  chop xs = let (as,bs) = splitAt w xs
+            in take w (as ++ if pad then repeat empty else []) : chop bs
+
+  topHs     = tr $ th "con" 1 (text " ") : map (th "label" 1 . int)
+                                                [ 0 .. min elNum w - 1 ]
+  row n es  = tr $ (th "ix" 1 (int (n*w))) : map td es
+
+--------------------------------------------------------------------------------
+newtype Html = Html { exportHtml :: String }
+
+table :: String -> [Html] -> Html
+table cl body = Html $ "<table class=" ++ show cl ++ ">" ++
+                       concatMap exportHtml body ++
+                       "</table>"
+
+tr :: [Html] -> Html
+tr body = Html $ "<tr>" ++ concatMap exportHtml body ++ "</tr>"
+
+th :: String -> Int -> Html -> Html
+th cl n body = Html $ "<th class=" ++ show cl ++
+                         " colspan=" ++ show (show n) ++ ">" ++
+                      exportHtml body ++
+                      "</th>"
+
+td :: Html -> Html
+td body = Html $ "<td>" ++ exportHtml body ++ "</td>"
+
+td' :: String -> Html -> Html
+td' cl body = Html $ "<td class=" ++ show cl ++ ">" ++
+                     exportHtml body ++
+                     "</td>"
+
+span :: String -> Html -> Html
+span cl body = Html $ "<span class=" ++ show cl ++ ">" ++
+                      exportHtml body ++
+                      "</span>"
+
+empty :: Html
+empty = Html  ""
+
+int :: Int -> Html
+int = Html . show
+
+text :: String -> Html
+text = Html . concatMap esc
+  where
+  esc '<' = "&lt;"
+  esc '>' = "&gt;"
+  esc '&' = "&amp;"
+  esc ' ' = "&nbsp;"
+  esc c   = [c]
+
+-- | Wrap an Html fragment to make an Html page.
+htmlPage :: HtmlOpts -> Html -> String
+htmlPage opts body =
+  unlines
+  [ "<html>"
+  , "<head>"
+  , "<link href="  ++ show pstyle ++ " rel=" ++ show "stylesheet" ++ ">"
+  , "<script src=" ++ show jquery ++ "></script>"
+  , "<script src=" ++ show pjs    ++ "></script>"
+  , "<body>"
+  , exportHtml  body
+  , "</body>"
+  , "</html>"
+  ]
+  where
+  -- XXX: slashes on Windows?
+  dir    = case dataDir opts of
+             "" -> ""
+             d  -> d ++ "/"
+  jquery = dir ++ "style/jquery.js"
+  pjs    = dir ++ "style/pretty-show.js"
+  pstyle = dir ++ "style/pretty-show.css"
+
+
diff --git a/cabal/pretty-show-1.6.16/Text/Show/Parser.y b/cabal/pretty-show-1.6.16/Text/Show/Parser.y
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/Text/Show/Parser.y
@@ -0,0 +1,130 @@
+{
+-- We use these options because Happy generates code with a lot of warnings.
+{-# LANGUAGE Trustworthy #-}
+module Text.Show.Parser (parseValue) where
+
+import Text.Show.Value
+import Language.Haskell.Lexer
+}
+
+%token
+
+        '='             { (Reservedop, (_,"=")) }
+        '('             { (Special, (_,"(")) }
+        ')'             { (Special, (_,")")) }
+        '{'             { (Special, (_,"{")) }
+        '}'             { (Special, (_,"}")) }
+        '['             { (Special, (_,"[")) }
+        ']'             { (Special, (_,"]")) }
+        '<'             { (Varsym, (_,"<")) }
+        '>'             { (Varsym, (_,">")) }
+        ','             { (Special, (_,",")) }
+        '-'             { (Varsym,  (_,"-")) }
+        '%'             { (Varsym,  (_,"%")) }
+        '`'             { (Special, (_,"`")) }
+
+        INT             { (IntLit,   (_,$$)) }
+        FLOAT           { (FloatLit, (_,$$)) }
+        STRING          { (StringLit, (_,$$)) }
+        CHAR            { (CharLit,  (_,$$)) }
+
+        VARID           { (Varid,    (_,$$)) }
+        QVARID          { (Qvarid,   (_,$$)) }
+        VARSYM          { (Varsym,   (_,$$)) }
+        QVARSYM         { (Qvarsym,  (_,$$)) }
+        CONID           { (Conid,    (_,$$)) }
+        QCONID          { (Qconid,   (_,$$)) }
+        CONSYM          { (Consym,   (_,$$)) }
+        QCONSYM         { (Qconsym,  (_,$$)) }
+        RESOP           { (Reservedop, (_,$$)) }
+
+
+%monad { Maybe } { (>>=) } { return }
+%name parseValue value
+%tokentype { PosToken }
+
+
+%%
+
+value                        :: { Value }
+  : value '%' app_value         { Ratio $1 $3 }
+  | app_value                   { $1 }
+  | app_value list1(infixelem)  { InfixCons $1 $2 }
+
+infixelem                    :: { (String,Value) }
+  : infixcon app_value          { ($1,$2) }
+
+app_value                    :: { Value }
+  : list1(avalue)               { mkValue $1 }
+
+
+avalue                       :: { Value }
+  : '(' value ')'               { $2 }
+  | '[' sep(value,',') ']'      { List $2 }
+  | '(' tuple ')'               { Tuple $2 }
+  | con '{' sep(field,',') '}'  { Rec $1 $3 }
+  | con                         { Con $1 [] }
+  | INT                         { Integer $1 }
+  | FLOAT                       { Float $1 }
+  | STRING                      { String $1 }
+  | CHAR                        { Char $1 }
+  | '-' avalue                  { Neg $2 }
+
+con                          :: { String }
+  : CONID                       { $1 }
+  | QCONID                      { $1 }
+  | prefix(CONSYM)              { $1 }
+  | prefix(QCONSYM)             { $1 }
+  -- to support things like "fromList x"
+  | VARID                       { $1 }
+  | QVARID                      { $1 }
+  | prefix(VARSYM)              { $1 }
+  | prefix(QVARSYM)             { $1 }
+  | '<' VARID '>'               { "<" ++ $2 ++ ">" } -- note: looses space
+  | '<' CONID '>'               { "<" ++ $2 ++ ">" } -- ditto
+
+infixcon                     :: { String }
+  : CONSYM                      { $1 }
+  | QCONSYM                     { $1 }
+  | '`' CONID '`'               { backtick $2 }
+  | '`' QCONID '`'              { backtick $2 }
+  | RESOP                       { $1 }
+
+field                        :: { (Name,Value) }
+  : VARID '=' value             { ($1,$3) }
+
+tuple                        :: { [Value] }
+  :                             { [] }
+  | value ',' sep1(value,',')   { $1 : $3 }
+
+-- Common Rule Patterns --------------------------------------------------------
+prefix(p)       : '(' p ')'           { "(" ++ $2 ++ ")" }
+
+sep1(p,q)       : p list(snd(q,p))    { $1 : $2 }
+sep(p,q)        : sep1(p,q)           { $1 }
+                |                     { [] }
+
+snd(p,q)        : p q                 { $2 }
+
+list1(p)        : rev_list1(p)        { reverse $1 }
+list(p)         : list1(p)            { $1 }
+                |                     { [] }
+
+rev_list1(p)    : p                   { [$1] }
+                | rev_list1(p) p      { $2 : $1 }
+
+
+
+{
+backtick :: String -> String
+backtick s = "`" ++ s ++ "`"
+
+happyError :: [PosToken] -> Maybe a
+happyError ((_,(p,_)) : _) = Nothing -- error ("Parser error at: " ++ show p)
+happyError []              = Nothing -- error ("Parser error at EOF")
+
+mkValue :: [Value] -> Value
+mkValue [v]             = v
+mkValue (Con x [] : vs) = Con x vs
+mkValue vs              = Con "" vs
+}
diff --git a/cabal/pretty-show-1.6.16/Text/Show/Pretty.hs b/cabal/pretty-show-1.6.16/Text/Show/Pretty.hs
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/Text/Show/Pretty.hs
@@ -0,0 +1,186 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Text.Show.Pretty
+-- Copyright   :  (c) Iavor S. Diatchki 2009
+-- License     :  MIT
+--
+-- Maintainer  :  iavor.diatchki@gmail.com
+-- Stability   :  provisional
+-- Portability :  Haskell 98
+--
+-- Functions for human-readable derived 'Show' instances.
+--------------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE Safe #-}
+module Text.Show.Pretty
+  ( -- * Generic representation of values
+    Value(..), Name
+  , valToStr
+  , valToDoc
+  , valToHtmlPage
+
+    -- * Values using the 'Show' class
+  , parseValue, reify, ppDoc, ppShow, pPrint
+
+  , -- * Working with listlike ("foldable") collections
+    ppDocList, ppShowList, pPrintList
+
+    -- * Values using the 'PrettyVal' class
+  , dumpDoc, dumpStr, PrettyVal(..)
+
+    -- * Rendering values to Html
+  , valToHtml, HtmlOpts(..), defaultHtmlOpts, htmlPage, Html(..)
+
+    -- * Get location of data files
+  , getDataDir
+
+    -- * Deprecated
+  , ppValue
+  ) where
+
+import Text.PrettyPrint
+import qualified Text.Show.Parser as P
+import Text.Show.Value
+import Text.Show.PrettyVal
+import Text.Show.Html
+import Data.Foldable(Foldable,toList)
+import Language.Haskell.Lexer(rmSpace,lexerPass0)
+import Paths_pretty_show (getDataDir)
+
+#if MIN_VERSION_base(4,11,0)
+import Prelude hiding ( (<>) )
+#else
+import Prelude
+#endif
+
+{-# DEPRECATED ppValue "Please use `valToDoc` instead." #-}
+ppValue :: Value -> Doc
+ppValue = valToDoc
+
+reify :: Show a => a -> Maybe Value
+reify = parseValue . show
+
+parseValue :: String -> Maybe Value
+parseValue = P.parseValue . rmSpace . lexerPass0
+
+-- | Convert a generic value into a pretty 'String', if possible.
+ppShow :: Show a => a -> String
+ppShow = show . ppDoc
+
+-- | Pretty print something that may be converted to a list as a list.
+-- Each entry is on a separate line, which means that we don't do clever
+-- pretty printing, and so this works well for large strucutures.
+ppShowList :: (Foldable f, Show a) => f a -> String
+ppShowList = show . ppDocList
+
+-- | Try to show a value, prettily. If we do not understand the value, then we
+--   just use its standard 'Show' instance.
+ppDoc :: Show a => a -> Doc
+ppDoc a = case parseValue txt of
+            Just v  -> valToDoc v
+            Nothing -> text txt
+  where txt = show a
+
+-- | Pretty print something that may be converted to a list as a list.
+-- Each entry is on a separate line, which means that we don't do clever
+-- pretty printing, and so this works well for large strucutures.
+ppDocList :: (Foldable f, Show a) => f a -> Doc
+ppDocList = blockWith vcat '[' ']' . map ppDoc . toList
+
+-- | Pretty print a generic value to stdout. This is particularly useful in the
+-- GHCi interactive environment.
+pPrint :: Show a => a -> IO ()
+pPrint = putStrLn . ppShow
+
+-- | Pretty print something that may be converted to a list as a list.
+-- Each entry is on a separate line, which means that we don't do clever
+-- pretty printing, and so this works well for large strucutures.
+pPrintList :: (Foldable f, Show a) => f a -> IO ()
+pPrintList = putStrLn . ppShowList
+
+-- | Render a value in the 'PrettyVal' class to a 'Doc'.
+-- The benefit of this function is that 'PrettyVal' instances may
+-- be derived automatically using generics.
+dumpDoc :: PrettyVal a => a -> Doc
+dumpDoc = valToDoc . prettyVal
+
+-- | Render a value in the 'PrettyVal' class to a 'String'.
+-- The benefit of this function is that 'PrettyVal' instances may
+-- be derived automatically using generics.
+dumpStr :: PrettyVal a => a -> String
+dumpStr = show . dumpDoc
+
+
+-- | Pretty print a generic value. Our intention is that the result is
+--   equivalent to the 'Show' instance for the original value, except possibly
+--   easier to understand by a human.
+valToStr :: Value -> String
+valToStr = show . valToDoc
+
+-- | Pretty print a generic value. Our intention is that the result is
+--   equivalent to the 'Show' instance for the original value, except possibly
+--   easier to understand by a human.
+valToDoc :: Value -> Doc
+valToDoc val = case val of
+  Con c vs         -> ppCon c vs
+  InfixCons v1 cvs -> hang_sep (go v1 cvs)
+    where
+      go v []            = [ppInfixAtom v]
+      go v ((n,v2):cvs') = (ppInfixAtom v <+> text n):go v2 cvs'
+
+      hang_sep [] = empty
+      hang_sep (x:xs) = hang x 2 (sep xs)
+    -- hang (ppInfixAtom v1) 2 (sep [ text n <+> ppInfixAtom v | (n,v) <- cvs ])
+  Rec c fs         -> hang (text c) 2 $ block '{' '}' (map ppField fs)
+    where ppField (x,v) = hang (text x <+> char '=') 2 (valToDoc v)
+
+  List vs          -> block '[' ']' (map valToDoc vs)
+  Tuple vs         -> block '(' ')' (map valToDoc vs)
+  Neg v            -> char '-' <> ppAtom v
+  Ratio x y        -> hang (ppAtom x <+> text "%") 2 (ppAtom y)
+  Integer x        -> text x
+  Float x          -> text x
+  Char x           -> text x
+  String x         -> text x
+
+
+-- Private ---------------------------------------------------------------------
+
+ppAtom :: Value -> Doc
+ppAtom v
+  | isAtom v  = valToDoc v
+  | otherwise = parens (valToDoc v)
+
+ppInfixAtom :: Value -> Doc
+ppInfixAtom v
+  | isInfixAtom v = valToDoc v
+  | otherwise     = parens (valToDoc v)
+
+ppCon :: Name -> [Value] -> Doc
+ppCon "" vs = sep (map ppAtom vs)
+ppCon c vs  = hang (text c) 2 (sep (map ppAtom vs))
+
+isAtom               :: Value -> Bool
+isAtom (Con _ (_:_))  = False
+isAtom (InfixCons {}) = False
+isAtom (Ratio {})     = False
+isAtom (Neg {})       = False
+isAtom _              = True
+
+-- Don't put parenthesis around constructors in infix chains
+isInfixAtom          :: Value -> Bool
+isInfixAtom (InfixCons {}) = False
+isInfixAtom (Ratio {})     = False
+isInfixAtom (Neg {})       = False
+isInfixAtom _              = True
+
+block :: Char -> Char -> [Doc] -> Doc
+block = blockWith sep
+
+blockWith :: ([Doc] -> Doc) -> Char -> Char -> [Doc] -> Doc
+blockWith _ a b []      = char a <> char b
+blockWith f a b (d:ds)  = f $
+    (char a <+> d) : [ char ',' <+> x | x <- ds ] ++ [ char b ]
+
+
diff --git a/cabal/pretty-show-1.6.16/Text/Show/PrettyVal.hs b/cabal/pretty-show-1.6.16/Text/Show/PrettyVal.hs
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/Text/Show/PrettyVal.hs
@@ -0,0 +1,130 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE Safe #-}
+#ifndef NO_GENERICS
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}
+{-# LANGUAGE DefaultSignatures #-}
+#endif
+module Text.Show.PrettyVal ( PrettyVal(prettyVal) ) where
+
+import Text.Show.Value
+
+#ifndef NO_GENERICS
+import Data.Ratio
+import Data.Word
+import Data.Int
+import GHC.Generics
+#endif
+
+-- | A class for types that may be reified into a value.
+-- Instances of this class may be derived automatically,
+-- for datatypes that support `Generics`.
+class PrettyVal a where
+  prettyVal :: a -> Value
+  listValue :: [a] -> Value
+
+#ifndef NO_GENERICS
+
+  default prettyVal :: (GDump (Rep a), Generic a) => a -> Value
+  prettyVal = oneVal . gdump . from
+
+  default listValue :: [a] -> Value
+  listValue = List . map prettyVal
+
+
+class GDump f where
+  gdump :: f a -> [(Name,Value)]
+
+instance GDump U1 where
+  gdump U1 = []
+
+instance (GDump f, GDump g) => GDump (f :*: g) where
+  gdump (xs :*: ys) = gdump xs ++ gdump ys
+
+instance (GDump f, GDump g) => GDump (f :+: g) where
+  gdump (L1 x) = gdump x
+  gdump (R1 x) = gdump x
+
+instance PrettyVal a => GDump (K1 t a) where
+  gdump (K1 x) = [ ("", prettyVal x) ]
+
+instance (GDump f, Datatype d) => GDump (M1 D d f) where
+  gdump (M1 x) = gdump x
+
+instance (GDump f, Constructor c) => GDump (M1 C c f) where
+  gdump c@(M1 x)
+    | conIsRecord c = [ ("", Rec   name (gdump x)) ]
+    | isTuple name  = [ ("", Tuple (map snd (gdump x))) ]
+    | otherwise     = [ ("", Con   name (map snd (gdump x))) ]
+
+    where
+    name = conName c
+
+    isTuple ('(' : cs) = case span (== ',') cs of
+                           (_,")") -> True
+                           _ -> False
+    isTuple _          = False
+
+instance (GDump f, Selector s) => GDump (M1 S s f) where
+  gdump it@(M1 x) = repeat (selName it) `zip` map snd (gdump x)
+
+oneVal :: [(Name,Value)] -> Value
+oneVal x =
+  case x of
+    [ ("",v) ]               -> v
+    fs | all (null . fst) fs -> Con "?" (map snd fs)
+       | otherwise           -> Rec "?" fs
+
+
+mkNum :: (Ord a, Num a, Show a) => (String -> Value) -> a -> Value
+mkNum c x
+  | x >= 0    = c (show x)
+  | otherwise = Neg (c (show (negate x)))
+
+instance PrettyVal Int     where prettyVal   = mkNum Integer
+instance PrettyVal Integer where prettyVal   = mkNum Integer
+instance PrettyVal Float   where prettyVal x = Float (show x)
+instance PrettyVal Double  where prettyVal x = Float (show x)
+
+instance PrettyVal Word8   where prettyVal x = Integer (show x)
+instance PrettyVal Word16  where prettyVal x = Integer (show x)
+instance PrettyVal Word32  where prettyVal x = Integer (show x)
+instance PrettyVal Word64  where prettyVal x = Integer (show x)
+
+instance PrettyVal Int8    where prettyVal   = mkNum Integer
+instance PrettyVal Int16   where prettyVal   = mkNum Integer
+instance PrettyVal Int32   where prettyVal   = mkNum Integer
+instance PrettyVal Int64   where prettyVal   = mkNum Integer
+
+instance PrettyVal Char    where
+  prettyVal x    = Char (show x)
+  listValue xs = String xs
+
+instance PrettyVal a => PrettyVal [a] where
+  prettyVal xs   = listValue xs
+
+instance (PrettyVal a, Integral a) => PrettyVal (Ratio a) where
+  prettyVal r = Ratio (prettyVal (numerator r)) (prettyVal (denominator r))
+
+instance (PrettyVal a1, PrettyVal a2) => PrettyVal (a1,a2)
+instance (PrettyVal a1, PrettyVal a2, PrettyVal a3) => PrettyVal (a1,a2,a3)
+instance (PrettyVal a1, PrettyVal a2, PrettyVal a3,
+          PrettyVal a4) => PrettyVal (a1,a2,a3,a4)
+
+instance (PrettyVal a1, PrettyVal a2, PrettyVal a3,
+          PrettyVal a4, PrettyVal a5) => PrettyVal (a1,a2,a3,a4,a5)
+
+instance (PrettyVal a1, PrettyVal a2, PrettyVal a3,
+          PrettyVal a4, PrettyVal a5, PrettyVal a6) => PrettyVal (a1,a2,a3,a4,a5,a6)
+
+instance (PrettyVal a1, PrettyVal a2, PrettyVal a3,
+          PrettyVal a4, PrettyVal a5, PrettyVal a6, PrettyVal a7)
+  => PrettyVal (a1,a2,a3,a4,a5,a6,a7)
+
+instance PrettyVal Bool
+instance PrettyVal Ordering
+instance PrettyVal a => PrettyVal (Maybe a)
+instance (PrettyVal a, PrettyVal b) => PrettyVal (Either a b)
+
+#endif
+
diff --git a/cabal/pretty-show-1.6.16/Text/Show/Value.hs b/cabal/pretty-show-1.6.16/Text/Show/Value.hs
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/Text/Show/Value.hs
@@ -0,0 +1,41 @@
+--------------------------------------------------------------------------------
+-- |
+-- Module      :  Text.Show.Value
+-- Copyright   :  (c) Iavor S. Diatchki 2009
+-- License     :  MIT
+--
+-- Maintainer  :  iavor.diatchki@gmail.com
+-- Stability   :  provisional
+-- Portability :  Haskell 98
+--
+-- Generic representation of Showable values.
+--------------------------------------------------------------------------------
+
+{-# LANGUAGE Safe #-}
+module Text.Show.Value ( Name, Value(..) ) where
+
+-- | A name.
+type Name     = String
+
+-- | Generic Haskell values.
+-- 'NaN' and 'Infinity' are represented as constructors.
+-- The 'String' in the literals is the text for the literals \"as is\".
+--
+-- A chain of infix constructors means that they appeared in the input string
+-- without parentheses, i.e
+--
+-- @1 :+: 2 :*: 3@ is represented with @InfixCons 1 [(":+:",2),(":*:",3)]@, whereas
+--
+-- @1 :+: (2 :*: 3)@ is represented with @InfixCons 1 [(":+:",InfixCons 2 [(":*:",3)])]@.
+data Value    = Con Name [Value]               -- ^ Data constructor
+              | InfixCons Value [(Name,Value)] -- ^ Infix data constructor chain
+              | Rec Name [ (Name,Value) ]      -- ^ Record value
+              | Tuple [Value]                  -- ^ Tuple
+              | List [Value]                   -- ^ List
+              | Neg Value                      -- ^ Negated value
+              | Ratio Value Value              -- ^ Rational
+              | Integer String                 -- ^ Non-negative integer
+              | Float String                   -- ^ Non-negative floating num.
+              | Char String                    -- ^ Character
+              | String String                  -- ^ String
+                deriving (Eq,Show)
diff --git a/cabal/pretty-show-1.6.16/bin/ppsh.hs b/cabal/pretty-show-1.6.16/bin/ppsh.hs
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/bin/ppsh.hs
@@ -0,0 +1,44 @@
+import Text.Show.Pretty
+import System.Environment
+import System.IO(hPutStrLn,stderr)
+
+main :: IO ()
+main =
+  do as <- getArgs
+     case as of
+       ["--test"] -> interactLn (show . selftest1)
+
+       ["--html"] ->
+         do txt <- getContents
+            case parseValue txt of
+              Just v  ->
+                do dir <- getDataDir
+                   let opts = defaultHtmlOpts { dataDir = dir }
+                   putStrLn (valToHtmlPage opts v)
+              Nothing -> hPutStrLn stderr "Failed to parse value."
+
+       []         -> interactLn $ \s -> case parseValue s of
+                                          Just v  -> show (valToDoc v)
+                                          Nothing -> s
+       _ -> hPutStrLn stderr $ unlines
+              [ "usage: ppsh < showed_value > pretty_value"
+              , "   --html      Generate HTML."
+              , "   --test      Self test: True means we passed."
+              ]
+
+
+interactLn :: (String -> String) -> IO ()
+interactLn f = interact f >> putStrLn ""
+
+selftest :: Value -> Bool
+selftest v = case parseValue $ show $ valToDoc v of
+               Just v1  -> v1 == v
+               Nothing  -> False
+
+selftest1 :: String -> Bool
+selftest1 txt = case parseValue txt of
+                  Just v  -> selftest v
+                  Nothing -> True
+
+
+
diff --git a/cabal/pretty-show-1.6.16/pretty-show.cabal b/cabal/pretty-show-1.6.16/pretty-show.cabal
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/pretty-show.cabal
@@ -0,0 +1,73 @@
+name:           pretty-show
+version:        1.6.16
+category:       Text
+
+synopsis:       Tools for working with derived `Show` instances and generic
+                inspection of values.
+description:
+  We provide a library and an executable for working with derived 'Show'
+  instances. By using the library, we can parse derived 'Show' instances into a
+  generic data structure. The @ppsh@ tool uses the library to produce
+  human-readable versions of 'Show' instances, which can be quite handy for
+  debugging Haskell programs.  We can also render complex generic values into
+  an interactive Html page, for easier examination.
+
+license:        MIT
+license-file:   LICENSE
+author:         Iavor S. Diatchki
+maintainer:     iavor.diatchki@gmail.com
+
+homepage:       http://wiki.github.com/yav/pretty-show
+
+cabal-version:  >= 1.8
+build-type:     Simple
+
+tested-with:    GHC == 7.10.3
+                GHC == 8.0.2
+                GHC == 8.2.2
+
+data-files:
+  style/jquery.js
+  style/jquery-src.js
+  style/pretty-show.js
+  style/pretty-show.css
+
+extra-source-files:
+  CHANGELOG
+
+library
+  exposed-modules:
+    Text.Show.Pretty
+  other-modules:
+    Text.Show.Html
+    Text.Show.Parser
+    Text.Show.Value
+    Text.Show.PrettyVal
+    Paths_pretty_show
+  build-depends:
+    array          >= 0.2  &&  < 2,
+    base           >= 4.5  &&  < 5,
+    haskell-lexer  >= 1    &&  < 2,
+    pretty         >= 1    &&  < 2,
+    filepath,
+    ghc-prim
+  ghc-options: -Wall -O2
+  if impl(ghc < 7.4)
+    cpp-options: -DNO_GENERICS
+  build-tools: happy
+
+executable ppsh
+  main-is: ppsh.hs
+  other-modules: Paths_pretty_show
+
+  hs-source-dirs: bin
+  build-depends:
+    base          >= 4.5  &&  < 5,
+    pretty-show
+  ghc-options: -Wall
+
+source-repository head
+  type:     git
+  location: https://github.com/yav/pretty-show.git
+
+
diff --git a/cabal/pretty-show-1.6.16/style/jquery-src.js b/cabal/pretty-show-1.6.16/style/jquery-src.js
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/style/jquery-src.js
@@ -0,0 +1,10337 @@
+/*!
+ * jQuery JavaScript Library v1.11.0
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-01-23T21:02Z
+ */
+
+(function( global, factory ) {
+
+	if ( typeof module === "object" && typeof module.exports === "object" ) {
+		// For CommonJS and CommonJS-like environments where a proper window is present,
+		// execute the factory and get jQuery
+		// For environments that do not inherently posses a window with a document
+		// (such as Node.js), expose a jQuery-making factory as module.exports
+		// This accentuates the need for the creation of a real window
+		// e.g. var jQuery = require("jquery")(window);
+		// See ticket #14549 for more info
+		module.exports = global.document ?
+			factory( global, true ) :
+			function( w ) {
+				if ( !w.document ) {
+					throw new Error( "jQuery requires a window with a document" );
+				}
+				return factory( w );
+			};
+	} else {
+		factory( global );
+	}
+
+// Pass this if window is not defined yet
+}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Can't do this because several apps including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+// Support: Firefox 18+
+//
+
+var deletedIds = [];
+
+var slice = deletedIds.slice;
+
+var concat = deletedIds.concat;
+
+var push = deletedIds.push;
+
+var indexOf = deletedIds.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var trim = "".trim;
+
+var support = {};
+
+
+
+var
+	version = "1.11.0",
+
+	// Define a local copy of jQuery
+	jQuery = function( selector, context ) {
+		// The jQuery object is actually just the init constructor 'enhanced'
+		// Need init if jQuery is called (just allow error to be thrown if not included)
+		return new jQuery.fn.init( selector, context );
+	},
+
+	// Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
+	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+	// Matches dashed string for camelizing
+	rmsPrefix = /^-ms-/,
+	rdashAlpha = /-([\da-z])/gi,
+
+	// Used by jQuery.camelCase as callback to replace()
+	fcamelCase = function( all, letter ) {
+		return letter.toUpperCase();
+	};
+
+jQuery.fn = jQuery.prototype = {
+	// The current version of jQuery being used
+	jquery: version,
+
+	constructor: jQuery,
+
+	// Start with an empty selector
+	selector: "",
+
+	// The default length of a jQuery object is 0
+	length: 0,
+
+	toArray: function() {
+		return slice.call( this );
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num != null ?
+
+			// Return a 'clean' array
+			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
+
+			// Return just the object
+			slice.call( this );
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems ) {
+
+		// Build a new jQuery matched element set
+		var ret = jQuery.merge( this.constructor(), elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+		ret.context = this.context;
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function( elem, i ) {
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	slice: function() {
+		return this.pushStack( slice.apply( this, arguments ) );
+	},
+
+	first: function() {
+		return this.eq( 0 );
+	},
+
+	last: function() {
+		return this.eq( -1 );
+	},
+
+	eq: function( i ) {
+		var len = this.length,
+			j = +i + ( i < 0 ? len : 0 );
+		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
+	},
+
+	end: function() {
+		return this.prevObject || this.constructor(null);
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: push,
+	sort: deletedIds.sort,
+	splice: deletedIds.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+	var src, copyIsArray, copy, name, options, clone,
+		target = arguments[0] || {},
+		i = 1,
+		length = arguments.length,
+		deep = false;
+
+	// Handle a deep copy situation
+	if ( typeof target === "boolean" ) {
+		deep = target;
+
+		// skip the boolean and the target
+		target = arguments[ i ] || {};
+		i++;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+		target = {};
+	}
+
+	// extend jQuery itself if only one argument is passed
+	if ( i === length ) {
+		target = this;
+		i--;
+	}
+
+	for ( ; i < length; i++ ) {
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null ) {
+			// Extend the base object
+			for ( name in options ) {
+				src = target[ name ];
+				copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy ) {
+					continue;
+				}
+
+				// Recurse if we're merging plain objects or arrays
+				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+					if ( copyIsArray ) {
+						copyIsArray = false;
+						clone = src && jQuery.isArray(src) ? src : [];
+
+					} else {
+						clone = src && jQuery.isPlainObject(src) ? src : {};
+					}
+
+					// Never move original objects, clone them
+					target[ name ] = jQuery.extend( deep, clone, copy );
+
+				// Don't bring in undefined values
+				} else if ( copy !== undefined ) {
+					target[ name ] = copy;
+				}
+			}
+		}
+	}
+
+	// Return the modified object
+	return target;
+};
+
+jQuery.extend({
+	// Unique for each copy of jQuery on the page
+	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+	// Assume jQuery is ready without the ready module
+	isReady: true,
+
+	error: function( msg ) {
+		throw new Error( msg );
+	},
+
+	noop: function() {},
+
+	// See test/unit/core.js for details concerning isFunction.
+	// Since version 1.3, DOM methods and functions like alert
+	// aren't supported. They return false on IE (#2968).
+	isFunction: function( obj ) {
+		return jQuery.type(obj) === "function";
+	},
+
+	isArray: Array.isArray || function( obj ) {
+		return jQuery.type(obj) === "array";
+	},
+
+	isWindow: function( obj ) {
+		/* jshint eqeqeq: false */
+		return obj != null && obj == obj.window;
+	},
+
+	isNumeric: function( obj ) {
+		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
+		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+		// subtraction forces infinities to NaN
+		return obj - parseFloat( obj ) >= 0;
+	},
+
+	isEmptyObject: function( obj ) {
+		var name;
+		for ( name in obj ) {
+			return false;
+		}
+		return true;
+	},
+
+	isPlainObject: function( obj ) {
+		var key;
+
+		// Must be an Object.
+		// Because of IE, we also have to check the presence of the constructor property.
+		// Make sure that DOM nodes and window objects don't pass through, as well
+		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+			return false;
+		}
+
+		try {
+			// Not own constructor property must be Object
+			if ( obj.constructor &&
+				!hasOwn.call(obj, "constructor") &&
+				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+				return false;
+			}
+		} catch ( e ) {
+			// IE8,9 Will throw exceptions on certain host objects #9897
+			return false;
+		}
+
+		// Support: IE<9
+		// Handle iteration over inherited properties before own properties.
+		if ( support.ownLast ) {
+			for ( key in obj ) {
+				return hasOwn.call( obj, key );
+			}
+		}
+
+		// Own properties are enumerated firstly, so to speed up,
+		// if last one is own, then all properties are own.
+		for ( key in obj ) {}
+
+		return key === undefined || hasOwn.call( obj, key );
+	},
+
+	type: function( obj ) {
+		if ( obj == null ) {
+			return obj + "";
+		}
+		return typeof obj === "object" || typeof obj === "function" ?
+			class2type[ toString.call(obj) ] || "object" :
+			typeof obj;
+	},
+
+	// Evaluates a script in a global context
+	// Workarounds based on findings by Jim Driscoll
+	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+	globalEval: function( data ) {
+		if ( data && jQuery.trim( data ) ) {
+			// We use execScript on Internet Explorer
+			// We use an anonymous function so that context is window
+			// rather than jQuery in Firefox
+			( window.execScript || function( data ) {
+				window[ "eval" ].call( window, data );
+			} )( data );
+		}
+	},
+
+	// Convert dashed to camelCase; used by the css and data modules
+	// Microsoft forgot to hump their vendor prefix (#9572)
+	camelCase: function( string ) {
+		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+	},
+
+	// args is for internal usage only
+	each: function( obj, callback, args ) {
+		var value,
+			i = 0,
+			length = obj.length,
+			isArray = isArraylike( obj );
+
+		if ( args ) {
+			if ( isArray ) {
+				for ( ; i < length; i++ ) {
+					value = callback.apply( obj[ i ], args );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( i in obj ) {
+					value = callback.apply( obj[ i ], args );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			}
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( isArray ) {
+				for ( ; i < length; i++ ) {
+					value = callback.call( obj[ i ], i, obj[ i ] );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( i in obj ) {
+					value = callback.call( obj[ i ], i, obj[ i ] );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			}
+		}
+
+		return obj;
+	},
+
+	// Use native String.trim function wherever possible
+	trim: trim && !trim.call("\uFEFF\xA0") ?
+		function( text ) {
+			return text == null ?
+				"" :
+				trim.call( text );
+		} :
+
+		// Otherwise use our own trimming functionality
+		function( text ) {
+			return text == null ?
+				"" :
+				( text + "" ).replace( rtrim, "" );
+		},
+
+	// results is for internal usage only
+	makeArray: function( arr, results ) {
+		var ret = results || [];
+
+		if ( arr != null ) {
+			if ( isArraylike( Object(arr) ) ) {
+				jQuery.merge( ret,
+					typeof arr === "string" ?
+					[ arr ] : arr
+				);
+			} else {
+				push.call( ret, arr );
+			}
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, arr, i ) {
+		var len;
+
+		if ( arr ) {
+			if ( indexOf ) {
+				return indexOf.call( arr, elem, i );
+			}
+
+			len = arr.length;
+			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+			for ( ; i < len; i++ ) {
+				// Skip accessing in sparse arrays
+				if ( i in arr && arr[ i ] === elem ) {
+					return i;
+				}
+			}
+		}
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		var len = +second.length,
+			j = 0,
+			i = first.length;
+
+		while ( j < len ) {
+			first[ i++ ] = second[ j++ ];
+		}
+
+		// Support: IE<9
+		// Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
+		if ( len !== len ) {
+			while ( second[j] !== undefined ) {
+				first[ i++ ] = second[ j++ ];
+			}
+		}
+
+		first.length = i;
+
+		return first;
+	},
+
+	grep: function( elems, callback, invert ) {
+		var callbackInverse,
+			matches = [],
+			i = 0,
+			length = elems.length,
+			callbackExpect = !invert;
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( ; i < length; i++ ) {
+			callbackInverse = !callback( elems[ i ], i );
+			if ( callbackInverse !== callbackExpect ) {
+				matches.push( elems[ i ] );
+			}
+		}
+
+		return matches;
+	},
+
+	// arg is for internal usage only
+	map: function( elems, callback, arg ) {
+		var value,
+			i = 0,
+			length = elems.length,
+			isArray = isArraylike( elems ),
+			ret = [];
+
+		// Go through the array, translating each of the items to their new values
+		if ( isArray ) {
+			for ( ; i < length; i++ ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret.push( value );
+				}
+			}
+
+		// Go through every key on the object,
+		} else {
+			for ( i in elems ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret.push( value );
+				}
+			}
+		}
+
+		// Flatten any nested arrays
+		return concat.apply( [], ret );
+	},
+
+	// A global GUID counter for objects
+	guid: 1,
+
+	// Bind a function to a context, optionally partially applying any
+	// arguments.
+	proxy: function( fn, context ) {
+		var args, proxy, tmp;
+
+		if ( typeof context === "string" ) {
+			tmp = fn[ context ];
+			context = fn;
+			fn = tmp;
+		}
+
+		// Quick check to determine if target is callable, in the spec
+		// this throws a TypeError, but we will just return undefined.
+		if ( !jQuery.isFunction( fn ) ) {
+			return undefined;
+		}
+
+		// Simulated bind
+		args = slice.call( arguments, 2 );
+		proxy = function() {
+			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+		};
+
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+		return proxy;
+	},
+
+	now: function() {
+		return +( new Date() );
+	},
+
+	// jQuery.support is not used in Core but other projects attach their
+	// properties to it so it needs to exist.
+	support: support
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+	class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+function isArraylike( obj ) {
+	var length = obj.length,
+		type = jQuery.type( obj );
+
+	if ( type === "function" || jQuery.isWindow( obj ) ) {
+		return false;
+	}
+
+	if ( obj.nodeType === 1 && length ) {
+		return true;
+	}
+
+	return type === "array" || length === 0 ||
+		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v1.10.16
+ * http://sizzlejs.com/
+ *
+ * Copyright 2013 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-01-13
+ */
+(function( window ) {
+
+var i,
+	support,
+	Expr,
+	getText,
+	isXML,
+	compile,
+	outermostContext,
+	sortInput,
+	hasDuplicate,
+
+	// Local document vars
+	setDocument,
+	document,
+	docElem,
+	documentIsHTML,
+	rbuggyQSA,
+	rbuggyMatches,
+	matches,
+	contains,
+
+	// Instance-specific data
+	expando = "sizzle" + -(new Date()),
+	preferredDoc = window.document,
+	dirruns = 0,
+	done = 0,
+	classCache = createCache(),
+	tokenCache = createCache(),
+	compilerCache = createCache(),
+	sortOrder = function( a, b ) {
+		if ( a === b ) {
+			hasDuplicate = true;
+		}
+		return 0;
+	},
+
+	// General-purpose constants
+	strundefined = typeof undefined,
+	MAX_NEGATIVE = 1 << 31,
+
+	// Instance methods
+	hasOwn = ({}).hasOwnProperty,
+	arr = [],
+	pop = arr.pop,
+	push_native = arr.push,
+	push = arr.push,
+	slice = arr.slice,
+	// Use a stripped-down indexOf if we can't use a native one
+	indexOf = arr.indexOf || function( elem ) {
+		var i = 0,
+			len = this.length;
+		for ( ; i < len; i++ ) {
+			if ( this[i] === elem ) {
+				return i;
+			}
+		}
+		return -1;
+	},
+
+	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+	// Regular expressions
+
+	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+	whitespace = "[\\x20\\t\\r\\n\\f]",
+	// http://www.w3.org/TR/css3-syntax/#characters
+	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+	// Loosely modeled on CSS identifier characters
+	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+	identifier = characterEncoding.replace( "w", "w#" ),
+
+	// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
+	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
+		"*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
+
+	// Prefer arguments quoted,
+	//   then not containing pseudos/brackets,
+	//   then attribute selectors/non-parenthetical expressions,
+	//   then anything else
+	// These preferences are here to reduce the number of selectors
+	//   needing tokenize in the PSEUDO preFilter
+	pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
+
+	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+	rpseudo = new RegExp( pseudos ),
+	ridentifier = new RegExp( "^" + identifier + "$" ),
+
+	matchExpr = {
+		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
+		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+		"ATTR": new RegExp( "^" + attributes ),
+		"PSEUDO": new RegExp( "^" + pseudos ),
+		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+		// For use in libraries implementing .is()
+		// We use this for POS matching in `select`
+		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+	},
+
+	rinputs = /^(?:input|select|textarea|button)$/i,
+	rheader = /^h\d$/i,
+
+	rnative = /^[^{]+\{\s*\[native \w/,
+
+	// Easily-parseable/retrievable ID or TAG or CLASS selectors
+	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+	rsibling = /[+~]/,
+	rescape = /'|\\/g,
+
+	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+	funescape = function( _, escaped, escapedWhitespace ) {
+		var high = "0x" + escaped - 0x10000;
+		// NaN means non-codepoint
+		// Support: Firefox
+		// Workaround erroneous numeric interpretation of +"0x"
+		return high !== high || escapedWhitespace ?
+			escaped :
+			high < 0 ?
+				// BMP codepoint
+				String.fromCharCode( high + 0x10000 ) :
+				// Supplemental Plane codepoint (surrogate pair)
+				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+	};
+
+// Optimize for push.apply( _, NodeList )
+try {
+	push.apply(
+		(arr = slice.call( preferredDoc.childNodes )),
+		preferredDoc.childNodes
+	);
+	// Support: Android<4.0
+	// Detect silently failing push.apply
+	arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+	push = { apply: arr.length ?
+
+		// Leverage slice if possible
+		function( target, els ) {
+			push_native.apply( target, slice.call(els) );
+		} :
+
+		// Support: IE<9
+		// Otherwise append directly
+		function( target, els ) {
+			var j = target.length,
+				i = 0;
+			// Can't trust NodeList.length
+			while ( (target[j++] = els[i++]) ) {}
+			target.length = j - 1;
+		}
+	};
+}
+
+function Sizzle( selector, context, results, seed ) {
+	var match, elem, m, nodeType,
+		// QSA vars
+		i, groups, old, nid, newContext, newSelector;
+
+	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+		setDocument( context );
+	}
+
+	context = context || document;
+	results = results || [];
+
+	if ( !selector || typeof selector !== "string" ) {
+		return results;
+	}
+
+	if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
+		return [];
+	}
+
+	if ( documentIsHTML && !seed ) {
+
+		// Shortcuts
+		if ( (match = rquickExpr.exec( selector )) ) {
+			// Speed-up: Sizzle("#ID")
+			if ( (m = match[1]) ) {
+				if ( nodeType === 9 ) {
+					elem = context.getElementById( m );
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document (jQuery #6963)
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE, Opera, and Webkit return items
+						// by name instead of ID
+						if ( elem.id === m ) {
+							results.push( elem );
+							return results;
+						}
+					} else {
+						return results;
+					}
+				} else {
+					// Context is not a document
+					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+						contains( context, elem ) && elem.id === m ) {
+						results.push( elem );
+						return results;
+					}
+				}
+
+			// Speed-up: Sizzle("TAG")
+			} else if ( match[2] ) {
+				push.apply( results, context.getElementsByTagName( selector ) );
+				return results;
+
+			// Speed-up: Sizzle(".CLASS")
+			} else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
+				push.apply( results, context.getElementsByClassName( m ) );
+				return results;
+			}
+		}
+
+		// QSA path
+		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+			nid = old = expando;
+			newContext = context;
+			newSelector = nodeType === 9 && selector;
+
+			// qSA works strangely on Element-rooted queries
+			// We can work around this by specifying an extra ID on the root
+			// and working up from there (Thanks to Andrew Dupont for the technique)
+			// IE 8 doesn't work on object elements
+			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+				groups = tokenize( selector );
+
+				if ( (old = context.getAttribute("id")) ) {
+					nid = old.replace( rescape, "\\$&" );
+				} else {
+					context.setAttribute( "id", nid );
+				}
+				nid = "[id='" + nid + "'] ";
+
+				i = groups.length;
+				while ( i-- ) {
+					groups[i] = nid + toSelector( groups[i] );
+				}
+				newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
+				newSelector = groups.join(",");
+			}
+
+			if ( newSelector ) {
+				try {
+					push.apply( results,
+						newContext.querySelectorAll( newSelector )
+					);
+					return results;
+				} catch(qsaError) {
+				} finally {
+					if ( !old ) {
+						context.removeAttribute("id");
+					}
+				}
+			}
+		}
+	}
+
+	// All others
+	return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ *	deleting the oldest entry
+ */
+function createCache() {
+	var keys = [];
+
+	function cache( key, value ) {
+		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+		if ( keys.push( key + " " ) > Expr.cacheLength ) {
+			// Only keep the most recent entries
+			delete cache[ keys.shift() ];
+		}
+		return (cache[ key + " " ] = value);
+	}
+	return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+	fn[ expando ] = true;
+	return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+	var div = document.createElement("div");
+
+	try {
+		return !!fn( div );
+	} catch (e) {
+		return false;
+	} finally {
+		// Remove from its parent by default
+		if ( div.parentNode ) {
+			div.parentNode.removeChild( div );
+		}
+		// release memory in IE
+		div = null;
+	}
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+	var arr = attrs.split("|"),
+		i = attrs.length;
+
+	while ( i-- ) {
+		Expr.attrHandle[ arr[i] ] = handler;
+	}
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+	var cur = b && a,
+		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+			( ~b.sourceIndex || MAX_NEGATIVE ) -
+			( ~a.sourceIndex || MAX_NEGATIVE );
+
+	// Use IE sourceIndex if available on both nodes
+	if ( diff ) {
+		return diff;
+	}
+
+	// Check if b follows a
+	if ( cur ) {
+		while ( (cur = cur.nextSibling) ) {
+			if ( cur === b ) {
+				return -1;
+			}
+		}
+	}
+
+	return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return name === "input" && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return (name === "input" || name === "button") && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+	return markFunction(function( argument ) {
+		argument = +argument;
+		return markFunction(function( seed, matches ) {
+			var j,
+				matchIndexes = fn( [], seed.length, argument ),
+				i = matchIndexes.length;
+
+			// Match elements found at the specified indexes
+			while ( i-- ) {
+				if ( seed[ (j = matchIndexes[i]) ] ) {
+					seed[j] = !(matches[j] = seed[j]);
+				}
+			}
+		});
+	});
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+	return context && typeof context.getElementsByTagName !== strundefined && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+	// documentElement is verified for cases where it doesn't yet exist
+	// (such as loading iframes in IE - #4833)
+	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+	return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+	var hasCompare,
+		doc = node ? node.ownerDocument || node : preferredDoc,
+		parent = doc.defaultView;
+
+	// If no document and documentElement is available, return
+	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+		return document;
+	}
+
+	// Set our document
+	document = doc;
+	docElem = doc.documentElement;
+
+	// Support tests
+	documentIsHTML = !isXML( doc );
+
+	// Support: IE>8
+	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
+	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
+	// IE6-8 do not support the defaultView property so parent will be undefined
+	if ( parent && parent !== parent.top ) {
+		// IE11 does not have attachEvent, so all must suffer
+		if ( parent.addEventListener ) {
+			parent.addEventListener( "unload", function() {
+				setDocument();
+			}, false );
+		} else if ( parent.attachEvent ) {
+			parent.attachEvent( "onunload", function() {
+				setDocument();
+			});
+		}
+	}
+
+	/* Attributes
+	---------------------------------------------------------------------- */
+
+	// Support: IE<8
+	// Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
+	support.attributes = assert(function( div ) {
+		div.className = "i";
+		return !div.getAttribute("className");
+	});
+
+	/* getElement(s)By*
+	---------------------------------------------------------------------- */
+
+	// Check if getElementsByTagName("*") returns only elements
+	support.getElementsByTagName = assert(function( div ) {
+		div.appendChild( doc.createComment("") );
+		return !div.getElementsByTagName("*").length;
+	});
+
+	// Check if getElementsByClassName can be trusted
+	support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
+		div.innerHTML = "<div class='a'></div><div class='a i'></div>";
+
+		// Support: Safari<4
+		// Catch class over-caching
+		div.firstChild.className = "i";
+		// Support: Opera<10
+		// Catch gEBCN failure to find non-leading classes
+		return div.getElementsByClassName("i").length === 2;
+	});
+
+	// Support: IE<10
+	// Check if getElementById returns elements by name
+	// The broken getElementById methods don't pick up programatically-set names,
+	// so use a roundabout getElementsByName test
+	support.getById = assert(function( div ) {
+		docElem.appendChild( div ).id = expando;
+		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
+	});
+
+	// ID find and filter
+	if ( support.getById ) {
+		Expr.find["ID"] = function( id, context ) {
+			if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
+				var m = context.getElementById( id );
+				// Check parentNode to catch when Blackberry 4.6 returns
+				// nodes that are no longer in the document #6963
+				return m && m.parentNode ? [m] : [];
+			}
+		};
+		Expr.filter["ID"] = function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				return elem.getAttribute("id") === attrId;
+			};
+		};
+	} else {
+		// Support: IE6/7
+		// getElementById is not reliable as a find shortcut
+		delete Expr.find["ID"];
+
+		Expr.filter["ID"] =  function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+				return node && node.value === attrId;
+			};
+		};
+	}
+
+	// Tag
+	Expr.find["TAG"] = support.getElementsByTagName ?
+		function( tag, context ) {
+			if ( typeof context.getElementsByTagName !== strundefined ) {
+				return context.getElementsByTagName( tag );
+			}
+		} :
+		function( tag, context ) {
+			var elem,
+				tmp = [],
+				i = 0,
+				results = context.getElementsByTagName( tag );
+
+			// Filter out possible comments
+			if ( tag === "*" ) {
+				while ( (elem = results[i++]) ) {
+					if ( elem.nodeType === 1 ) {
+						tmp.push( elem );
+					}
+				}
+
+				return tmp;
+			}
+			return results;
+		};
+
+	// Class
+	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+		if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
+			return context.getElementsByClassName( className );
+		}
+	};
+
+	/* QSA/matchesSelector
+	---------------------------------------------------------------------- */
+
+	// QSA and matchesSelector support
+
+	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+	rbuggyMatches = [];
+
+	// qSa(:focus) reports false when true (Chrome 21)
+	// We allow this because of a bug in IE8/9 that throws an error
+	// whenever `document.activeElement` is accessed on an iframe
+	// So, we allow :focus to pass through QSA all the time to avoid the IE error
+	// See http://bugs.jquery.com/ticket/13378
+	rbuggyQSA = [];
+
+	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
+		// Build QSA regex
+		// Regex strategy adopted from Diego Perini
+		assert(function( div ) {
+			// Select is set to empty string on purpose
+			// This is to test IE's treatment of not explicitly
+			// setting a boolean content attribute,
+			// since its presence should be enough
+			// http://bugs.jquery.com/ticket/12359
+			div.innerHTML = "<select t=''><option selected=''></option></select>";
+
+			// Support: IE8, Opera 10-12
+			// Nothing should be selected when empty strings follow ^= or $= or *=
+			if ( div.querySelectorAll("[t^='']").length ) {
+				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+			}
+
+			// Support: IE8
+			// Boolean attributes and "value" are not treated correctly
+			if ( !div.querySelectorAll("[selected]").length ) {
+				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+			}
+
+			// Webkit/Opera - :checked should return selected option elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			// IE8 throws error here and will not see later tests
+			if ( !div.querySelectorAll(":checked").length ) {
+				rbuggyQSA.push(":checked");
+			}
+		});
+
+		assert(function( div ) {
+			// Support: Windows 8 Native Apps
+			// The type and name attributes are restricted during .innerHTML assignment
+			var input = doc.createElement("input");
+			input.setAttribute( "type", "hidden" );
+			div.appendChild( input ).setAttribute( "name", "D" );
+
+			// Support: IE8
+			// Enforce case-sensitivity of name attribute
+			if ( div.querySelectorAll("[name=d]").length ) {
+				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+			}
+
+			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+			// IE8 throws error here and will not see later tests
+			if ( !div.querySelectorAll(":enabled").length ) {
+				rbuggyQSA.push( ":enabled", ":disabled" );
+			}
+
+			// Opera 10-11 does not throw on post-comma invalid pseudos
+			div.querySelectorAll("*,:x");
+			rbuggyQSA.push(",.*:");
+		});
+	}
+
+	if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||
+		docElem.mozMatchesSelector ||
+		docElem.oMatchesSelector ||
+		docElem.msMatchesSelector) )) ) {
+
+		assert(function( div ) {
+			// Check to see if it's possible to do matchesSelector
+			// on a disconnected node (IE 9)
+			support.disconnectedMatch = matches.call( div, "div" );
+
+			// This should fail with an exception
+			// Gecko does not error, returns false instead
+			matches.call( div, "[s!='']:x" );
+			rbuggyMatches.push( "!=", pseudos );
+		});
+	}
+
+	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+	/* Contains
+	---------------------------------------------------------------------- */
+	hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+	// Element contains another
+	// Purposefully does not implement inclusive descendent
+	// As in, an element does not contain itself
+	contains = hasCompare || rnative.test( docElem.contains ) ?
+		function( a, b ) {
+			var adown = a.nodeType === 9 ? a.documentElement : a,
+				bup = b && b.parentNode;
+			return a === bup || !!( bup && bup.nodeType === 1 && (
+				adown.contains ?
+					adown.contains( bup ) :
+					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+			));
+		} :
+		function( a, b ) {
+			if ( b ) {
+				while ( (b = b.parentNode) ) {
+					if ( b === a ) {
+						return true;
+					}
+				}
+			}
+			return false;
+		};
+
+	/* Sorting
+	---------------------------------------------------------------------- */
+
+	// Document order sorting
+	sortOrder = hasCompare ?
+	function( a, b ) {
+
+		// Flag for duplicate removal
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		// Sort on method existence if only one input has compareDocumentPosition
+		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+		if ( compare ) {
+			return compare;
+		}
+
+		// Calculate position if both inputs belong to the same document
+		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+			a.compareDocumentPosition( b ) :
+
+			// Otherwise we know they are disconnected
+			1;
+
+		// Disconnected nodes
+		if ( compare & 1 ||
+			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+			// Choose the first element that is related to our preferred document
+			if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+				return -1;
+			}
+			if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+				return 1;
+			}
+
+			// Maintain original order
+			return sortInput ?
+				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
+				0;
+		}
+
+		return compare & 4 ? -1 : 1;
+	} :
+	function( a, b ) {
+		// Exit early if the nodes are identical
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		var cur,
+			i = 0,
+			aup = a.parentNode,
+			bup = b.parentNode,
+			ap = [ a ],
+			bp = [ b ];
+
+		// Parentless nodes are either documents or disconnected
+		if ( !aup || !bup ) {
+			return a === doc ? -1 :
+				b === doc ? 1 :
+				aup ? -1 :
+				bup ? 1 :
+				sortInput ?
+				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
+				0;
+
+		// If the nodes are siblings, we can do a quick check
+		} else if ( aup === bup ) {
+			return siblingCheck( a, b );
+		}
+
+		// Otherwise we need full lists of their ancestors for comparison
+		cur = a;
+		while ( (cur = cur.parentNode) ) {
+			ap.unshift( cur );
+		}
+		cur = b;
+		while ( (cur = cur.parentNode) ) {
+			bp.unshift( cur );
+		}
+
+		// Walk down the tree looking for a discrepancy
+		while ( ap[i] === bp[i] ) {
+			i++;
+		}
+
+		return i ?
+			// Do a sibling check if the nodes have a common ancestor
+			siblingCheck( ap[i], bp[i] ) :
+
+			// Otherwise nodes in our document sort first
+			ap[i] === preferredDoc ? -1 :
+			bp[i] === preferredDoc ? 1 :
+			0;
+	};
+
+	return doc;
+};
+
+Sizzle.matches = function( expr, elements ) {
+	return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	// Make sure that attribute selectors are quoted
+	expr = expr.replace( rattributeQuotes, "='$1']" );
+
+	if ( support.matchesSelector && documentIsHTML &&
+		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
+
+		try {
+			var ret = matches.call( elem, expr );
+
+			// IE 9's matchesSelector returns false on disconnected nodes
+			if ( ret || support.disconnectedMatch ||
+					// As well, disconnected nodes are said to be in a document
+					// fragment in IE 9
+					elem.document && elem.document.nodeType !== 11 ) {
+				return ret;
+			}
+		} catch(e) {}
+	}
+
+	return Sizzle( expr, document, null, [elem] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+	// Set document vars if needed
+	if ( ( context.ownerDocument || context ) !== document ) {
+		setDocument( context );
+	}
+	return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	var fn = Expr.attrHandle[ name.toLowerCase() ],
+		// Don't get fooled by Object.prototype properties (jQuery #13807)
+		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+			fn( elem, name, !documentIsHTML ) :
+			undefined;
+
+	return val !== undefined ?
+		val :
+		support.attributes || !documentIsHTML ?
+			elem.getAttribute( name ) :
+			(val = elem.getAttributeNode(name)) && val.specified ?
+				val.value :
+				null;
+};
+
+Sizzle.error = function( msg ) {
+	throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+	var elem,
+		duplicates = [],
+		j = 0,
+		i = 0;
+
+	// Unless we *know* we can detect duplicates, assume their presence
+	hasDuplicate = !support.detectDuplicates;
+	sortInput = !support.sortStable && results.slice( 0 );
+	results.sort( sortOrder );
+
+	if ( hasDuplicate ) {
+		while ( (elem = results[i++]) ) {
+			if ( elem === results[ i ] ) {
+				j = duplicates.push( i );
+			}
+		}
+		while ( j-- ) {
+			results.splice( duplicates[ j ], 1 );
+		}
+	}
+
+	// Clear input after sorting to release objects
+	// See https://github.com/jquery/sizzle/pull/225
+	sortInput = null;
+
+	return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+	var node,
+		ret = "",
+		i = 0,
+		nodeType = elem.nodeType;
+
+	if ( !nodeType ) {
+		// If no nodeType, this is expected to be an array
+		while ( (node = elem[i++]) ) {
+			// Do not traverse comment nodes
+			ret += getText( node );
+		}
+	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+		// Use textContent for elements
+		// innerText usage removed for consistency of new lines (jQuery #11153)
+		if ( typeof elem.textContent === "string" ) {
+			return elem.textContent;
+		} else {
+			// Traverse its children
+			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+				ret += getText( elem );
+			}
+		}
+	} else if ( nodeType === 3 || nodeType === 4 ) {
+		return elem.nodeValue;
+	}
+	// Do not include comment or processing instruction nodes
+
+	return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+	// Can be adjusted by the user
+	cacheLength: 50,
+
+	createPseudo: markFunction,
+
+	match: matchExpr,
+
+	attrHandle: {},
+
+	find: {},
+
+	relative: {
+		">": { dir: "parentNode", first: true },
+		" ": { dir: "parentNode" },
+		"+": { dir: "previousSibling", first: true },
+		"~": { dir: "previousSibling" }
+	},
+
+	preFilter: {
+		"ATTR": function( match ) {
+			match[1] = match[1].replace( runescape, funescape );
+
+			// Move the given value to match[3] whether quoted or unquoted
+			match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
+
+			if ( match[2] === "~=" ) {
+				match[3] = " " + match[3] + " ";
+			}
+
+			return match.slice( 0, 4 );
+		},
+
+		"CHILD": function( match ) {
+			/* matches from matchExpr["CHILD"]
+				1 type (only|nth|...)
+				2 what (child|of-type)
+				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+				4 xn-component of xn+y argument ([+-]?\d*n|)
+				5 sign of xn-component
+				6 x of xn-component
+				7 sign of y-component
+				8 y of y-component
+			*/
+			match[1] = match[1].toLowerCase();
+
+			if ( match[1].slice( 0, 3 ) === "nth" ) {
+				// nth-* requires argument
+				if ( !match[3] ) {
+					Sizzle.error( match[0] );
+				}
+
+				// numeric x and y parameters for Expr.filter.CHILD
+				// remember that false/true cast respectively to 0/1
+				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+			// other types prohibit arguments
+			} else if ( match[3] ) {
+				Sizzle.error( match[0] );
+			}
+
+			return match;
+		},
+
+		"PSEUDO": function( match ) {
+			var excess,
+				unquoted = !match[5] && match[2];
+
+			if ( matchExpr["CHILD"].test( match[0] ) ) {
+				return null;
+			}
+
+			// Accept quoted arguments as-is
+			if ( match[3] && match[4] !== undefined ) {
+				match[2] = match[4];
+
+			// Strip excess characters from unquoted arguments
+			} else if ( unquoted && rpseudo.test( unquoted ) &&
+				// Get excess from tokenize (recursively)
+				(excess = tokenize( unquoted, true )) &&
+				// advance to the next closing parenthesis
+				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+				// excess is a negative index
+				match[0] = match[0].slice( 0, excess );
+				match[2] = unquoted.slice( 0, excess );
+			}
+
+			// Return only captures needed by the pseudo filter method (type and argument)
+			return match.slice( 0, 3 );
+		}
+	},
+
+	filter: {
+
+		"TAG": function( nodeNameSelector ) {
+			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+			return nodeNameSelector === "*" ?
+				function() { return true; } :
+				function( elem ) {
+					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+				};
+		},
+
+		"CLASS": function( className ) {
+			var pattern = classCache[ className + " " ];
+
+			return pattern ||
+				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+				classCache( className, function( elem ) {
+					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
+				});
+		},
+
+		"ATTR": function( name, operator, check ) {
+			return function( elem ) {
+				var result = Sizzle.attr( elem, name );
+
+				if ( result == null ) {
+					return operator === "!=";
+				}
+				if ( !operator ) {
+					return true;
+				}
+
+				result += "";
+
+				return operator === "=" ? result === check :
+					operator === "!=" ? result !== check :
+					operator === "^=" ? check && result.indexOf( check ) === 0 :
+					operator === "*=" ? check && result.indexOf( check ) > -1 :
+					operator === "$=" ? check && result.slice( -check.length ) === check :
+					operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
+					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+					false;
+			};
+		},
+
+		"CHILD": function( type, what, argument, first, last ) {
+			var simple = type.slice( 0, 3 ) !== "nth",
+				forward = type.slice( -4 ) !== "last",
+				ofType = what === "of-type";
+
+			return first === 1 && last === 0 ?
+
+				// Shortcut for :nth-*(n)
+				function( elem ) {
+					return !!elem.parentNode;
+				} :
+
+				function( elem, context, xml ) {
+					var cache, outerCache, node, diff, nodeIndex, start,
+						dir = simple !== forward ? "nextSibling" : "previousSibling",
+						parent = elem.parentNode,
+						name = ofType && elem.nodeName.toLowerCase(),
+						useCache = !xml && !ofType;
+
+					if ( parent ) {
+
+						// :(first|last|only)-(child|of-type)
+						if ( simple ) {
+							while ( dir ) {
+								node = elem;
+								while ( (node = node[ dir ]) ) {
+									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+										return false;
+									}
+								}
+								// Reverse direction for :only-* (if we haven't yet done so)
+								start = dir = type === "only" && !start && "nextSibling";
+							}
+							return true;
+						}
+
+						start = [ forward ? parent.firstChild : parent.lastChild ];
+
+						// non-xml :nth-child(...) stores cache data on `parent`
+						if ( forward && useCache ) {
+							// Seek `elem` from a previously-cached index
+							outerCache = parent[ expando ] || (parent[ expando ] = {});
+							cache = outerCache[ type ] || [];
+							nodeIndex = cache[0] === dirruns && cache[1];
+							diff = cache[0] === dirruns && cache[2];
+							node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+							while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+								// Fallback to seeking `elem` from the start
+								(diff = nodeIndex = 0) || start.pop()) ) {
+
+								// When found, cache indexes on `parent` and break
+								if ( node.nodeType === 1 && ++diff && node === elem ) {
+									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+									break;
+								}
+							}
+
+						// Use previously-cached element index if available
+						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+							diff = cache[1];
+
+						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+						} else {
+							// Use the same loop as above to seek `elem` from the start
+							while ( (node = ++nodeIndex && node && node[ dir ] ||
+								(diff = nodeIndex = 0) || start.pop()) ) {
+
+								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+									// Cache the index of each encountered element
+									if ( useCache ) {
+										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+									}
+
+									if ( node === elem ) {
+										break;
+									}
+								}
+							}
+						}
+
+						// Incorporate the offset, then check against cycle size
+						diff -= last;
+						return diff === first || ( diff % first === 0 && diff / first >= 0 );
+					}
+				};
+		},
+
+		"PSEUDO": function( pseudo, argument ) {
+			// pseudo-class names are case-insensitive
+			// http://www.w3.org/TR/selectors/#pseudo-classes
+			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+			// Remember that setFilters inherits from pseudos
+			var args,
+				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+					Sizzle.error( "unsupported pseudo: " + pseudo );
+
+			// The user may use createPseudo to indicate that
+			// arguments are needed to create the filter function
+			// just as Sizzle does
+			if ( fn[ expando ] ) {
+				return fn( argument );
+			}
+
+			// But maintain support for old signatures
+			if ( fn.length > 1 ) {
+				args = [ pseudo, pseudo, "", argument ];
+				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+					markFunction(function( seed, matches ) {
+						var idx,
+							matched = fn( seed, argument ),
+							i = matched.length;
+						while ( i-- ) {
+							idx = indexOf.call( seed, matched[i] );
+							seed[ idx ] = !( matches[ idx ] = matched[i] );
+						}
+					}) :
+					function( elem ) {
+						return fn( elem, 0, args );
+					};
+			}
+
+			return fn;
+		}
+	},
+
+	pseudos: {
+		// Potentially complex pseudos
+		"not": markFunction(function( selector ) {
+			// Trim the selector passed to compile
+			// to avoid treating leading and trailing
+			// spaces as combinators
+			var input = [],
+				results = [],
+				matcher = compile( selector.replace( rtrim, "$1" ) );
+
+			return matcher[ expando ] ?
+				markFunction(function( seed, matches, context, xml ) {
+					var elem,
+						unmatched = matcher( seed, null, xml, [] ),
+						i = seed.length;
+
+					// Match elements unmatched by `matcher`
+					while ( i-- ) {
+						if ( (elem = unmatched[i]) ) {
+							seed[i] = !(matches[i] = elem);
+						}
+					}
+				}) :
+				function( elem, context, xml ) {
+					input[0] = elem;
+					matcher( input, null, xml, results );
+					return !results.pop();
+				};
+		}),
+
+		"has": markFunction(function( selector ) {
+			return function( elem ) {
+				return Sizzle( selector, elem ).length > 0;
+			};
+		}),
+
+		"contains": markFunction(function( text ) {
+			return function( elem ) {
+				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+			};
+		}),
+
+		// "Whether an element is represented by a :lang() selector
+		// is based solely on the element's language value
+		// being equal to the identifier C,
+		// or beginning with the identifier C immediately followed by "-".
+		// The matching of C against the element's language value is performed case-insensitively.
+		// The identifier C does not have to be a valid language name."
+		// http://www.w3.org/TR/selectors/#lang-pseudo
+		"lang": markFunction( function( lang ) {
+			// lang value must be a valid identifier
+			if ( !ridentifier.test(lang || "") ) {
+				Sizzle.error( "unsupported lang: " + lang );
+			}
+			lang = lang.replace( runescape, funescape ).toLowerCase();
+			return function( elem ) {
+				var elemLang;
+				do {
+					if ( (elemLang = documentIsHTML ?
+						elem.lang :
+						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+						elemLang = elemLang.toLowerCase();
+						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+					}
+				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+				return false;
+			};
+		}),
+
+		// Miscellaneous
+		"target": function( elem ) {
+			var hash = window.location && window.location.hash;
+			return hash && hash.slice( 1 ) === elem.id;
+		},
+
+		"root": function( elem ) {
+			return elem === docElem;
+		},
+
+		"focus": function( elem ) {
+			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+		},
+
+		// Boolean properties
+		"enabled": function( elem ) {
+			return elem.disabled === false;
+		},
+
+		"disabled": function( elem ) {
+			return elem.disabled === true;
+		},
+
+		"checked": function( elem ) {
+			// In CSS3, :checked should return both checked and selected elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			var nodeName = elem.nodeName.toLowerCase();
+			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+		},
+
+		"selected": function( elem ) {
+			// Accessing this property makes selected-by-default
+			// options in Safari work properly
+			if ( elem.parentNode ) {
+				elem.parentNode.selectedIndex;
+			}
+
+			return elem.selected === true;
+		},
+
+		// Contents
+		"empty": function( elem ) {
+			// http://www.w3.org/TR/selectors/#empty-pseudo
+			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+			//   but not by others (comment: 8; processing instruction: 7; etc.)
+			// nodeType < 6 works because attributes (2) do not appear as children
+			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+				if ( elem.nodeType < 6 ) {
+					return false;
+				}
+			}
+			return true;
+		},
+
+		"parent": function( elem ) {
+			return !Expr.pseudos["empty"]( elem );
+		},
+
+		// Element/input types
+		"header": function( elem ) {
+			return rheader.test( elem.nodeName );
+		},
+
+		"input": function( elem ) {
+			return rinputs.test( elem.nodeName );
+		},
+
+		"button": function( elem ) {
+			var name = elem.nodeName.toLowerCase();
+			return name === "input" && elem.type === "button" || name === "button";
+		},
+
+		"text": function( elem ) {
+			var attr;
+			return elem.nodeName.toLowerCase() === "input" &&
+				elem.type === "text" &&
+
+				// Support: IE<8
+				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+		},
+
+		// Position-in-collection
+		"first": createPositionalPseudo(function() {
+			return [ 0 ];
+		}),
+
+		"last": createPositionalPseudo(function( matchIndexes, length ) {
+			return [ length - 1 ];
+		}),
+
+		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			return [ argument < 0 ? argument + length : argument ];
+		}),
+
+		"even": createPositionalPseudo(function( matchIndexes, length ) {
+			var i = 0;
+			for ( ; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"odd": createPositionalPseudo(function( matchIndexes, length ) {
+			var i = 1;
+			for ( ; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			var i = argument < 0 ? argument + length : argument;
+			for ( ; --i >= 0; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			var i = argument < 0 ? argument + length : argument;
+			for ( ; ++i < length; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		})
+	}
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+	Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+	Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+function tokenize( selector, parseOnly ) {
+	var matched, match, tokens, type,
+		soFar, groups, preFilters,
+		cached = tokenCache[ selector + " " ];
+
+	if ( cached ) {
+		return parseOnly ? 0 : cached.slice( 0 );
+	}
+
+	soFar = selector;
+	groups = [];
+	preFilters = Expr.preFilter;
+
+	while ( soFar ) {
+
+		// Comma and first run
+		if ( !matched || (match = rcomma.exec( soFar )) ) {
+			if ( match ) {
+				// Don't consume trailing commas as valid
+				soFar = soFar.slice( match[0].length ) || soFar;
+			}
+			groups.push( (tokens = []) );
+		}
+
+		matched = false;
+
+		// Combinators
+		if ( (match = rcombinators.exec( soFar )) ) {
+			matched = match.shift();
+			tokens.push({
+				value: matched,
+				// Cast descendant combinators to space
+				type: match[0].replace( rtrim, " " )
+			});
+			soFar = soFar.slice( matched.length );
+		}
+
+		// Filters
+		for ( type in Expr.filter ) {
+			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+				(match = preFilters[ type ]( match ))) ) {
+				matched = match.shift();
+				tokens.push({
+					value: matched,
+					type: type,
+					matches: match
+				});
+				soFar = soFar.slice( matched.length );
+			}
+		}
+
+		if ( !matched ) {
+			break;
+		}
+	}
+
+	// Return the length of the invalid excess
+	// if we're just parsing
+	// Otherwise, throw an error or return tokens
+	return parseOnly ?
+		soFar.length :
+		soFar ?
+			Sizzle.error( selector ) :
+			// Cache the tokens
+			tokenCache( selector, groups ).slice( 0 );
+}
+
+function toSelector( tokens ) {
+	var i = 0,
+		len = tokens.length,
+		selector = "";
+	for ( ; i < len; i++ ) {
+		selector += tokens[i].value;
+	}
+	return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+	var dir = combinator.dir,
+		checkNonElements = base && dir === "parentNode",
+		doneName = done++;
+
+	return combinator.first ?
+		// Check against closest ancestor/preceding element
+		function( elem, context, xml ) {
+			while ( (elem = elem[ dir ]) ) {
+				if ( elem.nodeType === 1 || checkNonElements ) {
+					return matcher( elem, context, xml );
+				}
+			}
+		} :
+
+		// Check against all ancestor/preceding elements
+		function( elem, context, xml ) {
+			var oldCache, outerCache,
+				newCache = [ dirruns, doneName ];
+
+			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+			if ( xml ) {
+				while ( (elem = elem[ dir ]) ) {
+					if ( elem.nodeType === 1 || checkNonElements ) {
+						if ( matcher( elem, context, xml ) ) {
+							return true;
+						}
+					}
+				}
+			} else {
+				while ( (elem = elem[ dir ]) ) {
+					if ( elem.nodeType === 1 || checkNonElements ) {
+						outerCache = elem[ expando ] || (elem[ expando ] = {});
+						if ( (oldCache = outerCache[ dir ]) &&
+							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+							// Assign to newCache so results back-propagate to previous elements
+							return (newCache[ 2 ] = oldCache[ 2 ]);
+						} else {
+							// Reuse newcache so results back-propagate to previous elements
+							outerCache[ dir ] = newCache;
+
+							// A match means we're done; a fail means we have to keep checking
+							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+								return true;
+							}
+						}
+					}
+				}
+			}
+		};
+}
+
+function elementMatcher( matchers ) {
+	return matchers.length > 1 ?
+		function( elem, context, xml ) {
+			var i = matchers.length;
+			while ( i-- ) {
+				if ( !matchers[i]( elem, context, xml ) ) {
+					return false;
+				}
+			}
+			return true;
+		} :
+		matchers[0];
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+	var elem,
+		newUnmatched = [],
+		i = 0,
+		len = unmatched.length,
+		mapped = map != null;
+
+	for ( ; i < len; i++ ) {
+		if ( (elem = unmatched[i]) ) {
+			if ( !filter || filter( elem, context, xml ) ) {
+				newUnmatched.push( elem );
+				if ( mapped ) {
+					map.push( i );
+				}
+			}
+		}
+	}
+
+	return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+	if ( postFilter && !postFilter[ expando ] ) {
+		postFilter = setMatcher( postFilter );
+	}
+	if ( postFinder && !postFinder[ expando ] ) {
+		postFinder = setMatcher( postFinder, postSelector );
+	}
+	return markFunction(function( seed, results, context, xml ) {
+		var temp, i, elem,
+			preMap = [],
+			postMap = [],
+			preexisting = results.length,
+
+			// Get initial elements from seed or context
+			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+			// Prefilter to get matcher input, preserving a map for seed-results synchronization
+			matcherIn = preFilter && ( seed || !selector ) ?
+				condense( elems, preMap, preFilter, context, xml ) :
+				elems,
+
+			matcherOut = matcher ?
+				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+					// ...intermediate processing is necessary
+					[] :
+
+					// ...otherwise use results directly
+					results :
+				matcherIn;
+
+		// Find primary matches
+		if ( matcher ) {
+			matcher( matcherIn, matcherOut, context, xml );
+		}
+
+		// Apply postFilter
+		if ( postFilter ) {
+			temp = condense( matcherOut, postMap );
+			postFilter( temp, [], context, xml );
+
+			// Un-match failing elements by moving them back to matcherIn
+			i = temp.length;
+			while ( i-- ) {
+				if ( (elem = temp[i]) ) {
+					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+				}
+			}
+		}
+
+		if ( seed ) {
+			if ( postFinder || preFilter ) {
+				if ( postFinder ) {
+					// Get the final matcherOut by condensing this intermediate into postFinder contexts
+					temp = [];
+					i = matcherOut.length;
+					while ( i-- ) {
+						if ( (elem = matcherOut[i]) ) {
+							// Restore matcherIn since elem is not yet a final match
+							temp.push( (matcherIn[i] = elem) );
+						}
+					}
+					postFinder( null, (matcherOut = []), temp, xml );
+				}
+
+				// Move matched elements from seed to results to keep them synchronized
+				i = matcherOut.length;
+				while ( i-- ) {
+					if ( (elem = matcherOut[i]) &&
+						(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
+
+						seed[temp] = !(results[temp] = elem);
+					}
+				}
+			}
+
+		// Add elements to results, through postFinder if defined
+		} else {
+			matcherOut = condense(
+				matcherOut === results ?
+					matcherOut.splice( preexisting, matcherOut.length ) :
+					matcherOut
+			);
+			if ( postFinder ) {
+				postFinder( null, results, matcherOut, xml );
+			} else {
+				push.apply( results, matcherOut );
+			}
+		}
+	});
+}
+
+function matcherFromTokens( tokens ) {
+	var checkContext, matcher, j,
+		len = tokens.length,
+		leadingRelative = Expr.relative[ tokens[0].type ],
+		implicitRelative = leadingRelative || Expr.relative[" "],
+		i = leadingRelative ? 1 : 0,
+
+		// The foundational matcher ensures that elements are reachable from top-level context(s)
+		matchContext = addCombinator( function( elem ) {
+			return elem === checkContext;
+		}, implicitRelative, true ),
+		matchAnyContext = addCombinator( function( elem ) {
+			return indexOf.call( checkContext, elem ) > -1;
+		}, implicitRelative, true ),
+		matchers = [ function( elem, context, xml ) {
+			return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+				(checkContext = context).nodeType ?
+					matchContext( elem, context, xml ) :
+					matchAnyContext( elem, context, xml ) );
+		} ];
+
+	for ( ; i < len; i++ ) {
+		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+		} else {
+			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+			// Return special upon seeing a positional matcher
+			if ( matcher[ expando ] ) {
+				// Find the next relative operator (if any) for proper handling
+				j = ++i;
+				for ( ; j < len; j++ ) {
+					if ( Expr.relative[ tokens[j].type ] ) {
+						break;
+					}
+				}
+				return setMatcher(
+					i > 1 && elementMatcher( matchers ),
+					i > 1 && toSelector(
+						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
+						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+					).replace( rtrim, "$1" ),
+					matcher,
+					i < j && matcherFromTokens( tokens.slice( i, j ) ),
+					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+					j < len && toSelector( tokens )
+				);
+			}
+			matchers.push( matcher );
+		}
+	}
+
+	return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+	var bySet = setMatchers.length > 0,
+		byElement = elementMatchers.length > 0,
+		superMatcher = function( seed, context, xml, results, outermost ) {
+			var elem, j, matcher,
+				matchedCount = 0,
+				i = "0",
+				unmatched = seed && [],
+				setMatched = [],
+				contextBackup = outermostContext,
+				// We must always have either seed elements or outermost context
+				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+				// Use integer dirruns iff this is the outermost matcher
+				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+				len = elems.length;
+
+			if ( outermost ) {
+				outermostContext = context !== document && context;
+			}
+
+			// Add elements passing elementMatchers directly to results
+			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+			// Support: IE<9, Safari
+			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+				if ( byElement && elem ) {
+					j = 0;
+					while ( (matcher = elementMatchers[j++]) ) {
+						if ( matcher( elem, context, xml ) ) {
+							results.push( elem );
+							break;
+						}
+					}
+					if ( outermost ) {
+						dirruns = dirrunsUnique;
+					}
+				}
+
+				// Track unmatched elements for set filters
+				if ( bySet ) {
+					// They will have gone through all possible matchers
+					if ( (elem = !matcher && elem) ) {
+						matchedCount--;
+					}
+
+					// Lengthen the array for every element, matched or not
+					if ( seed ) {
+						unmatched.push( elem );
+					}
+				}
+			}
+
+			// Apply set filters to unmatched elements
+			matchedCount += i;
+			if ( bySet && i !== matchedCount ) {
+				j = 0;
+				while ( (matcher = setMatchers[j++]) ) {
+					matcher( unmatched, setMatched, context, xml );
+				}
+
+				if ( seed ) {
+					// Reintegrate element matches to eliminate the need for sorting
+					if ( matchedCount > 0 ) {
+						while ( i-- ) {
+							if ( !(unmatched[i] || setMatched[i]) ) {
+								setMatched[i] = pop.call( results );
+							}
+						}
+					}
+
+					// Discard index placeholder values to get only actual matches
+					setMatched = condense( setMatched );
+				}
+
+				// Add matches to results
+				push.apply( results, setMatched );
+
+				// Seedless set matches succeeding multiple successful matchers stipulate sorting
+				if ( outermost && !seed && setMatched.length > 0 &&
+					( matchedCount + setMatchers.length ) > 1 ) {
+
+					Sizzle.uniqueSort( results );
+				}
+			}
+
+			// Override manipulation of globals by nested matchers
+			if ( outermost ) {
+				dirruns = dirrunsUnique;
+				outermostContext = contextBackup;
+			}
+
+			return unmatched;
+		};
+
+	return bySet ?
+		markFunction( superMatcher ) :
+		superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
+	var i,
+		setMatchers = [],
+		elementMatchers = [],
+		cached = compilerCache[ selector + " " ];
+
+	if ( !cached ) {
+		// Generate a function of recursive functions that can be used to check each element
+		if ( !group ) {
+			group = tokenize( selector );
+		}
+		i = group.length;
+		while ( i-- ) {
+			cached = matcherFromTokens( group[i] );
+			if ( cached[ expando ] ) {
+				setMatchers.push( cached );
+			} else {
+				elementMatchers.push( cached );
+			}
+		}
+
+		// Cache the compiled function
+		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+	}
+	return cached;
+};
+
+function multipleContexts( selector, contexts, results ) {
+	var i = 0,
+		len = contexts.length;
+	for ( ; i < len; i++ ) {
+		Sizzle( selector, contexts[i], results );
+	}
+	return results;
+}
+
+function select( selector, context, results, seed ) {
+	var i, tokens, token, type, find,
+		match = tokenize( selector );
+
+	if ( !seed ) {
+		// Try to minimize operations if there is only one group
+		if ( match.length === 1 ) {
+
+			// Take a shortcut and set the context if the root selector is an ID
+			tokens = match[0] = match[0].slice( 0 );
+			if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+					support.getById && context.nodeType === 9 && documentIsHTML &&
+					Expr.relative[ tokens[1].type ] ) {
+
+				context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+				if ( !context ) {
+					return results;
+				}
+				selector = selector.slice( tokens.shift().value.length );
+			}
+
+			// Fetch a seed set for right-to-left matching
+			i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+			while ( i-- ) {
+				token = tokens[i];
+
+				// Abort if we hit a combinator
+				if ( Expr.relative[ (type = token.type) ] ) {
+					break;
+				}
+				if ( (find = Expr.find[ type ]) ) {
+					// Search, expanding context for leading sibling combinators
+					if ( (seed = find(
+						token.matches[0].replace( runescape, funescape ),
+						rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+					)) ) {
+
+						// If seed is empty or no tokens remain, we can return early
+						tokens.splice( i, 1 );
+						selector = seed.length && toSelector( tokens );
+						if ( !selector ) {
+							push.apply( results, seed );
+							return results;
+						}
+
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	// Compile and execute a filtering function
+	// Provide `match` to avoid retokenization if we modified the selector above
+	compile( selector, match )(
+		seed,
+		context,
+		!documentIsHTML,
+		results,
+		rsibling.test( selector ) && testContext( context.parentNode ) || context
+	);
+	return results;
+}
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome<14
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( div1 ) {
+	// Should return 1, but returns 4 (following)
+	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( div ) {
+	div.innerHTML = "<a href='#'></a>";
+	return div.firstChild.getAttribute("href") === "#" ;
+}) ) {
+	addHandle( "type|href|height|width", function( elem, name, isXML ) {
+		if ( !isXML ) {
+			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+		}
+	});
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( div ) {
+	div.innerHTML = "<input/>";
+	div.firstChild.setAttribute( "value", "" );
+	return div.firstChild.getAttribute( "value" ) === "";
+}) ) {
+	addHandle( "value", function( elem, name, isXML ) {
+		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+			return elem.defaultValue;
+		}
+	});
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( div ) {
+	return div.getAttribute("disabled") == null;
+}) ) {
+	addHandle( booleans, function( elem, name, isXML ) {
+		var val;
+		if ( !isXML ) {
+			return elem[ name ] === true ? name.toLowerCase() :
+					(val = elem.getAttributeNode( name )) && val.specified ?
+					val.value :
+				null;
+		}
+	});
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+	if ( jQuery.isFunction( qualifier ) ) {
+		return jQuery.grep( elements, function( elem, i ) {
+			/* jshint -W018 */
+			return !!qualifier.call( elem, i, elem ) !== not;
+		});
+
+	}
+
+	if ( qualifier.nodeType ) {
+		return jQuery.grep( elements, function( elem ) {
+			return ( elem === qualifier ) !== not;
+		});
+
+	}
+
+	if ( typeof qualifier === "string" ) {
+		if ( risSimple.test( qualifier ) ) {
+			return jQuery.filter( qualifier, elements, not );
+		}
+
+		qualifier = jQuery.filter( qualifier, elements );
+	}
+
+	return jQuery.grep( elements, function( elem ) {
+		return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
+	});
+}
+
+jQuery.filter = function( expr, elems, not ) {
+	var elem = elems[ 0 ];
+
+	if ( not ) {
+		expr = ":not(" + expr + ")";
+	}
+
+	return elems.length === 1 && elem.nodeType === 1 ?
+		jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+		jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+			return elem.nodeType === 1;
+		}));
+};
+
+jQuery.fn.extend({
+	find: function( selector ) {
+		var i,
+			ret = [],
+			self = this,
+			len = self.length;
+
+		if ( typeof selector !== "string" ) {
+			return this.pushStack( jQuery( selector ).filter(function() {
+				for ( i = 0; i < len; i++ ) {
+					if ( jQuery.contains( self[ i ], this ) ) {
+						return true;
+					}
+				}
+			}) );
+		}
+
+		for ( i = 0; i < len; i++ ) {
+			jQuery.find( selector, self[ i ], ret );
+		}
+
+		// Needed because $( selector, context ) becomes $( context ).find( selector )
+		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+		ret.selector = this.selector ? this.selector + " " + selector : selector;
+		return ret;
+	},
+	filter: function( selector ) {
+		return this.pushStack( winnow(this, selector || [], false) );
+	},
+	not: function( selector ) {
+		return this.pushStack( winnow(this, selector || [], true) );
+	},
+	is: function( selector ) {
+		return !!winnow(
+			this,
+
+			// If this is a positional/relative selector, check membership in the returned set
+			// so $("p:first").is("p:last") won't return true for a doc with two "p".
+			typeof selector === "string" && rneedsContext.test( selector ) ?
+				jQuery( selector ) :
+				selector || [],
+			false
+		).length;
+	}
+});
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+	// Use the correct document accordingly with window argument (sandbox)
+	document = window.document,
+
+	// A simple way to check for HTML strings
+	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+	// Strict HTML recognition (#11290: must start with <)
+	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+	init = jQuery.fn.init = function( selector, context ) {
+		var match, elem;
+
+		// HANDLE: $(""), $(null), $(undefined), $(false)
+		if ( !selector ) {
+			return this;
+		}
+
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+				// Assume that strings that start and end with <> are HTML and skip the regex check
+				match = [ null, selector, null ];
+
+			} else {
+				match = rquickExpr.exec( selector );
+			}
+
+			// Match html or make sure no context is specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] ) {
+					context = context instanceof jQuery ? context[0] : context;
+
+					// scripts is true for back-compat
+					// Intentionally let the error be thrown if parseHTML is not present
+					jQuery.merge( this, jQuery.parseHTML(
+						match[1],
+						context && context.nodeType ? context.ownerDocument || context : document,
+						true
+					) );
+
+					// HANDLE: $(html, props)
+					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+						for ( match in context ) {
+							// Properties of context are called as methods if possible
+							if ( jQuery.isFunction( this[ match ] ) ) {
+								this[ match ]( context[ match ] );
+
+							// ...and otherwise set as attributes
+							} else {
+								this.attr( match, context[ match ] );
+							}
+						}
+					}
+
+					return this;
+
+				// HANDLE: $(#id)
+				} else {
+					elem = document.getElementById( match[2] );
+
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document #6963
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id !== match[2] ) {
+							return rootjQuery.find( selector );
+						}
+
+						// Otherwise, we inject the element directly into the jQuery object
+						this.length = 1;
+						this[0] = elem;
+					}
+
+					this.context = document;
+					this.selector = selector;
+					return this;
+				}
+
+			// HANDLE: $(expr, $(...))
+			} else if ( !context || context.jquery ) {
+				return ( context || rootjQuery ).find( selector );
+
+			// HANDLE: $(expr, context)
+			// (which is just equivalent to: $(context).find(expr)
+			} else {
+				return this.constructor( context ).find( selector );
+			}
+
+		// HANDLE: $(DOMElement)
+		} else if ( selector.nodeType ) {
+			this.context = this[0] = selector;
+			this.length = 1;
+			return this;
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) ) {
+			return typeof rootjQuery.ready !== "undefined" ?
+				rootjQuery.ready( selector ) :
+				// Execute immediately if ready is not present
+				selector( jQuery );
+		}
+
+		if ( selector.selector !== undefined ) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return jQuery.makeArray( selector, this );
+	};
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+	// methods guaranteed to produce a unique set when starting from a unique set
+	guaranteedUnique = {
+		children: true,
+		contents: true,
+		next: true,
+		prev: true
+	};
+
+jQuery.extend({
+	dir: function( elem, dir, until ) {
+		var matched = [],
+			cur = elem[ dir ];
+
+		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+			if ( cur.nodeType === 1 ) {
+				matched.push( cur );
+			}
+			cur = cur[dir];
+		}
+		return matched;
+	},
+
+	sibling: function( n, elem ) {
+		var r = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType === 1 && n !== elem ) {
+				r.push( n );
+			}
+		}
+
+		return r;
+	}
+});
+
+jQuery.fn.extend({
+	has: function( target ) {
+		var i,
+			targets = jQuery( target, this ),
+			len = targets.length;
+
+		return this.filter(function() {
+			for ( i = 0; i < len; i++ ) {
+				if ( jQuery.contains( this, targets[i] ) ) {
+					return true;
+				}
+			}
+		});
+	},
+
+	closest: function( selectors, context ) {
+		var cur,
+			i = 0,
+			l = this.length,
+			matched = [],
+			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+				jQuery( selectors, context || this.context ) :
+				0;
+
+		for ( ; i < l; i++ ) {
+			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
+				// Always skip document fragments
+				if ( cur.nodeType < 11 && (pos ?
+					pos.index(cur) > -1 :
+
+					// Don't pass non-elements to Sizzle
+					cur.nodeType === 1 &&
+						jQuery.find.matchesSelector(cur, selectors)) ) {
+
+					matched.push( cur );
+					break;
+				}
+			}
+		}
+
+		return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
+	},
+
+	// Determine the position of an element within
+	// the matched set of elements
+	index: function( elem ) {
+
+		// No argument, return index in parent
+		if ( !elem ) {
+			return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
+		}
+
+		// index in selector
+		if ( typeof elem === "string" ) {
+			return jQuery.inArray( this[0], jQuery( elem ) );
+		}
+
+		// Locate the position of the desired element
+		return jQuery.inArray(
+			// If it receives a jQuery object, the first element is used
+			elem.jquery ? elem[0] : elem, this );
+	},
+
+	add: function( selector, context ) {
+		return this.pushStack(
+			jQuery.unique(
+				jQuery.merge( this.get(), jQuery( selector, context ) )
+			)
+		);
+	},
+
+	addBack: function( selector ) {
+		return this.add( selector == null ?
+			this.prevObject : this.prevObject.filter(selector)
+		);
+	}
+});
+
+function sibling( cur, dir ) {
+	do {
+		cur = cur[ dir ];
+	} while ( cur && cur.nodeType !== 1 );
+
+	return cur;
+}
+
+jQuery.each({
+	parent: function( elem ) {
+		var parent = elem.parentNode;
+		return parent && parent.nodeType !== 11 ? parent : null;
+	},
+	parents: function( elem ) {
+		return jQuery.dir( elem, "parentNode" );
+	},
+	parentsUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "parentNode", until );
+	},
+	next: function( elem ) {
+		return sibling( elem, "nextSibling" );
+	},
+	prev: function( elem ) {
+		return sibling( elem, "previousSibling" );
+	},
+	nextAll: function( elem ) {
+		return jQuery.dir( elem, "nextSibling" );
+	},
+	prevAll: function( elem ) {
+		return jQuery.dir( elem, "previousSibling" );
+	},
+	nextUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "nextSibling", until );
+	},
+	prevUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "previousSibling", until );
+	},
+	siblings: function( elem ) {
+		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+	},
+	children: function( elem ) {
+		return jQuery.sibling( elem.firstChild );
+	},
+	contents: function( elem ) {
+		return jQuery.nodeName( elem, "iframe" ) ?
+			elem.contentDocument || elem.contentWindow.document :
+			jQuery.merge( [], elem.childNodes );
+	}
+}, function( name, fn ) {
+	jQuery.fn[ name ] = function( until, selector ) {
+		var ret = jQuery.map( this, fn, until );
+
+		if ( name.slice( -5 ) !== "Until" ) {
+			selector = until;
+		}
+
+		if ( selector && typeof selector === "string" ) {
+			ret = jQuery.filter( selector, ret );
+		}
+
+		if ( this.length > 1 ) {
+			// Remove duplicates
+			if ( !guaranteedUnique[ name ] ) {
+				ret = jQuery.unique( ret );
+			}
+
+			// Reverse order for parents* and prev-derivatives
+			if ( rparentsprev.test( name ) ) {
+				ret = ret.reverse();
+			}
+		}
+
+		return this.pushStack( ret );
+	};
+});
+var rnotwhite = (/\S+/g);
+
+
+
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+	var object = optionsCache[ options ] = {};
+	jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+		object[ flag ] = true;
+	});
+	return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ *	options: an optional list of space-separated options that will change how
+ *			the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ *	once:			will ensure the callback list can only be fired once (like a Deferred)
+ *
+ *	memory:			will keep track of previous values and will call any callback added
+ *					after the list has been fired right away with the latest "memorized"
+ *					values (like a Deferred)
+ *
+ *	unique:			will ensure a callback can only be added once (no duplicate in the list)
+ *
+ *	stopOnFalse:	interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+	// Convert options from String-formatted to Object-formatted if needed
+	// (we check in cache first)
+	options = typeof options === "string" ?
+		( optionsCache[ options ] || createOptions( options ) ) :
+		jQuery.extend( {}, options );
+
+	var // Flag to know if list is currently firing
+		firing,
+		// Last fire value (for non-forgettable lists)
+		memory,
+		// Flag to know if list was already fired
+		fired,
+		// End of the loop when firing
+		firingLength,
+		// Index of currently firing callback (modified by remove if needed)
+		firingIndex,
+		// First callback to fire (used internally by add and fireWith)
+		firingStart,
+		// Actual callback list
+		list = [],
+		// Stack of fire calls for repeatable lists
+		stack = !options.once && [],
+		// Fire callbacks
+		fire = function( data ) {
+			memory = options.memory && data;
+			fired = true;
+			firingIndex = firingStart || 0;
+			firingStart = 0;
+			firingLength = list.length;
+			firing = true;
+			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+					memory = false; // To prevent further calls using add
+					break;
+				}
+			}
+			firing = false;
+			if ( list ) {
+				if ( stack ) {
+					if ( stack.length ) {
+						fire( stack.shift() );
+					}
+				} else if ( memory ) {
+					list = [];
+				} else {
+					self.disable();
+				}
+			}
+		},
+		// Actual Callbacks object
+		self = {
+			// Add a callback or a collection of callbacks to the list
+			add: function() {
+				if ( list ) {
+					// First, we save the current length
+					var start = list.length;
+					(function add( args ) {
+						jQuery.each( args, function( _, arg ) {
+							var type = jQuery.type( arg );
+							if ( type === "function" ) {
+								if ( !options.unique || !self.has( arg ) ) {
+									list.push( arg );
+								}
+							} else if ( arg && arg.length && type !== "string" ) {
+								// Inspect recursively
+								add( arg );
+							}
+						});
+					})( arguments );
+					// Do we need to add the callbacks to the
+					// current firing batch?
+					if ( firing ) {
+						firingLength = list.length;
+					// With memory, if we're not firing then
+					// we should call right away
+					} else if ( memory ) {
+						firingStart = start;
+						fire( memory );
+					}
+				}
+				return this;
+			},
+			// Remove a callback from the list
+			remove: function() {
+				if ( list ) {
+					jQuery.each( arguments, function( _, arg ) {
+						var index;
+						while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+							list.splice( index, 1 );
+							// Handle firing indexes
+							if ( firing ) {
+								if ( index <= firingLength ) {
+									firingLength--;
+								}
+								if ( index <= firingIndex ) {
+									firingIndex--;
+								}
+							}
+						}
+					});
+				}
+				return this;
+			},
+			// Check if a given callback is in the list.
+			// If no argument is given, return whether or not list has callbacks attached.
+			has: function( fn ) {
+				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+			},
+			// Remove all callbacks from the list
+			empty: function() {
+				list = [];
+				firingLength = 0;
+				return this;
+			},
+			// Have the list do nothing anymore
+			disable: function() {
+				list = stack = memory = undefined;
+				return this;
+			},
+			// Is it disabled?
+			disabled: function() {
+				return !list;
+			},
+			// Lock the list in its current state
+			lock: function() {
+				stack = undefined;
+				if ( !memory ) {
+					self.disable();
+				}
+				return this;
+			},
+			// Is it locked?
+			locked: function() {
+				return !stack;
+			},
+			// Call all callbacks with the given context and arguments
+			fireWith: function( context, args ) {
+				if ( list && ( !fired || stack ) ) {
+					args = args || [];
+					args = [ context, args.slice ? args.slice() : args ];
+					if ( firing ) {
+						stack.push( args );
+					} else {
+						fire( args );
+					}
+				}
+				return this;
+			},
+			// Call all the callbacks with the given arguments
+			fire: function() {
+				self.fireWith( this, arguments );
+				return this;
+			},
+			// To know if the callbacks have already been called at least once
+			fired: function() {
+				return !!fired;
+			}
+		};
+
+	return self;
+};
+
+
+jQuery.extend({
+
+	Deferred: function( func ) {
+		var tuples = [
+				// action, add listener, listener list, final state
+				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+				[ "notify", "progress", jQuery.Callbacks("memory") ]
+			],
+			state = "pending",
+			promise = {
+				state: function() {
+					return state;
+				},
+				always: function() {
+					deferred.done( arguments ).fail( arguments );
+					return this;
+				},
+				then: function( /* fnDone, fnFail, fnProgress */ ) {
+					var fns = arguments;
+					return jQuery.Deferred(function( newDefer ) {
+						jQuery.each( tuples, function( i, tuple ) {
+							var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+							// deferred[ done | fail | progress ] for forwarding actions to newDefer
+							deferred[ tuple[1] ](function() {
+								var returned = fn && fn.apply( this, arguments );
+								if ( returned && jQuery.isFunction( returned.promise ) ) {
+									returned.promise()
+										.done( newDefer.resolve )
+										.fail( newDefer.reject )
+										.progress( newDefer.notify );
+								} else {
+									newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+								}
+							});
+						});
+						fns = null;
+					}).promise();
+				},
+				// Get a promise for this deferred
+				// If obj is provided, the promise aspect is added to the object
+				promise: function( obj ) {
+					return obj != null ? jQuery.extend( obj, promise ) : promise;
+				}
+			},
+			deferred = {};
+
+		// Keep pipe for back-compat
+		promise.pipe = promise.then;
+
+		// Add list-specific methods
+		jQuery.each( tuples, function( i, tuple ) {
+			var list = tuple[ 2 ],
+				stateString = tuple[ 3 ];
+
+			// promise[ done | fail | progress ] = list.add
+			promise[ tuple[1] ] = list.add;
+
+			// Handle state
+			if ( stateString ) {
+				list.add(function() {
+					// state = [ resolved | rejected ]
+					state = stateString;
+
+				// [ reject_list | resolve_list ].disable; progress_list.lock
+				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+			}
+
+			// deferred[ resolve | reject | notify ]
+			deferred[ tuple[0] ] = function() {
+				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+				return this;
+			};
+			deferred[ tuple[0] + "With" ] = list.fireWith;
+		});
+
+		// Make the deferred a promise
+		promise.promise( deferred );
+
+		// Call given func if any
+		if ( func ) {
+			func.call( deferred, deferred );
+		}
+
+		// All done!
+		return deferred;
+	},
+
+	// Deferred helper
+	when: function( subordinate /* , ..., subordinateN */ ) {
+		var i = 0,
+			resolveValues = slice.call( arguments ),
+			length = resolveValues.length,
+
+			// the count of uncompleted subordinates
+			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+			// Update function for both resolve and progress values
+			updateFunc = function( i, contexts, values ) {
+				return function( value ) {
+					contexts[ i ] = this;
+					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+					if ( values === progressValues ) {
+						deferred.notifyWith( contexts, values );
+
+					} else if ( !(--remaining) ) {
+						deferred.resolveWith( contexts, values );
+					}
+				};
+			},
+
+			progressValues, progressContexts, resolveContexts;
+
+		// add listeners to Deferred subordinates; treat others as resolved
+		if ( length > 1 ) {
+			progressValues = new Array( length );
+			progressContexts = new Array( length );
+			resolveContexts = new Array( length );
+			for ( ; i < length; i++ ) {
+				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+					resolveValues[ i ].promise()
+						.done( updateFunc( i, resolveContexts, resolveValues ) )
+						.fail( deferred.reject )
+						.progress( updateFunc( i, progressContexts, progressValues ) );
+				} else {
+					--remaining;
+				}
+			}
+		}
+
+		// if we're not waiting on anything, resolve the master
+		if ( !remaining ) {
+			deferred.resolveWith( resolveContexts, resolveValues );
+		}
+
+		return deferred.promise();
+	}
+});
+
+
+// The deferred used on DOM ready
+var readyList;
+
+jQuery.fn.ready = function( fn ) {
+	// Add the callback
+	jQuery.ready.promise().done( fn );
+
+	return this;
+};
+
+jQuery.extend({
+	// Is the DOM ready to be used? Set to true once it occurs.
+	isReady: false,
+
+	// A counter to track how many items to wait for before
+	// the ready event fires. See #6781
+	readyWait: 1,
+
+	// Hold (or release) the ready event
+	holdReady: function( hold ) {
+		if ( hold ) {
+			jQuery.readyWait++;
+		} else {
+			jQuery.ready( true );
+		}
+	},
+
+	// Handle when the DOM is ready
+	ready: function( wait ) {
+
+		// Abort if there are pending holds or we're already ready
+		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+			return;
+		}
+
+		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+		if ( !document.body ) {
+			return setTimeout( jQuery.ready );
+		}
+
+		// Remember that the DOM is ready
+		jQuery.isReady = true;
+
+		// If a normal DOM Ready event fired, decrement, and wait if need be
+		if ( wait !== true && --jQuery.readyWait > 0 ) {
+			return;
+		}
+
+		// If there are functions bound, to execute
+		readyList.resolveWith( document, [ jQuery ] );
+
+		// Trigger any bound ready events
+		if ( jQuery.fn.trigger ) {
+			jQuery( document ).trigger("ready").off("ready");
+		}
+	}
+});
+
+/**
+ * Clean-up method for dom ready events
+ */
+function detach() {
+	if ( document.addEventListener ) {
+		document.removeEventListener( "DOMContentLoaded", completed, false );
+		window.removeEventListener( "load", completed, false );
+
+	} else {
+		document.detachEvent( "onreadystatechange", completed );
+		window.detachEvent( "onload", completed );
+	}
+}
+
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+	// readyState === "complete" is good enough for us to call the dom ready in oldIE
+	if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
+		detach();
+		jQuery.ready();
+	}
+}
+
+jQuery.ready.promise = function( obj ) {
+	if ( !readyList ) {
+
+		readyList = jQuery.Deferred();
+
+		// Catch cases where $(document).ready() is called after the browser event has already occurred.
+		// we once tried to use readyState "interactive" here, but it caused issues like the one
+		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+		if ( document.readyState === "complete" ) {
+			// Handle it asynchronously to allow scripts the opportunity to delay ready
+			setTimeout( jQuery.ready );
+
+		// Standards-based browsers support DOMContentLoaded
+		} else if ( document.addEventListener ) {
+			// Use the handy event callback
+			document.addEventListener( "DOMContentLoaded", completed, false );
+
+			// A fallback to window.onload, that will always work
+			window.addEventListener( "load", completed, false );
+
+		// If IE event model is used
+		} else {
+			// Ensure firing before onload, maybe late but safe also for iframes
+			document.attachEvent( "onreadystatechange", completed );
+
+			// A fallback to window.onload, that will always work
+			window.attachEvent( "onload", completed );
+
+			// If IE and not a frame
+			// continually check to see if the document is ready
+			var top = false;
+
+			try {
+				top = window.frameElement == null && document.documentElement;
+			} catch(e) {}
+
+			if ( top && top.doScroll ) {
+				(function doScrollCheck() {
+					if ( !jQuery.isReady ) {
+
+						try {
+							// Use the trick by Diego Perini
+							// http://javascript.nwbox.com/IEContentLoaded/
+							top.doScroll("left");
+						} catch(e) {
+							return setTimeout( doScrollCheck, 50 );
+						}
+
+						// detach all dom ready events
+						detach();
+
+						// and execute any waiting functions
+						jQuery.ready();
+					}
+				})();
+			}
+		}
+	}
+	return readyList.promise( obj );
+};
+
+
+var strundefined = typeof undefined;
+
+
+
+// Support: IE<9
+// Iteration over object's inherited properties before its own
+var i;
+for ( i in jQuery( support ) ) {
+	break;
+}
+support.ownLast = i !== "0";
+
+// Note: most support tests are defined in their respective modules.
+// false until the test is run
+support.inlineBlockNeedsLayout = false;
+
+jQuery(function() {
+	// We need to execute this one support test ASAP because we need to know
+	// if body.style.zoom needs to be set.
+
+	var container, div,
+		body = document.getElementsByTagName("body")[0];
+
+	if ( !body ) {
+		// Return for frameset docs that don't have a body
+		return;
+	}
+
+	// Setup
+	container = document.createElement( "div" );
+	container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
+
+	div = document.createElement( "div" );
+	body.appendChild( container ).appendChild( div );
+
+	if ( typeof div.style.zoom !== strundefined ) {
+		// Support: IE<8
+		// Check if natively block-level elements act like inline-block
+		// elements when setting their display to 'inline' and giving
+		// them layout
+		div.style.cssText = "border:0;margin:0;width:1px;padding:1px;display:inline;zoom:1";
+
+		if ( (support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 )) ) {
+			// Prevent IE 6 from affecting layout for positioned elements #11048
+			// Prevent IE from shrinking the body in IE 7 mode #12869
+			// Support: IE<8
+			body.style.zoom = 1;
+		}
+	}
+
+	body.removeChild( container );
+
+	// Null elements to avoid leaks in IE
+	container = div = null;
+});
+
+
+
+
+(function() {
+	var div = document.createElement( "div" );
+
+	// Execute the test only if not already executed in another module.
+	if (support.deleteExpando == null) {
+		// Support: IE<9
+		support.deleteExpando = true;
+		try {
+			delete div.test;
+		} catch( e ) {
+			support.deleteExpando = false;
+		}
+	}
+
+	// Null elements to avoid leaks in IE.
+	div = null;
+})();
+
+
+/**
+ * Determines whether an object can have data
+ */
+jQuery.acceptData = function( elem ) {
+	var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
+		nodeType = +elem.nodeType || 1;
+
+	// Do not set data on non-element DOM nodes because it will not be cleared (#8335).
+	return nodeType !== 1 && nodeType !== 9 ?
+		false :
+
+		// Nodes accept data unless otherwise specified; rejection can be conditional
+		!noData || noData !== true && elem.getAttribute("classid") === noData;
+};
+
+
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+	rmultiDash = /([A-Z])/g;
+
+function dataAttr( elem, key, data ) {
+	// If nothing was found internally, try to fetch any
+	// data from the HTML5 data-* attribute
+	if ( data === undefined && elem.nodeType === 1 ) {
+
+		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+		data = elem.getAttribute( name );
+
+		if ( typeof data === "string" ) {
+			try {
+				data = data === "true" ? true :
+					data === "false" ? false :
+					data === "null" ? null :
+					// Only convert to a number if it doesn't change the string
+					+data + "" === data ? +data :
+					rbrace.test( data ) ? jQuery.parseJSON( data ) :
+					data;
+			} catch( e ) {}
+
+			// Make sure we set the data so it isn't changed later
+			jQuery.data( elem, key, data );
+
+		} else {
+			data = undefined;
+		}
+	}
+
+	return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+	var name;
+	for ( name in obj ) {
+
+		// if the public data object is empty, the private is still empty
+		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+			continue;
+		}
+		if ( name !== "toJSON" ) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
+	if ( !jQuery.acceptData( elem ) ) {
+		return;
+	}
+
+	var ret, thisCache,
+		internalKey = jQuery.expando,
+
+		// We have to handle DOM nodes and JS objects differently because IE6-7
+		// can't GC object references properly across the DOM-JS boundary
+		isNode = elem.nodeType,
+
+		// Only DOM nodes need the global jQuery cache; JS object data is
+		// attached directly to the object so GC can occur automatically
+		cache = isNode ? jQuery.cache : elem,
+
+		// Only defining an ID for JS objects if its cache already exists allows
+		// the code to shortcut on the same path as a DOM node with no cache
+		id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+	// Avoid doing any more work than we need to when trying to get data on an
+	// object that has no data at all
+	if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
+		return;
+	}
+
+	if ( !id ) {
+		// Only DOM nodes need a new unique ID for each element since their data
+		// ends up in the global cache
+		if ( isNode ) {
+			id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
+		} else {
+			id = internalKey;
+		}
+	}
+
+	if ( !cache[ id ] ) {
+		// Avoid exposing jQuery metadata on plain JS objects when the object
+		// is serialized using JSON.stringify
+		cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
+	}
+
+	// An object can be passed to jQuery.data instead of a key/value pair; this gets
+	// shallow copied over onto the existing cache
+	if ( typeof name === "object" || typeof name === "function" ) {
+		if ( pvt ) {
+			cache[ id ] = jQuery.extend( cache[ id ], name );
+		} else {
+			cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+		}
+	}
+
+	thisCache = cache[ id ];
+
+	// jQuery data() is stored in a separate object inside the object's internal data
+	// cache in order to avoid key collisions between internal data and user-defined
+	// data.
+	if ( !pvt ) {
+		if ( !thisCache.data ) {
+			thisCache.data = {};
+		}
+
+		thisCache = thisCache.data;
+	}
+
+	if ( data !== undefined ) {
+		thisCache[ jQuery.camelCase( name ) ] = data;
+	}
+
+	// Check for both converted-to-camel and non-converted data property names
+	// If a data property was specified
+	if ( typeof name === "string" ) {
+
+		// First Try to find as-is property data
+		ret = thisCache[ name ];
+
+		// Test for null|undefined property data
+		if ( ret == null ) {
+
+			// Try to find the camelCased property
+			ret = thisCache[ jQuery.camelCase( name ) ];
+		}
+	} else {
+		ret = thisCache;
+	}
+
+	return ret;
+}
+
+function internalRemoveData( elem, name, pvt ) {
+	if ( !jQuery.acceptData( elem ) ) {
+		return;
+	}
+
+	var thisCache, i,
+		isNode = elem.nodeType,
+
+		// See jQuery.data for more information
+		cache = isNode ? jQuery.cache : elem,
+		id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+	// If there is already no cache entry for this object, there is no
+	// purpose in continuing
+	if ( !cache[ id ] ) {
+		return;
+	}
+
+	if ( name ) {
+
+		thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+		if ( thisCache ) {
+
+			// Support array or space separated string names for data keys
+			if ( !jQuery.isArray( name ) ) {
+
+				// try the string as a key before any manipulation
+				if ( name in thisCache ) {
+					name = [ name ];
+				} else {
+
+					// split the camel cased version by spaces unless a key with the spaces exists
+					name = jQuery.camelCase( name );
+					if ( name in thisCache ) {
+						name = [ name ];
+					} else {
+						name = name.split(" ");
+					}
+				}
+			} else {
+				// If "name" is an array of keys...
+				// When data is initially created, via ("key", "val") signature,
+				// keys will be converted to camelCase.
+				// Since there is no way to tell _how_ a key was added, remove
+				// both plain key and camelCase key. #12786
+				// This will only penalize the array argument path.
+				name = name.concat( jQuery.map( name, jQuery.camelCase ) );
+			}
+
+			i = name.length;
+			while ( i-- ) {
+				delete thisCache[ name[i] ];
+			}
+
+			// If there is no data left in the cache, we want to continue
+			// and let the cache object itself get destroyed
+			if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
+				return;
+			}
+		}
+	}
+
+	// See jQuery.data for more information
+	if ( !pvt ) {
+		delete cache[ id ].data;
+
+		// Don't destroy the parent cache unless the internal data object
+		// had been the only thing left in it
+		if ( !isEmptyDataObject( cache[ id ] ) ) {
+			return;
+		}
+	}
+
+	// Destroy the cache
+	if ( isNode ) {
+		jQuery.cleanData( [ elem ], true );
+
+	// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+	/* jshint eqeqeq: false */
+	} else if ( support.deleteExpando || cache != cache.window ) {
+		/* jshint eqeqeq: true */
+		delete cache[ id ];
+
+	// When all else fails, null
+	} else {
+		cache[ id ] = null;
+	}
+}
+
+jQuery.extend({
+	cache: {},
+
+	// The following elements (space-suffixed to avoid Object.prototype collisions)
+	// throw uncatchable exceptions if you attempt to set expando properties
+	noData: {
+		"applet ": true,
+		"embed ": true,
+		// ...but Flash objects (which have this classid) *can* handle expandos
+		"object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
+	},
+
+	hasData: function( elem ) {
+		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+		return !!elem && !isEmptyDataObject( elem );
+	},
+
+	data: function( elem, name, data ) {
+		return internalData( elem, name, data );
+	},
+
+	removeData: function( elem, name ) {
+		return internalRemoveData( elem, name );
+	},
+
+	// For internal use only.
+	_data: function( elem, name, data ) {
+		return internalData( elem, name, data, true );
+	},
+
+	_removeData: function( elem, name ) {
+		return internalRemoveData( elem, name, true );
+	}
+});
+
+jQuery.fn.extend({
+	data: function( key, value ) {
+		var i, name, data,
+			elem = this[0],
+			attrs = elem && elem.attributes;
+
+		// Special expections of .data basically thwart jQuery.access,
+		// so implement the relevant behavior ourselves
+
+		// Gets all values
+		if ( key === undefined ) {
+			if ( this.length ) {
+				data = jQuery.data( elem );
+
+				if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+					i = attrs.length;
+					while ( i-- ) {
+						name = attrs[i].name;
+
+						if ( name.indexOf("data-") === 0 ) {
+							name = jQuery.camelCase( name.slice(5) );
+
+							dataAttr( elem, name, data[ name ] );
+						}
+					}
+					jQuery._data( elem, "parsedAttrs", true );
+				}
+			}
+
+			return data;
+		}
+
+		// Sets multiple values
+		if ( typeof key === "object" ) {
+			return this.each(function() {
+				jQuery.data( this, key );
+			});
+		}
+
+		return arguments.length > 1 ?
+
+			// Sets one value
+			this.each(function() {
+				jQuery.data( this, key, value );
+			}) :
+
+			// Gets one value
+			// Try to fetch any internally stored data first
+			elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
+	},
+
+	removeData: function( key ) {
+		return this.each(function() {
+			jQuery.removeData( this, key );
+		});
+	}
+});
+
+
+jQuery.extend({
+	queue: function( elem, type, data ) {
+		var queue;
+
+		if ( elem ) {
+			type = ( type || "fx" ) + "queue";
+			queue = jQuery._data( elem, type );
+
+			// Speed up dequeue by getting out quickly if this is just a lookup
+			if ( data ) {
+				if ( !queue || jQuery.isArray(data) ) {
+					queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+				} else {
+					queue.push( data );
+				}
+			}
+			return queue || [];
+		}
+	},
+
+	dequeue: function( elem, type ) {
+		type = type || "fx";
+
+		var queue = jQuery.queue( elem, type ),
+			startLength = queue.length,
+			fn = queue.shift(),
+			hooks = jQuery._queueHooks( elem, type ),
+			next = function() {
+				jQuery.dequeue( elem, type );
+			};
+
+		// If the fx queue is dequeued, always remove the progress sentinel
+		if ( fn === "inprogress" ) {
+			fn = queue.shift();
+			startLength--;
+		}
+
+		if ( fn ) {
+
+			// Add a progress sentinel to prevent the fx queue from being
+			// automatically dequeued
+			if ( type === "fx" ) {
+				queue.unshift( "inprogress" );
+			}
+
+			// clear up the last queue stop function
+			delete hooks.stop;
+			fn.call( elem, next, hooks );
+		}
+
+		if ( !startLength && hooks ) {
+			hooks.empty.fire();
+		}
+	},
+
+	// not intended for public consumption - generates a queueHooks object, or returns the current one
+	_queueHooks: function( elem, type ) {
+		var key = type + "queueHooks";
+		return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+			empty: jQuery.Callbacks("once memory").add(function() {
+				jQuery._removeData( elem, type + "queue" );
+				jQuery._removeData( elem, key );
+			})
+		});
+	}
+});
+
+jQuery.fn.extend({
+	queue: function( type, data ) {
+		var setter = 2;
+
+		if ( typeof type !== "string" ) {
+			data = type;
+			type = "fx";
+			setter--;
+		}
+
+		if ( arguments.length < setter ) {
+			return jQuery.queue( this[0], type );
+		}
+
+		return data === undefined ?
+			this :
+			this.each(function() {
+				var queue = jQuery.queue( this, type, data );
+
+				// ensure a hooks for this queue
+				jQuery._queueHooks( this, type );
+
+				if ( type === "fx" && queue[0] !== "inprogress" ) {
+					jQuery.dequeue( this, type );
+				}
+			});
+	},
+	dequeue: function( type ) {
+		return this.each(function() {
+			jQuery.dequeue( this, type );
+		});
+	},
+	clearQueue: function( type ) {
+		return this.queue( type || "fx", [] );
+	},
+	// Get a promise resolved when queues of a certain type
+	// are emptied (fx is the type by default)
+	promise: function( type, obj ) {
+		var tmp,
+			count = 1,
+			defer = jQuery.Deferred(),
+			elements = this,
+			i = this.length,
+			resolve = function() {
+				if ( !( --count ) ) {
+					defer.resolveWith( elements, [ elements ] );
+				}
+			};
+
+		if ( typeof type !== "string" ) {
+			obj = type;
+			type = undefined;
+		}
+		type = type || "fx";
+
+		while ( i-- ) {
+			tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+			if ( tmp && tmp.empty ) {
+				count++;
+				tmp.empty.add( resolve );
+			}
+		}
+		resolve();
+		return defer.promise( obj );
+	}
+});
+var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
+
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+var isHidden = function( elem, el ) {
+		// isHidden might be called from jQuery#filter function;
+		// in that case, element will be second argument
+		elem = el || elem;
+		return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+	};
+
+
+
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+	var i = 0,
+		length = elems.length,
+		bulk = key == null;
+
+	// Sets many values
+	if ( jQuery.type( key ) === "object" ) {
+		chainable = true;
+		for ( i in key ) {
+			jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+		}
+
+	// Sets one value
+	} else if ( value !== undefined ) {
+		chainable = true;
+
+		if ( !jQuery.isFunction( value ) ) {
+			raw = true;
+		}
+
+		if ( bulk ) {
+			// Bulk operations run against the entire set
+			if ( raw ) {
+				fn.call( elems, value );
+				fn = null;
+
+			// ...except when executing function values
+			} else {
+				bulk = fn;
+				fn = function( elem, key, value ) {
+					return bulk.call( jQuery( elem ), value );
+				};
+			}
+		}
+
+		if ( fn ) {
+			for ( ; i < length; i++ ) {
+				fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+			}
+		}
+	}
+
+	return chainable ?
+		elems :
+
+		// Gets
+		bulk ?
+			fn.call( elems ) :
+			length ? fn( elems[0], key ) : emptyGet;
+};
+var rcheckableType = (/^(?:checkbox|radio)$/i);
+
+
+
+(function() {
+	var fragment = document.createDocumentFragment(),
+		div = document.createElement("div"),
+		input = document.createElement("input");
+
+	// Setup
+	div.setAttribute( "className", "t" );
+	div.innerHTML = "  <link/><table></table><a href='/a'>a</a>";
+
+	// IE strips leading whitespace when .innerHTML is used
+	support.leadingWhitespace = div.firstChild.nodeType === 3;
+
+	// Make sure that tbody elements aren't automatically inserted
+	// IE will insert them into empty tables
+	support.tbody = !div.getElementsByTagName( "tbody" ).length;
+
+	// Make sure that link elements get serialized correctly by innerHTML
+	// This requires a wrapper element in IE
+	support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
+
+	// Makes sure cloning an html5 element does not cause problems
+	// Where outerHTML is undefined, this still works
+	support.html5Clone =
+		document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
+
+	// Check if a disconnected checkbox will retain its checked
+	// value of true after appended to the DOM (IE6/7)
+	input.type = "checkbox";
+	input.checked = true;
+	fragment.appendChild( input );
+	support.appendChecked = input.checked;
+
+	// Make sure textarea (and checkbox) defaultValue is properly cloned
+	// Support: IE6-IE11+
+	div.innerHTML = "<textarea>x</textarea>";
+	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+
+	// #11217 - WebKit loses check when the name is after the checked attribute
+	fragment.appendChild( div );
+	div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
+
+	// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
+	// old WebKit doesn't clone checked state correctly in fragments
+	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+	// Support: IE<9
+	// Opera does not clone events (and typeof div.attachEvent === undefined).
+	// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
+	support.noCloneEvent = true;
+	if ( div.attachEvent ) {
+		div.attachEvent( "onclick", function() {
+			support.noCloneEvent = false;
+		});
+
+		div.cloneNode( true ).click();
+	}
+
+	// Execute the test only if not already executed in another module.
+	if (support.deleteExpando == null) {
+		// Support: IE<9
+		support.deleteExpando = true;
+		try {
+			delete div.test;
+		} catch( e ) {
+			support.deleteExpando = false;
+		}
+	}
+
+	// Null elements to avoid leaks in IE.
+	fragment = div = input = null;
+})();
+
+
+(function() {
+	var i, eventName,
+		div = document.createElement( "div" );
+
+	// Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
+	for ( i in { submit: true, change: true, focusin: true }) {
+		eventName = "on" + i;
+
+		if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
+			// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
+			div.setAttribute( eventName, "t" );
+			support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
+		}
+	}
+
+	// Null elements to avoid leaks in IE.
+	div = null;
+})();
+
+
+var rformElems = /^(?:input|select|textarea)$/i,
+	rkeyEvent = /^key/,
+	rmouseEvent = /^(?:mouse|contextmenu)|click/,
+	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+
+function returnTrue() {
+	return true;
+}
+
+function returnFalse() {
+	return false;
+}
+
+function safeActiveElement() {
+	try {
+		return document.activeElement;
+	} catch ( err ) { }
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+	global: {},
+
+	add: function( elem, types, handler, data, selector ) {
+		var tmp, events, t, handleObjIn,
+			special, eventHandle, handleObj,
+			handlers, type, namespaces, origType,
+			elemData = jQuery._data( elem );
+
+		// Don't attach events to noData or text/comment nodes (but allow plain objects)
+		if ( !elemData ) {
+			return;
+		}
+
+		// Caller can pass in an object of custom data in lieu of the handler
+		if ( handler.handler ) {
+			handleObjIn = handler;
+			handler = handleObjIn.handler;
+			selector = handleObjIn.selector;
+		}
+
+		// Make sure that the handler has a unique ID, used to find/remove it later
+		if ( !handler.guid ) {
+			handler.guid = jQuery.guid++;
+		}
+
+		// Init the element's event structure and main handler, if this is the first
+		if ( !(events = elemData.events) ) {
+			events = elemData.events = {};
+		}
+		if ( !(eventHandle = elemData.handle) ) {
+			eventHandle = elemData.handle = function( e ) {
+				// Discard the second event of a jQuery.event.trigger() and
+				// when an event is called after a page has unloaded
+				return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
+					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+					undefined;
+			};
+			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+			eventHandle.elem = elem;
+		}
+
+		// Handle multiple events separated by a space
+		types = ( types || "" ).match( rnotwhite ) || [ "" ];
+		t = types.length;
+		while ( t-- ) {
+			tmp = rtypenamespace.exec( types[t] ) || [];
+			type = origType = tmp[1];
+			namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+			// There *must* be a type, no attaching namespace-only handlers
+			if ( !type ) {
+				continue;
+			}
+
+			// If event changes its type, use the special event handlers for the changed type
+			special = jQuery.event.special[ type ] || {};
+
+			// If selector defined, determine special event api type, otherwise given type
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+
+			// Update special based on newly reset type
+			special = jQuery.event.special[ type ] || {};
+
+			// handleObj is passed to all event handlers
+			handleObj = jQuery.extend({
+				type: type,
+				origType: origType,
+				data: data,
+				handler: handler,
+				guid: handler.guid,
+				selector: selector,
+				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+				namespace: namespaces.join(".")
+			}, handleObjIn );
+
+			// Init the event handler queue if we're the first
+			if ( !(handlers = events[ type ]) ) {
+				handlers = events[ type ] = [];
+				handlers.delegateCount = 0;
+
+				// Only use addEventListener/attachEvent if the special events handler returns false
+				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+					// Bind the global event handler to the element
+					if ( elem.addEventListener ) {
+						elem.addEventListener( type, eventHandle, false );
+
+					} else if ( elem.attachEvent ) {
+						elem.attachEvent( "on" + type, eventHandle );
+					}
+				}
+			}
+
+			if ( special.add ) {
+				special.add.call( elem, handleObj );
+
+				if ( !handleObj.handler.guid ) {
+					handleObj.handler.guid = handler.guid;
+				}
+			}
+
+			// Add to the element's handler list, delegates in front
+			if ( selector ) {
+				handlers.splice( handlers.delegateCount++, 0, handleObj );
+			} else {
+				handlers.push( handleObj );
+			}
+
+			// Keep track of which events have ever been used, for event optimization
+			jQuery.event.global[ type ] = true;
+		}
+
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	// Detach an event or set of events from an element
+	remove: function( elem, types, handler, selector, mappedTypes ) {
+		var j, handleObj, tmp,
+			origCount, t, events,
+			special, handlers, type,
+			namespaces, origType,
+			elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+		if ( !elemData || !(events = elemData.events) ) {
+			return;
+		}
+
+		// Once for each type.namespace in types; type may be omitted
+		types = ( types || "" ).match( rnotwhite ) || [ "" ];
+		t = types.length;
+		while ( t-- ) {
+			tmp = rtypenamespace.exec( types[t] ) || [];
+			type = origType = tmp[1];
+			namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+			// Unbind all events (on this namespace, if provided) for the element
+			if ( !type ) {
+				for ( type in events ) {
+					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+				}
+				continue;
+			}
+
+			special = jQuery.event.special[ type ] || {};
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+			handlers = events[ type ] || [];
+			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+			// Remove matching events
+			origCount = j = handlers.length;
+			while ( j-- ) {
+				handleObj = handlers[ j ];
+
+				if ( ( mappedTypes || origType === handleObj.origType ) &&
+					( !handler || handler.guid === handleObj.guid ) &&
+					( !tmp || tmp.test( handleObj.namespace ) ) &&
+					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+					handlers.splice( j, 1 );
+
+					if ( handleObj.selector ) {
+						handlers.delegateCount--;
+					}
+					if ( special.remove ) {
+						special.remove.call( elem, handleObj );
+					}
+				}
+			}
+
+			// Remove generic event handler if we removed something and no more handlers exist
+			// (avoids potential for endless recursion during removal of special event handlers)
+			if ( origCount && !handlers.length ) {
+				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+					jQuery.removeEvent( elem, type, elemData.handle );
+				}
+
+				delete events[ type ];
+			}
+		}
+
+		// Remove the expando if it's no longer used
+		if ( jQuery.isEmptyObject( events ) ) {
+			delete elemData.handle;
+
+			// removeData also checks for emptiness and clears the expando if empty
+			// so use it instead of delete
+			jQuery._removeData( elem, "events" );
+		}
+	},
+
+	trigger: function( event, data, elem, onlyHandlers ) {
+		var handle, ontype, cur,
+			bubbleType, special, tmp, i,
+			eventPath = [ elem || document ],
+			type = hasOwn.call( event, "type" ) ? event.type : event,
+			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
+
+		cur = tmp = elem = elem || document;
+
+		// Don't do events on text and comment nodes
+		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return;
+		}
+
+		// focus/blur morphs to focusin/out; ensure we're not firing them right now
+		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+			return;
+		}
+
+		if ( type.indexOf(".") >= 0 ) {
+			// Namespaced trigger; create a regexp to match event type in handle()
+			namespaces = type.split(".");
+			type = namespaces.shift();
+			namespaces.sort();
+		}
+		ontype = type.indexOf(":") < 0 && "on" + type;
+
+		// Caller can pass in a jQuery.Event object, Object, or just an event type string
+		event = event[ jQuery.expando ] ?
+			event :
+			new jQuery.Event( type, typeof event === "object" && event );
+
+		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+		event.isTrigger = onlyHandlers ? 2 : 3;
+		event.namespace = namespaces.join(".");
+		event.namespace_re = event.namespace ?
+			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+			null;
+
+		// Clean up the event in case it is being reused
+		event.result = undefined;
+		if ( !event.target ) {
+			event.target = elem;
+		}
+
+		// Clone any incoming data and prepend the event, creating the handler arg list
+		data = data == null ?
+			[ event ] :
+			jQuery.makeArray( data, [ event ] );
+
+		// Allow special events to draw outside the lines
+		special = jQuery.event.special[ type ] || {};
+		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+			return;
+		}
+
+		// Determine event propagation path in advance, per W3C events spec (#9951)
+		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+			bubbleType = special.delegateType || type;
+			if ( !rfocusMorph.test( bubbleType + type ) ) {
+				cur = cur.parentNode;
+			}
+			for ( ; cur; cur = cur.parentNode ) {
+				eventPath.push( cur );
+				tmp = cur;
+			}
+
+			// Only add window if we got to document (e.g., not plain obj or detached DOM)
+			if ( tmp === (elem.ownerDocument || document) ) {
+				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+			}
+		}
+
+		// Fire handlers on the event path
+		i = 0;
+		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
+
+			event.type = i > 1 ?
+				bubbleType :
+				special.bindType || type;
+
+			// jQuery handler
+			handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+			if ( handle ) {
+				handle.apply( cur, data );
+			}
+
+			// Native handler
+			handle = ontype && cur[ ontype ];
+			if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
+				event.result = handle.apply( cur, data );
+				if ( event.result === false ) {
+					event.preventDefault();
+				}
+			}
+		}
+		event.type = type;
+
+		// If nobody prevented the default action, do it now
+		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+			if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
+				jQuery.acceptData( elem ) ) {
+
+				// Call a native DOM method on the target with the same name name as the event.
+				// Can't use an .isFunction() check here because IE6/7 fails that test.
+				// Don't do default actions on window, that's where global variables be (#6170)
+				if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
+
+					// Don't re-trigger an onFOO event when we call its FOO() method
+					tmp = elem[ ontype ];
+
+					if ( tmp ) {
+						elem[ ontype ] = null;
+					}
+
+					// Prevent re-triggering of the same event, since we already bubbled it above
+					jQuery.event.triggered = type;
+					try {
+						elem[ type ]();
+					} catch ( e ) {
+						// IE<9 dies on focus/blur to hidden element (#1486,#12518)
+						// only reproducible on winXP IE8 native, not IE9 in IE8 mode
+					}
+					jQuery.event.triggered = undefined;
+
+					if ( tmp ) {
+						elem[ ontype ] = tmp;
+					}
+				}
+			}
+		}
+
+		return event.result;
+	},
+
+	dispatch: function( event ) {
+
+		// Make a writable jQuery.Event from the native event object
+		event = jQuery.event.fix( event );
+
+		var i, ret, handleObj, matched, j,
+			handlerQueue = [],
+			args = slice.call( arguments ),
+			handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
+			special = jQuery.event.special[ event.type ] || {};
+
+		// Use the fix-ed jQuery.Event rather than the (read-only) native event
+		args[0] = event;
+		event.delegateTarget = this;
+
+		// Call the preDispatch hook for the mapped type, and let it bail if desired
+		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+			return;
+		}
+
+		// Determine handlers
+		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+		// Run delegates first; they may want to stop propagation beneath us
+		i = 0;
+		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+			event.currentTarget = matched.elem;
+
+			j = 0;
+			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+
+				// Triggered event must either 1) have no namespace, or
+				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+
+					event.handleObj = handleObj;
+					event.data = handleObj.data;
+
+					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+							.apply( matched.elem, args );
+
+					if ( ret !== undefined ) {
+						if ( (event.result = ret) === false ) {
+							event.preventDefault();
+							event.stopPropagation();
+						}
+					}
+				}
+			}
+		}
+
+		// Call the postDispatch hook for the mapped type
+		if ( special.postDispatch ) {
+			special.postDispatch.call( this, event );
+		}
+
+		return event.result;
+	},
+
+	handlers: function( event, handlers ) {
+		var sel, handleObj, matches, i,
+			handlerQueue = [],
+			delegateCount = handlers.delegateCount,
+			cur = event.target;
+
+		// Find delegate handlers
+		// Black-hole SVG <use> instance trees (#13180)
+		// Avoid non-left-click bubbling in Firefox (#3861)
+		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
+
+			/* jshint eqeqeq: false */
+			for ( ; cur != this; cur = cur.parentNode || this ) {
+				/* jshint eqeqeq: true */
+
+				// Don't check non-elements (#13208)
+				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+				if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
+					matches = [];
+					for ( i = 0; i < delegateCount; i++ ) {
+						handleObj = handlers[ i ];
+
+						// Don't conflict with Object.prototype properties (#13203)
+						sel = handleObj.selector + " ";
+
+						if ( matches[ sel ] === undefined ) {
+							matches[ sel ] = handleObj.needsContext ?
+								jQuery( sel, this ).index( cur ) >= 0 :
+								jQuery.find( sel, this, null, [ cur ] ).length;
+						}
+						if ( matches[ sel ] ) {
+							matches.push( handleObj );
+						}
+					}
+					if ( matches.length ) {
+						handlerQueue.push({ elem: cur, handlers: matches });
+					}
+				}
+			}
+		}
+
+		// Add the remaining (directly-bound) handlers
+		if ( delegateCount < handlers.length ) {
+			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+		}
+
+		return handlerQueue;
+	},
+
+	fix: function( event ) {
+		if ( event[ jQuery.expando ] ) {
+			return event;
+		}
+
+		// Create a writable copy of the event object and normalize some properties
+		var i, prop, copy,
+			type = event.type,
+			originalEvent = event,
+			fixHook = this.fixHooks[ type ];
+
+		if ( !fixHook ) {
+			this.fixHooks[ type ] = fixHook =
+				rmouseEvent.test( type ) ? this.mouseHooks :
+				rkeyEvent.test( type ) ? this.keyHooks :
+				{};
+		}
+		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+		event = new jQuery.Event( originalEvent );
+
+		i = copy.length;
+		while ( i-- ) {
+			prop = copy[ i ];
+			event[ prop ] = originalEvent[ prop ];
+		}
+
+		// Support: IE<9
+		// Fix target property (#1925)
+		if ( !event.target ) {
+			event.target = originalEvent.srcElement || document;
+		}
+
+		// Support: Chrome 23+, Safari?
+		// Target should not be a text node (#504, #13143)
+		if ( event.target.nodeType === 3 ) {
+			event.target = event.target.parentNode;
+		}
+
+		// Support: IE<9
+		// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
+		event.metaKey = !!event.metaKey;
+
+		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+	},
+
+	// Includes some event props shared by KeyEvent and MouseEvent
+	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+	fixHooks: {},
+
+	keyHooks: {
+		props: "char charCode key keyCode".split(" "),
+		filter: function( event, original ) {
+
+			// Add which for key events
+			if ( event.which == null ) {
+				event.which = original.charCode != null ? original.charCode : original.keyCode;
+			}
+
+			return event;
+		}
+	},
+
+	mouseHooks: {
+		props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+		filter: function( event, original ) {
+			var body, eventDoc, doc,
+				button = original.button,
+				fromElement = original.fromElement;
+
+			// Calculate pageX/Y if missing and clientX/Y available
+			if ( event.pageX == null && original.clientX != null ) {
+				eventDoc = event.target.ownerDocument || document;
+				doc = eventDoc.documentElement;
+				body = eventDoc.body;
+
+				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
+			}
+
+			// Add relatedTarget, if necessary
+			if ( !event.relatedTarget && fromElement ) {
+				event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+			}
+
+			// Add which for click: 1 === left; 2 === middle; 3 === right
+			// Note: button is not normalized, so don't use it
+			if ( !event.which && button !== undefined ) {
+				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+			}
+
+			return event;
+		}
+	},
+
+	special: {
+		load: {
+			// Prevent triggered image.load events from bubbling to window.load
+			noBubble: true
+		},
+		focus: {
+			// Fire native event if possible so blur/focus sequence is correct
+			trigger: function() {
+				if ( this !== safeActiveElement() && this.focus ) {
+					try {
+						this.focus();
+						return false;
+					} catch ( e ) {
+						// Support: IE<9
+						// If we error on focus to hidden element (#1486, #12518),
+						// let .trigger() run the handlers
+					}
+				}
+			},
+			delegateType: "focusin"
+		},
+		blur: {
+			trigger: function() {
+				if ( this === safeActiveElement() && this.blur ) {
+					this.blur();
+					return false;
+				}
+			},
+			delegateType: "focusout"
+		},
+		click: {
+			// For checkbox, fire native event so checked state will be right
+			trigger: function() {
+				if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
+					this.click();
+					return false;
+				}
+			},
+
+			// For cross-browser consistency, don't fire native .click() on links
+			_default: function( event ) {
+				return jQuery.nodeName( event.target, "a" );
+			}
+		},
+
+		beforeunload: {
+			postDispatch: function( event ) {
+
+				// Even when returnValue equals to undefined Firefox will still show alert
+				if ( event.result !== undefined ) {
+					event.originalEvent.returnValue = event.result;
+				}
+			}
+		}
+	},
+
+	simulate: function( type, elem, event, bubble ) {
+		// Piggyback on a donor event to simulate a different one.
+		// Fake originalEvent to avoid donor's stopPropagation, but if the
+		// simulated event prevents default then we do the same on the donor.
+		var e = jQuery.extend(
+			new jQuery.Event(),
+			event,
+			{
+				type: type,
+				isSimulated: true,
+				originalEvent: {}
+			}
+		);
+		if ( bubble ) {
+			jQuery.event.trigger( e, null, elem );
+		} else {
+			jQuery.event.dispatch.call( elem, e );
+		}
+		if ( e.isDefaultPrevented() ) {
+			event.preventDefault();
+		}
+	}
+};
+
+jQuery.removeEvent = document.removeEventListener ?
+	function( elem, type, handle ) {
+		if ( elem.removeEventListener ) {
+			elem.removeEventListener( type, handle, false );
+		}
+	} :
+	function( elem, type, handle ) {
+		var name = "on" + type;
+
+		if ( elem.detachEvent ) {
+
+			// #8545, #7054, preventing memory leaks for custom events in IE6-8
+			// detachEvent needed property on element, by name of that event, to properly expose it to GC
+			if ( typeof elem[ name ] === strundefined ) {
+				elem[ name ] = null;
+			}
+
+			elem.detachEvent( name, handle );
+		}
+	};
+
+jQuery.Event = function( src, props ) {
+	// Allow instantiation without the 'new' keyword
+	if ( !(this instanceof jQuery.Event) ) {
+		return new jQuery.Event( src, props );
+	}
+
+	// Event object
+	if ( src && src.type ) {
+		this.originalEvent = src;
+		this.type = src.type;
+
+		// Events bubbling up the document may have been marked as prevented
+		// by a handler lower down the tree; reflect the correct value.
+		this.isDefaultPrevented = src.defaultPrevented ||
+				src.defaultPrevented === undefined && (
+				// Support: IE < 9
+				src.returnValue === false ||
+				// Support: Android < 4.0
+				src.getPreventDefault && src.getPreventDefault() ) ?
+			returnTrue :
+			returnFalse;
+
+	// Event type
+	} else {
+		this.type = src;
+	}
+
+	// Put explicitly provided properties onto the event object
+	if ( props ) {
+		jQuery.extend( this, props );
+	}
+
+	// Create a timestamp if incoming event doesn't have one
+	this.timeStamp = src && src.timeStamp || jQuery.now();
+
+	// Mark it as fixed
+	this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+	isDefaultPrevented: returnFalse,
+	isPropagationStopped: returnFalse,
+	isImmediatePropagationStopped: returnFalse,
+
+	preventDefault: function() {
+		var e = this.originalEvent;
+
+		this.isDefaultPrevented = returnTrue;
+		if ( !e ) {
+			return;
+		}
+
+		// If preventDefault exists, run it on the original event
+		if ( e.preventDefault ) {
+			e.preventDefault();
+
+		// Support: IE
+		// Otherwise set the returnValue property of the original event to false
+		} else {
+			e.returnValue = false;
+		}
+	},
+	stopPropagation: function() {
+		var e = this.originalEvent;
+
+		this.isPropagationStopped = returnTrue;
+		if ( !e ) {
+			return;
+		}
+		// If stopPropagation exists, run it on the original event
+		if ( e.stopPropagation ) {
+			e.stopPropagation();
+		}
+
+		// Support: IE
+		// Set the cancelBubble property of the original event to true
+		e.cancelBubble = true;
+	},
+	stopImmediatePropagation: function() {
+		this.isImmediatePropagationStopped = returnTrue;
+		this.stopPropagation();
+	}
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+	mouseenter: "mouseover",
+	mouseleave: "mouseout"
+}, function( orig, fix ) {
+	jQuery.event.special[ orig ] = {
+		delegateType: fix,
+		bindType: fix,
+
+		handle: function( event ) {
+			var ret,
+				target = this,
+				related = event.relatedTarget,
+				handleObj = event.handleObj;
+
+			// For mousenter/leave call the handler if related is outside the target.
+			// NB: No relatedTarget if the mouse left/entered the browser window
+			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+				event.type = handleObj.origType;
+				ret = handleObj.handler.apply( this, arguments );
+				event.type = fix;
+			}
+			return ret;
+		}
+	};
+});
+
+// IE submit delegation
+if ( !support.submitBubbles ) {
+
+	jQuery.event.special.submit = {
+		setup: function() {
+			// Only need this for delegated form submit events
+			if ( jQuery.nodeName( this, "form" ) ) {
+				return false;
+			}
+
+			// Lazy-add a submit handler when a descendant form may potentially be submitted
+			jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+				// Node name check avoids a VML-related crash in IE (#9807)
+				var elem = e.target,
+					form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+				if ( form && !jQuery._data( form, "submitBubbles" ) ) {
+					jQuery.event.add( form, "submit._submit", function( event ) {
+						event._submit_bubble = true;
+					});
+					jQuery._data( form, "submitBubbles", true );
+				}
+			});
+			// return undefined since we don't need an event listener
+		},
+
+		postDispatch: function( event ) {
+			// If form was submitted by the user, bubble the event up the tree
+			if ( event._submit_bubble ) {
+				delete event._submit_bubble;
+				if ( this.parentNode && !event.isTrigger ) {
+					jQuery.event.simulate( "submit", this.parentNode, event, true );
+				}
+			}
+		},
+
+		teardown: function() {
+			// Only need this for delegated form submit events
+			if ( jQuery.nodeName( this, "form" ) ) {
+				return false;
+			}
+
+			// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+			jQuery.event.remove( this, "._submit" );
+		}
+	};
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !support.changeBubbles ) {
+
+	jQuery.event.special.change = {
+
+		setup: function() {
+
+			if ( rformElems.test( this.nodeName ) ) {
+				// IE doesn't fire change on a check/radio until blur; trigger it on click
+				// after a propertychange. Eat the blur-change in special.change.handle.
+				// This still fires onchange a second time for check/radio after blur.
+				if ( this.type === "checkbox" || this.type === "radio" ) {
+					jQuery.event.add( this, "propertychange._change", function( event ) {
+						if ( event.originalEvent.propertyName === "checked" ) {
+							this._just_changed = true;
+						}
+					});
+					jQuery.event.add( this, "click._change", function( event ) {
+						if ( this._just_changed && !event.isTrigger ) {
+							this._just_changed = false;
+						}
+						// Allow triggered, simulated change events (#11500)
+						jQuery.event.simulate( "change", this, event, true );
+					});
+				}
+				return false;
+			}
+			// Delegated event; lazy-add a change handler on descendant inputs
+			jQuery.event.add( this, "beforeactivate._change", function( e ) {
+				var elem = e.target;
+
+				if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
+					jQuery.event.add( elem, "change._change", function( event ) {
+						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+							jQuery.event.simulate( "change", this.parentNode, event, true );
+						}
+					});
+					jQuery._data( elem, "changeBubbles", true );
+				}
+			});
+		},
+
+		handle: function( event ) {
+			var elem = event.target;
+
+			// Swallow native change events from checkbox/radio, we already triggered them above
+			if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+				return event.handleObj.handler.apply( this, arguments );
+			}
+		},
+
+		teardown: function() {
+			jQuery.event.remove( this, "._change" );
+
+			return !rformElems.test( this.nodeName );
+		}
+	};
+}
+
+// Create "bubbling" focus and blur events
+if ( !support.focusinBubbles ) {
+	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+		// Attach a single capturing handler on the document while someone wants focusin/focusout
+		var handler = function( event ) {
+				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+			};
+
+		jQuery.event.special[ fix ] = {
+			setup: function() {
+				var doc = this.ownerDocument || this,
+					attaches = jQuery._data( doc, fix );
+
+				if ( !attaches ) {
+					doc.addEventListener( orig, handler, true );
+				}
+				jQuery._data( doc, fix, ( attaches || 0 ) + 1 );
+			},
+			teardown: function() {
+				var doc = this.ownerDocument || this,
+					attaches = jQuery._data( doc, fix ) - 1;
+
+				if ( !attaches ) {
+					doc.removeEventListener( orig, handler, true );
+					jQuery._removeData( doc, fix );
+				} else {
+					jQuery._data( doc, fix, attaches );
+				}
+			}
+		};
+	});
+}
+
+jQuery.fn.extend({
+
+	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+		var type, origFn;
+
+		// Types can be a map of types/handlers
+		if ( typeof types === "object" ) {
+			// ( types-Object, selector, data )
+			if ( typeof selector !== "string" ) {
+				// ( types-Object, data )
+				data = data || selector;
+				selector = undefined;
+			}
+			for ( type in types ) {
+				this.on( type, selector, data, types[ type ], one );
+			}
+			return this;
+		}
+
+		if ( data == null && fn == null ) {
+			// ( types, fn )
+			fn = selector;
+			data = selector = undefined;
+		} else if ( fn == null ) {
+			if ( typeof selector === "string" ) {
+				// ( types, selector, fn )
+				fn = data;
+				data = undefined;
+			} else {
+				// ( types, data, fn )
+				fn = data;
+				data = selector;
+				selector = undefined;
+			}
+		}
+		if ( fn === false ) {
+			fn = returnFalse;
+		} else if ( !fn ) {
+			return this;
+		}
+
+		if ( one === 1 ) {
+			origFn = fn;
+			fn = function( event ) {
+				// Can use an empty set, since event contains the info
+				jQuery().off( event );
+				return origFn.apply( this, arguments );
+			};
+			// Use same guid so caller can remove using origFn
+			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+		}
+		return this.each( function() {
+			jQuery.event.add( this, types, fn, data, selector );
+		});
+	},
+	one: function( types, selector, data, fn ) {
+		return this.on( types, selector, data, fn, 1 );
+	},
+	off: function( types, selector, fn ) {
+		var handleObj, type;
+		if ( types && types.preventDefault && types.handleObj ) {
+			// ( event )  dispatched jQuery.Event
+			handleObj = types.handleObj;
+			jQuery( types.delegateTarget ).off(
+				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+				handleObj.selector,
+				handleObj.handler
+			);
+			return this;
+		}
+		if ( typeof types === "object" ) {
+			// ( types-object [, selector] )
+			for ( type in types ) {
+				this.off( type, selector, types[ type ] );
+			}
+			return this;
+		}
+		if ( selector === false || typeof selector === "function" ) {
+			// ( types [, fn] )
+			fn = selector;
+			selector = undefined;
+		}
+		if ( fn === false ) {
+			fn = returnFalse;
+		}
+		return this.each(function() {
+			jQuery.event.remove( this, types, fn, selector );
+		});
+	},
+
+	trigger: function( type, data ) {
+		return this.each(function() {
+			jQuery.event.trigger( type, data, this );
+		});
+	},
+	triggerHandler: function( type, data ) {
+		var elem = this[0];
+		if ( elem ) {
+			return jQuery.event.trigger( type, data, elem, true );
+		}
+	}
+});
+
+
+function createSafeFragment( document ) {
+	var list = nodeNames.split( "|" ),
+		safeFrag = document.createDocumentFragment();
+
+	if ( safeFrag.createElement ) {
+		while ( list.length ) {
+			safeFrag.createElement(
+				list.pop()
+			);
+		}
+	}
+	return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+	rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
+	rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+	rleadingWhitespace = /^\s+/,
+	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+	rtagName = /<([\w:]+)/,
+	rtbody = /<tbody/i,
+	rhtml = /<|&#?\w+;/,
+	rnoInnerhtml = /<(?:script|style|link)/i,
+	// checked="checked" or checked
+	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+	rscriptType = /^$|\/(?:java|ecma)script/i,
+	rscriptTypeMasked = /^true\/(.*)/,
+	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
+
+	// We have to close these tags to support XHTML (#13200)
+	wrapMap = {
+		option: [ 1, "<select multiple='multiple'>", "</select>" ],
+		legend: [ 1, "<fieldset>", "</fieldset>" ],
+		area: [ 1, "<map>", "</map>" ],
+		param: [ 1, "<object>", "</object>" ],
+		thead: [ 1, "<table>", "</table>" ],
+		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+		// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
+		// unless wrapped in a div with non-breaking characters in front of it.
+		_default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>"  ]
+	},
+	safeFragment = createSafeFragment( document ),
+	fragmentDiv = safeFragment.appendChild( document.createElement("div") );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+function getAll( context, tag ) {
+	var elems, elem,
+		i = 0,
+		found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
+			typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
+			undefined;
+
+	if ( !found ) {
+		for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
+			if ( !tag || jQuery.nodeName( elem, tag ) ) {
+				found.push( elem );
+			} else {
+				jQuery.merge( found, getAll( elem, tag ) );
+			}
+		}
+	}
+
+	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+		jQuery.merge( [ context ], found ) :
+		found;
+}
+
+// Used in buildFragment, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+	if ( rcheckableType.test( elem.type ) ) {
+		elem.defaultChecked = elem.checked;
+	}
+}
+
+// Support: IE<8
+// Manipulating tables requires a tbody
+function manipulationTarget( elem, content ) {
+	return jQuery.nodeName( elem, "table" ) &&
+		jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
+
+		elem.getElementsByTagName("tbody")[0] ||
+			elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
+		elem;
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+	elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
+	return elem;
+}
+function restoreScript( elem ) {
+	var match = rscriptTypeMasked.exec( elem.type );
+	if ( match ) {
+		elem.type = match[1];
+	} else {
+		elem.removeAttribute("type");
+	}
+	return elem;
+}
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+	var elem,
+		i = 0;
+	for ( ; (elem = elems[i]) != null; i++ ) {
+		jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
+	}
+}
+
+function cloneCopyEvent( src, dest ) {
+
+	if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+		return;
+	}
+
+	var type, i, l,
+		oldData = jQuery._data( src ),
+		curData = jQuery._data( dest, oldData ),
+		events = oldData.events;
+
+	if ( events ) {
+		delete curData.handle;
+		curData.events = {};
+
+		for ( type in events ) {
+			for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+				jQuery.event.add( dest, type, events[ type ][ i ] );
+			}
+		}
+	}
+
+	// make the cloned public data object a copy from the original
+	if ( curData.data ) {
+		curData.data = jQuery.extend( {}, curData.data );
+	}
+}
+
+function fixCloneNodeIssues( src, dest ) {
+	var nodeName, e, data;
+
+	// We do not need to do anything for non-Elements
+	if ( dest.nodeType !== 1 ) {
+		return;
+	}
+
+	nodeName = dest.nodeName.toLowerCase();
+
+	// IE6-8 copies events bound via attachEvent when using cloneNode.
+	if ( !support.noCloneEvent && dest[ jQuery.expando ] ) {
+		data = jQuery._data( dest );
+
+		for ( e in data.events ) {
+			jQuery.removeEvent( dest, e, data.handle );
+		}
+
+		// Event data gets referenced instead of copied if the expando gets copied too
+		dest.removeAttribute( jQuery.expando );
+	}
+
+	// IE blanks contents when cloning scripts, and tries to evaluate newly-set text
+	if ( nodeName === "script" && dest.text !== src.text ) {
+		disableScript( dest ).text = src.text;
+		restoreScript( dest );
+
+	// IE6-10 improperly clones children of object elements using classid.
+	// IE10 throws NoModificationAllowedError if parent is null, #12132.
+	} else if ( nodeName === "object" ) {
+		if ( dest.parentNode ) {
+			dest.outerHTML = src.outerHTML;
+		}
+
+		// This path appears unavoidable for IE9. When cloning an object
+		// element in IE9, the outerHTML strategy above is not sufficient.
+		// If the src has innerHTML and the destination does not,
+		// copy the src.innerHTML into the dest.innerHTML. #10324
+		if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
+			dest.innerHTML = src.innerHTML;
+		}
+
+	} else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+		// IE6-8 fails to persist the checked state of a cloned checkbox
+		// or radio button. Worse, IE6-7 fail to give the cloned element
+		// a checked appearance if the defaultChecked value isn't also set
+
+		dest.defaultChecked = dest.checked = src.checked;
+
+		// IE6-7 get confused and end up setting the value of a cloned
+		// checkbox/radio button to an empty string instead of "on"
+		if ( dest.value !== src.value ) {
+			dest.value = src.value;
+		}
+
+	// IE6-8 fails to return the selected option to the default selected
+	// state when cloning options
+	} else if ( nodeName === "option" ) {
+		dest.defaultSelected = dest.selected = src.defaultSelected;
+
+	// IE6-8 fails to set the defaultValue to the correct value when
+	// cloning other types of input fields
+	} else if ( nodeName === "input" || nodeName === "textarea" ) {
+		dest.defaultValue = src.defaultValue;
+	}
+}
+
+jQuery.extend({
+	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+		var destElements, node, clone, i, srcElements,
+			inPage = jQuery.contains( elem.ownerDocument, elem );
+
+		if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
+			clone = elem.cloneNode( true );
+
+		// IE<=8 does not properly clone detached, unknown element nodes
+		} else {
+			fragmentDiv.innerHTML = elem.outerHTML;
+			fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+		}
+
+		if ( (!support.noCloneEvent || !support.noCloneChecked) &&
+				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+
+			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+			destElements = getAll( clone );
+			srcElements = getAll( elem );
+
+			// Fix all IE cloning issues
+			for ( i = 0; (node = srcElements[i]) != null; ++i ) {
+				// Ensure that the destination node is not null; Fixes #9587
+				if ( destElements[i] ) {
+					fixCloneNodeIssues( node, destElements[i] );
+				}
+			}
+		}
+
+		// Copy the events from the original to the clone
+		if ( dataAndEvents ) {
+			if ( deepDataAndEvents ) {
+				srcElements = srcElements || getAll( elem );
+				destElements = destElements || getAll( clone );
+
+				for ( i = 0; (node = srcElements[i]) != null; i++ ) {
+					cloneCopyEvent( node, destElements[i] );
+				}
+			} else {
+				cloneCopyEvent( elem, clone );
+			}
+		}
+
+		// Preserve script evaluation history
+		destElements = getAll( clone, "script" );
+		if ( destElements.length > 0 ) {
+			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+		}
+
+		destElements = srcElements = node = null;
+
+		// Return the cloned set
+		return clone;
+	},
+
+	buildFragment: function( elems, context, scripts, selection ) {
+		var j, elem, contains,
+			tmp, tag, tbody, wrap,
+			l = elems.length,
+
+			// Ensure a safe fragment
+			safe = createSafeFragment( context ),
+
+			nodes = [],
+			i = 0;
+
+		for ( ; i < l; i++ ) {
+			elem = elems[ i ];
+
+			if ( elem || elem === 0 ) {
+
+				// Add nodes directly
+				if ( jQuery.type( elem ) === "object" ) {
+					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+				// Convert non-html into a text node
+				} else if ( !rhtml.test( elem ) ) {
+					nodes.push( context.createTextNode( elem ) );
+
+				// Convert html into DOM nodes
+				} else {
+					tmp = tmp || safe.appendChild( context.createElement("div") );
+
+					// Deserialize a standard representation
+					tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
+					wrap = wrapMap[ tag ] || wrapMap._default;
+
+					tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
+
+					// Descend through wrappers to the right content
+					j = wrap[0];
+					while ( j-- ) {
+						tmp = tmp.lastChild;
+					}
+
+					// Manually add leading whitespace removed by IE
+					if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+						nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
+					}
+
+					// Remove IE's autoinserted <tbody> from table fragments
+					if ( !support.tbody ) {
+
+						// String was a <table>, *may* have spurious <tbody>
+						elem = tag === "table" && !rtbody.test( elem ) ?
+							tmp.firstChild :
+
+							// String was a bare <thead> or <tfoot>
+							wrap[1] === "<table>" && !rtbody.test( elem ) ?
+								tmp :
+								0;
+
+						j = elem && elem.childNodes.length;
+						while ( j-- ) {
+							if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
+								elem.removeChild( tbody );
+							}
+						}
+					}
+
+					jQuery.merge( nodes, tmp.childNodes );
+
+					// Fix #12392 for WebKit and IE > 9
+					tmp.textContent = "";
+
+					// Fix #12392 for oldIE
+					while ( tmp.firstChild ) {
+						tmp.removeChild( tmp.firstChild );
+					}
+
+					// Remember the top-level container for proper cleanup
+					tmp = safe.lastChild;
+				}
+			}
+		}
+
+		// Fix #11356: Clear elements from fragment
+		if ( tmp ) {
+			safe.removeChild( tmp );
+		}
+
+		// Reset defaultChecked for any radios and checkboxes
+		// about to be appended to the DOM in IE 6/7 (#8060)
+		if ( !support.appendChecked ) {
+			jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
+		}
+
+		i = 0;
+		while ( (elem = nodes[ i++ ]) ) {
+
+			// #4087 - If origin and destination elements are the same, and this is
+			// that element, do not do anything
+			if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
+				continue;
+			}
+
+			contains = jQuery.contains( elem.ownerDocument, elem );
+
+			// Append to fragment
+			tmp = getAll( safe.appendChild( elem ), "script" );
+
+			// Preserve script evaluation history
+			if ( contains ) {
+				setGlobalEval( tmp );
+			}
+
+			// Capture executables
+			if ( scripts ) {
+				j = 0;
+				while ( (elem = tmp[ j++ ]) ) {
+					if ( rscriptType.test( elem.type || "" ) ) {
+						scripts.push( elem );
+					}
+				}
+			}
+		}
+
+		tmp = null;
+
+		return safe;
+	},
+
+	cleanData: function( elems, /* internal */ acceptData ) {
+		var elem, type, id, data,
+			i = 0,
+			internalKey = jQuery.expando,
+			cache = jQuery.cache,
+			deleteExpando = support.deleteExpando,
+			special = jQuery.event.special;
+
+		for ( ; (elem = elems[i]) != null; i++ ) {
+			if ( acceptData || jQuery.acceptData( elem ) ) {
+
+				id = elem[ internalKey ];
+				data = id && cache[ id ];
+
+				if ( data ) {
+					if ( data.events ) {
+						for ( type in data.events ) {
+							if ( special[ type ] ) {
+								jQuery.event.remove( elem, type );
+
+							// This is a shortcut to avoid jQuery.event.remove's overhead
+							} else {
+								jQuery.removeEvent( elem, type, data.handle );
+							}
+						}
+					}
+
+					// Remove cache only if it was not already removed by jQuery.event.remove
+					if ( cache[ id ] ) {
+
+						delete cache[ id ];
+
+						// IE does not allow us to delete expando properties from nodes,
+						// nor does it have a removeAttribute function on Document nodes;
+						// we must handle all of these cases
+						if ( deleteExpando ) {
+							delete elem[ internalKey ];
+
+						} else if ( typeof elem.removeAttribute !== strundefined ) {
+							elem.removeAttribute( internalKey );
+
+						} else {
+							elem[ internalKey ] = null;
+						}
+
+						deletedIds.push( id );
+					}
+				}
+			}
+		}
+	}
+});
+
+jQuery.fn.extend({
+	text: function( value ) {
+		return access( this, function( value ) {
+			return value === undefined ?
+				jQuery.text( this ) :
+				this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+		}, null, value, arguments.length );
+	},
+
+	append: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+				var target = manipulationTarget( this, elem );
+				target.appendChild( elem );
+			}
+		});
+	},
+
+	prepend: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+				var target = manipulationTarget( this, elem );
+				target.insertBefore( elem, target.firstChild );
+			}
+		});
+	},
+
+	before: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.parentNode ) {
+				this.parentNode.insertBefore( elem, this );
+			}
+		});
+	},
+
+	after: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.parentNode ) {
+				this.parentNode.insertBefore( elem, this.nextSibling );
+			}
+		});
+	},
+
+	remove: function( selector, keepData /* Internal Use Only */ ) {
+		var elem,
+			elems = selector ? jQuery.filter( selector, this ) : this,
+			i = 0;
+
+		for ( ; (elem = elems[i]) != null; i++ ) {
+
+			if ( !keepData && elem.nodeType === 1 ) {
+				jQuery.cleanData( getAll( elem ) );
+			}
+
+			if ( elem.parentNode ) {
+				if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
+					setGlobalEval( getAll( elem, "script" ) );
+				}
+				elem.parentNode.removeChild( elem );
+			}
+		}
+
+		return this;
+	},
+
+	empty: function() {
+		var elem,
+			i = 0;
+
+		for ( ; (elem = this[i]) != null; i++ ) {
+			// Remove element nodes and prevent memory leaks
+			if ( elem.nodeType === 1 ) {
+				jQuery.cleanData( getAll( elem, false ) );
+			}
+
+			// Remove any remaining nodes
+			while ( elem.firstChild ) {
+				elem.removeChild( elem.firstChild );
+			}
+
+			// If this is a select, ensure that it displays empty (#12336)
+			// Support: IE<9
+			if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
+				elem.options.length = 0;
+			}
+		}
+
+		return this;
+	},
+
+	clone: function( dataAndEvents, deepDataAndEvents ) {
+		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+		return this.map(function() {
+			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+		});
+	},
+
+	html: function( value ) {
+		return access( this, function( value ) {
+			var elem = this[ 0 ] || {},
+				i = 0,
+				l = this.length;
+
+			if ( value === undefined ) {
+				return elem.nodeType === 1 ?
+					elem.innerHTML.replace( rinlinejQuery, "" ) :
+					undefined;
+			}
+
+			// See if we can take a shortcut and just use innerHTML
+			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+				( support.htmlSerialize || !rnoshimcache.test( value )  ) &&
+				( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+				!wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
+
+				value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+				try {
+					for (; i < l; i++ ) {
+						// Remove element nodes and prevent memory leaks
+						elem = this[i] || {};
+						if ( elem.nodeType === 1 ) {
+							jQuery.cleanData( getAll( elem, false ) );
+							elem.innerHTML = value;
+						}
+					}
+
+					elem = 0;
+
+				// If using innerHTML throws an exception, use the fallback method
+				} catch(e) {}
+			}
+
+			if ( elem ) {
+				this.empty().append( value );
+			}
+		}, null, value, arguments.length );
+	},
+
+	replaceWith: function() {
+		var arg = arguments[ 0 ];
+
+		// Make the changes, replacing each context element with the new content
+		this.domManip( arguments, function( elem ) {
+			arg = this.parentNode;
+
+			jQuery.cleanData( getAll( this ) );
+
+			if ( arg ) {
+				arg.replaceChild( elem, this );
+			}
+		});
+
+		// Force removal if there was no new content (e.g., from empty arguments)
+		return arg && (arg.length || arg.nodeType) ? this : this.remove();
+	},
+
+	detach: function( selector ) {
+		return this.remove( selector, true );
+	},
+
+	domManip: function( args, callback ) {
+
+		// Flatten any nested arrays
+		args = concat.apply( [], args );
+
+		var first, node, hasScripts,
+			scripts, doc, fragment,
+			i = 0,
+			l = this.length,
+			set = this,
+			iNoClone = l - 1,
+			value = args[0],
+			isFunction = jQuery.isFunction( value );
+
+		// We can't cloneNode fragments that contain checked, in WebKit
+		if ( isFunction ||
+				( l > 1 && typeof value === "string" &&
+					!support.checkClone && rchecked.test( value ) ) ) {
+			return this.each(function( index ) {
+				var self = set.eq( index );
+				if ( isFunction ) {
+					args[0] = value.call( this, index, self.html() );
+				}
+				self.domManip( args, callback );
+			});
+		}
+
+		if ( l ) {
+			fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
+			first = fragment.firstChild;
+
+			if ( fragment.childNodes.length === 1 ) {
+				fragment = first;
+			}
+
+			if ( first ) {
+				scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+				hasScripts = scripts.length;
+
+				// Use the original fragment for the last item instead of the first because it can end up
+				// being emptied incorrectly in certain situations (#8070).
+				for ( ; i < l; i++ ) {
+					node = fragment;
+
+					if ( i !== iNoClone ) {
+						node = jQuery.clone( node, true, true );
+
+						// Keep references to cloned scripts for later restoration
+						if ( hasScripts ) {
+							jQuery.merge( scripts, getAll( node, "script" ) );
+						}
+					}
+
+					callback.call( this[i], node, i );
+				}
+
+				if ( hasScripts ) {
+					doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+					// Reenable scripts
+					jQuery.map( scripts, restoreScript );
+
+					// Evaluate executable scripts on first document insertion
+					for ( i = 0; i < hasScripts; i++ ) {
+						node = scripts[ i ];
+						if ( rscriptType.test( node.type || "" ) &&
+							!jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
+
+							if ( node.src ) {
+								// Optional AJAX dependency, but won't run scripts if not present
+								if ( jQuery._evalUrl ) {
+									jQuery._evalUrl( node.src );
+								}
+							} else {
+								jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
+							}
+						}
+					}
+				}
+
+				// Fix #11809: Avoid leaking memory
+				fragment = first = null;
+			}
+		}
+
+		return this;
+	}
+});
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function( name, original ) {
+	jQuery.fn[ name ] = function( selector ) {
+		var elems,
+			i = 0,
+			ret = [],
+			insert = jQuery( selector ),
+			last = insert.length - 1;
+
+		for ( ; i <= last; i++ ) {
+			elems = i === last ? this : this.clone(true);
+			jQuery( insert[i] )[ original ]( elems );
+
+			// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
+			push.apply( ret, elems.get() );
+		}
+
+		return this.pushStack( ret );
+	};
+});
+
+
+var iframe,
+	elemdisplay = {};
+
+/**
+ * Retrieve the actual display of a element
+ * @param {String} name nodeName of the element
+ * @param {Object} doc Document object
+ */
+// Called only from within defaultDisplay
+function actualDisplay( name, doc ) {
+	var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+
+		// getDefaultComputedStyle might be reliably used only on attached element
+		display = window.getDefaultComputedStyle ?
+
+			// Use of this method is a temporary fix (more like optmization) until something better comes along,
+			// since it was removed from specification and supported only in FF
+			window.getDefaultComputedStyle( elem[ 0 ] ).display : jQuery.css( elem[ 0 ], "display" );
+
+	// We don't have any data stored on the element,
+	// so use "detach" method as fast way to get rid of the element
+	elem.detach();
+
+	return display;
+}
+
+/**
+ * Try to determine the default display value of an element
+ * @param {String} nodeName
+ */
+function defaultDisplay( nodeName ) {
+	var doc = document,
+		display = elemdisplay[ nodeName ];
+
+	if ( !display ) {
+		display = actualDisplay( nodeName, doc );
+
+		// If the simple way fails, read from inside an iframe
+		if ( display === "none" || !display ) {
+
+			// Use the already-created iframe if possible
+			iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
+
+			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+			doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
+
+			// Support: IE
+			doc.write();
+			doc.close();
+
+			display = actualDisplay( nodeName, doc );
+			iframe.detach();
+		}
+
+		// Store the correct default display
+		elemdisplay[ nodeName ] = display;
+	}
+
+	return display;
+}
+
+
+(function() {
+	var a, shrinkWrapBlocksVal,
+		div = document.createElement( "div" ),
+		divReset =
+			"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;" +
+			"display:block;padding:0;margin:0;border:0";
+
+	// Setup
+	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+	a = div.getElementsByTagName( "a" )[ 0 ];
+
+	a.style.cssText = "float:left;opacity:.5";
+
+	// Make sure that element opacity exists
+	// (IE uses filter instead)
+	// Use a regex to work around a WebKit issue. See #5145
+	support.opacity = /^0.5/.test( a.style.opacity );
+
+	// Verify style float existence
+	// (IE uses styleFloat instead of cssFloat)
+	support.cssFloat = !!a.style.cssFloat;
+
+	div.style.backgroundClip = "content-box";
+	div.cloneNode( true ).style.backgroundClip = "";
+	support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+	// Null elements to avoid leaks in IE.
+	a = div = null;
+
+	support.shrinkWrapBlocks = function() {
+		var body, container, div, containerStyles;
+
+		if ( shrinkWrapBlocksVal == null ) {
+			body = document.getElementsByTagName( "body" )[ 0 ];
+			if ( !body ) {
+				// Test fired too early or in an unsupported environment, exit.
+				return;
+			}
+
+			containerStyles = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px";
+			container = document.createElement( "div" );
+			div = document.createElement( "div" );
+
+			body.appendChild( container ).appendChild( div );
+
+			// Will be changed later if needed.
+			shrinkWrapBlocksVal = false;
+
+			if ( typeof div.style.zoom !== strundefined ) {
+				// Support: IE6
+				// Check if elements with layout shrink-wrap their children
+				div.style.cssText = divReset + ";width:1px;padding:1px;zoom:1";
+				div.innerHTML = "<div></div>";
+				div.firstChild.style.width = "5px";
+				shrinkWrapBlocksVal = div.offsetWidth !== 3;
+			}
+
+			body.removeChild( container );
+
+			// Null elements to avoid leaks in IE.
+			body = container = div = null;
+		}
+
+		return shrinkWrapBlocksVal;
+	};
+
+})();
+var rmargin = (/^margin/);
+
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+
+
+var getStyles, curCSS,
+	rposition = /^(top|right|bottom|left)$/;
+
+if ( window.getComputedStyle ) {
+	getStyles = function( elem ) {
+		return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
+	};
+
+	curCSS = function( elem, name, computed ) {
+		var width, minWidth, maxWidth, ret,
+			style = elem.style;
+
+		computed = computed || getStyles( elem );
+
+		// getPropertyValue is only needed for .css('filter') in IE9, see #12537
+		ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
+
+		if ( computed ) {
+
+			if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+				ret = jQuery.style( elem, name );
+			}
+
+			// A tribute to the "awesome hack by Dean Edwards"
+			// Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
+			// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+			// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+			if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+				// Remember the original values
+				width = style.width;
+				minWidth = style.minWidth;
+				maxWidth = style.maxWidth;
+
+				// Put in the new values to get a computed value out
+				style.minWidth = style.maxWidth = style.width = ret;
+				ret = computed.width;
+
+				// Revert the changed values
+				style.width = width;
+				style.minWidth = minWidth;
+				style.maxWidth = maxWidth;
+			}
+		}
+
+		// Support: IE
+		// IE returns zIndex value as an integer.
+		return ret === undefined ?
+			ret :
+			ret + "";
+	};
+} else if ( document.documentElement.currentStyle ) {
+	getStyles = function( elem ) {
+		return elem.currentStyle;
+	};
+
+	curCSS = function( elem, name, computed ) {
+		var left, rs, rsLeft, ret,
+			style = elem.style;
+
+		computed = computed || getStyles( elem );
+		ret = computed ? computed[ name ] : undefined;
+
+		// Avoid setting ret to empty string here
+		// so we don't default to auto
+		if ( ret == null && style && style[ name ] ) {
+			ret = style[ name ];
+		}
+
+		// From the awesome hack by Dean Edwards
+		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+		// If we're not dealing with a regular pixel number
+		// but a number that has a weird ending, we need to convert it to pixels
+		// but not position css attributes, as those are proportional to the parent element instead
+		// and we can't measure the parent instead because it might trigger a "stacking dolls" problem
+		if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+
+			// Remember the original values
+			left = style.left;
+			rs = elem.runtimeStyle;
+			rsLeft = rs && rs.left;
+
+			// Put in the new values to get a computed value out
+			if ( rsLeft ) {
+				rs.left = elem.currentStyle.left;
+			}
+			style.left = name === "fontSize" ? "1em" : ret;
+			ret = style.pixelLeft + "px";
+
+			// Revert the changed values
+			style.left = left;
+			if ( rsLeft ) {
+				rs.left = rsLeft;
+			}
+		}
+
+		// Support: IE
+		// IE returns zIndex value as an integer.
+		return ret === undefined ?
+			ret :
+			ret + "" || "auto";
+	};
+}
+
+
+
+
+function addGetHookIf( conditionFn, hookFn ) {
+	// Define the hook, we'll check on the first run if it's really needed.
+	return {
+		get: function() {
+			var condition = conditionFn();
+
+			if ( condition == null ) {
+				// The test was not ready at this point; screw the hook this time
+				// but check again when needed next time.
+				return;
+			}
+
+			if ( condition ) {
+				// Hook not needed (or it's not possible to use it due to missing dependency),
+				// remove it.
+				// Since there are no other hooks for marginRight, remove the whole object.
+				delete this.get;
+				return;
+			}
+
+			// Hook needed; redefine it so that the support test is not executed again.
+
+			return (this.get = hookFn).apply( this, arguments );
+		}
+	};
+}
+
+
+(function() {
+	var a, reliableHiddenOffsetsVal, boxSizingVal, boxSizingReliableVal,
+		pixelPositionVal, reliableMarginRightVal,
+		div = document.createElement( "div" ),
+		containerStyles = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px",
+		divReset =
+			"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;" +
+			"display:block;padding:0;margin:0;border:0";
+
+	// Setup
+	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+	a = div.getElementsByTagName( "a" )[ 0 ];
+
+	a.style.cssText = "float:left;opacity:.5";
+
+	// Make sure that element opacity exists
+	// (IE uses filter instead)
+	// Use a regex to work around a WebKit issue. See #5145
+	support.opacity = /^0.5/.test( a.style.opacity );
+
+	// Verify style float existence
+	// (IE uses styleFloat instead of cssFloat)
+	support.cssFloat = !!a.style.cssFloat;
+
+	div.style.backgroundClip = "content-box";
+	div.cloneNode( true ).style.backgroundClip = "";
+	support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+	// Null elements to avoid leaks in IE.
+	a = div = null;
+
+	jQuery.extend(support, {
+		reliableHiddenOffsets: function() {
+			if ( reliableHiddenOffsetsVal != null ) {
+				return reliableHiddenOffsetsVal;
+			}
+
+			var container, tds, isSupported,
+				div = document.createElement( "div" ),
+				body = document.getElementsByTagName( "body" )[ 0 ];
+
+			if ( !body ) {
+				// Return for frameset docs that don't have a body
+				return;
+			}
+
+			// Setup
+			div.setAttribute( "className", "t" );
+			div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+
+			container = document.createElement( "div" );
+			container.style.cssText = containerStyles;
+
+			body.appendChild( container ).appendChild( div );
+
+			// Support: IE8
+			// Check if table cells still have offsetWidth/Height when they are set
+			// to display:none and there are still other visible table cells in a
+			// table row; if so, offsetWidth/Height are not reliable for use when
+			// determining if an element has been hidden directly using
+			// display:none (it is still safe to use offsets if a parent element is
+			// hidden; don safety goggles and see bug #4512 for more information).
+			div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
+			tds = div.getElementsByTagName( "td" );
+			tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
+			isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+			tds[ 0 ].style.display = "";
+			tds[ 1 ].style.display = "none";
+
+			// Support: IE8
+			// Check if empty table cells still have offsetWidth/Height
+			reliableHiddenOffsetsVal = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+			body.removeChild( container );
+
+			// Null elements to avoid leaks in IE.
+			div = body = null;
+
+			return reliableHiddenOffsetsVal;
+		},
+
+		boxSizing: function() {
+			if ( boxSizingVal == null ) {
+				computeStyleTests();
+			}
+			return boxSizingVal;
+		},
+
+		boxSizingReliable: function() {
+			if ( boxSizingReliableVal == null ) {
+				computeStyleTests();
+			}
+			return boxSizingReliableVal;
+		},
+
+		pixelPosition: function() {
+			if ( pixelPositionVal == null ) {
+				computeStyleTests();
+			}
+			return pixelPositionVal;
+		},
+
+		reliableMarginRight: function() {
+			var body, container, div, marginDiv;
+
+			// Use window.getComputedStyle because jsdom on node.js will break without it.
+			if ( reliableMarginRightVal == null && window.getComputedStyle ) {
+				body = document.getElementsByTagName( "body" )[ 0 ];
+				if ( !body ) {
+					// Test fired too early or in an unsupported environment, exit.
+					return;
+				}
+
+				container = document.createElement( "div" );
+				div = document.createElement( "div" );
+				container.style.cssText = containerStyles;
+
+				body.appendChild( container ).appendChild( div );
+
+				// Check if div with explicit width and no margin-right incorrectly
+				// gets computed margin-right based on width of container. (#3333)
+				// Fails in WebKit before Feb 2011 nightlies
+				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+				marginDiv = div.appendChild( document.createElement( "div" ) );
+				marginDiv.style.cssText = div.style.cssText = divReset;
+				marginDiv.style.marginRight = marginDiv.style.width = "0";
+				div.style.width = "1px";
+
+				reliableMarginRightVal =
+					!parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
+
+				body.removeChild( container );
+			}
+
+			return reliableMarginRightVal;
+		}
+	});
+
+	function computeStyleTests() {
+		var container, div,
+			body = document.getElementsByTagName( "body" )[ 0 ];
+
+		if ( !body ) {
+			// Test fired too early or in an unsupported environment, exit.
+			return;
+		}
+
+		container = document.createElement( "div" );
+		div = document.createElement( "div" );
+		container.style.cssText = containerStyles;
+
+		body.appendChild( container ).appendChild( div );
+
+		div.style.cssText =
+			"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;" +
+				"position:absolute;display:block;padding:1px;border:1px;width:4px;" +
+				"margin-top:1%;top:1%";
+
+		// Workaround failing boxSizing test due to offsetWidth returning wrong value
+		// with some non-1 values of body zoom, ticket #13543
+		jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() {
+			boxSizingVal = div.offsetWidth === 4;
+		});
+
+		// Will be changed later if needed.
+		boxSizingReliableVal = true;
+		pixelPositionVal = false;
+		reliableMarginRightVal = true;
+
+		// Use window.getComputedStyle because jsdom on node.js will break without it.
+		if ( window.getComputedStyle ) {
+			pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+			boxSizingReliableVal =
+				( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+		}
+
+		body.removeChild( container );
+
+		// Null elements to avoid leaks in IE.
+		div = body = null;
+	}
+
+})();
+
+
+// A method for quickly swapping in/out CSS properties to get correct calculations.
+jQuery.swap = function( elem, options, callback, args ) {
+	var ret, name,
+		old = {};
+
+	// Remember the old values, and insert the new ones
+	for ( name in options ) {
+		old[ name ] = elem.style[ name ];
+		elem.style[ name ] = options[ name ];
+	}
+
+	ret = callback.apply( elem, args || [] );
+
+	// Revert the old values
+	for ( name in options ) {
+		elem.style[ name ] = old[ name ];
+	}
+
+	return ret;
+};
+
+
+var
+		ralpha = /alpha\([^)]*\)/i,
+	ropacity = /opacity\s*=\s*([^)]*)/,
+
+	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
+	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
+
+	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+	cssNormalTransform = {
+		letterSpacing: 0,
+		fontWeight: 400
+	},
+
+	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
+
+
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+	// shortcut for names that are not vendor prefixed
+	if ( name in style ) {
+		return name;
+	}
+
+	// check for vendor prefixed names
+	var capName = name.charAt(0).toUpperCase() + name.slice(1),
+		origName = name,
+		i = cssPrefixes.length;
+
+	while ( i-- ) {
+		name = cssPrefixes[ i ] + capName;
+		if ( name in style ) {
+			return name;
+		}
+	}
+
+	return origName;
+}
+
+function showHide( elements, show ) {
+	var display, elem, hidden,
+		values = [],
+		index = 0,
+		length = elements.length;
+
+	for ( ; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+
+		values[ index ] = jQuery._data( elem, "olddisplay" );
+		display = elem.style.display;
+		if ( show ) {
+			// Reset the inline display of this element to learn if it is
+			// being hidden by cascaded rules or not
+			if ( !values[ index ] && display === "none" ) {
+				elem.style.display = "";
+			}
+
+			// Set elements which have been overridden with display: none
+			// in a stylesheet to whatever the default browser style is
+			// for such an element
+			if ( elem.style.display === "" && isHidden( elem ) ) {
+				values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+			}
+		} else {
+
+			if ( !values[ index ] ) {
+				hidden = isHidden( elem );
+
+				if ( display && display !== "none" || !hidden ) {
+					jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
+				}
+			}
+		}
+	}
+
+	// Set the display of most of the elements in a second loop
+	// to avoid the constant reflow
+	for ( index = 0; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+			elem.style.display = show ? values[ index ] || "" : "none";
+		}
+	}
+
+	return elements;
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+	var matches = rnumsplit.exec( value );
+	return matches ?
+		// Guard against undefined "subtract", e.g., when used as in cssHooks
+		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+		value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+	var i = extra === ( isBorderBox ? "border" : "content" ) ?
+		// If we already have the right measurement, avoid augmentation
+		4 :
+		// Otherwise initialize for horizontal or vertical properties
+		name === "width" ? 1 : 0,
+
+		val = 0;
+
+	for ( ; i < 4; i += 2 ) {
+		// both box models exclude margin, so add it if we want it
+		if ( extra === "margin" ) {
+			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+		}
+
+		if ( isBorderBox ) {
+			// border-box includes padding, so remove it if we want content
+			if ( extra === "content" ) {
+				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+			}
+
+			// at this point, extra isn't border nor margin, so remove border
+			if ( extra !== "margin" ) {
+				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+			}
+		} else {
+			// at this point, extra isn't content, so add padding
+			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+			// at this point, extra isn't content nor padding, so add border
+			if ( extra !== "padding" ) {
+				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+			}
+		}
+	}
+
+	return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+	// Start with offset property, which is equivalent to the border-box value
+	var valueIsBorderBox = true,
+		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+		styles = getStyles( elem ),
+		isBorderBox = support.boxSizing() && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+	// some non-html elements return undefined for offsetWidth, so check for null/undefined
+	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+	if ( val <= 0 || val == null ) {
+		// Fall back to computed then uncomputed css if necessary
+		val = curCSS( elem, name, styles );
+		if ( val < 0 || val == null ) {
+			val = elem.style[ name ];
+		}
+
+		// Computed unit is not pixels. Stop here and return.
+		if ( rnumnonpx.test(val) ) {
+			return val;
+		}
+
+		// we need the check for style in case a browser which returns unreliable values
+		// for getComputedStyle silently falls back to the reliable elem.style
+		valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );
+
+		// Normalize "", auto, and prepare for extra
+		val = parseFloat( val ) || 0;
+	}
+
+	// use the active box-sizing model to add/subtract irrelevant styles
+	return ( val +
+		augmentWidthOrHeight(
+			elem,
+			name,
+			extra || ( isBorderBox ? "border" : "content" ),
+			valueIsBorderBox,
+			styles
+		)
+	) + "px";
+}
+
+jQuery.extend({
+	// Add in style property hooks for overriding the default
+	// behavior of getting and setting a style property
+	cssHooks: {
+		opacity: {
+			get: function( elem, computed ) {
+				if ( computed ) {
+					// We should always get a number back from opacity
+					var ret = curCSS( elem, "opacity" );
+					return ret === "" ? "1" : ret;
+				}
+			}
+		}
+	},
+
+	// Don't automatically add "px" to these possibly-unitless properties
+	cssNumber: {
+		"columnCount": true,
+		"fillOpacity": true,
+		"fontWeight": true,
+		"lineHeight": true,
+		"opacity": true,
+		"order": true,
+		"orphans": true,
+		"widows": true,
+		"zIndex": true,
+		"zoom": true
+	},
+
+	// Add in properties whose names you wish to fix before
+	// setting or getting the value
+	cssProps: {
+		// normalize float css property
+		"float": support.cssFloat ? "cssFloat" : "styleFloat"
+	},
+
+	// Get and set the style property on a DOM Node
+	style: function( elem, name, value, extra ) {
+		// Don't set styles on text and comment nodes
+		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+			return;
+		}
+
+		// Make sure that we're working with the right name
+		var ret, type, hooks,
+			origName = jQuery.camelCase( name ),
+			style = elem.style;
+
+		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+		// gets hook for the prefixed version
+		// followed by the unprefixed version
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// Check if we're setting a value
+		if ( value !== undefined ) {
+			type = typeof value;
+
+			// convert relative number strings (+= or -=) to relative numbers. #7345
+			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+				// Fixes bug #9237
+				type = "number";
+			}
+
+			// Make sure that null and NaN values aren't set. See: #7116
+			if ( value == null || value !== value ) {
+				return;
+			}
+
+			// If a number was passed in, add 'px' to the (except for certain CSS properties)
+			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+				value += "px";
+			}
+
+			// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
+			// but it would mean to define eight (for every problematic property) identical functions
+			if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
+				style[ name ] = "inherit";
+			}
+
+			// If a hook was provided, use that value, otherwise just set the specified value
+			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+
+				// Support: IE
+				// Swallow errors from 'invalid' CSS values (#5509)
+				try {
+					// Support: Chrome, Safari
+					// Setting style to blank string required to delete "style: x !important;"
+					style[ name ] = "";
+					style[ name ] = value;
+				} catch(e) {}
+			}
+
+		} else {
+			// If a hook was provided get the non-computed value from there
+			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+				return ret;
+			}
+
+			// Otherwise just get the value from the style object
+			return style[ name ];
+		}
+	},
+
+	css: function( elem, name, extra, styles ) {
+		var num, val, hooks,
+			origName = jQuery.camelCase( name );
+
+		// Make sure that we're working with the right name
+		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+		// gets hook for the prefixed version
+		// followed by the unprefixed version
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// If a hook was provided get the computed value from there
+		if ( hooks && "get" in hooks ) {
+			val = hooks.get( elem, true, extra );
+		}
+
+		// Otherwise, if a way to get the computed value exists, use that
+		if ( val === undefined ) {
+			val = curCSS( elem, name, styles );
+		}
+
+		//convert "normal" to computed value
+		if ( val === "normal" && name in cssNormalTransform ) {
+			val = cssNormalTransform[ name ];
+		}
+
+		// Return, converting to number if forced or a qualifier was provided and val looks numeric
+		if ( extra === "" || extra ) {
+			num = parseFloat( val );
+			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
+		}
+		return val;
+	}
+});
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+	jQuery.cssHooks[ name ] = {
+		get: function( elem, computed, extra ) {
+			if ( computed ) {
+				// certain elements can have dimension info if we invisibly show them
+				// however, it must have a current display style that would benefit from this
+				return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
+					jQuery.swap( elem, cssShow, function() {
+						return getWidthOrHeight( elem, name, extra );
+					}) :
+					getWidthOrHeight( elem, name, extra );
+			}
+		},
+
+		set: function( elem, value, extra ) {
+			var styles = extra && getStyles( elem );
+			return setPositiveNumber( elem, value, extra ?
+				augmentWidthOrHeight(
+					elem,
+					name,
+					extra,
+					support.boxSizing() && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+					styles
+				) : 0
+			);
+		}
+	};
+});
+
+if ( !support.opacity ) {
+	jQuery.cssHooks.opacity = {
+		get: function( elem, computed ) {
+			// IE uses filters for opacity
+			return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+				( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
+				computed ? "1" : "";
+		},
+
+		set: function( elem, value ) {
+			var style = elem.style,
+				currentStyle = elem.currentStyle,
+				opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+				filter = currentStyle && currentStyle.filter || style.filter || "";
+
+			// IE has trouble with opacity if it does not have layout
+			// Force it by setting the zoom level
+			style.zoom = 1;
+
+			// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+			// if value === "", then remove inline opacity #12685
+			if ( ( value >= 1 || value === "" ) &&
+					jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
+					style.removeAttribute ) {
+
+				// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+				// if "filter:" is present at all, clearType is disabled, we want to avoid this
+				// style.removeAttribute is IE Only, but so apparently is this code path...
+				style.removeAttribute( "filter" );
+
+				// if there is no filter style applied in a css rule or unset inline opacity, we are done
+				if ( value === "" || currentStyle && !currentStyle.filter ) {
+					return;
+				}
+			}
+
+			// otherwise, set new filter values
+			style.filter = ralpha.test( filter ) ?
+				filter.replace( ralpha, opacity ) :
+				filter + " " + opacity;
+		}
+	};
+}
+
+jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
+	function( elem, computed ) {
+		if ( computed ) {
+			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+			// Work around by temporarily setting element display to inline-block
+			return jQuery.swap( elem, { "display": "inline-block" },
+				curCSS, [ elem, "marginRight" ] );
+		}
+	}
+);
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+	margin: "",
+	padding: "",
+	border: "Width"
+}, function( prefix, suffix ) {
+	jQuery.cssHooks[ prefix + suffix ] = {
+		expand: function( value ) {
+			var i = 0,
+				expanded = {},
+
+				// assumes a single number if not a string
+				parts = typeof value === "string" ? value.split(" ") : [ value ];
+
+			for ( ; i < 4; i++ ) {
+				expanded[ prefix + cssExpand[ i ] + suffix ] =
+					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+			}
+
+			return expanded;
+		}
+	};
+
+	if ( !rmargin.test( prefix ) ) {
+		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+	}
+});
+
+jQuery.fn.extend({
+	css: function( name, value ) {
+		return access( this, function( elem, name, value ) {
+			var styles, len,
+				map = {},
+				i = 0;
+
+			if ( jQuery.isArray( name ) ) {
+				styles = getStyles( elem );
+				len = name.length;
+
+				for ( ; i < len; i++ ) {
+					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+				}
+
+				return map;
+			}
+
+			return value !== undefined ?
+				jQuery.style( elem, name, value ) :
+				jQuery.css( elem, name );
+		}, name, value, arguments.length > 1 );
+	},
+	show: function() {
+		return showHide( this, true );
+	},
+	hide: function() {
+		return showHide( this );
+	},
+	toggle: function( state ) {
+		if ( typeof state === "boolean" ) {
+			return state ? this.show() : this.hide();
+		}
+
+		return this.each(function() {
+			if ( isHidden( this ) ) {
+				jQuery( this ).show();
+			} else {
+				jQuery( this ).hide();
+			}
+		});
+	}
+});
+
+
+function Tween( elem, options, prop, end, easing ) {
+	return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+	constructor: Tween,
+	init: function( elem, options, prop, end, easing, unit ) {
+		this.elem = elem;
+		this.prop = prop;
+		this.easing = easing || "swing";
+		this.options = options;
+		this.start = this.now = this.cur();
+		this.end = end;
+		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+	},
+	cur: function() {
+		var hooks = Tween.propHooks[ this.prop ];
+
+		return hooks && hooks.get ?
+			hooks.get( this ) :
+			Tween.propHooks._default.get( this );
+	},
+	run: function( percent ) {
+		var eased,
+			hooks = Tween.propHooks[ this.prop ];
+
+		if ( this.options.duration ) {
+			this.pos = eased = jQuery.easing[ this.easing ](
+				percent, this.options.duration * percent, 0, 1, this.options.duration
+			);
+		} else {
+			this.pos = eased = percent;
+		}
+		this.now = ( this.end - this.start ) * eased + this.start;
+
+		if ( this.options.step ) {
+			this.options.step.call( this.elem, this.now, this );
+		}
+
+		if ( hooks && hooks.set ) {
+			hooks.set( this );
+		} else {
+			Tween.propHooks._default.set( this );
+		}
+		return this;
+	}
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+	_default: {
+		get: function( tween ) {
+			var result;
+
+			if ( tween.elem[ tween.prop ] != null &&
+				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+				return tween.elem[ tween.prop ];
+			}
+
+			// passing an empty string as a 3rd parameter to .css will automatically
+			// attempt a parseFloat and fallback to a string if the parse fails
+			// so, simple values such as "10px" are parsed to Float.
+			// complex values such as "rotate(1rad)" are returned as is.
+			result = jQuery.css( tween.elem, tween.prop, "" );
+			// Empty strings, null, undefined and "auto" are converted to 0.
+			return !result || result === "auto" ? 0 : result;
+		},
+		set: function( tween ) {
+			// use step hook for back compat - use cssHook if its there - use .style if its
+			// available and use plain properties where available
+			if ( jQuery.fx.step[ tween.prop ] ) {
+				jQuery.fx.step[ tween.prop ]( tween );
+			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+			} else {
+				tween.elem[ tween.prop ] = tween.now;
+			}
+		}
+	}
+};
+
+// Support: IE <=9
+// Panic based approach to setting things on disconnected nodes
+
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+	set: function( tween ) {
+		if ( tween.elem.nodeType && tween.elem.parentNode ) {
+			tween.elem[ tween.prop ] = tween.now;
+		}
+	}
+};
+
+jQuery.easing = {
+	linear: function( p ) {
+		return p;
+	},
+	swing: function( p ) {
+		return 0.5 - Math.cos( p * Math.PI ) / 2;
+	}
+};
+
+jQuery.fx = Tween.prototype.init;
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+
+
+
+var
+	fxNow, timerId,
+	rfxtypes = /^(?:toggle|show|hide)$/,
+	rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
+	rrun = /queueHooks$/,
+	animationPrefilters = [ defaultPrefilter ],
+	tweeners = {
+		"*": [ function( prop, value ) {
+			var tween = this.createTween( prop, value ),
+				target = tween.cur(),
+				parts = rfxnum.exec( value ),
+				unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+				// Starting value computation is required for potential unit mismatches
+				start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
+					rfxnum.exec( jQuery.css( tween.elem, prop ) ),
+				scale = 1,
+				maxIterations = 20;
+
+			if ( start && start[ 3 ] !== unit ) {
+				// Trust units reported by jQuery.css
+				unit = unit || start[ 3 ];
+
+				// Make sure we update the tween properties later on
+				parts = parts || [];
+
+				// Iteratively approximate from a nonzero starting point
+				start = +target || 1;
+
+				do {
+					// If previous iteration zeroed out, double until we get *something*
+					// Use a string for doubling factor so we don't accidentally see scale as unchanged below
+					scale = scale || ".5";
+
+					// Adjust and apply
+					start = start / scale;
+					jQuery.style( tween.elem, prop, start + unit );
+
+				// Update scale, tolerating zero or NaN from tween.cur()
+				// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+			}
+
+			// Update tween properties
+			if ( parts ) {
+				start = tween.start = +start || +target || 0;
+				tween.unit = unit;
+				// If a +=/-= token was provided, we're doing a relative animation
+				tween.end = parts[ 1 ] ?
+					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
+					+parts[ 2 ];
+			}
+
+			return tween;
+		} ]
+	};
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+	setTimeout(function() {
+		fxNow = undefined;
+	});
+	return ( fxNow = jQuery.now() );
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+	var which,
+		attrs = { height: type },
+		i = 0;
+
+	// if we include width, step value is 1 to do all cssExpand values,
+	// if we don't include width, step value is 2 to skip over Left and Right
+	includeWidth = includeWidth ? 1 : 0;
+	for ( ; i < 4 ; i += 2 - includeWidth ) {
+		which = cssExpand[ i ];
+		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+	}
+
+	if ( includeWidth ) {
+		attrs.opacity = attrs.width = type;
+	}
+
+	return attrs;
+}
+
+function createTween( value, prop, animation ) {
+	var tween,
+		collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+		index = 0,
+		length = collection.length;
+	for ( ; index < length; index++ ) {
+		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
+
+			// we're done with this property
+			return tween;
+		}
+	}
+}
+
+function defaultPrefilter( elem, props, opts ) {
+	/* jshint validthis: true */
+	var prop, value, toggle, tween, hooks, oldfire, display, dDisplay,
+		anim = this,
+		orig = {},
+		style = elem.style,
+		hidden = elem.nodeType && isHidden( elem ),
+		dataShow = jQuery._data( elem, "fxshow" );
+
+	// handle queue: false promises
+	if ( !opts.queue ) {
+		hooks = jQuery._queueHooks( elem, "fx" );
+		if ( hooks.unqueued == null ) {
+			hooks.unqueued = 0;
+			oldfire = hooks.empty.fire;
+			hooks.empty.fire = function() {
+				if ( !hooks.unqueued ) {
+					oldfire();
+				}
+			};
+		}
+		hooks.unqueued++;
+
+		anim.always(function() {
+			// doing this makes sure that the complete handler will be called
+			// before this completes
+			anim.always(function() {
+				hooks.unqueued--;
+				if ( !jQuery.queue( elem, "fx" ).length ) {
+					hooks.empty.fire();
+				}
+			});
+		});
+	}
+
+	// height/width overflow pass
+	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+		// Make sure that nothing sneaks out
+		// Record all 3 overflow attributes because IE does not
+		// change the overflow attribute when overflowX and
+		// overflowY are set to the same value
+		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+		// Set display property to inline-block for height/width
+		// animations on inline elements that are having width/height animated
+		display = jQuery.css( elem, "display" );
+		dDisplay = defaultDisplay( elem.nodeName );
+		if ( display === "none" ) {
+			display = dDisplay;
+		}
+		if ( display === "inline" &&
+				jQuery.css( elem, "float" ) === "none" ) {
+
+			// inline-level elements accept inline-block;
+			// block-level elements need to be inline with layout
+			if ( !support.inlineBlockNeedsLayout || dDisplay === "inline" ) {
+				style.display = "inline-block";
+			} else {
+				style.zoom = 1;
+			}
+		}
+	}
+
+	if ( opts.overflow ) {
+		style.overflow = "hidden";
+		if ( !support.shrinkWrapBlocks() ) {
+			anim.always(function() {
+				style.overflow = opts.overflow[ 0 ];
+				style.overflowX = opts.overflow[ 1 ];
+				style.overflowY = opts.overflow[ 2 ];
+			});
+		}
+	}
+
+	// show/hide pass
+	for ( prop in props ) {
+		value = props[ prop ];
+		if ( rfxtypes.exec( value ) ) {
+			delete props[ prop ];
+			toggle = toggle || value === "toggle";
+			if ( value === ( hidden ? "hide" : "show" ) ) {
+
+				// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
+				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+					hidden = true;
+				} else {
+					continue;
+				}
+			}
+			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+		}
+	}
+
+	if ( !jQuery.isEmptyObject( orig ) ) {
+		if ( dataShow ) {
+			if ( "hidden" in dataShow ) {
+				hidden = dataShow.hidden;
+			}
+		} else {
+			dataShow = jQuery._data( elem, "fxshow", {} );
+		}
+
+		// store state if its toggle - enables .stop().toggle() to "reverse"
+		if ( toggle ) {
+			dataShow.hidden = !hidden;
+		}
+		if ( hidden ) {
+			jQuery( elem ).show();
+		} else {
+			anim.done(function() {
+				jQuery( elem ).hide();
+			});
+		}
+		anim.done(function() {
+			var prop;
+			jQuery._removeData( elem, "fxshow" );
+			for ( prop in orig ) {
+				jQuery.style( elem, prop, orig[ prop ] );
+			}
+		});
+		for ( prop in orig ) {
+			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+
+			if ( !( prop in dataShow ) ) {
+				dataShow[ prop ] = tween.start;
+				if ( hidden ) {
+					tween.end = tween.start;
+					tween.start = prop === "width" || prop === "height" ? 1 : 0;
+				}
+			}
+		}
+	}
+}
+
+function propFilter( props, specialEasing ) {
+	var index, name, easing, value, hooks;
+
+	// camelCase, specialEasing and expand cssHook pass
+	for ( index in props ) {
+		name = jQuery.camelCase( index );
+		easing = specialEasing[ name ];
+		value = props[ index ];
+		if ( jQuery.isArray( value ) ) {
+			easing = value[ 1 ];
+			value = props[ index ] = value[ 0 ];
+		}
+
+		if ( index !== name ) {
+			props[ name ] = value;
+			delete props[ index ];
+		}
+
+		hooks = jQuery.cssHooks[ name ];
+		if ( hooks && "expand" in hooks ) {
+			value = hooks.expand( value );
+			delete props[ name ];
+
+			// not quite $.extend, this wont overwrite keys already present.
+			// also - reusing 'index' from above because we have the correct "name"
+			for ( index in value ) {
+				if ( !( index in props ) ) {
+					props[ index ] = value[ index ];
+					specialEasing[ index ] = easing;
+				}
+			}
+		} else {
+			specialEasing[ name ] = easing;
+		}
+	}
+}
+
+function Animation( elem, properties, options ) {
+	var result,
+		stopped,
+		index = 0,
+		length = animationPrefilters.length,
+		deferred = jQuery.Deferred().always( function() {
+			// don't match elem in the :animated selector
+			delete tick.elem;
+		}),
+		tick = function() {
+			if ( stopped ) {
+				return false;
+			}
+			var currentTime = fxNow || createFxNow(),
+				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+				// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+				temp = remaining / animation.duration || 0,
+				percent = 1 - temp,
+				index = 0,
+				length = animation.tweens.length;
+
+			for ( ; index < length ; index++ ) {
+				animation.tweens[ index ].run( percent );
+			}
+
+			deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+			if ( percent < 1 && length ) {
+				return remaining;
+			} else {
+				deferred.resolveWith( elem, [ animation ] );
+				return false;
+			}
+		},
+		animation = deferred.promise({
+			elem: elem,
+			props: jQuery.extend( {}, properties ),
+			opts: jQuery.extend( true, { specialEasing: {} }, options ),
+			originalProperties: properties,
+			originalOptions: options,
+			startTime: fxNow || createFxNow(),
+			duration: options.duration,
+			tweens: [],
+			createTween: function( prop, end ) {
+				var tween = jQuery.Tween( elem, animation.opts, prop, end,
+						animation.opts.specialEasing[ prop ] || animation.opts.easing );
+				animation.tweens.push( tween );
+				return tween;
+			},
+			stop: function( gotoEnd ) {
+				var index = 0,
+					// if we are going to the end, we want to run all the tweens
+					// otherwise we skip this part
+					length = gotoEnd ? animation.tweens.length : 0;
+				if ( stopped ) {
+					return this;
+				}
+				stopped = true;
+				for ( ; index < length ; index++ ) {
+					animation.tweens[ index ].run( 1 );
+				}
+
+				// resolve when we played the last frame
+				// otherwise, reject
+				if ( gotoEnd ) {
+					deferred.resolveWith( elem, [ animation, gotoEnd ] );
+				} else {
+					deferred.rejectWith( elem, [ animation, gotoEnd ] );
+				}
+				return this;
+			}
+		}),
+		props = animation.props;
+
+	propFilter( props, animation.opts.specialEasing );
+
+	for ( ; index < length ; index++ ) {
+		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+		if ( result ) {
+			return result;
+		}
+	}
+
+	jQuery.map( props, createTween, animation );
+
+	if ( jQuery.isFunction( animation.opts.start ) ) {
+		animation.opts.start.call( elem, animation );
+	}
+
+	jQuery.fx.timer(
+		jQuery.extend( tick, {
+			elem: elem,
+			anim: animation,
+			queue: animation.opts.queue
+		})
+	);
+
+	// attach callbacks from options
+	return animation.progress( animation.opts.progress )
+		.done( animation.opts.done, animation.opts.complete )
+		.fail( animation.opts.fail )
+		.always( animation.opts.always );
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+	tweener: function( props, callback ) {
+		if ( jQuery.isFunction( props ) ) {
+			callback = props;
+			props = [ "*" ];
+		} else {
+			props = props.split(" ");
+		}
+
+		var prop,
+			index = 0,
+			length = props.length;
+
+		for ( ; index < length ; index++ ) {
+			prop = props[ index ];
+			tweeners[ prop ] = tweeners[ prop ] || [];
+			tweeners[ prop ].unshift( callback );
+		}
+	},
+
+	prefilter: function( callback, prepend ) {
+		if ( prepend ) {
+			animationPrefilters.unshift( callback );
+		} else {
+			animationPrefilters.push( callback );
+		}
+	}
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+		complete: fn || !fn && easing ||
+			jQuery.isFunction( speed ) && speed,
+		duration: speed,
+		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+	};
+
+	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+	// normalize opt.queue - true/undefined/null -> "fx"
+	if ( opt.queue == null || opt.queue === true ) {
+		opt.queue = "fx";
+	}
+
+	// Queueing
+	opt.old = opt.complete;
+
+	opt.complete = function() {
+		if ( jQuery.isFunction( opt.old ) ) {
+			opt.old.call( this );
+		}
+
+		if ( opt.queue ) {
+			jQuery.dequeue( this, opt.queue );
+		}
+	};
+
+	return opt;
+};
+
+jQuery.fn.extend({
+	fadeTo: function( speed, to, easing, callback ) {
+
+		// show any hidden elements after setting opacity to 0
+		return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+			// animate to the value specified
+			.end().animate({ opacity: to }, speed, easing, callback );
+	},
+	animate: function( prop, speed, easing, callback ) {
+		var empty = jQuery.isEmptyObject( prop ),
+			optall = jQuery.speed( speed, easing, callback ),
+			doAnimation = function() {
+				// Operate on a copy of prop so per-property easing won't be lost
+				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+				// Empty animations, or finishing resolves immediately
+				if ( empty || jQuery._data( this, "finish" ) ) {
+					anim.stop( true );
+				}
+			};
+			doAnimation.finish = doAnimation;
+
+		return empty || optall.queue === false ?
+			this.each( doAnimation ) :
+			this.queue( optall.queue, doAnimation );
+	},
+	stop: function( type, clearQueue, gotoEnd ) {
+		var stopQueue = function( hooks ) {
+			var stop = hooks.stop;
+			delete hooks.stop;
+			stop( gotoEnd );
+		};
+
+		if ( typeof type !== "string" ) {
+			gotoEnd = clearQueue;
+			clearQueue = type;
+			type = undefined;
+		}
+		if ( clearQueue && type !== false ) {
+			this.queue( type || "fx", [] );
+		}
+
+		return this.each(function() {
+			var dequeue = true,
+				index = type != null && type + "queueHooks",
+				timers = jQuery.timers,
+				data = jQuery._data( this );
+
+			if ( index ) {
+				if ( data[ index ] && data[ index ].stop ) {
+					stopQueue( data[ index ] );
+				}
+			} else {
+				for ( index in data ) {
+					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+						stopQueue( data[ index ] );
+					}
+				}
+			}
+
+			for ( index = timers.length; index--; ) {
+				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+					timers[ index ].anim.stop( gotoEnd );
+					dequeue = false;
+					timers.splice( index, 1 );
+				}
+			}
+
+			// start the next in the queue if the last step wasn't forced
+			// timers currently will call their complete callbacks, which will dequeue
+			// but only if they were gotoEnd
+			if ( dequeue || !gotoEnd ) {
+				jQuery.dequeue( this, type );
+			}
+		});
+	},
+	finish: function( type ) {
+		if ( type !== false ) {
+			type = type || "fx";
+		}
+		return this.each(function() {
+			var index,
+				data = jQuery._data( this ),
+				queue = data[ type + "queue" ],
+				hooks = data[ type + "queueHooks" ],
+				timers = jQuery.timers,
+				length = queue ? queue.length : 0;
+
+			// enable finishing flag on private data
+			data.finish = true;
+
+			// empty the queue first
+			jQuery.queue( this, type, [] );
+
+			if ( hooks && hooks.stop ) {
+				hooks.stop.call( this, true );
+			}
+
+			// look for any active animations, and finish them
+			for ( index = timers.length; index--; ) {
+				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+					timers[ index ].anim.stop( true );
+					timers.splice( index, 1 );
+				}
+			}
+
+			// look for any animations in the old queue and finish them
+			for ( index = 0; index < length; index++ ) {
+				if ( queue[ index ] && queue[ index ].finish ) {
+					queue[ index ].finish.call( this );
+				}
+			}
+
+			// turn off finishing flag
+			delete data.finish;
+		});
+	}
+});
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+	var cssFn = jQuery.fn[ name ];
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return speed == null || typeof speed === "boolean" ?
+			cssFn.apply( this, arguments ) :
+			this.animate( genFx( name, true ), speed, easing, callback );
+	};
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+	slideDown: genFx("show"),
+	slideUp: genFx("hide"),
+	slideToggle: genFx("toggle"),
+	fadeIn: { opacity: "show" },
+	fadeOut: { opacity: "hide" },
+	fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return this.animate( props, speed, easing, callback );
+	};
+});
+
+jQuery.timers = [];
+jQuery.fx.tick = function() {
+	var timer,
+		timers = jQuery.timers,
+		i = 0;
+
+	fxNow = jQuery.now();
+
+	for ( ; i < timers.length; i++ ) {
+		timer = timers[ i ];
+		// Checks the timer has not already been removed
+		if ( !timer() && timers[ i ] === timer ) {
+			timers.splice( i--, 1 );
+		}
+	}
+
+	if ( !timers.length ) {
+		jQuery.fx.stop();
+	}
+	fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+	jQuery.timers.push( timer );
+	if ( timer() ) {
+		jQuery.fx.start();
+	} else {
+		jQuery.timers.pop();
+	}
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.start = function() {
+	if ( !timerId ) {
+		timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+	}
+};
+
+jQuery.fx.stop = function() {
+	clearInterval( timerId );
+	timerId = null;
+};
+
+jQuery.fx.speeds = {
+	slow: 600,
+	fast: 200,
+	// Default speed
+	_default: 400
+};
+
+
+// Based off of the plugin by Clint Helfers, with permission.
+// http://blindsignals.com/index.php/2009/07/jquery-delay/
+jQuery.fn.delay = function( time, type ) {
+	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+	type = type || "fx";
+
+	return this.queue( type, function( next, hooks ) {
+		var timeout = setTimeout( next, time );
+		hooks.stop = function() {
+			clearTimeout( timeout );
+		};
+	});
+};
+
+
+(function() {
+	var a, input, select, opt,
+		div = document.createElement("div" );
+
+	// Setup
+	div.setAttribute( "className", "t" );
+	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+	a = div.getElementsByTagName("a")[ 0 ];
+
+	// First batch of tests.
+	select = document.createElement("select");
+	opt = select.appendChild( document.createElement("option") );
+	input = div.getElementsByTagName("input")[ 0 ];
+
+	a.style.cssText = "top:1px";
+
+	// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+	support.getSetAttribute = div.className !== "t";
+
+	// Get the style information from getAttribute
+	// (IE uses .cssText instead)
+	support.style = /top/.test( a.getAttribute("style") );
+
+	// Make sure that URLs aren't manipulated
+	// (IE normalizes it by default)
+	support.hrefNormalized = a.getAttribute("href") === "/a";
+
+	// Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
+	support.checkOn = !!input.value;
+
+	// Make sure that a selected-by-default option has a working selected property.
+	// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+	support.optSelected = opt.selected;
+
+	// Tests for enctype support on a form (#6743)
+	support.enctype = !!document.createElement("form").enctype;
+
+	// Make sure that the options inside disabled selects aren't marked as disabled
+	// (WebKit marks them as disabled)
+	select.disabled = true;
+	support.optDisabled = !opt.disabled;
+
+	// Support: IE8 only
+	// Check if we can trust getAttribute("value")
+	input = document.createElement( "input" );
+	input.setAttribute( "value", "" );
+	support.input = input.getAttribute( "value" ) === "";
+
+	// Check if an input maintains its value after becoming a radio
+	input.value = "t";
+	input.setAttribute( "type", "radio" );
+	support.radioValue = input.value === "t";
+
+	// Null elements to avoid leaks in IE.
+	a = input = select = opt = div = null;
+})();
+
+
+var rreturn = /\r/g;
+
+jQuery.fn.extend({
+	val: function( value ) {
+		var hooks, ret, isFunction,
+			elem = this[0];
+
+		if ( !arguments.length ) {
+			if ( elem ) {
+				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+					return ret;
+				}
+
+				ret = elem.value;
+
+				return typeof ret === "string" ?
+					// handle most common string cases
+					ret.replace(rreturn, "") :
+					// handle cases where value is null/undef or number
+					ret == null ? "" : ret;
+			}
+
+			return;
+		}
+
+		isFunction = jQuery.isFunction( value );
+
+		return this.each(function( i ) {
+			var val;
+
+			if ( this.nodeType !== 1 ) {
+				return;
+			}
+
+			if ( isFunction ) {
+				val = value.call( this, i, jQuery( this ).val() );
+			} else {
+				val = value;
+			}
+
+			// Treat null/undefined as ""; convert numbers to string
+			if ( val == null ) {
+				val = "";
+			} else if ( typeof val === "number" ) {
+				val += "";
+			} else if ( jQuery.isArray( val ) ) {
+				val = jQuery.map( val, function( value ) {
+					return value == null ? "" : value + "";
+				});
+			}
+
+			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+			// If set returns undefined, fall back to normal setting
+			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+				this.value = val;
+			}
+		});
+	}
+});
+
+jQuery.extend({
+	valHooks: {
+		option: {
+			get: function( elem ) {
+				var val = jQuery.find.attr( elem, "value" );
+				return val != null ?
+					val :
+					jQuery.text( elem );
+			}
+		},
+		select: {
+			get: function( elem ) {
+				var value, option,
+					options = elem.options,
+					index = elem.selectedIndex,
+					one = elem.type === "select-one" || index < 0,
+					values = one ? null : [],
+					max = one ? index + 1 : options.length,
+					i = index < 0 ?
+						max :
+						one ? index : 0;
+
+				// Loop through all the selected options
+				for ( ; i < max; i++ ) {
+					option = options[ i ];
+
+					// oldIE doesn't update selected after form reset (#2551)
+					if ( ( option.selected || i === index ) &&
+							// Don't return options that are disabled or in a disabled optgroup
+							( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
+							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+						// Get the specific value for the option
+						value = jQuery( option ).val();
+
+						// We don't need an array for one selects
+						if ( one ) {
+							return value;
+						}
+
+						// Multi-Selects return an array
+						values.push( value );
+					}
+				}
+
+				return values;
+			},
+
+			set: function( elem, value ) {
+				var optionSet, option,
+					options = elem.options,
+					values = jQuery.makeArray( value ),
+					i = options.length;
+
+				while ( i-- ) {
+					option = options[ i ];
+
+					if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {
+
+						// Support: IE6
+						// When new option element is added to select box we need to
+						// force reflow of newly added node in order to workaround delay
+						// of initialization properties
+						try {
+							option.selected = optionSet = true;
+
+						} catch ( _ ) {
+
+							// Will be executed only in IE6
+							option.scrollHeight;
+						}
+
+					} else {
+						option.selected = false;
+					}
+				}
+
+				// Force browsers to behave consistently when non-matching value is set
+				if ( !optionSet ) {
+					elem.selectedIndex = -1;
+				}
+
+				return options;
+			}
+		}
+	}
+});
+
+// Radios and checkboxes getter/setter
+jQuery.each([ "radio", "checkbox" ], function() {
+	jQuery.valHooks[ this ] = {
+		set: function( elem, value ) {
+			if ( jQuery.isArray( value ) ) {
+				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+			}
+		}
+	};
+	if ( !support.checkOn ) {
+		jQuery.valHooks[ this ].get = function( elem ) {
+			// Support: Webkit
+			// "" is returned instead of "on" if a value isn't specified
+			return elem.getAttribute("value") === null ? "on" : elem.value;
+		};
+	}
+});
+
+
+
+
+var nodeHook, boolHook,
+	attrHandle = jQuery.expr.attrHandle,
+	ruseDefault = /^(?:checked|selected)$/i,
+	getSetAttribute = support.getSetAttribute,
+	getSetInput = support.input;
+
+jQuery.fn.extend({
+	attr: function( name, value ) {
+		return access( this, jQuery.attr, name, value, arguments.length > 1 );
+	},
+
+	removeAttr: function( name ) {
+		return this.each(function() {
+			jQuery.removeAttr( this, name );
+		});
+	}
+});
+
+jQuery.extend({
+	attr: function( elem, name, value ) {
+		var hooks, ret,
+			nType = elem.nodeType;
+
+		// don't get/set attributes on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		// Fallback to prop when attributes are not supported
+		if ( typeof elem.getAttribute === strundefined ) {
+			return jQuery.prop( elem, name, value );
+		}
+
+		// All attributes are lowercase
+		// Grab necessary hook if one is defined
+		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+			name = name.toLowerCase();
+			hooks = jQuery.attrHooks[ name ] ||
+				( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
+		}
+
+		if ( value !== undefined ) {
+
+			if ( value === null ) {
+				jQuery.removeAttr( elem, name );
+
+			} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				elem.setAttribute( name, value + "" );
+				return value;
+			}
+
+		} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+			return ret;
+
+		} else {
+			ret = jQuery.find.attr( elem, name );
+
+			// Non-existent attributes return null, we normalize to undefined
+			return ret == null ?
+				undefined :
+				ret;
+		}
+	},
+
+	removeAttr: function( elem, value ) {
+		var name, propName,
+			i = 0,
+			attrNames = value && value.match( rnotwhite );
+
+		if ( attrNames && elem.nodeType === 1 ) {
+			while ( (name = attrNames[i++]) ) {
+				propName = jQuery.propFix[ name ] || name;
+
+				// Boolean attributes get special treatment (#10870)
+				if ( jQuery.expr.match.bool.test( name ) ) {
+					// Set corresponding property to false
+					if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+						elem[ propName ] = false;
+					// Support: IE<9
+					// Also clear defaultChecked/defaultSelected (if appropriate)
+					} else {
+						elem[ jQuery.camelCase( "default-" + name ) ] =
+							elem[ propName ] = false;
+					}
+
+				// See #9699 for explanation of this approach (setting first, then removal)
+				} else {
+					jQuery.attr( elem, name, "" );
+				}
+
+				elem.removeAttribute( getSetAttribute ? name : propName );
+			}
+		}
+	},
+
+	attrHooks: {
+		type: {
+			set: function( elem, value ) {
+				if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+					// Setting the type on a radio button after the value resets the value in IE6-9
+					// Reset value to default in case type is set after value during creation
+					var val = elem.value;
+					elem.setAttribute( "type", value );
+					if ( val ) {
+						elem.value = val;
+					}
+					return value;
+				}
+			}
+		}
+	}
+});
+
+// Hook for boolean attributes
+boolHook = {
+	set: function( elem, value, name ) {
+		if ( value === false ) {
+			// Remove boolean attributes when set to false
+			jQuery.removeAttr( elem, name );
+		} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+			// IE<8 needs the *property* name
+			elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
+
+		// Use defaultChecked and defaultSelected for oldIE
+		} else {
+			elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
+		}
+
+		return name;
+	}
+};
+
+// Retrieve booleans specially
+jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+
+	var getter = attrHandle[ name ] || jQuery.find.attr;
+
+	attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
+		function( elem, name, isXML ) {
+			var ret, handle;
+			if ( !isXML ) {
+				// Avoid an infinite loop by temporarily removing this function from the getter
+				handle = attrHandle[ name ];
+				attrHandle[ name ] = ret;
+				ret = getter( elem, name, isXML ) != null ?
+					name.toLowerCase() :
+					null;
+				attrHandle[ name ] = handle;
+			}
+			return ret;
+		} :
+		function( elem, name, isXML ) {
+			if ( !isXML ) {
+				return elem[ jQuery.camelCase( "default-" + name ) ] ?
+					name.toLowerCase() :
+					null;
+			}
+		};
+});
+
+// fix oldIE attroperties
+if ( !getSetInput || !getSetAttribute ) {
+	jQuery.attrHooks.value = {
+		set: function( elem, value, name ) {
+			if ( jQuery.nodeName( elem, "input" ) ) {
+				// Does not return so that setAttribute is also used
+				elem.defaultValue = value;
+			} else {
+				// Use nodeHook if defined (#1954); otherwise setAttribute is fine
+				return nodeHook && nodeHook.set( elem, value, name );
+			}
+		}
+	};
+}
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+	// Use this for any attribute in IE6/7
+	// This fixes almost every IE6/7 issue
+	nodeHook = {
+		set: function( elem, value, name ) {
+			// Set the existing or create a new attribute node
+			var ret = elem.getAttributeNode( name );
+			if ( !ret ) {
+				elem.setAttributeNode(
+					(ret = elem.ownerDocument.createAttribute( name ))
+				);
+			}
+
+			ret.value = value += "";
+
+			// Break association with cloned elements by also using setAttribute (#9646)
+			if ( name === "value" || value === elem.getAttribute( name ) ) {
+				return value;
+			}
+		}
+	};
+
+	// Some attributes are constructed with empty-string values when not defined
+	attrHandle.id = attrHandle.name = attrHandle.coords =
+		function( elem, name, isXML ) {
+			var ret;
+			if ( !isXML ) {
+				return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
+					ret.value :
+					null;
+			}
+		};
+
+	// Fixing value retrieval on a button requires this module
+	jQuery.valHooks.button = {
+		get: function( elem, name ) {
+			var ret = elem.getAttributeNode( name );
+			if ( ret && ret.specified ) {
+				return ret.value;
+			}
+		},
+		set: nodeHook.set
+	};
+
+	// Set contenteditable to false on removals(#10429)
+	// Setting to empty string throws an error as an invalid value
+	jQuery.attrHooks.contenteditable = {
+		set: function( elem, value, name ) {
+			nodeHook.set( elem, value === "" ? false : value, name );
+		}
+	};
+
+	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
+	// This is for removals
+	jQuery.each([ "width", "height" ], function( i, name ) {
+		jQuery.attrHooks[ name ] = {
+			set: function( elem, value ) {
+				if ( value === "" ) {
+					elem.setAttribute( name, "auto" );
+					return value;
+				}
+			}
+		};
+	});
+}
+
+if ( !support.style ) {
+	jQuery.attrHooks.style = {
+		get: function( elem ) {
+			// Return undefined in the case of empty string
+			// Note: IE uppercases css property names, but if we were to .toLowerCase()
+			// .cssText, that would destroy case senstitivity in URL's, like in "background"
+			return elem.style.cssText || undefined;
+		},
+		set: function( elem, value ) {
+			return ( elem.style.cssText = value + "" );
+		}
+	};
+}
+
+
+
+
+var rfocusable = /^(?:input|select|textarea|button|object)$/i,
+	rclickable = /^(?:a|area)$/i;
+
+jQuery.fn.extend({
+	prop: function( name, value ) {
+		return access( this, jQuery.prop, name, value, arguments.length > 1 );
+	},
+
+	removeProp: function( name ) {
+		name = jQuery.propFix[ name ] || name;
+		return this.each(function() {
+			// try/catch handles cases where IE balks (such as removing a property on window)
+			try {
+				this[ name ] = undefined;
+				delete this[ name ];
+			} catch( e ) {}
+		});
+	}
+});
+
+jQuery.extend({
+	propFix: {
+		"for": "htmlFor",
+		"class": "className"
+	},
+
+	prop: function( elem, name, value ) {
+		var ret, hooks, notxml,
+			nType = elem.nodeType;
+
+		// don't get/set properties on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+		if ( notxml ) {
+			// Fix name and attach hooks
+			name = jQuery.propFix[ name ] || name;
+			hooks = jQuery.propHooks[ name ];
+		}
+
+		if ( value !== undefined ) {
+			return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
+				ret :
+				( elem[ name ] = value );
+
+		} else {
+			return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
+				ret :
+				elem[ name ];
+		}
+	},
+
+	propHooks: {
+		tabIndex: {
+			get: function( elem ) {
+				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+				// Use proper attribute retrieval(#12072)
+				var tabindex = jQuery.find.attr( elem, "tabindex" );
+
+				return tabindex ?
+					parseInt( tabindex, 10 ) :
+					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+						0 :
+						-1;
+			}
+		}
+	}
+});
+
+// Some attributes require a special call on IE
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !support.hrefNormalized ) {
+	// href/src property should get the full normalized URL (#10299/#12915)
+	jQuery.each([ "href", "src" ], function( i, name ) {
+		jQuery.propHooks[ name ] = {
+			get: function( elem ) {
+				return elem.getAttribute( name, 4 );
+			}
+		};
+	});
+}
+
+// Support: Safari, IE9+
+// mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !support.optSelected ) {
+	jQuery.propHooks.selected = {
+		get: function( elem ) {
+			var parent = elem.parentNode;
+
+			if ( parent ) {
+				parent.selectedIndex;
+
+				// Make sure that it also works with optgroups, see #5701
+				if ( parent.parentNode ) {
+					parent.parentNode.selectedIndex;
+				}
+			}
+			return null;
+		}
+	};
+}
+
+jQuery.each([
+	"tabIndex",
+	"readOnly",
+	"maxLength",
+	"cellSpacing",
+	"cellPadding",
+	"rowSpan",
+	"colSpan",
+	"useMap",
+	"frameBorder",
+	"contentEditable"
+], function() {
+	jQuery.propFix[ this.toLowerCase() ] = this;
+});
+
+// IE6/7 call enctype encoding
+if ( !support.enctype ) {
+	jQuery.propFix.enctype = "encoding";
+}
+
+
+
+
+var rclass = /[\t\r\n\f]/g;
+
+jQuery.fn.extend({
+	addClass: function( value ) {
+		var classes, elem, cur, clazz, j, finalValue,
+			i = 0,
+			len = this.length,
+			proceed = typeof value === "string" && value;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).addClass( value.call( this, j, this.className ) );
+			});
+		}
+
+		if ( proceed ) {
+			// The disjunction here is for better compressibility (see removeClass)
+			classes = ( value || "" ).match( rnotwhite ) || [];
+
+			for ( ; i < len; i++ ) {
+				elem = this[ i ];
+				cur = elem.nodeType === 1 && ( elem.className ?
+					( " " + elem.className + " " ).replace( rclass, " " ) :
+					" "
+				);
+
+				if ( cur ) {
+					j = 0;
+					while ( (clazz = classes[j++]) ) {
+						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+							cur += clazz + " ";
+						}
+					}
+
+					// only assign if different to avoid unneeded rendering.
+					finalValue = jQuery.trim( cur );
+					if ( elem.className !== finalValue ) {
+						elem.className = finalValue;
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	removeClass: function( value ) {
+		var classes, elem, cur, clazz, j, finalValue,
+			i = 0,
+			len = this.length,
+			proceed = arguments.length === 0 || typeof value === "string" && value;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).removeClass( value.call( this, j, this.className ) );
+			});
+		}
+		if ( proceed ) {
+			classes = ( value || "" ).match( rnotwhite ) || [];
+
+			for ( ; i < len; i++ ) {
+				elem = this[ i ];
+				// This expression is here for better compressibility (see addClass)
+				cur = elem.nodeType === 1 && ( elem.className ?
+					( " " + elem.className + " " ).replace( rclass, " " ) :
+					""
+				);
+
+				if ( cur ) {
+					j = 0;
+					while ( (clazz = classes[j++]) ) {
+						// Remove *all* instances
+						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+							cur = cur.replace( " " + clazz + " ", " " );
+						}
+					}
+
+					// only assign if different to avoid unneeded rendering.
+					finalValue = value ? jQuery.trim( cur ) : "";
+					if ( elem.className !== finalValue ) {
+						elem.className = finalValue;
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	toggleClass: function( value, stateVal ) {
+		var type = typeof value;
+
+		if ( typeof stateVal === "boolean" && type === "string" ) {
+			return stateVal ? this.addClass( value ) : this.removeClass( value );
+		}
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( i ) {
+				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+			});
+		}
+
+		return this.each(function() {
+			if ( type === "string" ) {
+				// toggle individual class names
+				var className,
+					i = 0,
+					self = jQuery( this ),
+					classNames = value.match( rnotwhite ) || [];
+
+				while ( (className = classNames[ i++ ]) ) {
+					// check each className given, space separated list
+					if ( self.hasClass( className ) ) {
+						self.removeClass( className );
+					} else {
+						self.addClass( className );
+					}
+				}
+
+			// Toggle whole class name
+			} else if ( type === strundefined || type === "boolean" ) {
+				if ( this.className ) {
+					// store className if set
+					jQuery._data( this, "__className__", this.className );
+				}
+
+				// If the element has a class name or if we're passed "false",
+				// then remove the whole classname (if there was one, the above saved it).
+				// Otherwise bring back whatever was previously saved (if anything),
+				// falling back to the empty string if nothing was stored.
+				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+			}
+		});
+	},
+
+	hasClass: function( selector ) {
+		var className = " " + selector + " ",
+			i = 0,
+			l = this.length;
+		for ( ; i < l; i++ ) {
+			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+});
+
+
+
+
+// Return jQuery for attributes-only inclusion
+
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+	// Handle event binding
+	jQuery.fn[ name ] = function( data, fn ) {
+		return arguments.length > 0 ?
+			this.on( name, null, data, fn ) :
+			this.trigger( name );
+	};
+});
+
+jQuery.fn.extend({
+	hover: function( fnOver, fnOut ) {
+		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+	},
+
+	bind: function( types, data, fn ) {
+		return this.on( types, null, data, fn );
+	},
+	unbind: function( types, fn ) {
+		return this.off( types, null, fn );
+	},
+
+	delegate: function( selector, types, data, fn ) {
+		return this.on( types, selector, data, fn );
+	},
+	undelegate: function( selector, types, fn ) {
+		// ( namespace ) or ( selector, types [, fn] )
+		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+	}
+});
+
+
+var nonce = jQuery.now();
+
+var rquery = (/\?/);
+
+
+
+var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
+
+jQuery.parseJSON = function( data ) {
+	// Attempt to parse using the native JSON parser first
+	if ( window.JSON && window.JSON.parse ) {
+		// Support: Android 2.3
+		// Workaround failure to string-cast null input
+		return window.JSON.parse( data + "" );
+	}
+
+	var requireNonComma,
+		depth = null,
+		str = jQuery.trim( data + "" );
+
+	// Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
+	// after removing valid tokens
+	return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
+
+		// Force termination if we see a misplaced comma
+		if ( requireNonComma && comma ) {
+			depth = 0;
+		}
+
+		// Perform no more replacements after returning to outermost depth
+		if ( depth === 0 ) {
+			return token;
+		}
+
+		// Commas must not follow "[", "{", or ","
+		requireNonComma = open || comma;
+
+		// Determine new depth
+		// array/object open ("[" or "{"): depth += true - false (increment)
+		// array/object close ("]" or "}"): depth += false - true (decrement)
+		// other cases ("," or primitive): depth += true - true (numeric cast)
+		depth += !close - !open;
+
+		// Remove this token
+		return "";
+	}) ) ?
+		( Function( "return " + str ) )() :
+		jQuery.error( "Invalid JSON: " + data );
+};
+
+
+// Cross-browser xml parsing
+jQuery.parseXML = function( data ) {
+	var xml, tmp;
+	if ( !data || typeof data !== "string" ) {
+		return null;
+	}
+	try {
+		if ( window.DOMParser ) { // Standard
+			tmp = new DOMParser();
+			xml = tmp.parseFromString( data, "text/xml" );
+		} else { // IE
+			xml = new ActiveXObject( "Microsoft.XMLDOM" );
+			xml.async = "false";
+			xml.loadXML( data );
+		}
+	} catch( e ) {
+		xml = undefined;
+	}
+	if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+		jQuery.error( "Invalid XML: " + data );
+	}
+	return xml;
+};
+
+
+var
+	// Document location
+	ajaxLocParts,
+	ajaxLocation,
+
+	rhash = /#.*$/,
+	rts = /([?&])_=[^&]*/,
+	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+	// #7653, #8125, #8152: local protocol detection
+	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+	rnoContent = /^(?:GET|HEAD)$/,
+	rprotocol = /^\/\//,
+	rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
+
+	/* Prefilters
+	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+	 * 2) These are called:
+	 *    - BEFORE asking for a transport
+	 *    - AFTER param serialization (s.data is a string if s.processData is true)
+	 * 3) key is the dataType
+	 * 4) the catchall symbol "*" can be used
+	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+	 */
+	prefilters = {},
+
+	/* Transports bindings
+	 * 1) key is the dataType
+	 * 2) the catchall symbol "*" can be used
+	 * 3) selection will start with transport dataType and THEN go to "*" if needed
+	 */
+	transports = {},
+
+	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+	allTypes = "*/".concat("*");
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+	ajaxLocation = location.href;
+} catch( e ) {
+	// Use the href attribute of an A element
+	// since IE will modify it given document.location
+	ajaxLocation = document.createElement( "a" );
+	ajaxLocation.href = "";
+	ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+	// dataTypeExpression is optional and defaults to "*"
+	return function( dataTypeExpression, func ) {
+
+		if ( typeof dataTypeExpression !== "string" ) {
+			func = dataTypeExpression;
+			dataTypeExpression = "*";
+		}
+
+		var dataType,
+			i = 0,
+			dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
+
+		if ( jQuery.isFunction( func ) ) {
+			// For each dataType in the dataTypeExpression
+			while ( (dataType = dataTypes[i++]) ) {
+				// Prepend if requested
+				if ( dataType.charAt( 0 ) === "+" ) {
+					dataType = dataType.slice( 1 ) || "*";
+					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+
+				// Otherwise append
+				} else {
+					(structure[ dataType ] = structure[ dataType ] || []).push( func );
+				}
+			}
+		}
+	};
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+	var inspected = {},
+		seekingTransport = ( structure === transports );
+
+	function inspect( dataType ) {
+		var selected;
+		inspected[ dataType ] = true;
+		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+			if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+				options.dataTypes.unshift( dataTypeOrTransport );
+				inspect( dataTypeOrTransport );
+				return false;
+			} else if ( seekingTransport ) {
+				return !( selected = dataTypeOrTransport );
+			}
+		});
+		return selected;
+	}
+
+	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+	var deep, key,
+		flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+	for ( key in src ) {
+		if ( src[ key ] !== undefined ) {
+			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+		}
+	}
+	if ( deep ) {
+		jQuery.extend( true, target, deep );
+	}
+
+	return target;
+}
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+	var firstDataType, ct, finalDataType, type,
+		contents = s.contents,
+		dataTypes = s.dataTypes;
+
+	// Remove auto dataType and get content-type in the process
+	while ( dataTypes[ 0 ] === "*" ) {
+		dataTypes.shift();
+		if ( ct === undefined ) {
+			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+		}
+	}
+
+	// Check if we're dealing with a known content-type
+	if ( ct ) {
+		for ( type in contents ) {
+			if ( contents[ type ] && contents[ type ].test( ct ) ) {
+				dataTypes.unshift( type );
+				break;
+			}
+		}
+	}
+
+	// Check to see if we have a response for the expected dataType
+	if ( dataTypes[ 0 ] in responses ) {
+		finalDataType = dataTypes[ 0 ];
+	} else {
+		// Try convertible dataTypes
+		for ( type in responses ) {
+			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+				finalDataType = type;
+				break;
+			}
+			if ( !firstDataType ) {
+				firstDataType = type;
+			}
+		}
+		// Or just use first one
+		finalDataType = finalDataType || firstDataType;
+	}
+
+	// If we found a dataType
+	// We add the dataType to the list if needed
+	// and return the corresponding response
+	if ( finalDataType ) {
+		if ( finalDataType !== dataTypes[ 0 ] ) {
+			dataTypes.unshift( finalDataType );
+		}
+		return responses[ finalDataType ];
+	}
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+	var conv2, current, conv, tmp, prev,
+		converters = {},
+		// Work with a copy of dataTypes in case we need to modify it for conversion
+		dataTypes = s.dataTypes.slice();
+
+	// Create converters map with lowercased keys
+	if ( dataTypes[ 1 ] ) {
+		for ( conv in s.converters ) {
+			converters[ conv.toLowerCase() ] = s.converters[ conv ];
+		}
+	}
+
+	current = dataTypes.shift();
+
+	// Convert to each sequential dataType
+	while ( current ) {
+
+		if ( s.responseFields[ current ] ) {
+			jqXHR[ s.responseFields[ current ] ] = response;
+		}
+
+		// Apply the dataFilter if provided
+		if ( !prev && isSuccess && s.dataFilter ) {
+			response = s.dataFilter( response, s.dataType );
+		}
+
+		prev = current;
+		current = dataTypes.shift();
+
+		if ( current ) {
+
+			// There's only work to do if current dataType is non-auto
+			if ( current === "*" ) {
+
+				current = prev;
+
+			// Convert response if prev dataType is non-auto and differs from current
+			} else if ( prev !== "*" && prev !== current ) {
+
+				// Seek a direct converter
+				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+				// If none found, seek a pair
+				if ( !conv ) {
+					for ( conv2 in converters ) {
+
+						// If conv2 outputs current
+						tmp = conv2.split( " " );
+						if ( tmp[ 1 ] === current ) {
+
+							// If prev can be converted to accepted input
+							conv = converters[ prev + " " + tmp[ 0 ] ] ||
+								converters[ "* " + tmp[ 0 ] ];
+							if ( conv ) {
+								// Condense equivalence converters
+								if ( conv === true ) {
+									conv = converters[ conv2 ];
+
+								// Otherwise, insert the intermediate dataType
+								} else if ( converters[ conv2 ] !== true ) {
+									current = tmp[ 0 ];
+									dataTypes.unshift( tmp[ 1 ] );
+								}
+								break;
+							}
+						}
+					}
+				}
+
+				// Apply converter (if not an equivalence)
+				if ( conv !== true ) {
+
+					// Unless errors are allowed to bubble, catch and return them
+					if ( conv && s[ "throws" ] ) {
+						response = conv( response );
+					} else {
+						try {
+							response = conv( response );
+						} catch ( e ) {
+							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return { state: "success", data: response };
+}
+
+jQuery.extend({
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Last-Modified header cache for next request
+	lastModified: {},
+	etag: {},
+
+	ajaxSettings: {
+		url: ajaxLocation,
+		type: "GET",
+		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+		global: true,
+		processData: true,
+		async: true,
+		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+		/*
+		timeout: 0,
+		data: null,
+		dataType: null,
+		username: null,
+		password: null,
+		cache: null,
+		throws: false,
+		traditional: false,
+		headers: {},
+		*/
+
+		accepts: {
+			"*": allTypes,
+			text: "text/plain",
+			html: "text/html",
+			xml: "application/xml, text/xml",
+			json: "application/json, text/javascript"
+		},
+
+		contents: {
+			xml: /xml/,
+			html: /html/,
+			json: /json/
+		},
+
+		responseFields: {
+			xml: "responseXML",
+			text: "responseText",
+			json: "responseJSON"
+		},
+
+		// Data converters
+		// Keys separate source (or catchall "*") and destination types with a single space
+		converters: {
+
+			// Convert anything to text
+			"* text": String,
+
+			// Text to html (true = no transformation)
+			"text html": true,
+
+			// Evaluate text as a json expression
+			"text json": jQuery.parseJSON,
+
+			// Parse text as xml
+			"text xml": jQuery.parseXML
+		},
+
+		// For options that shouldn't be deep extended:
+		// you can add your own custom options here if
+		// and when you create one that shouldn't be
+		// deep extended (see ajaxExtend)
+		flatOptions: {
+			url: true,
+			context: true
+		}
+	},
+
+	// Creates a full fledged settings object into target
+	// with both ajaxSettings and settings fields.
+	// If target is omitted, writes into ajaxSettings.
+	ajaxSetup: function( target, settings ) {
+		return settings ?
+
+			// Building a settings object
+			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+			// Extending ajaxSettings
+			ajaxExtend( jQuery.ajaxSettings, target );
+	},
+
+	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+	ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+	// Main method
+	ajax: function( url, options ) {
+
+		// If url is an object, simulate pre-1.5 signature
+		if ( typeof url === "object" ) {
+			options = url;
+			url = undefined;
+		}
+
+		// Force options to be an object
+		options = options || {};
+
+		var // Cross-domain detection vars
+			parts,
+			// Loop variable
+			i,
+			// URL without anti-cache param
+			cacheURL,
+			// Response headers as string
+			responseHeadersString,
+			// timeout handle
+			timeoutTimer,
+
+			// To know if global events are to be dispatched
+			fireGlobals,
+
+			transport,
+			// Response headers
+			responseHeaders,
+			// Create the final options object
+			s = jQuery.ajaxSetup( {}, options ),
+			// Callbacks context
+			callbackContext = s.context || s,
+			// Context for global events is callbackContext if it is a DOM node or jQuery collection
+			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+				jQuery( callbackContext ) :
+				jQuery.event,
+			// Deferreds
+			deferred = jQuery.Deferred(),
+			completeDeferred = jQuery.Callbacks("once memory"),
+			// Status-dependent callbacks
+			statusCode = s.statusCode || {},
+			// Headers (they are sent all at once)
+			requestHeaders = {},
+			requestHeadersNames = {},
+			// The jqXHR state
+			state = 0,
+			// Default abort message
+			strAbort = "canceled",
+			// Fake xhr
+			jqXHR = {
+				readyState: 0,
+
+				// Builds headers hashtable if needed
+				getResponseHeader: function( key ) {
+					var match;
+					if ( state === 2 ) {
+						if ( !responseHeaders ) {
+							responseHeaders = {};
+							while ( (match = rheaders.exec( responseHeadersString )) ) {
+								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+							}
+						}
+						match = responseHeaders[ key.toLowerCase() ];
+					}
+					return match == null ? null : match;
+				},
+
+				// Raw string
+				getAllResponseHeaders: function() {
+					return state === 2 ? responseHeadersString : null;
+				},
+
+				// Caches the header
+				setRequestHeader: function( name, value ) {
+					var lname = name.toLowerCase();
+					if ( !state ) {
+						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+						requestHeaders[ name ] = value;
+					}
+					return this;
+				},
+
+				// Overrides response content-type header
+				overrideMimeType: function( type ) {
+					if ( !state ) {
+						s.mimeType = type;
+					}
+					return this;
+				},
+
+				// Status-dependent callbacks
+				statusCode: function( map ) {
+					var code;
+					if ( map ) {
+						if ( state < 2 ) {
+							for ( code in map ) {
+								// Lazy-add the new callback in a way that preserves old ones
+								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+							}
+						} else {
+							// Execute the appropriate callbacks
+							jqXHR.always( map[ jqXHR.status ] );
+						}
+					}
+					return this;
+				},
+
+				// Cancel the request
+				abort: function( statusText ) {
+					var finalText = statusText || strAbort;
+					if ( transport ) {
+						transport.abort( finalText );
+					}
+					done( 0, finalText );
+					return this;
+				}
+			};
+
+		// Attach deferreds
+		deferred.promise( jqXHR ).complete = completeDeferred.add;
+		jqXHR.success = jqXHR.done;
+		jqXHR.error = jqXHR.fail;
+
+		// Remove hash character (#7531: and string promotion)
+		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+		// Handle falsy url in the settings object (#10093: consistency with old signature)
+		// We also use the url parameter if available
+		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+		// Alias method option to type as per ticket #12004
+		s.type = options.method || options.type || s.method || s.type;
+
+		// Extract dataTypes list
+		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
+
+		// A cross-domain request is in order when we have a protocol:host:port mismatch
+		if ( s.crossDomain == null ) {
+			parts = rurl.exec( s.url.toLowerCase() );
+			s.crossDomain = !!( parts &&
+				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
+						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
+			);
+		}
+
+		// Convert data if not already a string
+		if ( s.data && s.processData && typeof s.data !== "string" ) {
+			s.data = jQuery.param( s.data, s.traditional );
+		}
+
+		// Apply prefilters
+		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+		// If request was aborted inside a prefilter, stop there
+		if ( state === 2 ) {
+			return jqXHR;
+		}
+
+		// We can fire global events as of now if asked to
+		fireGlobals = s.global;
+
+		// Watch for a new set of requests
+		if ( fireGlobals && jQuery.active++ === 0 ) {
+			jQuery.event.trigger("ajaxStart");
+		}
+
+		// Uppercase the type
+		s.type = s.type.toUpperCase();
+
+		// Determine if request has content
+		s.hasContent = !rnoContent.test( s.type );
+
+		// Save the URL in case we're toying with the If-Modified-Since
+		// and/or If-None-Match header later on
+		cacheURL = s.url;
+
+		// More options handling for requests with no content
+		if ( !s.hasContent ) {
+
+			// If data is available, append data to url
+			if ( s.data ) {
+				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+				// #9682: remove data so that it's not used in an eventual retry
+				delete s.data;
+			}
+
+			// Add anti-cache in url if needed
+			if ( s.cache === false ) {
+				s.url = rts.test( cacheURL ) ?
+
+					// If there is already a '_' parameter, set its value
+					cacheURL.replace( rts, "$1_=" + nonce++ ) :
+
+					// Otherwise add one to the end
+					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
+			}
+		}
+
+		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+		if ( s.ifModified ) {
+			if ( jQuery.lastModified[ cacheURL ] ) {
+				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+			}
+			if ( jQuery.etag[ cacheURL ] ) {
+				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+			}
+		}
+
+		// Set the correct header, if data is being sent
+		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+			jqXHR.setRequestHeader( "Content-Type", s.contentType );
+		}
+
+		// Set the Accepts header for the server, depending on the dataType
+		jqXHR.setRequestHeader(
+			"Accept",
+			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+				s.accepts[ "*" ]
+		);
+
+		// Check for headers option
+		for ( i in s.headers ) {
+			jqXHR.setRequestHeader( i, s.headers[ i ] );
+		}
+
+		// Allow custom headers/mimetypes and early abort
+		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+			// Abort if not done already and return
+			return jqXHR.abort();
+		}
+
+		// aborting is no longer a cancellation
+		strAbort = "abort";
+
+		// Install callbacks on deferreds
+		for ( i in { success: 1, error: 1, complete: 1 } ) {
+			jqXHR[ i ]( s[ i ] );
+		}
+
+		// Get transport
+		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+		// If no transport, we auto-abort
+		if ( !transport ) {
+			done( -1, "No Transport" );
+		} else {
+			jqXHR.readyState = 1;
+
+			// Send global event
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+			}
+			// Timeout
+			if ( s.async && s.timeout > 0 ) {
+				timeoutTimer = setTimeout(function() {
+					jqXHR.abort("timeout");
+				}, s.timeout );
+			}
+
+			try {
+				state = 1;
+				transport.send( requestHeaders, done );
+			} catch ( e ) {
+				// Propagate exception as error if not done
+				if ( state < 2 ) {
+					done( -1, e );
+				// Simply rethrow otherwise
+				} else {
+					throw e;
+				}
+			}
+		}
+
+		// Callback for when everything is done
+		function done( status, nativeStatusText, responses, headers ) {
+			var isSuccess, success, error, response, modified,
+				statusText = nativeStatusText;
+
+			// Called once
+			if ( state === 2 ) {
+				return;
+			}
+
+			// State is "done" now
+			state = 2;
+
+			// Clear timeout if it exists
+			if ( timeoutTimer ) {
+				clearTimeout( timeoutTimer );
+			}
+
+			// Dereference transport for early garbage collection
+			// (no matter how long the jqXHR object will be used)
+			transport = undefined;
+
+			// Cache response headers
+			responseHeadersString = headers || "";
+
+			// Set readyState
+			jqXHR.readyState = status > 0 ? 4 : 0;
+
+			// Determine if successful
+			isSuccess = status >= 200 && status < 300 || status === 304;
+
+			// Get response data
+			if ( responses ) {
+				response = ajaxHandleResponses( s, jqXHR, responses );
+			}
+
+			// Convert no matter what (that way responseXXX fields are always set)
+			response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+			// If successful, handle type chaining
+			if ( isSuccess ) {
+
+				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+				if ( s.ifModified ) {
+					modified = jqXHR.getResponseHeader("Last-Modified");
+					if ( modified ) {
+						jQuery.lastModified[ cacheURL ] = modified;
+					}
+					modified = jqXHR.getResponseHeader("etag");
+					if ( modified ) {
+						jQuery.etag[ cacheURL ] = modified;
+					}
+				}
+
+				// if no content
+				if ( status === 204 || s.type === "HEAD" ) {
+					statusText = "nocontent";
+
+				// if not modified
+				} else if ( status === 304 ) {
+					statusText = "notmodified";
+
+				// If we have data, let's convert it
+				} else {
+					statusText = response.state;
+					success = response.data;
+					error = response.error;
+					isSuccess = !error;
+				}
+			} else {
+				// We extract error from statusText
+				// then normalize statusText and status for non-aborts
+				error = statusText;
+				if ( status || !statusText ) {
+					statusText = "error";
+					if ( status < 0 ) {
+						status = 0;
+					}
+				}
+			}
+
+			// Set data for the fake xhr object
+			jqXHR.status = status;
+			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+			// Success/Error
+			if ( isSuccess ) {
+				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+			} else {
+				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+			}
+
+			// Status-dependent callbacks
+			jqXHR.statusCode( statusCode );
+			statusCode = undefined;
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+					[ jqXHR, s, isSuccess ? success : error ] );
+			}
+
+			// Complete
+			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+				// Handle the global AJAX counter
+				if ( !( --jQuery.active ) ) {
+					jQuery.event.trigger("ajaxStop");
+				}
+			}
+		}
+
+		return jqXHR;
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get( url, data, callback, "json" );
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get( url, undefined, callback, "script" );
+	}
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+	jQuery[ method ] = function( url, data, callback, type ) {
+		// shift arguments if data argument was omitted
+		if ( jQuery.isFunction( data ) ) {
+			type = type || callback;
+			callback = data;
+			data = undefined;
+		}
+
+		return jQuery.ajax({
+			url: url,
+			type: method,
+			dataType: type,
+			data: data,
+			success: callback
+		});
+	};
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
+	jQuery.fn[ type ] = function( fn ) {
+		return this.on( type, fn );
+	};
+});
+
+
+jQuery._evalUrl = function( url ) {
+	return jQuery.ajax({
+		url: url,
+		type: "GET",
+		dataType: "script",
+		async: false,
+		global: false,
+		"throws": true
+	});
+};
+
+
+jQuery.fn.extend({
+	wrapAll: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapAll( html.call(this, i) );
+			});
+		}
+
+		if ( this[0] ) {
+			// The elements to wrap the target around
+			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+			if ( this[0].parentNode ) {
+				wrap.insertBefore( this[0] );
+			}
+
+			wrap.map(function() {
+				var elem = this;
+
+				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+					elem = elem.firstChild;
+				}
+
+				return elem;
+			}).append( this );
+		}
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapInner( html.call(this, i) );
+			});
+		}
+
+		return this.each(function() {
+			var self = jQuery( this ),
+				contents = self.contents();
+
+			if ( contents.length ) {
+				contents.wrapAll( html );
+
+			} else {
+				self.append( html );
+			}
+		});
+	},
+
+	wrap: function( html ) {
+		var isFunction = jQuery.isFunction( html );
+
+		return this.each(function(i) {
+			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+		});
+	},
+
+	unwrap: function() {
+		return this.parent().each(function() {
+			if ( !jQuery.nodeName( this, "body" ) ) {
+				jQuery( this ).replaceWith( this.childNodes );
+			}
+		}).end();
+	}
+});
+
+
+jQuery.expr.filters.hidden = function( elem ) {
+	// Support: Opera <= 12.12
+	// Opera reports offsetWidths and offsetHeights less than zero on some elements
+	return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
+		(!support.reliableHiddenOffsets() &&
+			((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+};
+
+jQuery.expr.filters.visible = function( elem ) {
+	return !jQuery.expr.filters.hidden( elem );
+};
+
+
+
+
+var r20 = /%20/g,
+	rbracket = /\[\]$/,
+	rCRLF = /\r?\n/g,
+	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+	rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+function buildParams( prefix, obj, traditional, add ) {
+	var name;
+
+	if ( jQuery.isArray( obj ) ) {
+		// Serialize array item.
+		jQuery.each( obj, function( i, v ) {
+			if ( traditional || rbracket.test( prefix ) ) {
+				// Treat each array item as a scalar.
+				add( prefix, v );
+
+			} else {
+				// Item is non-scalar (array or object), encode its numeric index.
+				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+			}
+		});
+
+	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
+		// Serialize object item.
+		for ( name in obj ) {
+			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+		}
+
+	} else {
+		// Serialize scalar item.
+		add( prefix, obj );
+	}
+}
+
+// Serialize an array of form elements or a set of
+// key/values into a query string
+jQuery.param = function( a, traditional ) {
+	var prefix,
+		s = [],
+		add = function( key, value ) {
+			// If value is a function, invoke it and return its value
+			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+		};
+
+	// Set traditional to true for jQuery <= 1.3.2 behavior.
+	if ( traditional === undefined ) {
+		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+	}
+
+	// If an array was passed in, assume that it is an array of form elements.
+	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+		// Serialize the form elements
+		jQuery.each( a, function() {
+			add( this.name, this.value );
+		});
+
+	} else {
+		// If traditional, encode the "old" way (the way 1.3.2 or older
+		// did it), otherwise encode params recursively.
+		for ( prefix in a ) {
+			buildParams( prefix, a[ prefix ], traditional, add );
+		}
+	}
+
+	// Return the resulting serialization
+	return s.join( "&" ).replace( r20, "+" );
+};
+
+jQuery.fn.extend({
+	serialize: function() {
+		return jQuery.param( this.serializeArray() );
+	},
+	serializeArray: function() {
+		return this.map(function() {
+			// Can add propHook for "elements" to filter or add form elements
+			var elements = jQuery.prop( this, "elements" );
+			return elements ? jQuery.makeArray( elements ) : this;
+		})
+		.filter(function() {
+			var type = this.type;
+			// Use .is(":disabled") so that fieldset[disabled] works
+			return this.name && !jQuery( this ).is( ":disabled" ) &&
+				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+				( this.checked || !rcheckableType.test( type ) );
+		})
+		.map(function( i, elem ) {
+			var val = jQuery( this ).val();
+
+			return val == null ?
+				null :
+				jQuery.isArray( val ) ?
+					jQuery.map( val, function( val ) {
+						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+					}) :
+					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+		}).get();
+	}
+});
+
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
+	// Support: IE6+
+	function() {
+
+		// XHR cannot access local files, always use ActiveX for that case
+		return !this.isLocal &&
+
+			// Support: IE7-8
+			// oldIE XHR does not support non-RFC2616 methods (#13240)
+			// See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
+			// and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
+			// Although this check for six methods instead of eight
+			// since IE also does not support "trace" and "connect"
+			/^(get|post|head|put|delete|options)$/i.test( this.type ) &&
+
+			createStandardXHR() || createActiveXHR();
+	} :
+	// For all other browsers, use the standard XMLHttpRequest object
+	createStandardXHR;
+
+var xhrId = 0,
+	xhrCallbacks = {},
+	xhrSupported = jQuery.ajaxSettings.xhr();
+
+// Support: IE<10
+// Open requests must be manually aborted on unload (#5280)
+if ( window.ActiveXObject ) {
+	jQuery( window ).on( "unload", function() {
+		for ( var key in xhrCallbacks ) {
+			xhrCallbacks[ key ]( undefined, true );
+		}
+	});
+}
+
+// Determine support properties
+support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+xhrSupported = support.ajax = !!xhrSupported;
+
+// Create transport if the browser can provide an xhr
+if ( xhrSupported ) {
+
+	jQuery.ajaxTransport(function( options ) {
+		// Cross domain only allowed if supported through XMLHttpRequest
+		if ( !options.crossDomain || support.cors ) {
+
+			var callback;
+
+			return {
+				send: function( headers, complete ) {
+					var i,
+						xhr = options.xhr(),
+						id = ++xhrId;
+
+					// Open the socket
+					xhr.open( options.type, options.url, options.async, options.username, options.password );
+
+					// Apply custom fields if provided
+					if ( options.xhrFields ) {
+						for ( i in options.xhrFields ) {
+							xhr[ i ] = options.xhrFields[ i ];
+						}
+					}
+
+					// Override mime type if needed
+					if ( options.mimeType && xhr.overrideMimeType ) {
+						xhr.overrideMimeType( options.mimeType );
+					}
+
+					// X-Requested-With header
+					// For cross-domain requests, seeing as conditions for a preflight are
+					// akin to a jigsaw puzzle, we simply never set it to be sure.
+					// (it can always be set on a per-request basis or even using ajaxSetup)
+					// For same-domain requests, won't change header if already provided.
+					if ( !options.crossDomain && !headers["X-Requested-With"] ) {
+						headers["X-Requested-With"] = "XMLHttpRequest";
+					}
+
+					// Set headers
+					for ( i in headers ) {
+						// Support: IE<9
+						// IE's ActiveXObject throws a 'Type Mismatch' exception when setting
+						// request header to a null-value.
+						//
+						// To keep consistent with other XHR implementations, cast the value
+						// to string and ignore `undefined`.
+						if ( headers[ i ] !== undefined ) {
+							xhr.setRequestHeader( i, headers[ i ] + "" );
+						}
+					}
+
+					// Do send the request
+					// This may raise an exception which is actually
+					// handled in jQuery.ajax (so no try/catch here)
+					xhr.send( ( options.hasContent && options.data ) || null );
+
+					// Listener
+					callback = function( _, isAbort ) {
+						var status, statusText, responses;
+
+						// Was never called and is aborted or complete
+						if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+							// Clean up
+							delete xhrCallbacks[ id ];
+							callback = undefined;
+							xhr.onreadystatechange = jQuery.noop;
+
+							// Abort manually if needed
+							if ( isAbort ) {
+								if ( xhr.readyState !== 4 ) {
+									xhr.abort();
+								}
+							} else {
+								responses = {};
+								status = xhr.status;
+
+								// Support: IE<10
+								// Accessing binary-data responseText throws an exception
+								// (#11426)
+								if ( typeof xhr.responseText === "string" ) {
+									responses.text = xhr.responseText;
+								}
+
+								// Firefox throws an exception when accessing
+								// statusText for faulty cross-domain requests
+								try {
+									statusText = xhr.statusText;
+								} catch( e ) {
+									// We normalize with Webkit giving an empty statusText
+									statusText = "";
+								}
+
+								// Filter status for non standard behaviors
+
+								// If the request is local and we have data: assume a success
+								// (success with no data won't get notified, that's the best we
+								// can do given current implementations)
+								if ( !status && options.isLocal && !options.crossDomain ) {
+									status = responses.text ? 200 : 404;
+								// IE - #1450: sometimes returns 1223 when it should be 204
+								} else if ( status === 1223 ) {
+									status = 204;
+								}
+							}
+						}
+
+						// Call complete if needed
+						if ( responses ) {
+							complete( status, statusText, responses, xhr.getAllResponseHeaders() );
+						}
+					};
+
+					if ( !options.async ) {
+						// if we're in sync mode we fire the callback
+						callback();
+					} else if ( xhr.readyState === 4 ) {
+						// (IE6 & IE7) if it's in cache and has been
+						// retrieved directly we need to fire the callback
+						setTimeout( callback );
+					} else {
+						// Add to the list of active xhr callbacks
+						xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
+					}
+				},
+
+				abort: function() {
+					if ( callback ) {
+						callback( undefined, true );
+					}
+				}
+			};
+		}
+	});
+}
+
+// Functions to create xhrs
+function createStandardXHR() {
+	try {
+		return new window.XMLHttpRequest();
+	} catch( e ) {}
+}
+
+function createActiveXHR() {
+	try {
+		return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+	} catch( e ) {}
+}
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup({
+	accepts: {
+		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+	},
+	contents: {
+		script: /(?:java|ecma)script/
+	},
+	converters: {
+		"text script": function( text ) {
+			jQuery.globalEval( text );
+			return text;
+		}
+	}
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+	if ( s.cache === undefined ) {
+		s.cache = false;
+	}
+	if ( s.crossDomain ) {
+		s.type = "GET";
+		s.global = false;
+	}
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+	// This transport only deals with cross domain requests
+	if ( s.crossDomain ) {
+
+		var script,
+			head = document.head || jQuery("head")[0] || document.documentElement;
+
+		return {
+
+			send: function( _, callback ) {
+
+				script = document.createElement("script");
+
+				script.async = true;
+
+				if ( s.scriptCharset ) {
+					script.charset = s.scriptCharset;
+				}
+
+				script.src = s.url;
+
+				// Attach handlers for all browsers
+				script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+					if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+						// Handle memory leak in IE
+						script.onload = script.onreadystatechange = null;
+
+						// Remove the script
+						if ( script.parentNode ) {
+							script.parentNode.removeChild( script );
+						}
+
+						// Dereference the script
+						script = null;
+
+						// Callback if not abort
+						if ( !isAbort ) {
+							callback( 200, "success" );
+						}
+					}
+				};
+
+				// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
+				// Use native DOM manipulation to avoid our domManip AJAX trickery
+				head.insertBefore( script, head.firstChild );
+			},
+
+			abort: function() {
+				if ( script ) {
+					script.onload( undefined, true );
+				}
+			}
+		};
+	}
+});
+
+
+
+
+var oldCallbacks = [],
+	rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+	jsonp: "callback",
+	jsonpCallback: function() {
+		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+		this[ callback ] = true;
+		return callback;
+	}
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+	var callbackName, overwritten, responseContainer,
+		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+			"url" :
+			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+		);
+
+	// Handle iff the expected data type is "jsonp" or we have a parameter to set
+	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+		// Get callback name, remembering preexisting value associated with it
+		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+			s.jsonpCallback() :
+			s.jsonpCallback;
+
+		// Insert callback into url or form data
+		if ( jsonProp ) {
+			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+		} else if ( s.jsonp !== false ) {
+			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+		}
+
+		// Use data converter to retrieve json after script execution
+		s.converters["script json"] = function() {
+			if ( !responseContainer ) {
+				jQuery.error( callbackName + " was not called" );
+			}
+			return responseContainer[ 0 ];
+		};
+
+		// force json dataType
+		s.dataTypes[ 0 ] = "json";
+
+		// Install callback
+		overwritten = window[ callbackName ];
+		window[ callbackName ] = function() {
+			responseContainer = arguments;
+		};
+
+		// Clean-up function (fires after converters)
+		jqXHR.always(function() {
+			// Restore preexisting value
+			window[ callbackName ] = overwritten;
+
+			// Save back as free
+			if ( s[ callbackName ] ) {
+				// make sure that re-using the options doesn't screw things around
+				s.jsonpCallback = originalSettings.jsonpCallback;
+
+				// save the callback name for future use
+				oldCallbacks.push( callbackName );
+			}
+
+			// Call if it was a function and we have a response
+			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+				overwritten( responseContainer[ 0 ] );
+			}
+
+			responseContainer = overwritten = undefined;
+		});
+
+		// Delegate to script
+		return "script";
+	}
+});
+
+
+
+
+// data: string of html
+// context (optional): If specified, the fragment will be created in this context, defaults to document
+// keepScripts (optional): If true, will include scripts passed in the html string
+jQuery.parseHTML = function( data, context, keepScripts ) {
+	if ( !data || typeof data !== "string" ) {
+		return null;
+	}
+	if ( typeof context === "boolean" ) {
+		keepScripts = context;
+		context = false;
+	}
+	context = context || document;
+
+	var parsed = rsingleTag.exec( data ),
+		scripts = !keepScripts && [];
+
+	// Single tag
+	if ( parsed ) {
+		return [ context.createElement( parsed[1] ) ];
+	}
+
+	parsed = jQuery.buildFragment( [ data ], context, scripts );
+
+	if ( scripts && scripts.length ) {
+		jQuery( scripts ).remove();
+	}
+
+	return jQuery.merge( [], parsed.childNodes );
+};
+
+
+// Keep a copy of the old load method
+var _load = jQuery.fn.load;
+
+/**
+ * Load a url into a page
+ */
+jQuery.fn.load = function( url, params, callback ) {
+	if ( typeof url !== "string" && _load ) {
+		return _load.apply( this, arguments );
+	}
+
+	var selector, response, type,
+		self = this,
+		off = url.indexOf(" ");
+
+	if ( off >= 0 ) {
+		selector = url.slice( off, url.length );
+		url = url.slice( 0, off );
+	}
+
+	// If it's a function
+	if ( jQuery.isFunction( params ) ) {
+
+		// We assume that it's the callback
+		callback = params;
+		params = undefined;
+
+	// Otherwise, build a param string
+	} else if ( params && typeof params === "object" ) {
+		type = "POST";
+	}
+
+	// If we have elements to modify, make the request
+	if ( self.length > 0 ) {
+		jQuery.ajax({
+			url: url,
+
+			// if "type" variable is undefined, then "GET" method will be used
+			type: type,
+			dataType: "html",
+			data: params
+		}).done(function( responseText ) {
+
+			// Save response for use in complete callback
+			response = arguments;
+
+			self.html( selector ?
+
+				// If a selector was specified, locate the right elements in a dummy div
+				// Exclude scripts to avoid IE 'Permission Denied' errors
+				jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+				// Otherwise use the full result
+				responseText );
+
+		}).complete( callback && function( jqXHR, status ) {
+			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+		});
+	}
+
+	return this;
+};
+
+
+
+
+jQuery.expr.filters.animated = function( elem ) {
+	return jQuery.grep(jQuery.timers, function( fn ) {
+		return elem === fn.elem;
+	}).length;
+};
+
+
+
+
+
+var docElem = window.document.documentElement;
+
+/**
+ * Gets a window from an element
+ */
+function getWindow( elem ) {
+	return jQuery.isWindow( elem ) ?
+		elem :
+		elem.nodeType === 9 ?
+			elem.defaultView || elem.parentWindow :
+			false;
+}
+
+jQuery.offset = {
+	setOffset: function( elem, options, i ) {
+		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+			position = jQuery.css( elem, "position" ),
+			curElem = jQuery( elem ),
+			props = {};
+
+		// set position first, in-case top/left are set even on static elem
+		if ( position === "static" ) {
+			elem.style.position = "relative";
+		}
+
+		curOffset = curElem.offset();
+		curCSSTop = jQuery.css( elem, "top" );
+		curCSSLeft = jQuery.css( elem, "left" );
+		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+			jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
+
+		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+		if ( calculatePosition ) {
+			curPosition = curElem.position();
+			curTop = curPosition.top;
+			curLeft = curPosition.left;
+		} else {
+			curTop = parseFloat( curCSSTop ) || 0;
+			curLeft = parseFloat( curCSSLeft ) || 0;
+		}
+
+		if ( jQuery.isFunction( options ) ) {
+			options = options.call( elem, i, curOffset );
+		}
+
+		if ( options.top != null ) {
+			props.top = ( options.top - curOffset.top ) + curTop;
+		}
+		if ( options.left != null ) {
+			props.left = ( options.left - curOffset.left ) + curLeft;
+		}
+
+		if ( "using" in options ) {
+			options.using.call( elem, props );
+		} else {
+			curElem.css( props );
+		}
+	}
+};
+
+jQuery.fn.extend({
+	offset: function( options ) {
+		if ( arguments.length ) {
+			return options === undefined ?
+				this :
+				this.each(function( i ) {
+					jQuery.offset.setOffset( this, options, i );
+				});
+		}
+
+		var docElem, win,
+			box = { top: 0, left: 0 },
+			elem = this[ 0 ],
+			doc = elem && elem.ownerDocument;
+
+		if ( !doc ) {
+			return;
+		}
+
+		docElem = doc.documentElement;
+
+		// Make sure it's not a disconnected DOM node
+		if ( !jQuery.contains( docElem, elem ) ) {
+			return box;
+		}
+
+		// If we don't have gBCR, just use 0,0 rather than error
+		// BlackBerry 5, iOS 3 (original iPhone)
+		if ( typeof elem.getBoundingClientRect !== strundefined ) {
+			box = elem.getBoundingClientRect();
+		}
+		win = getWindow( doc );
+		return {
+			top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
+			left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+		};
+	},
+
+	position: function() {
+		if ( !this[ 0 ] ) {
+			return;
+		}
+
+		var offsetParent, offset,
+			parentOffset = { top: 0, left: 0 },
+			elem = this[ 0 ];
+
+		// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
+		if ( jQuery.css( elem, "position" ) === "fixed" ) {
+			// we assume that getBoundingClientRect is available when computed position is fixed
+			offset = elem.getBoundingClientRect();
+		} else {
+			// Get *real* offsetParent
+			offsetParent = this.offsetParent();
+
+			// Get correct offsets
+			offset = this.offset();
+			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+				parentOffset = offsetParent.offset();
+			}
+
+			// Add offsetParent borders
+			parentOffset.top  += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+		}
+
+		// Subtract parent offsets and element margins
+		// note: when an element has margin: auto the offsetLeft and marginLeft
+		// are the same in Safari causing offset.left to incorrectly be 0
+		return {
+			top:  offset.top  - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
+		};
+	},
+
+	offsetParent: function() {
+		return this.map(function() {
+			var offsetParent = this.offsetParent || docElem;
+
+			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
+				offsetParent = offsetParent.offsetParent;
+			}
+			return offsetParent || docElem;
+		});
+	}
+});
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+	var top = /Y/.test( prop );
+
+	jQuery.fn[ method ] = function( val ) {
+		return access( this, function( elem, method, val ) {
+			var win = getWindow( elem );
+
+			if ( val === undefined ) {
+				return win ? (prop in win) ? win[ prop ] :
+					win.document.documentElement[ method ] :
+					elem[ method ];
+			}
+
+			if ( win ) {
+				win.scrollTo(
+					!top ? val : jQuery( win ).scrollLeft(),
+					top ? val : jQuery( win ).scrollTop()
+				);
+
+			} else {
+				elem[ method ] = val;
+			}
+		}, method, val, arguments.length, null );
+	};
+});
+
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// getComputedStyle returns percent when specified for top/left/bottom/right
+// rather than make the css module depend on the offset module, we just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+		function( elem, computed ) {
+			if ( computed ) {
+				computed = curCSS( elem, prop );
+				// if curCSS returns percentage, fallback to offset
+				return rnumnonpx.test( computed ) ?
+					jQuery( elem ).position()[ prop ] + "px" :
+					computed;
+			}
+		}
+	);
+});
+
+
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+		// margin is only for outerHeight, outerWidth
+		jQuery.fn[ funcName ] = function( margin, value ) {
+			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+			return access( this, function( elem, type, value ) {
+				var doc;
+
+				if ( jQuery.isWindow( elem ) ) {
+					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+					// isn't a whole lot we can do. See pull request at this URL for discussion:
+					// https://github.com/jquery/jquery/pull/764
+					return elem.document.documentElement[ "client" + name ];
+				}
+
+				// Get document width or height
+				if ( elem.nodeType === 9 ) {
+					doc = elem.documentElement;
+
+					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+					// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+					return Math.max(
+						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+						elem.body[ "offset" + name ], doc[ "offset" + name ],
+						doc[ "client" + name ]
+					);
+				}
+
+				return value === undefined ?
+					// Get width or height on the element, requesting but not forcing parseFloat
+					jQuery.css( elem, type, extra ) :
+
+					// Set width or height on the element
+					jQuery.style( elem, type, value, extra );
+			}, type, chainable ? margin : undefined, chainable, null );
+		};
+	});
+});
+
+
+// The number of elements contained in the matched element set
+jQuery.fn.size = function() {
+	return this.length;
+};
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+
+
+
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+if ( typeof define === "function" && define.amd ) {
+	define( "jquery", [], function() {
+		return jQuery;
+	});
+}
+
+
+
+
+var
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+
+	// Map over the $ in case of overwrite
+	_$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+	if ( window.$ === jQuery ) {
+		window.$ = _$;
+	}
+
+	if ( deep && window.jQuery === jQuery ) {
+		window.jQuery = _jQuery;
+	}
+
+	return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in
+// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( typeof noGlobal === strundefined ) {
+	window.jQuery = window.$ = jQuery;
+}
+
+
+
+
+return jQuery;
+
+}));
diff --git a/cabal/pretty-show-1.6.16/style/jquery.js b/cabal/pretty-show-1.6.16/style/jquery.js
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/style/jquery.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.11.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k="".trim,l={},m="1.11.0",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(l.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:k&&!k.call("\ufeff\xa0")?function(a){return null==a?"":k.call(a)}:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||n.guid++,e):void 0},now:function(){return+new Date},support:l}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(O),U=new RegExp("^"+M+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L.replace("w","w*")+")"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=/'|\\/g,ab=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),bb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{G.apply(D=H.call(t.childNodes),t.childNodes),D[t.childNodes.length].nodeType}catch(cb){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function db(a,b,d,e){var f,g,h,i,j,m,p,q,u,v;if((b?b.ownerDocument||b:t)!==l&&k(b),b=b||l,d=d||[],!a||"string"!=typeof a)return d;if(1!==(i=b.nodeType)&&9!==i)return[];if(n&&!e){if(f=Z.exec(a))if(h=f[1]){if(9===i){if(g=b.getElementById(h),!g||!g.parentNode)return d;if(g.id===h)return d.push(g),d}else if(b.ownerDocument&&(g=b.ownerDocument.getElementById(h))&&r(b,g)&&g.id===h)return d.push(g),d}else{if(f[2])return G.apply(d,b.getElementsByTagName(a)),d;if((h=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(h)),d}if(c.qsa&&(!o||!o.test(a))){if(q=p=s,u=b,v=9===i&&a,1===i&&"object"!==b.nodeName.toLowerCase()){m=ob(a),(p=b.getAttribute("id"))?q=p.replace(_,"\\$&"):b.setAttribute("id",q),q="[id='"+q+"'] ",j=m.length;while(j--)m[j]=q+pb(m[j]);u=$.test(a)&&mb(b.parentNode)||b,v=m.join(",")}if(v)try{return G.apply(d,u.querySelectorAll(v)),d}catch(w){}finally{p||b.removeAttribute("id")}}}return xb(a.replace(P,"$1"),b,d,e)}function eb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function fb(a){return a[s]=!0,a}function gb(a){var b=l.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function hb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function ib(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||B)-(~a.sourceIndex||B);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function jb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function kb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function lb(a){return fb(function(b){return b=+b,fb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function mb(a){return a&&typeof a.getElementsByTagName!==A&&a}c=db.support={},f=db.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},k=db.setDocument=function(a){var b,e=a?a.ownerDocument||a:t,g=e.defaultView;return e!==l&&9===e.nodeType&&e.documentElement?(l=e,m=e.documentElement,n=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){k()},!1):g.attachEvent&&g.attachEvent("onunload",function(){k()})),c.attributes=gb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=gb(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(e.getElementsByClassName)&&gb(function(a){return a.innerHTML="<div class='a'></div><div class='a i'></div>",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=gb(function(a){return m.appendChild(a).id=s,!e.getElementsByName||!e.getElementsByName(s).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==A&&n){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){var c=typeof a.getAttributeNode!==A&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==A?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==A&&n?b.getElementsByClassName(a):void 0},p=[],o=[],(c.qsa=Y.test(e.querySelectorAll))&&(gb(function(a){a.innerHTML="<select t=''><option selected=''></option></select>",a.querySelectorAll("[t^='']").length&&o.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||o.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll(":checked").length||o.push(":checked")}),gb(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&o.push("name"+K+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||o.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),o.push(",.*:")})),(c.matchesSelector=Y.test(q=m.webkitMatchesSelector||m.mozMatchesSelector||m.oMatchesSelector||m.msMatchesSelector))&&gb(function(a){c.disconnectedMatch=q.call(a,"div"),q.call(a,"[s!='']:x"),p.push("!=",O)}),o=o.length&&new RegExp(o.join("|")),p=p.length&&new RegExp(p.join("|")),b=Y.test(m.compareDocumentPosition),r=b||Y.test(m.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},z=b?function(a,b){if(a===b)return j=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===t&&r(t,a)?-1:b===e||b.ownerDocument===t&&r(t,b)?1:i?I.call(i,a)-I.call(i,b):0:4&d?-1:1)}:function(a,b){if(a===b)return j=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],k=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:i?I.call(i,a)-I.call(i,b):0;if(f===g)return ib(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)k.unshift(c);while(h[d]===k[d])d++;return d?ib(h[d],k[d]):h[d]===t?-1:k[d]===t?1:0},e):l},db.matches=function(a,b){return db(a,null,null,b)},db.matchesSelector=function(a,b){if((a.ownerDocument||a)!==l&&k(a),b=b.replace(S,"='$1']"),!(!c.matchesSelector||!n||p&&p.test(b)||o&&o.test(b)))try{var d=q.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return db(b,l,null,[a]).length>0},db.contains=function(a,b){return(a.ownerDocument||a)!==l&&k(a),r(a,b)},db.attr=function(a,b){(a.ownerDocument||a)!==l&&k(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!n):void 0;return void 0!==f?f:c.attributes||!n?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},db.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},db.uniqueSort=function(a){var b,d=[],e=0,f=0;if(j=!c.detectDuplicates,i=!c.sortStable&&a.slice(0),a.sort(z),j){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return i=null,a},e=db.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=db.selectors={cacheLength:50,createPseudo:fb,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ab,bb),a[3]=(a[4]||a[5]||"").replace(ab,bb),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||db.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&db.error(a[0]),a},PSEUDO:function(a){var b,c=!a[5]&&a[2];return V.CHILD.test(a[0])?null:(a[3]&&void 0!==a[4]?a[2]=a[4]:c&&T.test(c)&&(b=ob(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ab,bb).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=w[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&w(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==A&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=db.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),t=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&t){k=q[s]||(q[s]={}),j=k[a]||[],n=j[0]===u&&j[1],m=j[0]===u&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[u,n,m];break}}else if(t&&(j=(b[s]||(b[s]={}))[a])&&j[0]===u)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(t&&((l[s]||(l[s]={}))[a]=[u,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||db.error("unsupported pseudo: "+a);return e[s]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?fb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:fb(function(a){var b=[],c=[],d=g(a.replace(P,"$1"));return d[s]?fb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:fb(function(a){return function(b){return db(a,b).length>0}}),contains:fb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:fb(function(a){return U.test(a||"")||db.error("unsupported lang: "+a),a=a.replace(ab,bb).toLowerCase(),function(b){var c;do if(c=n?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===m},focus:function(a){return a===l.activeElement&&(!l.hasFocus||l.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:lb(function(){return[0]}),last:lb(function(a,b){return[b-1]}),eq:lb(function(a,b,c){return[0>c?c+b:c]}),even:lb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:lb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:lb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:lb(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=jb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=kb(b);function nb(){}nb.prototype=d.filters=d.pseudos,d.setFilters=new nb;function ob(a,b){var c,e,f,g,h,i,j,k=x[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=Q.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=R.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(P," ")}),h=h.slice(c.length));for(g in d.filter)!(e=V[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?db.error(a):x(a,i).slice(0)}function pb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function qb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=v++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[u,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[s]||(b[s]={}),(h=i[d])&&h[0]===u&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function rb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function sb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function tb(a,b,c,d,e,f){return d&&!d[s]&&(d=tb(d)),e&&!e[s]&&(e=tb(e,f)),fb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||wb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:sb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=sb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=sb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ub(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],i=g||d.relative[" "],j=g?1:0,k=qb(function(a){return a===b},i,!0),l=qb(function(a){return I.call(b,a)>-1},i,!0),m=[function(a,c,d){return!g&&(d||c!==h)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>j;j++)if(c=d.relative[a[j].type])m=[qb(rb(m),c)];else{if(c=d.filter[a[j].type].apply(null,a[j].matches),c[s]){for(e=++j;f>e;e++)if(d.relative[a[e].type])break;return tb(j>1&&rb(m),j>1&&pb(a.slice(0,j-1).concat({value:" "===a[j-2].type?"*":""})).replace(P,"$1"),c,e>j&&ub(a.slice(j,e)),f>e&&ub(a=a.slice(e)),f>e&&pb(a))}m.push(c)}return rb(m)}function vb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,i,j,k){var m,n,o,p=0,q="0",r=f&&[],s=[],t=h,v=f||e&&d.find.TAG("*",k),w=u+=null==t?1:Math.random()||.1,x=v.length;for(k&&(h=g!==l&&g);q!==x&&null!=(m=v[q]);q++){if(e&&m){n=0;while(o=a[n++])if(o(m,g,i)){j.push(m);break}k&&(u=w)}c&&((m=!o&&m)&&p--,f&&r.push(m))}if(p+=q,c&&q!==p){n=0;while(o=b[n++])o(r,s,g,i);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=E.call(j));s=sb(s)}G.apply(j,s),k&&!f&&s.length>0&&p+b.length>1&&db.uniqueSort(j)}return k&&(u=w,h=t),r};return c?fb(f):f}g=db.compile=function(a,b){var c,d=[],e=[],f=y[a+" "];if(!f){b||(b=ob(a)),c=b.length;while(c--)f=ub(b[c]),f[s]?d.push(f):e.push(f);f=y(a,vb(e,d))}return f};function wb(a,b,c){for(var d=0,e=b.length;e>d;d++)db(a,b[d],c);return c}function xb(a,b,e,f){var h,i,j,k,l,m=ob(a);if(!f&&1===m.length){if(i=m[0]=m[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&c.getById&&9===b.nodeType&&n&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(ab,bb),b)||[])[0],!b)return e;a=a.slice(i.shift().value.length)}h=V.needsContext.test(a)?0:i.length;while(h--){if(j=i[h],d.relative[k=j.type])break;if((l=d.find[k])&&(f=l(j.matches[0].replace(ab,bb),$.test(i[0].type)&&mb(b.parentNode)||b))){if(i.splice(h,1),a=f.length&&pb(i),!a)return G.apply(e,f),e;break}}}return g(a,m)(f,b,!n,e,$.test(a)&&mb(b.parentNode)||b),e}return c.sortStable=s.split("").sort(z).join("")===s,c.detectDuplicates=!!j,k(),c.sortDetached=gb(function(a){return 1&a.compareDocumentPosition(l.createElement("div"))}),gb(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||hb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&gb(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||hb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),gb(function(a){return null==a.getAttribute("disabled")})||hb(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),db}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=a.document,A=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,B=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:A.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:z,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=z.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return y.find(a);this.length=1,this[0]=d}return this.context=z,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};B.prototype=n.fn,y=n(z);var C=/^(?:parents|prev(?:Until|All))/,D={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!n(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function E(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return E(a,"nextSibling")},prev:function(a){return E(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(D[a]||(e=n.unique(e)),C.test(a)&&(e=e.reverse())),this.pushStack(e)}});var F=/\S+/g,G={};function H(a){var b=G[a]={};return n.each(a.match(F)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?G[a]||H(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&n.each(arguments,function(a,c){var d;while((d=n.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){if(a===!0?!--n.readyWait:!n.isReady){if(!z.body)return setTimeout(n.ready);n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(z,[n]),n.fn.trigger&&n(z).trigger("ready").off("ready"))}}});function J(){z.addEventListener?(z.removeEventListener("DOMContentLoaded",K,!1),a.removeEventListener("load",K,!1)):(z.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(z.addEventListener||"load"===event.type||"complete"===z.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===z.readyState)setTimeout(n.ready);else if(z.addEventListener)z.addEventListener("DOMContentLoaded",K,!1),a.addEventListener("load",K,!1);else{z.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&z.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!n.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}J(),n.ready()}}()}return I.promise(b)};var L="undefined",M;for(M in n(l))break;l.ownLast="0"!==M,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c=z.getElementsByTagName("body")[0];c&&(a=z.createElement("div"),a.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",b=z.createElement("div"),c.appendChild(a).appendChild(b),typeof b.style.zoom!==L&&(b.style.cssText="border:0;margin:0;width:1px;padding:1px;display:inline;zoom:1",(l.inlineBlockNeedsLayout=3===b.offsetWidth)&&(c.style.zoom=1)),c.removeChild(a),a=b=null)}),function(){var a=z.createElement("div");if(null==l.deleteExpando){l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}}a=null}(),n.acceptData=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(n.acceptData(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f
+}}function S(a,b,c){if(n.acceptData(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d]));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=n._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var T=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,U=["Top","Right","Bottom","Left"],V=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},W=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},X=/^(?:checkbox|radio)$/i;!function(){var a=z.createDocumentFragment(),b=z.createElement("div"),c=z.createElement("input");if(b.setAttribute("className","t"),b.innerHTML="  <link/><table></table><a href='/a'>a</a>",l.leadingWhitespace=3===b.firstChild.nodeType,l.tbody=!b.getElementsByTagName("tbody").length,l.htmlSerialize=!!b.getElementsByTagName("link").length,l.html5Clone="<:nav></:nav>"!==z.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,a.appendChild(c),l.appendChecked=c.checked,b.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,a.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){l.noCloneEvent=!1}),b.cloneNode(!0).click()),null==l.deleteExpando){l.deleteExpando=!0;try{delete b.test}catch(d){l.deleteExpando=!1}}a=b=c=null}(),function(){var b,c,d=z.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),l[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var Y=/^(?:input|select|textarea)$/i,Z=/^key/,$=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,ab=/^([^.]*)(?:\.(.+)|)$/;function bb(){return!0}function cb(){return!1}function db(){try{return z.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof n===L||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(F)||[""],h=b.length;while(h--)f=ab.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(F)||[""],j=b.length;while(j--)if(h=ab.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,m,o=[d||z],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||z,3!==d.nodeType&&8!==d.nodeType&&!_.test(p+n.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[n.expando]?b:new n.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),k=n.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!n.isWindow(d)){for(i=k.delegateType||p,_.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||z)&&o.push(l.defaultView||l.parentWindow||a)}m=0;while((h=o[m++])&&!b.isPropagationStopped())b.type=m>1?i:k.bindType||p,f=(n._data(h,"events")||{})[b.type]&&n._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&n.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&n.acceptData(d)&&g&&d[p]&&!n.isWindow(d)){l=d[g],l&&(d[g]=null),n.event.triggered=p;try{d[p]()}catch(r){}n.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((n.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?n(c,this).index(i)>=0:n.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=$.test(e)?this.mouseHooks:Z.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||z),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||z,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==db()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===db()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return n.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=z.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===L&&(a[d]=null),a.detachEvent(d,c))},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&(a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault())?bb:cb):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:cb,isPropagationStopped:cb,isImmediatePropagationStopped:cb,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=bb,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=bb,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),l.submitBubbles||(n.event.special.submit={setup:function(){return n.nodeName(this,"form")?!1:void n.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=n.nodeName(b,"input")||n.nodeName(b,"button")?b.form:void 0;c&&!n._data(c,"submitBubbles")&&(n.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),n._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&n.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return n.nodeName(this,"form")?!1:void n.event.remove(this,"._submit")}}),l.changeBubbles||(n.event.special.change={setup:function(){return Y.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(n.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),n.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),n.event.simulate("change",this,a,!0)})),!1):void n.event.add(this,"beforeactivate._change",function(a){var b=a.target;Y.test(b.nodeName)&&!n._data(b,"changeBubbles")&&(n.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||n.event.simulate("change",this.parentNode,a,!0)}),n._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return n.event.remove(this,"._change"),!Y.test(this.nodeName)}}),l.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=n._data(d,b);e||d.addEventListener(a,c,!0),n._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=n._data(d,b)-1;e?n._data(d,b,e):(d.removeEventListener(a,c,!0),n._removeData(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=cb;else if(!d)return this;return 1===e&&(g=d,d=function(a){return n().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=cb),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});function eb(a){var b=fb.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var fb="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gb=/ jQuery\d+="(?:null|\d+)"/g,hb=new RegExp("<(?:"+fb+")[\\s/>]","i"),ib=/^\s+/,jb=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,kb=/<([\w:]+)/,lb=/<tbody/i,mb=/<|&#?\w+;/,nb=/<(?:script|style|link)/i,ob=/checked\s*(?:[^=]|=\s*.checked.)/i,pb=/^$|\/(?:java|ecma)script/i,qb=/^true\/(.*)/,rb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,sb={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:l.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},tb=eb(z),ub=tb.appendChild(z.createElement("div"));sb.optgroup=sb.option,sb.tbody=sb.tfoot=sb.colgroup=sb.caption=sb.thead,sb.th=sb.td;function vb(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==L?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==L?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,vb(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function wb(a){X.test(a.type)&&(a.defaultChecked=a.checked)}function xb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function yb(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function zb(a){var b=qb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ab(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}function Bb(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Cb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(yb(b).text=a.text,zb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&X.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}n.extend({clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!hb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ub.innerHTML=a.outerHTML,ub.removeChild(f=ub.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=vb(f),h=vb(a),g=0;null!=(e=h[g]);++g)d[g]&&Cb(e,d[g]);if(b)if(c)for(h=h||vb(a),d=d||vb(f),g=0;null!=(e=h[g]);g++)Bb(e,d[g]);else Bb(a,f);return d=vb(f,"script"),d.length>0&&Ab(d,!i&&vb(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k,m=a.length,o=eb(b),p=[],q=0;m>q;q++)if(f=a[q],f||0===f)if("object"===n.type(f))n.merge(p,f.nodeType?[f]:f);else if(mb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(kb.exec(f)||["",""])[1].toLowerCase(),k=sb[i]||sb._default,h.innerHTML=k[1]+f.replace(jb,"<$1></$2>")+k[2],e=k[0];while(e--)h=h.lastChild;if(!l.leadingWhitespace&&ib.test(f)&&p.push(b.createTextNode(ib.exec(f)[0])),!l.tbody){f="table"!==i||lb.test(f)?"<table>"!==k[1]||lb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)n.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}n.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),l.appendChecked||n.grep(vb(p,"input"),wb),q=0;while(f=p[q++])if((!d||-1===n.inArray(f,d))&&(g=n.contains(f.ownerDocument,f),h=vb(o.appendChild(f),"script"),g&&Ab(h),c)){e=0;while(f=h[e++])pb.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.deleteExpando,m=n.event.special;null!=(d=a[h]);h++)if((b||n.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k?delete d[i]:typeof d.removeAttribute!==L?d.removeAttribute(i):d[i]=null,c.push(f))}}}),n.fn.extend({text:function(a){return W(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||z).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(vb(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&Ab(vb(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(vb(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return W(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(gb,""):void 0;if(!("string"!=typeof a||nb.test(a)||!l.htmlSerialize&&hb.test(a)||!l.leadingWhitespace&&ib.test(a)||sb[(kb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(jb,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(vb(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(vb(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,k=this.length,m=this,o=k-1,p=a[0],q=n.isFunction(p);if(q||k>1&&"string"==typeof p&&!l.checkClone&&ob.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(k&&(i=n.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=n.map(vb(i,"script"),yb),f=g.length;k>j;j++)d=i,j!==o&&(d=n.clone(d,!0,!0),f&&n.merge(g,vb(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,n.map(g,zb),j=0;f>j;j++)d=g[j],pb.test(d.type||"")&&!n._data(d,"globalEval")&&n.contains(h,d)&&(d.src?n._evalUrl&&n._evalUrl(d.src):n.globalEval((d.text||d.textContent||d.innerHTML||"").replace(rb,"")));i=c=null}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],g=n(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Db,Eb={};function Fb(b,c){var d=n(c.createElement(b)).appendTo(c.body),e=a.getDefaultComputedStyle?a.getDefaultComputedStyle(d[0]).display:n.css(d[0],"display");return d.detach(),e}function Gb(a){var b=z,c=Eb[a];return c||(c=Fb(a,b),"none"!==c&&c||(Db=(Db||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Db[0].contentWindow||Db[0].contentDocument).document,b.write(),b.close(),c=Fb(a,b),Db.detach()),Eb[a]=c),c}!function(){var a,b,c=z.createElement("div"),d="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;padding:0;margin:0;border:0";c.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=c.getElementsByTagName("a")[0],a.style.cssText="float:left;opacity:.5",l.opacity=/^0.5/.test(a.style.opacity),l.cssFloat=!!a.style.cssFloat,c.style.backgroundClip="content-box",c.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===c.style.backgroundClip,a=c=null,l.shrinkWrapBlocks=function(){var a,c,e,f;if(null==b){if(a=z.getElementsByTagName("body")[0],!a)return;f="border:0;width:0;height:0;position:absolute;top:0;left:-9999px",c=z.createElement("div"),e=z.createElement("div"),a.appendChild(c).appendChild(e),b=!1,typeof e.style.zoom!==L&&(e.style.cssText=d+";width:1px;padding:1px;zoom:1",e.innerHTML="<div></div>",e.firstChild.style.width="5px",b=3!==e.offsetWidth),a.removeChild(c),a=c=e=null}return b}}();var Hb=/^margin/,Ib=new RegExp("^("+T+")(?!px)[a-z%]+$","i"),Jb,Kb,Lb=/^(top|right|bottom|left)$/;a.getComputedStyle?(Jb=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)},Kb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Jb(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),Ib.test(g)&&Hb.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):z.documentElement.currentStyle&&(Jb=function(a){return a.currentStyle},Kb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Jb(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Ib.test(g)&&!Lb.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Mb(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h=z.createElement("div"),i="border:0;width:0;height:0;position:absolute;top:0;left:-9999px",j="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;padding:0;margin:0;border:0";h.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",b=h.getElementsByTagName("a")[0],b.style.cssText="float:left;opacity:.5",l.opacity=/^0.5/.test(b.style.opacity),l.cssFloat=!!b.style.cssFloat,h.style.backgroundClip="content-box",h.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===h.style.backgroundClip,b=h=null,n.extend(l,{reliableHiddenOffsets:function(){if(null!=c)return c;var a,b,d,e=z.createElement("div"),f=z.getElementsByTagName("body")[0];if(f)return e.setAttribute("className","t"),e.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=z.createElement("div"),a.style.cssText=i,f.appendChild(a).appendChild(e),e.innerHTML="<table><tr><td></td><td>t</td></tr></table>",b=e.getElementsByTagName("td"),b[0].style.cssText="padding:0;margin:0;border:0;display:none",d=0===b[0].offsetHeight,b[0].style.display="",b[1].style.display="none",c=d&&0===b[0].offsetHeight,f.removeChild(a),e=f=null,c},boxSizing:function(){return null==d&&k(),d},boxSizingReliable:function(){return null==e&&k(),e},pixelPosition:function(){return null==f&&k(),f},reliableMarginRight:function(){var b,c,d,e;if(null==g&&a.getComputedStyle){if(b=z.getElementsByTagName("body")[0],!b)return;c=z.createElement("div"),d=z.createElement("div"),c.style.cssText=i,b.appendChild(c).appendChild(d),e=d.appendChild(z.createElement("div")),e.style.cssText=d.style.cssText=j,e.style.marginRight=e.style.width="0",d.style.width="1px",g=!parseFloat((a.getComputedStyle(e,null)||{}).marginRight),b.removeChild(c)}return g}});function k(){var b,c,h=z.getElementsByTagName("body")[0];h&&(b=z.createElement("div"),c=z.createElement("div"),b.style.cssText=i,h.appendChild(b).appendChild(c),c.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;display:block;padding:1px;border:1px;width:4px;margin-top:1%;top:1%",n.swap(h,null!=h.style.zoom?{zoom:1}:{},function(){d=4===c.offsetWidth}),e=!0,f=!1,g=!0,a.getComputedStyle&&(f="1%"!==(a.getComputedStyle(c,null)||{}).top,e="4px"===(a.getComputedStyle(c,null)||{width:"4px"}).width),h.removeChild(b),c=h=null)}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Nb=/alpha\([^)]*\)/i,Ob=/opacity\s*=\s*([^)]*)/,Pb=/^(none|table(?!-c[ea]).+)/,Qb=new RegExp("^("+T+")(.*)$","i"),Rb=new RegExp("^([+-])=("+T+")","i"),Sb={position:"absolute",visibility:"hidden",display:"block"},Tb={letterSpacing:0,fontWeight:400},Ub=["Webkit","O","Moz","ms"];function Vb(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Ub.length;while(e--)if(b=Ub[e]+c,b in a)return b;return d}function Wb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=n._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&V(d)&&(f[g]=n._data(d,"olddisplay",Gb(d.nodeName)))):f[g]||(e=V(d),(c&&"none"!==c||!e)&&n._data(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Xb(a,b,c){var d=Qb.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Yb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+U[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+U[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+U[f]+"Width",!0,e))):(g+=n.css(a,"padding"+U[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+U[f]+"Width",!0,e)));return g}function Zb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Jb(a),g=l.boxSizing()&&"border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Kb(a,b,f),(0>e||null==e)&&(e=a.style[b]),Ib.test(e))return e;d=g&&(l.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Yb(a,b,c||(g?"border":"content"),d,f)+"px"}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Kb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":l.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;if(b=n.cssProps[h]||(n.cssProps[h]=Vb(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Rb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]="",i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Vb(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Kb(a,b,d)),"normal"===f&&b in Tb&&(f=Tb[b]),""===c||c?(e=parseFloat(f),c===!0||n.isNumeric(e)?e||0:f):f}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?0===a.offsetWidth&&Pb.test(n.css(a,"display"))?n.swap(a,Sb,function(){return Zb(a,b,d)}):Zb(a,b,d):void 0},set:function(a,c,d){var e=d&&Jb(a);return Xb(a,c,d?Yb(a,b,d,l.boxSizing()&&"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),l.opacity||(n.cssHooks.opacity={get:function(a,b){return Ob.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=n.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===n.trim(f.replace(Nb,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Nb.test(f)?f.replace(Nb,e):f+" "+e)}}),n.cssHooks.marginRight=Mb(l.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},Kb,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+U[d]+b]=f[d]||f[d-2]||f[0];return e}},Hb.test(a)||(n.cssHooks[a+b].set=Xb)}),n.fn.extend({css:function(a,b){return W(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Jb(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)
+},a,b,arguments.length>1)},show:function(){return Wb(this,!0)},hide:function(){return Wb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){V(this)?n(this).show():n(this).hide()})}});function $b(a,b,c,d,e){return new $b.prototype.init(a,b,c,d,e)}n.Tween=$b,$b.prototype={constructor:$b,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=$b.propHooks[this.prop];return a&&a.get?a.get(this):$b.propHooks._default.get(this)},run:function(a){var b,c=$b.propHooks[this.prop];return this.pos=b=this.options.duration?n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):$b.propHooks._default.set(this),this}},$b.prototype.init.prototype=$b.prototype,$b.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},$b.propHooks.scrollTop=$b.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=$b.prototype.init,n.fx.step={};var _b,ac,bc=/^(?:toggle|show|hide)$/,cc=new RegExp("^(?:([+-])=|)("+T+")([a-z%]*)$","i"),dc=/queueHooks$/,ec=[jc],fc={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=cc.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&cc.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function gc(){return setTimeout(function(){_b=void 0}),_b=n.now()}function hc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=U[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function ic(a,b,c){for(var d,e=(fc[b]||[]).concat(fc["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function jc(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&V(a),r=n._data(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,"display"),k=Gb(a.nodeName),"none"===j&&(j=k),"inline"===j&&"none"===n.css(a,"float")&&(l.inlineBlockNeedsLayout&&"inline"!==k?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],bc.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}if(!n.isEmptyObject(o)){r?"hidden"in r&&(q=r.hidden):r=n._data(a,"fxshow",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,"fxshow");for(b in o)n.style(a,b,o[b])});for(d in o)g=ic(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function kc(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function lc(a,b,c){var d,e,f=0,g=ec.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=_b||gc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:_b||gc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(kc(k,j.opts.specialEasing);g>f;f++)if(d=ec[f].call(j,a,k,j.opts))return d;return n.map(k,ic,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(lc,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],fc[c]=fc[c]||[],fc[c].unshift(b)},prefilter:function(a,b){b?ec.unshift(a):ec.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(V).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=lc(this,n.extend({},a),f);(e||n._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=n._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&dc.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=n._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(hc(b,!0),a,d,e)}}),n.each({slideDown:hc("show"),slideUp:hc("hide"),slideToggle:hc("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=n.timers,c=0;for(_b=n.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||n.fx.stop(),_b=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){ac||(ac=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(ac),ac=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e=z.createElement("div");e.setAttribute("className","t"),e.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=e.getElementsByTagName("a")[0],c=z.createElement("select"),d=c.appendChild(z.createElement("option")),b=e.getElementsByTagName("input")[0],a.style.cssText="top:1px",l.getSetAttribute="t"!==e.className,l.style=/top/.test(a.getAttribute("style")),l.hrefNormalized="/a"===a.getAttribute("href"),l.checkOn=!!b.value,l.optSelected=d.selected,l.enctype=!!z.createElement("form").enctype,c.disabled=!0,l.optDisabled=!d.disabled,b=z.createElement("input"),b.setAttribute("value",""),l.input=""===b.getAttribute("value"),b.value="t",b.setAttribute("type","radio"),l.radioValue="t"===b.value,a=b=c=d=e=null}();var mc=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(mc,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.text(a)}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(l.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)if(d=e[g],n.inArray(n.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var nc,oc,pc=n.expr.attrHandle,qc=/^(?:checked|selected)$/i,rc=l.getSetAttribute,sc=l.input;n.fn.extend({attr:function(a,b){return W(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===L?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?oc:nc)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(F);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)?sc&&rc||!qc.test(c)?a[d]=!1:a[n.camelCase("default-"+c)]=a[d]=!1:n.attr(a,c,""),a.removeAttribute(rc?c:d)},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),oc={set:function(a,b,c){return b===!1?n.removeAttr(a,c):sc&&rc||!qc.test(c)?a.setAttribute(!rc&&n.propFix[c]||c,c):a[n.camelCase("default-"+c)]=a[c]=!0,c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=pc[b]||n.find.attr;pc[b]=sc&&rc||!qc.test(b)?function(a,b,d){var e,f;return d||(f=pc[b],pc[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,pc[b]=f),e}:function(a,b,c){return c?void 0:a[n.camelCase("default-"+b)]?b.toLowerCase():null}}),sc&&rc||(n.attrHooks.value={set:function(a,b,c){return n.nodeName(a,"input")?void(a.defaultValue=b):nc&&nc.set(a,b,c)}}),rc||(nc={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},pc.id=pc.name=pc.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},n.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:nc.set},n.attrHooks.contenteditable={set:function(a,b,c){nc.set(a,""===b?!1:b,c)}},n.each(["width","height"],function(a,b){n.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),l.style||(n.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var tc=/^(?:input|select|textarea|button|object)$/i,uc=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return W(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return a=n.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):tc.test(a.nodeName)||uc.test(a.nodeName)&&a.href?0:-1}}}}),l.hrefNormalized||n.each(["href","src"],function(a,b){n.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this}),l.enctype||(n.propFix.enctype="encoding");var vc=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(F)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(vc," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(F)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(vc," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(F)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===L||"boolean"===c)&&(this.className&&n._data(this,"__className__",this.className),this.className=this.className||a===!1?"":n._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(vc," ").indexOf(b)>=0)return!0;return!1}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var wc=n.now(),xc=/\?/,yc=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;n.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=n.trim(b+"");return e&&!n.trim(e.replace(yc,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():n.error("Invalid JSON: "+b)},n.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var zc,Ac,Bc=/#.*$/,Cc=/([?&])_=[^&]*/,Dc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Ec=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Fc=/^(?:GET|HEAD)$/,Gc=/^\/\//,Hc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Ic={},Jc={},Kc="*/".concat("*");try{Ac=location.href}catch(Lc){Ac=z.createElement("a"),Ac.href="",Ac=Ac.href}zc=Hc.exec(Ac.toLowerCase())||[];function Mc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(F)||[];if(n.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Nc(a,b,c,d){var e={},f=a===Jc;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Oc(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&n.extend(!0,a,c),a}function Pc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Qc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ac,type:"GET",isLocal:Ec.test(zc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Kc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Oc(Oc(a,n.ajaxSettings),b):Oc(n.ajaxSettings,a)},ajaxPrefilter:Mc(Ic),ajaxTransport:Mc(Jc),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Dc.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||Ac)+"").replace(Bc,"").replace(Gc,zc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(F)||[""],null==k.crossDomain&&(c=Hc.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===zc[1]&&c[2]===zc[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(zc[3]||("http:"===zc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),Nc(Ic,k,b,v),2===t)return v;h=k.global,h&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Fc.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(xc.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Cc.test(e)?e.replace(Cc,"$1_="+wc++):e+(xc.test(e)?"&":"?")+"_="+wc++)),k.ifModified&&(n.lastModified[e]&&v.setRequestHeader("If-Modified-Since",n.lastModified[e]),n.etag[e]&&v.setRequestHeader("If-None-Match",n.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Kc+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Nc(Jc,k,b,v)){v.readyState=1,h&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Pc(k,v,c)),u=Qc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(n.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){if(n.isFunction(a))return this.each(function(b){n(this).wrapAll(a.call(this,b))});if(this[0]){var b=n(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!l.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||n.css(a,"display"))},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var Rc=/%20/g,Sc=/\[\]$/,Tc=/\r?\n/g,Uc=/^(?:submit|button|image|reset|file)$/i,Vc=/^(?:input|select|textarea|keygen)/i;function Wc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||Sc.test(a)?d(a,e):Wc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Wc(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Wc(c,a[c],b,e);return d.join("&").replace(Rc,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&Vc.test(this.nodeName)&&!Uc.test(a)&&(this.checked||!X.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(Tc,"\r\n")}}):{name:b.name,value:c.replace(Tc,"\r\n")}}).get()}}),n.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&$c()||_c()}:$c;var Xc=0,Yc={},Zc=n.ajaxSettings.xhr();a.ActiveXObject&&n(a).on("unload",function(){for(var a in Yc)Yc[a](void 0,!0)}),l.cors=!!Zc&&"withCredentials"in Zc,Zc=l.ajax=!!Zc,Zc&&n.ajaxTransport(function(a){if(!a.crossDomain||l.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Xc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Yc[g],b=void 0,f.onreadystatechange=n.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Yc[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function $c(){try{return new a.XMLHttpRequest}catch(b){}}function _c(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=z.head||n("head")[0]||z.documentElement;return{send:function(d,e){b=z.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var ad=[],bd=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=ad.pop()||n.expando+"_"+wc++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(bd.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&bd.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(bd,"$1"+e):b.jsonp!==!1&&(b.url+=(xc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,ad.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||z;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var cd=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&cd)return cd.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=a.slice(h,a.length),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&n.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var dd=a.document.documentElement;function ed(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&n.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?(typeof e.getBoundingClientRect!==L&&(d=e.getBoundingClientRect()),c=ed(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0),c.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||dd;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||dd})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return W(this,function(a,d,e){var f=ed(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Mb(l.pixelPosition,function(a,c){return c?(c=Kb(a,b),Ib.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return W(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var fd=a.jQuery,gd=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=gd),b&&a.jQuery===n&&(a.jQuery=fd),n},typeof b===L&&(a.jQuery=a.$=n),n});
diff --git a/cabal/pretty-show-1.6.16/style/pretty-show.css b/cabal/pretty-show-1.6.16/style/pretty-show.css
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/style/pretty-show.css
@@ -0,0 +1,32 @@
+table.tallRecord             { border: 1px solid #9c9; border-top-width: 5px }
+table.tallRecord>tbody>tr>th { background-color: #cfc }
+
+table.wideTuple              { border: 1px solid #9c9 }
+table.wideTuple >tbody>tr>td { padding-left: 5px; padding-right: 5px }
+
+table.tallList  >tbody>tr>th,
+table.recordList>tbody>tr>th,
+table.wideList  >tbody>tr>th  { background-color: #ffc; border: 1px solid #cc9 }
+
+.con, .label, .ix { font-weight: normal }
+
+/* Things that get clicked */
+table.recordList>tbody>tr>th.ix,
+table.recordList>tbody>tr>th.con,
+table.tallList  >tbody>tr>th.ix,
+table.tallList  >tbody>tr>th.con,
+table.tallRecord>tbody>tr>th.con,
+table.tallRecord>tbody>tr>th.label,
+table.wideList  >tbody>tr>th.con { cursor: hand }
+
+/* Things that get closed */
+table.tallRecord>tbody>tr>th.closed,
+table.tallList  >tbody>tr>th.closed,
+table.recordList>tbody>tr>th.closed,
+table.wideList  >tbody>tr>th.closed  { background-color: #ccf }
+
+/* rational numbers */
+table.ratio>tbody>tr>td           { text-align: center }
+table.ratio>tbody>tr>td.numerator { border-bottom: solid black 1px }
+
+.char, .integer { font-family: monospace }
diff --git a/cabal/pretty-show-1.6.16/style/pretty-show.js b/cabal/pretty-show-1.6.16/style/pretty-show.js
new file mode 100644
--- /dev/null
+++ b/cabal/pretty-show-1.6.16/style/pretty-show.js
@@ -0,0 +1,23 @@
+function toggle_con(obj) {
+  var x = $(obj.currentTarget);
+  x.toggleClass("closed");
+  x.parent().siblings().fadeToggle();
+  x.siblings().fadeToggle();
+}
+
+function toggle_lab(obj) {
+  var x = $(obj.currentTarget);
+  x.toggleClass("closed");
+  x.siblings().fadeToggle();
+  }
+
+$(function () {
+  $("table.recordList>tbody>tr>th.ix").click(toggle_lab);
+  $("table.tallRecord>tbody>tr>th.label").click(toggle_lab);
+  $("table.tallList>tbody>tr>th.ix").click(toggle_lab);
+
+  $("table.recordList>tbody>tr>th.con").click(toggle_con);
+  $("table.tallList>tbody>tr>th.con").click(toggle_con);
+  $("table.wideList>tbody>tr>th.con").click(toggle_con);
+  $("table.tallRecord>tbody>tr>th.con").click(toggle_con);
+})
diff --git a/cabal/solver-benchmarks/solver-benchmarks.cabal b/cabal/solver-benchmarks/solver-benchmarks.cabal
--- a/cabal/solver-benchmarks/solver-benchmarks.cabal
+++ b/cabal/solver-benchmarks/solver-benchmarks.cabal
@@ -1,5 +1,5 @@
 name:          solver-benchmarks
-version:       2.1.0.0
+version:       2.4.1.0
 copyright:     2003-2017, Cabal Development Team (see AUTHORS file)
 license:       BSD3
 license-file:  LICENSE
@@ -29,7 +29,7 @@
   build-depends:
     base,
     bytestring,
-    Cabal >= 2.1,
+    Cabal >= 2.3,
     optparse-applicative,
     process,
     time,
diff --git a/cabal/solver-benchmarks/tests/HackageBenchmarkTest.hs b/cabal/solver-benchmarks/tests/HackageBenchmarkTest.hs
--- a/cabal/solver-benchmarks/tests/HackageBenchmarkTest.hs
+++ b/cabal/solver-benchmarks/tests/HackageBenchmarkTest.hs
@@ -1,7 +1,7 @@
 import HackageBenchmark
 import Statistics.Types (mkPValue)
 import Test.Tasty (TestTree, defaultMain, testGroup)
-import Test.Tasty.HUnit (assert, testCase, (@?=))
+import Test.Tasty.HUnit (assertBool, testCase, (@?=))
 
 main :: IO ()
 main = defaultMain tests
@@ -11,19 +11,19 @@
 
     testGroup "isSignificantTimeDifference" [
 
-        testCase "detect increase in distribution" $ assert $
+        testCase "detect increase in distribution" $ assertBool "" $
             isSignificantTimeDifference (mkPValue 0.05) [1,2..7] [4,5..10]
 
-      , testCase "detect decrease in distribution" $ assert $
+      , testCase "detect decrease in distribution" $ assertBool "" $
             isSignificantTimeDifference (mkPValue 0.05) [1,2..7] [-2,-1..4]
 
-      , testCase "ignore same data" $ assert $
+      , testCase "ignore same data" $ assertBool "" $
             not $ isSignificantTimeDifference (mkPValue 0.05) [1,2..10] [1,2..10]
 
-      , testCase "same data with high p-value is significant" $ assert $
+      , testCase "same data with high p-value is significant" $ assertBool "" $
             isSignificantTimeDifference (mkPValue 0.9) [1,2..10] [1,2..10]
 
-      , testCase "ignore outlier" $ assert $
+      , testCase "ignore outlier" $ assertBool "" $
             not $ isSignificantTimeDifference (mkPValue 0.05) [1, 2, 1, 1, 1] [2, 1, 50, 1, 1]
       ]
 
@@ -47,43 +47,44 @@
 
   , testGroup "isSignificantResult" [
 
-        testCase "different results are significant" $ assert $
+        testCase "different results are significant" $ assertBool "" $
             isSignificantResult NoInstallPlan BackjumpLimit
 
-      , testCase "unknown result is significant" $ assert $
+      , testCase "unknown result is significant" $ assertBool "" $
             isSignificantResult Unknown Unknown
 
-      , testCase "PkgNotFound is significant" $ assert $
+      , testCase "PkgNotFound is significant" $ assertBool "" $
             isSignificantResult PkgNotFound PkgNotFound
 
-      , testCase "same expected error is not significant" $ assert $
+      , testCase "same expected error is not significant" $ assertBool "" $
             not $ isSignificantResult NoInstallPlan NoInstallPlan
 
-      , testCase "success is not significant" $ assert $
+      , testCase "success is not significant" $ assertBool "" $
             not $ isSignificantResult Solution Solution
     ]
 
   , testGroup "shouldContinueAfterFirstTrial" [
 
-        testCase "rerun when min difference is zero" $ assert $
+        testCase "rerun when min difference is zero" $ assertBool "" $
                   shouldContinueAfterFirstTrial 0 1.0 1.0 Solution Solution
 
-      , testCase "rerun when min difference is zero, even with timeout" $ assert $
+      , testCase "rerun when min difference is zero, even with timeout" $
+                  assertBool "" $
                   shouldContinueAfterFirstTrial 0 1.0 1.0 Timeout Timeout
 
-      , testCase "treat timeouts as the same time" $ assert $
+      , testCase "treat timeouts as the same time" $ assertBool "" $
             not $ shouldContinueAfterFirstTrial 0.000001 89.9 92.0 Timeout Timeout
 
-      , testCase "skip when times are too close - 1" $ assert $
+      , testCase "skip when times are too close - 1" $ assertBool "" $
             not $ shouldContinueAfterFirstTrial 10 1.0 0.91  Solution Solution
 
-      , testCase "skip when times are too close - 2" $ assert $
+      , testCase "skip when times are too close - 2" $ assertBool "" $
             not $ shouldContinueAfterFirstTrial 10 1.0 1.09  Solution Solution
 
-      , testCase "rerun when times aren't too close - 1" $ assert $
+      , testCase "rerun when times aren't too close - 1" $ assertBool "" $
                   shouldContinueAfterFirstTrial 10 1.0 0.905 Solution Solution
 
-      , testCase "rerun when times aren't too close - 2" $ assert $
+      , testCase "rerun when times aren't too close - 2" $ assertBool "" $
                   shouldContinueAfterFirstTrial 10 1.0 1.1   Solution Solution
     ]
   ]
diff --git a/cabal/stack.yaml b/cabal/stack.yaml
--- a/cabal/stack.yaml
+++ b/cabal/stack.yaml
@@ -1,10 +1,11 @@
-resolver: nightly-2017-11-01
+resolver: lts-11.6
 packages:
 - Cabal/
 - cabal-install/
 - cabal-testsuite/
 extra-deps:
   - resolv-0.1.1.1
+  - QuickCheck-2.11.3
 nix:
   packages:
   - autoconf
diff --git a/cabal/travis-common.sh b/cabal/travis-common.sh
--- a/cabal/travis-common.sh
+++ b/cabal/travis-common.sh
@@ -1,7 +1,8 @@
 set -e
 
-HACKAGE_REPO_TOOL_VERSION="0.1.1"
-CABAL_VERSION="2.1.0.0"
+HACKAGE_REPO_TOOL_VERSION="0.1.1.1"
+CABAL_VERSION="2.4.1.0"
+CABAL_INSTALL_VERSION="2.4.1.0"
 
 if [ "$TRAVIS_OS_NAME" = "linux" ]; then
     ARCH="x86_64-linux"
@@ -13,10 +14,10 @@
 CABAL_LOCAL_DB="${TRAVIS_BUILD_DIR}/dist-newstyle/packagedb/ghc-${GHCVER}"
 CABAL_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/Cabal-${CABAL_VERSION}"
 CABAL_TESTSUITE_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/cabal-testsuite-${CABAL_VERSION}"
-CABAL_INSTALL_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/cabal-install-${CABAL_VERSION}"
-CABAL_INSTALL_SETUP="${CABAL_INSTALL_BDIR}/setup/setup"
+CABAL_INSTALL_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/cabal-install-${CABAL_INSTALL_VERSION}"
 SOLVER_BENCHMARKS_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/solver-benchmarks-${CABAL_VERSION}"
-HACKAGE_REPO_TOOL_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/hackage-repo-tool-${HACKAGE_REPO_TOOL_VERSION}/c/hackage-repo-tool"
+HACKAGE_REPO_TOOL_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/hackage-repo-tool-${HACKAGE_REPO_TOOL_VERSION}/x/hackage-repo-tool"
+CABAL_INSTALL_EXE=${CABAL_INSTALL_BDIR}/x/cabal/build/cabal/cabal
 
 # ---------------------------------------------------------------------
 # Timing / diagnostic output
@@ -40,9 +41,10 @@
     echo "$* took $duration seconds."
     echo "whole job took $total_duration seconds so far."
 
-	# Terminate on OSX
-	if [ $total_duration -ge 2400 -a $(uname) = "Darwin" ]; then
-		echo "Job taking over 40 minutes. Terminating"
+	# Terminate if the job is taking too long (we must do this to
+	# preserve the populated cache for the next run).
+	if [ $total_duration -ge 2400 ]; then
+		echo "Job taking over 38 minutes. Terminating"
 		exit 1
 	fi
     echo "----"
diff --git a/cabal/travis-deploy.sh b/cabal/travis-deploy.sh
--- a/cabal/travis-deploy.sh
+++ b/cabal/travis-deploy.sh
@@ -8,7 +8,7 @@
     (cd cabal-website && git checkout --track -b gh-pages origin/gh-pages)
     rm -rf cabal-website/doc
     mkdir -p cabal-website/doc/html
-    mv dist-newstyle/build/Cabal-2.1.0.0/doc/html/Cabal \
+    mv dist-newstyle/build/`uname -m`-$TRAVIS_OS_NAME/ghc-$GHCVER/Cabal-2.4.1.0/doc/html/Cabal \
        cabal-website/doc/html/Cabal
     (cd cabal-website && git add --all .)
     (cd cabal-website && \
diff --git a/cabal/travis-install.sh b/cabal/travis-install.sh
--- a/cabal/travis-install.sh
+++ b/cabal/travis-install.sh
@@ -9,11 +9,11 @@
     travis_retry sudo apt-get install --force-yes ghc-$GHCVER
 fi
 
-if [ -z ${STACKAGE_RESOLVER+x} ]; then
+if [ -z ${STACK_CONFIG+x} ]; then
     if [ "$TRAVIS_OS_NAME" = "linux" ]; then
         travis_retry sudo add-apt-repository -y ppa:hvr/ghc
         travis_retry sudo apt-get update
-        travis_retry sudo apt-get install --force-yes cabal-install-head cabal-install-2.0 happy-1.19.5 alex-3.1.7 ghc-$GHCVER-prof ghc-$GHCVER-dyn
+        travis_retry sudo apt-get install --force-yes cabal-install-2.4 happy-1.19.5 alex-3.1.7 ghc-$GHCVER-prof ghc-$GHCVER-dyn
         if [ "x$TEST_OTHER_VERSIONS" = "xYES" ]; then travis_retry sudo apt-get install --force-yes ghc-7.0.4-prof ghc-7.0.4-dyn ghc-7.2.2-prof ghc-7.2.2-dyn ghc-head-prof ghc-head-dyn; fi
 
     elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
@@ -60,7 +60,7 @@
         cd ..;
 
         mkdir "${HOME}/bin"
-        travis_retry curl -L https://www.haskell.org/cabal/release/cabal-install-2.0.0.0/cabal-install-2.0.0.0-x86_64-apple-darwin-sierra.tar.xz | tar xJO > "${HOME}/bin/cabal"
+        travis_retry curl -L https://downloads.haskell.org/~cabal/cabal-install-2.4.0.0/cabal-install-2.4.0.0-x86_64-apple-darwin-sierra.tar.gz | tar xzO > "${HOME}/bin/cabal"
         chmod a+x "${HOME}/bin/cabal"
         "${HOME}/bin/cabal" --version
 
@@ -73,7 +73,8 @@
     mkdir -p ~/.local/bin
     travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 \
         | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
-    stack setup --resolver "$STACKAGE_RESOLVER"
+    ~/.local/bin/stack --version
+    ~/.local/bin/stack setup --stack-yaml "$STACK_CONFIG"
 
 fi
 
diff --git a/cabal/travis-meta.sh b/cabal/travis-meta.sh
--- a/cabal/travis-meta.sh
+++ b/cabal/travis-meta.sh
@@ -2,8 +2,6 @@
 
 . ./travis-common.sh
 
-export PATH=/opt/cabal/head/bin:$PATH
-
 # ---------------------------------------------------------------------
 # Check that auto-generated files/fields are up to date.
 # ---------------------------------------------------------------------
@@ -12,8 +10,12 @@
 # Currently doesn't work because Travis uses --depth=50 when cloning.
 #./Cabal/misc/gen-authors.sh > AUTHORS
 
+timed cabal update
+
 # Regenerate files
+timed make lexer
 timed make gen-extra-source-files
+timed make spdx
 
 # Fail if the diff is not empty.
 timed ./Cabal/misc/travis-diff-files.sh
diff --git a/cabal/travis-script.sh b/cabal/travis-script.sh
--- a/cabal/travis-script.sh
+++ b/cabal/travis-script.sh
@@ -73,18 +73,22 @@
 # Install executables if necessary
 # ---------------------------------------------------------------------
 
-if ! command -v happy; then
+#if ! command -v happy; then
     timed cabal install $jobs happy
-fi
+#fi
 
 # ---------------------------------------------------------------------
 # Setup our local project
 # ---------------------------------------------------------------------
 
-cp cabal.project.travis cabal.project.local
+make cabal-install-monolithic
+if [ "x$CABAL_LIB_ONLY" = "xYES" ]; then
+    cp cabal.project.travis.libonly cabal.project
+fi
+cp cabal.project.local.travis cabal.project.local
 
 # hackage-repo-tool is a bit touchy to install on GHC 8.0, so instead we
-# do it via new-build.  See also cabal.project.travis.  The downside of
+# do it via new-build.  See also cabal.project.local.travis.  The downside of
 # doing it this way is that the build product cannot be cached, but
 # hackage-repo-tool is a relatively small package so it's good.
 timed cabal unpack hackage-repo-tool-${HACKAGE_REPO_TOOL_VERSION}
@@ -102,10 +106,11 @@
     # NB: Best to do everything for a single package together as it's
     # more efficient (since new-build will uselessly try to rebuild
     # Cabal otherwise).
-    timed cabal new-build $jobs Cabal Cabal:unit-tests Cabal:check-tests Cabal:parser-tests Cabal:parser-hackage-tests --enable-tests
+    timed cabal new-build $jobs Cabal Cabal:unit-tests Cabal:check-tests Cabal:parser-tests Cabal:hackage-tests --enable-tests
 
     # Run haddock.
     if [ "$TRAVIS_OS_NAME" = "linux" ]; then
+        # TODO: use new-haddock?
         (cd Cabal && timed cabal act-as-setup --build-type=Simple -- haddock --builddir=${CABAL_BDIR}) || exit $?
     fi
 
@@ -163,29 +168,31 @@
    exit 1;
 fi
 
-# Haddock
-# TODO: Figure out why this needs to be run before big tests
-if [ "$TRAVIS_OS_NAME" = "linux" ]; then
-    (cd cabal-install && timed ${CABAL_INSTALL_SETUP} haddock --builddir=${CABAL_INSTALL_BDIR} ) || exit $?
-fi
-
 # Tests need this
-timed ${CABAL_INSTALL_BDIR}/build/cabal/cabal update
+timed ${CABAL_INSTALL_EXE} update
 
 # Big tests
-(cd cabal-testsuite && timed ${CABAL_TESTSUITE_BDIR}/build/cabal-tests/cabal-tests --builddir=${CABAL_TESTSUITE_BDIR} -j3 --skip-setup-tests --with-cabal ${CABAL_INSTALL_BDIR}/build/cabal/cabal --with-hackage-repo-tool ${HACKAGE_REPO_TOOL_BDIR}/build/hackage-repo-tool/hackage-repo-tool $TEST_OPTIONS) || exit $?
+(cd cabal-testsuite && timed ${CABAL_TESTSUITE_BDIR}/build/cabal-tests/cabal-tests --builddir=${CABAL_TESTSUITE_BDIR} -j3 --skip-setup-tests --with-cabal ${CABAL_INSTALL_EXE} --with-hackage-repo-tool ${HACKAGE_REPO_TOOL_BDIR}/build/hackage-repo-tool/hackage-repo-tool $TEST_OPTIONS) || exit $?
 
-(cd cabal-install && timed cabal check) || exit $?
+# Cabal check
+# TODO: remove -main-is and re-enable me.
+# (cd cabal-install && timed cabal check) || exit $?
 
 if [ "x$TEST_SOLVER_BENCHMARKS" = "xYES" ]; then
     timed cabal new-build $jobs solver-benchmarks:hackage-benchmark solver-benchmarks:unit-tests
-    timed ${SOLVER_BENCHMARKS_BDIR}/c/unit-tests/build/unit-tests/unit-tests $TEST_OPTIONS
+    timed ${SOLVER_BENCHMARKS_BDIR}/t/unit-tests/build/unit-tests/unit-tests $TEST_OPTIONS
 fi
 
+# Haddock
+# TODO: >= 8.4.3 would be nicer
+if [ "$TRAVIS_OS_NAME" = "linux" -a "$GHCVER" == "8.4.4" ]; then
+    timed cabal new-haddock cabal-install
+fi
+
 unset CABAL_BUILDDIR
 
 # Check what we got
-${CABAL_INSTALL_BDIR}/build/cabal/cabal --version
+${CABAL_INSTALL_EXE} --version
 
 # If this fails, we WANT to fail, because the tests will not be running then
 (timed ./travis/upload.sh) || exit $?
diff --git a/cabal/travis-solver-debug-flags.sh b/cabal/travis-solver-debug-flags.sh
--- a/cabal/travis-solver-debug-flags.sh
+++ b/cabal/travis-solver-debug-flags.sh
@@ -1,16 +1,9 @@
 #!/bin/sh
 
 # Build cabal with solver debug flags enabled.
-#
-# We use a sandbox, because cabal-install-1.24.0.0's new-build command tries to
-# build tracetree's dependencies with the inplace Cabal, which leads to compile
-# errors. We also need to skip the tests, because debug-tracetree prints the
-# whole solver tree as JSON.
+# We need to skip the tests, because debug-tracetree prints the whole solver
+# tree as JSON.
 
 cabal update
-cd cabal-install
-cabal sandbox init
-cabal sandbox add-source ../Cabal
-cabal install --dependencies-only --constraint "cabal-install +debug-tracetree +debug-conflict-sets"
-cabal configure --ghc-option=-Werror --constraint "cabal-install +debug-tracetree +debug-conflict-sets"
-cabal build
+cabal install happy
+cabal new-build exe:cabal --constraint "cabal-install +debug-tracetree +debug-conflict-sets"
diff --git a/cabal/travis-stack.sh b/cabal/travis-stack.sh
--- a/cabal/travis-stack.sh
+++ b/cabal/travis-stack.sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 
-if [ -z ${STACKAGE_RESOLVER+x} ]; then
-    echo "STACKAGE_RESOLVER environment variable not set."
+if [ -z ${STACK_CONFIG+x} ]; then
+    echo "STACK_CONFIG environment variable not set."
     echo "This build case is not configured correctly."
     exit 1
 fi
@@ -12,6 +12,10 @@
 # Build Cabal via Stack(age).
 # ---------------------------------------------------------------------
 
-stack build \
+~/.local/bin/stack --version
+
+~/.local/bin/stack build \
     --no-terminal \
-    --resolver "$STACKAGE_RESOLVER"
+    --stack-yaml "$STACK_CONFIG" \
+    --test \
+    --bench --no-run-benchmarks
diff --git a/cabal/travis/README.md b/cabal/travis/README.md
--- a/cabal/travis/README.md
+++ b/cabal/travis/README.md
@@ -23,10 +23,11 @@
 
 2. Once the build is successful, we invoke upload.sh to upload
    the build products to the cabal-binaries repository.  This is done
-   using the private key id_rsa (associated with haskell-pushbot's
-   account).  This upload contains its own .travis.yml (customized
-   for the particular build matrix configuration), and some special
-   JSON metadata in the commit message.
+   using the ROT-13'ed private key id_rsa.rot13 (associated with
+   haskell-pushbot's account).  This upload contains its own .travis.yml
+   (customized for the particular build matrix configuration), and some
+   special JSON metadata in the commit message.  ROT-13 is used to
+   prevent GitHub from deciding the private key is compromised.
 
 3. Triggered by the push to cabal-binaries, Travis on haskell-pushbot
    will run the tests.  After this finishes, it will invoke a webhook
@@ -55,7 +56,8 @@
 * Create a new GitHub account to replace haskell-pushbot
 
 * Generate a new private key, associate it with the GH account, and
-  replace id_rsa and id_rsa.pub with the new account
+  replace id_rsa.rot13 and id_rsa.pub with the ROT-13'ed private
+  key and the public key.
 
 * Create a new binaries repository, modify the invocation of
   "git remote add" in upload.sh to point to the new location.
diff --git a/cabal/travis/binaries/.travis.yml b/cabal/travis/binaries/.travis.yml
--- a/cabal/travis/binaries/.travis.yml
+++ b/cabal/travis/binaries/.travis.yml
@@ -12,7 +12,7 @@
  - export PATH=$HOME/bin:$PATH
  - export PATH=$HOME/.cabal/bin:$PATH
  - export PATH=$HOME/.local/bin:$PATH
- - export PATH=/opt/cabal/1.24/bin:$PATH
+ - export PATH=/opt/cabal/2.4/bin:$PATH
  - export PATH=/opt/happy/1.19.5/bin:$PATH
  - export PATH=/opt/alex/3.1.7/bin:$PATH
  - ./travis-install.sh
diff --git a/cabal/travis/binaries/travis-cleanup.sh b/cabal/travis/binaries/travis-cleanup.sh
--- a/cabal/travis/binaries/travis-cleanup.sh
+++ b/cabal/travis/binaries/travis-cleanup.sh
@@ -3,6 +3,6 @@
 # See travis/upload.sh for more documentation
 
 git remote set-url --push origin git@github.com:haskell-pushbot/cabal-binaries.git
-(umask 177 && cp id_rsa $HOME/.ssh/id_rsa)
+(umask 177 && tr A-Za-z N-ZA-Mn-za-m < id_rsa.rot13 > $HOME/.ssh/id_rsa)
 ssh-keyscan github.com >> $HOME/.ssh/known_hosts
 git push origin --delete "$(git rev-parse --abbrev-ref HEAD)"
diff --git a/cabal/travis/binaries/travis-test.sh b/cabal/travis/binaries/travis-test.sh
--- a/cabal/travis/binaries/travis-test.sh
+++ b/cabal/travis/binaries/travis-test.sh
@@ -2,6 +2,11 @@
 
 . ./travis-common.sh
 
+# Get the binaries
+S3_URL=$(curl -X POST "https://s3-bouncer.herokuapp.com/get/$(cat s3-object.txt)")
+curl "$S3_URL" > binaries.tgz
+tar xzf binaries.tgz
+
 # --hide-successes uses terminal control characters which mess up
 # Travis's log viewer.  So just print them all!
 TEST_OPTIONS=""
@@ -20,7 +25,12 @@
 (cd Cabal && timed ./parser-tests $TEST_OPTIONS) || exit $?
 
 # Test we can parse Hackage
-(cd Cabal && timed ./parser-hackage-tests $TEST_OPTIONS) | tail || exit $?
+# Note: no $TEST_OPTIONS as this isn't tasty suite
+
+# fetch 01-index.tar,
+# `hackage-tests parsec` tries to parse all of cabal files in the index.
+cabal update
+(cd Cabal && timed ./hackage-tests parsec) || exit $?
 
 if [ "x$CABAL_LIB_ONLY" = "xYES" ]; then
     exit 0;
diff --git a/cabal/travis/id_rsa b/cabal/travis/id_rsa
deleted file mode 100644
--- a/cabal/travis/id_rsa
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAwyBagHDRv7lqPz0Jus26XmLa9erl29MAT2ns2LURbszqhP6v
-KW5bp0bYeCrBOhUUq14tNpI/5xDnHdt1GJGztiLzTu9FLy7gts4xmkYlkiAJeUkg
-RGUeWDU0oK6Df5jkxu0N+tYcxMFMZLi1Nmm4ISGpYPHvfAPwRDRAojFZBFFI1vYO
-4awyz5X6DaMHu/D+TSTHDBzNDtq2oCWtDT1hh2Bhtxw5ZGeujlEXWLkp9eoA/TU/
-RBWL4s2xAot81iEWNN5xhFijlt2RsBLpqTj+TcEpvU9xMXYkQFpyqPJzxMsjHo4i
-50qnZdKQXeZJd/ZmIiAt4B4/tlSLz6RUmfSQfwIDAQABAoIBAQCXlrD4i61Hx2IV
-UvQWHfGlliMJXb3JM3lQOLh5+uFaNPQU8k9eXo/xuoY9hOmsl+gA4h86ABCJEIac
-mXu05Ky62RgwwI39A+wr2LCMa+aQSTdS9E6PFAeo+1yxYCJkpIFHUa7EqkabTJhu
-v1h4t1UG2EHgQNSOgfjM49M6rh+7y5b8NDH/67y0ygdaXQAlqPOxmllKAKJWKrCd
-zsrhaZXezPljblzGQpaV0+EhGGbrrqaos+kdraZcYXqo++sGEnITg2ElCHtGf0/0
-h1yr1PtNeLvhC0w/3piZnA58ls8OmXy0erVi9Pj1LLGEbeuFSz81+6SpmORgx1Kd
-4jazO1mxAoGBAOM2SXvmqS+8CCI3u52I9bbkE4keIM54tzFLNHWQknVHQn04GGxC
-lXjjcTyLNW2rT04RfGs2tXSse3sgEg1x/4uqo/kJvdZAAG9vUlWNukzqEVawVu84
-AJhhqWQWGSdOhnOS7G2aXjdrTfIvlvwjuUBii4s0fRw6QE0s5vpVyNh9AoGBANvZ
-WtYnuQuzsedhZDB0Chrg/z83DYpxlubDeP3iWnT7eBXes1nTLM0r9AChFCbyX6Ml
-Wd5phCbjvZrtQG04E90xHQNFq77F5q9U8D0gJIDi3fcktRrP9pCQqZhCbuLTKhxa
-eFFS3W8c7pivQLsdwr29wZK+yegN6ksZax7OktmrAoGAewGw1rsRbR5G6P9zOt4i
-6FihmuIMsLr5sl4ckGksYQGrJU9xKWsCsOexLi3PRwgvbvxYd1Ku+fNHBmleXJkS
-1/IRw4lalNshYTLLSDXqXil6KYxeBDQ1XknBAsZT58vDTl6EUPH5f9c/45WQEADn
-EcxH750C/n0qwp1EjtJSYaECgYBTSZi8IPhdkooHWkIWiR9651pLnJOoqze73Lnt
-lN8oCkyIHIJduT7zy3747g0wZAoPSIsvU1IZWZXvJ4qM1f3Qgla3cqGJ+HdYXRlW
-TuMFYO0uP93MdpS2V9eoMyLHE7CUZUHHrVjuS0uo1Fv1h2TLdSPscBMVso/cO5j1
-ZtUDWQKBgQCrIdI4X25eQg7h9noZkOkv0puQQJ/g/+sE7DOL6van74dtVSbgahwu
-/7umITYSfvkEFfbck5m7Yvsaje1Mzj0skXX8tST80WrCYwJ3BCY+BYvHoYOjhPt/
-q3Ycs1SPZ0Ao7/NkTEnkv0+hIGb5K99UvvLNXTk83pYcS09i5TfXDA==
------END RSA PRIVATE KEY-----
diff --git a/cabal/travis/id_rsa.pub b/cabal/travis/id_rsa.pub
--- a/cabal/travis/id_rsa.pub
+++ b/cabal/travis/id_rsa.pub
@@ -1,1 +1,1 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDIFqAcNG/uWo/PQm6zbpeYtr16uXb0wBPaezYtRFuzOqE/q8pblunRth4KsE6FRSrXi02kj/nEOcd23UYkbO2IvNO70UvLuC2zjGaRiWSIAl5SSBEZR5YNTSgroN/mOTG7Q361hzEwUxkuLU2abghIalg8e98A/BENECiMVkEUUjW9g7hrDLPlfoNowe78P5NJMcMHM0O2ragJa0NPWGHYGG3HDlkZ66OURdYuSn16gD9NT9EFYvizbECi3zWIRY03nGEWKOW3ZGwEumpOP5NwSm9T3ExdiRAWnKo8nPEyyMejiLnSqdl0pBd5kl39mYiIC3gHj+2VIvPpFSZ9JB/ ezyang@sabre
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8Vn3Fy0GADv2HAn2ebYi7/6lreuGMfhFOy68UZWmVGOvIFlThcnZRE+nCA9oqt/KZnBtnsr2mK1taoS0IbnG46dlNlpWdeb1e5RSEia9AexDqih2vhwuV40qxByJHdfI9PovSsMJ+7pCCvtxSEGxtqu5RegwGR7Crjqly5U/3eGW+w5D46KeZyfEQtT6bCRwM3QzSoN1k50OcIOf+u3k3ffPM3V6Fvy3l7mTddvo0ymPLrr632FzqetJyd6m26Bq03EXLE2VADGAPKsKg9XxcDaOnh+o1rCvpv4jX757mRTMOtnUzsRgM5QXWUgXDOlOxCDS+wnVSp1080WSckx0h ezyang@sabre
diff --git a/cabal/travis/id_rsa.rot13 b/cabal/travis/id_rsa.rot13
new file mode 100644
--- /dev/null
+++ b/cabal/travis/id_rsa.rot13
@@ -0,0 +1,27 @@
+-----ORTVA EFN CEVINGR XRL-----
+ZVVRcDVONNXPNDRNiSM9kpgOtN79ujW9az2Vh/+cn3euwU4EGfhiSTIcyEwelOMH
+4KW2HECcjtCnXeslzMjoM7X9cvgoJdRgPT5khBaMGMnIaKz9KhHHuVziDUfD6bbq
+e4pYyrAXfDpvE3KlCG6Y0eQPsh6Dte7pHuOfonehHKbZOxrjd46cphIC93uyifBD
++BvazpakRYH+zjxpQA0Z0dQqMBqQaPQa/eg5A33mmA1ruo8g5r5x3Ko6AZcwl66+
+g9up6aeFparcghtngAkSlkAyDNktQlePbCI8KN2wc4sdAnje6o+V1++r5xHmQeM1
+Z7RLQBHS1yVSjmcGfDt0ifW1HdqqCASxaWZqVDVQNDNONbVONDP7BbE4VSXlBeGO
+OoUM0Tjj8Ym880QZPChglVQ5yfA6wQoOE6bRVJHYih8DvNUKz9kM5e27it4L5yf/
+4dQOSNXY4QJ9xlvGG1K5j2D9Fu7ymQVW51bEu//1qhczlU/RnYImBi2Un18/Qzlf
+/L5YXenC43OqbFKMQTKBqgyiAuKxUM/zSDRAzRk6rzpVfiAxJ/uZmoUmPZoviZvr
+xKUjEPS17AByHA/GftLaLxliH6MS5Coe3M99WjvylbTxfkxmoHCVFKClJvSLkcy/
+LMGtWZ1749mb2y/mmH2zqf4w7ZVB1Un/2372BfQBUSQKi822NO04zTY+q4vhyBf0
+uddPxrtONbTONBhwG1/zlgOb3aR9gNJAhSc9aXHdE2n0FgGEg4A/NIRshcHJZJpn
+ELOYFq3ec7mabIlguXJoSjlg4FzB22Yc+CAofyXhXWkjV5PxmHtps6VrH/g8o7aW
+FQMY7ufFcXIW9r8aUDjtXrKhlrrWopgxr20nOxo/0it2OXwB/4DWSYgONbTONZlp
+09eAk7rLbWJyhFBAeT7S+oJI0A1JrQYkQKP0K0XdeNHTcowv3S8hFlOgNF3BHNKl
+xi+RsZgw/Y12JQJVpX3iOOCfqAB3MjUhJhMu9Rr/hANMoyphtXSVBQ3WMxPzwluc
+7l090EDlCxt64bODVEtXd0CFvT76D2yHogBGgHauNbTONZ1iwipfodihxrvzt/aU
+vr+FmrjAuGlprEH8IpAJPu7uP7zWWY8s33VifMUPY3M5q2jzq5jhY5ISGlK9C3Kb
+FYknhVuiNRpYJJM01+uQhS7hSNtDtOB40oIZ06IHkdv4M6e+YpikveKSGgNUA+e4
+vfprkyETT3q9TBwKg1f005qONbTNKNoqZwtQo4ilQqkiaWVUm/dmPCmZ6NNDW7yY
+Awzc7d4pzSLMP0YqbhTYLWLzEMsMKuAjRtEteVaLQf6/qoEpTM660ffl8SL4hvTr
+BXtg2zqpyOjpPWVqjTkr/0fc9xUmrIKZNFxtqSw0fw/ck5EPwwTrCr7r9vfEGech
+7wVgN4RPtLRN4NwuvRca5bO0fJ6oqBVhxb6MKvghe2E30LLOaq/8mulLibgqD6kE
+Cqvl381VIUCLLNRfCA6NEBFM1J7fpzC+W0VAfvm/9DinCz0x0RsvpoQ1cTFBahLc
+aQPFILNrdLWISQmbAoJ9GEJxMi8M8n7cKZUi1/v8zXsleCARnn2P8YR=
+-----RAQ EFN CEVINGR XRL-----
diff --git a/cabal/travis/upload.sh b/cabal/travis/upload.sh
--- a/cabal/travis/upload.sh
+++ b/cabal/travis/upload.sh
@@ -39,7 +39,7 @@
 # Setup SSH key we will use to push to binaries repository.
 # umask to get the permissions to be 600 (not 400, because the deploy
 # script in .travis.yml is going to clobber this private key)
-(umask 177 && cp id_rsa $HOME/.ssh/id_rsa)
+(umask 177 && tr A-Za-z N-ZA-Mn-za-m < id_rsa.rot13 > $HOME/.ssh/id_rsa)
 
 # Setup SSH keys
 ssh-keyscan github.com >> $HOME/.ssh/known_hosts
@@ -65,27 +65,38 @@
 cp -R $TRAVIS_BUILD_DIR/Cabal/tests                                  Cabal
 cp -R $TRAVIS_BUILD_DIR/cabal-install/tests                          cabal-install
 # Copy in credentials so we can delete branch when done
-cp $TRAVIS_BUILD_DIR/travis/id_rsa .
+cp $TRAVIS_BUILD_DIR/travis/id_rsa.rot13 .
 # Install all of the necessary files for testing
 cp $TRAVIS_BUILD_DIR/travis-install.sh .
 cp $TRAVIS_BUILD_DIR/travis-common.sh .
-# The binaries to test (statically linked, of course!)
-cp ${CABAL_BDIR}/c/unit-tests/build/unit-tests/unit-tests                         Cabal
-cp ${CABAL_BDIR}/c/check-tests/build/check-tests/check-tests                 Cabal
-cp ${CABAL_BDIR}/c/parser-tests/build/parser-tests/parser-tests                 Cabal
-cp ${CABAL_BDIR}/c/parser-hackage-tests/build/parser-hackage-tests/parser-hackage-tests Cabal
+
+cp ${CABAL_BDIR}/t/unit-tests/build/unit-tests/unit-tests          Cabal
+cp ${CABAL_BDIR}/t/check-tests/build/check-tests/check-tests       Cabal
+cp ${CABAL_BDIR}/t/parser-tests/build/parser-tests/parser-tests    Cabal
+cp ${CABAL_BDIR}/t/hackage-tests/build/hackage-tests/hackage-tests Cabal
+BINARIES="Cabal/unit-tests Cabal/check-tests Cabal/parser-tests Cabal/hackage-tests"
 if [ "x$CABAL_LIB_ONLY" != "xYES" ]; then
-    cp ${CABAL_INSTALL_BDIR}/build/cabal/cabal                       cabal-install
+    cp ${CABAL_INSTALL_EXE}                       cabal-install
+    BINARIES="cabal-install/cabal $BINARIES"
 fi
 
+# The binaries to test (statically linked, of course!)
+tar czf binaries.tgz $BINARIES
+rm $BINARIES # Don't check me in!
+
+# Upload to S3
+S3_URL=$(curl -X POST "https://s3-bouncer.herokuapp.com/put")
+curl "$S3_URL" --upload-file binaries.tgz
+rm binaries.tgz # Don't check me in!
+echo "$S3_URL" | xargs basename | cut -d '?' -f 1 > s3-object.txt
+
 # Add, commit, push
 git add .
 # The JSON in the commit message is used by the webhook listening
 # on the downstream repo to figure out who to communicate the
 # status update back to
-git commit -m '{"origin":"'$ORIGIN'",
+git commit -m '{"url":"'$URL'",
 
-"url":"'$URL'",
 "account":"'$ACCOUNT'",
 "repo":"'$REPO'",
 "commit": "'$COMMIT'",
diff --git a/cabal/update-cabal-files.sh b/cabal/update-cabal-files.sh
deleted file mode 100644
--- a/cabal/update-cabal-files.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-(cd Cabal; misc/gen-extra-source-files.hs Cabal.cabal)
-(cd cabal-install; ../Cabal/misc/gen-extra-source-files.hs cabal-install.cabal)
diff --git a/cabal/validate.sh b/cabal/validate.sh
new file mode 100644
--- /dev/null
+++ b/cabal/validate.sh
@@ -0,0 +1,199 @@
+#!/bin/sh
+# shellcheck disable=SC2086
+
+# Help
+if [ "$1" = "help" ]; then
+cat <<EOF
+This is a helper script to build and run tests locally.
+It does about the same things as appveyor.yml, only using cabal new-build.
+
+Simple usage:
+
+    $ HC=ghc-7.10.3 sh validate.sh
+
+Multiple ghcs (serial), this takes very long.
+
+    $ sh validate.sh ghc-7.6.3 ghc-7.8.4 ghc-7.10.3 ghc-8.0.2 ghc-8.2.2
+
+Params (with defaults)
+
+    JOBS=-j4                 cabal new-build -j argument
+    TESTSUITEJOBS=-j3        cabal-tests -j argument
+    CABALTESTS=true          Run Cabal tests
+    CABALINSTALLTESTS=true   Run cabal-install tests
+    CABALSUITETESTS=true     Run cabal-testsuite
+EOF
+exit 0
+fi
+
+# Loop thru compilers if given as an argument
+if [ $# -ne 0 ]; then
+    set -e
+    for HC in "$@"; do
+        export HC
+        sh $0
+    done
+    exit 0
+fi
+
+HC=${HC-ghc-8.2.2}
+JOBS=${JOBS--j4}
+TESTSUITEJOBS=${TESTSUITEJOBS--j3}
+
+CABALTESTS=${CABALTESTS-true}
+CABALINSTALLTESTS=${CABALINSTALLTESTS-true}
+CABALSUITETESTS=${CABALSUITETESTS-true}
+
+CABAL_VERSION="2.4.1.0"
+if [ "$(uname)" = "Linux" ]; then
+    ARCH="x86_64-linux"
+else
+    ARCH="x86_64-osx"
+fi
+
+BUILDDIR=dist-newstyle-validate-$HC
+CABAL_TESTSUITE_BDIR="$(pwd)/$BUILDDIR/build/$ARCH/$HC/cabal-testsuite-${CABAL_VERSION}"
+
+CABALNEWBUILD="cabal new-build $JOBS -w $HC --builddir=$BUILDDIR --project-file=cabal.project.validate"
+CABALPLAN="cabal-plan --builddir=$BUILDDIR"
+
+OUTPUT=$(mktemp)
+
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+BLUE='\033[0;34m'
+CYAN='\033[0;96m'
+RESET='\033[0m' # No Color
+
+JOB_START_TIME=$(date +%s)
+
+timed() {
+    PRETTYCMD=$(echo "$@" | sed -E 's/\/home[^ ]*\/([^\/])/**\/\1/g')
+    echo "$BLUE>>> $PRETTYCMD $RESET"
+    start_time=$(date +%s)
+
+    "$@" > "$OUTPUT" 2>&1
+    # echo "MOCK" > "$OUTPUT"
+    RET=$?
+
+    end_time=$(date +%s)
+    duration=$((end_time - start_time))
+    tduration=$((end_time - JOB_START_TIME))
+
+    if [ $RET -eq 0 ]; then
+        echo "$GREEN<<< $PRETTYCMD $RESET ($duration/$tduration sec)"
+
+        # if output is relatively short, show everything
+        if [ "$(wc -l < "$OUTPUT")" -le 20 ]; then
+            cat "$OUTPUT"
+        else
+            echo "..."
+            tail -n 5 "$OUTPUT"
+        fi
+
+        rm -f "$OUTPUT"
+
+        # bottom-margin
+        echo ""
+    else
+        echo "$RED<<< $PRETTYCMD $RESET ($duration/$tduration sec, $RET)"
+        cat "$OUTPUT"
+        echo "$RED<<< $* $RESET ($duration/$tduration sec, $RET)"
+        rm -f "$OUTPUT"
+        exit 1
+    fi
+}
+
+# Info
+echo "$CYAN!!! Validating with $HC $RESET"
+
+timed ghc --version
+timed cabal --version
+timed cabal-plan --version
+
+
+# Cabal
+echo "$CYAN=== Cabal: build ======================================= $(date +%T) === $RESET"
+
+timed $CABALNEWBUILD Cabal:lib:Cabal --enable-tests --disable-benchmarks --dry-run || exit 1
+timed $CABALNEWBUILD Cabal:lib:Cabal --enable-tests --disable-benchmarks --dep || exit 1
+timed $CABALNEWBUILD Cabal:lib:Cabal --enable-tests --disable-benchmarks || exit 1
+
+# Environment files interfere with legacy Custom setup builds in sandbox
+# https://github.com/haskell/cabal/issues/4642
+rm -rf .ghc.environment.*
+
+## Cabal tests
+if $CABALTESTS; then
+echo "$CYAN=== Cabal: test ======================================== $(date +%T) === $RESET"
+
+timed $CABALNEWBUILD Cabal:tests --enable-tests --disable-benchmarks --dry-run || exit 1
+timed $CABALNEWBUILD Cabal:tests --enable-tests --disable-benchmarks || exit 1
+rm -rf .ghc.environment.*
+
+CMD="$($CABALPLAN list-bin Cabal:test:unit-tests) $TESTSUITEJOBS --hide-successes"
+(cd Cabal && timed $CMD) || exit 1
+
+CMD="$($CABALPLAN list-bin Cabal:test:check-tests) $TESTSUITEJOBS --hide-successes"
+(cd Cabal && timed $CMD) || exit 1
+
+CMD="$($CABALPLAN list-bin Cabal:test:parser-tests) $TESTSUITEJOBS --hide-successes"
+(cd Cabal && timed $CMD) || exit 1
+
+CMD=$($CABALPLAN list-bin Cabal:test:hackage-tests)
+(cd Cabal && timed $CMD parsec d) || exit 1
+(cd Cabal && timed $CMD roundtrip k) || exit 1
+
+fi # $CABALTESTS
+
+
+# cabal-testsuite
+# cabal test ssuite is run first
+echo "$CYAN=== cabal-install cabal-testsuite: build =============== $(date +%T) === $RESET"
+
+timed $CABALNEWBUILD all --enable-tests --disable-benchmarks --dry-run || exit 1
+
+# For some reason this sometimes fails. So we try twice.
+CMD="$CABALNEWBUILD all --enable-tests --disable-benchmarks"
+(timed $CMD) || (timed $CMD) || exit 1
+rm -rf .ghc.environment.*
+
+
+# cabal-install tests
+if $CABALINSTALLTESTS; then
+echo "$CYAN=== cabal-install: test ================================ $(date +%T) === $RESET"
+
+# this are sorted in asc time used, quicker tests first.
+CMD="$($CABALPLAN list-bin cabal-install:test:solver-quickcheck) $TESTSUITEJOBS --hide-successes"
+(cd cabal-install && timed $CMD) || exit 1
+
+# This doesn't work in parallel either
+CMD="$($CABALPLAN list-bin cabal-install:test:unit-tests) -j1 --hide-successes"
+(cd cabal-install && timed $CMD) || exit 1
+
+# Only single job, otherwise we fail with "Heap exhausted"
+CMD="$($CABALPLAN list-bin cabal-install:test:memory-usage-tests) -j1 --hide-successes"
+(cd cabal-install && timed $CMD) || exit 1
+
+# This test-suite doesn't like concurrency
+CMD="$($CABALPLAN list-bin cabal-install:test:integration-tests2) -j1 --hide-successes"
+(cd cabal-install && timed $CMD) || exit 1
+
+fi # CABALINSTALLTESTS
+
+
+# cabal-testsuite tests
+if $CABALSUITETESTS; then
+echo "$CYAN=== cabal-testsuite: test ============================== $(date +%T) === $RESET"
+
+CMD="$($CABALPLAN list-bin cabal-testsuite:exe:cabal-tests) --builddir=$CABAL_TESTSUITE_BDIR --with-cabal=$($CABALPLAN list-bin cabal-install:exe:cabal) $TESTSUITEJOBS --hide-successes"
+(cd cabal-testsuite && timed $CMD) || exit 1
+
+fi # CABALSUITETESTS
+
+
+# Footer
+JOB_END_TIME=$(date +%s)
+tduration=$((JOB_END_TIME - JOB_START_TIME))
+
+echo "$CYAN!!! Validation took $tduration seconds. $RESET"
diff --git a/hackport.cabal b/hackport.cabal
--- a/hackport.cabal
+++ b/hackport.cabal
@@ -1,5 +1,5 @@
 Name:           hackport
-Version:        0.6.2
+Version:        0.6.3
 License:        GPL
 License-file:   LICENSE
 Author:         Henning Günther, Duncan Coutts, Lennart Kolmodin
@@ -48,6 +48,7 @@
     binary,
     random,
     stm,
+    text,
     unix,
     -- cabal-install depends
     async,
