blob: e8d864e5a9673a952d19c1968085d8c4dc0eb98c [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
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#
Angel Ponsa3edc6e2020-07-17 20:19:51 +020070# _R Suppress warnings for out-of-order record representation clauses:
71# We reorder fields on purpose.
72#
Nico Huber5e9b1b52016-10-08 22:09:33 +020073# T Suppress warnings for tracking of deleted conditional code:
74# We use static options to select code paths at compile time.
75#
76# U Suppress warnings on unused entities:
77# Would have lots of warnings for unused register definitions,
78# `withs` for debugging etc.
79#
80# .U Deactivate warnings on unordered enumeration types:
81# As SPARK doesn't support `pragma Ordered` by now, we don't
82# use that, yet.
83#
84# .W Suppress warnings on unnecessary Warnings Off pragmas:
85# Things get really messy when you use different compiler
86# versions, otherwise.
87# .Y Disable information messages for why package spec needs body:
88# Those messages are annoying. But don't forget to enable those,
89# if you need the information.
Nico Huberd8fae232024-04-22 11:58:18 +020090ADAFLAGS += -gnatwa.eeD.HHTU.U.W.Y_R
Nico Huber5e9b1b52016-10-08 22:09:33 +020091# Disable style checks for now
92ADAFLAGS += -gnatyN
93
94MAKEFLAGS += -rR
95
96# Make is silent per default, but 'make V=1' will show all compiler calls.
97ifneq ($(V),1)
98.SILENT:
99endif
100
101# must come rather early
102.SECONDEXPANSION:
103
Nico Huberf43881f2017-03-05 13:43:20 +0100104ifeq ($(link-type),archive)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200105$(binary): $$($(name)-objs)
106 @printf " AR $(subst $(obj)/,,$@)\n"
107 ar cr $@ $^
Nico Huberf43881f2017-03-05 13:43:20 +0100108else ifeq ($(link-type),program)
109$(binary): $$($(name)-objs)
110 @printf " LINK $(subst $(obj)/,,$@)\n"
111 $(CC) -o $@ $^ \
112 $(addprefix -L,$(abspath $($(name)-extra-objs))) \
113 $(addprefix -l,$(patsubst lib%,%,$($(name)-deplibs))) \
114 -lgnat
115endif
Nico Huber5e9b1b52016-10-08 22:09:33 +0200116
117$(foreach dep,$($(name)-deplibs), \
118 $(eval $(name)-extra-objs += $($(dep)-dir)/lib) \
119 $(eval $(name)-extra-incs += $($(dep)-dir)/include))
120
121# Converts one or more source file paths to their corresponding build/ paths.
122# Only .ads and .adb get converted to .o, other files keep their names.
123# $1 file path (list)
124src-to-obj = \
125 $(addprefix $(obj)/,\
126 $(patsubst $(obj)/%,%, \
Nico Hubere86fff92017-03-04 13:20:37 +0100127 $(patsubst %.c,%.o,\
Nico Huber5e9b1b52016-10-08 22:09:33 +0200128 $(patsubst %.ads,%.o,\
129 $(patsubst %.adb,%.o,\
Nico Hubere86fff92017-03-04 13:20:37 +0100130 $(2))))))
Nico Huber5e9b1b52016-10-08 22:09:33 +0200131
132# Converts one or more source file paths to the corresponding build/ paths
133# of their Ada library information (.ali) files.
134# $1 file path (list)
135src-to-ali = \
136 $(addprefix $(obj)/,\
137 $(patsubst $(obj)/%,%, \
138 $(patsubst %.ads,%.ali,\
139 $(patsubst %.adb,%.ali,\
140 $(filter %.ads %.adb,$(2))))))
141
142# Clean -y variables, include Makefile.inc
143# Add paths to files in $(name)-y to $(name)-srcs
144# Add subdirs-y to subdirs
145# $1 dir to read Makefile.inc from
146includemakefile = \
147 $(eval $(name)-y :=) \
Nico Huberf43881f2017-03-05 13:43:20 +0100148 $(eval $(name)-main-y :=) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200149 $(eval $(name)-gen-y :=) \
150 $(eval $(name)-proof-y :=) \
151 $(eval subdirs-y :=) \
152 $(eval include $(1)/Makefile.inc) \
Nico Huberf43881f2017-03-05 13:43:20 +0100153 $(eval $(name)-main-src += \
154 $(subst $(top)/,, \
155 $(abspath $(patsubst $(1)//%,/%,$(addprefix $(1)/,$($(name)-main-y)))))) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200156 $(eval $(name)-srcs += \
157 $(subst $(top)/,, \
Nico Huber868915f2017-02-13 15:28:58 +0100158 $(abspath $(patsubst $(1)//%,/%,$(addprefix $(1)/,$($(name)-y)))))) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200159 $(eval $(name)-gens += \
160 $(subst $(top)/,, \
161 $(abspath $($(name)-gen-y)))) \
162 $(eval $(name)-proof += \
163 $(subst $(top)/,, \
164 $(abspath $(addprefix $(1)/,$($(name)-proof-y))))) \
165 $(eval subdirs += \
166 $(subst $(top)/,, \
167 $(abspath $(addprefix $(1)/,$(subdirs-y))))) \
168
169# For each path in $(subdirs) call includemakefiles
170# Repeat until subdirs is empty
171evaluate_subdirs = \
172 $(eval cursubdirs := $(subdirs)) \
173 $(eval subdirs :=) \
174 $(foreach dir,$(cursubdirs), \
175 $(call includemakefile,$(dir))) \
176 $(if $(subdirs), \
177 $(call evaluate_subdirs))
178
179# collect all object files eligible for building
180subdirs := .
181$(call evaluate_subdirs)
182
Nico Huberf43881f2017-03-05 13:43:20 +0100183$(name)-srcs += $($(name)-main-src)
184
Nico Huber5e9b1b52016-10-08 22:09:33 +0200185# Eliminate duplicate mentions of source files
186$(name)-srcs := $(sort $($(name)-srcs))
187$(name)-gens := $(sort $($(name)-gens))
188
189# For Ada includes
190$(name)-ada-dirs := $(sort $(dir $(filter %.ads %.adb,$($(name)-srcs) $($(name)-gens))))
191
192# To track dependencies, we need all Ada specification (.ads) files in
193# *-srcs. Extract / filter all specification files that have a matching
194# body (.adb) file here (specifications without a body are valid sources
195# in Ada).
Nico Huberbd0ed912018-06-17 17:58:57 +0200196# $1 source list
197filter_extra_specs = \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200198 $(filter \
Nico Huberbd0ed912018-06-17 17:58:57 +0200199 $(addprefix %/,$(patsubst %.adb,%.ads, \
200 $(notdir $(filter %.adb,$($(name)-srcs) $($(name)-gens))))), \
201 $(filter %.ads,$(1)))
202$(name)-extra-specs := $(call filter_extra_specs,$($(name)-srcs))
Nico Huber5e9b1b52016-10-08 22:09:33 +0200203$(name)-srcs := $(filter-out $($(name)-extra-specs),$($(name)-srcs))
Nico Huberbd0ed912018-06-17 17:58:57 +0200204$(name)-extra-gens := $(call filter_extra_specs,$($(name)-gens))
205$(name)-gens := $(filter-out $($(name)-extra-gens),$($(name)-gens))
Nico Huber5e9b1b52016-10-08 22:09:33 +0200206
207$(name)-objs := $(call src-to-obj,,$($(name)-srcs) $($(name)-gens))
208$(name)-alis := $(call src-to-ali,,$($(name)-srcs) $($(name)-gens))
209
210# For gnatprove
211$(name)-proof-dirs := \
212 $(sort $(dir $($(name)-proof)) \
213 $(filter-out ada/% %/ada/%,$($(name)-ada-dirs)))
214
215# For mkdir
216alldirs := $(abspath $(dir $(sort $($(name)-objs))))
217
218# Reads dependencies from an Ada library information (.ali) file
219# Only basenames (with suffix) are preserved so we have to look the
220# paths up in $($(name)-srcs) $($(name)-gens).
221# $1 ali file
222create_ada_deps = \
223 $(if $(wildcard $(1)),\
224 $(filter \
225 $(addprefix %/,$(shell sed -ne's/^D \([^\t]\+\).*$$/\1/p' $(1) 2>/dev/null)), \
Nico Huberbd0ed912018-06-17 17:58:57 +0200226 $($(name)-srcs) $($(name)-gens) $($(name)-extra-specs) $($(name)-extra-gens)), \
227 $($(name)-gens) $($(name)-extra-gens))
Nico Huber5e9b1b52016-10-08 22:09:33 +0200228
229# Adds dependency rules
230# $1 source file
231add_ada_deps = \
232 $(call src-to-obj,,$(1)): $(1) \
233 $(call create_ada_deps,$(call src-to-ali,,$(1)))
234
Nico Hubere86fff92017-03-04 13:20:37 +0100235# Writes a compilation rule for Ada sources
Nico Huber5e9b1b52016-10-08 22:09:33 +0200236# $1 source type (ads, adb)
237# $2 source files (including the colon)
238# $3 obj path prefix (including the trailing slash)
Nico Huber78ca5822017-03-05 13:51:49 +0100239# $4 compiler flags (if empty, $(ADAFLAGS) apply)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200240define add_ada_rule
241$(2) $(3)%.o: %.$(1)
242 @printf " COMPILE $$(subst $(obj)/,,$$@)\n"
243 $(CC) \
Angel Ponsd822df52020-07-17 20:41:16 +0200244 $(if $(4),$(4),$$(ADAFLAGS)) \
Nico Huber78ca5822017-03-05 13:51:49 +0100245 $(addprefix -I,$($(name)-ada-dirs) $($(name)-extra-incs)) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200246 -c -o $$@ $$<
247endef
248
249# For sources
250$(foreach type,ads adb, \
251 $(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-srcs))):,$(obj)/)))
252$(foreach file,$($(name)-srcs) $($(name)-gens), \
253 $(eval $(call add_ada_deps,$(file))))
254
255# For generated sources already in $(obj)/
256$(foreach type,ads adb, \
257 $(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-gens))):,)))
258
259# Ali files are generated along with the object file. They need an empty
260# recipe for correct updating.
261$($(name)-alis): %.ali: %.o ;
262
263# To support complex package initializations, we need to call the
264# emitted code explicitly. gnatbind gathers all the calls for us
Nico Huberf43881f2017-03-05 13:43:20 +0100265# and exports them as a procedure $(name)_adainit().
266ifeq ($(link-type),archive)
267$(name)-bind-dirs := $($(name)-extra-objs)
268$(name)-bind-flags := -a -n -L$(name)_ada
269$(name)-bind-alis = $(patsubst /%,%,$(subst $(dir $@),,$^))
270else ifeq ($(link-type),program)
271$(name)-bind-dirs := $(sort $(dir $($(name)-objs))) $($(name)-extra-objs)
272$(name)-bind-flags :=
273$(name)-bind-alis = $(subst $(dir $@),,$(call src-to-ali,,$($(name)-main-src)))
274endif
275$(obj)/b__$(prefixed-name).adb: $($(name)-alis)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200276 @printf " BIND $(subst $(obj)/,,$@)\n"
277 # We have to give gnatbind a simple filename (without leading
278 # path components) so just cd there.
279 cd $(dir $@) && \
Nico Huberf43881f2017-03-05 13:43:20 +0100280 $(GNATBIND) $(addprefix -aO,$(abspath $($(name)-bind-dirs))) \
281 $($(name)-bind-flags) -o $(notdir $@) $($(name)-bind-alis)
Nico Huber78ca5822017-03-05 13:51:49 +0100282$(eval $(call add_ada_rule,adb,$(obj)/b__$(prefixed-name).o:,,$(filter-out -gnatec=%,$(ADAFLAGS))))
Nico Huberf43881f2017-03-05 13:43:20 +0100283$(name)-objs += $(obj)/b__$(prefixed-name).o
Nico Huber5e9b1b52016-10-08 22:09:33 +0200284
Nico Hubere86fff92017-03-04 13:20:37 +0100285# Compilation rule for C sources
286$(call src-to-obj,,$(filter %.c,$($(name)-srcs))): $(obj)/%.o: %.c
287 @printf " COMPILE $(subst $(obj)/,,$@)\n"
288 $(CC) $(CFLAGS) -c -o $@ $<
289
Nico Huber5e9b1b52016-10-08 22:09:33 +0200290$(shell mkdir -p $(alldirs))
291
292$(name)-install-srcs = $(sort \
Nico Huberbd0ed912018-06-17 17:58:57 +0200293 $($(name)-extra-specs) $($(name)-extra-gens) $(filter %.ads,$($(name)-srcs) $($(name)-gens)) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200294 $(foreach adb,$(filter %.adb,$($(name)-srcs)), \
295 $(shell grep -q '^U .*\<BN\>' $(call src-to-ali,,$(adb)) 2>/dev/null && echo $(adb))))
296
297$(name)-install-proof = \
298 $(filter $(addprefix %/,$(notdir $($(name)-install-srcs))),$($(name)-proof)) \
299 $(filter-out $(addprefix %/,$(notdir $($(name)-proof))),$($(name)-install-srcs))
300
Nico Huberba378302017-07-09 18:56:24 +0200301install: $(binary) $($(name)-alis) $($(name)-gens) $(libgpr)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200302 install -d $(DESTDIR)/lib $(DESTDIR)/include $(DESTDIR)/proof
303 printf " INSTALL $(subst $(obj)/,,$(binary))\n"
304 install $(binary) $(DESTDIR)/lib/
305 $(foreach file,$($(name)-install) $(libgpr), \
306 printf " INSTALL $(subst $(obj)/,,$(file))\n"; \
307 install $(file) $(DESTDIR);)
308 printf " INSTALL $(cnf)\n"
309 install $(cnf) $(DESTDIR)/config
310 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-alis))
311 install $($(name)-alis) $(DESTDIR)/lib/
312 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-srcs))
313 install $($(name)-install-srcs) $(DESTDIR)/include/
314 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-proof))
315 install $($(name)-install-proof) $(DESTDIR)/proof/
316
317clean::
318 rm -rf $(obj) $(name).gpr
319
320distclean: clean
321 rm -rf dest
322
323.PHONY: install clean distclean