Skip to content

Commit ba317c2

Browse files
committed
Actually _use_ setup deps in configure and co
The only problematic thing is that when we call `cabal clean` or `cabal haddock` (and possibly others), _without_ first having called `configure`, we attempt to build the setup script without calling the solver at all. This means that if you do, say, cabal configure cabal clean cabal clean for a package with a custom setup script that really needs setup dependencies (for instance, because there are two versions of Cabal in the global package DB and the setup script needs the _older_ one), then first call to `clean` will succeed, but the second call will fail because we will try to build the setup script without the solver and that will fail.
1 parent a721fbf commit ba317c2

File tree

3 files changed

+142
-62
lines changed

3 files changed

+142
-62
lines changed

cabal-install/Distribution/Client/Configure.hs

Lines changed: 101 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
-----------------------------------------------------------------------------
1414
module Distribution.Client.Configure (
1515
configure,
16+
configureSetupScript,
1617
chooseCabalVersion,
1718
) where
1819

@@ -30,6 +31,8 @@ import Distribution.Client.SetupWrapper
3031
import Distribution.Client.Targets
3132
( userToPackageConstraint )
3233
import qualified Distribution.Client.ComponentDeps as CD
34+
import Distribution.Package (PackageId)
35+
import Distribution.Client.JobControl (Lock)
3336

3437
import Distribution.Simple.Compiler
3538
( Compiler, CompilerInfo, compilerInfo, PackageDB(..), PackageDBStack )
@@ -41,7 +44,10 @@ import Distribution.Simple.Utils
4144
( defaultPackageDesc )
4245
import qualified Distribution.InstalledPackageInfo as Installed
4346
import Distribution.Package
44-
( Package(..), packageName, Dependency(..), thisPackageVersion )
47+
( Package(..), InstalledPackageId, packageName
48+
, Dependency(..), thisPackageVersion
49+
)
50+
import qualified Distribution.PackageDescription as PkgDesc
4551
import Distribution.PackageDescription.Parse
4652
( readPackageDescription )
4753
import Distribution.PackageDescription.Configuration
@@ -60,6 +66,7 @@ import Distribution.Version
6066
#if !MIN_VERSION_base(4,8,0)
6167
import Data.Monoid (Monoid(..))
6268
#endif
69+
import Data.Maybe (isJust, fromMaybe)
6370

6471
-- | Choose the Cabal version such that the setup scripts compiled against this
6572
-- version will support the given command-line flags.
@@ -101,52 +108,114 @@ configure verbosity packageDBs repos comp platform conf
101108
progress
102109
case maybePlan of
103110
Left message -> do
104-
info verbosity message
105-
setupWrapper verbosity (setupScriptOptions installedPkgIndex) Nothing
111+
info verbosity $
112+
"Warning: solver failed to find a solution:\n"
113+
++ message
114+
++ "Trying configure anyway."
115+
setupWrapper verbosity (setupScriptOptions installedPkgIndex Nothing) Nothing
106116
configureCommand (const configFlags) extraArgs
107117

108118
Right installPlan -> case InstallPlan.ready installPlan of
109-
[pkg@(ReadyPackage (SourcePackage _ _ (LocalUnpackedPackage _) _) _ _ _)] ->
119+
[pkg@(ReadyPackage (SourcePackage _ _ (LocalUnpackedPackage _) _) _ _ _)] -> do
110120
configurePackage verbosity
111121
(InstallPlan.planPlatform installPlan)
112122
(InstallPlan.planCompiler installPlan)
113-
(setupScriptOptions installedPkgIndex)
123+
(setupScriptOptions installedPkgIndex (Just pkg))
114124
configFlags pkg extraArgs
115125

116126
_ -> die $ "internal error: configure install plan should have exactly "
117127
++ "one local ready package."
118128

