summaryrefslogtreecommitdiff
path: root/ghc/compiler/main/DriverMkDepend.hs
blob: 46e8cdc10d4e5fd092a4349cbeb176c8c1f256cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
-----------------------------------------------------------------------------
-- $Id: DriverMkDepend.hs,v 1.15 2001/08/03 07:44:47 sof Exp $
--
-- GHC Driver
--
-- (c) Simon Marlow 2000
--
-----------------------------------------------------------------------------

module DriverMkDepend where

#include "HsVersions.h"

import DriverState
import DriverUtil
import DriverFlags
import SysTools		( newTempName )
import qualified SysTools
import Module
import Config
import Module		( isHomeModule )
import Finder		( findModuleDep )
import HscTypes		( ModuleLocation(..) )
import Util
import Panic

import IOExts
import Exception

import Directory
import IO
import Monad
import Maybe

-------------------------------------------------------------------------------
-- mkdependHS

	-- flags
GLOBAL_VAR(v_Dep_makefile, 		"Makefile", String);
GLOBAL_VAR(v_Dep_include_prelude, 	False, Bool);
GLOBAL_VAR(v_Dep_exclude_mods,          [], [String]);
GLOBAL_VAR(v_Dep_suffixes,		[], [String]);
GLOBAL_VAR(v_Dep_warnings,		True, Bool);

	-- global vars
GLOBAL_VAR(v_Dep_makefile_hdl,  error "dep_makefile_hdl", Maybe Handle);
GLOBAL_VAR(v_Dep_tmp_file,      error "dep_tmp_file", String);
GLOBAL_VAR(v_Dep_tmp_hdl,       error "dep_tmp_hdl", Handle);
GLOBAL_VAR(v_Dep_dir_contents,  error "dep_dir_contents", [(String,[String])]);

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

-- for compatibility with the old mkDependHS, we accept options of the form
-- -optdep-f -optdep.depend, etc.
dep_opts = [
   (  "s", 			SepArg (add v_Dep_suffixes) ),
   (  "f", 			SepArg (writeIORef v_Dep_makefile) ),
   (  "w", 			NoArg (writeIORef v_Dep_warnings False) ),
   (  "-include-prelude",  	NoArg (writeIORef v_Dep_include_prelude True) )
--   (  "-exclude-module=",       Prefix (add v_Dep_exclude_mods) )
--   (  "x",                      Prefix (add v_Dep_exclude_mods) )
 ]

beginMkDependHS :: IO ()
beginMkDependHS = do

  	-- slurp in the mkdependHS-style options
  flags <- getStaticOpts v_Opt_dep
  _ <- processArgs dep_opts flags []

     	-- open a new temp file in which to stuff the dependency info
     	-- as we go along.
  dep_file <- newTempName "dep"
  writeIORef v_Dep_tmp_file dep_file
  tmp_hdl <- openFile dep_file WriteMode
  writeIORef v_Dep_tmp_hdl tmp_hdl

  	-- open the makefile
  makefile <- readIORef v_Dep_makefile
  exists <- doesFileExist makefile
  if not exists
	then do 
	   writeIORef v_Dep_makefile_hdl Nothing
	   return ()

	else do
  	   makefile_hdl <- openFile makefile ReadMode
  	   writeIORef v_Dep_makefile_hdl (Just makefile_hdl)

		-- slurp through until we get the magic start string,
		-- copying the contents into dep_makefile
  	   let slurp = do
		l <- hGetLine makefile_hdl
		if (l == depStartMarker)
			then return ()
			else do hPutStrLn tmp_hdl l; slurp
	 
		-- slurp through until we get the magic end marker,
		-- throwing away the contents
  	   let chuck = do
		l <- hGetLine makefile_hdl
		if (l == depEndMarker)
			then return ()
			else chuck
	 
	   catchJust ioErrors slurp 
		(\e -> if isEOFError e then return () else ioError e)
	   catchJust ioErrors chuck
		(\e -> if isEOFError e then return () else ioError e)


	-- write the magic marker into the tmp file
  hPutStrLn tmp_hdl depStartMarker

  	-- cache the contents of all the import directories, for future
	-- reference.
  import_dirs <- readIORef v_Import_paths
  pkg_import_dirs <- getPackageImportPath
  import_dir_contents <- mapM softGetDirectoryContents import_dirs
  pkg_import_dir_contents <- mapM softGetDirectoryContents pkg_import_dirs
  writeIORef v_Dep_dir_contents 
	(zip import_dirs import_dir_contents ++
  	 zip pkg_import_dirs pkg_import_dir_contents)

  return ()


endMkDependHS :: IO ()
endMkDependHS = do
  makefile     <- readIORef v_Dep_makefile
  makefile_hdl <- readIORef v_Dep_makefile_hdl
  tmp_file     <- readIORef v_Dep_tmp_file
  tmp_hdl      <- readIORef v_Dep_tmp_hdl

	-- write the magic marker into the tmp file
  hPutStrLn tmp_hdl depEndMarker

  case makefile_hdl of
     Nothing  -> return ()
     Just hdl -> do

	  -- slurp the rest of the original makefile and copy it into the output
  	let slurp = do
		l <- hGetLine hdl
		hPutStrLn tmp_hdl l
		slurp
	 
  	catchJust ioErrors slurp 
		(\e -> if isEOFError e then return () else ioError e)

	hClose hdl

  hClose tmp_hdl  -- make sure it's flushed

	-- Create a backup of the original makefile
  when (isJust makefile_hdl)
       (SysTools.copy ("Backing up " ++ makefile) makefile (makefile++".bak"))

  	-- Copy the new makefile in place
  SysTools.copy "Installing new makefile" tmp_file makefile


findDependency :: Bool -> FilePath -> ModuleName -> IO (Maybe (String, Bool))
findDependency is_source src imp = do
   excl_mods <- readIORef v_Dep_exclude_mods
   include_prelude <- readIORef v_Dep_include_prelude
   let imp_mod = moduleNameUserString imp
   if imp_mod `elem` excl_mods 
      then return Nothing
      else do
	r <- findModuleDep imp is_source
	case r of 
	   Just (mod,loc)
		| isHomeModule mod || include_prelude
		-> return (Just (ml_hi_file loc, not is_source))
		| otherwise 
		-> return Nothing
	   Nothing -> throwDyn (ProgramError 
		(src ++ ": " ++ "can't locate import `" ++ imp_mod ++ "'"))