MAKEFILE_REL_PATH := $(lastword $(MAKEFILE_LIST))
LINKED_MAKEFILE_PATH := $(shell readlink $(MAKEFILE_REL_PATH))
ifeq ( $(LINKED_MAKEFILE_PATH), )
MAKEFILE_PATH := $(MAKEFILE_REL_PATH)
else
MAKEFILE_PATH := $(LINKED_MAKEFILE_PATH)
endif
BASE := $(shell cd $(CURDIR)/$(dir $(MAKEFILE_PATH)) ; echo $$PWD)
# BASE := ${BASEDIR}
CONFIG_FILE := $(BASE)/.config
CONFIG_HASH_FILE := $(BASE)/.config_hash

__all: $(CONFIG_FILE) _all

$(CONFIG_FILE):
	$(BASE)/buildsystem/configGenerator.sh > $@

#$(CONFIG_HASH_FILE): $(CONFIG_FILE)
#	CONFIG_HASH_VAL = /.$(shell crc32 $(CONFIG_FILE))
#	echo $(CONFIG_HASH_VAL) > $@

CONFIG_HASH := /.$(shell crc32 $(CONFIG_FILE))
PROJECTS_FILE := $(BASE)$(CONFIG_HASH)/projects.inc

_all: $(PROJECTS_FILE) all

$(PROJECTS_FILE): $(CONIG_FILE)
	@if [ ! -f $@ ]; then mkdir -p $@ ; rm -rf $@ ; fi
	@echo "###################################################################" > $@
	@echo "# Autogenerated file. DO NOT EDIT." >> $@
	@echo "# Created on `date`" >> $@
	@echo "# using `uname -nrs`" >> $@
	@echo "# by $(BASE)/Makefile." >> $@
	@echo "###################################################################" >> $@
	@echo >> $@
	@cd $(BASE) ; echo PROJECTS = `find . -type d | grep -v "\./\..*$$\|\.$$\|\.svn\|buildsystem\|docs\|tests"` >> $@
	@echo >> $@

OBJSDIR    := $(BASE)$(CONFIG_HASH)/.objs
DEPSDIR    := $(BASE)$(CONFIG_HASH)/.deps
CTAGS_FILE := $(BASE)/.tags

-include $(CONFIG_FILE)

-include $(PROJECTS_FILE)
SUBDIR_PROJECTS := $(patsubst ./%, $(BASE)$(CONFIG_HASH)/%/project.inc, $(PROJECTS))
-include $(SUBDIR_PROJECTS)

TESTBINS  = $(patsubst ./%.cpp, $(OBJSDIR)/%.bin, $(TESTS))
C_OBJECTS = $(patsubst ./%.c,   $(OBJSDIR)/%.o,   $(C_SOURCES))
OBJECTS   = $(patsubst ./%.cpp, $(OBJSDIR)/%.o,   $(SOURCES))
DEPENDS   = $(patsubst $(OBJSDIR)/%.o, $(DEPSDIR)/%.cpp.d, $(OBJECTS))

$(BASE)$(CONFIG_HASH)/%/project.inc: $(BASE)/%
	@if [ ! -f $@ ]; then mkdir -p $@ ; rm -rf $@ ; fi
	@cd $(BASE) ; $(BASE)/buildsystem/projectGenerator.sh $(patsubst $(BASE)/%, %, $<) > $@

all: subdirs $(TARGETS) tests docs $(CTAGS_FILE) install

subdirs: $(CONFIG_FILE) $(SUBDIR_PROJECTS)

$(OBJSDIR)/%/d:
	@mkdir -p $@ ; rm -rf $@

$(DEPSDIR)/%/d:
	@mkdir -p $@ ; rm -rf $@

$(DEPSDIR)/%.c.d: $(BASE)/%.c $(DEPSDIR)/%/d
	$(CC_DEPS) $(CFLAGS) -MT $(patsubst $(BASE)/%.c, $(OBJSDIR)/%.o, $<) -MD -E $< -MF $@ > /dev/null

$(OBJSDIR)/%.o: $(BASE)/%.c $(OBJSDIR)/%/d $(DEPSDIR)/%.c.d
	$(CC) $(CFLAGS) -c $< -o $@