119129
where
120-
setupScriptOptions index = SetupScriptOptions {
121-
useCabalVersion = chooseCabalVersion configExFlags
122-
(flagToMaybe (configCabalVersion configExFlags)),
123-
useCompiler = Just comp,
124-
usePlatform = Just platform,
125-
usePackageDB = packageDBs',
126-
usePackageIndex = index',
127-
useProgramConfig = conf,
128-
useDistPref = fromFlagOrDefault
129-
(useDistPref defaultSetupScriptOptions)
130-
(configDistPref configFlags),
131-
useLoggingHandle = Nothing,
132-
useWorkingDir = Nothing,
133-
useWin32CleanHack = False,
134-
forceExternalSetupMethod = False,
135-
setupCacheLock = Nothing
136-
}
137-
where
138-
-- Hack: we typically want to allow the UserPackageDB for finding the
139-
-- Cabal lib when compiling any Setup.hs even if we're doing a global
140-
-- install. However we also allow looking in a specific package db.
141-
(packageDBs', index') =
142-
case packageDBs of
143-
(GlobalPackageDB:dbs) | UserPackageDB `notElem` dbs
144-
-> (GlobalPackageDB:UserPackageDB:dbs, Nothing)
145-
-- but if the user is using an odd db stack, don't touch it
146-
dbs -> (dbs, Just index)
130+
setupScriptOptions :: InstalledPackageIndex -> Maybe ReadyPackage -> SetupScriptOptions
131+
setupScriptOptions =
132+
configureSetupScript
133+
packageDBs
134+
comp
135+
platform
136+
conf
137+
(fromFlagOrDefault
138+
(useDistPref defaultSetupScriptOptions)
139+
(configDistPref configFlags))
140+
(chooseCabalVersion
141+
configExFlags
142+
(flagToMaybe (configCabalVersion configExFlags)))
143+
Nothing
144+
False
147145

148146
logMsg message rest = debug verbosity message >> rest
149147

148+
configureSetupScript :: PackageDBStack
149+
-> Compiler
150+
-> Platform
151+
-> ProgramConfiguration
152+
-> FilePath
153+
-> VersionRange
154+
-> Maybe Lock
155+
-> Bool
156+
-> InstalledPackageIndex
157+
-> Maybe ReadyPackage
158+
-> SetupScriptOptions
159+
configureSetupScript packageDBs
160+
comp
161+
platform
162+
conf
163+
distPref
164+
cabalVersion
165+
lock
166+
forceExternal
167+
index
168+
mpkg
169+
= SetupScriptOptions {
170+
useCabalVersion = cabalVersion
171+
, useCompiler = Just comp
172+
, usePlatform = Just platform
173+
, usePackageDB = packageDBs'
174+
, usePackageIndex = index'
175+
, useProgramConfig = conf
176+
, useDistPref = distPref
177+
, useLoggingHandle = Nothing
178+
, useWorkingDir = Nothing
179+
, setupCacheLock = lock
180+
, useWin32CleanHack = False
181+
, forceExternalSetupMethod = forceExternal
182+
-- If we have explicit setup dependencies, list them; otherwise, we give
183+
-- the empty list of dependencies; ideally, we would fix the version of
184+
-- Cabal here, so that we no longer need the special case for that in
185+
-- `compileSetupExecutable` in `externalSetupMethod`, but we don't yet
186+
-- know the version of Cabal at this point, but only find this there.
187+
-- Therefore, for now, we just leave this blank.
188+
, useDependencies = fromMaybe [] explicitSetupDeps
189+
, useDependenciesExclusive = isJust explicitSetupDeps
190+
}
191+
where
192+
-- When we are compiling a legacy setup script without an explicit
193+
-- setup stanza, we typically want to allow the UserPackageDB for
194+
-- finding the Cabal lib when compiling any Setup.hs even if we're doing
195+
-- a global install. However we also allow looking in a specific package
196+
-- db.
197+
packageDBs' :: PackageDBStack
198+
index' :: Maybe InstalledPackageIndex
199+
(packageDBs', index') =
200+
case packageDBs of
201+
(GlobalPackageDB:dbs) | UserPackageDB `notElem` dbs
202+
, Nothing <- explicitSetupDeps
203+
-> (GlobalPackageDB:UserPackageDB:dbs, Nothing)
204+
-- but if the user is using an odd db stack, don't touch it
205+
_otherwise -> (packageDBs, Just index)
206+
207+
explicitSetupDeps :: Maybe [(InstalledPackageId, PackageId)]
208+
explicitSetupDeps = do
209+
ReadyPackage (SourcePackage _ gpkg _ _) _ _ deps <- mpkg
210+
-- Check if there is an explicit setup stanza
211+
_buildInfo <- PkgDesc.setupBuildInfo (PkgDesc.packageDescription gpkg)
212+
-- Return the setup dependencies computed by the solver
213+
return [ ( Installed.installedPackageId deppkg
214+
, Installed.sourcePackageId deppkg
215+
)
216+
| deppkg <- CD.setupDeps deps
217+
]
218+
150219
-- | Make an 'InstallPlan' for the unpacked package in the current directory,
151220
-- and all its dependencies.
152221
--

