diff --git a/Cabal.cabal b/Cabal.cabal
--- a/Cabal.cabal
+++ b/Cabal.cabal
@@ -1,5 +1,5 @@
 name: Cabal
-version: 1.24.0.0
+version: 1.24.1.0
 copyright: 2003-2006, Isaac Jones
            2005-2011, Duncan Coutts
 license: BSD3
@@ -334,7 +334,7 @@
     tasty-hunit,
     tasty-quickcheck,
     pretty,
-    QuickCheck >= 2.7 && < 2.9,
+    QuickCheck >= 2.7 && < 2.10,
     Cabal
   ghc-options: -Wall
   default-language: Haskell98
diff --git a/Distribution/Compat/GetShortPathName.hs b/Distribution/Compat/GetShortPathName.hs
--- a/Distribution/Compat/GetShortPathName.hs
+++ b/Distribution/Compat/GetShortPathName.hs
@@ -30,16 +30,23 @@
 
 -- | On Windows, retrieves the short path form of the specified path. On
 -- non-Windows, does nothing. See https://github.com/haskell/cabal/issues/3185.
+--
+-- From MS's GetShortPathName docs:
+--
+--      Passing NULL for [the second] parameter and zero for cchBuffer
+--      will always return the required buffer size for a
+--      specified lpszLongPath.
+--
 getShortPathName :: FilePath -> IO FilePath
 getShortPathName path =
-  Win32.withTString path $ \c_path ->
+  Win32.withTString path $ \c_path -> do
+    c_len <- Win32.failIfZero "GetShortPathName #1 failed!" $
+      c_GetShortPathName c_path Win32.nullPtr 0
+    let arr_len = fromIntegral c_len
     allocaArray arr_len $ \c_out -> do
-      void $ Win32.failIfZero "GetShortPathName failed!" $
+      void $ Win32.failIfZero "GetShortPathName #2 failed!" $
         c_GetShortPathName c_path c_out c_len
       Win32.peekTString c_out
-  where
-    arr_len = length path + 1
-    c_len   = fromIntegral arr_len
 
 #else
 
diff --git a/Distribution/InstalledPackageInfo.hs b/Distribution/InstalledPackageInfo.hs
--- a/Distribution/InstalledPackageInfo.hs
+++ b/Distribution/InstalledPackageInfo.hs
@@ -83,6 +83,7 @@
         trusted           :: Bool,
         importDirs        :: [FilePath],
         libraryDirs       :: [FilePath],
+        libraryDynDirs    :: [FilePath],
         dataDir           :: FilePath,
         hsLibraries       :: [String],
         extraLibraries    :: [String],
@@ -143,6 +144,7 @@
         trusted           = False,
         importDirs        = [],
         libraryDirs       = [],
+        libraryDynDirs    = [],
         dataDir           = "",
         hsLibraries       = [],
         extraLibraries    = [],
@@ -187,11 +189,11 @@
 
 instance Text ExposedModule where
     disp (ExposedModule m reexport) =
-        Disp.sep [ disp m
-                 , case reexport of
-                    Just m' -> Disp.sep [Disp.text "from", disp m']
-                    Nothing -> Disp.empty
-                 ]
+        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
@@ -315,6 +317,9 @@
  , 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})
diff --git a/Distribution/Simple/Build/PathsModule.hs b/Distribution/Simple/Build/PathsModule.hs
--- a/Distribution/Simple/Build/PathsModule.hs
+++ b/Distribution/Simple/Build/PathsModule.hs
@@ -71,7 +71,7 @@
         pragmas++
         "module " ++ display paths_modulename ++ " (\n"++
         "    version,\n"++
-        "    getBinDir, getLibDir, getDataDir, getLibexecDir,\n"++
+        "    getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir,\n"++
         "    getDataFileName, getSysconfDir\n"++
         "  ) where\n"++
         "\n"++
@@ -108,9 +108,10 @@
           "\n\nbindirrel :: FilePath\n" ++
           "bindirrel = " ++ show flat_bindirreloc ++
           "\n"++
-          "\ngetBinDir, getLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath\n"++
+          "\ngetBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath\n"++
           "getBinDir = "++mkGetEnvOrReloc "bindir" flat_bindirreloc++"\n"++
           "getLibDir = "++mkGetEnvOrReloc "libdir" flat_libdirreloc++"\n"++
+          "getDynLibDir = "++mkGetEnvOrReloc "dynlibdir" flat_dynlibdirreloc++"\n"++
           "getDataDir = "++mkGetEnvOrReloc "datadir" flat_datadirreloc++"\n"++
           "getLibexecDir = "++mkGetEnvOrReloc "libexecdir" flat_libexecdirreloc++"\n"++
           "getSysconfDir = "++mkGetEnvOrReloc "sysconfdir" flat_sysconfdirreloc++"\n"++
@@ -124,16 +125,18 @@
           "\n"++
           filename_stuff
         | absolute =
-          "\nbindir, libdir, datadir, libexecdir, sysconfdir :: FilePath\n"++
+          "\nbindir, libdir, dynlibdir, datadir, libexecdir, sysconfdir :: FilePath\n"++
           "\nbindir     = " ++ show flat_bindir ++
           "\nlibdir     = " ++ show flat_libdir ++
+          "\ndynlibdir  = " ++ show flat_dynlibdir ++
           "\ndatadir    = " ++ show flat_datadir ++
           "\nlibexecdir = " ++ show flat_libexecdir ++
           "\nsysconfdir = " ++ show flat_sysconfdir ++
           "\n"++
-          "\ngetBinDir, getLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath\n"++
+          "\ngetBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath\n"++
           "getBinDir = "++mkGetEnvOr "bindir" "return bindir"++"\n"++
           "getLibDir = "++mkGetEnvOr "libdir" "return libdir"++"\n"++
+          "getDynLibDir = "++mkGetEnvOr "dynlibdir" "return dynlibdir"++"\n"++
           "getDataDir = "++mkGetEnvOr "datadir" "return datadir"++"\n"++
           "getLibexecDir = "++mkGetEnvOr "libexecdir" "return libexecdir"++"\n"++
           "getSysconfDir = "++mkGetEnvOr "sysconfdir" "return sysconfdir"++"\n"++
