blob: 2509b58f2005cee0d9441d590a0fabe9e4e95030 [file] [log] [blame]
Nico Huber5e9b1b52016-10-08 22:09:33 +02001libhw-dir := $(dir $(lastword $(MAKEFILE_LIST)))
2
3DESTDIR ?= dest
4
5name ?= hw
6hw-install = Makefile Makefile.proof gnat.adc spark.adc
7
8top := $(CURDIR)
9cnf := .config
10obj := build
11
12binary := $(obj)/lib$(name).a
13$(binary):
14
15space :=
16space +=
17comma := ,
18
19$(foreach dep,$($(name)-deplibs), \
20 $(eval -include $($(dep)-dir)/config))
21-include $(cnf)
22
23include $(libhw-dir)/Makefile.proof
24
25CC = $(CROSS_COMPILE)gcc
26GNATBIND = $(CROSS_COMPILE)gnatbind
27
28ADAFLAGS += -gnatA -gnatec=$(libhw-dir)/gnat.adc
29ADAFLAGS += -gnatg -gnatp
30ADAFLAGS += -Wuninitialized -Wall -Werror
31ADAFLAGS += -pipe -g
32ADAFLAGS += -Wstrict-aliasing -Wshadow
33ADAFLAGS += -fno-common -fomit-frame-pointer
34ADAFLAGS += -ffunction-sections -fdata-sections
35# Ada warning options:
36#
37# a Activate most optional warnings.
38# .e Activate every optional warnings.
39# e Treat warnings and style checks as errors.
40#
41# D Suppress warnings on implicit dereferences:
42# As SPARK does not accept access types we have to map the
43# dynamically chosen register locations to a static SPARK
44# variable.
45#
46# .H Suppress warnings on holes/gaps in records:
47# We are modelling hardware here!
48#
49# H Suppress warnings on hiding:
50# It's too annoying, you run out of ideas for identifiers fast.
51#
52# T Suppress warnings for tracking of deleted conditional code:
53# We use static options to select code paths at compile time.
54#
55# U Suppress warnings on unused entities:
56# Would have lots of warnings for unused register definitions,
57# `withs` for debugging etc.
58#
59# .U Deactivate warnings on unordered enumeration types:
60# As SPARK doesn't support `pragma Ordered` by now, we don't
61# use that, yet.
62#
63# .W Suppress warnings on unnecessary Warnings Off pragmas:
64# Things get really messy when you use different compiler
65# versions, otherwise.
66# .Y Disable information messages for why package spec needs body:
67# Those messages are annoying. But don't forget to enable those,
68# if you need the information.
69ADAFLAGS += -gnatwa.eeD.HHTU.U.W.Y
70# Disable style checks for now
71ADAFLAGS += -gnatyN
72
73MAKEFLAGS += -rR
74
75# Make is silent per default, but 'make V=1' will show all compiler calls.
76ifneq ($(V),1)
77.SILENT:
78endif
79
80# must come rather early
81.SECONDEXPANSION:
82
83$(binary): $$($(name)-objs)
84 @printf " AR $(subst $(obj)/,,$@)\n"
85 ar cr $@ $^
86
87$(foreach dep,$($(name)-deplibs), \
88 $(eval $(name)-extra-objs += $($(dep)-dir)/lib) \
89 $(eval $(name)-extra-incs += $($(dep)-dir)/include))
90
91# Converts one or more source file paths to their corresponding build/ paths.
92# Only .ads and .adb get converted to .o, other files keep their names.
93# $1 file path (list)
94src-to-obj = \
95 $(addprefix $(obj)/,\
96 $(patsubst $(obj)/%,%, \
97 $(patsubst %.ads,%.o,\
98 $(patsubst %.adb,%.o,\
99 $(2)))))
100
101# Converts one or more source file paths to the corresponding build/ paths
102# of their Ada library information (.ali) files.
103# $1 file path (list)
104src-to-ali = \
105 $(addprefix $(obj)/,\
106 $(patsubst $(obj)/%,%, \
107 $(patsubst %.ads,%.ali,\
108 $(patsubst %.adb,%.ali,\
109 $(filter %.ads %.adb,$(2))))))
110
111# Clean -y variables, include Makefile.inc
112# Add paths to files in $(name)-y to $(name)-srcs
113# Add subdirs-y to subdirs
114# $1 dir to read Makefile.inc from
115includemakefile = \
116 $(eval $(name)-y :=) \
117 $(eval $(name)-gen-y :=) \
118 $(eval $(name)-proof-y :=) \
119 $(eval subdirs-y :=) \
120 $(eval include $(1)/Makefile.inc) \
121 $(eval $(name)-srcs += \
122 $(subst $(top)/,, \
123 $(abspath $(addprefix $(1)/,$($(name)-y))))) \
124 $(eval $(name)-gens += \
125 $(subst $(top)/,, \
126 $(abspath $($(name)-gen-y)))) \
127 $(eval $(name)-proof += \
128 $(subst $(top)/,, \
129 $(abspath $(addprefix $(1)/,$($(name)-proof-y))))) \
130 $(eval subdirs += \
131 $(subst $(top)/,, \
132 $(abspath $(addprefix $(1)/,$(subdirs-y))))) \
133
134# For each path in $(subdirs) call includemakefiles
135# Repeat until subdirs is empty
136evaluate_subdirs = \
137 $(eval cursubdirs := $(subdirs)) \
138 $(eval subdirs :=) \
139 $(foreach dir,$(cursubdirs), \
140 $(call includemakefile,$(dir))) \
141 $(if $(subdirs), \
142 $(call evaluate_subdirs))
143
144# collect all object files eligible for building
145subdirs := .
146$(call evaluate_subdirs)
147
148# Eliminate duplicate mentions of source files
149$(name)-srcs := $(sort $($(name)-srcs))
150$(name)-gens := $(sort $($(name)-gens))
151
152# For Ada includes
153$(name)-ada-dirs := $(sort $(dir $(filter %.ads %.adb,$($(name)-srcs) $($(name)-gens))))
154
155# To track dependencies, we need all Ada specification (.ads) files in
156# *-srcs. Extract / filter all specification files that have a matching
157# body (.adb) file here (specifications without a body are valid sources
158# in Ada).
159$(name)-extra-specs := \
160 $(filter \
161 $(addprefix %/,$(patsubst %.adb,%.ads,$(notdir $(filter %.adb,$($(name)-srcs))))), \
162 $(filter %.ads,$($(name)-srcs) $($(name)-gens)))
163$(name)-srcs := $(filter-out $($(name)-extra-specs),$($(name)-srcs))
164$(name)-gens := $(filter-out $($(name)-extra-specs),$($(name)-gens))
165
166$(name)-objs := $(call src-to-obj,,$($(name)-srcs) $($(name)-gens))
167$(name)-alis := $(call src-to-ali,,$($(name)-srcs) $($(name)-gens))
168
169# For gnatprove
170$(name)-proof-dirs := \
171 $(sort $(dir $($(name)-proof)) \
172 $(filter-out ada/% %/ada/%,$($(name)-ada-dirs)))
173
174# For mkdir
175alldirs := $(abspath $(dir $(sort $($(name)-objs))))
176
177# Reads dependencies from an Ada library information (.ali) file
178# Only basenames (with suffix) are preserved so we have to look the
179# paths up in $($(name)-srcs) $($(name)-gens).
180# $1 ali file
181create_ada_deps = \
182 $(if $(wildcard $(1)),\
183 $(filter \
184 $(addprefix %/,$(shell sed -ne's/^D \([^\t]\+\).*$$/\1/p' $(1) 2>/dev/null)), \
185 $($(name)-srcs) $($(name)-gens) $($(name)-extra-specs)), \
186 $($(name)-gens))
187
188# Adds dependency rules
189# $1 source file
190add_ada_deps = \
191 $(call src-to-obj,,$(1)): $(1) \
192 $(call create_ada_deps,$(call src-to-ali,,$(1)))
193
194# Writes a compilation rule for a source type
195# $1 source type (ads, adb)
196# $2 source files (including the colon)
197# $3 obj path prefix (including the trailing slash)
198define add_ada_rule
199$(2) $(3)%.o: %.$(1)
200 @printf " COMPILE $$(subst $(obj)/,,$$@)\n"
201 $(CC) \
202 $(ADAFLAGS) $(addprefix -I,$($(name)-ada-dirs) $($(name)-extra-incs)) \
203 -c -o $$@ $$<
204endef
205
206# For sources
207$(foreach type,ads adb, \
208 $(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-srcs))):,$(obj)/)))
209$(foreach file,$($(name)-srcs) $($(name)-gens), \
210 $(eval $(call add_ada_deps,$(file))))
211
212# For generated sources already in $(obj)/
213$(foreach type,ads adb, \
214 $(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-gens))):,)))
215
216# Ali files are generated along with the object file. They need an empty
217# recipe for correct updating.
218$($(name)-alis): %.ali: %.o ;
219
220# To support complex package initializations, we need to call the
221# emitted code explicitly. gnatbind gathers all the calls for us
222# and exports them as a procedure $(name)_adainit(). Every stage that
223# uses Ada code has to call it!
224$(obj)/b__lib$(name).adb: $($(name)-alis)
225 @printf " BIND $(subst $(obj)/,,$@)\n"
226 # We have to give gnatbind a simple filename (without leading
227 # path components) so just cd there.
228 cd $(dir $@) && \
229 $(GNATBIND) $(addprefix -aO,$(abspath $($(name)-extra-objs))) \
230 -a -n -L$(name)_ada -o $(notdir $@) \
231 $(subst $(dir $@),,$^)
232$(eval $(call add_ada_rule,adb,$(obj)/b__lib$(name).o:,))
233$(name)-objs += $(obj)/b__lib$(name).o
234
235$(shell mkdir -p $(alldirs))
236
237$(name)-install-srcs = $(sort \
238 $($(name)-extra-specs) $(filter %.ads,$($(name)-srcs)) \
239 $(foreach adb,$(filter %.adb,$($(name)-srcs)), \
240 $(shell grep -q '^U .*\<BN\>' $(call src-to-ali,,$(adb)) 2>/dev/null && echo $(adb))))
241
242$(name)-install-proof = \
243 $(filter $(addprefix %/,$(notdir $($(name)-install-srcs))),$($(name)-proof)) \
244 $(filter-out $(addprefix %/,$(notdir $($(name)-proof))),$($(name)-install-srcs))
245
246install: $(binary) $($(name)-alis) $(libgpr)
247 install -d $(DESTDIR)/lib $(DESTDIR)/include $(DESTDIR)/proof
248 printf " INSTALL $(subst $(obj)/,,$(binary))\n"
249 install $(binary) $(DESTDIR)/lib/
250 $(foreach file,$($(name)-install) $(libgpr), \
251 printf " INSTALL $(subst $(obj)/,,$(file))\n"; \
252 install $(file) $(DESTDIR);)
253 printf " INSTALL $(cnf)\n"
254 install $(cnf) $(DESTDIR)/config
255 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-alis))
256 install $($(name)-alis) $(DESTDIR)/lib/
257 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-srcs))
258 install $($(name)-install-srcs) $(DESTDIR)/include/
259 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-proof))
260 install $($(name)-install-proof) $(DESTDIR)/proof/
261
262clean::
263 rm -rf $(obj) $(name).gpr
264
265distclean: clean
266 rm -rf dest
267
268.PHONY: install clean distclean