[project @ 2000-10-24 08:40:09 by simonpj]
[ghc-hetmet.git] / ghc / compiler / main / Main.hs
1 {-# OPTIONS -W -fno-warn-incomplete-patterns #-}
2 -----------------------------------------------------------------------------
3 -- $Id: Main.hs,v 1.6 2000/10/17 13:22:11 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    build_hsc_opts
161
162         -- the rest of the arguments are "dynamic"
163    srcs <- processArgs dynamic_flags non_static []
164         -- save the "initial DynFlags" away
165    dyn_flags <- readIORef v_DynFlags
166    writeIORef v_InitDynFlags dyn_flags
167
168         -- complain about any unknown flags
169    let unknown_flags = [ f | ('-':f) <- srcs ]
170    mapM unknownFlagErr unknown_flags
171
172         -- get the -v flag
173    verb <- readIORef verbose
174
175    when verb (do hPutStr stderr "Glasgow Haskell Compiler, Version "
176                  hPutStr stderr version_str
177                  hPutStr stderr ", for Haskell 98, compiled by GHC version "
178                  hPutStrLn stderr booter_version)
179
180    when verb (hPutStrLn stderr ("Using package config file: " ++ conf_file))
181
182         -- mkdependHS is special
183    when (mode == DoMkDependHS) beginMkDependHS
184
185         -- make is special
186    when (mode == DoMake) beginMake
187
188         -- for each source file, find which phases to run
189    pipelines <- mapM (genPipeline mode stop_flag) srcs
190    let src_pipelines = zip srcs pipelines
191
192    o_file <- readIORef output_file
193    if isJust o_file && mode /= DoLink && length srcs > 1
194         then throwDyn (UsageError "can't apply -o option to multiple source files")
195         else do
196
197    if null srcs then throwDyn (UsageError "no input files") else do
198
199         -- save the flag state, because this could be modified by OPTIONS pragmas
200         -- during the compilation, and we'll need to restore it before starting
201         -- the next compilation.
202    saved_driver_state <- readIORef driver_state
203
204    let compileFile (src, phases) = do
205           r <- runPipeline phases src (mode==DoLink) True
206           writeIORef driver_state saved_driver_state
207           return r
208
209    o_files <- mapM compileFile src_pipelines
210
211    when (mode == DoMkDependHS) endMkDependHS
212    when (mode == DoLink) (doLink o_files)
213
214         -- grab the last -B option on the command line, and
215         -- set topDir to its value.
216 setTopDir :: [String] -> IO [String]
217 setTopDir args = do
218   let (minusbs, others) = partition (prefixMatch "-B") args
219   (case minusbs of
220     []   -> writeIORef topDir clibdir
221     some -> writeIORef topDir (drop 2 (last some)))
222   return others
223
224 beginMake = panic "`ghc --make' unimplemented"
225
226 -----------------------------------------------------------------------------
227 -- compatibility code
228
229 #if __GLASGOW_HASKELL__ <= 408
230 catchJust = catchIO
231 ioErrors  = justIoErrors
232 throwTo   = raiseInThread
233 #endif
234
235 #ifdef mingw32_TARGET_OS
236 foreign import "_getpid" getProcessID :: IO Int 
237 #endif