[project @ 2000-10-24 16:08:16 by simonmar]
[ghc-hetmet.git] / ghc / compiler / main / Main.hs
1 {-# OPTIONS -W -fno-warn-incomplete-patterns #-}
2 -----------------------------------------------------------------------------
3 -- $Id: Main.hs,v 1.8 2000/10/24 16:08:16 simonmar Exp $
4 --
5 -- GHC Driver program
6 --
7 -- (c) Simon Marlow 2000
8 --
9 -----------------------------------------------------------------------------
10
11 -- with path so that ghc -M can find config.h
12 #include "../includes/config.h"
13
14 module Main (main) where
15
16 #include "HsVersions.h"
17
18 import DriverPipeline
19 import DriverState
20 import DriverFlags
21 import DriverMkDepend
22 import DriverUtil
23 import TmpFiles
24 import Config
25 import Util
26 import Panic
27
28 import Concurrent
29 #ifndef mingw32_TARGET_OS
30 import Posix
31 #endif
32 import Directory
33 import IOExts
34 import Exception
35 import Dynamic
36
37 import IO
38 import Monad
39 import List
40 import System
41 import Maybe
42
43 -----------------------------------------------------------------------------
44 -- Changes:
45
46 -- * -fglasgow-exts NO LONGER IMPLIES -package lang!!!  (-fglasgow-exts is a
47 --   dynamic flag whereas -package is a static flag.)
48
49 -----------------------------------------------------------------------------
50 -- ToDo:
51
52 -- new mkdependHS doesn't support all the options that the old one did (-X et al.)
53 -- time commands when run with -v
54 -- split marker
55 -- mkDLL
56 -- java generation
57 -- user ways
58 -- Win32 support: proper signal handling
59 -- make sure OPTIONS in .hs file propogate to .hc file if -C or -keep-hc-file-too
60 -- reading the package configuration file is too slow
61 -- -H, -K, -Rghc-timing
62 -- hi-diffs
63
64 -----------------------------------------------------------------------------
65 -- Differences vs. old driver:
66
67 -- No more "Enter your Haskell program, end with ^D (on a line of its own):"
68 -- consistency checking removed (may do this properly later)
69 -- removed -noC
70 -- no hi diffs (could be added later)
71 -- no -Ofile
72
73 -----------------------------------------------------------------------------
74 -- Main loop
75
76 main =
77   -- all error messages are propagated as exceptions
78   handleDyn (\dyn -> case dyn of
79                           PhaseFailed _phase code -> exitWith code
80                           Interrupted -> exitWith (ExitFailure 1)
81                           _ -> do hPutStrLn stderr (show (dyn :: BarfKind))
82                                   exitWith (ExitFailure 1)
83               ) $ do
84
85    -- make sure we clean up after ourselves
86    later (do  forget_it <- readIORef keep_tmp_files
87               unless forget_it $ do
88               verb <- readIORef verbose
89               cleanTempFiles verb
90      ) $ do
91         -- exceptions will be blocked while we clean the temporary files,
92         -- so there shouldn't be any difficulty if we receive further
93         -- signals.
94
95         -- install signal handlers
96    main_thread <- myThreadId
97
98 #ifndef mingw32_TARGET_OS
99    let sig_handler = Catch (throwTo main_thread 
100                                 (DynException (toDyn Interrupted)))
101    installHandler sigQUIT sig_handler Nothing 
102    installHandler sigINT  sig_handler Nothing
103 #endif
104
105    pgm    <- getProgName
106    writeIORef prog_name pgm
107
108    argv   <- getArgs
109
110         -- grab any -B options from the command line first
111    argv'  <- setTopDir argv
112    top_dir <- readIORef topDir
113
114    let installed s = top_dir ++ s
115        inplace s   = top_dir ++ '/':cCURRENT_DIR ++ '/':s
116
117        installed_pkgconfig = installed ("package.conf")
118        inplace_pkgconfig   = inplace (cGHC_DRIVER_DIR ++ "/package.conf.inplace")
119
120         -- discover whether we're running in a build tree or in an installation,
121         -- by looking for the package configuration file.
122    am_installed <- doesFileExist installed_pkgconfig
123
124    if am_installed
125         then writeIORef path_package_config installed_pkgconfig
126         else do am_inplace <- doesFileExist inplace_pkgconfig
127                 if am_inplace
128                     then writeIORef path_package_config inplace_pkgconfig
129                     else throwDyn (OtherError "can't find package.conf")
130
131         -- set the location of our various files
132    if am_installed
133         then do writeIORef path_usage (installed "ghc-usage.txt")
134                 writeIORef pgm_L (installed "unlit")
135                 writeIORef pgm_m (installed "ghc-asm")
136                 writeIORef pgm_s (installed "ghc-split")
137
138         else do writeIORef path_usage (inplace (cGHC_DRIVER_DIR ++ "/ghc-usage.txt"))
139                 writeIORef pgm_L (inplace cGHC_UNLIT)
140                 writeIORef pgm_m (inplace cGHC_MANGLER)
141                 writeIORef pgm_s (inplace cGHC_SPLIT)
142
143         -- read the package configuration
144    conf_file <- readIORef path_package_config
145    contents <- readFile conf_file
146    writeIORef package_details (read contents)
147
148         -- find the phase to stop after (i.e. -E, -C, -c, -S flags)
149    (flags2, mode, stop_flag) <- getGhcMode argv'
150    writeIORef v_GhcMode mode
151
152         -- process all the other arguments, and get the source files
153    non_static <- processArgs static_flags flags2 []
154
155         -- find the build tag, and re-process the build-specific options
156    more_opts <- findBuildTag
157    _ <- processArgs static_flags more_opts []
158  
159         -- give the static flags to hsc
160    static_opts <- buildStaticHscOpts
161    writeIORef static_hsc_opts static_opts
162
163         -- build the default DynFlags (these may be adjusted on a per
164         -- module basis by OPTIONS pragmas and settings in the interpreter).
165
166    core_todo <- buildCoreToDo
167    stg_todo  <- buildStgToDo
168
169    lang <- readIORef hsc_lang
170    writeIORef v_DynFlags 
171         DynFlags{ coreToDo = core_todo,
172                   stgToDo  = stg_todo,
173                   hscLang  = lang,
174                   -- leave out hscOutName for now
175                   flags = [] }
176
177         -- warnings
178     warn_level <- readIORef warning_opt
179     let warn_opts =  case warn_level of
180                         W_default -> standardWarnings
181                         W_        -> minusWOpts
182                         W_all     -> minusWallOpts
183                         W_not     -> []
184
185         -- the rest of the arguments are "dynamic"
186    srcs <- processArgs dynamic_flags non_static []
187         -- save the "initial DynFlags" away
188    dyn_flags <- readIORef v_DynFlags
189    writeIORef v_InitDynFlags 
190
191         -- complain about any unknown flags
192    let unknown_flags = [ f | ('-':f) <- srcs ]
193    mapM unknownFlagErr unknown_flags
194
195         -- get the -v flag
196    verb <- readIORef verbose
197
198    when verb (do hPutStr stderr "Glasgow Haskell Compiler, Version "
199                  hPutStr stderr version_str
200                  hPutStr stderr ", for Haskell 98, compiled by GHC version "
201                  hPutStrLn stderr booter_version)
202
203    when verb (hPutStrLn stderr ("Using package config file: " ++ conf_file))
204
205         -- mkdependHS is special
206    when (mode == DoMkDependHS) beginMkDependHS
207
208         -- make is special
209    when (mode == DoMake) beginMake
210
211         -- for each source file, find which phases to run
212    pipelines <- mapM (genPipeline mode stop_flag) srcs
213    let src_pipelines = zip srcs pipelines
214
215    o_file <- readIORef output_file
216    if isJust o_file && mode /= DoLink && length srcs > 1
217         then throwDyn (UsageError "can't apply -o option to multiple source files")
218         else do
219
220    if null srcs then throwDyn (UsageError "no input files") else do
221
222         -- save the flag state, because this could be modified by OPTIONS pragmas
223         -- during the compilation, and we'll need to restore it before starting
224         -- the next compilation.
225    saved_driver_state <- readIORef driver_state
226
227    let compileFile (src, phases) = do
228           r <- runPipeline phases src (mode==DoLink) True
229           writeIORef driver_state saved_driver_state
230           return r
231
232    o_files <- mapM compileFile src_pipelines
233
234    when (mode == DoMkDependHS) endMkDependHS
235    when (mode == DoLink) (doLink o_files)
236
237         -- grab the last -B option on the command line, and
238         -- set topDir to its value.
239 setTopDir :: [String] -> IO [String]
240 setTopDir args = do
241   let (minusbs, others) = partition (prefixMatch "-B") args
242   (case minusbs of
243     []   -> writeIORef topDir clibdir
244     some -> writeIORef topDir (drop 2 (last some)))
245   return others
246
247 beginMake = panic "`ghc --make' unimplemented"
248
249 -----------------------------------------------------------------------------
250 -- compatibility code
251
252 #if __GLASGOW_HASKELL__ <= 408
253 catchJust = catchIO
254 ioErrors  = justIoErrors
255 throwTo   = raiseInThread
256 #endif
257
258 #ifdef mingw32_TARGET_OS
259 foreign import "_getpid" getProcessID :: IO Int 
260 #endif