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