+ when (verb >= 2) (hPutStrLn stderr ("compile: input file " ++ 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
+ opts <- getOptionsFromSource input_fnpp
+ (dyn_flags,unhandled_flags) <- processDynamicFlags opts dyn_flags
+ checkProcessArgsResult unhandled_flags input_fn
+
+ 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 <- readIORef v_Include_paths
+ writeIORef v_Include_paths (current_dir : old_paths)
+ -- put back the old include paths afterward.
+ later (writeIORef v_Include_paths old_paths) $ do
+
+ -- Figure out what lang we're generating
+ todo <- readIORef v_GhcMode
+ hsc_lang <- hscMaybeAdjustTarget todo src_flavour (hscTarget dyn_flags)
+ -- ... and what the next phase should be
+ next_phase <- hscNextPhase src_flavour hsc_lang
+ -- ... and what file to generate the output into
+ get_output_fn <- genOutputFilenameFunc next_phase False Nothing basename
+ output_fn <- get_output_fn next_phase (Just location)
+
+ let dyn_flags' = dyn_flags { hscTarget = hsc_lang,
+ hscOutName = output_fn,
+ hscStubCOutName = basename ++ "_stub.c",
+ hscStubHOutName = basename ++ "_stub.h",
+ extCoreName = basename ++ ".hcr" }
+
+ -- -no-recomp should also work with --make
+ let do_recomp = recompFlag dyn_flags
+ source_unchanged' = source_unchanged && do_recomp
+ hsc_env' = hsc_env { hsc_dflags = dyn_flags' }
+
+ -- run the compiler
+ hsc_result <- hscMain hsc_env' printErrorsAndWarnings mod_summary
+ source_unchanged' have_object old_iface
+
+ case hsc_result of
+ HscFail -> return CompErrs
+
+ HscNoRecomp details iface -> return (CompOK details Nothing iface Nothing)
+
+ HscRecomp details rdr_env iface
+ stub_h_exists stub_c_exists maybe_interpreted_code
+
+ | isHsBoot src_flavour -- No further compilation to do
+ -> return (CompOK details rdr_env iface Nothing)
+
+ | otherwise -- Normal Haskell source files
+ -> do
+ let
+ maybe_stub_o <- compileStub dyn_flags' stub_c_exists
+ let stub_unlinked = case maybe_stub_o of
+ Nothing -> []
+ Just stub_o -> [ DotO stub_o ]
+
+ (hs_unlinked, unlinked_time) <-
+ case hsc_lang of
+
+ -- in interpreted mode, just return the compiled code
+ -- as our "unlinked" object.
+ HscInterpreted ->
+ case maybe_interpreted_code of
+#ifdef GHCI
+ Just comp_bc -> return ([BCOs comp_bc], 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.
+#endif
+ Nothing -> panic "compile: no interpreted code"
+
+ -- we're in batch mode: finish the compilation pipeline.
+ _other -> do
+ let object_filename = ml_obj_file location
+
+ runPipeline DoLink dyn_flags ""
+ True Nothing output_fn (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 rdr_env iface (Just linkable))
+
+-----------------------------------------------------------------------------
+-- stub .h and .c files (for foreign export support)
+
+compileStub dflags stub_c_exists
+ | not stub_c_exists = return Nothing
+ | stub_c_exists = do
+ -- compile the _stub.c file w/ gcc
+ let stub_c = hscStubCOutName dflags
+ (_, stub_o) <- runPipeline DoLink dflags "stub-compile"
+ True{-persistent output-}
+ Nothing{-no specific output file-}
+ stub_c
+ Nothing{-no ModLocation-}
+ return (Just stub_o)
+
+
+-- ---------------------------------------------------------------------------
+-- Link
+
+link :: GhciMode -- interactive or batch
+ -> DynFlags -- dynamic flags
+ -> Bool -- attempt linking in batch mode?
+ -> HomePackageTable -- what to link
+ -> IO SuccessFlag
+
+-- For the moment, in the batch linker, we don't bother to tell doLink
+-- which packages to link -- it just tries all that are available.
+-- batch_attempt_linking should only be *looked at* in batch mode. It
+-- should only be True if the upsweep was successful and someone
+-- exports main, i.e., we have good reason to believe that linking
+-- will succeed.
+
+#ifdef GHCI
+link Interactive dflags batch_attempt_linking hpt
+ = do -- Not Linking...(demand linker will do the job)
+ return Succeeded
+#endif
+
+link Batch dflags batch_attempt_linking hpt
+ | batch_attempt_linking
+ = do
+ let
+ home_mod_infos = moduleEnvElts hpt
+
+ -- the packages we depend on
+ pkg_deps = concatMap (dep_pkgs . mi_deps . hm_iface) home_mod_infos
+
+ -- the linkables to link
+ linkables = map hm_linkable home_mod_infos
+
+ when (verb >= 3) $ do
+ hPutStrLn stderr "link: linkables are ..."
+ hPutStrLn stderr (showSDoc (vcat (map ppr linkables)))
+
+ -- check for the -no-link flag
+ omit_linking <- readIORef v_NoLink
+ if omit_linking
+ then do when (verb >= 3) $
+ hPutStrLn stderr "link(batch): linking omitted (-c flag given)."
+ return Succeeded
+ else do
+
+ when (verb >= 1) $
+ hPutStrLn stderr "Linking ..."
+
+ let getOfiles (LM _ _ us) = map nameOfObject (filter isObject us)
+ obj_files = concatMap getOfiles linkables
+
+ -- Don't showPass in Batch mode; doLink will do that for us.
+ staticLink dflags obj_files pkg_deps
+
+ when (verb >= 3) (hPutStrLn stderr "link: done")
+
+ -- staticLink only returns if it succeeds
+ return Succeeded
+
+ | otherwise
+ = do when (verb >= 3) $ do
+ hPutStrLn stderr "link(batch): upsweep (partially) failed OR"
+ hPutStrLn stderr " Main.main not exported; not linking."
+ return Succeeded
+ where
+ verb = verbosity dflags
+
+-- ---------------------------------------------------------------------------
+-- Run a compilation pipeline, consisting of multiple phases.
+
+-- The DynFlags can be modified by phases in the pipeline (eg. by
+-- OPTIONS pragmas), and the changes affect later phases in the
+-- pipeline, but we throw away the resulting DynFlags at the end.