# Let's try makefiles on Kotlin or JAVA	
# we will try to create one sample makefile to compile and create JAR files
# both java and kotlin are jvm - running compiler on single files is bad
# both java and kotlin are diffent from c as the compilers honor package structure not folders
#   so we compile in src/main/java but that gets used as base by compiler

# Project Artifacts - Starts with SRC_FILES
PNAME=jabba
ENTRYPOINT=com.reliancy.jabba.Router
DIR_COMPILE=build
DIR_PACKAGE=dist
DIR_SRC=src
DIR_LIB=target/lib
MANIFEST=
MANIFEST_AUTO=$(DIR_PACKAGE)/manifest.mf

ASSETS=%.txt %.html %.css %.js %.png %.jsp
# Params
KOTLIN_BASE=$(DIR_SRC)/main/kotlin
KOTLIN_EXT = kt
JAVA_BASE=$(DIR_SRC)/main/java
JAVA_EXT = java
OBJ_EXT = class
JFLAGS=-g
KFLAGS=
KOTLIN_TODO=kotlin_todo.txt
JAVA_TODO=java_todo.txt

# Tools
PRINT	:= @printf
RM		:= @rm -rf
COPY	:= @cp
MOVE	:= @mv
JVC		:= javac
KTC		:= java -jar $(subst \,/,$(KOTLIN_HOME))/lib/kotlin-compiler.jar
TEST_IF := @test -s
JAR		:= @jar -cvfm
MAKEDIR	:= @mkdir -p
CFIND	:= find
FIND    := @$(CFIND)

