    {-# LANGUAGE CPP #-}
    -- | Convenience hooks for writing custom @Setup.hs@ files for
    -- bindings.
    module Data.GI.CodeGen.CabalHooks
        ( setupBinding
        , setupCompatWrapper
        , configureDryRun
        , TaggedOverride(..)
        ) where

    import qualified Distribution.ModuleName as MN
    import Distribution.Simple.LocalBuildInfo
    import Distribution.Simple.Setup
    import Distribution.Simple (UserHooks(..), simpleUserHooks,
                                defaultMainWithHooks, OptimisationLevel(..))
    import Distribution.PackageDescription

    import Data.GI.CodeGen.API (loadGIRInfo)
    import Data.GI.CodeGen.Code (genCode, writeModuleTree, listModuleTree,
                                 ModuleInfo, transitiveModuleDeps)
    import Data.GI.CodeGen.CodeGen (genModule)
    import Data.GI.CodeGen.Config (Config(..))
    import Data.GI.CodeGen.LibGIRepository (setupTypelibSearchPath)
    import Data.GI.CodeGen.ModulePath (toModulePath)
    import Data.GI.CodeGen.Overrides (parseOverrides, girFixups,
                                      filterAPIsAndDeps)
    import Data.GI.CodeGen.Util (utf8ReadFile, utf8WriteFile, ucFirst, splitOn)

    import System.Directory (createDirectoryIfMissing)
    import System.FilePath (joinPath, takeDirectory, (</>))

    import Control.Monad (forM)

    import Data.Maybe (fromJust, fromMaybe)
    import qualified Data.Map as M
    #if !MIN_VERSION_base(4,11,0)
    import Data.Monoid ((<>))
    #endif
    import qualified Data.Set as S
    import Data.Text (Text)
    import qualified Data.Text as T

    #ifndef EXTRA_GIR_SEARCH_PATH
    #define EXTRA_GIR_SEARCH_PATH
    #endif

    type ConfHook = (GenericPackageDescription, HookedBuildInfo) -> ConfigFlags
                  -> IO LocalBuildInfo

    -- | Included overrides file.
    data TaggedOverride =
      TaggedOverride { TaggedOverride -> Text
    overrideTag   :: Text
                       -- ^ Tag for the override, for error reporting purposes.
                     , TaggedOverride -> Text
    overrideText  :: Text
                     }

    -- | Generate the code for the given module.
    genModuleCode :: Text -- ^ name
                  -> Text -- ^ version
                  -> Text -- ^ pkgName
                  -> Text -- ^ pkgVersion
                  -> Bool -- ^ verbose
                  -> [TaggedOverride] -- ^ Explicit overrides
                  -> IO ModuleInfo
    genModuleCode :: Text
    -> Text
    -> Text
    -> Text
    -> Bool
    -> [TaggedOverride]
    -> IO ModuleInfo
    genModuleCode Text
    name Text
    version Text
    pkgName Text
    pkgVersion Bool
    verbosity [TaggedOverride]
    overrides = do
      [String] -> IO ()
    setupTypelibSearchPath []

      parsed <- [TaggedOverride]
    -> (TaggedOverride -> IO Overrides) -> IO [Overrides]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    t a -> (a -> m b) -> m (t b)
    forM [TaggedOverride]
    overrides ((TaggedOverride -> IO Overrides) -> IO [Overrides])
    -> (TaggedOverride -> IO Overrides) -> IO [Overrides]
    forall a b. (a -> b) -> a -> b
    $ \(TaggedOverride Text
    tag Text
    ovText) -> do
        Text -> IO (Either Text Overrides)
    parseOverrides Text
    ovText IO (Either Text Overrides)
    -> (Either Text Overrides -> IO Overrides) -> IO Overrides
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \case
          Left Text
    err -> String -> IO Overrides
    forall a. HasCallStack => String -> a
    error (String -> IO Overrides) -> String -> IO Overrides
    forall a b. (a -> b) -> a -> b
    $ String
    "Error when parsing overrides file \""
                      String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Text -> String
    T.unpack Text
    tag String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    "\":"
                      String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Text -> String
    T.unpack Text
    err
          Right Overrides
    ovs -> Overrides -> IO Overrides
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Overrides
    ovs

      let ovs = [Overrides] -> Overrides
    forall a. Monoid a => [a] -> a
    mconcat [Overrides]
    parsed

      (gir, girDeps) <- loadGIRInfo verbosity name (Just version) [EXTRA_GIR_SEARCH_PATH] (girFixups ovs)
      let (apis, deps) = filterAPIsAndDeps ovs gir girDeps
          allAPIs = Map Name API -> Map Name API -> Map Name API
    forall k a. Ord k => Map k a -> Map k a -> Map k a
    M.union Map Name API
    apis Map Name API
    deps
          cfg = Config {modName :: Text
    modName = Text
    name,
                        modVersion :: Text
    modVersion = Text
    version,
                        ghcPkgName :: Text
    ghcPkgName = Text
    pkgName,
                        ghcPkgVersion :: Text
    ghcPkgVersion = Text
    pkgVersion,
                        verbose :: Bool
    verbose = Bool
    verbosity,
                        overrides :: Overrides
    overrides = Overrides
    ovs}

      return $ genCode cfg allAPIs (toModulePath name) (genModule apis)

    -- | Write a module containing information about the configuration for
    -- the package.
    genConfigModule :: Maybe FilePath -> Text -> Maybe TaggedOverride ->
                       [Text] -> IO ()
    genConfigModule :: Maybe String -> Text -> Maybe TaggedOverride -> [Text] -> IO ()
    genConfigModule Maybe String
    outputDir Text
    modName Maybe TaggedOverride
    maybeGiven [Text]
    modules = do
      let fname :: String
    fname = [String] -> String
    joinPath [ String -> Maybe String -> String
    forall a. a -> Maybe a -> a
    fromMaybe String
    "" Maybe String
    outputDir
                           , String
    "GI"
                           , Text -> String
    T.unpack (Text -> Text
    ucFirst Text
    modName)
                           , String
    "Config.hs" ]
          dirname :: String
    dirname = String -> String
    takeDirectory String
    fname

      Bool -> String -> IO ()
    createDirectoryIfMissing Bool
    True String
    dirname

      String -> Text -> IO ()
    utf8WriteFile String
    fname (Text -> IO ()) -> Text -> IO ()
    forall a b. (a -> b) -> a -> b
    $ [Text] -> Text
    T.unlines
        [ Text
    "{-# LANGUAGE OverloadedStrings #-}"
        , Text
    "-- | Build time configuration used during code generation."
        , Text
    "module GI." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    ucFirst Text
    modName Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ".Config ( overrides, modules ) where"
        , Text
    ""
        , Text
    "import qualified Data.Text as T"
        , Text
    "import Data.Text (Text)"
        , Text
    ""
        , Text
    "-- | Overrides used when generating these bindings."
        , Text
    "overrides :: Text"
        , Text
    "overrides = T.unlines"
        , [Text] -> Text
    formatList (Maybe TaggedOverride -> [Text]
    overrides Maybe TaggedOverride
    maybeGiven)
        , Text
    ""
        , Text
    "-- | Modules in this package"
        , Text
    "modules :: [Text]"
        , Text
    "modules = " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <>
          [Text] -> Text
    formatList ((Text
    "GI." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    ucFirst Text
    modName Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ".Config") Text -> [Text] -> [Text]
    forall a. a -> [a] -> [a]
    : [Text]
    modules)
        ]

      where overrides :: Maybe TaggedOverride -> [Text]
            overrides :: Maybe TaggedOverride -> [Text]
    overrides Maybe TaggedOverride
    Nothing = []
            overrides (Just (TaggedOverride Text
    _ Text
    ovText)) = Text -> [Text]
    T.lines Text
    ovText

            formatList :: [Text] -> Text
            formatList :: [Text] -> Text
    formatList [Text]
    l = Text
    " [ "
                           Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> [Text] -> Text
    T.intercalate Text
    "\n , " ((Text -> Text) -> [Text] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (String -> Text
    T.pack (String -> Text) -> (Text -> String) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    forall a. Show a => a -> String
    show) [Text]
    l)
                           Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "]"

    -- | A convenience helper for `confHook`, such that bindings for the
    -- given module are generated in the @configure@ step of @cabal@.
    confCodeGenHook :: Text -- ^ name
                    -> Text -- ^ version
                    -> Text -- ^ pkgName
                    -> Text -- ^ pkgVersion
                    -> Bool -- ^ verbose
                    -> Maybe FilePath -- ^ overrides file
                    -> [TaggedOverride] -- ^ other overrides
                    -> Maybe FilePath -- ^ output dir
                    -> ConfHook -- ^ previous `confHook`
                    -> ConfHook
    confCodeGenHook :: Text
    -> Text
    -> Text
    -> Text
    -> Bool
    -> Maybe String
    -> [TaggedOverride]
    -> Maybe String
    -> ConfHook
    -> ConfHook
    confCodeGenHook Text
    name Text
    version Text
    pkgName Text
    pkgVersion Bool
    verbosity
                    Maybe String
    overridesFile [TaggedOverride]
    inheritedOverrides Maybe String
    outputDir
                    ConfHook
    defaultConfHook (GenericPackageDescription
    gpd, HookedBuildInfo
    hbi) ConfigFlags
    flags = do

      givenOvs <- (String -> IO TaggedOverride)
    -> Maybe String -> IO (Maybe TaggedOverride)
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> Maybe a -> f (Maybe b)
    traverse (\String
    fname -> Text -> Text -> TaggedOverride
    TaggedOverride (String -> Text
    T.pack String
    fname) (Text -> TaggedOverride) -> IO Text -> IO TaggedOverride
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> IO Text
    utf8ReadFile String
    fname) Maybe String
    overridesFile

      let ovs = [TaggedOverride]
    -> (TaggedOverride -> [TaggedOverride])
    -> Maybe TaggedOverride
    -> [TaggedOverride]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [TaggedOverride]
    inheritedOverrides (TaggedOverride -> [TaggedOverride] -> [TaggedOverride]
    forall a. a -> [a] -> [a]
    :[TaggedOverride]
    inheritedOverrides) Maybe TaggedOverride
    givenOvs
      m <- genModuleCode name version pkgName pkgVersion verbosity ovs

      let buildInfo = String -> ModuleName
    forall a. IsString a => String -> a
    MN.fromString (String -> ModuleName) -> (Text -> String) -> Text -> ModuleName
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack (Text -> ModuleName) -> Text -> ModuleName
    forall a b. (a -> b) -> a -> b
    $ Text
    "GI." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    ucFirst Text
    name Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ".Config"
          em' = ModuleName
    buildInfo ModuleName -> [ModuleName] -> [ModuleName]
    forall a. a -> [a] -> [a]
    : (Text -> ModuleName) -> [Text] -> [ModuleName]
    forall a b. (a -> b) -> [a] -> [b]
    map (String -> ModuleName
    forall a. IsString a => String -> a
    MN.fromString (String -> ModuleName) -> (Text -> String) -> Text -> ModuleName
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack) (ModuleInfo -> [Text]
    listModuleTree ModuleInfo
    m)
          lib = ((CondTree ConfVar [Dependency] Library -> Library
    forall v c a. CondTree v c a -> a
    condTreeData (CondTree ConfVar [Dependency] Library -> Library)
    -> (GenericPackageDescription
        -> CondTree ConfVar [Dependency] Library)
    -> GenericPackageDescription
    -> Library
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Maybe (CondTree ConfVar [Dependency] Library)
    -> CondTree ConfVar [Dependency] Library
    forall a. HasCallStack => Maybe a -> a
    fromJust (Maybe (CondTree ConfVar [Dependency] Library)
     -> CondTree ConfVar [Dependency] Library)
    -> (GenericPackageDescription
        -> Maybe (CondTree ConfVar [Dependency] Library))
    -> GenericPackageDescription
    -> CondTree ConfVar [Dependency] Library
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GenericPackageDescription
    -> Maybe (CondTree ConfVar [Dependency] Library)
    condLibrary) GenericPackageDescription
    gpd)
          bi = Library -> BuildInfo
    libBuildInfo Library
    lib
    #if MIN_VERSION_base(4,11,0)
          bi' = BuildInfo
    bi {autogenModules = em'}
    #else
          bi' = bi
    #endif
          lib' = Library
    lib {exposedModules = em', libBuildInfo = bi'}
          cL' = ((Maybe (CondTree ConfVar [Dependency] Library)
    -> CondTree ConfVar [Dependency] Library
    forall a. HasCallStack => Maybe a -> a
    fromJust (Maybe (CondTree ConfVar [Dependency] Library)
     -> CondTree ConfVar [Dependency] Library)
    -> (GenericPackageDescription
        -> Maybe (CondTree ConfVar [Dependency] Library))
    -> GenericPackageDescription
    -> CondTree ConfVar [Dependency] Library
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GenericPackageDescription
    -> Maybe (CondTree ConfVar [Dependency] Library)
    condLibrary) GenericPackageDescription
    gpd) {condTreeData = lib'}
          gpd' = GenericPackageDescription
    gpd {condLibrary = Just cL'}

      modules <- writeModuleTree verbosity outputDir m

      genConfigModule outputDir name givenOvs modules

      lbi <- defaultConfHook (gpd', hbi) flags

      return (lbi {withOptimization = NoOptimisation})

    -- | The entry point for @Setup.hs@ files in bindings.
    setupBinding :: Text -- ^ name
                 -> Text -- ^ version
                 -> Text -- ^ pkgName
                 -> Text -- ^ pkgVersion
                 -> Bool -- ^ verbose
                 -> Maybe FilePath -- ^ overrides file
                 -> [TaggedOverride] -- ^ Explicit overrides
                 -> Maybe FilePath -- ^ output dir
                 -> IO ()
    setupBinding :: Text
    -> Text
    -> Text
    -> Text
    -> Bool
    -> Maybe String
    -> [TaggedOverride]
    -> Maybe String
    -> IO ()
    setupBinding Text
    name Text
    version Text
    pkgName Text
    pkgVersion Bool
    verbose Maybe String
    overridesFile [TaggedOverride]
    overrides Maybe String
    outputDir =
        UserHooks -> IO ()
    defaultMainWithHooks (UserHooks
    simpleUserHooks {
                                confHook = confCodeGenHook name version
                                           pkgName pkgVersion
                                           verbose
                                           overridesFile overrides outputDir
                                           (confHook simpleUserHooks)
                              })

    compatGenConfHook :: String -- ^ New version of the package
                      -> [Text] -- ^ The list of modules to re-export
                      -> ConfHook -- ^ previous `confHook`
                      -> ConfHook
    compatGenConfHook :: String -> [Text] -> ConfHook -> ConfHook
    compatGenConfHook String
    newVersion [Text]
    modules ConfHook
    defaultConfHook (GenericPackageDescription
    gpd, HookedBuildInfo
    hbi) ConfigFlags
    flags = do
      let em' :: [ModuleName]
    em' = (Text -> ModuleName) -> [Text] -> [ModuleName]
    forall a b. (a -> b) -> [a] -> [b]
    map (String -> ModuleName
    forall a. IsString a => String -> a
    MN.fromString (String -> ModuleName) -> (Text -> String) -> Text -> ModuleName
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack) [Text]
    modules
          lib :: Library
    lib = ((CondTree ConfVar [Dependency] Library -> Library
    forall v c a. CondTree v c a -> a
    condTreeData (CondTree ConfVar [Dependency] Library -> Library)
    -> (GenericPackageDescription
        -> CondTree ConfVar [Dependency] Library)
    -> GenericPackageDescription
    -> Library
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Maybe (CondTree ConfVar [Dependency] Library)
    -> CondTree ConfVar [Dependency] Library
    forall a. HasCallStack => Maybe a -> a
    fromJust (Maybe (CondTree ConfVar [Dependency] Library)
     -> CondTree ConfVar [Dependency] Library)
    -> (GenericPackageDescription
        -> Maybe (CondTree ConfVar [Dependency] Library))
    -> GenericPackageDescription
    -> CondTree ConfVar [Dependency] Library
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GenericPackageDescription
    -> Maybe (CondTree ConfVar [Dependency] Library)
    condLibrary) GenericPackageDescription
    gpd)
          bi :: BuildInfo
    bi = Library -> BuildInfo
    libBuildInfo Library
    lib
    #if MIN_VERSION_base(4,11,0)
          bi' :: BuildInfo
    bi' = BuildInfo
    bi {autogenModules = em'}
    #else
          bi' = bi
    #endif
          lib' :: Library
    lib' = Library
    lib {exposedModules = em', libBuildInfo = bi'}
          cL' :: CondTree ConfVar [Dependency] Library
    cL' = ((Maybe (CondTree ConfVar [Dependency] Library)
    -> CondTree ConfVar [Dependency] Library
    forall a. HasCallStack => Maybe a -> a
    fromJust (Maybe (CondTree ConfVar [Dependency] Library)
     -> CondTree ConfVar [Dependency] Library)
    -> (GenericPackageDescription
        -> Maybe (CondTree ConfVar [Dependency] Library))
    -> GenericPackageDescription
    -> CondTree ConfVar [Dependency] Library
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GenericPackageDescription
    -> Maybe (CondTree ConfVar [Dependency] Library)
    condLibrary) GenericPackageDescription
    gpd) {condTreeData = lib'}
          gpd' :: GenericPackageDescription
    gpd' = GenericPackageDescription
    gpd {condLibrary = Just cL'}

      (Text -> IO ()) -> [Text] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ (String -> IO ()
    writeCompatModule (String -> IO ()) -> (Text -> String) -> Text -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack) [Text]
    modules

      lbi <- ConfHook
    defaultConfHook (GenericPackageDescription
    gpd', HookedBuildInfo
    hbi) ConfigFlags
    flags

      return (lbi {withOptimization = NoOptimisation})

      where
        writeCompatModule :: String -> IO ()
        writeCompatModule :: String -> IO ()
    writeCompatModule String
    modName = do
          fname <- case [String] -> Maybe ([String], String)
    forall a. [a] -> Maybe ([a], a)
    unsnoc (Char -> String -> [String]
    forall a. Eq a => a -> [a] -> [[a]]
    splitOn Char
    '.' String
    modName) of
                     Maybe ([String], String)
    Nothing -> String -> IO String
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String -> IO String) -> String -> IO String
    forall a b. (a -> b) -> a -> b
    $ String
    modName String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    ".hs"
                     Just ([], String
    last) -> String -> IO String
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String -> IO String) -> String -> IO String
    forall a b. (a -> b) -> a -> b
    $ String
    last String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    ".hs"
                     Just ([String]
    init, String
    last) -> let path :: String
    path = [String] -> String
    joinPath [String]
    init
                                          in do
                                            Bool -> String -> IO ()
    createDirectoryIfMissing Bool
    True String
    path
                                            String -> IO String
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String -> IO String) -> String -> IO String
    forall a b. (a -> b) -> a -> b
    $ String
    path String -> String -> String
    </> (String
    last String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    ".hs")
          utf8WriteFile fname modContents

          where modContents :: Text
                modContents :: Text
    modContents = let
                  mod :: Text
    mod = String -> Text
    T.pack String
    modName
                  link :: Text
    link = Text
    "[" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> String -> Text
    T.pack String
    newVersion
                         Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "](https://hackage.haskell.org/package/"
                         Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> String -> Text
    T.pack String
    newVersion Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    ")"
                  in [Text] -> Text
    T.unlines [
                  Text
    "{-# LANGUAGE PackageImports #-}"
                  , Text
    "{- | This is a backwards-compatibility module re-exporting the contents of the "
                  , Text
    mod Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    " module in the " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    link Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    " package."
                  , Text
    ""
                  , Text
    "The link below will take you to the relevant entry in the " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    link Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    " documentation."
                  , Text
    "-}"
                  , Text
    "module " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    mod Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    " ("
                  , Text
    "  module X) where"
                  , Text
    ""
                  , Text
    "import \"" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> String -> Text
    T.pack String
    newVersion Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "\" " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    mod Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    " as X"
                  ]

                -- Data.List.unsnoc is relatively recent (base 4.19.0.0),
                -- so we just copy the definition.
                unsnoc :: [a] -> Maybe ([a], a)
                unsnoc :: forall a. [a] -> Maybe ([a], a)
    unsnoc = (a -> Maybe ([a], a) -> Maybe ([a], a))
    -> Maybe ([a], a) -> [a] -> Maybe ([a], a)
    forall a b. (a -> b -> b) -> b -> [a] -> b
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (\a
    x -> ([a], a) -> Maybe ([a], a)
    forall a. a -> Maybe a
    Just (([a], a) -> Maybe ([a], a))
    -> (Maybe ([a], a) -> ([a], a)) -> Maybe ([a], a) -> Maybe ([a], a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([a], a) -> (([a], a) -> ([a], a)) -> Maybe ([a], a) -> ([a], a)
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe ([], a
    x) (\(~([a]
    a, a
    b)) -> (a
    x a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : [a]
    a, a
    b))) Maybe ([a], a)
    forall a. Maybe a
    Nothing

    -- | The entry point for @Setup.hs@ files in compat bindings.
    setupCompatWrapper :: String   -- ^ New package
                       -> [Text] -- ^ List of files in the new package
                       -> IO ()
    setupCompatWrapper :: String -> [Text] -> IO ()
    setupCompatWrapper String
    newPackage [Text]
    modules =
        UserHooks -> IO ()
    defaultMainWithHooks (UserHooks
    simpleUserHooks {
                                confHook = compatGenConfHook newPackage modules
                                           (confHook simpleUserHooks)
                              })

    -- | Return the list of modules that `setupHaskellGIBinding` would
    -- create, together with the set of dependencies loaded while
    -- generating the code.
    configureDryRun :: Text -- ^ name
                    -> Text -- ^ version
                    -> Text -- ^ pkgName
                    -> Text -- ^ pkgVersion
                    -> Maybe FilePath -- ^ Overrides file
                    -> [TaggedOverride] -- ^ Other overrides to load
                    -> IO ([Text], S.Set Text)
    configureDryRun :: Text
    -> Text
    -> Text
    -> Text
    -> Maybe String
    -> [TaggedOverride]
    -> IO ([Text], Set Text)
    configureDryRun Text
    name Text
    version Text
    pkgName Text
    pkgVersion Maybe String
    overridesFile [TaggedOverride]
    inheritedOverrides = do
      givenOvs <- (String -> IO TaggedOverride)
    -> Maybe String -> IO (Maybe TaggedOverride)
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> Maybe a -> f (Maybe b)
    traverse (\String
    fname -> Text -> Text -> TaggedOverride
    TaggedOverride (String -> Text
    T.pack String
    fname) (Text -> TaggedOverride) -> IO Text -> IO TaggedOverride
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> IO Text
    utf8ReadFile String
    fname) Maybe String
    overridesFile

      let ovs = [TaggedOverride]
    -> (TaggedOverride -> [TaggedOverride])
    -> Maybe TaggedOverride
    -> [TaggedOverride]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [TaggedOverride]
    inheritedOverrides (TaggedOverride -> [TaggedOverride] -> [TaggedOverride]
    forall a. a -> [a] -> [a]
    :[TaggedOverride]
    inheritedOverrides) Maybe TaggedOverride
    givenOvs
      m <- genModuleCode name version pkgName pkgVersion False ovs

      return (("GI." <> ucFirst name <> ".Config") : listModuleTree m,
               transitiveModuleDeps m)