# 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))

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

ifeq (,$(filter buildtest,$(MAKECMDGOALS)))
	ifneq (,$(BOARD_WHITELIST))
		ifeq (,$(filter $(BOARD),$(BOARD_WHITELIST)))
$(error This application only runs on following boards: $(BOARD_WHITELIST))
		endif
	endif

	ifneq (,$(filter $(BOARD),$(BOARD_BLACKLIST)))
$(error This application does not run on following boards: $(BOARD_BLACKLIST))
	endif
endif

# if you want to publish the board into the sources as an uppercase #define
BB = $(shell echo $(BOARD)|tr 'a-z' 'A-Z'|tr '-' '_')
CPUDEF = $(shell echo $(CPU)|tr 'a-z' 'A-Z'|tr '-' '_')
CFLAGS += -DBOARD_$(BB) -DCPU_$(CPUDEF)

BINDIRBASE ?= $(CURDIR)/bin
BINDIR ?= $(abspath $(BINDIRBASE)/$(BOARD))/

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

BOARD := $(strip $(BOARD))

# mandatory includes!
include $(RIOTBASE)/Makefile.modules
include $(RIOTBOARD)/$(BOARD)/Makefile.include
include $(RIOTCPU)/$(CPU)/Makefile.include
include $(RIOTBASE)/Makefile.dep

# 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

# Test if there where dependencies against a module in DISABLE_MODULE.
ifneq (, $(filter $(DISABLE_MODULE), $(USEMODULE)))
$(error "Required modules were disabled using DISABLE_MODULE: $(sort $(filter $(DISABLE_MODULE), $(USEMODULE)))")
endif

# Feature test default CFLAGS and LINKFLAGS for the set compiled.
include $(RIOTBASE)/Makefile.cflags

# make the RIOT version available to the program
GIT_STRING := $(shell git describe --always --abbrev=4 --dirty=-`hostname`)
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
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 doc term objsize buildsize buildsizes buildsizes-diff buildinfo

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,

## 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)

$(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 || exit 1; done
	rm -rf $(BINDIR) $(CLEANFILES)

flash: all
	$(FLASHER) $(FFLAGS)

term:
	$(TERMPROG) $(PORT)

doc:
	make -BC $(RIOTBASE) doc

debug:
	$(DEBUGGER) $(DEBUGGER_FLAGS)

# Extra make goals for testing and comparing changes.
include $(RIOTBASE)/Makefile.buildtests

# Export variables used throughout the whole make system:
include $(RIOTBASE)/Makefile.vars