{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} module Distribution.Types.HookedBuildInfo ( HookedBuildInfo, emptyHookedBuildInfo, ) where -- import Distribution.Compat.Prelude import Distribution.Types.BuildInfo import Distribution.Types.UnqualComponentName -- | 'HookedBuildInfo' is mechanism that hooks can use to -- override the 'BuildInfo's inside packages. One example -- use-case (which is used in core libraries today) is as -- a way of passing flags which are computed by a configure -- script into Cabal. In this case, the autoconf build type adds -- hooks to read in a textual 'HookedBuildInfo' format prior -- to doing any operations. -- -- Quite honestly, this mechanism is a massive hack since we shouldn't -- be editing the 'PackageDescription' data structure (it's easy -- to assume that this data structure shouldn't change and -- run into bugs, see for example 1c20a6328579af9e37677d507e2e9836ef70ab9d). -- But it's a bit convenient, because there isn't another data -- structure that allows adding extra 'BuildInfo' style things. -- -- In any case, a lot of care has to be taken to make sure the -- 'HookedBuildInfo' is applied to the 'PackageDescription'. In -- general this process occurs in "Distribution.Simple", which is -- responsible for orchestrating the hooks mechanism. The -- general strategy: -- -- 1. We run the pre-hook, which produces a 'HookedBuildInfo' -- (e.g., in the Autoconf case, it reads it out from a file). -- 2. We sanity-check the hooked build info with -- 'sanityCheckHookedBuildInfo'. -- 3. We update our 'PackageDescription' (either freshly read -- or cached from 'LocalBuildInfo') with 'updatePackageDescription'. -- -- In principle, we are also supposed to update the copy of -- the 'PackageDescription' stored in 'LocalBuildInfo' -- at 'localPkgDescr'. Unfortunately, in practice, there -- are lots of Custom setup scripts which fail to update -- 'localPkgDescr' so you really shouldn't rely on it. -- It's not DEPRECATED because there are legitimate uses -- for it, but... yeah. Sharp knife. See -- <https://github.com/haskell/cabal/issues/3606> -- for more information on the issue. -- -- It is not well-specified whether or not a 'HookedBuildInfo' applied -- at configure time is persistent to the 'LocalBuildInfo'. The -- fact that 'HookedBuildInfo' is passed to 'confHook' MIGHT SUGGEST -- that the 'HookedBuildInfo' is applied at this time, but actually -- since 9317b67e6122ab14e53f81b573bd0ecb388eca5a it has been ONLY used -- to create a modified package description that we check for problems: -- it is never actually saved to the LBI. Since 'HookedBuildInfo' is -- applied monoidally to the existing build infos (and it is not an -- idempotent monoid), it could break things to save it, since we -- are obligated to apply any new 'HookedBuildInfo' and then we'd -- get the effect twice. But this does mean we have to re-apply -- it every time. Hey, it's more flexibility. type HookedBuildInfo = (Maybe BuildInfo, [(UnqualComponentName, BuildInfo)]) emptyHookedBuildInfo :: HookedBuildInfo emptyHookedBuildInfo :: HookedBuildInfo emptyHookedBuildInfo = (forall a. Maybe a Nothing, [])