################################################################################
# initialization
################################################################################

# set some defaults if this is not being called from the main makefile
ifndef CALLED_FROM_MAIN

	# compilers
	CXX     := g++#            # C++ compiler
	PY3     := python3#        # Python 3.x
	PIP     := $(PY3) -m pip#  # Python pip
	SPHINX  := sphinx-build#   # Python documentation

	# aliases
	CP     := cp -rv
	MV     := mv -v
	RM     := rm -rfv

	# color definitions
	blue := $(shell tput setaf 6)
	sgr0 := $(shell tput sgr0)

	# detect os (linux, darwin)
	OS := $(shell uname -s | tr '[:upper:]' '[:lower:]')

	# detect bit size
	UNAME_M := $(shell uname -m)
	ifeq ($(UNAME_M),$(filter $(UNAME_M),x86_64 arm64 aarch64))
		ARCH := 64
	else
		ARCH := 32
	endif

	# get the extension for compiled python libraries, lib directory, and python library version
	ifneq (, $(shell which $(PY3)))  # if python is installed
		LIBEXT_PY := $(shell $(PY3) -c 'import sysconfig; print(sysconfig.get_config_var("EXT_SUFFIX"))')
	endif

endif


################################################################################
# compilation parameters
################################################################################

# define output file
OUT := libslbmPyshell$(LIBEXT_PY)
OUTDIR := ../lib

# includes
INC := -Icc/include -I../GeoTessCPP/include -I../SLBM/include $(shell $(PY3) -m pybind11 --includes)

# libraries
LIBS := -L$(OUTDIR) -lgeotesscpp -lslbm

# compiling parameters
ifeq ($(UNAME_M),$(filter $(UNAME_M),arm64 aarch64))
	CXXFLAGS := -mcpu=native
else
	CXXFLAGS := -march=native -m$(ARCH)
endif
CXXFLAGS += -D$(OS) -O1 -fPIC -std=c++11

# specific LD_FLAGS on Mac
ifeq ($(OS),darwin)

	# always required for pybind11
	OTHER_LDFLAGS += -undefined dynamic_lookup

	# if using clang instead of gnu compiler, set additional flags
	CLANG := $(shell $(CXX) -v 2>&1 | grep -qi clang; echo $$?)
	ifeq ($(CLANG),0)
		CXXFLAGS += -Wno-deprecated-declarations
		OTHER_LDFLAGS += -undefined dynamic_lookup -rpath @loader_path
	endif

endif

# list of objects to compile
OBJS = cc/src/slbm_Py_shell.o


################################################################################
# recipes
################################################################################

# recipe to make everything and run tests
all: initialize slbmpyshell slbmpymod finalize msg_outro

# command that tells us which recipes don't build source files
.PHONY: all initialize msg_intro slbmpyshell slbmpymod msg_docs docs finalize msg_outro clean cleanall


# initialize compilation script
initialize: msg_intro

# print intro message
msg_intro:
	@echo "$(blue)------------------------------------------------------------$(sgr0)"
	@echo "$(blue)Making RSTT Python library...$(sgr0)"
	@echo "$(blue)------------------------------------------------------------$(sgr0)"

# print outro message
msg_outro:
	@printf "$(blue)To install the 'rstt' module, run:\n$(sgr0)"
	@printf "$(blue) $$ $(PIP) install --no-index --find-links=$(shell pwd)/wheel rstt\n$(sgr0)"

# to build any *.o file, compile its corresponding *.cc file
%.o: %.cc
	@printf "$(blue)(Building obj) $(sgr0)"
	$(CXX) $(CXXFLAGS) $(INC) -o $@ -c $<


# build library after building each prerequisite in $(OBJS)
slbmpyshell: initialize $(OUT)

# MacOS
ifeq ($(OS),darwin)
$(OUT): $(OBJS)
	@printf "$(blue)(Building lib) $(sgr0)"
	$(CXX) $(CXXFLAGS) -shared $(OTHER_LDFLAGS) -o $(OUT) $(OBJS) $(LIBS)

# linux
else
$(OUT): $(OBJS)
	@printf "$(blue)(Building lib) $(sgr0)"
	$(CXX) $(CXXFLAGS) -shared -Wl,-rpath,'$$ORIGIN' -o $(OUT) $(OBJS) $(LIBS)

endif


# build module
slbmpymod: slbmpyshell
	@printf "$(blue)(Copying shared libs) $(sgr0)"
	$(CP) ../lib/libgeotesscpp.* ../lib/libslbm.* ./python/rstt/
	$(MV) ./libslbmPyshell.* ./python/rstt/
	@printf "$(blue)(Compiling module) $(sgr0)"
	$(PIP) wheel --no-build-isolation -w wheel python/


# print docs msg
msg_docs:
	@echo "$(blue)------------------------------------------------------------$(sgr0)"
	@echo "$(blue)Making RSTT Python documentation...$(sgr0)"
	@echo "$(blue)------------------------------------------------------------$(sgr0)"

# documentation
docs: msg_docs doc/html
doc/html:
ifeq (, $(shell which $(SPHINX)))  # sphinx is not installed
	@printf "$(blue)(Building HTML docs) $(sgr0)"
	@echo "$(SPHINX) is not installed. Skipping..."

else  # sphinx is installed
	@printf "$(blue)(Building HTML docs) $(sgr0)"
	cd doc; $(MAKE) html
	$(MV) doc/_build/html doc/
	$(RM) doc/_build

endif


# move files and clean up
finalize:
	@printf "$(blue)(Moving files) $(sgr0)"
	$(CP) ./python/rstt ../lib/

clean:
	@printf "$(blue)(Clean *.o) $(sgr0)"
	$(RM) cc/src/*.o

cleanall: clean
	@printf "$(blue)(Clean docs) $(sgr0)"
	$(RM) doc/html
	@printf "$(blue)(Clean libs) $(sgr0)"
	$(RM) $(OUTDIR)/rstt python/rstt/*.dylib python/rstt/*.so
	@printf "$(blue)(Clean module) $(sgr0)"
	$(RM) wheel python/rstt.egg-info python/build python/rstt/__pycache__
