about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/languages-frameworks/haskell.section.md61
-rw-r--r--nixos/doc/manual/release-notes/rl-2411.section.md8
-rw-r--r--pkgs/development/compilers/ghc/Cabal-3.12-paths-fix-cycle-aarch64-darwin.patch596
-rw-r--r--pkgs/development/compilers/ghc/common-hadrian.nix8
-rw-r--r--pkgs/development/haskell-modules/configuration-darwin.nix23
-rw-r--r--pkgs/development/haskell-modules/configuration-ghc-9.0.x.nix7
-rw-r--r--pkgs/development/haskell-modules/configuration-ghc-9.6.x.nix3
-rw-r--r--pkgs/development/haskell-modules/configuration-ghc-9.8.x.nix2
-rw-r--r--pkgs/development/haskell-modules/configuration-hackage2nix/broken.yaml1
-rw-r--r--pkgs/development/haskell-modules/configuration-hackage2nix/main.yaml59
-rw-r--r--pkgs/development/haskell-modules/configuration-nix.nix7
-rw-r--r--pkgs/development/haskell-modules/generic-builder.nix76
-rw-r--r--pkgs/development/haskell-modules/hackage-packages.nix114
-rw-r--r--pkgs/development/haskell-modules/lib/compose.nix3
-rw-r--r--pkgs/top-level/all-packages.nix2
-rw-r--r--pkgs/top-level/release-haskell.nix39
16 files changed, 941 insertions, 68 deletions
diff --git a/doc/languages-frameworks/haskell.section.md b/doc/languages-frameworks/haskell.section.md
index dde55c329a4ac..e363e90854ad3 100644
--- a/doc/languages-frameworks/haskell.section.md
+++ b/doc/languages-frameworks/haskell.section.md
@@ -923,14 +923,59 @@ for this to work.
 
 `justStaticExecutables drv`
 : Only build and install the executables produced by `drv`, removing everything