cabal-install/Distribution/Client/Install.hs

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ import System.IO.Error
6363

6464
import Distribution.Client.Targets
6565
import Distribution.Client.Configure
66-
( chooseCabalVersion )
66+
( chooseCabalVersion, configureSetupScript )
6767
import Distribution.Client.Dependency
6868
import Distribution.Client.Dependency.Types
6969
( Solver(..) )
@@ -1005,7 +1005,7 @@ performInstallations verbosity
10051005
installLocalPackage verbosity buildLimit
10061006
(packageId pkg) src' distPref $ \mpath ->
10071007
installUnpackedPackage verbosity buildLimit installLock numJobs pkg_key
1008-
(setupScriptOptions installedPkgIndex cacheLock)
1008+
(setupScriptOptions installedPkgIndex cacheLock rpkg)
10091009
miscOptions configFlags' installFlags haddockFlags
10101010
cinfo platform pkg pkgoverride mpath useLogFile
10111011

@@ -1019,31 +1019,19 @@ performInstallations verbosity
10191019
distPref = fromFlagOrDefault (useDistPref defaultSetupScriptOptions)
10201020
(configDistPref configFlags)
10211021

1022-
setupScriptOptions index lock = SetupScriptOptions {
1023-
useCabalVersion = chooseCabalVersion configExFlags
1024-
(libVersion miscOptions),
1025-
useCompiler = Just comp,
1026-
usePlatform = Just platform,
1027-
-- Hack: we typically want to allow the UserPackageDB for finding the
1028-
-- Cabal lib when compiling any Setup.hs even if we're doing a global
1029-
-- install. However we also allow looking in a specific package db.
1030-
usePackageDB = if UserPackageDB `elem` packageDBs
1031-
then packageDBs
1032-
else let (db@GlobalPackageDB:dbs) = packageDBs
1033-
in db : UserPackageDB : dbs,
1034-
--TODO: use Ord instance:
1035-
-- insert UserPackageDB packageDBs
1036-
usePackageIndex = if UserPackageDB `elem` packageDBs
1037-
then Just index
1038-
else Nothing,
1039-
useProgramConfig = conf,
1040-
useDistPref = distPref,
1041-
useLoggingHandle = Nothing,
1042-
useWorkingDir = Nothing,
1043-
forceExternalSetupMethod = parallelInstall,
1044-
useWin32CleanHack = False,
1045-
setupCacheLock = Just lock
1046-
}
1022+
setupScriptOptions index lock rpkg =
1023+
configureSetupScript
1024+
packageDBs
1025+
comp
1026+
platform
1027+
conf
1028+
distPref
1029+
(chooseCabalVersion configExFlags (libVersion miscOptions))
1030+
(Just lock)
1031+
parallelInstall
1032+
index
1033+
(Just rpkg)
1034+
10471035
reportingLevel = fromFlag (installBuildReports installFlags)
10481036
logsDir = fromFlag (globalLogsDir globalFlags)
10491037

