Skip to content

Commit c7ee23b

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 79fed6b commit c7ee23b

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
@@ -596,49 +598,77 @@ removeBound RelaxUpper RelaxDepModNone = removeUpperBound
596598
removeBound RelaxLower RelaxDepModCaret = transformCaretLower
597599
removeBound RelaxUpper RelaxDepModCaret = transformCaretUpper
598600

599-
-- | Supply defaults for packages without explicit Setup dependencies
601+
-- | Supply defaults for packages without explicit Setup dependencies.
602+
-- It also serves to add the implicit dependency on @hooks-exe@ needed to
603+
-- compile the @Setup.hs@ executable produced from 'SetupHooks' when
604+
-- @build-type: Hooks@. The first argument function determines which implicit
605+
-- dependencies are needed (including the one on @hooks-exe@).
600606
--
601607
-- Note: It's important to apply 'addDefaultSetupDepends' after
602608
-- 'addSourcePackages'. Otherwise, the packages inserted by
603609
-- 'addSourcePackages' won't have upper bounds in dependencies relaxed.
604610
addDefaultSetupDependencies
605-
:: (UnresolvedSourcePackage -> Maybe [Dependency])
611+
:: (Maybe [Dependency] -> PD.BuildType -> Maybe PD.SetupBuildInfo -> Maybe PD.SetupBuildInfo)
612+
-- ^ Function to update the SetupBuildInfo of the package using those dependencies
613+
-> (UnresolvedSourcePackage -> Maybe [Dependency])
614+
-- ^ Function to determine extra setup dependencies
606615
-> DepResolverParams
607616
-> DepResolverParams
608-
addDefaultSetupDependencies defaultSetupDeps params =
617+
addDefaultSetupDependencies applyDefaultSetupDeps defaultSetupDeps params =
609618
params
610619
{ depResolverSourcePkgIndex =
611-
fmap applyDefaultSetupDeps (depResolverSourcePkgIndex params)
620+
fmap go (depResolverSourcePkgIndex params)
612621
}
613622
where
614-
applyDefaultSetupDeps :: UnresolvedSourcePackage -> UnresolvedSourcePackage
615-
applyDefaultSetupDeps srcpkg =
623+
go :: UnresolvedSourcePackage -> UnresolvedSourcePackage
624+
go srcpkg =
616625
srcpkg
617626
{ srcpkgDescription =
618627
gpkgdesc
619628
{ PD.packageDescription =
620629
pkgdesc
621630
{ PD.setupBuildInfo =
622-
case PD.setupBuildInfo pkgdesc of
623-
Just sbi -> Just sbi
624-
Nothing -> case defaultSetupDeps srcpkg of
625-
Nothing -> Nothing
626-
Just deps
627-
| isCustom ->
628-
Just
629-
PD.SetupBuildInfo
630-
{ PD.defaultSetupDepends = True
631-
, PD.setupDepends = deps
632-
}
633-
| otherwise -> Nothing
631+
applyDefaultSetupDeps
632+
(defaultSetupDeps srcpkg)
633+
(PD.buildType pkgdesc)
634+
(PD.setupBuildInfo pkgdesc)
634635
}
635636
}
636637
}
637638
where
638-
isCustom = PD.buildType pkgdesc == PD.Custom || PD.buildType pkgdesc == PD.Hooks
639639
gpkgdesc = srcpkgDescription srcpkg
640640
pkgdesc = PD.packageDescription gpkgdesc
641641

642+
setImplicitSetupInfo
643+
:: Maybe [Dependency]
644+
-> PD.BuildType
645+
-> Maybe PD.SetupBuildInfo
646+
-> Maybe PD.SetupBuildInfo
647+
setImplicitSetupInfo mdeps buildty msetupinfo =
648+
case msetupinfo of
649+
Just sbi -> Just sbi
650+
Nothing -> case mdeps of
651+
Nothing -> Nothing
652+
Just deps
653+
| isCustom ->
654+
Just
655+
PD.SetupBuildInfo
656+
{ PD.defaultSetupDepends = True
657+
, PD.setupDepends = deps
658+
}
659+
| otherwise -> Nothing
660+
where
661+
isCustom = buildty == PD.Custom || buildty == PD.Hooks
662+
663+
extendSetupInfoDeps :: Maybe [Dependency] -> PD.BuildType -> Maybe PD.SetupBuildInfo -> Maybe PD.SetupBuildInfo
664+
extendSetupInfoDeps mDeps buildTy mSetupInfo
665+
| Nothing <- mSetupInfo =
666+
assert
667+
(buildTy /= PD.Hooks) -- Hooks needs explicit setup-depends
668+
Nothing
669+
| Just setupInfo <- mSetupInfo =
670+
Just setupInfo{PD.setupDepends = PD.setupDepends setupInfo ++ fromMaybe [] mDeps}
671+
642672
-- | If a package has a custom setup then we need to add a setup-depends
643673
-- on Cabal.
644674
addSetupCabalMinVersionConstraint
@@ -734,7 +764,7 @@ standardInstallPolicy
734764
-> [PackageSpecifier UnresolvedSourcePackage]
735765
-> DepResolverParams
736766
standardInstallPolicy installedPkgIndex sourcePkgDb pkgSpecifiers =
737-
addDefaultSetupDependencies mkDefaultSetupDeps $
767+
addDefaultSetupDependencies setImplicitSetupInfo mkDefaultSetupDeps $
738768
basicInstallPolicy
739769
installedPkgIndex
740770
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
)
@@ -1329,6 +1330,13 @@ planPackages
13291330
. removeLowerBounds solverSettingAllowOlder
13301331
. removeUpperBounds solverSettingAllowNewer
13311332
. addDefaultSetupDependencies
1333+
extendSetupInfoDeps
1334+
( mkHooksSetupImplicitDeps
1335+
. PD.packageDescription
1336+
. srcpkgDescription
1337+
)
1338+
. addDefaultSetupDependencies
1339+
setImplicitSetupInfo
13321340
( mkDefaultSetupDeps comp platform
13331341
. PD.packageDescription
13341342
. 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)