# Use install.sh for Build Tools installation
# Use . export.sh for PATH settings

# https://stackoverflow.com/questions/1612278/pre-build-step-in-makefile

TARGET = CAN_FW

DEBUG = 1

OPT = -Og

ifeq ($(DEBUG), 1)
BUILD_DIR = build/$(MODEL)_Debug
else
BUILD_DIR = build/$(MODEL)_Release
endif

#######################################
# SOURCES
#######################################

C_SOURCES = \


CPP_SOURCES = \
$(wildcard libs/*.cpp) \
$(wildcard src/*.cpp) \
$(wildcard src/immo/*.cpp)


ASM_SOURCES = \


#######################################
# INCLUES
#######################################

# AS includes
AS_INCLUDES =

# C includes
C_INCLUDES =  \
-Ilibs \
-Isrc

#######################################
# OTHER MAKE VARIABLES
#######################################

CXX = arm-none-eabi-g++
CC = arm-none-eabi-gcc
AS = arm-none-eabi-gcc -x assembler-with-cpp
CP = arm-none-eabi-objcopy
SZ = arm-none-eabi-size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S

# mcu
MCU = -mcpu=cortex-m3 -mthumb

# AS defines
AS_DEFS =

# C defines
C_DEFS = -DSTM32F10X_CL -DHSE_VALUE=16000000 -DCAN_FIRMWARE=1

# CXX defines
CXX_DEFS = -DSTM32F10X_CL -DHSE_VALUE=16000000 -DCAN_FIRMWARE=1

ifeq ($(MODEL),M2)
C_DEFS += -DMOBICAR_1_2=1
CXX_DEFS += -DMOBICAR_1_2=1
endif

ifeq ($(MODEL),M3)
C_DEFS += -DMOBICAR_3=1
CXX_DEFS += -DMOBICAR_3=1
endif

# compile gcc flags
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections

CXXFLAGS = $(MCU) $(CXX_DEFS) $(C_INCLUDES) $(OPT)
CXXFLAGS += -Wall#											All warnings
CXXFLAGS += -fmessage-length=0#								Number of lines for error messages
CXXFLAGS += -fsigned-char#									Default char is signed
CXXFLAGS += -fdata-sections -ffunction-sections#			Place each function or data item into its own section (use garbage collector --gc-sections in linker)
CXXFLAGS += -ffreestanding#									Freestanding environment (without standard library)
CXXFLAGS += -Wuninitialized#								Uninitialized variables warning
CXXFLAGS += -Wpointer-arith#								Warning for arithmetic operations with 'void *'
CXXFLAGS += -Wshadow#										Warning if a local var shadows another one
CXXFLAGS += -Wlogical-op#									Warn about suspicious uses of logical operators in expressions
CXXFLAGS += -Waggregate-return#								Warn if any functions that return structures or unions are defined or called
CXXFLAGS += -Wfloat-equal#									Warn if floating-point values are used in equality comparisons
CXXFLAGS += -std=gnu++11#									C++ standart
CXXFLAGS += -fabi-version=0#								Fix ABI version
CXXFLAGS += -fno-exceptions#								Disable the generation of code needed to support C++ exceptions
CXXFLAGS += -fno-rtti#										Disable C++ runtime
CXXFLAGS += -fno-use-cxa-atexit#							Do not use standard library for calling destructors
CXXFLAGS += -fno-threadsafe-statics#						Do not emit the extra code to use the routines specified in the C++ ABI for thread-safe initialization of local statics


ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf -ggdb
CXXFLAGS += -g -gdwarf -ggdb
C_DEFS += -DDEBUG
CXX_DEFS += -DDEBUG
endif

# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
CXXFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"

#######################################
# LDFLAGS
#######################################
# link script
ifeq ($(MODEL),M2)
LDSCRIPT = sys/M1_CAN_FW.ld
endif
ifeq ($(MODEL),M3)
LDSCRIPT = sys/M3_CAN_FW.ld
endif

LDFLAGS = $(MCU)
LDFLAGS += -Wl,--gc-sections#						Dead code removal (linker garbage collector)
LDFLAGS += -Wl,--print-memory-usage#				Print FLASH/RAM memory table
LDFLAGS += -T$(LDSCRIPT)#							Linker script
# LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(TARGET).map#		MAP file
LDFLAGS += -nostartfiles#							Do not use startup code before the main()
LDFLAGS += -nodefaultlibs#							Do not use default libs
LDFLAGS += -nostdlib#								Do not use std lib
LDFLAGS += -Wl,--no-warn-rwx-segment#				Remove RWX warning


#######################################
# build the application
#######################################
# list of cpp program objects
OBJECTS = $(addprefix $(BUILD_DIR)/, $(CPP_SOURCES:.cpp=.cpp.o))

# list of C objects
OBJECTS += $(addprefix $(BUILD_DIR)/, $(C_SOURCES:.c=.c.o))

# list of ASM program objects
UPPER_CASE_ASM_SOURCES = $(filter %.S, $(ASM_SOURCES))
LOWER_CASE_ASM_SOURCES = $(filter %.s, $(ASM_SOURCES))

OBJECTS += $(addprefix $(BUILD_DIR)/, $(UPPER_CASE_ASM_SOURCES:.S=.S.o))
OBJECTS += $(addprefix $(BUILD_DIR)/, $(LOWER_CASE_ASM_SOURCES:.s=.s.o))

# default action
.DEFAULT_GOAL := all
all:
	@echo Use MODEL variable with debug/release target:
	@echo make -e MODEL=M2 debug
	@echo make -e MODEL=M2 release
	@echo make -e MODEL=M3 debug
	@echo make -e MODEL=M3 release

# Colors
NC =\e[0m
RED =\e[0;31m
GREEN =\e[0;32m
BLUE =\e[0;36m

.SECONDEXPANSION:

ERROR_HANDLER = && printf "$(GREEN)OK$(NC)\n" || (printf "$(RED)ERROR$(NC)\n"; exit 1)

$(BUILD_DIR)/%.cpp.o: %.cpp Makefile | $$(@D)/
	@printf "compile $(BLUE)$<$(NC) "
	@$(CXX) -E -c $(CXXFLAGS) $< -o $@ || (printf "$(RED)ERROR$(NC)\n"; exit 1)
	@iconv -f UTF-8 -t CP1251 $@ > $@.i
	@$(CXX) -c $(CXXFLAGS) $@.i -o $@ $(ERROR_HANDLER)

$(BUILD_DIR)/%.c.o: %.c Makefile | $$(@D)/
	@printf "compile $(BLUE)$<$(NC) "
	@$(CC) -c $(CFLAGS) $< -o $@ $(ERROR_HANDLER)

$(BUILD_DIR)/%.s.o: %.s Makefile | $$(@D)/
	@printf "compile $(BLUE)$<$(NC) "
	@$(AS) -c $(CFLAGS) $< -o $@ $(ERROR_HANDLER)

$(BUILD_DIR)/%.S.o: %.S Makefile | $$(@D)/
	@printf "compile $(BLUE)$<$(NC) "
	@$(AS) -c $(CFLAGS) $< -o $@ $(ERROR_HANDLER)

$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
	@printf "linking $(BLUE)$@$(NC)\n"
	@$(CXX) $(OBJECTS) $(LDFLAGS) -o $@ || (printf "$(RED)linker ERROR$(NC)\n"; exit 1)
#	$(SZ) $@

# https://www.cmcrossroads.com/article/making-directories-gnu-make
%/:
	@mkdir -p $@

$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf
	@printf "generate $(BLUE)$@$(NC) "
	@$(HEX) $< $@ $(ERROR_HANDLER)
	@sys/hex2fw.sh $@ || exit 1

ifeq ($(DEBUG), 1)
STARTMSG = Building $(MODEL) Debug
else
STARTMSG = Building $(MODEL) Release
endif

build_app:
	@printf "$(GREEN)-----------------------$(NC)\n"
	@printf "$(GREEN)  $(STARTMSG)$(NC)\n"
	@printf "$(GREEN)-----------------------$(NC)\n"
	@sys/version.sh;
#	@sys/changelog.sh;
	@make -j --no-print-directory --output-sync $(BUILD_DIR)/$(TARGET).hex
	@printf "$(GREEN)-----------------------$(NC)\n"

clean:
	@rm -rf $(BUILD_DIR)

debug:
	@make clean --no-print-directory
	@make build_app --no-print-directory

release:
	@make clean --no-print-directory -e DEBUG=0
	@make build_app --no-print-directory -e OPT=-Os DEBUG=0

printvars:
	@echo "MODEL: $(MODEL)"
	@echo "C_DEFS: $(C_DEFS)"
	@echo "CXX_DEFS: $(CXX_DEFS)"

-include $(OBJECTS:.o=.d)

# *** EOF ***