cabal-install/Distribution/Client/SetupWrapper.hs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import Distribution.Version
2929
, withinRange )
3030
import Distribution.InstalledPackageInfo (installedPackageId)
3131
import Distribution.Package
32-
( InstalledPackageId(..), PackageIdentifier(..),
32+
( InstalledPackageId(..), PackageIdentifier(..), PackageId,
3333
PackageName(..), Package(..), packageName
3434
, packageVersion, Dependency(..) )
3535
import Distribution.PackageDescription
@@ -128,6 +128,19 @@ data SetupScriptOptions = SetupScriptOptions {
128128
useWorkingDir :: Maybe FilePath,
129129
forceExternalSetupMethod :: Bool,
130130

131+
-- | List of dependencies to use when building Setup.hs
132+
useDependencies :: [(InstalledPackageId, PackageId)],
133+
134+
-- | Is the list of setup dependencies exclusive?
135+
--
136+
-- This is here for legacy reasons. Before the introduction of the explicit
137+
-- setup stanza in .cabal files we compiled Setup.hs scripts with all
138+
-- packages in the environment visible, but we will needed to restrict
139+
-- _some_ packages; in particular, we need to restrict the version of Cabal
140+
-- that the setup script gets linked against (this was the only "dependency
141+
-- constraint" that we had previously for Setup scripts).
142+
useDependenciesExclusive :: Bool,
143+
131144
-- Used only by 'cabal clean' on Windows.
132145
--
133146
-- Note: win32 clean hack
@@ -161,6 +174,8 @@ defaultSetupScriptOptions = SetupScriptOptions {
161174
usePlatform = Nothing,
162175
usePackageDB = [GlobalPackageDB, UserPackageDB],
163176
usePackageIndex = Nothing,
177+
useDependencies = [],
178+
useDependenciesExclusive = False,
164179
useProgramConfig = emptyProgramConfiguration,
165180
useDistPref = defaultDistPref,
166181
useLoggingHandle = Nothing,
@@ -247,6 +262,7 @@ buildTypeAction (UnknownBuildType _) = error "buildTypeAction UnknownBuildType"
247262
externalSetupMethod :: SetupMethod
248263
externalSetupMethod verbosity options pkg bt mkargs = do
249264
debug verbosity $ "Using external setup method with build-type " ++ show bt
265+
debug verbosity $ "Using explicit dependencies: " ++ show (useDependenciesExclusive options)
250266
createDirectoryIfMissingVerbose verbosity True setupDir
251267
(cabalLibVersion, mCabalLibInstalledPkgId, options') <- cabalLibVersionToUse
252268
debug verbosity $ "Using Cabal library version " ++ display cabalLibVersion
@@ -491,6 +507,9 @@ externalSetupMethod verbosity options pkg bt mkargs = do
491507
= case compilerFlavor compiler of
492508
GHCJS -> (ghcjsProgram, ["-build-runner"])
493509
_ -> (ghcProgram, ["-threaded"])
510+
cabalDep = maybe [] (\ipkgid -> [(ipkgid, cabalPkgid)])
511+
maybeCabalLibInstalledPkgId
512+
addRenaming (ipid, pid) = (ipid, pid, defaultRenaming)
494513
ghcOptions = mempty {
495514
ghcOptVerbosity = Flag verbosity
496515
, ghcOptMode = Flag GhcModeMake
@@ -501,9 +520,13 @@ externalSetupMethod verbosity options pkg bt mkargs = do
501520
, ghcOptSourcePathClear = Flag True
502521
, ghcOptSourcePath = toNubListR [workingDir]
503522
, ghcOptPackageDBs = usePackageDB options''
523+
, ghcOptHideAllPackages = Flag (useDependenciesExclusive options')
504524
, ghcOptPackages = toNubListR $
505-
maybe [] (\ipkgid -> [(ipkgid, cabalPkgid, defaultRenaming)])
506-
maybeCabalLibInstalledPkgId
525+
map addRenaming $
526+
if useDependenciesExclusive options'
527+
then useDependencies options'
528+
else useDependencies options'
529+
++ cabalDep
507530
, ghcOptExtra = toNubListR extraOpts
508531
}
509532
let ghcCmdLine = renderGhcOptions compiler ghcOptions

0 commit comments

Comments
 (0)