Skip to content
Snippets Groups Projects
Makefile.include 22.73 KiB
# 'Makefile.include' directory, must be evaluated before other 'include'
_riotbase := $(dir $(lastword $(MAKEFILE_LIST)))

# include RIOT_MAKEFILES_GLOBAL_PRE configuration files
# allows setting user specific system wide configuration parsed before the body
# of $(RIOTBASE)/Makefile.include
include $(RIOT_MAKEFILES_GLOBAL_PRE)

# Globally set default goal to `all`
.DEFAULT_GOAL := all

# include Makefile.local if it exists
-include Makefile.local

# set undefined variables
RIOTBASE       ?= $(_riotbase)
CCACHE_BASEDIR ?= $(RIOTBASE)
RIOTCPU        ?= $(RIOTBASE)/cpu
RIOTBOARD      ?= $(RIOTBASE)/boards
RIOTMAKE       ?= $(RIOTBASE)/makefiles
RIOTPKG        ?= $(RIOTBASE)/pkg
RIOTTOOLS      ?= $(RIOTBASE)/dist/tools
RIOTPROJECT    ?= $(shell git rev-parse --show-toplevel 2>/dev/null || pwd)
GITCACHE       ?= $(RIOTTOOLS)/git/git-cache
GIT_CACHE_DIR  ?= $(HOME)/.gitcache
BUILD_DIR      ?= $(RIOTBASE)/build
APPDIR         ?= $(CURDIR)
BINDIRBASE     ?= $(APPDIR)/bin
BINDIR         ?= $(BINDIRBASE)/$(BOARD)
PKGDIRBASE     ?= $(BINDIRBASE)/pkg/$(BOARD)
DLCACHE        ?= $(RIOTTOOLS)/dlcache/dlcache.sh
DLCACHE_DIR    ?= $(RIOTBASE)/.dlcache

__DIRECTORY_VARIABLES := \
  RIOTBASE \
  RIOTCPU \
  RIOTBOARD \
  RIOTMAKE \
  RIOTPKG \
  RIOTTOOLS \
  RIOTPROJECT \
  APPDIR \
  BUILD_DIR \
  BINDIRBASE \
  BINDIR \
  CCACHE_BASEDIR \
  GITCACHE \
  PKGDIRBASE \
  DLCACHE_DIR \
  #

# Make all paths absolute.
override RIOTBASE       := $(abspath $(RIOTBASE))
override CCACHE_BASEDIR := $(abspath $(CCACHE_BASEDIR))
override RIOTCPU        := $(abspath $(RIOTCPU))
override RIOTBOARD      := $(abspath $(RIOTBOARD))
override RIOTMAKE       := $(abspath $(RIOTMAKE))
override RIOTPKG        := $(abspath $(RIOTPKG))
override RIOTTOOLS      := $(abspath $(RIOTTOOLS))
override RIOTPROJECT    := $(abspath $(RIOTPROJECT))
override GITCACHE       := $(abspath $(GITCACHE))
override APPDIR         := $(abspath $(APPDIR))
override BUILD_DIR      := $(abspath $(BUILD_DIR))
override BINDIRBASE     := $(abspath $(BINDIRBASE))
override BINDIR         := $(abspath $(BINDIR))
override PKGDIRBASE     := $(abspath $(PKGDIRBASE))
override DLCACHE_DIR    := $(abspath $(DLCACHE_DIR))

# Ensure that all directories are set and don't contain spaces.
ifneq (, $(filter-out 1, $(foreach v,$(__DIRECTORY_VARIABLES),$(words $($(v))))))
  $(info Aborting compilation for your safety.)
  $(info Related variables = $(__DIRECTORY_VARIABLES))
  $(error Make sure no path override is empty or contains spaces!)
endif

# Use absolute paths in recusive "make" even if overriden on command line.
MAKEOVERRIDES += $(foreach v,$(__DIRECTORY_VARIABLES),$(v)=$($(v)))

