#===============================================================================
# Copyright 2004 Intel Corporation.
#
# This software and the related documents are Intel copyrighted  materials,  and
# your use of  them is  governed by the  express license  under which  they were
# provided to you (License).  Unless the License provides otherwise, you may not
# use, modify, copy, publish, distribute,  disclose or transmit this software or
# the related documents without Intel's prior written permission.
#
# This software and the related documents  are provided as  is,  with no express
# or implied  warranties,  other  than those  that are  expressly stated  in the
# License.
#===============================================================================

##  Content:
##      Intel(R) oneAPI Math Kernel Library Custom Shared Object builder
##
##******************************************************************************

help:
	@echo
	@echo "Usage: make libintel64 [<options>]"
	@echo
	@echo "  libintel64"
	@echo "      A makefile target to build a dynamic library that contains the"
	@echo "      specified oneMKL entry-point functions."
	@echo
	@echo "  <options>"
	@echo
	@echo "    name=<so_name>"
	@echo "        The name of the shared object to be created without the '.so' extension."
	@echo "        Default: mkl_custom"
	@echo
	@echo "    export=<file_name>"
	@echo "        The name of the file that contains the list of entry points"
	@echo "        to be included to the shared object."
	@echo "        Default: user_example_list"
	@echo
	@echo "    interface={lp64|ilp64}"
	@echo "        The lp64 interface uses the 32-bit integer type, while the"
	@echo "        ilp64 interface uses the 64-bit integer type."
	@echo "        Default: lp64"
	@echo
	@echo "    threading={parallel|sequential}"
	@echo "        Specifies whether to use oneMKL in the threaded or sequential mode."
	@echo "        Default: parallel"
	@echo
	@echo "    parallel={intel|tbb|gnu}"
	@echo "        Specifies whether to use Intel OpenMP, Intel oneTBB or GNU* OpenMP (for GNU compiler only)."
	@echo "        Default: intel"
	@echo
	@echo "    cluster={no|yes}"
	@echo "        Specifies whether oneMKL cluster components (BLACS, ScaLAPACK or/and CDFT)"
	@echo "        are needed to build the custom shared object."
	@echo "        Default: no"
	@echo
	@echo "    blacs_mpi={intelmpi|openmpi}"
	@echo "        Specifies which pre-compiled oneMKL BLACS library to use. Ignored if 'cluster=no'."
	@echo "        Default: intelmpi"
	@echo
	@echo "    BLACSDIR=<BLACS_directory>"
	@echo "        Specifies the path to a custom oneMKL BLACS library. Ignored if 'cluster=no'."
	@echo "        Default: \$$(MKLROOT)/lib"
	@echo
	@echo "    blacs_name=<lib_name>"
	@echo "        Specifies the name of the custom oneMKL BLACS library to use (without the '.a' extension)."
	@echo "        Ignored if 'cluster=no'. 'blacs_mpi' is ignored if 'blacs_name' was specified."
	@echo "        Default: libmkl_blacs_<blacs_mpi>_<interface>"
	@echo
	@echo "    MKLROOT=<path>"
	@echo "        Intel(R) oneMKL installation directory."
	@echo "        Default: ../../../.."
	@echo
	@echo "    xerbla=<err_handler>"
	@echo "        The name of the object file that contains the user's error handler."
	@echo "        By default the native oneMKL XERBLA is used."
	@echo
	@echo
	@echo "Usage examples:"
	@echo
	@echo "  make libintel64"
	@echo "      This command creates 'mkl_custom.so' for Intel(R) 64 architecture."
	@echo "      Function list is taken from the predefined file 'user_example_list'."
	@echo "      It uses the lp64 interface, Intel OpenMP, and oneMKL XERBLA."
	@echo
	@echo "  make libintel64 name=my_cluster export=cluster_example_list interface=ilp64 cluster=yes"
	@echo "      This command creates 'my_cluster.so' for Intel(R) 64 architecture."
	@echo "      Function list is taken from the predefined file 'cluster_example_list'."
	@echo "      It uses the ilp64 interface, Intel OpenMP, and oneMKL XERBLA."
	@echo "      Moreover, it has support of cluster libraries, where oneMKL BLACS"
	@echo "      library is pre-compiled with Intel(R) MPI."
	@echo

