.DEFAULT_GOAL := all

APPLICATION ?= blinky

PLATFORM ?= nrf52
TARGET_FILE ?= $(APPLICATION).elf

CC = $(CROSS_COMPILE)gcc
CPP = $(CROSS_COMPILE)cpp
CXX = $(CROSS_COMPILE)g++
OBJCOPY = $(CROSS_COMPILE)objcopy
SIZE = $(CROSS_COMPILE)size

SRC_DIR = src
OBJ_DIR = obj/$(PLATFORM)
BIN_DIR = bin/$(PLATFORM)

CPP_FLAGS += $(addprefix -I, $(INCLUDES))

C_SRCS = $(wildcard $(SRC_DIR)/*.c)
C_SRCS += $(wildcard $(SRC_DIR)/platform/$(PLATFORM)/*.c)
C_SRCS += $(wildcard $(SRC_DIR)/application/$(APPLICATION)/*.c)
C_OBJS = $(patsubst $(SRC_DIR)%,$(OBJ_DIR)%,$(patsubst %.c,%.c.o,$(C_SRCS)))

CC_SRCS = $(wildcard $(SRC_DIR)/*.cc)
CC_SRCS += $(wildcard $(SRC_DIR)/platform/$(PLATFORM)/*.cc)
CC_SRCS += $(wildcard $(SRC_DIR)/application/$(APPLICATION)/*.cc)
CC_OBJS = $(patsubst $(SRC_DIR)%,$(OBJ_DIR)%,$(patsubst %.cc,%.cc.o,$(CC_SRCS)))

OBJS = $(NRF_A_OBJS) $(NRF_C_OBJS) $(C_OBJS) $(CC_OBJS)

TARGET = $(BIN_DIR)/$(TARGET_FILE)
TARGET_HEX = $(patsubst %.elf,%.hex,$(TARGET))
TARGET_PACKAGE = $(patsubst %.hex,%.zip,$(TARGET_HEX))
THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))

INCLUDES += include/
INCLUDES += include/application/$(APPLICATION)

OPT = 3
C_FLAGS += -O$(OPT) -g$(OPT)
C_FLAGS += -Wall -Werror
C_FLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
C_FLAGS += -DPLATFORM_$(PLATFORM)

CXX_FLAGS += -O$(OPT) -g$(OPT)
CXX_FLAGS += -Wall -Werror
CXX_FLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
CXX_FLAGS += -DPLATFORM_$(PLATFORM)

LIBS += c nosys m

include config/build/$(PLATFORM)/$(APPLICATION)/Makefile.$(APPLICATION)

.PHONY: all install uninstall clean distclean debug
all: $(TARGET)

debug:
	@echo $(CC_OBJS)

clean:
	rm -f $(TARGET) $(TARGET_HEX) $(TARGET_PACKAGE)
	rm -f $(OBJS) $(patsubst %.o,%.d,$(OBJS))

distclean:
	rm -rf bin obj

$(TARGET): $(OBJS) $(THIS_MAKEFILE)
	@mkdir -p $(dir $@)
	$(CXX) $(CXX_FLAGS) $(LD_FLAGS) $(OBJS) $(addprefix -l,$(LIBS)) -o $@
	ln -sf $(shell pwd)/$@ $(shell pwd)/bin/firmware.elf
	$(SIZE) -x $@

$(TARGET_HEX): $(TARGET) $(THIS_MAKEFILE)
	$(OBJCOPY) -O ihex $(TARGET) $(TARGET_HEX)
	ln -sf $(shell pwd)/$@ $(shell pwd)/bin/firmware.hex

$(OBJ_DIR)/%.d: $(SRC_DIR)/%.c $(THIS_MAKEFILE)
	@mkdir -p $(dir $@)
	$(CPP) -MM -MF $@ -MP -MT $(patsubst %.d,%.o,$@) $(C_FLAGS) $(CPP_FLAGS) $(patsubst $(OBJ_DIR)/%.d,$(SRC_DIR)/%.c,$@)

$(OBJ_DIR)/%.d: $(SRC_DIR)/%.cc $(THIS_MAKEFILE)
	@mkdir -p $(dir $@)
	$(CPP) -MM -MF $@ -MP -MT $(patsubst %.d,%.o,$@) $(CXX_FLAGS) $(CPP_FLAGS) $(patsubst $(OBJ_DIR)/%.d,$(SRC_DIR)/%.cc,$@)

$(OBJ_DIR)/%.cc.o: $(SRC_DIR)/%.cc $(THIS_MAKEFILE)
	@mkdir -p $(dir $@)
	$(CXX) -c $(CPP_FLAGS) $(CXX_FLAGS) $< -o $@

$(OBJ_DIR)/%.c.o: $(SRC_DIR)/%.c $(THIS_MAKEFILE)
	@mkdir -p $(dir $@)
	$(CC) -c $(CPP_FLAGS) $(C_FLAGS) $< -o $@

ifeq "$(findstring $(MAKECMDGOALS), clean distclean)" ""
-include $(patsubst %.o,%.d,$(OBJS))
endif