# new common makefile for linux and windows
# JNI library name to be used by fispro
# shared library
# architecture
# the arch command is only valid under Linux/UNIX

# uncomment next line for compilation on Windows 32 bits
# OS=WIN32
# uncomment next line for compilation on Windows 64 bits
# OS=WIN64

# uncomment next line for debug mode
#DEBUG=true

# uncomment next line for OPENMP compilation - valid only for gcc version >=4.3
#OPENMP=true 

# if NODYN flag do not use libfispro.so 
ifndef NODYN
NODYN=true
endif

ifndef DESTDIR
DESTDIR=/opt/fispro
endif

JNILIB=libjnifis.so
RUNS=$(BIN)/$(JNILIB) $(BIN)/perf $(BIN)/sample $(BIN)/vocreduc $(BIN)/readdata $(BIN)/medfis $(BIN)/km $(BIN)/fpa $(BIN)/genrules $(BIN)/fistree $(BIN)/fislinks $(BIN)/hfpselect $(BIN)/hfpsr $(BIN)/hfpvertex $(BIN)/fisimple $(BIN)/wm $(BIN)/fisopt $(BIN)/superfis $(BIN)/ols

ifeq ($(NODYN),true)
RUNS+=$(BIN)/libfispro.so
endif

# path for binaries
BIN=../bin

# OS-default=LINUX
# for win32 run OS=WIN32;make
# for win64 run OS=WIN64;make
ifndef OS
OS=LINUX
endif
# the arch command is only valid under Linux/UNIX
#ARCH=$(shell arch)
ARCH=$(shell uname -m)
export ARCH

# includes for jni in $JDK

# for win -no gsl package needed - static link - libraries in  subdirectory
# includes for jni in JDK
ifeq ($(OS),$(filter $(OS),WIN32 WIN64))
JNILIB=jnifis.dll
# enter path to GSL library
GSL=/E/cpp/gsl/1.8
INCLUDE=-I$(GSL)/include
# enter path to JDK
JDK=/E/java/jdk/1.8.0_161-x64
INCLUDE+=-I$(JDK)/include -I$(JDK)/include/win32
endif

ifeq ($(OS),LINUX)
JNILIB=libjnifis.so
INCLUDE=-I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux
endif

# C Compiler - make sure gcc-v returns gcc version >=3.0
CC=g++
INCLUDE+= -Ibase -Ifpa -Igenfis -Ifistree -Ilinks -Ihfp -Isimple -Ifisopt -Iwm -Iols -Isuperfis

# flags for shared library dll (windows) or shared library (Linux)
LFLAGS=-D_JNI_IMPLEMENTATION_ -shared
ifeq ($(OS),$(filter $(OS),WIN32 WIN64))
LFLAGS+=-static -Wl,--kill-at
endif

# flag -DDEBUG
ifdef DEBUG
OPT=-g -DDEBUG -O0
else
OPT=-O3 -DNDEBUG
endif

# win32
ifeq ($(OS),WIN32)
OPT+= -m32
endif
# win64
ifeq ($(OS),WIN64)
OPT+= -m64
endif

ifeq ($(OS),LINUX)
ifeq ($(ARCH),x86_64)
OPT+=-fPIC
endif
endif

ifdef OPENMP
ifeq ($(CXX),g++)
OPT+=-fopenmp
LIBOMP=-lgomp
endif
endif

GCC_VERSION = $(shell gcc -dumpversion)
# force c++11 standard compilation for gcc version < 6
GCC_6 = 6
ifeq ($(GCC_6), $(lastword $(sort $(GCC_VERSION) $(GCC_6))))
  OPT += -std=c++11 
endif

#CCFLAGS=$(INCLUDE) -w $(OPT) -fopenmp
CCFLAGS=$(INCLUDE) -Wall $(OPT)

# C++ programs in subdirectories independent of JNI library and java

