diff options
author | Nico Huber <nico.h@gmx.de> | 2016-01-14 01:13:33 +0100 |
---|---|---|
committer | Nico Huber <nico.h@gmx.de> | 2016-09-19 11:14:18 +0200 |
commit | 2e09d2b239ff2dfdba89011fd64d9a07da0d8717 (patch) | |
tree | 74a3e2f4fd172232e81c2881ae1e3dfaae7bdf9a /Makefile | |
parent | fec0328c5f653233859d4aec7dae0b94acb67e97 (diff) | |
download | coreboot-2e09d2b239ff2dfdba89011fd64d9a07da0d8717.tar.xz |
Make Ada a first class citizen
Some remarks on the make process:
o We usually leave Ada specs (.ads files which are like c headers)
together with the bodies (implementations in .adb files) in one
directory. So we have to know, where they live.
o If there is no matching .adb an .ads is a valid source file and
we'll generate an object file from it.
o Object files need to have the same basename as their source files :-/
That's why we put them in build/<class>/ dirs now.
o We track dependencies by looking at the compiler output (.ali files
which accompany every .o). This way we don't need any gnatmake
magic, or even more complex, less portable tools.
For ADAFLAGS_common, I simply copied the CFLAGS_common whilst dropping
everything unsupported and adding sane warning options.
The set of language features is highly restricted (see gnat.adc). This
should suit the embedded nature of coreboot and helps proving absence
of runtime errors with SPARK.
Change-Id: I70df9adbd467ecd2dc7c5c1cf418b7765aca4e93
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/13044
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Reviewed-by: Edward O'Callaghan <edward.ocallaghan@koparo.com>
Diffstat (limited to 'Makefile')
-rw-r--r-- | Makefile | 78 |
1 files changed, 74 insertions, 4 deletions
@@ -183,16 +183,32 @@ add-special-class= \ $(eval special-classes+=$(1)) # Converts one or more source file paths to their corresponding build/ paths. -# Only .c and .S get converted to .o, other files (like .ld) keep their name. +# Only .ads, adb, .c and .S get converted to .o, other files (like .ld) keep +# their name. # $1 stage name # $2 file path (list) src-to-obj=\ $(patsubst $(obj)/%,$(obj)/$(1)/%,\ $(patsubst $(obj)/$(1)/%,$(obj)/%,\ $(patsubst src/%,$(obj)/%,\ + $(patsubst %.ads,%.o,\ + $(patsubst %.adb,%.o,\ $(patsubst %.c,%.o,\ $(patsubst %.S,%.o,\ - $(subst .$(1),,$(2))))))) + $(subst .$(1),,$(2))))))))) + +# Converts one or more source file paths to the corresponding build/ paths +# of their Ada library information (.ali) files. +# $1 stage name +# $2 file path (list) +src-to-ali=\ + $(patsubst $(obj)/%,$(obj)/$(1)/%,\ + $(patsubst $(obj)/$(1)/%,$(obj)/%,\ + $(patsubst src/%,$(obj)/%,\ + $(patsubst %.ads,%.ali,\ + $(patsubst %.adb,%.ali,\ + $(subst .$(1),,\ + $(filter %.ads %.adb,$(2)))))))) # Clean -y variables, include Makefile.inc # Add paths to files in X-y to X-srcs @@ -229,7 +245,22 @@ endif # Eliminate duplicate mentions of source files in a class $(foreach class,$(classes),$(eval $(class)-srcs:=$(sort $($(class)-srcs)))) +# To track dependencies, we need all Ada specification (.ads) files in +# *-srcs. Extract / filter all specification files that have a matching +# body (.adb) file here (specifications without a body are valid sources +# in Ada). +$(foreach class,$(classes),$(eval $(class)-extra-specs := \ + $(filter \ + $(addprefix %/,$(patsubst %.adb,%.ads,$(notdir $(filter %.adb,$($(class)-srcs))))), \ + $(filter %.ads,$($(class)-srcs))))) +$(foreach class,$(classes),$(eval $(class)-srcs := \ + $(filter-out $($(class)-extra-specs),$($(class)-srcs)))) + $(foreach class,$(classes),$(eval $(class)-objs:=$(call src-to-obj,$(class),$($(class)-srcs)))) +$(foreach class,$(classes),$(eval $(class)-alis:=$(call src-to-ali,$(class),$($(class)-srcs)))) + +# For Ada includes +$(foreach class,$(classes),$(eval $(class)-ada-dirs:=$(sort $(dir $(filter %.ads %.adb,$($(class)-srcs)) $($(class)-extra-specs))))) # Save all objs before processing them (for dependency inclusion) originalobjs:=$(foreach var, $(addsuffix -objs,$(classes)), $($(var))) @@ -242,6 +273,17 @@ allsrcs:=$(foreach var, $(addsuffix -srcs,$(classes)), $($(var))) allobjs:=$(foreach var, $(addsuffix -objs,$(classes)), $($(var))) alldirs:=$(sort $(abspath $(dir $(allobjs)))) +# Reads dependencies from an Ada library information (.ali) file +# Only basenames (with suffix) are preserved so we have to look the +# paths up in $($(stage)-srcs). +# $1 stage name +# $2 ali file +create_ada_deps=$$(if $(2),\ + gnat.adc \ + $$(filter \ + $$(addprefix %/,$$(shell sed -ne's/^D \([^\t]\+\).*$$$$/\1/p' $(2) 2>/dev/null)), \ + $$($(1)-srcs) $$($(1)-extra-specs))) + # macro to define template macros that are used by use_template macro define create_cc_template # $1 obj class @@ -250,9 +292,13 @@ define create_cc_template # $4 additional dependencies ifn$(EMPTY)def $(1)-objs_$(2)_template de$(EMPTY)fine $(1)-objs_$(2)_template -$$(call src-to-obj,$1,$$(1).$2): $$(1).$2 $(KCONFIG_AUTOHEADER) $(4) +$$(call src-to-obj,$1,$$(1).$2): $$(1).$2 $$(call create_ada_deps,$1,$$(call src-to-ali,$1,$$(1).$2)) $(KCONFIG_AUTOHEADER) $(4) @printf " CC $$$$(subst $$$$(obj)/,,$$$$(@))\n" - $(CC_$(1)) -MMD $$$$(CPPFLAGS_$(1)) $$$$(CFLAGS_$(1)) -MT $$$$(@) $(3) -c -o $$$$@ $$$$< + $(CC_$(1)) \ + $$(if $$(filter-out ads adb,$(2)), \ + -MMD $$$$(CPPFLAGS_$(1)) $$$$(CFLAGS_$(1)) -MT $$$$(@), \ + $$$$(ADAFLAGS_$(1)) $$$$(addprefix -I,$$$$($(1)-ada-dirs))) \ + $(3) -c -o $$$$@ $$$$< en$(EMPTY)def end$(EMPTY)if endef @@ -267,6 +313,30 @@ $(foreach class,$(classes), \ foreach-src=$(foreach file,$($(1)-srcs),$(eval $(call $(1)-objs_$(subst .,,$(suffix $(file)))_template,$(basename $(file))))) $(eval $(foreach class,$(classes),$(call foreach-src,$(class)))) +# To supported complex package initializations, we need to call the +# emitted code explicitly. gnatbind gathers all the calls for us +# and exports them as a procedure $(stage)_adainit(). Every stage that +# uses Ada code has to call it! +define gnatbind_template +# $1 class +$$(obj)/$(1)/b__$(1).adb: $$$$(filter-out $$(obj)/$(1)/b__$(1).ali,$$$$($(1)-alis)) + @printf " BIND $$(subst $$(obj)/,,$$@)\n" + # We have to give gnatbind a simple filename (without leading + # path components) so just cd there. + cd $$(dir $$@) && \ + $$(GNATBIND_$(1)) -a -n \ + -L$(1)_ada -o $$(notdir $$@) \ + $$(subst $$(dir $$@),,$$^) +$$(obj)/$(1)/b__$(1).o: $$(obj)/$(1)/b__$(1).adb + @printf " CC $$(subst $$(obj)/,,$$@)\n" + $(CC_$(1)) $$(ADAFLAGS_$(1)) -c -o $$@ $$< +$(1)-objs += $$(obj)/$(1)/b__$(1).o +$($(1)-alis): %.ali: %.o +endef + +$(eval $(foreach class,$(classes), \ + $(if $($(class)-alis),$(call gnatbind_template,$(class))))) + DEPENDENCIES += $(addsuffix .d,$(basename $(allobjs))) -include $(DEPENDENCIES) |