root/compiler/main/DriverMkDepend.hs

Revision 62875b799e013a720fca6c5f6e9e3cefed2e9e62, 14.3 KB (checked in by David Terei <davidterei@…>, 13 months ago)

Remove unused imports

  • Property mode set to 100644
Line 
1{-# OPTIONS -fno-cse #-}
2-- -fno-cse is needed for GLOBAL_VAR's to behave properly
3
4-----------------------------------------------------------------------------
5--
6-- Makefile Dependency Generation
7--
8-- (c) The University of Glasgow 2005
9--
10-----------------------------------------------------------------------------
11
12module DriverMkDepend (
13        doMkDependHS
14  ) where
15
16#include "HsVersions.h"
17
18import qualified GHC
19import GhcMonad
20import HsSyn            ( ImportDecl(..) )
21import DynFlags
22import Util
23import HscTypes
24import SysTools         ( newTempName )
25import qualified SysTools
26import Module
27import Digraph          ( SCC(..) )
28import Finder
29import Outputable
30import Panic
31import SrcLoc
32import Data.List
33import FastString
34
35import Exception
36import ErrUtils
37
38import System.Directory
39import System.FilePath
40import System.IO
41import System.IO.Error  ( isEOFError )
42import Control.Monad    ( when )
43import Data.Maybe       ( isJust )
44
45-----------------------------------------------------------------
46--
47--              The main function
48--
49-----------------------------------------------------------------
50
51doMkDependHS :: GhcMonad m => [FilePath] -> m ()
52doMkDependHS srcs = do
53    -- Initialisation
54    dflags <- GHC.getSessionDynFlags
55    files <- liftIO $ beginMkDependHS dflags
56
57    -- Do the downsweep to find all the modules
58    targets <- mapM (\s -> GHC.guessTarget s Nothing) srcs
59    GHC.setTargets targets
60    let excl_mods = depExcludeMods dflags
61    mod_summaries <- GHC.depanal excl_mods True {- Allow dup roots -}
62
63    -- Sort into dependency order
64    -- There should be no cycles
65    let sorted = GHC.topSortModuleGraph False mod_summaries Nothing
66
67    -- Print out the dependencies if wanted
68    liftIO $ debugTraceMsg dflags 2 (text "Module dependencies" $$ ppr sorted)
69
70    -- Prcess them one by one, dumping results into makefile
71    -- and complaining about cycles
72    hsc_env <- getSession
73    root <- liftIO getCurrentDirectory
74    mapM_ (liftIO . processDeps dflags hsc_env excl_mods root (mkd_tmp_hdl files)) sorted
75
76    -- If -ddump-mod-cycles, show cycles in the module graph
77    liftIO $ dumpModCycles dflags mod_summaries
78
79    -- Tidy up
80    liftIO $ endMkDependHS dflags files
81
82    -- Unconditional exiting is a bad idea.  If an error occurs we'll get an
83    --exception; if that is not caught it's fine, but at least we have a
84    --chance to find out exactly what went wrong.  Uncomment the following
85    --line if you disagree.
86
87    --`GHC.ghcCatch` \_ -> io $ exitWith (ExitFailure 1)
88
89-----------------------------------------------------------------
90--
91--              beginMkDependHs
92--      Create a temporary file,
93--      find the Makefile,
94--      slurp through it, etc
95--
96-----------------------------------------------------------------
97
98data MkDepFiles
99  = MkDep { mkd_make_file :: FilePath,          -- Name of the makefile
100            mkd_make_hdl  :: Maybe Handle,      -- Handle for the open makefile
101            mkd_tmp_file  :: FilePath,          -- Name of the temporary file
102            mkd_tmp_hdl   :: Handle }           -- Handle of the open temporary file
103
104beginMkDependHS :: DynFlags -> IO MkDepFiles
105beginMkDependHS dflags = do
106        -- open a new temp file in which to stuff the dependency info
107        -- as we go along.
108  tmp_file <- newTempName dflags "dep"
109  tmp_hdl <- openFile tmp_file WriteMode
110
111        -- open the makefile
112  let makefile = depMakefile dflags
113  exists <- doesFileExist makefile
114  mb_make_hdl <-
115        if not exists
116        then return Nothing
117        else do
118           makefile_hdl <- openFile makefile ReadMode
119
120                -- slurp through until we get the magic start string,
121                -- copying the contents into dep_makefile
122           let slurp = do
123                l <- hGetLine makefile_hdl
124                if (l == depStartMarker)
125                        then return ()
126                        else do hPutStrLn tmp_hdl l; slurp
127
128                -- slurp through until we get the magic end marker,
129                -- throwing away the contents
130           let chuck = do
131                l <- hGetLine makefile_hdl
132                if (l == depEndMarker)
133                        then return ()
134                        else chuck
135
136           catchIO slurp
137                (\e -> if isEOFError e then return () else ioError e)
138           catchIO chuck
139                (\e -> if isEOFError e then return () else ioError e)
140
141           return (Just makefile_hdl)
142
143
144        -- write the magic marker into the tmp file
145  hPutStrLn tmp_hdl depStartMarker
146
147  return (MkDep { mkd_make_file = makefile, mkd_make_hdl = mb_make_hdl,
148                  mkd_tmp_file  = tmp_file, mkd_tmp_hdl  = tmp_hdl})
149
150
151-----------------------------------------------------------------
152--
153--              processDeps
154--
155-----------------------------------------------------------------
156
157processDeps :: DynFlags
158            -> HscEnv
159            -> [ModuleName]
160            -> FilePath
161            -> Handle           -- Write dependencies to here
162            -> SCC ModSummary
163            -> IO ()
164-- Write suitable dependencies to handle
165-- Always:
166--                      this.o : this.hs
167--
168-- If the dependency is on something other than a .hi file:
169--                      this.o this.p_o ... : dep
170-- otherwise
171--                      this.o ...   : dep.hi
172--                      this.p_o ... : dep.p_hi
173--                      ...
174-- (where .o is $osuf, and the other suffixes come from
175-- the cmdline -s options).
176--
177-- For {-# SOURCE #-} imports the "hi" will be "hi-boot".
178
179processDeps _ _ _ _ _ (CyclicSCC nodes)
180  =     -- There shouldn't be any cycles; report them
181    ghcError (ProgramError (showSDoc $ GHC.cyclicModuleErr nodes))
182
183processDeps dflags hsc_env excl_mods root hdl (AcyclicSCC node)
184  = do  { let extra_suffixes = depSuffixes dflags
185              include_pkg_deps = depIncludePkgDeps dflags
186              src_file  = msHsFilePath node
187              obj_file  = msObjFilePath node
188              obj_files = insertSuffixes obj_file extra_suffixes
189
190              do_imp loc is_boot pkg_qual imp_mod
191                = do { mb_hi <- findDependency hsc_env loc pkg_qual imp_mod
192                                               is_boot include_pkg_deps
193                     ; case mb_hi of {
194                           Nothing      -> return () ;
195                           Just hi_file -> do
196                     { let hi_files = insertSuffixes hi_file extra_suffixes
197                           write_dep (obj,hi) = writeDependency root hdl [obj] hi
198
199                        -- Add one dependency for each suffix;
200                        -- e.g.         A.o   : B.hi
201                        --              A.x_o : B.x_hi
202                     ; mapM_ write_dep (obj_files `zip` hi_files) }}}
203
204
205                -- Emit std dependency of the object(s) on the source file
206                -- Something like       A.o : A.hs
207        ; writeDependency root hdl obj_files src_file
208
209                -- Emit a dependency for each import
210
211        ; let do_imps is_boot idecls = sequence_
212                    [ do_imp loc is_boot (ideclPkgQual i) mod
213                    | L loc i <- idecls,
214                      let mod = unLoc (ideclName i),
215                      mod `notElem` excl_mods ]
216
217        ; do_imps True  (ms_srcimps node)
218        ; do_imps False (ms_imps node)
219        }
220
221
222findDependency  :: HscEnv
223                -> SrcSpan
224                -> Maybe FastString     -- package qualifier, if any
225                -> ModuleName           -- Imported module
226                -> IsBootInterface      -- Source import
227                -> Bool                 -- Record dependency on package modules
228                -> IO (Maybe FilePath)  -- Interface file file
229findDependency hsc_env srcloc pkg imp is_boot include_pkg_deps
230  = do  {       -- Find the module; this will be fast because
231                -- we've done it once during downsweep
232          r <- findImportedModule hsc_env imp pkg
233        ; case r of
234            Found loc _
235                -- Home package: just depend on the .hi or hi-boot file
236                | isJust (ml_hs_file loc) || include_pkg_deps
237                -> return (Just (addBootSuffix_maybe is_boot (ml_hi_file loc)))
238
239                -- Not in this package: we don't need a dependency
240                | otherwise
241                -> return Nothing
242
243            fail -> throwOneError $ mkPlainErrMsg srcloc $
244                        cannotFindModule (hsc_dflags hsc_env) imp fail
245        }
246
247-----------------------------
248writeDependency :: FilePath -> Handle -> [FilePath] -> FilePath -> IO ()
249-- (writeDependency r h [t1,t2] dep) writes to handle h the dependency
250--      t1 t2 : dep
251writeDependency root hdl targets dep
252  = do let -- We need to avoid making deps on
253           --     c:/foo/...
254           -- on cygwin as make gets confused by the :
255           -- Making relative deps avoids some instances of this.
256           dep' = makeRelative root dep
257           forOutput = escapeSpaces . reslash Forwards . normalise
258           output = unwords (map forOutput targets) ++ " : " ++ forOutput dep'
259       hPutStrLn hdl output
260
261-----------------------------
262insertSuffixes
263        :: FilePath     -- Original filename;   e.g. "foo.o"
264        -> [String]     -- Extra suffices       e.g. ["x","y"]
265        -> [FilePath]   -- Zapped filenames     e.g. ["foo.o", "foo.x_o", "foo.y_o"]
266        -- Note that that the extra bit gets inserted *before* the old suffix
267        -- We assume the old suffix contains no dots, so we can strip it with removeSuffix
268
269        -- NOTE: we used to have this comment
270                -- In order to construct hi files with alternate suffixes, we
271                -- now have to find the "basename" of the hi file.  This is
272                -- difficult because we can't just split the hi filename
273                -- at the last dot - the hisuf might have dots in it.  So we
274                -- check whether the hi filename ends in hisuf, and if it does,
275                -- we strip off hisuf, otherwise we strip everything after the
276                -- last dot.
277        -- But I'm not sure we care about hisufs with dots in them.
278        -- Lots of other things will break first!
279
280insertSuffixes file_name extras
281  = file_name : [ basename <.> (extra ++ "_" ++ suffix) | extra <- extras ]
282  where
283    (basename, suffix) = case splitExtension file_name of
284                         -- Drop the "." from the extension
285                         (b, s) -> (b, drop 1 s)
286
287
288-----------------------------------------------------------------
289--
290--              endMkDependHs
291--      Complete the makefile, close the tmp file etc
292--
293-----------------------------------------------------------------
294
295endMkDependHS :: DynFlags -> MkDepFiles -> IO ()
296
297endMkDependHS dflags
298   (MkDep { mkd_make_file = makefile, mkd_make_hdl =  makefile_hdl,
299            mkd_tmp_file  = tmp_file, mkd_tmp_hdl  =  tmp_hdl })
300  = do
301  -- write the magic marker into the tmp file
302  hPutStrLn tmp_hdl depEndMarker
303
304  case makefile_hdl of
305     Nothing  -> return ()
306     Just hdl -> do
307
308          -- slurp the rest of the original makefile and copy it into the output
309        let slurp = do
310                l <- hGetLine hdl
311                hPutStrLn tmp_hdl l
312                slurp
313
314        catchIO slurp
315                (\e -> if isEOFError e then return () else ioError e)
316
317        hClose hdl
318
319  hClose tmp_hdl  -- make sure it's flushed
320
321        -- Create a backup of the original makefile
322  when (isJust makefile_hdl)
323       (SysTools.copy dflags ("Backing up " ++ makefile)
324          makefile (makefile++".bak"))
325
326        -- Copy the new makefile in place
327  SysTools.copy dflags "Installing new makefile" tmp_file makefile
328
329
330-----------------------------------------------------------------
331--              Module cycles
332-----------------------------------------------------------------
333
334dumpModCycles :: DynFlags -> [ModSummary] -> IO ()
335dumpModCycles dflags mod_summaries
336  | not (dopt Opt_D_dump_mod_cycles dflags)
337  = return ()
338
339  | null cycles
340  = putMsg dflags (ptext (sLit "No module cycles"))
341
342  | otherwise
343  = putMsg dflags (hang (ptext (sLit "Module cycles found:")) 2 pp_cycles)
344  where
345
346    cycles :: [[ModSummary]]
347    cycles = [ c | CyclicSCC c <- GHC.topSortModuleGraph True mod_summaries Nothing ]
348
349    pp_cycles = vcat [ (ptext (sLit "---------- Cycle") <+> int n <+> ptext (sLit "----------"))
350                        $$ pprCycle c $$ blankLine
351                     | (n,c) <- [1..] `zip` cycles ]
352
353pprCycle :: [ModSummary] -> SDoc
354-- Print a cycle, but show only the imports within the cycle
355pprCycle summaries = pp_group (CyclicSCC summaries)
356  where
357    cycle_mods :: [ModuleName]  -- The modules in this cycle
358    cycle_mods = map (moduleName . ms_mod) summaries
359
360    pp_group (AcyclicSCC ms) = pp_ms ms
361    pp_group (CyclicSCC mss)
362        = ASSERT( not (null boot_only) )
363                -- The boot-only list must be non-empty, else there would
364                -- be an infinite chain of non-boot imoprts, and we've
365                -- already checked for that in processModDeps
366          pp_ms loop_breaker $$ vcat (map pp_group groups)
367        where
368          (boot_only, others) = partition is_boot_only mss
369          is_boot_only ms = not (any in_group (map (ideclName.unLoc) (ms_imps ms)))
370          in_group (L _ m) = m `elem` group_mods
371          group_mods = map (moduleName . ms_mod) mss
372
373          loop_breaker = head boot_only
374          all_others   = tail boot_only ++ others
375          groups = GHC.topSortModuleGraph True all_others Nothing
376
377    pp_ms summary = text mod_str <> text (take (20 - length mod_str) (repeat ' '))
378                       <+> (pp_imps empty (map (ideclName.unLoc) (ms_imps summary)) $$
379                            pp_imps (ptext (sLit "{-# SOURCE #-}")) (map (ideclName.unLoc) (ms_srcimps summary)))
380        where
381          mod_str = moduleNameString (moduleName (ms_mod summary))
382
383    pp_imps :: SDoc -> [Located ModuleName] -> SDoc
384    pp_imps _    [] = empty
385    pp_imps what lms
386        = case [m | L _ m <- lms, m `elem` cycle_mods] of
387            [] -> empty
388            ms -> what <+> ptext (sLit "imports") <+>
389                                pprWithCommas ppr ms
390
391-----------------------------------------------------------------
392--
393--              Flags
394--
395-----------------------------------------------------------------
396
397depStartMarker, depEndMarker :: String
398depStartMarker = "# DO NOT DELETE: Beginning of Haskell dependencies"
399depEndMarker   = "# DO NOT DELETE: End of Haskell dependencies"
Note: See TracBrowser for help on using the browser.