circleci: Bump down thread count
[ghc.git] / rules / hi-rule.mk
1 # -----------------------------------------------------------------------------
2 #
3 # (c) 2009 The University of Glasgow
4 #
5 # This file is part of the GHC build system.
6 #
7 # To understand how the build system works and how to modify it, see
8 # http://ghc.haskell.org/trac/ghc/wiki/Building/Architecture
9 # http://ghc.haskell.org/trac/ghc/wiki/Building/Modifying
10 #
11 # -----------------------------------------------------------------------------
12
13
14 # Here's an interesting rule!
15
16 # The .hi file may or may not change when we compile the corresponding
17 # .hs file. If GHC figures out that the .hi file has not changed, it
18 # doesn't touch it. This is a useful optimisation, because it means
19 # some modules may not get recompiled if the .hi files of the modules
20 # they depend on have not changed.
21 #
22 # See:
23 # http://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/RecompilationAvoidance
24 #
25 # So how do we express this dependency to make? The exact form of
26 # this rule is quite fragile. Here are some versions that don't work
27 # very well:
28 #
29 # %.hi : %.o
30 # @if [ ! -f $@ ] ; then \
31 # echo Panic! $< exists, but $@ does not.; \
32 # exit 1; \
33 # fi
34 #
35 # This version adds a useful sanity check, and is a good solution,
36 # except that it means spawning a shell. This can be expensive,
37 # especially on Windows where spawning a shell takes about 0.3s.
38 # We'd like to avoid the shell if necessary. This also hides the
39 # message "nothing to be done for 'all'", since make thinks it has
40 # actually done something. Therefore we only use this version
41 # if ExtraMakefileSanityChecks is enabled.
42 #
43 # %.hi : %.o
44 #
45 # This version doesn't work: GNU make knows it has't done anything to
46 # update the .hi file, so even if the .o file has been updated, it
47 # won't rebuild anything that depends on the .hi file. So you might
48 # think a more correct way is to change the .hs rule:
49 #
50 # %.hi %.o : %.hs
51 # $(HC) ...
52 #
53 # this says "compiling %.hs updates both %.hi and %.o", but that's not
54 # true, since compiling the .hs file might not update the .hi file, if
55 # the .hi file didn't change. And if we use this version, then make
56 # will keep trying to rebuild %.hi if it is out of date with respect
57 # to %.hs.
58 #
59 # Using this form seems to be the best compromise:
60 #
61 # %.hi : %.o ;
62 #
63 # the ';' at the end signifies an "empty command" (see the GNU make
64 # documentation). An empty command is enough to get GNU make to think
65 # it has updated %.hi, but without actually spawning a shell to do so.
66 #
67 # However, given that rule, make thinks that it can make .hi files
68 # for any object file, even if the object file was created from e.g.
69 # a C source file. We therefore also add a dependency on the .hs/.lhs
70 # source file, which means we end up with rules like:
71 #
72 # a/%.hi : a/%.o b/%.hs ;
73 #
74 # But! If a file is not explicitly mentioned in a makefile, then if
75 # make needs to build it using such a %-rule then it treats it as an
76 # 'intermediate file', and deletes it when it is finished. Most .hi
77 # files are mentioned in .depend* files, as some other module depends on
78 # them, but there are some library modules that aren't imported by
79 # anything in the tree.
80 #
81 # We could stop make from deleting the .hi files by declaring
82 # ".SECONDARY:", but if we do that then make takes a pathologically long
83 # time with our build system. So we now generate (by calling hi-rule
84 # from .depend* files) rules that look like
85 #
86 # a/B.hi a/B.dyn_hi : %hi : %o x/B.hs
87 #
88 # Now all the .hi files are explicitly mentioned in the makefiles, so
89 # make doesn't think they are merely intermediate files, and doesn't
90 # delete them.
91
92 ifeq "$(ExtraMakefileSanityChecks)" "NO"
93
94 define hi-rule # $1 = rule header
95 $1 ;
96 endef
97
98 else
99
100 define hi-rule # $1 = rule header
101 $1
102 @if [ ! -f $$@ ] ; then \
103 echo "Panic! $$< exists, but $$@ does not."; \
104 exit 1; \
105 fi
106
107 endef
108
109 endif
110