# Path to the current directory relative to RIOTPROJECT
# trailing '/' is important when RIOTPROJECT == CURDIR
BUILDRELPATH ?= $(patsubst $(RIOTPROJECT)/%,%,$(CURDIR)/)

# get host operating system
OS := $(shell uname)

# set python path, e.g. for tests
PYTHONPATH := $(RIOTBASE)/dist/pythonlibs/:$(PYTHONPATH)

# Include Docker settings near the top because we need to build the environment
# command line before some of the variable origins are overwritten below when
# using abspath, strip etc.
include $(RIOTMAKE)/docker.inc.mk

# include color echo macros
include $(RIOTMAKE)/color.inc.mk

# include concurrency helpers
include $(RIOTMAKE)/info-nproc.inc.mk

GLOBAL_GOALS += buildtest info-boards-supported info-boards-features-missing info-buildsizes info-buildsizes-diff
ifneq (, $(filter $(GLOBAL_GOALS), $(MAKECMDGOALS)))
  BOARD=none
endif

ifeq (none,$(BOARD))
  include $(RIOTMAKE)/info-global.inc.mk
  include $(RIOTMAKE)/buildtests.inc.mk
else

all: link

include $(RIOTMAKE)/info.inc.mk

# Static code analysis tools provided by LLVM
include $(RIOTMAKE)/scan-build.inc.mk

export RIOTBUILD_CONFIG_HEADER_C = $(BINDIR)/riotbuild/riotbuild.h

ifeq ($(OS),Darwin)
  OPEN   := open
else
  OPEN   := xdg-open
endif

QUIET ?= 1

ifeq ($(QUIET),1)
  Q=@
  MAKEFLAGS += --no-print-directory
else
  Q=
endif

QQ=

# Set this to 1 to enable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
DEVELHELP ?= 0
ifeq ($(DEVELHELP),1)
  CFLAGS += -DDEVELHELP
endif

# Fail on warnings. Can be overridden by `make WERROR=0`.
WERROR ?= 1
export WERROR
ifeq ($(WERROR),1)
  CFLAGS += -Werror
endif

WPEDANTIC ?= 0
export WPEDANTIC
ifeq ($(WPEDANTIC),1)
  CFLAGS += -Wpedantic
endif

# Provide a shallow sanity check. You cannot call `make` in a module directory.
export __RIOTBUILD_FLAG := RIOT

BOARD := $(strip $(BOARD))
APPLICATION := $(strip $(APPLICATION))

# provide common external programs for `Makefile.include`s

ifeq (,$(and $(DOWNLOAD_TO_STDOUT),$(DOWNLOAD_TO_FILE)))
  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))
    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

# Tool saving stdin to a file only on content update.
# It keeps the file timestamp if it would end up the same.
LAZYSPONGE ?= $(RIOTTOOLS)/lazysponge/lazysponge.py
LAZYSPONGE_FLAGS ?= $(if $(filter 1,$(QUIET)),,--verbose)

ifeq (, $(APPLICATION))
    $(error An application name must be specified as APPLICATION.)
endif
ifneq (0,$(shell test -d $(RIOTBOARD)/$(BOARD); echo $$?))
    $(error The specified board $(BOARD) does not exist.)
endif

# Use TOOLCHAIN environment variable to select the toolchain to use.
# Default for macOS: llvm; for other OS: gnu
ifeq ($(BOARD),native)
ifeq ($(OS),Darwin)
TOOLCHAIN ?= llvm
endif
endif
TOOLCHAIN ?= gnu

# TOOLCHAIN = clang is an alias for TOOLCHAIN = llvm
ifeq (clang,$(TOOLCHAIN))
# use override so that we can redefine a variable set on the command line (as
# opposed to one set in the environment)
override TOOLCHAIN := llvm
endif
# TOOLCHAIN = gcc is an alias for TOOLCHAIN = gnu
ifeq (gcc,$(TOOLCHAIN))
# use override so that we can redefine a variable set on the command line (as
# opposed to one set in the environment)
override TOOLCHAIN := gnu
endif

