LIB_NAME = jbeegfs
JAR_NAME = jbeegfs

SOURCEDIR = ../source
BEEGFS_INCLUDE = -I../../client_devel/include -I../../client_module/include

SOURCES = $(shell find $(SOURCEDIR)/ -name '*.java')

# JAVA_BUILD_DIR: Classfiles. Is packaged into the jar file later (so should we add META-INF or
# a manifest file at some point, this would go in here too.
JAVA_BUILD_DIR = java_build
# Note: this ignores inner classes (as does the %.class rule below). But since their .class files
# are always generated at the same time as their containing classes, we are fine as long as no one
# messes with the inner class files manually.
CLASSFILES = $(patsubst $(SOURCEDIR)/%.java, $(JAVA_BUILD_DIR)/%.class, $(SOURCES))
# CPP_BUILD_DIR: Build dir for the native library - also contains header files generated by javah.

CPP_BUILD_DIR = native_build
# CPPHEADER: The header file(s) (again, ignoring inner classes) generated from the classfiles for
# the C++ compiler.
CPPHEADER = $(CPP_BUILD_DIR)/com_beegfs_JBeeGFS.h
# CPPINCLUDES: includes needed for JNI - we copy those into our local build dir because the 'native'
# target might be built on a system without java installed
CPPINCLUDES = $(CPP_BUILD_DIR)/jni.h $(CPP_BUILD_DIR)/jni_md.h

CLASSPATH = ../hadoop_jars/\*:$(CPP_BUILD_DIR)/
# JAVA_HOME: Path to java installation. This uses the java set by the 'alternatives' tool.
JAVA_HOME = $(shell readlink -e `dirname \`readlink -e \\\`which javac\\\`\``/..)
# derive paths to javac, javah and jar from the JAVA_HOME.
JAVAC = $(JAVA_HOME)/bin/javac
JAVAH = $(JAVA_HOME)/bin/javah
JAVADOC = $(JAVA_HOME)/bin/javadoc
JAR = $(JAVA_HOME)/bin/jar
JAVACOPTS = -classpath $(CLASSPATH) -d $(JAVA_BUILD_DIR) -sourcepath $(SOURCEDIR)

DOCDIR = doc


.PHONY: all jar native compile cppheader docs clean

all: jar native

jar: $(JAR_NAME).jar

$(JAR_NAME).jar: $(CLASSFILES)
	cd $(JAVA_BUILD_DIR) && $(JAR) cf ../$(JAR_NAME).jar com

native: lib$(LIB_NAME).so

lib$(LIB_NAME).so: $(CPP_BUILD_DIR)/lib$(LIB_NAME).so
	cp $(CPP_BUILD_DIR)/lib$(LIB_NAME).so .

cppheaders: $(CPPHEADER) $(CPPINCLUDES)

# Java 11 no longer has javah.
ifneq ($(or $(findstring javac 11.,$(shell $(JAVAC) -version)), $(findstring javac 17.,$(shell $(JAVAC) -version))), $(findstring javac 21.,$(shell $(JAVAC) -version))),)
$(CPPHEADER): $(CLASSFILES) | $(CPP_BUILD_DIR)
	$(JAVAC) -classpath $(JAVA_BUILD_DIR) -d $(CPP_BUILD_DIR) -h $(CPP_BUILD_DIR) $(SOURCES)
else # But java 1.8 needs it.
$(CPPHEADER): $(CLASSFILES) | $(CPP_BUILD_DIR)
	$(JAVAH) -jni -classpath $(JAVA_BUILD_DIR) -d $(CPP_BUILD_DIR) com.beegfs.JBeeGFS
endif

$(CPP_BUILD_DIR)/jni.h: | $(CPP_BUILD_DIR)
	cp $(JAVA_HOME)/include/jni.h $@

$(CPP_BUILD_DIR)/jni_md.h: | $(CPP_BUILD_DIR)
	cp $(JAVA_HOME)/include/linux/jni_md.h $@

$(CPP_BUILD_DIR)/lib$(LIB_NAME).so: $(SOURCEDIR)/jbeegfs.cpp cppheaders | $(CPP_BUILD_DIR)
	g++ -shared -fpic -o $(CPP_BUILD_DIR)/lib$(LIB_NAME).so $(BEEGFS_INCLUDE) \
			-I$(CPP_BUILD_DIR) $(SOURCEDIR)/jbeegfs.cpp

compile: $(CLASSFILES)

$(JAVA_BUILD_DIR)/%.class: $(SOURCEDIR)/%.java | $(JAVA_BUILD_DIR)
	$(JAVAC) $(JAVACOPTS) $<

$(CPP_BUILD_DIR):
	mkdir $(CPP_BUILD_DIR)

$(JAVA_BUILD_DIR):
	mkdir -p $(JAVA_BUILD_DIR)

.IGNORE: docs # ignore javadoc complaints about missing external documentation.

docs: $(SOURCES)
	$(JAVADOC) -private -d $(DOCDIR) $(SOURCES)

clean:
	rm -rf $(DOCDIR) $(CPP_BUILD_DIR) $(JAVA_BUILD_DIR) $(JAR_NAME).jar lib$(LIB_NAME).so
