forked from chipsalliance/synlig
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Makefile
executable file
·436 lines (349 loc) · 13.5 KB
/
Makefile
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
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
#!/usr/bin/env -S sh -c '/usr/bin/env make -j$(nproc) -rR -Oline -f "$0" "$@"'
#--------------------------------------------------------------------------------
# Setup make itself.
.ONESHELL:
SHELL := bash
override .SHELLFLAGS := -e -u -o pipefail -O nullglob -O extglob -O globstar -c
# Unset all default build- and recipe-related variables.
# Since this is exactly what `-R` make flag does don't bother if it is set.
override letter_makeflags := $(filter-out -%,$(firstword ${MAKEFLAGS}))
ifeq ($(findstring R,${l.letter_makeflags}),)
$(foreach v,$(filter-out MAKE% GNUMAKE% .%,$(.VARIABLES)), \
$(if $(filter default,$(origin ${v})), \
$(eval override undefine ${v}) \
) \
)
SUFFIXES :=
endif
override undefine letter_makeflags
#--------------------------------------------------------------------------------
# Detect build type.
CFG_BUILD_TYPE := release
ifneq ($(filter install@asan build@asan,${MAKECMDGOALS}),)
CFG_BUILD_TYPE := asan
ENABLE_ASAN := 1
endif
ifneq ($(filter plugin,${MAKECMDGOALS}),)
CFG_BUILD_TYPE := plugin
endif
ifneq ($(filter install@pysynlig build@pysynlig,${MAKECMDGOALS}),)
CFG_BUILD_TYPE := pysynlig
endif
#--------------------------------------------------------------------------------
# Load config.
override TOP_DIR := $(dir $(abspath $(lastword ${MAKEFILE_LIST})))
include ${TOP_DIR}buildconfig.mk
#--------------------------------------------------------------------------------
# Convert path from relative to absolute (assuming `${2}` or `${TOP_DIR}` as
# the base).
#
# ${1}: List of paths.
# ${2}: Base directory for relative paths. Optional, `${TOP_DIR}` if missing.
ToAbsPaths = $(strip $(foreach p,$(strip ${1}),\
$(patsubst //,/,$(abspath $(or \
$(filter /%,${p}), \
$(or $(strip ${2}),${TOP_DIR})${p} \
))$(if $(filter %/ %/.. %/.,${p}),/))\
))
# Convert path from relative to absolute (assuming `${2}` or `${TOP_DIR}` as
# the base) and add trailing `/` if not already present.
#
# ${1}: List of directory paths.
# ${2}: Base directory for relative paths. Optional, `${TOP_DIR}` if missing.
ToAbsDirPaths = $(call ToAbsPaths,$(addsuffix /,$(strip ${1})),${2})
ShQuote = '$(subst ${C.QUOT},'\'',$(strip ${1}))'
ShQuoteList = $(foreach v,$(strip ${1}),$(call ShQuote,$v))
#--------------------------------------------------------------------------------
# Make sure internal variables are not overridden through command line.
# Special variables are those with at least one lowercase letter in the name.
# We could use `override` everywhere, but that's quite verbose.
override command_line_illegal_vars := $(strip $(foreach v,${.VARIABLES},\
$(if $(filter command_line,$(subst ${C.SP},_,$(origin ${v}))),${v})\
))
override command_line_illegal_vars := $(shell \
for f in $(call ShQuoteList,${command_line_illegal_vars}); do \
[[ "$$f" =~ ^[A-Z][A-Z0-9_]*$$ ]] || echo "$$f"; \
done;\
)
ifdef command_line_illegal_vars
override define error_message :=
ERROR${C.DC} Overridding internal variables through make${C.QUOT}s command line is prohibited.
Overriden variables${C.DC}
$(subst ${C.NL}${C.SP},${C.NL},$(foreach v,${command_line_illegal_vars},- ${v} $(if $(filter simple,$(flavor ${v})),:=,=) ${${v}}${C.NL}))
..
endef
$(error ${error_message})
endif
override undefine command_line_illegal_vars
#--------------------------------------------------------------------------------
# Validate configuration variable values and assign them to variables without
# `CFG_` prefix used internally.
override ALL_ALLOWED_BUILD_TYPES := release asan plugin pysynlig
$(if $(filter-out 1,$(words $(filter ${ALL_ALLOWED_BUILD_TYPES},${CFG_BUILD_TYPE}))),\
$(error CFG_BUILD_TYPE: invalid value (${CFG_BUILD_TYPE}). Must be one of: ${ALL_ALLOWED_BUILD_TYPES})\
)
override BUILD_TYPE := ${CFG_BUILD_TYPE}
_cfg_build_type := $(value CFG_BUILD_TYPE)
_cfg_build_type_eq := $(if $(filter recursive,$(flavor CFG_BUILD_TYPE)),=,:=)
override BUILD_DIR := $(call ToAbsDirPaths,${CFG_BUILD_DIR})
# Resolve BUILD_DIR with CFG_BUILD_TYPE set to space to get common path prefix for
# each build type.
override CFG_BUILD_TYPE = ${C.SP}
override build_dir_common_parent := $(call ToAbsDirPaths,$(dir $(firstword ${CFG_BUILD_DIR})))
ifeq (${build_dir_common_parent},${BUILD_DIR})
# BUILD_DIR does not depend on CFG_BUILD_TYPE. Do not create "current" symlink.
override undefine build_dir_current_symlink
else
# Resolve BUILD_DIR with CFG_BUILD_TYPE set to "current" and remove common prefix
# to get "common" symlink path
override CFG_BUILD_TYPE = current
override build_dir_current_symlink := $(patsubst %/,%,$(call ToAbsDirPaths,${CFG_BUILD_DIR}))
# Calculate relative symlink target
override build_dir_current_symlink_target := $(firstword $(subst /,${C.SP},$(patsubst ${build_dir_common_parent}%,%,${BUILD_DIR})))
endif
override undefine CFG_BUILD_TYPE
$(eval CFG_BUILD_TYPE ${_cfg_build_type_eq} ${_cfg_build_type})
override OUT_DIR := $(call ToAbsDirPaths,${CFG_OUT_DIR})
# Resolve OUT_DIR with CFG_BUILD_TYPE set to space to get common path prefix for
# each build type.
override CFG_BUILD_TYPE = ${C.SP}
override out_dir_common_parent := $(call ToAbsDirPaths,$(dir $(firstword ${CFG_OUT_DIR})))
ifeq (${out_dir_common_parent},${OUT_DIR})
# OUT_DIR does not depend on CFG_BUILD_TYPE. Do not create "current" symlink.
override undefine out_dir_current_symlink
else
# Resolve OUT_DIR with CFG_BUILD_TYPE set to "current" and remove common prefix
# to get "common" symlink path
override CFG_BUILD_TYPE = current
override out_dir_current_symlink := $(patsubst %/,%,$(call ToAbsDirPaths,${CFG_OUT_DIR}))
# Calculate relative symlink target
override out_dir_current_symlink_target := $(firstword $(subst /,${C.SP},$(patsubst ${out_dir_common_parent}%,%,${OUT_DIR})))
endif
override undefine CFG_BUILD_TYPE
$(eval CFG_BUILD_TYPE ${_cfg_build_type_eq} ${_cfg_build_type})
override undefine _cfg_build_type
override undefine _cfg_build_type_eq
# Set derived constants
override BUILD_DIR := ${CFG_BUILD_DIR}
override OUT_DIR := ${CFG_OUT_DIR}
GetTargetBuildDir = $(call ToAbsPaths,${BUILD_DIR}${1}/)
# Export non-empty tool-related variables
tool_related_variables := CC CXX LD CPPFLAGS CXXFLAGS LDFLAGS LDLIBS MAKE
$(foreach v,${tool_related_variables},$(if ${${v}},$(eval export ${v})))
#--------------------------------------------------------------------------------
# Print table with date and configuration.
# Skip this for informational targets.
ifneq ($(filter-out list help,${MAKECMDGOALS}),)
variables_to_dump := \
CFG_BUILD_TYPE \
CFG_BUILD_DIR \
CFG_OUT_DIR \
CC \
CXX \
LD \
CPPFLAGS \
CXXFLAGS \
LDFLAGS \
LDLIBS
# Measuring variable name + ":"
longest_variable_len := $(shell printf '%s:\n' $(call ShQuoteList,${variables_to_dump}) | wc -L)
$(info -)
$(info | $(shell printf '%-${longest_variable_len}s\t%s' 'Date:' "$$(date --iso-8601=seconds)"))
$(info |)
$(foreach v,${variables_to_dump},\
$(info | $(shell \
printf '%-${longest_variable_len}s\t%s' $(call ShQuote,${v}:) $(call ShQuote,${${v}})\
))\
)
$(info -)
undefine longest_variable_len
undefine variables_to_dump
endif
#--------------------------------------------------------------------------------
# Check whether build configuration changed, and warn if so.
# Skip this for targets that do not build anything.
ifneq ($(filter-out list clean help,${MAKECMDGOALS}),)
define buildconfig_state_file_content :=
CFG_BUILD_TYPE:=${BUILD_TYPE}
CC:=${CC}
CXX:=${CXX}
LD:=${LD}
CPPFLAGS:=${CPPFLAGS}
CXXFLAGS:=${CXXFLAGS}
LDFLAGS:=${LDFLAGS}
LDLIBS:=${LDLIBS}
endef
buildconfig_state_file := $(wildcard ${BUILD_DIR}buildconfig)
ifdef buildconfig_state_file
$(file >${buildconfig_state_file}.new,${buildconfig_state_file_content}${C.NL})
config_changed := $(shell cmp ${buildconfig_state_file} ${buildconfig_state_file}.new || echo 1)
ifdef config_changed
$(shell mv ${buildconfig_state_file} ${buildconfig_state_file}.old)
$(shell cd ${BUILD_DIR}; diff -tu buildconfig.old buildconfig.new > ${BUILD_DIR}.buildconfig.diff)
define warning_message :=
WARNING${C.DC} Build configuration for the build directory changed!
It is recommended to interrupt this build and clean the directory with:
${MAKE} CFG_BUILD_DIR:=${BUILD_DIR} clean
Configuration diff:
--------------------------------------------------------------------------------
$(file <${BUILD_DIR}.buildconfig.diff)
--------------------------------------------------------------------------------
This message won't be shown again. The original buildconfig file has been moved to:
${buildconfig_state_file}.old
endef
$(shell rm ${BUILD_DIR}.buildconfig.diff)
$(warning ${warning_message})
undefine warning_message
endif
$(shell cp ${buildconfig_state_file}.new ${buildconfig_state_file})
undefine config_changed
else
buildconfig_state_file := ${BUILD_DIR}buildconfig
$(shell mkdir -p ${BUILD_DIR})
$(file >${buildconfig_state_file},${buildconfig_state_file_content}${C.NL})
endif
undefine buildconfig_state_file_content
undefine buildconfig_state_file
endif
#--------------------------------------------------------------------------------
# Set the linker flag
#
ifneq (${LD},ld)
USE_LD_FLAG = -fuse-ld=${LD}
endif
#--------------------------------------------------------------------------------
# Include module-makefiles
GetTargetStructName = target[${1}]
makefiles_to_include := \
src/Build.synlig.mk \
third_party/Build.*.mk \
src/frontends/*/Build.mk \
tests/*/Build.mk \
lib/*/Build.mk
$(foreach THIS_BUILD_MK,$(wildcard $(call ToAbsPaths,${makefiles_to_include})),\
$(eval include ${THIS_BUILD_MK})\
)
#--------------------------------------------------------------------------------
# Create common targets
_GetTargetsList = $(patsubst $(call GetTargetStructName,%).${1},%,$(filter $(call GetTargetStructName,%).${1},${.VARIABLES}))
GetTargetsList = $(call _GetTargetsList,$(or $(strip ${1}),output_files))
.PHONY: list
list :
@:
printf '${F.B}Common targets${F.!B}\n\n'
printf ' %s\n' \
'list ${F.D}|${F.!D} help' \
'build' \
'install' \
'clean' \
'tools' \
'plugin' \
;
echo
printf '${F.B}Common component targets${F.!B} (`${F.I}component${F.!I}` is a component name placeholder)\n\n'
printf ' %s\n' \
'build@${F.I}component${F.!I}' \
'install@${F.I}component${F.!I} ${F.D}|${F.!D} @${F.I}component${F.!I}' \
'clean@${F.I}component${F.!I}' \
;
echo
printf '${F.B}Component sources cleanup targets${F.!B}\n\n'
printf ' %s\n' $(call ShQuoteList,$(addprefix srcclean@,$(call GetTargetsList,src_clean_command)))
echo
printf '${F.B}Available components${F.!B}\n\n'
printf ' %s\n' $(call ShQuoteList,${GetTargetsList})
echo
.PHONY: help
help : list
.PHONY: build
build : build@surelog build@synlig
.PHONY: install
install : install@synlig
.PHONY: build-plugin
build-plugin : build@surelog build@yosys build@systemverilog-plugin
.PHONY: install-plugin
install-plugin : build@surelog install@yosys install@systemverilog-plugin
#####################################################
# WARNING #
# Using synlig as yosys plugin is deprecated. It is #
# recommended to build synlig as standalone binary. #
#####################################################
.PHONY: plugin
plugin : build-plugin
.PHONY: build@asan
build@asan : build
.PHONY: install@asan
install@asan : install
.PHONY: build@pysynlig
build@pysynlig : build
.PHONY: install@pysynlig
install@pysynlig : install
install@eqy: ${OUT_DIR}/bin/synlig-config ${TOP_DIR}/third_party/eqy/.git
install@sby: ${OUT_DIR}/bin/synlig-config ${TOP_DIR}/third_party/sby/.git
install@sv2v: ${TOP_DIR}/third_party/sv2v/.git
.PHONY: tools
tools: install@eqy install@sby install@sv2v install@yosys-tools
.PHONY: clean
clean : $(foreach t,${GetTargetsList},$(if ${$(call GetTargetStructName,${t}).src_clean_command},srcclean@${t}))
@:
if [[ -e ${BUILD_DIR}buildconfig ]]; then
rm -rf ${BUILD_DIR}
fi
#--------------------------------------------------------------------------------
# Create component targets
# Skip this for informational targets.
ifneq ($(filter-out list help,${MAKECMDGOALS}),)
$(sort $(foreach v,$(filter $(call GetTargetStructName,%).output_dirs,${.VARIABLES}),${${v}})) :
@mkdir -p $@
override define _single_target_rules
.PHONY: @${t}
@${t} : install@${t}
.PHONY: build@${t}
build@${t} : ${${ts}.output_files}
.PHONY: install@${t}
install@${t} : private t := ${t}
install@${t} : private ts := ${ts}
install@${t} : build@${t}
ifdef ${ts}.install_command
+@${${ts}.install_command}
else
$(foreach srcdst,${${ts}.install_copy_list},\
$(foreach src,$(word 1,$(subst :,${C.SP},${srcdst})),\
$(foreach dst,$(call ToAbsPaths,${OUT_DIR}$(word 2,$(subst :,${C.SP},${srcdst}))),\
$(if $(filter %/,${dst}),mkdir -p ${dst}${C.NL})\
cp -ar ${src} ${dst}${C.NL}\
)\
)\
)
endif
.PHONY: clean@${t}
clean@${t} : private t := ${t}
clean@${t} :
rm -rf $(call ShQuote,$(call GetTargetBuildDir,${t}))
ifdef ${ts}.rules
${${ts}.output_files} &: private t := ${t}
${${ts}.output_files} &: private ts := ${ts}
$(eval $(value ${ts}.rules))
endif
ifdef ${ts}.build_command
${${ts}.output_files} &: private t := ${t}
${${ts}.output_files} &: private ts := ${ts}
${${ts}.output_files} &: ${${ts}.input_files} | ${${ts}.output_dirs}
+@${${ts}.build_command}
endif
ifdef ${ts}.src_clean_command
.PHONY: srcclean@${t}
srcclean@${t} : private t := ${t}
srcclean@${t} : private ts := ${ts}
srcclean@${t} :
+${${ts}.src_clean_command}
clean@${t} : srcclean@${t}
endif
endef
$(foreach t,${GetTargetsList},$(foreach ts,$(call GetTargetStructName,${t}),$(eval $(value _single_target_rules))))
endif
#--------------------------------------------------------------------------------
# Add Yosys patches target
include ${TOP_DIR}/src/yosys_patches/Makefile.inc
build@synlig: apply_yosys_patches
build@yosys: apply_yosys_patches