-that may refer to other Haskell packages' store paths (like libraries and
-documentation). This dramatically reduces the closure size of the resulting
-derivation. Note that the executables are only statically linked against their
-Haskell dependencies, but will still link dynamically against libc, GMP and
-other system library dependencies. If dependencies use their Cabal-generated
-`Paths_*` module, this may not work as well if GHC's dead code elimination
-is unable to remove the references to the dependency's store path that module
-contains.
+  that may refer to other Haskell packages' store paths (like libraries and
+  documentation). This dramatically reduces the closure size of the resulting
+  derivation. Note that the executables are only statically linked against their
+  Haskell dependencies, but will still link dynamically against libc, GMP and
+  other system library dependencies.
+
+  If the library being built or its dependencies use their Cabal-generated
+  `Paths_*` module, this may not work as well if GHC's dead code elimination is
+  unable to remove the references to the dependency's store path that module
+  contains. (See [nixpkgs#164630][164630] for more information.)
+
+  Importing the `Paths_*` module may cause builds to fail with this message:
+
+  ```
+  error: output '/nix/store/64k8iw0ryz76qpijsnl9v87fb26v28z8-my-haskell-package-1.0.0.0' is not allowed to refer to the following paths:
+           /nix/store/5q5s4a07gaz50h04zpfbda8xjs8wrnhg-ghc-9.6.3
+  ```
+
+  If that happens, first disable the check for GHC references and rebuild the
+  derivation:
+
+  ```nix
+  pkgs.haskell.lib.overrideCabal
+    (pkgs.haskell.lib.justStaticExecutables my-haskell-package)
+    (drv: {
+      disallowGhcReference = false;
+    })
+  ```
+
+  Then use `strings` to determine which libraries are responsible:
+
+  ```
+  $ nix-build ...
+  $ strings result/bin/my-haskell-binary | grep /nix/store/
+  ...
+  /nix/store/n7ciwdlg8yyxdhbrgd6yc2d8ypnwpmgq-hs-opentelemetry-sdk-0.0.3.6/bin
+  ...
+  ```
+
+  Finally, use `remove-references-to` to delete those store paths from the produced output:
+
+  ```nix
+  pkgs.haskell.lib.overrideCabal
+    (pkgs.haskell.lib.justStaticExecutables my-haskell-package)
+    (drv: {
+      postInstall = ''
+        ${drv.postInstall or ""}
+        remove-references-to -t ${pkgs.haskellPackages.hs-opentelemetry-sdk}
+      '';
+    })
+  ```
+
+[164630]: https://github.com/NixOS/nixpkgs/issues/164630
 
 `enableSeparateBinOutput drv`
 : Install executables produced by `drv` to a separate `bin` output. This
diff --git a/nixos/doc/manual/release-notes/rl-2411.section.md b/nixos/doc/manual/release-notes/rl-2411.section.md
index d821a6e6cc1ff..67e03a1203e1a 100644
--- a/nixos/doc/manual/release-notes/rl-2411.section.md
+++ b/nixos/doc/manual/release-notes/rl-2411.section.md
@@ -36,6 +36,14 @@
   before changing the package to `pkgs.stalwart-mail` in
   [`services.stalwart-mail.package`](#opt-services.stalwart-mail.package).
 
+- `haskell.lib.compose.justStaticExecutables` now disallows references to GHC in the
+  output by default, to alert users to closure size issues caused by
+  [#164630](https://github.com/NixOS/nixpkgs/issues/164630). See ["Packaging
+  Helpers" in the Haskell section of the Nixpkgs
+  manual](https://nixos.org/manual/nixpkgs/unstable/#haskell-packaging-helpers)
+  for information on working around `output '...' is not allowed to refer to
+  the following paths` errors caused by this change.
+
 - The `stalwart-mail` module now uses RocksDB as the default storage backend
   for `stateVersion` ≥ 24.11. (It was previously using SQLite for structured
   data and the filesystem for blobs).
diff --git a/pkgs/development/compilers/ghc/Cabal-3.12-paths-fix-cycle-aarch64-darwin.patch b/pkgs/development/compilers/ghc/Cabal-3.12-paths-fix-cycle-aarch64-darwin.patch
new file mode 100644
index 0000000000000..f094790088c2f
--- /dev/null
+++ b/pkgs/development/compilers/ghc/Cabal-3.12-paths-fix-cycle-aarch64-darwin.patch
@@ -0,0 +1,596 @@
+This patch is based on https://github.com/sternenseemann/cabal/compare/Cabal-v3.12.0.0..e836ef53c1f80bf99a70f9c4ee5976e9f3830215
+and has been postprocessed with `filterdiff --strip=1 --addoldprefix=a/libraries/Cabal/ --addnewprefix=b/libraries/Cabal/`.
+
+Reasoning and explanation of the patch can be found in the comment in the diff for PathsModule.hs below.
+
+diffCabal/src/Distribution/Simple/Build/PathsModule.hs b/Cabal/src/Distribution/Simple/Build/PathsModule.hs
+index 892e5bd38..391f5b130 100644
+--- a/libraries/Cabal/Cabal/src/Distribution/Simple/Build/PathsModule.hs
++++ b/libraries/Cabal/Cabal/src/Distribution/Simple/Build/PathsModule.hs
+@@ -51,6 +51,7 @@ generatePathsModule pkg_descr lbi clbi =
+       , Z.zIsWindows = isWindows
+       , Z.zIsI386 = buildArch == I386
+       , Z.zIsX8664 = buildArch == X86_64
++      , Z.zOr = (||)
+       , Z.zNot = not
+       , Z.zManglePkgName = showPkgName
+       , Z.zPrefix = show flat_prefix
+@@ -60,8 +61,110 @@ generatePathsModule pkg_descr lbi clbi =
+       , Z.zDatadir = zDatadir
+       , Z.zLibexecdir = zLibexecdir
+       , Z.zSysconfdir = zSysconfdir
++      , -- Sadly we can't be cleverer about this – we can't have literals in the template
++        Z.zShouldEmitDataDir = shouldEmit "DataDir"
++      , Z.zShouldEmitLibDir = shouldEmit "LibDir"
++      , Z.zShouldEmitDynLibDir = shouldEmit "DynLibDir"
++      , Z.zShouldEmitLibexecDir = shouldEmit "LibexecDir"
++      , Z.zShouldEmitSysconfDir = shouldEmit "SysconfDir"
++      , Z.zWarning = zWarning
++      , Z.zShouldEmitWarning = zShouldEmitWarning
+       }
+   where
++    -- GHC's NCG backend for aarch64-darwin does not support link-time dead code
++    -- elimination to the extent that NCG does for other targets. Consequently,
++    -- we struggle with unnecessarily retained store path references due to the
++    -- use of `Paths_*` modules – even if `getLibDir` is not used, it'll end up
++    -- in the final library or executables we build.
++    --
++    -- When using a different output for the executables and library, this
++    -- becomes more sinister: The library will contain a reference to the bin
++    -- output and itself due to `getLibDir` and `getBinDir`, but the executables
++    -- will do so, too. Either due to linking dynamically or because the library
++    -- is linked statically into the executable and retains those references.
++    -- Since Nix disallows cyclical references between two outputs, it becomes
++    -- impossible to use the `Paths_*` module and a separate `bin` output for
++    -- aarch64-darwin.
++    --
++    -- The solution we have resorted to for now, is to trim the `Paths_*` module
++    -- dynamically depending on what references *could* be used without causing
++    -- a cyclical reference. That has the effect that any code that would not
++    -- cause a cyclical reference with dead code elimination will compile and
++    -- work for aarch64-darwin. If the code would use a `get*Dir` function that
++    -- has been omitted, this would indicate that the code would have caused a
++    -- cyclical reference anyways.
++    --
++    -- The logic for this makes some pretty big assumptions about installation
++    -- prefixes that probably only hold fully in nixpkgs with
++    -- `haskellPackages.mkDerivation`. Simple uses outside nixpkgs that have
++    -- everything below the same prefix should continue to work as expected,
++    -- though.
++    --
++    -- We assume the following:
++    --
++    -- - flat_prefix is `$out`.
++    -- - flat_libdir etc. are always below `$out`.
++    --
++    -- Since in the normal case due to static linking `$bin` and `$out` will
++    -- have the same references in libraries/executables, we need to either
++    -- prevent usage of `getBinDir` or `getLibDir` to break the cycle in case
++    -- `flat_bindir` is not below `$out`. We have decided to always allow usage
++    -- of `getBinDir`, so `getLibDir` gets dropped if a separate `bin` output is
++    -- used. This has the simple reason that `$out` which contains `flat_libdir`
++    -- tends to be quite big – we would like to have a `bin` output that doesn't
++    -- require keeping that around.
++    pathEmittable :: FilePath -> Bool
++    pathEmittable p
++      -- If the executable installation target is below `$out` the reference
++      -- cycle is within a single output (since libs are installed to `$out`)
++      -- and thus unproblematic. We can use any and all `get*Dir` functions.
++      | flat_prefix `isPrefixOf` flat_bindir = True
++      -- Otherwise, we need to disallow all `get*Dir` functions that would cause
++      -- a reference to `$out` which contains the libraries that would in turn
++      -- reference `$bin`. This always include `flat_libdir` and friends, but
++      -- can also include `flat_datadir` if no separate output for data files is
++      -- used.
++      | otherwise = not (flat_prefix `isPrefixOf` p)
++
++    -- This list maps the "name" of the directory to whether we want to include
++    -- it in the `Paths_*` module or not. `shouldEmit` performs a lookup in this.
++    dirs :: [(String, Bool)]
++    dirs =
++      map
++        (\(name, path) -> (name, pathEmittable path))
++        [ ("LibDir", flat_libdir)
++        , ("DynLibDir", flat_dynlibdir)
++        , ("DataDir", flat_datadir)
++        , ("LibexecDir", flat_libexecdir)
++        , ("SysconfDir", flat_sysconfdir)
++        ]
++
++    shouldEmit :: String -> Bool
++    shouldEmit name =
++      case lookup name dirs of
++        Just b -> b
++        Nothing -> error "panic! BUG in Cabal Paths_ patch for aarch64-darwin, report this at https://github.com/nixos/nixpkgs/issues"
++
++    -- This is a comma separated list of all functions that have been emitted.
++    -- This is included in a GHC warning which will be attached to the `Paths_*`
++    -- module in case we are dropping any `get*Dir` functions that would
++    -- normally exist.
++    --
++    -- TODO: getDataFileName is not accounted for at the moment.
++    omittedFunctions :: String
++    omittedFunctions =
++      intercalate ", " $
++        map (("get" ++) . fst) $
++          filter (not . snd) dirs
++
++    zWarning :: String
++    zWarning =
++      show $
++        "The following functions have been omitted by a nixpkgs-specific patch to Cabal: "
++          ++ omittedFunctions
++    zShouldEmitWarning :: Bool
++    zShouldEmitWarning = any (not . snd) dirs
++
+     supports_cpp = supports_language_pragma
+     supports_rebindable_syntax = ghc_newer_than (mkVersion [7, 0, 1])
+     supports_language_pragma = ghc_newer_than (mkVersion [6, 6, 1])
+diffCabal/src/Distribution/Simple/Build/PathsModule/Z.hs b/Cabal/src/Distribution/Simple/Build/PathsModule/Z.hs
+index 25c924720..a8278675e 100644
+--- a/libraries/Cabal/Cabal/src/Distribution/Simple/Build/PathsModule/Z.hs
++++ b/libraries/Cabal/Cabal/src/Distribution/Simple/Build/PathsModule/Z.hs
+@@ -19,6 +19,14 @@ data Z
+          zDatadir :: FilePath,
+          zLibexecdir :: FilePath,
+          zSysconfdir :: FilePath,
++         zShouldEmitLibDir :: Bool,
++         zShouldEmitDynLibDir :: Bool,
++         zShouldEmitLibexecDir :: Bool,
++         zShouldEmitDataDir :: Bool,
++         zShouldEmitSysconfDir :: Bool,
++         zShouldEmitWarning :: Bool,
++         zWarning :: String,
++         zOr :: (Bool -> Bool -> Bool),
+          zNot :: (Bool -> Bool),
+          zManglePkgName :: (PackageName -> String)}
+     deriving Generic
+@@ -54,10 +62,51 @@ render z_root = execWriter $ do
+   tell "{-# OPTIONS_GHC -w #-}\n"
+   tell "module Paths_"
+   tell (zManglePkgName z_root (zPackageName z_root))
+-  tell " (\n"
++  tell "\n"
++  tell "  "
++  if (zShouldEmitWarning z_root)
++  then do
++    tell "{-# WARNING "
++    tell (zWarning z_root)
++    tell " #-}"
++    return ()
++  else do
++    return ()
++  tell "\n"
++  tell "  (\n"
+   tell "    version,\n"
+-  tell "    getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir,\n"
+-  tell "    getDataFileName, getSysconfDir\n"
++  tell "    getBinDir,\n"
++  if (zOr z_root (zNot z_root (zAbsolute z_root)) (zShouldEmitLibDir z_root))
++  then do
++    tell "    getLibDir,\n"
++    return ()
++  else do
++    return ()
++  if (zOr z_root (zNot z_root (zAbsolute z_root)) (zShouldEmitDynLibDir z_root))
++  then do
++    tell "    getDynLibDir,\n"
++    return ()
++  else do
++    return ()
++  if (zOr z_root (zNot z_root (zAbsolute z_root)) (zShouldEmitLibexecDir z_root))
++  then do
++    tell "    getLibexecDir,\n"
++    return ()
++  else do
++    return ()
++  if (zOr z_root (zNot z_root (zAbsolute z_root)) (zShouldEmitDataDir z_root))
++  then do
++    tell "    getDataFileName,\n"
++    tell "    getDataDir,\n"
++    return ()
++  else do
++    return ()
++  if (zOr z_root (zNot z_root (zAbsolute z_root)) (zShouldEmitSysconfDir z_root))
++  then do
++    tell "    getSysconfDir\n"
++    return ()
++  else do
++    return ()
+   tell "  ) where\n"
+   tell "\n"
+   if (zNot z_root (zAbsolute z_root))
+@@ -106,12 +155,15 @@ render z_root = execWriter $ do
+   tell (zVersionDigits z_root)
+   tell " []\n"
+   tell "\n"
+-  tell "getDataFileName :: FilePath -> IO FilePath\n"
+-  tell "getDataFileName name = do\n"
+-  tell "  dir <- getDataDir\n"
+-  tell "  return (dir `joinFileName` name)\n"
+-  tell "\n"
+-  tell "getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath\n"
++  if (zOr z_root (zNot z_root (zAbsolute z_root)) (zShouldEmitDataDir z_root))
++  then do
++    tell "getDataFileName :: FilePath -> IO FilePath\n"
++    tell "getDataFileName name = do\n"
++    tell "  dir <- getDataDir\n"
++    tell "  return (dir `joinFileName` name)\n"
++    return ()
++  else do
++    return ()
+   tell "\n"
+   let
+     z_var0_function_defs = do
+@@ -139,6 +191,7 @@ render z_root = execWriter $ do
+   tell "\n"
+   if (zRelocatable z_root)
+   then do
++    tell "\n"
+     tell "\n"
+     tell "getPrefixDirReloc :: FilePath -> IO FilePath\n"
+     tell "getPrefixDirReloc dirRel = do\n"
+@@ -148,31 +201,37 @@ render z_root = execWriter $ do
+     tell (zBindir z_root)
+     tell ") `joinFileName` dirRel)\n"
+     tell "\n"
++    tell "getBinDir     :: IO FilePath\n"
+     tell "getBinDir     = catchIO (getEnv \""
+     tell (zManglePkgName z_root (zPackageName z_root))
+     tell "_bindir\")     (\\_ -> getPrefixDirReloc $ "
+     tell (zBindir z_root)
+     tell ")\n"
++    tell "getLibDir     :: IO FilePath\n"
+     tell "getLibDir     = catchIO (getEnv \""
+     tell (zManglePkgName z_root (zPackageName z_root))
+     tell "_libdir\")     (\\_ -> getPrefixDirReloc $ "
+     tell (zLibdir z_root)
+     tell ")\n"
++    tell "getDynLibDir  :: IO FilePath\n"
+     tell "getDynLibDir  = catchIO (getEnv \""
+     tell (zManglePkgName z_root (zPackageName z_root))
+     tell "_dynlibdir\")  (\\_ -> getPrefixDirReloc $ "
+     tell (zDynlibdir z_root)
+     tell ")\n"
++    tell "getDataDir    :: IO FilePath\n"
+     tell "getDataDir    = catchIO (getEnv \""
+     tell (zManglePkgName z_root (zPackageName z_root))
+     tell "_datadir\")    (\\_ -> getPrefixDirReloc $ "
+     tell (zDatadir z_root)
+     tell ")\n"
++    tell "getLibexecDir :: IO FilePath\n"
+     tell "getLibexecDir = catchIO (getEnv \""
+     tell (zManglePkgName z_root (zPackageName z_root))
+     tell "_libexecdir\") (\\_ -> getPrefixDirReloc $ "
+     tell (zLibexecdir z_root)
+     tell ")\n"
++    tell "getSysconfDir :: IO FilePath\n"
+     tell "getSysconfDir = catchIO (getEnv \""
+     tell (zManglePkgName z_root (zPackageName z_root))
+     tell "_sysconfdir\") (\\_ -> getPrefixDirReloc $ "
+@@ -186,72 +245,119 @@ render z_root = execWriter $ do
+     if (zAbsolute z_root)
+     then do
+       tell "\n"
+-      tell "bindir, libdir, dynlibdir, datadir, libexecdir, sysconfdir :: FilePath\n"
++      tell "bindir     :: FilePath\n"
+       tell "bindir     = "
+       tell (zBindir z_root)
+       tell "\n"
+-      tell "libdir     = "
+-      tell (zLibdir z_root)
+-      tell "\n"
+-      tell "dynlibdir  = "
+-      tell (zDynlibdir z_root)
++      tell "getBinDir     :: IO FilePath\n"
++      tell "getBinDir     = catchIO (getEnv \""
++      tell (zManglePkgName z_root (zPackageName z_root))
++      tell "_bindir\")     (\\_ -> return bindir)\n"
+       tell "\n"
+-      tell "datadir    = "
+-      tell (zDatadir z_root)
++      if (zShouldEmitLibDir z_root)
++      then do
++        tell "libdir     :: FilePath\n"
++        tell "libdir     = "
++        tell (zLibdir z_root)
++        tell "\n"
++        tell "getLibDir     :: IO FilePath\n"
++        tell "getLibDir     = catchIO (getEnv \""
++        tell (zManglePkgName z_root (zPackageName z_root))
++        tell "_libdir\")     (\\_ -> return libdir)\n"
++        return ()
++      else do
++        return ()
+       tell "\n"
+-      tell "libexecdir = "
+-      tell (zLibexecdir z_root)
++      if (zShouldEmitDynLibDir z_root)
++      then do
++        tell "dynlibdir  :: FilePath\n"
++        tell "dynlibdir  = "
++        tell (zDynlibdir z_root)
++        tell "\n"
++        tell "getDynLibDir  :: IO FilePath\n"
++        tell "getDynLibDir  = catchIO (getEnv \""
++        tell (zManglePkgName z_root (zPackageName z_root))
++        tell "_dynlibdir\")  (\\_ -> return dynlibdir)\n"
++        return ()
++      else do
++        return ()
+       tell "\n"
+-      tell "sysconfdir = "
+-      tell (zSysconfdir z_root)
++      if (zShouldEmitDataDir z_root)
++      then do
++        tell "datadir    :: FilePath\n"
++        tell "datadir    = "
++        tell (zDatadir z_root)
++        tell "\n"
++        tell "getDataDir    :: IO FilePath\n"
++        tell "getDataDir    = catchIO (getEnv \""
++        tell (zManglePkgName z_root (zPackageName z_root))
++        tell "_datadir\")    (\\_ -> return datadir)\n"
++        return ()
++      else do
++        return ()
+       tell "\n"
++      if (zShouldEmitLibexecDir z_root)
++      then do
++        tell "libexecdir :: FilePath\n"
++        tell "libexecdir = "
++        tell (zLibexecdir z_root)
++        tell "\n"
++        tell "getLibexecDir :: IO FilePath\n"
++        tell "getLibexecDir = catchIO (getEnv \""
++        tell (zManglePkgName z_root (zPackageName z_root))
++        tell "_libexecdir\") (\\_ -> return libexecdir)\n"
++        return ()
++      else do
++        return ()
+       tell "\n"
+-      tell "getBinDir     = catchIO (getEnv \""
+-      tell (zManglePkgName z_root (zPackageName z_root))
+-      tell "_bindir\")     (\\_ -> return bindir)\n"
+-      tell "getLibDir     = catchIO (getEnv \""
+-      tell (zManglePkgName z_root (zPackageName z_root))
+-      tell "_libdir\")     (\\_ -> return libdir)\n"
+-      tell "getDynLibDir  = catchIO (getEnv \""
+-      tell (zManglePkgName z_root (zPackageName z_root))
+-      tell "_dynlibdir\")  (\\_ -> return dynlibdir)\n"
+-      tell "getDataDir    = catchIO (getEnv \""
+-      tell (zManglePkgName z_root (zPackageName z_root))
+-      tell "_datadir\")    (\\_ -> return datadir)\n"
+-      tell "getLibexecDir = catchIO (getEnv \""
+-      tell (zManglePkgName z_root (zPackageName z_root))
+-      tell "_libexecdir\") (\\_ -> return libexecdir)\n"
+-      tell "getSysconfDir = catchIO (getEnv \""
+-      tell (zManglePkgName z_root (zPackageName z_root))
+-      tell "_sysconfdir\") (\\_ -> return sysconfdir)\n"
++      if (zShouldEmitSysconfDir z_root)
++      then do
++        tell "sysconfdir :: FilePath\n"
++        tell "sysconfdir = "
++        tell (zSysconfdir z_root)
++        tell "\n"
++        tell "getSysconfDir :: IO FilePath\n"
++        tell "getSysconfDir = catchIO (getEnv \""
++        tell (zManglePkgName z_root (zPackageName z_root))
++        tell "_sysconfdir\") (\\_ -> return sysconfdir)\n"
++        return ()
++      else do
++        return ()
+       tell "\n"
+       return ()
+     else do
+       if (zIsWindows z_root)
+       then do
++        tell "\n"
+         tell "\n"
+         tell "prefix :: FilePath\n"
+         tell "prefix = "
+         tell (zPrefix z_root)
+         tell "\n"
+         tell "\n"
++        tell "getBinDir     :: IO FilePath\n"
+         tell "getBinDir     = getPrefixDirRel $ "
+         tell (zBindir z_root)
+         tell "\n"
++        tell "getLibDir     :: IO FilePath\n"
+         tell "getLibDir     = "
+         tell (zLibdir z_root)
+         tell "\n"
++        tell "getDynLibDir  :: IO FilePath\n"
+         tell "getDynLibDir  = "
+         tell (zDynlibdir z_root)
+         tell "\n"
++        tell "getDataDir    :: IO FilePath\n"
+         tell "getDataDir    = catchIO (getEnv \""
+         tell (zManglePkgName z_root (zPackageName z_root))
+         tell "_datadir\")    (\\_ -> "
+         tell (zDatadir z_root)
+         tell ")\n"
++        tell "getLibexecDir :: IO FilePath\n"
+         tell "getLibexecDir = "
+         tell (zLibexecdir z_root)
+         tell "\n"
++        tell "getSysconfDir :: IO FilePath\n"
+         tell "getSysconfDir = "
+         tell (zSysconfdir z_root)
+         tell "\n"
+diffcabal-dev-scripts/src/GenPathsModule.hs b/cabal-dev-scripts/src/GenPathsModule.hs
+index 46ef779e2..e9f5e099f 100644
+--- a/libraries/Cabal/cabal-dev-scripts/src/GenPathsModule.hs
++++ b/libraries/Cabal/cabal-dev-scripts/src/GenPathsModule.hs
+@@ -41,6 +41,16 @@ $(capture "decls" [d|
+         , zLibexecdir :: FilePath
+         , zSysconfdir :: FilePath
+ 
++        , zShouldEmitLibDir     :: Bool
++        , zShouldEmitDynLibDir  :: Bool
++        , zShouldEmitLibexecDir :: Bool
++        , zShouldEmitDataDir    :: Bool
++        , zShouldEmitSysconfDir :: Bool
++
++        , zShouldEmitWarning :: Bool
++        , zWarning           :: String
++
++        , zOr                         :: Bool -> Bool -> Bool
+         , zNot                        :: Bool -> Bool
+         , zManglePkgName              :: PackageName -> String
+         }
+difftemplates/Paths_pkg.template.hs b/templates/Paths_pkg.template.hs
+index 8e1e03d27..cc5c86701 100644
+--- a/libraries/Cabal/templates/Paths_pkg.template.hs
++++ b/libraries/Cabal/templates/Paths_pkg.template.hs
+@@ -14,10 +14,31 @@
+ {% endif %}
+ {-# OPTIONS_GHC -fno-warn-missing-import-lists #-}
+ {-# OPTIONS_GHC -w #-}
+-module Paths_{{ manglePkgName packageName }} (
++module Paths_{{ manglePkgName packageName }}
++  {% if shouldEmitWarning %}{-# WARNING {{ warning }} #-}{% endif %}
++  (
+     version,
+-    getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir,
+-    getDataFileName, getSysconfDir
++    getBinDir,
++{# We only care about the absolute case for our emit logic, since only in this
++   case references are incurred. We are not going to hit isWindows and relocatable
++   has no absolute references to begin with.
++#}
++{% if or (not absolute) shouldEmitLibDir %}
++    getLibDir,
++{% endif %}
++{% if or (not absolute) shouldEmitDynLibDir %}
++    getDynLibDir,
++{% endif %}
++{% if or (not absolute) shouldEmitLibexecDir %}
++    getLibexecDir,
++{% endif %}
++{% if or (not absolute) shouldEmitDataDir %}
++    getDataFileName,
++    getDataDir,
++{% endif %}
++{% if or (not absolute) shouldEmitSysconfDir %}
++    getSysconfDir
++{% endif %}
+   ) where
+ 
+ {% if not absolute %}
+@@ -56,12 +77,12 @@ catchIO = Exception.catch
+ version :: Version
+ version = Version {{ versionDigits }} []
+ 
++{% if or (not absolute) shouldEmitDataDir %}
+ getDataFileName :: FilePath -> IO FilePath
+ getDataFileName name = do
+   dir <- getDataDir
+   return (dir `joinFileName` name)
+-
+-getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath
++{% endif %}
+ 
+ {% defblock function_defs %}
+ minusFileName :: FilePath -> String -> FilePath
+@@ -90,48 +111,93 @@ splitFileName p = (reverse (path2++drive), reverse fname)
+ 
+ {% if relocatable %}
+ 
++{# Relocatable can not incur any absolute references, so we can ignore it.
++   Additionally, --enable-relocatable is virtually useless in Nix builds
++#}
++
+ getPrefixDirReloc :: FilePath -> IO FilePath
+ getPrefixDirReloc dirRel = do
+   exePath <- getExecutablePath
+   let (dir,_) = splitFileName exePath
+   return ((dir `minusFileName` {{ bindir }}) `joinFileName` dirRel)
+ 
++getBinDir     :: IO FilePath
+ getBinDir     = catchIO (getEnv "{{ manglePkgName packageName }}_bindir")     (\_ -> getPrefixDirReloc $ {{ bindir }})
++getLibDir     :: IO FilePath
+ getLibDir     = catchIO (getEnv "{{ manglePkgName packageName }}_libdir")     (\_ -> getPrefixDirReloc $ {{ libdir }})
++getDynLibDir  :: IO FilePath
+ getDynLibDir  = catchIO (getEnv "{{ manglePkgName packageName }}_dynlibdir")  (\_ -> getPrefixDirReloc $ {{ dynlibdir }})
++getDataDir    :: IO FilePath
+ getDataDir    = catchIO (getEnv "{{ manglePkgName packageName }}_datadir")    (\_ -> getPrefixDirReloc $ {{ datadir }})
++getLibexecDir :: IO FilePath
+ getLibexecDir = catchIO (getEnv "{{ manglePkgName packageName }}_libexecdir") (\_ -> getPrefixDirReloc $ {{ libexecdir }})
++getSysconfDir :: IO FilePath
+ getSysconfDir = catchIO (getEnv "{{ manglePkgName packageName }}_sysconfdir") (\_ -> getPrefixDirReloc $ {{ sysconfdir }})
+ 
+ {% useblock function_defs %}
+ 
+ {% elif absolute %}
+ 
+-bindir, libdir, dynlibdir, datadir, libexecdir, sysconfdir :: FilePath
++bindir     :: FilePath
+ bindir     = {{ bindir }}
+-libdir     = {{ libdir }}
+-dynlibdir  = {{ dynlibdir }}
+-datadir    = {{ datadir }}
+-libexecdir = {{ libexecdir }}
+-sysconfdir = {{ sysconfdir }}
+-
++getBinDir     :: IO FilePath
+ getBinDir     = catchIO (getEnv "{{ manglePkgName packageName }}_bindir")     (\_ -> return bindir)
++
++{% if shouldEmitLibDir %}
++libdir     :: FilePath
++libdir     = {{ libdir }}
++getLibDir     :: IO FilePath
+ getLibDir     = catchIO (getEnv "{{ manglePkgName packageName }}_libdir")     (\_ -> return libdir)
++{% endif %}
++
++{% if shouldEmitDynLibDir %}
++dynlibdir  :: FilePath
++dynlibdir  = {{ dynlibdir }}
++getDynLibDir  :: IO FilePath
+ getDynLibDir  = catchIO (getEnv "{{ manglePkgName packageName }}_dynlibdir")  (\_ -> return dynlibdir)
++{% endif %}
++
++{% if shouldEmitDataDir %}
++datadir    :: FilePath
++datadir    = {{ datadir }}
++getDataDir    :: IO FilePath
+ getDataDir    = catchIO (getEnv "{{ manglePkgName packageName }}_datadir")    (\_ -> return datadir)
++{% endif %}
++
++{% if shouldEmitLibexecDir %}
++libexecdir :: FilePath
++libexecdir = {{ libexecdir }}
++getLibexecDir :: IO FilePath
+ getLibexecDir = catchIO (getEnv "{{ manglePkgName packageName }}_libexecdir") (\_ -> return libexecdir)
++{% endif %}
++
++{% if shouldEmitSysconfDir %}
++sysconfdir :: FilePath
++sysconfdir = {{ sysconfdir }}
++getSysconfDir :: IO FilePath
+ getSysconfDir = catchIO (getEnv "{{ manglePkgName packageName }}_sysconfdir") (\_ -> return sysconfdir)
++{% endif %}
+ 
+ {% elif isWindows %}
+ 
++{# We are only trying to fix the problem for aarch64-darwin with this patch,
++   so let's ignore Windows which we can reach via pkgsCross, for example.
++#}
++
+ prefix :: FilePath
+ prefix = {{ prefix }}
+ 
++getBinDir     :: IO FilePath
+ getBinDir     = getPrefixDirRel $ {{ bindir }}
++getLibDir     :: IO FilePath
+ getLibDir     = {{ libdir }}
++getDynLibDir  :: IO FilePath
+ getDynLibDir  = {{ dynlibdir }}
++getDataDir    :: IO FilePath
+ getDataDir    = catchIO (getEnv "{{ manglePkgName packageName }}_datadir")    (\_ -> {{ datadir }})
++getLibexecDir :: IO FilePath
+ getLibexecDir = {{ libexecdir }}
++getSysconfDir :: IO FilePath
+ getSysconfDir = {{ sysconfdir }}
+ 
+ getPrefixDirRel :: FilePath -> IO FilePath
diff --git a/pkgs/development/compilers/ghc/common-hadrian.nix b/pkgs/development/compilers/ghc/common-hadrian.nix
index 55cc96dfd3ed9..2ebb552ec6097 100644
--- a/pkgs/development/compilers/ghc/common-hadrian.nix
+++ b/pkgs/development/compilers/ghc/common-hadrian.nix
@@ -177,7 +177,9 @@
           # These cause problems as they're not eliminated by GHC's dead code
           # elimination on aarch64-darwin. (see
           # https://github.com/NixOS/nixpkgs/issues/140774 for details).
-          ./Cabal-at-least-3.6-paths-fix-cycle-aarch64-darwin.patch
+          (if lib.versionOlder version "9.10"
+           then ./Cabal-at-least-3.6-paths-fix-cycle-aarch64-darwin.patch
+           else ./Cabal-3.12-paths-fix-cycle-aarch64-darwin.patch)
         ]
         # Prevents passing --hyperlinked-source to haddock. This is a custom
         # workaround as we wait for this to be configurable via userSettings or
@@ -425,8 +427,8 @@ stdenv.mkDerivation ({
     "--disable-large-address-space"
   ] ++ lib.optionals enableDwarf [
     "--enable-dwarf-unwind"
-    "--with-libdw-includes=${lib.getDev elfutils}/include"
-    "--with-libdw-libraries=${lib.getLib elfutils}/lib"
+    "--with-libdw-includes=${lib.getDev targetPackages.elfutils}/include"
+    "--with-libdw-libraries=${lib.getLib targetPackages.elfutils}/lib"
   ] ++ lib.optionals targetPlatform.isDarwin [
     # Darwin uses llvm-ar. GHC will try to use `-L` with `ar` when it is `llvm-ar`
     # but it doesn’t currently work because Cabal never uses `-L` on Darwin. See:
diff --git a/pkgs/development/haskell-modules/configuration-darwin.nix b/pkgs/development/haskell-modules/configuration-darwin.nix
index 701c86200bd51..79317c9da55f2 100644
--- a/pkgs/development/haskell-modules/configuration-darwin.nix
+++ b/pkgs/development/haskell-modules/configuration-darwin.nix
@@ -110,6 +110,12 @@ self: super: ({
         substituteInPlace System/X509/MacOS.hs --replace security /usr/bin/security
       '' + (drv.postPatch or "");
     }) super.x509-system;
+  crypton-x509-system = overrideCabal (drv:
+    lib.optionalAttrs (!pkgs.stdenv.cc.nativeLibc) {
+      postPatch = ''
+        substituteInPlace System/X509/MacOS.hs --replace security /usr/bin/security
+      '' + (drv.postPatch or "");
+    }) super.crypton-x509-system;
 
   # https://github.com/haskell-foundation/foundation/pull/412
   foundation = dontCheck super.foundation;
@@ -335,6 +341,15 @@ self: super: ({
 
 } // lib.optionalAttrs pkgs.stdenv.isAarch64 {  # aarch64-darwin
 
+  cabal2nix = overrideCabal (old: {
+    postInstall = ''
+      ${old.postInstall or ""}
+      remove-references-to -t ${self.hpack} "$out/bin/cabal2nix"
+      # Note: The `data` output is needed at runtime.
+      remove-references-to -t ${self.distribution-nixpkgs.out} "$out/bin/hackage2nix"
+    '';
+  }) super.cabal2nix;
+
   # https://github.com/fpco/unliftio/issues/87
   unliftio = dontCheck super.unliftio;
   # This is the same issue as above; the rio tests call functions in unliftio
@@ -371,4 +386,12 @@ self: super: ({
   # same
   # https://hydra.nixos.org/build/174540882/nixlog/9
   jacinda = dontCheck super.jacinda;
+
+  # Greater floating point error on x86_64-darwin (!) for some reason
+  # https://github.com/ekmett/ad/issues/113
+  ad = overrideCabal (drv: {
+    testFlags = drv.testFlags or [ ] ++ [
+      "-p" "!/issue-108/"
+    ];
+  }) super.ad;
 })
diff --git a/pkgs/development/haskell-modules/configuration-ghc-9.0.x.nix b/pkgs/development/haskell-modules/configuration-ghc-9.0.x.nix
index cdaa712ecd9aa..45cbd487762b2 100644
--- a/pkgs/development/haskell-modules/configuration-ghc-9.0.x.nix
+++ b/pkgs/development/haskell-modules/configuration-ghc-9.0.x.nix
@@ -86,7 +86,12 @@ self: super: {
   haskell-language-server =  throw "haskell-language-server has dropped support for ghc 9.0 in version 2.4.0.0, please use a newer ghc version or an older nixpkgs version";
 
   # Needs to use ghc-lib due to incompatible GHC
-  ghc-tags = doDistribute (addBuildDepend self.ghc-lib self.ghc-tags_1_6);
+  ghc-tags = doDistribute (addBuildDepend self.ghc-lib self.ghc-tags_1_5);
+
+  # ghc-lib >= 9.6 and friends no longer build with GHC 9.0
+  ghc-lib-parser = doDistribute self.ghc-lib-parser_9_2_8_20230729;
+  ghc-lib-parser-ex = doDistribute self.ghc-lib-parser-ex_9_2_1_1;
+  ghc-lib = doDistribute self.ghc-lib_9_2_8_20230729;
 
   # Test suite sometimes segfaults with GHC 9.0.1 and 9.0.2
   # https://github.com/ekmett/reflection/issues/51
diff --git a/pkgs/development/haskell-modules/configuration-ghc-9.6.x.nix b/pkgs/development/haskell-modules/configuration-ghc-9.6.x.nix
index 14084bcf03d54..4edc24f10add2 100644
--- a/pkgs/development/haskell-modules/configuration-ghc-9.6.x.nix
+++ b/pkgs/development/haskell-modules/configuration-ghc-9.6.x.nix
@@ -69,6 +69,9 @@ self: super: {
   # https://github.com/mokus0/th-extras/pull/21
   th-extras = doJailbreak super.th-extras;
 
+  # not in Stackage, needs to match ghc-lib
+  ghc-tags = doDistribute self.ghc-tags_1_7;
+
   #
   # Too strict bounds without upstream fix
   #
diff --git a/pkgs/development/haskell-modules/configuration-ghc-9.8.x.nix b/pkgs/development/haskell-modules/configuration-ghc-9.8.x.nix
index 5248e2d3ab918..ba0f6c31a216e 100644
--- a/pkgs/development/haskell-modules/configuration-ghc-9.8.x.nix
+++ b/pkgs/development/haskell-modules/configuration-ghc-9.8.x.nix
@@ -55,7 +55,7 @@ self: super: {
   th-abstraction = doDistribute self.th-abstraction_0_7_0_0;
   ghc-lib-parser = doDistribute self.ghc-lib-parser_9_8_2_20240223;
   ghc-lib-parser-ex = doDistribute self.ghc-lib-parser-ex_9_8_0_2;
-  ghc-lib = doDistribute self.ghc-lib_9_10_1_20240511;
+  ghc-lib = doDistribute self.ghc-lib_9_8_2_20240223;
   megaparsec = doDistribute self.megaparsec_9_6_1;
   # TODO: remove when aeson updates or launches a revision
   # see https://github.com/haskell/aeson/issues/1089 and https://github.com/haskell/aeson/pulls/1088
diff --git a/pkgs/development/haskell-modules/configuration-hackage2nix/broken.yaml b/pkgs/development/haskell-modules/configuration-hackage2nix/broken.yaml
index d97a98caf77fc..fe1e0b579ba38 100644
--- a/pkgs/development/haskell-modules/configuration-hackage2nix/broken.yaml
+++ b/pkgs/development/haskell-modules/configuration-hackage2nix/broken.yaml
@@ -2014,7 +2014,6 @@ broken-packages:
   - ghc-syb # failure in job https://hydra.nixos.org/build/233236783 at 2023-09-02
   - ghc-syb-utils # failure in job https://hydra.nixos.org/build/233229196 at 2023-09-02
   - ghc-symbol # failure in job https://hydra.nixos.org/build/252710738 at 2024-03-16
-  - ghc-tags # failure in job https://hydra.nixos.org/build/252730131 at 2024-03-16
   - ghc-tags-plugin # failure in job https://hydra.nixos.org/build/233229916 at 2023-09-02
   - ghc-time-alloc-prof # failure in job https://hydra.nixos.org/build/233242289 at 2023-09-02
   - ghc-usage # failure in job https://hydra.nixos.org/build/233199565 at 2023-09-02
diff --git a/pkgs/development/haskell-modules/configuration-hackage2nix/main.yaml b/pkgs/development/haskell-modules/configuration-hackage2nix/main.yaml
index d5be691e5969f..e3ea841b3ece3 100644
--- a/pkgs/development/haskell-modules/configuration-hackage2nix/main.yaml
+++ b/pkgs/development/haskell-modules/configuration-hackage2nix/main.yaml
@@ -66,10 +66,11 @@ extra-packages:
   - ghc-exactprint == 1.5.*             # 2023-03-30: needed for GHC == 9.2
   - ghc-exactprint == 1.6.*             # 2023-03-30: needed for GHC == 9.4
   - ghc-exactprint == 1.8.*             # 2024-05-20: needed for GHC == 9.8
-  - ghc-lib == 9.2.*                    # 2022-02-17: preserve for GHC 9.2
-  - ghc-lib-parser == 9.2.*             # 2022-02-17: preserve for GHC 9.2
+  - ghc-lib == 9.2.*                    # 2022-02-17: preserve for GHC 8.10, 9.0
+  - ghc-lib == 9.8.*                    # 2024-05-19: preserve for GHC 9.8
+  - ghc-lib-parser == 9.2.*             # 2022-02-17: preserve for GHC 8.10, 9.0
   - ghc-lib-parser == 9.8.*             # 2024-05-19: preserve for GHC 9.8
-  - ghc-lib-parser-ex == 9.2.*          # 2022-07-13: preserve for GHC 9.2
+  - ghc-lib-parser-ex == 9.2.*          # 2022-07-13: preserve for GHC 8.10, 9.0
   - ghc-lib-parser-ex == 9.8.*          # 2024-05-19: preserve for GHC 9.8
   - ghc-syntax-highlighter == 0.0.10.*  # 2023-11-20:
   - gi-soup == 2.4.28                   # 2023-04-05: the last version to support libsoup-2.4 (and thus be compatible with our other gi- packages)
@@ -118,6 +119,7 @@ extra-packages:
   - retrie < 1.2.0.0                    # 2022-12-30: required for hls on ghc < 9.2
   - ghc-tags == 1.5.*                   # 2023-02-18: preserve for ghc-lib == 9.2.*
   - ghc-tags == 1.6.*                   # 2023-02-18: preserve for ghc-lib == 9.4.*
+  - ghc-tags == 1.7.*                   # 2023-02-18: preserve for ghc-lib == 9.6.*
   - shake-cabal < 0.2.2.3               # 2023-07-01: last version to support Cabal 3.6.*
   - algebraic-graphs < 0.7              # 2023-08-14: Needed for building weeder < 2.6.0
   - fuzzyset == 0.2.4                   # 2023-12-20: Needed for building postgrest > 10
@@ -128,6 +130,57 @@ extra-packages:
 package-maintainers:
   abbradar:
     - Agda
+  alexfmpe:
+    - aeson-gadt-th
+    - basic-sop
+    - cli-extras
+    - cli-git
+    - cli-nix
+    - commutative-semigroups
+    - constraints-extras
+    - dependent-map
+    - dependent-monoidal-map
+    - dependent-sum
+    - dependent-sum-aeson-orphans
+    - dependent-sum-template
+    - gargoyle
+    - gargoyle-postgresql
+    - gargoyle-postgresql-connect
+    - gargoyle-postgresql-nix
+    - generics-sop
+    - ghcjs-base
+    - ghcjs-dom
+    - ghcjs-dom-hello
+    - ghcjs-dom-javascript
+    - haveibeenpwned
+    - jsaddle
+    - jsaddle-clib
+    - jsaddle-dom
+    - jsaddle-hello
+    - jsaddle-warp
+    - jsaddle-webkit2gtk
+    - jsaddle-wkwebview
+    - json-sop
+    - large-generics
+    - large-records
+    - lens-sop
+    - linux-namespaces
+    - monoidal-containers
+    - nix-thunk
+    - patch
+    - proto-lens-arbitrary
+    - proto3-suite
+    - proto3-wire
+    - records-sop
+    - reflex
+    - reflex-dom
+    - reflex-dom-core
+    - reflex-gadt-api
+    - universe
+    - universe-some
+    - vessel
+    - warp
+    - which
   Anton-Latukha:
     - hnix
     - hnix-store-core
diff --git a/pkgs/development/haskell-modules/configuration-nix.nix b/pkgs/development/haskell-modules/configuration-nix.nix
index 6b49a4ec25aa4..fda739cd25ad8 100644
--- a/pkgs/development/haskell-modules/configuration-nix.nix
+++ b/pkgs/development/haskell-modules/configuration-nix.nix
@@ -770,9 +770,12 @@ self: super: builtins.intersectAttrs super {
     preInstall = drv.preInstall or "" + ''
       installTargets="install"
       installFlagsArray+=(
-        "BUILDER=:"
         "PREFIX="
         "DESTDIR=$out"
+        # Prevent Makefile from calling cabal/Setup again
+        "BUILDER=:"
+        # Make Haskell build dependencies available
+        "GHC=${self.buildHaskellPackages.ghc.targetPrefix}ghc -global-package-db -package-db $setupPackageConfDir"
       )
     '';
     installPhase = null;
@@ -973,7 +976,7 @@ self: super: builtins.intersectAttrs super {
     preCheck = ''
       export HOME=$TMPDIR/home
       export PATH=$PWD/dist/build/ihaskell:$PATH
-      export GHC_PACKAGE_PATH=$PWD/dist/package.conf.inplace/:$GHC_PACKAGE_PATH
+      export NIX_GHC_PACKAGE_PATH_FOR_TEST=$PWD/dist/package.conf.inplace/:$packageConfDir:
     '';
   }) super.ihaskell;
 
diff --git a/pkgs/development/haskell-modules/generic-builder.nix b/pkgs/development/haskell-modules/generic-builder.nix
index f9acdd0f4a27b..5ba364311dd03 100644
--- a/pkgs/development/haskell-modules/generic-builder.nix
+++ b/pkgs/development/haskell-modules/generic-builder.nix
@@ -110,6 +110,28 @@ in
   # build products from that prior build as a starting point for accelerating
   # this build
 , previousIntermediates ? null
+  # References to these store paths are forbidden in the produced output.
+, disallowedRequisites ? []
+  # Whether to allow the produced output to refer to `ghc`.
+  #
+  # This is used by `haskell.lib.justStaticExecutables` to help prevent static
+  # Haskell binaries from having erroneous dependencies on GHC.
+  #
+  # Generated `Paths_*` modules include paths for the runtime library
+  # directory (and similar) of the package being built. If the `Paths_*`
+  # module is imported, this creates a dependency from the static binary
+  # being built to the _library_ being built (which is dynamically linked
+  # and depends on the GHC used to build it).
+  #
+  # To avoid this:
+  # 1. Build the impacted derivation.
+  # 2. Run `strings` on the built binary of the impacted derivation to
+  #    locate the store paths it depends on.
+  # 3. Add `remove-references-to -t ${bad-store-path-in-binary}` to the
+  #    impacted derivation's `postInstall`.
+  #
+  # See: https://github.com/NixOS/nixpkgs/issues/164630
+, disallowGhcReference ? false
 , # Cabal 3.8 which is shipped by default for GHC >= 9.3 always calls
   # `pkg-config --libs --static` as part of the configure step. This requires
   # Requires.private dependencies of pkg-config dependencies to be present in
@@ -370,6 +392,34 @@ let
   '';
 
   intermediatesDir = "share/haskell/${ghc.version}/${pname}-${version}/dist";
+
+  # This is a script suitable for --test-wrapper of Setup.hs' test command
+  # (https://cabal.readthedocs.io/en/3.12/setup-commands.html#cmdoption-runhaskell-Setup.hs-test-test-wrapper).
+  # We use it to set some environment variables that the test suite may need,
+  # e.g. GHC_PACKAGE_PATH to invoke GHC(i) at runtime with build dependencies
+  # available. See the comment accompanying checkPhase below on how to customize
+  # this behavior. We need to use a wrapper script since Cabal forbids setting
+  # certain environment variables since they can alter GHC's behavior (e.g.
+  # GHC_PACKAGE_PATH) and cause failures. While building, Cabal will set
+  # GHC_ENVIRONMENT to make the packages picked at configure time available to
+  # GHC, but unfortunately not at test time. The test wrapper script will be
+  # executed after such environment checks, so we can take some liberties which
+  # is unproblematic since we know our synthetic package db matches what Cabal
+  # will see at configure time exactly. See also
+  # <https://github.com/haskell/cabal/issues/7792>.
+  testWrapperScript = buildPackages.writeShellScript
+    "haskell-generic-builder-test-wrapper.sh"
+    ''
+      set -eu
+
+      # We expect this to be either empty or set by checkPhase
+      if [[ -n "''${NIX_GHC_PACKAGE_PATH_FOR_TEST}" ]]; then
+        export GHC_PACKAGE_PATH="''${NIX_GHC_PACKAGE_PATH_FOR_TEST}"
+      fi
+
+      exec "$@"
+    '';
+
 in lib.fix (drv:
 
 stdenv.mkDerivation ({
@@ -528,8 +578,6 @@ stdenv.mkDerivation ({
   configurePhase = ''
     runHook preConfigure
 
-    unset GHC_PACKAGE_PATH      # Cabal complains if this variable is set during configure.
-
     echo configureFlags: $configureFlags
     ${setupCommand} configure $configureFlags 2>&1 | ${coreutils}/bin/tee "$NIX_BUILD_TOP/cabal-configure.log"
     ${lib.optionalString (!allowInconsistentDependencies) ''
@@ -538,7 +586,6 @@ stdenv.mkDerivation ({
         exit 1
       fi
     ''}
-    export GHC_PACKAGE_PATH="$packageConfDir:"
 
     runHook postConfigure
   '';
@@ -565,12 +612,22 @@ stdenv.mkDerivation ({
   # Run test suite(s) and pass `checkFlags` as well as `checkFlagsArray`.
   # `testFlags` are added to `checkFlagsArray` each prefixed with
   # `--test-option`, so Cabal passes it to the underlying test suite binary.
+  #
+  # We also take care of setting GHC_PACKAGE_PATH during test suite execution,
+  # so it can run GHC(i) with build dependencies available:
+  # - If NIX_GHC_PACKAGE_PATH_FOR_TEST is set, it become the value of GHC_PACKAGE_PATH
+  #   while the test suite is executed.
+  # - If it is empty, it'll be unset during test suite execution.
+  # - Otherwise GHC_PACKAGE_PATH will have the package db used for configuring
+  #   plus GHC's core packages.
   checkPhase = ''
     runHook preCheck
     checkFlagsArray+=(
       "--show-details=streaming"
+      "--test-wrapper=${testWrapperScript}"
       ${lib.escapeShellArgs (builtins.map (opt: "--test-option=${opt}") testFlags)}
     )
+    export NIX_GHC_PACKAGE_PATH_FOR_TEST="''${NIX_GHC_PACKAGE_PATH_FOR_TEST:-$packageConfDir:}"
     ${setupCommand} test ${testTarget} $checkFlags ''${checkFlagsArray:+"''${checkFlagsArray[@]}"}
     runHook postCheck
   '';
@@ -647,7 +704,7 @@ stdenv.mkDerivation ({
 
   passthru = passthru // rec {
 
-    inherit pname version;
+    inherit pname version disallowGhcReference;
 
     compiler = ghc;
 
@@ -808,10 +865,19 @@ stdenv.mkDerivation ({
 // optionalAttrs (args ? dontStrip)              { inherit dontStrip; }
 // optionalAttrs (postPhases != [])              { inherit postPhases; }
 // optionalAttrs (stdenv.buildPlatform.libc == "glibc"){ LOCALE_ARCHIVE = "${glibcLocales}/lib/locale/locale-archive"; }
+// optionalAttrs (disallowedRequisites != [] || disallowGhcReference) {
+  disallowedRequisites =
+    disallowedRequisites
+    ++ (
+      if disallowGhcReference
+      then [ghc]
+      else []
+    );
+}
 
 # Implicit pointer to integer conversions are errors by default since clang 15.
 # Works around https://gitlab.haskell.org/ghc/ghc/-/issues/23456.
-// lib.optionalAttrs (stdenv.hasCC && stdenv.cc.isClang) {
+// optionalAttrs (stdenv.hasCC && stdenv.cc.isClang) {
   NIX_CFLAGS_COMPILE = "-Wno-error=int-conversion";
 }
 )
diff --git a/pkgs/development/haskell-modules/hackage-packages.nix b/pkgs/development/haskell-modules/hackage-packages.nix
index 7496c31cd5601..59af7cdf0e59e 100644
--- a/pkgs/development/haskell-modules/hackage-packages.nix
+++ b/pkgs/development/haskell-modules/hackage-packages.nix
@@ -26537,6 +26537,7 @@ self: {
        description = "Derivation of Aeson instances for GADTs";
        license = lib.licenses.bsd3;
        mainProgram = "readme";
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "aeson-generic-compat" = callPackage
@@ -46689,6 +46690,7 @@ self: {
        ];
        description = "Basic examples and functions for generics-sop";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "basics" = callPackage
@@ -67187,6 +67189,7 @@ self: {
        ];
        description = "Miscellaneous utilities for building and working with command line interfaces";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "cli-git" = callPackage
@@ -67203,6 +67206,7 @@ self: {
        ];
        description = "Bindings to the git command-line interface";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "cli-nix" = callPackage
@@ -67219,6 +67223,7 @@ self: {
        ];
        description = "Bindings to the nix command-line interface";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "cli-setup" = callPackage
@@ -70705,6 +70710,7 @@ self: {
        libraryHaskellDepends = [ base containers ];
        description = "Commutative semigroups";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "commutative-semigroups_0_2_0_1" = callPackage
@@ -70717,6 +70723,7 @@ self: {
        description = "Commutative semigroups";
        license = lib.licenses.bsd3;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "comonad" = callPackage
@@ -74500,6 +74507,7 @@ self: {
        description = "Utility package for constraints";
        license = lib.licenses.bsd3;
        mainProgram = "readme";
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "constrictor" = callPackage
@@ -86484,6 +86492,7 @@ self: {
        description = "Dependent finite maps (partial dependent products)";
        license = "unknown";
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "dependent-map" = callPackage
@@ -86501,6 +86510,7 @@ self: {
        ];
        description = "Dependent finite maps (partial dependent products)";
        license = "unknown";
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "dependent-monoidal-map" = callPackage
@@ -86517,6 +86527,7 @@ self: {
        ];
        description = "Dependent map that uses semigroup mappend";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "dependent-state" = callPackage
@@ -86543,6 +86554,7 @@ self: {
        description = "Dependent sum type";
        license = lib.licenses.publicDomain;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "dependent-sum" = callPackage
@@ -86556,6 +86568,7 @@ self: {
        libraryHaskellDepends = [ base constraints-extras some ];
        description = "Dependent sum type";
        license = lib.licenses.publicDomain;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "dependent-sum-aeson-orphans" = callPackage
@@ -86572,6 +86585,7 @@ self: {
        ];
        description = "JSON instances for DSum, DMap, and Some";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "dependent-sum-template" = callPackage
@@ -86588,6 +86602,7 @@ self: {
        testHaskellDepends = [ base constraints-extras dependent-sum ];
        description = "Template Haskell code to generate instances of classes in dependent-sum package";
        license = lib.licenses.publicDomain;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "dependent-sum-template_0_2_0_1" = callPackage
@@ -86609,6 +86624,7 @@ self: {
        description = "Template Haskell code to generate instances of classes in some package";
        license = lib.licenses.publicDomain;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "depends" = callPackage
@@ -115749,6 +115765,7 @@ self: {
        ];
        description = "Automatically spin up and spin down local daemons";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "gargoyle-postgresql" = callPackage
@@ -115770,6 +115787,7 @@ self: {
        ];
        description = "Manage PostgreSQL servers with gargoyle";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "gargoyle-postgresql-connect" = callPackage
@@ -115787,6 +115805,7 @@ self: {
        ];
        description = "Connect to gargoyle-managed postgresql instances";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "gargoyle-postgresql-nix" = callPackage
@@ -115807,6 +115826,7 @@ self: {
        ];
        description = "Manage PostgreSQL servers with gargoyle and nix";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "garlic-bread" = callPackage
@@ -117516,6 +117536,7 @@ self: {
        ];
        description = "Generic Programming using True Sums of Products";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "generics-sop_0_5_1_4" = callPackage
@@ -117538,6 +117559,7 @@ self: {
        description = "Generic Programming using True Sums of Products";
        license = lib.licenses.bsd3;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "generics-sop-lens" = callPackage
@@ -119906,6 +119928,28 @@ self: {
        license = lib.licenses.bsd3;
      }) {};
 
+  "ghc-lib_9_8_2_20240223" = callPackage
+    ({ mkDerivation, alex, array, base, binary, bytestring, containers
+     , deepseq, directory, exceptions, filepath, ghc-lib-parser
+     , ghc-prim, happy, hpc, parsec, pretty, process, rts
+     , semaphore-compat, stm, time, transformers, unix
+     }:
+     mkDerivation {
+       pname = "ghc-lib";
+       version = "9.8.2.20240223";
+       sha256 = "12lmk3ipd1pyiwzmnb0zgbw86yy7mhsy530dnackwidg3ww07nia";
+       enableSeparateDataOutput = true;
+       libraryHaskellDepends = [
+         array base binary bytestring containers deepseq directory
+         exceptions filepath ghc-lib-parser ghc-prim hpc parsec pretty
+         process rts semaphore-compat stm time transformers unix
+       ];
+       libraryToolDepends = [ alex happy ];
+       description = "The GHC API, decoupled from GHC versions";
+       license = lib.licenses.bsd3;
+       hydraPlatforms = lib.platforms.none;
+     }) {};
+
   "ghc-lib_9_10_1_20240511" = callPackage
     ({ mkDerivation, alex, array, base, binary, bytestring, containers
      , deepseq, directory, exceptions, filepath, ghc-lib-parser
@@ -120633,7 +120677,6 @@ self: {
        license = lib.licenses.mpl20;
        hydraPlatforms = lib.platforms.none;
        mainProgram = "ghc-tags";
-       broken = true;
      }) {};
 
   "ghc-tags_1_6" = callPackage
@@ -120657,7 +120700,29 @@ self: {
        license = lib.licenses.mpl20;
        hydraPlatforms = lib.platforms.none;
        mainProgram = "ghc-tags";
-       broken = true;
+     }) {};
+
+  "ghc-tags_1_7" = callPackage
+    ({ mkDerivation, aeson, async, attoparsec, base, bytestring
+     , containers, deepseq, directory, filepath, ghc, ghc-boot
+     , ghc-paths, optparse-applicative, process, stm, temporary, text
+     , time, vector, yaml
+     }:
+     mkDerivation {
+       pname = "ghc-tags";
+       version = "1.7";
+       sha256 = "17189yi1zffgcdwx0nb6n4pbv3jhfajhfnag84fnqwy4kbvl5ma4";
+       isLibrary = false;
+       isExecutable = true;
+       executableHaskellDepends = [
+         aeson async attoparsec base bytestring containers deepseq directory
+         filepath ghc ghc-boot ghc-paths optparse-applicative process stm
+         temporary text time vector yaml
+       ];
+       description = "Utility for generating ctags and etags with GHC API";
+       license = lib.licenses.mpl20;
+       hydraPlatforms = lib.platforms.none;
+       mainProgram = "ghc-tags";
      }) {};
 
   "ghc-tags" = callPackage
@@ -120679,9 +120744,7 @@ self: {
        ];
        description = "Utility for generating ctags and etags with GHC API";
        license = lib.licenses.mpl20;
-       hydraPlatforms = lib.platforms.none;
        mainProgram = "ghc-tags";
-       broken = true;
      }) {};
 
   "ghc-tags-core" = callPackage
@@ -121290,6 +121353,7 @@ self: {
        sha256 = "1cx9jqpbr6b30qckp2zpsfk3swa58snjb79pq0l6485nvrxa9mls";
        description = "base library for GHCJS";
        license = lib.licenses.mit;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "ghcjs-base-stub" = callPackage
@@ -121336,6 +121400,7 @@ self: {
        ];
        description = "DOM library that supports both GHCJS and GHC";
        license = lib.licenses.mit;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "ghcjs-dom-hello" = callPackage
@@ -121358,6 +121423,7 @@ self: {
        description = "GHCJS DOM Hello World, an example package";
        license = lib.licenses.mit;
        badPlatforms = lib.platforms.darwin;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "ghcjs-dom-javascript" = callPackage
@@ -121369,6 +121435,7 @@ self: {
        description = "DOM library using JSFFI and GHCJS";
        license = lib.licenses.mit;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
        broken = true;
      }) {};
 
@@ -144055,6 +144122,7 @@ self: {
        description = "Library for checking for weak/compromised passwords";
        license = lib.licenses.bsd3;
        mainProgram = "readme";
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "haven" = callPackage
@@ -178568,6 +178636,7 @@ self: {
        ];
        description = "Interface for JavaScript that works with GHCJS and GHC";
        license = lib.licenses.mit;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "jsaddle-clib" = callPackage
@@ -178583,6 +178652,7 @@ self: {
        ];
        description = "Interface for JavaScript that works with GHCJS and GHC";
        license = lib.licenses.mit;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "jsaddle-dom" = callPackage
@@ -178598,6 +178668,7 @@ self: {
        ];
        description = "DOM library that uses jsaddle to support both GHCJS and GHC";
        license = lib.licenses.mit;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "jsaddle-hello" = callPackage
@@ -178618,6 +178689,7 @@ self: {
        description = "JSaddle Hello World, an example package";
        license = lib.licenses.mit;
        badPlatforms = lib.platforms.darwin;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "jsaddle-warp" = callPackage
@@ -178640,7 +178712,9 @@ self: {
        ];
        description = "Interface for JavaScript that works with GHCJS and GHC";
        license = lib.licenses.mit;
-       maintainers = [ lib.maintainers.maralorn ];
+       maintainers = [
+         lib.maintainers.alexfmpe lib.maintainers.maralorn
+       ];
      }) {};
 
   "jsaddle-webkit2gtk" = callPackage
@@ -178661,6 +178735,7 @@ self: {
        description = "Interface for JavaScript that works with GHCJS and GHC";
        license = lib.licenses.mit;
        badPlatforms = lib.platforms.darwin;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "jsaddle-webkitgtk" = callPackage
@@ -178691,6 +178766,7 @@ self: {
        description = "Interface for JavaScript that works with GHCJS and GHC";
        license = lib.licenses.mit;
        platforms = lib.platforms.darwin;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "jsc" = callPackage
@@ -179460,6 +179536,7 @@ self: {
        description = "Generics JSON (de)serialization using generics-sop";
        license = lib.licenses.bsd3;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "json-spec" = callPackage
@@ -186940,6 +187017,7 @@ self: {
        ];
        description = "Generic programming API for large-records and large-anon";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "large-hashable" = callPackage
@@ -186999,6 +187077,7 @@ self: {
        description = "Efficient compilation for large records, linear in the size of the record";
        license = lib.licenses.bsd3;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
        broken = true;
      }) {};
 
@@ -189081,6 +189160,7 @@ self: {
        description = "Computing lenses generically using generics-sop";
        license = lib.licenses.bsd3;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
        broken = true;
      }) {};
 
@@ -192499,6 +192579,7 @@ self: {
        description = "Work with linux namespaces: create new or enter existing ones";
        license = lib.licenses.bsd3;
        platforms = lib.platforms.linux;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "linux-perf" = callPackage
@@ -209002,6 +209083,7 @@ self: {
        ];
        description = "Containers with monoidal accumulation";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "monoidal-functors" = callPackage
@@ -218837,6 +218919,7 @@ self: {
        description = "Lightweight dependency management with Nix";
        license = lib.licenses.bsd3;
        mainProgram = "nix-thunk";
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "nix-tools" = callPackage
@@ -231253,6 +231336,7 @@ self: {
        testHaskellDepends = [ base containers hedgehog HUnit ];
        description = "Data structures for describing changes to other data structures";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "patch-combinators" = callPackage
@@ -247283,6 +247367,7 @@ self: {
        ];
        description = "Arbitrary instances for proto-lens";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "proto-lens-combinators" = callPackage
@@ -247470,6 +247555,7 @@ self: {
        description = "A higher-level API to the proto3-wire library";
        license = lib.licenses.asl20;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "proto3-wire" = callPackage
@@ -247495,6 +247581,7 @@ self: {
        benchmarkHaskellDepends = [ base bytestring criterion random ];
        description = "A low-level implementation of the Protocol Buffers (version 3) wire format";
        license = lib.licenses.asl20;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "protobuf" = callPackage
@@ -255541,6 +255628,7 @@ self: {
        ];
        description = "Record subtyping and record utilities with generics-sop";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "records-th" = callPackage
@@ -256446,6 +256534,7 @@ self: {
        ];
        description = "Higher-order Functional Reactive Programming";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "reflex-animation" = callPackage
@@ -256549,7 +256638,9 @@ self: {
        ];
        description = "Functional Reactive Web Apps with Reflex";
        license = lib.licenses.bsd3;
-       maintainers = [ lib.maintainers.maralorn ];
+       maintainers = [
+         lib.maintainers.alexfmpe lib.maintainers.maralorn
+       ];
      }) {};
 
   "reflex-dom-ace" = callPackage
@@ -256648,6 +256739,7 @@ self: {
        description = "Functional Reactive Web Apps with Reflex";
        license = lib.licenses.bsd3;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
        broken = true;
      }) {chrome-test-utils = null;};
 
@@ -256858,6 +256950,7 @@ self: {
        license = lib.licenses.bsd3;
        hydraPlatforms = lib.platforms.none;
        mainProgram = "readme";
+       maintainers = [ lib.maintainers.alexfmpe ];
        broken = true;
      }) {};
 
@@ -317176,6 +317269,7 @@ self: {
        ];
        description = "A class for finite and recursively enumerable types";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "universe_1_2_3" = callPackage
@@ -317193,6 +317287,7 @@ self: {
        description = "A class for finite and recursively enumerable types";
        license = lib.licenses.bsd3;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "universe-base" = callPackage
@@ -317354,6 +317449,7 @@ self: {
        testHaskellDepends = [ base some template-haskell universe-base ];
        description = "Universe instances for Some from some";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "universe-some_1_2_2" = callPackage
@@ -317372,6 +317468,7 @@ self: {
        description = "Universe instances for Some from some";
        license = lib.licenses.bsd3;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "universe-th" = callPackage
@@ -322333,6 +322430,7 @@ self: {
        description = "Functor-parametric containers";
        license = lib.licenses.bsd3;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
        broken = true;
      }) {};
 
@@ -326025,6 +326123,7 @@ self: {
        description = "A fast, light-weight web server for WAI applications";
        license = lib.licenses.mit;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "warp" = callPackage
@@ -326059,6 +326158,7 @@ self: {
        ];
        description = "A fast, light-weight web server for WAI applications";
        license = lib.licenses.mit;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "warp_3_4_1" = callPackage
@@ -326096,6 +326196,7 @@ self: {
        description = "A fast, light-weight web server for WAI applications";
        license = lib.licenses.mit;
        hydraPlatforms = lib.platforms.none;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "warp-dynamic" = callPackage
@@ -328656,6 +328757,7 @@ self: {
        libraryHaskellDepends = [ base shelly template-haskell text ];
        description = "Determine the full path to an executable";
        license = lib.licenses.bsd3;
+       maintainers = [ lib.maintainers.alexfmpe ];
      }) {};
 
   "while-lang-parser" = callPackage
diff --git a/pkgs/development/haskell-modules/lib/compose.nix b/pkgs/development/haskell-modules/lib/compose.nix
index 09cee08b91c1f..492091ef35fc2 100644
--- a/pkgs/development/haskell-modules/lib/compose.nix
+++ b/pkgs/development/haskell-modules/lib/compose.nix
@@ -290,7 +290,7 @@ rec {
   /* link executables statically against haskell libs to reduce
      closure size
    */
-  justStaticExecutables = overrideCabal (drv: {
+ justStaticExecutables = overrideCabal (drv: {
     enableSharedExecutables = false;
     enableLibraryProfiling = false;
     isLibrary = false;
@@ -300,6 +300,7 @@ rec {
       # Remove every directory which could have links to other store paths.
       rm -rf $out/lib $out/nix-support $out/share/doc
     '';
+    disallowGhcReference = true;
   });
 
   /* Build a source distribution tarball instead of using the source files
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 6b01555699100..267ced487062b 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -20572,7 +20572,7 @@ with pkgs;
 
   elfio = callPackage ../development/libraries/elfio { };
 
-  emanote = haskell.lib.compose.justStaticExecutables haskellPackages.emanote;
+  emanote = haskellPackages.emanote;
 
   enchant2 = callPackage ../development/libraries/enchant/2.x.nix { };
   enchant = enchant2;
diff --git a/pkgs/top-level/release-haskell.nix b/pkgs/top-level/release-haskell.nix
index a778583172b2e..31f8f501904dd 100644
--- a/pkgs/top-level/release-haskell.nix
+++ b/pkgs/top-level/release-haskell.nix
@@ -502,28 +502,18 @@ let
       # package sets (like Cabal, jailbreak-cabal) are
       # working as expected.
       cabal-install = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       Cabal_3_10_3_0 = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       Cabal-syntax_3_10_3_0 = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       cabal2nix = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       cabal2nix-unstable = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       funcmp = released;
@@ -536,26 +526,18 @@ let
         compilerNames.ghc9101
       ] released;
       hoogle = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       hlint = lib.subtractLists [
         compilerNames.ghc902
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       hpack = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       hsdns = released;
       jailbreak-cabal = released;
       language-nix = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       large-hashable = [
@@ -563,8 +545,6 @@ let
       ];
       nix-paths = released;
       titlecase = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       ghc-api-compat = [
@@ -575,43 +555,30 @@ let
         compilerNames.ghc8107
       ];
       ghc-lib = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       ghc-lib-parser = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       ghc-lib-parser-ex = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       ghc-source-gen = [
         # Feel free to remove these as they break,
-        # ghc-source-gen currently doesn't support GHC 9.4
         compilerNames.ghc8107
         compilerNames.ghc902
         compilerNames.ghc928
       ];
-      # broken on 2024-03-16
-      # ghc-tags = lib.subtractLists [
-      #   compilerNames.ghc981
-      #   compilerNames.ghc982
-      # ] released;
+      ghc-tags = lib.subtractLists [
+        compilerNames.ghc9101
+      ] released;
       hashable = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
       primitive = lib.subtractLists [
         compilerNames.ghc9101
       ] released;
       weeder = lib.subtractLists [
-        compilerNames.ghc981
-        compilerNames.ghc982
         compilerNames.ghc9101
       ] released;
     })