diff --git a/Cabal.cabal b/Cabal.cabal
--- a/Cabal.cabal
+++ b/Cabal.cabal
@@ -1,6 +1,6 @@
-cabal-version: 2.2
+cabal-version: 3.0
 name:          Cabal
-version:       3.12.0.0
+version:       3.12.1.0
 copyright:     2003-2024, Cabal Development Team (see AUTHORS file)
 license:       BSD-3-Clause
 license-file:  LICENSE
@@ -34,9 +34,9 @@
   hs-source-dirs: src
 
   build-depends:
-    Cabal-syntax ^>= 3.12,
+    Cabal-syntax ^>= 3.12.1.0,
     array      >= 0.4.0.1  && < 0.6,
-    base       >= 4.9      && < 5,
+    base       >= 4.11     && < 5,
     bytestring >= 0.10.0.0 && < 0.13,
     containers >= 0.5.0.0  && < 0.8,
     deepseq    >= 1.3.0.1  && < 1.6,
diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,6 @@
+# 3.12.1.0 [Artem Pelenitsyn](mailto:a.pelenitsyn@gmail.com) June 2024
+* See https://github.com/haskell/cabal/blob/master/release-notes/Cabal-3.12.1.0.md
+
 # 3.12.0.0 [Francesco Ariis](mailto:fa-ml@ariis.it) May 2024
 * See https://github.com/haskell/cabal/blob/master/release-notes/Cabal-3.12.0.0.md
 
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
@@ -483,12 +483,7 @@
     (isJust $ defaultLanguage bi)
     (PackageBuildWarning CVDefaultLanguage)
   -- CheckSpecVer sv.
-  checkP
-    ( sv >= CabalSpecV1_10
-        && sv < CabalSpecV3_4
-        && isNothing (defaultLanguage bi)
-    )
-    (PackageBuildWarning CVDefaultLanguageComponent)
+  checkDefaultLanguage
   -- Check use of 'extra-framework-dirs' field.
   checkSpecVer
     CabalSpecV1_24
@@ -534,6 +529,17 @@
         (not . null $ cvs)
         (PackageDistInexcusable CVSources)
 
+    checkDefaultLanguage :: Monad m => CheckM m ()
+    checkDefaultLanguage = do
+      -- < 1.10 has no `default-language` field.
+      when
+        (sv >= CabalSpecV1_10 && isNothing (defaultLanguage bi))
+        -- < 3.4 mandatory, after just a suggestion.
+        ( if sv < CabalSpecV3_4
+            then tellP (PackageBuildWarning CVDefaultLanguageComponent)
+            else tellP (PackageDistInexcusable CVDefaultLanguageComponentSoft)
+        )
+
 -- Tests for extensions usage which can break Cabal < 1.4.
 checkBuildInfoExtensions :: Monad m => BuildInfo -> CheckM m ()
 checkBuildInfoExtensions bi = do
@@ -852,14 +858,14 @@
       let ghcNoRts = rmRtsOpts opts
       checkAlternatives
         title
-        "extensions"
+        "default-extensions"
         [ (flag, prettyShow extension)
         | flag <- ghcNoRts
         , Just extension <- [ghcExtension flag]
         ]
       checkAlternatives
         title
-        "extensions"
+        "default-extensions"
         [ (flag, extension)
         | flag@('-' : 'X' : extension) <- ghcNoRts
         ]
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
@@ -233,6 +233,7 @@
   | CVTestSuite
   | CVDefaultLanguage
   | CVDefaultLanguageComponent
+  | CVDefaultLanguageComponentSoft
   | CVExtraDocFiles
   | CVMultiLib
   | CVReexported
@@ -394,6 +395,7 @@
   | CICVTestSuite
   | CICVDefaultLanguage
   | CICVDefaultLanguageComponent
+  | CICVDefaultLanguageComponentSoft
   | CICVExtraDocFiles
   | CICVMultiLib
   | CICVReexported
@@ -534,6 +536,7 @@
 checkExplanationId (CVTestSuite{}) = CICVTestSuite
 checkExplanationId (CVDefaultLanguage{}) = CICVDefaultLanguage
 checkExplanationId (CVDefaultLanguageComponent{}) = CICVDefaultLanguageComponent
+checkExplanationId (CVDefaultLanguageComponentSoft{}) = CICVDefaultLanguageComponentSoft
 checkExplanationId (CVExtraDocFiles{}) = CICVExtraDocFiles
 checkExplanationId (CVMultiLib{}) = CICVMultiLib
 checkExplanationId (CVReexported{}) = CICVReexported
@@ -679,6 +682,7 @@
 ppCheckExplanationId CICVTestSuite = "test-cabal-ver"
 ppCheckExplanationId CICVDefaultLanguage = "default-language"
 ppCheckExplanationId CICVDefaultLanguageComponent = "no-default-language"
+ppCheckExplanationId CICVDefaultLanguageComponentSoft = "add-language"
 ppCheckExplanationId CICVExtraDocFiles = "extra-doc-files"
 ppCheckExplanationId CICVMultiLib = "multilib"
 ppCheckExplanationId CICVReexported = "reexported-modules"
