1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/Makefile.include
René Kijewski 162850b332 make: Implement optional features
Fixes #1876

This PR introduces `FEATURES_OPTIONAL` which can be used to tell the
Make system, that the application would like to use some feature, but
the build should proceed even if the selected board cannot provide the
optional feature.

`make buildtest` and `make info-supported-boards` heed this variable
when examining the list of supported boards.

If a word is present in `FEATURES_REQUIRED` and `FEATURES_OPTIONAL`,
then `FEATURES_OPTIONAL` takes precedence.
2014-10-26 23:18:58 +01:00

248 lines
7.5 KiB
Makefile

# Provide a shallow sanity check. You cannot call `make` in a module directory.
export __RIOTBUILD_FLAG := RIOT
# set undefined variables
RIOTBASE ?= $(shell dirname "$(lastword $(MAKEFILE_LIST))")
RIOTBASE := $(abspath $(RIOTBASE))
RIOTCPU ?= $(RIOTBASE)/cpu
RIOTCPU := $(abspath $(RIOTCPU))
RIOTBOARD ?= $(RIOTBASE)/boards
RIOTBOARD := $(abspath $(RIOTBOARD))
BINDIRBASE ?= $(CURDIR)/bin
BINDIR ?= $(abspath $(BINDIRBASE)/$(BOARD))/
ifeq ($(QUIET),1)
AD=@
MAKEFLAGS += --no-print-directory
else
AD=
endif
BOARD := $(strip $(BOARD))
# provide common external programs for `Makefile.include`s
ifeq (,$(AXEL))
ifeq (0,$(shell which axel 2>&1 > /dev/null ; echo $$?))
AXEL := $(shell which axel)
endif
endif
ifeq (,$(WGET))
ifeq (0,$(shell which wget 2>&1 > /dev/null ; echo $$?))
WGET := $(shell which wget)
endif
endif
ifeq (,$(CURL))
ifeq (0,$(shell which curl 2>&1 > /dev/null ; echo $$?))
CURL := $(shell which curl)
endif
endif
ifeq (,$(WGET)$(CURL))
$(error Neither wget nor curl is installed!)
endif
ifeq (,$(DOWNLOAD_TO_STDOUT))
DOWNLOAD_TO_STDOUT := $(if $(CURL),$(CURL) -s,$(WGET) -q -O-)
endif
ifeq (,$(DOWNLOAD_TO_FILE))
ifneq (,$(AXEL))
DOWNLOAD_TO_FILE := $(AXEL) -n 4 -q -a -o
else
DOWNLOAD_TO_FILE := $(if $(WGET),$(WGET) -nv -c -O,$(CURL) -s -o)
endif
endif
ifeq (,$(UNZIP_HERE))
ifeq (0,$(shell which unzip 2>&1 > /dev/null ; echo $$?))
UNZIP_HERE := $(shell which unzip) -q
else
ifeq (0,$(shell which 7z 2>&1 > /dev/null ; echo $$?))
UNZIP_HERE := $(shell which 7z) x -bd
else
$(error Neither unzip nor 7z is installed.)
endif
endif
endif
# mandatory includes!
include $(RIOTBASE)/Makefile.modules
include $(RIOTBOARD)/$(BOARD)/Makefile.include
include $(RIOTCPU)/$(CPU)/Makefile.include
include $(RIOTBASE)/Makefile.dep
ifeq ($(strip $(MCU)),)
MCU = $(CPU)
endif
# import list of provided features
-include $(RIOTBOARD)/$(BOARD)/Makefile.features
# if you want to publish the board into the sources as an uppercase #define
BOARDDEF := $(shell echo $(BOARD) | tr 'a-z' 'A-Z' | tr '-' '_')
CPUDEF := $(shell echo $(CPU) | tr 'a-z' 'A-Z' | tr '-' '_')
MCUDEF := $(shell echo $(MCU) | tr 'a-z' 'A-Z' | tr '-' '_')
CFLAGS += -DBOARD_$(BOARDDEF)='"$(BOARD)"' -DRIOT_BOARD=BOARD_$(BOARDDEF)
CFLAGS += -DCPU_$(CPUDEF)='"$(CPU)"' -DRIOT_CPU=CPU_$(CPUDEF)
CFLAGS += -DMCU_$(MCUDEF)='"$(MCU)"' -DRIOT_MCU=MCU_$(MCUDEF)
# OSX fails to create empty archives. Provide a wrapper to catch that error.
ifneq (0, $(shell mkdir -p $(BINDIR); $(AR) -rc $(BINDIR)empty-archive.a 2> /dev/null; echo $$?))
AR := $(RIOTBASE)/dist/ar-wrapper $(AR)
endif
# Feature test default CFLAGS and LINKFLAGS for the set compiled.
include $(RIOTBASE)/Makefile.cflags
# make the RIOT version available to the program
ifeq ($(origin RIOT_VERSION), undefined)
GIT_STRING := $(shell git describe --always --abbrev=4 --dirty=-`hostname` 2> /dev/null)
ifneq (,$(GIT_STRING))
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
ifeq ($(strip $(GIT_BRANCH)),master)
RIOT_VERSION := $(GIT_STRING)
else
RIOT_VERSION := $(GIT_STRING)-$(GIT_BRANCH)
endif
else
RIOT_VERSION := UNKNOWN (builddir: $(RIOTBASE))
endif
endif
export CFLAGS += -DRIOT_VERSION='"$(RIOT_VERSION)"'
# the binaries to link
BASELIBS += $(BINDIR)$(BOARD)_base.a
BASELIBS += $(BINDIR)${APPLICATION}.a
BASELIBS += $(USEPKG:%=${BINDIR}%.a)
.PHONY: all clean flash term doc debug debug-server reset objdump
ELFFILE ?= $(BINDIR)$(APPLICATION).elf
HEXFILE ?= $(ELFFILE:.elf=.hex)
# variables used to complie and link c++
CPPMIX ?= $(if $(wildcard *.cpp),1,)
# We assume $(LINK) to be gcc-like. Use `LINKFLAGPREFIX :=` for ld-like linker options.
LINKFLAGPREFIX ?= -Wl,
DIRS += $(EXTERNAL_MODULE_DIRS)
## make script for your application. Build RIOT-base here!
all: ..build-message $(USEPKG:%=${BINDIR}%.a) $(APPDEPS)
$(AD)DIRS="$(DIRS)" "$(MAKE)" -C $(CURDIR) -f $(RIOTBASE)/Makefile.application
ifeq (,$(RIOTNOLINK))
ifeq ($(BUILDOSXNATIVE),1)
$(AD)$(if $(CPPMIX),$(CXX),$(LINK)) $(UNDEF) -o $(ELFFILE) $(BASELIBS) $(LINKFLAGS) $(LINKFLAGPREFIX)-no_pie
else
$(AD)$(if $(CPPMIX),$(CXX),$(LINK)) $(UNDEF) -o $(ELFFILE) $(LINKFLAGPREFIX)--start-group $(BASELIBS) -lm $(LINKFLAGPREFIX)--end-group $(LINKFLAGPREFIX)-Map=$(BINDIR)$(APPLICATION).map $(LINKFLAGS)
endif
$(AD)$(SIZE) $(ELFFILE)
$(AD)$(OBJCOPY) $(OFLAGS) $(ELFFILE) $(HEXFILE)
endif
..build-message:
@echo "Building application $(APPLICATION) for $(BOARD) w/ MCU $(MCU)."
# add extra include paths for packages in $(USEMODULE)
export USEMODULE_INCLUDES =
include $(RIOTBASE)/sys/Makefile.include
include $(RIOTBASE)/drivers/Makefile.include
USEMODULE_INCLUDES_ = $(shell echo $(USEMODULE_INCLUDES) | tr ' ' '\n' | awk '!a[$$0]++' | tr '\n' ' ')
INCLUDES += $(USEMODULE_INCLUDES_:%=-I%)
# The `clean` needs to be serialized before everything else.
ifneq (, $(filter clean, $(MAKECMDGOALS)))
all $(BASELIBS) $(USEPKG:%=$(RIOTBASE)/pkg/%/Makefile.include): clean
endif
# include Makefile.includes for packages in $(USEPKG)
$(RIOTBASE)/pkg/%/Makefile.include::
$(AD)"$(MAKE)" -C $(RIOTBASE)/pkg/$* Makefile.include
.PHONY: $(USEPKG:%=$(RIOTBASE)/pkg/%/Makefile.include)
-include $(USEPKG:%=$(RIOTBASE)/pkg/%/Makefile.include)
.PHONY: $(USEPKG:%=${BINDIR}%.a)
$(USEPKG:%=${BINDIR}%.a):
@mkdir -p ${BINDIR}
"$(MAKE)" -C $(RIOTBASE)/pkg/$(patsubst ${BINDIR}%.a,%,$@)
clean:
-@for i in $(USEPKG) ; do "$(MAKE)" -C $(RIOTBASE)/pkg/$$i clean ; done
-@rm -rf $(BINDIR)
distclean:
-@for i in $(USEPKG) ; do "$(MAKE)" -C $(RIOTBASE)/pkg/$$i distclean ; done
-@rm -rf $(BINDIRBASE)
flash: all
$(FLASHER) $(FFLAGS)
term:
$(TERMPROG) $(TERMFLAGS)
doc:
make -BC $(RIOTBASE) doc
debug:
$(DEBUGGER) $(DEBUGGER_FLAGS)
debug-server:
$(DEBUGSERVER) $(DEBUGSERVER_FLAGS)
reset:
$(RESET) $(RESET_FLAGS)
objdump:
$(PREFIX)objdump -S -D -h $(ELFFILE) | less
# Extra make goals for testing and comparing changes.
include $(RIOTBASE)/Makefile.buildtests
# Export variables used throughout the whole make system:
include $(RIOTBASE)/Makefile.vars
ifneq (, $(filter all, $(if $(MAKECMDGOALS), $(MAKECMDGOALS), all)))
EXPECT_ERRORS :=
# Test if there where dependencies against a module in DISABLE_MODULE.
ifneq (, $(filter $(DISABLE_MODULE), $(USEMODULE)))
$(shell $(COLOR_ECHO) "$(COLOR_RED)Required modules were disabled using DISABLE_MODULE:$(COLOR_RESET)"\
"$(sort $(filter $(DISABLE_MODULE), $(USEMODULE)))" 1>&2)
EXPECT_ERRORS := 1
endif
# Test if all feature requirements were met by the selected board.
ifneq (, $(filter-out $(FEATURES_PROVIDED) $(FEATURES_OPTIONAL), $(FEATURES_REQUIRED)))
$(shell $(COLOR_ECHO) "$(COLOR_RED)There are unsatisfied feature requirements:$(COLOR_RESET)"\
"$(sort $(filter-out $(FEATURES_PROVIDED) $(FEATURES_OPTIONAL), $(FEATURES_REQUIRED)))" 1>&2)
EXPECT_ERRORS := 1
endif
# If there is a whitelist, then test if the board is whitelisted.
ifneq (, $(BOARD_WHITELIST))
ifeq (, $(filter $(BOARD_WHITELIST), $(BOARD)))
$(shell $(COLOR_ECHO) "$(COLOR_RED)The selected BOARD=${BOARD} is not whitelisted:$(COLOR_RESET) ${BOARD_WHITELIST}" 1>&2)
EXPECT_ERRORS := 1
endif
endif
# If there is a blacklist, then test if the board is blacklisted.
ifneq (, $(BOARD_BLACKLIST))
ifneq (, $(filter $(BOARD_BLACKLIST), $(BOARD)))
$(shell $(COLOR_ECHO) "$(COLOR_RED)The selected BOARD=${BOARD} is blacklisted:$(COLOR_RESET) ${BOARD_BLACKLIST}" 1>&2)
EXPECT_ERRORS := 1
endif
endif
ifneq (, $(EXPECT_ERRORS))
$(shell $(COLOR_ECHO) "\n\n$(COLOR_RED)EXPECT ERRORS!$(COLOR_RESET)\n\n" 1>&2)
endif
endif