export # export all variable to sub-Makefile
CC=mipsel-unknown-elf-gcc
AS=mipsel-unknown-elf-as
LD=mipsel-unknown-elf-ld
DU=mipsel-unknown-elf-objdump


#current directory absolute path
SOFT_PATH  	= $(shell pwd)/

SYS_NAME    = sys
BOOT_NAME   = boot
LIB_NAME    = libs

SYS_PATH    = $(SOFT_PATH)$(SYS_NAME)
BOOT_PATH   = $(SOFT_PATH)$(BOOT_NAME)
LIB_PATH    = $(SOFT_PATH)$(LIB_NAME)
MAP_PATH    = $(SOFT_PATH)xml/
BUILD_PATH 	= $(SOFT_PATH)build/
ELF_PATH	= $(SOFT_PATH)build/

#list of all applications directory
APP_DIRS 	= $(shell ls -d apps/*/ ) 

SYS_OBJS_LIST = \
		sys_handler.o \
		init.o 		\
		giet.o \
		switch.o \
		common.o \
		ctx_handler.o \
		drivers.o \
		exc_handler.o \
		irq_handler.o \
		task_init.o 

BOOT_OBJS_LIST = reset.o \
				boot_handler.o 

#LIB_SRCS = $(wildcard $(LIB_NAME)/*.c)
LIB_OBJS_LIST = stdio.o\
				mwmr.o\
				common.o

LIB_OBJS = $(patsubst %,$(LIB_NAME)/%,$(LIB_OBJS_LIST))
SYS_OBJS   = $(patsubst %,$(SYS_NAME)/%,$(SYS_OBJS_LIST))
BOOT_OBJS   = $(patsubst %,$(BOOT_NAME)/%,$(BOOT_OBJS_LIST))


CFLAGS=-Wall -ffreestanding -mno-gpopt -mips32 -g

SYS_INCLUDE = -I$(SYS_PATH) -I$(MAP_PATH) -I$(LIB_PATH) -I.

BOOT_INCLUDE = -I$(BOOT_PATH) -I$(MAP_PATH) -I$(LIB_PATH) -I.

INCLUDE		= -I$(LIB_PATH) -I$(SOFT_PATH) -I$(SYS_PATH) -I$(MAP_PATH)

TRASH= /dev/null||true

.PHONY: apps prepare

all: prepare soft.elf
	
## merge all *.elf to soft.elf
soft.elf: boot.elf sys.elf map.bin apps 
	$(MAKE) -C mover
	mover/mover.x  map.bin 
	$(DU) -D $@ > $(BUILD_PATH)$@.txt

## prepare the environement
prepare:
	@mkdir $(BUILD_PATH) 2>$(TRASH)
	@mkdir $(ELF_PATH) 2>$(TRASH)

## compile the parser
## mapping compilation
map.bin: map.xml
	$(MAKE) -C xml 				
	xml/xml2bin map.xml map.bin

## system compilation
sys.elf: $(SYS_OBJS) $(SYS_PATH)/sys.ld
	(cd $(BUILD_PATH); $(LD) -o $@ -T $(SYS_PATH)/sys.ld $(SYS_OBJS) )
	(cd $(BUILD_PATH); $(DU) -D $@ > $@.txt)

$(SYS_NAME)/%.o: $(SYS_NAME)/%.c 
	@mkdir $(BUILD_PATH)/$(SYS_NAME) 2>$(TRASH)
	$(CC) $(SYS_INCLUDE) $(CFLAGS)  -c -o $(BUILD_PATH)/$@ $<

$(SYS_NAME)/%.o: $(SYS_NAME)/%.s
	@mkdir $(BUILD_PATH)/$(SYS_NAME) 2>$(TRASH)
	$(CC) $(SYS_INCLUDE) $(CFLAGS)  -c -o $(BUILD_PATH)/$@ $<

$(SYS_NAME)/%.o: $(SYS_NAME)/%.S
	@mkdir $(BUILD_PATH)/$(SYS_NAME) 2>$(TRASH)
	$(CC) $(SYS_INCLUDE) $(CFLAGS)  -c -o $(BUILD_PATH)/$@ $<

## boot compilation
boot.elf: $(BOOT_OBJS) $(BOOT_PATH)/boot.ld
	(cd $(BUILD_PATH); $(LD) -o $@ -T $(BOOT_PATH)/boot.ld $(BOOT_OBJS) )
	(cd $(BUILD_PATH); $(DU) -D $@ > $@.txt)

$(BOOT_NAME)/%.o: $(BOOT_NAME)/%.c 
	@mkdir $(BUILD_PATH)/$(BOOT_NAME) 2>$(TRASH)
	$(CC) $(BOOT_INCLUDE) $(CFLAGS)  -c -o $(BUILD_PATH)/$@ $<

$(BOOT_NAME)/%.o: $(BOOT_NAME)/%.s
	@mkdir $(BUILD_PATH)/$(BOOT_NAME) 2>$(TRASH)
	$(CC) $(BOOT_INCLUDE) $(CFLAGS)  -c -o $(BUILD_PATH)/$@ $<

$(BOOT_NAME)/%.o: $(BOOT_NAME)/%.S
	@mkdir $(BUILD_PATH)/$(BOOT_NAME) 2>$(TRASH)
	$(CC) $(BOOT_INCLUDE) $(CFLAGS)  -c -o $(BUILD_PATH)/$@ $<

##libs compilation
$(LIB_NAME)/%.o: $(LIB_NAME)/%.c
	@mkdir $(BUILD_PATH)/$(LIB_NAME) 2>$(TRASH)
	$(CC) $(CFLAGS) $(INCLUDE) -c -o $(BUILD_PATH)/$@ $<

## applications 
apps: $(LIB_OBJS)
	@echo "---------------------------------------------BUILDING APPS------------------------------------------------------"
	set -e; for d in $(APP_DIRS); do $(MAKE)  -C $$d ; echo "Compiling $$d";  done

### special rules
clean:
	rm -f *.o *.elf *.bin *.txt core *~  2>$(TRASH)
	$(MAKE) clean -C xml/ 2>$(TRASH)
	$(MAKE) clean -C mover/ 2>$(TRASH)
	rm -r $(BUILD_PATH) 2>$(TRASH)
	set -e; for d in $(APP_DIRS); do $(MAKE) clean -C $$d ; done
