CXX			:= g++
RM			:= rm -f
MKDIR		:= mkdir -p
RMDIR		:= rmdir
SED			:= sed

CXXFLAGS	:= -std=c++11 -O2
CXXDFLAGS	:= -std=c++11 -g -Wall
LDFLAGS		:= 

VPATH		:= src:utils
CXXINCLUDE	:= $(patsubst %,-I%,$(subst :, ,$(VPATH)))

OBJDIR		:= obj
BINDIR		:= bin
Dirs		:= $(OBJDIR) $(BINDIR)

Main		:= $(BINDIR)/main
Test		:= $(BINDIR)/unit_test

Objects		:= $(patsubst %.cpp, $(OBJDIR)/%.o, $(notdir $(wildcard *.cpp */*.cpp)))

all: $(Main) $(Test)

$(OBJDIR)/%.o: %.cpp | $(Dirs)
	$(CXX) $(CXXFLAGS) $(CXXINCLUDE) -c $< -o $@

$(OBJDIR)/%.d: %.cpp | $(Dirs)
	@set -e; $(RM) $@; \
	$(CXX) $(CXXFLAGS) $(CXXINCLUDE) -MM $< > $@.$$$$; \
	$(SED) -i 's,\($*\)\.o[ :]*,\1.o $@ : ,g' $@.$$$$; \
	$(SED) '1s/^/$(OBJDIR)\//' < $@.$$$$ > $@; \
	$(RM) $@.$$$$

ifneq ($(MAKECMDGOALS),clean)
-include $(Objects:.o=.d)
endif

$(Main):	$(filter-out $(OBJDIR)/$(subst $(BINDIR)/,,$(Test).o), $(Objects))
	$(CXX) $(CXXFLAGS) $(CXXINCLUDE) -o $@ $^ $(LDFLAGS)

$(Test):	$(filter-out $(OBJDIR)/$(subst $(BINDIR)/,,$(Main).o), $(Objects))
	$(CXX) $(CXXFLAGS) $(CXXINCLUDE) -o $@ $^ $(LDFLAGS)

$(Dirs):
	$(MKDIR) $@

debug: CXXFLAGS := $(CXXDFLAGS)
debug: $(Main) $(Test)

run: $(Main)
	$(Main)

test: $(Test)
	$(Test)

# to avoid rm -rf
clean:
	$(RM) $(OBJDIR)/*.o
	$(RM) $(OBJDIR)/*.d
	$(RM) $(Main)
	$(RM) $(Test)
	-$(RMDIR) $(OBJDIR)
	-$(RMDIR) $(BINDIR)

.PHONY: all debug run test clean
