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