Changes between Version 1 and Version 2 of DependencyTracking


Ignore:
Timestamp:
Sep 5, 2011 2:21:59 PM (3 years ago)
Author:
simonpj
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DependencyTracking

    v1 v2  
     1= Improved dependency tracking for --make = 
     2 
    13Many packages these days are using Template Haskell to grab information from the filesystem at compile time. I'll use Hamlet as a motivating example, though this applies to others as well. 
    24 
    35In Hamlet, you can specify an external file as the source for your HTML template code, with something like: 
     6{{{ 
     7{-# LANGUAGE TemplateHaskell #-} 
     8module M where 
     9  import X 
     10  import Y 
     11  $(renderHamlet $(hamletFile "myfile.hamlet")) 
     12}}} 
     13Now suppose "myfile.hamlet" is updated, but there are no changes in `M.hs`, `X.hs`, `Y.hs` (and their imports).  Then `ghc --make` will think that `M` doesn't need recompiling at all and will not recompile `M` (possibly saying "Recompilation is NOT required"). Which is obviously wrong.   
    414 
    5     {{{renderHamlet $(hamletFile "myfile.hamlet")}}} 
     15Even with plain module-at-a-time `ghc -c M.hs`, GHC may wrongly fail to recompile M because it thinks its unnecessary. You have to use `-fforce-recomp` to make it happen. 
    616 
    7 Unfortunately, if "myfile.hamlet" is updated, without making any changes to the Haskell code, then GHC will not know to recompile the source, and the updated HTML code will not filter through. 
     17The situation is very similar with CPP: 
     18{{{ 
     19{-# LANGUAGE Cpp #-} 
     20module M where 
     21  import X 
     22  import Y 
     23  #include "myfile.h" 
     24}}} 
     25Again `ghc --make` will fail to see the dependency on "myfile.h" and may therefore fail to recompile `M` when it should really do so. 
    826 
    9 To solve this, a [http://www.reddit.com/r/haskell/comments/k4lc4/yesod_the_limitations_of_haskell/c2hipo3 possible solution] is to add a new function to the template-haskell package: 
     27== Possible solution == 
     28 
     29The solution comes in these pieces: 
     30 1. A part (different for TH and CPP) that tells GHC what files went into compiling M 
     31 2. A way (shared) to record this "file-dependency info" in M's interface file, `M.hi` 
     32 3. A new bit of the recompilation check that makes M recompile if any of its file-dependencies are out of date. 
     33 
     34Concering (2), GHC already has a components of M.hi that records "usages": fingerprints of the things that GHC used in compiling M.  This is the `mi_usages` field of `HscTypes.ModIface`.  To record the extra dependency we can just add a new constructor to `HscTypes.Usage` for `FileUsage`.  (Record an absolute, not relative path!) 
     35 
     36Then (3) is relatively easy: just check the modification date of `M.o` against the dependened-on file. 
     37 
     38That leaves (1).  We'll need: 
     39 
     40 * A new field in `TcgGblEnv` to accumulate file-dependencies. 
     41 
     42 * Some way for `#include` directives to be recorded in that list (presumably by interpreting the #line directives that CPP outputs. 
     43 
     44 * A way for Template Haskell code to express a dependency.  A [http://www.reddit.com/r/haskell/comments/k4lc4/yesod_the_limitations_of_haskell/c2hipo3 possible solution] is to add a new function to the template-haskell package: 
    1045 
    1146    {{{addDependentFile :: FilePath -> Q ()}}} 
    1247 
    13 When GHC encounters this, it will add the specified file as a dependency for the given Haskell file. If the file is updated or is not present, then a recompile will be required. 
     48 This in turn would require the `Qusai` class to support such an operation. 
     49 
     50'''Note''' that `ghc -M` would not spit out these dependencies.  The solution proposed here simply records what dependencies where encountered ''while compiling M'', and hence when M should be re-compiled. It doesn't tell you (in advance) which files compiling M ''will'' depend on.