# fispro objects
OBJECTS=$(BIN)/common.o $(BIN)/aggreg.o $(BIN)/defuz.o $(BIN)/fis.o $(BIN)/in.o $(BIN)/out.o $(BIN)/mf.o $(BIN)/rule.o $(BIN)/gensample.o $(BIN)/fpa.o $(BIN)/genfis.o $(BIN)/fistree.o $(BIN)/calctree.o $(BIN)/prune.o $(BIN)/criteria.o $(BIN)/tree.o $(BIN)/linkfis.o $(BIN)/hfpfis.o $(BIN)/hfpin.o $(BIN)/hfpintri.o $(BIN)/sethfpfis.o $(BIN)/fisimple.o $(BIN)/fiswm.o $(BIN)/fis_jnifis.o $(BIN)/algo.o $(BIN)/avect.o $(BIN)/conteneur.o $(BIN)/fib.o $(BIN)/sifopt.o $(BIN)/sw.o $(BIN)/optotd.o  $(BIN)/optdto.o $(BIN)/optconstraint.o  $(BIN)/optkeyutil.o $(BIN)/permutation.o $(BIN)/mfdposs.o $(BIN)/pt.o $(BIN)/ols.o $(BIN)/fisols.o $(BIN)/medfis.o $(BIN)/dist.o

# gsl objects from library-static link  for windows
#                          dynamic link for Linux
ifeq ($(OS),WIN32)
OBJECTSGSL=$(GSL)/lib/libgsl.a $(GSL)/lib/libgslcblas.a
BIN=../bin-x86
endif
ifeq ($(OS),WIN64)
OBJECTSGSL=$(GSL)/lib64/libgsl.a $(GSL)/lib64/libgslcblas.a
BIN=../bin-amd64
endif
ifeq ($(OS),LINUX)
OBJECTSGSL=-lgsl -lgslcblas
endif


all : init build

init : 
	echo making directory for binaries
	mkdir -p $(BIN)

build :	buildjni buildprogs

buildjni : $(BIN)/$(JNILIB)

# build shared jni library libjnifis
$(BIN)/$(JNILIB) : $(OBJECTS) 
	echo building jni library
#	$(CC) $(CCFLAGS) $(LFLAGS) -o $(BIN)/$(JNILIB) $(OBJECTS) $(OBJECTSGSL) -lm -lgomp -lpthread
	$(CC) $(CCFLAGS) $(LFLAGS) -o $(BIN)/$(JNILIB) $(OBJECTS) $(OBJECTSGSL) -lm $(LIBOMP)
	echo jni library successfully built

# compile common
$(BIN)/common.o : base/common.cpp base/common.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/common.o base/common.cpp

# compile aggreg
$(BIN)/aggreg.o : base/aggreg.cpp base/fis.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/aggreg.o base/aggreg.cpp

# compile defuz
$(BIN)/defuz.o : base/defuz.cpp base/defuz.h base/fis.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/defuz.o base/defuz.cpp

# compile fis
$(BIN)/fis.o : base/fis.cpp base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/fis.o base/fis.cpp 

# compile in
$(BIN)/in.o : base/in.cpp base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/in.o base/in.cpp 

# compile out
$(BIN)/out.o : base/out.cpp base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/out.o base/out.cpp 

# compile mf
$(BIN)/mf.o : base/mf.cpp base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/mf.o base/mf.cpp 

# compile mfdposs
$(BIN)/mfdposs.o : base/mfdposs.cpp base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/mfdposs.o base/mfdposs.cpp 

# compile pt
$(BIN)/pt.o : base/pt.cpp  base/fis.h  base/mf.h base/rule.h base/defuz.h base/common.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/pt.o base/pt.cpp

# compile rule
$(BIN)/rule.o : base/rule.cpp base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/rule.o base/rule.cpp 

# compile gensample
$(BIN)/gensample.o : base/gensample.cpp base/gensample.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/gensample.o base/gensample.cpp

