blob: 359a28c62bbeb5e0130864bf040a0cd96c864f44 [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
Nico Huberf43881f2017-03-05 13:43:20 +010012link-type ?= archive
13
14ifeq ($(link-type),archive)
15prefixed-name ?= lib$(name)
16binary-suffix ?= .a
17else ifeq ($(link-type),program)
18prefixed-name ?= $(name)
19binary-suffix ?=
20endif
21binary := $(obj)/$(prefixed-name)$(binary-suffix)
Nico Huber5e9b1b52016-10-08 22:09:33 +020022$(binary):
23
24space :=
25space +=
26comma := ,
27
Nico Hubercf01ab62017-03-05 23:22:39 +010028strip_quotes = $(strip $(subst ",,$(1)))
29# fix syntax highlighting with an odd emoticon "))
Nico Huberf86fb182016-10-09 20:43:42 +020030
Nico Huber5e9b1b52016-10-08 22:09:33 +020031$(foreach dep,$($(name)-deplibs), \
32 $(eval -include $($(dep)-dir)/config))
33-include $(cnf)
34
35include $(libhw-dir)/Makefile.proof
36
37CC = $(CROSS_COMPILE)gcc
38GNATBIND = $(CROSS_COMPILE)gnatbind
39
Nico Hubere86fff92017-03-04 13:20:37 +010040CFLAGS += -Wuninitialized -Wall -Werror
41CFLAGS += -pipe -g
42CFLAGS += -Wstrict-aliasing -Wshadow
43CFLAGS += -fno-common -fomit-frame-pointer
44CFLAGS += -ffunction-sections -fdata-sections
45
Nico Huber9d5d0252017-03-05 13:37:48 +010046ADAFLAGS += $(CFLAGS) -gnatA -gnatec=$(libhw-dir)/gnat.adc -gnatp
Nico Huber5e9b1b52016-10-08 22:09:33 +020047# Ada warning options:
48#
49# a Activate most optional warnings.
50# .e Activate every optional warnings.
51# e Treat warnings and style checks as errors.
52#
53# D Suppress warnings on implicit dereferences:
54# As SPARK does not accept access types we have to map the
55# dynamically chosen register locations to a static SPARK
56# variable.
57#
58# .H Suppress warnings on holes/gaps in records:
59# We are modelling hardware here!
60#
61# H Suppress warnings on hiding:
62# It's too annoying, you run out of ideas for identifiers fast.
63#
64# T Suppress warnings for tracking of deleted conditional code:
65# We use static options to select code paths at compile time.
66#
67# U Suppress warnings on unused entities:
68# Would have lots of warnings for unused register definitions,
69# `withs` for debugging etc.
70#
71# .U Deactivate warnings on unordered enumeration types:
72# As SPARK doesn't support `pragma Ordered` by now, we don't
73# use that, yet.
74#
75# .W Suppress warnings on unnecessary Warnings Off pragmas:
76# Things get really messy when you use different compiler
77# versions, otherwise.
78# .Y Disable information messages for why package spec needs body:
79# Those messages are annoying. But don't forget to enable those,
80# if you need the information.
81ADAFLAGS += -gnatwa.eeD.HHTU.U.W.Y
82# Disable style checks for now
83ADAFLAGS += -gnatyN
84
85MAKEFLAGS += -rR
86
87# Make is silent per default, but 'make V=1' will show all compiler calls.
88ifneq ($(V),1)
89.SILENT:
90endif
91
92# must come rather early
93.SECONDEXPANSION:
94
Nico Huberf43881f2017-03-05 13:43:20 +010095ifeq ($(link-type),archive)
Nico Huber5e9b1b52016-10-08 22:09:33 +020096$(binary): $$($(name)-objs)
97 @printf " AR $(subst $(obj)/,,$@)\n"
98 ar cr $@ $^
Nico Huberf43881f2017-03-05 13:43:20 +010099else ifeq ($(link-type),program)
100$(binary): $$($(name)-objs)
101 @printf " LINK $(subst $(obj)/,,$@)\n"
102 $(CC) -o $@ $^ \
103 $(addprefix -L,$(abspath $($(name)-extra-objs))) \
104 $(addprefix -l,$(patsubst lib%,%,$($(name)-deplibs))) \
105 -lgnat
106endif
Nico Huber5e9b1b52016-10-08 22:09:33 +0200107
108$(foreach dep,$($(name)-deplibs), \
109 $(eval $(name)-extra-objs += $($(dep)-dir)/lib) \
110 $(eval $(name)-extra-incs += $($(dep)-dir)/include))
111
112# Converts one or more source file paths to their corresponding build/ paths.
113# Only .ads and .adb get converted to .o, other files keep their names.
114# $1 file path (list)
115src-to-obj = \
116 $(addprefix $(obj)/,\
117 $(patsubst $(obj)/%,%, \
Nico Hubere86fff92017-03-04 13:20:37 +0100118 $(patsubst %.c,%.o,\
Nico Huber5e9b1b52016-10-08 22:09:33 +0200119 $(patsubst %.ads,%.o,\
120 $(patsubst %.adb,%.o,\
Nico Hubere86fff92017-03-04 13:20:37 +0100121 $(2))))))
Nico Huber5e9b1b52016-10-08 22:09:33 +0200122
123# Converts one or more source file paths to the corresponding build/ paths
124# of their Ada library information (.ali) files.
125# $1 file path (list)
126src-to-ali = \
127 $(addprefix $(obj)/,\
128 $(patsubst $(obj)/%,%, \
129 $(patsubst %.ads,%.ali,\
130 $(patsubst %.adb,%.ali,\
131 $(filter %.ads %.adb,$(2))))))
132
133# Clean -y variables, include Makefile.inc
134# Add paths to files in $(name)-y to $(name)-srcs
135# Add subdirs-y to subdirs
136# $1 dir to read Makefile.inc from
137includemakefile = \
138 $(eval $(name)-y :=) \
Nico Huberf43881f2017-03-05 13:43:20 +0100139 $(eval $(name)-main-y :=) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200140 $(eval $(name)-gen-y :=) \
141 $(eval $(name)-proof-y :=) \
142 $(eval subdirs-y :=) \
143 $(eval include $(1)/Makefile.inc) \
Nico Huberf43881f2017-03-05 13:43:20 +0100144 $(eval $(name)-main-src += \
145 $(subst $(top)/,, \
146 $(abspath $(patsubst $(1)//%,/%,$(addprefix $(1)/,$($(name)-main-y)))))) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200147 $(eval $(name)-srcs += \
148 $(subst $(top)/,, \
Nico Huber868915f2017-02-13 15:28:58 +0100149 $(abspath $(patsubst $(1)//%,/%,$(addprefix $(1)/,$($(name)-y)))))) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200150 $(eval $(name)-gens += \
151 $(subst $(top)/,, \
152 $(abspath $($(name)-gen-y)))) \
153 $(eval $(name)-proof += \
154 $(subst $(top)/,, \
155 $(abspath $(addprefix $(1)/,$($(name)-proof-y))))) \
156 $(eval subdirs += \
157 $(subst $(top)/,, \
158 $(abspath $(addprefix $(1)/,$(subdirs-y))))) \
159
160# For each path in $(subdirs) call includemakefiles
161# Repeat until subdirs is empty
162evaluate_subdirs = \
163 $(eval cursubdirs := $(subdirs)) \
164 $(eval subdirs :=) \
165 $(foreach dir,$(cursubdirs), \
166 $(call includemakefile,$(dir))) \
167 $(if $(subdirs), \
168 $(call evaluate_subdirs))
169
170# collect all object files eligible for building
171subdirs := .
172$(call evaluate_subdirs)
173
Nico Huberf43881f2017-03-05 13:43:20 +0100174$(name)-srcs += $($(name)-main-src)
175
Nico Huber5e9b1b52016-10-08 22:09:33 +0200176# Eliminate duplicate mentions of source files
177$(name)-srcs := $(sort $($(name)-srcs))
178$(name)-gens := $(sort $($(name)-gens))
179
180# For Ada includes
181$(name)-ada-dirs := $(sort $(dir $(filter %.ads %.adb,$($(name)-srcs) $($(name)-gens))))
182
183# To track dependencies, we need all Ada specification (.ads) files in
184# *-srcs. Extract / filter all specification files that have a matching
185# body (.adb) file here (specifications without a body are valid sources
186# in Ada).
187$(name)-extra-specs := \
188 $(filter \
189 $(addprefix %/,$(patsubst %.adb,%.ads,$(notdir $(filter %.adb,$($(name)-srcs))))), \
190 $(filter %.ads,$($(name)-srcs) $($(name)-gens)))
191$(name)-srcs := $(filter-out $($(name)-extra-specs),$($(name)-srcs))
192$(name)-gens := $(filter-out $($(name)-extra-specs),$($(name)-gens))
193
194$(name)-objs := $(call src-to-obj,,$($(name)-srcs) $($(name)-gens))
195$(name)-alis := $(call src-to-ali,,$($(name)-srcs) $($(name)-gens))
196
197# For gnatprove
198$(name)-proof-dirs := \
199 $(sort $(dir $($(name)-proof)) \
200 $(filter-out ada/% %/ada/%,$($(name)-ada-dirs)))
201
202# For mkdir
203alldirs := $(abspath $(dir $(sort $($(name)-objs))))
204
205# Reads dependencies from an Ada library information (.ali) file
206# Only basenames (with suffix) are preserved so we have to look the
207# paths up in $($(name)-srcs) $($(name)-gens).
208# $1 ali file
209create_ada_deps = \
210 $(if $(wildcard $(1)),\
211 $(filter \
212 $(addprefix %/,$(shell sed -ne's/^D \([^\t]\+\).*$$/\1/p' $(1) 2>/dev/null)), \
213 $($(name)-srcs) $($(name)-gens) $($(name)-extra-specs)), \
214 $($(name)-gens))
215
216# Adds dependency rules
217# $1 source file
218add_ada_deps = \
219 $(call src-to-obj,,$(1)): $(1) \
220 $(call create_ada_deps,$(call src-to-ali,,$(1)))
221
Nico Hubere86fff92017-03-04 13:20:37 +0100222# Writes a compilation rule for Ada sources
Nico Huber5e9b1b52016-10-08 22:09:33 +0200223# $1 source type (ads, adb)
224# $2 source files (including the colon)
225# $3 obj path prefix (including the trailing slash)
Nico Huber78ca5822017-03-05 13:51:49 +0100226# $4 compiler flags (if empty, $(ADAFLAGS) apply)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200227define add_ada_rule
228$(2) $(3)%.o: %.$(1)
229 @printf " COMPILE $$(subst $(obj)/,,$$@)\n"
230 $(CC) \
Nico Huber78ca5822017-03-05 13:51:49 +0100231 $(if $(4),$(4),$(ADAFLAGS)) \
232 $(addprefix -I,$($(name)-ada-dirs) $($(name)-extra-incs)) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200233 -c -o $$@ $$<
234endef
235
236# For sources
237$(foreach type,ads adb, \
238 $(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-srcs))):,$(obj)/)))
239$(foreach file,$($(name)-srcs) $($(name)-gens), \
240 $(eval $(call add_ada_deps,$(file))))
241
242# For generated sources already in $(obj)/
243$(foreach type,ads adb, \
244 $(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-gens))):,)))
245
246# Ali files are generated along with the object file. They need an empty
247# recipe for correct updating.
248$($(name)-alis): %.ali: %.o ;
249
250# To support complex package initializations, we need to call the
251# emitted code explicitly. gnatbind gathers all the calls for us
Nico Huberf43881f2017-03-05 13:43:20 +0100252# and exports them as a procedure $(name)_adainit().
253ifeq ($(link-type),archive)
254$(name)-bind-dirs := $($(name)-extra-objs)
255$(name)-bind-flags := -a -n -L$(name)_ada
256$(name)-bind-alis = $(patsubst /%,%,$(subst $(dir $@),,$^))
257else ifeq ($(link-type),program)
258$(name)-bind-dirs := $(sort $(dir $($(name)-objs))) $($(name)-extra-objs)
259$(name)-bind-flags :=
260$(name)-bind-alis = $(subst $(dir $@),,$(call src-to-ali,,$($(name)-main-src)))
261endif
262$(obj)/b__$(prefixed-name).adb: $($(name)-alis)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200263 @printf " BIND $(subst $(obj)/,,$@)\n"
264 # We have to give gnatbind a simple filename (without leading
265 # path components) so just cd there.
266 cd $(dir $@) && \
Nico Huberf43881f2017-03-05 13:43:20 +0100267 $(GNATBIND) $(addprefix -aO,$(abspath $($(name)-bind-dirs))) \
268 $($(name)-bind-flags) -o $(notdir $@) $($(name)-bind-alis)
Nico Huber78ca5822017-03-05 13:51:49 +0100269$(eval $(call add_ada_rule,adb,$(obj)/b__$(prefixed-name).o:,,$(filter-out -gnatec=%,$(ADAFLAGS))))
Nico Huberf43881f2017-03-05 13:43:20 +0100270$(name)-objs += $(obj)/b__$(prefixed-name).o
Nico Huber5e9b1b52016-10-08 22:09:33 +0200271
Nico Hubere86fff92017-03-04 13:20:37 +0100272# Compilation rule for C sources
273$(call src-to-obj,,$(filter %.c,$($(name)-srcs))): $(obj)/%.o: %.c
274 @printf " COMPILE $(subst $(obj)/,,$@)\n"
275 $(CC) $(CFLAGS) -c -o $@ $<
276
Nico Huber5e9b1b52016-10-08 22:09:33 +0200277$(shell mkdir -p $(alldirs))
278
279$(name)-install-srcs = $(sort \
280 $($(name)-extra-specs) $(filter %.ads,$($(name)-srcs)) \
281 $(foreach adb,$(filter %.adb,$($(name)-srcs)), \
282 $(shell grep -q '^U .*\<BN\>' $(call src-to-ali,,$(adb)) 2>/dev/null && echo $(adb))))
283
284$(name)-install-proof = \
285 $(filter $(addprefix %/,$(notdir $($(name)-install-srcs))),$($(name)-proof)) \
286 $(filter-out $(addprefix %/,$(notdir $($(name)-proof))),$($(name)-install-srcs))
287
288install: $(binary) $($(name)-alis) $(libgpr)
289 install -d $(DESTDIR)/lib $(DESTDIR)/include $(DESTDIR)/proof
290 printf " INSTALL $(subst $(obj)/,,$(binary))\n"
291 install $(binary) $(DESTDIR)/lib/
292 $(foreach file,$($(name)-install) $(libgpr), \
293 printf " INSTALL $(subst $(obj)/,,$(file))\n"; \
294 install $(file) $(DESTDIR);)
295 printf " INSTALL $(cnf)\n"
296 install $(cnf) $(DESTDIR)/config
297 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-alis))
298 install $($(name)-alis) $(DESTDIR)/lib/
299 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-srcs))
300 install $($(name)-install-srcs) $(DESTDIR)/include/
301 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-proof))
302 install $($(name)-install-proof) $(DESTDIR)/proof/
303
304clean::
305 rm -rf $(obj) $(name).gpr
306
307distclean: clean
308 rm -rf dest
309
310.PHONY: install clean distclean