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