-
Notifications
You must be signed in to change notification settings - Fork 11
/
Makefile
326 lines (280 loc) · 10.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
libhw-dir := $(dir $(lastword $(MAKEFILE_LIST)))
DESTDIR ?= dest
name ?= hw
hw-install = Makefile Makefile.proof debug.adc gnat.adc spark.adc
top := $(CURDIR)
cnf := .config
obj := build
link-type ?= archive
ifeq ($(link-type),archive)
prefixed-name ?= lib$(name)
binary-suffix ?= .a
else ifeq ($(link-type),program)
prefixed-name ?= $(name)
binary-suffix ?=
endif
binary := $(obj)/$(prefixed-name)$(binary-suffix)
$(binary):
space :=
space := $(space) $(space)
comma := ,
strip_quotes = $(strip $(subst ",,$(1)))
# fix syntax highlighting with an odd emoticon "))
$(foreach dep,$($(name)-deplibs), \
$(eval -include $($(dep)-dir)/config))
-include $(cnf)
include $(libhw-dir)/Makefile.proof
ifeq ($(DEBUG),1)
gnat-adc = $(libhw-dir)/debug.adc
else
gnat-adc = $(libhw-dir)/gnat.adc
endif
CC = $(CROSS_COMPILE)gcc
GNATBIND = $(CROSS_COMPILE)gnatbind
GCC_MAJOR = $(shell echo __GNUC__ | $(CC) -E - 2>/dev/null | tail -1)
CFLAGS += -Wuninitialized -Wall -Werror
CFLAGS += -pipe -g
CFLAGS += -Wstrict-aliasing -Wshadow
CFLAGS += -fno-common -fomit-frame-pointer
CFLAGS += -ffunction-sections -fdata-sections
ADAFLAGS += $(CFLAGS) -gnatA -gnatec=$(gnat-adc) -gnatp
# Ada warning options:
#
# a Activate most optional warnings.
# .e Activate every optional warnings.
# e Treat warnings and style checks as errors.
#
# D Suppress warnings on implicit dereferences:
# As SPARK does not accept access types we have to map the
# dynamically chosen register locations to a static SPARK
# variable.
#
# .H Suppress warnings on holes/gaps in records:
# We are modelling hardware here!
#
# H Suppress warnings on hiding:
# It's too annoying, you run out of ideas for identifiers fast.
#
# _R Suppress warnings for out-of-order record representation clauses:
# We reorder fields on purpose.
#
# T Suppress warnings for tracking of deleted conditional code:
# We use static options to select code paths at compile time.
#
# U Suppress warnings on unused entities:
# Would have lots of warnings for unused register definitions,
# `withs` for debugging etc.
#
# .U Deactivate warnings on unordered enumeration types:
# As SPARK doesn't support `pragma Ordered` by now, we don't
# use that, yet.
#
# .W Suppress warnings on unnecessary Warnings Off pragmas:
# Things get really messy when you use different compiler
# versions, otherwise.
# .Y Disable information messages for why package spec needs body:
# Those messages are annoying. But don't forget to enable those,
# if you need the information.
ADAFLAGS += -gnatwa.eeD.HHTU.U.W.Y
ADAFLAGS += $(if $(filter 10,$(GCC_MAJOR)),-gnatw_R)
# Disable style checks for now
ADAFLAGS += -gnatyN
MAKEFLAGS += -rR
# Make is silent per default, but 'make V=1' will show all compiler calls.
ifneq ($(V),1)
.SILENT:
endif
# must come rather early
.SECONDEXPANSION:
ifeq ($(link-type),archive)
$(binary): $$($(name)-objs)
@printf " AR $(subst $(obj)/,,$@)\n"
ar cr $@ $^
else ifeq ($(link-type),program)
$(binary): $$($(name)-objs)
@printf " LINK $(subst $(obj)/,,$@)\n"
$(CC) -o $@ $^ \
$(addprefix -L,$(abspath $($(name)-extra-objs))) \
$(addprefix -l,$(patsubst lib%,%,$($(name)-deplibs))) \
-lgnat
endif
$(foreach dep,$($(name)-deplibs), \
$(eval $(name)-extra-objs += $($(dep)-dir)/lib) \
$(eval $(name)-extra-incs += $($(dep)-dir)/include))
# Converts one or more source file paths to their corresponding build/ paths.
# Only .ads and .adb get converted to .o, other files keep their names.
# $1 file path (list)
src-to-obj = \
$(addprefix $(obj)/,\
$(patsubst $(obj)/%,%, \
$(patsubst %.c,%.o,\
$(patsubst %.ads,%.o,\
$(patsubst %.adb,%.o,\
$(2))))))
# Converts one or more source file paths to the corresponding build/ paths
# of their Ada library information (.ali) files.
# $1 file path (list)
src-to-ali = \
$(addprefix $(obj)/,\
$(patsubst $(obj)/%,%, \
$(patsubst %.ads,%.ali,\
$(patsubst %.adb,%.ali,\
$(filter %.ads %.adb,$(2))))))
# Clean -y variables, include Makefile.inc
# Add paths to files in $(name)-y to $(name)-srcs
# Add subdirs-y to subdirs
# $1 dir to read Makefile.inc from
includemakefile = \
$(eval $(name)-y :=) \
$(eval $(name)-main-y :=) \
$(eval $(name)-gen-y :=) \
$(eval $(name)-proof-y :=) \
$(eval subdirs-y :=) \
$(eval include $(1)/Makefile.inc) \
$(eval $(name)-main-src += \
$(subst $(top)/,, \
$(abspath $(patsubst $(1)//%,/%,$(addprefix $(1)/,$($(name)-main-y)))))) \
$(eval $(name)-srcs += \
$(subst $(top)/,, \
$(abspath $(patsubst $(1)//%,/%,$(addprefix $(1)/,$($(name)-y)))))) \
$(eval $(name)-gens += \
$(subst $(top)/,, \
$(abspath $($(name)-gen-y)))) \
$(eval $(name)-proof += \
$(subst $(top)/,, \
$(abspath $(addprefix $(1)/,$($(name)-proof-y))))) \
$(eval subdirs += \
$(subst $(top)/,, \
$(abspath $(addprefix $(1)/,$(subdirs-y))))) \
# For each path in $(subdirs) call includemakefiles
# Repeat until subdirs is empty
evaluate_subdirs = \
$(eval cursubdirs := $(subdirs)) \
$(eval subdirs :=) \
$(foreach dir,$(cursubdirs), \
$(call includemakefile,$(dir))) \
$(if $(subdirs), \
$(call evaluate_subdirs))
# collect all object files eligible for building
subdirs := .
$(call evaluate_subdirs)
$(name)-srcs += $($(name)-main-src)
# Eliminate duplicate mentions of source files
$(name)-srcs := $(sort $($(name)-srcs))
$(name)-gens := $(sort $($(name)-gens))
# For Ada includes
$(name)-ada-dirs := $(sort $(dir $(filter %.ads %.adb,$($(name)-srcs) $($(name)-gens))))
# To track dependencies, we need all Ada specification (.ads) files in
# *-srcs. Extract / filter all specification files that have a matching
# body (.adb) file here (specifications without a body are valid sources
# in Ada).
# $1 source list
filter_extra_specs = \
$(filter \
$(addprefix %/,$(patsubst %.adb,%.ads, \
$(notdir $(filter %.adb,$($(name)-srcs) $($(name)-gens))))), \
$(filter %.ads,$(1)))
$(name)-extra-specs := $(call filter_extra_specs,$($(name)-srcs))
$(name)-srcs := $(filter-out $($(name)-extra-specs),$($(name)-srcs))
$(name)-extra-gens := $(call filter_extra_specs,$($(name)-gens))
$(name)-gens := $(filter-out $($(name)-extra-gens),$($(name)-gens))
$(name)-objs := $(call src-to-obj,,$($(name)-srcs) $($(name)-gens))
$(name)-alis := $(call src-to-ali,,$($(name)-srcs) $($(name)-gens))
# For gnatprove
$(name)-proof-dirs := \
$(sort $(dir $($(name)-proof)) \
$(filter-out ada/% %/ada/%,$($(name)-ada-dirs)))
# For mkdir
alldirs := $(abspath $(dir $(sort $($(name)-objs))))
# Reads dependencies from an Ada library information (.ali) file
# Only basenames (with suffix) are preserved so we have to look the
# paths up in $($(name)-srcs) $($(name)-gens).
# $1 ali file
create_ada_deps = \
$(if $(wildcard $(1)),\
$(filter \
$(addprefix %/,$(shell sed -ne's/^D \([^\t]\+\).*$$/\1/p' $(1) 2>/dev/null)), \
$($(name)-srcs) $($(name)-gens) $($(name)-extra-specs) $($(name)-extra-gens)), \
$($(name)-gens) $($(name)-extra-gens))
# Adds dependency rules
# $1 source file
add_ada_deps = \
$(call src-to-obj,,$(1)): $(1) \
$(call create_ada_deps,$(call src-to-ali,,$(1)))
# Writes a compilation rule for Ada sources
# $1 source type (ads, adb)
# $2 source files (including the colon)
# $3 obj path prefix (including the trailing slash)
# $4 compiler flags (if empty, $(ADAFLAGS) apply)
define add_ada_rule
$(2) $(3)%.o: %.$(1)
@printf " COMPILE $$(subst $(obj)/,,$$@)\n"
$(CC) \
$(if $(4),$(4),$$(ADAFLAGS)) \
$(addprefix -I,$($(name)-ada-dirs) $($(name)-extra-incs)) \
-c -o $$@ $$<
endef
# For sources
$(foreach type,ads adb, \
$(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-srcs))):,$(obj)/)))
$(foreach file,$($(name)-srcs) $($(name)-gens), \
$(eval $(call add_ada_deps,$(file))))
# For generated sources already in $(obj)/
$(foreach type,ads adb, \
$(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-gens))):,)))
# Ali files are generated along with the object file. They need an empty
# recipe for correct updating.
$($(name)-alis): %.ali: %.o ;
# To support complex package initializations, we need to call the
# emitted code explicitly. gnatbind gathers all the calls for us
# and exports them as a procedure $(name)_adainit().
ifeq ($(link-type),archive)
$(name)-bind-dirs := $($(name)-extra-objs)
$(name)-bind-flags := -a -n -L$(name)_ada
$(name)-bind-alis = $(patsubst /%,%,$(subst $(dir $@),,$^))
else ifeq ($(link-type),program)
$(name)-bind-dirs := $(sort $(dir $($(name)-objs))) $($(name)-extra-objs)
$(name)-bind-flags :=
$(name)-bind-alis = $(subst $(dir $@),,$(call src-to-ali,,$($(name)-main-src)))
endif
$(obj)/b__$(prefixed-name).adb: $($(name)-alis)
@printf " BIND $(subst $(obj)/,,$@)\n"
# We have to give gnatbind a simple filename (without leading
# path components) so just cd there.
cd $(dir $@) && \
$(GNATBIND) $(addprefix -aO,$(abspath $($(name)-bind-dirs))) \
$($(name)-bind-flags) -o $(notdir $@) $($(name)-bind-alis)
$(eval $(call add_ada_rule,adb,$(obj)/b__$(prefixed-name).o:,,$(filter-out -gnatec=%,$(ADAFLAGS))))
$(name)-objs += $(obj)/b__$(prefixed-name).o
# Compilation rule for C sources
$(call src-to-obj,,$(filter %.c,$($(name)-srcs))): $(obj)/%.o: %.c
@printf " COMPILE $(subst $(obj)/,,$@)\n"
$(CC) $(CFLAGS) -c -o $@ $<
$(shell mkdir -p $(alldirs))
$(name)-install-srcs = $(sort \
$($(name)-extra-specs) $($(name)-extra-gens) $(filter %.ads,$($(name)-srcs) $($(name)-gens)) \
$(foreach adb,$(filter %.adb,$($(name)-srcs)), \
$(shell grep -q '^U .*\<BN\>' $(call src-to-ali,,$(adb)) 2>/dev/null && echo $(adb))))
$(name)-install-proof = \
$(filter $(addprefix %/,$(notdir $($(name)-install-srcs))),$($(name)-proof)) \
$(filter-out $(addprefix %/,$(notdir $($(name)-proof))),$($(name)-install-srcs))
install: $(binary) $($(name)-alis) $($(name)-gens) $(libgpr)
install -d $(DESTDIR)/lib $(DESTDIR)/include $(DESTDIR)/proof
printf " INSTALL $(subst $(obj)/,,$(binary))\n"
install $(binary) $(DESTDIR)/lib/
$(foreach file,$($(name)-install) $(libgpr), \
printf " INSTALL $(subst $(obj)/,,$(file))\n"; \
install $(file) $(DESTDIR);)
printf " INSTALL $(cnf)\n"
install $(cnf) $(DESTDIR)/config
printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-alis))
install $($(name)-alis) $(DESTDIR)/lib/
printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-srcs))
install $($(name)-install-srcs) $(DESTDIR)/include/
printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-proof))
install $($(name)-install-proof) $(DESTDIR)/proof/
clean::
rm -rf $(obj) $(name).gpr
distclean: clean
rm -rf dest
.PHONY: install clean distclean