blob: a25deb66ce326f3da93c09fee1a7b594d3bb166b [file] [log] [blame]
Nico Huber5e9b1b52016-10-08 22:09:33 +02001libhw-dir := $(dir $(lastword $(MAKEFILE_LIST)))
2
3DESTDIR ?= dest
4
5name ?= hw
Nico Huber36934fb2017-07-13 00:08:21 +02006hw-install = Makefile Makefile.proof debug.adc gnat.adc spark.adc
Nico Huber5e9b1b52016-10-08 22:09:33 +02007
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
Nico Huber36934fb2017-07-13 00:08:21 +020037ifeq ($(DEBUG),1)
38gnat-adc = $(libhw-dir)/debug.adc
39else
40gnat-adc = $(libhw-dir)/gnat.adc
41endif
42
Nico Huber5e9b1b52016-10-08 22:09:33 +020043CC = $(CROSS_COMPILE)gcc
44GNATBIND = $(CROSS_COMPILE)gnatbind
45
Nico Hubere86fff92017-03-04 13:20:37 +010046CFLAGS += -Wuninitialized -Wall -Werror
47CFLAGS += -pipe -g
48CFLAGS += -Wstrict-aliasing -Wshadow
49CFLAGS += -fno-common -fomit-frame-pointer
50CFLAGS += -ffunction-sections -fdata-sections
51
Nico Huber36934fb2017-07-13 00:08:21 +020052ADAFLAGS += $(CFLAGS) -gnatA -gnatec=$(gnat-adc) -gnatp
Nico Huber5e9b1b52016-10-08 22:09:33 +020053# Ada warning options:
54#
55# a Activate most optional warnings.
56# .e Activate every optional warnings.
57# e Treat warnings and style checks as errors.
58#
59# D Suppress warnings on implicit dereferences:
60# As SPARK does not accept access types we have to map the
61# dynamically chosen register locations to a static SPARK
62# variable.
63#
64# .H Suppress warnings on holes/gaps in records:
65# We are modelling hardware here!
66#
67# H Suppress warnings on hiding:
68# It's too annoying, you run out of ideas for identifiers fast.
69#
70# T Suppress warnings for tracking of deleted conditional code:
71# We use static options to select code paths at compile time.
72#
73# U Suppress warnings on unused entities:
74# Would have lots of warnings for unused register definitions,
75# `withs` for debugging etc.
76#
77# .U Deactivate warnings on unordered enumeration types:
78# As SPARK doesn't support `pragma Ordered` by now, we don't
79# use that, yet.
80#
81# .W Suppress warnings on unnecessary Warnings Off pragmas:
82# Things get really messy when you use different compiler
83# versions, otherwise.
84# .Y Disable information messages for why package spec needs body:
85# Those messages are annoying. But don't forget to enable those,
86# if you need the information.
87ADAFLAGS += -gnatwa.eeD.HHTU.U.W.Y
88# Disable style checks for now
89ADAFLAGS += -gnatyN
90
91MAKEFLAGS += -rR
92
93# Make is silent per default, but 'make V=1' will show all compiler calls.
94ifneq ($(V),1)
95.SILENT:
96endif
97
98# must come rather early
99.SECONDEXPANSION:
100
Nico Huberf43881f2017-03-05 13:43:20 +0100101ifeq ($(link-type),archive)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200102$(binary): $$($(name)-objs)
103 @printf " AR $(subst $(obj)/,,$@)\n"
104 ar cr $@ $^
Nico Huberf43881f2017-03-05 13:43:20 +0100105else ifeq ($(link-type),program)
106$(binary): $$($(name)-objs)
107 @printf " LINK $(subst $(obj)/,,$@)\n"
108 $(CC) -o $@ $^ \
109 $(addprefix -L,$(abspath $($(name)-extra-objs))) \
110 $(addprefix -l,$(patsubst lib%,%,$($(name)-deplibs))) \
111 -lgnat
112endif
Nico Huber5e9b1b52016-10-08 22:09:33 +0200113
114$(foreach dep,$($(name)-deplibs), \
115 $(eval $(name)-extra-objs += $($(dep)-dir)/lib) \
116 $(eval $(name)-extra-incs += $($(dep)-dir)/include))
117
118# Converts one or more source file paths to their corresponding build/ paths.
119# Only .ads and .adb get converted to .o, other files keep their names.
120# $1 file path (list)
121src-to-obj = \
122 $(addprefix $(obj)/,\
123 $(patsubst $(obj)/%,%, \
Nico Hubere86fff92017-03-04 13:20:37 +0100124 $(patsubst %.c,%.o,\
Nico Huber5e9b1b52016-10-08 22:09:33 +0200125 $(patsubst %.ads,%.o,\
126 $(patsubst %.adb,%.o,\
Nico Hubere86fff92017-03-04 13:20:37 +0100127 $(2))))))
Nico Huber5e9b1b52016-10-08 22:09:33 +0200128
129# Converts one or more source file paths to the corresponding build/ paths
130# of their Ada library information (.ali) files.
131# $1 file path (list)
132src-to-ali = \
133 $(addprefix $(obj)/,\
134 $(patsubst $(obj)/%,%, \
135 $(patsubst %.ads,%.ali,\
136 $(patsubst %.adb,%.ali,\
137 $(filter %.ads %.adb,$(2))))))
138
139# Clean -y variables, include Makefile.inc
140# Add paths to files in $(name)-y to $(name)-srcs
141# Add subdirs-y to subdirs
142# $1 dir to read Makefile.inc from
143includemakefile = \
144 $(eval $(name)-y :=) \
Nico Huberf43881f2017-03-05 13:43:20 +0100145 $(eval $(name)-main-y :=) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200146 $(eval $(name)-gen-y :=) \
147 $(eval $(name)-proof-y :=) \
148 $(eval subdirs-y :=) \
149 $(eval include $(1)/Makefile.inc) \
Nico Huberf43881f2017-03-05 13:43:20 +0100150 $(eval $(name)-main-src += \
151 $(subst $(top)/,, \
152 $(abspath $(patsubst $(1)//%,/%,$(addprefix $(1)/,$($(name)-main-y)))))) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200153 $(eval $(name)-srcs += \
154 $(subst $(top)/,, \
Nico Huber868915f2017-02-13 15:28:58 +0100155 $(abspath $(patsubst $(1)//%,/%,$(addprefix $(1)/,$($(name)-y)))))) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200156 $(eval $(name)-gens += \
157 $(subst $(top)/,, \
158 $(abspath $($(name)-gen-y)))) \
159 $(eval $(name)-proof += \
160 $(subst $(top)/,, \
161 $(abspath $(addprefix $(1)/,$($(name)-proof-y))))) \
162 $(eval subdirs += \
163 $(subst $(top)/,, \
164 $(abspath $(addprefix $(1)/,$(subdirs-y))))) \
165
166# For each path in $(subdirs) call includemakefiles
167# Repeat until subdirs is empty
168evaluate_subdirs = \
169 $(eval cursubdirs := $(subdirs)) \
170 $(eval subdirs :=) \
171 $(foreach dir,$(cursubdirs), \
172 $(call includemakefile,$(dir))) \
173 $(if $(subdirs), \
174 $(call evaluate_subdirs))
175
176# collect all object files eligible for building
177subdirs := .
178$(call evaluate_subdirs)
179
Nico Huberf43881f2017-03-05 13:43:20 +0100180$(name)-srcs += $($(name)-main-src)
181
Nico Huber5e9b1b52016-10-08 22:09:33 +0200182# Eliminate duplicate mentions of source files
183$(name)-srcs := $(sort $($(name)-srcs))
184$(name)-gens := $(sort $($(name)-gens))
185
186# For Ada includes
187$(name)-ada-dirs := $(sort $(dir $(filter %.ads %.adb,$($(name)-srcs) $($(name)-gens))))
188
189# To track dependencies, we need all Ada specification (.ads) files in
190# *-srcs. Extract / filter all specification files that have a matching
191# body (.adb) file here (specifications without a body are valid sources
192# in Ada).
Nico Huberbd0ed912018-06-17 17:58:57 +0200193# $1 source list
194filter_extra_specs = \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200195 $(filter \
Nico Huberbd0ed912018-06-17 17:58:57 +0200196 $(addprefix %/,$(patsubst %.adb,%.ads, \
197 $(notdir $(filter %.adb,$($(name)-srcs) $($(name)-gens))))), \
198 $(filter %.ads,$(1)))
199$(name)-extra-specs := $(call filter_extra_specs,$($(name)-srcs))
Nico Huber5e9b1b52016-10-08 22:09:33 +0200200$(name)-srcs := $(filter-out $($(name)-extra-specs),$($(name)-srcs))
Nico Huberbd0ed912018-06-17 17:58:57 +0200201$(name)-extra-gens := $(call filter_extra_specs,$($(name)-gens))
202$(name)-gens := $(filter-out $($(name)-extra-gens),$($(name)-gens))
Nico Huber5e9b1b52016-10-08 22:09:33 +0200203
204$(name)-objs := $(call src-to-obj,,$($(name)-srcs) $($(name)-gens))
205$(name)-alis := $(call src-to-ali,,$($(name)-srcs) $($(name)-gens))
206
207# For gnatprove
208$(name)-proof-dirs := \
209 $(sort $(dir $($(name)-proof)) \
210 $(filter-out ada/% %/ada/%,$($(name)-ada-dirs)))
211
212# For mkdir
213alldirs := $(abspath $(dir $(sort $($(name)-objs))))
214
215# Reads dependencies from an Ada library information (.ali) file
216# Only basenames (with suffix) are preserved so we have to look the
217# paths up in $($(name)-srcs) $($(name)-gens).
218# $1 ali file
219create_ada_deps = \
220 $(if $(wildcard $(1)),\
221 $(filter \
222 $(addprefix %/,$(shell sed -ne's/^D \([^\t]\+\).*$$/\1/p' $(1) 2>/dev/null)), \
Nico Huberbd0ed912018-06-17 17:58:57 +0200223 $($(name)-srcs) $($(name)-gens) $($(name)-extra-specs) $($(name)-extra-gens)), \
224 $($(name)-gens) $($(name)-extra-gens))
Nico Huber5e9b1b52016-10-08 22:09:33 +0200225
226# Adds dependency rules
227# $1 source file
228add_ada_deps = \
229 $(call src-to-obj,,$(1)): $(1) \
230 $(call create_ada_deps,$(call src-to-ali,,$(1)))
231
Nico Hubere86fff92017-03-04 13:20:37 +0100232# Writes a compilation rule for Ada sources
Nico Huber5e9b1b52016-10-08 22:09:33 +0200233# $1 source type (ads, adb)
234# $2 source files (including the colon)
235# $3 obj path prefix (including the trailing slash)
Nico Huber78ca5822017-03-05 13:51:49 +0100236# $4 compiler flags (if empty, $(ADAFLAGS) apply)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200237define add_ada_rule
238$(2) $(3)%.o: %.$(1)
239 @printf " COMPILE $$(subst $(obj)/,,$$@)\n"
240 $(CC) \
Nico Huber78ca5822017-03-05 13:51:49 +0100241 $(if $(4),$(4),$(ADAFLAGS)) \
242 $(addprefix -I,$($(name)-ada-dirs) $($(name)-extra-incs)) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200243 -c -o $$@ $$<
244endef
245
246# For sources
247$(foreach type,ads adb, \
248 $(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-srcs))):,$(obj)/)))
249$(foreach file,$($(name)-srcs) $($(name)-gens), \
250 $(eval $(call add_ada_deps,$(file))))
251
252# For generated sources already in $(obj)/
253$(foreach type,ads adb, \
254 $(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-gens))):,)))
255
256# Ali files are generated along with the object file. They need an empty
257# recipe for correct updating.
258$($(name)-alis): %.ali: %.o ;
259
260# To support complex package initializations, we need to call the
261# emitted code explicitly. gnatbind gathers all the calls for us
Nico Huberf43881f2017-03-05 13:43:20 +0100262# and exports them as a procedure $(name)_adainit().
263ifeq ($(link-type),archive)
264$(name)-bind-dirs := $($(name)-extra-objs)
265$(name)-bind-flags := -a -n -L$(name)_ada
266$(name)-bind-alis = $(patsubst /%,%,$(subst $(dir $@),,$^))
267else ifeq ($(link-type),program)
268$(name)-bind-dirs := $(sort $(dir $($(name)-objs))) $($(name)-extra-objs)
269$(name)-bind-flags :=
270$(name)-bind-alis = $(subst $(dir $@),,$(call src-to-ali,,$($(name)-main-src)))
271endif
272$(obj)/b__$(prefixed-name).adb: $($(name)-alis)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200273 @printf " BIND $(subst $(obj)/,,$@)\n"
274 # We have to give gnatbind a simple filename (without leading
275 # path components) so just cd there.
276 cd $(dir $@) && \
Nico Huberf43881f2017-03-05 13:43:20 +0100277 $(GNATBIND) $(addprefix -aO,$(abspath $($(name)-bind-dirs))) \
278 $($(name)-bind-flags) -o $(notdir $@) $($(name)-bind-alis)
Nico Huber78ca5822017-03-05 13:51:49 +0100279$(eval $(call add_ada_rule,adb,$(obj)/b__$(prefixed-name).o:,,$(filter-out -gnatec=%,$(ADAFLAGS))))
Nico Huberf43881f2017-03-05 13:43:20 +0100280$(name)-objs += $(obj)/b__$(prefixed-name).o
Nico Huber5e9b1b52016-10-08 22:09:33 +0200281
Nico Hubere86fff92017-03-04 13:20:37 +0100282# Compilation rule for C sources
283$(call src-to-obj,,$(filter %.c,$($(name)-srcs))): $(obj)/%.o: %.c
284 @printf " COMPILE $(subst $(obj)/,,$@)\n"
285 $(CC) $(CFLAGS) -c -o $@ $<
286
Nico Huber5e9b1b52016-10-08 22:09:33 +0200287$(shell mkdir -p $(alldirs))
288
289$(name)-install-srcs = $(sort \
Nico Huberbd0ed912018-06-17 17:58:57 +0200290 $($(name)-extra-specs) $($(name)-extra-gens) $(filter %.ads,$($(name)-srcs) $($(name)-gens)) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200291 $(foreach adb,$(filter %.adb,$($(name)-srcs)), \
292 $(shell grep -q '^U .*\<BN\>' $(call src-to-ali,,$(adb)) 2>/dev/null && echo $(adb))))
293
294$(name)-install-proof = \
295 $(filter $(addprefix %/,$(notdir $($(name)-install-srcs))),$($(name)-proof)) \
296 $(filter-out $(addprefix %/,$(notdir $($(name)-proof))),$($(name)-install-srcs))
297
Nico Huberba378302017-07-09 18:56:24 +0200298install: $(binary) $($(name)-alis) $($(name)-gens) $(libgpr)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200299 install -d $(DESTDIR)/lib $(DESTDIR)/include $(DESTDIR)/proof
300 printf " INSTALL $(subst $(obj)/,,$(binary))\n"
301 install $(binary) $(DESTDIR)/lib/
302 $(foreach file,$($(name)-install) $(libgpr), \
303 printf " INSTALL $(subst $(obj)/,,$(file))\n"; \
304 install $(file) $(DESTDIR);)
305 printf " INSTALL $(cnf)\n"
306 install $(cnf) $(DESTDIR)/config
307 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-alis))
308 install $($(name)-alis) $(DESTDIR)/lib/
309 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-srcs))
310 install $($(name)-install-srcs) $(DESTDIR)/include/
311 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-proof))
312 install $($(name)-install-proof) $(DESTDIR)/proof/
313
314clean::
315 rm -rf $(obj) $(name).gpr
316
317distclean: clean
318 rm -rf dest
319
320.PHONY: install clean distclean