diff --git a/Cabal.cabal b/Cabal.cabal
--- a/Cabal.cabal
+++ b/Cabal.cabal
@@ -1,6 +1,6 @@
 cabal-version: 3.0
 name:          Cabal
-version:       3.14.1.1
+version:       3.14.2.0
 copyright:     2003-2024, Cabal Development Team (see AUTHORS file)
 license:       BSD-3-Clause
 license-file:  LICENSE
diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,6 @@
+# 3.14.2.0 [Mikolaj Konarski](mailto:mikolaj@well-typed.com) April 2025
+* See https://github.com/haskell/cabal/blob/master/release-notes/Cabal-3.14.2.0.md
+
 # 3.14.1.0 [Hécate](mailto:hecate+github@glitchbra.in) November 2024
 * See https://github.com/haskell/cabal/blob/master/release-notes/Cabal-3.14.1.0.md
 
diff --git a/src/Distribution/Backpack/Configure.hs b/src/Distribution/Backpack/Configure.hs
--- a/src/Distribution/Backpack/Configure.hs
+++ b/src/Distribution/Backpack/Configure.hs
@@ -103,6 +103,8 @@
     let conf_pkg_map =
           Map.fromListWith
             Map.union
+            $
+            -- Normal dependencies
             [ ( pc_pkgname pkg
               , Map.singleton
                   (pc_compname pkg)
@@ -115,8 +117,8 @@
               )
             | pkg <- prePkgDeps
             ]
-            `Map.union` Map.fromListWith
-              Map.union
+              ++
+              -- Promised dependencies
               [ (pkg, Map.singleton (ann_cname aid) aid)
               | ConfiguredPromisedComponent pkg aid <- promisedPkgDeps
               ]
diff --git a/src/Distribution/Compat/Async.hs b/src/Distribution/Compat/Async.hs
--- a/src/Distribution/Compat/Async.hs
+++ b/src/Distribution/Compat/Async.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE CPP #-}
-
 -- | 'Async', yet using 'MVar's.
 --
 -- Adopted from @async@ library
diff --git a/src/Distribution/Compat/Internal/TempFile.hs b/src/Distribution/Compat/Internal/TempFile.hs
--- a/src/Distribution/Compat/Internal/TempFile.hs
+++ b/src/Distribution/Compat/Internal/TempFile.hs
@@ -15,17 +15,17 @@
 import System.IO (Handle, openBinaryTempFile, openTempFile)
 #if defined(__IO_MANAGER_WINIO__)
 import System.IO              (openBinaryTempFileWithDefaultPermissions)
+import System.Posix.Internals (c_getpid)
 #else
 import Control.Exception      (onException)
 import Data.Bits              ((.|.))
 import Foreign.C              (CInt, eEXIST, getErrno, errnoToIOError)
 import GHC.IO.Handle.FD       (fdToHandle)
-import System.Posix.Internals (c_open, c_close, o_EXCL, o_BINARY, withFilePath,
+import System.Posix.Internals (c_getpid, c_open, c_close, o_EXCL, o_BINARY, withFilePath,
                                o_CREAT, o_RDWR, o_NONBLOCK, o_NOCTTY)
 #endif
 
 import System.IO.Error (isAlreadyExistsError)
-import System.Posix.Internals (c_getpid)
 
 #if defined(mingw32_HOST_OS) || defined(ghcjs_HOST_OS)
 import System.Directory       ( createDirectory )
diff --git a/src/Distribution/Compat/ResponseFile.hs b/src/Distribution/Compat/ResponseFile.hs
--- a/src/Distribution/Compat/ResponseFile.hs
+++ b/src/Distribution/Compat/ResponseFile.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE RankNTypes #-}
 
diff --git a/src/Distribution/Compat/Stack.hs b/src/Distribution/Compat/Stack.hs
--- a/src/Distribution/Compat/Stack.hs
+++ b/src/Distribution/Compat/Stack.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE ImplicitParams #-}
 {-# LANGUAGE RankNTypes #-}
 
diff --git a/src/Distribution/Compat/Time.hs b/src/Distribution/Compat/Time.hs
--- a/src/Distribution/Compat/Time.hs
+++ b/src/Distribution/Compat/Time.hs
@@ -41,13 +41,14 @@
 
 #else
 
-import System.Posix.Files ( FileStatus, getFileStatus )
-
+import System.Posix.Files
+  ( FileStatus, getFileStatus
 #if MIN_VERSION_unix(2,6,0)
-import System.Posix.Files ( modificationTimeHiRes )
+  , modificationTimeHiRes
 #else
-import System.Posix.Files ( modificationTime )
+  , modificationTime
 #endif
+  )
 
 #endif
 
diff --git a/src/Distribution/PackageDescription/Check.hs b/src/Distribution/PackageDescription/Check.hs
--- a/src/Distribution/PackageDescription/Check.hs
+++ b/src/Distribution/PackageDescription/Check.hs
@@ -568,8 +568,20 @@
       rck =
         PackageDistSuspiciousWarn
           . MissingUpperBounds CETSetup
-  checkPVP ick is
-  checkPVPs rck rs
+      leuck =
+        PackageDistSuspiciousWarn
+          . LEUpperBounds CETSetup
+      tzuck =
+        PackageDistSuspiciousWarn
+          . TrailingZeroUpperBounds CETSetup
+      gtlck =
+        PackageDistSuspiciousWarn
+          . GTLowerBounds CETSetup
+  checkPVP (checkDependencyVersionRange $ not . hasUpperBound) ick is
+  checkPVPs (checkDependencyVersionRange $ not . hasUpperBound) rck rs
+  checkPVPs (checkDependencyVersionRange hasLEUpperBound) leuck ds
+  checkPVPs (checkDependencyVersionRange hasTrailingZeroUpperBound) tzuck ds
+  checkPVPs (checkDependencyVersionRange hasGTLowerBound) gtlck ds
 
 checkPackageId :: Monad m => PackageIdentifier -> CheckM m ()
 checkPackageId (PackageIdentifier pkgName_ _pkgVersion_) = do
diff --git a/src/Distribution/PackageDescription/Check/Common.hs b/src/Distribution/PackageDescription/Check/Common.hs
--- a/src/Distribution/PackageDescription/Check/Common.hs
+++ b/src/Distribution/PackageDescription/Check/Common.hs
@@ -16,6 +16,7 @@
   , partitionDeps
   , checkPVP
   , checkPVPs
+  , checkDependencyVersionRange
   ) where
 
 import Distribution.Compat.Prelude
@@ -116,34 +117,32 @@
 -- for important dependencies like base).
 checkPVP
   :: Monad m
