Skip to content

Commit 9cea27f

Browse files
alt-romessheaf
authored andcommitted
hooks: Implicitly depend on hooks-exe
The `hooks-exe` package enables `SetupHooks` values to be converted into a `Setup.hs` executable which can be executed independently of Cabal. The `Setup.hs` executable wrapping `SetupHooks` is quite important to preserve the interface used by other tools when packages migrate to `Hooks` from `Custom`. Even though `hooks-exe` is an internal dependency required by the `Setup.hs` wrapper around `SetupHooks`, it is a dependency nonetheless. Given the internal nature of `hooks-exe`, we don't want to impose on our users the obligation to add a dependency on `hooks-exe` in their setup-depends field. Instead, we want `hooks-exe` to be implicitly added to the setup dependencies. This commit does that exactly.
1 parent 7c1a03d commit 9cea27f

File tree

3 files changed

+91
-21
lines changed

3 files changed

+91
-21
lines changed

cabal-install/src/Distribution/Client/Dependency.hs

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ module Distribution.Client.Dependency
6565
, addSetupCabalMinVersionConstraint
6666
, addSetupCabalMaxVersionConstraint
6767
, addSetupCabalProfiledDynamic
68+
, setImplicitSetupInfo
69+
, extendSetupInfoDeps
6870
) where
6971

7072
import Distribution.Client.Compat.Prelude
@@ -604,49 +606,77 @@ removeBound RelaxUpper RelaxDepModNone = removeUpperBound
604606
removeBound RelaxLower RelaxDepModCaret = transformCaretLower
605607
removeBound RelaxUpper RelaxDepModCaret = transformCaretUpper
606608

607-
-- | Supply defaults for packages without explicit Setup dependencies
609+
-- | Supply defaults for packages without explicit Setup dependencies.
610+
-- It also serves to add the implicit dependency on @hooks-exe@ needed to
611+
-- compile the @Setup.hs@ executable produced from 'SetupHooks' when
612+
-- @build-type: Hooks@. The first argument function determines which implicit
613+
-- dependencies are needed (including the one on @hooks-exe@).
608614
--
609615
-- Note: It's important to apply 'addDefaultSetupDepends' after
610616
-- 'addSourcePackages'. Otherwise, the packages inserted by
611617
-- 'addSourcePackages' won't have upper bounds in dependencies relaxed.
612618
addDefaultSetupDependencies
613-
:: (UnresolvedSourcePackage -> Maybe [Dependency])
619+
:: (Maybe [Dependency] -> PD.BuildType -> Maybe PD.SetupBuildInfo -> Maybe PD.SetupBuildInfo)
620+
-- ^ Function to update the SetupBuildInfo of the package using those dependencies
621+
-> (UnresolvedSourcePackage -> Maybe [Dependency])
622+
-- ^ Function to determine extra setup dependencies
614623
-> DepResolverParams
615624
-> DepResolverParams
616-
addDefaultSetupDependencies defaultSetupDeps params =
625+
addDefaultSetupDependencies applyDefaultSetupDeps defaultSetupDeps params =
617626
params
618627
{ depResolverSourcePkgIndex =
619-
fmap applyDefaultSetupDeps (depResolverSourcePkgIndex params)
628+
fmap go (depResolverSourcePkgIndex params)
620629
}
621630
where
622-
applyDefaultSetupDeps :: UnresolvedSourcePackage -> UnresolvedSourcePackage
623-
applyDefaultSetupDeps srcpkg =
631+
go :: UnresolvedSourcePackage -> UnresolvedSourcePackage
632+
go srcpkg =
624633
srcpkg
625634
{ srcpkgDescription =
626635
gpkgdesc
627636
{ PD.packageDescription =
628637
pkgdesc
629638
{ PD.setupBuildInfo =
630-
case PD.setupBuildInfo pkgdesc of
631-
Just sbi -> Just sbi
632-
Nothing -> case defaultSetupDeps srcpkg of
633-
Nothing -> Nothing
634-
Just deps
635-
| isCustom ->
636-
Just
637-
PD.SetupBuildInfo
638-
{ PD.defaultSetupDepends = True
639-
, PD.setupDepends = deps
640-
}
641-
| otherwise -> Nothing
639+
applyDefaultSetupDeps
640+
(defaultSetupDeps srcpkg)
641+
(PD.buildType pkgdesc)
642+
(PD.setupBuildInfo pkgdesc)
642643
}
643644
}
644645
}
645646
where
646-
isCustom = PD.buildType pkgdesc == PD.Custom || PD.buildType pkgdesc == PD.Hooks
647647
gpkgdesc = srcpkgDescription srcpkg
648648
pkgdesc = PD.packageDescription gpkgdesc
649649

