    {-# LANGUAGE CPP #-}

    -----------------------------------------------------------------------------
    --
    -- Makefile Dependency Generation
    --
    -- (c) The University of Glasgow 2005
    --
    -----------------------------------------------------------------------------

    module GHC.Driver.MakeFile
       ( doMkDependHS
       )
    where

    #include "HsVersions.h"

    import GHC.Prelude

    import qualified GHC
    import GHC.Driver.Monad
    import GHC.Driver.Session
    import GHC.Driver.Ppr
    import GHC.Utils.Misc
    import GHC.Driver.Env
    import qualified GHC.SysTools as SysTools
    import GHC.Data.Graph.Directed ( SCC(..) )
    import GHC.Utils.Outputable
    import GHC.Utils.Panic
    import GHC.Types.SourceError
    import GHC.Types.SrcLoc
    import Data.List (partition)
    import GHC.Data.FastString
    import GHC.Utils.TmpFs

    import GHC.Iface.Load (cannotFindModule)

    import GHC.Unit.Module
    import GHC.Unit.Module.ModSummary
    import GHC.Unit.Module.Graph
    import GHC.Unit.Finder

    import GHC.Utils.Exception
    import GHC.Utils.Error
    import GHC.Utils.Logger

    import System.Directory
    import System.FilePath
    import System.IO
    import System.IO.Error  ( isEOFError )
    import Control.Monad    ( when, forM_ )
    import Data.Maybe       ( isJust )
    import Data.IORef
    import qualified Data.Set as Set

    -----------------------------------------------------------------
    --
    --              The main function
    --
    -----------------------------------------------------------------

    doMkDependHS :: GhcMonad m => [FilePath] -> m ()
    doMkDependHS :: forall (m :: * -> *). GhcMonad m => [String] -> m ()
    doMkDependHS [String]
    srcs = do
        Logger
    logger <- m Logger
    forall (m :: * -> *). HasLogger m => m Logger
    getLogger

        -- Initialisation
        DynFlags
    dflags0 <- m DynFlags
    forall (m :: * -> *). GhcMonad m => m DynFlags
    GHC.getSessionDynFlags

        -- We kludge things a bit for dependency generation. Rather than
        -- generating dependencies for each way separately, we generate
        -- them once and then duplicate them for each way's osuf/hisuf.
        -- We therefore do the initial dependency generation with an empty
        -- way and .o/.hi extensions, regardless of any flags that might
        -- be specified.
        let dflags :: DynFlags
    dflags = DynFlags
    dflags0
                { targetWays_ :: Ways
    targetWays_ = Ways
    forall a. Set a
    Set.empty
                , hiSuf_ :: String
    hiSuf_      = String
    "hi"
                , objectSuf_ :: String
    objectSuf_  = String
    "o"
                }
        DynFlags -> m ()
    forall (m :: * -> *). GhcMonad m => DynFlags -> m ()
    GHC.setSessionDynFlags DynFlags
    dflags

        Bool -> m () -> m ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when ([String] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null (DynFlags -> [String]
    depSuffixes DynFlags
    dflags)) (m () -> m ()) -> m () -> m ()
    forall a b. (a -> b) -> a -> b
    $ IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $
            GhcException -> IO ()
    forall a. GhcException -> IO a
    throwGhcExceptionIO (String -> GhcException
    ProgramError String
    "You must specify at least one -dep-suffix")

        TmpFs
    tmpfs <- HscEnv -> TmpFs
    hsc_tmpfs (HscEnv -> TmpFs) -> m HscEnv -> m TmpFs
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> m HscEnv
    forall (m :: * -> *). GhcMonad m => m HscEnv
    getSession
        MkDepFiles
    files <- IO MkDepFiles -> m MkDepFiles
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO MkDepFiles -> m MkDepFiles) -> IO MkDepFiles -> m MkDepFiles
    forall a b. (a -> b) -> a -> b
    $ Logger -> TmpFs -> DynFlags -> IO MkDepFiles
    beginMkDependHS Logger
    logger TmpFs
    tmpfs DynFlags
    dflags

        -- Do the downsweep to find all the modules
        [Target]
    targets <- (String -> m Target) -> [String] -> m [Target]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM (\String
    s -> String -> Maybe Phase -> m Target
    forall (m :: * -> *).
    GhcMonad m =>
    String -> Maybe Phase -> m Target
    GHC.guessTarget String
    s Maybe Phase
    forall a. Maybe a
    Nothing) [String]
    srcs
        [Target] -> m ()
    forall (m :: * -> *). GhcMonad m => [Target] -> m ()
    GHC.setTargets [Target]
    targets
        let excl_mods :: [ModuleName]
    excl_mods = DynFlags -> [ModuleName]
    depExcludeMods DynFlags
    dflags
        ModuleGraph
    module_graph <- [ModuleName] -> Bool -> m ModuleGraph
    forall (m :: * -> *).
    GhcMonad m =>
    [ModuleName] -> Bool -> m ModuleGraph
    GHC.depanal [ModuleName]
    excl_mods Bool
    True {- Allow dup roots -}

        -- Sort into dependency order
        -- There should be no cycles
        let sorted :: [SCC ModuleGraphNode]
    sorted = Bool -> ModuleGraph -> Maybe ModuleName -> [SCC ModuleGraphNode]
    GHC.topSortModuleGraph Bool
    False ModuleGraph
    module_graph Maybe ModuleName
    forall a. Maybe a
    Nothing

        -- Print out the dependencies if wanted
        IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Logger -> DynFlags -> Int -> SDoc -> IO ()
    debugTraceMsg Logger
    logger DynFlags
    dflags Int
    2 (String -> SDoc
    text String
    "Module dependencies" SDoc -> SDoc -> SDoc
    $$ [SCC ModuleGraphNode] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [SCC ModuleGraphNode]
    sorted)

        -- Process them one by one, dumping results into makefile
        -- and complaining about cycles
        HscEnv
    hsc_env <- m HscEnv
    forall (m :: * -> *). GhcMonad m => m HscEnv
    getSession
        String
    root <- IO String -> m String
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO String
    getCurrentDirectory
        (SCC ModuleGraphNode -> m ()) -> [SCC ModuleGraphNode] -> m ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ (IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ())
    -> (SCC ModuleGraphNode -> IO ()) -> SCC ModuleGraphNode -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DynFlags
    -> HscEnv
    -> [ModuleName]
    -> String
    -> Handle
    -> SCC ModuleGraphNode
    -> IO ()
    processDeps DynFlags
    dflags HscEnv
    hsc_env [ModuleName]
    excl_mods String
    root (MkDepFiles -> Handle
    mkd_tmp_hdl MkDepFiles
    files)) [SCC ModuleGraphNode]
    sorted

        -- If -ddump-mod-cycles, show cycles in the module graph
        IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Logger -> DynFlags -> ModuleGraph -> IO ()
    dumpModCycles Logger
    logger DynFlags
    dflags ModuleGraph
    module_graph

        -- Tidy up
        IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Logger -> DynFlags -> MkDepFiles -> IO ()
    endMkDependHS Logger
    logger DynFlags
    dflags MkDepFiles
    files

        -- Unconditional exiting is a bad idea.  If an error occurs we'll get an
        --exception; if that is not caught it's fine, but at least we have a
        --chance to find out exactly what went wrong.  Uncomment the following
        --line if you disagree.

        --`GHC.ghcCatch` \_ -> io $ exitWith (ExitFailure 1)

    -----------------------------------------------------------------
    --
    --              beginMkDependHs
    --      Create a temporary file,
    --      find the Makefile,
    --      slurp through it, etc
    --
    -----------------------------------------------------------------

    data MkDepFiles
      = MkDep { MkDepFiles -> String
    mkd_make_file :: FilePath,          -- Name of the makefile
                MkDepFiles -> Maybe Handle
    mkd_make_hdl  :: Maybe Handle,      -- Handle for the open makefile
                MkDepFiles -> String
    mkd_tmp_file  :: FilePath,          -- Name of the temporary file
                MkDepFiles -> Handle
    mkd_tmp_hdl   :: Handle }           -- Handle of the open temporary file

    beginMkDependHS :: Logger -> TmpFs -> DynFlags -> IO MkDepFiles
    beginMkDependHS :: Logger -> TmpFs -> DynFlags -> IO MkDepFiles
    beginMkDependHS Logger
    logger TmpFs
    tmpfs DynFlags
    dflags = do
            -- open a new temp file in which to stuff the dependency info
            -- as we go along.
      String
    tmp_file <- Logger
    -> TmpFs -> DynFlags -> TempFileLifetime -> String -> IO String
    newTempName Logger
    logger TmpFs
    tmpfs DynFlags
    dflags TempFileLifetime
    TFL_CurrentModule String
    "dep"
      Handle
    tmp_hdl <- String -> IOMode -> IO Handle
    openFile String
    tmp_file IOMode
    WriteMode

            -- open the makefile
      let makefile :: String
    makefile = DynFlags -> String
    depMakefile DynFlags
    dflags
      Bool
    exists <- String -> IO Bool
    doesFileExist String
    makefile
      Maybe Handle
    mb_make_hdl <-
            if Bool -> Bool
    not Bool
    exists
            then Maybe Handle -> IO (Maybe Handle)
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe Handle
    forall a. Maybe a
    Nothing
            else do
               Handle
    makefile_hdl <- String -> IOMode -> IO Handle
    openFile String
    makefile IOMode
    ReadMode

                    -- slurp through until we get the magic start string,
                    -- copying the contents into dep_makefile
               let slurp :: IO ()
    slurp = do
                    String
    l <- Handle -> IO String
    hGetLine Handle
    makefile_hdl
                    if (String
    l String -> String -> Bool
    forall a. Eq a => a -> a -> Bool
    == String
    depStartMarker)
                            then () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
                            else do Handle -> String -> IO ()
    hPutStrLn Handle
    tmp_hdl String
    l; IO ()
    slurp

                    -- slurp through until we get the magic end marker,
                    -- throwing away the contents
               let chuck :: IO ()
    chuck = do
                    String
    l <- Handle -> IO String
    hGetLine Handle
    makefile_hdl
                    if (String
    l String -> String -> Bool
    forall a. Eq a => a -> a -> Bool
    == String
    depEndMarker)
                            then () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
                            else IO ()
    chuck

               IO () -> (IOException -> IO ()) -> IO ()
    forall a. IO a -> (IOException -> IO a) -> IO a
    catchIO IO ()
    slurp
                    (\IOException
    e -> if IOException -> Bool
    isEOFError IOException
    e then () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return () else IOException -> IO ()
    forall a. IOException -> IO a
    ioError IOException
    e)
               IO () -> (IOException -> IO ()) -> IO ()
    forall a. IO a -> (IOException -> IO a) -> IO a
    catchIO IO ()
    chuck
                    (\IOException
    e -> if IOException -> Bool
    isEOFError IOException
    e then () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return () else IOException -> IO ()
    forall a. IOException -> IO a
    ioError IOException
    e)

               Maybe Handle -> IO (Maybe Handle)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Handle -> Maybe Handle
    forall a. a -> Maybe a
    Just Handle
    makefile_hdl)

            -- write the magic marker into the tmp file
      Handle -> String -> IO ()
    hPutStrLn Handle
    tmp_hdl String
    depStartMarker

      MkDepFiles -> IO MkDepFiles
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MkDep { mkd_make_file :: String
    mkd_make_file = String
    makefile, mkd_make_hdl :: Maybe Handle
    mkd_make_hdl = Maybe Handle
    mb_make_hdl,
                      mkd_tmp_file :: String
    mkd_tmp_file  = String
    tmp_file, mkd_tmp_hdl :: Handle
    mkd_tmp_hdl  = Handle
    tmp_hdl})

    -----------------------------------------------------------------
    --
    --              processDeps
    --
    -----------------------------------------------------------------

    processDeps :: DynFlags
                -> HscEnv
                -> [ModuleName]
                -> FilePath
                -> Handle           -- Write dependencies to here
                -> SCC ModuleGraphNode
                -> IO ()
    -- Write suitable dependencies to handle
    -- Always:
    --                      this.o : this.hs
    --
    -- If the dependency is on something other than a .hi file:
    --                      this.o this.p_o ... : dep
    -- otherwise
    --                      this.o ...   : dep.hi
    --                      this.p_o ... : dep.p_hi
    --                      ...
    -- (where .o is $osuf, and the other suffixes come from
    -- the cmdline -s options).
    --
    -- For {-# SOURCE #-} imports the "hi" will be "hi-boot".

    processDeps :: DynFlags
    -> HscEnv
    -> [ModuleName]
    -> String
    -> Handle
    -> SCC ModuleGraphNode
    -> IO ()
    processDeps DynFlags
    dflags HscEnv
    _ [ModuleName]
    _ String
    _ Handle
    _ (CyclicSCC [ModuleGraphNode]
    nodes)
      =     -- There shouldn't be any cycles; report them
        GhcException -> IO ()
    forall a. GhcException -> IO a
    throwGhcExceptionIO (GhcException -> IO ()) -> GhcException -> IO ()
    forall a b. (a -> b) -> a -> b
    $ String -> GhcException
    ProgramError (String -> GhcException) -> String -> GhcException
    forall a b. (a -> b) -> a -> b
    $
          DynFlags -> SDoc -> String
    showSDoc DynFlags
    dflags (SDoc -> String) -> SDoc -> String
    forall a b. (a -> b) -> a -> b
    $ [ModuleGraphNode] -> SDoc
    GHC.cyclicModuleErr [ModuleGraphNode]
    nodes

    processDeps DynFlags
    dflags HscEnv
    _ [ModuleName]
    _ String
    _ Handle
    _ (AcyclicSCC (InstantiationNode InstantiatedUnit
    node))
      =     -- There shouldn't be any backpack instantiations; report them as well
        GhcException -> IO ()
    forall a. GhcException -> IO a
    throwGhcExceptionIO (GhcException -> IO ()) -> GhcException -> IO ()
    forall a b. (a -> b) -> a -> b
    $ String -> GhcException
    ProgramError (String -> GhcException) -> String -> GhcException
    forall a b. (a -> b) -> a -> b
    $
          DynFlags -> SDoc -> String
    showSDoc DynFlags
    dflags (SDoc -> String) -> SDoc -> String
    forall a b. (a -> b) -> a -> b
    $
            [SDoc] -> SDoc
    vcat [ String -> SDoc
    text String
    "Unexpected backpack instantiation in dependency graph while constructing Makefile:"
                 , Int -> SDoc -> SDoc
    nest Int
    2 (SDoc -> SDoc) -> SDoc -> SDoc
    forall a b. (a -> b) -> a -> b
    $ InstantiatedUnit -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr InstantiatedUnit
    node ]

    processDeps DynFlags
    dflags HscEnv
    hsc_env [ModuleName]
    excl_mods String
    root Handle
    hdl (AcyclicSCC (ModuleNode (ExtendedModSummary ModSummary
    node [InstantiatedUnit]
    _)))
      = do  { let extra_suffixes :: [String]
    extra_suffixes = DynFlags -> [String]
    depSuffixes DynFlags
    dflags
                  include_pkg_deps :: Bool
    include_pkg_deps = DynFlags -> Bool
    depIncludePkgDeps DynFlags
    dflags
                  src_file :: String
    src_file  = ModSummary -> String
    msHsFilePath ModSummary
    node
                  obj_file :: String
    obj_file  = ModSummary -> String
    msObjFilePath ModSummary
    node
                  obj_files :: [String]
    obj_files = String -> [String] -> [String]
    insertSuffixes String
    obj_file [String]
    extra_suffixes

                  do_imp :: SrcSpan
    -> IsBootInterface -> Maybe FastString -> ModuleName -> IO ()
    do_imp SrcSpan
    loc IsBootInterface
    is_boot Maybe FastString
    pkg_qual ModuleName
    imp_mod
                    = do { Maybe String
    mb_hi <- HscEnv
    -> SrcSpan
    -> Maybe FastString
    -> ModuleName
    -> IsBootInterface
    -> Bool
    -> IO (Maybe String)
    findDependency HscEnv
    hsc_env SrcSpan
    loc Maybe FastString
    pkg_qual ModuleName
    imp_mod
                                                   IsBootInterface
    is_boot Bool
    include_pkg_deps
                         ; case Maybe String
    mb_hi of {
                               Maybe String
    Nothing      -> () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return () ;
                               Just String
    hi_file -> do
                         { let hi_files :: [String]
    hi_files = String -> [String] -> [String]
    insertSuffixes String
    hi_file [String]
    extra_suffixes
                               write_dep :: (String, String) -> IO ()
    write_dep (String
    obj,String
    hi) = String -> Handle -> [String] -> String -> IO ()
    writeDependency String
    root Handle
    hdl [String
    obj] String
    hi

                            -- Add one dependency for each suffix;
                            -- e.g.         A.o   : B.hi
                            --              A.x_o : B.x_hi
                         ; ((String, String) -> IO ()) -> [(String, String)] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ (String, String) -> IO ()
    write_dep ([String]
    obj_files [String] -> [String] -> [(String, String)]
    forall a b. [a] -> [b] -> [(a, b)]
    `zip` [String]
    hi_files) }}}

                    -- Emit std dependency of the object(s) on the source file
                    -- Something like       A.o : A.hs
            ; String -> Handle -> [String] -> String -> IO ()
    writeDependency String
    root Handle
    hdl [String]
    obj_files String
    src_file

              -- add dependency between objects and their corresponding .hi-boot
              -- files if the module has a corresponding .hs-boot file (#14482)
            ; Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (ModSummary -> IsBootInterface
    isBootSummary ModSummary
    node IsBootInterface -> IsBootInterface -> Bool
    forall a. Eq a => a -> a -> Bool
    == IsBootInterface
    IsBoot) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
                let hi_boot :: String
    hi_boot = ModSummary -> String
    msHiFilePath ModSummary
    node
                let obj :: String
    obj     = String -> String
    removeBootSuffix (ModSummary -> String
    msObjFilePath ModSummary
    node)
                [String] -> (String -> IO ()) -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    t a -> (a -> m b) -> m ()
    forM_ [String]
    extra_suffixes ((String -> IO ()) -> IO ()) -> (String -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \String
    suff -> do
                   let way_obj :: [String]
    way_obj     = String -> [String] -> [String]
    insertSuffixes String
    obj     [String
    suff]
                   let way_hi_boot :: [String]
    way_hi_boot = String -> [String] -> [String]
    insertSuffixes String
    hi_boot [String
    suff]
                   (String -> IO ()) -> [String] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ (String -> Handle -> [String] -> String -> IO ()
    writeDependency String
    root Handle
    hdl [String]
    way_obj) [String]
    way_hi_boot

                    -- Emit a dependency for each CPP import
            ; Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (DynFlags -> Bool
    depIncludeCppDeps DynFlags
    dflags) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
                -- CPP deps are descovered in the module parsing phase by parsing
                -- comment lines left by the preprocessor.
                -- Note that GHC.parseModule may throw an exception if the module
                -- fails to parse, which may not be desirable (see #16616).
              { Session
    session <- IORef HscEnv -> Session
    Session (IORef HscEnv -> Session) -> IO (IORef HscEnv) -> IO Session
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> HscEnv -> IO (IORef HscEnv)
    forall a. a -> IO (IORef a)
    newIORef HscEnv
    hsc_env
              ; ParsedModule
    parsedMod <- Ghc ParsedModule -> Session -> IO ParsedModule
    forall a. Ghc a -> Session -> IO a
    reflectGhc (ModSummary -> Ghc ParsedModule
    forall (m :: * -> *). GhcMonad m => ModSummary -> m ParsedModule
    GHC.parseModule ModSummary
    node) Session
    session
              ; (String -> IO ()) -> [String] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ (String -> Handle -> [String] -> String -> IO ()
    writeDependency String
    root Handle
    hdl [String]
    obj_files)
                      (ParsedModule -> [String]
    GHC.pm_extra_src_files ParsedModule
    parsedMod)
              }

                    -- Emit a dependency for each import

            ; let do_imps :: IsBootInterface
    -> [(Maybe FastString, GenLocated SrcSpan ModuleName)] -> IO ()
    do_imps IsBootInterface
    is_boot [(Maybe FastString, GenLocated SrcSpan ModuleName)]
    idecls = [IO ()] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a.
    (Foldable t, Monad m) =>
    t (m a) -> m ()
    sequence_
                        [ SrcSpan
    -> IsBootInterface -> Maybe FastString -> ModuleName -> IO ()
    do_imp SrcSpan
    loc IsBootInterface
    is_boot Maybe FastString
    mb_pkg ModuleName
    mod
                        | (Maybe FastString
    mb_pkg, L SrcSpan
    loc ModuleName
    mod) <- [(Maybe FastString, GenLocated SrcSpan ModuleName)]
    idecls,
                          ModuleName
    mod ModuleName -> [ModuleName] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `notElem` [ModuleName]
    excl_mods ]

            ; IsBootInterface
    -> [(Maybe FastString, GenLocated SrcSpan ModuleName)] -> IO ()
    do_imps IsBootInterface
    IsBoot (ModSummary -> [(Maybe FastString, GenLocated SrcSpan ModuleName)]
    ms_srcimps ModSummary
    node)
            ; IsBootInterface
    -> [(Maybe FastString, GenLocated SrcSpan ModuleName)] -> IO ()
    do_imps IsBootInterface
    NotBoot (ModSummary -> [(Maybe FastString, GenLocated SrcSpan ModuleName)]
    ms_imps ModSummary
    node)
            }

    findDependency  :: HscEnv
                    -> SrcSpan
                    -> Maybe FastString     -- package qualifier, if any
                    -> ModuleName           -- Imported module
                    -> IsBootInterface      -- Source import
                    -> Bool                 -- Record dependency on package modules
                    -> IO (Maybe FilePath)  -- Interface file
    findDependency :: HscEnv
    -> SrcSpan
    -> Maybe FastString
    -> ModuleName
    -> IsBootInterface
    -> Bool
    -> IO (Maybe String)
    findDependency HscEnv
    hsc_env SrcSpan
    srcloc Maybe FastString
    pkg ModuleName
    imp IsBootInterface
    is_boot Bool
    include_pkg_deps
      = do  {       -- Find the module; this will be fast because
                    -- we've done it once during downsweep
              FindResult
    r <- HscEnv -> ModuleName -> Maybe FastString -> IO FindResult
    findImportedModule HscEnv
    hsc_env ModuleName
    imp Maybe FastString
    pkg
            ; case FindResult
    r of
                Found ModLocation
    loc Module
    _
                    -- Home package: just depend on the .hi or hi-boot file
                    | Maybe String -> Bool
    forall a. Maybe a -> Bool
    isJust (ModLocation -> Maybe String
    ml_hs_file ModLocation
    loc) Bool -> Bool -> Bool
    || Bool
    include_pkg_deps
                    -> Maybe String -> IO (Maybe String)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String -> Maybe String
    forall a. a -> Maybe a
    Just (IsBootInterface -> String -> String
    addBootSuffix_maybe IsBootInterface
    is_boot (ModLocation -> String
    ml_hi_file ModLocation
    loc)))

                    -- Not in this package: we don't need a dependency
                    | Bool
    otherwise
                    -> Maybe String -> IO (Maybe String)
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe String
    forall a. Maybe a
    Nothing

                FindResult
    fail ->
                    MsgEnvelope DecoratedSDoc -> IO (Maybe String)
    forall (io :: * -> *) a.
    MonadIO io =>
    MsgEnvelope DecoratedSDoc -> io a
    throwOneError (MsgEnvelope DecoratedSDoc -> IO (Maybe String))
    -> MsgEnvelope DecoratedSDoc -> IO (Maybe String)
    forall a b. (a -> b) -> a -> b
    $ SrcSpan -> SDoc -> MsgEnvelope DecoratedSDoc
    mkPlainMsgEnvelope SrcSpan
    srcloc (SDoc -> MsgEnvelope DecoratedSDoc)
    -> SDoc -> MsgEnvelope DecoratedSDoc
    forall a b. (a -> b) -> a -> b
    $
                         HscEnv -> ModuleName -> FindResult -> SDoc
    cannotFindModule HscEnv
    hsc_env ModuleName
    imp FindResult
    fail
            }

    -----------------------------
    writeDependency :: FilePath -> Handle -> [FilePath] -> FilePath -> IO ()
    -- (writeDependency r h [t1,t2] dep) writes to handle h the dependency
    --      t1 t2 : dep
    writeDependency :: String -> Handle -> [String] -> String -> IO ()
    writeDependency String
    root Handle
    hdl [String]
    targets String
    dep
      = do let -- We need to avoid making deps on
               --     c:/foo/...
               -- on cygwin as make gets confused by the :
               -- Making relative deps avoids some instances of this.
               dep' :: String
    dep' = String -> String -> String
    makeRelative String
    root String
    dep
               forOutput :: String -> String
    forOutput = String -> String
    escapeSpaces (String -> String) -> (String -> String) -> String -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Direction -> String -> String
    reslash Direction
    Forwards (String -> String) -> (String -> String) -> String -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> String
    normalise
               output :: String
    output = [String] -> String
    unwords ((String -> String) -> [String] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map String -> String
    forOutput [String]
    targets) String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    " : " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String -> String
    forOutput String
    dep'
           Handle -> String -> IO ()
    hPutStrLn Handle
    hdl String
    output

    -----------------------------
    insertSuffixes
            :: FilePath     -- Original filename;   e.g. "foo.o"
            -> [String]     -- Suffix prefixes      e.g. ["x_", "y_"]
            -> [FilePath]   -- Zapped filenames     e.g. ["foo.x_o", "foo.y_o"]
            -- Note that the extra bit gets inserted *before* the old suffix
            -- We assume the old suffix contains no dots, so we know where to
            -- split it
    insertSuffixes :: String -> [String] -> [String]
    insertSuffixes String
    file_name [String]
    extras
      = [ String
    basename String -> String -> String
    <.> (String
    extra String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    suffix) | String
    extra <- [String]
    extras ]
      where
        (String
    basename, String
    suffix) = case String -> (String, String)
    splitExtension String
    file_name of
                             -- Drop the "." from the extension
                             (String
    b, String
    s) -> (String
    b, Int -> String -> String
    forall a. Int -> [a] -> [a]
    drop Int
    1 String
    s)

    -----------------------------------------------------------------
    --
    --              endMkDependHs
    --      Complete the makefile, close the tmp file etc
    --
    -----------------------------------------------------------------

    endMkDependHS :: Logger -> DynFlags -> MkDepFiles -> IO ()

    endMkDependHS :: Logger -> DynFlags -> MkDepFiles -> IO ()
    endMkDependHS Logger
    logger DynFlags
    dflags
       (MkDep { mkd_make_file :: MkDepFiles -> String
    mkd_make_file = String
    makefile, mkd_make_hdl :: MkDepFiles -> Maybe Handle
    mkd_make_hdl =  Maybe Handle
    makefile_hdl,
                mkd_tmp_file :: MkDepFiles -> String
    mkd_tmp_file  = String
    tmp_file, mkd_tmp_hdl :: MkDepFiles -> Handle
    mkd_tmp_hdl  =  Handle
    tmp_hdl })
      = do
      -- write the magic marker into the tmp file
      Handle -> String -> IO ()
    hPutStrLn Handle
    tmp_hdl String
    depEndMarker

      case Maybe Handle
    makefile_hdl of
         Maybe Handle
    Nothing  -> () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
         Just Handle
    hdl -> do

              -- slurp the rest of the original makefile and copy it into the output
            let slurp :: IO ()
    slurp = do
                    String
    l <- Handle -> IO String
    hGetLine Handle
    hdl
                    Handle -> String -> IO ()
    hPutStrLn Handle
    tmp_hdl String
    l
                    IO ()
    slurp

            IO () -> (IOException -> IO ()) -> IO ()
    forall a. IO a -> (IOException -> IO a) -> IO a
    catchIO IO ()
    slurp
                    (\IOException
    e -> if IOException -> Bool
    isEOFError IOException
    e then () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return () else IOException -> IO ()
    forall a. IOException -> IO a
    ioError IOException
    e)

            Handle -> IO ()
    hClose Handle
    hdl

      Handle -> IO ()
    hClose Handle
    tmp_hdl  -- make sure it's flushed

            -- Create a backup of the original makefile
      Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Maybe Handle -> Bool
    forall a. Maybe a -> Bool
    isJust Maybe Handle
    makefile_hdl)
           (Logger -> DynFlags -> String -> String -> String -> IO ()
    SysTools.copy Logger
    logger DynFlags
    dflags (String
    "Backing up " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    makefile)
              String
    makefile (String
    makefileString -> String -> String
    forall a. [a] -> [a] -> [a]
    ++String
    ".bak"))

            -- Copy the new makefile in place
      Logger -> DynFlags -> String -> String -> String -> IO ()
    SysTools.copy Logger
    logger DynFlags
    dflags String
    "Installing new makefile" String
    tmp_file String
    makefile

    -----------------------------------------------------------------
    --              Module cycles
    -----------------------------------------------------------------

    dumpModCycles :: Logger -> DynFlags -> ModuleGraph -> IO ()
    dumpModCycles :: Logger -> DynFlags -> ModuleGraph -> IO ()
    dumpModCycles Logger
    logger DynFlags
    dflags ModuleGraph
    module_graph
      | Bool -> Bool
    not (DumpFlag -> DynFlags -> Bool
    dopt DumpFlag
    Opt_D_dump_mod_cycles DynFlags
    dflags)
      = () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

      | [[ModSummary]] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [[ModSummary]]
    cycles
      = Logger -> DynFlags -> SDoc -> IO ()
    putMsg Logger
    logger DynFlags
    dflags (String -> SDoc
    text String
    "No module cycles")

      | Bool
    otherwise
      = Logger -> DynFlags -> SDoc -> IO ()
    putMsg Logger
    logger DynFlags
    dflags (SDoc -> Int -> SDoc -> SDoc
    hang (String -> SDoc
    text String
    "Module cycles found:") Int
    2 SDoc
    pp_cycles)
      where
        topoSort :: [SCC ModSummary]
    topoSort = [SCC ModuleGraphNode] -> [SCC ModSummary]
    filterToposortToModules ([SCC ModuleGraphNode] -> [SCC ModSummary])
    -> [SCC ModuleGraphNode] -> [SCC ModSummary]
    forall a b. (a -> b) -> a -> b
    $
          Bool -> ModuleGraph -> Maybe ModuleName -> [SCC ModuleGraphNode]
    GHC.topSortModuleGraph Bool
    True ModuleGraph
    module_graph Maybe ModuleName
    forall a. Maybe a
    Nothing

        cycles :: [[ModSummary]]
        cycles :: [[ModSummary]]
    cycles =
          [ [ModSummary]
    c | CyclicSCC [ModSummary]
    c <- [SCC ModSummary]
    topoSort ]

        pp_cycles :: SDoc
    pp_cycles = [SDoc] -> SDoc
    vcat [ (String -> SDoc
    text String
    "---------- Cycle" SDoc -> SDoc -> SDoc
    <+> Int -> SDoc
    int Int
    n SDoc -> SDoc -> SDoc
    <+> PtrString -> SDoc
    ptext (String -> PtrString
    sLit String
    "----------"))
                            SDoc -> SDoc -> SDoc
    $$ [ModSummary] -> SDoc
    pprCycle [ModSummary]
    c SDoc -> SDoc -> SDoc
    $$ SDoc
    blankLine
                         | (Int
    n,[ModSummary]
    c) <- [Int
    1..] [Int] -> [[ModSummary]] -> [(Int, [ModSummary])]
    forall a b. [a] -> [b] -> [(a, b)]
    `zip` [[ModSummary]]
    cycles ]

    pprCycle :: [ModSummary] -> SDoc
    -- Print a cycle, but show only the imports within the cycle
    pprCycle :: [ModSummary] -> SDoc
    pprCycle [ModSummary]
    summaries = SCC ModSummary -> SDoc
    pp_group ([ModSummary] -> SCC ModSummary
    forall vertex. [vertex] -> SCC vertex
    CyclicSCC [ModSummary]
    summaries)
      where
        cycle_mods :: [ModuleName]  -- The modules in this cycle
        cycle_mods :: [ModuleName]
    cycle_mods = (ModSummary -> ModuleName) -> [ModSummary] -> [ModuleName]
    forall a b. (a -> b) -> [a] -> [b]
    map (Module -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName (Module -> ModuleName)
    -> (ModSummary -> Module) -> ModSummary -> ModuleName
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ModSummary -> Module
    ms_mod) [ModSummary]
    summaries

        pp_group :: SCC ModSummary -> SDoc
    pp_group (AcyclicSCC ModSummary
    ms) = ModSummary -> SDoc
    pp_ms ModSummary
    ms
        pp_group (CyclicSCC [ModSummary]
    mss)
            = ASSERT( not (null boot_only) )
                    -- The boot-only list must be non-empty, else there would
                    -- be an infinite chain of non-boot imports, and we've
                    -- already checked for that in processModDeps
              ModSummary -> SDoc
    pp_ms ModSummary
    loop_breaker SDoc -> SDoc -> SDoc
    $$ [SDoc] -> SDoc
    vcat ((SCC ModSummary -> SDoc) -> [SCC ModSummary] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map SCC ModSummary -> SDoc
    pp_group [SCC ModSummary]
    groups)
            where
              ([ModSummary]
    boot_only, [ModSummary]
    others) = (ModSummary -> Bool)
    -> [ModSummary] -> ([ModSummary], [ModSummary])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    partition ModSummary -> Bool
    is_boot_only [ModSummary]
    mss
              is_boot_only :: ModSummary -> Bool
    is_boot_only ModSummary
    ms = Bool -> Bool
    not ((GenLocated SrcSpan ModuleName -> Bool)
    -> [GenLocated SrcSpan ModuleName] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any GenLocated SrcSpan ModuleName -> Bool
    in_group (((Maybe FastString, GenLocated SrcSpan ModuleName)
     -> GenLocated SrcSpan ModuleName)
    -> [(Maybe FastString, GenLocated SrcSpan ModuleName)]
    -> [GenLocated SrcSpan ModuleName]
    forall a b. (a -> b) -> [a] -> [b]
    map (Maybe FastString, GenLocated SrcSpan ModuleName)
    -> GenLocated SrcSpan ModuleName
    forall a b. (a, b) -> b
    snd (ModSummary -> [(Maybe FastString, GenLocated SrcSpan ModuleName)]
    ms_imps ModSummary
    ms)))
              in_group :: GenLocated SrcSpan ModuleName -> Bool
    in_group (L SrcSpan
    _ ModuleName
    m) = ModuleName
    m ModuleName -> [ModuleName] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [ModuleName]
    group_mods
              group_mods :: [ModuleName]
    group_mods = (ModSummary -> ModuleName) -> [ModSummary] -> [ModuleName]
    forall a b. (a -> b) -> [a] -> [b]
    map (Module -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName (Module -> ModuleName)
    -> (ModSummary -> Module) -> ModSummary -> ModuleName
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ModSummary -> Module
    ms_mod) [ModSummary]
    mss

              loop_breaker :: ModSummary
    loop_breaker = [ModSummary] -> ModSummary
    forall a. [a] -> a
    head [ModSummary]
    boot_only
              all_others :: [ModSummary]
    all_others   = [ModSummary] -> [ModSummary]
    forall a. [a] -> [a]
    tail [ModSummary]
    boot_only [ModSummary] -> [ModSummary] -> [ModSummary]
    forall a. [a] -> [a] -> [a]
    ++ [ModSummary]
    others
              groups :: [SCC ModSummary]
    groups = [SCC ModuleGraphNode] -> [SCC ModSummary]
    filterToposortToModules ([SCC ModuleGraphNode] -> [SCC ModSummary])
    -> [SCC ModuleGraphNode] -> [SCC ModSummary]
    forall a b. (a -> b) -> a -> b
    $
                Bool -> ModuleGraph -> Maybe ModuleName -> [SCC ModuleGraphNode]
    GHC.topSortModuleGraph Bool
    True ([ExtendedModSummary] -> ModuleGraph
    mkModuleGraph ([ExtendedModSummary] -> ModuleGraph)
    -> [ExtendedModSummary] -> ModuleGraph
    forall a b. (a -> b) -> a -> b
    $ ModSummary -> ExtendedModSummary
    extendModSummaryNoDeps (ModSummary -> ExtendedModSummary)
    -> [ModSummary] -> [ExtendedModSummary]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> [ModSummary]
    all_others) Maybe ModuleName
    forall a. Maybe a
    Nothing

        pp_ms :: ModSummary -> SDoc
    pp_ms ModSummary
    summary = String -> SDoc
    text String
    mod_str SDoc -> SDoc -> SDoc
    <> String -> SDoc
    text (Int -> String -> String
    forall a. Int -> [a] -> [a]
    take (Int
    20 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - String -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length String
    mod_str) (Char -> String
    forall a. a -> [a]
    repeat Char
    ' '))
                           SDoc -> SDoc -> SDoc
    <+> (SDoc -> [GenLocated SrcSpan ModuleName] -> SDoc
    pp_imps SDoc
    empty (((Maybe FastString, GenLocated SrcSpan ModuleName)
     -> GenLocated SrcSpan ModuleName)
    -> [(Maybe FastString, GenLocated SrcSpan ModuleName)]
    -> [GenLocated SrcSpan ModuleName]
    forall a b. (a -> b) -> [a] -> [b]
    map (Maybe FastString, GenLocated SrcSpan ModuleName)
    -> GenLocated SrcSpan ModuleName
    forall a b. (a, b) -> b
    snd (ModSummary -> [(Maybe FastString, GenLocated SrcSpan ModuleName)]
    ms_imps ModSummary
    summary)) SDoc -> SDoc -> SDoc
    $$
                                SDoc -> [GenLocated SrcSpan ModuleName] -> SDoc
    pp_imps (String -> SDoc
    text String
    "{-# SOURCE #-}") (((Maybe FastString, GenLocated SrcSpan ModuleName)
     -> GenLocated SrcSpan ModuleName)
    -> [(Maybe FastString, GenLocated SrcSpan ModuleName)]
    -> [GenLocated SrcSpan ModuleName]
    forall a b. (a -> b) -> [a] -> [b]
    map (Maybe FastString, GenLocated SrcSpan ModuleName)
    -> GenLocated SrcSpan ModuleName
    forall a b. (a, b) -> b
    snd (ModSummary -> [(Maybe FastString, GenLocated SrcSpan ModuleName)]
    ms_srcimps ModSummary
    summary)))
            where
              mod_str :: String
    mod_str = ModuleName -> String
    moduleNameString (Module -> ModuleName
    forall unit. GenModule unit -> ModuleName
    moduleName (ModSummary -> Module
    ms_mod ModSummary
    summary))

        pp_imps :: SDoc -> [Located ModuleName] -> SDoc
        pp_imps :: SDoc -> [GenLocated SrcSpan ModuleName] -> SDoc
    pp_imps SDoc
    _    [] = SDoc
    empty
        pp_imps SDoc
    what [GenLocated SrcSpan ModuleName]
    lms
            = case [ModuleName
    m | L SrcSpan
    _ ModuleName
    m <- [GenLocated SrcSpan ModuleName]
    lms, ModuleName
    m ModuleName -> [ModuleName] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [ModuleName]
    cycle_mods] of
                [] -> SDoc
    empty
                [ModuleName]
    ms -> SDoc
    what SDoc -> SDoc -> SDoc
    <+> String -> SDoc
    text String
    "imports" SDoc -> SDoc -> SDoc
    <+>
                                    (ModuleName -> SDoc) -> [ModuleName] -> SDoc
    forall a. (a -> SDoc) -> [a] -> SDoc
    pprWithCommas ModuleName -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [ModuleName]
    ms

    -----------------------------------------------------------------
    --
    --              Flags
    --
    -----------------------------------------------------------------

    depStartMarker, depEndMarker :: String
    depStartMarker :: String
    depStartMarker = String
    "# DO NOT DELETE: Beginning of Haskell dependencies"
    depEndMarker :: String
    depEndMarker   = String
    "# DO NOT DELETE: End of Haskell dependencies"