# ================= Libraries and Includes ====================================

BLA_INCLUDE_DIR = ./BLAS/include
DAT_INCLUDE_DIR = ./DataStruct/include
INO_INCLUDE_DIR = ./InputOutput/include
ENM_INCLUDE_DIR = ./ElasticNet/Network/include
HES_INCLUDE_DIR = ./ElasticNet/Hessian/include
COR_INCLUDE_DIR = ./EigenSolvers/Core/include
BCD_INCLUDE_DIR = ./EigenSolvers/JacobiDavidson/include
FIL_INCLUDE_DIR = ./EigenSolvers/Filters/include
MAT_INCLUDE_DIR = ./MatVect/include
TLS_INCLUDE_DIR = ./Analysis/include
CUD_INCLUDE_DIR = ./CUDA_Kernels/include
GMP_INCLUDE_DIR = /opt/homebrew/Cellar/gmp/6.3.0/include

GMP_LIB_DIR = -L/opt/homebrew/Cellar/gmp/6.3.0/lib
GMP_LIBS = -lgmp
BLAS_LIBS = -lblas -llapack
THREAD_LIBS = -lpthread

# ================= Project Directories ====================================

INC_DIR = ./project/include
SRC_DIR = ./project/src
OBJ_DIR = ./project/src
BIN_DIR = ./bin

# ================= Project Name ===========================================

EXT=
NAME=ProteinNM
NAMEOBJ=$(OBJ_DIR)/$(NAME).o
NAMEBIN=$(BIN_DIR)/$(NAME)$(EXT)

# ================= Compilers and Flags ====================================

CC 		:= gcc
CFLAGS 		:= -c -O3 -ansi -Wall -Werror -pedantic 
CPP 		:= g++
CPPFLAGS	:= -c -std=c++14 -O3 -Wdeprecated-declarations -Wuninitialized -ansi -Wall -std=c++0x

INCLUDE_DIRS := -I$(BLA_INCLUDE_DIR) -I$(DAT_INCLUDE_DIR) -I$(INC_DIR) -I$(INO_INCLUDE_DIR) -I$(ENM_INCLUDE_DIR) -I$(HES_INCLUDE_DIR) -I$(TLS_INCLUDE_DIR) -I$(MAT_INCLUDE_DIR) -I$(COR_INCLUDE_DIR) -I$(FIL_INCLUDE_DIR) -I$(GMP_INCLUDE_DIR) -I$(BCD_INCLUDE_DIR)

LIB_DIRS = $(GMP_LIB_DIR)

LIBS = $(BLAS_LIBS) $(THREAD_LIBS) $(GMP_LIBS)

LOAD_LIB_PATH =

LD_FLAGS = -O3

# ================= Modifiers based on flags ===============================

ifeq ($(strip $(ARCH)),)
CPPFLAGS   += 
else ifneq ($(findstring $(ARCH),avx2 AVX2),)
CPPFLAGS   += -DSIMD -march=native
else ifneq ($(findstring $(ARCH),neon NEON),)
CPPFLAGS   += -DSIMD
else ifneq ($(findstring $(ARCH),gpu GPU),)
LIBS = -lcublas -lcurand -lcusolver -lcusparse -lblas -llapack
INCLUDE_DIRS += -I$(CUD_INCLUDE_DIR)
CPP             := nvcc
CPPFLAGS         := -c -O3 -DGPU -x cu
endif

ifeq ($(strip $(type)),)
CPPFLAGS   += -DDOUBLE
else ifneq ($(findstring $(type),single float),)
CPPFLAGS   +=
else ifeq ($(type),double)
CPPFLAGS   += -DDOUBLE
endif

# ================= Pattern rules ==========================================

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
	$(CPP) $(CPPFLAGS) $(INCLUDE_DIRS) $< -o $@

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
	$(CC) $(CFLAGS) $(INCLUDE_DIRS) $< -o $@

# ================= Compile source code ====================================

OBJECTS = \
$(NAMEOBJ)

# ================= Generate Executable ====================================

$(NAMEBIN) : $(OBJECTS)
	$(CPP) -o $(NAMEBIN) $(LD_FLAGS) $(OBJECTS) $(LIB_DIRS) $(LIBS) $(LOAD_LIB_PATH)

all: $(OBJECTS)
	$(CPP) -o $(NAMEBIN) $(LD_FLAGS) $(OBJECTS) $(LIB_DIRS) $(LIBS) $(LOAD_LIB_PATH)

clean:
	touch $(OBJ_DIR)/junk.o; rm -f $(OBJ_DIR)/*.o $(NAMEBIN)
