summaryrefslogtreecommitdiff
path: root/Makefile
blob: 726801db0286ad4017e68823392c27919cc0a4b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

ifeq "$(wildcard distrib/)" ""

# We're in a bindist

.PHONY: default
default:
	@echo 'Run "make install" to install'
	@false

.PHONY: install
install:
	$(MAKE) -r --no-print-directory -f ghc.mk install BINDIST=YES NO_INCLUDE_DEPS=YES

.PHONY: show
show:
	$(MAKE) -r --no-print-directory -f ghc.mk $@

else

# The problem we need to solve is as follows.  
#
# GNU make supports included Makefiles, and it is clever enough to try
# to update those Makefiles when they are out-of-date or missing.  It
# first reads all the Makefiles, and then tries to build each one if
# it is out-of-date, using the rules in the Makefiles themselves.
# When it has brought all the Makefiles up-to-date, it restarts itself
# to read the newly-generated Makefiles.
#
# This works fine, unless there are dependencies *between* the
# Makefiles.  For example in the GHC build, for each package we have a
# package-data.mk file which is generated by the ghc-cabal program,
# and we have a .depend file.  The .depend file cannot be generated
# until package-data.mk has been generated and make has been restarted
# to read in its contents, because it is the package-data.mk file that
# tells us which modules are in the package.  But make always makes
# all the Makefiles before restarting - it doesn't take into account a
# dependency between Makefiles and restart itself earlier.

# Consider the following makefile:

# --------------------
# all :
#
# include inc1.mk
# 
# inc1.mk : Makefile
# 	echo "X = C" >$@
# 
# include inc2.mk
# 
# inc2.mk : inc1.mk
# 	echo "Y = $(X)" >$@
# --------------------

# Now try it:
# 
# $ make -f fail.mk
# fail.mk:3: inc1.mk: No such file or directory
# fail.mk:8: inc2.mk: No such file or directory
# echo "X = C" >inc1.mk
# echo "Y = " >inc2.mk
# make: Nothing to be done for `all'.

# make built both inc1.mk and inc2.mk without restarting itself
# between the two (even though we added a dependency on inc1.mk from
# inc2.mk).
#
# The solution we adopt in the GHC build system is essentially this:

# --------------------
# PHASE = 0
# 
# ifeq "$(PHASE)" "0"
# all :
# 	$(MAKE) PHASE=1
# else
# all :
# endif
# 
# -include inc1.mk
# 
# inc1.mk : Makefile
# 	echo "X = C" >$@
# 
# ifneq "$(PHASE)" "0"
# include inc2.mk
# 
# inc2.mk : inc1.mk
# 	echo "Y = $(X)" >$@
# endif
# 
# clean :
# 	rm -f inc1.mk inc2.mk
# --------------------

# That is, every time make is invoked, we force it to update inc1.mk
# and then restart.  In the GHC build system we need to divide the
# build into 4 phases in fact, with a restart between each phase.  See
# ghc.mk for the details on what happens in each phase and why.

default : all
	@:

# No need to update makefiles for these targets:
REALGOALS=$(filter-out clean clean_% distclean maintainer-clean show,$(MAKECMDGOALS))

# NB. not the same as saying '%: ...', which doesn't do the right thing:
# it does nothing if we specify a target that already exists.
.PHONY: $(REALGOALS)
$(REALGOALS) all:
	@echo "===--- updating makefiles phase 0"
	$(MAKE) -r --no-print-directory -f ghc.mk phase=0 just-makefiles
	@echo "===--- updating makefiles phase 1"
	$(MAKE) -r --no-print-directory -f ghc.mk phase=1 just-makefiles
	@echo "===--- updating makefiles phase 2"
	$(MAKE) -r --no-print-directory -f ghc.mk phase=2 just-makefiles
	@echo "===--- updating makefiles phase 3"
	$(MAKE) -r --no-print-directory -f ghc.mk phase=3 just-makefiles
	@echo "===--- finished updating makefiles"
	$(MAKE) -r --no-print-directory -f ghc.mk $@

binary-dist:
	rm -f bindist-list
	$(MAKE) -r --no-print-directory -f ghc.mk bindist BINDIST=YES
	$(MAKE) -r --no-print-directory -f ghc.mk binary-dist

clean distclean maintainer-clean:
	$(MAKE) -r --no-print-directory -f ghc.mk $@
	test ! -d testsuite || $(MAKE) -C testsuite $@

$(filter clean_%, $(MAKECMDGOALS)) : clean_% :
	$(MAKE) -r --no-print-directory -f ghc.mk $@

show:
	$(MAKE) -r --no-print-directory -f ghc.mk $@

# If the user says 'make A B', then we don't want to invoke two
# instances of the rule above in parallel:
.NOTPARALLEL:

endif