ifeq (,$(TOOLCHAIN))
override TOOLCHAIN := gnu
endif

export TOOLCHAIN

# default toolchain prefix, defaults to target triple followed by a dash, you
# will most likely not need to touch this.
export PREFIX ?= $(if $(TARGET_ARCH),$(TARGET_ARCH)-)

# Add standard include directories
INCLUDES += -I$(RIOTBASE)/core/include -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/sys/include

# process provided features
include $(RIOTBOARD)/$(BOARD)/Makefile.features

# mandatory includes!
include $(RIOTMAKE)/pseudomodules.inc.mk
include $(RIOTMAKE)/defaultmodules.inc.mk

# Include Board and CPU configuration
INCLUDES += $(addprefix -I,$(wildcard $(RIOTBOARD)/$(BOARD)/include))
include $(RIOTBOARD)/$(BOARD)/Makefile.include
INCLUDES += -I$(RIOTCPU)/$(CPU)/include
include $(RIOTCPU)/$(CPU)/Makefile.include

# Sanity check
# The check is only done after 'include $(RIOTBOARD)/$(BOARD)/Makefile.include'
# because we need to have the 'CPU' variable defined
ifeq (,$(filter $(RIOTCPU)/$(CPU)/Makefile.features,$(MAKEFILE_LIST)))
  $(error $$(RIOTCPU)/$$(CPU)/Makefile.features must have been included by the board / board common Makefile.features)
endif

# Assume GCC/GNU as supported toolchain if CPU's Makefile.include doesn't
# provide this macro
TOOLCHAINS_SUPPORTED ?= gnu
# Import all toolchain settings
include $(RIOTMAKE)/toolchain/$(TOOLCHAIN).inc.mk

# Tell ccache to pass the original file to the compiler, instead of passing the
# preprocessed code. Without this setting, the compilation will fail with
# -Wimplicit-fallthrough warnings even when the fall through case is properly
# commented because the preprocessor has stripped the comments from the code.
# This also fixes some other false warnings when compiling with LLVM/Clang.
# The environment variable only affects builds with ccache (e.g. on CI/Murdock).
# Non cached builds are not affected in any way.
# For more information, see http://petereisentraut.blogspot.com/2011/09/ccache-and-clang-part-2.html
export CCACHE_CPP2=yes

# get number of interfaces straight before resolving dependencies
GNRC_NETIF_NUMOF ?= 1

ifneq ($(GNRC_NETIF_NUMOF),1)
  CFLAGS += -DGNRC_NETIF_NUMOF=$(GNRC_NETIF_NUMOF)
endif

# handle removal of default modules
USEMODULE += $(filter-out $(DISABLE_MODULE), $(DEFAULT_MODULE))

# process dependencies
include $(RIOTBASE)/Makefile.dep

ifeq ($(strip $(MCU)),)
	MCU = $(CPU)
endif

# set some settings useful for continuous integration builds
ifeq ($(RIOT_CI_BUILD),1)
    RIOT_VERSION_OVERRIDE:=buildtest
    ifneq ($(filter $(BOARD_INSUFFICIENT_MEMORY), $(BOARD)),)
        $(info CI-build: skipping link step)
        RIOTNOLINK:=1
    endif
    # be more quiet when building for CI
    QQ:=@
endif

# 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 $$?; rm -f $(BINDIR)/empty-archive.a 2>&1 > /dev/null))
	AR := $(RIOTBASE)/dist/ar-wrapper $(AR)
endif

# Feature test default CFLAGS and LINKFLAGS for the set compiled.
include $(RIOTMAKE)/cflags.inc.mk

# Include VERSION for releases
-include $(RIOTBASE)/VERSION