650+
setImplicitSetupInfo
651+
:: Maybe [Dependency]
652+
-> PD.BuildType
653+
-> Maybe PD.SetupBuildInfo
654+
-> Maybe PD.SetupBuildInfo
655+
setImplicitSetupInfo mdeps buildty msetupinfo =
656+
case msetupinfo of
657+
Just sbi -> Just sbi
658+
Nothing -> case mdeps of
659+
Nothing -> Nothing
660+
Just deps
661+
| isCustom ->
662+
Just
663+
PD.SetupBuildInfo
664+
{ PD.defaultSetupDepends = True
665+
, PD.setupDepends = deps
666+
}
667+
| otherwise -> Nothing
668+
where
669+
isCustom = buildty == PD.Custom || buildty == PD.Hooks
670+
671+
extendSetupInfoDeps :: Maybe [Dependency] -> PD.BuildType -> Maybe PD.SetupBuildInfo -> Maybe PD.SetupBuildInfo
672+
extendSetupInfoDeps mDeps buildTy mSetupInfo
673+
| Nothing <- mSetupInfo =
674+
assert
675+
(buildTy /= PD.Hooks) -- Hooks needs explicit setup-depends
676+
Nothing
677+
| Just setupInfo <- mSetupInfo =
678+
Just setupInfo{PD.setupDepends = PD.setupDepends setupInfo ++ fromMaybe [] mDeps}
679+
650680
-- | If a package has a custom setup then we need to add a setup-depends
651681
-- on Cabal.
652682
addSetupCabalMinVersionConstraint
@@ -742,7 +772,7 @@ standardInstallPolicy
742772
-> [PackageSpecifier UnresolvedSourcePackage]
743773
-> DepResolverParams
744774
standardInstallPolicy installedPkgIndex sourcePkgDb pkgSpecifiers =
745-
addDefaultSetupDependencies mkDefaultSetupDeps $
775+
addDefaultSetupDependencies setImplicitSetupInfo mkDefaultSetupDeps $
746776
basicInstallPolicy
747777
installedPkgIndex
748778
sourcePkgDb

cabal-install/src/Distribution/Client/ProjectPlanning.hs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ import Distribution.Client.ProjectPlanOutput
126126
import Distribution.Client.ProjectPlanning.SetupPolicy
127127
( NonSetupLibDepSolverPlanPackage (..)
128128
, mkDefaultSetupDeps
129+
, mkHooksSetupImplicitDeps
129130
, packageSetupScriptSpecVersion
130131
, packageSetupScriptStyle
131132
)
@@ -1365,6 +1366,13 @@ planPackages
13651366
. removeLowerBounds solverSettingAllowOlder
13661367
. removeUpperBounds solverSettingAllowNewer
13671368
. addDefaultSetupDependencies
1369+
extendSetupInfoDeps
1370+
( mkHooksSetupImplicitDeps
1371+
. PD.packageDescription
1372+
. srcpkgDescription
1373+
)
1374+
. addDefaultSetupDependencies
1375+
setImplicitSetupInfo
13681376
( mkDefaultSetupDeps comp platform
13691377
. PD.packageDescription
13701378
. srcpkgDescription

cabal-install/src/Distribution/Client/ProjectPlanning/SetupPolicy.hs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,16 @@
2222
-- In cases 1 and 2 we obviously have to build an external Setup.hs script,
2323
-- while in case 4 we can use the internal library API.
2424
--
25+
-- Since @3.14.0.0@ we must also consider the @Setup.hs@ scripts constructed
26+
-- from 'SetupHooks' values, because these generated @Setup.hs@ scripts depend
27+
-- on the @hooks-exe@ package (which creates an executable from 'SetupHooks').
28+
-- Therefore, 'SetupPolicy' is also concerned with augmenting the setup
29+
-- dependencies with @hooks-exe@ when @build-type: Hooks@.
30+
--
2531
-- @since 3.12.0.0
2632
module Distribution.Client.ProjectPlanning.SetupPolicy
2733
( mkDefaultSetupDeps
34+
, mkHooksSetupImplicitDeps
2835
, packageSetupScriptStyle
2936
, packageSetupScriptSpecVersion
3037
, NonSetupLibDepSolverPlanPackage (..)
@@ -157,6 +164,30 @@ mkDefaultSetupDeps compiler platform pkg =
157164
csvToVersion :: CabalSpecVersion -> Version
158165
csvToVersion = mkVersion . cabalSpecMinimumLibraryVersion
159166

167+
-- | Returns an implicit dependency on @hooks-exe@ needed to create a
168+
-- @Setup.hs@ executable from a 'SetupHooks' value, if @build-type: Hooks@,
169+
-- as well as a dependency on @Cabal@ if there isn't one already.
170+
--
171+
-- @since 3.14.0.0
172+
mkHooksSetupImplicitDeps
173+
:: PackageDescription
174+
-> Maybe [Dependency]
175+
mkHooksSetupImplicitDeps pkg
176+
| Hooks <- buildType pkg =
177+
Just $
178+
[Dependency hooksExePkgname anyVersion mainLibSet]
179+
-- Add a dependency on Cabal if there isn't one, so that we can compile:
180+
-- module Main where
181+
-- import Distribution.Simple (defaultMainWithSetupHooks)
182+
-- import SetupHooks (setupHooks)
183+
-- main = defaultMainWithSetupHooks setupHooks
184+
++ [ Dependency cabalPkgname (orLaterVersion $ mkVersion [3, 13, 0]) mainLibSet
185+
| setupBI <- maybeToList $ setupBuildInfo pkg
186+
, not $ any ((== cabalPkgname) . depPkgName) $ setupDepends setupBI
187+
]
188+
| otherwise =
189+
Nothing
190+
160191
-- | A newtype for 'SolverPlanPackage' for which the
161192
-- dependency graph considers only dependencies on libraries which are
162193
-- NOT from setup dependencies. Used to compute the set
@@ -216,8 +247,9 @@ packageSetupScriptSpecVersion _ pkg libDepGraph deps =
216247
fromMaybe [] $
217248
Graph.closure libDepGraph (CD.setupDeps deps)
218249

219-
cabalPkgname :: PackageName
250+
cabalPkgname, hooksExePkgname :: PackageName
220251
cabalPkgname = mkPackageName "Cabal"
252+
hooksExePkgname = mkPackageName "hooks-exe"
221253

222254
legacyCustomSetupPkgs :: Compiler -> Platform -> [PackageName]
223255
legacyCustomSetupPkgs compiler (Platform _ os) =

0 commit comments

Comments
 (0)