@@ -151,6 +154,8 @@
           "getBinDir = getPrefixDirRel bindirrel\n\n"++
           "getLibDir :: IO FilePath\n"++
           "getLibDir = "++mkGetDir flat_libdir flat_libdirrel++"\n\n"++
+          "getDynLibDir :: IO FilePath\n"++
+          "getDynLibDir = "++mkGetDir flat_dynlibdir flat_dynlibdirrel++"\n\n"++
           "getDataDir :: IO FilePath\n"++
           "getDataDir =  "++ mkGetEnvOr "datadir"
                               (mkGetDir flat_datadir flat_datadirrel)++"\n\n"++
@@ -173,6 +178,7 @@
           prefix     = flat_prefix,
           bindir     = flat_bindir,
           libdir     = flat_libdir,
+          dynlibdir  = flat_dynlibdir,
           datadir    = flat_datadir,
           libexecdir = flat_libexecdir,
           sysconfdir = flat_sysconfdir
@@ -180,6 +186,7 @@
         InstallDirs {
           bindir     = flat_bindirrel,
           libdir     = flat_libdirrel,
+          dynlibdir  = flat_dynlibdirrel,
           datadir    = flat_datadirrel,
           libexecdir = flat_libexecdirrel,
           sysconfdir = flat_sysconfdirrel
@@ -187,6 +194,7 @@
 
         flat_bindirreloc = shortRelativePath flat_prefix flat_bindir
         flat_libdirreloc = shortRelativePath flat_prefix flat_libdir
+        flat_dynlibdirreloc = shortRelativePath flat_prefix flat_dynlibdir
         flat_datadirreloc = shortRelativePath flat_prefix flat_datadir
         flat_libexecdirreloc = shortRelativePath flat_prefix flat_libexecdir
         flat_sysconfdirreloc = shortRelativePath flat_prefix flat_sysconfdir
diff --git a/Distribution/Simple/BuildPaths.hs b/Distribution/Simple/BuildPaths.hs
--- a/Distribution/Simple/BuildPaths.hs
+++ b/Distribution/Simple/BuildPaths.hs
@@ -13,7 +13,7 @@
 
 module Distribution.Simple.BuildPaths (
     defaultDistPref, srcPref,
-    hscolourPref, haddockPref,
+    haddockDirName, hscolourPref, haddockPref,
     autogenModulesDir,
 
     autogenModuleName,
@@ -48,12 +48,19 @@
 srcPref :: FilePath -> FilePath
 srcPref distPref = distPref </> "src"
 
-hscolourPref :: FilePath -> PackageDescription -> FilePath
+hscolourPref :: HaddockTarget -> FilePath -> PackageDescription -> FilePath
 hscolourPref = haddockPref
 
-haddockPref :: FilePath -> PackageDescription -> FilePath
-haddockPref distPref pkg_descr
-    = distPref </> "doc" </> "html" </> display (packageName pkg_descr)
+-- | This is the name of the directory in which the generated haddocks
+-- should be stored. It does not include the @<dist>/doc/html@ prefix.
+haddockDirName :: HaddockTarget -> PackageDescription -> FilePath
+haddockDirName ForDevelopment = display . packageName
+haddockDirName ForHackage = (++ "-docs") . display . packageId
+
+-- | The directory to which generated haddock documentation should be written.
+haddockPref :: HaddockTarget -> FilePath -> PackageDescription -> FilePath
+haddockPref haddockTarget distPref pkg_descr
+    = distPref </> "doc" </> "html" </> haddockDirName haddockTarget pkg_descr
 
 -- |The directory in which we put auto-generated modules
 autogenModulesDir :: LocalBuildInfo -> String
diff --git a/Distribution/Simple/Compiler.hs b/Distribution/Simple/Compiler.hs
--- a/Distribution/Simple/Compiler.hs
+++ b/Distribution/Simple/Compiler.hs
@@ -56,6 +56,7 @@
         unifiedIPIDRequired,
         packageKeySupported,
         unitIdSupported,
+        libraryDynDirSupported,
 
         -- * Support for profiling detail levels
         ProfDetailLevel(..),
@@ -290,6 +291,13 @@
 -- | Does this compiler support unit IDs?
 unitIdSupported :: Compiler -> Bool
 unitIdSupported = ghcSupported "Uses unit IDs"
+
+-- | Does this compiler support a package database entry with:
+-- "dynamic-library-dirs"?
+libraryDynDirSupported :: Compiler -> Bool
+libraryDynDirSupported comp = case compilerFlavor comp of
+  GHC -> compilerVersion comp >= Version [8,0,1,20161021] []
+  _   -> False
 
 -- | Utility function for GHC only features
 ghcSupported :: String -> Compiler -> Bool
diff --git a/Distribution/Simple/Configure.hs b/Distribution/Simple/Configure.hs
--- a/Distribution/Simple/Configure.hs
+++ b/Distribution/Simple/Configure.hs
@@ -42,6 +42,7 @@
                                       getPackageDBContents,
                                       configCompiler, configCompilerAux,
                                       configCompilerEx, configCompilerAuxEx,
+                                      computeEffectiveProfiling,
                                       ccLdOptionsBuildInfo,
                                       checkForeignDeps,
                                       interpretPackageDbFlags,
@@ -310,6 +311,29 @@
                       -> IO FilePath
 findDistPrefOrDefault = findDistPref defaultDistPref
 
+-- | Compute the effective value of the profiling flags
+-- @--enable-library-profiling@ and @--enable-executable-profiling@
+-- from the specified 'ConfigFlags'.  This may be useful for
+-- external Cabal tools which need to interact with Setup in
+-- a backwards-compatible way: the most predictable mechanism
+-- for enabling profiling across many legacy versions is to
+-- NOT use @--enable-profiling@ and use those two flags instead.
+--
+-- Note that @--enable-executable-profiling@ also affects profiling
+-- of benchmarks and (non-detailed) test suites.
+computeEffectiveProfiling :: ConfigFlags -> (Bool {- lib -}, Bool {- exe -})
+computeEffectiveProfiling cfg =
+    -- The --profiling flag sets the default for both libs and exes,
+    -- but can be overidden by --library-profiling, or the old deprecated
+    -- --executable-profiling flag.
+    --
+    -- The --profiling-detail and --library-profiling-detail flags behave
+    -- similarly
+    let profEnabledBoth = fromFlagOrDefault False (configProf cfg)
+        profEnabledLib  = fromFlagOrDefault profEnabledBoth (configProfLib cfg)
+        profEnabledExe  = fromFlagOrDefault profEnabledBoth (configProfExe cfg)
+    in (profEnabledLib, profEnabledExe)
+
 -- |Perform the \"@.\/setup configure@\" action.
 -- Returns the @.setup-config@ file.
 configure :: (GenericPackageDescription, HookedBuildInfo)
@@ -578,16 +602,8 @@
         ++ "is not being built. Linking will fail if any executables "
         ++ "depend on the library."
 
-    -- The --profiling flag sets the default for both libs and exes,
-    -- but can be overidden by --library-profiling, or the old deprecated
-    -- --executable-profiling flag.
-    let profEnabledLibOnly = configProfLib cfg
-        profEnabledBoth    = fromFlagOrDefault False (configProf cfg)
-        profEnabledLib = fromFlagOrDefault profEnabledBoth profEnabledLibOnly
-        profEnabledExe = fromFlagOrDefault profEnabledBoth (configProfExe cfg)
+    let (profEnabledLib, profEnabledExe) = computeEffectiveProfiling cfg
 
-    -- The --profiling-detail and --library-profiling-detail flags behave
-    -- similarly
     profDetailLibOnly <- checkProfDetail (configProfLibDetail cfg)
     profDetailBoth    <- liftM (fromFlagOrDefault ProfDetailDefault)
                                (checkProfDetail (configProfDetail cfg))
@@ -668,6 +684,7 @@
 
     dirinfo "Binaries"         (bindir dirs)     (bindir relative)
     dirinfo "Libraries"        (libdir dirs)     (libdir relative)
+    dirinfo "Dynamic libraries" (dynlibdir dirs) (dynlibdir relative)
     dirinfo "Private binaries" (libexecdir dirs) (libexecdir relative)
     dirinfo "Data files"       (datadir dirs)    (datadir relative)
     dirinfo "Documentation"    (docdir dirs)     (docdir relative)
diff --git a/Distribution/Simple/GHC.hs b/Distribution/Simple/GHC.hs
--- a/Distribution/Simple/GHC.hs
+++ b/Distribution/Simple/GHC.hs
@@ -144,17 +144,22 @@
 
   ghcInfo <- Internal.getGhcInfo verbosity implInfo ghcProg
   let ghcInfoMap = M.fromList ghcInfo
+      extensions = -- workaround https://ghc.haskell.org/ticket/11214
+                   filterExt JavaScriptFFI $
+                   -- see 'filterExtTH' comment below
+                   filterExtTH $ extensions0
 
       -- starting with GHC 8.0, `TemplateHaskell` will be omitted from
       -- `--supported-extensions` when it's not available.
       -- for older GHCs we can use the "Have interpreter" property to
       -- filter out `TemplateHaskell`
-      extensions | ghcVersion < Version [8] []
-                 , Just "NO" <- M.lookup "Have interpreter" ghcInfoMap
-                   = filter ((/= EnableExtension TemplateHaskell) . fst)
-                     extensions0
-                 | otherwise = extensions0
+      filterExtTH | ghcVersion < Version [8] []
+                   , Just "NO" <- M.lookup "Have interpreter" ghcInfoMap
+                   = filterExt TemplateHaskell
+                  | otherwise = id
 
+      filterExt ext = filter ((/= EnableExtension ext) . fst)
+
   let comp = Compiler {
         compilerId         = CompilerId GHC ghcVersion,
         compilerAbiTag     = NoAbiTag,
@@ -720,6 +725,7 @@
                                               && ghcVersion < Version [7,8] []
                                             then toFlag sharedLibInstallPath
                                             else mempty,
+                ghcOptHideAllPackages    = toFlag True,
                 ghcOptNoAutoLinkPackages = toFlag True,
                 ghcOptPackageDBs         = withPackageDB lbi,
                 ghcOptPackages           = toNubListR $
diff --git a/Distribution/Simple/GHC/IPI642.hs b/Distribution/Simple/GHC/IPI642.hs
--- a/Distribution/Simple/GHC/IPI642.hs
+++ b/Distribution/Simple/GHC/IPI642.hs
@@ -84,6 +84,7 @@
     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,
diff --git a/Distribution/Simple/GHC/Internal.hs b/Distribution/Simple/GHC/Internal.hs
--- a/Distribution/Simple/GHC/Internal.hs
+++ b/Distribution/Simple/GHC/Internal.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE PatternGuards #-}
+
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Distribution.Simple.GHC.Internal
@@ -139,8 +140,10 @@
     mbStripLocation = M.lookup "strip command" ghcInfo
 
     ccFlags        = getFlags "C compiler flags"
-    gccLinkerFlags = getFlags "Gcc Linker flags"
-    ldLinkerFlags  = getFlags "Ld Linker flags"
+    -- GHC 7.8 renamed "Gcc Linker flags" to "C compiler link flags"
+    -- and "Ld Linker flags" to "ld flags" (GHC #4862).
+    gccLinkerFlags = getFlags "Gcc Linker flags" ++ getFlags "C compiler link flags"
+    ldLinkerFlags  = getFlags "Ld Linker flags" ++ getFlags "ld flags"
 
     -- It appears that GHC 7.6 and earlier encode the tokenized flags as a
     -- [String] in these settings whereas later versions just encode the flags as
@@ -194,8 +197,11 @@
              withTempFile tempDir ".o" $ \testofile testohnd -> do
                hPutStrLn testchnd "int foo() { return 0; }"
                hClose testchnd; hClose testohnd
-               rawSystemProgram verbosity ghcProg ["-c", testcfile,
-                                                   "-o", testofile]
+               rawSystemProgram verbosity ghcProg
+                          [ "-hide-all-packages"
+                          , "-c", testcfile
+                          , "-o", testofile
+                          ]
                withTempFile tempDir ".o" $ \testofile' testohnd' ->
                  do
                    hClose testohnd'
@@ -339,6 +345,7 @@
 
       ghcOptCppIncludePath = toNubListR $ [autogenModulesDir lbi, odir]
                                           ++ PD.includeDirs bi,
+      ghcOptHideAllPackages= toFlag True,
       ghcOptPackageDBs     = withPackageDB lbi,
       ghcOptPackages       = toNubListR $ mkGhcOptPackages clbi,
       ghcOptCcOptions      = toNubListR $
@@ -364,12 +371,12 @@
 componentGhcOptions verbosity lbi bi clbi odir =
     mempty {
       ghcOptVerbosity       = toFlag verbosity,
-      ghcOptHideAllPackages = toFlag True,
       ghcOptCabal           = toFlag True,
       ghcOptThisUnitId      = case clbi of
         LibComponentLocalBuildInfo { componentCompatPackageKey = pk }
           -> toFlag pk
         _ -> Mon.mempty,
+      ghcOptHideAllPackages = toFlag True,
       ghcOptPackageDBs      = withPackageDB lbi,
       ghcOptPackages        = toNubListR $ mkGhcOptPackages clbi,
       ghcOptSplitObjs       = toFlag (splitObjs lbi),
diff --git a/Distribution/Simple/GHCJS.hs b/Distribution/Simple/GHCJS.hs
--- a/Distribution/Simple/GHCJS.hs
+++ b/Distribution/Simple/GHCJS.hs
@@ -789,8 +789,9 @@
            else error "libAbiHash: Can't find an enabled library way"
   --
   (ghcjsProg, _) <- requireProgram verbosity ghcjsProgram (withPrograms lbi)
-  getProgramInvocationOutput verbosity
-    (ghcInvocation ghcjsProg comp platform ghcArgs)
+  hash <- getProgramInvocationOutput verbosity
+          (ghcInvocation ghcjsProg comp platform ghcArgs)
+  return (takeWhile (not . isSpace) hash)
 
 adjustExts :: String -> String -> GhcOptions -> GhcOptions
 adjustExts hiSuf objSuf opts =
diff --git a/Distribution/Simple/Haddock.hs b/Distribution/Simple/Haddock.hs
--- a/Distribution/Simple/Haddock.hs
+++ b/Distribution/Simple/Haddock.hs
@@ -135,15 +135,15 @@
         comp          = compiler lbi
         platform      = hostPlatform lbi
 
-        flags
-          | fromFlag (haddockForHackage flags') = flags'
+        flags = case haddockTarget of
+          ForDevelopment -> flags'
+          ForHackage -> flags'
             { haddockHoogle       = Flag True
             , haddockHtml         = Flag True
             , haddockHtmlLocation = Flag (pkg_url ++ "/docs")
             , haddockContents     = Flag (toPathTemplate pkg_url)
             , haddockHscolour     = Flag True
             }
-          | otherwise = flags'
         pkg_url       = "/package/$pkg-$version"
         flag f        = fromFlag $ f flags
 
@@ -151,6 +151,8 @@
                        { optKeepTempFiles = flag haddockKeepTempFiles }
         htmlTemplate  = fmap toPathTemplate . flagToMaybe . haddockHtmlLocation
                         $ flags
+        haddockTarget =
+          fromFlagOrDefault ForDevelopment (haddockForHackage flags')
 
     setupMessage verbosity "Running Haddock for" (packageId pkg_descr)
     (confHaddock, version, _) <-
@@ -180,15 +182,14 @@
     initialBuildSteps (flag haddockDistPref) pkg_descr lbi verbosity
 
     when (flag haddockHscolour) $
-      hscolour' (warn verbosity) pkg_descr lbi suffixes
+      hscolour' (warn verbosity) haddockTarget pkg_descr lbi suffixes
       (defaultHscolourFlags `mappend` haddockToHscolour flags)
 
     libdirArgs <- getGhcLibDir  verbosity lbi
     let commonArgs = mconcat
             [ libdirArgs
             , fromFlags (haddockTemplateEnv lbi (packageId pkg_descr)) flags
-            , fromPackageDescription forDist pkg_descr ]
-        forDist = fromFlagOrDefault False (haddockForHackage flags)
+            , fromPackageDescription haddockTarget pkg_descr ]
 
     let pre c = preprocessComponent pkg_descr c lbi False verbosity suffixes
     withAllComponentsInBuildOrder pkg_descr lbi $ \component clbi -> do
@@ -249,11 +250,12 @@
       argOutputDir = maybe mempty Dir . flagToMaybe $ haddockDistPref flags
     }
 
-fromPackageDescription :: Bool -> PackageDescription -> HaddockArgs
-fromPackageDescription forDist pkg_descr =
+fromPackageDescription :: HaddockTarget -> PackageDescription -> HaddockArgs
+fromPackageDescription haddockTarget pkg_descr =
       mempty { argInterfaceFile = Flag $ haddockName pkg_descr,
                argPackageName = Flag $ packageId $ pkg_descr,
-               argOutputDir = Dir $ "doc" </> "html" </> name,
+               argOutputDir = Dir $
+                   "doc" </> "html" </> haddockDirName haddockTarget pkg_descr,
                argPrologue = Flag $ if null desc then synopsis pkg_descr
                                     else desc,
                argTitle = Flag $ showPkg ++ subtitle
@@ -261,9 +263,6 @@
       where
         desc = PD.description pkg_descr
         showPkg = display (packageId pkg_descr)
-        name
-          | forDist = showPkg ++ "-docs"
-          | otherwise = display (packageName pkg_descr)
         subtitle | null (synopsis pkg_descr) = ""
                  | otherwise                 = ": " ++ synopsis pkg_descr
 
@@ -469,8 +468,13 @@
                  withTempFileEx tmpFileOpts outputDir "haddock-response.txt" $
                     \responseFileName hf -> do
                          when haddockSupportsUTF8 (hSetEncoding hf utf8)
-                         hPutStr hf $ unlines $ map escapeArg renderedArgs
+                         let responseContents =
+                                 unlines $ map escapeArg renderedArgs
+                         hPutStr hf responseContents
                          hClose hf
+                         info verbosity $ responseFileName ++ " contents: <<<"
+                         info verbosity responseContents
+                         info verbosity $ ">>> " ++ responseFileName
                          let respFile = "@" ++ responseFileName
                          k ([respFile], result)
                else
@@ -648,18 +652,19 @@
   -- we preprocess even if hscolour won't be found on the machine
   -- will this upset someone?
   initialBuildSteps distPref pkg_descr lbi verbosity
-  hscolour' die pkg_descr lbi suffixes flags
+  hscolour' die ForDevelopment pkg_descr lbi suffixes flags
  where
    verbosity  = fromFlag (hscolourVerbosity flags)
    distPref = fromFlag $ hscolourDistPref flags
 
 hscolour' :: (String -> IO ()) -- ^ Called when the 'hscolour' exe is not found.
+          -> HaddockTarget
           -> PackageDescription
           -> LocalBuildInfo
           -> [PPSuffixHandler]
           -> HscolourFlags
           -> IO ()
-hscolour' onNoHsColour pkg_descr lbi suffixes flags =
+hscolour' onNoHsColour haddockTarget pkg_descr lbi suffixes flags =
     either onNoHsColour (\(hscolourProg, _, _) -> go hscolourProg) =<<
       lookupProgramVersion verbosity hscolourProgram
       (orLaterVersion (Version [1,8] [])) (withPrograms lbi)
@@ -668,7 +673,7 @@
     go hscolourProg = do
       setupMessage verbosity "Running hscolour for" (packageId pkg_descr)
       createDirectoryIfMissingVerbose verbosity True $
-        hscolourPref distPref pkg_descr
+        hscolourPref haddockTarget distPref pkg_descr
 
       let pre c = preprocessComponent pkg_descr c lbi False verbosity suffixes
       withAllComponentsInBuildOrder pkg_descr lbi $ \comp _ -> do
@@ -676,7 +681,7 @@
         let
           doExe com = case (compToExe com) of
             Just exe -> do
-              let outputDir = hscolourPref distPref pkg_descr
+              let outputDir = hscolourPref haddockTarget distPref pkg_descr
                               </> exeName exe </> "src"
               runHsColour hscolourProg outputDir =<< getExeSourceFiles lbi exe
             Nothing -> do
@@ -685,7 +690,7 @@
               return ()
         case comp of
           CLib lib -> do
-            let outputDir = hscolourPref distPref pkg_descr </> "src"
+            let outputDir = hscolourPref haddockTarget distPref pkg_descr </> "src"
             runHsColour hscolourProg outputDir =<< getLibSourceFiles lbi lib
           CExe   _ -> when (fromFlag (hscolourExecutables flags)) $ doExe comp
           CTest  _ -> when (fromFlag (hscolourTestSuites  flags)) $ doExe comp
diff --git a/Distribution/Simple/Install.hs b/Distribution/Simple/Install.hs
--- a/Distribution/Simple/Install.hs
+++ b/Distribution/Simple/Install.hs
@@ -26,7 +26,8 @@
          , die, info, notice, warn, matchDirFileGlob )
 import Distribution.Simple.Compiler
          ( CompilerFlavor(..), compilerFlavor )
-import Distribution.Simple.Setup (CopyFlags(..), fromFlag)
+import Distribution.Simple.Setup (CopyFlags(..), fromFlag
+                                 ,HaddockTarget(ForDevelopment))
 
 import qualified Distribution.Simple.GHC   as GHC
 import qualified Distribution.Simple.GHCJS as GHCJS
@@ -59,7 +60,7 @@
       installDirs@(InstallDirs {
          bindir     = binPref,
          libdir     = libPref,
---         dynlibdir  = dynlibPref, --see TODO below
+         dynlibdir  = dynlibPref,
          datadir    = dataPref,
          docdir     = docPref,
          htmldir    = htmlPref,
@@ -69,18 +70,13 @@
              -- binPref should be computed per executable
              = absoluteInstallDirs pkg_descr lbi copydest
 
-      --TODO: decide if we need the user to be able to control the libdir
-      -- for shared libs independently of the one for static libs. If so
-      -- it should also have a flag in the command line UI
-      -- For the moment use dynlibdir = libdir
-      dynlibPref = libPref
       progPrefixPref = substPathTemplate (packageId pkg_descr) lbi (progPrefix lbi)
       progSuffixPref = substPathTemplate (packageId pkg_descr) lbi (progSuffix lbi)
 
   unless (hasLibs pkg_descr || hasExes pkg_descr) $
       die "No executables and no library found. Nothing to do."
-  docExists <- doesDirectoryExist $ haddockPref distPref pkg_descr
-  info verbosity ("directory " ++ haddockPref distPref pkg_descr ++
+  docExists <- doesDirectoryExist $ haddockPref ForDevelopment distPref pkg_descr
+  info verbosity ("directory " ++ haddockPref ForDevelopment distPref pkg_descr ++
                   " does exist: " ++ show docExists)
 
   installDataFiles verbosity pkg_descr dataPref
@@ -88,13 +84,13 @@
   when docExists $ do
       createDirectoryIfMissingVerbose verbosity True htmlPref
       installDirectoryContents verbosity
-          (haddockPref distPref pkg_descr) htmlPref
+          (haddockPref ForDevelopment distPref pkg_descr) htmlPref
       -- setPermissionsRecursive [Read] htmlPref
       -- The haddock interface file actually already got installed
       -- in the recursive copy, but now we install it where we actually
       -- want it to be (normally the same place). We could remove the
       -- copy in htmlPref first.
-      let haddockInterfaceFileSrc  = haddockPref distPref pkg_descr
+      let haddockInterfaceFileSrc  = haddockPref ForDevelopment distPref pkg_descr
                                                    </> haddockName pkg_descr
           haddockInterfaceFileDest = interfacePref </> haddockName pkg_descr
       -- We only generate the haddock interface file for libs, So if the
diff --git a/Distribution/Simple/InstallDirs.hs b/Distribution/Simple/InstallDirs.hs
--- a/Distribution/Simple/InstallDirs.hs
+++ b/Distribution/Simple/InstallDirs.hs
@@ -182,7 +182,11 @@
            LHC    -> "$compiler"
            UHC    -> "$pkgid"
            _other -> "$abi" </> "$libname",
-      dynlibdir    = "$libdir",
+      dynlibdir    = "$libdir" </> case comp of
+           JHC    -> "$compiler"
+           LHC    -> "$compiler"
+           UHC    -> "$pkgid"
+           _other -> "$abi",
       libexecdir   = case buildOS of
         Windows   -> "$prefix" </> "$libname"
         _other    -> "$prefix" </> "libexec",
@@ -331,6 +335,7 @@
      | BindirVar     -- ^ The @$bindir@ path variable
      | LibdirVar     -- ^ The @$libdir@ path variable
      | LibsubdirVar  -- ^ The @$libsubdir@ path variable
+     | DynlibdirVar  -- ^ The @$dynlibdir@ path variable
      | DatadirVar    -- ^ The @$datadir@ path variable
      | DatasubdirVar -- ^ The @$datasubdir@ path variable
      | DocdirVar     -- ^ The @$docdir@ path variable
@@ -426,6 +431,7 @@
   ,(BindirVar,     bindir     dirs)
   ,(LibdirVar,     libdir     dirs)
   ,(LibsubdirVar,  libsubdir  dirs)
+  ,(DynlibdirVar,  dynlibdir  dirs)
   ,(DatadirVar,    datadir    dirs)
   ,(DatasubdirVar, datasubdir dirs)
   ,(DocdirVar,     docdir     dirs)
@@ -448,6 +454,7 @@
   show BindirVar     = "bindir"
   show LibdirVar     = "libdir"
   show LibsubdirVar  = "libsubdir"
+  show DynlibdirVar  = "dynlibdir"
   show DatadirVar    = "datadir"
   show DatasubdirVar = "datasubdir"
   show DocdirVar     = "docdir"
@@ -476,6 +483,7 @@
                  ,("bindir",     BindirVar)
                  ,("libdir",     LibdirVar)
                  ,("libsubdir",  LibsubdirVar)
+                 ,("dynlibdir",  DynlibdirVar)
                  ,("datadir",    DatadirVar)
                  ,("datasubdir", DatasubdirVar)
                  ,("docdir",     DocdirVar)
diff --git a/Distribution/Simple/LocalBuildInfo.hs b/Distribution/Simple/LocalBuildInfo.hs
--- a/Distribution/Simple/LocalBuildInfo.hs
+++ b/Distribution/Simple/LocalBuildInfo.hs
@@ -441,10 +441,15 @@
                           ]
 
     let ipkgs          = allPackages (installedPkgs lbi)
-        allDepLibDirs  = concatMap Installed.libraryDirs ipkgs
+        -- First look for dynamic libraries in `dynamic-library-dirs`, and use
+        -- `library-dirs` as a fall back.
+        getDynDir pkg  = case Installed.libraryDynDirs pkg of
+                           [] -> Installed.libraryDirs pkg
+                           d  -> d
+        allDepLibDirs  = concatMap getDynDir ipkgs
         internalLib
           | inplace    = buildDir lbi
-          | otherwise  = libdir installDirs
+          | otherwise  = dynlibdir installDirs
         allDepLibDirs' = if hasInternalDeps
                             then internalLib : allDepLibDirs
                             else allDepLibDirs
diff --git a/Distribution/Simple/Register.hs b/Distribution/Simple/Register.hs
--- a/Distribution/Simple/Register.hs
+++ b/Distribution/Simple/Register.hs
@@ -323,9 +323,8 @@
     IPI.importDirs         = [ libdir installDirs | hasModules ],
     -- Note. the libsubdir and datasubdir templates have already been expanded
     -- into libdir and datadir.
-    IPI.libraryDirs        = if hasLibrary
-                               then libdir installDirs : extraLibDirs bi
-                               else                      extraLibDirs bi,
+    IPI.libraryDirs        = libdirs,
+    IPI.libraryDynDirs     = dynlibdirs,
     IPI.dataDir            = datadir installDirs,
     IPI.hsLibraries        = if hasLibrary
                                then [getHSLibraryName (componentUnitId clbi)]
@@ -349,10 +348,25 @@
     bi = libBuildInfo lib
     (absinc, relinc) = partition isAbsolute (includeDirs bi)
     hasModules = not $ null (libModules lib)
+    comp = compiler lbi
     hasLibrary = hasModules || not (null (cSources bi))
                             || (not (null (jsSources bi)) &&
-                                compilerFlavor (compiler lbi) == GHCJS)
+                                compilerFlavor comp == GHCJS)
+    (libdirs, dynlibdirs)
+      | not hasLibrary
+      = (extraLibDirs bi, [])
+      -- the dynamic-library-dirs defaults to the library-dirs if not specified,
+      -- so this works whether the dynamic-library-dirs field is supported or not
 
+      | libraryDynDirSupported comp
+      = (libdir    installDirs : extraLibDirs bi,
+         dynlibdir installDirs : extraLibDirs bi)
+
+      | otherwise
+      = (libdir installDirs : dynlibdir installDirs : extraLibDirs bi, [])
+      -- the compiler doesn't understand the dynamic-library-dirs field so we
+      -- add the dyn directory to the "normal" list in the library-dirs field
+
 -- | Construct 'InstalledPackageInfo' for a library that is in place in the
 -- build tree.
 --
@@ -377,6 +391,7 @@
     installDirs =
       (absoluteInstallDirs pkg lbi NoCopyDest) {
         libdir     = inplaceDir </> libTargetDir,
+        dynlibdir  = inplaceDir </> libTargetDir,
         datadir    = inplaceDir </> dataDir pkg,
         docdir     = inplaceDocdir,
         htmldir    = inplaceHtmldir,
diff --git a/Distribution/Simple/Setup.hs b/Distribution/Simple/Setup.hs
--- a/Distribution/Simple/Setup.hs
+++ b/Distribution/Simple/Setup.hs
@@ -39,6 +39,7 @@
   configAbsolutePaths, readPackageDbList, showPackageDbList,
   CopyFlags(..),     emptyCopyFlags,     defaultCopyFlags,     copyCommand,
   InstallFlags(..),  emptyInstallFlags,  defaultInstallFlags,  installCommand,
+  HaddockTarget(..),
   HaddockFlags(..),  emptyHaddockFlags,  defaultHaddockFlags,  haddockCommand,
   HscolourFlags(..), emptyHscolourFlags, defaultHscolourFlags, hscolourCommand,
   BuildFlags(..),    emptyBuildFlags,    defaultBuildFlags,    buildCommand,
@@ -766,6 +767,11 @@
       libsubdir (\v flags -> flags { libsubdir = v })
       installDirArg
 
+  , option "" ["dynlibdir"]
+      "installation directory for dynamic libraries"
+      dynlibdir (\v flags -> flags { dynlibdir = v })
+      installDirArg
+
   , option "" ["libexecdir"]
       "installation directory for program executables"
       libexecdir (\v flags -> flags { libexecdir = v })
@@ -1209,13 +1215,27 @@
 -- * Haddock flags
 -- ------------------------------------------------------------
 
+
+-- | When we build haddock documentation, there are two cases:
+--
+-- 1. We build haddocks only for the current development version,
+--    intended for local use and not for distribution. In this case,
+--    we store the generated documentation in @<dist>/doc/html/<package name>@.
+--
+-- 2. We build haddocks for intended for uploading them to hackage.
+--    In this case, we need to follow the layout that hackage expects
+--    from documentation tarballs, and we might also want to use different
+--    flags than for development builds, so in this case we store the generated
+--    documentation in @<dist>/doc/html/<package id>-docs@.
+data HaddockTarget = ForHackage | ForDevelopment deriving (Eq, Show, Generic)
+
 data HaddockFlags = HaddockFlags {
     haddockProgramPaths :: [(String, FilePath)],
     haddockProgramArgs  :: [(String, [String])],
     haddockHoogle       :: Flag Bool,
     haddockHtml         :: Flag Bool,
     haddockHtmlLocation :: Flag String,
-    haddockForHackage   :: Flag Bool,
+    haddockForHackage   :: Flag HaddockTarget,
     haddockExecutables  :: Flag Bool,
     haddockTestSuites   :: Flag Bool,
     haddockBenchmarks   :: Flag Bool,
@@ -1237,7 +1257,7 @@
     haddockHoogle       = Flag False,
     haddockHtml         = Flag False,
     haddockHtmlLocation = NoFlag,
-    haddockForHackage   = Flag False,
+    haddockForHackage   = Flag ForDevelopment,
     haddockExecutables  = Flag False,
     haddockTestSuites   = Flag False,
     haddockBenchmarks   = Flag False,
@@ -1306,7 +1326,7 @@
   ,option "" ["for-hackage"]
    "Collection of flags to generate documentation suitable for upload to hackage"
    haddockForHackage (\v flags -> flags { haddockForHackage = v })
-   trueArg
+   (noArg (Flag ForHackage))
 
   ,option "" ["executables"]
    "Run haddock for Executables targets"
diff --git a/Distribution/Version.hs b/Distribution/Version.hs
--- a/Distribution/Version.hs
+++ b/Distribution/Version.hs
@@ -53,6 +53,7 @@
   laterVersion, earlierVersion,
   orLaterVersion, orEarlierVersion,
   unionVersionRanges, intersectVersionRanges,
+  differenceVersionRanges,
   invertVersionRange,
   withinVersion,
   betweenVersionsInclusive,
@@ -239,6 +240,16 @@
 --
 intersectVersionRanges :: VersionRange -> VersionRange -> VersionRange
 intersectVersionRanges = IntersectVersionRanges
+
+-- | The difference of two version ranges
+--
+-- >   withinRange v' (differenceVersionRanges vr1 vr2)
+-- > = withinRange v' vr1 && not (withinRange v' vr2)
+--
+-- @since 1.24.1.0
+differenceVersionRanges :: VersionRange -> VersionRange -> VersionRange
+differenceVersionRanges vr1 vr2 =
+    intersectVersionRanges vr1 (invertVersionRange vr2)
 
 -- | The inverse of a version range
 --
diff --git a/changelog b/changelog
--- a/changelog
+++ b/changelog
@@ -1,4 +1,14 @@
 -*-change-log-*-
+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).
+
+1.24.0.1 Ryan Thomas <ryan@ryant.org> May 2016
+	* Linker flags are now set correctly on GHC >= 7.8 (#3443).
 
 1.24.0.0 Ryan Thomas <ryan@ryant.org> May 2016
 	* Support GHC 8.
diff --git a/doc/developing-packages.markdown b/doc/developing-packages.markdown
--- a/doc/developing-packages.markdown
+++ b/doc/developing-packages.markdown
@@ -1317,9 +1317,9 @@
 
     It is only syntactic sugar. It is exactly equivalent to `foo >= 1.2 && < 1.3`.
 
-    Note: Prior to Cabal 1.8, build-depends specified in each section
+    Note: Prior to Cabal 1.8, `build-depends` specified in each section
     were global to all sections. This was unintentional, but some packages
-    were written to depend on it, so if you need your build-depends to
+    were written to depend on it, so if you need your `build-depends` to
     be local to each section, you must specify at least
     `Cabal-Version: >= 1.8` in your `.cabal` file.
 
@@ -1899,7 +1899,23 @@
 :   Fork the package's source repository using the appropriate version control
     system. The optional argument allows to choose a specific repository kind.
 
+## Custom setup scripts
 
+The optional `custom-setup` stanza contains information needed for the
+compilation of custom `Setup.hs` scripts,
+
+~~~~~~~~~~~~~~~~
+custom-setup
+  setup-depends:
+    base >= 4.5 && < 4.11,
+    Cabal < 1.25
+~~~~~~~~~~~~~~~~
+
+`setup-depends:` _package list_
+:   The dependencies needed to compile `Setup.hs`. See the
+    [`build-depends`](#build-information) section for a description of the
+    syntax expected by this field.
+
 ## Accessing data files from package code ##
 
 The placement on the target system of files listed in the `data-files`
@@ -1936,6 +1952,7 @@
 
 getBinDir :: IO FilePath
 getLibDir :: IO FilePath
+getDynLibDir :: IO FilePath
 getDataDir :: IO FilePath
 getLibexecDir :: IO FilePath
 getSysconfDir :: IO FilePath
@@ -2148,6 +2165,10 @@
     details, but note that this interface is experimental, and likely
     to change in future releases.
 
+    If you use a custom `Setup.hs` file you should strongly consider adding a
+    `custom-setup` stanza with a `setup-depends` field to ensure that your
+    setup script does not break with future dependency versions.
+
   * You could delegate all the work to `make`, though this is unlikely
     to be very portable. Cabal supports this with the `build-type`
     `Make` and a trivial setup library [Distribution.Make][dist-make],
@@ -2165,7 +2186,7 @@
     `unregister`, `clean`, `dist` and `docs`. Some options to commands
     are passed through as follows:
 
-      * The `--with-hc-pkg`, `--prefix`, `--bindir`, `--libdir`, `--datadir`,
+      * The `--with-hc-pkg`, `--prefix`, `--bindir`, `--libdir`, `--dynlibdir`, `--datadir`,
         `--libexecdir` and `--sysconfdir` options to the `configure` command are
         passed on to the `configure` script. In addition the value of the
         `--with-compiler` option is passed in a `--with-hc` option and all
@@ -2181,6 +2202,7 @@
                 $(MAKE) install prefix=$(destdir)/$(prefix) \
                                 bindir=$(destdir)/$(bindir) \
                                 libdir=$(destdir)/$(libdir) \
+                                dynlibdir=$(destdir)/$(dynlibdir) \
                                 datadir=$(destdir)/$(datadir) \
                                 libexecdir=$(destdir)/$(libexecdir) \
                                 sysconfdir=$(destdir)/$(sysconfdir) \
diff --git a/doc/index.markdown b/doc/index.markdown
--- a/doc/index.markdown
+++ b/doc/index.markdown
@@ -1,5 +1,5 @@
 % Cabal User Guide
-**Version: 1.24.0.0**
+**Version: 1.24.1.0**
 
 Cabal is the standard package system for [Haskell] software. It helps
 people to configure, build and install Haskell software and to
diff --git a/doc/installing-packages.markdown b/doc/installing-packages.markdown
--- a/doc/installing-packages.markdown
+++ b/doc/installing-packages.markdown
@@ -405,7 +405,7 @@
 [system-dependent
 parameters](developing-packages.html#system-dependent-parameters) or on
 [complex packages](developing-packages.html#more-complex-packages)), it
-is passed the `--with-hc-pkg`, `--prefix`, `--bindir`, `--libdir`,
+is passed the `--with-hc-pkg`, `--prefix`, `--bindir`, `--libdir`, `--dynlibdir`,
 `--datadir`, `--libexecdir` and `--sysconfdir` options. In addition the
 value of the `--with-compiler` option is passed in a `--with-hc` option
 and all options specified with `--configure-option=` are passed on.
@@ -498,6 +498,17 @@
     variables: `$prefix`, `$bindir`, `$pkgid`, `$pkg`, `$version`,
     `$compiler`, `$os`, `$arch`, `$abi`, `$abitag`
 
+`--dynlibdir=`_dir_
+:   Dynamic libraries are installed here.
+
+    By default, this is set to `$libdir/$abi`, which is usually not equal to
+    `$libdir/$libsubdir`.
+
+    In the simple build system, _dir_ may contain the following path
+    variables: `$prefix`, `$bindir`, `$libdir`, `$pkgid`, `$pkg`, `$version`,
+    `$compiler`, `$os`, `$arch`, `$abi`, `$abitag`
+
+
 `--libexecdir=`_dir_
 :   Executables that are not expected to be invoked directly by the user
     are installed here.
@@ -590,6 +601,9 @@
 `$libdir`
 :   As above but for `--libdir`
 
+`$dynlibdir`
+:   As above but for `--dynlibdir`
+
 `$libsubdir`
 :   As above but for `--libsubdir`
 
@@ -643,6 +657,7 @@
 `--bindir`                 `$prefix\bin`                                             `$prefix/bin`
 `--libdir`                 `$prefix`                                                 `$prefix/lib`
 `--libsubdir` (others)     `$pkgid\$compiler`                                        `$pkgid/$compiler`
+`--dynlibdir`              `$libdir\$abi`                                            `$libdir/$abi`
 `--libexecdir`             `$prefix\$pkgid`                                          `$prefix/libexec`
 `--datadir` (executable)   `$prefix`                                                 `$prefix/share`
 `--datadir` (library)      `C:\Program Files\Haskell`                                `$prefix/share`
@@ -666,7 +681,7 @@
 built.
 
 In order to achieve this, we require that for an executable on Windows,
-all of `$bindir`, `$libdir`, `$datadir` and `$libexecdir` begin with
+all of `$bindir`, `$libdir`, `$dynlibdir`, `$datadir` and `$libexecdir` begin with
 `$prefix`. If this is not the case then the compiled executable will
 have baked-in all absolute paths.
 
diff --git a/tests/UnitTests/Distribution/Version.hs b/tests/UnitTests/Distribution/Version.hs
--- a/tests/UnitTests/Distribution/Version.hs
+++ b/tests/UnitTests/Distribution/Version.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# OPTIONS_GHC -fno-warn-orphans
                 -fno-warn-incomplete-patterns
                 -fno-warn-deprecations
@@ -12,9 +13,12 @@
 
 import Test.Tasty
 import Test.Tasty.QuickCheck
-import Test.QuickCheck.Utils
 import qualified Test.Laws as Laws
 
+#if !MIN_VERSION_QuickCheck(2,9,0)
+import Test.QuickCheck.Utils
+#endif
+
 import Control.Monad (liftM, liftM2)
 import Data.Maybe (isJust, fromJust)
 import Data.List (sort, sortBy, nub)
@@ -41,6 +45,7 @@
   , property prop_orEarlierVersion
   , property prop_unionVersionRanges
   , property prop_intersectVersionRanges
+  , property prop_differenceVersionRanges
   , property prop_invertVersionRange
   , property prop_withinVersion
   , property prop_foldVersionRange
@@ -99,6 +104,7 @@
 --     -- , property prop_parse_disp5
 --   ]
 
+#if !MIN_VERSION_QuickCheck(2,9,0)
 instance Arbitrary Version where
   arbitrary = do
     branch <- smallListOf1 $
@@ -114,6 +120,7 @@
     [ Version branch' [] | branch' <- shrink branch, not (null branch') ]
   shrink (Version branch _tags) =
     [ Version branch [] ]
+#endif
 
 instance Arbitrary VersionRange where
   arbitrary = sized verRangeExp
@@ -195,6 +202,11 @@
 prop_intersectVersionRanges vr1 vr2 v' =
      withinRange v' (intersectVersionRanges vr1 vr2)
   == (withinRange v' vr1 && withinRange v' vr2)
+
+prop_differenceVersionRanges :: VersionRange -> VersionRange -> Version -> Bool
+prop_differenceVersionRanges vr1 vr2 v' =
+     withinRange v' (differenceVersionRanges vr1 vr2)
+  == (withinRange v' vr1 && not (withinRange v' vr2))
 
 prop_invertVersionRange :: VersionRange -> Version -> Bool
 prop_invertVersionRange vr v' =
