+
+-- ---------------------------------------------------------------------------
+-- Pre-process
+
+-- Just preprocess a file, put the result in a temp. file (used by the
+-- compilation manager during the summary phase).
+--
+-- We return the augmented DynFlags, because they contain the result
+-- of slurping in the OPTIONS pragmas
+
+preprocess :: DynFlags -> (FilePath, Maybe Phase) -> IO (DynFlags, FilePath)
+preprocess dflags (filename, mb_phase) =
+ ASSERT2(isJust mb_phase || isHaskellSrcFilename filename, text filename)
+ runPipeline anyHsc dflags (filename, mb_phase) Temporary Nothing{-no ModLocation-}
+
+-- ---------------------------------------------------------------------------
+-- Compile
+
+-- Compile a single module, under the control of the compilation manager.
+--
+-- This is the interface between the compilation manager and the
+-- compiler proper (hsc), where we deal with tedious details like
+-- reading the OPTIONS pragma from the source file, and passing the
+-- output of hsc through the C compiler.
+
+-- NB. No old interface can also mean that the source has changed.
+
+compile :: HscEnv
+ -> ModSummary
+ -> Maybe Linkable -- Just linkable <=> source unchanged
+ -> Maybe ModIface -- Old interface, if available
+ -> Int -> Int
+ -> IO CompResult
+
+data CompResult
+ = CompOK ModDetails -- New details
+ ModIface -- New iface
+ (Maybe Linkable) -- a Maybe, for the same reasons as hm_linkable
+
+ | CompErrs
+
+
+compile hsc_env mod_summary maybe_old_linkable old_iface mod_index nmods = do
+
+ let dflags0 = hsc_dflags hsc_env
+ this_mod = ms_mod mod_summary
+ src_flavour = ms_hsc_src mod_summary
+
+ have_object
+ | Just l <- maybe_old_linkable, isObjectLinkable l = True
+ | otherwise = False
+
+ showPass dflags0 ("Compiling " ++ showModMsg have_object mod_summary)
+
+ let location = ms_location mod_summary
+ let input_fn = expectJust "compile:hs" (ml_hs_file location)
+ let input_fnpp = expectJust "compile:hspp" (ms_hspp_file mod_summary)
+
+ debugTraceMsg dflags0 2 (text "compile: input file" <+> text input_fnpp)
+
+ -- Add in the OPTIONS from the source file
+ -- This is nasty: we've done this once already, in the compilation manager
+ -- It might be better to cache the flags in the ml_hspp_file field,say
+ let hspp_buf = expectJust "compile:hspp_buf" (ms_hspp_buf mod_summary)
+ opts = getOptionsFromStringBuffer hspp_buf input_fn
+ (dflags1,unhandled_flags) <- parseDynamicFlags dflags0 (map snd opts)
+ if (not (null unhandled_flags))
+ then do printErrorsAndWarnings dflags1 (optionsErrorMsgs unhandled_flags opts input_fn)
+ return CompErrs
+ else do
+
+ let (basename, _) = splitFilename input_fn
+
+ -- We add the directory in which the .hs files resides) to the import path.
+ -- This is needed when we try to compile the .hc file later, if it
+ -- imports a _stub.h file that we created here.
+ let current_dir = directoryOf basename
+ old_paths = includePaths dflags1
+ dflags = dflags1 { includePaths = current_dir : old_paths }
+
+ -- Figure out what lang we're generating
+ let hsc_lang = hscMaybeAdjustTarget dflags StopLn src_flavour (hscTarget dflags)
+ -- ... and what the next phase should be
+ let next_phase = hscNextPhase dflags src_flavour hsc_lang
+ -- ... and what file to generate the output into
+ output_fn <- getOutputFilename dflags next_phase
+ Temporary basename next_phase (Just location)
+
+ let dflags' = dflags { hscTarget = hsc_lang,
+ hscOutName = output_fn,
+ extCoreName = basename ++ ".hcr" }
+
+ -- -no-recomp should also work with --make
+ let do_recomp = dopt Opt_RecompChecking dflags
+ source_unchanged = isJust maybe_old_linkable && do_recomp
+ hsc_env' = hsc_env { hsc_dflags = dflags' }
+ object_filename = ml_obj_file location
+
+ let getStubLinkable False = return []
+ getStubLinkable True
+ = do stub_o <- compileStub dflags' this_mod location
+ return [ DotO stub_o ]
+
+ handleMake (HscNoRecomp, iface, details)
+ = ASSERT (isJust maybe_old_linkable)
+ return (CompOK details iface maybe_old_linkable)
+ handleMake (HscRecomp hasStub, iface, details)
+ | isHsBoot src_flavour
+ = return (CompOK details iface Nothing)
+ | otherwise
+ = do stub_unlinked <- getStubLinkable hasStub
+ (hs_unlinked, unlinked_time) <-
+ case hsc_lang of
+ HscNothing
+ -> return ([], ms_hs_date mod_summary)
+ -- We're in --make mode: finish the compilation pipeline.
+ _other
+ -> do runPipeline StopLn dflags (output_fn,Nothing) Persistent
+ (Just location)
+ -- The object filename comes from the ModLocation
+ o_time <- getModificationTime object_filename
+ return ([DotO object_filename], o_time)
+ let linkable = LM unlinked_time this_mod
+ (hs_unlinked ++ stub_unlinked)
+ return (CompOK details iface (Just linkable))
+
+ handleInterpreted (InteractiveNoRecomp, iface, details)
+ = ASSERT (isJust maybe_old_linkable)
+ return (CompOK details iface maybe_old_linkable)
+ handleInterpreted (InteractiveRecomp hasStub comp_bc, iface, details)
+ = do stub_unlinked <- getStubLinkable hasStub
+ let hs_unlinked = [BCOs comp_bc]
+ unlinked_time = ms_hs_date mod_summary
+ -- Why do we use the timestamp of the source file here,
+ -- rather than the current time? This works better in
+ -- the case where the local clock is out of sync
+ -- with the filesystem's clock. It's just as accurate:
+ -- if the source is modified, then the linkable will
+ -- be out of date.
+ let linkable = LM unlinked_time this_mod
+ (hs_unlinked ++ stub_unlinked)
+ return (CompOK details iface (Just linkable))
+
+ let runCompiler compiler handle
+ = do mbResult <- compiler hsc_env' mod_summary
+ source_unchanged old_iface
+ (Just (mod_index, nmods))
+ case mbResult of
+ Nothing -> return CompErrs
+ Just result -> handle result
+ -- run the compiler
+ case hsc_lang of
+ HscInterpreted | not (isHsBoot src_flavour) -- We can't compile boot files to
+ -- bytecode so don't even try.
+ -> runCompiler hscCompileInteractive handleInterpreted
+ _other
+ -> runCompiler hscCompileMake handleMake