diff options
Diffstat (limited to 'ghc')
-rw-r--r-- | ghc/docs/users_guide/recomp.lit | 196 |
1 files changed, 162 insertions, 34 deletions
diff --git a/ghc/docs/users_guide/recomp.lit b/ghc/docs/users_guide/recomp.lit index 5b3abe8f17..55c64f467f 100644 --- a/ghc/docs/users_guide/recomp.lit +++ b/ghc/docs/users_guide/recomp.lit @@ -1,41 +1,169 @@ %************************************************************************ %* * -\section[recomp]{The GHC recompilation checker (and using `make')} +\section[separate-compilation]{Separate compilation} +\index{separate compilation} \index{recompilation checker} \index{make and recompilation} %* * %************************************************************************ -WIth the introduction of Haskell~1.3, the module system (nicely -improved, thank you very much) requires a substantially different -implementation, which we did (as of release GHC~2.01). - -We have taken a fairly radical approach and implemented a ``go to the -horse's mouth'' scheme; that is, when seeking out information about an -entity \tr{Foo.bar}, GHC will always look in the interface for -\tr{Foo}---no matter what interface {\em told us} about \tr{Foo.bar} -(via re-exporting and whatnot). - -This ``horse's mouth'' scheme removes some of the most unsavoury -aspects of GHC~0.2x's behaviour (because of picking up duff -information about re-exported entities). However, the keen-minded -user will see that it makes it difficult to maintain -\tr{make}-friendly dependencies between modules. - -Enter the ``recompilation checker'', which you invoke merely by adding -a \tr{-recomp} option\index{-recomp option} to your GHC command line. -(You should also create ordinary `make' dependencies; there's an -example of how to do this in \sectionref{mkdependHS}.) - -GHC will now start ``compiling'' much more often than in the old days, -but it will frequently bail out quickly, saying the recompile is -\tr{NOT NEEDED}. What a beautiful sight! - -%The recompilation checker is not finished. Its main faults are: -%(a)~it doesn't yet do the right things for instance declarations; -%(b)~it doesn't do anything about pragmas (happily, GHC~2.01 doesn't -%produce any); (c)~it has no good solution for mutually-recursive -%modules. - -Patrick Sansom has a workshop paper about how all these things should -be done. Ask him (email: \tr{sansom}) if you want a copy. +This section describes how GHC supports separate compilation. + +\subsection[hi-files]{Interface files} + +When GHC compiles a source module @A@, it generates an object @A.o@, {\em and} a +companion {\em interface file} @A.hi@. The interface file +contains information needed by the compiler when it compiles any module @B@ that +imports @A@, whether directly or indirectly. When compiling @B@, GHC will +read @A.hi@ to find the details that it needs to know about things defined in @A@. + +Furthermore, when compiling module @C@ which imports @B@, GHC may decide that it +needs to know something about @A@ --- for example, @B@ might export a function +that involves a type defined in @A@. In this case, GHC will go and read @A.hi@ even +though @C@ does not explicitly import @A@ at all. + +The interface file may contain all sorts of things that aren't explicitly +exported from @A@ by the programmer. For example, even though a data type is exported +abstractly, @A.hi@ will contain the full data type definition. For small function +definitions, @A.hi@ will contain the complete definition of the function. For +bigger functions, @A.hi@ will contain strictness information about the function. And so on. +GHC puts much more information into @.hi@ files when you use @-O@. Without @-O@ +it puts in just the minimum; with @-O@ it lobs in a whole pile of stuff. + +@A.hi@ should really be thought of as a compiler-readable version of @A.o@. +If you use a @.hi@ file that wasn't generated by the same compilation run that +generates the @.o@ file the compiler may assume all sorts of incorrect things about @A@, +resulting in core dumps and other unpleasant happenings. + +In the olden days, GHC compared the newly-generated @.hi@ file with the previous version; +if they were identical, it left the old one alone and didn't change its modification date. +In consequence, importers of a module with an unchanged output @.hi@ file were not recompiled. + +This doesn't work any more. In our earlier example, module @C@ does +not import module @A@ directly, yet changes to @A.hi@ should force a +recompilation of @C@. And some changes to @A@ (changing the +definition of a function that appears in an inlining of a function +exported by @B@, say) may conceivably not change @B.hi@ one jot. So +now + + +\subsection[recomp]{The recompilation checker} + +GHC keeps a version number on each interface file, and on each type +signature within the interface file. It also keeps in every interface +file a list of the version numbers of everything it used when it last +compiled the file. If the source file's modification date is earlier +than the @.o@ file's date (i.e. the source hasn't changed since the +file was last compiled), and you give GHC the @-recomp@ flag, then GHC +will be clever. It compares the version numbers on the things it +needs this time with the version numbers on the things it needed last +time (gleaned from the interface file of the module being compiled); +if they are all the same it stops compiling rather early in the +process saying ``Recompilation not required''. What a beautiful +sight! + +It's still an experimental feature (that's why @-recomp@ is off by +default), so tell us if you think it doesn't work. + +Patrick Sansom has a workshop paper about how all this is +done. Ask him (email: \tr{sansom}) if you want a copy. + +\subsection{Using @make@} + +It is reasonably straightforward to set up a \tr{Makefile} to use with +GHC, assuming you name your source files the same as your modules. +Thus: +\begin{verbatim} +HC = ghc +HC_OPTS = -cpp $(EXTRA_HC_OPTS) + +SRCS = Main.lhs Foo.lhs Bar.lhs +OBJS = Main.o Foo.o Bar.o + +.SUFFIXES : .o .hi .lhs .hc .s + +cool_pgm : $(OBJS) + $(RM) $@ + $(HC) -o $@ $(HC_OPTS) $(OBJS) + +# Standard suffix rules +.o.hi: + @: + +.lhs.o: + $(RM) $@ + $(HC) -c $< $(HC_OPTS) + +.hs.o: + $(RM) $@ + $(HC) -c $< $(HC_OPTS) + +# Optional +.hc.o: + $(RM) $@ + $(HC) -c $< $(HC_OPTS) + +# Optional +.s.o: + $(RM) $@ + $(HC) -c $< $(HC_OPTS) + + +# Inter-module dependencies +Foo.o Foo.hc Foo.s : Baz.hi # Foo imports Baz +Main.o Main.hc Main.s : Foo.hi Baz.hi # Main imports Foo and Baz +\end{verbatim} + +(Sophisticated \tr{make} variants may achieve some of the above more +elegantly. Notably, @gmake@'s pattern rules let you write the more comprehensible: +\begin{verbatim} +%.o : %.lhs + $(RM) $@ + $(HC) -c $< $(HC_OPTS) +\end{verbatim} +What we've shown should work with any \tr{make}.) + +Note the cheesy \tr{.o.hi} rule: It records the dependency of the +interface (\tr{.hi}) file on the source. The rule says a \tr{.hi} +file can be made from a \tr{.o} file by doing... nothing. Which is +true. + +Note the inter-module dependencies at the end of the Makefile, which take the form +\begin{verbatim} +Foo.o Foo.hc Foo.s : Baz.hi # Foo imports Baz +\end{verbatim} +They tell @make@ that if any of @Foo.o@, @Foo.hc@ or @Foo.s@ have +an earlier modification date than @Baz.hi@, then the out-of-date +file must be brought up to date. To bring it up to date, @make@ looks +for a rule to do so; one of the preceding suffix rules does the job nicely. + +Putting inter-dependencies of the form \tr{Foo.o : Bar.hi} into your +\tr{Makefile} by hand is rather error-prone. Don't worry---never +fear, \tr{mkdependHS} is here! (and is distributed as part of GHC) +Add the following to your \tr{Makefile}: +\begin{verbatim} +depend : + mkdependHS -- $(HC_OPTS) -- $(SRCS) +\end{verbatim} +Now, before you start compiling, and any time you change the +\tr{imports} in your program, do \tr{make depend} before you do +\tr{make cool_pgm}. \tr{mkdependHS} will append the needed +dependencies to your \tr{Makefile}. @mkdependHS@ is fully +describe in \Sectionref{mkdependHS}. + + + + + + +A few caveats about this simple scheme: (a)~You may need to compile +some modules explicitly to create their interfaces in the first place +(e.g., \tr{make Bar.o} to create \tr{Bar.hi}). (b)~You may have to +type \tr{make} more than once for the dependencies to have full +effect. However, a \tr{make} run that does nothing {\em does} mean +``everything's up-to-date.'' (c) This scheme will work with +mutually-recursive modules but, again, it may take multiple +iterations to ``settle.'' + + + |