# location of the Python header files
 
PYTHON_VERSION = 3.7m
PYTHON_VERSION_SHORT = 37
PYTHON_INCLUDE =$(CONDA_PREFIX)/include/python$(PYTHON_VERSION)
PYTHON_LIB =$(CONDA_PREFIX)/lib/python3.7/config-3.7m-x86_64-linux-gnu-lpython$(PYTHON_VERSION)

NV_PREFIX = /usr/local/cuda
NVCC=$(NV_PREFIX)/bin/nvcc
NVLIB=$(NV_PREFIX)/lib64/
# location of the Boost Python include files and library
 
BOOST_INC =$(CONDA_PREFIX)/include 
BOOST_LIB =$(CONDA_PREFIX)/lib 

# TODO: compile features/wrappers using generic commands, see: https://stackoverflow.com/questions/2908057/can-i-compile-all-cpp-files-in-src-to-os-in-obj-then-link-to-binary-in
FEATURE_SRC_DIR := features
FEATURE_OBJ_DIR := obj/feature_obj
FEATURE_SRC_FILES := $(wildcard $(FEATURE_SRC_DIR)/*.cpp)
FEATURE_OBJ_FILES := $(patsubst $(FEATURE_SRC_DIR)/%.cpp,$(FEATURE_OBJ_DIR)/%.o,$(FEATURE_SRC_FILES))

GPU_FEATURE_SRC_DIR := gpu_features
GPU_FEATURE_OBJ_DIR := obj/gpu_feature_obj
GPU_FEATURE_SRC_FILES := $(wildcard $(GPU_FEATURE_SRC_DIR)/*.cpp)
GPU_FEATURE_OBJ_FILES := $(patsubst $(GPU_FEATURE_SRC_DIR)/%.cpp,$(GPU_FEATURE_OBJ_DIR)/%.o,$(GPU_FEATURE_SRC_FILES))

WRAPPER_SRC_DIR := wrappers
WRAPPER_OBJ_DIR := obj/wrapper_obj
WRAPPER_SRC_FILES := $(wildcard $(WRAPPER_SRC_DIR)/*.cpp)
WRAPPER_OBJ_FILES := $(patsubst $(WRAPPER_SRC_DIR)/%.cpp,$(WRAPPER_OBJ_DIR)/%.o,$(WRAPPER_SRC_FILES))

GPU_WRAPPER_SRC_DIR := gpu_wrappers
GPU_WRAPPER_OBJ_DIR := obj/gpu_wrapper_obj
GPU_WRAPPER_SRC_FILES := $(wildcard $(GPU_WRAPPER_SRC_DIR)/*.cpp)
GPU_WRAPPER_OBJ_FILES := $(patsubst $(GPU_WRAPPER_SRC_DIR)/%.cpp,$(GPU_WRAPPER_OBJ_DIR)/%.o,$(GPU_WRAPPER_SRC_FILES))


UTILS_SRC_DIR := utils
UTILS_OBJ_DIR := obj/utils_obj
UTILS_SRC_FILES := $(wildcard $(UTILS_SRC_DIR)/*.cpp)
UTILS_OBJ_FILES := $(patsubst $(UTILS_SRC_DIR)/%.cpp,$(UTILS_OBJ_DIR)/%.o,$(UTILS_SRC_FILES))

INCLUDES_DIR = includes


CFLAGS = -fPIC -c -std=c++11
NVFLAGS = -x cu -arch=sm_35 -dc -Xcompiler 
# compile mesh classes
TARGET = LibExportMain
FEATURE = ExampleFeatureCalculator
WRAPPER = ExampleWrapper

OUTPUT_NAME = _features
# OUTPUT_NAME = features

CACHE_GRAPH = CacheGraph
CONVERTER = ConvertedGNXReciever
FEATURE_TEMPLATE=FeatureCalculator

.PHONY:clean preScript
accelerated_graph_features/$(OUTPUT_NAME).so: $(TARGET).o $(WRAPPER_OBJ_FILES) $(UTILS_OBJ_FILES) $(FEATURE_OBJ_FILES) $(GPU_FEATURE_OBJ_FILES) $(GPU_WRAPPER_OBJ_FILES) $(CACHE_GRAPH).o $(FEATURE_TEMPLATE).o
	$(NVCC) -arch=sm_35 -dlink -Xcompiler -fPIC -std=c++11 $(TARGET).o $(GPU_FEATURE_OBJ_FILES) $(GPU_WRAPPER_OBJ_FILES) -o obj/gpuCode.o
	g++ -shared -Wl,--export-dynamic $^ obj/gpuCode.o -L$(PYTHON_LIB) -lpython$(PYTHON_VERSION) -L$(BOOST_LIB) -lboost_python$(PYTHON_VERSION_SHORT) -L$(NVLIB) -lcudart -o $@


################  Changes for each feature #######################
$(FEATURE_OBJ_DIR)/%.o: $(FEATURE_SRC_DIR)/%.cpp $(INCLUDES_DIR)/%.h
	g++ $(CFLAGS) -o $@ $<
   
$(WRAPPER_OBJ_DIR)/%.o: $(WRAPPER_SRC_DIR)/%.cpp $(WRAPPER_SRC_DIR)/%.h
	g++ $(CFLAGS) -I$(PYTHON_LIB) -I$(PYTHON_INCLUDE) -I$(BOOST_INC) -o $@ $<

$(GPU_FEATURE_OBJ_DIR)/%.o: $(GPU_FEATURE_SRC_DIR)/%.cpp $(INCLUDES_DIR)/%.h
	$(NVCC) $(NVFLAGS) $(CFLAGS) -o $@ $<

$(GPU_WRAPPER_OBJ_DIR)/%.o: $(GPU_WRAPPER_SRC_DIR)/%.cpp $(GPU_WRAPPER_SRC_DIR)/%.h
	$(NVCC) $(NVFLAGS) $(CFLAGS) -I$(PYTHON_LIB) -I$(PYTHON_INCLUDE) -I$(BOOST_INC) -o $@ $<



#$(FEATURE).o: features/$(FEATURE).cpp # includes/$(CACHE_GRAPH).h
#	g++ $(CFLAGS) -o $@ $^
#	
#$(WRAPPER).o: wrappers/$(WRAPPER).cpp # includes/$(FEATURE).h includes/$(CONVERTER).h
#	g++ $(CFLAGS) -I$(PYTHON_INCLUDE) -I$(BOOST_INC) -o $@ $^

############### From here, always the same #######################
preScript:
	mkdir -p obj
	mkdir -p $(FEATURE_OBJ_DIR) $(WRAPPER_OBJ_DIR) $(UTILS_OBJ_DIR) $(GPU_FEATURE_OBJ_DIR) $(GPU_WRAPPER_OBJ_DIR)

$(TARGET).o:$(TARGET).cpp preScript 
	$(NVCC) $(NVFLAGS) $(CFLAGS) -I$(PYTHON_LIB) -I$(PYTHON_INCLUDE) -I$(BOOST_INC) $< -o $@ 	

$(CACHE_GRAPH).o: arch/$(CACHE_GRAPH).cpp
	g++ $(CFLAGS) $^

$(UTILS_OBJ_DIR)/%.o: $(UTILS_SRC_DIR)/%.cpp
	g++ $(CFLAGS) -I$(PYTHON_LIB) -I$(PYTHON_INCLUDE) -I$(BOOST_INC) -o $@ $^

$(FEATURE_TEMPLATE).o: arch/$(FEATURE_TEMPLATE).cpp
	g++ $(CFLAGS) $^

clean:
	rm accelerated_graph_features/$(OUTPUT_NAME).so $(TARGET).o $(WRAPPER_OBJ_FILES) $(UTILS_OBJ_FILES) $(FEATURE_OBJ_FILES) $(CACHE_GRAPH).o $(FEATURE_TEMPLATE).o
