root/ghc/Main.hs

Revision 93299cce9a4f7bc65b8164f779a37ef7f9f7c4a0, 29.7 KB (checked in by Simon Marlow <marlowsd@…>, 3 months ago)

Tweak to flag parsing (#5921)

-o2/Main.exe should be an invalid flag, not a linker input

  • Property mode set to 100644
Line 
1{-# OPTIONS -fno-warn-incomplete-patterns -optc-DNON_POSIX_SOURCE #-}
2
3-----------------------------------------------------------------------------
4--
5-- GHC Driver program
6--
7-- (c) The University of Glasgow 2005
8--
9-----------------------------------------------------------------------------
10
11module Main (main) where
12
13-- The official GHC API
14import qualified GHC
15import GHC              ( -- DynFlags(..), HscTarget(..),
16                          -- GhcMode(..), GhcLink(..),
17                          Ghc, GhcMonad(..),
18                          LoadHowMuch(..) )
19import CmdLineParser
20
21-- Implementations of the various modes (--show-iface, mkdependHS. etc.)
22import LoadIface        ( showIface )
23import HscMain          ( newHscEnv )
24import DriverPipeline   ( oneShot, compileFile )
25import DriverMkDepend   ( doMkDependHS )
26#ifdef GHCI
27import InteractiveUI    ( interactiveUI, ghciWelcomeMsg )
28#endif
29
30
31-- Various other random stuff that we need
32import Config
33import HscTypes
34import Packages         ( dumpPackages )
35import DriverPhases     ( Phase(..), isSourceFilename, anyHsc,
36                          startPhase, isHaskellSrcFilename )
37import BasicTypes       ( failed )
38import StaticFlags
39import StaticFlagParser
40import DynFlags
41import ErrUtils
42import FastString
43import Outputable
44import SrcLoc
45import Util
46import Panic
47import MonadUtils       ( liftIO )
48
49-- Imports for --abi-hash
50import LoadIface           ( loadUserInterface )
51import Module              ( mkModuleName )
52import Finder              ( findImportedModule, cannotFindInterface )
53import TcRnMonad           ( initIfaceCheck )
54import Binary              ( openBinMem, put_, fingerprintBinMem )
55
56-- Standard Haskell libraries
57import System.IO
58import System.Environment
59import System.Exit
60import System.FilePath
61import Control.Monad
62import Data.Char
63import Data.List
64import Data.Maybe
65
66-----------------------------------------------------------------------------
67-- ToDo:
68
69-- time commands when run with -v
70-- user ways
71-- Win32 support: proper signal handling
72-- reading the package configuration file is too slow
73-- -K<size>
74
75-----------------------------------------------------------------------------
76-- GHC's command-line interface
77
78main :: IO ()
79main = do
80   hSetBuffering stdout NoBuffering
81   GHC.defaultErrorHandler defaultLogAction defaultFlushOut $ do
82    -- 1. extract the -B flag from the args
83    argv0 <- getArgs
84
85    let (minusB_args, argv1) = partition ("-B" `isPrefixOf`) argv0
86        mbMinusB | null minusB_args = Nothing
87                 | otherwise = Just (drop 2 (last minusB_args))
88
89    let argv1' = map (mkGeneralLocated "on the commandline") argv1
90    (argv2, staticFlagWarnings) <- parseStaticFlags argv1'
91
92    -- 2. Parse the "mode" flags (--make, --interactive etc.)
93    (mode, argv3, modeFlagWarnings) <- parseModeFlags argv2
94
95    let flagWarnings = staticFlagWarnings ++ modeFlagWarnings
96
97    -- If all we want to do is something like showing the version number
98    -- then do it now, before we start a GHC session etc. This makes
99    -- getting basic information much more resilient.
100
101    -- In particular, if we wait until later before giving the version
102    -- number then bootstrapping gets confused, as it tries to find out
103    -- what version of GHC it's using before package.conf exists, so
104    -- starting the session fails.
105    case mode of
106        Left preStartupMode ->
107            do case preStartupMode of
108                   ShowSupportedExtensions -> showSupportedExtensions
109                   ShowVersion             -> showVersion
110                   ShowNumVersion          -> putStrLn cProjectVersion
111                   Print str               -> putStrLn str
112        Right postStartupMode ->
113            -- start our GHC session
114            GHC.runGhc mbMinusB $ do
115
116            dflags <- GHC.getSessionDynFlags
117
118            case postStartupMode of
119                Left preLoadMode ->
120                    liftIO $ do
121                        case preLoadMode of
122                            ShowInfo               -> showInfo dflags
123                            ShowGhcUsage           -> showGhcUsage  dflags
124                            ShowGhciUsage          -> showGhciUsage dflags
125                            PrintWithDynFlags f    -> putStrLn (f dflags)
126                Right postLoadMode ->
127                    main' postLoadMode dflags argv3 flagWarnings
128
129main' :: PostLoadMode -> DynFlags -> [Located String] -> [Located String]
130      -> Ghc ()
131main' postLoadMode dflags0 args flagWarnings = do
132  -- set the default GhcMode, HscTarget and GhcLink.  The HscTarget
133  -- can be further adjusted on a module by module basis, using only
134  -- the -fvia-C and -fasm flags.  If the default HscTarget is not
135  -- HscC or HscAsm, -fvia-C and -fasm have no effect.
136  let dflt_target = hscTarget dflags0
137      (mode, lang, link)
138         = case postLoadMode of
139               DoInteractive   -> (CompManager, HscInterpreted, LinkInMemory)
140               DoEval _        -> (CompManager, HscInterpreted, LinkInMemory)
141               DoMake          -> (CompManager, dflt_target,    LinkBinary)
142               DoMkDependHS    -> (MkDepend,    dflt_target,    LinkBinary)
143               DoAbiHash       -> (OneShot,     dflt_target,    LinkBinary)
144               _               -> (OneShot,     dflt_target,    LinkBinary)
145
146  let dflags1 = dflags0{ ghcMode   = mode,
147                         hscTarget = lang,
148                         ghcLink   = link,
149                         -- leave out hscOutName for now
150                         hscOutName = panic "Main.main:hscOutName not set",
151                         verbosity = case postLoadMode of
152                                         DoEval _ -> 0
153                                         _other   -> 1
154                        }
155
156      -- turn on -fimplicit-import-qualified for GHCi now, so that it
157      -- can be overriden from the command-line
158      -- XXX: this should really be in the interactive DynFlags, but
159      -- we don't set that until later in interactiveUI
160      dflags1a | DoInteractive <- postLoadMode = imp_qual_enabled
161               | DoEval _      <- postLoadMode = imp_qual_enabled
162               | otherwise                 = dflags1
163        where imp_qual_enabled = dflags1 `dopt_set` Opt_ImplicitImportQualified
164
165        -- The rest of the arguments are "dynamic"
166        -- Leftover ones are presumably files
167  (dflags2, fileish_args, dynamicFlagWarnings) <- GHC.parseDynamicFlags dflags1a args
168
169  let flagWarnings' = flagWarnings ++ dynamicFlagWarnings
170
171  handleSourceError (\e -> do
172       GHC.printException e
173       liftIO $ exitWith (ExitFailure 1)) $ do
174         liftIO $ handleFlagWarnings dflags2 flagWarnings'
175
176        -- make sure we clean up after ourselves
177  GHC.defaultCleanupHandler dflags2 $ do
178
179  liftIO $ showBanner postLoadMode dflags2
180
181  -- we've finished manipulating the DynFlags, update the session
182  _ <- GHC.setSessionDynFlags dflags2
183  dflags3 <- GHC.getSessionDynFlags
184  hsc_env <- GHC.getSession
185
186  let
187     -- To simplify the handling of filepaths, we normalise all filepaths right
188     -- away - e.g., for win32 platforms, backslashes are converted
189     -- into forward slashes.
190    normal_fileish_paths = map (normalise . unLoc) fileish_args
191    (srcs, objs)         = partition_args normal_fileish_paths [] []
192
193  -- Note: have v_Ld_inputs maintain the order in which 'objs' occurred on
194  --       the command-line.
195  liftIO $ mapM_ (consIORef v_Ld_inputs) (reverse objs)
196
197        ---------------- Display configuration -----------
198  when (verbosity dflags3 >= 4) $
199        liftIO $ dumpPackages dflags3
200
201  when (verbosity dflags3 >= 3) $ do
202        liftIO $ hPutStrLn stderr ("Hsc static flags: " ++ unwords staticFlags)
203
204        ---------------- Final sanity checking -----------
205  liftIO $ checkOptions postLoadMode dflags3 srcs objs
206
207  ---------------- Do the business -----------
208  handleSourceError (\e -> do
209       GHC.printException e
210       liftIO $ exitWith (ExitFailure 1)) $ do
211    case postLoadMode of
212       ShowInterface f        -> liftIO $ doShowIface dflags3 f
213       DoMake                 -> doMake srcs
214       DoMkDependHS           -> doMkDependHS (map fst srcs)
215       StopBefore p           -> liftIO (oneShot hsc_env p srcs)
216       DoInteractive          -> interactiveUI srcs Nothing
217       DoEval exprs           -> interactiveUI srcs $ Just $ reverse exprs
218       DoAbiHash              -> abiHash srcs
219
220  liftIO $ dumpFinalStats dflags3
221
222#ifndef GHCI
223interactiveUI :: b -> c -> Ghc ()
224interactiveUI _ _ =
225  ghcError (CmdLineError "not built for interactive use")
226#endif
227
228-- -----------------------------------------------------------------------------
229-- Splitting arguments into source files and object files.  This is where we
230-- interpret the -x <suffix> option, and attach a (Maybe Phase) to each source
231-- file indicating the phase specified by the -x option in force, if any.
232
233partition_args :: [String] -> [(String, Maybe Phase)] -> [String]
234               -> ([(String, Maybe Phase)], [String])
235partition_args [] srcs objs = (reverse srcs, reverse objs)
236partition_args ("-x":suff:args) srcs objs
237  | "none" <- suff      = partition_args args srcs objs
238  | StopLn <- phase     = partition_args args srcs (slurp ++ objs)
239  | otherwise           = partition_args rest (these_srcs ++ srcs) objs
240        where phase = startPhase suff
241              (slurp,rest) = break (== "-x") args
242              these_srcs = zip slurp (repeat (Just phase))
243partition_args (arg:args) srcs objs
244  | looks_like_an_input arg = partition_args args ((arg,Nothing):srcs) objs
245  | otherwise               = partition_args args srcs (arg:objs)
246
247    {-
248      We split out the object files (.o, .dll) and add them
249      to v_Ld_inputs for use by the linker.
250
251      The following things should be considered compilation manager inputs:
252
253       - haskell source files (strings ending in .hs, .lhs or other
254         haskellish extension),
255
256       - module names (not forgetting hierarchical module names),
257
258       - things beginning with '-' are flags that were not recognised by
259         the flag parser, and we want them to generate errors later in
260         checkOptions, so we class them as source files (#5921)
261
262       - and finally we consider everything not containing a '.' to be
263         a comp manager input, as shorthand for a .hs or .lhs filename.
264
265      Everything else is considered to be a linker object, and passed
266      straight through to the linker.
267    -}
268looks_like_an_input :: String -> Bool
269looks_like_an_input m =  isSourceFilename m
270                      || looksLikeModuleName m
271                      || "-" `isPrefixOf` m
272                      || '.' `notElem` m
273
274-- -----------------------------------------------------------------------------
275-- Option sanity checks
276
277-- | Ensure sanity of options.
278--
279-- Throws 'UsageError' or 'CmdLineError' if not.
280checkOptions :: PostLoadMode -> DynFlags -> [(String,Maybe Phase)] -> [String] -> IO ()
281     -- Final sanity checking before kicking off a compilation (pipeline).
282checkOptions mode dflags srcs objs = do
283     -- Complain about any unknown flags
284   let unknown_opts = [ f | (f@('-':_), _) <- srcs ]
285   when (notNull unknown_opts) (unknownFlagsErr unknown_opts)
286
287   when (notNull (filter isRTSWay (wayNames dflags))
288         && isInterpretiveMode mode) $
289        hPutStrLn stderr ("Warning: -debug, -threaded and -ticky are ignored by GHCi")
290
291        -- -prof and --interactive are not a good combination
292   when (notNull (filter (not . isRTSWay) (wayNames dflags))
293         && isInterpretiveMode mode) $
294      do ghcError (UsageError
295                   "--interactive can't be used with -prof or -unreg.")
296        -- -ohi sanity check
297   if (isJust (outputHi dflags) &&
298      (isCompManagerMode mode || srcs `lengthExceeds` 1))
299        then ghcError (UsageError "-ohi can only be used when compiling a single source file")
300        else do
301
302        -- -o sanity checking
303   if (srcs `lengthExceeds` 1 && isJust (outputFile dflags)
304         && not (isLinkMode mode))
305        then ghcError (UsageError "can't apply -o to multiple source files")
306        else do
307
308   let not_linking = not (isLinkMode mode) || isNoLink (ghcLink dflags)
309
310   when (not_linking && not (null objs)) $
311        hPutStrLn stderr ("Warning: the following files would be used as linker inputs, but linking is not being done: " ++ unwords objs)
312
313        -- Check that there are some input files
314        -- (except in the interactive case)
315   if null srcs && (null objs || not_linking) && needsInputsMode mode
316        then ghcError (UsageError "no input files")
317        else do
318
319     -- Verify that output files point somewhere sensible.
320   verifyOutputFiles dflags
321
322
323-- Compiler output options
324
325-- called to verify that the output files & directories
326-- point somewhere valid.
327--
328-- The assumption is that the directory portion of these output
329-- options will have to exist by the time 'verifyOutputFiles'
330-- is invoked.
331--
332verifyOutputFiles :: DynFlags -> IO ()
333verifyOutputFiles dflags = do
334  -- not -odir: we create the directory for -odir if it doesn't exist (#2278).
335  let ofile = outputFile dflags
336  when (isJust ofile) $ do
337     let fn = fromJust ofile
338     flg <- doesDirNameExist fn
339     when (not flg) (nonExistentDir "-o" fn)
340  let ohi = outputHi dflags
341  when (isJust ohi) $ do
342     let hi = fromJust ohi
343     flg <- doesDirNameExist hi
344     when (not flg) (nonExistentDir "-ohi" hi)
345 where
346   nonExistentDir flg dir =
347     ghcError (CmdLineError ("error: directory portion of " ++
348                             show dir ++ " does not exist (used with " ++
349                             show flg ++ " option.)"))
350
351-----------------------------------------------------------------------------
352-- GHC modes of operation
353
354type Mode = Either PreStartupMode PostStartupMode
355type PostStartupMode = Either PreLoadMode PostLoadMode
356
357data PreStartupMode
358  = ShowVersion             -- ghc -V/--version
359  | ShowNumVersion          -- ghc --numeric-version
360  | ShowSupportedExtensions -- ghc --supported-extensions
361  | Print String            -- ghc --print-foo
362
363showVersionMode, showNumVersionMode, showSupportedExtensionsMode :: Mode
364showVersionMode             = mkPreStartupMode ShowVersion
365showNumVersionMode          = mkPreStartupMode ShowNumVersion
366showSupportedExtensionsMode = mkPreStartupMode ShowSupportedExtensions
367
368mkPreStartupMode :: PreStartupMode -> Mode
369mkPreStartupMode = Left
370
371isShowVersionMode :: Mode -> Bool
372isShowVersionMode (Left ShowVersion) = True
373isShowVersionMode _ = False
374
375isShowNumVersionMode :: Mode -> Bool
376isShowNumVersionMode (Left ShowNumVersion) = True
377isShowNumVersionMode _ = False
378
379data PreLoadMode
380  = ShowGhcUsage                           -- ghc -?
381  | ShowGhciUsage                          -- ghci -?
382  | ShowInfo                               -- ghc --info
383  | PrintWithDynFlags (DynFlags -> String) -- ghc --print-foo
384
385showGhcUsageMode, showGhciUsageMode, showInfoMode :: Mode
386showGhcUsageMode = mkPreLoadMode ShowGhcUsage
387showGhciUsageMode = mkPreLoadMode ShowGhciUsage
388showInfoMode = mkPreLoadMode ShowInfo
389
390printSetting :: String -> Mode
391printSetting k = mkPreLoadMode (PrintWithDynFlags f)
392    where f dflags = fromMaybe (panic ("Setting not found: " ++ show k))
393                   $ lookup k (compilerInfo dflags)
394
395mkPreLoadMode :: PreLoadMode -> Mode
396mkPreLoadMode = Right . Left
397
398isShowGhcUsageMode :: Mode -> Bool
399isShowGhcUsageMode (Right (Left ShowGhcUsage)) = True
400isShowGhcUsageMode _ = False
401
402isShowGhciUsageMode :: Mode -> Bool
403isShowGhciUsageMode (Right (Left ShowGhciUsage)) = True
404isShowGhciUsageMode _ = False
405
406data PostLoadMode
407  = ShowInterface FilePath  -- ghc --show-iface
408  | DoMkDependHS            -- ghc -M
409  | StopBefore Phase        -- ghc -E | -C | -S
410                            -- StopBefore StopLn is the default
411  | DoMake                  -- ghc --make
412  | DoInteractive           -- ghc --interactive
413  | DoEval [String]         -- ghc -e foo -e bar => DoEval ["bar", "foo"]
414  | DoAbiHash               -- ghc --abi-hash
415
416doMkDependHSMode, doMakeMode, doInteractiveMode, doAbiHashMode :: Mode
417doMkDependHSMode = mkPostLoadMode DoMkDependHS
418doMakeMode = mkPostLoadMode DoMake
419doInteractiveMode = mkPostLoadMode DoInteractive
420doAbiHashMode = mkPostLoadMode DoAbiHash
421
422showInterfaceMode :: FilePath -> Mode
423showInterfaceMode fp = mkPostLoadMode (ShowInterface fp)
424
425stopBeforeMode :: Phase -> Mode
426stopBeforeMode phase = mkPostLoadMode (StopBefore phase)
427
428doEvalMode :: String -> Mode
429doEvalMode str = mkPostLoadMode (DoEval [str])
430
431mkPostLoadMode :: PostLoadMode -> Mode
432mkPostLoadMode = Right . Right
433
434isDoInteractiveMode :: Mode -> Bool
435isDoInteractiveMode (Right (Right DoInteractive)) = True
436isDoInteractiveMode _ = False
437
438isStopLnMode :: Mode -> Bool
439isStopLnMode (Right (Right (StopBefore StopLn))) = True
440isStopLnMode _ = False
441
442isDoMakeMode :: Mode -> Bool
443isDoMakeMode (Right (Right DoMake)) = True
444isDoMakeMode _ = False
445
446#ifdef GHCI
447isInteractiveMode :: PostLoadMode -> Bool
448isInteractiveMode DoInteractive = True
449isInteractiveMode _             = False
450#endif
451
452-- isInterpretiveMode: byte-code compiler involved
453isInterpretiveMode :: PostLoadMode -> Bool
454isInterpretiveMode DoInteractive = True
455isInterpretiveMode (DoEval _)    = True
456isInterpretiveMode _             = False
457
458needsInputsMode :: PostLoadMode -> Bool
459needsInputsMode DoMkDependHS    = True
460needsInputsMode (StopBefore _)  = True
461needsInputsMode DoMake          = True
462needsInputsMode _               = False
463
464-- True if we are going to attempt to link in this mode.
465-- (we might not actually link, depending on the GhcLink flag)
466isLinkMode :: PostLoadMode -> Bool
467isLinkMode (StopBefore StopLn) = True
468isLinkMode DoMake              = True
469isLinkMode DoInteractive       = True
470isLinkMode (DoEval _)          = True
471isLinkMode _                   = False
472
473isCompManagerMode :: PostLoadMode -> Bool
474isCompManagerMode DoMake        = True
475isCompManagerMode DoInteractive = True
476isCompManagerMode (DoEval _)    = True
477isCompManagerMode _             = False
478
479-- -----------------------------------------------------------------------------
480-- Parsing the mode flag
481
482parseModeFlags :: [Located String]
483               -> IO (Mode,
484                      [Located String],
485                      [Located String])
486parseModeFlags args = do
487  let ((leftover, errs1, warns), (mModeFlag, errs2, flags')) =
488          runCmdLine (processArgs mode_flags args)
489                     (Nothing, [], [])
490      mode = case mModeFlag of
491             Nothing     -> doMakeMode
492             Just (m, _) -> m
493      errs = errs1 ++ map (mkGeneralLocated "on the commandline") errs2
494  when (not (null errs)) $ ghcError $ errorsToGhcException errs
495  return (mode, flags' ++ leftover, warns)
496
497type ModeM = CmdLineP (Maybe (Mode, String), [String], [Located String])
498  -- mode flags sometimes give rise to new DynFlags (eg. -C, see below)
499  -- so we collect the new ones and return them.
500
501mode_flags :: [Flag ModeM]
502mode_flags =
503  [  ------- help / version ----------------------------------------------
504    Flag "?"                     (PassFlag (setMode showGhcUsageMode))
505  , Flag "-help"                 (PassFlag (setMode showGhcUsageMode))
506  , Flag "V"                     (PassFlag (setMode showVersionMode))
507  , Flag "-version"              (PassFlag (setMode showVersionMode))
508  , Flag "-numeric-version"      (PassFlag (setMode showNumVersionMode))
509  , Flag "-info"                 (PassFlag (setMode showInfoMode))
510  , Flag "-supported-languages"  (PassFlag (setMode showSupportedExtensionsMode))
511  , Flag "-supported-extensions" (PassFlag (setMode showSupportedExtensionsMode))
512  ] ++
513  [ Flag k'                      (PassFlag (setMode (printSetting k)))
514  | k <- ["Project version",
515          "Booter version",
516          "Stage",
517          "Build platform",
518          "Host platform",
519          "Target platform",
520          "Have interpreter",
521          "Object splitting supported",
522          "Have native code generator",
523          "Support SMP",
524          "Unregisterised",
525          "Tables next to code",
526          "RTS ways",
527          "Leading underscore",
528          "Debug on",
529          "LibDir",
530          "Global Package DB",
531          "C compiler flags",
532          "Gcc Linker flags",
533          "Ld Linker flags"],
534    let k' = "-print-" ++ map (replaceSpace . toLower) k
535        replaceSpace ' ' = '-'
536        replaceSpace c   = c
537  ] ++
538      ------- interfaces ----------------------------------------------------
539  [ Flag "-show-iface"  (HasArg (\f -> setMode (showInterfaceMode f)
540                                               "--show-iface"))
541
542      ------- primary modes ------------------------------------------------
543  , Flag "c"            (PassFlag (\f -> do setMode (stopBeforeMode StopLn) f
544                                            addFlag "-no-link" f))
545  , Flag "M"            (PassFlag (setMode doMkDependHSMode))
546  , Flag "E"            (PassFlag (setMode (stopBeforeMode anyHsc)))
547  , Flag "C"            (PassFlag setGenerateC)
548  , Flag "S"            (PassFlag (setMode (stopBeforeMode As)))
549  , Flag "-make"        (PassFlag (setMode doMakeMode))
550  , Flag "-interactive" (PassFlag (setMode doInteractiveMode))
551  , Flag "-abi-hash"    (PassFlag (setMode doAbiHashMode))
552  , Flag "e"            (SepArg   (\s -> setMode (doEvalMode s) "-e"))
553  ]
554
555setGenerateC :: String -> EwM ModeM ()
556setGenerateC f
557  | cGhcUnregisterised /= "YES" = do
558        addWarn ("Compiler not unregisterised, so ignoring " ++ f)
559  | otherwise = do
560        setMode (stopBeforeMode HCc) f
561        addFlag "-fvia-C" f
562
563setMode :: Mode -> String -> EwM ModeM ()
564setMode newMode newFlag = liftEwM $ do
565    (mModeFlag, errs, flags') <- getCmdLineState
566    let (modeFlag', errs') =
567            case mModeFlag of
568            Nothing -> ((newMode, newFlag), errs)
569            Just (oldMode, oldFlag) ->
570                case (oldMode, newMode) of
571                    -- -c/--make are allowed together, and mean --make -no-link
572                    _ |  isStopLnMode oldMode && isDoMakeMode newMode
573                      || isStopLnMode newMode && isDoMakeMode oldMode ->
574                      ((doMakeMode, "--make"), [])
575
576                    -- If we have both --help and --interactive then we
577                    -- want showGhciUsage
578                    _ | isShowGhcUsageMode oldMode &&
579                        isDoInteractiveMode newMode ->
580                            ((showGhciUsageMode, oldFlag), [])
581                      | isShowGhcUsageMode newMode &&
582                        isDoInteractiveMode oldMode ->
583                            ((showGhciUsageMode, newFlag), [])
584                    -- Otherwise, --help/--version/--numeric-version always win
585                      | isDominantFlag oldMode -> ((oldMode, oldFlag), [])
586                      | isDominantFlag newMode -> ((newMode, newFlag), [])
587                    -- We need to accumulate eval flags like "-e foo -e bar"
588                    (Right (Right (DoEval esOld)),
589                     Right (Right (DoEval [eNew]))) ->
590                        ((Right (Right (DoEval (eNew : esOld))), oldFlag),
591                         errs)
592                    -- Saying e.g. --interactive --interactive is OK
593                    _ | oldFlag == newFlag -> ((oldMode, oldFlag), errs)
594                    -- Otherwise, complain
595                    _ -> let err = flagMismatchErr oldFlag newFlag
596                         in ((oldMode, oldFlag), err : errs)
597    putCmdLineState (Just modeFlag', errs', flags')
598  where isDominantFlag f = isShowGhcUsageMode   f ||
599                           isShowGhciUsageMode  f ||
600                           isShowVersionMode    f ||
601                           isShowNumVersionMode f
602
603flagMismatchErr :: String -> String -> String
604flagMismatchErr oldFlag newFlag
605    = "cannot use `" ++ oldFlag ++  "' with `" ++ newFlag ++ "'"
606
607addFlag :: String -> String -> EwM ModeM ()
608addFlag s flag = liftEwM $ do
609  (m, e, flags') <- getCmdLineState
610  putCmdLineState (m, e, mkGeneralLocated loc s : flags')
611    where loc = "addFlag by " ++ flag ++ " on the commandline"
612
613-- ----------------------------------------------------------------------------
614-- Run --make mode
615
616doMake :: [(String,Maybe Phase)] -> Ghc ()
617doMake srcs  = do
618    let (hs_srcs, non_hs_srcs) = partition haskellish srcs
619
620        haskellish (f,Nothing) =
621          looksLikeModuleName f || isHaskellSrcFilename f || '.' `notElem` f
622        haskellish (_,Just phase) =
623          phase `notElem` [As, Cc, Cobjc, Cobjcpp, CmmCpp, Cmm, StopLn]
624
625    hsc_env <- GHC.getSession
626
627    -- if we have no haskell sources from which to do a dependency
628    -- analysis, then just do one-shot compilation and/or linking.
629    -- This means that "ghc Foo.o Bar.o -o baz" links the program as
630    -- we expect.
631    if (null hs_srcs)
632       then liftIO (oneShot hsc_env StopLn srcs)
633       else do
634
635    o_files <- mapM (\x -> liftIO $ compileFile hsc_env StopLn x)
636                 non_hs_srcs
637    liftIO $ mapM_ (consIORef v_Ld_inputs) (reverse o_files)
638
639    targets <- mapM (uncurry GHC.guessTarget) hs_srcs
640    GHC.setTargets targets
641    ok_flag <- GHC.load LoadAllTargets
642
643    when (failed ok_flag) (liftIO $ exitWith (ExitFailure 1))
644    return ()
645
646
647-- ---------------------------------------------------------------------------
648-- --show-iface mode
649
650doShowIface :: DynFlags -> FilePath -> IO ()
651doShowIface dflags file = do
652  hsc_env <- newHscEnv dflags
653  showIface hsc_env file
654
655-- ---------------------------------------------------------------------------
656-- Various banners and verbosity output.
657
658showBanner :: PostLoadMode -> DynFlags -> IO ()
659showBanner _postLoadMode dflags = do
660   let verb = verbosity dflags
661
662#ifdef GHCI
663   -- Show the GHCi banner
664   when (isInteractiveMode _postLoadMode && verb >= 1) $ putStrLn ghciWelcomeMsg
665#endif
666
667   -- Display details of the configuration in verbose mode
668   when (verb >= 2) $
669    do hPutStr stderr "Glasgow Haskell Compiler, Version "
670       hPutStr stderr cProjectVersion
671       hPutStr stderr ", stage "
672       hPutStr stderr cStage
673       hPutStr stderr " booted by GHC version "
674       hPutStrLn stderr cBooterVersion
675
676-- We print out a Read-friendly string, but a prettier one than the
677-- Show instance gives us
678showInfo :: DynFlags -> IO ()
679showInfo dflags = do
680        let sq x = " [" ++ x ++ "\n ]"
681        putStrLn $ sq $ intercalate "\n ," $ map show $ compilerInfo dflags
682
683showSupportedExtensions :: IO ()
684showSupportedExtensions = mapM_ putStrLn supportedLanguagesAndExtensions
685
686showVersion :: IO ()
687showVersion = putStrLn (cProjectName ++ ", version " ++ cProjectVersion)
688
689showGhcUsage :: DynFlags -> IO ()
690showGhcUsage = showUsage False
691
692showGhciUsage :: DynFlags -> IO ()
693showGhciUsage = showUsage True
694
695showUsage :: Bool -> DynFlags -> IO ()
696showUsage ghci dflags = do
697  let usage_path = if ghci then ghciUsagePath dflags
698                           else ghcUsagePath dflags
699  usage <- readFile usage_path
700  dump usage
701  where
702     dump ""          = return ()
703     dump ('$':'$':s) = putStr progName >> dump s
704     dump (c:s)       = putChar c >> dump s
705
706dumpFinalStats :: DynFlags -> IO ()
707dumpFinalStats dflags =
708  when (dopt Opt_D_faststring_stats dflags) $ dumpFastStringStats dflags
709
710dumpFastStringStats :: DynFlags -> IO ()
711dumpFastStringStats dflags = do
712  buckets <- getFastStringTable
713  let (entries, longest, is_z, has_z) = countFS 0 0 0 0 buckets
714      msg = text "FastString stats:" $$
715            nest 4 (vcat [text "size:           " <+> int (length buckets),
716                          text "entries:        " <+> int entries,
717                          text "longest chain:  " <+> int longest,
718                          text "z-encoded:      " <+> (is_z `pcntOf` entries),
719                          text "has z-encoding: " <+> (has_z `pcntOf` entries)
720                         ])
721        -- we usually get more "has z-encoding" than "z-encoded", because
722        -- when we z-encode a string it might hash to the exact same string,
723        -- which will is not counted as "z-encoded".  Only strings whose
724        -- Z-encoding is different from the original string are counted in
725        -- the "z-encoded" total.
726  putMsg dflags msg
727  where
728   x `pcntOf` y = int ((x * 100) `quot` y) <> char '%'
729
730countFS :: Int -> Int -> Int -> Int -> [[FastString]] -> (Int, Int, Int, Int)
731countFS entries longest is_z has_z [] = (entries, longest, is_z, has_z)
732countFS entries longest is_z has_z (b:bs) =
733  let
734        len = length b
735        longest' = max len longest
736        entries' = entries + len
737        is_zs = length (filter isZEncoded b)
738        has_zs = length (filter hasZEncoding b)
739  in
740        countFS entries' longest' (is_z + is_zs) (has_z + has_zs) bs
741
742-- -----------------------------------------------------------------------------
743-- ABI hash support
744
745{-
746        ghc --abi-hash Data.Foo System.Bar
747
748Generates a combined hash of the ABI for modules Data.Foo and
749System.Bar.  The modules must already be compiled, and appropriate -i
750options may be necessary in order to find the .hi files.
751
752This is used by Cabal for generating the InstalledPackageId for a
753package.  The InstalledPackageId must change when the visible ABI of
754the package chagnes, so during registration Cabal calls ghc --abi-hash
755to get a hash of the package's ABI.
756-}
757
758abiHash :: [(String, Maybe Phase)] -> Ghc ()
759abiHash strs = do
760  hsc_env <- getSession
761  let dflags = hsc_dflags hsc_env
762
763  liftIO $ do
764
765  let find_it str = do
766         let modname = mkModuleName str
767         r <- findImportedModule hsc_env modname Nothing
768         case r of
769           Found _ m -> return m
770           _error    -> ghcError $ CmdLineError $ showSDoc $
771                          cannotFindInterface dflags modname r
772
773  mods <- mapM find_it (map fst strs)
774
775  let get_iface modl = loadUserInterface False (text "abiHash") modl
776  ifaces <- initIfaceCheck hsc_env $ mapM get_iface mods
777
778  bh <- openBinMem (3*1024) -- just less than a block
779  put_ bh opt_HiVersion
780    -- package hashes change when the compiler version changes (for now)
781    -- see #5328
782  mapM_ (put_ bh . mi_mod_hash) ifaces
783  f <- fingerprintBinMem bh
784
785  putStrLn (showSDoc (ppr f))
786
787-- -----------------------------------------------------------------------------
788-- Util
789
790unknownFlagsErr :: [String] -> a
791unknownFlagsErr fs = ghcError (UsageError ("unrecognised flags: " ++ unwords fs))
Note: See TracBrowser for help on using the browser.