summaryrefslogtreecommitdiff
path: root/rules/build-prog.mk
blob: 8d2bcd25c50d4b5ba1fe03c25cc5560e1c01e74f (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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# -----------------------------------------------------------------------------
#
# (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
#      https://gitlab.haskell.org/ghc/ghc/wikis/building/architecture
#      https://gitlab.haskell.org/ghc/ghc/wikis/building/modifying
#
# -----------------------------------------------------------------------------


# Build a program.
#
# $(eval $(call build-prog,utils/genapply,dist-install,1))

define build-prog
$(call trace, build-prog($1,$2,$3))
$(call profStart, build-prog($1,$2,$3))
# $1 = dir
# $2 = distdir
# $3 = GHC stage to use (0 == bootstrapping compiler)

ifeq "$$($1_$2_PROGNAME)" ""
$$(error $1_$2_PROGNAME is not set)
endif
ifneq "$$($1_$2_PROG)" ""
$$(error $1_$2_PROG is set)
endif
$1_$2_PROG = $$($1_$2_PROGNAME)$$(exeext$3)

ifeq "$$(findstring $3,0 1 2)" ""
$$(error $1/$2: stage argument to build-prog should be 0, 1, or 2)
endif

$(call clean-target,$1,$2,$1/$2)

$$(eval $$(call build-prog-vars,$1,$2,$3))

ifneq "$$($1_$2_NOT_NEEDED)" "YES"
$$(eval $$(call build-prog-helper,$1,$2,$3))
endif
$(call profEnd, build-prog($1,$2,$3))
endef





define build-prog-vars
# $1 = dir
# $2 = distdir
# $3 = GHC stage to use (0 == bootstrapping compiler)

ifeq "$$($1_USES_CABAL)" "YES"
$1_$2_USES_CABAL = YES
endif

ifeq "$$(Windows_Host)" "YES"
$1_$2_WANT_INPLACE_WRAPPER = NO
else ifneq "$$($1_$2_INSTALL_INPLACE)" "YES"
$1_$2_WANT_INPLACE_WRAPPER = NO
else ifeq "$$($1_$2_SHELL_WRAPPER)" "YES"
$1_$2_WANT_INPLACE_WRAPPER = YES
else ifeq "$$(DYNAMIC_GHC_PROGRAMS)" "YES"
$1_$2_WANT_INPLACE_WRAPPER = YES
else
$1_$2_WANT_INPLACE_WRAPPER = NO
endif

ifeq "$$(Windows_Host)" "YES"
$1_$2_WANT_INSTALLED_WRAPPER = NO
else ifneq "$$($1_$2_INSTALL)" "YES"
$1_$2_WANT_INSTALLED_WRAPPER = NO
else ifeq "$$($1_$2_SHELL_WRAPPER)" "YES"
$1_$2_WANT_INSTALLED_WRAPPER = YES
else
$1_$2_WANT_INSTALLED_WRAPPER = NO
endif

$1_$2_depfile_base = $1/$2/build/.depend

ifeq "$$($1_$2_INSTALL_INPLACE)" "NO"
ifneq "$$(CLEANING)" "YES"
$1_$2_INPLACE = $$(error $1_$2 should not be installed inplace, but INPLACE var evaluated)
else
$1_$2_INPLACE =
endif
else
ifneq "$$($$($1_$2_PROGNAME)_INPLACE)" ""
$$(error $$($1_$2_PROGNAME)_INPLACE defined twice)
endif
#
# Where do we install the wrapper and the binary?
#   $$($1_$2_PROGNAME)_INPLACE  The thing we run (script or binary)
#   $1_$2_INPLACE               The binary
#
ifeq "$$($1_$2_TOPDIR)" "YES"
$$($1_$2_PROGNAME)_INPLACE = $$(INPLACE_LIB)/bin/$$($1_$2_PROG)
ifeq "$$($1_$2_WANT_INPLACE_WRAPPER)" "YES"
$1_$2_INPLACE = $$(INPLACE_LIB)/bin/$$($1_$2_PROG).bin
else
$1_$2_INPLACE = $$(INPLACE_LIB)/bin/$$($1_$2_PROG)
endif
else
$$($1_$2_PROGNAME)_INPLACE = $$(INPLACE_BIN)/$$($1_$2_PROG)
ifeq "$$($1_$2_WANT_INPLACE_WRAPPER)" "YES"
$1_$2_INPLACE = $$(INPLACE_LIB)/bin/$$($1_$2_PROG)
else
$1_$2_INPLACE = $$($$($1_$2_PROGNAME)_INPLACE)
endif
endif
endif

endef





define build-prog-helper
# $1 = dir
# $2 = distdir
# $3 = GHC stage to use (0 == bootstrapping compiler)

$(call package-config,$1,$2,$3)

ifeq "$$($1_$2_USES_CABAL)" "YES"
$(call build-package-data,$1,$2,$3)
ifneq "$$(NO_INCLUDE_PKGDATA)" "YES"
ifeq "$3" "0"
include $1/$2/package-data.mk
else ifeq "$(phase)" "final"
include $1/$2/package-data.mk
endif
endif
endif

$(call all-target,$1,all_$1_$2)
$(call all-target,$1_$2,$1/$2/build/tmp/$$($1_$2_PROG))

$(call shell-wrapper,$1,$2)

ifeq "$$($1_$2_PROGRAM_WAY)" ""
ifeq "$3" "0"
$1_$2_PROGRAM_WAY = v
else ifeq "$$(DYNAMIC_GHC_PROGRAMS)" "YES"
$1_$2_PROGRAM_WAY = dyn
else
$1_$2_PROGRAM_WAY = v
endif
endif

$1_$2_WAYS = $$($1_$2_PROGRAM_WAY)

$1_$2_DYNAMIC_TOO = NO

$(call hs-sources,$1,$2)
$(call c-sources,$1,$2)

# --- IMPLICIT RULES

$(call distdir-opts,$1,$2,$3)
$(call distdir-way-opts,$1,$2,$$($1_$2_PROGRAM_WAY),$3)

ifeq "$3" "0"
# For stage 0, we use GHC to compile C sources so that we don't have to
# worry about where the RTS header files are
$(call c-suffix-rules,$1,$2,$$($1_$2_PROGRAM_WAY),YES)
else
ifeq "$$($1_$2_UseGhcForCC)" "YES"
$(call c-suffix-rules,$1,$2,$$($1_$2_PROGRAM_WAY),YES)
else
$(call c-suffix-rules,$1,$2,$$($1_$2_PROGRAM_WAY),NO)
endif
endif

$$(foreach dir,$$($1_$2_HS_SRC_DIRS),\
  $$(eval $$(call hs-suffix-rules-srcdir,$1,$2,$$(dir))))
$(call hs-suffix-way-rules,$1,$2,$$($1_$2_PROGRAM_WAY))

$(call c-objs,$1,$2,$$($1_$2_PROGRAM_WAY))
$(call hs-objs,$1,$2,$$($1_$2_PROGRAM_WAY))

$1_$2_LINK_WITH_GCC = NO

ifeq "$$($1_$2_$$($1_$2_PROGRAM_WAY)_HS_OBJS)" ""
# We don't want to link the GHC RTS into C-only programs. There's no
# point, and it confuses the test that all GHC-compiled programs
# were compiled with the right GHC.
$1_$2_$$($1_$2_PROGRAM_WAY)_GHC_LD_OPTS += -no-auto-link-packages -no-hs-main
endif

ifneq "$$(BINDIST)" "YES"

# The quadrupled $'s here are because the _<way>_LIB variables aren't
# necessarily set when this part of the makefile is read
#
# See Note [inconsistent distdirs] in rules/build-package-way.mk for why
# we are computing the dist-dir from the GHC stage and not just using
# the distdir parameter.
$1/$2/build/tmp/$$($1_$2_PROG) $1/$2/build/tmp/$$($1_$2_PROG).dll : \
    $$(foreach dep,$$($1_$2_TRANSITIVE_DEP_COMPONENT_IDS),\
        $$$$($$(dep)_dist-$(if $(filter 0,$3),boot,install)_PROGRAM_DEP_LIB))
# Workaround: We use TRANSITIVE_DEP_COMPONENT_IDS here as a workaround for
# #12078.

$1_$2_PROG_NEEDS_C_WRAPPER = NO
$1_$2_PROG_INPLACE = $$($1_$2_PROG)
ifeq "$$(Windows_Host) $$($1_$2_PROGRAM_WAY)" "YES dyn"
ifneq "$$($1_$2_HS_SRCS)" ""
$1_$2_PROG_NEEDS_C_WRAPPER = YES
$1_$2_PROG_INPLACE = inplace-$$($1_$2_PROG)
endif
endif

ifeq "$$($1_$2_PROG_NEEDS_C_WRAPPER)" "YES"

$1_$2_RTS_OPTS_FLAG = $$(lastword $$(filter -rtsopts -rtsopts=all -rtsopts=some -rtsopts=none -no-rtsopts,$$($1_$2_$$($1_$2_PROGRAM_WAY)_ALL_HC_OPTS)))
ifeq "$$($1_$2_RTS_OPTS_FLAG)" "-rtsopts"
$1_$2_RTS_OPTS = RtsOptsAll
else ifeq "$$($1_$2_RTS_OPTS_FLAG)" "-rtsopts=all"
$1_$2_RTS_OPTS = RtsOptsAll
else ifeq "$$($1_$2_RTS_OPTS_FLAG)" "-rtsopts=some"
$1_$2_RTS_OPTS = RtsOptsSafeOnly
else ifeq "$$($1_$2_RTS_OPTS_FLAG)" "-rtsopts=none"
$1_$2_RTS_OPTS = RtsOptsNone
else ifeq "$$($1_$2_RTS_OPTS_FLAG)" "-no-rtsopts"
$1_$2_RTS_OPTS = RtsOptsNone
else
$1_$2_RTS_OPTS = RtsOptsSafeOnly
endif

$1/$2/build/tmp/$$($1_$2_PROG)-inplace-wrapper.c: driver/utils/dynwrapper.c | $$$$(dir $$$$@)/.
	$$(call removeFiles,$$@)
	echo '#include <windows.h>' >> $$@
	echo '#include "Rts.h"' >> $$@
	echo 'LPTSTR path_dirs[] = {' >> $$@
	$$(foreach d,$$($1_$2_DEP_LIB_REL_DIRS),$$(call make-command,echo '    TEXT("/../../$$d")$$(comma)' >> $$@))
	echo '    TEXT("/../../$1/$2/build/tmp/"),' >> $$@
	echo '    NULL};' >> $$@
	echo 'LPTSTR progDll = TEXT("../../$1/$2/build/tmp/$$($1_$2_PROG).dll");' >> $$@
	echo 'LPTSTR rtsDll = TEXT("$$($$(WINDOWS_DYN_PROG_RTS))");' >> $$@
	echo 'int rtsOpts = $$($1_$2_RTS_OPTS);' >> $$@
	cat driver/utils/dynwrapper.c >> $$@

$1/$2/build/tmp/$$($1_$2_PROG)-wrapper.c: driver/utils/dynwrapper.c | $$$$(dir $$$$@)/.
	$$(call removeFiles,$$@)
	echo '#include <windows.h>' >> $$@
	echo '#include "Rts.h"' >> $$@
	echo 'LPTSTR path_dirs[] = {' >> $$@
	$$(foreach p,$$($1_$2_TRANSITIVE_DEP_COMPONENT_IDS),$$(call make-command,echo '    TEXT("/../lib/$$p")$$(comma)' >> $$@))
	echo '    TEXT("/../lib/"),' >> $$@
	echo '    NULL};' >> $$@
	echo 'LPTSTR progDll = TEXT("../lib/$$($1_$2_PROG).dll");' >> $$@
	echo 'LPTSTR rtsDll = TEXT("$$($$(WINDOWS_DYN_PROG_RTS))");' >> $$@
	echo 'int rtsOpts = $$($1_$2_RTS_OPTS);' >> $$@
	cat driver/utils/dynwrapper.c >> $$@

$1/$2/build/tmp/$$($1_$2_PROG_INPLACE) : $1/$2/build/tmp/$$($1_$2_PROG)-inplace-wrapper.c $1/$2/build/tmp/$$($1_$2_PROG).dll | $$$$(dir $$$$@)/.
	$$(call cmd,$1_$2_HC) -no-hs-main -no-auto-link-packages -optc-g -optc-O0 $$< -o $$@

$1/$2/build/tmp/$$($1_$2_PROG) : $1/$2/build/tmp/$$($1_$2_PROG)-wrapper.c $1/$2/build/tmp/$$($1_$2_PROG).dll | $$$$(dir $$$$@)/.
	$$(call cmd,$1_$2_HC) -no-hs-main -no-auto-link-packages -optc-g -optc-O0 $$< -o $$@

$1/$2/build/tmp/$$($1_$2_PROG).dll : $$($1_$2_$$($1_$2_PROGRAM_WAY)_HS_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_C_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_CXX_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_S_OBJS) $$($1_$2_OTHER_OBJS) | $$$$(dir $$$$@)/.
	$$(call build-dll,$1,$2,$$($1_$2_PROGRAM_WAY),,$$($1_$2_$$($1_$2_PROGRAM_WAY)_HS_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_C_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_CXX_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_S_OBJS) $$($1_$2_OTHER_OBJS),$$@)
else # $1_$2_PROG_NEEDS_C_WRAPPER=NO
ifeq "$$($1_$2_LINK_WITH_GCC)" "NO"
$1/$2/build/tmp/$$($1_$2_PROG) : $$($1_$2_$$($1_$2_PROGRAM_WAY)_HS_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_C_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_CXX_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_S_OBJS) $$($1_$2_OTHER_OBJS) | $$$$(dir $$$$@)/.
	$$(call cmd,$1_$2_HC) -o $$@ $$($1_$2_$$($1_$2_PROGRAM_WAY)_ALL_HC_OPTS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_GHC_LD_OPTS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_HS_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_C_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_CXX_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_S_OBJS) $$($1_$2_OTHER_OBJS) $$(addprefix -l,$$($1_$2_EXTRA_LIBRARIES))

else
$1/$2/build/tmp/$$($1_$2_PROG) : $$($1_$2_$$($1_$2_PROGRAM_WAY)_HS_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_C_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_CXX_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_S_OBJS) $$($1_$2_OTHER_OBJS) | $$$$(dir $$$$@)/.
	$$(call cmd,$1_$2_CC) -o $$@ $$($1_$2_$$($1_$2_PROGRAM_WAY)_ALL_CC_OPTS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_ALL_LD_OPTS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_HS_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_C_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_CXX_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_S_OBJS) $$($1_$2_OTHER_OBJS) $$($1_$2_$$($1_$2_PROGRAM_WAY)_EXTRA_CC_OPTS) $$(addprefix -l,$$($1_$2_EXTRA_LIBRARIES))
endif
endif # $1_$2_PROG_NEEDS_C_WRAPPER

# Note [lib-depends]
# ~~~~~~~~~~~~~~~~~~
# If this program is built with stage1 or greater, we
# need to depend on the libraries too.  NB. since $(ALL_STAGE1_LIBS) and
# $(ALL_RTS_LIBS) are not defined until after libraries/*/ghc.mk have
# been included, this introduces an ordering dependency.
ifneq "$$(CLEANING)" "YES"
ifneq "$3" "0"
ifneq "$$($1_$2_HS_SRCS)" ""
ifeq "$$(strip $$(ALL_STAGE1_$$($1_$2_PROGRAM_WAY)_LIBS))" ""
$$(error ordering failure in $1 ($2): ALL_STAGE1_$$($1_$2_PROGRAM_WAY)_LIBS is empty)
endif
$1/$2/build/tmp/$$($1_$2_PROG) : $$(ALL_STAGE1_$$($1_$2_PROGRAM_WAY)_LIBS) $$(ALL_RTS_LIBS)
endif
endif
endif

ifeq "$$($1_$2_INSTALL_INPLACE)" "YES"
$$($1_$2_INPLACE) : $1/$2/build/tmp/$$($1_$2_PROG_INPLACE) | $$$$(dir $$$$@)/.
	$$(INSTALL) -m 755 $$< $$@
endif

endif # BINDIST

ifneq "$$($1_$2_INSTALL_INPLACE)" "NO"
$(call all-target,$1_$2,$$($1_$2_INPLACE))
endif
$(call clean-target,$1,$2_inplace,$$($1_$2_INPLACE))

ifeq "$$($1_$2_INSTALL)" "YES"
ifeq "$$($1_$2_PROG_NEEDS_C_WRAPPER)" "YES"
INSTALL_LIBS     += $1/$2/build/tmp/$$($1_$2_PROG).dll
endif
ifeq "$$($1_$2_WANT_INSTALLED_WRAPPER)" "YES"
INSTALL_LIBEXECS += $1/$2/build/tmp/$$($1_$2_PROG)
else ifeq "$$($1_$2_TOPDIR)" "YES"
INSTALL_LIBEXECS += $1/$2/build/tmp/$$($1_$2_PROG)
else
INSTALL_BINS     += $1/$2/build/tmp/$$($1_$2_PROG)
endif
endif

$(call dependencies,$1,$2,$3)

# The Main module of a program implicitly depends on GHC.TopHandler
# so we need to add a dependency for that. As we don't know which
# module contains Main, we just make all modules in the program
# depend on it.
#
# See Note [inconsistent distdirs] in rules/build-package-way.mk for why
# we hard-code dist-install; GHC will use stage2/stage3 here so we
# cannot use the distdir parameter.
ifneq "$3" "0"
$$(foreach o,$$($1_$2_$$($1_$2_PROGRAM_WAY)_HS_OBJS),$$(eval $$(call add-dependency,$$o,libraries/base/dist-install/build/GHC/TopHandler.$$($$($1_$2_PROGRAM_WAY)_osuf))))
endif

endef