[project @ 2000-10-11 15:26:18 by simonmar]
[ghc-hetmet.git] / ghc / compiler / main / Main.hs
1 {-# OPTIONS -W -fno-warn-incomplete-patterns #-}
2 -----------------------------------------------------------------------------
3 -- $Id: Main.hs,v 1.4 2000/10/11 15:26:18 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_C (installed "hsc")
136                 writeIORef pgm_m (installed "ghc-asm")
137                 writeIORef pgm_s (installed "ghc-split")
138
139         else do writeIORef path_usage (inplace (cGHC_DRIVER_DIR ++ "/ghc-usage.txt"))
140                 writeIORef pgm_L (inplace cGHC_UNLIT)
141                 writeIORef pgm_C (inplace cGHC_HSC)
142                 writeIORef pgm_m (inplace cGHC_MANGLER)
143                 writeIORef pgm_s (inplace cGHC_SPLIT)
144
145         -- read the package configuration
146    conf_file <- readIORef path_package_config
147    contents <- readFile conf_file
148    writeIORef package_details (read contents)
149
150         -- find the phase to stop after (i.e. -E, -C, -c, -S flags)
151    (flags2, mode, stop_flag) <- getGhcMode argv'
152    writeIORef v_GhcMode mode
153
154         -- process all the other arguments, and get the source files
155    non_static <- processArgs static_flags flags2 []
156
157         -- find the build tag, and re-process the build-specific options
158    more_opts <- findBuildTag
159    _ <- processArgs static_flags more_opts []
160  
161         -- give the static flags to hsc
162    build_hsc_opts
163
164         -- the rest of the arguments are "dynamic"
165    srcs <- processArgs dynamic_flags non_static []
166
167         -- complain about any unknown flags
168    let unknown_flags = [ f | ('-':f) <- srcs ]
169    mapM unknownFlagErr unknown_flags
170
171         -- get the -v flag
172    verb <- readIORef verbose
173
174    when verb (do hPutStr stderr "Glasgow Haskell Compiler, Version "
175                  hPutStr stderr version_str
176                  hPutStr stderr ", for Haskell 98, compiled by GHC version "
177                  hPutStrLn stderr booter_version)
178
179    when verb (hPutStrLn stderr ("Using package config file: " ++ conf_file))
180
181         -- mkdependHS is special
182    when (mode == DoMkDependHS) beginMkDependHS
183
184         -- make is special
185    when (mode == DoMake) beginMake
186
187         -- for each source file, find which phases to run
188    pipelines <- mapM (genPipeline mode stop_flag) srcs
189    let src_pipelines = zip srcs pipelines
190
191    o_file <- readIORef output_file
192    if isJust o_file && mode /= DoLink && length srcs > 1
193         then throwDyn (UsageError "can't apply -o option to multiple source files")
194         else do
195
196    if null srcs then throwDyn (UsageError "no input files") else do
197
198         -- save the flag state, because this could be modified by OPTIONS pragmas
199         -- during the compilation, and we'll need to restore it before starting
200         -- the next compilation.
201    saved_driver_state <- readIORef driver_state
202
203    let compileFile (src, phases) = do
204           r <- runPipeline phases src (mode==DoLink) True
205           writeIORef driver_state saved_driver_state
206           return r
207
208    o_files <- mapM compileFile src_pipelines
209
210    when (mode == DoMkDependHS) endMkDependHS
211
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