$(DEPSDIR)/%.mm.d: $(BASE)/%.mm $(DEPSDIR)/%/d
	$(CXX_DEPS) $(CXXFLAGS) -MT $(patsubst $(BASE)/%.mm, $(OBJSDIR)/%.o, $<) -MD -E $< -MF $@ > /dev/null

$(OBJSDIR)/%.o: $(BASE)/%.mm $(OBJSDIR)/%/d $(DEPSDIR)/%.mm.d
	$(CXX) $(CXXFLAGS) -c $< -o $@

$(DEPSDIR)/%.cpp.d: $(BASE)/%.cpp $(DEPSDIR)/%/d
	$(CXX_DEPS) $(CXXFLAGS) -MT $(patsubst $(BASE)/%.cpp, $(OBJSDIR)/%.o, $<) -MD -E $< -MF $@ > /dev/null

$(OBJSDIR)/%.o: $(BASE)/%.cpp $(OBJSDIR)/%/d $(DEPSDIR)/%.cpp.d
	$(CXX) $(CXXFLAGS) -c $< -o $@

$(OBJSDIR)/%.bin: $(BASE)/%.cpp $(OBJSDIR)/%/d
	@# echo c++ $(CXXFLAGS) $< -o $@ $(LFLAGS) $(shell cat `dirname $<`/depends 2> /dev/null)
	$(CXX) $(CXXFLAGS) $< -g -o $@ $(LFLAGS) $(shell cat `dirname $<`/depends 2> /dev/null)

build-info:
	@echo 'const char buildDate[] = "' `date` '";' > build-info.c
	@echo 'const char buildMachine[] = "' `uname -m` '";' > build-info.c
	@echo 'const char buildOS[] = "' `uname -s` '";' > build-info.c
	@echo 'const char buildOSVersion[] = "' `uname -r` '";' > build-info.c
	$(CC_QUIET) $(CFLAGS) -c build-info.c -o $(OBJSDIR)/build-info.o
	@rm build-info.c

debug:
	@echo Debug
	@echo base: $(BASE)
	@echo objs: $(OBJECTS)
	@echo deps: $(DEPENDS)
	@echo libs: $(LIBS)
	@echo incs: $(INCLUDES)
	@echo deps: $(DEPS)

release:
	@echo Release

tests: $(TESTBINS)
	@echo ------------------
	@echo Running Tests
	@echo ------------------
	@echo "$(TESTBINS)" | xargs -t -n 1 -J x `echo x`

docs:
	@echo ------------------
	@echo Building Documentation
	@echo ------------------

$(CTAGS_FILE): $(patsubst %, $(BASE)/%, $(SOURCES) $(HEADERS))
	@echo ------------------
	@echo Building Tags
	@echo ------------------
	# @if [ ! -f $(BASE)/.system-tags ] ; then ctags -t -f $(BASE)/.system-tags -a /usr/include/*.h /usr/include/*/*.h ; fi 2> /dev/null
	@if [ ! -f $(BASE)/.system-tags ] ; then ctags --c-kinds=+p --fields=+S -f $(BASE)/.system-tags -a /usr/include/*.h /usr/include/*/*.h ; fi 2> /dev/null
	# @ctags -t -f $(BASE)/.local-tags $^ 2> /dev/null ; true
	# @ctags -R --c-kinds=+p --fields=+S -f $(BASE)/.local-tags $^ 2> /dev/null ; true
	@ctags --c-kinds=+p --fields=+S -f $(BASE)/.local-tags $^ 2> /dev/null ; true
	@cat $(BASE)/.system-tags $(BASE)/.local-tags > $@
	@rm -rf $(BASE)/.system-tags $(BASE)/.local-tags

install:
	@echo ------------------
	@echo Installing
	@echo ------------------
	@echo Install

clean: $(CONFIG_FILE)
	@$(DEL) $(BASE)$(CONFIG_HASH) $(TARGETS) $(CTAGS_FILE)

clean_all: clean
	@$(DEL) $(SUBDIR_PROJECTS) $(TARGETS) $(CTAGS_FILE) $(OBJSDIR) $(DEPSDIR) $(PROJECTS_FILE) $(CONFIG_FILE)

.PHONY: _all all subdirs clean clean_all debug release build-info test docs install

-include $(DEPENDS)

