-----------------------------------------------------------------------------
-- |
-- Module      :  Distribution.Simple
-- Copyright   :  Isaac Jones 2003-2005
--
-- Maintainer  :  cabal-devel@haskell.org
-- Portability :  portable
--
-- This is the command line front end to the Simple build system. When given
-- the parsed command-line args and package information, is able to perform
-- basic commands like configure, build, install, register, etc.
--
-- This module exports the main functions that Setup.hs scripts use. It
-- re-exports the 'UserHooks' type, the standard entry points like
-- 'defaultMain' and 'defaultMainWithHooks' and the predefined sets of
-- 'UserHooks' that custom @Setup.hs@ scripts can extend to add their own
-- behaviour.
--
-- This module isn't called \"Simple\" because it's simple.  Far from
-- it.  It's called \"Simple\" because it does complicated things to
-- simple software.
--
-- The original idea was that there could be different build systems that all
-- presented the same compatible command line interfaces. There is still a
-- "Distribution.Make" system but in practice no packages use it.

{- All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.

    * Neither the name of Isaac Jones nor the names of other
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -}

{-
Work around this warning:
libraries/Cabal/Distribution/Simple.hs:78:0:
    Warning: In the use of `runTests'
             (imported from Distribution.Simple.UserHooks):
             Deprecated: "Please use the new testing interface instead!"
-}
{-# OPTIONS_GHC -fno-warn-deprecations #-}

module Distribution.Simple (
        module Distribution.Package,
        module Distribution.Version,
        module Distribution.License,
        module Distribution.Simple.Compiler,
        module Language.Haskell.Extension,
        -- * Simple interface
        defaultMain, defaultMainNoRead, defaultMainArgs,
        -- * Customization
        UserHooks(..), Args,
        defaultMainWithHooks, defaultMainWithHooksArgs,
        -- ** Standard sets of hooks
        simpleUserHooks,
        autoconfUserHooks,
        defaultUserHooks, emptyUserHooks,
        -- ** Utils
        defaultHookedPackageDesc
  ) where

-- local
import Distribution.Simple.Compiler hiding (Flag)
import Distribution.Simple.UserHooks
import Distribution.Package --must not specify imports, since we're exporting moule.
import Distribution.PackageDescription
         ( PackageDescription(..), GenericPackageDescription, Executable(..)
         , updatePackageDescription, hasLibs
         , HookedBuildInfo, emptyHookedBuildInfo )
import Distribution.PackageDescription.Parse
         ( readPackageDescription, readHookedBuildInfo )
import Distribution.PackageDescription.Configuration
         ( flattenPackageDescription )
import Distribution.Simple.Program
         ( defaultProgramConfiguration, addKnownPrograms, builtinPrograms
         , restoreProgramConfiguration, reconfigurePrograms )
import Distribution.Simple.PreProcess (knownSuffixHandlers, PPSuffixHandler)
import Distribution.Simple.Setup
import Distribution.Simple.Command

import Distribution.Simple.Build        ( build )
import Distribution.Simple.SrcDist      ( sdist )
import Distribution.Simple.Register
         ( register, unregister )

import Distribution.Simple.Configure
         ( getPersistBuildConfig, maybeGetPersistBuildConfig
         , writePersistBuildConfig, checkPersistBuildConfigOutdated
         , configure, checkForeignDeps )

import Distribution.Simple.LocalBuildInfo ( LocalBuildInfo(..) )
import Distribution.Simple.BuildPaths ( srcPref)
import Distribution.Simple.Test (test)
import Distribution.Simple.Install (install)
import Distribution.Simple.Haddock (haddock, hscolour)
import Distribution.Simple.Utils
         (die, notice, info, warn, setupMessage, chattyTry,
          defaultPackageDesc, defaultHookedPackageDesc,
          rawSystemExitWithEnv, cabalVersion, topHandler )
import Distribution.System
         ( OS(..), buildOS )
import Distribution.Verbosity
import Language.Haskell.Extension
import Distribution.Version
import Distribution.License
import Distribution.Text
         ( display )

-- Base
import System.Environment(getArgs, getProgName, getEnvironment)
import System.Directory(removeFile, doesFileExist,
                        doesDirectoryExist, removeDirectoryRecursive)
import System.Exit
import System.IO.Error   (isDoesNotExistError)
import Distribution.Compat.Exception (catchIO, throwIOIO)

import Control.Monad   (when)
import Data.List       (intersperse, unionBy, nub, (\\))

-- | A simple implementation of @main@ for a Cabal setup script.
-- It reads the package description file using IO, and performs the
-- action specified on the command line.
defaultMain :: IO ()
defaultMain = getArgs :: IO [String]getArgs (>>=) :: Monad m => forall a b. m a -> (a -> m b) -> m b>>= defaultMainHelper :: UserHooks -> Args -> IO ()defaultMainHelper simpleUserHooks :: UserHookssimpleUserHooks

-- | A version of 'defaultMain' that is passed the command line
-- arguments, rather than getting them from the environment.
defaultMainArgs :: [String] -> IO ()
defaultMainArgs = defaultMainHelper :: UserHooks -> Args -> IO ()defaultMainHelper simpleUserHooks :: UserHookssimpleUserHooks

-- | A customizable version of 'defaultMain'.
defaultMainWithHooks :: UserHooks -> IO ()
defaultMainWithHooks hooks = getArgs :: IO [String]getArgs (>>=) :: Monad m => forall a b. m a -> (a -> m b) -> m b>>= defaultMainHelper :: UserHooks -> Args -> IO ()defaultMainHelper hooks :: UserHookshooks

-- | A customizable version of 'defaultMain' that also takes the command
-- line arguments.
defaultMainWithHooksArgs :: UserHooks -> [String] -> IO ()
defaultMainWithHooksArgs = defaultMainHelper :: UserHooks -> Args -> IO ()defaultMainHelper

-- | Like 'defaultMain', but accepts the package description as input
-- rather than using IO to read it.
defaultMainNoRead :: GenericPackageDescription -> IO ()
defaultMainNoRead pkg_descr =
  getArgs :: IO [String]getArgs (>>=) :: Monad m => forall a b. m a -> (a -> m b) -> m b>>=
  defaultMainHelper :: UserHooks -> Args -> IO ()defaultMainHelper simpleUserHooks :: UserHookssimpleUserHooks { readDesc = return :: Monad m => forall a. a -> m areturn (Just :: a -> Maybe aJust pkg_descr :: GenericPackageDescriptionpkg_descr) }

defaultMainHelper :: UserHooks -> Args -> IO ()
defaultMainHelper hooks args = topHandler :: IO a -> IO atopHandler ($) :: (a -> b) -> a -> b$
  case commandsRun ::
  CommandUI a
  -> [Command action]
  -> [String]
  -> CommandParse (a, CommandParse action)commandsRun globalCommand :: CommandUI GlobalFlagsglobalCommand commands :: [Command (IO ())]commands args :: Argsargs of
    CommandHelp   help                 -> printHelp :: (String -> String) -> IO ()printHelp help :: String -> Stringhelp
    CommandList   opts                 -> printOptionsList :: [String] -> IO ()printOptionsList opts :: [String]opts
    CommandErrors errs                 -> printErrors :: [[Char]] -> IO bprintErrors errs :: [[Char]]errs
    CommandReadyToGo (flags, commandParse)  ->
      case commandParse :: CommandParse (IO ())commandParse of
        _ | fromFlag :: Flag a -> afromFlag (globalVersion :: GlobalFlags -> Flag BoolglobalVersion flags :: GlobalFlagsflags)        -> printVersion :: IO ()printVersion
          | fromFlag :: Flag a -> afromFlag (globalNumericVersion :: GlobalFlags -> Flag BoolglobalNumericVersion flags :: GlobalFlagsflags) -> printNumericVersion :: IO ()printNumericVersion
        CommandHelp     help           -> printHelp :: (String -> String) -> IO ()printHelp help :: String -> Stringhelp
        CommandList     opts           -> printOptionsList :: [String] -> IO ()printOptionsList opts :: [String]opts
        CommandErrors   errs           -> printErrors :: [[Char]] -> IO bprintErrors errs :: [[Char]]errs
        CommandReadyToGo action        -> action :: IO ()action

  where
    printHelp help = getProgName :: IO StringgetProgName (>>=) :: Monad m => forall a b. m a -> (a -> m b) -> m b>>= putStr :: String -> IO ()putStr (.) :: (b -> c) -> (a -> b) -> a -> c. help :: String -> Stringhelp
    printOptionsList = putStr :: String -> IO ()putStr (.) :: (b -> c) -> (a -> b) -> a -> c. unlines :: [String] -> Stringunlines
    printErrors errs = do
      putStr :: String -> IO ()putStr (concat :: [[a]] -> [a]concat (intersperse :: a -> [a] -> [a]intersperse "\n" errs :: [[Char]]errs))
      exitWith :: ExitCode -> IO aexitWith (ExitFailure :: Int -> ExitCodeExitFailure 1)
    printNumericVersion = putStrLn :: String -> IO ()putStrLn ($) :: (a -> b) -> a -> b$ display :: Text a => a -> Stringdisplay cabalVersion :: VersioncabalVersion
    printVersion        = putStrLn :: String -> IO ()putStrLn ($) :: (a -> b) -> a -> b$ "Cabal library version "
                                  (++) :: [a] -> [a] -> [a]++ display :: Text a => a -> Stringdisplay cabalVersion :: VersioncabalVersion

    progs = addKnownPrograms :: [Program] -> ProgramDb -> ProgramDbaddKnownPrograms (hookedPrograms :: UserHooks -> [Program]hookedPrograms hooks :: UserHookshooks) defaultProgramConfiguration :: ProgramConfigurationdefaultProgramConfiguration
    commands =
      [configureCommand :: ProgramConfiguration -> CommandUI ConfigFlagsconfigureCommand progs :: ProgramDbprogs commandAddAction ::
  CommandUI flags -> (flags -> [String] -> action) -> Command action`commandAddAction` \fs as ->
                                                 configureAction ::
  UserHooks -> ConfigFlags -> Args -> IO LocalBuildInfoconfigureAction    hooks :: UserHookshooks fs :: ConfigFlagsfs as :: [String]as (>>) :: Monad m => forall a b. m a -> m b -> m b>> return :: Monad m => forall a. a -> m areturn ()
      ,buildCommand :: ProgramConfiguration -> CommandUI BuildFlagsbuildCommand     progs :: ProgramDbprogs commandAddAction ::
  CommandUI flags -> (flags -> [String] -> action) -> Command action`commandAddAction` buildAction :: UserHooks -> BuildFlags -> Args -> IO ()buildAction        hooks :: UserHookshooks
      ,installCommand :: CommandUI InstallFlagsinstallCommand         commandAddAction ::
  CommandUI flags -> (flags -> [String] -> action) -> Command action`commandAddAction` installAction :: UserHooks -> InstallFlags -> Args -> IO ()installAction      hooks :: UserHookshooks
      ,copyCommand :: CommandUI CopyFlagscopyCommand            commandAddAction ::
  CommandUI flags -> (flags -> [String] -> action) -> Command action`commandAddAction` copyAction :: UserHooks -> CopyFlags -> Args -> IO ()copyAction         hooks :: UserHookshooks
      ,haddockCommand :: CommandUI HaddockFlagshaddockCommand         commandAddAction ::
  CommandUI flags -> (flags -> [String] -> action) -> Command action`commandAddAction` haddockAction :: UserHooks -> HaddockFlags -> Args -> IO ()haddockAction      hooks :: UserHookshooks
      ,cleanCommand :: CommandUI CleanFlagscleanCommand           commandAddAction ::
  CommandUI flags -> (flags -> [String] -> action) -> Command action`commandAddAction` cleanAction :: UserHooks -> CleanFlags -> Args -> IO ()cleanAction        hooks :: UserHookshooks
      ,sdistCommand :: CommandUI SDistFlagssdistCommand           commandAddAction ::
  CommandUI flags -> (flags -> [String] -> action) -> Command action`commandAddAction` sdistAction :: UserHooks -> SDistFlags -> Args -> IO ()sdistAction        hooks :: UserHookshooks
      ,hscolourCommand :: CommandUI HscolourFlagshscolourCommand        commandAddAction ::
  CommandUI flags -> (flags -> [String] -> action) -> Command action`commandAddAction` hscolourAction :: UserHooks -> HscolourFlags -> Args -> IO ()hscolourAction     hooks :: UserHookshooks
      ,registerCommand :: CommandUI RegisterFlagsregisterCommand        commandAddAction ::
  CommandUI flags -> (flags -> [String] -> action) -> Command action`commandAddAction` registerAction :: UserHooks -> RegisterFlags -> Args -> IO ()registerAction     hooks :: UserHookshooks
      ,unregisterCommand :: CommandUI RegisterFlagsunregisterCommand      commandAddAction ::
  CommandUI flags -> (flags -> [String] -> action) -> Command action`commandAddAction` unregisterAction :: UserHooks -> RegisterFlags -> Args -> IO ()unregisterAction   hooks :: UserHookshooks
      ,testCommand :: CommandUI TestFlagstestCommand            commandAddAction ::
  CommandUI flags -> (flags -> [String] -> action) -> Command action`commandAddAction` testAction :: UserHooks -> TestFlags -> Args -> IO ()testAction         hooks :: UserHookshooks
      ]

-- | Combine the preprocessors in the given hooks with the
-- preprocessors built into cabal.
allSuffixHandlers :: UserHooks
                  -> [PPSuffixHandler]
allSuffixHandlers hooks
    = overridesPP ::
  [PPSuffixHandler] -> [PPSuffixHandler] -> [PPSuffixHandler]overridesPP (hookedPreProcessors :: UserHooks -> [PPSuffixHandler]hookedPreProcessors hooks :: UserHookshooks) knownSuffixHandlers :: [PPSuffixHandler]knownSuffixHandlers
    where
      overridesPP :: [PPSuffixHandler] -> [PPSuffixHandler] -> [PPSuffixHandler]
      overridesPP = unionBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]unionBy (\x y -> fst :: (a, b) -> afst x :: PPSuffixHandlerx (==) :: Eq a => a -> a -> Bool== fst :: (a, b) -> afst y :: PPSuffixHandlery)

configureAction :: UserHooks -> ConfigFlags -> Args -> IO LocalBuildInfo
configureAction hooks flags args = do
                let distPref = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ configDistPref :: ConfigFlags -> Flag FilePathconfigDistPref flags :: GlobalFlagsflags
                pbi <- preConf :: UserHooks -> Args -> ConfigFlags -> IO HookedBuildInfopreConf hooks :: UserHookshooks args :: Argsargs flags :: GlobalFlagsflags

                (mb_pd_file, pkg_descr0) <- confPkgDescr :: IO (Maybe FilePath, GenericPackageDescription)confPkgDescr

                --    get_pkg_descr (configVerbosity flags')
                --let pkg_descr = updatePackageDescription pbi pkg_descr0
                let epkg_descr = (pkg_descr0 :: GenericPackageDescriptionpkg_descr0, pbi :: HookedBuildInfopbi)

                --(warns, ers) <- sanityCheckPackage pkg_descr
                --errorOut (configVerbosity flags') warns ers

                localbuildinfo0 <- confHook ::
  UserHooks
  -> (GenericPackageDescription, HookedBuildInfo)
  -> ConfigFlags
  -> IO LocalBuildInfoconfHook hooks :: UserHookshooks epkg_descr :: (GenericPackageDescription, HookedBuildInfo)epkg_descr flags :: GlobalFlagsflags

                -- remember the .cabal filename if we know it
                -- and all the extra command line args
                let localbuildinfo = localbuildinfo0 :: LocalBuildInfolocalbuildinfo0 {
                                       pkgDescrFile = mb_pd_file :: Maybe FilePathmb_pd_file,
                                       extraConfigArgs = args :: Argsargs
                                     }
                writePersistBuildConfig :: FilePath -> LocalBuildInfo -> IO ()writePersistBuildConfig distPref :: FilePathdistPref localbuildinfo :: LocalBuildInfolocalbuildinfo

                let pkg_descr = localPkgDescr :: LocalBuildInfo -> PackageDescriptionlocalPkgDescr localbuildinfo :: LocalBuildInfolocalbuildinfo
                postConf ::
  UserHooks
  -> Args
  -> ConfigFlags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()postConf hooks :: UserHookshooks args :: Argsargs flags :: GlobalFlagsflags pkg_descr :: GenericPackageDescriptionpkg_descr localbuildinfo :: LocalBuildInfolocalbuildinfo
                return :: Monad m => forall a. a -> m areturn localbuildinfo :: LocalBuildInfolocalbuildinfo
              where
                verbosity = fromFlag :: Flag a -> afromFlag (configVerbosity :: ConfigFlags -> Flag VerbosityconfigVerbosity flags :: GlobalFlagsflags)
                confPkgDescr :: IO (Maybe FilePath, GenericPackageDescription)
                confPkgDescr = do
                  mdescr <- readDesc :: UserHooks -> IO (Maybe GenericPackageDescription)readDesc hooks :: UserHookshooks
                  case mdescr :: Maybe GenericPackageDescriptionmdescr of
                    Just descr -> return :: Monad m => forall a. a -> m areturn (Nothing :: Maybe aNothing, descr :: GenericPackageDescriptiondescr)
                    Nothing -> do
                      pdfile <- defaultPackageDesc :: Verbosity -> IO FilePathdefaultPackageDesc verbosity :: Verbosityverbosity
                      descr  <- readPackageDescription ::
  Verbosity -> FilePath -> IO GenericPackageDescriptionreadPackageDescription verbosity :: Verbosityverbosity pdfile :: FilePathpdfile
                      return :: Monad m => forall a. a -> m areturn (Just :: a -> Maybe aJust pdfile :: FilePathpdfile, descr :: GenericPackageDescriptiondescr)

buildAction :: UserHooks -> BuildFlags -> Args -> IO ()
buildAction hooks flags args = do
  let distPref  = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ buildDistPref :: BuildFlags -> Flag FilePathbuildDistPref flags :: GlobalFlagsflags
      verbosity = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ buildVerbosity :: BuildFlags -> Flag VerbositybuildVerbosity flags :: GlobalFlagsflags

  lbi <- getBuildConfig ::
  UserHooks -> Verbosity -> FilePath -> IO LocalBuildInfogetBuildConfig hooks :: UserHookshooks verbosity :: Verbosityverbosity distPref :: FilePathdistPref
  progs <- reconfigurePrograms ::
  Verbosity
  -> [(String, FilePath)]
  -> [(String, [ProgArg])]
  -> ProgramDb
  -> IO ProgramDbreconfigurePrograms verbosity :: Verbosityverbosity
             (buildProgramPaths :: BuildFlags -> [(String, FilePath)]buildProgramPaths flags :: GlobalFlagsflags)
             (buildProgramArgs :: BuildFlags -> [(String, [String])]buildProgramArgs flags :: GlobalFlagsflags)
             (withPrograms :: LocalBuildInfo -> ProgramConfigurationwithPrograms lbi :: LocalBuildInfolbi)

  hookedAction ::
  (UserHooks -> Args -> flags -> IO HookedBuildInfo)
  -> (UserHooks
      -> PackageDescription
      -> LocalBuildInfo
      -> UserHooks
      -> flags
      -> IO ())
  -> (UserHooks
      -> Args
      -> flags
      -> PackageDescription
      -> LocalBuildInfo
      -> IO ())
  -> IO LocalBuildInfo
  -> UserHooks
  -> flags
  -> Args
  -> IO ()hookedAction preBuild :: UserHooks -> Args -> BuildFlags -> IO HookedBuildInfopreBuild buildHook ::
  UserHooks
  -> PackageDescription
  -> LocalBuildInfo
  -> UserHooks
  -> BuildFlags
  -> IO ()buildHook postBuild ::
  UserHooks
  -> Args
  -> BuildFlags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()postBuild
               (return :: Monad m => forall a. a -> m areturn lbi :: LocalBuildInfolbi { withPrograms = progs :: ProgramDbprogs })
               hooks :: UserHookshooks flags :: GlobalFlagsflags args :: Argsargs

hscolourAction :: UserHooks -> HscolourFlags -> Args -> IO ()
hscolourAction hooks flags args
    = do let distPref  = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ hscolourDistPref :: HscolourFlags -> Flag FilePathhscolourDistPref flags :: GlobalFlagsflags
             verbosity = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ hscolourVerbosity :: HscolourFlags -> Flag VerbosityhscolourVerbosity flags :: GlobalFlagsflags
         hookedAction ::
  (UserHooks -> Args -> flags -> IO HookedBuildInfo)
  -> (UserHooks
      -> PackageDescription
      -> LocalBuildInfo
      -> UserHooks
      -> flags
      -> IO ())
  -> (UserHooks
      -> Args
      -> flags
      -> PackageDescription
      -> LocalBuildInfo
      -> IO ())
  -> IO LocalBuildInfo
  -> UserHooks
  -> flags
  -> Args
  -> IO ()hookedAction preHscolour ::
  UserHooks -> Args -> HscolourFlags -> IO HookedBuildInfopreHscolour hscolourHook ::
  UserHooks
  -> PackageDescription
  -> LocalBuildInfo
  -> UserHooks
  -> HscolourFlags
  -> IO ()hscolourHook postHscolour ::
  UserHooks
  -> Args
  -> HscolourFlags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()postHscolour
                      (getBuildConfig ::
  UserHooks -> Verbosity -> FilePath -> IO LocalBuildInfogetBuildConfig hooks :: UserHookshooks verbosity :: Verbosityverbosity distPref :: FilePathdistPref)
                      hooks :: UserHookshooks flags :: GlobalFlagsflags args :: Argsargs

haddockAction :: UserHooks -> HaddockFlags -> Args -> IO ()
haddockAction hooks flags args = do
  let distPref  = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ haddockDistPref :: HaddockFlags -> Flag FilePathhaddockDistPref flags :: GlobalFlagsflags
      verbosity = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ haddockVerbosity :: HaddockFlags -> Flag VerbosityhaddockVerbosity flags :: GlobalFlagsflags

  lbi <- getBuildConfig ::
  UserHooks -> Verbosity -> FilePath -> IO LocalBuildInfogetBuildConfig hooks :: UserHookshooks verbosity :: Verbosityverbosity distPref :: FilePathdistPref
  progs <- reconfigurePrograms ::
  Verbosity
  -> [(String, FilePath)]
  -> [(String, [ProgArg])]
  -> ProgramDb
  -> IO ProgramDbreconfigurePrograms verbosity :: Verbosityverbosity
             (haddockProgramPaths :: HaddockFlags -> [(String, FilePath)]haddockProgramPaths flags :: GlobalFlagsflags)
             (haddockProgramArgs :: HaddockFlags -> [(String, [String])]haddockProgramArgs flags :: GlobalFlagsflags)
             (withPrograms :: LocalBuildInfo -> ProgramConfigurationwithPrograms lbi :: LocalBuildInfolbi)

  hookedAction ::
  (UserHooks -> Args -> flags -> IO HookedBuildInfo)
  -> (UserHooks
      -> PackageDescription
      -> LocalBuildInfo
      -> UserHooks
      -> flags
      -> IO ())
  -> (UserHooks
      -> Args
      -> flags
      -> PackageDescription
      -> LocalBuildInfo
      -> IO ())
  -> IO LocalBuildInfo
  -> UserHooks
  -> flags
  -> Args
  -> IO ()hookedAction preHaddock ::
  UserHooks -> Args -> HaddockFlags -> IO HookedBuildInfopreHaddock haddockHook ::
  UserHooks
  -> PackageDescription
  -> LocalBuildInfo
  -> UserHooks
  -> HaddockFlags
  -> IO ()haddockHook postHaddock ::
  UserHooks
  -> Args
  -> HaddockFlags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()postHaddock
               (return :: Monad m => forall a. a -> m areturn lbi :: LocalBuildInfolbi { withPrograms = progs :: ProgramDbprogs })
               hooks :: UserHookshooks flags :: GlobalFlagsflags args :: Argsargs

cleanAction :: UserHooks -> CleanFlags -> Args -> IO ()
cleanAction hooks flags args = do
                pbi <- preClean :: UserHooks -> Args -> CleanFlags -> IO HookedBuildInfopreClean hooks :: UserHookshooks args :: Argsargs flags :: GlobalFlagsflags

                pdfile <- defaultPackageDesc :: Verbosity -> IO FilePathdefaultPackageDesc verbosity :: Verbosityverbosity
                ppd <- readPackageDescription ::
  Verbosity -> FilePath -> IO GenericPackageDescriptionreadPackageDescription verbosity :: Verbosityverbosity pdfile :: FilePathpdfile
                let pkg_descr0 = flattenPackageDescription ::
  GenericPackageDescription -> PackageDescriptionflattenPackageDescription ppd :: GenericPackageDescriptionppd
                -- We don't sanity check for clean as an error
                -- here would prevent cleaning:
                --sanityCheckHookedBuildInfo pkg_descr0 pbi
                let pkg_descr = updatePackageDescription ::
  HookedBuildInfo -> PackageDescription -> PackageDescriptionupdatePackageDescription pbi :: HookedBuildInfopbi pkg_descr0 :: GenericPackageDescriptionpkg_descr0

                cleanHook ::
  UserHooks
  -> PackageDescription
  -> ()
  -> UserHooks
  -> CleanFlags
  -> IO ()cleanHook hooks :: UserHookshooks pkg_descr :: GenericPackageDescriptionpkg_descr () hooks :: UserHookshooks flags :: GlobalFlagsflags
                postClean ::
  UserHooks
  -> Args
  -> CleanFlags
  -> PackageDescription
  -> ()
  -> IO ()postClean hooks :: UserHookshooks args :: Argsargs flags :: GlobalFlagsflags pkg_descr :: GenericPackageDescriptionpkg_descr ()
  where verbosity = fromFlag :: Flag a -> afromFlag (cleanVerbosity :: CleanFlags -> Flag VerbositycleanVerbosity flags :: GlobalFlagsflags)

copyAction :: UserHooks -> CopyFlags -> Args -> IO ()
copyAction hooks flags args
    = do let distPref  = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ copyDistPref :: CopyFlags -> Flag FilePathcopyDistPref flags :: GlobalFlagsflags
             verbosity = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ copyVerbosity :: CopyFlags -> Flag VerbositycopyVerbosity flags :: GlobalFlagsflags
         hookedAction ::
  (UserHooks -> Args -> flags -> IO HookedBuildInfo)
  -> (UserHooks
      -> PackageDescription
      -> LocalBuildInfo
      -> UserHooks
      -> flags
      -> IO ())
  -> (UserHooks
      -> Args
      -> flags
      -> PackageDescription
      -> LocalBuildInfo
      -> IO ())
  -> IO LocalBuildInfo
  -> UserHooks
  -> flags
  -> Args
  -> IO ()hookedAction preCopy :: UserHooks -> Args -> CopyFlags -> IO HookedBuildInfopreCopy copyHook ::
  UserHooks
  -> PackageDescription
  -> LocalBuildInfo
  -> UserHooks
  -> CopyFlags
  -> IO ()copyHook postCopy ::
  UserHooks
  -> Args
  -> CopyFlags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()postCopy
                      (getBuildConfig ::
  UserHooks -> Verbosity -> FilePath -> IO LocalBuildInfogetBuildConfig hooks :: UserHookshooks verbosity :: Verbosityverbosity distPref :: FilePathdistPref)
                      hooks :: UserHookshooks flags :: GlobalFlagsflags args :: Argsargs

installAction :: UserHooks -> InstallFlags -> Args -> IO ()
installAction hooks flags args
    = do let distPref  = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ installDistPref :: InstallFlags -> Flag FilePathinstallDistPref flags :: GlobalFlagsflags
             verbosity = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ installVerbosity :: InstallFlags -> Flag VerbosityinstallVerbosity flags :: GlobalFlagsflags
         hookedAction ::
  (UserHooks -> Args -> flags -> IO HookedBuildInfo)
  -> (UserHooks
      -> PackageDescription
      -> LocalBuildInfo
      -> UserHooks
      -> flags
      -> IO ())
  -> (UserHooks
      -> Args
      -> flags
      -> PackageDescription
      -> LocalBuildInfo
      -> IO ())
  -> IO LocalBuildInfo
  -> UserHooks
  -> flags
  -> Args
  -> IO ()hookedAction preInst :: UserHooks -> Args -> InstallFlags -> IO HookedBuildInfopreInst instHook ::
  UserHooks
  -> PackageDescription
  -> LocalBuildInfo
  -> UserHooks
  -> InstallFlags
  -> IO ()instHook postInst ::
  UserHooks
  -> Args
  -> InstallFlags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()postInst
                      (getBuildConfig ::
  UserHooks -> Verbosity -> FilePath -> IO LocalBuildInfogetBuildConfig hooks :: UserHookshooks verbosity :: Verbosityverbosity distPref :: FilePathdistPref)
                      hooks :: UserHookshooks flags :: GlobalFlagsflags args :: Argsargs

sdistAction :: UserHooks -> SDistFlags -> Args -> IO ()
sdistAction hooks flags args = do
                let distPref = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ sDistDistPref :: SDistFlags -> Flag FilePathsDistDistPref flags :: GlobalFlagsflags
                pbi <- preSDist :: UserHooks -> Args -> SDistFlags -> IO HookedBuildInfopreSDist hooks :: UserHookshooks args :: Argsargs flags :: GlobalFlagsflags

                mlbi <- maybeGetPersistBuildConfig :: FilePath -> IO (Maybe LocalBuildInfo)maybeGetPersistBuildConfig distPref :: FilePathdistPref
                pdfile <- defaultPackageDesc :: Verbosity -> IO FilePathdefaultPackageDesc verbosity :: Verbosityverbosity
                ppd <- readPackageDescription ::
  Verbosity -> FilePath -> IO GenericPackageDescriptionreadPackageDescription verbosity :: Verbosityverbosity pdfile :: FilePathpdfile
                let pkg_descr0 = flattenPackageDescription ::
  GenericPackageDescription -> PackageDescriptionflattenPackageDescription ppd :: GenericPackageDescriptionppd
                sanityCheckHookedBuildInfo ::
  PackageDescription -> HookedBuildInfo -> IO ()sanityCheckHookedBuildInfo pkg_descr0 :: GenericPackageDescriptionpkg_descr0 pbi :: HookedBuildInfopbi
                let pkg_descr = updatePackageDescription ::
  HookedBuildInfo -> PackageDescription -> PackageDescriptionupdatePackageDescription pbi :: HookedBuildInfopbi pkg_descr0 :: GenericPackageDescriptionpkg_descr0

                sDistHook ::
  UserHooks
  -> PackageDescription
  -> Maybe LocalBuildInfo
  -> UserHooks
  -> SDistFlags
  -> IO ()sDistHook hooks :: UserHookshooks pkg_descr :: GenericPackageDescriptionpkg_descr mlbi :: Maybe LocalBuildInfomlbi hooks :: UserHookshooks flags :: GlobalFlagsflags
                postSDist ::
  UserHooks
  -> Args
  -> SDistFlags
  -> PackageDescription
  -> Maybe LocalBuildInfo
  -> IO ()postSDist hooks :: UserHookshooks args :: Argsargs flags :: GlobalFlagsflags pkg_descr :: GenericPackageDescriptionpkg_descr mlbi :: Maybe LocalBuildInfomlbi
  where verbosity = fromFlag :: Flag a -> afromFlag (sDistVerbosity :: SDistFlags -> Flag VerbositysDistVerbosity flags :: GlobalFlagsflags)

testAction :: UserHooks -> TestFlags -> Args -> IO ()
testAction hooks flags args = do
    let distPref  = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ testDistPref :: TestFlags -> Flag FilePathtestDistPref flags :: GlobalFlagsflags
        verbosity = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ testVerbosity :: TestFlags -> Flag VerbositytestVerbosity flags :: GlobalFlagsflags
    localBuildInfo <- getBuildConfig ::
  UserHooks -> Verbosity -> FilePath -> IO LocalBuildInfogetBuildConfig hooks :: UserHookshooks verbosity :: Verbosityverbosity distPref :: FilePathdistPref
    let pkg_descr = localPkgDescr :: LocalBuildInfo -> PackageDescriptionlocalPkgDescr localBuildInfo :: LocalBuildInfolocalBuildInfo
    -- It is safe to do 'runTests' before the new test handler because the
    -- default action is a no-op and if the package uses the old test interface
    -- the new handler will find no tests.
    runTests ::
  UserHooks
  -> Args
  -> Bool
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()runTests hooks :: UserHookshooks args :: Argsargs False :: BoolFalse pkg_descr :: GenericPackageDescriptionpkg_descr localBuildInfo :: LocalBuildInfolocalBuildInfo
    --FIXME: this is a hack, passing the args inside the flags
    -- it's because the args to not get passed to the main test hook
    let flags' = flags :: GlobalFlagsflags { testList = Flag :: a -> Flag aFlag args :: Argsargs }
    hookedAction ::
  (UserHooks -> Args -> flags -> IO HookedBuildInfo)
  -> (UserHooks
      -> PackageDescription
      -> LocalBuildInfo
      -> UserHooks
      -> flags
      -> IO ())
  -> (UserHooks
      -> Args
      -> flags
      -> PackageDescription
      -> LocalBuildInfo
      -> IO ())
  -> IO LocalBuildInfo
  -> UserHooks
  -> flags
  -> Args
  -> IO ()hookedAction preTest :: UserHooks -> Args -> TestFlags -> IO HookedBuildInfopreTest testHook ::
  UserHooks
  -> PackageDescription
  -> LocalBuildInfo
  -> UserHooks
  -> TestFlags
  -> IO ()testHook postTest ::
  UserHooks
  -> Args
  -> TestFlags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()postTest
            (getBuildConfig ::
  UserHooks -> Verbosity -> FilePath -> IO LocalBuildInfogetBuildConfig hooks :: UserHookshooks verbosity :: Verbosityverbosity distPref :: FilePathdistPref)
            hooks :: UserHookshooks flags' :: TestFlagsflags' args :: Argsargs

registerAction :: UserHooks -> RegisterFlags -> Args -> IO ()
registerAction hooks flags args
    = do let distPref  = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ regDistPref :: RegisterFlags -> Flag FilePathregDistPref flags :: GlobalFlagsflags
             verbosity = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ regVerbosity :: RegisterFlags -> Flag VerbosityregVerbosity flags :: GlobalFlagsflags
         hookedAction ::
  (UserHooks -> Args -> flags -> IO HookedBuildInfo)
  -> (UserHooks
      -> PackageDescription
      -> LocalBuildInfo
      -> UserHooks
      -> flags
      -> IO ())
  -> (UserHooks
      -> Args
      -> flags
      -> PackageDescription
      -> LocalBuildInfo
      -> IO ())
  -> IO LocalBuildInfo
  -> UserHooks
  -> flags
  -> Args
  -> IO ()hookedAction preReg :: UserHooks -> Args -> RegisterFlags -> IO HookedBuildInfopreReg regHook ::
  UserHooks
  -> PackageDescription
  -> LocalBuildInfo
  -> UserHooks
  -> RegisterFlags
  -> IO ()regHook postReg ::
  UserHooks
  -> Args
  -> RegisterFlags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()postReg
                      (getBuildConfig ::
  UserHooks -> Verbosity -> FilePath -> IO LocalBuildInfogetBuildConfig hooks :: UserHookshooks verbosity :: Verbosityverbosity distPref :: FilePathdistPref)
                      hooks :: UserHookshooks flags :: GlobalFlagsflags args :: Argsargs

unregisterAction :: UserHooks -> RegisterFlags -> Args -> IO ()
unregisterAction hooks flags args
    = do let distPref  = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ regDistPref :: RegisterFlags -> Flag FilePathregDistPref flags :: GlobalFlagsflags
             verbosity = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ regVerbosity :: RegisterFlags -> Flag VerbosityregVerbosity flags :: GlobalFlagsflags
         hookedAction ::
  (UserHooks -> Args -> flags -> IO HookedBuildInfo)
  -> (UserHooks
      -> PackageDescription
      -> LocalBuildInfo
      -> UserHooks
      -> flags
      -> IO ())
  -> (UserHooks
      -> Args
      -> flags
      -> PackageDescription
      -> LocalBuildInfo
      -> IO ())
  -> IO LocalBuildInfo
  -> UserHooks
  -> flags
  -> Args
  -> IO ()hookedAction preUnreg ::
  UserHooks -> Args -> RegisterFlags -> IO HookedBuildInfopreUnreg unregHook ::
  UserHooks
  -> PackageDescription
  -> LocalBuildInfo
  -> UserHooks
  -> RegisterFlags
  -> IO ()unregHook postUnreg ::
  UserHooks
  -> Args
  -> RegisterFlags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()postUnreg
                      (getBuildConfig ::
  UserHooks -> Verbosity -> FilePath -> IO LocalBuildInfogetBuildConfig hooks :: UserHookshooks verbosity :: Verbosityverbosity distPref :: FilePathdistPref)
                      hooks :: UserHookshooks flags :: GlobalFlagsflags args :: Argsargs

hookedAction :: (UserHooks -> Args -> flags -> IO HookedBuildInfo)
        -> (UserHooks -> PackageDescription -> LocalBuildInfo
                      -> UserHooks -> flags -> IO ())
        -> (UserHooks -> Args -> flags -> PackageDescription
                      -> LocalBuildInfo -> IO ())
        -> IO LocalBuildInfo
        -> UserHooks -> flags -> Args -> IO ()
hookedAction pre_hook cmd_hook post_hook get_build_config hooks flags args = do
   pbi <- pre_hook :: UserHooks -> Args -> flags -> IO HookedBuildInfopre_hook hooks :: UserHookshooks args :: Argsargs flags :: GlobalFlagsflags
   localbuildinfo <- get_build_config :: IO LocalBuildInfoget_build_config
   let pkg_descr0 = localPkgDescr :: LocalBuildInfo -> PackageDescriptionlocalPkgDescr localbuildinfo :: LocalBuildInfolocalbuildinfo
   --pkg_descr0 <- get_pkg_descr (get_verbose flags)
   sanityCheckHookedBuildInfo ::
  PackageDescription -> HookedBuildInfo -> IO ()sanityCheckHookedBuildInfo pkg_descr0 :: GenericPackageDescriptionpkg_descr0 pbi :: HookedBuildInfopbi
   let pkg_descr = updatePackageDescription ::
  HookedBuildInfo -> PackageDescription -> PackageDescriptionupdatePackageDescription pbi :: HookedBuildInfopbi pkg_descr0 :: GenericPackageDescriptionpkg_descr0
   -- TODO: should we write the modified package descr back to the
   -- localbuildinfo?
   cmd_hook ::
  UserHooks
  -> PackageDescription
  -> LocalBuildInfo
  -> UserHooks
  -> flags
  -> IO ()cmd_hook hooks :: UserHookshooks pkg_descr :: GenericPackageDescriptionpkg_descr localbuildinfo :: LocalBuildInfolocalbuildinfo hooks :: UserHookshooks flags :: GlobalFlagsflags
   post_hook ::
  UserHooks
  -> Args
  -> flags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()post_hook hooks :: UserHookshooks args :: Argsargs flags :: GlobalFlagsflags pkg_descr :: GenericPackageDescriptionpkg_descr localbuildinfo :: LocalBuildInfolocalbuildinfo
  where

sanityCheckHookedBuildInfo :: PackageDescription -> HookedBuildInfo -> IO ()
sanityCheckHookedBuildInfo PackageDescription { library = Nothing } (Just _,_)
    = die :: String -> IO adie ($) :: (a -> b) -> a -> b$ "The buildinfo contains info for a library, "
         (++) :: [a] -> [a] -> [a]++ "but the package does not have a library."

sanityCheckHookedBuildInfo pkg_descr (_, hookExes)
    | not :: Bool -> Boolnot (null :: [a] -> Boolnull nonExistant :: [String]nonExistant)
    = die :: String -> IO adie ($) :: (a -> b) -> a -> b$ "The buildinfo contains info for an executable called '"
         (++) :: [a] -> [a] -> [a]++ head :: [a] -> ahead nonExistant :: [String]nonExistant (++) :: [a] -> [a] -> [a]++ "' but the package does not have a "
         (++) :: [a] -> [a] -> [a]++ "executable with that name."
  where
    pkgExeNames  = nub :: Eq a => [a] -> [a]nub (map :: (a -> b) -> [a] -> [b]map exeName :: Executable -> StringexeName (executables :: PackageDescription -> [Executable]executables pkg_descr :: GenericPackageDescriptionpkg_descr))
    hookExeNames = nub :: Eq a => [a] -> [a]nub (map :: (a -> b) -> [a] -> [b]map fst :: (a, b) -> afst hookExes :: [(String, BuildInfo)]hookExes)
    nonExistant  = hookExeNames :: [String]hookExeNames (\\) :: Eq a => [a] -> [a] -> [a]\\ pkgExeNames :: [String]pkgExeNames

sanityCheckHookedBuildInfo _ _ = return :: Monad m => forall a. a -> m areturn ()


getBuildConfig :: UserHooks -> Verbosity -> FilePath -> IO LocalBuildInfo
getBuildConfig hooks verbosity distPref = do
  lbi_wo_programs <- getPersistBuildConfig :: FilePath -> IO LocalBuildInfogetPersistBuildConfig distPref :: FilePathdistPref
  -- Restore info about unconfigured programs, since it is not serialized
  let lbi = lbi_wo_programs :: LocalBuildInfolbi_wo_programs {
    withPrograms = restoreProgramConfiguration ::
  [Program] -> ProgramConfiguration -> ProgramConfigurationrestoreProgramConfiguration
                     (builtinPrograms :: [Program]builtinPrograms (++) :: [a] -> [a] -> [a]++ hookedPrograms :: UserHooks -> [Program]hookedPrograms hooks :: UserHookshooks)
                     (withPrograms :: LocalBuildInfo -> ProgramConfigurationwithPrograms lbi_wo_programs :: LocalBuildInfolbi_wo_programs)
  }

  case pkgDescrFile :: LocalBuildInfo -> Maybe FilePathpkgDescrFile lbi :: LocalBuildInfolbi of
    Nothing -> return :: Monad m => forall a. a -> m areturn lbi :: LocalBuildInfolbi
    Just pkg_descr_file -> do
      outdated <- checkPersistBuildConfigOutdated :: FilePath -> FilePath -> IO BoolcheckPersistBuildConfigOutdated distPref :: FilePathdistPref pkg_descr_file :: FilePathpkg_descr_file
      if outdated :: Booloutdated
        then reconfigure :: FilePath -> LocalBuildInfo -> IO LocalBuildInforeconfigure pkg_descr_file :: FilePathpkg_descr_file lbi :: LocalBuildInfolbi
        else return :: Monad m => forall a. a -> m areturn lbi :: LocalBuildInfolbi

  where
    reconfigure :: FilePath -> LocalBuildInfo -> IO LocalBuildInfo
    reconfigure pkg_descr_file lbi = do
      notice :: Verbosity -> String -> IO ()notice verbosity :: Verbosityverbosity ($) :: (a -> b) -> a -> b$ pkg_descr_file :: FilePathpkg_descr_file (++) :: [a] -> [a] -> [a]++ " has been changed. "
                      (++) :: [a] -> [a] -> [a]++ "Re-configuring with most recently used options. " 
                      (++) :: [a] -> [a] -> [a]++ "If this fails, please run configure manually.\n"
      let cFlags = configFlags :: LocalBuildInfo -> ConfigFlagsconfigFlags lbi :: LocalBuildInfolbi
      let cFlags' = cFlags :: ConfigFlagscFlags {
            -- Since the list of unconfigured programs is not serialized,
            -- restore it to the same value as normally used at the beginning
            -- of a conigure run:
            configPrograms = restoreProgramConfiguration ::
  [Program] -> ProgramConfiguration -> ProgramConfigurationrestoreProgramConfiguration
                               (builtinPrograms :: [Program]builtinPrograms (++) :: [a] -> [a] -> [a]++ hookedPrograms :: UserHooks -> [Program]hookedPrograms hooks :: UserHookshooks)
                               (configPrograms :: ConfigFlags -> ProgramConfigurationconfigPrograms cFlags :: ConfigFlagscFlags),

            -- Use the current, not saved verbosity level:
            configVerbosity = Flag :: a -> Flag aFlag verbosity :: Verbosityverbosity
          }
      configureAction ::
  UserHooks -> ConfigFlags -> Args -> IO LocalBuildInfoconfigureAction hooks :: UserHookshooks cFlags' :: ConfigFlagscFlags' (extraConfigArgs :: LocalBuildInfo -> [String]extraConfigArgs lbi :: LocalBuildInfolbi)


-- --------------------------------------------------------------------------
-- Cleaning

clean :: PackageDescription -> CleanFlags -> IO ()
clean pkg_descr flags = do
    let distPref = fromFlag :: Flag a -> afromFlag ($) :: (a -> b) -> a -> b$ cleanDistPref :: CleanFlags -> Flag FilePathcleanDistPref flags :: GlobalFlagsflags
    notice :: Verbosity -> String -> IO ()notice verbosity :: Verbosityverbosity "cleaning..."

    maybeConfig <- if fromFlag :: Flag a -> afromFlag (cleanSaveConf :: CleanFlags -> Flag BoolcleanSaveConf flags :: GlobalFlagsflags)
                     then maybeGetPersistBuildConfig :: FilePath -> IO (Maybe LocalBuildInfo)maybeGetPersistBuildConfig distPref :: FilePathdistPref
                     else return :: Monad m => forall a. a -> m areturn Nothing :: Maybe aNothing

    -- remove the whole dist/ directory rather than tracking exactly what files
    -- we created in there.
    chattyTry :: String -> IO () -> IO ()chattyTry "removing dist/" ($) :: (a -> b) -> a -> b$ do
      exists <- doesDirectoryExist :: FilePath -> IO BooldoesDirectoryExist distPref :: FilePathdistPref
      when :: Monad m => Bool -> m () -> m ()when exists :: Boolexists (removeDirectoryRecursive :: FilePath -> IO ()removeDirectoryRecursive distPref :: FilePathdistPref)

    -- Any extra files the user wants to remove
    mapM_ :: Monad m => (a -> m b) -> [a] -> m ()mapM_ removeFileOrDirectory :: FilePath -> IO ()removeFileOrDirectory (extraTmpFiles :: PackageDescription -> [FilePath]extraTmpFiles pkg_descr :: GenericPackageDescriptionpkg_descr)

    -- If the user wanted to save the config, write it back
    maybe :: b -> (a -> b) -> Maybe a -> bmaybe (return :: Monad m => forall a. a -> m areturn ()) (writePersistBuildConfig :: FilePath -> LocalBuildInfo -> IO ()writePersistBuildConfig distPref :: FilePathdistPref) maybeConfig :: Maybe LocalBuildInfomaybeConfig

  where
        removeFileOrDirectory :: FilePath -> IO ()
        removeFileOrDirectory fname = do
            isDir <- doesDirectoryExist :: FilePath -> IO BooldoesDirectoryExist fname :: FilePathfname
            isFile <- doesFileExist :: FilePath -> IO BooldoesFileExist fname :: FilePathfname
            if isDir :: BoolisDir then removeDirectoryRecursive :: FilePath -> IO ()removeDirectoryRecursive fname :: FilePathfname
              else if isFile :: BoolisFile then removeFile :: FilePath -> IO ()removeFile fname :: FilePathfname
              else return :: Monad m => forall a. a -> m areturn ()
        verbosity = fromFlag :: Flag a -> afromFlag (cleanVerbosity :: CleanFlags -> Flag VerbositycleanVerbosity flags :: GlobalFlagsflags)

-- --------------------------------------------------------------------------
-- Default hooks

-- | Hooks that correspond to a plain instantiation of the
-- \"simple\" build system
simpleUserHooks :: UserHooks
simpleUserHooks =
    emptyUserHooks :: UserHooksemptyUserHooks {
       confHook  = configure ::
  (GenericPackageDescription, HookedBuildInfo)
  -> ConfigFlags
  -> IO LocalBuildInfoconfigure,
       postConf  = finalChecks ::
  t -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()finalChecks,
       buildHook = defaultBuildHook ::
  PackageDescription
  -> LocalBuildInfo
  -> UserHooks
  -> BuildFlags
  -> IO ()defaultBuildHook,
       copyHook  = \desc lbi _ f -> install ::
  PackageDescription -> LocalBuildInfo -> CopyFlags -> IO ()install desc :: PackageDescriptiondesc lbi :: LocalBuildInfolbi f :: RegisterFlagsf, -- has correct 'copy' behavior with params
       testHook = defaultTestHook ::
  PackageDescription
  -> LocalBuildInfo
  -> UserHooks
  -> TestFlags
  -> IO ()defaultTestHook,
       instHook  = defaultInstallHook ::
  PackageDescription
  -> LocalBuildInfo
  -> UserHooks
  -> InstallFlags
  -> IO ()defaultInstallHook,
       sDistHook = \p l h f -> sdist ::
  PackageDescription
  -> Maybe LocalBuildInfo
  -> SDistFlags
  -> (FilePath -> FilePath)
  -> [PPSuffixHandler]
  -> IO ()sdist p :: PackageDescriptionp l :: LocalBuildInfol f :: RegisterFlagsf srcPref :: FilePath -> FilePathsrcPref (allSuffixHandlers :: UserHooks -> [PPSuffixHandler]allSuffixHandlers h :: UserHooksh),
       cleanHook = \p _ _ f -> clean :: PackageDescription -> CleanFlags -> IO ()clean p :: PackageDescriptionp f :: RegisterFlagsf,
       hscolourHook = \p l h f -> hscolour ::
  PackageDescription
  -> LocalBuildInfo
  -> [PPSuffixHandler]
  -> HscolourFlags
  -> IO ()hscolour p :: PackageDescriptionp l :: LocalBuildInfol (allSuffixHandlers :: UserHooks -> [PPSuffixHandler]allSuffixHandlers h :: UserHooksh) f :: RegisterFlagsf,
       haddockHook  = \p l h f -> haddock ::
  PackageDescription
  -> LocalBuildInfo
  -> [PPSuffixHandler]
  -> HaddockFlags
  -> IO ()haddock  p :: PackageDescriptionp l :: LocalBuildInfol (allSuffixHandlers :: UserHooks -> [PPSuffixHandler]allSuffixHandlers h :: UserHooksh) f :: RegisterFlagsf,
       regHook   = defaultRegHook ::
  PackageDescription
  -> LocalBuildInfo
  -> UserHooks
  -> RegisterFlags
  -> IO ()defaultRegHook,
       unregHook = \p l _ f -> unregister ::
  PackageDescription -> LocalBuildInfo -> RegisterFlags -> IO ()unregister p :: PackageDescriptionp l :: LocalBuildInfol f :: RegisterFlagsf
      }
  where
    finalChecks _args flags pkg_descr lbi =
      checkForeignDeps ::
  PackageDescription -> LocalBuildInfo -> Verbosity -> IO ()checkForeignDeps pkg_descr :: GenericPackageDescriptionpkg_descr lbi :: LocalBuildInfolbi (lessVerbose :: Verbosity -> VerbositylessVerbose verbosity :: Verbosityverbosity)
      where
        verbosity = fromFlag :: Flag a -> afromFlag (configVerbosity :: ConfigFlags -> Flag VerbosityconfigVerbosity flags :: GlobalFlagsflags)

-- | Basic autoconf 'UserHooks':
--
-- * 'postConf' runs @.\/configure@, if present.
--
-- * the pre-hooks 'preBuild', 'preClean', 'preCopy', 'preInst',
--   'preReg' and 'preUnreg' read additional build information from
--   /package/@.buildinfo@, if present.
--
-- Thus @configure@ can use local system information to generate
-- /package/@.buildinfo@ and possibly other files.

{-# DEPRECATED defaultUserHooks
     "Use simpleUserHooks or autoconfUserHooks, unless you need Cabal-1.2\n             compatibility in which case you must stick with defaultUserHooks" #-}
defaultUserHooks :: UserHooks
defaultUserHooks = autoconfUserHooks :: UserHooksautoconfUserHooks {
          confHook = \pkg flags -> do
                       let verbosity = fromFlag :: Flag a -> afromFlag (configVerbosity :: ConfigFlags -> Flag VerbosityconfigVerbosity flags :: GlobalFlagsflags)
                       warn :: Verbosity -> String -> IO ()warn verbosity :: Verbosityverbosity ($) :: (a -> b) -> a -> b$
                         "defaultUserHooks in Setup script is deprecated."
                       confHook ::
  UserHooks
  -> (GenericPackageDescription, HookedBuildInfo)
  -> ConfigFlags
  -> IO LocalBuildInfoconfHook autoconfUserHooks :: UserHooksautoconfUserHooks pkg :: (GenericPackageDescription, HookedBuildInfo)pkg flags :: GlobalFlagsflags,
          postConf = oldCompatPostConf ::
  [String]
  -> ConfigFlags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()oldCompatPostConf
    }
    -- This is the annoying old version that only runs configure if it exists.
    -- It's here for compatibility with existing Setup.hs scripts. See:
    -- http://hackage.haskell.org/trac/hackage/ticket/165
    where oldCompatPostConf args flags pkg_descr lbi
              = do let verbosity = fromFlag :: Flag a -> afromFlag (configVerbosity :: ConfigFlags -> Flag VerbosityconfigVerbosity flags :: GlobalFlagsflags)
                   noExtraFlags :: [String] -> IO ()noExtraFlags args :: Argsargs
                   confExists <- doesFileExist :: FilePath -> IO BooldoesFileExist "configure"
                   when :: Monad m => Bool -> m () -> m ()when confExists :: BoolconfExists ($) :: (a -> b) -> a -> b$
                       runConfigureScript ::
  Verbosity -> Bool -> ConfigFlags -> LocalBuildInfo -> IO ()runConfigureScript verbosity :: Verbosityverbosity
                         backwardsCompatHack :: BoolbackwardsCompatHack flags :: GlobalFlagsflags lbi :: LocalBuildInfolbi

                   pbi <- getHookedBuildInfo :: Verbosity -> IO HookedBuildInfogetHookedBuildInfo verbosity :: Verbosityverbosity
                   sanityCheckHookedBuildInfo ::
  PackageDescription -> HookedBuildInfo -> IO ()sanityCheckHookedBuildInfo pkg_descr :: GenericPackageDescriptionpkg_descr pbi :: HookedBuildInfopbi
                   let pkg_descr' = updatePackageDescription ::
  HookedBuildInfo -> PackageDescription -> PackageDescriptionupdatePackageDescription pbi :: HookedBuildInfopbi pkg_descr :: GenericPackageDescriptionpkg_descr
                   postConf ::
  UserHooks
  -> Args
  -> ConfigFlags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()postConf simpleUserHooks :: UserHookssimpleUserHooks args :: Argsargs flags :: GlobalFlagsflags pkg_descr' :: PackageDescriptionpkg_descr' lbi :: LocalBuildInfolbi

          backwardsCompatHack = True :: BoolTrue

autoconfUserHooks :: UserHooks
autoconfUserHooks
    = simpleUserHooks :: UserHookssimpleUserHooks
      {
       postConf    = defaultPostConf ::
  Args
  -> ConfigFlags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()defaultPostConf,
       preBuild    = readHook ::
  (a -> Flag Verbosity) -> Args -> a -> IO HookedBuildInforeadHook buildVerbosity :: BuildFlags -> Flag VerbositybuildVerbosity,
       preClean    = readHook ::
  (a -> Flag Verbosity) -> Args -> a -> IO HookedBuildInforeadHook cleanVerbosity :: CleanFlags -> Flag VerbositycleanVerbosity,
       preCopy     = readHook ::
  (a -> Flag Verbosity) -> Args -> a -> IO HookedBuildInforeadHook copyVerbosity :: CopyFlags -> Flag VerbositycopyVerbosity,
       preInst     = readHook ::
  (a -> Flag Verbosity) -> Args -> a -> IO HookedBuildInforeadHook installVerbosity :: InstallFlags -> Flag VerbosityinstallVerbosity,
       preHscolour = readHook ::
  (a -> Flag Verbosity) -> Args -> a -> IO HookedBuildInforeadHook hscolourVerbosity :: HscolourFlags -> Flag VerbosityhscolourVerbosity,
       preHaddock  = readHook ::
  (a -> Flag Verbosity) -> Args -> a -> IO HookedBuildInforeadHook haddockVerbosity :: HaddockFlags -> Flag VerbosityhaddockVerbosity,
       preReg      = readHook ::
  (a -> Flag Verbosity) -> Args -> a -> IO HookedBuildInforeadHook regVerbosity :: RegisterFlags -> Flag VerbosityregVerbosity,
       preUnreg    = readHook ::
  (a -> Flag Verbosity) -> Args -> a -> IO HookedBuildInforeadHook regVerbosity :: RegisterFlags -> Flag VerbosityregVerbosity
      }
    where defaultPostConf :: Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()
          defaultPostConf args flags pkg_descr lbi
              = do let verbosity = fromFlag :: Flag a -> afromFlag (configVerbosity :: ConfigFlags -> Flag VerbosityconfigVerbosity flags :: GlobalFlagsflags)
                   noExtraFlags :: [String] -> IO ()noExtraFlags args :: Argsargs
                   confExists <- doesFileExist :: FilePath -> IO BooldoesFileExist "configure"
                   if confExists :: BoolconfExists
                     then runConfigureScript ::
  Verbosity -> Bool -> ConfigFlags -> LocalBuildInfo -> IO ()runConfigureScript verbosity :: Verbosityverbosity
                            backwardsCompatHack :: BoolbackwardsCompatHack flags :: GlobalFlagsflags lbi :: LocalBuildInfolbi
                     else die :: String -> IO adie "configure script not found."

                   pbi <- getHookedBuildInfo :: Verbosity -> IO HookedBuildInfogetHookedBuildInfo verbosity :: Verbosityverbosity
                   sanityCheckHookedBuildInfo ::
  PackageDescription -> HookedBuildInfo -> IO ()sanityCheckHookedBuildInfo pkg_descr :: GenericPackageDescriptionpkg_descr pbi :: HookedBuildInfopbi
                   let pkg_descr' = updatePackageDescription ::
  HookedBuildInfo -> PackageDescription -> PackageDescriptionupdatePackageDescription pbi :: HookedBuildInfopbi pkg_descr :: GenericPackageDescriptionpkg_descr
                   postConf ::
  UserHooks
  -> Args
  -> ConfigFlags
  -> PackageDescription
  -> LocalBuildInfo
  -> IO ()postConf simpleUserHooks :: UserHookssimpleUserHooks args :: Argsargs flags :: GlobalFlagsflags pkg_descr' :: PackageDescriptionpkg_descr' lbi :: LocalBuildInfolbi

          backwardsCompatHack = False :: BoolFalse

          readHook :: (a -> Flag Verbosity) -> Args -> a -> IO HookedBuildInfo
          readHook get_verbosity a flags = do
              noExtraFlags :: [String] -> IO ()noExtraFlags a :: Argsa
              getHookedBuildInfo :: Verbosity -> IO HookedBuildInfogetHookedBuildInfo verbosity :: Verbosityverbosity
            where
              verbosity = fromFlag :: Flag a -> afromFlag (get_verbosity :: a -> Flag Verbosityget_verbosity flags :: GlobalFlagsflags)

runConfigureScript :: Verbosity -> Bool -> ConfigFlags -> LocalBuildInfo
                   -> IO ()
runConfigureScript verbosity backwardsCompatHack flags lbi = do

  env <- getEnvironment :: IO [(String, String)]getEnvironment
  let programConfig = withPrograms :: LocalBuildInfo -> ProgramConfigurationwithPrograms lbi :: LocalBuildInfolbi
  (ccProg, ccFlags) <- configureCCompiler ::
  Verbosity -> ProgramConfiguration -> IO (FilePath, [String])configureCCompiler verbosity :: Verbosityverbosity programConfig :: ProgramConfigurationprogramConfig
  -- The C compiler's compilation and linker flags (e.g.
  -- "C compiler flags" and "Gcc Linker flags" from GHC) have already
  -- been merged into ccFlags, so we set both CFLAGS and LDFLAGS
  -- to ccFlags
  -- We don't try and tell configure which ld to use, as we don't have
  -- a way to pass its flags too
  let env' = appendToEnvironment ::
  (a, [Char]) -> [(a, [Char])] -> [(a, [Char])]appendToEnvironment ("CFLAGS",  unwords :: [String] -> Stringunwords ccFlags :: [String]ccFlags)
             env :: [(String, String)]env
      args' = args :: Argsargs (++) :: [a] -> [a] -> [a]++ ["--with-gcc=" (++) :: [a] -> [a] -> [a]++ ccProg :: FilePathccProg]
  handleNoWindowsSH :: IO a -> IO ahandleNoWindowsSH ($) :: (a -> b) -> a -> b$
    rawSystemExitWithEnv ::
  Verbosity -> FilePath -> [String] -> [(String, String)] -> IO ()rawSystemExitWithEnv verbosity :: Verbosityverbosity "sh" args' :: [[Char]]args' env' :: [([Char], [Char])]env'

  where
    args = "configure" (:) :: a -> [a] -> [a]: configureArgs :: Bool -> ConfigFlags -> [String]configureArgs backwardsCompatHack :: BoolbackwardsCompatHack flags :: GlobalFlagsflags

    appendToEnvironment (key, val) [] = [(key :: akey, val :: [Char]val)]
    appendToEnvironment (key, val) (kv@(k, v) : rest)
     | key :: akey (==) :: Eq a => a -> a -> Bool== k :: ak  = (key :: akey, v :: [Char]v (++) :: [a] -> [a] -> [a]++ " " (++) :: [a] -> [a] -> [a]++ val :: [Char]val) (:) :: a -> [a] -> [a]: rest :: [(a, [Char])]rest
     | otherwise :: Boolotherwise = kv :: (a, [Char])kv (:) :: a -> [a] -> [a]: appendToEnvironment ::
  (a, [Char]) -> [(a, [Char])] -> [(a, [Char])]appendToEnvironment (key :: akey, val :: [Char]val) rest :: [(a, [Char])]rest

    handleNoWindowsSH action
      | buildOS :: OSbuildOS (/=) :: Eq a => a -> a -> Bool/= Windows :: OSWindows
      = action :: IO ()action

      | otherwise :: Boolotherwise
      = action :: IO ()action
          catchIO :: IO a -> (IOException -> IO a) -> IO a`catchIO` \ioe -> if isDoesNotExistError :: IOError -> BoolisDoesNotExistError ioe :: IOExceptionioe
                              then die :: String -> IO adie notFoundMsg :: [Char]notFoundMsg
                              else throwIOIO :: IOException -> IO athrowIOIO ioe :: IOExceptionioe

    notFoundMsg = "The package has a './configure' script. This requires a "
               (++) :: [a] -> [a] -> [a]++ "Unix compatibility toolchain such as MinGW+MSYS or Cygwin."

getHookedBuildInfo :: Verbosity -> IO HookedBuildInfo
getHookedBuildInfo verbosity = do
  maybe_infoFile <- defaultHookedPackageDesc :: IO (Maybe FilePath)defaultHookedPackageDesc
  case maybe_infoFile :: Maybe FilePathmaybe_infoFile of
    Nothing       -> return :: Monad m => forall a. a -> m areturn emptyHookedBuildInfo :: HookedBuildInfoemptyHookedBuildInfo
    Just infoFile -> do
      info :: Verbosity -> String -> IO ()info verbosity :: Verbosityverbosity ($) :: (a -> b) -> a -> b$ "Reading parameters from " (++) :: [a] -> [a] -> [a]++ infoFile :: FilePathinfoFile
      readHookedBuildInfo :: Verbosity -> FilePath -> IO HookedBuildInforeadHookedBuildInfo verbosity :: Verbosityverbosity infoFile :: FilePathinfoFile

defaultTestHook :: PackageDescription -> LocalBuildInfo
                -> UserHooks -> TestFlags -> IO ()
defaultTestHook pkg_descr localbuildinfo _ flags =
    test :: PackageDescription -> LocalBuildInfo -> TestFlags -> IO ()test pkg_descr :: GenericPackageDescriptionpkg_descr localbuildinfo :: LocalBuildInfolocalbuildinfo flags :: GlobalFlagsflags

defaultInstallHook :: PackageDescription -> LocalBuildInfo
                   -> UserHooks -> InstallFlags -> IO ()
defaultInstallHook pkg_descr localbuildinfo _ flags = do
  let copyFlags = defaultCopyFlags :: CopyFlagsdefaultCopyFlags {
                      copyDistPref   = installDistPref :: InstallFlags -> Flag FilePathinstallDistPref flags :: GlobalFlagsflags,
                      copyDest       = toFlag :: a -> Flag atoFlag NoCopyDest :: CopyDestNoCopyDest,
                      copyVerbosity  = installVerbosity :: InstallFlags -> Flag VerbosityinstallVerbosity flags :: GlobalFlagsflags
                  }
  install ::
  PackageDescription -> LocalBuildInfo -> CopyFlags -> IO ()install pkg_descr :: GenericPackageDescriptionpkg_descr localbuildinfo :: LocalBuildInfolocalbuildinfo copyFlags :: CopyFlagscopyFlags
  let registerFlags = defaultRegisterFlags :: RegisterFlagsdefaultRegisterFlags {
                          regDistPref  = installDistPref :: InstallFlags -> Flag FilePathinstallDistPref flags :: GlobalFlagsflags,
                          regInPlace   = installInPlace :: InstallFlags -> Flag BoolinstallInPlace flags :: GlobalFlagsflags,
                          regPackageDB = installPackageDB :: InstallFlags -> Flag PackageDBinstallPackageDB flags :: GlobalFlagsflags,
                          regVerbosity = installVerbosity :: InstallFlags -> Flag VerbosityinstallVerbosity flags :: GlobalFlagsflags
                      }
  when :: Monad m => Bool -> m () -> m ()when (hasLibs :: PackageDescription -> BoolhasLibs pkg_descr :: GenericPackageDescriptionpkg_descr) ($) :: (a -> b) -> a -> b$ register ::
  PackageDescription -> LocalBuildInfo -> RegisterFlags -> IO ()register pkg_descr :: GenericPackageDescriptionpkg_descr localbuildinfo :: LocalBuildInfolocalbuildinfo registerFlags :: RegisterFlagsregisterFlags

defaultBuildHook :: PackageDescription -> LocalBuildInfo
        -> UserHooks -> BuildFlags -> IO ()
defaultBuildHook pkg_descr localbuildinfo hooks flags =
  build ::
  PackageDescription
  -> LocalBuildInfo
  -> BuildFlags
  -> [PPSuffixHandler]
  -> IO ()build pkg_descr :: GenericPackageDescriptionpkg_descr localbuildinfo :: LocalBuildInfolocalbuildinfo flags :: GlobalFlagsflags (allSuffixHandlers :: UserHooks -> [PPSuffixHandler]allSuffixHandlers hooks :: UserHookshooks)

defaultRegHook :: PackageDescription -> LocalBuildInfo
        -> UserHooks -> RegisterFlags -> IO ()
defaultRegHook pkg_descr localbuildinfo _ flags =
    if hasLibs :: PackageDescription -> BoolhasLibs pkg_descr :: GenericPackageDescriptionpkg_descr
    then register ::
  PackageDescription -> LocalBuildInfo -> RegisterFlags -> IO ()register pkg_descr :: GenericPackageDescriptionpkg_descr localbuildinfo :: LocalBuildInfolocalbuildinfo flags :: GlobalFlagsflags
    else setupMessage :: Verbosity -> String -> PackageIdentifier -> IO ()setupMessage verbosity :: Verbosityverbosity
           "Package contains no library to register:" (packageId :: Package pkg => pkg -> PackageIdentifierpackageId pkg_descr :: GenericPackageDescriptionpkg_descr)
  where verbosity = fromFlag :: Flag a -> afromFlag (regVerbosity :: RegisterFlags -> Flag VerbosityregVerbosity flags :: GlobalFlagsflags)