##------------------------------------------------------------------------------

ifndef MKLROOT
MKLROOT = ../../../..
endif

mklintel64_libpath = $(MKLROOT)/lib

ifndef CMPLR_ROOT
compilerintel64_libpath = $(ONEAPI_ROOT)/lib
else
compilerintel64_libpath = $(CMPLR_ROOT)/lib
endif

ifndef TBBROOT
tbbintel64_libpath = $(ONEAPI_ROOT)/lib
else
tbbintel64_libpath = $(TBBROOT)/lib
endif

export = user_example_list
name = mkl_custom

ifdef xerbla
XERBLA = "$(xerbla)"
else
XERBLA =
endif

ifndef interface
interface = lp64
endif

ifneq ($(interface),ilp64)
ifneq ($(interface),lp64)
interface = lp64
endif
endif

ifndef threading
threading = parallel
endif
ifndef parallel
parallel = intel
endif

IFACE_COMP_PART = intel

ifeq ($(parallel),gnu)
IFACE_THREADING_PART = gnu
LOPT_INTEL64 = -lgomp
else ifeq ($(parallel),tbb)
IFACE_THREADING_PART = tbb
LOPT_INTEL64 = -L"$(tbbintel64_libpath)" -ltbb
else
IFACE_THREADING_PART = intel
LOPT_INTEL64 = -L"$(compilerintel64_libpath)" -liomp5
endif

IFACE_LIB = libmkl_$(IFACE_COMP_PART)_$(interface).a

ifeq ($(threading),sequential)
THREADING_LIB = libmkl_sequential.a
LOPT_INTEL64 =
else
THREADING_LIB = libmkl_$(IFACE_THREADING_PART)_thread.a
endif
LOPT_INTEL64 += -lpthread

CORE_LIB = libmkl_core.a
PURE_IFACE_LIB = -lmkl_rt

ifeq ($(cluster),yes)
ifndef blacs_mpi
blacs_mpi = intelmpi
endif

ifneq ($(blacs_name),)
ifndef BLACSDIR
BLACSDIR = "$(mklintel64_libpath)"
endif
BLACS_LIB = "$(BLACSDIR)/$(blacs_name).a"
else
BLACS_LIB = "$(mklintel64_libpath)/libmkl_blacs_$(blacs_mpi)_$(interface).a"
endif
SCALAPACK_LIB = "$(mklintel64_libpath)/libmkl_scalapack_$(interface).a"
CDFT_LIB = "$(mklintel64_libpath)/libmkl_cdft_core.a"
else
BLACS_LIB =
SCALAPACK_LIB =
CDFT_LIB =
endif

SYSTEM_LIBS = -lm -ldl

libintel64 intel64 em64t: $(export)
	export LIBRARY_PATH=$(LIBRARY_PATH):$(LD_LIBRARY_PATH); \
	gcc -shared -Wl,-z,relro,-z,now -Bdynamic \
	$(XERBLA) $(addprefix -u ,$(shell grep -v '^[\#;]' "$(export)")) \
	-u mkl_serv_finalize -Wl,-fini=mkl_serv_finalize \
	-Wl,--start-group \
	$(SCALAPACK_LIB) $(CDFT_LIB) $(BLACS_LIB) \
	"$(mklintel64_libpath)/$(IFACE_LIB)" \
	"$(mklintel64_libpath)/$(THREADING_LIB)" \
	"$(mklintel64_libpath)/$(CORE_LIB)" \
	-Wl,--end-group \
	$(LOPT_INTEL64) $(SYSTEM_LIBS) \
	-o "$(name).so"