# compile dist
$(BIN)/dist.o : base/dist.cpp base/fis.h  
	$(CC) -c $(CCFLAGS) -o $(BIN)/dist.o base/dist.cpp

# compile fpa
$(BIN)/fpa.o : fpa/fpa.cpp fpa/fpa.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/fpa.o fpa/fpa.cpp

# compile genfis
$(BIN)/genfis.o : genfis/genfis.cpp genfis/genfis.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/genfis.o genfis/genfis.cpp

# compile fistree objects
$(BIN)/fistree.o : fistree/fistree.cpp fistree/fistree.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/fistree.o fistree/fistree.cpp 

$(BIN)/prune.o : fistree/prune.cpp fistree/fistree.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/prune.o fistree/prune.cpp 

$(BIN)/calctree.o : fistree/calctree.cpp fistree/fistree.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/calctree.o fistree/calctree.cpp

$(BIN)/tree.o : fistree/tree.cpp fistree/fistree.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/tree.o fistree/tree.cpp

$(BIN)/criteria.o : fistree/criteria.cpp fistree/fistree.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/criteria.o fistree/criteria.cpp
# end fistree objects

# compile linkfis
$(BIN)/linkfis.o : links/linkfis.cpp links/linkfis.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/linkfis.o links/linkfis.cpp 

# compile hfpfis
$(BIN)/hfpfis.o : hfp/hfpfis.cpp hfp/hfpfis.h hfp/hfpin.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/hfpfis.o hfp/hfpfis.cpp 

# compile hfpin
$(BIN)/hfpin.o : hfp/hfpin.cpp hfp/hfpin.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/hfpin.o hfp/hfpin.cpp 

# compile hfpintri
$(BIN)/hfpintri.o : hfp/hfpintri.cpp hfp/hfpin.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/hfpintri.o hfp/hfpintri.cpp 

$(BIN)/sethfpfis.o : hfp/sethfpfis.cpp  hfp/sethfpfis.h base/common.h base/common.cpp 
	$(CC) -c $(CCFLAGS) -o $(BIN)/sethfpfis.o hfp/sethfpfis.cpp

# compile fisimple
$(BIN)/fisimple.o : simple/fisimple.cpp simple/fisimple.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/fisimple.o simple/fisimple.cpp 

# compile wm
$(BIN)/fiswm.o : wm/fiswm.cpp wm/fiswm.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/fiswm.o wm/fiswm.cpp 

# compile fisopt
$(BIN)/algo.o : fisopt/algo.cpp fisopt/algo.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/algo.o fisopt/algo.cpp 

$(BIN)/avect.o : fisopt/avect.cpp fisopt/avect.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/avect.o fisopt/avect.cpp

$(BIN)/conteneur.o : fisopt/conteneur.cpp fisopt/conteneur.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/conteneur.o fisopt/conteneur.cpp

$(BIN)/fib.o : fisopt/fib.cpp fisopt/algo.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/fib.o fisopt/fib.cpp

$(BIN)/sw.o : fisopt/sw.cpp fisopt/algo.h base/common.h base/mf.h base/rule.h base/defuz.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/sw.o fisopt/sw.cpp

$(BIN)/sifopt.o : fisopt/sifopt.cpp fisopt/sifopt.h fisopt/algo.h base/common.h base/mf.h base/rule.h base/defuz.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/sifopt.o fisopt/sifopt.cpp

$(BIN)/optotd.o : fisopt/optotd.cpp fisopt/sifopt.h fisopt/algo.h base/common.h base/mf.h base/rule.h base/defuz.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/optotd.o fisopt/optotd.cpp

$(BIN)/optdto.o : fisopt/optdto.cpp fisopt/sifopt.h fisopt/algo.h base/common.h base/mf.h base/rule.h base/defuz.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/optdto.o fisopt/optdto.cpp

$(BIN)/optkeyutil.o : fisopt/optkeyutil.cpp fisopt/sifopt.h fisopt/algo.h base/common.h base/mf.h base/rule.h base/defuz.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/optkeyutil.o fisopt/optkeyutil.cpp

