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_DIR    = sys
LIB_DIR    = libs
BOOT_DIR   = boot

BOOT_PATH   = $(SOFT_PATH)$(BOOT_DIR)
SYS_PATH    = $(SOFT_PATH)$(SYS_DIR)
LIB_PATH    = $(SOFT_PATH)$(LIB_DIR)
XML_PATH    = $(SOFT_PATH)xml/
MEMO_PATH   = $(SOFT_PATH)memo/
BUILD_PATH 	= $(SOFT_PATH)build/
ELF_PATH	= $(SOFT_PATH)build/
APP_PATH	= $(SOFT_PATH)apps/

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

SYS_OBJS_LIST = \
        vm_handler.o \
		sys_handler.o \
		giet.o \
		switch.o \
		common.o \
		ctx_handler.o \
		drivers.o \
		exc_handler.o \
		irq_handler.o \
		kernel_init.o

BOOT_OBJS_LIST = reset.o \
				boot_handler.o 

#LIB_SRCS = $(wildcard $(LIB_DIR)/*.c)
LIB_OBJS_LIST = stdio.o \
				mwmr_channel.o \
				barrier.o \
				spin_lock.o 

LIB_OBJS	= $(patsubst %,$(LIB_DIR)/%,$(LIB_OBJS_LIST))
SYS_OBJS  	= $(patsubst %,$(SYS_DIR)/%,$(SYS_OBJS_LIST))
BOOT_OBJS   = $(patsubst %,$(BOOT_DIR)/%,$(BOOT_OBJS_LIST))


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

SYS_INCLUDE  = -I$(SYS_PATH)  -I$(XML_PATH) -I$(LIB_PATH) -I.
BOOT_INCLUDE = -I$(BOOT_PATH) -I$(XML_PATH) -I$(LIB_PATH) -I.
LIB_INCLUDE	 = -I$(LIB_PATH)  -I$(XML_PATH) -I.
APP_INCLUDE	 = -I$(LIB_PATH)  -I$(XML_PATH) -I$(SOFT_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 $(MEMO_PATH)
	$(MEMO_PATH)/memo.x  map.bin 
	$(DU) -D $@ > $(BUILD_PATH)$@.txt

## prepare the environement
prepare:
	@mkdir $(BUILD_PATH) 				2>$(TRASH)
	@mkdir $(ELF_PATH) 	 				2>$(TRASH)
	@mkdir $(BUILD_PATH)/$(BOOT_DIR) 	2>$(TRASH)
	@mkdir $(BUILD_PATH)/$(LIB_DIR) 	2>$(TRASH)
	@mkdir $(BUILD_PATH)/$(SYS_DIR) 	2>$(TRASH)

### mapping compilation
map.bin: map.xml
	$(MAKE) -C $(XML_PATH)
	$(XML_PATH)/xml2bin $(SOFT_PATH)map.xml $(SOFT_PATH)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_DIR)/%.o: $(SYS_DIR)/%.c 
	$(CC) $(SYS_INCLUDE) $(CFLAGS)  -c -o $(BUILD_PATH)/$@ $<

$(SYS_DIR)/%.o: $(SYS_DIR)/%.s
	$(CC) $(SYS_INCLUDE) $(CFLAGS)  -c -o $(BUILD_PATH)/$@ $<

$(SYS_DIR)/%.o: $(SYS_DIR)/%.S
	$(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_DIR)/%.o: $(BOOT_DIR)/%.c 
	$(CC) $(BOOT_INCLUDE) $(CFLAGS)  -c -o $(BUILD_PATH)/$@ $<

$(BOOT_DIR)/%.o: $(BOOT_DIR)/%.s
	$(CC) $(BOOT_INCLUDE) $(CFLAGS)  -c -o $(BUILD_PATH)/$@ $<

$(BOOT_DIR)/%.o: $(BOOT_DIR)/%.S
	$(CC) $(BOOT_INCLUDE) $(CFLAGS)  -c -o $(BUILD_PATH)/$@ $<

### libs compilation
$(LIB_DIR)/%.o: $(LIB_DIR)/%.c
	$(CC) $(CFLAGS) $(LIB_INCLUDE) -c -o $(BUILD_PATH)/$@ $<

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

### clean 
clean:
	rm -f *.o *.elf *.bin *.txt core *~  	2>$(TRASH)
	$(MAKE) -s clean -C $(XML_PATH)			2>$(TRASH)
	$(MAKE) -s clean -C $(MEMO_PATH)		2>$(TRASH)
	rm -r $(BUILD_PATH) 					2>$(TRASH)
	rm -r $(ELF_PATH) 						2>$(TRASH)
	set -e; for d in $(APP_DIRS); do $(MAKE) clean -f config.mk -C $$d ; done
