#------------------------------------------------------------------------------
#              VARIABLES APPENDED TO BY INCLUDED MAKEFILE FRAGMENTS
#------------------------------------------------------------------------------

# List of include directories for -I compiler option (-I added when used).
# Includes the BSP.
ALT_INCLUDE_DIRS :=

# List of library directories for -L linker option (-L added when used).
# Includes the BSP.
ALT_LIBRARY_DIRS :=

# List of library names for -l linker option (-l added when used).
# Includes the BSP.
ALT_LIBRARY_NAMES :=

# List of library names for -msys-lib linker option (-msys-lib added when used).
# These are libraries that might be located in the BSP and depend on the BSP
# library, or vice versa
ALT_BSP_DEP_LIBRARY_NAMES :=

# List of dependencies for the linker.  This is usually the full pathname
# of each library (*.a) file.
# Includes the BSP.
ALT_LDDEPS :=

# List of root library directories that support running make to build them.
# Includes the BSP and any ALT libraries.
MAKEABLE_LIBRARY_ROOT_DIRS :=

# Generic flags passed to the compiler for different types of input files.
ALT_CFLAGS :=
ALT_CXXFLAGS :=
ALT_CPPFLAGS :=
ALT_ASFLAGS :=
ALT_LDFLAGS :=

#------------------------------------------------------------------------------
#                                 TOOLS
#------------------------------------------------------------------------------
CC      := nios2-elf-gcc -xc
CXX     := nios2-elf-gcc -xc++
AS      := nios2-elf-gcc
AR      := nios2-elf-ar
LD      := nios2-elf-g++
NM      := nios2-elf-nm
RM      := rm -f
OBJDUMP := nios2-elf-objdump
OBJCOPY := nios2-elf-objcopy
STACKREPORT := nios2-stackreport
DOWNLOAD := nios2-download
FLASHPROG := nios2-flash-programmer

#------------------------------------------------------------------------------
#                           DEFAULT TARGET
#------------------------------------------------------------------------------

# Put "all" rule before included makefile fragments because they may
# define rules and we don't want one of those to become the default rule.
.PHONY : all
all : build_pre_process libs app build_post_process 

#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
#                           GENERATED SETTINGS START                         v
#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

#START GENERATED

# Define path to the application ELF. 
# It may be used by the makefile fragments so is defined before including them. 
# 
ELF := dhrystone.elf

# Paths to C, C++, and assembly source files.
C_SRCS += dhry21a.c
C_SRCS += dhry21b.c
C_SRCS += timers_b.c
CXX_SRCS :=
ASM_SRCS :=

# Path to root of object file tree.
OBJ_ROOT_DIR := obj

# Options to control objdump.
CREATE_OBJDUMP := 1
OBJDUMP_INCLUDE_SOURCE := 0
OBJDUMP_FULL_CONTENTS := 0

# Options to enable/disable optional files.
CREATE_ELF_DERIVED_FILES := 0
CREATE_LINKER_MAP := 1

# Common arguments for ALT_CFLAGSs
APP_CFLAGS_DEFINED_SYMBOLS := -DALT_RELEASE -DWANT_INLINE_STRCMP
APP_CFLAGS_UNDEFINED_SYMBOLS :=
APP_CFLAGS_OPTIMIZATION := -O3
APP_CFLAGS_DEBUG_LEVEL := -g1
APP_CFLAGS_WARNINGS := -Wall
APP_CFLAGS_USER_FLAGS := -funsigned-char -fno-inline

# Linker options that have default values assigned later if not
# assigned here.
LINKER_SCRIPT :=
CRT0 :=
SYS_LIB :=

# Define path to the root of the BSP.
BSP_ROOT_DIR := ../../bsp/hal_dhrystone
# Define absolute path to the root of the BSP.
ABS_BSP_ROOT_DIR := $(shell cd "$(BSP_ROOT_DIR)"; pwd)

ifeq ($(BSP_ROOT_DIR),)
$(error Edit Makefile and provide a value for BSP_ROOT_DIR)
endif

# Include makefile fragments.  Define variable ALT_LIBRARY_ROOT_DIR before
# including each makefile fragment so that it knows the path to itself.
BSP_INCLUDE_FILE := $(BSP_ROOT_DIR)/public.mk
ALT_LIBRARY_ROOT_DIR := $(BSP_ROOT_DIR)
include $(BSP_INCLUDE_FILE)
# C2H will need this to touch the BSP public.mk and avoid the sopc file out-of-date error during a BSP make
ABS_BSP_INCLUDE_FILE := $(ABS_BSP_ROOT_DIR)/public.mk

