-> Maybe ModLocation -- A ModLocation, if this is a Haskell module
-> IO (DynFlags, FilePath) -- (final flags, output filename)
-runPipeline stop_phase dflags (input_fn, mb_phase) mb_basename output maybe_loc
+runPipeline stop_phase dflags0 (input_fn, mb_phase) mb_basename output maybe_loc
= do
- let (input_basename, suffix) = splitFilename input_fn
+ let
+ (input_basename, suffix) = splitFilename input_fn
basename | Just b <- mb_basename = b
| otherwise = input_basename
+ -- Decide where dump files should go based on the pipeline output
+ dflags = dflags0 { dumpPrefix = Just (basename ++ ".") }
+
-- If we were given a -x flag, then use that phase to start from
start_phase = fromMaybe (startPhase suffix) mb_phase
#include "HsVersions.h"
-import Module ( Module, mkModuleName, mkModule )
+import Module ( Module, mkModuleName, mkModule, ModLocation )
import PackageConfig
import PrelNames ( mAIN )
#ifdef i386_TARGET_ARCH
| Opt_D_dump_minimal_imports
| Opt_D_dump_mod_cycles
| Opt_D_faststring_stats
+ | Opt_DumpToFile -- Redirect dump output to files instead of stdout.
| Opt_DoCoreLinting
| Opt_DoStgLinting
| Opt_DoCmmLinting
- | Opt_WarnIsError -- -Werror; makes warnings fatal
+ | Opt_WarnIsError -- -Werror; makes warnings fatal
| Opt_WarnDuplicateExports
| Opt_WarnHiShadows
| Opt_WarnImplicitPrelude
| Opt_KeepRawSFiles
| Opt_KeepTmpFiles
- deriving (Eq)
+ deriving (Eq, Show)
data DynFlags = DynFlags {
ghcMode :: GhcMode,
outputFile :: Maybe String,
outputHi :: Maybe String,
+ -- | This is set by DriverPipeline.runPipeline based on where
+ -- its output is going.
+ dumpPrefix :: Maybe FilePath,
+
+ -- | Override the dumpPrefix set by runPipeline.
+ -- Set by -ddump-file-prefix
+ dumpPrefixForce :: Maybe FilePath,
+
includePaths :: [String],
libraryPaths :: [String],
frameworkPaths :: [String], -- used on darwin only
outputFile = Nothing,
outputHi = Nothing,
+ dumpPrefix = Nothing,
+ dumpPrefixForce = Nothing,
includePaths = [],
libraryPaths = [],
frameworkPaths = [],
setOutputFile f d = d{ outputFile = f}
setOutputHi f d = d{ outputHi = f}
+setDumpPrefixForce f d = d { dumpPrefixForce = f}
+
-- XXX HACK: Prelude> words "'does not' work" ===> ["'does","not'","work"]
-- Config.hs should really use Option.
setPgmP f d = let (pgm:args) = words f in d{ pgm_P = (pgm, map Option args)}
, ( "hidir" , HasArg (upd . setHiDir . Just))
, ( "tmpdir" , HasArg (upd . setTmpDir))
, ( "stubdir" , HasArg (upd . setStubDir . Just))
+ , ( "ddump-file-prefix", HasArg (upd . setDumpPrefixForce . Just))
------- Keeping temporary files -------------------------------------
-- These can be singular (think ghc -c) or plural (think ghc --make)
, ( "ddump-vect", setDumpFlag Opt_D_dump_vect)
, ( "ddump-hpc", setDumpFlag Opt_D_dump_hpc)
, ( "ddump-mod-cycles", setDumpFlag Opt_D_dump_mod_cycles)
-
+ , ( "ddump-to-file", setDumpFlag Opt_DumpToFile)
, ( "ddump-hi-diffs", NoArg (setDynFlag Opt_D_dump_hi_diffs))
, ( "dcore-lint", NoArg (setDynFlag Opt_DoCoreLinting))
, ( "dstg-lint", NoArg (setDynFlag Opt_DoStgLinting))
#include "HsVersions.h"
+import Module ( ModLocation(..))
import Bag ( Bag, bagToList, isEmptyBag, emptyBag )
import SrcLoc ( SrcSpan )
import Util ( sortLe )
import System.Exit ( ExitCode(..), exitWith )
import Data.Dynamic
-
+import Data.List
+import System.IO
-- -----------------------------------------------------------------------------
-- Basic error messages: just render a message with a source location.
LT -> True
EQ -> True
GT -> False
-\end{code}
-\begin{code}
+
+
ghcExit :: DynFlags -> Int -> IO ()
ghcExit dflags val
| val == 0 = exitWith ExitSuccess
| otherwise = do errorMsg dflags (text "\nCompilation had errors\n\n")
exitWith (ExitFailure val)
-\end{code}
-\begin{code}
doIfSet :: Bool -> IO () -> IO ()
doIfSet flag action | flag = action
| otherwise = return ()
doIfSet_dyn :: DynFlags -> DynFlag -> IO () -> IO()
doIfSet_dyn dflags flag action | dopt flag dflags = action
| otherwise = return ()
-\end{code}
-\begin{code}
+-- -----------------------------------------------------------------------------
+-- Dumping
+
dumpIfSet :: Bool -> String -> SDoc -> IO ()
dumpIfSet flag hdr doc
| not flag = return ()
dumpIfSet_core dflags flag hdr doc
| dopt flag dflags
|| verbosity dflags >= 4
- || dopt Opt_D_verbose_core2core dflags = printDump (mkDumpDoc hdr doc)
+ || dopt Opt_D_verbose_core2core dflags
+ = writeDump dflags flag (mkDumpDoc hdr doc)
| otherwise = return ()
dumpIfSet_dyn :: DynFlags -> DynFlag -> String -> SDoc -> IO ()
dumpIfSet_dyn dflags flag hdr doc
| dopt flag dflags || verbosity dflags >= 4
- = printDump (mkDumpDoc hdr doc)
+ = writeDump dflags flag (mkDumpDoc hdr doc)
| otherwise
= return ()
where
line = text (replicate 20 '=')
+
+-- | Write out a dump.
+-- If --dump-to-file is set then this goes to a file.
+-- otherwise emit to stdout.
+writeDump :: DynFlags -> DynFlag -> SDoc -> IO ()
+writeDump dflags dflag doc
+ = do let mFile = chooseDumpFile dflags dflag
+ case mFile of
+ -- write the dump to a file
+ Just fileName
+ -> do handle <- openFile fileName AppendMode
+ hPrintDump handle doc
+ hClose handle
+
+ -- write the dump to stdout
+ Nothing
+ -> do printDump doc
+
+
+-- | Choose where to put a dump file based on DynFlags
+--
+chooseDumpFile :: DynFlags -> DynFlag -> Maybe String
+chooseDumpFile dflags dflag
+
+ -- dump file location is being forced
+ -- by the --ddump-file-prefix flag.
+ | dumpToFile
+ , Just prefix <- dumpPrefixForce dflags
+ = Just $ prefix ++ (beautifyDumpName dflag)
+
+ -- dump file location chosen by DriverPipeline.runPipeline
+ | dumpToFile
+ , Just prefix <- dumpPrefix dflags
+ = Just $ prefix ++ (beautifyDumpName dflag)
+
+ -- we haven't got a place to put a dump file.
+ | otherwise
+ = Nothing
+
+ where dumpToFile = dopt Opt_DumpToFile dflags
+
+
+-- | Build a nice file name from name of a DynFlag constructor
+beautifyDumpName :: DynFlag -> String
+beautifyDumpName dflag
+ = let str = show dflag
+ cut = if isPrefixOf "Opt_D_" str
+ then drop 6 str
+ else str
+ dash = map (\c -> case c of
+ '_' -> '-'
+ _ -> c)
+ cut
+ in dash
+
+
-- -----------------------------------------------------------------------------
-- Outputting messages from the compiler
debugTraceMsg :: DynFlags -> Int -> Message -> IO ()
debugTraceMsg dflags val msg
= ifVerbose dflags val (log_action dflags SevInfo noSrcSpan defaultDumpStyle msg)
+
\end{code}
hang, punctuate,
speakNth, speakNTimes, speakN, speakNOf, plural,
- printSDoc, printErrs, printDump,
+ printSDoc, printErrs, hPrintDump, printDump,
printForC, printForAsm, printForUser,
pprCode, mkCodeStyle,
showSDoc, showSDocForUser, showSDocDebug, showSDocDump,
hFlush stderr
printDump :: SDoc -> IO ()
-printDump doc = do
- Pretty.printDoc PageMode stdout (better_doc defaultDumpStyle)
- hFlush stdout
+printDump doc = hPrintDump stdout doc
+
+hPrintDump :: Handle -> SDoc -> IO ()
+hPrintDump h doc = do
+ Pretty.printDoc PageMode h (better_doc defaultDumpStyle)
+ hFlush h
where
better_doc = doc $$ text ""