# File Sets
ALL_SRC=$(subst \,/,$(shell $(CFIND) $(DIR_SRC) -type f))
ASSETS_SRC=$(filter $(ASSETS),$(ALL_SRC))
ASSETS_JAVA:=$(subst $(JAVA_BASE),$(DIR_COMPILE),$(filter $(JAVA_BASE)/%,$(ASSETS_SRC)))
ASSETS_KOTLIN:=$(subst $(KOTLIN_BASE),$(DIR_COMPILE),$(filter $(KOTLIN_BASE)/%,$(ASSETS_SRC)))
SRC_DIRS ?=$(subst \,/,$(shell $(CFIND) $(DIR_SRC) -type d -print))
KOTLIN_SRC=$(foreach dir,$(SRC_DIRS),$(filter $(KOTLIN_BASE)/%,$(wildcard $(dir)/*.$(KOTLIN_EXT))))
KOTLIN_OBJ=$(KOTLIN_SRC:$(KOTLIN_BASE)/%.$(KOTLIN_EXT)=$(DIR_COMPILE)/%.$(OBJ_EXT))
JAVA_SRC=$(foreach dir,$(SRC_DIRS),$(filter $(JAVA_BASE)/%,$(wildcard $(dir)/*.$(JAVA_EXT))))
JAVA_OBJ=$(JAVA_SRC:$(JAVA_BASE)/%.$(JAVA_EXT)=$(DIR_COMPILE)/%.$(OBJ_EXT))
LIBS=$(foreach dir,$(DIR_LIB),$(wildcard $(dir)/*.jar))
SPACE=$() $()
CLASSPATH=$(subst $(SPACE),;,$(LIBS))
JFLAGS:= -cp '$(CLASSPATH)'
KFLAGS:= -cp '$(CLASSPATH)'

# Common Targets
.SUFFIXES:

# rule to build kotlin
$(DIR_COMPILE)/%.$(OBJ_EXT): $(KOTLIN_BASE)/%.$(KOTLIN_EXT)
	$(PRINT) '\tCollecting source: %s\n' $<
	$(PRINT) "$<\n" >> $(DIR_COMPILE)/$(KOTLIN_TODO)
# rule to build java
$(DIR_COMPILE)/%.$(OBJ_EXT): $(JAVA_BASE)/%.$(JAVA_EXT)
	$(PRINT) '\tCollecting source: %s\n' $<
	$(PRINT) "$<\n" >> $(DIR_COMPILE)/$(JAVA_TODO)
# rule to move assets - observe static pattern rules
$(ASSETS_KOTLIN): $(DIR_COMPILE)/% : $(KOTLIN_BASE)/%
	$(MAKEDIR) $(dir $@)
	$(COPY) --update $< $@ && printf "\tCopy asset:$< -> $@\n"
$(ASSETS_JAVA): $(DIR_COMPILE)/% : $(JAVA_BASE)/%
	$(MAKEDIR) $(dir $@)
	$(COPY) --update $< $@ && printf "\tCopy asset:$< -> $@\n"

#default: dist
package: compile | $(DIR_PACKAGE)
	$(PRINT) "Packaging\n"
	$(RM) $(DIR_COMPILE)/$(KOTLIN_TODO)
	$(RM) $(DIR_COMPILE)/$(JAVA_TODO)
#	$(FIND) $(BUILD_DIR) -name "META-INF" -exec rm -rf {} +
ifeq ($(MANIFEST),)
	$(PRINT) "Manifest-Version: 1.0\n" >> $(MANIFEST_AUTO)
	$(PRINT) "Created-By: Reliancy Makefile\n" >> $(MANIFEST_AUTO)
	$(PRINT) "Class-Path: $(foreach lib,$(LIBS),lib/$(notdir $(lib)))\n" >> $(MANIFEST_AUTO)
ifneq ($(ENTRYPOINT),)
	$(PRINT) "Main-Class: $(ENTRYPOINT)\n" >> $(MANIFEST_AUTO)
endif
else
	$(COPY) $(MANIFEST) $(MANIFEST_AUTO)
endif
	$(JAR) $(DIR_PACKAGE)/$(PNAME).jar $(MANIFEST_AUTO) -C $(DIR_COMPILE) .
compile: compile_kotlin compile_java
	$(PRINT) "Compiling done.\n"

compile_kotlin: $(KOTLIN_OBJ) | $(DIR_COMPILE) $(ASSETS_KOTLIN)
ifneq ($(KOTLIN_OBJ),)
#	$(PRINT) "KtSrc:$(KOTLIN_SRC)\n"
#	$(PRINT) "KtObj:$(KOTLIN_OBJ)\n"
	$(PRINT) 'Building Kotlin\n'
	$(KTC) $(KFLAGS) -d $(DIR_COMPILE) @$(DIR_COMPILE)/$(KOTLIN_TODO)
endif

compile_java: $(JAVA_OBJ) | $(DIR_COMPILE) $(ASSETS_JAVA)
ifneq ($(JAVA_OBJ),)
	$(PRINT) "JavaSrc:$(JAVA_SRC)\n"
	$(PRINT) "JavaObj:$(JAVA_OBJ)\n"
	$(PRINT) "Building Java\n"
	@$(JVC) $(JFLAGS) -d $(DIR_COMPILE) @$(DIR_COMPILE)/$(JAVA_TODO)
endif

$(DIR_COMPILE):
	$(PRINT) "prepare dir: $(DIR_COMPILE).\n"
	$(MAKEDIR) $(DIR_COMPILE)
	$(RM) $(DIR_COMPILE)/$(KOTLIN_TODO)
	$(RM) $(DIR_COMPILE)/$(JAVA_TODO)

$(DIR_PACKAGE):
	$(PRINT) "prepare dir: $(DIR_PACKAGE).\n"
	$(MAKEDIR) $(DIR_PACKAGE)
	$(MAKEDIR) $(DIR_PACKAGE)/lib
	$(COPY) $(LIBS) $(DIR_PACKAGE)/lib/

run:
	$(PRINT) "Running\n"
test:
	$(PRINT) "Testing\n"
clean:
	$(RM) $(DIR_COMPILE)
	$(RM) $(DIR_PACKAGE)
.PHONY: package compile dirs run test clean 