# List of application specific include directories, library directories and library names
APP_INCLUDE_DIRS :=
APP_LIBRARY_DIRS :=
APP_LIBRARY_NAMES :=

# Pre- and post- processor settings.
BUILD_PRE_PROCESS :=
BUILD_POST_PROCESS :=

OBJDUMP_INCLUDE_SOURCE := 1


#END GENERATED

#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#                            GENERATED SETTINGS END                           ^
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

#------------------------------------------------------------------------------
#                 VARIABLES DEPENDENT ON GENERATED CONTENT
#------------------------------------------------------------------------------

# If the BSP public.mk indicates that ALT_SIM_OPTIMIZE is set, rename the ELF 
# by prefixing it with RUN_ON_HDL_SIMULATOR_ONLY_.  
ifneq ($(filter -DALT_SIM_OPTIMIZE,$(ALT_CPPFLAGS)),)
ELF := RUN_ON_HDL_SIMULATOR_ONLY_$(ELF)
endif


# If the BSP public.mk indicates that ALT_PROVIDE_GMON is set, add option to download_elf target
ifneq ($(filter -DALT_PROVIDE_GMON,$(ALT_CPPFLAGS)),)
GMON_OUT_FILENAME := gmon.out
WRITE_GMON_OPTION := --write-gmon $(GMON_OUT_FILENAME)
endif

# Name of ELF application.
APP_NAME := $(basename $(ELF))

# Set to defaults if variables not already defined in settings.
ifeq ($(LINKER_SCRIPT),)
LINKER_SCRIPT := $(BSP_LINKER_SCRIPT)
endif
ifeq ($(CRT0),)
CRT0 := $(BSP_CRT0)
endif
ifeq ($(SYS_LIB),)
SYS_LIB := $(BSP_SYS_LIB)
endif

OBJDUMP_NAME := $(APP_NAME).objdump
OBJDUMP_FLAGS := --disassemble --syms --all-header
ifeq ($(OBJDUMP_INCLUDE_SOURCE),1)
OBJDUMP_FLAGS += --source
endif
ifeq ($(OBJDUMP_FULL_CONTENTS),1)
OBJDUMP_FLAGS += --full-contents
endif

# Create list of linker dependencies (*.a files).
APP_LDDEPS := $(ALT_LDDEPS) $(LDDEPS)

# Take lists and add required prefixes.
APP_INC_DIRS := $(addprefix -I, $(ALT_INCLUDE_DIRS) $(APP_INCLUDE_DIRS) $(INC_DIRS))
ASM_INC_PREFIX := -Wa,-I
APP_ASM_INC_DIRS := $(addprefix $(ASM_INC_PREFIX), $(ALT_INCLUDE_DIRS) $(APP_INCLUDE_DIRS) $(INC_DIRS))
APP_LIB_DIRS := $(addprefix -L, $(ALT_LIBRARY_DIRS) $(APP_LIBRARY_DIRS) $(LIB_DIRS))
APP_LIBS := $(addprefix -l, $(ALT_LIBRARY_NAMES) $(APP_LIBRARY_NAMES) $(LIBS))
APP_BSP_DEP_LIBS := $(addprefix -msys-lib=, $(ALT_BSP_DEP_LIBRARY_NAMES))

# Arguments for the C preprocessor, C/C++ compiler, assembler, and linker.
APP_CFLAGS := $(APP_CFLAGS_DEFINED_SYMBOLS) \
              $(APP_CFLAGS_UNDEFINED_SYMBOLS) \
              $(APP_CFLAGS_OPTIMIZATION) \
              $(APP_CFLAGS_DEBUG_LEVEL) \
              $(APP_CFLAGS_WARNINGS) \
              $(APP_CFLAGS_USER_FLAGS) \
              $(ALT_CFLAGS) \
              $(CFLAGS)

# Arguments only for the C++ compiler.
APP_CXXFLAGS := $(ALT_CXXFLAGS) $(CXXFLAGS)

# Arguments only for the C preprocessor.
# Prefix each include directory with -I.
APP_CPPFLAGS := $(APP_INC_DIRS) \
                $(ALT_CPPFLAGS) \
                $(CPPFLAGS)

# Arguments only for the assembler.
APP_ASFLAGS := $(APP_ASM_INC_DIRS) \
               $(ALT_ASFLAGS) \
               $(ASFLAGS)

