blob: 09881e5b6ff8818e5ecd80db78f33e2af512fc96 [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).
193$(name)-extra-specs := \
194 $(filter \
195 $(addprefix %/,$(patsubst %.adb,%.ads,$(notdir $(filter %.adb,$($(name)-srcs))))), \
196 $(filter %.ads,$($(name)-srcs) $($(name)-gens)))
197$(name)-srcs := $(filter-out $($(name)-extra-specs),$($(name)-srcs))
198$(name)-gens := $(filter-out $($(name)-extra-specs),$($(name)-gens))
199
200$(name)-objs := $(call src-to-obj,,$($(name)-srcs) $($(name)-gens))
201$(name)-alis := $(call src-to-ali,,$($(name)-srcs) $($(name)-gens))
202
203# For gnatprove
204$(name)-proof-dirs := \
205 $(sort $(dir $($(name)-proof)) \
206 $(filter-out ada/% %/ada/%,$($(name)-ada-dirs)))
207
208# For mkdir
209alldirs := $(abspath $(dir $(sort $($(name)-objs))))
210
211# Reads dependencies from an Ada library information (.ali) file
212# Only basenames (with suffix) are preserved so we have to look the
213# paths up in $($(name)-srcs) $($(name)-gens).
214# $1 ali file
215create_ada_deps = \
216 $(if $(wildcard $(1)),\
217 $(filter \
218 $(addprefix %/,$(shell sed -ne's/^D \([^\t]\+\).*$$/\1/p' $(1) 2>/dev/null)), \
219 $($(name)-srcs) $($(name)-gens) $($(name)-extra-specs)), \
220 $($(name)-gens))
221
222# Adds dependency rules
223# $1 source file
224add_ada_deps = \
225 $(call src-to-obj,,$(1)): $(1) \
226 $(call create_ada_deps,$(call src-to-ali,,$(1)))
227
Nico Hubere86fff92017-03-04 13:20:37 +0100228# Writes a compilation rule for Ada sources
Nico Huber5e9b1b52016-10-08 22:09:33 +0200229# $1 source type (ads, adb)
230# $2 source files (including the colon)
231# $3 obj path prefix (including the trailing slash)
Nico Huber78ca5822017-03-05 13:51:49 +0100232# $4 compiler flags (if empty, $(ADAFLAGS) apply)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200233define add_ada_rule
234$(2) $(3)%.o: %.$(1)
235 @printf " COMPILE $$(subst $(obj)/,,$$@)\n"
236 $(CC) \
Nico Huber78ca5822017-03-05 13:51:49 +0100237 $(if $(4),$(4),$(ADAFLAGS)) \
238 $(addprefix -I,$($(name)-ada-dirs) $($(name)-extra-incs)) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200239 -c -o $$@ $$<
240endef
241
242# For sources
243$(foreach type,ads adb, \
244 $(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-srcs))):,$(obj)/)))
245$(foreach file,$($(name)-srcs) $($(name)-gens), \
246 $(eval $(call add_ada_deps,$(file))))
247
248# For generated sources already in $(obj)/
249$(foreach type,ads adb, \
250 $(eval $(call add_ada_rule,$(type),$(call src-to-obj,,$(filter %.$(type),$($(name)-gens))):,)))
251
252# Ali files are generated along with the object file. They need an empty
253# recipe for correct updating.
254$($(name)-alis): %.ali: %.o ;
255
256# To support complex package initializations, we need to call the
257# emitted code explicitly. gnatbind gathers all the calls for us
Nico Huberf43881f2017-03-05 13:43:20 +0100258# and exports them as a procedure $(name)_adainit().
259ifeq ($(link-type),archive)
260$(name)-bind-dirs := $($(name)-extra-objs)
261$(name)-bind-flags := -a -n -L$(name)_ada
262$(name)-bind-alis = $(patsubst /%,%,$(subst $(dir $@),,$^))
263else ifeq ($(link-type),program)
264$(name)-bind-dirs := $(sort $(dir $($(name)-objs))) $($(name)-extra-objs)
265$(name)-bind-flags :=
266$(name)-bind-alis = $(subst $(dir $@),,$(call src-to-ali,,$($(name)-main-src)))
267endif
268$(obj)/b__$(prefixed-name).adb: $($(name)-alis)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200269 @printf " BIND $(subst $(obj)/,,$@)\n"
270 # We have to give gnatbind a simple filename (without leading
271 # path components) so just cd there.
272 cd $(dir $@) && \
Nico Huberf43881f2017-03-05 13:43:20 +0100273 $(GNATBIND) $(addprefix -aO,$(abspath $($(name)-bind-dirs))) \
274 $($(name)-bind-flags) -o $(notdir $@) $($(name)-bind-alis)
Nico Huber78ca5822017-03-05 13:51:49 +0100275$(eval $(call add_ada_rule,adb,$(obj)/b__$(prefixed-name).o:,,$(filter-out -gnatec=%,$(ADAFLAGS))))
Nico Huberf43881f2017-03-05 13:43:20 +0100276$(name)-objs += $(obj)/b__$(prefixed-name).o
Nico Huber5e9b1b52016-10-08 22:09:33 +0200277
Nico Hubere86fff92017-03-04 13:20:37 +0100278# Compilation rule for C sources
279$(call src-to-obj,,$(filter %.c,$($(name)-srcs))): $(obj)/%.o: %.c
280 @printf " COMPILE $(subst $(obj)/,,$@)\n"
281 $(CC) $(CFLAGS) -c -o $@ $<
282
Nico Huber5e9b1b52016-10-08 22:09:33 +0200283$(shell mkdir -p $(alldirs))
284
285$(name)-install-srcs = $(sort \
Nico Huberba378302017-07-09 18:56:24 +0200286 $($(name)-extra-specs) $(filter %.ads,$($(name)-srcs) $($(name)-gens)) \
Nico Huber5e9b1b52016-10-08 22:09:33 +0200287 $(foreach adb,$(filter %.adb,$($(name)-srcs)), \
288 $(shell grep -q '^U .*\<BN\>' $(call src-to-ali,,$(adb)) 2>/dev/null && echo $(adb))))
289
290$(name)-install-proof = \
291 $(filter $(addprefix %/,$(notdir $($(name)-install-srcs))),$($(name)-proof)) \
292 $(filter-out $(addprefix %/,$(notdir $($(name)-proof))),$($(name)-install-srcs))
293
Nico Huberba378302017-07-09 18:56:24 +0200294install: $(binary) $($(name)-alis) $($(name)-gens) $(libgpr)
Nico Huber5e9b1b52016-10-08 22:09:33 +0200295 install -d $(DESTDIR)/lib $(DESTDIR)/include $(DESTDIR)/proof
296 printf " INSTALL $(subst $(obj)/,,$(binary))\n"
297 install $(binary) $(DESTDIR)/lib/
298 $(foreach file,$($(name)-install) $(libgpr), \
299 printf " INSTALL $(subst $(obj)/,,$(file))\n"; \
300 install $(file) $(DESTDIR);)
301 printf " INSTALL $(cnf)\n"
302 install $(cnf) $(DESTDIR)/config
303 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-alis))
304 install $($(name)-alis) $(DESTDIR)/lib/
305 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-srcs))
306 install $($(name)-install-srcs) $(DESTDIR)/include/
307 printf " INSTALL %s\n" $(subst $(obj)/,,$($(name)-install-proof))
308 install $($(name)-install-proof) $(DESTDIR)/proof/
309
310clean::
311 rm -rf $(obj) $(name).gpr
312
313distclean: clean
314 rm -rf dest
315
316.PHONY: install clean distclean