diff options
author | Edward Z. Yang <ezyang@cs.stanford.edu> | 2014-12-27 10:50:01 -0800 |
---|---|---|
committer | Edward Z. Yang <ezyang@cs.stanford.edu> | 2015-01-03 11:56:14 -0800 |
commit | 2223e196b2dc5340d70e58be011c279d381b4319 (patch) | |
tree | 3c587547990df7c62d73598f9dfe991afb0b4880 /compiler | |
parent | af4d99803ea7676f88f250ad56a8c31c1c8cd5bc (diff) | |
download | haskell-2223e196b2dc5340d70e58be011c279d381b4319.tar.gz |
Fix #9243 so recompilation avoidance works with -fno-code
Summary:
Where we track timestamps of object files, also track timestamps
for interface files. When -fno-code -fwrite-interface is enabled, use
the interface file timestamp as an extra check to see if the files are
up-to-date. We had to apply this logic to one-shot and make modes.
This fix would be good to merge into 7.10; it makes using -fno-code
-fwrite-interface for flywheel type checking usable.
Signed-off-by: Edward Z. Yang <ezyang@cs.stanford.edu>
Test Plan: validate and new test cases
Reviewers: austin
Subscribers: carter, thomie
Differential Revision: https://phabricator.haskell.org/D596
GHC Trac Issues: #9243
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/main/DriverPipeline.hs | 19 | ||||
-rw-r--r-- | compiler/main/GhcMake.hs | 40 | ||||
-rw-r--r-- | compiler/main/HscTypes.hs | 4 |
3 files changed, 57 insertions, 6 deletions
diff --git a/compiler/main/DriverPipeline.hs b/compiler/main/DriverPipeline.hs index e8be29759b..6d597f9437 100644 --- a/compiler/main/DriverPipeline.hs +++ b/compiler/main/DriverPipeline.hs @@ -30,7 +30,7 @@ module DriverPipeline ( runPhase, exeFileName, mkExtraObjToLinkIntoBinary, mkNoteObjsToLinkIntoBinary, maybeCreateManifest, runPhase_MoveBinary, - linkingNeeded, checkLinkInfo + linkingNeeded, checkLinkInfo, writeInterfaceOnlyMode ) where #include "HsVersions.h" @@ -935,6 +935,11 @@ runPhase (RealPhase (Hsc src_flavour)) input_fn dflags0 location <- getLocation src_flavour mod_name let o_file = ml_obj_file location -- The real object file + hi_file = ml_hi_file location + dest_file | writeInterfaceOnlyMode dflags + = hi_file + | otherwise + = o_file -- Figure out if the source has changed, for recompilation avoidance. -- @@ -952,10 +957,10 @@ runPhase (RealPhase (Hsc src_flavour)) input_fn dflags0 -- (b) we aren't going all the way to .o file (e.g. ghc -S) then return SourceModified -- Otherwise look at file modification dates - else do o_file_exists <- doesFileExist o_file - if not o_file_exists + else do dest_file_exists <- doesFileExist dest_file + if not dest_file_exists then return SourceModified -- Need to recompile - else do t2 <- getModificationUTCTime o_file + else do t2 <- getModificationUTCTime dest_file if t2 > src_timestamp then return SourceUnmodified else return SourceModified @@ -975,6 +980,7 @@ runPhase (RealPhase (Hsc src_flavour)) input_fn dflags0 ms_location = location, ms_hs_date = src_timestamp, ms_obj_date = Nothing, + ms_iface_date = Nothing, ms_textual_imps = imps, ms_srcimps = src_imps } @@ -2248,6 +2254,11 @@ joinObjectFiles dflags o_files output_fn = do -- ----------------------------------------------------------------------------- -- Misc. +writeInterfaceOnlyMode :: DynFlags -> Bool +writeInterfaceOnlyMode dflags = + gopt Opt_WriteInterface dflags && + HscNothing == hscTarget dflags + -- | What phase to run after one of the backend code generators has run hscPostBackendPhase :: DynFlags -> HscSource -> HscTarget -> Phase hscPostBackendPhase _ HsBootFile _ = StopLn diff --git a/compiler/main/GhcMake.hs b/compiler/main/GhcMake.hs index 1fb6f71af2..cd670b36cd 100644 --- a/compiler/main/GhcMake.hs +++ b/compiler/main/GhcMake.hs @@ -1136,6 +1136,15 @@ upsweep old_hpt stable_mods cleanup sccs = do upsweep' old_hpt1 done' mods (mod_index+1) nmods +maybeGetIfaceDate :: DynFlags -> ModLocation -> IO (Maybe UTCTime) +maybeGetIfaceDate dflags location + | writeInterfaceOnlyMode dflags + -- Minor optimization: it should be harmless to check the hi file location + -- always, but it's better to avoid hitting the filesystem if possible. + = modificationTimeIfExists (ml_hi_file location) + | otherwise + = return Nothing + -- | Compile a single module. Always produce a Linkable for it if -- successful. If no compilation happened, return the old Linkable. upsweep_mod :: HscEnv @@ -1150,6 +1159,7 @@ upsweep_mod hsc_env old_hpt (stable_obj, stable_bco) summary mod_index nmods this_mod_name = ms_mod_name summary this_mod = ms_mod summary mb_obj_date = ms_obj_date summary + mb_if_date = ms_iface_date summary obj_fn = ml_obj_file (ms_location summary) hs_date = ms_hs_date summary @@ -1287,11 +1297,26 @@ upsweep_mod hsc_env old_hpt (stable_obj, stable_bco) summary mod_index nmods linkable <- liftIO $ findObjectLinkable this_mod obj_fn obj_date compile_it_discard_iface (Just linkable) SourceUnmodified + -- See Note [Recompilation checking when typechecking only] + | writeInterfaceOnlyMode dflags, + Just if_date <- mb_if_date, + if_date >= hs_date -> do + liftIO $ debugTraceMsg (hsc_dflags hsc_env) 5 + (text "skipping tc'd mod:" <+> ppr this_mod_name) + compile_it Nothing SourceUnmodified + _otherwise -> do liftIO $ debugTraceMsg (hsc_dflags hsc_env) 5 (text "compiling mod:" <+> ppr this_mod_name) compile_it Nothing SourceModified +-- Note [Recompilation checking when typechecking only] +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-- If we are compiling with -fno-code -fwrite-interface, there won't +-- be any object code that we can compare against, nor should there +-- be: we're *just* generating interface files. In this case, we +-- want to check if the interface file is new, in lieu of the object +-- file. See also Trac #9243. -- Filter modules in the HPT @@ -1691,6 +1716,7 @@ summariseFile hsc_env old_summaries file mb_phase obj_allowed maybe_buf | Just old_summary <- findSummaryBySourceFile old_summaries file = do let location = ms_location old_summary + dflags = hsc_dflags hsc_env src_timestamp <- get_src_timestamp -- The file exists; we checked in getRootSummary above. @@ -1707,7 +1733,9 @@ summariseFile hsc_env old_summaries file mb_phase obj_allowed maybe_buf || obj_allowed -- bug #1205 then liftIO $ getObjTimestamp location NotBoot else return Nothing - return old_summary{ ms_obj_date = obj_timestamp } + hi_timestamp <- maybeGetIfaceDate dflags location + return old_summary{ ms_obj_date = obj_timestamp + , ms_iface_date = hi_timestamp } else new_summary src_timestamp @@ -1745,6 +1773,8 @@ summariseFile hsc_env old_summaries file mb_phase obj_allowed maybe_buf then liftIO $ modificationTimeIfExists (ml_obj_file location) else return Nothing + hi_timestamp <- maybeGetIfaceDate dflags location + return (ModSummary { ms_mod = mod, ms_hsc_src = hsc_src, ms_location = location, ms_hspp_file = hspp_fn, @@ -1752,6 +1782,7 @@ summariseFile hsc_env old_summaries file mb_phase obj_allowed maybe_buf ms_hspp_buf = Just buf, ms_srcimps = srcimps, ms_textual_imps = the_imps, ms_hs_date = src_timestamp, + ms_iface_date = hi_timestamp, ms_obj_date = obj_timestamp }) findSummaryBySourceFile :: [ModSummary] -> FilePath -> Maybe ModSummary @@ -1808,7 +1839,9 @@ summariseModule hsc_env old_summary_map is_boot (L loc wanted_mod) || obj_allowed -- bug #1205 then getObjTimestamp location is_boot else return Nothing - return (Just (Right old_summary{ ms_obj_date = obj_timestamp })) + hi_timestamp <- maybeGetIfaceDate dflags location + return (Just (Right old_summary{ ms_obj_date = obj_timestamp + , ms_iface_date = hi_timestamp})) | otherwise = -- source changed: re-summarise. new_summary location (ms_mod old_summary) src_fn src_timestamp @@ -1880,6 +1913,8 @@ summariseModule hsc_env old_summary_map is_boot (L loc wanted_mod) then getObjTimestamp location is_boot else return Nothing + hi_timestamp <- maybeGetIfaceDate dflags location + return (Just (Right (ModSummary { ms_mod = mod, ms_hsc_src = hsc_src, ms_location = location, @@ -1889,6 +1924,7 @@ summariseModule hsc_env old_summary_map is_boot (L loc wanted_mod) ms_srcimps = srcimps, ms_textual_imps = the_imps, ms_hs_date = src_timestamp, + ms_iface_date = hi_timestamp, ms_obj_date = obj_timestamp }))) diff --git a/compiler/main/HscTypes.hs b/compiler/main/HscTypes.hs index 29ee78c2b3..2d3203934c 100644 --- a/compiler/main/HscTypes.hs +++ b/compiler/main/HscTypes.hs @@ -2357,6 +2357,10 @@ data ModSummary -- ^ Timestamp of source file ms_obj_date :: Maybe UTCTime, -- ^ Timestamp of object, if we have one + ms_iface_date :: Maybe UTCTime, + -- ^ Timestamp of hi file, if we *only* are typechecking (it is + -- 'Nothing' otherwise. + -- See Note [Recompilation checking when typechecking only] and #9243 ms_srcimps :: [Located (ImportDecl RdrName)], -- ^ Source imports of the module ms_textual_imps :: [Located (ImportDecl RdrName)], |