From 42b8dc1f7d449a9b9de94640f38479f01b0c1eff Mon Sep 17 00:00:00 2001
From: sheaf <sam.derbyshire@gmail.com>
Date: Thu, 9 May 2024 11:21:35 +0200
Subject: [PATCH] Add NoImplicitPrelude to buildTypeScript

This allows us to compile Setup.hs without depending on base.
In particular, this ensures that a package with `build-type: Hooks`
and a custom setup stanza that does not depend on base successfully
compiles.

Tested in PackageTests/SetupHooks/SetupHooksNoBase.
---
 .../Client/ProjectPlanning/SetupPolicy.hs        |  6 ++----
 .../src/Distribution/Client/SetupWrapper.hs      | 13 +++++++++++--
 .../SetupHooks/SetupHooksNoBase/A.hs             |  2 ++
 .../SetupHooks/SetupHooksNoBase/SetupHooks.hs    |  8 ++++++++
 .../SetupHooks/SetupHooksNoBase/cabal.project    |  1 +
 .../SetupHooks/SetupHooksNoBase/cabal.test.hs    | 14 ++++++++++++++
 .../setup-hooks-no-base-test.cabal               | 16 ++++++++++++++++
 7 files changed, 54 insertions(+), 6 deletions(-)
 create mode 100644 cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/A.hs
 create mode 100644 cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/SetupHooks.hs
 create mode 100644 cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/cabal.project
 create mode 100644 cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/cabal.test.hs
 create mode 100644 cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/setup-hooks-no-base-test.cabal

diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning/SetupPolicy.hs b/cabal-install/src/Distribution/Client/ProjectPlanning/SetupPolicy.hs
index 212a5d93f8..a510ea2bff 100644
--- a/cabal-install/src/Distribution/Client/ProjectPlanning/SetupPolicy.hs
+++ b/cabal-install/src/Distribution/Client/ProjectPlanning/SetupPolicy.hs
@@ -133,11 +133,10 @@ mkDefaultSetupDeps compiler platform pkg =
 
     -- For other build types (like Simple) if we still need to compile an
     -- external Setup.hs, it'll be one of the simple ones that only depends
-    -- on Cabal and base.
+    -- on Cabal.
     SetupNonCustomExternalLib ->
       Just
         [ Dependency cabalPkgname cabalConstraint mainLibSet
-        , Dependency basePkgname anyVersion mainLibSet
         ]
       where
         cabalConstraint = orLaterVersion (csvToVersion (specVersion pkg))
@@ -217,9 +216,8 @@ packageSetupScriptSpecVersion _ pkg libDepGraph deps =
         fromMaybe [] $
           Graph.closure libDepGraph (CD.setupDeps deps)
 
-cabalPkgname, basePkgname :: PackageName
+cabalPkgname :: PackageName
 cabalPkgname = mkPackageName "Cabal"
-basePkgname = mkPackageName "base"
 
 legacyCustomSetupPkgs :: Compiler -> Platform -> [PackageName]
 legacyCustomSetupPkgs compiler (Platform _ os) =
diff --git a/cabal-install/src/Distribution/Client/SetupWrapper.hs b/cabal-install/src/Distribution/Client/SetupWrapper.hs
index 32b492541d..4040c26bce 100644
--- a/cabal-install/src/Distribution/Client/SetupWrapper.hs
+++ b/cabal-install/src/Distribution/Client/SetupWrapper.hs
@@ -181,6 +181,7 @@ import Distribution.Utils.NubList
 import Distribution.Verbosity
 
 import Data.List (foldl1')
+import qualified Data.Map.Lazy as Map
 import Distribution.Simple.Setup (globalCommand)
 import Distribution.Client.Compat.ExecutablePath (getExecutablePath)
 import Distribution.Compat.Process (proc)
@@ -858,7 +859,7 @@ getExternalSetupMethod verbosity options pkg bt = do
       rewriteFileLBS verbosity (i setupHs) (buildTypeScript cabalLibVersion)
 
     buildTypeScript :: Version -> BS.ByteString
-    buildTypeScript cabalLibVersion = case bt of
+    buildTypeScript cabalLibVersion = "{-# LANGUAGE NoImplicitPrelude #-}\n" <> case bt of
       Simple -> "import Distribution.Simple; main = defaultMain\n"
       Configure
         | cabalLibVersion >= mkVersion [1, 3, 10] -> "import Distribution.Simple; main = defaultMainWithHooks autoconfUserHooks\n"
@@ -1111,6 +1112,13 @@ getExternalSetupMethod verbosity options pkg bt = do
                         | useVersionMacros options'
                         ]
                   , ghcOptExtra = extraOpts