@@ -1163,6 +1167,10 @@
     ++ "Haskell98 or Haskell2010). If a component uses different languages "
     ++ "in different modules then list the other ones in the "
     ++ "'other-languages' field."
+ppExplanation CVDefaultLanguageComponentSoft =
+  "Without `default-language`, cabal will default to Haskell98, which is "
+    ++ "probably not what you want. Please add `default-language` to all "
+    ++ "targets."
 ppExplanation CVExtraDocFiles =
   "To use the 'extra-doc-files' field the package needs to specify "
     ++ "'cabal-version: 1.18' or higher."
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
@@ -34,6 +34,10 @@
   , writeBuiltinAutogenFiles
   , writeAutogenFiles
 
+    -- ** Legacy functions
+  , componentInitialBuildSteps
+  , initialBuildSteps
+
     -- * Internal package database creation
   , createInternalPackageDB
   ) where
@@ -928,6 +932,61 @@
         GHC -> GHC.replFLib flags NoFlag pkg_descr lbi exe clbi
         _ -> dieWithException verbosity REPLNotSupported
 
+-- | Runs 'componentInitialBuildSteps' on every configured component.
+--
+-- Legacy function: does not run pre-build hooks or pre-processors. This function
+-- is insufficient on its own to prepare the build for a package.
+--
+-- Consumers wanting to prepare the sources of a package, e.g. in order to
+-- launch a REPL session, are advised to run @Setup repl --repl-multi-file=<fn>@
+-- instead.
+initialBuildSteps
+  :: FilePath
+  -- ^ "dist" prefix
+  -> PackageDescription
+  -- ^ mostly information from the .cabal file
+  -> LocalBuildInfo
+  -- ^ Configuration information
+  -> Verbosity
+  -- ^ The verbosity to use
+  -> IO ()
+initialBuildSteps distPref pkg_descr lbi verbosity =
+  withAllComponentsInBuildOrder pkg_descr lbi $ \_comp clbi ->
+    componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity
+{-# DEPRECATED
+  initialBuildSteps
+  "This function does not prepare all source files for a package. Suggestion: use 'Setup repl --repl-multi-file=<fn>'."
+  #-}
+
+-- | Creates the autogenerated files for a particular configured component.
+--
+-- Legacy function: does not run pre-build hooks or pre-processors. This function
+-- is insufficient on its own to prepare the build for a component.
+--
+-- Consumers wanting to prepare the sources of a component, e.g. in order to
+-- launch a REPL session, are advised to run
+-- @Setup repl <compName> --repl-multi-file=<fn>@ instead.
+componentInitialBuildSteps
+  :: FilePath
+  -- ^ "dist" prefix
+  -> PackageDescription
+  -- ^ mostly information from the .cabal file
+  -> LocalBuildInfo
+  -- ^ Configuration information
+  -> ComponentLocalBuildInfo
+  -- ^ Build info about the component
+  -> Verbosity
+  -- ^ The verbosity to use
+  -> IO ()
+componentInitialBuildSteps _distPref pkg_descr lbi clbi verbosity = do
+  let compBuildDir = componentBuildDir lbi clbi
+  createDirectoryIfMissingVerbose verbosity True compBuildDir
+  writeBuiltinAutogenFiles verbosity pkg_descr lbi clbi
+{-# DEPRECATED
+  componentInitialBuildSteps
+  "This function does not prepare all source files for a component. Suggestion: use 'Setup repl <compName> --repl-multi-file=<fn>'."
+  #-}
+
 -- | Pre-build steps for a component: creates the autogenerated files
 -- for a particular configured component.
 preBuildComponent
@@ -939,7 +998,8 @@
 preBuildComponent verbosity lbi tgt = do
   let pkg_descr = localPkgDescr lbi
       clbi = targetCLBI tgt
-  createDirectoryIfMissingVerbose verbosity True (componentBuildDir lbi clbi)
+      compBuildDir = componentBuildDir lbi clbi
+  createDirectoryIfMissingVerbose verbosity True compBuildDir
   writeBuiltinAutogenFiles verbosity pkg_descr lbi clbi
 
 -- | Generate and write to disk all built-in autogenerated files
diff --git a/src/Distribution/Simple/Build/Macros/Z.hs b/src/Distribution/Simple/Build/Macros/Z.hs
--- a/src/Distribution/Simple/Build/Macros/Z.hs
+++ b/src/Distribution/Simple/Build/Macros/Z.hs
@@ -3,8 +3,8 @@
 module Distribution.Simple.Build.Macros.Z (render, Z(..), ZPackage (..), ZTool (..)) where
 import Distribution.ZinzaPrelude
 data Z
-    = Z {zPackages :: ([ZPackage]),
-         zTools :: ([ZTool]),
+    = Z {zPackages :: [ZPackage],
+         zTools :: [ZTool],
          zPackageKey :: String,
          zComponentId :: String,
          zPackageVersion :: Version,
diff --git a/src/Distribution/Simple/Errors.hs b/src/Distribution/Simple/Errors.hs
--- a/src/Distribution/Simple/Errors.hs
+++ b/src/Distribution/Simple/Errors.hs
@@ -48,7 +48,8 @@
   | EnableBenchMark
   | BenchMarkNameDisabled String
   | NoBenchMark String
-  | NoLibraryFound
+  | -- | @NoLibraryFound@ has been downgraded to a warning, and is therefore no longer emitted.
+    NoLibraryFound
   | CompilerNotInstalled CompilerFlavor
   | CantFindIncludeFile String
   | UnsupportedTestSuite String
diff --git a/src/Distribution/Simple/GHC/Build/Link.hs b/src/Distribution/Simple/GHC/Build/Link.hs
--- a/src/Distribution/Simple/GHC/Build/Link.hs
+++ b/src/Distribution/Simple/GHC/Build/Link.hs
@@ -655,7 +655,9 @@
           writeFileAtomic (out_dir </> this_unit) $
             BS.pack $
               escapeArgs $
-                extra_opts ++ renderGhcOptions comp platform (ghcOpts{ghcOptMode = NoFlag})
+                extra_opts
+                  ++ renderGhcOptions comp platform (ghcOpts{ghcOptMode = NoFlag})
+                  ++ programOverrideArgs ghcProg
 
 replNoLoad :: Ord a => ReplOptions -> NubListR a -> NubListR a
 replNoLoad replFlags l
diff --git a/src/Distribution/Simple/Install.hs b/src/Distribution/Simple/Install.hs
--- a/src/Distribution/Simple/Install.hs
+++ b/src/Distribution/Simple/Install.hs
@@ -114,7 +114,7 @@
 
     checkHasLibsOrExes =
       unless (hasLibs pkg_descr || hasForeignLibs pkg_descr || hasExes pkg_descr) $
-        dieWithException verbosity NoLibraryFound
+        warn verbosity "No executables and no library found. Nothing to do."
 
 -- | Copy package global files.
 copyPackage
@@ -282,7 +282,7 @@
 -- | Install the files listed in data-files
 installDataFiles :: Verbosity -> PackageDescription -> FilePath -> IO ()
 installDataFiles verbosity pkg_descr destDataDir =
-  flip traverse_ (dataFiles pkg_descr) $ \glob -> do
+  for_ (dataFiles pkg_descr) $ \glob -> do
     let srcDataDirRaw = dataDir pkg_descr
         srcDataDir =
           if null srcDataDirRaw
diff --git a/src/Distribution/Simple/Program/GHC.hs b/src/Distribution/Simple/Program/GHC.hs
--- a/src/Distribution/Simple/Program/GHC.hs
+++ b/src/Distribution/Simple/Program/GHC.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MultiWayIf #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -223,8 +224,27 @@
                   , "keep-going" -- try harder, the build will still fail if it's erroneous
                   , "print-axiom-incomps" -- print more debug info for closed type families
                   ]
+              , from
+                  [9, 2]
+                  [ "family-application-cache"
+                  ]
+              , from
+                  [9, 6]
+                  [ "print-redundant-promotion-ticks"
+                  , "show-error-context"
+                  ]
+              , from
+                  [9, 8]
+                  [ "unoptimized-core-for-interpreter"
+                  ]
+              , from
+                  [9, 10]
+                  [ "diagnostics-as-json"
+                  , "print-error-index-links"
+                  , "break-points"
+                  ]
               ]
-          , flagIn . invertibleFlagSet "-d" $ ["ppr-case-as-let", "ppr-ticks"]
+          , flagIn $ invertibleFlagSet "-d" ["ppr-case-as-let", "ppr-ticks"]
           , isOptIntFlag
           , isIntFlag
           , if safeToFilterWarnings
@@ -285,6 +305,7 @@
         , from [8, 6] ["-dhex-word-literals"]
         , from [8, 8] ["-fshow-docs-of-hole-fits", "-fno-show-docs-of-hole-fits"]
         , from [9, 0] ["-dlinear-core-lint"]
+        , from [9, 10] ["-dipe-stats"]
         ]
 
     isOptIntFlag :: String -> Any
@@ -694,7 +715,10 @@
               | flagProfAuto implInfo -> ["-fprof-auto-exported"]
               | otherwise -> ["-auto"]
         , ["-split-sections" | flagBool ghcOptSplitSections]
-        , ["-split-objs" | flagBool ghcOptSplitObjs]
+        , case compilerCompatVersion GHC comp of
+            -- the -split-objs flag was removed in GHC 9.8
+            Just ver | ver >= mkVersion [9, 8] -> []
+            _ -> ["-split-objs" | flagBool ghcOptSplitObjs]
         , case flagToMaybe (ghcOptHPCDir opts) of
             Nothing -> []
             Just hpcdir -> ["-fhpc", "-hpcdir", hpcdir]
@@ -784,8 +808,7 @@
           -- Packages
 
           concat
-            [ [ case () of
-                  _
+            [ [ if
                     | unitIdSupported comp -> "-this-unit-id"
                     | packageKeySupported comp -> "-this-package-key"
                     | otherwise -> "-package-name"