$(BIN)/optconstraint.o :  fisopt/optconstraint.cpp fisopt/sifopt.h fisopt/algo.h base/common.h base/mf.h base/rule.h base/defuz.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/optconstraint.o fisopt/optconstraint.cpp

$(BIN)/permutation.o :  fisopt/permutation.cpp fisopt/sifopt.h fisopt/algo.h base/common.h base/mf.h base/rule.h base/defuz.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/permutation.o fisopt/permutation.cpp

$(BIN)/medfis.o : fisopt/medfis.cpp base/common.h base/fis.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/medfis.o fisopt/medfis.cpp

$(BIN)/ols.o :  ols/ols.cpp ols/ols.h ols/fisols.h base/common.h base/mf.h base/rule.h base/defuz.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/ols.o ols/ols.cpp

$(BIN)/fisols.o :  ols/fisols.cpp ols/ols.h ols/fisols.h base/common.h base/mf.h base/rule.h base/defuz.h
	$(CC) -c $(CCFLAGS) -o $(BIN)/fisols.o ols/fisols.cpp

# compile fis_jnifis
$(BIN)/fis_jnifis.o : jni/fis_jnifis.cpp jni/fis_jnifis.h fpa/fpa.h base/fis.h base/common.h base/mf.h base/rule.h base/defuz.h 
	$(CC) -c $(CCFLAGS) -o $(BIN)/fis_jnifis.o jni/fis_jnifis.cpp

buildprogs : fis fpaexec genrules fistreeexec linksexec hfpall simpleexec wmexec fisoptexec sample vocreduc readdata km superfisexec olsexec

fis :
	cd base;$(MAKE) -f makefile NODYN=$(NODYN)
	echo base library and programs successfully built

fpaexec :
	cd fpa;$(MAKE) -f makefpa NODYN=$(NODYN)
	echo fpa binary successfully built

genrules :
	cd genfis;$(MAKE) -f makegenrules NODYN=$(NODYN)
	echo genrules binary successfully built

fistreeexec :
	cd fistree;$(MAKE) -f makefistree NODYN=$(NODYN)
	echo fistree binary successfully built

linksexec :
	cd links;$(MAKE) -f makelinks NODYN=$(NODYN)
	echo links binary successfully built

hfpall :
	cd hfp;$(MAKE) -f makehfpall NODYN=$(NODYN)
	echo hfp binaries successfully built

simpleexec :
	cd simple;$(MAKE) -f makesimple NODYN=$(NODYN)
	echo simple binary successfully built

wmexec :
	cd wm;$(MAKE) -f makewm
	echo wm binary successfully built

fisoptexec :
	cd fisopt;$(MAKE) -f makefisopt;$(MAKE) -f makeloopoptimsample
	echo fisopt binary successfully built
	echo loopoptims binary successfully built

olsexec :
	cd ols;$(MAKE) -f makeols NODYN=$(NODYN)
	echo ols binary successfully built

sample :
	cd base;$(MAKE) -f makesample NODYN=$(NODYN)
	echo sample binary successfully built

vocreduc :
	cd base;$(MAKE) -f makevocreduc NODYN=$(NODYN)
	echo vocreduc binary successfully built

readdata :
	cd base;$(MAKE) -f makereaddata NODYN=$(NODYN)
	echo readdata binary successfully built

km :
	cd base;$(MAKE) -f makekm NODYN=$(NODYN)
	echo km binary successfully built

superfisexec :
	cd superfis;$(MAKE) -f makesuperfis NODYN=$(NODYN)
	echo superfis binary successfully built

install:
	mkdir -p $(DESTDIR)/bin;cp $(RUNS) $(DESTDIR)/bin

clean : 
	/bin/rm -f $(BIN)/*.o $(BIN)/libfispro.* $(BIN)/jnifis.dll $(BIN)/*.exe

cleanall :
	/bin/rm -f $(BIN)/*

