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