# Arguments only for the linker.
APP_LDFLAGS := \
           -msys-crt0='$(CRT0)' \
           -msys-lib=$(SYS_LIB) \
           $(APP_LIB_DIRS) \
           $(ALT_LDFLAGS) \
           $(LDFLAGS)

LINKER_MAP_NAME := $(APP_NAME).map
ifeq ($(CREATE_LINKER_MAP), 1)
APP_LDFLAGS += -Wl,-Map=$(LINKER_MAP_NAME)
endif


#------------------------------------------------------------------------------
#           MAKEFILE INCLUDES DEPENDENT ON GENERATED CONTENT
#------------------------------------------------------------------------------
# mem_init.mk is a generated makefile fragment. This file defines all targets
# used to generate HDL initialization simulation files and pre-initialized
# onchip memory files.
MEM_INIT_FILE :=  $(BSP_ROOT_DIR)/mem_init.mk
include $(MEM_INIT_FILE)

# Create list of object files to be built using the list of source files.
# The source file hierarchy is preserved in the object tree.
# The supported file extensions are:
#
# .c            - for C files
# .cxx .cc .cpp - for C++ files
# .S .s         - for assembler files

OBJ_LIST := $(sort $(C_SRCS:.c=.o)  \
              $(patsubst %.cxx, %.o,                              \
                $(patsubst %.cc, %.o,                             \
                  $(patsubst %.cpp, %.o, $(CXX_SRCS))))           \
              $(patsubst %.S, %.o, $(patsubst %.s, %.o, $(ASM_SRCS))))

# The adjust-path macro
# 
# If COMSPEC is defined, Make is launched from Windows through
# Cygwin.  This adjust-path macro will call 'cygpath -u' on all
# paths to ensure they are readable by Make.
#
# If COMSPEC is not defined, Make is launched from *nix, and no adjustment
# is necessary

ifdef COMSPEC
	adjust-path = $(shell cygpath -u "$1")
else
	adjust-path = $1
endif

# Relative-pathed objects that being with "../" are handled differently.
#
# Regular objects are created as 
#   $(OBJ_ROOT_DIR)/<path>/<filename>.o
# where the path structure is maintained under the obj directory.  This
# applies for both absolute and relative paths; in the absolute path
# case this means the entire source path will be recreated under the obj
# directory.  This is done to allow two source files with the same name
# to be included as part of the project.
#
# Note: On Cygwin, the path recreated under the obj directory will be 
# the cygpath -u output path.
#
# Relative-path objects that begin with "../" cause problems under this 
# scheme, as $(OBJ_ROOT_DIR)/../<rest of path>/ can potentially put the object
# files anywhere in the system, creating clutter and polluting the source tree.
# As such, their paths are flattened - the object file created will be 
# $(OBJ_ROOT_DIR)/<filename>.o.  Due to this, two files specified with 
# "../" in the beginning cannot have the same name in the project.  VPATH 
# will be set for these sources to allow make to relocate the source file 
# via %.o rules.
#
# The following lines separate the object list into the flatten and regular
# lists, and then handles them as appropriate.

FLATTEN_OBJ_LIST += $(strip $(foreach s,$(OBJ_LIST),$(if $(filter ../%,$s),$s)))
REGULAR_OBJ_LIST += $(filter-out $(FLATTEN_OBJ_LIST),$(OBJ_LIST))

FLATTEN_APP_OBJS := $(addprefix $(OBJ_ROOT_DIR)/, \
			$(foreach s,$(FLATTEN_OBJ_LIST),$(notdir $s)))

VPATH := $(sort $(dir $(FLATTEN_OBJ_LIST)))

APP_OBJS := $(addprefix $(OBJ_ROOT_DIR)/, \
		$(foreach s,$(REGULAR_OBJ_LIST),$(call adjust-path,$s))) \
	    $(FLATTEN_APP_OBJS)

# Add any extra user-provided object files.
APP_OBJS += $(OBJS)

# Create list of dependancy files for each object file.
APP_DEPS := $(APP_OBJS:.o=.d)

#------------------------------------------------------------------------------
#                           BUILD PRE/POST PROCESS
#------------------------------------------------------------------------------
build_pre_process :
	$(BUILD_PRE_PROCESS)

build_post_process :
	$(BUILD_POST_PROCESS)

.PHONY: build_pre_process build_post_process

#------------------------------------------------------------------------------
#                     PATTERN RULES TO BUILD OBJECTS
#------------------------------------------------------------------------------

