blob: fb4c43cf7bb44f88f27a1a04cbea526d1aa96a2e [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 :=
Angel Pons4e229102020-02-28 22:19:39 +010025space := $(space) $(space)
Nico Huber5e9b1b52016-10-08 22:09:33 +020026comma := ,
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
Angel Ponsa3edc6e2020-07-17 20:19:51 +020046GCC_MAJOR = $(shell echo __GNUC__ | $(CC) -E - 2>/dev/null | tail -1)
47
Nico Hubere86fff92017-03-04 13:20:37 +010048CFLAGS += -Wuninitialized -Wall -Werror
49CFLAGS += -pipe -g
50CFLAGS += -Wstrict-aliasing -Wshadow
51CFLAGS += -fno-common -fomit-frame-pointer
52CFLAGS += -ffunction-sections -fdata-sections
53
Nico Huber36934fb2017-07-13 00:08:21 +020054ADAFLAGS += $(CFLAGS) -gnatA -gnatec=$(gnat-adc) -gnatp
Nico Huber5e9b1b52016-10-08 22:09:33 +020055# Ada warning options:
56#
57# a Activate most optional warnings.
58# .e Activate every optional warnings.
59# e Treat warnings and style checks as errors.
60#
61# D Suppress warnings on implicit dereferences:
62# As SPARK does not accept access types we have to map the
63# dynamically chosen register locations to a static SPARK
64# variable.
65#
66# .H Suppress warnings on holes/gaps in records:
67# We are modelling hardware here!
68#
69# H Suppress warnings on hiding:
70# It's too annoying, you run out of ideas for identifiers fast.
71#
Angel Ponsa3edc6e2020-07-17 20:19:51 +020072# _R Suppress warnings for out-of-order record representation clauses:
73# We reorder fields on purpose.
74#
Nico Huber5e9b1b52016-10-08 22:09:33 +020075# T Suppress warnings for tracking of deleted conditional code:
76# We use static options to select code paths at compile time.
77#
78# U Suppress warnings on unused entities:
79# Would have lots of warnings for unused register definitions,
80# `withs` for debugging etc.
81#
82# .U Deactivate warnings on unordered enumeration types:
83# As SPARK doesn't support `pragma Ordered` by now, we don't
84# use that, yet.
85#
86# .W Suppress warnings on unnecessary Warnings Off pragmas:
87# Things get really messy when you use different compiler
88# versions, otherwise.
89# .Y Disable information messages for why package spec needs body:
90# Those messages are annoying. But don't forget to enable those,
91# if you need the information.
92ADAFLAGS += -gnatwa.eeD.HHTU.U.W.Y
Angel Ponsa3edc6e2020-07-17 20:19:51 +020093ADAFLAGS += $(if $(filter 10,$(GCC_MAJOR)),-gnatw_R)
Nico Huber5e9b1b52016-10-08 22:09:33 +020094# Disable style checks for now
95ADAFLAGS += -gnatyN
96
97MAKEFLAGS += -rR
98
99# Make is silent per default, but 'make V=1' will show all compiler calls.
100ifneq ($(V),1)
101.SILENT:
102endif
103
104# must come rather early
105.SECONDEXPANSION:
106
Nico Huberf43881f2017-03-05 13:43:20 +0100107ifeq ($(link-type),archive)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200108$(binary): $$($(name)-objs)
109 @printf " AR $(subst $(obj)/,,$@)\n"
110 ar cr $@ $^
Nico Huberf43881f2017-03-05 13:43:20 +0100111else ifeq ($(link-type),program)
112$(binary): $$($(name)-objs)
113 @printf " LINK $(subst $(obj)/,,$@)\n"
114 $(CC) -o $@ $^ \
115 $(addprefix -L,$(abspath $($(name)-extra-objs))) \
116 $(addprefix -l,$(patsubst lib%,%,$($(name)-deplibs))) \
117 -lgnat
118endif
Nico Huber5e9b1b52016-10-08 22:09:33 +0200119
120$(foreach dep,$($(name)-deplibs), \
121 $(eval $(name)-extra-objs += $($(dep)-dir)/lib) \
122 $(eval $(name)-extra-incs += $($(dep)-dir)/include))
123
124# Converts one or more source file paths to their corresponding build/ paths.
125# Only .ads and .adb get converted to .o, other files keep their names.
126# $1 file path (list)
127src-to-obj = \
128 $(addprefix $(obj)/,\
129 $(patsubst $(obj)/%,%, \
Nico Hubere86fff92017-03-04 13:20:37 +0100130 $(patsubst %.c,%.o,\
Nico Huber5e9b1b52016-10-08 22:09:33 +0200131 $(patsubst %.ads,%.o,\
132 $(patsubst %.adb,%.o,\
Nico Hubere86fff92017-03-04 13:20:37 +0100133 $(2))))))
Nico Huber5e9b1b52016-10-08 22:09:33 +0200134
135# Converts one or more source file paths to the corresponding build/ paths
136# of their Ada library information (.ali) files.
137# $1 file path (list)
138src-to-ali = \
139 $(addprefix $(obj)/,\
140 $(patsubst $(obj)/%,%, \
141 $(patsubst %.ads,%.ali,\
142 $(patsubst %.adb,%.ali,\
143 $(filter %.ads %.adb,$(2))))))
144
145# Clean -y variables, include Makefile.inc
146# Add paths to files in $(name)-y to $(name)-srcs
147# Add subdirs-y to subdirs
148# $1 dir to read Makefile.inc from
149includemakefile = \
150 $(eval $(name)-y :=) \
Nico Huberf43881f2017-03-05 13:43:20 +0100151 $(eval $(name)-main-y :=) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200152 $(eval $(name)-gen-y :=) \
153 $(eval $(name)-proof-y :=) \
154 $(eval subdirs-y :=) \
155 $(eval include $(1)/Makefile.inc) \
Nico Huberf43881f2017-03-05 13:43:20 +0100156 $(eval $(name)-main-src += \
157 $(subst $(top)/,, \
158 $(abspath $(patsubst $(1)//%,/%,$(addprefix $(1)/,$($(name)-main-y)))))) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200159 $(eval $(name)-srcs += \
160 $(subst $(top)/,, \
Nico Huber868915f2017-02-13 15:28:58 +0100161 $(abspath $(patsubst $(1)//%,/%,$(addprefix $(1)/,$($(name)-y)))))) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200162 $(eval $(name)-gens += \
163 $(subst $(top)/,, \
164 $(abspath $($(name)-gen-y)))) \
165 $(eval $(name)-proof += \
166 $(subst $(top)/,, \
167 $(abspath $(addprefix $(1)/,$($(name)-proof-y))))) \
168 $(eval subdirs += \
169 $(subst $(top)/,, \
170 $(abspath $(addprefix $(1)/,$(subdirs-y))))) \
171
172# For each path in $(subdirs) call includemakefiles
173# Repeat until subdirs is empty
174evaluate_subdirs = \
175 $(eval cursubdirs := $(subdirs)) \
176 $(eval subdirs :=) \
177 $(foreach dir,$(cursubdirs), \
178 $(call includemakefile,$(dir))) \
179 $(if $(subdirs), \
180 $(call evaluate_subdirs))
181
182# collect all object files eligible for building
183subdirs := .
184$(call evaluate_subdirs)
185
Nico Huberf43881f2017-03-05 13:43:20 +0100186$(name)-srcs += $($(name)-main-src)
187
Nico Huber5e9b1b52016-10-08 22:09:33 +0200188# Eliminate duplicate mentions of source files
189$(name)-srcs := $(sort $($(name)-srcs))
190$(name)-gens := $(sort $($(name)-gens))
191
192# For Ada includes
193$(name)-ada-dirs := $(sort $(dir $(filter %.ads %.adb,$($(name)-srcs) $($(name)-gens))))
194
195# To track dependencies, we need all Ada specification (.ads) files in
196# *-srcs. Extract / filter all specification files that have a matching
197# body (.adb) file here (specifications without a body are valid sources
198# in Ada).
Nico Huberbd0ed912018-06-17 17:58:57 +0200199# $1 source list
200filter_extra_specs = \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200201 $(filter \
Nico Huberbd0ed912018-06-17 17:58:57 +0200202 $(addprefix %/,$(patsubst %.adb,%.ads, \
203 $(notdir $(filter %.adb,$($(name)-srcs) $($(name)-gens))))), \
204 $(filter %.ads,$(1)))
205$(name)-extra-specs := $(call filter_extra_specs,$($(name)-srcs))
Nico Huber5e9b1b52016-10-08 22:09:33 +0200206$(name)-srcs := $(filter-out $($(name)-extra-specs),$($(name)-srcs))
Nico Huberbd0ed912018-06-17 17:58:57 +0200207$(name)-extra-gens := $(call filter_extra_specs,$($(name)-gens))
208$(name)-gens := $(filter-out $($(name)-extra-gens),$($(name)-gens))
Nico Huber5e9b1b52016-10-08 22:09:33 +0200209
210$(name)-objs := $(call src-to-obj,,$($(name)-srcs) $($(name)-gens))
211$(name)-alis := $(call src-to-ali,,$($(name)-srcs) $($(name)-gens))
212
213# For gnatprove
214$(name)-proof-dirs := \
215 $(sort $(dir $($(name)-proof)) \
216 $(filter-out ada/% %/ada/%,$($(name)-ada-dirs)))
217
218# For mkdir
219alldirs := $(abspath $(dir $(sort $($(name)-objs))))
220
221# Reads dependencies from an Ada library information (.ali) file
222# Only basenames (with suffix) are preserved so we have to look the
223# paths up in $($(name)-srcs) $($(name)-gens).
224# $1 ali file
225create_ada_deps = \
226 $(if $(wildcard $(1)),\
227 $(filter \
228 $(addprefix %/,$(shell sed -ne's/^D \([^\t]\+\).*$$/\1/p' $(1) 2>/dev/null)), \
Nico Huberbd0ed912018-06-17 17:58:57 +0200229 $($(name)-srcs) $($(name)-gens) $($(name)-extra-specs) $($(name)-extra-gens)), \
230 $($(name)-gens) $($(name)-extra-gens))
Nico Huber5e9b1b52016-10-08 22:09:33 +0200231
232# Adds dependency rules
233# $1 source file
234add_ada_deps = \
235 $(call src-to-obj,,$(1)): $(1) \
236 $(call create_ada_deps,$(call src-to-ali,,$(1)))
237
Nico Hubere86fff92017-03-04 13:20:37 +0100238# Writes a compilation rule for Ada sources
Nico Huber5e9b1b52016-10-08 22:09:33 +0200239# $1 source type (ads, adb)
240# $2 source files (including the colon)
241# $3 obj path prefix (including the trailing slash)
Nico Huber78ca5822017-03-05 13:51:49 +0100242# $4 compiler flags (if empty, $(ADAFLAGS) apply)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200243define add_ada_rule
244$(2) $(3)%.o: %.$(1)
245 @printf " COMPILE $$(subst $(obj)/,,$$@)\n"
246 $(CC) \
Angel Ponsd822df52020-07-17 20:41:16 +0200247 $(if $(4),$(4),$$(ADAFLAGS)) \
Nico Huber78ca5822017-03-05 13:51:49 +0100248 $(addprefix -I,$($(name)-ada-dirs) $($(name)-extra-incs)) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200249 -c -o $$@ $$<
250endef
251
252# For sources
253$(foreach type,ads adb, \
254 $(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-srcs))):,$(obj)/)))
255$(foreach file,$($(name)-srcs) $($(name)-gens), \
256 $(eval $(call add_ada_deps,$(file))))
257
258# For generated sources already in $(obj)/
259$(foreach type,ads adb, \
260 $(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-gens))):,)))
261
262# Ali files are generated along with the object file. They need an empty
263# recipe for correct updating.
264$($(name)-alis): %.ali: %.o ;
265
266# To support complex package initializations, we need to call the
267# emitted code explicitly. gnatbind gathers all the calls for us
Nico Huberf43881f2017-03-05 13:43:20 +0100268# and exports them as a procedure $(name)_adainit().
269ifeq ($(link-type),archive)
270$(name)-bind-dirs := $($(name)-extra-objs)
271$(name)-bind-flags := -a -n -L$(name)_ada
272$(name)-bind-alis = $(patsubst /%,%,$(subst $(dir $@),,$^))
273else ifeq ($(link-type),program)
274$(name)-bind-dirs := $(sort $(dir $($(name)-objs))) $($(name)-extra-objs)
275$(name)-bind-flags :=
276$(name)-bind-alis = $(subst $(dir $@),,$(call src-to-ali,,$($(name)-main-src)))
277endif
278$(obj)/b__$(prefixed-name).adb: $($(name)-alis)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200279 @printf " BIND $(subst $(obj)/,,$@)\n"
280 # We have to give gnatbind a simple filename (without leading
281 # path components) so just cd there.
282 cd $(dir $@) && \
Nico Huberf43881f2017-03-05 13:43:20 +0100283 $(GNATBIND) $(addprefix -aO,$(abspath $($(name)-bind-dirs))) \
284 $($(name)-bind-flags) -o $(notdir $@) $($(name)-bind-alis)
Nico Huber78ca5822017-03-05 13:51:49 +0100285$(eval $(call add_ada_rule,adb,$(obj)/b__$(prefixed-name).o:,,$(filter-out -gnatec=%,$(ADAFLAGS))))
Nico Huberf43881f2017-03-05 13:43:20 +0100286$(name)-objs += $(obj)/b__$(prefixed-name).o
Nico Huber5e9b1b52016-10-08 22:09:33 +0200287
Nico Hubere86fff92017-03-04 13:20:37 +0100288# Compilation rule for C sources
289$(call src-to-obj,,$(filter %.c,$($(name)-srcs))): $(obj)/%.o: %.c
290 @printf " COMPILE $(subst $(obj)/,,$@)\n"
291 $(CC) $(CFLAGS) -c -o $@ $<
292
Nico Huber5e9b1b52016-10-08 22:09:33 +0200293$(shell mkdir -p $(alldirs))
294
295$(name)-install-srcs = $(sort \
Nico Huberbd0ed912018-06-17 17:58:57 +0200296 $($(name)-extra-specs) $($(name)-extra-gens) $(filter %.ads,$($(name)-srcs) $($(name)-gens)) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200297 $(foreach adb,$(filter %.adb,$($(name)-srcs)), \
298 $(shell grep -q '^U .*\<BN\>' $(call src-to-ali,,$(adb)) 2>/dev/null && echo $(adb))))
299
300$(name)-install-proof = \
301 $(filter $(addprefix %/,$(notdir $($(name)-install-srcs))),$($(name)-proof)) \
302 $(filter-out $(addprefix %/,$(notdir $($(name)-proof))),$($(name)-install-srcs))
303
Nico Huberba378302017-07-09 18:56:24 +0200304install: $(binary) $($(name)-alis) $($(name)-gens) $(libgpr)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200305 install -d $(DESTDIR)/lib $(DESTDIR)/include $(DESTDIR)/proof
306 printf " INSTALL $(subst $(obj)/,,$(binary))\n"
307 install $(binary) $(DESTDIR)/lib/
308 $(foreach file,$($(name)-install) $(libgpr), \
309 printf " INSTALL $(subst $(obj)/,,$(file))\n"; \
310 install $(file) $(DESTDIR);)
311 printf " INSTALL $(cnf)\n"
312 install $(cnf) $(DESTDIR)/config
313 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-alis))
314 install $($(name)-alis) $(DESTDIR)/lib/
315 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-srcs))
316 install $($(name)-install-srcs) $(DESTDIR)/include/
317 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-proof))
318 install $($(name)-install-proof) $(DESTDIR)/proof/
319
320clean::
321 rm -rf $(obj) $(name).gpr
322
323distclean: clean
324 rm -rf dest
325
326.PHONY: install clean distclean