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

# set undefined variables
RIOTBASE ?= $(shell dirname "$(lastword $(MAKEFILE_LIST))")
export RIOTBASE := $(abspath $(RIOTBASE))

RIOTCPU ?= $(RIOTBASE)/cpu
export RIOTCPU := $(abspath $(RIOTCPU))

RIOTBOARD ?= $(RIOTBASE)/boards
export 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)

export CFLAGS

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

ifeq ($(QUIET),1)
	AD=@
else
	AD=
endif
export AD

BOARD := $(strip $(BOARD))

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

# 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

# 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

export ELFFILE ?= $(BINDIR)$(APPLICATION).elf
export HEXFILE ?= $(ELFFILE:.elf=.hex)

## make script for your application. Build RIOT-base here!
all: $(BINDIR)$(APPLICATION).a
	@echo "Building application $(APPLICATION) for $(BOARD) w/ MCU $(MCU)."
	"$(MAKE)" -C $(RIOTBOARD)/$(BOARD)
	"$(MAKE)" -C $(RIOTBASE)
ifeq (,$(RIOTNOLINK))
ifeq ($(BUILDOSXNATIVE),1)
	$(AD)$(LINK) $(UNDEF) -o $(ELFFILE) $(BASELIBS) $(LINKFLAGS) -Wl,-no_pie
else
	$(AD)$(LINK) $(UNDEF) -o $(ELFFILE) -Wl,--start-group $(BASELIBS) -lm -Wl,--end-group  -Wl,-Map=$(BINDIR)$(APPLICATION).map $(LINKFLAGS)
endif
	$(AD)$(SIZE) $(ELFFILE)
	$(AD)$(OBJCOPY) $(OFLAGS) $(ELFFILE) $(HEXFILE)
endif

# string array of all names of c files in dir
SRC = $(wildcard *.c)

# string array of all names replaced .c with .o
OBJ = $(SRC:%.c=${BINDIR}${APPLICATION}/%.o)

$(BINDIR)$(APPLICATION).a: $(OBJ)
	$(AD)$(AR) -rc $(BINDIR)$(APPLICATION).a $(OBJ)

# 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)))
    $(OBJ) $(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)

# pull in dependency info for *existing* .o files
-include $(OBJ:.o=.d)

$(BINDIR)$(APPLICATION)/%.o: %.c $(PROJDEPS) $(USEPKG:%=${BINDIR}%.a)
	@echo; echo "Compiling.... $*.c"; echo
	$(AD)mkdir -p "$(dir $@)"
	$(AD)$(CC) $(CFLAGS) $(INCLUDES) -c "$<" -o "$@"

$(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