+                  , ghcOptExtensions = toNubListR $
+                      if bt == Custom || any (isBasePkgId . snd) selectedDeps
+                      then []
+                      else [ Simple.DisableExtension Simple.ImplicitPrelude ]
+                        -- Pass -WNoImplicitPrelude to avoid depending on base
+                        -- when compiling a Simple Setup.hs file.
+                  , ghcOptExtensionMap = Map.fromList . Simple.compilerExtensions $ compiler
                   }
           let ghcCmdLine = renderGhcOptions compiler platform ghcOptions
           when (useVersionMacros options') $
@@ -1131,5 +1139,6 @@ getExternalSetupMethod verbosity options pkg bt = do
               hPutStr logHandle output
         return $ i setupProgFile
 
-isCabalPkgId :: PackageIdentifier -> Bool
+isCabalPkgId, isBasePkgId :: PackageIdentifier -> Bool
 isCabalPkgId (PackageIdentifier pname _) = pname == mkPackageName "Cabal"
+isBasePkgId (PackageIdentifier pname _) = pname == mkPackageName "base"
diff --git a/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/A.hs b/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/A.hs
new file mode 100644
index 0000000000..90d08ce658
--- /dev/null
+++ b/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/A.hs
@@ -0,0 +1,2 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module A where {}
diff --git a/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/SetupHooks.hs b/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/SetupHooks.hs
new file mode 100644
index 0000000000..5d843bb9fb
--- /dev/null
+++ b/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/SetupHooks.hs
@@ -0,0 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module SetupHooks ( setupHooks ) where
+
+import Distribution.Simple.SetupHooks ( SetupHooks, noSetupHooks )
+
+setupHooks :: SetupHooks
+setupHooks = noSetupHooks
diff --git a/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/cabal.project b/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/cabal.project
new file mode 100644
index 0000000000..e6fdbadb43
--- /dev/null
+++ b/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/cabal.project
@@ -0,0 +1 @@
+packages: .
diff --git a/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/cabal.test.hs b/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/cabal.test.hs
new file mode 100644
index 0000000000..83a13355cd
--- /dev/null
+++ b/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/cabal.test.hs
@@ -0,0 +1,14 @@
+import Test.Cabal.Prelude
+
+-- Test that we can compile the Setup.hs script for a package with
+-- build-type:Hooks without requiring a dependency on 'base'.
+--
+-- NB: we specifically don't include a 'Setup.hs' file in this package,
+-- as we rely on 'cabal-install' generating one that does not incur an extra
+-- dependency on base.
+main = cabalTest $ do
+  mpkgdb <- testPackageDbPath <$> getTestEnv
+  case mpkgdb of
+    Nothing -> skip "Cabal-hooks library unavailable."
+    Just _pkgdb -> recordMode DoNotRecord $ do
+      cabal "v2-build" [ "all" ]
diff --git a/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/setup-hooks-no-base-test.cabal b/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/setup-hooks-no-base-test.cabal
new file mode 100644
index 0000000000..a75c76d07f
--- /dev/null
+++ b/cabal-testsuite/PackageTests/SetupHooks/SetupHooksNoBase/setup-hooks-no-base-test.cabal
@@ -0,0 +1,16 @@
+cabal-version:       3.14
+name:                setup-hooks-no-base-test
+version:             0.1.0.0
+synopsis:            Test that we can build Setup.hs without base
+license:             BSD-3-Clause
+author:              NA
+maintainer:          NA
+category:            Testing
+build-type:          Hooks
+
+custom-setup
+  setup-depends: Cabal-hooks
+
+library
+  exposed-modules:  A
+  default-language: Haskell2010
-- 
GitLab