# make the RIOT version available to the program
ifeq ($(origin RIOT_VERSION), undefined)
  GIT_STRING := $(shell git --git-dir="$(RIOTBASE)/.git" describe --always --abbrev=4 2> /dev/null)
  ifneq (,$(GIT_STRING))
    GIT_BRANCH := $(shell git --git-dir="$(RIOTBASE)/.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

# Set module by prepending APPLICATION name with 'application_'.
# It prevents conflict with application and modules with the same name.
APPLICATION_MODULE ?= application_$(APPLICATION)

# the binaries to link
BASELIBS += $(BINDIR)/$(APPLICATION_MODULE).a
BASELIBS += $(APPDEPS)


# add extra include paths for packages in $(USEMODULE)
export USEMODULE_INCLUDES =

include $(RIOTBASE)/sys/Makefile.include
include $(RIOTBASE)/drivers/Makefile.include

# include Makefile.includes for packages in $(USEPKG)
-include $(USEPKG:%=$(RIOTPKG)/%/Makefile.include)

# include external modules configuration
-include $(EXTERNAL_MODULE_DIRS:%=%/Makefile.include)

# Deduplicate includes without sorting them
# see https://stackoverflow.com/questions/16144115/makefile-remove-duplicate-words-without-sorting
define uniq
  $(eval seen :=)
  $(foreach _,$1,$(if $(filter $_,$(seen)),,$(eval seen += $_)))
  $(seen)
endef

USEMODULE_INCLUDES_ = $(strip $(call uniq,$(USEMODULE_INCLUDES)))

INCLUDES += $(USEMODULE_INCLUDES_:%=-I%)


# include bindist target
include $(RIOTMAKE)/bindist.inc.mk

# Add all USEMODULE modules to CFLAGS and populate BASELIBS
include $(RIOTMAKE)/modules.inc.mk


.PHONY: all link clean flash flash-only term doc debug debug-server reset objdump help info-modules
.PHONY: print-size elffile binfile hexfile
.PHONY: ..in-docker-container

# Targets that depend on FORCE will always be rebuilt. Contrary to a .PHONY
# target, they are considered real files and the modification timestamp is taken
# into account.
#
# FORCE is useful for goals that may keep outputs unchanged (for example, if it
# depends on environment or configuration variables). If the goal were .PHONY, it
# would trigger a rebuild of all its dependents regardless of file modification.
#
# As general rule, use .PHONY only for non-file targets.
#
# For more information, see:
# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
# https://www.gnu.org/software/make/manual/html_node/Force-Targets.html
.PHONY: FORCE

ELFFILE ?= $(BINDIR)/$(APPLICATION).elf
HEXFILE ?= $(ELFFILE:.elf=.hex)
BINFILE ?= $(ELFFILE:.elf=.bin)

# Targets to get given file
elffile: $(ELFFILE)
hexfile: $(HEXFILE)
binfile: $(BINFILE)

# variables used to compile 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)

# Define dependencies required for building (headers, downloading source files,)
BUILDDEPS += $(RIOTBUILD_CONFIG_HEADER_C)
BUILDDEPS += pkg-prepare
BUILDDEPS += $(APPDEPS)

# Save value to verify it is not modified later
_BASELIBS_VALUE_BEFORE_USAGE := $(BASELIBS)

# Linker rule
$(ELFFILE): FORCE
ifeq ($(BUILDOSXNATIVE),1)
  _LINK = $(if $(CPPMIX),$(LINKXX),$(LINK)) $(UNDEF) $$(find $(BASELIBS) -size +8c) $(LINKFLAGS) $(LINKFLAGPREFIX)-no_pie
else
  _LINK = $(if $(CPPMIX),$(LINKXX),$(LINK)) $(UNDEF) $(LINKFLAGPREFIX)--start-group $(BASELIBS) -lm $(LINKFLAGPREFIX)--end-group $(LINKFLAGS) $(LINKFLAGPREFIX)-Map=$(BINDIR)/$(APPLICATION).map
endif # BUILDOSXNATIVE

# include bootloaders support. When trying to overwrite one variable
# like HEXFILE, the value will already have been evaluated when declaring
# the link target. Therefore, it must be placed before `link`.
include $(RIOTMAKE)/boot/riotboot.mk

ifeq ($(BUILD_IN_DOCKER),1)
link: ..in-docker-container
else
ifeq (,$(RIOTNOLINK))
link: ..compiler-check ..build-message $(ELFFILE) $(HEXFILE) print-size
else
link: ..compiler-check ..build-message $(BASELIBS)
endif # RIOTNOLINK

$(ELFFILE): $(BASELIBS)
	$(Q)$(_LINK) -o $@

$(BINDIR)/$(APPLICATION_MODULE).a: pkg-build $(BUILDDEPS)
	$(Q)DIRS="$(DIRS)" "$(MAKE)" -C $(APPDIR) -f $(RIOTMAKE)/application.inc.mk
$(BINDIR)/$(APPLICATION_MODULE).a: FORCE

# Other modules are built by application.inc.mk and packages building
_SUBMAKE_LIBS = $(filter-out $(BINDIR)/$(APPLICATION_MODULE).a $(APPDEPS), $(BASELIBS))
$(_SUBMAKE_LIBS): $(BINDIR)/$(APPLICATION_MODULE).a pkg-build

# 'print-size' triggers a rebuild. Use 'info-buildsize' if you do not need to rebuild.
print-size: $(ELFFILE)
	$(Q)$(SIZE) $(SIZEFLAGS) $<

%.hex: %.elf
	$(Q)$(OBJCOPY) $(OFLAGS) -Oihex $< $@

%.bin: %.elf
	$(Q)$(OBJCOPY) $(OFLAGS) -Obinary $< $@

endif # BUILD_IN_DOCKER

# Check given command is available in the path
#   check_cmd 'command' 'description'
define check_cmd
	@command -v $1 >/dev/null 2>&1 || \
	  { $(COLOR_ECHO) \
	    '$(COLOR_RED)$2 $1 is required but not found in PATH.  Aborting.$(COLOR_RESET)'; \
	    exit 1;}
endef

..compiler-check:
	$(call check_cmd,$(CC),Compiler)

..build-message:
	@$(COLOR_ECHO) '$(COLOR_GREEN)Building application "$(APPLICATION)" for "$(BOARD)" with MCU "$(MCU)".$(COLOR_RESET)'
	@$(COLOR_ECHO)

# The `clean` needs to be serialized before everything else.
ifneq (, $(filter clean, $(MAKECMDGOALS)))
    all $(BASELIBS) $(BUILDDEPS) ..in-docker-container: clean
endif

.PHONY: pkg-prepare pkg-build pkg-build-%
pkg-prepare:
	-@for i in $(USEPKG) ; do "$(MAKE)" -C $(RIOTPKG)/$$i prepare ; done

pkg-build: $(USEPKG:%=pkg-build-%)
pkg-build-%: $(BUILDDEPS)
	$(QQ)"$(MAKE)" -C $(RIOTPKG)/$*

clean:
	-@for i in $(USEPKG) ; do "$(MAKE)" -C $(RIOTPKG)/$$i clean ; done
	-@rm -rf $(BINDIR)
	-@rm -rf $(SCANBUILD_OUTPUTDIR)

# Remove intermediates, but keep the .elf, .hex and .map etc.
clean-intermediates:
	-@for i in $(USEPKG) ; do "$(MAKE)" -C $(RIOTPKG)/$$i distclean ; done
	-@rm -rf $(BINDIR)/*.a $(BINDIR)/*/

clean-pkg:
	-@for i in $(USEPKG) ; do "$(MAKE)" -C $(RIOTPKG)/$$i distclean ; done

distclean:
	-@for i in $(USEPKG) ; do "$(MAKE)" -C $(RIOTPKG)/$$i distclean ; done
	-@rm -rf $(BINDIRBASE)

define flash-recipe
  $(call check_cmd,$(FLASHER),Flash program)
  $(FLASHER) $(FFLAGS)
endef

# Do not add dependencies to "flash" directly, use FLASHDEPS, as this is shared
# with flash-only too

flash: all $(FLASHDEPS)
	$(flash-recipe)

flash-only: $(FLASHDEPS)
	$(flash-recipe)

preflash: $(BUILD_BEFORE_FLASH)
	$(PREFLASHER) $(PREFFLAGS)

term: $(filter flash, $(MAKECMDGOALS)) $(TERMDEPS)
	$(call check_cmd,$(TERMPROG),Terminal program)
	$(TERMPROG) $(TERMFLAGS)

list-ttys:
	$(Q)$(RIOTTOOLS)/usb-serial/list-ttys.sh

doc:
	make -BC $(RIOTBASE) doc

debug:
	$(call check_cmd,$(DEBUGGER),Debug program)
	$(DEBUGGER) $(DEBUGGER_FLAGS)

debug-server:
	$(call check_cmd,$(DEBUGSERVER),Debug server program)
	$(DEBUGSERVER) $(DEBUGSERVER_FLAGS)

emulate:
	$(call check_cmd,$(EMULATOR),Emulation program)
	$(EMULATOR) $(EMULATOR_FLAGS)
reset:
	$(call check_cmd,$(RESET),Reset program)
	$(RESET) $(RESET_FLAGS)

TESTS ?= $(foreach file,$(wildcard $(APPDIR)/tests/*),\
                        $(shell test -f $(file) -a -x $(file) && echo $(file)))
test: $(TEST_DEPS)
	$(Q) for t in $(TESTS); do \
		$$t || exit 1; \
	done

# Default OBJDUMPFLAGS for platforms which do not specify it:
OBJDUMPFLAGS ?= -S -D -h

objdump:
	$(call check_cmd,$(OBJDUMP),Objdump program)
	$(OBJDUMP) $(OBJDUMPFLAGS) $(ELFFILE) | less

# Support Eclipse IDE.
include $(RIOTMAKE)/eclipse.inc.mk

# Export variables used throughout the whole make system:
include $(RIOTMAKE)/vars.inc.mk

# Include build targets for selected tools
include $(RIOTMAKE)/tools/targets.inc.mk

# Warn if the selected board and drivers don't provide all needed features:
ifneq (, $(filter all flash, $(if $(MAKECMDGOALS), $(MAKECMDGOALS), all)))
  EXPECT_ERRORS :=
  EXPECT_CONFLICT :=

  # 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)
    USEMODULE := $(filter-out $(DISABLE_MODULE), $(USEMODULE))
    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

  # Test if any used feature conflict with another one.
  CONFLICT := $(foreach var,$(FEATURES_CONFLICT),$(if $(filter $(words $(subst :, ,$(var))),$(words $(filter $(FEATURES_USED),$(subst :, ,$(var))))),$(subst :, ,$(var))))
  ifneq (, $(strip $(CONFLICT)))
    $(shell $(COLOR_ECHO) "$(COLOR_YELLOW)The following features may conflict:$(COLOR_RESET)"\
                          "$(COLOR_GREEN)$(sort $(filter $(FEATURES_USED), $(CONFLICT)))$(COLOR_RESET)" 1>&2)
    ifneq (, $(FEATURES_CONFLICT_MSG))
        $(shell $(COLOR_ECHO) "$(COLOR_YELLOW)Rationale: $(COLOR_RESET)$(FEATURES_CONFLICT_MSG)" 1>&2)
    endif
    EXPECT_CONFLICT := 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

  #  test if toolchain is supported.
  ifeq (,$(filter $(TOOLCHAIN),$(TOOLCHAINS_SUPPORTED)))
    $(shell $(COLOR_ECHO) "$(COLOR_RED)The selected TOOLCHAIN=$(TOOLCHAIN) is not supported.$(COLOR_RESET)\nSupported toolchains: $(TOOLCHAINS_SUPPORTED)" 1>&2)
    EXPECT_ERRORS := 1
  endif

  # If there is a blacklist, then test if the board is blacklisted.
  ifneq (,$(TOOLCHAINS_BLACKLIST))
    ifneq (,$(filter $(TOOLCHAIN),$(TOOLCHAINS_BLACKLIST)))
      $(shell $(COLOR_ECHO) "$(COLOR_RED)The selected TOOLCHAIN=$(TOOLCHAIN) is blacklisted:$(COLOR_RESET) $(TOOLCHAINS_BLACKLIST)" 1>&2)
      EXPECT_ERRORS := 1
    endif
  endif

  ifneq (, $(EXPECT_CONFLICT))
    $(shell $(COLOR_ECHO) "\n$(COLOR_YELLOW)EXPECT undesired behaviour!$(COLOR_RESET)" 1>&2)
  endif

  ifneq (, $(EXPECT_ERRORS))
    $(shell $(COLOR_ECHO) "\n\n$(COLOR_RED)EXPECT ERRORS!$(COLOR_RESET)\n\n" 1>&2)
  endif

endif

help:
	@$(MAKE) -qp | sed -ne 's/\(^[a-z][a-z_-]*\):.*/\1/p' | sort | uniq

ifneq (,$(filter iotlab-m3 wsn430-v1_3b wsn430-v1_4,$(BOARD)))
  ifneq (,$(filter iotlab-%,$(MAKECMDGOALS)))
    include $(RIOTBASE)/dist/testbed-support/Makefile.iotlab
  endif
endif
ifneq (,$(IOTLAB_NODE))
  # iot-lab serial and flasher
  include $(RIOTBASE)/dist/testbed-support/makefile.iotlab.single.inc.mk
endif

# Include desvirt Makefile
include $(RIOTTOOLS)/desvirt/Makefile.desvirt

# Build a header file with all common macro definitions and undefinitions
# make it depend on FORCE to re-run of the script every time even if the file exists
# The script will only touch the file if anything has changed since last time.
$(RIOTBUILD_CONFIG_HEADER_C): FORCE
	@mkdir -p '$(dir $@)'
	$(Q)'$(RIOTTOOLS)/genconfigheader/genconfigheader.sh' $(CFLAGS_WITH_MACROS) \
		| '$(LAZYSPONGE)' $(LAZYSPONGE_FLAGS) '$@'

CFLAGS_WITH_MACROS := $(CFLAGS)

ifneq (,$(RIOT_VERSION_OVERRIDE))
export CFLAGS_WITH_MACROS += -DRIOT_VERSION=\"$(RIOT_VERSION_OVERRIDE)\"
else
export CFLAGS_WITH_MACROS += -DRIOT_VERSION=\"$(RIOT_VERSION)\"
endif

CFLAGS := $(patsubst -D%,,$(CFLAGS))
CFLAGS := $(patsubst -U%,,$(CFLAGS))
CFLAGS += -include '$(RIOTBUILD_CONFIG_HEADER_C)'

# include mcuboot support
include $(RIOTMAKE)/mcuboot.mk

# include Murdock helpers
include $(RIOTMAKE)/murdock.inc.mk
# Sanity check, 'all' should be the default goal
ifneq (all, $(.DEFAULT_GOAL))
  $(error .DEFAULT_GOAL := $(.DEFAULT_GOAL))
endif


# Detect if BASELIBS changed since its first use
ifneq ($(_BASELIBS_VALUE_BEFORE_USAGE),$(BASELIBS))
  $(warning $(sort $(filter-out $(_BASELIBS_VALUE_BEFORE_USAGE), $(BASELIBS)) \
                   $(filter-out $(BASELIBS), $(_BASELIBS_VALUE_BEFORE_USAGE))))
  $(error BASELIBS value changed)
endif

endif # BOARD=none

# include RIOT_MAKEFILES_GLOBAL_POST configuration files
# allows setting user specific system wide configuration parsed after the body
# of $(RIOTBASE)/Makefile.include
include $(RIOT_MAKEFILES_GLOBAL_POST)