$(OBJ_ROOT_DIR)/%.o: %.c
	@echo Info: Compiling $< to $@
	@mkdir -p $(dir $@)
	$(CC) -MD -c $(APP_CPPFLAGS) $(APP_CFLAGS) -o $@ $<
	$(CC_POST_PROCESS)

$(OBJ_ROOT_DIR)/%.o: %.cpp
	@echo Info: Compiling $< to $@
	@mkdir -p $(dir $@)
	$(CXX) -MD -c $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $<
	$(CXX_POST_PROCESS)

$(OBJ_ROOT_DIR)/%.o: %.cc
	@echo Info: Compiling $< to $@
	@mkdir -p $(dir $@)
	$(CXX) -MD -c $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $<
	$(CXX_POST_PROCESS)

$(OBJ_ROOT_DIR)/%.o: %.cxx
	@echo Info: Compiling $< to $@
	@mkdir -p $(dir $@)
	$(CXX) -MD -c $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $<
	$(CXX_POST_PROCESS)

$(OBJ_ROOT_DIR)/%.o: %.S
	@echo Info: Assembling $< to $@
	@mkdir -p $(dir $@)
	$(AS) -MD -c $(APP_CPPFLAGS) $(APP_CFLAGS) $(APP_ASFLAGS) -o $@ $<
	$(AS_POST_PROCESS)

$(OBJ_ROOT_DIR)/%.o: %.s
	@echo Info: Assembling $< to $@
	@mkdir -p $(dir $@)
	$(AS) -MD -c $(APP_CFLAGS) $(APP_ASFLAGS) -o $@ $<
	$(AS_POST_PROCESS)

#------------------------------------------------------------------------------
#                     PATTERN RULES TO INTERMEDIATE FILES
#------------------------------------------------------------------------------

$(OBJ_ROOT_DIR)/%.s: %.c
	@echo Info: Compiling $< to $@
	@mkdir -p $(dir $@)
	$(CC) -S $(APP_CPPFLAGS) $(APP_CFLAGS) -o $@ $<

$(OBJ_ROOT_DIR)/%.s: %.cpp
	@echo Info: Compiling $< to $@
	@mkdir -p $(dir $@)
	$(CXX) -S $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $<

$(OBJ_ROOT_DIR)/%.s: %.cc
	@echo Info: Compiling $< to $@
	@mkdir -p $(dir $@)
	$(CXX) -S $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $<

$(OBJ_ROOT_DIR)/%.s: %.cxx
	@echo Info: Compiling $< to $@
	@mkdir -p $(dir $@)
	$(CXX) -S $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $<

$(OBJ_ROOT_DIR)/%.i: %.c
	@echo Info: Compiling $< to $@
	@mkdir -p $(dir $@)
	$(CC) -E $(APP_CPPFLAGS) $(APP_CFLAGS) -o $@ $<

$(OBJ_ROOT_DIR)/%.i: %.cpp
	@echo Info: Compiling $< to $@
	@mkdir -p $(dir $@)
	$(CXX) -E $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $<

$(OBJ_ROOT_DIR)/%.i: %.cc
	@echo Info: Compiling $< to $@
	@mkdir -p $(dir $@)
	$(CXX) -E $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $<

$(OBJ_ROOT_DIR)/%.i: %.cxx
	@echo Info: Compiling $< to $@
	@mkdir -p $(dir $@)
	$(CXX) -E $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $<

#------------------------------------------------------------------------------
#                        TARGET RULES
#------------------------------------------------------------------------------

.PHONY : help
help :
	@echo 'Summary of Makefile targets'
	@echo '  Build targets:'
	@echo '    all (default)    - Application and all libraries (including BSP)'
	@echo '    bsp              - Just the BSP'
	@echo '    libs             - All libraries (including BSP)'
	@echo '    flash            - All flash files'	
	@echo '    mem_init_install - All memory initialization files'
	@echo '  Clean targets:'
	@echo '    clean_all        - Application and all libraries (including BSP)'
	@echo '    clean            - Just the application'
	@echo '    clean_bsp        - Just the BSP'
	@echo '    clean_libs       - All libraries (including BSP)'
	@echo '  Run targets:'
	@echo '    download-elf     - Download and run your elf executable'
	@echo '    program-flash    - Program flash contents to the board'

# Handy rule to skip making libraries and just make application.
.PHONY : app
app : $(ELF)

ifeq ($(CREATE_OBJDUMP), 1)
app : $(OBJDUMP_NAME)
endif

ifeq ($(CREATE_ELF_DERIVED_FILES),1)
app : elf_derived_files
endif

