[project @ 2005-10-14 11:22:41 by simonpj]
[ghc-hetmet.git] / ghc / compiler / main / DriverPipeline.hs
index 910d491..025a09b 100644 (file)
@@ -42,7 +42,6 @@ import ErrUtils
 import DynFlags
 import StaticFlags     ( v_Ld_inputs, opt_Static, WayName(..) )
 import Config
-import RdrName         ( GlobalRdrEnv )
 import Panic
 import Util
 import StringBuffer    ( hGetStringBuffer )
@@ -54,6 +53,7 @@ import ParserCoreUtils        ( getCoreModuleName )
 import SrcLoc          ( srcLocSpan, mkSrcLoc )
 import FastString      ( mkFastString )
 import Bag             ( listToBag, emptyBag )
+import SrcLoc          ( Located(..) )
 
 import EXCEPTION
 import DATA_IOREF      ( readIORef, writeIORef, IORef )
@@ -189,10 +189,12 @@ compile hsc_env msg_act mod_summary maybe_old_linkable old_iface mod_index nmods
 
        | otherwise     -- Normal source file
        -> do
-          maybe_stub_o <- compileStub dflags' stub_c_exists
-          let stub_unlinked = case maybe_stub_o of
-                                 Nothing -> []
-                                 Just stub_o -> [ DotO stub_o ]
+          stub_unlinked <-
+            if stub_c_exists then do
+               stub_o <- compileStub dflags' object_filename
+               return [ DotO stub_o ]
+            else
+               return []
 
           (hs_unlinked, unlinked_time) <-
             case hsc_lang of
@@ -212,6 +214,9 @@ compile hsc_env msg_act mod_summary maybe_old_linkable old_iface mod_index nmods
 #endif
                       Nothing -> panic "compile: no interpreted code"
 
+               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
@@ -229,14 +234,31 @@ compile hsc_env msg_act mod_summary maybe_old_linkable old_iface mod_index nmods
 -----------------------------------------------------------------------------
 -- stub .h and .c files (for foreign export support)
 
-compileStub dflags stub_c_exists
-  | not stub_c_exists = return Nothing
-  | stub_c_exists = do
+-- The _stub.c file is derived from the haskell source file (but stored
+-- in hscStubCOutName in the dflags for some reason, probably historical).
+-- Consequently, we derive the _stub.o filename from the haskell object
+-- filename.  
+--
+-- This isn't necessarily the same as the object filename we
+-- would get if we just compiled the _stub.c file using the pipeline.
+-- For example:
+--
+--    ghc src/A.hs -odir obj
+-- 
+-- results in obj/A.o, and src/A_stub.c.  If we compile src/A_stub.c with
+-- -odir obj, we would get obj/src/A_stub.o, which is wrong; we want
+-- obj/A_stub.o.
+
+compileStub dflags object_filename = do
+       let (o_base, o_ext) = splitFilename object_filename
+           stub_o = o_base ++ "_stub" `joinFileExt` o_ext
+
        -- compile the _stub.c file w/ gcc
        let stub_c = hscStubCOutName dflags
-       (_, stub_o) <- runPipeline StopLn dflags
-                           (stub_c,Nothing) Persistent Nothing{-no ModLocation-}
-       return (Just stub_o)
+       runPipeline StopLn dflags (stub_c,Nothing) 
+               (SpecificFile stub_o) Nothing{-no ModLocation-}
+
+       return stub_o
 
 
 -- ---------------------------------------------------------------------------
@@ -285,11 +307,27 @@ link BatchCompile dflags batch_attempt_linking hpt
                  return Succeeded
          else do
 
-       debugTraceMsg dflags 1 "Linking ..."
-
        let getOfiles (LM _ _ us) = map nameOfObject (filter isObject us)
            obj_files = concatMap getOfiles linkables
 
+           exe_file = exeFileName dflags
+
+       -- if the modification time on the executable is later than the
+       -- modification times on all of the objects, then omit linking
+       -- (unless the -no-recomp flag was given).
+       e_exe_time <- IO.try $ getModificationTime exe_file
+       let linking_needed 
+               | Left _  <- e_exe_time = True
+               | Right t <- e_exe_time = 
+                       any (t <) (map linkableTime linkables)
+
+       if dopt Opt_RecompChecking dflags && not linking_needed
+          then do debugTraceMsg dflags 1 (exe_file ++ " is up to date, linking not required.")
+                  return Succeeded
+          else do
+
+       debugTraceMsg dflags 1 "Linking ..."
+
        -- Don't showPass in Batch mode; doLink will do that for us.
         staticLink dflags obj_files pkg_deps
 
@@ -508,7 +546,7 @@ getOutputFilename dflags stop_phase output basename
 
                odir_persistent
                   | Just loc <- maybe_location = ml_obj_file loc
-                  | Just d <- odir = replaceFilenameDirectory persistent d
+                  | Just d <- odir = d `joinFileName` persistent
                   | otherwise      = persistent
 
 
@@ -621,7 +659,7 @@ runPhase (Hsc src_flavour) stop dflags0 basename suff input_fn get_output_fn _ma
                                  ; return (Nothing, mkModule m) }
 
                other -> do { buf <- hGetStringBuffer input_fn
-                           ; (_,_,mod_name) <- getImports dflags buf input_fn
+                           ; (_,_,L _ mod_name) <- getImports dflags buf input_fn
                            ; return (Just buf, mod_name) }
 
   -- Build a ModLocation to pass to hscMain.
@@ -734,11 +772,9 @@ runPhase (Hsc src_flavour) stop dflags0 basename suff input_fn get_output_fn _ma
                      stub_h_exists stub_c_exists
                      _maybe_interpreted_code -> do
 
-               -- Deal with stubs 
-               maybe_stub_o <- compileStub dflags' stub_c_exists
-               case maybe_stub_o of
-                     Nothing     -> return ()
-                     Just stub_o -> consIORef v_Ld_inputs stub_o
+               when stub_c_exists $ do
+                       stub_o <- compileStub dflags' o_file
+                       consIORef v_Ld_inputs stub_o
 
                -- In the case of hs-boot files, generate a dummy .o-boot 
                -- stamp file for the benefit of Make
@@ -1078,18 +1114,12 @@ getHCFilePackages filename =
 staticLink :: DynFlags -> [FilePath] -> [PackageId] -> IO ()
 staticLink dflags o_files dep_packages = do
     let verb = getVerbFlag dflags
+        output_fn = exeFileName dflags
 
     -- get the full list of packages to link with, by combining the
     -- explicit packages with the auto packages and all of their
     -- dependencies, and eliminating duplicates.
 
-    let o_file = outputFile dflags
-#if defined(mingw32_HOST_OS)
-    let output_fn = case o_file of { Just s -> s; Nothing -> "main.exe"; }
-#else
-    let output_fn = case o_file of { Just s -> s; Nothing -> "a.out"; }
-#endif
-
     pkg_lib_paths <- getPackageLibraryPath dflags dep_packages
     let pkg_lib_path_opts = map ("-L"++) pkg_lib_paths
 
@@ -1175,6 +1205,17 @@ staticLink dflags o_files dep_packages = do
              if success then return ()
                         else throwDyn (InstallationError ("cannot move binary to PVM dir")))
 
+
+exeFileName :: DynFlags -> FilePath
+exeFileName dflags
+  | Just s <- outputFile dflags = s
+  | otherwise = 
+#if defined(mingw32_HOST_OS)
+       "main.exe"
+#else
+       "a.out"
+#endif
+
 -----------------------------------------------------------------------------
 -- Making a DLL (only for Win32)