CFGS := $(wildcard config/*.cfg.sh)
SRCS := $(wildcard common/*.cpp) $(wildcard linux/*.cpp)
TARGET := Blinker

CPP := g++
CONFIG :=
DEFINE :=
INCLUDE := -Icommon -Ilinux
CFLAGS := -Wall -Wextra -Werror -O2
LDFLAGS :=
LIBS := -lBlinkenLib

CFGS_BASE := $(patsubst %.cfg.sh,%,$(CFGS))
CFGS_MK := $(addsuffix .cfg.mk,$(CFGS_BASE))
SRCS_BASE := $(patsubst %.cpp,%,$(SRCS))
DEPS := $(addsuffix .d,$(SRCS_BASE))
OBJS := $(addsuffix .o,$(SRCS_BASE))

.PHONY: all clean distclean
.SUFFIXES:
.SECONDARY:

all: $(DEPS) $(TARGET)

ifneq ($(MAKECMDGOALS),clean)
  ifneq ($(MAKECMDGOALS),distclean)
    include config.mk
    -include $(DEPS)
  endif
endif

DEFINE += -DBLINKER_CONFIG="\"$(CONFIG)\""

config.mk: $(CFGS_MK)
	cat /dev/null $^ >$@

%.cfg.mk: %.cfg.sh
	sh $< >$@

%.d: %.cpp Makefile config.mk
	$(CPP) $(DEFINE) $(INCLUDE) $(CFLAGS) -MM -MF $@ -MT $(@:.d=.o) $<

%.o: %.cpp Makefile
	$(CPP) $(DEFINE) $(INCLUDE) $(CFLAGS) -c -o $@ $<

$(TARGET): $(OBJS)
	$(CPP) $(LDFLAGS) -o $@ $+ $(LIBS)

clean:
	rm -f $(DEPS) $(OBJS) $(TARGET)

distclean: clean
	rm -f config.mk $(CFGS_MK)