X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=rules%2Fhi-rule.mk;h=35baffd11a17dae36031cbc12cae30ec4adac98b;hp=07b65ed8e102fad30647dc148c9f1da7337f1d97;hb=7b0ff1792d699ff02a604163c9ccf4a98a1ca3eb;hpb=34cc75e1a62638f2833815746ebce0a9114dc26b diff --git a/rules/hi-rule.mk b/rules/hi-rule.mk index 07b65ed..35baffd 100644 --- a/rules/hi-rule.mk +++ b/rules/hi-rule.mk @@ -1,25 +1,72 @@ +# ----------------------------------------------------------------------------- +# +# (c) 2009 The University of Glasgow +# +# This file is part of the GHC build system. +# +# To understand how the build system works and how to modify it, see +# http://hackage.haskell.org/trac/ghc/wiki/Building/Architecture +# http://hackage.haskell.org/trac/ghc/wiki/Building/Modifying +# +# ----------------------------------------------------------------------------- + # Here's an interesting rule! -# The .hi file depends on the .o file, -# so if the .hi file is dated earlier than the .o file (commonly the case, -# when interfaces are stable) this rule just makes sure that the .o file, -# is up to date. Then it does nothing to generate the .hi file from the -# .o file, because the act of making sure the .o file is up to date also -# updates the .hi file (if necessary). + +# The .hi file may or may not change when we compile the corresponding +# .hs file. If GHC figures out that the .hi file has not changed, it +# doesn't touch it. This is a useful optimisation, because it means +# some modules may not get recompiled if the .hi files of the modules +# they depend on have not changed. +# +# See: +# http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/RecompilationAvoidance +# +# So how do we express this dependency to make? The exact form of +# this rule is quite fragile. Here are some versions that don't work +# very well: +# +# %.hi : %.o +# @if [ ! -f $@ ] ; then \ +# echo Panic! $< exists, but $@ does not.; \ +# exit 1; \ +# fi +# +# This version adds a useful sanity check; but it is also expensive on +# Windows where spawning a shell takes a while (about 0.3s). We'd +# like to avoid the shell if necessary. This also hides the message +# "nothing to be done for 'all'", since make thinks it has actually done +# something. +# +# %.hi : %.o +# +# This version doesn't work: GNU make knows it has't done anything to +# update the .hi file, so even if the .o file has been updated, it +# won't rebuild anything that depends on the .hi file. So you might +# think a more correct way is to change the .hs rule: +# +# %.hi %.o : %.hs +# $(HC) ... +# +# this says "compiling %.hs updates both %.hi and %.o", but that's not +# true, since compiling the .hs file might not update the .hi file, if +# the .hi file didn't change. And if we use this version, then make +# will keep trying to rebuild %.hi if it is out of date with respect +# to %.hs. +# +# Using this form seems to be the best compromise: +# +# %.hi : %.o ; +# +# the ';' at the end signifies an "empty command" (see the GNU make +# documentation). An empty command is enough to get GNU make to think +# it has updated %.hi, but without actually spawning a shell to do so. define hi-rule # $1 = way -%.$$($1_hisuf) : %.$$($1_osuf) - @if [ ! -f $$@ ] ; then \ - echo Panic! $$< exists, but $$@ does not.; \ - exit 1; \ - else exit 0 ; \ - fi - -%.$$($1_way_)hi-boot : %.$$($1_way_)o-boot - @if [ ! -f $$@ ] ; then \ - echo Panic! $$< exists, but $$@ does not.; \ - exit 1; \ - else exit 0 ; \ - fi + +%.$$($1_hisuf) : %.$$($1_osuf) ; + +%.$$($1_way_)hi-boot : %.$$($1_way_)o-boot ; + endef