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