# Handy rule for making just the BSP.
.PHONY : bsp
bsp : $(BSP_ROOT_DIR)
	@echo Info: Building $<
	@$(MAKE) --no-print-directory -C $<

# Make sure all makeable libraries (including the BSP) are up-to-date.
.PHONY : libs
libs :
	@for library_dir in $(MAKEABLE_LIBRARY_ROOT_DIRS); do \
        echo Info: Building $$library_dir;                      \
		$(MAKE) --no-print-directory -C $$library_dir;                         \
	done

$(APP_LDDEPS): libs
	@true

# Clean just the application.
.PHONY : clean
ifeq ($(CREATE_ELF_DERIVED_FILES),1)
clean : clean_elf_derived_files
else
clean :
endif
	@echo Info: Cleaning application
	@$(RM) -r $(ELF) $(OBJDUMP_NAME) $(LINKER_MAP_NAME) $(OBJ_ROOT_DIR)

# Clean just the BSP.
.PHONY : clean_bsp
clean_bsp :
	@echo Info: Cleaning $(BSP_ROOT_DIR)
	@$(MAKE) --no-print-directory -C $(BSP_ROOT_DIR) clean

# Clean all makeable libraries including the BSP.
.PHONY : clean_libs
clean_libs :
	@for library_dir in $(MAKEABLE_LIBRARY_ROOT_DIRS); do \
        echo Info: Cleaning $$library_dir;                      \
		$(MAKE) --no-print-directory -C $$library_dir clean;                   \
	done

# Clean application and all makeable libraries including the BSP.
.PHONY : clean_all
clean_all : clean mem_init_clean
	@for library_dir in $(MAKEABLE_LIBRARY_ROOT_DIRS); do \
        echo Info: Cleaning $$library_dir;                      \
		$(MAKE) --no-print-directory -C $$library_dir clean;                   \
	done

# Include the dependency files unless the make goal is performing a clean
# of the application.
ifneq ($(firstword $(MAKECMDGOALS)),clean)
ifneq ($(firstword $(MAKECMDGOALS)),clean_all)
-include $(APP_DEPS)
endif
endif

.PHONY : download-elf
download-elf : $(ELF)
	@echo Info: Downloading $(ELF)
	$(DOWNLOAD) --go --cpu_name=$(CPU_NAME) $(SOPC_SYSID_FLAG) $(WRITE_GMON_OPTION) $(ELF)

# Delete the target of a rule if it has changed and its commands exit 
# with a nonzero exit status.
.DELETE_ON_ERROR:

# Rules for flash programming commands
PROGRAM_FLASH_SUFFIX := -program
PROGRAM_FLASH_TARGET := $(addsuffix $(PROGRAM_FLASH_SUFFIX), $(FLASH_FILES))

.PHONY : program-flash
program-flash : $(PROGRAM_FLASH_TARGET)

.PHONY : $(PROGRAM_FLASH_TARGET)
$(PROGRAM_FLASH_TARGET) : flash
	@echo Info: Programming $(basename $@).flash
	@if [ -z "$($(basename $@)_EPCS_FLAGS)" ]; \
	then \
		echo $(FLASHPROG) $(SOPC_SYSID_FLAG) --base=$($(basename $@)_START) $(basename $@).flash; \
		$(FLASHPROG) $(SOPC_SYSID_FLAG) --base=$($(basename $@)_START) $(basename $@).flash; \
	else \
		echo $(FLASHPROG) $(SOPC_SYSID_FLAG) --epcs --base=$($(basename $@)_START) $(basename $@).flash; \
		$(FLASHPROG) $(SOPC_SYSID_FLAG) --epcs --base=$($(basename $@)_START) $(basename $@).flash; \
	fi

#------------------------------------------------------------------------------
#                         ELF TARGET RULE
#------------------------------------------------------------------------------
# Rule for constructing the executable elf file.
$(ELF) : $(APP_OBJS) $(LINKER_SCRIPT) $(APP_LDDEPS)
	@echo Info: Linking $@
	$(LD) -T'$(LINKER_SCRIPT)' $(APP_LDFLAGS) $(APP_CFLAGS) -o $@ $(filter-out $(CRT0),$(APP_OBJS)) $(APP_LIBS) $(APP_BSP_DEP_LIBS)
	@$(STACKREPORT) $@

$(OBJDUMP_NAME) : $(ELF)
	@echo Info: Creating $@
	$(OBJDUMP) $(OBJDUMP_FLAGS) $< >$@

