# == DEFAULT VALUES ===

# Path to unpacked emWin source package, expected to be specified on command line
EMWIN_ROOT ?= emWin_source

# Path to configuration headers. If the configuration does not exist it will be created using default template.
CONFIG_PATH ?= emWin_Config

# Output path for the public headers.
HEADER_PATH ?= emWin_header

# Output path for the library
LIBRARY_PATH ?= emWin_library

# Target library path/name, defaults to GUI.a
LIB_NAME ?= GUI.a

# Temporary directory is used to store intermediate files required to build the library, namely object files.
TMP_DIR ?= tmp


# === CHECK PRECONDITIONS ===

MAKE_MINVERSION := 4.0

# Support for $(file) function is required, check make version
ifneq ($(MAKE_MINVERSION), $(firstword $(sort $(MAKE_VERSION) $(MAKE_MINVERSION))))
$(error This Makefile requires GNU make version $(MAKE_MINVERSION) or higher)
endif


# === VARIABLES ===

# Paths to directories within the emWin source package.
DEFAULT_CONFIG := $(subst \,/, $(EMWIN_ROOT)/Start/Config)
SOURCE_ROOT := $(subst \,/, $(EMWIN_ROOT)/Start/GUI)

# Create list of paths with sources and headers to build
SOURCE_PATH := $(wildcard $(SOURCE_ROOT)/*)

# Set output paths
OBJ_DIR := $(TMP_DIR)/$(basename $(subst \,/,$(LIB_NAME)))
LIB_OUT := $(LIBRARY_PATH)/$(subst \,/,$(LIB_NAME))
LIB_DIR := $(patsubst %/,%,$(dir $(LIB_OUT)))

# Create lists of sources and objects
SOURCES := $(notdir $(foreach _dir, $(SOURCE_PATH), $(wildcard $(_dir)/*.c)))
OBJS := $(addprefix $(OBJ_DIR)/,$(patsubst %.c,%.o,$(SOURCES)))

HEADERS := $(notdir $(foreach _dir, $(SOURCE_PATH), $(wildcard $(_dir)/*.h)))
#PUBLIC_HEADERS := $(foreach _name, $(HEADERS), $(if $(or $(findstring Private, $(_name)), $(findstring Intern, $(_name)), $(findstring Opt, $(_name))),,$(_name)))
PUBLIC_HEADERS := $(addprefix $(HEADER_PATH)/,$(strip $(PUBLIC_HEADERS)))

CONFIG_HEADERS := $(addprefix $(CONFIG_PATH)/,$(notdir $(foreach _dir, $(DEFAULT_CONFIG), $(wildcard $(_dir)/*.h))))

# Helper variables to use literal space and newline
_empty :=
_space := $(_empty) $(_empty)
define _newline


endef

# Set VPATH so that make is able to find the prerequisites
VPATH := $(subst $(_space),:,$(SOURCE_PATH))

# Set include path for compiler to the config directory and all source directories containing headers
INCLUDE_PATH := $(CONFIG_PATH) $(strip $(foreach _dir, $(SOURCE_PATH), $(if $(wildcard $(_dir)/*.h), $(_dir))))


# === TARGETS ===

.PHONY: all
all: $(CONFIG_HEADERS) $(PUBLIC_HEADERS) $(LIB_OUT)


.PHONY: lib 
lib: $(LIB_OUT)


.PHONY: objs
objs: $(OBJS)


.PHONY: config
objs: $(CONFIG_HEADERS)


.PHONY: headers
headers: $(PUBLIC_HEADERS)


.PHONY: clean
clean:
	rm -rf $(OBJ_DIR)
	rm -f $(LIB_OUT)
	rm -f $(PUBLIC_HEADERS)


.PHONY: tidy
tidy:
	rm -rf $(TMP_DIR)

	
# === RULES ===

# Treat objects as secondary.
.SECONDARY : $(OBJS)

# Dependency rule to produce error if source directory does not exist
$(SOURCE_ROOT):
	$(error Unable to find emWin source directory $@)

# Packing the library
$(LIB_OUT): $(OBJ_DIR)/OBJS.lst $(OBJS) $(SOURCE_ROOT) | $(OBJ_DIR) $(LIB_DIR)
	rm -f $@
	$(AR) $(ARFLAGS)$<

# Compilation of .o from corresponding .c placing it into desired object directory.
# It is assumed that object may depend on any header. HEADERS.lst is used as an intermediate target to speed up make
$(OBJ_DIR)/%.o: %.c $(CONFIG_HEADERS) $(OBJ_DIR)/HEADERS.lst | $(OBJ_DIR)
	$(CC) $(CFLAGS) $(addprefix -I ,$(INCLUDE_PATH)) -c -o $@ $<

# Rule to copy required headers from source path
$(HEADER_PATH)/%.h: %.h | $(HEADER_PATH)
	cp --preserve=timestamp $< $@

# Rule to create configuration headers by cloning default ones
$(CONFIG_PATH)/%.h: | $(DEFAULT_CONFIG)/%.h $(CONFIG_PATH)
	cp --preserve=timestamp $(firstword $|) $@

# Rule to create missing directories
$(HEADER_PATH) $(CONFIG_PATH) $(OBJ_DIR) $(LIB_DIR):
	mkdir -p $@

.SECONDEXPANSION:
$(OBJ_DIR)/%.lst: $$(%) | $(OBJ_DIR)
	$(file > $@,$(subst $(_space),$(_newline),$^))