-  => (String -> PackageCheck) -- Warn message dependend on name
+  => (Dependency -> Bool)
+  -> (String -> PackageCheck) -- Warn message depends on name
   -- (e.g. "base", "Cabal").
   -> [Dependency]
   -> CheckM m ()
-checkPVP ckf ds = do
-  let ods = checkPVPPrim ds
+checkPVP p ckf ds = do
+  let ods = filter p ds
   mapM_ (tellP . ckf . unPackageName . depPkgName) ods
 
 -- PVP dependency check for a list of dependencies. Some code duplication
 -- is sadly needed to provide more ergonimic error messages.
 checkPVPs
   :: Monad m
-  => ( [String]
+  => (Dependency -> Bool)
+  -> ( [String]
        -> PackageCheck -- Grouped error message, depends on a
        -- set of names.
      )
   -> [Dependency] -- Deps to analyse.
   -> CheckM m ()
-checkPVPs cf ds
+checkPVPs p cf ds
   | null ns = return ()
   | otherwise = tellP (cf ns)
   where
-    ods = checkPVPPrim ds
+    ods = filter p ds
     ns = map (unPackageName . depPkgName) ods
 
--- Returns dependencies without upper bounds.
-checkPVPPrim :: [Dependency] -> [Dependency]
-checkPVPPrim ds = filter withoutUpper ds
-  where
-    withoutUpper :: Dependency -> Bool
-    withoutUpper (Dependency _ ver _) = not . hasUpperBound $ ver
+checkDependencyVersionRange :: (VersionRange -> Bool) -> Dependency -> Bool
+checkDependencyVersionRange p (Dependency _ ver _) = p ver
diff --git a/src/Distribution/PackageDescription/Check/Target.hs b/src/Distribution/PackageDescription/Check/Target.hs
--- a/src/Distribution/PackageDescription/Check/Target.hs
+++ b/src/Distribution/PackageDescription/Check/Target.hs
@@ -331,17 +331,30 @@
   checkAutogenModules ams bi
 
   -- PVP: we check for base and all other deps.
+  let ds = mergeDependencies $ targetBuildDepends bi
   (ids, rds) <-
     partitionDeps
       ads
       [mkUnqualComponentName "base"]
-      (mergeDependencies $ targetBuildDepends bi)
+      ds
   let ick = const (PackageDistInexcusable BaseNoUpperBounds)
       rck = PackageDistSuspiciousWarn . MissingUpperBounds cet
-  checkPVP ick ids
+      leuck = PackageDistSuspiciousWarn . LEUpperBounds cet
+      tzuck = PackageDistSuspiciousWarn . TrailingZeroUpperBounds cet
+      gtlck = PackageDistSuspiciousWarn . GTLowerBounds cet
+  checkPVP (checkDependencyVersionRange $ not . hasUpperBound) ick ids
   unless
     (isInternalTarget cet)
-    (checkPVPs rck rds)
+    (checkPVPs (checkDependencyVersionRange $ not . hasUpperBound) rck rds)
+  unless
+    (isInternalTarget cet)
+    (checkPVPs (checkDependencyVersionRange hasLEUpperBound) leuck ds)
+  unless
+    (isInternalTarget cet)
+    (checkPVPs (checkDependencyVersionRange hasTrailingZeroUpperBound) tzuck ds)
+  unless
+    (isInternalTarget cet)
+    (checkPVPs (checkDependencyVersionRange hasGTLowerBound) gtlck ds)
 
   -- Custom fields well-formedness (ASCII).
   mapM_ checkCustomField (customFieldsBI bi)
diff --git a/src/Distribution/PackageDescription/Check/Warning.hs b/src/Distribution/PackageDescription/Check/Warning.hs
--- a/src/Distribution/PackageDescription/Check/Warning.hs
+++ b/src/Distribution/PackageDescription/Check/Warning.hs
@@ -256,6 +256,9 @@
   | UnknownCompiler [String]
   | BaseNoUpperBounds
   | MissingUpperBounds CEType [String]
+  | LEUpperBounds CEType [String]
+  | TrailingZeroUpperBounds CEType [String]
+  | GTLowerBounds CEType [String]
   | SuspiciousFlagName [String]
   | DeclaredUsedFlags (Set.Set FlagName) (Set.Set FlagName)
   | NonASCIICustomField [String]
@@ -419,6 +422,9 @@
   | CIUnknownCompiler
   | CIBaseNoUpperBounds
   | CIMissingUpperBounds
+  | CILEUpperBounds
+  | CITrailingZeroUpperBounds
+  | CIGTLowerBounds
   | CISuspiciousFlagName
   | CIDeclaredUsedFlags
   | CINonASCIICustomField
@@ -561,6 +567,9 @@
 checkExplanationId (UnknownCompiler{}) = CIUnknownCompiler
 checkExplanationId (BaseNoUpperBounds{}) = CIBaseNoUpperBounds
 checkExplanationId (MissingUpperBounds{}) = CIMissingUpperBounds
+checkExplanationId (LEUpperBounds{}) = CILEUpperBounds
+checkExplanationId (TrailingZeroUpperBounds{}) = CITrailingZeroUpperBounds
+checkExplanationId (GTLowerBounds{}) = CIGTLowerBounds
 checkExplanationId (SuspiciousFlagName{}) = CISuspiciousFlagName
 checkExplanationId (DeclaredUsedFlags{}) = CIDeclaredUsedFlags
 checkExplanationId (NonASCIICustomField{}) = CINonASCIICustomField
@@ -588,11 +597,13 @@
 
 type CheckExplanationIDString = String
 
--- A one-word identifier for each CheckExplanation
---
--- ☞ N.B: if you modify anything here, remeber to change the documentation
--- in @doc/cabal-commands.rst@!
+-- | A one-word identifier for each @CheckExplanation@.
 ppCheckExplanationId :: CheckExplanationID -> CheckExplanationIDString
+-- NOTE: If you modify anything here, remember to change the documentation
+-- in @doc/cabal-commands.rst@!
+-- NOTE: These strings will have to satisfy a test that these messages don't
+-- have too many dashes:
+--   $ cabal run Cabal-tests:unit-tests -- --pattern=Parsimonious
 ppCheckExplanationId CIParseWarning = "parser-warning"
 ppCheckExplanationId CINoNameField = "no-name-field"
 ppCheckExplanationId CINoVersionField = "no-version-field"
@@ -708,6 +719,9 @@
 ppCheckExplanationId CIUnknownCompiler = "unknown-compiler"
 ppCheckExplanationId CIBaseNoUpperBounds = "missing-bounds-important"
 ppCheckExplanationId CIMissingUpperBounds = "missing-upper-bounds"
+ppCheckExplanationId CILEUpperBounds = "le-upper-bounds"
+ppCheckExplanationId CITrailingZeroUpperBounds = "tz-upper-bounds"
+ppCheckExplanationId CIGTLowerBounds = "gt-lower-bounds"
 ppCheckExplanationId CISuspiciousFlagName = "suspicious-flag"
 ppCheckExplanationId CIDeclaredUsedFlags = "unused-flag"
 ppCheckExplanationId CINonASCIICustomField = "non-ascii"
@@ -1301,15 +1315,33 @@
     ++ "version. For example if you have tested your package with 'base' "
     ++ "version 4.5 and 4.6 then use 'build-depends: base >= 4.5 && < 4.7'."
 ppExplanation (MissingUpperBounds ct names) =
-  let separator = "\n  - "
-   in "On "
-        ++ ppCET ct
-        ++ ", "
-        ++ "these packages miss upper bounds:"
-        ++ separator
-        ++ List.intercalate separator names
-        ++ "\n"
-        ++ "Please add them. There is more information at https://pvp.haskell.org/"
+  "On "
+    ++ ppCET ct
+    ++ ", "
+    ++ "these packages miss upper bounds:"
+    ++ listSep names
+    ++ "Please add them. There is more information at https://pvp.haskell.org/"
+ppExplanation (LEUpperBounds ct names) =
+  "On "
+    ++ ppCET ct
+    ++ ", "
+    ++ "these packages have less than or equals (<=) upper bounds:"
+    ++ listSep names
+    ++ "Please use less than (<) for upper bounds."
+ppExplanation (TrailingZeroUpperBounds ct names) =
+  "On "
+    ++ ppCET ct
+    ++ ", "
+    ++ "these packages have upper bounds with trailing zeros:"
+    ++ listSep names
+    ++ "Please avoid trailing zeros for upper bounds."
+ppExplanation (GTLowerBounds ct names) =
+  "On "
+    ++ ppCET ct
+    ++ ", "
+    ++ "these packages have greater than (>) lower bounds:"
+    ++ listSep names
+    ++ "Please use greater than or equals (>=) for lower bounds."
 ppExplanation (SuspiciousFlagName invalidFlagNames) =
   "Suspicious flag names: "
     ++ unwords invalidFlagNames
@@ -1470,6 +1502,11 @@
         else "extra-source-files"
 
 -- * Formatting utilities
+
+listSep :: [String] -> String
+listSep names =
+  let separator = "\n  - "
+   in separator ++ List.intercalate separator names ++ "\n"
 
 commaSep :: [String] -> String
 commaSep = List.intercalate ", "
diff --git a/src/Distribution/Simple/Bench.hs b/src/Distribution/Simple/Bench.hs
--- a/src/Distribution/Simple/Bench.hs
+++ b/src/Distribution/Simple/Bench.hs
@@ -23,10 +23,9 @@
 import Distribution.Compat.Prelude
 import Prelude ()
 
-import Distribution.Compat.Environment
 import qualified Distribution.PackageDescription as PD
 import Distribution.Pretty
-import Distribution.Simple.Build (addInternalBuildTools)
+import Distribution.Simple.Build (addInternalBuildToolsFixed)
 import Distribution.Simple.BuildPaths
 import Distribution.Simple.Compiler
 import Distribution.Simple.Errors
@@ -58,6 +57,7 @@
   -- ^ flags sent to benchmark
   -> IO ()
 bench args pkg_descr lbi flags = do
+  curDir <- LBI.absoluteWorkingDirLBI lbi
   let verbosity = fromFlag $ benchmarkVerbosity flags
       benchmarkNames = args
       pkgBenchmarks = PD.benchmarks pkg_descr
@@ -72,7 +72,8 @@
               lbi
                 { -- Include any build-tool-depends on build tools internal to the current package.
                   LBI.withPrograms =
-                    addInternalBuildTools
+                    addInternalBuildToolsFixed
+                      (Just curDir)
                       pkg_descr
                       lbi
                       (benchmarkBuildInfo bm)
@@ -90,15 +91,12 @@
               dieWithException verbosity $
                 NoBenchMarkProgram cmd
 
-            existingEnv <- getEnvironment
-
             -- Compute the appropriate environment for running the benchmark
             let progDb = LBI.withPrograms lbiForBench
                 pathVar = progSearchPath progDb
                 envOverrides = progOverrideEnv progDb
             newPath <- programSearchPathAsPATHVar pathVar
-            overrideEnv <- fromMaybe [] <$> getEffectiveEnvironment ([("PATH", Just newPath)] ++ envOverrides)
-            let shellEnv = overrideEnv ++ existingEnv
+            shellEnv <- getFullEnvironment ([("PATH", Just newPath)] ++ envOverrides)
 
             -- Add (DY)LD_LIBRARY_PATH if needed
             shellEnv' <-
diff --git a/src/Distribution/Simple/Build.hs b/src/Distribution/Simple/Build.hs
--- a/src/Distribution/Simple/Build.hs
+++ b/src/Distribution/Simple/Build.hs
@@ -48,6 +48,7 @@
 
     -- * Handling of internal build tools
   , addInternalBuildTools
+  , addInternalBuildToolsFixed
   ) where
 
 import Distribution.Compat.Prelude
@@ -188,13 +189,15 @@
     -- dumped.
     dumpBuildInfo verbosity distPref (configDumpBuildInfo (configFlags lbi)) pkg_descr lbi flags
 
+    curDir <- absoluteWorkingDirLBI lbi
+
     -- Now do the actual building
     (\f -> foldM_ f (installedPkgs lbi) componentsToBuild) $ \index target -> do
       let comp = targetComponent target
           clbi = targetCLBI target
           bi = componentBuildInfo comp
           -- Include any build-tool-depends on build tools internal to the current package.
-          progs' = addInternalBuildTools pkg_descr lbi bi (withPrograms lbi)
+          progs' = addInternalBuildToolsFixed (Just curDir) pkg_descr lbi bi (withPrograms lbi)
           lbi' =
             lbi
               { withPrograms = progs'
@@ -376,17 +379,20 @@
 
     internalPackageDB <- createInternalPackageDB verbosity lbi distPref
 
-    let lbiForComponent comp lbi' =
-          lbi'
-            { withPackageDB = withPackageDB lbi ++ [internalPackageDB]
-            , withPrograms =
-                -- Include any build-tool-depends on build tools internal to the current package.
-                addInternalBuildTools
-                  pkg_descr
-                  lbi'
-                  (componentBuildInfo comp)
-                  (withPrograms lbi')
-            }
+    let lbiForComponent comp lbi' = do
+          curDir <- absoluteWorkingDirLBI lbi'
+          return $
+            lbi'
+              { withPackageDB = withPackageDB lbi' ++ [internalPackageDB]
+              , withPrograms =
+                  -- Include any build-tool-depends on build tools internal to the current package.
+                  addInternalBuildToolsFixed
+                    (Just curDir)
+                    pkg_descr
+                    lbi'
+                    (componentBuildInfo comp)
+                    (withPrograms lbi')
+              }
         runPreBuildHooks :: LocalBuildInfo -> TargetInfo -> IO ()
         runPreBuildHooks lbi2 tgt =
           let inputs =
@@ -404,7 +410,7 @@
       [ do
         let clbi = targetCLBI subtarget
             comp = targetComponent subtarget
-            lbi' = lbiForComponent comp lbi
+        lbi' <- lbiForComponent comp lbi
         preBuildComponent runPreBuildHooks verbosity lbi' subtarget
         buildComponent
           (mempty{buildCommonFlags = mempty{setupVerbosity = toFlag verbosity}})
@@ -421,7 +427,7 @@
     -- REPL for target components
     let clbi = targetCLBI target
         comp = targetComponent target
-        lbi' = lbiForComponent comp lbi
+    lbi' <- lbiForComponent comp lbi
     preBuildComponent runPreBuildHooks verbosity lbi' target
     replComponent flags verbosity pkg_descr lbi' suffixHandlers comp clbi distPref
 
@@ -925,13 +931,18 @@
 --    directory environment variable for the current package to the current
 --    'progOverrideEnv', so that any programs configured from now on will be
 --    able to invoke these build tools.
-addInternalBuildTools
-  :: PackageDescription
+--
+--  NB: This function will be removed in the next Cabal major version
+--  (use addInternalBuildTools instead). This function is introduced solely for
+--  backporting in a PVP compliant way.
+addInternalBuildToolsFixed
+  :: Maybe (AbsolutePath (Dir Pkg))
+  -> PackageDescription
   -> LocalBuildInfo
   -> BuildInfo
   -> ProgramDb
   -> ProgramDb
-addInternalBuildTools pkg lbi bi progs =
+addInternalBuildToolsFixed mpwd pkg lbi bi progs =
   prependProgramSearchPathNoLogging
     internalToolPaths
     [pkgDataDirVar]
@@ -950,13 +961,27 @@
                 buildDir lbi
                   </> makeRelativePathEx (toolName' </> toolName' <.> exeExtension (hostPlatform lbi))
       ]
-    mbWorkDir = mbWorkDirLBI lbi
-    rawDataDir = dataDir pkg
-    dataDirPath
-      | null $ getSymbolicPath rawDataDir =
-          interpretSymbolicPath mbWorkDir sameDirectory
-      | otherwise =
-          interpretSymbolicPath mbWorkDir rawDataDir
+
+    dataDirPath :: FilePath
+    dataDirPath =
+      case mpwd of
+        -- This is an absolute path, so if a process changes directory, it can still
+        -- find the datadir (#10717)
+        Just pwd -> interpretSymbolicPathAbsolute pwd (dataDir pkg)
+        -- This is just wrong, but implemented for PVP compliance..
+        Nothing -> interpretSymbolicPathCWD (dataDir pkg)
+
+{-# WARNING addInternalBuildTools "This function is broken, use addInternalBuildToolsFixed instead" #-}
+
+-- | A backwards compatible (broken) version of `addInternalBuildTools`, do not
+-- use this function. Use 'addInternalBuildToolsFixed' instead.
+addInternalBuildTools
+  :: PackageDescription
+  -> LocalBuildInfo
+  -> BuildInfo
+  -> ProgramDb
+  -> ProgramDb
+addInternalBuildTools = addInternalBuildToolsFixed Nothing
 
 -- TODO: build separate libs in separate dirs so that we can build
 -- multiple libs, e.g. for 'LibTest' library-style test suites
diff --git a/src/Distribution/Simple/GHC.hs b/src/Distribution/Simple/GHC.hs
--- a/src/Distribution/Simple/GHC.hs
+++ b/src/Distribution/Simple/GHC.hs
@@ -125,23 +125,28 @@
 import Distribution.Verbosity
 import Distribution.Version
 import Language.Haskell.Extension
-import System.Directory
-  ( canonicalizePath
-  , createDirectoryIfMissing
-  , doesDirectoryExist
-  , doesFileExist
-  , getAppUserDataDirectory
-  , getDirectoryContents
-  )
 import System.FilePath
   ( isRelative
   , takeDirectory
   )
 import qualified System.Info
 #ifndef mingw32_HOST_OS
-import System.Directory (renameFile)
 import System.Posix (createSymbolicLink)
 #endif /* mingw32_HOST_OS */
+
+{- FOURMOLU_DISABLE -}
+import System.Directory
+  ( canonicalizePath
+  , createDirectoryIfMissing
+  , doesDirectoryExist
+  , doesFileExist
+  , getAppUserDataDirectory
+  , getDirectoryContents
+#ifndef mingw32_HOST_OS
+  , renameFile
+#endif
+  )
+{- FOURMOLU_ENABLE -}
 
 import Distribution.Simple.Setup (BuildingWhat (..))
 import Distribution.Simple.Setup.Build
diff --git a/src/Distribution/Simple/GHCJS.hs b/src/Distribution/Simple/GHCJS.hs
--- a/src/Distribution/Simple/GHCJS.hs
+++ b/src/Distribution/Simple/GHCJS.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE RankNTypes #-}
diff --git a/src/Distribution/Simple/Haddock.hs b/src/Distribution/Simple/Haddock.hs
--- a/src/Distribution/Simple/Haddock.hs
+++ b/src/Distribution/Simple/Haddock.hs
@@ -336,12 +336,13 @@
       createInternalPackageDB verbosity lbi (flag $ setupDistPref . haddockCommonFlags)
 
     (\f -> foldM_ f (installedPkgs lbi) targets') $ \index target -> do
+      curDir <- absoluteWorkingDirLBI lbi
       let
         component = targetComponent target
         clbi = targetCLBI target
         bi = componentBuildInfo component
         -- Include any build-tool-depends on build tools internal to the current package.
-        progs' = addInternalBuildTools pkg_descr lbi bi (withPrograms lbi)
+        progs' = addInternalBuildToolsFixed (Just curDir) pkg_descr lbi bi (withPrograms lbi)
         lbi' =
           lbi
             { withPrograms = progs'
diff --git a/src/Distribution/Simple/Program/Run.hs b/src/Distribution/Simple/Program/Run.hs
--- a/src/Distribution/Simple/Program/Run.hs
+++ b/src/Distribution/Simple/Program/Run.hs
@@ -30,6 +30,7 @@
   , getProgramInvocationOutputAndErrors
   , getProgramInvocationLBSAndErrors
   , getEffectiveEnvironment
+  , getFullEnvironment
   ) where
 
 import Distribution.Compat.Prelude
@@ -236,6 +237,12 @@
 -- | Return the current environment extended with the given overrides.
 -- If an entry is specified twice in @overrides@, the second entry takes
 -- precedence.
+--
+-- getEffectiveEnvironment returns 'Nothing' when there are no overrides.
+-- It returns an argument that is suitable to pass directly to 'CreateProcess' to
+-- override the environment.
+-- If you need the full environment to manipulate further, even when there are no overrides,
+-- then call 'getFullEnvironment'.
 getEffectiveEnvironment
   :: [(String, Maybe String)]
   -> IO (Maybe [(String, String)])
@@ -246,6 +253,17 @@
     apply os env = foldl' (flip update) env os
     update (var, Nothing) = Map.delete var
     update (var, Just val) = Map.insert var val
+
+-- | Like 'getEffectiveEnvironment', but when no overrides are specified,
+-- returns the full environment instead of 'Nothing'.
+getFullEnvironment
+  :: [(String, Maybe String)]
+  -> IO [(String, String)]
+getFullEnvironment overrides = do
+  menv <- getEffectiveEnvironment overrides
+  case menv of
+    Just env -> return env
+    Nothing -> getEnvironment
 
 -- | Like the unix xargs program. Useful for when we've got very long command
 -- lines that might overflow an OS limit on command line length and so you
diff --git a/src/Distribution/Simple/Program/Strip.hs b/src/Distribution/Simple/Program/Strip.hs
--- a/src/Distribution/Simple/Program/Strip.hs
+++ b/src/Distribution/Simple/Program/Strip.hs
@@ -58,6 +58,10 @@
     IOS -> return ()
     AIX -> return ()
     Solaris -> return ()
+    OpenBSD ->
+      -- '--strip-unneeded' sometimes strips too much on OpenBSD.
+      -- -- See https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/ports/lang/ghc/patches/patch-libraries_Cabal_Cabal_Distribution_Simple_Program_Strip_hs
+      return ()
     Windows ->
       -- Stripping triggers a bug in 'strip.exe' for
       -- libraries with lots identically named modules. See
diff --git a/src/Distribution/Simple/Register.hs b/src/Distribution/Simple/Register.hs
--- a/src/Distribution/Simple/Register.hs
+++ b/src/Distribution/Simple/Register.hs
@@ -549,8 +549,8 @@
     , IPI.ldOptions = ldOptions bi
     , IPI.frameworks = map getSymbolicPath $ frameworks bi
     , IPI.frameworkDirs = map getSymbolicPath $ extraFrameworkDirs bi
-    , IPI.haddockInterfaces = [haddockdir installDirs </> haddockLibraryPath pkg lib]
-    , IPI.haddockHTMLs = [htmldir installDirs]
+    , IPI.haddockInterfaces = [haddockdir installDirs </> haddockLibraryPath pkg lib | hasModules]
+    , IPI.haddockHTMLs = [htmldir installDirs | hasModules]
     , IPI.pkgRoot = Nothing
     , IPI.libVisibility = libVisibility lib
     }
diff --git a/src/Distribution/Simple/Setup.hs b/src/Distribution/Simple/Setup.hs
--- a/src/Distribution/Simple/Setup.hs
+++ b/src/Distribution/Simple/Setup.hs
@@ -1,12 +1,9 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE RankNTypes #-}
-
------------------------------------------------------------------------------
 
 -- |
 -- Module      :  Distribution.Simple.Setup
diff --git a/src/Distribution/Simple/Setup/Benchmark.hs b/src/Distribution/Simple/Setup/Benchmark.hs
--- a/src/Distribution/Simple/Setup/Benchmark.hs
+++ b/src/Distribution/Simple/Setup/Benchmark.hs
@@ -1,12 +1,9 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ViewPatterns #-}
-
------------------------------------------------------------------------------
 
 -- |
 -- Module      :  Distribution.Simple.Benchmark
diff --git a/src/Distribution/Simple/Setup/Build.hs b/src/Distribution/Simple/Setup/Build.hs
--- a/src/Distribution/Simple/Setup/Build.hs
+++ b/src/Distribution/Simple/Setup/Build.hs
@@ -1,12 +1,9 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ViewPatterns #-}
-
------------------------------------------------------------------------------
 
 -- |
 -- Module      :  Distribution.Simple.Setup.Build
diff --git a/src/Distribution/Simple/Setup/Clean.hs b/src/Distribution/Simple/Setup/Clean.hs
--- a/src/Distribution/Simple/Setup/Clean.hs
+++ b/src/Distribution/Simple/Setup/Clean.hs
@@ -1,12 +1,9 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ViewPatterns #-}
-
------------------------------------------------------------------------------
 
 -- |
 -- Module      :  Distribution.Simple.Setup.Clean
diff --git a/src/Distribution/Simple/Setup/Common.hs b/src/Distribution/Simple/Setup/Common.hs
--- a/src/Distribution/Simple/Setup/Common.hs
+++ b/src/Distribution/Simple/Setup/Common.hs
@@ -1,12 +1,9 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE DeriveTraversable #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE RankNTypes #-}
-
------------------------------------------------------------------------------
 
 -- |
 -- Module      :  Distribution.Simple.Setup.Common
diff --git a/src/Distribution/Simple/Setup/Copy.hs b/src/Distribution/Simple/Setup/Copy.hs
--- a/src/Distribution/Simple/Setup/Copy.hs
+++ b/src/Distribution/Simple/Setup/Copy.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DeriveGeneric #-}
@@ -6,8 +5,6 @@
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ViewPatterns #-}
-
------------------------------------------------------------------------------
 
 -- |
 -- Module      :  Distribution.Simple.Setup.Copy
diff --git a/src/Distribution/Simple/Setup/Global.hs b/src/Distribution/Simple/Setup/Global.hs
--- a/src/Distribution/Simple/Setup/Global.hs
+++ b/src/Distribution/Simple/Setup/Global.hs
@@ -1,10 +1,7 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE RankNTypes #-}
-
------------------------------------------------------------------------------
 
 -- |
 -- Module      :  Distribution.Simple.Setup.Global
diff --git a/src/Distribution/Simple/Setup/Haddock.hs b/src/Distribution/Simple/Setup/Haddock.hs
--- a/src/Distribution/Simple/Setup/Haddock.hs
+++ b/src/Distribution/Simple/Setup/Haddock.hs
@@ -1,12 +1,9 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ViewPatterns #-}
-
------------------------------------------------------------------------------
 
 -- |
 -- Module      :  Distribution.Simple.Setup.Haddock
diff --git a/src/Distribution/Simple/Setup/Hscolour.hs b/src/Distribution/Simple/Setup/Hscolour.hs
--- a/src/Distribution/Simple/Setup/Hscolour.hs
+++ b/src/Distribution/Simple/Setup/Hscolour.hs
@@ -1,12 +1,9 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ViewPatterns #-}
-
------------------------------------------------------------------------------
 
 -- |
 -- Module      :  Distribution.Simple.Setup.Hscolour
diff --git a/src/Distribution/Simple/Setup/Install.hs b/src/Distribution/Simple/Setup/Install.hs
--- a/src/Distribution/Simple/Setup/Install.hs
+++ b/src/Distribution/Simple/Setup/Install.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DeriveGeneric #-}
@@ -6,8 +5,6 @@
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ViewPatterns #-}
-
------------------------------------------------------------------------------
 
 -- |
 -- Module      :  Distribution.Simple.Setup.Install
diff --git a/src/Distribution/Simple/Setup/Register.hs b/src/Distribution/Simple/Setup/Register.hs
--- a/src/Distribution/Simple/Setup/Register.hs
+++ b/src/Distribution/Simple/Setup/Register.hs
@@ -1,12 +1,9 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ViewPatterns #-}
-
------------------------------------------------------------------------------
 
 -- |
 -- Module      :  Distribution.Simple.Setup.Register
diff --git a/src/Distribution/Simple/Setup/Repl.hs b/src/Distribution/Simple/Setup/Repl.hs
--- a/src/Distribution/Simple/Setup/Repl.hs
+++ b/src/Distribution/Simple/Setup/Repl.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
@@ -6,8 +5,6 @@
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ViewPatterns #-}
 
------------------------------------------------------------------------------
-
 -- |
 -- Module      :  Distribution.Simple.Setup.Repl
 -- Copyright   :  Isaac Jones 2003-2004
@@ -132,8 +129,7 @@
     , 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"
+            ++ "parameters and opens an interactive interpreter session.\n"
             ++ "\n"
             ++ "Otherwise, (re)configures with the given or default flags, and "
             ++ "loads the interpreter with the relevant modules. For executables, "
diff --git a/src/Distribution/Simple/Setup/SDist.hs b/src/Distribution/Simple/Setup/SDist.hs
--- a/src/Distribution/Simple/Setup/SDist.hs
+++ b/src/Distribution/Simple/Setup/SDist.hs
@@ -1,12 +1,9 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ViewPatterns #-}
-
------------------------------------------------------------------------------
 
 -- |
 -- Module      :  Distribution.Simple.Setup.SDist
diff --git a/src/Distribution/Simple/Setup/Test.hs b/src/Distribution/Simple/Setup/Test.hs
--- a/src/Distribution/Simple/Setup/Test.hs
+++ b/src/Distribution/Simple/Setup/Test.hs
@@ -1,12 +1,9 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ViewPatterns #-}
-
------------------------------------------------------------------------------
 
 -- |
 -- Module      :  Distribution.Simple.Test
diff --git a/src/Distribution/Simple/Test.hs b/src/Distribution/Simple/Test.hs
--- a/src/Distribution/Simple/Test.hs
+++ b/src/Distribution/Simple/Test.hs
@@ -27,7 +27,7 @@
 
 import qualified Distribution.PackageDescription as PD
 import Distribution.Pretty
-import Distribution.Simple.Build (addInternalBuildTools)
+import Distribution.Simple.Build (addInternalBuildToolsFixed)
 import Distribution.Simple.Compiler
 import Distribution.Simple.Hpc
 import Distribution.Simple.InstallDirs
@@ -70,6 +70,7 @@
   -- ^ flags sent to test
   -> IO ()
 test args pkg_descr lbi0 flags = do
+  curDir <- LBI.absoluteWorkingDirLBI lbi0
   let common = testCommonFlags flags
       verbosity = fromFlag $ setupVerbosity common
       distPref = fromFlag $ setupDistPref common
@@ -95,7 +96,8 @@
               lbi
                 { withPrograms =
                     -- Include any build-tool-depends on build tools internal to the current package.
-                    addInternalBuildTools
+                    addInternalBuildToolsFixed
+                      (Just curDir)
                       pkg_descr
                       lbi
                       (PD.testBuildInfo suite)
diff --git a/src/Distribution/Simple/Test/ExeV10.hs b/src/Distribution/Simple/Test/ExeV10.hs
--- a/src/Distribution/Simple/Test/ExeV10.hs
+++ b/src/Distribution/Simple/Test/ExeV10.hs
@@ -8,7 +8,6 @@
 import Distribution.Compat.Prelude
 import Prelude ()
 
-import Distribution.Compat.Environment
 import qualified Distribution.PackageDescription as PD
 import Distribution.Simple.BuildPaths
 import Distribution.Simple.Compiler
@@ -64,8 +63,6 @@
       way = guessWay lbi
       tixDir_ = i $ tixDir distPref way
 
-  existingEnv <- getEnvironment
-
   let cmd =
         i (LBI.buildDir lbi)
           </> testName'
@@ -92,14 +89,19 @@
       pathVar = progSearchPath progDb
       envOverrides = progOverrideEnv progDb
   newPath <- programSearchPathAsPATHVar pathVar
-  overrideEnv <- fromMaybe [] <$> getEffectiveEnvironment ([("PATH", Just newPath)] ++ envOverrides)
   let opts =
         map
           (testOption pkg_descr lbi suite)
           (testOptions flags)
       tixFile = packageRoot (testCommonFlags flags) </> getSymbolicPath (tixFilePath distPref way (testName'))
-      shellEnv = [("HPCTIXFILE", tixFile) | isCoverageEnabled] ++ overrideEnv ++ existingEnv
 
+  shellEnv <-
+    getFullEnvironment
+      ( [("PATH", Just newPath)]
+          ++ [("HPCTIXFILE", Just tixFile) | isCoverageEnabled]
+          ++ envOverrides
+      )
+
   -- Add (DY)LD_LIBRARY_PATH if needed
   shellEnv' <-
     if LBI.withDynExe lbi
@@ -125,13 +127,17 @@
         -- drain the output.
         evaluate (force logText)
 
+  let mbWorkDir =
+        interpretSymbolicPathCWD
+          <$> flagToMaybe (setupWorkingDir (testCommonFlags flags))
+
   (exit, logText) <- case testWrapper flags of
     Flag path ->
       rawSystemIOWithEnvAndAction
         verbosity
         path
         (cmd : opts)
-        Nothing
+        mbWorkDir
         (Just shellEnv')
         getLogText
         -- these handles are automatically closed
@@ -143,7 +149,7 @@
         verbosity
         cmd
         opts
-        Nothing
+        mbWorkDir
         (Just shellEnv')
         getLogText
         -- these handles are automatically closed
diff --git a/src/Distribution/Simple/Test/LibV09.hs b/src/Distribution/Simple/Test/LibV09.hs
--- a/src/Distribution/Simple/Test/LibV09.hs
+++ b/src/Distribution/Simple/Test/LibV09.hs
@@ -17,7 +17,6 @@
 import Distribution.Types.UnqualComponentName
 import Prelude ()
 
-import Distribution.Compat.Environment
 import Distribution.Compat.Internal.TempFile
 import Distribution.Compat.Process (proc)
 import Distribution.ModuleName
@@ -70,7 +69,6 @@
       way = guessWay lbi
 
   let mbWorkDir = LBI.mbWorkDirLBI lbi
-  existingEnv <- getEnvironment
 
   let cmd =
         interpretSymbolicPath mbWorkDir (LBI.buildDir lbi)
@@ -100,15 +98,17 @@
         pathVar = progSearchPath progDb
         envOverrides = progOverrideEnv progDb
     newPath <- programSearchPathAsPATHVar pathVar
-    overrideEnv <- fromMaybe [] <$> getEffectiveEnvironment ([("PATH", Just newPath)] ++ envOverrides)
 
     -- Run test executable
     let opts = map (testOption pkg_descr lbi suite) $ testOptions flags
         tixFile = i $ tixFilePath distPref way testName'
-        shellEnv =
-          [("HPCTIXFILE", tixFile) | isCoverageEnabled]
-            ++ overrideEnv
-            ++ existingEnv
+
+    shellEnv <-
+      getFullEnvironment
+        ( [("PATH", Just newPath)]
+            ++ [("HPCTIXFILE", Just tixFile) | isCoverageEnabled]
+            ++ envOverrides
+        )
     -- Add (DY)LD_LIBRARY_PATH if needed
     shellEnv' <-
       if LBI.withDynExe lbi
diff --git a/src/Distribution/Utils/MapAccum.hs b/src/Distribution/Utils/MapAccum.hs
--- a/src/Distribution/Utils/MapAccum.hs
+++ b/src/Distribution/Utils/MapAccum.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE CPP #-}
-
 module Distribution.Utils.MapAccum (mapAccumM) where
 
 import Distribution.Compat.Prelude
diff --git a/src/Distribution/Utils/Progress.hs b/src/Distribution/Utils/Progress.hs
--- a/src/Distribution/Utils/Progress.hs
+++ b/src/Distribution/Utils/Progress.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveFunctor #-}
 
 -- Note: This module was copied from cabal-install.
